Cesanta / v7 Featured

Embedded JavaScript virtual machine

Dependents:   DISCO-F469NI_javascript_blinker

Committer:
Marko Mikulicic
Date:
Tue Oct 11 09:13:50 2016 +0200
Revision:
0:c0ecb8bf28eb
Child:
1:887cf63a2a0b
Import v7 from git

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 0:c0ecb8bf28eb 47
Marko Mikulicic 0:c0ecb8bf28eb 48 /* If not specified explicitly, we guess platform by defines. */
Marko Mikulicic 0:c0ecb8bf28eb 49 #ifndef CS_PLATFORM
Marko Mikulicic 0:c0ecb8bf28eb 50
Marko Mikulicic 0:c0ecb8bf28eb 51 #if defined(TARGET_IS_MSP432P4XX) || defined(__MSP432P401R__)
Marko Mikulicic 0:c0ecb8bf28eb 52
Marko Mikulicic 0:c0ecb8bf28eb 53 #define CS_PLATFORM CS_P_MSP432
Marko Mikulicic 0:c0ecb8bf28eb 54 #elif defined(cc3200)
Marko Mikulicic 0:c0ecb8bf28eb 55 #define CS_PLATFORM CS_P_CC3200
Marko Mikulicic 0:c0ecb8bf28eb 56 #elif defined(__unix__) || defined(__APPLE__)
Marko Mikulicic 0:c0ecb8bf28eb 57 #define CS_PLATFORM CS_P_UNIX
Marko Mikulicic 0:c0ecb8bf28eb 58 #elif defined(_WIN32)
Marko Mikulicic 0:c0ecb8bf28eb 59 #define CS_PLATFORM CS_P_WINDOWS
Marko Mikulicic 0:c0ecb8bf28eb 60 #endif
Marko Mikulicic 0:c0ecb8bf28eb 61
Marko Mikulicic 0:c0ecb8bf28eb 62 #ifndef CS_PLATFORM
Marko Mikulicic 0:c0ecb8bf28eb 63 #error "CS_PLATFORM is not specified and we couldn't guess it."
Marko Mikulicic 0:c0ecb8bf28eb 64 #endif
Marko Mikulicic 0:c0ecb8bf28eb 65
Marko Mikulicic 0:c0ecb8bf28eb 66 #endif /* !defined(CS_PLATFORM) */
Marko Mikulicic 0:c0ecb8bf28eb 67
Marko Mikulicic 0:c0ecb8bf28eb 68 /* Amalgamated: #include "common/platforms/platform_unix.h" */
Marko Mikulicic 0:c0ecb8bf28eb 69 /* Amalgamated: #include "common/platforms/platform_windows.h" */
Marko Mikulicic 0:c0ecb8bf28eb 70 /* Amalgamated: #include "common/platforms/platform_esp_lwip.h" */
Marko Mikulicic 0:c0ecb8bf28eb 71 /* Amalgamated: #include "common/platforms/platform_cc3200.h" */
Marko Mikulicic 0:c0ecb8bf28eb 72 /* Amalgamated: #include "common/platforms/platform_cc3100.h" */
Marko Mikulicic 0:c0ecb8bf28eb 73
Marko Mikulicic 0:c0ecb8bf28eb 74 /* Common stuff */
Marko Mikulicic 0:c0ecb8bf28eb 75
Marko Mikulicic 0:c0ecb8bf28eb 76 #ifdef __GNUC__
Marko Mikulicic 0:c0ecb8bf28eb 77 #define NORETURN __attribute__((noreturn))
Marko Mikulicic 0:c0ecb8bf28eb 78 #define NOINLINE __attribute__((noinline))
Marko Mikulicic 0:c0ecb8bf28eb 79 #define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
Marko Mikulicic 0:c0ecb8bf28eb 80 #define NOINSTR __attribute__((no_instrument_function))
Marko Mikulicic 0:c0ecb8bf28eb 81 #else
Marko Mikulicic 0:c0ecb8bf28eb 82 #define NORETURN
Marko Mikulicic 0:c0ecb8bf28eb 83 #define NOINLINE
Marko Mikulicic 0:c0ecb8bf28eb 84 #define WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 85 #define NOINSTR
Marko Mikulicic 0:c0ecb8bf28eb 86 #endif /* __GNUC__ */
Marko Mikulicic 0:c0ecb8bf28eb 87
Marko Mikulicic 0:c0ecb8bf28eb 88 #ifndef ARRAY_SIZE
Marko Mikulicic 0:c0ecb8bf28eb 89 #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
Marko Mikulicic 0:c0ecb8bf28eb 90 #endif
Marko Mikulicic 0:c0ecb8bf28eb 91
Marko Mikulicic 0:c0ecb8bf28eb 92 #endif /* CS_COMMON_PLATFORM_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 93 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 94 #line 1 "common/platforms/platform_windows.h"
Marko Mikulicic 0:c0ecb8bf28eb 95 #endif
Marko Mikulicic 0:c0ecb8bf28eb 96 #ifndef CS_COMMON_PLATFORMS_PLATFORM_WINDOWS_H_
Marko Mikulicic 0:c0ecb8bf28eb 97 #define CS_COMMON_PLATFORMS_PLATFORM_WINDOWS_H_
Marko Mikulicic 0:c0ecb8bf28eb 98 #if CS_PLATFORM == CS_P_WINDOWS
Marko Mikulicic 0:c0ecb8bf28eb 99
Marko Mikulicic 0:c0ecb8bf28eb 100 /*
Marko Mikulicic 0:c0ecb8bf28eb 101 * MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
Marko Mikulicic 0:c0ecb8bf28eb 102 * MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)
Marko Mikulicic 0:c0ecb8bf28eb 103 * MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012)
Marko Mikulicic 0:c0ecb8bf28eb 104 * MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010)
Marko Mikulicic 0:c0ecb8bf28eb 105 * MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008)
Marko Mikulicic 0:c0ecb8bf28eb 106 * MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005)
Marko Mikulicic 0:c0ecb8bf28eb 107 * MSVC++ 7.1 _MSC_VER == 1310 (Visual Studio 2003)
Marko Mikulicic 0:c0ecb8bf28eb 108 * MSVC++ 7.0 _MSC_VER == 1300
Marko Mikulicic 0:c0ecb8bf28eb 109 * MSVC++ 6.0 _MSC_VER == 1200
Marko Mikulicic 0:c0ecb8bf28eb 110 * MSVC++ 5.0 _MSC_VER == 1100
Marko Mikulicic 0:c0ecb8bf28eb 111 */
Marko Mikulicic 0:c0ecb8bf28eb 112 #ifdef _MSC_VER
Marko Mikulicic 0:c0ecb8bf28eb 113 #pragma warning(disable : 4127) /* FD_SET() emits warning, disable it */
Marko Mikulicic 0:c0ecb8bf28eb 114 #pragma warning(disable : 4204) /* missing c99 support */
Marko Mikulicic 0:c0ecb8bf28eb 115 #endif
Marko Mikulicic 0:c0ecb8bf28eb 116
Marko Mikulicic 0:c0ecb8bf28eb 117 #define _WINSOCK_DEPRECATED_NO_WARNINGS 1
Marko Mikulicic 0:c0ecb8bf28eb 118 #define _CRT_SECURE_NO_WARNINGS
Marko Mikulicic 0:c0ecb8bf28eb 119
Marko Mikulicic 0:c0ecb8bf28eb 120 #include <assert.h>
Marko Mikulicic 0:c0ecb8bf28eb 121 #include <direct.h>
Marko Mikulicic 0:c0ecb8bf28eb 122 #include <errno.h>
Marko Mikulicic 0:c0ecb8bf28eb 123 #include <fcntl.h>
Marko Mikulicic 0:c0ecb8bf28eb 124 #include <io.h>
Marko Mikulicic 0:c0ecb8bf28eb 125 #include <limits.h>
Marko Mikulicic 0:c0ecb8bf28eb 126 #include <signal.h>
Marko Mikulicic 0:c0ecb8bf28eb 127 #include <stddef.h>
Marko Mikulicic 0:c0ecb8bf28eb 128 #include <stdio.h>
Marko Mikulicic 0:c0ecb8bf28eb 129 #include <stdlib.h>
Marko Mikulicic 0:c0ecb8bf28eb 130 #include <sys/stat.h>
Marko Mikulicic 0:c0ecb8bf28eb 131 #include <time.h>
Marko Mikulicic 0:c0ecb8bf28eb 132
Marko Mikulicic 0:c0ecb8bf28eb 133 #ifdef _MSC_VER
Marko Mikulicic 0:c0ecb8bf28eb 134 #pragma comment(lib, "ws2_32.lib") /* Linking with winsock library */
Marko Mikulicic 0:c0ecb8bf28eb 135 #endif
Marko Mikulicic 0:c0ecb8bf28eb 136
Marko Mikulicic 0:c0ecb8bf28eb 137 #include <winsock2.h>
Marko Mikulicic 0:c0ecb8bf28eb 138 #include <ws2tcpip.h>
Marko Mikulicic 0:c0ecb8bf28eb 139 #include <windows.h>
Marko Mikulicic 0:c0ecb8bf28eb 140 #include <process.h>
Marko Mikulicic 0:c0ecb8bf28eb 141
Marko Mikulicic 0:c0ecb8bf28eb 142 #if defined(_MSC_VER) && _MSC_VER >= 1800
Marko Mikulicic 0:c0ecb8bf28eb 143 #define strdup _strdup
Marko Mikulicic 0:c0ecb8bf28eb 144 #endif
Marko Mikulicic 0:c0ecb8bf28eb 145
Marko Mikulicic 0:c0ecb8bf28eb 146 #ifndef EINPROGRESS
Marko Mikulicic 0:c0ecb8bf28eb 147 #define EINPROGRESS WSAEINPROGRESS
Marko Mikulicic 0:c0ecb8bf28eb 148 #endif
Marko Mikulicic 0:c0ecb8bf28eb 149 #ifndef EWOULDBLOCK
Marko Mikulicic 0:c0ecb8bf28eb 150 #define EWOULDBLOCK WSAEWOULDBLOCK
Marko Mikulicic 0:c0ecb8bf28eb 151 #endif
Marko Mikulicic 0:c0ecb8bf28eb 152 #ifndef __func__
Marko Mikulicic 0:c0ecb8bf28eb 153 #define STRX(x) #x
Marko Mikulicic 0:c0ecb8bf28eb 154 #define STR(x) STRX(x)
Marko Mikulicic 0:c0ecb8bf28eb 155 #define __func__ __FILE__ ":" STR(__LINE__)
Marko Mikulicic 0:c0ecb8bf28eb 156 #endif
Marko Mikulicic 0:c0ecb8bf28eb 157 #define snprintf _snprintf
Marko Mikulicic 0:c0ecb8bf28eb 158 #define fileno _fileno
Marko Mikulicic 0:c0ecb8bf28eb 159 #define vsnprintf _vsnprintf
Marko Mikulicic 0:c0ecb8bf28eb 160 #define sleep(x) Sleep((x) *1000)
Marko Mikulicic 0:c0ecb8bf28eb 161 #define to64(x) _atoi64(x)
Marko Mikulicic 0:c0ecb8bf28eb 162 #if !defined(__MINGW32__) && !defined(__MINGW64__)
Marko Mikulicic 0:c0ecb8bf28eb 163 #define popen(x, y) _popen((x), (y))
Marko Mikulicic 0:c0ecb8bf28eb 164 #define pclose(x) _pclose(x)
Marko Mikulicic 0:c0ecb8bf28eb 165 #endif
Marko Mikulicic 0:c0ecb8bf28eb 166 #define rmdir _rmdir
Marko Mikulicic 0:c0ecb8bf28eb 167 #if defined(_MSC_VER) && _MSC_VER >= 1400
Marko Mikulicic 0:c0ecb8bf28eb 168 #define fseeko(x, y, z) _fseeki64((x), (y), (z))
Marko Mikulicic 0:c0ecb8bf28eb 169 #else
Marko Mikulicic 0:c0ecb8bf28eb 170 #define fseeko(x, y, z) fseek((x), (y), (z))
Marko Mikulicic 0:c0ecb8bf28eb 171 #endif
Marko Mikulicic 0:c0ecb8bf28eb 172 #if defined(_MSC_VER) && _MSC_VER <= 1200
Marko Mikulicic 0:c0ecb8bf28eb 173 typedef unsigned long uintptr_t;
Marko Mikulicic 0:c0ecb8bf28eb 174 typedef long intptr_t;
Marko Mikulicic 0:c0ecb8bf28eb 175 #endif
Marko Mikulicic 0:c0ecb8bf28eb 176 typedef int socklen_t;
Marko Mikulicic 0:c0ecb8bf28eb 177 #if _MSC_VER >= 1700
Marko Mikulicic 0:c0ecb8bf28eb 178 #include <stdint.h>
Marko Mikulicic 0:c0ecb8bf28eb 179 #else
Marko Mikulicic 0:c0ecb8bf28eb 180 typedef signed char int8_t;
Marko Mikulicic 0:c0ecb8bf28eb 181 typedef unsigned char uint8_t;
Marko Mikulicic 0:c0ecb8bf28eb 182 typedef int int32_t;
Marko Mikulicic 0:c0ecb8bf28eb 183 typedef unsigned int uint32_t;
Marko Mikulicic 0:c0ecb8bf28eb 184 typedef short int16_t;
Marko Mikulicic 0:c0ecb8bf28eb 185 typedef unsigned short uint16_t;
Marko Mikulicic 0:c0ecb8bf28eb 186 typedef __int64 int64_t;
Marko Mikulicic 0:c0ecb8bf28eb 187 typedef unsigned __int64 uint64_t;
Marko Mikulicic 0:c0ecb8bf28eb 188 #endif
Marko Mikulicic 0:c0ecb8bf28eb 189 typedef SOCKET sock_t;
Marko Mikulicic 0:c0ecb8bf28eb 190 typedef uint32_t in_addr_t;
Marko Mikulicic 0:c0ecb8bf28eb 191 #ifndef UINT16_MAX
Marko Mikulicic 0:c0ecb8bf28eb 192 #define UINT16_MAX 65535
Marko Mikulicic 0:c0ecb8bf28eb 193 #endif
Marko Mikulicic 0:c0ecb8bf28eb 194 #ifndef UINT32_MAX
Marko Mikulicic 0:c0ecb8bf28eb 195 #define UINT32_MAX 4294967295
Marko Mikulicic 0:c0ecb8bf28eb 196 #endif
Marko Mikulicic 0:c0ecb8bf28eb 197 #ifndef pid_t
Marko Mikulicic 0:c0ecb8bf28eb 198 #define pid_t HANDLE
Marko Mikulicic 0:c0ecb8bf28eb 199 #endif
Marko Mikulicic 0:c0ecb8bf28eb 200 #define INT64_FMT "I64d"
Marko Mikulicic 0:c0ecb8bf28eb 201 #define INT64_X_FMT "I64x"
Marko Mikulicic 0:c0ecb8bf28eb 202 #define SIZE_T_FMT "Iu"
Marko Mikulicic 0:c0ecb8bf28eb 203 #if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
Marko Mikulicic 0:c0ecb8bf28eb 204 typedef struct stat cs_stat_t;
Marko Mikulicic 0:c0ecb8bf28eb 205 #else
Marko Mikulicic 0:c0ecb8bf28eb 206 typedef struct _stati64 cs_stat_t;
Marko Mikulicic 0:c0ecb8bf28eb 207 #endif
Marko Mikulicic 0:c0ecb8bf28eb 208 #ifndef S_ISDIR
Marko Mikulicic 0:c0ecb8bf28eb 209 #define S_ISDIR(x) (((x) &_S_IFMT) == _S_IFDIR)
Marko Mikulicic 0:c0ecb8bf28eb 210 #endif
Marko Mikulicic 0:c0ecb8bf28eb 211 #ifndef S_ISREG
Marko Mikulicic 0:c0ecb8bf28eb 212 #define S_ISREG(x) (((x) &_S_IFMT) == _S_IFREG)
Marko Mikulicic 0:c0ecb8bf28eb 213 #endif
Marko Mikulicic 0:c0ecb8bf28eb 214 #define DIRSEP '\\'
Marko Mikulicic 0:c0ecb8bf28eb 215
Marko Mikulicic 0:c0ecb8bf28eb 216 #ifndef va_copy
Marko Mikulicic 0:c0ecb8bf28eb 217 #ifdef __va_copy
Marko Mikulicic 0:c0ecb8bf28eb 218 #define va_copy __va_copy
Marko Mikulicic 0:c0ecb8bf28eb 219 #else
Marko Mikulicic 0:c0ecb8bf28eb 220 #define va_copy(x, y) (x) = (y)
Marko Mikulicic 0:c0ecb8bf28eb 221 #endif
Marko Mikulicic 0:c0ecb8bf28eb 222 #endif
Marko Mikulicic 0:c0ecb8bf28eb 223
Marko Mikulicic 0:c0ecb8bf28eb 224 #ifndef MG_MAX_HTTP_REQUEST_SIZE
Marko Mikulicic 0:c0ecb8bf28eb 225 #define MG_MAX_HTTP_REQUEST_SIZE 8192
Marko Mikulicic 0:c0ecb8bf28eb 226 #endif
Marko Mikulicic 0:c0ecb8bf28eb 227
Marko Mikulicic 0:c0ecb8bf28eb 228 #ifndef MG_MAX_HTTP_SEND_MBUF
Marko Mikulicic 0:c0ecb8bf28eb 229 #define MG_MAX_HTTP_SEND_MBUF 4096
Marko Mikulicic 0:c0ecb8bf28eb 230 #endif
Marko Mikulicic 0:c0ecb8bf28eb 231
Marko Mikulicic 0:c0ecb8bf28eb 232 #ifndef MG_MAX_HTTP_HEADERS
Marko Mikulicic 0:c0ecb8bf28eb 233 #define MG_MAX_HTTP_HEADERS 40
Marko Mikulicic 0:c0ecb8bf28eb 234 #endif
Marko Mikulicic 0:c0ecb8bf28eb 235
Marko Mikulicic 0:c0ecb8bf28eb 236 #endif /* CS_PLATFORM == CS_P_WINDOWS */
Marko Mikulicic 0:c0ecb8bf28eb 237 #endif /* CS_COMMON_PLATFORMS_PLATFORM_WINDOWS_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 238 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 239 #line 1 "common/platforms/platform_unix.h"
Marko Mikulicic 0:c0ecb8bf28eb 240 #endif
Marko Mikulicic 0:c0ecb8bf28eb 241 #ifndef CS_COMMON_PLATFORMS_PLATFORM_UNIX_H_
Marko Mikulicic 0:c0ecb8bf28eb 242 #define CS_COMMON_PLATFORMS_PLATFORM_UNIX_H_
Marko Mikulicic 0:c0ecb8bf28eb 243 #if CS_PLATFORM == CS_P_UNIX
Marko Mikulicic 0:c0ecb8bf28eb 244
Marko Mikulicic 0:c0ecb8bf28eb 245 #ifndef _XOPEN_SOURCE
Marko Mikulicic 0:c0ecb8bf28eb 246 #define _XOPEN_SOURCE 600
Marko Mikulicic 0:c0ecb8bf28eb 247 #endif
Marko Mikulicic 0:c0ecb8bf28eb 248
Marko Mikulicic 0:c0ecb8bf28eb 249 /* <inttypes.h> wants this for C++ */
Marko Mikulicic 0:c0ecb8bf28eb 250 #ifndef __STDC_FORMAT_MACROS
Marko Mikulicic 0:c0ecb8bf28eb 251 #define __STDC_FORMAT_MACROS
Marko Mikulicic 0:c0ecb8bf28eb 252 #endif
Marko Mikulicic 0:c0ecb8bf28eb 253
Marko Mikulicic 0:c0ecb8bf28eb 254 /* C++ wants that for INT64_MAX */
Marko Mikulicic 0:c0ecb8bf28eb 255 #ifndef __STDC_LIMIT_MACROS
Marko Mikulicic 0:c0ecb8bf28eb 256 #define __STDC_LIMIT_MACROS
Marko Mikulicic 0:c0ecb8bf28eb 257 #endif
Marko Mikulicic 0:c0ecb8bf28eb 258
Marko Mikulicic 0:c0ecb8bf28eb 259 /* Enable fseeko() and ftello() functions */
Marko Mikulicic 0:c0ecb8bf28eb 260 #ifndef _LARGEFILE_SOURCE
Marko Mikulicic 0:c0ecb8bf28eb 261 #define _LARGEFILE_SOURCE
Marko Mikulicic 0:c0ecb8bf28eb 262 #endif
Marko Mikulicic 0:c0ecb8bf28eb 263
Marko Mikulicic 0:c0ecb8bf28eb 264 /* Enable 64-bit file offsets */
Marko Mikulicic 0:c0ecb8bf28eb 265 #ifndef _FILE_OFFSET_BITS
Marko Mikulicic 0:c0ecb8bf28eb 266 #define _FILE_OFFSET_BITS 64
Marko Mikulicic 0:c0ecb8bf28eb 267 #endif
Marko Mikulicic 0:c0ecb8bf28eb 268
Marko Mikulicic 0:c0ecb8bf28eb 269 #include <arpa/inet.h>
Marko Mikulicic 0:c0ecb8bf28eb 270 #include <assert.h>
Marko Mikulicic 0:c0ecb8bf28eb 271 #include <ctype.h>
Marko Mikulicic 0:c0ecb8bf28eb 272 #include <dirent.h>
Marko Mikulicic 0:c0ecb8bf28eb 273 #include <errno.h>
Marko Mikulicic 0:c0ecb8bf28eb 274 #include <fcntl.h>
Marko Mikulicic 0:c0ecb8bf28eb 275 #include <inttypes.h>
Marko Mikulicic 0:c0ecb8bf28eb 276 #include <stdint.h>
Marko Mikulicic 0:c0ecb8bf28eb 277 #include <limits.h>
Marko Mikulicic 0:c0ecb8bf28eb 278 #include <math.h>
Marko Mikulicic 0:c0ecb8bf28eb 279 #include <netdb.h>
Marko Mikulicic 0:c0ecb8bf28eb 280 #include <netinet/in.h>
Marko Mikulicic 0:c0ecb8bf28eb 281 #include <pthread.h>
Marko Mikulicic 0:c0ecb8bf28eb 282 #include <signal.h>
Marko Mikulicic 0:c0ecb8bf28eb 283 #include <stdarg.h>
Marko Mikulicic 0:c0ecb8bf28eb 284 #include <stdio.h>
Marko Mikulicic 0:c0ecb8bf28eb 285 #include <stdlib.h>
Marko Mikulicic 0:c0ecb8bf28eb 286 #include <string.h>
Marko Mikulicic 0:c0ecb8bf28eb 287 #include <sys/socket.h>
Marko Mikulicic 0:c0ecb8bf28eb 288 #include <sys/select.h>
Marko Mikulicic 0:c0ecb8bf28eb 289 #include <sys/stat.h>
Marko Mikulicic 0:c0ecb8bf28eb 290 #include <sys/time.h>
Marko Mikulicic 0:c0ecb8bf28eb 291 #include <sys/types.h>
Marko Mikulicic 0:c0ecb8bf28eb 292 #include <unistd.h>
Marko Mikulicic 0:c0ecb8bf28eb 293
Marko Mikulicic 0:c0ecb8bf28eb 294 /*
Marko Mikulicic 0:c0ecb8bf28eb 295 * osx correctly avoids defining strtoll when compiling in strict ansi mode.
Marko Mikulicic 0:c0ecb8bf28eb 296 * We require strtoll, and if your embedded pre-c99 compiler lacks one, please
Marko Mikulicic 0:c0ecb8bf28eb 297 * implement a shim.
Marko Mikulicic 0:c0ecb8bf28eb 298 */
Marko Mikulicic 0:c0ecb8bf28eb 299 #if !(defined(__DARWIN_C_LEVEL) && __DARWIN_C_LEVEL >= 200809L)
Marko Mikulicic 0:c0ecb8bf28eb 300 long long strtoll(const char *, char **, int);
Marko Mikulicic 0:c0ecb8bf28eb 301 #endif
Marko Mikulicic 0:c0ecb8bf28eb 302
Marko Mikulicic 0:c0ecb8bf28eb 303 typedef int sock_t;
Marko Mikulicic 0:c0ecb8bf28eb 304 #define INVALID_SOCKET (-1)
Marko Mikulicic 0:c0ecb8bf28eb 305 #define SIZE_T_FMT "zu"
Marko Mikulicic 0:c0ecb8bf28eb 306 typedef struct stat cs_stat_t;
Marko Mikulicic 0:c0ecb8bf28eb 307 #define DIRSEP '/'
Marko Mikulicic 0:c0ecb8bf28eb 308 #define to64(x) strtoll(x, NULL, 10)
Marko Mikulicic 0:c0ecb8bf28eb 309 #define INT64_FMT PRId64
Marko Mikulicic 0:c0ecb8bf28eb 310 #define INT64_X_FMT PRIx64
Marko Mikulicic 0:c0ecb8bf28eb 311
Marko Mikulicic 0:c0ecb8bf28eb 312 #ifndef __cdecl
Marko Mikulicic 0:c0ecb8bf28eb 313 #define __cdecl
Marko Mikulicic 0:c0ecb8bf28eb 314 #endif
Marko Mikulicic 0:c0ecb8bf28eb 315
Marko Mikulicic 0:c0ecb8bf28eb 316 #ifndef va_copy
Marko Mikulicic 0:c0ecb8bf28eb 317 #ifdef __va_copy
Marko Mikulicic 0:c0ecb8bf28eb 318 #define va_copy __va_copy
Marko Mikulicic 0:c0ecb8bf28eb 319 #else
Marko Mikulicic 0:c0ecb8bf28eb 320 #define va_copy(x, y) (x) = (y)
Marko Mikulicic 0:c0ecb8bf28eb 321 #endif
Marko Mikulicic 0:c0ecb8bf28eb 322 #endif
Marko Mikulicic 0:c0ecb8bf28eb 323
Marko Mikulicic 0:c0ecb8bf28eb 324 #define closesocket(x) close(x)
Marko Mikulicic 0:c0ecb8bf28eb 325
Marko Mikulicic 0:c0ecb8bf28eb 326 #ifndef MG_MAX_HTTP_REQUEST_SIZE
Marko Mikulicic 0:c0ecb8bf28eb 327 #define MG_MAX_HTTP_REQUEST_SIZE 8192
Marko Mikulicic 0:c0ecb8bf28eb 328 #endif
Marko Mikulicic 0:c0ecb8bf28eb 329
Marko Mikulicic 0:c0ecb8bf28eb 330 #ifndef MG_MAX_HTTP_SEND_MBUF
Marko Mikulicic 0:c0ecb8bf28eb 331 #define MG_MAX_HTTP_SEND_MBUF 4096
Marko Mikulicic 0:c0ecb8bf28eb 332 #endif
Marko Mikulicic 0:c0ecb8bf28eb 333
Marko Mikulicic 0:c0ecb8bf28eb 334 #ifndef MG_MAX_HTTP_HEADERS
Marko Mikulicic 0:c0ecb8bf28eb 335 #define MG_MAX_HTTP_HEADERS 40
Marko Mikulicic 0:c0ecb8bf28eb 336 #endif
Marko Mikulicic 0:c0ecb8bf28eb 337
Marko Mikulicic 0:c0ecb8bf28eb 338 #endif /* CS_PLATFORM == CS_P_UNIX */
Marko Mikulicic 0:c0ecb8bf28eb 339 #endif /* CS_COMMON_PLATFORMS_PLATFORM_UNIX_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 340 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 341 #line 1 "common/platforms/platform_esp_lwip.h"
Marko Mikulicic 0:c0ecb8bf28eb 342 #endif
Marko Mikulicic 0:c0ecb8bf28eb 343 #ifndef CS_COMMON_PLATFORMS_PLATFORM_ESP_LWIP_H_
Marko Mikulicic 0:c0ecb8bf28eb 344 #define CS_COMMON_PLATFORMS_PLATFORM_ESP_LWIP_H_
Marko Mikulicic 0:c0ecb8bf28eb 345 #if CS_PLATFORM == CS_P_ESP_LWIP
Marko Mikulicic 0:c0ecb8bf28eb 346
Marko Mikulicic 0:c0ecb8bf28eb 347 #include <assert.h>
Marko Mikulicic 0:c0ecb8bf28eb 348 #include <ctype.h>
Marko Mikulicic 0:c0ecb8bf28eb 349 #include <fcntl.h>
Marko Mikulicic 0:c0ecb8bf28eb 350 #include <inttypes.h>
Marko Mikulicic 0:c0ecb8bf28eb 351 #include <string.h>
Marko Mikulicic 0:c0ecb8bf28eb 352 #include <sys/stat.h>
Marko Mikulicic 0:c0ecb8bf28eb 353 #include <sys/time.h>
Marko Mikulicic 0:c0ecb8bf28eb 354
Marko Mikulicic 0:c0ecb8bf28eb 355 #include <lwip/err.h>
Marko Mikulicic 0:c0ecb8bf28eb 356 #include <lwip/ip_addr.h>
Marko Mikulicic 0:c0ecb8bf28eb 357 #include <lwip/inet.h>
Marko Mikulicic 0:c0ecb8bf28eb 358 #include <lwip/netdb.h>
Marko Mikulicic 0:c0ecb8bf28eb 359 #include <lwip/dns.h>
Marko Mikulicic 0:c0ecb8bf28eb 360
Marko Mikulicic 0:c0ecb8bf28eb 361 #ifndef LWIP_PROVIDE_ERRNO
Marko Mikulicic 0:c0ecb8bf28eb 362 #include <errno.h>
Marko Mikulicic 0:c0ecb8bf28eb 363 #endif
Marko Mikulicic 0:c0ecb8bf28eb 364
Marko Mikulicic 0:c0ecb8bf28eb 365 #define LWIP_TIMEVAL_PRIVATE 0
Marko Mikulicic 0:c0ecb8bf28eb 366
Marko Mikulicic 0:c0ecb8bf28eb 367 #if LWIP_SOCKET
Marko Mikulicic 0:c0ecb8bf28eb 368 #include <lwip/sockets.h>
Marko Mikulicic 0:c0ecb8bf28eb 369 #define SOMAXCONN 10
Marko Mikulicic 0:c0ecb8bf28eb 370 #else
Marko Mikulicic 0:c0ecb8bf28eb 371 /* We really need the definitions from sockets.h. */
Marko Mikulicic 0:c0ecb8bf28eb 372 #undef LWIP_SOCKET
Marko Mikulicic 0:c0ecb8bf28eb 373 #define LWIP_SOCKET 1
Marko Mikulicic 0:c0ecb8bf28eb 374 #include <lwip/sockets.h>
Marko Mikulicic 0:c0ecb8bf28eb 375 #undef LWIP_SOCKET
Marko Mikulicic 0:c0ecb8bf28eb 376 #define LWIP_SOCKET 0
Marko Mikulicic 0:c0ecb8bf28eb 377 #endif
Marko Mikulicic 0:c0ecb8bf28eb 378
Marko Mikulicic 0:c0ecb8bf28eb 379 typedef int sock_t;
Marko Mikulicic 0:c0ecb8bf28eb 380 #define INVALID_SOCKET (-1)
Marko Mikulicic 0:c0ecb8bf28eb 381 #define SIZE_T_FMT "u"
Marko Mikulicic 0:c0ecb8bf28eb 382 typedef struct stat cs_stat_t;
Marko Mikulicic 0:c0ecb8bf28eb 383 #define DIRSEP '/'
Marko Mikulicic 0:c0ecb8bf28eb 384 #define to64(x) strtoll(x, NULL, 10)
Marko Mikulicic 0:c0ecb8bf28eb 385 #define INT64_FMT PRId64
Marko Mikulicic 0:c0ecb8bf28eb 386 #define INT64_X_FMT PRIx64
Marko Mikulicic 0:c0ecb8bf28eb 387 #define __cdecl
Marko Mikulicic 0:c0ecb8bf28eb 388
Marko Mikulicic 0:c0ecb8bf28eb 389 unsigned long os_random(void);
Marko Mikulicic 0:c0ecb8bf28eb 390 #define random os_random
Marko Mikulicic 0:c0ecb8bf28eb 391
Marko Mikulicic 0:c0ecb8bf28eb 392 #endif /* CS_PLATFORM == CS_P_ESP_LWIP */
Marko Mikulicic 0:c0ecb8bf28eb 393 #endif /* CS_COMMON_PLATFORMS_PLATFORM_ESP_LWIP_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 394 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 395 #line 1 "common/mbuf.h"
Marko Mikulicic 0:c0ecb8bf28eb 396 #endif
Marko Mikulicic 0:c0ecb8bf28eb 397 /*
Marko Mikulicic 0:c0ecb8bf28eb 398 * Copyright (c) 2015 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 399 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 400 */
Marko Mikulicic 0:c0ecb8bf28eb 401
Marko Mikulicic 0:c0ecb8bf28eb 402 /*
Marko Mikulicic 0:c0ecb8bf28eb 403 * === Memory Buffers
Marko Mikulicic 0:c0ecb8bf28eb 404 *
Marko Mikulicic 0:c0ecb8bf28eb 405 * Mbufs are mutable/growing memory buffers, like C++ strings.
Marko Mikulicic 0:c0ecb8bf28eb 406 * Mbuf can append data to the end of a buffer or insert data into arbitrary
Marko Mikulicic 0:c0ecb8bf28eb 407 * position in the middle of a buffer. The buffer grows automatically when
Marko Mikulicic 0:c0ecb8bf28eb 408 * needed.
Marko Mikulicic 0:c0ecb8bf28eb 409 */
Marko Mikulicic 0:c0ecb8bf28eb 410
Marko Mikulicic 0:c0ecb8bf28eb 411 #ifndef CS_COMMON_MBUF_H_
Marko Mikulicic 0:c0ecb8bf28eb 412 #define CS_COMMON_MBUF_H_
Marko Mikulicic 0:c0ecb8bf28eb 413
Marko Mikulicic 0:c0ecb8bf28eb 414 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 415 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 416 #endif
Marko Mikulicic 0:c0ecb8bf28eb 417
Marko Mikulicic 0:c0ecb8bf28eb 418 #include <stdlib.h>
Marko Mikulicic 0:c0ecb8bf28eb 419
Marko Mikulicic 0:c0ecb8bf28eb 420 #ifndef MBUF_SIZE_MULTIPLIER
Marko Mikulicic 0:c0ecb8bf28eb 421 #define MBUF_SIZE_MULTIPLIER 1.5
Marko Mikulicic 0:c0ecb8bf28eb 422 #endif
Marko Mikulicic 0:c0ecb8bf28eb 423
Marko Mikulicic 0:c0ecb8bf28eb 424 /* Memory buffer descriptor */
Marko Mikulicic 0:c0ecb8bf28eb 425 struct mbuf {
Marko Mikulicic 0:c0ecb8bf28eb 426 char *buf; /* Buffer pointer */
Marko Mikulicic 0:c0ecb8bf28eb 427 size_t len; /* Data length. Data is located between offset 0 and len. */
Marko Mikulicic 0:c0ecb8bf28eb 428 size_t size; /* Buffer size allocated by realloc(1). Must be >= len */
Marko Mikulicic 0:c0ecb8bf28eb 429 };
Marko Mikulicic 0:c0ecb8bf28eb 430
Marko Mikulicic 0:c0ecb8bf28eb 431 /*
Marko Mikulicic 0:c0ecb8bf28eb 432 * Initialises an Mbuf.
Marko Mikulicic 0:c0ecb8bf28eb 433 * `initial_capacity` specifies the initial capacity of the mbuf.
Marko Mikulicic 0:c0ecb8bf28eb 434 */
Marko Mikulicic 0:c0ecb8bf28eb 435 void mbuf_init(struct mbuf *, size_t initial_capacity);
Marko Mikulicic 0:c0ecb8bf28eb 436
Marko Mikulicic 0:c0ecb8bf28eb 437 /* Frees the space allocated for the mbuffer and resets the mbuf structure. */
Marko Mikulicic 0:c0ecb8bf28eb 438 void mbuf_free(struct mbuf *);
Marko Mikulicic 0:c0ecb8bf28eb 439
Marko Mikulicic 0:c0ecb8bf28eb 440 /*
Marko Mikulicic 0:c0ecb8bf28eb 441 * Appends data to the Mbuf.
Marko Mikulicic 0:c0ecb8bf28eb 442 *
Marko Mikulicic 0:c0ecb8bf28eb 443 * Returns the number of bytes appended or 0 if out of memory.
Marko Mikulicic 0:c0ecb8bf28eb 444 */
Marko Mikulicic 0:c0ecb8bf28eb 445 size_t mbuf_append(struct mbuf *, const void *data, size_t data_size);
Marko Mikulicic 0:c0ecb8bf28eb 446
Marko Mikulicic 0:c0ecb8bf28eb 447 /*
Marko Mikulicic 0:c0ecb8bf28eb 448 * Inserts data at a specified offset in the Mbuf.
Marko Mikulicic 0:c0ecb8bf28eb 449 *
Marko Mikulicic 0:c0ecb8bf28eb 450 * Existing data will be shifted forwards and the buffer will
Marko Mikulicic 0:c0ecb8bf28eb 451 * be grown if necessary.
Marko Mikulicic 0:c0ecb8bf28eb 452 * Returns the number of bytes inserted.
Marko Mikulicic 0:c0ecb8bf28eb 453 */
Marko Mikulicic 0:c0ecb8bf28eb 454 size_t mbuf_insert(struct mbuf *, size_t, const void *, size_t);
Marko Mikulicic 0:c0ecb8bf28eb 455
Marko Mikulicic 0:c0ecb8bf28eb 456 /* Removes `data_size` bytes from the beginning of the buffer. */
Marko Mikulicic 0:c0ecb8bf28eb 457 void mbuf_remove(struct mbuf *, size_t data_size);
Marko Mikulicic 0:c0ecb8bf28eb 458
Marko Mikulicic 0:c0ecb8bf28eb 459 /*
Marko Mikulicic 0:c0ecb8bf28eb 460 * Resizes an Mbuf.
Marko Mikulicic 0:c0ecb8bf28eb 461 *
Marko Mikulicic 0:c0ecb8bf28eb 462 * If `new_size` is smaller than buffer's `len`, the
Marko Mikulicic 0:c0ecb8bf28eb 463 * resize is not performed.
Marko Mikulicic 0:c0ecb8bf28eb 464 */
Marko Mikulicic 0:c0ecb8bf28eb 465 void mbuf_resize(struct mbuf *, size_t new_size);
Marko Mikulicic 0:c0ecb8bf28eb 466
Marko Mikulicic 0:c0ecb8bf28eb 467 /* Shrinks an Mbuf by resizing its `size` to `len`. */
Marko Mikulicic 0:c0ecb8bf28eb 468 void mbuf_trim(struct mbuf *);
Marko Mikulicic 0:c0ecb8bf28eb 469
Marko Mikulicic 0:c0ecb8bf28eb 470 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 471 }
Marko Mikulicic 0:c0ecb8bf28eb 472 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 473
Marko Mikulicic 0:c0ecb8bf28eb 474 #endif /* CS_COMMON_MBUF_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 475 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 476 #line 1 "common/platforms/simplelink/cs_simplelink.h"
Marko Mikulicic 0:c0ecb8bf28eb 477 #endif
Marko Mikulicic 0:c0ecb8bf28eb 478 /*
Marko Mikulicic 0:c0ecb8bf28eb 479 * Copyright (c) 2014-2016 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 480 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 481 */
Marko Mikulicic 0:c0ecb8bf28eb 482
Marko Mikulicic 0:c0ecb8bf28eb 483 #ifndef CS_COMMON_PLATFORMS_SIMPLELINK_CS_SIMPLELINK_H_
Marko Mikulicic 0:c0ecb8bf28eb 484 #define CS_COMMON_PLATFORMS_SIMPLELINK_CS_SIMPLELINK_H_
Marko Mikulicic 0:c0ecb8bf28eb 485
Marko Mikulicic 0:c0ecb8bf28eb 486 /* If simplelink.h is already included, all bets are off. */
Marko Mikulicic 0:c0ecb8bf28eb 487 #if defined(MG_SOCKET_SIMPLELINK) && !defined(__SIMPLELINK_H__)
Marko Mikulicic 0:c0ecb8bf28eb 488
Marko Mikulicic 0:c0ecb8bf28eb 489 #include <stdbool.h>
Marko Mikulicic 0:c0ecb8bf28eb 490
Marko Mikulicic 0:c0ecb8bf28eb 491 #ifndef __TI_COMPILER_VERSION__
Marko Mikulicic 0:c0ecb8bf28eb 492 #undef __CONCAT
Marko Mikulicic 0:c0ecb8bf28eb 493 #undef FD_CLR
Marko Mikulicic 0:c0ecb8bf28eb 494 #undef FD_ISSET
Marko Mikulicic 0:c0ecb8bf28eb 495 #undef FD_SET
Marko Mikulicic 0:c0ecb8bf28eb 496 #undef FD_SETSIZE
Marko Mikulicic 0:c0ecb8bf28eb 497 #undef FD_ZERO
Marko Mikulicic 0:c0ecb8bf28eb 498 #undef fd_set
Marko Mikulicic 0:c0ecb8bf28eb 499 #endif
Marko Mikulicic 0:c0ecb8bf28eb 500
Marko Mikulicic 0:c0ecb8bf28eb 501 /* We want to disable SL_INC_STD_BSD_API_NAMING, so we include user.h ourselves
Marko Mikulicic 0:c0ecb8bf28eb 502 * and undef it. */
Marko Mikulicic 0:c0ecb8bf28eb 503 #define PROVISIONING_API_H_
Marko Mikulicic 0:c0ecb8bf28eb 504 #include <simplelink/user.h>
Marko Mikulicic 0:c0ecb8bf28eb 505 #undef PROVISIONING_API_H_
Marko Mikulicic 0:c0ecb8bf28eb 506 #undef SL_INC_STD_BSD_API_NAMING
Marko Mikulicic 0:c0ecb8bf28eb 507
Marko Mikulicic 0:c0ecb8bf28eb 508 #include <simplelink/include/simplelink.h>
Marko Mikulicic 0:c0ecb8bf28eb 509 #include <simplelink/include/netapp.h>
Marko Mikulicic 0:c0ecb8bf28eb 510
Marko Mikulicic 0:c0ecb8bf28eb 511 /* Now define only the subset of the BSD API that we use.
Marko Mikulicic 0:c0ecb8bf28eb 512 * Notably, close(), read() and write() are not defined. */
Marko Mikulicic 0:c0ecb8bf28eb 513 #define AF_INET SL_AF_INET
Marko Mikulicic 0:c0ecb8bf28eb 514
Marko Mikulicic 0:c0ecb8bf28eb 515 #define socklen_t SlSocklen_t
Marko Mikulicic 0:c0ecb8bf28eb 516 #define sockaddr SlSockAddr_t
Marko Mikulicic 0:c0ecb8bf28eb 517 #define sockaddr_in SlSockAddrIn_t
Marko Mikulicic 0:c0ecb8bf28eb 518 #define in_addr SlInAddr_t
Marko Mikulicic 0:c0ecb8bf28eb 519
Marko Mikulicic 0:c0ecb8bf28eb 520 #define SOCK_STREAM SL_SOCK_STREAM
Marko Mikulicic 0:c0ecb8bf28eb 521 #define SOCK_DGRAM SL_SOCK_DGRAM
Marko Mikulicic 0:c0ecb8bf28eb 522
Marko Mikulicic 0:c0ecb8bf28eb 523 #define htonl sl_Htonl
Marko Mikulicic 0:c0ecb8bf28eb 524 #define ntohl sl_Ntohl
Marko Mikulicic 0:c0ecb8bf28eb 525 #define htons sl_Htons
Marko Mikulicic 0:c0ecb8bf28eb 526 #define ntohs sl_Ntohs
Marko Mikulicic 0:c0ecb8bf28eb 527
Marko Mikulicic 0:c0ecb8bf28eb 528 #ifndef EACCES
Marko Mikulicic 0:c0ecb8bf28eb 529 #define EACCES SL_EACCES
Marko Mikulicic 0:c0ecb8bf28eb 530 #endif
Marko Mikulicic 0:c0ecb8bf28eb 531 #ifndef EAFNOSUPPORT
Marko Mikulicic 0:c0ecb8bf28eb 532 #define EAFNOSUPPORT SL_EAFNOSUPPORT
Marko Mikulicic 0:c0ecb8bf28eb 533 #endif
Marko Mikulicic 0:c0ecb8bf28eb 534 #ifndef EAGAIN
Marko Mikulicic 0:c0ecb8bf28eb 535 #define EAGAIN SL_EAGAIN
Marko Mikulicic 0:c0ecb8bf28eb 536 #endif
Marko Mikulicic 0:c0ecb8bf28eb 537 #ifndef EBADF
Marko Mikulicic 0:c0ecb8bf28eb 538 #define EBADF SL_EBADF
Marko Mikulicic 0:c0ecb8bf28eb 539 #endif
Marko Mikulicic 0:c0ecb8bf28eb 540 #ifndef EINVAL
Marko Mikulicic 0:c0ecb8bf28eb 541 #define EINVAL SL_EINVAL
Marko Mikulicic 0:c0ecb8bf28eb 542 #endif
Marko Mikulicic 0:c0ecb8bf28eb 543 #ifndef ENOMEM
Marko Mikulicic 0:c0ecb8bf28eb 544 #define ENOMEM SL_ENOMEM
Marko Mikulicic 0:c0ecb8bf28eb 545 #endif
Marko Mikulicic 0:c0ecb8bf28eb 546 #ifndef EWOULDBLOCK
Marko Mikulicic 0:c0ecb8bf28eb 547 #define EWOULDBLOCK SL_EWOULDBLOCK
Marko Mikulicic 0:c0ecb8bf28eb 548 #endif
Marko Mikulicic 0:c0ecb8bf28eb 549
Marko Mikulicic 0:c0ecb8bf28eb 550 #define SOMAXCONN 8
Marko Mikulicic 0:c0ecb8bf28eb 551
Marko Mikulicic 0:c0ecb8bf28eb 552 #ifdef __cplusplus
Marko Mikulicic 0:c0ecb8bf28eb 553 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 554 #endif
Marko Mikulicic 0:c0ecb8bf28eb 555
Marko Mikulicic 0:c0ecb8bf28eb 556 const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
Marko Mikulicic 0:c0ecb8bf28eb 557 char *inet_ntoa(struct in_addr in);
Marko Mikulicic 0:c0ecb8bf28eb 558 int inet_pton(int af, const char *src, void *dst);
Marko Mikulicic 0:c0ecb8bf28eb 559
Marko Mikulicic 0:c0ecb8bf28eb 560 struct mg_mgr;
Marko Mikulicic 0:c0ecb8bf28eb 561 struct mg_connection;
Marko Mikulicic 0:c0ecb8bf28eb 562
Marko Mikulicic 0:c0ecb8bf28eb 563 typedef void (*mg_init_cb)(struct mg_mgr *mgr);
Marko Mikulicic 0:c0ecb8bf28eb 564 bool mg_start_task(int priority, int stack_size, mg_init_cb mg_init);
Marko Mikulicic 0:c0ecb8bf28eb 565
Marko Mikulicic 0:c0ecb8bf28eb 566 void mg_run_in_task(void (*cb)(struct mg_mgr *mgr, void *arg), void *cb_arg);
Marko Mikulicic 0:c0ecb8bf28eb 567
Marko Mikulicic 0:c0ecb8bf28eb 568 int sl_fs_init(void);
Marko Mikulicic 0:c0ecb8bf28eb 569
Marko Mikulicic 0:c0ecb8bf28eb 570 void sl_restart_cb(struct mg_mgr *mgr);
Marko Mikulicic 0:c0ecb8bf28eb 571
Marko Mikulicic 0:c0ecb8bf28eb 572 int sl_set_ssl_opts(struct mg_connection *nc);
Marko Mikulicic 0:c0ecb8bf28eb 573
Marko Mikulicic 0:c0ecb8bf28eb 574 #ifdef __cplusplus
Marko Mikulicic 0:c0ecb8bf28eb 575 }
Marko Mikulicic 0:c0ecb8bf28eb 576 #endif
Marko Mikulicic 0:c0ecb8bf28eb 577
Marko Mikulicic 0:c0ecb8bf28eb 578 #endif /* defined(MG_SOCKET_SIMPLELINK) && !defined(__SIMPLELINK_H__) */
Marko Mikulicic 0:c0ecb8bf28eb 579
Marko Mikulicic 0:c0ecb8bf28eb 580 #endif /* CS_COMMON_PLATFORMS_SIMPLELINK_CS_SIMPLELINK_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 581 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 582 #line 1 "common/platforms/platform_cc3200.h"
Marko Mikulicic 0:c0ecb8bf28eb 583 #endif
Marko Mikulicic 0:c0ecb8bf28eb 584 /*
Marko Mikulicic 0:c0ecb8bf28eb 585 * Copyright (c) 2014-2016 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 586 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 587 */
Marko Mikulicic 0:c0ecb8bf28eb 588
Marko Mikulicic 0:c0ecb8bf28eb 589 #ifndef CS_COMMON_PLATFORMS_PLATFORM_CC3200_H_
Marko Mikulicic 0:c0ecb8bf28eb 590 #define CS_COMMON_PLATFORMS_PLATFORM_CC3200_H_
Marko Mikulicic 0:c0ecb8bf28eb 591 #if CS_PLATFORM == CS_P_CC3200
Marko Mikulicic 0:c0ecb8bf28eb 592
Marko Mikulicic 0:c0ecb8bf28eb 593 #include <assert.h>
Marko Mikulicic 0:c0ecb8bf28eb 594 #include <ctype.h>
Marko Mikulicic 0:c0ecb8bf28eb 595 #include <errno.h>
Marko Mikulicic 0:c0ecb8bf28eb 596 #include <inttypes.h>
Marko Mikulicic 0:c0ecb8bf28eb 597 #include <stdint.h>
Marko Mikulicic 0:c0ecb8bf28eb 598 #include <string.h>
Marko Mikulicic 0:c0ecb8bf28eb 599 #include <time.h>
Marko Mikulicic 0:c0ecb8bf28eb 600
Marko Mikulicic 0:c0ecb8bf28eb 601 #ifndef __TI_COMPILER_VERSION__
Marko Mikulicic 0:c0ecb8bf28eb 602 #include <fcntl.h>
Marko Mikulicic 0:c0ecb8bf28eb 603 #include <sys/time.h>
Marko Mikulicic 0:c0ecb8bf28eb 604 #endif
Marko Mikulicic 0:c0ecb8bf28eb 605
Marko Mikulicic 0:c0ecb8bf28eb 606 #define MG_SOCKET_SIMPLELINK 1
Marko Mikulicic 0:c0ecb8bf28eb 607 #define MG_DISABLE_SOCKETPAIR 1
Marko Mikulicic 0:c0ecb8bf28eb 608 #define MG_DISABLE_SYNC_RESOLVER 1
Marko Mikulicic 0:c0ecb8bf28eb 609 #define MG_DISABLE_POPEN 1
Marko Mikulicic 0:c0ecb8bf28eb 610 #define MG_DISABLE_CGI 1
Marko Mikulicic 0:c0ecb8bf28eb 611 /* Only SPIFFS supports directories, SLFS does not. */
Marko Mikulicic 0:c0ecb8bf28eb 612 #ifndef CC3200_FS_SPIFFS
Marko Mikulicic 0:c0ecb8bf28eb 613 #define MG_DISABLE_DAV 1
Marko Mikulicic 0:c0ecb8bf28eb 614 #define MG_DISABLE_DIRECTORY_LISTING 1
Marko Mikulicic 0:c0ecb8bf28eb 615 #endif
Marko Mikulicic 0:c0ecb8bf28eb 616
Marko Mikulicic 0:c0ecb8bf28eb 617 /* Amalgamated: #include "common/platforms/simplelink/cs_simplelink.h" */
Marko Mikulicic 0:c0ecb8bf28eb 618
Marko Mikulicic 0:c0ecb8bf28eb 619 typedef int sock_t;
Marko Mikulicic 0:c0ecb8bf28eb 620 #define INVALID_SOCKET (-1)
Marko Mikulicic 0:c0ecb8bf28eb 621 #define SIZE_T_FMT "u"
Marko Mikulicic 0:c0ecb8bf28eb 622 typedef struct stat cs_stat_t;
Marko Mikulicic 0:c0ecb8bf28eb 623 #define DIRSEP '/'
Marko Mikulicic 0:c0ecb8bf28eb 624 #define to64(x) strtoll(x, NULL, 10)
Marko Mikulicic 0:c0ecb8bf28eb 625 #define INT64_FMT PRId64
Marko Mikulicic 0:c0ecb8bf28eb 626 #define INT64_X_FMT PRIx64
Marko Mikulicic 0:c0ecb8bf28eb 627 #define __cdecl
Marko Mikulicic 0:c0ecb8bf28eb 628
Marko Mikulicic 0:c0ecb8bf28eb 629 #define fileno(x) -1
Marko Mikulicic 0:c0ecb8bf28eb 630
Marko Mikulicic 0:c0ecb8bf28eb 631 /* Some functions we implement for Mongoose. */
Marko Mikulicic 0:c0ecb8bf28eb 632
Marko Mikulicic 0:c0ecb8bf28eb 633 #ifdef __cplusplus
Marko Mikulicic 0:c0ecb8bf28eb 634 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 635 #endif
Marko Mikulicic 0:c0ecb8bf28eb 636
Marko Mikulicic 0:c0ecb8bf28eb 637 #ifdef __TI_COMPILER_VERSION__
Marko Mikulicic 0:c0ecb8bf28eb 638 struct SlTimeval_t;
Marko Mikulicic 0:c0ecb8bf28eb 639 #define timeval SlTimeval_t
Marko Mikulicic 0:c0ecb8bf28eb 640 int gettimeofday(struct timeval *t, void *tz);
Marko Mikulicic 0:c0ecb8bf28eb 641
Marko Mikulicic 0:c0ecb8bf28eb 642 int asprintf(char **strp, const char *fmt, ...);
Marko Mikulicic 0:c0ecb8bf28eb 643
Marko Mikulicic 0:c0ecb8bf28eb 644 #endif
Marko Mikulicic 0:c0ecb8bf28eb 645
Marko Mikulicic 0:c0ecb8bf28eb 646 /* TI's libc does not have stat & friends, add them. */
Marko Mikulicic 0:c0ecb8bf28eb 647 #ifdef __TI_COMPILER_VERSION__
Marko Mikulicic 0:c0ecb8bf28eb 648
Marko Mikulicic 0:c0ecb8bf28eb 649 #include <file.h>
Marko Mikulicic 0:c0ecb8bf28eb 650
Marko Mikulicic 0:c0ecb8bf28eb 651 typedef unsigned int mode_t;
Marko Mikulicic 0:c0ecb8bf28eb 652 typedef size_t _off_t;
Marko Mikulicic 0:c0ecb8bf28eb 653 typedef long ssize_t;
Marko Mikulicic 0:c0ecb8bf28eb 654
Marko Mikulicic 0:c0ecb8bf28eb 655 struct stat {
Marko Mikulicic 0:c0ecb8bf28eb 656 int st_ino;
Marko Mikulicic 0:c0ecb8bf28eb 657 mode_t st_mode;
Marko Mikulicic 0:c0ecb8bf28eb 658 int st_nlink;
Marko Mikulicic 0:c0ecb8bf28eb 659 time_t st_mtime;
Marko Mikulicic 0:c0ecb8bf28eb 660 off_t st_size;
Marko Mikulicic 0:c0ecb8bf28eb 661 };
Marko Mikulicic 0:c0ecb8bf28eb 662
Marko Mikulicic 0:c0ecb8bf28eb 663 int _stat(const char *pathname, struct stat *st);
Marko Mikulicic 0:c0ecb8bf28eb 664 #define stat(a, b) _stat(a, b)
Marko Mikulicic 0:c0ecb8bf28eb 665
Marko Mikulicic 0:c0ecb8bf28eb 666 #define __S_IFMT 0170000
Marko Mikulicic 0:c0ecb8bf28eb 667
Marko Mikulicic 0:c0ecb8bf28eb 668 #define __S_IFDIR 0040000
Marko Mikulicic 0:c0ecb8bf28eb 669 #define __S_IFCHR 0020000
Marko Mikulicic 0:c0ecb8bf28eb 670 #define __S_IFREG 0100000
Marko Mikulicic 0:c0ecb8bf28eb 671
Marko Mikulicic 0:c0ecb8bf28eb 672 #define __S_ISTYPE(mode, mask) (((mode) &__S_IFMT) == (mask))
Marko Mikulicic 0:c0ecb8bf28eb 673
Marko Mikulicic 0:c0ecb8bf28eb 674 #define S_IFDIR __S_IFDIR
Marko Mikulicic 0:c0ecb8bf28eb 675 #define S_IFCHR __S_IFCHR
Marko Mikulicic 0:c0ecb8bf28eb 676 #define S_IFREG __S_IFREG
Marko Mikulicic 0:c0ecb8bf28eb 677 #define S_ISDIR(mode) __S_ISTYPE((mode), __S_IFDIR)
Marko Mikulicic 0:c0ecb8bf28eb 678 #define S_ISREG(mode) __S_ISTYPE((mode), __S_IFREG)
Marko Mikulicic 0:c0ecb8bf28eb 679
Marko Mikulicic 0:c0ecb8bf28eb 680 /* As of 5.2.7, TI compiler does not support va_copy() yet. */
Marko Mikulicic 0:c0ecb8bf28eb 681 #define va_copy(apc, ap) ((apc) = (ap))
Marko Mikulicic 0:c0ecb8bf28eb 682
Marko Mikulicic 0:c0ecb8bf28eb 683 #endif /* __TI_COMPILER_VERSION__ */
Marko Mikulicic 0:c0ecb8bf28eb 684
Marko Mikulicic 0:c0ecb8bf28eb 685 #ifdef CC3200_FS_SPIFFS
Marko Mikulicic 0:c0ecb8bf28eb 686 #include <common/spiffs/spiffs.h>
Marko Mikulicic 0:c0ecb8bf28eb 687
Marko Mikulicic 0:c0ecb8bf28eb 688 typedef struct {
Marko Mikulicic 0:c0ecb8bf28eb 689 spiffs_DIR dh;
Marko Mikulicic 0:c0ecb8bf28eb 690 struct spiffs_dirent de;
Marko Mikulicic 0:c0ecb8bf28eb 691 } DIR;
Marko Mikulicic 0:c0ecb8bf28eb 692
Marko Mikulicic 0:c0ecb8bf28eb 693 #define d_name name
Marko Mikulicic 0:c0ecb8bf28eb 694 #define dirent spiffs_dirent
Marko Mikulicic 0:c0ecb8bf28eb 695
Marko Mikulicic 0:c0ecb8bf28eb 696 DIR *opendir(const char *dir_name);
Marko Mikulicic 0:c0ecb8bf28eb 697 int closedir(DIR *dir);
Marko Mikulicic 0:c0ecb8bf28eb 698 struct dirent *readdir(DIR *dir);
Marko Mikulicic 0:c0ecb8bf28eb 699 #endif /* CC3200_FS_SPIFFS */
Marko Mikulicic 0:c0ecb8bf28eb 700
Marko Mikulicic 0:c0ecb8bf28eb 701 #ifdef CC3200_FS_SLFS
Marko Mikulicic 0:c0ecb8bf28eb 702 #define MG_FS_SLFS
Marko Mikulicic 0:c0ecb8bf28eb 703 #endif
Marko Mikulicic 0:c0ecb8bf28eb 704
Marko Mikulicic 0:c0ecb8bf28eb 705 #ifdef __cplusplus
Marko Mikulicic 0:c0ecb8bf28eb 706 }
Marko Mikulicic 0:c0ecb8bf28eb 707 #endif
Marko Mikulicic 0:c0ecb8bf28eb 708
Marko Mikulicic 0:c0ecb8bf28eb 709 #endif /* CS_PLATFORM == CS_P_CC3200 */
Marko Mikulicic 0:c0ecb8bf28eb 710 #endif /* CS_COMMON_PLATFORMS_PLATFORM_CC3200_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 711 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 712 #line 1 "common/platforms/platform_cc3100.h"
Marko Mikulicic 0:c0ecb8bf28eb 713 #endif
Marko Mikulicic 0:c0ecb8bf28eb 714 /*
Marko Mikulicic 0:c0ecb8bf28eb 715 * Copyright (c) 2014-2016 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 716 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 717 */
Marko Mikulicic 0:c0ecb8bf28eb 718
Marko Mikulicic 0:c0ecb8bf28eb 719 #ifndef CS_COMMON_PLATFORMS_PLATFORM_CC3100_H_
Marko Mikulicic 0:c0ecb8bf28eb 720 #define CS_COMMON_PLATFORMS_PLATFORM_CC3100_H_
Marko Mikulicic 0:c0ecb8bf28eb 721 #if CS_PLATFORM == CS_P_CC3100
Marko Mikulicic 0:c0ecb8bf28eb 722
Marko Mikulicic 0:c0ecb8bf28eb 723 #include <assert.h>
Marko Mikulicic 0:c0ecb8bf28eb 724 #include <ctype.h>
Marko Mikulicic 0:c0ecb8bf28eb 725 #include <errno.h>
Marko Mikulicic 0:c0ecb8bf28eb 726 #include <inttypes.h>
Marko Mikulicic 0:c0ecb8bf28eb 727 #include <stdint.h>
Marko Mikulicic 0:c0ecb8bf28eb 728 #include <string.h>
Marko Mikulicic 0:c0ecb8bf28eb 729 #include <time.h>
Marko Mikulicic 0:c0ecb8bf28eb 730
Marko Mikulicic 0:c0ecb8bf28eb 731 #define MG_SOCKET_SIMPLELINK 1
Marko Mikulicic 0:c0ecb8bf28eb 732 #define MG_DISABLE_SOCKETPAIR 1
Marko Mikulicic 0:c0ecb8bf28eb 733 #define MG_DISABLE_SYNC_RESOLVER 1
Marko Mikulicic 0:c0ecb8bf28eb 734 #define MG_DISABLE_POPEN 1
Marko Mikulicic 0:c0ecb8bf28eb 735 #define MG_DISABLE_CGI 1
Marko Mikulicic 0:c0ecb8bf28eb 736 #define MG_DISABLE_DAV 1
Marko Mikulicic 0:c0ecb8bf28eb 737 #define MG_DISABLE_DIRECTORY_LISTING 1
Marko Mikulicic 0:c0ecb8bf28eb 738 #define MG_DISABLE_FILESYSTEM 1
Marko Mikulicic 0:c0ecb8bf28eb 739
Marko Mikulicic 0:c0ecb8bf28eb 740 /*
Marko Mikulicic 0:c0ecb8bf28eb 741 * CC3100 SDK and STM32 SDK include headers w/out path, just like
Marko Mikulicic 0:c0ecb8bf28eb 742 * #include "simplelink.h". As result, we have to add all required directories
Marko Mikulicic 0:c0ecb8bf28eb 743 * into Makefile IPATH and do the same thing (include w/out path)
Marko Mikulicic 0:c0ecb8bf28eb 744 */
Marko Mikulicic 0:c0ecb8bf28eb 745
Marko Mikulicic 0:c0ecb8bf28eb 746 #include <simplelink.h>
Marko Mikulicic 0:c0ecb8bf28eb 747 #include <netapp.h>
Marko Mikulicic 0:c0ecb8bf28eb 748 #undef timeval
Marko Mikulicic 0:c0ecb8bf28eb 749
Marko Mikulicic 0:c0ecb8bf28eb 750 typedef int sock_t;
Marko Mikulicic 0:c0ecb8bf28eb 751 #define INVALID_SOCKET (-1)
Marko Mikulicic 0:c0ecb8bf28eb 752
Marko Mikulicic 0:c0ecb8bf28eb 753 #define to64(x) strtoll(x, NULL, 10)
Marko Mikulicic 0:c0ecb8bf28eb 754 #define INT64_FMT PRId64
Marko Mikulicic 0:c0ecb8bf28eb 755 #define INT64_X_FMT PRIx64
Marko Mikulicic 0:c0ecb8bf28eb 756 #define SIZE_T_FMT "u"
Marko Mikulicic 0:c0ecb8bf28eb 757
Marko Mikulicic 0:c0ecb8bf28eb 758 #define SOMAXCONN 8
Marko Mikulicic 0:c0ecb8bf28eb 759
Marko Mikulicic 0:c0ecb8bf28eb 760 const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
Marko Mikulicic 0:c0ecb8bf28eb 761 char *inet_ntoa(struct in_addr in);
Marko Mikulicic 0:c0ecb8bf28eb 762 int inet_pton(int af, const char *src, void *dst);
Marko Mikulicic 0:c0ecb8bf28eb 763
Marko Mikulicic 0:c0ecb8bf28eb 764 #endif /* CS_PLATFORM == CS_P_CC3100 */
Marko Mikulicic 0:c0ecb8bf28eb 765 #endif /* CS_COMMON_PLATFORMS_PLATFORM_CC3100_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 766 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 767 #line 1 "common/str_util.h"
Marko Mikulicic 0:c0ecb8bf28eb 768 #endif
Marko Mikulicic 0:c0ecb8bf28eb 769 /*
Marko Mikulicic 0:c0ecb8bf28eb 770 * Copyright (c) 2015 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 771 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 772 */
Marko Mikulicic 0:c0ecb8bf28eb 773
Marko Mikulicic 0:c0ecb8bf28eb 774 #ifndef CS_COMMON_STR_UTIL_H_
Marko Mikulicic 0:c0ecb8bf28eb 775 #define CS_COMMON_STR_UTIL_H_
Marko Mikulicic 0:c0ecb8bf28eb 776
Marko Mikulicic 0:c0ecb8bf28eb 777 #include <stdarg.h>
Marko Mikulicic 0:c0ecb8bf28eb 778 #include <stdlib.h>
Marko Mikulicic 0:c0ecb8bf28eb 779
Marko Mikulicic 0:c0ecb8bf28eb 780 #ifdef __cplusplus
Marko Mikulicic 0:c0ecb8bf28eb 781 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 782 #endif
Marko Mikulicic 0:c0ecb8bf28eb 783
Marko Mikulicic 0:c0ecb8bf28eb 784 size_t c_strnlen(const char *s, size_t maxlen);
Marko Mikulicic 0:c0ecb8bf28eb 785 int c_snprintf(char *buf, size_t buf_size, const char *format, ...);
Marko Mikulicic 0:c0ecb8bf28eb 786 int c_vsnprintf(char *buf, size_t buf_size, const char *format, va_list ap);
Marko Mikulicic 0:c0ecb8bf28eb 787 /*
Marko Mikulicic 0:c0ecb8bf28eb 788 * Find the first occurrence of find in s, where the search is limited to the
Marko Mikulicic 0:c0ecb8bf28eb 789 * first slen characters of s.
Marko Mikulicic 0:c0ecb8bf28eb 790 */
Marko Mikulicic 0:c0ecb8bf28eb 791 const char *c_strnstr(const char *s, const char *find, size_t slen);
Marko Mikulicic 0:c0ecb8bf28eb 792
Marko Mikulicic 0:c0ecb8bf28eb 793 #ifdef __cplusplus
Marko Mikulicic 0:c0ecb8bf28eb 794 }
Marko Mikulicic 0:c0ecb8bf28eb 795 #endif
Marko Mikulicic 0:c0ecb8bf28eb 796
Marko Mikulicic 0:c0ecb8bf28eb 797 #endif /* CS_COMMON_STR_UTIL_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 798 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 799 #line 1 "common/utf.h"
Marko Mikulicic 0:c0ecb8bf28eb 800 #endif
Marko Mikulicic 0:c0ecb8bf28eb 801 /*
Marko Mikulicic 0:c0ecb8bf28eb 802 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 803 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 804 */
Marko Mikulicic 0:c0ecb8bf28eb 805
Marko Mikulicic 0:c0ecb8bf28eb 806 #ifndef CS_COMMON_UTF_H_
Marko Mikulicic 0:c0ecb8bf28eb 807 #define CS_COMMON_UTF_H_
Marko Mikulicic 0:c0ecb8bf28eb 808
Marko Mikulicic 0:c0ecb8bf28eb 809 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 810 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 811 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 812
Marko Mikulicic 0:c0ecb8bf28eb 813 typedef unsigned char uchar;
Marko Mikulicic 0:c0ecb8bf28eb 814
Marko Mikulicic 0:c0ecb8bf28eb 815 typedef unsigned short Rune; /* 16 bits */
Marko Mikulicic 0:c0ecb8bf28eb 816
Marko Mikulicic 0:c0ecb8bf28eb 817 #define nelem(a) (sizeof(a) / sizeof(a)[0])
Marko Mikulicic 0:c0ecb8bf28eb 818
Marko Mikulicic 0:c0ecb8bf28eb 819 enum {
Marko Mikulicic 0:c0ecb8bf28eb 820 UTFmax = 3, /* maximum bytes per rune */
Marko Mikulicic 0:c0ecb8bf28eb 821 Runesync = 0x80, /* cannot represent part of a UTF sequence (<) */
Marko Mikulicic 0:c0ecb8bf28eb 822 Runeself = 0x80, /* rune and UTF sequences are the same (<) */
Marko Mikulicic 0:c0ecb8bf28eb 823 Runeerror = 0xFFFD /* decoding error in UTF */
Marko Mikulicic 0:c0ecb8bf28eb 824 /* Runemax = 0xFFFC */ /* maximum rune value */
Marko Mikulicic 0:c0ecb8bf28eb 825 };
Marko Mikulicic 0:c0ecb8bf28eb 826
Marko Mikulicic 0:c0ecb8bf28eb 827 /* Edit .+1,/^$/ | cfn $PLAN9/src/lib9/utf/?*.c | grep -v static |grep -v __ */
Marko Mikulicic 0:c0ecb8bf28eb 828 int chartorune(Rune *rune, const char *str);
Marko Mikulicic 0:c0ecb8bf28eb 829 int fullrune(const char *str, int n);
Marko Mikulicic 0:c0ecb8bf28eb 830 int isdigitrune(Rune c);
Marko Mikulicic 0:c0ecb8bf28eb 831 int isnewline(Rune c);
Marko Mikulicic 0:c0ecb8bf28eb 832 int iswordchar(Rune c);
Marko Mikulicic 0:c0ecb8bf28eb 833 int isalpharune(Rune c);
Marko Mikulicic 0:c0ecb8bf28eb 834 int islowerrune(Rune c);
Marko Mikulicic 0:c0ecb8bf28eb 835 int isspacerune(Rune c);
Marko Mikulicic 0:c0ecb8bf28eb 836 int isupperrune(Rune c);
Marko Mikulicic 0:c0ecb8bf28eb 837 int runetochar(char *str, Rune *rune);
Marko Mikulicic 0:c0ecb8bf28eb 838 Rune tolowerrune(Rune c);
Marko Mikulicic 0:c0ecb8bf28eb 839 Rune toupperrune(Rune c);
Marko Mikulicic 0:c0ecb8bf28eb 840 int utfnlen(const char *s, long m);
Marko Mikulicic 0:c0ecb8bf28eb 841 const char *utfnshift(const char *s, long m);
Marko Mikulicic 0:c0ecb8bf28eb 842
Marko Mikulicic 0:c0ecb8bf28eb 843 #if 0 /* Not implemented. */
Marko Mikulicic 0:c0ecb8bf28eb 844 int istitlerune(Rune c);
Marko Mikulicic 0:c0ecb8bf28eb 845 int runelen(Rune c);
Marko Mikulicic 0:c0ecb8bf28eb 846 int runenlen(Rune *r, int nrune);
Marko Mikulicic 0:c0ecb8bf28eb 847 Rune *runestrcat(Rune *s1, Rune *s2);
Marko Mikulicic 0:c0ecb8bf28eb 848 Rune *runestrchr(Rune *s, Rune c);
Marko Mikulicic 0:c0ecb8bf28eb 849 Rune *runestrcpy(Rune *s1, Rune *s2);
Marko Mikulicic 0:c0ecb8bf28eb 850 Rune *runestrdup(Rune *s);
Marko Mikulicic 0:c0ecb8bf28eb 851 Rune *runestrecpy(Rune *s1, Rune *es1, Rune *s2);
Marko Mikulicic 0:c0ecb8bf28eb 852 int runestrcmp(Rune *s1, Rune *s2);
Marko Mikulicic 0:c0ecb8bf28eb 853 long runestrlen(Rune *s);
Marko Mikulicic 0:c0ecb8bf28eb 854 Rune *runestrncat(Rune *s1, Rune *s2, long n);
Marko Mikulicic 0:c0ecb8bf28eb 855 int runestrncmp(Rune *s1, Rune *s2, long n);
Marko Mikulicic 0:c0ecb8bf28eb 856 Rune *runestrncpy(Rune *s1, Rune *s2, long n);
Marko Mikulicic 0:c0ecb8bf28eb 857 Rune *runestrrchr(Rune *s, Rune c);
Marko Mikulicic 0:c0ecb8bf28eb 858 Rune *runestrstr(Rune *s1, Rune *s2);
Marko Mikulicic 0:c0ecb8bf28eb 859 Rune totitlerune(Rune c);
Marko Mikulicic 0:c0ecb8bf28eb 860 char *utfecpy(char *to, char *e, char *from);
Marko Mikulicic 0:c0ecb8bf28eb 861 int utflen(char *s);
Marko Mikulicic 0:c0ecb8bf28eb 862 char *utfrrune(char *s, long c);
Marko Mikulicic 0:c0ecb8bf28eb 863 char *utfrune(char *s, long c);
Marko Mikulicic 0:c0ecb8bf28eb 864 char *utfutf(char *s1, char *s2);
Marko Mikulicic 0:c0ecb8bf28eb 865 #endif
Marko Mikulicic 0:c0ecb8bf28eb 866
Marko Mikulicic 0:c0ecb8bf28eb 867 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 868 }
Marko Mikulicic 0:c0ecb8bf28eb 869 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 870 #endif /* CS_COMMON_UTF_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 871 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 872 #line 1 "common/base64.h"
Marko Mikulicic 0:c0ecb8bf28eb 873 #endif
Marko Mikulicic 0:c0ecb8bf28eb 874 /*
Marko Mikulicic 0:c0ecb8bf28eb 875 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 876 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 877 */
Marko Mikulicic 0:c0ecb8bf28eb 878
Marko Mikulicic 0:c0ecb8bf28eb 879 #ifndef CS_COMMON_BASE64_H_
Marko Mikulicic 0:c0ecb8bf28eb 880 #define CS_COMMON_BASE64_H_
Marko Mikulicic 0:c0ecb8bf28eb 881
Marko Mikulicic 0:c0ecb8bf28eb 882 #ifndef DISABLE_BASE64
Marko Mikulicic 0:c0ecb8bf28eb 883
Marko Mikulicic 0:c0ecb8bf28eb 884 #include <stdio.h>
Marko Mikulicic 0:c0ecb8bf28eb 885
Marko Mikulicic 0:c0ecb8bf28eb 886 #ifdef __cplusplus
Marko Mikulicic 0:c0ecb8bf28eb 887 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 888 #endif
Marko Mikulicic 0:c0ecb8bf28eb 889
Marko Mikulicic 0:c0ecb8bf28eb 890 typedef void (*cs_base64_putc_t)(char, void *);
Marko Mikulicic 0:c0ecb8bf28eb 891
Marko Mikulicic 0:c0ecb8bf28eb 892 struct cs_base64_ctx {
Marko Mikulicic 0:c0ecb8bf28eb 893 /* cannot call it putc because it's a macro on some environments */
Marko Mikulicic 0:c0ecb8bf28eb 894 cs_base64_putc_t b64_putc;
Marko Mikulicic 0:c0ecb8bf28eb 895 unsigned char chunk[3];
Marko Mikulicic 0:c0ecb8bf28eb 896 int chunk_size;
Marko Mikulicic 0:c0ecb8bf28eb 897 void *user_data;
Marko Mikulicic 0:c0ecb8bf28eb 898 };
Marko Mikulicic 0:c0ecb8bf28eb 899
Marko Mikulicic 0:c0ecb8bf28eb 900 void cs_base64_init(struct cs_base64_ctx *ctx, cs_base64_putc_t putc,
Marko Mikulicic 0:c0ecb8bf28eb 901 void *user_data);
Marko Mikulicic 0:c0ecb8bf28eb 902 void cs_base64_update(struct cs_base64_ctx *ctx, const char *str, size_t len);
Marko Mikulicic 0:c0ecb8bf28eb 903 void cs_base64_finish(struct cs_base64_ctx *ctx);
Marko Mikulicic 0:c0ecb8bf28eb 904
Marko Mikulicic 0:c0ecb8bf28eb 905 void cs_base64_encode(const unsigned char *src, int src_len, char *dst);
Marko Mikulicic 0:c0ecb8bf28eb 906 void cs_fprint_base64(FILE *f, const unsigned char *src, int src_len);
Marko Mikulicic 0:c0ecb8bf28eb 907 int cs_base64_decode(const unsigned char *s, int len, char *dst);
Marko Mikulicic 0:c0ecb8bf28eb 908
Marko Mikulicic 0:c0ecb8bf28eb 909 #ifdef __cplusplus
Marko Mikulicic 0:c0ecb8bf28eb 910 }
Marko Mikulicic 0:c0ecb8bf28eb 911 #endif
Marko Mikulicic 0:c0ecb8bf28eb 912
Marko Mikulicic 0:c0ecb8bf28eb 913 #endif /* DISABLE_BASE64 */
Marko Mikulicic 0:c0ecb8bf28eb 914
Marko Mikulicic 0:c0ecb8bf28eb 915 #endif /* CS_COMMON_BASE64_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 916 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 917 #line 1 "common/md5.h"
Marko Mikulicic 0:c0ecb8bf28eb 918 #endif
Marko Mikulicic 0:c0ecb8bf28eb 919 /*
Marko Mikulicic 0:c0ecb8bf28eb 920 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 921 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 922 */
Marko Mikulicic 0:c0ecb8bf28eb 923
Marko Mikulicic 0:c0ecb8bf28eb 924 #ifndef CS_COMMON_MD5_H_
Marko Mikulicic 0:c0ecb8bf28eb 925 #define CS_COMMON_MD5_H_
Marko Mikulicic 0:c0ecb8bf28eb 926
Marko Mikulicic 0:c0ecb8bf28eb 927 /* Amalgamated: #include "common/platform.h" */
Marko Mikulicic 0:c0ecb8bf28eb 928
Marko Mikulicic 0:c0ecb8bf28eb 929 #ifdef __cplusplus
Marko Mikulicic 0:c0ecb8bf28eb 930 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 931 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 932
Marko Mikulicic 0:c0ecb8bf28eb 933 typedef struct MD5Context {
Marko Mikulicic 0:c0ecb8bf28eb 934 uint32_t buf[4];
Marko Mikulicic 0:c0ecb8bf28eb 935 uint32_t bits[2];
Marko Mikulicic 0:c0ecb8bf28eb 936 unsigned char in[64];
Marko Mikulicic 0:c0ecb8bf28eb 937 } MD5_CTX;
Marko Mikulicic 0:c0ecb8bf28eb 938
Marko Mikulicic 0:c0ecb8bf28eb 939 void MD5_Init(MD5_CTX *c);
Marko Mikulicic 0:c0ecb8bf28eb 940 void MD5_Update(MD5_CTX *c, const unsigned char *data, size_t len);
Marko Mikulicic 0:c0ecb8bf28eb 941 void MD5_Final(unsigned char *md, MD5_CTX *c);
Marko Mikulicic 0:c0ecb8bf28eb 942
Marko Mikulicic 0:c0ecb8bf28eb 943 /*
Marko Mikulicic 0:c0ecb8bf28eb 944 * Return stringified MD5 hash for NULL terminated list of pointer/length pairs.
Marko Mikulicic 0:c0ecb8bf28eb 945 * A length should be specified as size_t variable.
Marko Mikulicic 0:c0ecb8bf28eb 946 * Example:
Marko Mikulicic 0:c0ecb8bf28eb 947 *
Marko Mikulicic 0:c0ecb8bf28eb 948 * char buf[33];
Marko Mikulicic 0:c0ecb8bf28eb 949 * cs_md5(buf, "foo", (size_t) 3, "bar", (size_t) 3, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 950 */
Marko Mikulicic 0:c0ecb8bf28eb 951 char *cs_md5(char buf[33], ...);
Marko Mikulicic 0:c0ecb8bf28eb 952
Marko Mikulicic 0:c0ecb8bf28eb 953 /*
Marko Mikulicic 0:c0ecb8bf28eb 954 * Stringify binary data. Output buffer size must be 2 * size_of_input + 1
Marko Mikulicic 0:c0ecb8bf28eb 955 * because each byte of input takes 2 bytes in string representation
Marko Mikulicic 0:c0ecb8bf28eb 956 * plus 1 byte for the terminating \0 character.
Marko Mikulicic 0:c0ecb8bf28eb 957 */
Marko Mikulicic 0:c0ecb8bf28eb 958 void cs_to_hex(char *to, const unsigned char *p, size_t len);
Marko Mikulicic 0:c0ecb8bf28eb 959
Marko Mikulicic 0:c0ecb8bf28eb 960 #ifdef __cplusplus
Marko Mikulicic 0:c0ecb8bf28eb 961 }
Marko Mikulicic 0:c0ecb8bf28eb 962 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 963
Marko Mikulicic 0:c0ecb8bf28eb 964 #endif /* CS_COMMON_MD5_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 965 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 966 #line 1 "common/sha1.h"
Marko Mikulicic 0:c0ecb8bf28eb 967 #endif
Marko Mikulicic 0:c0ecb8bf28eb 968 /*
Marko Mikulicic 0:c0ecb8bf28eb 969 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 970 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 971 */
Marko Mikulicic 0:c0ecb8bf28eb 972
Marko Mikulicic 0:c0ecb8bf28eb 973 #ifndef CS_COMMON_SHA1_H_
Marko Mikulicic 0:c0ecb8bf28eb 974 #define CS_COMMON_SHA1_H_
Marko Mikulicic 0:c0ecb8bf28eb 975
Marko Mikulicic 0:c0ecb8bf28eb 976 #ifndef DISABLE_SHA1
Marko Mikulicic 0:c0ecb8bf28eb 977
Marko Mikulicic 0:c0ecb8bf28eb 978 /* Amalgamated: #include "common/platform.h" */
Marko Mikulicic 0:c0ecb8bf28eb 979
Marko Mikulicic 0:c0ecb8bf28eb 980 #ifdef __cplusplus
Marko Mikulicic 0:c0ecb8bf28eb 981 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 982 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 983
Marko Mikulicic 0:c0ecb8bf28eb 984 typedef struct {
Marko Mikulicic 0:c0ecb8bf28eb 985 uint32_t state[5];
Marko Mikulicic 0:c0ecb8bf28eb 986 uint32_t count[2];
Marko Mikulicic 0:c0ecb8bf28eb 987 unsigned char buffer[64];
Marko Mikulicic 0:c0ecb8bf28eb 988 } cs_sha1_ctx;
Marko Mikulicic 0:c0ecb8bf28eb 989
Marko Mikulicic 0:c0ecb8bf28eb 990 void cs_sha1_init(cs_sha1_ctx *);
Marko Mikulicic 0:c0ecb8bf28eb 991 void cs_sha1_update(cs_sha1_ctx *, const unsigned char *data, uint32_t len);
Marko Mikulicic 0:c0ecb8bf28eb 992 void cs_sha1_final(unsigned char digest[20], cs_sha1_ctx *);
Marko Mikulicic 0:c0ecb8bf28eb 993 void cs_hmac_sha1(const unsigned char *key, size_t key_len,
Marko Mikulicic 0:c0ecb8bf28eb 994 const unsigned char *text, size_t text_len,
Marko Mikulicic 0:c0ecb8bf28eb 995 unsigned char out[20]);
Marko Mikulicic 0:c0ecb8bf28eb 996 #ifdef __cplusplus
Marko Mikulicic 0:c0ecb8bf28eb 997 }
Marko Mikulicic 0:c0ecb8bf28eb 998 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 999
Marko Mikulicic 0:c0ecb8bf28eb 1000 #endif /* DISABLE_SHA1 */
Marko Mikulicic 0:c0ecb8bf28eb 1001
Marko Mikulicic 0:c0ecb8bf28eb 1002 #endif /* CS_COMMON_SHA1_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 1003 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 1004 #line 1 "common/cs_dirent.h"
Marko Mikulicic 0:c0ecb8bf28eb 1005 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1006 /*
Marko Mikulicic 0:c0ecb8bf28eb 1007 * Copyright (c) 2014-2016 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 1008 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 1009 */
Marko Mikulicic 0:c0ecb8bf28eb 1010
Marko Mikulicic 0:c0ecb8bf28eb 1011 #ifndef CS_COMMON_CS_DIRENT_H_
Marko Mikulicic 0:c0ecb8bf28eb 1012 #define CS_COMMON_CS_DIRENT_H_
Marko Mikulicic 0:c0ecb8bf28eb 1013
Marko Mikulicic 0:c0ecb8bf28eb 1014 #ifdef __cplusplus
Marko Mikulicic 0:c0ecb8bf28eb 1015 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 1016 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 1017
Marko Mikulicic 0:c0ecb8bf28eb 1018 #ifdef CS_ENABLE_SPIFFS
Marko Mikulicic 0:c0ecb8bf28eb 1019
Marko Mikulicic 0:c0ecb8bf28eb 1020 #include <spiffs.h>
Marko Mikulicic 0:c0ecb8bf28eb 1021
Marko Mikulicic 0:c0ecb8bf28eb 1022 typedef struct {
Marko Mikulicic 0:c0ecb8bf28eb 1023 spiffs_DIR dh;
Marko Mikulicic 0:c0ecb8bf28eb 1024 struct spiffs_dirent de;
Marko Mikulicic 0:c0ecb8bf28eb 1025 } DIR;
Marko Mikulicic 0:c0ecb8bf28eb 1026
Marko Mikulicic 0:c0ecb8bf28eb 1027 #define d_name name
Marko Mikulicic 0:c0ecb8bf28eb 1028 #define dirent spiffs_dirent
Marko Mikulicic 0:c0ecb8bf28eb 1029
Marko Mikulicic 0:c0ecb8bf28eb 1030 int rmdir(const char *path);
Marko Mikulicic 0:c0ecb8bf28eb 1031 int mkdir(const char *path, mode_t mode);
Marko Mikulicic 0:c0ecb8bf28eb 1032
Marko Mikulicic 0:c0ecb8bf28eb 1033 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1034
Marko Mikulicic 0:c0ecb8bf28eb 1035 #if defined(_WIN32)
Marko Mikulicic 0:c0ecb8bf28eb 1036 struct dirent {
Marko Mikulicic 0:c0ecb8bf28eb 1037 char d_name[MAX_PATH];
Marko Mikulicic 0:c0ecb8bf28eb 1038 };
Marko Mikulicic 0:c0ecb8bf28eb 1039
Marko Mikulicic 0:c0ecb8bf28eb 1040 typedef struct DIR {
Marko Mikulicic 0:c0ecb8bf28eb 1041 HANDLE handle;
Marko Mikulicic 0:c0ecb8bf28eb 1042 WIN32_FIND_DATAW info;
Marko Mikulicic 0:c0ecb8bf28eb 1043 struct dirent result;
Marko Mikulicic 0:c0ecb8bf28eb 1044 } DIR;
Marko Mikulicic 0:c0ecb8bf28eb 1045 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1046
Marko Mikulicic 0:c0ecb8bf28eb 1047 #if defined(_WIN32) || defined(CS_ENABLE_SPIFFS)
Marko Mikulicic 0:c0ecb8bf28eb 1048 DIR *opendir(const char *dir_name);
Marko Mikulicic 0:c0ecb8bf28eb 1049 int closedir(DIR *dir);
Marko Mikulicic 0:c0ecb8bf28eb 1050 struct dirent *readdir(DIR *dir);
Marko Mikulicic 0:c0ecb8bf28eb 1051 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1052
Marko Mikulicic 0:c0ecb8bf28eb 1053 #ifdef __cplusplus
Marko Mikulicic 0:c0ecb8bf28eb 1054 }
Marko Mikulicic 0:c0ecb8bf28eb 1055 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 1056
Marko Mikulicic 0:c0ecb8bf28eb 1057 #endif /* CS_COMMON_CS_DIRENT_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 1058 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 1059 #line 1 "common/cs_file.h"
Marko Mikulicic 0:c0ecb8bf28eb 1060 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1061 /*
Marko Mikulicic 0:c0ecb8bf28eb 1062 * Copyright (c) 2015 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 1063 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 1064 */
Marko Mikulicic 0:c0ecb8bf28eb 1065
Marko Mikulicic 0:c0ecb8bf28eb 1066 #ifndef CS_COMMON_CS_FILE_H_
Marko Mikulicic 0:c0ecb8bf28eb 1067 #define CS_COMMON_CS_FILE_H_
Marko Mikulicic 0:c0ecb8bf28eb 1068
Marko Mikulicic 0:c0ecb8bf28eb 1069 /* Amalgamated: #include "common/platform.h" */
Marko Mikulicic 0:c0ecb8bf28eb 1070
Marko Mikulicic 0:c0ecb8bf28eb 1071 #ifdef __cplusplus
Marko Mikulicic 0:c0ecb8bf28eb 1072 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 1073 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 1074
Marko Mikulicic 0:c0ecb8bf28eb 1075 /*
Marko Mikulicic 0:c0ecb8bf28eb 1076 * Read whole file `path` in memory. It is responsibility of the caller
Marko Mikulicic 0:c0ecb8bf28eb 1077 * to `free()` allocated memory. File content is guaranteed to be
Marko Mikulicic 0:c0ecb8bf28eb 1078 * '\0'-terminated. File size is returned in `size` variable, which does not
Marko Mikulicic 0:c0ecb8bf28eb 1079 * count terminating `\0`.
Marko Mikulicic 0:c0ecb8bf28eb 1080 * Return: allocated memory, or NULL on error.
Marko Mikulicic 0:c0ecb8bf28eb 1081 */
Marko Mikulicic 0:c0ecb8bf28eb 1082 char *cs_read_file(const char *path, size_t *size);
Marko Mikulicic 0:c0ecb8bf28eb 1083
Marko Mikulicic 0:c0ecb8bf28eb 1084 #ifdef CS_MMAP
Marko Mikulicic 0:c0ecb8bf28eb 1085 char *cs_mmap_file(const char *path, size_t *size);
Marko Mikulicic 0:c0ecb8bf28eb 1086 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1087
Marko Mikulicic 0:c0ecb8bf28eb 1088 #ifdef __cplusplus
Marko Mikulicic 0:c0ecb8bf28eb 1089 }
Marko Mikulicic 0:c0ecb8bf28eb 1090 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 1091
Marko Mikulicic 0:c0ecb8bf28eb 1092 #endif /* CS_COMMON_CS_FILE_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 1093 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 1094 #line 1 "common/coroutine.h"
Marko Mikulicic 0:c0ecb8bf28eb 1095 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1096 /*
Marko Mikulicic 0:c0ecb8bf28eb 1097 * Copyright (c) 2015 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 1098 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 1099 */
Marko Mikulicic 0:c0ecb8bf28eb 1100
Marko Mikulicic 0:c0ecb8bf28eb 1101 /*
Marko Mikulicic 0:c0ecb8bf28eb 1102 * Module that provides generic macros and functions to implement "coroutines",
Marko Mikulicic 0:c0ecb8bf28eb 1103 * i.e. C code that uses `mbuf` as a stack for function calls.
Marko Mikulicic 0:c0ecb8bf28eb 1104 *
Marko Mikulicic 0:c0ecb8bf28eb 1105 * More info: see the design doc: https://goo.gl/kfcG61
Marko Mikulicic 0:c0ecb8bf28eb 1106 */
Marko Mikulicic 0:c0ecb8bf28eb 1107
Marko Mikulicic 0:c0ecb8bf28eb 1108 #ifndef CS_COMMON_COROUTINE_H_
Marko Mikulicic 0:c0ecb8bf28eb 1109 #define CS_COMMON_COROUTINE_H_
Marko Mikulicic 0:c0ecb8bf28eb 1110
Marko Mikulicic 0:c0ecb8bf28eb 1111 /* Amalgamated: #include "common/mbuf.h" */
Marko Mikulicic 0:c0ecb8bf28eb 1112 /* Amalgamated: #include "common/platform.h" */
Marko Mikulicic 0:c0ecb8bf28eb 1113
Marko Mikulicic 0:c0ecb8bf28eb 1114 /* user-defined union, this module only operates on the pointer */
Marko Mikulicic 0:c0ecb8bf28eb 1115 union user_arg_ret;
Marko Mikulicic 0:c0ecb8bf28eb 1116
Marko Mikulicic 0:c0ecb8bf28eb 1117 /*
Marko Mikulicic 0:c0ecb8bf28eb 1118 * Type that represents size of local function variables. We assume we'll never
Marko Mikulicic 0:c0ecb8bf28eb 1119 * need more than 255 bytes of stack frame.
Marko Mikulicic 0:c0ecb8bf28eb 1120 */
Marko Mikulicic 0:c0ecb8bf28eb 1121 typedef uint8_t cr_locals_size_t;
Marko Mikulicic 0:c0ecb8bf28eb 1122
Marko Mikulicic 0:c0ecb8bf28eb 1123 /*
Marko Mikulicic 0:c0ecb8bf28eb 1124 * Descriptor of a single function; const array of such descriptors should
Marko Mikulicic 0:c0ecb8bf28eb 1125 * be given to `cr_context_init()`
Marko Mikulicic 0:c0ecb8bf28eb 1126 */
Marko Mikulicic 0:c0ecb8bf28eb 1127 struct cr_func_desc {
Marko Mikulicic 0:c0ecb8bf28eb 1128 /*
Marko Mikulicic 0:c0ecb8bf28eb 1129 * Size of the function's data that should be stored on stack.
Marko Mikulicic 0:c0ecb8bf28eb 1130 *
Marko Mikulicic 0:c0ecb8bf28eb 1131 * NOTE: you should use `CR_LOCALS_SIZEOF(your_type)` instead of `sizeof()`,
Marko Mikulicic 0:c0ecb8bf28eb 1132 * since this value should be aligned by the word boundary, and
Marko Mikulicic 0:c0ecb8bf28eb 1133 * `CR_LOCALS_SIZEOF()` takes care of this.
Marko Mikulicic 0:c0ecb8bf28eb 1134 */
Marko Mikulicic 0:c0ecb8bf28eb 1135 cr_locals_size_t locals_size;
Marko Mikulicic 0:c0ecb8bf28eb 1136 };
Marko Mikulicic 0:c0ecb8bf28eb 1137
Marko Mikulicic 0:c0ecb8bf28eb 1138 enum cr_status {
Marko Mikulicic 0:c0ecb8bf28eb 1139 CR_RES__OK,
Marko Mikulicic 0:c0ecb8bf28eb 1140 CR_RES__OK_YIELDED,
Marko Mikulicic 0:c0ecb8bf28eb 1141
Marko Mikulicic 0:c0ecb8bf28eb 1142 CR_RES__ERR_STACK_OVERFLOW,
Marko Mikulicic 0:c0ecb8bf28eb 1143
Marko Mikulicic 0:c0ecb8bf28eb 1144 /* Underflow can only be caused by memory corruption or bug in CR */
Marko Mikulicic 0:c0ecb8bf28eb 1145 CR_RES__ERR_STACK_DATA_UNDERFLOW,
Marko Mikulicic 0:c0ecb8bf28eb 1146 /* Underflow can only be caused by memory corruption or bug in CR */
Marko Mikulicic 0:c0ecb8bf28eb 1147 CR_RES__ERR_STACK_CALL_UNDERFLOW,
Marko Mikulicic 0:c0ecb8bf28eb 1148
Marko Mikulicic 0:c0ecb8bf28eb 1149 CR_RES__ERR_UNCAUGHT_EXCEPTION,
Marko Mikulicic 0:c0ecb8bf28eb 1150 };
Marko Mikulicic 0:c0ecb8bf28eb 1151
Marko Mikulicic 0:c0ecb8bf28eb 1152 /* Context of the coroutine engine */
Marko Mikulicic 0:c0ecb8bf28eb 1153 struct cr_ctx {
Marko Mikulicic 0:c0ecb8bf28eb 1154 /*
Marko Mikulicic 0:c0ecb8bf28eb 1155 * id of the next "function" to call. If no function is going to be called,
Marko Mikulicic 0:c0ecb8bf28eb 1156 * it's CR_FID__NONE.
Marko Mikulicic 0:c0ecb8bf28eb 1157 */
Marko Mikulicic 0:c0ecb8bf28eb 1158 uint8_t called_fid;
Marko Mikulicic 0:c0ecb8bf28eb 1159
Marko Mikulicic 0:c0ecb8bf28eb 1160 /*
Marko Mikulicic 0:c0ecb8bf28eb 1161 * when `called_fid` is not `CR_FID__NONE`, this field holds called
Marko Mikulicic 0:c0ecb8bf28eb 1162 * function's stack frame size
Marko Mikulicic 0:c0ecb8bf28eb 1163 */
Marko Mikulicic 0:c0ecb8bf28eb 1164 size_t call_locals_size;
Marko Mikulicic 0:c0ecb8bf28eb 1165
Marko Mikulicic 0:c0ecb8bf28eb 1166 /*
Marko Mikulicic 0:c0ecb8bf28eb 1167 * when `called_fid` is not `CR_FID__NONE`, this field holds called
Marko Mikulicic 0:c0ecb8bf28eb 1168 * function's arguments size
Marko Mikulicic 0:c0ecb8bf28eb 1169 */
Marko Mikulicic 0:c0ecb8bf28eb 1170 size_t call_arg_size;
Marko Mikulicic 0:c0ecb8bf28eb 1171
Marko Mikulicic 0:c0ecb8bf28eb 1172 /*
Marko Mikulicic 0:c0ecb8bf28eb 1173 * pointer to the current function's locals.
Marko Mikulicic 0:c0ecb8bf28eb 1174 * Needed to make `CR_CUR_LOCALS_PT()` fast.
Marko Mikulicic 0:c0ecb8bf28eb 1175 */
Marko Mikulicic 0:c0ecb8bf28eb 1176 uint8_t *p_cur_func_locals;
Marko Mikulicic 0:c0ecb8bf28eb 1177
Marko Mikulicic 0:c0ecb8bf28eb 1178 /* data stack */
Marko Mikulicic 0:c0ecb8bf28eb 1179 struct mbuf stack_data;
Marko Mikulicic 0:c0ecb8bf28eb 1180
Marko Mikulicic 0:c0ecb8bf28eb 1181 /* return stack */
Marko Mikulicic 0:c0ecb8bf28eb 1182 struct mbuf stack_ret;
Marko Mikulicic 0:c0ecb8bf28eb 1183
Marko Mikulicic 0:c0ecb8bf28eb 1184 /* index of the current fid + 1 in return stack */
Marko Mikulicic 0:c0ecb8bf28eb 1185 size_t cur_fid_idx;
Marko Mikulicic 0:c0ecb8bf28eb 1186
Marko Mikulicic 0:c0ecb8bf28eb 1187 /* pointer to the array of function descriptors */
Marko Mikulicic 0:c0ecb8bf28eb 1188 const struct cr_func_desc *p_func_descrs;
Marko Mikulicic 0:c0ecb8bf28eb 1189
Marko Mikulicic 0:c0ecb8bf28eb 1190 /* thrown exception. If nothing is currently thrown, it's `CR_EXC_ID__NONE` */
Marko Mikulicic 0:c0ecb8bf28eb 1191 uint8_t thrown_exc;
Marko Mikulicic 0:c0ecb8bf28eb 1192
Marko Mikulicic 0:c0ecb8bf28eb 1193 /* status: normally, it's `CR_RES__OK` */
Marko Mikulicic 0:c0ecb8bf28eb 1194 enum cr_status status;
Marko Mikulicic 0:c0ecb8bf28eb 1195
Marko Mikulicic 0:c0ecb8bf28eb 1196 /*
Marko Mikulicic 0:c0ecb8bf28eb 1197 * pointer to user-dependent union of arguments for all functions, as well as
Marko Mikulicic 0:c0ecb8bf28eb 1198 * return values, yielded and resumed values.
Marko Mikulicic 0:c0ecb8bf28eb 1199 */
Marko Mikulicic 0:c0ecb8bf28eb 1200 union user_arg_ret *p_arg_retval;
Marko Mikulicic 0:c0ecb8bf28eb 1201
Marko Mikulicic 0:c0ecb8bf28eb 1202 /* true if currently running function returns */
Marko Mikulicic 0:c0ecb8bf28eb 1203 unsigned need_return : 1;
Marko Mikulicic 0:c0ecb8bf28eb 1204
Marko Mikulicic 0:c0ecb8bf28eb 1205 /* true if currently running function yields */
Marko Mikulicic 0:c0ecb8bf28eb 1206 unsigned need_yield : 1;
Marko Mikulicic 0:c0ecb8bf28eb 1207
Marko Mikulicic 0:c0ecb8bf28eb 1208 #if defined(CR_TRACK_MAX_STACK_LEN)
Marko Mikulicic 0:c0ecb8bf28eb 1209 size_t stack_data_max_len;
Marko Mikulicic 0:c0ecb8bf28eb 1210 size_t stack_ret_max_len;
Marko Mikulicic 0:c0ecb8bf28eb 1211 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1212 };
Marko Mikulicic 0:c0ecb8bf28eb 1213
Marko Mikulicic 0:c0ecb8bf28eb 1214 /*
Marko Mikulicic 0:c0ecb8bf28eb 1215 * User's enum with function ids should use items of this one like this:
Marko Mikulicic 0:c0ecb8bf28eb 1216 *
Marko Mikulicic 0:c0ecb8bf28eb 1217 * enum my_func_id {
Marko Mikulicic 0:c0ecb8bf28eb 1218 * my_func_none = CR_FID__NONE,
Marko Mikulicic 0:c0ecb8bf28eb 1219 *
Marko Mikulicic 0:c0ecb8bf28eb 1220 * my_foo = CR_FID__USER,
Marko Mikulicic 0:c0ecb8bf28eb 1221 * my_foo1,
Marko Mikulicic 0:c0ecb8bf28eb 1222 * my_foo2,
Marko Mikulicic 0:c0ecb8bf28eb 1223 *
Marko Mikulicic 0:c0ecb8bf28eb 1224 * my_bar,
Marko Mikulicic 0:c0ecb8bf28eb 1225 * my_bar1,
Marko Mikulicic 0:c0ecb8bf28eb 1226 * };
Marko Mikulicic 0:c0ecb8bf28eb 1227 *
Marko Mikulicic 0:c0ecb8bf28eb 1228 */
Marko Mikulicic 0:c0ecb8bf28eb 1229 enum cr_fid {
Marko Mikulicic 0:c0ecb8bf28eb 1230 CR_FID__NONE,
Marko Mikulicic 0:c0ecb8bf28eb 1231 CR_FID__USER,
Marko Mikulicic 0:c0ecb8bf28eb 1232
Marko Mikulicic 0:c0ecb8bf28eb 1233 /* for internal usage only */
Marko Mikulicic 0:c0ecb8bf28eb 1234 CR_FID__TRY_MARKER = 0xff,
Marko Mikulicic 0:c0ecb8bf28eb 1235 };
Marko Mikulicic 0:c0ecb8bf28eb 1236
Marko Mikulicic 0:c0ecb8bf28eb 1237 /*
Marko Mikulicic 0:c0ecb8bf28eb 1238 * User's enum with exception ids should use items of this one like this:
Marko Mikulicic 0:c0ecb8bf28eb 1239 *
Marko Mikulicic 0:c0ecb8bf28eb 1240 * enum my_exc_id {
Marko Mikulicic 0:c0ecb8bf28eb 1241 * MY_EXC_ID__FIRST = CR_EXC_ID__USER,
Marko Mikulicic 0:c0ecb8bf28eb 1242 * MY_EXC_ID__SECOND,
Marko Mikulicic 0:c0ecb8bf28eb 1243 * MY_EXC_ID__THIRD,
Marko Mikulicic 0:c0ecb8bf28eb 1244 * };
Marko Mikulicic 0:c0ecb8bf28eb 1245 */
Marko Mikulicic 0:c0ecb8bf28eb 1246 enum cr_exc_id {
Marko Mikulicic 0:c0ecb8bf28eb 1247 CR_EXC_ID__NONE,
Marko Mikulicic 0:c0ecb8bf28eb 1248 CR_EXC_ID__USER,
Marko Mikulicic 0:c0ecb8bf28eb 1249 };
Marko Mikulicic 0:c0ecb8bf28eb 1250
Marko Mikulicic 0:c0ecb8bf28eb 1251 /*
Marko Mikulicic 0:c0ecb8bf28eb 1252 * A type whose size is a special case for macros `CR_LOCALS_SIZEOF()` and
Marko Mikulicic 0:c0ecb8bf28eb 1253 * `CR_ARG_SIZEOF()` : it is assumed as zero size.
Marko Mikulicic 0:c0ecb8bf28eb 1254 *
Marko Mikulicic 0:c0ecb8bf28eb 1255 * This hackery is needed because empty structs (that would yield sizeof 0) are
Marko Mikulicic 0:c0ecb8bf28eb 1256 * illegal in plain C.
Marko Mikulicic 0:c0ecb8bf28eb 1257 */
Marko Mikulicic 0:c0ecb8bf28eb 1258 typedef struct { uint8_t _dummy[((cr_locals_size_t) -1)]; } cr_zero_size_type_t;
Marko Mikulicic 0:c0ecb8bf28eb 1259
Marko Mikulicic 0:c0ecb8bf28eb 1260 /*
Marko Mikulicic 0:c0ecb8bf28eb 1261 * To be used in dispatcher switch: depending on the "fid" (function id), we
Marko Mikulicic 0:c0ecb8bf28eb 1262 * jump to the appropriate label.
Marko Mikulicic 0:c0ecb8bf28eb 1263 */
Marko Mikulicic 0:c0ecb8bf28eb 1264 #define CR_DEFINE_ENTRY_POINT(fid) \
Marko Mikulicic 0:c0ecb8bf28eb 1265 case fid: \
Marko Mikulicic 0:c0ecb8bf28eb 1266 goto fid
Marko Mikulicic 0:c0ecb8bf28eb 1267
Marko Mikulicic 0:c0ecb8bf28eb 1268 /*
Marko Mikulicic 0:c0ecb8bf28eb 1269 * Returns lvalue: id of the currently active "function". It just takes the id
Marko Mikulicic 0:c0ecb8bf28eb 1270 * from the appropriate position of the "stack".
Marko Mikulicic 0:c0ecb8bf28eb 1271 *
Marko Mikulicic 0:c0ecb8bf28eb 1272 * Client code only needs it in dispatcher switch.
Marko Mikulicic 0:c0ecb8bf28eb 1273 */
Marko Mikulicic 0:c0ecb8bf28eb 1274 #define CR_CURR_FUNC_C(p_ctx) \
Marko Mikulicic 0:c0ecb8bf28eb 1275 *(((cr_locals_size_t *) (p_ctx)->stack_ret.buf) + (p_ctx)->cur_fid_idx - 1)
Marko Mikulicic 0:c0ecb8bf28eb 1276
Marko Mikulicic 0:c0ecb8bf28eb 1277 /*
Marko Mikulicic 0:c0ecb8bf28eb 1278 * Prepare context for calling first function.
Marko Mikulicic 0:c0ecb8bf28eb 1279 *
Marko Mikulicic 0:c0ecb8bf28eb 1280 * Should be used outside of the exec loop, right after initializing
Marko Mikulicic 0:c0ecb8bf28eb 1281 * context with `cr_context_init()`
Marko Mikulicic 0:c0ecb8bf28eb 1282 *
Marko Mikulicic 0:c0ecb8bf28eb 1283 * `call_fid`: id of the function to be called
Marko Mikulicic 0:c0ecb8bf28eb 1284 */
Marko Mikulicic 0:c0ecb8bf28eb 1285 #define CR_FIRST_CALL_PREPARE_C(p_ctx, call_fid) \
Marko Mikulicic 0:c0ecb8bf28eb 1286 _CR_CALL_PREPARE(p_ctx, call_fid, CR_LOCALS_SIZEOF(call_fid##_locals_t), \
Marko Mikulicic 0:c0ecb8bf28eb 1287 CR_ARG_SIZEOF(call_fid##_arg_t), CR_FID__NONE)
Marko Mikulicic 0:c0ecb8bf28eb 1288
Marko Mikulicic 0:c0ecb8bf28eb 1289 /*
Marko Mikulicic 0:c0ecb8bf28eb 1290 * Call "function" with id `call_fid`: uses `_CR_CALL_PREPARE()` to prepare
Marko Mikulicic 0:c0ecb8bf28eb 1291 * stuff, and then jumps to the `_cr_iter_begin`, which will perform all
Marko Mikulicic 0:c0ecb8bf28eb 1292 * necessary bookkeeping.
Marko Mikulicic 0:c0ecb8bf28eb 1293 *
Marko Mikulicic 0:c0ecb8bf28eb 1294 * Should be used from eval loop only.
Marko Mikulicic 0:c0ecb8bf28eb 1295 *
Marko Mikulicic 0:c0ecb8bf28eb 1296 * `local_ret_fid`: id of the label right after the function call (where
Marko Mikulicic 0:c0ecb8bf28eb 1297 * currently running function will be resumed later)
Marko Mikulicic 0:c0ecb8bf28eb 1298 */
Marko Mikulicic 0:c0ecb8bf28eb 1299 #define CR_CALL_C(p_ctx, call_fid, local_ret_fid) \
Marko Mikulicic 0:c0ecb8bf28eb 1300 do { \
Marko Mikulicic 0:c0ecb8bf28eb 1301 _CR_CALL_PREPARE(p_ctx, call_fid, CR_LOCALS_SIZEOF(call_fid##_locals_t), \
Marko Mikulicic 0:c0ecb8bf28eb 1302 CR_ARG_SIZEOF(call_fid##_arg_t), local_ret_fid); \
Marko Mikulicic 0:c0ecb8bf28eb 1303 goto _cr_iter_begin; \
Marko Mikulicic 0:c0ecb8bf28eb 1304 local_ret_fid: \
Marko Mikulicic 0:c0ecb8bf28eb 1305 /* we'll get here when called function returns */ \
Marko Mikulicic 0:c0ecb8bf28eb 1306 ; \
Marko Mikulicic 0:c0ecb8bf28eb 1307 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 1308
Marko Mikulicic 0:c0ecb8bf28eb 1309 /*
Marko Mikulicic 0:c0ecb8bf28eb 1310 * "Return" the value `retval` from the current "function" with id `cur_fid`.
Marko Mikulicic 0:c0ecb8bf28eb 1311 * You have to specify `cur_fid` since different functions may have different
Marko Mikulicic 0:c0ecb8bf28eb 1312 * return types.
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 #define CR_RETURN_C(p_ctx, cur_fid, retval) \
Marko Mikulicic 0:c0ecb8bf28eb 1317 do { \
Marko Mikulicic 0:c0ecb8bf28eb 1318 /* copy ret to arg_retval */ \
Marko Mikulicic 0:c0ecb8bf28eb 1319 CR_ARG_RET_PT_C(p_ctx)->ret.cur_fid = (retval); \
Marko Mikulicic 0:c0ecb8bf28eb 1320 /* set need_return flag */ \
Marko Mikulicic 0:c0ecb8bf28eb 1321 (p_ctx)->need_return = 1; \
Marko Mikulicic 0:c0ecb8bf28eb 1322 goto _cr_iter_begin; \
Marko Mikulicic 0:c0ecb8bf28eb 1323 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 1324
Marko Mikulicic 0:c0ecb8bf28eb 1325 /*
Marko Mikulicic 0:c0ecb8bf28eb 1326 * Same as `CR_RETURN_C`, but without any return value
Marko Mikulicic 0:c0ecb8bf28eb 1327 */
Marko Mikulicic 0:c0ecb8bf28eb 1328 #define CR_RETURN_VOID_C(p_ctx) \
Marko Mikulicic 0:c0ecb8bf28eb 1329 do { \
Marko Mikulicic 0:c0ecb8bf28eb 1330 /* set need_return flag */ \
Marko Mikulicic 0:c0ecb8bf28eb 1331 (p_ctx)->need_return = 1; \
Marko Mikulicic 0:c0ecb8bf28eb 1332 goto _cr_iter_begin; \
Marko Mikulicic 0:c0ecb8bf28eb 1333 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 1334
Marko Mikulicic 0:c0ecb8bf28eb 1335 /*
Marko Mikulicic 0:c0ecb8bf28eb 1336 * Yield with the value `value`. It will be set just by the assigment operator
Marko Mikulicic 0:c0ecb8bf28eb 1337 * in the `yielded` field of the `union user_arg_ret`.
Marko Mikulicic 0:c0ecb8bf28eb 1338 *
Marko Mikulicic 0:c0ecb8bf28eb 1339 * `local_ret_fid`: id of the label right after the yielding (where currently
Marko Mikulicic 0:c0ecb8bf28eb 1340 * running function will be resumed later)
Marko Mikulicic 0:c0ecb8bf28eb 1341 *
Marko Mikulicic 0:c0ecb8bf28eb 1342 */
Marko Mikulicic 0:c0ecb8bf28eb 1343 #define CR_YIELD_C(p_ctx, value, local_ret_fid) \
Marko Mikulicic 0:c0ecb8bf28eb 1344 do { \
Marko Mikulicic 0:c0ecb8bf28eb 1345 /* copy ret to arg_retval */ \
Marko Mikulicic 0:c0ecb8bf28eb 1346 CR_ARG_RET_PT_C(p_ctx)->yielded = (value); \
Marko Mikulicic 0:c0ecb8bf28eb 1347 /* set need_yield flag */ \
Marko Mikulicic 0:c0ecb8bf28eb 1348 (p_ctx)->need_yield = 1; \
Marko Mikulicic 0:c0ecb8bf28eb 1349 \
Marko Mikulicic 0:c0ecb8bf28eb 1350 /* adjust return func id */ \
Marko Mikulicic 0:c0ecb8bf28eb 1351 CR_CURR_FUNC_C(p_ctx) = (local_ret_fid); \
Marko Mikulicic 0:c0ecb8bf28eb 1352 \
Marko Mikulicic 0:c0ecb8bf28eb 1353 goto _cr_iter_begin; \
Marko Mikulicic 0:c0ecb8bf28eb 1354 local_ret_fid: \
Marko Mikulicic 0:c0ecb8bf28eb 1355 /* we'll get here when the machine will be resumed */ \
Marko Mikulicic 0:c0ecb8bf28eb 1356 ; \
Marko Mikulicic 0:c0ecb8bf28eb 1357 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 1358
Marko Mikulicic 0:c0ecb8bf28eb 1359 /*
Marko Mikulicic 0:c0ecb8bf28eb 1360 * Prepare context for resuming with the given value. After using this
Marko Mikulicic 0:c0ecb8bf28eb 1361 * macro, you need to call your user-dependent exec function.
Marko Mikulicic 0:c0ecb8bf28eb 1362 */
Marko Mikulicic 0:c0ecb8bf28eb 1363 #define CR_RESUME_C(p_ctx, value) \
Marko Mikulicic 0:c0ecb8bf28eb 1364 do { \
Marko Mikulicic 0:c0ecb8bf28eb 1365 if ((p_ctx)->status == CR_RES__OK_YIELDED) { \
Marko Mikulicic 0:c0ecb8bf28eb 1366 CR_ARG_RET_PT_C(p_ctx)->resumed = (value); \
Marko Mikulicic 0:c0ecb8bf28eb 1367 (p_ctx)->status = CR_RES__OK; \
Marko Mikulicic 0:c0ecb8bf28eb 1368 } \
Marko Mikulicic 0:c0ecb8bf28eb 1369 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 1370
Marko Mikulicic 0:c0ecb8bf28eb 1371 /*
Marko Mikulicic 0:c0ecb8bf28eb 1372 * Evaluates to the yielded value (value given to `CR_YIELD_C()`)
Marko Mikulicic 0:c0ecb8bf28eb 1373 */
Marko Mikulicic 0:c0ecb8bf28eb 1374 #define CR_YIELDED_C(p_ctx) (CR_ARG_RET_PT_C(p_ctx)->yielded)
Marko Mikulicic 0:c0ecb8bf28eb 1375
Marko Mikulicic 0:c0ecb8bf28eb 1376 /*
Marko Mikulicic 0:c0ecb8bf28eb 1377 * Evaluates to the value given to `CR_RESUME_C()`
Marko Mikulicic 0:c0ecb8bf28eb 1378 */
Marko Mikulicic 0:c0ecb8bf28eb 1379 #define CR_RESUMED_C(p_ctx) (CR_ARG_RET_PT_C(p_ctx)->resumed)
Marko Mikulicic 0:c0ecb8bf28eb 1380
Marko Mikulicic 0:c0ecb8bf28eb 1381 /*
Marko Mikulicic 0:c0ecb8bf28eb 1382 * Beginning of the try-catch block.
Marko Mikulicic 0:c0ecb8bf28eb 1383 *
Marko Mikulicic 0:c0ecb8bf28eb 1384 * Should be used in eval loop only.
Marko Mikulicic 0:c0ecb8bf28eb 1385 *
Marko Mikulicic 0:c0ecb8bf28eb 1386 * `first_catch_fid`: function id of the first catch block.
Marko Mikulicic 0:c0ecb8bf28eb 1387 */
Marko Mikulicic 0:c0ecb8bf28eb 1388 #define CR_TRY_C(p_ctx, first_catch_fid) \
Marko Mikulicic 0:c0ecb8bf28eb 1389 do { \
Marko Mikulicic 0:c0ecb8bf28eb 1390 _CR_STACK_RET_ALLOC((p_ctx), _CR_TRY_SIZE); \
Marko Mikulicic 0:c0ecb8bf28eb 1391 /* update pointer to current function's locals (may be invalidated) */ \
Marko Mikulicic 0:c0ecb8bf28eb 1392 _CR_CUR_FUNC_LOCALS_UPD(p_ctx); \
Marko Mikulicic 0:c0ecb8bf28eb 1393 /* */ \
Marko Mikulicic 0:c0ecb8bf28eb 1394 _CR_TRY_MARKER(p_ctx) = CR_FID__TRY_MARKER; \
Marko Mikulicic 0:c0ecb8bf28eb 1395 _CR_TRY_CATCH_FID(p_ctx) = (first_catch_fid); \
Marko Mikulicic 0:c0ecb8bf28eb 1396 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 1397
Marko Mikulicic 0:c0ecb8bf28eb 1398 /*
Marko Mikulicic 0:c0ecb8bf28eb 1399 * Beginning of the individual catch block (and the end of the previous one, if
Marko Mikulicic 0:c0ecb8bf28eb 1400 * any)
Marko Mikulicic 0:c0ecb8bf28eb 1401 *
Marko Mikulicic 0:c0ecb8bf28eb 1402 * Should be used in eval loop only.
Marko Mikulicic 0:c0ecb8bf28eb 1403 *
Marko Mikulicic 0:c0ecb8bf28eb 1404 * `exc_id`: exception id to catch
Marko Mikulicic 0:c0ecb8bf28eb 1405 *
Marko Mikulicic 0:c0ecb8bf28eb 1406 * `catch_fid`: function id of this catch block.
Marko Mikulicic 0:c0ecb8bf28eb 1407 *
Marko Mikulicic 0:c0ecb8bf28eb 1408 * `next_catch_fid`: function id of the next catch block (or of the
Marko Mikulicic 0:c0ecb8bf28eb 1409 * `CR_ENDCATCH()`)
Marko Mikulicic 0:c0ecb8bf28eb 1410 */
Marko Mikulicic 0:c0ecb8bf28eb 1411 #define CR_CATCH_C(p_ctx, exc_id, catch_fid, next_catch_fid) \
Marko Mikulicic 0:c0ecb8bf28eb 1412 catch_fid: \
Marko Mikulicic 0:c0ecb8bf28eb 1413 do { \
Marko Mikulicic 0:c0ecb8bf28eb 1414 if ((p_ctx)->thrown_exc != (exc_id)) { \
Marko Mikulicic 0:c0ecb8bf28eb 1415 goto next_catch_fid; \
Marko Mikulicic 0:c0ecb8bf28eb 1416 } \
Marko Mikulicic 0:c0ecb8bf28eb 1417 (p_ctx)->thrown_exc = CR_EXC_ID__NONE; \
Marko Mikulicic 0:c0ecb8bf28eb 1418 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 1419
Marko Mikulicic 0:c0ecb8bf28eb 1420 /*
Marko Mikulicic 0:c0ecb8bf28eb 1421 * End of all catch blocks.
Marko Mikulicic 0:c0ecb8bf28eb 1422 *
Marko Mikulicic 0:c0ecb8bf28eb 1423 * Should be used in eval loop only.
Marko Mikulicic 0:c0ecb8bf28eb 1424 *
Marko Mikulicic 0:c0ecb8bf28eb 1425 * `endcatch_fid`: function id of this endcatch.
Marko Mikulicic 0:c0ecb8bf28eb 1426 */
Marko Mikulicic 0:c0ecb8bf28eb 1427 #define CR_ENDCATCH_C(p_ctx, endcatch_fid) \
Marko Mikulicic 0:c0ecb8bf28eb 1428 endcatch_fid: \
Marko Mikulicic 0:c0ecb8bf28eb 1429 do { \
Marko Mikulicic 0:c0ecb8bf28eb 1430 (p_ctx)->stack_ret.len -= _CR_TRY_SIZE; \
Marko Mikulicic 0:c0ecb8bf28eb 1431 /* if we still have non-handled exception, continue unwinding "stack" */ \
Marko Mikulicic 0:c0ecb8bf28eb 1432 if ((p_ctx)->thrown_exc != CR_EXC_ID__NONE) { \
Marko Mikulicic 0:c0ecb8bf28eb 1433 goto _cr_iter_begin; \
Marko Mikulicic 0:c0ecb8bf28eb 1434 } \
Marko Mikulicic 0:c0ecb8bf28eb 1435 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 1436
Marko Mikulicic 0:c0ecb8bf28eb 1437 /*
Marko Mikulicic 0:c0ecb8bf28eb 1438 * Throw exception.
Marko Mikulicic 0:c0ecb8bf28eb 1439 *
Marko Mikulicic 0:c0ecb8bf28eb 1440 * Should be used from eval loop only.
Marko Mikulicic 0:c0ecb8bf28eb 1441 *
Marko Mikulicic 0:c0ecb8bf28eb 1442 * `exc_id`: exception id to throw
Marko Mikulicic 0:c0ecb8bf28eb 1443 */
Marko Mikulicic 0:c0ecb8bf28eb 1444 #define CR_THROW_C(p_ctx, exc_id) \
Marko Mikulicic 0:c0ecb8bf28eb 1445 do { \
Marko Mikulicic 0:c0ecb8bf28eb 1446 assert((enum cr_exc_id)(exc_id) != CR_EXC_ID__NONE); \
Marko Mikulicic 0:c0ecb8bf28eb 1447 /* clear need_return flag */ \
Marko Mikulicic 0:c0ecb8bf28eb 1448 (p_ctx)->thrown_exc = (exc_id); \
Marko Mikulicic 0:c0ecb8bf28eb 1449 goto _cr_iter_begin; \
Marko Mikulicic 0:c0ecb8bf28eb 1450 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 1451
Marko Mikulicic 0:c0ecb8bf28eb 1452 /*
Marko Mikulicic 0:c0ecb8bf28eb 1453 * Get latest returned value from the given "function".
Marko Mikulicic 0:c0ecb8bf28eb 1454 *
Marko Mikulicic 0:c0ecb8bf28eb 1455 * `fid`: id of the function which returned value. Needed to ret value value
Marko Mikulicic 0:c0ecb8bf28eb 1456 * from the right field in the `(p_ctx)->arg_retval.ret` (different functions
Marko Mikulicic 0:c0ecb8bf28eb 1457 * may have different return types)
Marko Mikulicic 0:c0ecb8bf28eb 1458 */
Marko Mikulicic 0:c0ecb8bf28eb 1459 #define CR_RETURNED_C(p_ctx, fid) (CR_ARG_RET_PT_C(p_ctx)->ret.fid)
Marko Mikulicic 0:c0ecb8bf28eb 1460
Marko Mikulicic 0:c0ecb8bf28eb 1461 /*
Marko Mikulicic 0:c0ecb8bf28eb 1462 * Get currently thrown exception id. If nothing is being thrown at the moment,
Marko Mikulicic 0:c0ecb8bf28eb 1463 * `CR_EXC_ID__NONE` is returned
Marko Mikulicic 0:c0ecb8bf28eb 1464 */
Marko Mikulicic 0:c0ecb8bf28eb 1465 #define CR_THROWN_C(p_ctx) ((p_ctx)->thrown_exc)
Marko Mikulicic 0:c0ecb8bf28eb 1466
Marko Mikulicic 0:c0ecb8bf28eb 1467 /*
Marko Mikulicic 0:c0ecb8bf28eb 1468 * Like `sizeof()`, but it always evaluates to the multiple of `sizeof(void *)`
Marko Mikulicic 0:c0ecb8bf28eb 1469 *
Marko Mikulicic 0:c0ecb8bf28eb 1470 * It should be used for (struct cr_func_desc)::locals_size
Marko Mikulicic 0:c0ecb8bf28eb 1471 *
Marko Mikulicic 0:c0ecb8bf28eb 1472 * NOTE: instead of checking `sizeof(type) <= ((cr_locals_size_t) -1)`, I'd
Marko Mikulicic 0:c0ecb8bf28eb 1473 * better put the calculated value as it is, and if it overflows, then compiler
Marko Mikulicic 0:c0ecb8bf28eb 1474 * will generate warning, and this would help us to reveal our mistake. But
Marko Mikulicic 0:c0ecb8bf28eb 1475 * unfortunately, clang *always* generates this warning (even if the whole
Marko Mikulicic 0:c0ecb8bf28eb 1476 * expression yields 0), so we have to apply a bit more of dirty hacks here.
Marko Mikulicic 0:c0ecb8bf28eb 1477 */
Marko Mikulicic 0:c0ecb8bf28eb 1478 #define CR_LOCALS_SIZEOF(type) \
Marko Mikulicic 0:c0ecb8bf28eb 1479 ((sizeof(type) == sizeof(cr_zero_size_type_t)) \
Marko Mikulicic 0:c0ecb8bf28eb 1480 ? 0 \
Marko Mikulicic 0:c0ecb8bf28eb 1481 : (sizeof(type) <= ((cr_locals_size_t) -1) \
Marko Mikulicic 0:c0ecb8bf28eb 1482 ? ((cr_locals_size_t)(((sizeof(type)) + (sizeof(void *) - 1)) & \
Marko Mikulicic 0:c0ecb8bf28eb 1483 (~(sizeof(void *) - 1)))) \
Marko Mikulicic 0:c0ecb8bf28eb 1484 : ((cr_locals_size_t) -1)))
Marko Mikulicic 0:c0ecb8bf28eb 1485
Marko Mikulicic 0:c0ecb8bf28eb 1486 #define CR_ARG_SIZEOF(type) \
Marko Mikulicic 0:c0ecb8bf28eb 1487 ((sizeof(type) == sizeof(cr_zero_size_type_t)) ? 0 : sizeof(type))
Marko Mikulicic 0:c0ecb8bf28eb 1488
Marko Mikulicic 0:c0ecb8bf28eb 1489 /*
Marko Mikulicic 0:c0ecb8bf28eb 1490 * Returns pointer to the current function's stack locals, and casts to given
Marko Mikulicic 0:c0ecb8bf28eb 1491 * type.
Marko Mikulicic 0:c0ecb8bf28eb 1492 *
Marko Mikulicic 0:c0ecb8bf28eb 1493 * Typical usage might look as follows:
Marko Mikulicic 0:c0ecb8bf28eb 1494 *
Marko Mikulicic 0:c0ecb8bf28eb 1495 * #undef L
Marko Mikulicic 0:c0ecb8bf28eb 1496 * #define L CR_CUR_LOCALS_PT(p_ctx, struct my_foo_locals)
Marko Mikulicic 0:c0ecb8bf28eb 1497 *
Marko Mikulicic 0:c0ecb8bf28eb 1498 * Then, assuming `struct my_foo_locals` has the field `bar`, we can access it
Marko Mikulicic 0:c0ecb8bf28eb 1499 * like this:
Marko Mikulicic 0:c0ecb8bf28eb 1500 *
Marko Mikulicic 0:c0ecb8bf28eb 1501 * L->bar
Marko Mikulicic 0:c0ecb8bf28eb 1502 */
Marko Mikulicic 0:c0ecb8bf28eb 1503 #define CR_CUR_LOCALS_PT_C(p_ctx, type) ((type *) ((p_ctx)->p_cur_func_locals))
Marko Mikulicic 0:c0ecb8bf28eb 1504
Marko Mikulicic 0:c0ecb8bf28eb 1505 /*
Marko Mikulicic 0:c0ecb8bf28eb 1506 * Returns pointer to the user-defined union of arguments and return values:
Marko Mikulicic 0:c0ecb8bf28eb 1507 * `union user_arg_ret`
Marko Mikulicic 0:c0ecb8bf28eb 1508 */
Marko Mikulicic 0:c0ecb8bf28eb 1509 #define CR_ARG_RET_PT_C(p_ctx) ((p_ctx)->p_arg_retval)
Marko Mikulicic 0:c0ecb8bf28eb 1510
Marko Mikulicic 0:c0ecb8bf28eb 1511 #define CR_ARG_RET_PT() CR_ARG_RET_PT_C(p_ctx)
Marko Mikulicic 0:c0ecb8bf28eb 1512
Marko Mikulicic 0:c0ecb8bf28eb 1513 #define CR_CUR_LOCALS_PT(type) CR_CUR_LOCALS_PT_C(p_ctx, type)
Marko Mikulicic 0:c0ecb8bf28eb 1514
Marko Mikulicic 0:c0ecb8bf28eb 1515 #define CR_CURR_FUNC() CR_CURR_FUNC_C(p_ctx)
Marko Mikulicic 0:c0ecb8bf28eb 1516
Marko Mikulicic 0:c0ecb8bf28eb 1517 #define CR_CALL(call_fid, local_ret_fid) \
Marko Mikulicic 0:c0ecb8bf28eb 1518 CR_CALL_C(p_ctx, call_fid, local_ret_fid)
Marko Mikulicic 0:c0ecb8bf28eb 1519
Marko Mikulicic 0:c0ecb8bf28eb 1520 #define CR_RETURN(cur_fid, retval) CR_RETURN_C(p_ctx, cur_fid, retval)
Marko Mikulicic 0:c0ecb8bf28eb 1521
Marko Mikulicic 0:c0ecb8bf28eb 1522 #define CR_RETURN_VOID() CR_RETURN_VOID_C(p_ctx)
Marko Mikulicic 0:c0ecb8bf28eb 1523
Marko Mikulicic 0:c0ecb8bf28eb 1524 #define CR_RETURNED(fid) CR_RETURNED_C(p_ctx, fid)
Marko Mikulicic 0:c0ecb8bf28eb 1525
Marko Mikulicic 0:c0ecb8bf28eb 1526 #define CR_YIELD(value, local_ret_fid) CR_YIELD_C(p_ctx, value, local_ret_fid)
Marko Mikulicic 0:c0ecb8bf28eb 1527
Marko Mikulicic 0:c0ecb8bf28eb 1528 #define CR_YIELDED() CR_YIELDED_C(p_ctx)
Marko Mikulicic 0:c0ecb8bf28eb 1529
Marko Mikulicic 0:c0ecb8bf28eb 1530 #define CR_RESUME(value) CR_RESUME_C(p_ctx, value)
Marko Mikulicic 0:c0ecb8bf28eb 1531
Marko Mikulicic 0:c0ecb8bf28eb 1532 #define CR_RESUMED() CR_RESUMED_C(p_ctx)
Marko Mikulicic 0:c0ecb8bf28eb 1533
Marko Mikulicic 0:c0ecb8bf28eb 1534 #define CR_TRY(catch_name) CR_TRY_C(p_ctx, catch_name)
Marko Mikulicic 0:c0ecb8bf28eb 1535
Marko Mikulicic 0:c0ecb8bf28eb 1536 #define CR_CATCH(exc_id, catch_name, next_catch_name) \
Marko Mikulicic 0:c0ecb8bf28eb 1537 CR_CATCH_C(p_ctx, exc_id, catch_name, next_catch_name)
Marko Mikulicic 0:c0ecb8bf28eb 1538
Marko Mikulicic 0:c0ecb8bf28eb 1539 #define CR_ENDCATCH(endcatch_name) CR_ENDCATCH_C(p_ctx, endcatch_name)
Marko Mikulicic 0:c0ecb8bf28eb 1540
Marko Mikulicic 0:c0ecb8bf28eb 1541 #define CR_THROW(exc_id) CR_THROW_C(p_ctx, exc_id)
Marko Mikulicic 0:c0ecb8bf28eb 1542
Marko Mikulicic 0:c0ecb8bf28eb 1543 /* Private macros {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 1544
Marko Mikulicic 0:c0ecb8bf28eb 1545 #define _CR_CUR_FUNC_LOCALS_UPD(p_ctx) \
Marko Mikulicic 0:c0ecb8bf28eb 1546 do { \
Marko Mikulicic 0:c0ecb8bf28eb 1547 (p_ctx)->p_cur_func_locals = (uint8_t *) (p_ctx)->stack_data.buf + \
Marko Mikulicic 0:c0ecb8bf28eb 1548 (p_ctx)->stack_data.len - \
Marko Mikulicic 0:c0ecb8bf28eb 1549 _CR_CURR_FUNC_LOCALS_SIZE(p_ctx); \
Marko Mikulicic 0:c0ecb8bf28eb 1550 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 1551
Marko Mikulicic 0:c0ecb8bf28eb 1552 /*
Marko Mikulicic 0:c0ecb8bf28eb 1553 * Size of the stack needed for each try-catch block.
Marko Mikulicic 0:c0ecb8bf28eb 1554 * Use `_CR_TRY_MARKER()` and `_CR_TRY_CATCH_FID()` to get/set parts.
Marko Mikulicic 0:c0ecb8bf28eb 1555 */
Marko Mikulicic 0:c0ecb8bf28eb 1556 #define _CR_TRY_SIZE 2 /*CR_FID__TRY_MARKER, catch_fid*/
Marko Mikulicic 0:c0ecb8bf28eb 1557
Marko Mikulicic 0:c0ecb8bf28eb 1558 /*
Marko Mikulicic 0:c0ecb8bf28eb 1559 * Evaluates to lvalue where `CR_FID__TRY_MARKER` should be stored
Marko Mikulicic 0:c0ecb8bf28eb 1560 */
Marko Mikulicic 0:c0ecb8bf28eb 1561 #define _CR_TRY_MARKER(p_ctx) \
Marko Mikulicic 0:c0ecb8bf28eb 1562 *(((uint8_t *) (p_ctx)->stack_ret.buf) + (p_ctx)->stack_ret.len - 1)
Marko Mikulicic 0:c0ecb8bf28eb 1563
Marko Mikulicic 0:c0ecb8bf28eb 1564 /*
Marko Mikulicic 0:c0ecb8bf28eb 1565 * Evaluates to lvalue where `catch_fid` should be stored
Marko Mikulicic 0:c0ecb8bf28eb 1566 */
Marko Mikulicic 0:c0ecb8bf28eb 1567 #define _CR_TRY_CATCH_FID(p_ctx) \
Marko Mikulicic 0:c0ecb8bf28eb 1568 *(((uint8_t *) (p_ctx)->stack_ret.buf) + (p_ctx)->stack_ret.len - 2)
Marko Mikulicic 0:c0ecb8bf28eb 1569
Marko Mikulicic 0:c0ecb8bf28eb 1570 #define _CR_CURR_FUNC_LOCALS_SIZE(p_ctx) \
Marko Mikulicic 0:c0ecb8bf28eb 1571 ((p_ctx)->p_func_descrs[CR_CURR_FUNC_C(p_ctx)].locals_size)
Marko Mikulicic 0:c0ecb8bf28eb 1572
Marko Mikulicic 0:c0ecb8bf28eb 1573 /*
Marko Mikulicic 0:c0ecb8bf28eb 1574 * Prepare context for calling next function.
Marko Mikulicic 0:c0ecb8bf28eb 1575 *
Marko Mikulicic 0:c0ecb8bf28eb 1576 * See comments for `CR_CALL()` macro.
Marko Mikulicic 0:c0ecb8bf28eb 1577 */
Marko Mikulicic 0:c0ecb8bf28eb 1578 #define _CR_CALL_PREPARE(p_ctx, _call_fid, _locals_size, _arg_size, \
Marko Mikulicic 0:c0ecb8bf28eb 1579 local_ret_fid) \
Marko Mikulicic 0:c0ecb8bf28eb 1580 do { \
Marko Mikulicic 0:c0ecb8bf28eb 1581 /* adjust return func id */ \
Marko Mikulicic 0:c0ecb8bf28eb 1582 CR_CURR_FUNC_C(p_ctx) = (local_ret_fid); \
Marko Mikulicic 0:c0ecb8bf28eb 1583 \
Marko Mikulicic 0:c0ecb8bf28eb 1584 /* set called_fid */ \
Marko Mikulicic 0:c0ecb8bf28eb 1585 (p_ctx)->called_fid = (_call_fid); \
Marko Mikulicic 0:c0ecb8bf28eb 1586 \
Marko Mikulicic 0:c0ecb8bf28eb 1587 /* set sizes: locals and arg */ \
Marko Mikulicic 0:c0ecb8bf28eb 1588 (p_ctx)->call_locals_size = (_locals_size); \
Marko Mikulicic 0:c0ecb8bf28eb 1589 (p_ctx)->call_arg_size = (_arg_size); \
Marko Mikulicic 0:c0ecb8bf28eb 1590 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 1591
Marko Mikulicic 0:c0ecb8bf28eb 1592 #define _CR_STACK_DATA_OVF_CHECK(p_ctx, inc) (0)
Marko Mikulicic 0:c0ecb8bf28eb 1593
Marko Mikulicic 0:c0ecb8bf28eb 1594 #define _CR_STACK_DATA_UND_CHECK(p_ctx, dec) ((p_ctx)->stack_data.len < (dec))
Marko Mikulicic 0:c0ecb8bf28eb 1595
Marko Mikulicic 0:c0ecb8bf28eb 1596 #define _CR_STACK_RET_OVF_CHECK(p_ctx, inc) (0)
Marko Mikulicic 0:c0ecb8bf28eb 1597
Marko Mikulicic 0:c0ecb8bf28eb 1598 #define _CR_STACK_RET_UND_CHECK(p_ctx, dec) ((p_ctx)->stack_ret.len < (dec))
Marko Mikulicic 0:c0ecb8bf28eb 1599
Marko Mikulicic 0:c0ecb8bf28eb 1600 #define _CR_STACK_FID_OVF_CHECK(p_ctx, inc) (0)
Marko Mikulicic 0:c0ecb8bf28eb 1601
Marko Mikulicic 0:c0ecb8bf28eb 1602 #define _CR_STACK_FID_UND_CHECK(p_ctx, dec) ((p_ctx)->cur_fid_idx < (dec))
Marko Mikulicic 0:c0ecb8bf28eb 1603
Marko Mikulicic 0:c0ecb8bf28eb 1604 #if defined(CR_TRACK_MAX_STACK_LEN)
Marko Mikulicic 0:c0ecb8bf28eb 1605
Marko Mikulicic 0:c0ecb8bf28eb 1606 #define _CR_STACK_DATA_ALLOC(p_ctx, inc) \
Marko Mikulicic 0:c0ecb8bf28eb 1607 do { \
Marko Mikulicic 0:c0ecb8bf28eb 1608 mbuf_append(&((p_ctx)->stack_data), NULL, (inc)); \
Marko Mikulicic 0:c0ecb8bf28eb 1609 if ((p_ctx)->stack_data_max_len < (p_ctx)->stack_data.len) { \
Marko Mikulicic 0:c0ecb8bf28eb 1610 (p_ctx)->stack_data_max_len = (p_ctx)->stack_data.len; \
Marko Mikulicic 0:c0ecb8bf28eb 1611 } \
Marko Mikulicic 0:c0ecb8bf28eb 1612 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 1613
Marko Mikulicic 0:c0ecb8bf28eb 1614 #define _CR_STACK_RET_ALLOC(p_ctx, inc) \
Marko Mikulicic 0:c0ecb8bf28eb 1615 do { \
Marko Mikulicic 0:c0ecb8bf28eb 1616 mbuf_append(&((p_ctx)->stack_ret), NULL, (inc)); \
Marko Mikulicic 0:c0ecb8bf28eb 1617 if ((p_ctx)->stack_ret_max_len < (p_ctx)->stack_ret.len) { \
Marko Mikulicic 0:c0ecb8bf28eb 1618 (p_ctx)->stack_ret_max_len = (p_ctx)->stack_ret.len; \
Marko Mikulicic 0:c0ecb8bf28eb 1619 } \
Marko Mikulicic 0:c0ecb8bf28eb 1620 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 1621
Marko Mikulicic 0:c0ecb8bf28eb 1622 #else
Marko Mikulicic 0:c0ecb8bf28eb 1623
Marko Mikulicic 0:c0ecb8bf28eb 1624 #define _CR_STACK_DATA_ALLOC(p_ctx, inc) \
Marko Mikulicic 0:c0ecb8bf28eb 1625 do { \
Marko Mikulicic 0:c0ecb8bf28eb 1626 mbuf_append(&((p_ctx)->stack_data), NULL, (inc)); \
Marko Mikulicic 0:c0ecb8bf28eb 1627 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 1628
Marko Mikulicic 0:c0ecb8bf28eb 1629 #define _CR_STACK_RET_ALLOC(p_ctx, inc) \
Marko Mikulicic 0:c0ecb8bf28eb 1630 do { \
Marko Mikulicic 0:c0ecb8bf28eb 1631 mbuf_append(&((p_ctx)->stack_ret), NULL, (inc)); \
Marko Mikulicic 0:c0ecb8bf28eb 1632 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 1633
Marko Mikulicic 0:c0ecb8bf28eb 1634 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1635
Marko Mikulicic 0:c0ecb8bf28eb 1636 #define _CR_STACK_DATA_FREE(p_ctx, dec) \
Marko Mikulicic 0:c0ecb8bf28eb 1637 do { \
Marko Mikulicic 0:c0ecb8bf28eb 1638 (p_ctx)->stack_data.len -= (dec); \
Marko Mikulicic 0:c0ecb8bf28eb 1639 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 1640
Marko Mikulicic 0:c0ecb8bf28eb 1641 #define _CR_STACK_RET_FREE(p_ctx, dec) \
Marko Mikulicic 0:c0ecb8bf28eb 1642 do { \
Marko Mikulicic 0:c0ecb8bf28eb 1643 (p_ctx)->stack_ret.len -= (dec); \
Marko Mikulicic 0:c0ecb8bf28eb 1644 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 1645
Marko Mikulicic 0:c0ecb8bf28eb 1646 #define _CR_STACK_FID_ALLOC(p_ctx, inc) \
Marko Mikulicic 0:c0ecb8bf28eb 1647 do { \
Marko Mikulicic 0:c0ecb8bf28eb 1648 (p_ctx)->cur_fid_idx += (inc); \
Marko Mikulicic 0:c0ecb8bf28eb 1649 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 1650
Marko Mikulicic 0:c0ecb8bf28eb 1651 #define _CR_STACK_FID_FREE(p_ctx, dec) \
Marko Mikulicic 0:c0ecb8bf28eb 1652 do { \
Marko Mikulicic 0:c0ecb8bf28eb 1653 (p_ctx)->cur_fid_idx -= (dec); \
Marko Mikulicic 0:c0ecb8bf28eb 1654 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 1655
Marko Mikulicic 0:c0ecb8bf28eb 1656 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 1657
Marko Mikulicic 0:c0ecb8bf28eb 1658 /*
Marko Mikulicic 0:c0ecb8bf28eb 1659 * Should be used in eval loop right after `_cr_iter_begin:` label
Marko Mikulicic 0:c0ecb8bf28eb 1660 */
Marko Mikulicic 0:c0ecb8bf28eb 1661 enum cr_status cr_on_iter_begin(struct cr_ctx *p_ctx);
Marko Mikulicic 0:c0ecb8bf28eb 1662
Marko Mikulicic 0:c0ecb8bf28eb 1663 /*
Marko Mikulicic 0:c0ecb8bf28eb 1664 * Initialize context `p_ctx`.
Marko Mikulicic 0:c0ecb8bf28eb 1665 *
Marko Mikulicic 0:c0ecb8bf28eb 1666 * `p_arg_retval`: pointer to the user-defined `union user_arg_ret`
Marko Mikulicic 0:c0ecb8bf28eb 1667 *
Marko Mikulicic 0:c0ecb8bf28eb 1668 * `p_func_descrs`: array of all user function descriptors
Marko Mikulicic 0:c0ecb8bf28eb 1669 */
Marko Mikulicic 0:c0ecb8bf28eb 1670 void cr_context_init(struct cr_ctx *p_ctx, union user_arg_ret *p_arg_retval,
Marko Mikulicic 0:c0ecb8bf28eb 1671 size_t arg_retval_size,
Marko Mikulicic 0:c0ecb8bf28eb 1672 const struct cr_func_desc *p_func_descrs);
Marko Mikulicic 0:c0ecb8bf28eb 1673
Marko Mikulicic 0:c0ecb8bf28eb 1674 /*
Marko Mikulicic 0:c0ecb8bf28eb 1675 * free resources occupied by context (at least, "stack" arrays)
Marko Mikulicic 0:c0ecb8bf28eb 1676 */
Marko Mikulicic 0:c0ecb8bf28eb 1677 void cr_context_free(struct cr_ctx *p_ctx);
Marko Mikulicic 0:c0ecb8bf28eb 1678
Marko Mikulicic 0:c0ecb8bf28eb 1679 #endif /* CS_COMMON_COROUTINE_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 1680 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 1681 #line 1 "v7/src/features_profiles.h"
Marko Mikulicic 0:c0ecb8bf28eb 1682 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1683 /*
Marko Mikulicic 0:c0ecb8bf28eb 1684 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 1685 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 1686 */
Marko Mikulicic 0:c0ecb8bf28eb 1687
Marko Mikulicic 0:c0ecb8bf28eb 1688 #ifndef CS_V7_SRC_FEATURES_PROFILES_H_
Marko Mikulicic 0:c0ecb8bf28eb 1689 #define CS_V7_SRC_FEATURES_PROFILES_H_
Marko Mikulicic 0:c0ecb8bf28eb 1690
Marko Mikulicic 0:c0ecb8bf28eb 1691 #define V7_BUILD_PROFILE_MINIMAL 1
Marko Mikulicic 0:c0ecb8bf28eb 1692 #define V7_BUILD_PROFILE_MEDIUM 2
Marko Mikulicic 0:c0ecb8bf28eb 1693 #define V7_BUILD_PROFILE_FULL 3
Marko Mikulicic 0:c0ecb8bf28eb 1694
Marko Mikulicic 0:c0ecb8bf28eb 1695 #ifndef V7_BUILD_PROFILE
Marko Mikulicic 0:c0ecb8bf28eb 1696 #define V7_BUILD_PROFILE V7_BUILD_PROFILE_FULL
Marko Mikulicic 0:c0ecb8bf28eb 1697 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1698
Marko Mikulicic 0:c0ecb8bf28eb 1699 #endif /* CS_V7_SRC_FEATURES_PROFILES_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 1700 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 1701 #line 1 "v7/src/features_minimal.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 /* Amalgamated: #include "v7/src/features_profiles.h" */
Marko Mikulicic 0:c0ecb8bf28eb 1709
Marko Mikulicic 0:c0ecb8bf28eb 1710 #if V7_BUILD_PROFILE == V7_BUILD_PROFILE_MINIMAL
Marko Mikulicic 0:c0ecb8bf28eb 1711
Marko Mikulicic 0:c0ecb8bf28eb 1712 /* This space is intentionally left blank. */
Marko Mikulicic 0:c0ecb8bf28eb 1713
Marko Mikulicic 0:c0ecb8bf28eb 1714 #endif /* CS_V7_SRC_FEATURES_MINIMAL_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 1715 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 1716 #line 1 "v7/src/features_medium.h"
Marko Mikulicic 0:c0ecb8bf28eb 1717 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1718 /*
Marko Mikulicic 0:c0ecb8bf28eb 1719 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 1720 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 1721 */
Marko Mikulicic 0:c0ecb8bf28eb 1722
Marko Mikulicic 0:c0ecb8bf28eb 1723 /* Amalgamated: #include "v7/src/features_profiles.h" */
Marko Mikulicic 0:c0ecb8bf28eb 1724
Marko Mikulicic 0:c0ecb8bf28eb 1725 #if V7_BUILD_PROFILE == V7_BUILD_PROFILE_MEDIUM
Marko Mikulicic 0:c0ecb8bf28eb 1726
Marko Mikulicic 0:c0ecb8bf28eb 1727 #define V7_ENABLE__Date 1
Marko Mikulicic 0:c0ecb8bf28eb 1728 #define V7_ENABLE__Date__now 1
Marko Mikulicic 0:c0ecb8bf28eb 1729 #define V7_ENABLE__Date__UTC 1
Marko Mikulicic 0:c0ecb8bf28eb 1730 #define V7_ENABLE__Math 1
Marko Mikulicic 0:c0ecb8bf28eb 1731 #define V7_ENABLE__Math__atan2 1
Marko Mikulicic 0:c0ecb8bf28eb 1732 #define V7_ENABLE__RegExp 1
Marko Mikulicic 0:c0ecb8bf28eb 1733
Marko Mikulicic 0:c0ecb8bf28eb 1734 #endif /* CS_V7_SRC_FEATURES_MEDIUM_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 1735 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 1736 #line 1 "v7/src/features_full.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 #ifndef CS_V7_SRC_FEATURES_FULL_H_
Marko Mikulicic 0:c0ecb8bf28eb 1744 #define CS_V7_SRC_FEATURES_FULL_H_
Marko Mikulicic 0:c0ecb8bf28eb 1745
Marko Mikulicic 0:c0ecb8bf28eb 1746 /* Amalgamated: #include "v7/src/features_profiles.h" */
Marko Mikulicic 0:c0ecb8bf28eb 1747
Marko Mikulicic 0:c0ecb8bf28eb 1748 #if V7_BUILD_PROFILE == V7_BUILD_PROFILE_FULL
Marko Mikulicic 0:c0ecb8bf28eb 1749 /*
Marko Mikulicic 0:c0ecb8bf28eb 1750 * DO NOT EDIT.
Marko Mikulicic 0:c0ecb8bf28eb 1751 * This file is generated by scripts/gen-features-full.pl.
Marko Mikulicic 0:c0ecb8bf28eb 1752 */
Marko Mikulicic 0:c0ecb8bf28eb 1753 #ifndef CS_ENABLE_UTF8
Marko Mikulicic 0:c0ecb8bf28eb 1754 #define CS_ENABLE_UTF8 1
Marko Mikulicic 0:c0ecb8bf28eb 1755 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1756
Marko Mikulicic 0:c0ecb8bf28eb 1757 #define V7_ENABLE__Array__reduce 1
Marko Mikulicic 0:c0ecb8bf28eb 1758 #define V7_ENABLE__Blob 1
Marko Mikulicic 0:c0ecb8bf28eb 1759 #define V7_ENABLE__Date 1
Marko Mikulicic 0:c0ecb8bf28eb 1760 #define V7_ENABLE__Date__UTC 1
Marko Mikulicic 0:c0ecb8bf28eb 1761 #define V7_ENABLE__Date__getters 1
Marko Mikulicic 0:c0ecb8bf28eb 1762 #define V7_ENABLE__Date__now 1
Marko Mikulicic 0:c0ecb8bf28eb 1763 #define V7_ENABLE__Date__parse 1
Marko Mikulicic 0:c0ecb8bf28eb 1764 #define V7_ENABLE__Date__setters 1
Marko Mikulicic 0:c0ecb8bf28eb 1765 #define V7_ENABLE__Date__toJSON 1
Marko Mikulicic 0:c0ecb8bf28eb 1766 #define V7_ENABLE__Date__toLocaleString 1
Marko Mikulicic 0:c0ecb8bf28eb 1767 #define V7_ENABLE__Date__toString 1
Marko Mikulicic 0:c0ecb8bf28eb 1768 #define V7_ENABLE__File__list 1
Marko Mikulicic 0:c0ecb8bf28eb 1769 #define V7_ENABLE__File__require 1
Marko Mikulicic 0:c0ecb8bf28eb 1770 #define V7_ENABLE__Function__bind 1
Marko Mikulicic 0:c0ecb8bf28eb 1771 #define V7_ENABLE__Function__call 1
Marko Mikulicic 0:c0ecb8bf28eb 1772 #define V7_ENABLE__Math 1
Marko Mikulicic 0:c0ecb8bf28eb 1773 #define V7_ENABLE__Math__abs 1
Marko Mikulicic 0:c0ecb8bf28eb 1774 #define V7_ENABLE__Math__acos 1
Marko Mikulicic 0:c0ecb8bf28eb 1775 #define V7_ENABLE__Math__asin 1
Marko Mikulicic 0:c0ecb8bf28eb 1776 #define V7_ENABLE__Math__atan 1
Marko Mikulicic 0:c0ecb8bf28eb 1777 #define V7_ENABLE__Math__atan2 1
Marko Mikulicic 0:c0ecb8bf28eb 1778 #define V7_ENABLE__Math__ceil 1
Marko Mikulicic 0:c0ecb8bf28eb 1779 #define V7_ENABLE__Math__constants 1
Marko Mikulicic 0:c0ecb8bf28eb 1780 #define V7_ENABLE__Math__cos 1
Marko Mikulicic 0:c0ecb8bf28eb 1781 #define V7_ENABLE__Math__exp 1
Marko Mikulicic 0:c0ecb8bf28eb 1782 #define V7_ENABLE__Math__floor 1
Marko Mikulicic 0:c0ecb8bf28eb 1783 #define V7_ENABLE__Math__log 1
Marko Mikulicic 0:c0ecb8bf28eb 1784 #define V7_ENABLE__Math__max 1
Marko Mikulicic 0:c0ecb8bf28eb 1785 #define V7_ENABLE__Math__min 1
Marko Mikulicic 0:c0ecb8bf28eb 1786 #define V7_ENABLE__Math__pow 1
Marko Mikulicic 0:c0ecb8bf28eb 1787 #define V7_ENABLE__Math__random 1
Marko Mikulicic 0:c0ecb8bf28eb 1788 #define V7_ENABLE__Math__round 1
Marko Mikulicic 0:c0ecb8bf28eb 1789 #define V7_ENABLE__Math__sin 1
Marko Mikulicic 0:c0ecb8bf28eb 1790 #define V7_ENABLE__Math__sqrt 1
Marko Mikulicic 0:c0ecb8bf28eb 1791 #define V7_ENABLE__Math__tan 1
Marko Mikulicic 0:c0ecb8bf28eb 1792 #define V7_ENABLE__Memory__stats 1
Marko Mikulicic 0:c0ecb8bf28eb 1793 #define V7_ENABLE__NUMBER__NEGATIVE_INFINITY 1
Marko Mikulicic 0:c0ecb8bf28eb 1794 #define V7_ENABLE__NUMBER__POSITIVE_INFINITY 1
Marko Mikulicic 0:c0ecb8bf28eb 1795 #define V7_ENABLE__Object__create 1
Marko Mikulicic 0:c0ecb8bf28eb 1796 #define V7_ENABLE__Object__defineProperties 1
Marko Mikulicic 0:c0ecb8bf28eb 1797 #define V7_ENABLE__Object__getOwnPropertyDescriptor 1
Marko Mikulicic 0:c0ecb8bf28eb 1798 #define V7_ENABLE__Object__getOwnPropertyNames 1
Marko Mikulicic 0:c0ecb8bf28eb 1799 #define V7_ENABLE__Object__getPrototypeOf 1
Marko Mikulicic 0:c0ecb8bf28eb 1800 #define V7_ENABLE__Object__hasOwnProperty 1
Marko Mikulicic 0:c0ecb8bf28eb 1801 #define V7_ENABLE__Object__isExtensible 1
Marko Mikulicic 0:c0ecb8bf28eb 1802 #define V7_ENABLE__Object__isFrozen 1
Marko Mikulicic 0:c0ecb8bf28eb 1803 #define V7_ENABLE__Object__isPrototypeOf 1
Marko Mikulicic 0:c0ecb8bf28eb 1804 #define V7_ENABLE__Object__isSealed 1
Marko Mikulicic 0:c0ecb8bf28eb 1805 #define V7_ENABLE__Object__keys 1
Marko Mikulicic 0:c0ecb8bf28eb 1806 #define V7_ENABLE__Object__preventExtensions 1
Marko Mikulicic 0:c0ecb8bf28eb 1807 #define V7_ENABLE__Object__propertyIsEnumerable 1
Marko Mikulicic 0:c0ecb8bf28eb 1808 #define V7_ENABLE__Proxy 1
Marko Mikulicic 0:c0ecb8bf28eb 1809 #define V7_ENABLE__RegExp 1
Marko Mikulicic 0:c0ecb8bf28eb 1810 #define V7_ENABLE__StackTrace 1
Marko Mikulicic 0:c0ecb8bf28eb 1811 #define V7_ENABLE__String__localeCompare 1
Marko Mikulicic 0:c0ecb8bf28eb 1812 #define V7_ENABLE__String__localeLowerCase 1
Marko Mikulicic 0:c0ecb8bf28eb 1813 #define V7_ENABLE__String__localeUpperCase 1
Marko Mikulicic 0:c0ecb8bf28eb 1814
Marko Mikulicic 0:c0ecb8bf28eb 1815 #endif /* V7_BUILD_PROFILE == V7_BUILD_PROFILE_FULL */
Marko Mikulicic 0:c0ecb8bf28eb 1816
Marko Mikulicic 0:c0ecb8bf28eb 1817 #endif /* CS_V7_SRC_FEATURES_FULL_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 1818 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 1819 #line 1 "v7/src/v7_features.h"
Marko Mikulicic 0:c0ecb8bf28eb 1820 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1821 /*
Marko Mikulicic 0:c0ecb8bf28eb 1822 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 1823 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 1824 */
Marko Mikulicic 0:c0ecb8bf28eb 1825
Marko Mikulicic 0:c0ecb8bf28eb 1826 #ifndef CS_V7_SRC_V7_FEATURES_H_
Marko Mikulicic 0:c0ecb8bf28eb 1827 #define CS_V7_SRC_V7_FEATURES_H_
Marko Mikulicic 0:c0ecb8bf28eb 1828
Marko Mikulicic 0:c0ecb8bf28eb 1829 /* Only one will actually be used based on V7_BUILD_PROFILE. */
Marko Mikulicic 0:c0ecb8bf28eb 1830 /* Amalgamated: #include "v7/src/features_minimal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 1831 /* Amalgamated: #include "v7/src/features_medium.h" */
Marko Mikulicic 0:c0ecb8bf28eb 1832 /* Amalgamated: #include "v7/src/features_full.h" */
Marko Mikulicic 0:c0ecb8bf28eb 1833
Marko Mikulicic 0:c0ecb8bf28eb 1834 #endif /* CS_V7_SRC_V7_FEATURES_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 1835 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 1836 #line 1 "v7/src/internal.h"
Marko Mikulicic 0:c0ecb8bf28eb 1837 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1838 /*
Marko Mikulicic 0:c0ecb8bf28eb 1839 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 1840 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 1841 */
Marko Mikulicic 0:c0ecb8bf28eb 1842
Marko Mikulicic 0:c0ecb8bf28eb 1843 #ifndef CS_V7_SRC_INTERNAL_H_
Marko Mikulicic 0:c0ecb8bf28eb 1844 #define CS_V7_SRC_INTERNAL_H_
Marko Mikulicic 0:c0ecb8bf28eb 1845
Marko Mikulicic 0:c0ecb8bf28eb 1846 /* Amalgamated: #include "v7/src/license.h" */
Marko Mikulicic 0:c0ecb8bf28eb 1847
Marko Mikulicic 0:c0ecb8bf28eb 1848 /* Check whether we're compiling in an environment with no filesystem */
Marko Mikulicic 0:c0ecb8bf28eb 1849 #if defined(ARDUINO) && (ARDUINO == 106)
Marko Mikulicic 0:c0ecb8bf28eb 1850 #define V7_NO_FS
Marko Mikulicic 0:c0ecb8bf28eb 1851 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1852
Marko Mikulicic 0:c0ecb8bf28eb 1853 #ifndef FAST
Marko Mikulicic 0:c0ecb8bf28eb 1854 #define FAST
Marko Mikulicic 0:c0ecb8bf28eb 1855 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1856
Marko Mikulicic 0:c0ecb8bf28eb 1857 #ifndef STATIC
Marko Mikulicic 0:c0ecb8bf28eb 1858 #define STATIC
Marko Mikulicic 0:c0ecb8bf28eb 1859 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1860
Marko Mikulicic 0:c0ecb8bf28eb 1861 #ifndef ENDL
Marko Mikulicic 0:c0ecb8bf28eb 1862 #define ENDL "\n"
Marko Mikulicic 0:c0ecb8bf28eb 1863 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1864
Marko Mikulicic 0:c0ecb8bf28eb 1865 /*
Marko Mikulicic 0:c0ecb8bf28eb 1866 * In some compilers (watcom) NAN == NAN (and other comparisons) don't follow
Marko Mikulicic 0:c0ecb8bf28eb 1867 * the rules of IEEE 754. Since we don't know a priori which compilers
Marko Mikulicic 0:c0ecb8bf28eb 1868 * will generate correct code, we disable the fallback on selected platforms.
Marko Mikulicic 0:c0ecb8bf28eb 1869 * TODO(mkm): selectively disable on clang/gcc once we test this out.
Marko Mikulicic 0:c0ecb8bf28eb 1870 */
Marko Mikulicic 0:c0ecb8bf28eb 1871 #define V7_BROKEN_NAN
Marko Mikulicic 0:c0ecb8bf28eb 1872
Marko Mikulicic 0:c0ecb8bf28eb 1873 #undef _POSIX_C_SOURCE
Marko Mikulicic 0:c0ecb8bf28eb 1874 #define _POSIX_C_SOURCE 200809L
Marko Mikulicic 0:c0ecb8bf28eb 1875
Marko Mikulicic 0:c0ecb8bf28eb 1876 #include <assert.h>
Marko Mikulicic 0:c0ecb8bf28eb 1877 #ifndef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 1878 #include <ctype.h>
Marko Mikulicic 0:c0ecb8bf28eb 1879 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1880 #include <errno.h>
Marko Mikulicic 0:c0ecb8bf28eb 1881 #include <float.h>
Marko Mikulicic 0:c0ecb8bf28eb 1882 #include <limits.h>
Marko Mikulicic 0:c0ecb8bf28eb 1883 #include <math.h>
Marko Mikulicic 0:c0ecb8bf28eb 1884 #include <stdarg.h>
Marko Mikulicic 0:c0ecb8bf28eb 1885 #include <stddef.h>
Marko Mikulicic 0:c0ecb8bf28eb 1886 #include <stdio.h>
Marko Mikulicic 0:c0ecb8bf28eb 1887 #include <stdlib.h>
Marko Mikulicic 0:c0ecb8bf28eb 1888 #include <string.h>
Marko Mikulicic 0:c0ecb8bf28eb 1889 #include <setjmp.h>
Marko Mikulicic 0:c0ecb8bf28eb 1890
Marko Mikulicic 0:c0ecb8bf28eb 1891 /* Public API. Implemented in api.c */
Marko Mikulicic 0:c0ecb8bf28eb 1892 /* Amalgamated: #include "common/platform.h" */
Marko Mikulicic 0:c0ecb8bf28eb 1893
Marko Mikulicic 0:c0ecb8bf28eb 1894 #ifdef V7_WINDOWS
Marko Mikulicic 0:c0ecb8bf28eb 1895 #define vsnprintf _vsnprintf
Marko Mikulicic 0:c0ecb8bf28eb 1896 #define snprintf _snprintf
Marko Mikulicic 0:c0ecb8bf28eb 1897
Marko Mikulicic 0:c0ecb8bf28eb 1898 /* VS2015 Update 1 has ISO C99 `isnan` and `isinf` defined in math.h */
Marko Mikulicic 0:c0ecb8bf28eb 1899 #if _MSC_FULL_VER < 190023506
Marko Mikulicic 0:c0ecb8bf28eb 1900 #define isnan(x) _isnan(x)
Marko Mikulicic 0:c0ecb8bf28eb 1901 #define isinf(x) (!_finite(x))
Marko Mikulicic 0:c0ecb8bf28eb 1902 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1903
Marko Mikulicic 0:c0ecb8bf28eb 1904 #define __unused __pragma(warning(suppress : 4100))
Marko Mikulicic 0:c0ecb8bf28eb 1905 typedef __int64 int64_t;
Marko Mikulicic 0:c0ecb8bf28eb 1906 typedef int int32_t;
Marko Mikulicic 0:c0ecb8bf28eb 1907 typedef unsigned int uint32_t;
Marko Mikulicic 0:c0ecb8bf28eb 1908 typedef unsigned short uint16_t;
Marko Mikulicic 0:c0ecb8bf28eb 1909 typedef unsigned char uint8_t;
Marko Mikulicic 0:c0ecb8bf28eb 1910
Marko Mikulicic 0:c0ecb8bf28eb 1911 /* For 64bit VisualStudio 2010 */
Marko Mikulicic 0:c0ecb8bf28eb 1912 #ifndef _UINTPTR_T_DEFINED
Marko Mikulicic 0:c0ecb8bf28eb 1913 typedef unsigned long uintptr_t;
Marko Mikulicic 0:c0ecb8bf28eb 1914 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1915
Marko Mikulicic 0:c0ecb8bf28eb 1916 #ifndef __func__
Marko Mikulicic 0:c0ecb8bf28eb 1917 #define __func__ ""
Marko Mikulicic 0:c0ecb8bf28eb 1918 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1919
Marko Mikulicic 0:c0ecb8bf28eb 1920 #else
Marko Mikulicic 0:c0ecb8bf28eb 1921 #include <stdint.h>
Marko Mikulicic 0:c0ecb8bf28eb 1922 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1923
Marko Mikulicic 0:c0ecb8bf28eb 1924 /* Amalgamated: #include "v7/src/v7_features.h" */
Marko Mikulicic 0:c0ecb8bf28eb 1925
Marko Mikulicic 0:c0ecb8bf28eb 1926 /* MSVC6 doesn't have standard C math constants defined */
Marko Mikulicic 0:c0ecb8bf28eb 1927 #ifndef M_E
Marko Mikulicic 0:c0ecb8bf28eb 1928 #define M_E 2.71828182845904523536028747135266250
Marko Mikulicic 0:c0ecb8bf28eb 1929 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1930
Marko Mikulicic 0:c0ecb8bf28eb 1931 #ifndef M_LOG2E
Marko Mikulicic 0:c0ecb8bf28eb 1932 #define M_LOG2E 1.44269504088896340735992468100189214
Marko Mikulicic 0:c0ecb8bf28eb 1933 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1934
Marko Mikulicic 0:c0ecb8bf28eb 1935 #ifndef M_LOG10E
Marko Mikulicic 0:c0ecb8bf28eb 1936 #define M_LOG10E 0.434294481903251827651128918916605082
Marko Mikulicic 0:c0ecb8bf28eb 1937 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1938
Marko Mikulicic 0:c0ecb8bf28eb 1939 #ifndef M_LN2
Marko Mikulicic 0:c0ecb8bf28eb 1940 #define M_LN2 0.693147180559945309417232121458176568
Marko Mikulicic 0:c0ecb8bf28eb 1941 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1942
Marko Mikulicic 0:c0ecb8bf28eb 1943 #ifndef M_LN10
Marko Mikulicic 0:c0ecb8bf28eb 1944 #define M_LN10 2.30258509299404568401799145468436421
Marko Mikulicic 0:c0ecb8bf28eb 1945 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1946
Marko Mikulicic 0:c0ecb8bf28eb 1947 #ifndef M_PI
Marko Mikulicic 0:c0ecb8bf28eb 1948 #define M_PI 3.14159265358979323846264338327950288
Marko Mikulicic 0:c0ecb8bf28eb 1949 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1950
Marko Mikulicic 0:c0ecb8bf28eb 1951 #ifndef M_SQRT2
Marko Mikulicic 0:c0ecb8bf28eb 1952 #define M_SQRT2 1.41421356237309504880168872420969808
Marko Mikulicic 0:c0ecb8bf28eb 1953 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1954
Marko Mikulicic 0:c0ecb8bf28eb 1955 #ifndef M_SQRT1_2
Marko Mikulicic 0:c0ecb8bf28eb 1956 #define M_SQRT1_2 0.707106781186547524400844362104849039
Marko Mikulicic 0:c0ecb8bf28eb 1957 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1958
Marko Mikulicic 0:c0ecb8bf28eb 1959 #ifndef NAN
Marko Mikulicic 0:c0ecb8bf28eb 1960 extern double _v7_nan;
Marko Mikulicic 0:c0ecb8bf28eb 1961 #define HAS_V7_NAN
Marko Mikulicic 0:c0ecb8bf28eb 1962 #define NAN (_v7_nan)
Marko Mikulicic 0:c0ecb8bf28eb 1963 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1964
Marko Mikulicic 0:c0ecb8bf28eb 1965 #ifndef INFINITY
Marko Mikulicic 0:c0ecb8bf28eb 1966 extern double _v7_infinity;
Marko Mikulicic 0:c0ecb8bf28eb 1967 #define HAS_V7_INFINITY
Marko Mikulicic 0:c0ecb8bf28eb 1968 #define INFINITY (_v7_infinity)
Marko Mikulicic 0:c0ecb8bf28eb 1969 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1970
Marko Mikulicic 0:c0ecb8bf28eb 1971 #ifndef EXIT_SUCCESS
Marko Mikulicic 0:c0ecb8bf28eb 1972 #define EXIT_SUCCESS 0
Marko Mikulicic 0:c0ecb8bf28eb 1973 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1974
Marko Mikulicic 0:c0ecb8bf28eb 1975 #ifndef EXIT_FAILURE
Marko Mikulicic 0:c0ecb8bf28eb 1976 #define EXIT_FAILURE 1
Marko Mikulicic 0:c0ecb8bf28eb 1977 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1978
Marko Mikulicic 0:c0ecb8bf28eb 1979 #if defined(V7_ENABLE_GC_CHECK) || defined(V7_STACK_GUARD_MIN_SIZE) || \
Marko Mikulicic 0:c0ecb8bf28eb 1980 defined(V7_ENABLE_STACK_TRACKING) || defined(V7_ENABLE_CALL_TRACE)
Marko Mikulicic 0:c0ecb8bf28eb 1981 /* Need to enable GCC/clang instrumentation */
Marko Mikulicic 0:c0ecb8bf28eb 1982 #define V7_CYG_PROFILE_ON
Marko Mikulicic 0:c0ecb8bf28eb 1983 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1984
Marko Mikulicic 0:c0ecb8bf28eb 1985 #if defined(V7_CYG_PROFILE_ON)
Marko Mikulicic 0:c0ecb8bf28eb 1986 extern struct v7 *v7_head;
Marko Mikulicic 0:c0ecb8bf28eb 1987
Marko Mikulicic 0:c0ecb8bf28eb 1988 #if defined(V7_STACK_GUARD_MIN_SIZE)
Marko Mikulicic 0:c0ecb8bf28eb 1989 extern void *v7_sp_limit;
Marko Mikulicic 0:c0ecb8bf28eb 1990 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1991 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1992
Marko Mikulicic 0:c0ecb8bf28eb 1993 #ifndef ARRAY_SIZE
Marko Mikulicic 0:c0ecb8bf28eb 1994 #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
Marko Mikulicic 0:c0ecb8bf28eb 1995 #endif
Marko Mikulicic 0:c0ecb8bf28eb 1996
Marko Mikulicic 0:c0ecb8bf28eb 1997 #define V7_STATIC_ASSERT(COND, MSG) \
Marko Mikulicic 0:c0ecb8bf28eb 1998 typedef char static_assertion_##MSG[2 * (!!(COND)) - 1]
Marko Mikulicic 0:c0ecb8bf28eb 1999
Marko Mikulicic 0:c0ecb8bf28eb 2000 #define BUF_LEFT(size, used) (((size_t)(used) < (size)) ? ((size) - (used)) : 0)
Marko Mikulicic 0:c0ecb8bf28eb 2001
Marko Mikulicic 0:c0ecb8bf28eb 2002 #endif /* CS_V7_SRC_INTERNAL_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 2003 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 2004 #line 1 "v7/src/core_public.h"
Marko Mikulicic 0:c0ecb8bf28eb 2005 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2006 /*
Marko Mikulicic 0:c0ecb8bf28eb 2007 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 2008 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 2009 */
Marko Mikulicic 0:c0ecb8bf28eb 2010
Marko Mikulicic 0:c0ecb8bf28eb 2011 /*
Marko Mikulicic 0:c0ecb8bf28eb 2012 * === Core
Marko Mikulicic 0:c0ecb8bf28eb 2013 */
Marko Mikulicic 0:c0ecb8bf28eb 2014
Marko Mikulicic 0:c0ecb8bf28eb 2015 #ifndef CS_V7_SRC_CORE_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 2016 #define CS_V7_SRC_CORE_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 2017
Marko Mikulicic 0:c0ecb8bf28eb 2018 #ifndef _POSIX_C_SOURCE
Marko Mikulicic 0:c0ecb8bf28eb 2019 #define _POSIX_C_SOURCE 200809L
Marko Mikulicic 0:c0ecb8bf28eb 2020 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2021
Marko Mikulicic 0:c0ecb8bf28eb 2022 /* Amalgamated: #include "v7/src/license.h" */
Marko Mikulicic 0:c0ecb8bf28eb 2023 /* Amalgamated: #include "v7/src/v7_features.h" */
Marko Mikulicic 0:c0ecb8bf28eb 2024
Marko Mikulicic 0:c0ecb8bf28eb 2025 #include <stddef.h> /* For size_t */
Marko Mikulicic 0:c0ecb8bf28eb 2026 #include <stdio.h> /* For FILE */
Marko Mikulicic 0:c0ecb8bf28eb 2027
Marko Mikulicic 0:c0ecb8bf28eb 2028 /*
Marko Mikulicic 0:c0ecb8bf28eb 2029 * TODO(dfrank) : improve amalgamation, so that we'll be able to include
Marko Mikulicic 0:c0ecb8bf28eb 2030 * files here, and include common/platform.h
Marko Mikulicic 0:c0ecb8bf28eb 2031 *
Marko Mikulicic 0:c0ecb8bf28eb 2032 * For now, copy-pasting `WARN_UNUSED_RESULT` here
Marko Mikulicic 0:c0ecb8bf28eb 2033 */
Marko Mikulicic 0:c0ecb8bf28eb 2034 #ifdef __GNUC__
Marko Mikulicic 0:c0ecb8bf28eb 2035 #define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
Marko Mikulicic 0:c0ecb8bf28eb 2036 #define NOINSTR __attribute__((no_instrument_function))
Marko Mikulicic 0:c0ecb8bf28eb 2037 #else
Marko Mikulicic 0:c0ecb8bf28eb 2038 #define WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 2039 #define NOINSTR
Marko Mikulicic 0:c0ecb8bf28eb 2040 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2041
Marko Mikulicic 0:c0ecb8bf28eb 2042 #define V7_VERSION "1.0"
Marko Mikulicic 0:c0ecb8bf28eb 2043
Marko Mikulicic 0:c0ecb8bf28eb 2044 #if (defined(_WIN32) && !defined(__MINGW32__) && !defined(__MINGW64__)) || \
Marko Mikulicic 0:c0ecb8bf28eb 2045 (defined(_MSC_VER) && _MSC_VER <= 1200)
Marko Mikulicic 0:c0ecb8bf28eb 2046 #define V7_WINDOWS
Marko Mikulicic 0:c0ecb8bf28eb 2047 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2048
Marko Mikulicic 0:c0ecb8bf28eb 2049 #ifdef V7_WINDOWS
Marko Mikulicic 0:c0ecb8bf28eb 2050 typedef unsigned __int64 uint64_t;
Marko Mikulicic 0:c0ecb8bf28eb 2051 #else
Marko Mikulicic 0:c0ecb8bf28eb 2052 #include <inttypes.h>
Marko Mikulicic 0:c0ecb8bf28eb 2053 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2054 /* 64-bit value, used to store JS values */
Marko Mikulicic 0:c0ecb8bf28eb 2055 typedef uint64_t v7_val_t;
Marko Mikulicic 0:c0ecb8bf28eb 2056
Marko Mikulicic 0:c0ecb8bf28eb 2057 /* JavaScript `null` value */
Marko Mikulicic 0:c0ecb8bf28eb 2058 #define V7_NULL ((uint64_t) 0xfffe << 48)
Marko Mikulicic 0:c0ecb8bf28eb 2059
Marko Mikulicic 0:c0ecb8bf28eb 2060 /* JavaScript `undefined` value */
Marko Mikulicic 0:c0ecb8bf28eb 2061 #define V7_UNDEFINED ((uint64_t) 0xfffd << 48)
Marko Mikulicic 0:c0ecb8bf28eb 2062
Marko Mikulicic 0:c0ecb8bf28eb 2063 /* This if-0 is a dirty workaround to force etags to pick `struct v7` */
Marko Mikulicic 0:c0ecb8bf28eb 2064 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 2065 /* Opaque structure. V7 engine context. */
Marko Mikulicic 0:c0ecb8bf28eb 2066 struct v7 {
Marko Mikulicic 0:c0ecb8bf28eb 2067 /* ... */
Marko Mikulicic 0:c0ecb8bf28eb 2068 };
Marko Mikulicic 0:c0ecb8bf28eb 2069 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2070
Marko Mikulicic 0:c0ecb8bf28eb 2071 struct v7;
Marko Mikulicic 0:c0ecb8bf28eb 2072
Marko Mikulicic 0:c0ecb8bf28eb 2073 /*
Marko Mikulicic 0:c0ecb8bf28eb 2074 * Code which is returned by some of the v7 functions. If something other than
Marko Mikulicic 0:c0ecb8bf28eb 2075 * `V7_OK` is returned from some function, the caller function typically should
Marko Mikulicic 0:c0ecb8bf28eb 2076 * either immediately cleanup and return the code further, or handle the error.
Marko Mikulicic 0:c0ecb8bf28eb 2077 */
Marko Mikulicic 0:c0ecb8bf28eb 2078 enum v7_err {
Marko Mikulicic 0:c0ecb8bf28eb 2079 V7_OK,
Marko Mikulicic 0:c0ecb8bf28eb 2080 V7_SYNTAX_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 2081 V7_EXEC_EXCEPTION,
Marko Mikulicic 0:c0ecb8bf28eb 2082 V7_AST_TOO_LARGE,
Marko Mikulicic 0:c0ecb8bf28eb 2083 V7_INTERNAL_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 2084 };
Marko Mikulicic 0:c0ecb8bf28eb 2085
Marko Mikulicic 0:c0ecb8bf28eb 2086 /* JavaScript -> C call interface */
Marko Mikulicic 0:c0ecb8bf28eb 2087 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 2088 typedef enum v7_err(v7_cfunction_t)(struct v7 *v7, v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 2089
Marko Mikulicic 0:c0ecb8bf28eb 2090 /* Create V7 instance */
Marko Mikulicic 0:c0ecb8bf28eb 2091 struct v7 *v7_create(void);
Marko Mikulicic 0:c0ecb8bf28eb 2092
Marko Mikulicic 0:c0ecb8bf28eb 2093 /*
Marko Mikulicic 0:c0ecb8bf28eb 2094 * Customizations of initial V7 state; used by `v7_create_opt()`.
Marko Mikulicic 0:c0ecb8bf28eb 2095 */
Marko Mikulicic 0:c0ecb8bf28eb 2096 struct v7_create_opts {
Marko Mikulicic 0:c0ecb8bf28eb 2097 size_t object_arena_size;
Marko Mikulicic 0:c0ecb8bf28eb 2098 size_t function_arena_size;
Marko Mikulicic 0:c0ecb8bf28eb 2099 size_t property_arena_size;
Marko Mikulicic 0:c0ecb8bf28eb 2100 #ifdef V7_STACK_SIZE
Marko Mikulicic 0:c0ecb8bf28eb 2101 void *c_stack_base;
Marko Mikulicic 0:c0ecb8bf28eb 2102 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2103 #ifdef V7_FREEZE
Marko Mikulicic 0:c0ecb8bf28eb 2104 /* if not NULL, dump JS heap after init */
Marko Mikulicic 0:c0ecb8bf28eb 2105 char *freeze_file;
Marko Mikulicic 0:c0ecb8bf28eb 2106 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2107 };
Marko Mikulicic 0:c0ecb8bf28eb 2108
Marko Mikulicic 0:c0ecb8bf28eb 2109 /*
Marko Mikulicic 0:c0ecb8bf28eb 2110 * Like `v7_create()`, but allows to customize initial v7 state, see `struct
Marko Mikulicic 0:c0ecb8bf28eb 2111 * v7_create_opts`.
Marko Mikulicic 0:c0ecb8bf28eb 2112 */
Marko Mikulicic 0:c0ecb8bf28eb 2113 struct v7 *v7_create_opt(struct v7_create_opts opts);
Marko Mikulicic 0:c0ecb8bf28eb 2114
Marko Mikulicic 0:c0ecb8bf28eb 2115 /* Destroy V7 instance */
Marko Mikulicic 0:c0ecb8bf28eb 2116 void v7_destroy(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 2117
Marko Mikulicic 0:c0ecb8bf28eb 2118 /* Return root level (`global`) object of the given V7 instance. */
Marko Mikulicic 0:c0ecb8bf28eb 2119 v7_val_t v7_get_global(struct v7 *v);
Marko Mikulicic 0:c0ecb8bf28eb 2120
Marko Mikulicic 0:c0ecb8bf28eb 2121 /* Return current `this` object. */
Marko Mikulicic 0:c0ecb8bf28eb 2122 v7_val_t v7_get_this(struct v7 *v);
Marko Mikulicic 0:c0ecb8bf28eb 2123
Marko Mikulicic 0:c0ecb8bf28eb 2124 /* Return current `arguments` array */
Marko Mikulicic 0:c0ecb8bf28eb 2125 v7_val_t v7_get_arguments(struct v7 *v);
Marko Mikulicic 0:c0ecb8bf28eb 2126
Marko Mikulicic 0:c0ecb8bf28eb 2127 /* Return i-th argument */
Marko Mikulicic 0:c0ecb8bf28eb 2128 v7_val_t v7_arg(struct v7 *v, unsigned long i);
Marko Mikulicic 0:c0ecb8bf28eb 2129
Marko Mikulicic 0:c0ecb8bf28eb 2130 /* Return the length of `arguments` */
Marko Mikulicic 0:c0ecb8bf28eb 2131 unsigned long v7_argc(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 2132
Marko Mikulicic 0:c0ecb8bf28eb 2133 /*
Marko Mikulicic 0:c0ecb8bf28eb 2134 * Tells the GC about a JS value variable/field owned
Marko Mikulicic 0:c0ecb8bf28eb 2135 * by C code.
Marko Mikulicic 0:c0ecb8bf28eb 2136 *
Marko Mikulicic 0:c0ecb8bf28eb 2137 * User C code should own v7_val_t variables
Marko Mikulicic 0:c0ecb8bf28eb 2138 * if the value's lifetime crosses any invocation
Marko Mikulicic 0:c0ecb8bf28eb 2139 * to the v7 runtime that creates new objects or new
Marko Mikulicic 0:c0ecb8bf28eb 2140 * properties and thus can potentially trigger GC.
Marko Mikulicic 0:c0ecb8bf28eb 2141 *
Marko Mikulicic 0:c0ecb8bf28eb 2142 * The registration of the variable prevents the GC from mistakenly treat
Marko Mikulicic 0:c0ecb8bf28eb 2143 * the object as garbage. The GC might be triggered potentially
Marko Mikulicic 0:c0ecb8bf28eb 2144 * allows the GC to update pointers
Marko Mikulicic 0:c0ecb8bf28eb 2145 *
Marko Mikulicic 0:c0ecb8bf28eb 2146 * User code should also explicitly disown the variables with v7_disown once
Marko Mikulicic 0:c0ecb8bf28eb 2147 * it goes out of scope or the structure containing the v7_val_t field is freed.
Marko Mikulicic 0:c0ecb8bf28eb 2148 *
Marko Mikulicic 0:c0ecb8bf28eb 2149 * Example:
Marko Mikulicic 0:c0ecb8bf28eb 2150 *
Marko Mikulicic 0:c0ecb8bf28eb 2151 * ```
Marko Mikulicic 0:c0ecb8bf28eb 2152 * struct v7_val cb;
Marko Mikulicic 0:c0ecb8bf28eb 2153 * v7_own(v7, &cb);
Marko Mikulicic 0:c0ecb8bf28eb 2154 * cb = v7_array_get(v7, args, 0);
Marko Mikulicic 0:c0ecb8bf28eb 2155 * // do something with cb
Marko Mikulicic 0:c0ecb8bf28eb 2156 * v7_disown(v7, &cb);
Marko Mikulicic 0:c0ecb8bf28eb 2157 * ```
Marko Mikulicic 0:c0ecb8bf28eb 2158 */
Marko Mikulicic 0:c0ecb8bf28eb 2159 void v7_own(struct v7 *v7, v7_val_t *v);
Marko Mikulicic 0:c0ecb8bf28eb 2160
Marko Mikulicic 0:c0ecb8bf28eb 2161 /*
Marko Mikulicic 0:c0ecb8bf28eb 2162 * Returns 1 if value is found, 0 otherwise
Marko Mikulicic 0:c0ecb8bf28eb 2163 */
Marko Mikulicic 0:c0ecb8bf28eb 2164 int v7_disown(struct v7 *v7, v7_val_t *v);
Marko Mikulicic 0:c0ecb8bf28eb 2165
Marko Mikulicic 0:c0ecb8bf28eb 2166 /*
Marko Mikulicic 0:c0ecb8bf28eb 2167 * Enable or disable GC.
Marko Mikulicic 0:c0ecb8bf28eb 2168 *
Marko Mikulicic 0:c0ecb8bf28eb 2169 * Must be called before invoking v7_exec or v7_apply
Marko Mikulicic 0:c0ecb8bf28eb 2170 * from within a cfunction unless you know what you're doing.
Marko Mikulicic 0:c0ecb8bf28eb 2171 *
Marko Mikulicic 0:c0ecb8bf28eb 2172 * GC is disabled during execution of cfunctions in order to simplify
Marko Mikulicic 0:c0ecb8bf28eb 2173 * memory management of simple cfunctions.
Marko Mikulicic 0:c0ecb8bf28eb 2174 * However executing even small snippets of JS code causes a lot of memory
Marko Mikulicic 0:c0ecb8bf28eb 2175 * pressure. Enabling GC solves that but forces you to take care of the
Marko Mikulicic 0:c0ecb8bf28eb 2176 * reachability of your temporary V7 v7_val_t variables, as the GC needs
Marko Mikulicic 0:c0ecb8bf28eb 2177 * to know where they are since objects and strings can be either reclaimed
Marko Mikulicic 0:c0ecb8bf28eb 2178 * or relocated during a GC pass.
Marko Mikulicic 0:c0ecb8bf28eb 2179 */
Marko Mikulicic 0:c0ecb8bf28eb 2180 void v7_set_gc_enabled(struct v7 *v7, int enabled);
Marko Mikulicic 0:c0ecb8bf28eb 2181
Marko Mikulicic 0:c0ecb8bf28eb 2182 /*
Marko Mikulicic 0:c0ecb8bf28eb 2183 * Set an optional C stack limit.
Marko Mikulicic 0:c0ecb8bf28eb 2184 *
Marko Mikulicic 0:c0ecb8bf28eb 2185 * It sets a flag that will cause the interpreter
Marko Mikulicic 0:c0ecb8bf28eb 2186 * to throw an InterruptedError.
Marko Mikulicic 0:c0ecb8bf28eb 2187 * It's safe to call it from signal handlers and ISRs
Marko Mikulicic 0:c0ecb8bf28eb 2188 * on single threaded environments.
Marko Mikulicic 0:c0ecb8bf28eb 2189 */
Marko Mikulicic 0:c0ecb8bf28eb 2190 void v7_interrupt(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 2191
Marko Mikulicic 0:c0ecb8bf28eb 2192 /* Returns last parser error message. TODO: rename it to `v7_get_error()` */
Marko Mikulicic 0:c0ecb8bf28eb 2193 const char *v7_get_parser_error(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 2194
Marko Mikulicic 0:c0ecb8bf28eb 2195 #if defined(V7_ENABLE_STACK_TRACKING)
Marko Mikulicic 0:c0ecb8bf28eb 2196 /*
Marko Mikulicic 0:c0ecb8bf28eb 2197 * Available if only `V7_ENABLE_STACK_TRACKING` is defined.
Marko Mikulicic 0:c0ecb8bf28eb 2198 *
Marko Mikulicic 0:c0ecb8bf28eb 2199 * Stack metric id. See `v7_stack_stat()`
Marko Mikulicic 0:c0ecb8bf28eb 2200 */
Marko Mikulicic 0:c0ecb8bf28eb 2201 enum v7_stack_stat_what {
Marko Mikulicic 0:c0ecb8bf28eb 2202 /* max stack size consumed by `i_exec()` */
Marko Mikulicic 0:c0ecb8bf28eb 2203 V7_STACK_STAT_EXEC,
Marko Mikulicic 0:c0ecb8bf28eb 2204 /* max stack size consumed by `parse()` (which is called from `i_exec()`) */
Marko Mikulicic 0:c0ecb8bf28eb 2205 V7_STACK_STAT_PARSER,
Marko Mikulicic 0:c0ecb8bf28eb 2206
Marko Mikulicic 0:c0ecb8bf28eb 2207 V7_STACK_STATS_CNT
Marko Mikulicic 0:c0ecb8bf28eb 2208 };
Marko Mikulicic 0:c0ecb8bf28eb 2209
Marko Mikulicic 0:c0ecb8bf28eb 2210 /*
Marko Mikulicic 0:c0ecb8bf28eb 2211 * Available if only `V7_ENABLE_STACK_TRACKING` is defined.
Marko Mikulicic 0:c0ecb8bf28eb 2212 *
Marko Mikulicic 0:c0ecb8bf28eb 2213 * Returns stack metric specified by the metric id `what`. See
Marko Mikulicic 0:c0ecb8bf28eb 2214 * `v7_stack_stat_clean()`
Marko Mikulicic 0:c0ecb8bf28eb 2215 */
Marko Mikulicic 0:c0ecb8bf28eb 2216 int v7_stack_stat(struct v7 *v7, enum v7_stack_stat_what what);
Marko Mikulicic 0:c0ecb8bf28eb 2217
Marko Mikulicic 0:c0ecb8bf28eb 2218 /*
Marko Mikulicic 0:c0ecb8bf28eb 2219 * Available if only `V7_ENABLE_STACK_TRACKING` is defined.
Marko Mikulicic 0:c0ecb8bf28eb 2220 *
Marko Mikulicic 0:c0ecb8bf28eb 2221 * Clean all stack statistics gathered so far. See `v7_stack_stat()`
Marko Mikulicic 0:c0ecb8bf28eb 2222 */
Marko Mikulicic 0:c0ecb8bf28eb 2223 void v7_stack_stat_clean(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 2224 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2225
Marko Mikulicic 0:c0ecb8bf28eb 2226 #endif /* CS_V7_SRC_CORE_PUBLIC_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 2227 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 2228 #line 1 "v7/src/std_error.h"
Marko Mikulicic 0:c0ecb8bf28eb 2229 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2230 /*
Marko Mikulicic 0:c0ecb8bf28eb 2231 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 2232 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 2233 */
Marko Mikulicic 0:c0ecb8bf28eb 2234
Marko Mikulicic 0:c0ecb8bf28eb 2235 #ifndef CS_V7_SRC_STD_ERROR_H_
Marko Mikulicic 0:c0ecb8bf28eb 2236 #define CS_V7_SRC_STD_ERROR_H_
Marko Mikulicic 0:c0ecb8bf28eb 2237
Marko Mikulicic 0:c0ecb8bf28eb 2238 /* Amalgamated: #include "v7/src/license.h" */
Marko Mikulicic 0:c0ecb8bf28eb 2239
Marko Mikulicic 0:c0ecb8bf28eb 2240 struct v7;
Marko Mikulicic 0:c0ecb8bf28eb 2241
Marko Mikulicic 0:c0ecb8bf28eb 2242 /*
Marko Mikulicic 0:c0ecb8bf28eb 2243 * JavaScript error types
Marko Mikulicic 0:c0ecb8bf28eb 2244 */
Marko Mikulicic 0:c0ecb8bf28eb 2245 #define TYPE_ERROR "TypeError"
Marko Mikulicic 0:c0ecb8bf28eb 2246 #define SYNTAX_ERROR "SyntaxError"
Marko Mikulicic 0:c0ecb8bf28eb 2247 #define REFERENCE_ERROR "ReferenceError"
Marko Mikulicic 0:c0ecb8bf28eb 2248 #define INTERNAL_ERROR "InternalError"
Marko Mikulicic 0:c0ecb8bf28eb 2249 #define RANGE_ERROR "RangeError"
Marko Mikulicic 0:c0ecb8bf28eb 2250 #define EVAL_ERROR "EvalError"
Marko Mikulicic 0:c0ecb8bf28eb 2251 #define ERROR_CTOR_MAX 6
Marko Mikulicic 0:c0ecb8bf28eb 2252 /*
Marko Mikulicic 0:c0ecb8bf28eb 2253 * TODO(mkm): EvalError is not so important, we should guard it behind
Marko Mikulicic 0:c0ecb8bf28eb 2254 * something like `V7_ENABLE__EvalError`. However doing so makes it hard to
Marko Mikulicic 0:c0ecb8bf28eb 2255 * keep ERROR_CTOR_MAX up to date; perhaps let's find a better way of doing it.
Marko Mikulicic 0:c0ecb8bf28eb 2256 *
Marko Mikulicic 0:c0ecb8bf28eb 2257 * EvalError is useful mostly because we now have ecma tests failing:
Marko Mikulicic 0:c0ecb8bf28eb 2258 *
Marko Mikulicic 0:c0ecb8bf28eb 2259 * 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 2260 * +7600043 tests/ecmac.db|head -c 496): [{"message":"[EvalError] is not
Marko Mikulicic 0:c0ecb8bf28eb 2261 * defined"}]
Marko Mikulicic 0:c0ecb8bf28eb 2262 *
Marko Mikulicic 0:c0ecb8bf28eb 2263 * Those tests are not EvalError specific, and they do test that the exception
Marko Mikulicic 0:c0ecb8bf28eb 2264 * handling machinery works as intended.
Marko Mikulicic 0:c0ecb8bf28eb 2265 */
Marko Mikulicic 0:c0ecb8bf28eb 2266
Marko Mikulicic 0:c0ecb8bf28eb 2267 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 2268 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 2269 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 2270
Marko Mikulicic 0:c0ecb8bf28eb 2271 V7_PRIVATE void init_error(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 2272
Marko Mikulicic 0:c0ecb8bf28eb 2273 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 2274 }
Marko Mikulicic 0:c0ecb8bf28eb 2275 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 2276
Marko Mikulicic 0:c0ecb8bf28eb 2277 #endif /* CS_V7_SRC_STD_ERROR_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 2278 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 2279 #line 1 "v7/src/mm.h"
Marko Mikulicic 0:c0ecb8bf28eb 2280 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2281 /*
Marko Mikulicic 0:c0ecb8bf28eb 2282 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 2283 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 2284 */
Marko Mikulicic 0:c0ecb8bf28eb 2285
Marko Mikulicic 0:c0ecb8bf28eb 2286 #ifndef CS_V7_SRC_MM_H_
Marko Mikulicic 0:c0ecb8bf28eb 2287 #define CS_V7_SRC_MM_H_
Marko Mikulicic 0:c0ecb8bf28eb 2288
Marko Mikulicic 0:c0ecb8bf28eb 2289 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 2290
Marko Mikulicic 0:c0ecb8bf28eb 2291 typedef void (*gc_cell_destructor_t)(struct v7 *v7, void *);
Marko Mikulicic 0:c0ecb8bf28eb 2292
Marko Mikulicic 0:c0ecb8bf28eb 2293 struct gc_block {
Marko Mikulicic 0:c0ecb8bf28eb 2294 struct gc_block *next;
Marko Mikulicic 0:c0ecb8bf28eb 2295 struct gc_cell *base;
Marko Mikulicic 0:c0ecb8bf28eb 2296 size_t size;
Marko Mikulicic 0:c0ecb8bf28eb 2297 };
Marko Mikulicic 0:c0ecb8bf28eb 2298
Marko Mikulicic 0:c0ecb8bf28eb 2299 struct gc_arena {
Marko Mikulicic 0:c0ecb8bf28eb 2300 struct gc_block *blocks;
Marko Mikulicic 0:c0ecb8bf28eb 2301 size_t size_increment;
Marko Mikulicic 0:c0ecb8bf28eb 2302 struct gc_cell *free; /* head of free list */
Marko Mikulicic 0:c0ecb8bf28eb 2303 size_t cell_size;
Marko Mikulicic 0:c0ecb8bf28eb 2304
Marko Mikulicic 0:c0ecb8bf28eb 2305 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 2306 unsigned long allocations; /* cumulative counter of allocations */
Marko Mikulicic 0:c0ecb8bf28eb 2307 unsigned long garbage; /* cumulative counter of garbage */
Marko Mikulicic 0:c0ecb8bf28eb 2308 unsigned long alive; /* number of living cells */
Marko Mikulicic 0:c0ecb8bf28eb 2309 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2310
Marko Mikulicic 0:c0ecb8bf28eb 2311 gc_cell_destructor_t destructor;
Marko Mikulicic 0:c0ecb8bf28eb 2312
Marko Mikulicic 0:c0ecb8bf28eb 2313 int verbose;
Marko Mikulicic 0:c0ecb8bf28eb 2314 const char *name; /* for debugging purposes */
Marko Mikulicic 0:c0ecb8bf28eb 2315 };
Marko Mikulicic 0:c0ecb8bf28eb 2316
Marko Mikulicic 0:c0ecb8bf28eb 2317 #endif /* CS_V7_SRC_MM_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 2318 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 2319 #line 1 "v7/src/parser.h"
Marko Mikulicic 0:c0ecb8bf28eb 2320 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2321 /*
Marko Mikulicic 0:c0ecb8bf28eb 2322 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 2323 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 2324 */
Marko Mikulicic 0:c0ecb8bf28eb 2325
Marko Mikulicic 0:c0ecb8bf28eb 2326 #ifndef CS_V7_SRC_PARSER_H_
Marko Mikulicic 0:c0ecb8bf28eb 2327 #define CS_V7_SRC_PARSER_H_
Marko Mikulicic 0:c0ecb8bf28eb 2328
Marko Mikulicic 0:c0ecb8bf28eb 2329 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 2330 /* Amalgamated: #include "v7/src/core_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 2331
Marko Mikulicic 0:c0ecb8bf28eb 2332 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 2333
Marko Mikulicic 0:c0ecb8bf28eb 2334 struct v7;
Marko Mikulicic 0:c0ecb8bf28eb 2335 struct ast;
Marko Mikulicic 0:c0ecb8bf28eb 2336
Marko Mikulicic 0:c0ecb8bf28eb 2337 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 2338 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 2339 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 2340
Marko Mikulicic 0:c0ecb8bf28eb 2341 struct v7_pstate {
Marko Mikulicic 0:c0ecb8bf28eb 2342 const char *file_name;
Marko Mikulicic 0:c0ecb8bf28eb 2343 const char *source_code;
Marko Mikulicic 0:c0ecb8bf28eb 2344 const char *pc; /* Current parsing position */
Marko Mikulicic 0:c0ecb8bf28eb 2345 const char *src_end; /* End of source code */
Marko Mikulicic 0:c0ecb8bf28eb 2346 int line_no; /* Line number */
Marko Mikulicic 0:c0ecb8bf28eb 2347 int prev_line_no; /* Line number of previous token */
Marko Mikulicic 0:c0ecb8bf28eb 2348 int inhibit_in; /* True while `in` expressions are inhibited */
Marko Mikulicic 0:c0ecb8bf28eb 2349 int in_function; /* True if in a function */
Marko Mikulicic 0:c0ecb8bf28eb 2350 int in_loop; /* True if in a loop */
Marko Mikulicic 0:c0ecb8bf28eb 2351 int in_switch; /* True if in a switch block */
Marko Mikulicic 0:c0ecb8bf28eb 2352 int in_strict; /* True if in strict mode */
Marko Mikulicic 0:c0ecb8bf28eb 2353 };
Marko Mikulicic 0:c0ecb8bf28eb 2354
Marko Mikulicic 0:c0ecb8bf28eb 2355 V7_PRIVATE enum v7_err parse(struct v7 *v7, struct ast *a, const char *src,
Marko Mikulicic 0:c0ecb8bf28eb 2356 size_t src_len, int is_json);
Marko Mikulicic 0:c0ecb8bf28eb 2357
Marko Mikulicic 0:c0ecb8bf28eb 2358 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 2359 }
Marko Mikulicic 0:c0ecb8bf28eb 2360 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 2361
Marko Mikulicic 0:c0ecb8bf28eb 2362 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 2363
Marko Mikulicic 0:c0ecb8bf28eb 2364 #endif /* CS_V7_SRC_PARSER_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 2365 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 2366 #line 1 "v7/src/object_public.h"
Marko Mikulicic 0:c0ecb8bf28eb 2367 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2368 /*
Marko Mikulicic 0:c0ecb8bf28eb 2369 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 2370 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 2371 */
Marko Mikulicic 0:c0ecb8bf28eb 2372
Marko Mikulicic 0:c0ecb8bf28eb 2373 /*
Marko Mikulicic 0:c0ecb8bf28eb 2374 * === Objects
Marko Mikulicic 0:c0ecb8bf28eb 2375 */
Marko Mikulicic 0:c0ecb8bf28eb 2376
Marko Mikulicic 0:c0ecb8bf28eb 2377 #ifndef CS_V7_SRC_OBJECT_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 2378 #define CS_V7_SRC_OBJECT_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 2379
Marko Mikulicic 0:c0ecb8bf28eb 2380 /* Amalgamated: #include "v7/src/core_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 2381
Marko Mikulicic 0:c0ecb8bf28eb 2382 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 2383 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 2384 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 2385
Marko Mikulicic 0:c0ecb8bf28eb 2386 /*
Marko Mikulicic 0:c0ecb8bf28eb 2387 * Property attributes bitmask
Marko Mikulicic 0:c0ecb8bf28eb 2388 */
Marko Mikulicic 0:c0ecb8bf28eb 2389 typedef unsigned short v7_prop_attr_t;
Marko Mikulicic 0:c0ecb8bf28eb 2390 #define V7_PROPERTY_NON_WRITABLE (1 << 0)
Marko Mikulicic 0:c0ecb8bf28eb 2391 #define V7_PROPERTY_NON_ENUMERABLE (1 << 1)
Marko Mikulicic 0:c0ecb8bf28eb 2392 #define V7_PROPERTY_NON_CONFIGURABLE (1 << 2)
Marko Mikulicic 0:c0ecb8bf28eb 2393 #define V7_PROPERTY_GETTER (1 << 3)
Marko Mikulicic 0:c0ecb8bf28eb 2394 #define V7_PROPERTY_SETTER (1 << 4)
Marko Mikulicic 0:c0ecb8bf28eb 2395 #define _V7_PROPERTY_HIDDEN (1 << 5)
Marko Mikulicic 0:c0ecb8bf28eb 2396 /* property not managed by V7 HEAP */
Marko Mikulicic 0:c0ecb8bf28eb 2397 #define _V7_PROPERTY_OFF_HEAP (1 << 6)
Marko Mikulicic 0:c0ecb8bf28eb 2398 /* special property holding user data and destructor cb */
Marko Mikulicic 0:c0ecb8bf28eb 2399 #define _V7_PROPERTY_USER_DATA_AND_DESTRUCTOR (1 << 7)
Marko Mikulicic 0:c0ecb8bf28eb 2400 /*
Marko Mikulicic 0:c0ecb8bf28eb 2401 * not a property attribute, but a flag for `v7_def()`. It's here in order to
Marko Mikulicic 0:c0ecb8bf28eb 2402 * keep all offsets in one place
Marko Mikulicic 0:c0ecb8bf28eb 2403 */
Marko Mikulicic 0:c0ecb8bf28eb 2404 #define _V7_DESC_PRESERVE_VALUE (1 << 8)
Marko Mikulicic 0:c0ecb8bf28eb 2405
Marko Mikulicic 0:c0ecb8bf28eb 2406 #define V7_PROP_ATTR_IS_WRITABLE(a) (!(a & V7_PROPERTY_NON_WRITABLE))
Marko Mikulicic 0:c0ecb8bf28eb 2407 #define V7_PROP_ATTR_IS_ENUMERABLE(a) (!(a & V7_PROPERTY_NON_ENUMERABLE))
Marko Mikulicic 0:c0ecb8bf28eb 2408 #define V7_PROP_ATTR_IS_CONFIGURABLE(a) (!(a & V7_PROPERTY_NON_CONFIGURABLE))
Marko Mikulicic 0:c0ecb8bf28eb 2409
Marko Mikulicic 0:c0ecb8bf28eb 2410 /*
Marko Mikulicic 0:c0ecb8bf28eb 2411 * Internal helpers for `V7_DESC_...` macros
Marko Mikulicic 0:c0ecb8bf28eb 2412 */
Marko Mikulicic 0:c0ecb8bf28eb 2413 #define _V7_DESC_SHIFT 16
Marko Mikulicic 0:c0ecb8bf28eb 2414 #define _V7_DESC_MASK ((1 << _V7_DESC_SHIFT) - 1)
Marko Mikulicic 0:c0ecb8bf28eb 2415 #define _V7_MK_DESC(v, n) \
Marko Mikulicic 0:c0ecb8bf28eb 2416 (((v7_prop_attr_desc_t)(n)) << _V7_DESC_SHIFT | ((v) ? (n) : 0))
Marko Mikulicic 0:c0ecb8bf28eb 2417 #define _V7_MK_DESC_INV(v, n) _V7_MK_DESC(!(v), (n))
Marko Mikulicic 0:c0ecb8bf28eb 2418
Marko Mikulicic 0:c0ecb8bf28eb 2419 /*
Marko Mikulicic 0:c0ecb8bf28eb 2420 * Property attribute descriptors that may be given to `v7_def()`: for each
Marko Mikulicic 0:c0ecb8bf28eb 2421 * attribute (`v7_prop_attr_t`), there is a corresponding macro, which takes
Marko Mikulicic 0:c0ecb8bf28eb 2422 * param: either 1 (set attribute) or 0 (clear attribute). If some particular
Marko Mikulicic 0:c0ecb8bf28eb 2423 * attribute isn't mentioned at all, it's left unchanged (or default, if the
Marko Mikulicic 0:c0ecb8bf28eb 2424 * property is being created)
Marko Mikulicic 0:c0ecb8bf28eb 2425 *
Marko Mikulicic 0:c0ecb8bf28eb 2426 * There is additional flag: `V7_DESC_PRESERVE_VALUE`. If it is set, the
Marko Mikulicic 0:c0ecb8bf28eb 2427 * property value isn't changed (or set to `undefined` if the property is being
Marko Mikulicic 0:c0ecb8bf28eb 2428 * created)
Marko Mikulicic 0:c0ecb8bf28eb 2429 */
Marko Mikulicic 0:c0ecb8bf28eb 2430 typedef unsigned long v7_prop_attr_desc_t;
Marko Mikulicic 0:c0ecb8bf28eb 2431 #define V7_DESC_WRITABLE(v) _V7_MK_DESC_INV(v, V7_PROPERTY_NON_WRITABLE)
Marko Mikulicic 0:c0ecb8bf28eb 2432 #define V7_DESC_ENUMERABLE(v) _V7_MK_DESC_INV(v, V7_PROPERTY_NON_ENUMERABLE)
Marko Mikulicic 0:c0ecb8bf28eb 2433 #define V7_DESC_CONFIGURABLE(v) _V7_MK_DESC_INV(v, V7_PROPERTY_NON_CONFIGURABLE)
Marko Mikulicic 0:c0ecb8bf28eb 2434 #define V7_DESC_GETTER(v) _V7_MK_DESC(v, V7_PROPERTY_GETTER)
Marko Mikulicic 0:c0ecb8bf28eb 2435 #define V7_DESC_SETTER(v) _V7_MK_DESC(v, V7_PROPERTY_SETTER)
Marko Mikulicic 0:c0ecb8bf28eb 2436 #define V7_DESC_PRESERVE_VALUE _V7_DESC_PRESERVE_VALUE
Marko Mikulicic 0:c0ecb8bf28eb 2437
Marko Mikulicic 0:c0ecb8bf28eb 2438 #define _V7_DESC_HIDDEN(v) _V7_MK_DESC(v, _V7_PROPERTY_HIDDEN)
Marko Mikulicic 0:c0ecb8bf28eb 2439 #define _V7_DESC_OFF_HEAP(v) _V7_MK_DESC(v, _V7_PROPERTY_OFF_HEAP)
Marko Mikulicic 0:c0ecb8bf28eb 2440
Marko Mikulicic 0:c0ecb8bf28eb 2441 /* See `v7_set_destructor_cb` */
Marko Mikulicic 0:c0ecb8bf28eb 2442 typedef void(v7_destructor_cb_t)(struct v7 *v7, void *ud);
Marko Mikulicic 0:c0ecb8bf28eb 2443
Marko Mikulicic 0:c0ecb8bf28eb 2444 /* Make an empty object */
Marko Mikulicic 0:c0ecb8bf28eb 2445 v7_val_t v7_mk_object(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 2446
Marko Mikulicic 0:c0ecb8bf28eb 2447 /*
Marko Mikulicic 0:c0ecb8bf28eb 2448 * Returns true if the given value is an object or function.
Marko Mikulicic 0:c0ecb8bf28eb 2449 * i.e. it returns true if the value holds properties and can be
Marko Mikulicic 0:c0ecb8bf28eb 2450 * used as argument to `v7_get`, `v7_set` and `v7_def`.
Marko Mikulicic 0:c0ecb8bf28eb 2451 */
Marko Mikulicic 0:c0ecb8bf28eb 2452 int v7_is_object(v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 2453
Marko Mikulicic 0:c0ecb8bf28eb 2454 /* Set object's prototype. Return old prototype or undefined on error. */
Marko Mikulicic 0:c0ecb8bf28eb 2455 v7_val_t v7_set_proto(struct v7 *v7, v7_val_t obj, v7_val_t proto);
Marko Mikulicic 0:c0ecb8bf28eb 2456
Marko Mikulicic 0:c0ecb8bf28eb 2457 /* Get object's prototype. */
Marko Mikulicic 0:c0ecb8bf28eb 2458 v7_val_t v7_get_proto(struct v7 *v7, v7_val_t obj);
Marko Mikulicic 0:c0ecb8bf28eb 2459
Marko Mikulicic 0:c0ecb8bf28eb 2460 /*
Marko Mikulicic 0:c0ecb8bf28eb 2461 * Lookup property `name` in object `obj`. If `obj` holds no such property,
Marko Mikulicic 0:c0ecb8bf28eb 2462 * an `undefined` value is returned.
Marko Mikulicic 0:c0ecb8bf28eb 2463 *
Marko Mikulicic 0:c0ecb8bf28eb 2464 * If `name_len` is ~0, `name` is assumed to be NUL-terminated and
Marko Mikulicic 0:c0ecb8bf28eb 2465 * `strlen(name)` is used.
Marko Mikulicic 0:c0ecb8bf28eb 2466 */
Marko Mikulicic 0:c0ecb8bf28eb 2467 v7_val_t v7_get(struct v7 *v7, v7_val_t obj, const char *name, size_t name_len);
Marko Mikulicic 0:c0ecb8bf28eb 2468
Marko Mikulicic 0:c0ecb8bf28eb 2469 /*
Marko Mikulicic 0:c0ecb8bf28eb 2470 * Like `v7_get()`, but "returns" value through `res` pointer argument.
Marko Mikulicic 0:c0ecb8bf28eb 2471 * `res` must not be `NULL`.
Marko Mikulicic 0:c0ecb8bf28eb 2472 *
Marko Mikulicic 0:c0ecb8bf28eb 2473 * Caller should check the error code returned, and if it's something other
Marko Mikulicic 0:c0ecb8bf28eb 2474 * than `V7_OK`, perform cleanup and return this code further.
Marko Mikulicic 0:c0ecb8bf28eb 2475 */
Marko Mikulicic 0:c0ecb8bf28eb 2476 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 2477 enum v7_err v7_get_throwing(struct v7 *v7, v7_val_t obj, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 2478 size_t name_len, v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 2479
Marko Mikulicic 0:c0ecb8bf28eb 2480 /*
Marko Mikulicic 0:c0ecb8bf28eb 2481 * Define object property, similar to JavaScript `Object.defineProperty()`.
Marko Mikulicic 0:c0ecb8bf28eb 2482 *
Marko Mikulicic 0:c0ecb8bf28eb 2483 * `name`, `name_len` specify property name, `val` is a property value.
Marko Mikulicic 0:c0ecb8bf28eb 2484 * `attrs_desc` is a set of flags which can affect property's attributes,
Marko Mikulicic 0:c0ecb8bf28eb 2485 * see comment of `v7_prop_attr_desc_t` for details.
Marko Mikulicic 0:c0ecb8bf28eb 2486 *
Marko Mikulicic 0:c0ecb8bf28eb 2487 * If `name_len` is ~0, `name` is assumed to be NUL-terminated and
Marko Mikulicic 0:c0ecb8bf28eb 2488 * `strlen(name)` is used.
Marko Mikulicic 0:c0ecb8bf28eb 2489 *
Marko Mikulicic 0:c0ecb8bf28eb 2490 * Returns non-zero on success, 0 on error (e.g. out of memory).
Marko Mikulicic 0:c0ecb8bf28eb 2491 *
Marko Mikulicic 0:c0ecb8bf28eb 2492 * See also `v7_set()`.
Marko Mikulicic 0:c0ecb8bf28eb 2493 */
Marko Mikulicic 0:c0ecb8bf28eb 2494 int v7_def(struct v7 *v7, v7_val_t obj, const char *name, size_t name_len,
Marko Mikulicic 0:c0ecb8bf28eb 2495 v7_prop_attr_desc_t attrs_desc, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 2496
Marko Mikulicic 0:c0ecb8bf28eb 2497 /*
Marko Mikulicic 0:c0ecb8bf28eb 2498 * Set object property. Behaves just like JavaScript assignment.
Marko Mikulicic 0:c0ecb8bf28eb 2499 *
Marko Mikulicic 0:c0ecb8bf28eb 2500 * See also `v7_def()`.
Marko Mikulicic 0:c0ecb8bf28eb 2501 */
Marko Mikulicic 0:c0ecb8bf28eb 2502 int v7_set(struct v7 *v7, v7_val_t obj, const char *name, size_t len,
Marko Mikulicic 0:c0ecb8bf28eb 2503 v7_val_t val);
Marko Mikulicic 0:c0ecb8bf28eb 2504
Marko Mikulicic 0:c0ecb8bf28eb 2505 /*
Marko Mikulicic 0:c0ecb8bf28eb 2506 * A helper function to define object's method backed by a C function `func`.
Marko Mikulicic 0:c0ecb8bf28eb 2507 * `name` must be NUL-terminated.
Marko Mikulicic 0:c0ecb8bf28eb 2508 *
Marko Mikulicic 0:c0ecb8bf28eb 2509 * Return value is the same as for `v7_set()`.
Marko Mikulicic 0:c0ecb8bf28eb 2510 */
Marko Mikulicic 0:c0ecb8bf28eb 2511 int v7_set_method(struct v7 *, v7_val_t obj, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 2512 v7_cfunction_t *func);
Marko Mikulicic 0:c0ecb8bf28eb 2513
Marko Mikulicic 0:c0ecb8bf28eb 2514 /*
Marko Mikulicic 0:c0ecb8bf28eb 2515 * Delete own property `name` of the object `obj`. Does not follow the
Marko Mikulicic 0:c0ecb8bf28eb 2516 * prototype chain.
Marko Mikulicic 0:c0ecb8bf28eb 2517 *
Marko Mikulicic 0:c0ecb8bf28eb 2518 * If `name_len` is ~0, `name` is assumed to be NUL-terminated and
Marko Mikulicic 0:c0ecb8bf28eb 2519 * `strlen(name)` is used.
Marko Mikulicic 0:c0ecb8bf28eb 2520 *
Marko Mikulicic 0:c0ecb8bf28eb 2521 * Returns 0 on success, -1 on error.
Marko Mikulicic 0:c0ecb8bf28eb 2522 */
Marko Mikulicic 0:c0ecb8bf28eb 2523 int v7_del(struct v7 *v7, v7_val_t obj, const char *name, size_t name_len);
Marko Mikulicic 0:c0ecb8bf28eb 2524
Marko Mikulicic 0:c0ecb8bf28eb 2525 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 2526 struct prop_iter_proxy_ctx;
Marko Mikulicic 0:c0ecb8bf28eb 2527 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2528
Marko Mikulicic 0:c0ecb8bf28eb 2529 /*
Marko Mikulicic 0:c0ecb8bf28eb 2530 * Context for property iteration, see `v7_next_prop()`.
Marko Mikulicic 0:c0ecb8bf28eb 2531 *
Marko Mikulicic 0:c0ecb8bf28eb 2532 * Clients should not interpret contents of this structure, it's here merely to
Marko Mikulicic 0:c0ecb8bf28eb 2533 * allow clients to allocate it not from the heap.
Marko Mikulicic 0:c0ecb8bf28eb 2534 */
Marko Mikulicic 0:c0ecb8bf28eb 2535 struct prop_iter_ctx {
Marko Mikulicic 0:c0ecb8bf28eb 2536 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 2537 struct prop_iter_proxy_ctx *proxy_ctx;
Marko Mikulicic 0:c0ecb8bf28eb 2538 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2539 struct v7_property *cur_prop;
Marko Mikulicic 0:c0ecb8bf28eb 2540
Marko Mikulicic 0:c0ecb8bf28eb 2541 unsigned init : 1;
Marko Mikulicic 0:c0ecb8bf28eb 2542 };
Marko Mikulicic 0:c0ecb8bf28eb 2543
Marko Mikulicic 0:c0ecb8bf28eb 2544 /*
Marko Mikulicic 0:c0ecb8bf28eb 2545 * Initialize the property iteration context `ctx`, see `v7_next_prop()` for
Marko Mikulicic 0:c0ecb8bf28eb 2546 * usage example.
Marko Mikulicic 0:c0ecb8bf28eb 2547 */
Marko Mikulicic 0:c0ecb8bf28eb 2548 enum v7_err v7_init_prop_iter_ctx(struct v7 *v7, v7_val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 2549 struct prop_iter_ctx *ctx);
Marko Mikulicic 0:c0ecb8bf28eb 2550
Marko Mikulicic 0:c0ecb8bf28eb 2551 /*
Marko Mikulicic 0:c0ecb8bf28eb 2552 * Destruct the property iteration context `ctx`, see `v7_next_prop()` for
Marko Mikulicic 0:c0ecb8bf28eb 2553 * usage example
Marko Mikulicic 0:c0ecb8bf28eb 2554 */
Marko Mikulicic 0:c0ecb8bf28eb 2555 void v7_destruct_prop_iter_ctx(struct v7 *v7, struct prop_iter_ctx *ctx);
Marko Mikulicic 0:c0ecb8bf28eb 2556
Marko Mikulicic 0:c0ecb8bf28eb 2557 /*
Marko Mikulicic 0:c0ecb8bf28eb 2558 * Iterate over the `obj`'s properties.
Marko Mikulicic 0:c0ecb8bf28eb 2559 *
Marko Mikulicic 0:c0ecb8bf28eb 2560 * Usage example (here we assume we have some `v7_val_t obj`):
Marko Mikulicic 0:c0ecb8bf28eb 2561 *
Marko Mikulicic 0:c0ecb8bf28eb 2562 * struct prop_iter_ctx ctx;
Marko Mikulicic 0:c0ecb8bf28eb 2563 * v7_val_t name, val;
Marko Mikulicic 0:c0ecb8bf28eb 2564 * v7_prop_attr_t attrs;
Marko Mikulicic 0:c0ecb8bf28eb 2565 *
Marko Mikulicic 0:c0ecb8bf28eb 2566 * v7_init_prop_iter_ctx(v7, obj, &ctx);
Marko Mikulicic 0:c0ecb8bf28eb 2567 * while (v7_next_prop(v7, &ctx, &name, &val, &attrs)) {
Marko Mikulicic 0:c0ecb8bf28eb 2568 * if (V7_PROP_ATTR_IS_ENUMERABLE(attrs)) continue;
Marko Mikulicic 0:c0ecb8bf28eb 2569 * ...
Marko Mikulicic 0:c0ecb8bf28eb 2570 * }
Marko Mikulicic 0:c0ecb8bf28eb 2571 * v7_destruct_prop_iter_ctx(v7, &ctx);
Marko Mikulicic 0:c0ecb8bf28eb 2572 *
Marko Mikulicic 0:c0ecb8bf28eb 2573 * As you see, v7_next_prop will iterate through all properties, including
Marko Mikulicic 0:c0ecb8bf28eb 2574 * non-enumerable ones, and it's your responsibility to test the attributes
Marko Mikulicic 0:c0ecb8bf28eb 2575 * with the provided `V7_PROP_ATTR_*` macros and proceed as you see fit.
Marko Mikulicic 0:c0ecb8bf28eb 2576 */
Marko Mikulicic 0:c0ecb8bf28eb 2577 int v7_next_prop(struct v7 *v7, struct prop_iter_ctx *ctx, v7_val_t *name,
Marko Mikulicic 0:c0ecb8bf28eb 2578 v7_val_t *value, v7_prop_attr_t *attrs);
Marko Mikulicic 0:c0ecb8bf28eb 2579
Marko Mikulicic 0:c0ecb8bf28eb 2580 /* Returns true if the object is an instance of a given constructor. */
Marko Mikulicic 0:c0ecb8bf28eb 2581 int v7_is_instanceof(struct v7 *v7, v7_val_t o, const char *c);
Marko Mikulicic 0:c0ecb8bf28eb 2582
Marko Mikulicic 0:c0ecb8bf28eb 2583 /* Returns true if the object is an instance of a given constructor. */
Marko Mikulicic 0:c0ecb8bf28eb 2584 int v7_is_instanceof_v(struct v7 *v7, v7_val_t o, v7_val_t c);
Marko Mikulicic 0:c0ecb8bf28eb 2585
Marko Mikulicic 0:c0ecb8bf28eb 2586 /*
Marko Mikulicic 0:c0ecb8bf28eb 2587 * Associates an opaque C value (anything that can be casted to a `void * )
Marko Mikulicic 0:c0ecb8bf28eb 2588 * with an object.
Marko Mikulicic 0:c0ecb8bf28eb 2589 *
Marko Mikulicic 0:c0ecb8bf28eb 2590 * You can achieve a similar effect by just setting a special property with
Marko Mikulicic 0:c0ecb8bf28eb 2591 * a foreign value (see `v7_mk_foreign`), except user data offers the following
Marko Mikulicic 0:c0ecb8bf28eb 2592 * advantages:
Marko Mikulicic 0:c0ecb8bf28eb 2593 *
Marko Mikulicic 0:c0ecb8bf28eb 2594 * 1. You don't have to come up with some arbitrary "special" property name.
Marko Mikulicic 0:c0ecb8bf28eb 2595 * 2. JS scripts cannot access user data by mistake via property lookup.
Marko Mikulicic 0:c0ecb8bf28eb 2596 * 3. The user data is available to the destructor. When the desctructor is
Marko Mikulicic 0:c0ecb8bf28eb 2597 * invoked you cannot access any of its properties.
Marko Mikulicic 0:c0ecb8bf28eb 2598 * 4. Allows the implementation to use a more compact encoding
Marko Mikulicic 0:c0ecb8bf28eb 2599 *
Marko Mikulicic 0:c0ecb8bf28eb 2600 * Does nothing if `obj` is not a mutable object.
Marko Mikulicic 0:c0ecb8bf28eb 2601 */
Marko Mikulicic 0:c0ecb8bf28eb 2602 void v7_set_user_data(struct v7 *v7, v7_val_t obj, void *ud);
Marko Mikulicic 0:c0ecb8bf28eb 2603
Marko Mikulicic 0:c0ecb8bf28eb 2604 /*
Marko Mikulicic 0:c0ecb8bf28eb 2605 * Get the opaque user data set with `v7_set_user_data`.
Marko Mikulicic 0:c0ecb8bf28eb 2606 *
Marko Mikulicic 0:c0ecb8bf28eb 2607 * Returns NULL if there is no user data set or if `obj` is not an object.
Marko Mikulicic 0:c0ecb8bf28eb 2608 */
Marko Mikulicic 0:c0ecb8bf28eb 2609 void *v7_get_user_data(struct v7 *v7, v7_val_t obj);
Marko Mikulicic 0:c0ecb8bf28eb 2610
Marko Mikulicic 0:c0ecb8bf28eb 2611 /*
Marko Mikulicic 0:c0ecb8bf28eb 2612 * Register a callback which will be invoked when a given object gets
Marko Mikulicic 0:c0ecb8bf28eb 2613 * reclaimed by the garbage collector.
Marko Mikulicic 0:c0ecb8bf28eb 2614 *
Marko Mikulicic 0:c0ecb8bf28eb 2615 * The callback will be invoked while garbage collection is still in progress
Marko Mikulicic 0:c0ecb8bf28eb 2616 * and hence the internal state of the JS heap is in an undefined state.
Marko Mikulicic 0:c0ecb8bf28eb 2617 *
Marko Mikulicic 0:c0ecb8bf28eb 2618 * The only v7 API which is safe to use in this callback is `v7_disown()`,
Marko Mikulicic 0:c0ecb8bf28eb 2619 * that's why `v7` pointer is given to it. *Calls to any other v7 functions are
Marko Mikulicic 0:c0ecb8bf28eb 2620 * illegal here*.
Marko Mikulicic 0:c0ecb8bf28eb 2621 *
Marko Mikulicic 0:c0ecb8bf28eb 2622 * The intended use case is to reclaim resources allocated by C code.
Marko Mikulicic 0:c0ecb8bf28eb 2623 */
Marko Mikulicic 0:c0ecb8bf28eb 2624 void v7_set_destructor_cb(struct v7 *v7, v7_val_t obj, v7_destructor_cb_t *d);
Marko Mikulicic 0:c0ecb8bf28eb 2625
Marko Mikulicic 0:c0ecb8bf28eb 2626 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 2627 }
Marko Mikulicic 0:c0ecb8bf28eb 2628 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 2629
Marko Mikulicic 0:c0ecb8bf28eb 2630 #endif /* CS_V7_SRC_OBJECT_PUBLIC_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 2631 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 2632 #line 1 "v7/src/tokenizer.h"
Marko Mikulicic 0:c0ecb8bf28eb 2633 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2634 /*
Marko Mikulicic 0:c0ecb8bf28eb 2635 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 2636 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 2637 */
Marko Mikulicic 0:c0ecb8bf28eb 2638
Marko Mikulicic 0:c0ecb8bf28eb 2639 #ifndef CS_V7_SRC_TOKENIZER_H_
Marko Mikulicic 0:c0ecb8bf28eb 2640 #define CS_V7_SRC_TOKENIZER_H_
Marko Mikulicic 0:c0ecb8bf28eb 2641
Marko Mikulicic 0:c0ecb8bf28eb 2642 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 2643
Marko Mikulicic 0:c0ecb8bf28eb 2644 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 2645
Marko Mikulicic 0:c0ecb8bf28eb 2646 enum v7_tok {
Marko Mikulicic 0:c0ecb8bf28eb 2647 TOK_END_OF_INPUT,
Marko Mikulicic 0:c0ecb8bf28eb 2648 TOK_NUMBER,
Marko Mikulicic 0:c0ecb8bf28eb 2649 TOK_STRING_LITERAL,
Marko Mikulicic 0:c0ecb8bf28eb 2650 TOK_REGEX_LITERAL,
Marko Mikulicic 0:c0ecb8bf28eb 2651 TOK_IDENTIFIER,
Marko Mikulicic 0:c0ecb8bf28eb 2652
Marko Mikulicic 0:c0ecb8bf28eb 2653 /* Punctuators */
Marko Mikulicic 0:c0ecb8bf28eb 2654 TOK_OPEN_CURLY,
Marko Mikulicic 0:c0ecb8bf28eb 2655 TOK_CLOSE_CURLY,
Marko Mikulicic 0:c0ecb8bf28eb 2656 TOK_OPEN_PAREN,
Marko Mikulicic 0:c0ecb8bf28eb 2657 TOK_CLOSE_PAREN,
Marko Mikulicic 0:c0ecb8bf28eb 2658 TOK_COMMA,
Marko Mikulicic 0:c0ecb8bf28eb 2659 TOK_OPEN_BRACKET,
Marko Mikulicic 0:c0ecb8bf28eb 2660 TOK_CLOSE_BRACKET,
Marko Mikulicic 0:c0ecb8bf28eb 2661 TOK_DOT,
Marko Mikulicic 0:c0ecb8bf28eb 2662 TOK_COLON,
Marko Mikulicic 0:c0ecb8bf28eb 2663 TOK_SEMICOLON,
Marko Mikulicic 0:c0ecb8bf28eb 2664
Marko Mikulicic 0:c0ecb8bf28eb 2665 /* Equality ops, in this order */
Marko Mikulicic 0:c0ecb8bf28eb 2666 TOK_EQ,
Marko Mikulicic 0:c0ecb8bf28eb 2667 TOK_EQ_EQ,
Marko Mikulicic 0:c0ecb8bf28eb 2668 TOK_NE,
Marko Mikulicic 0:c0ecb8bf28eb 2669 TOK_NE_NE,
Marko Mikulicic 0:c0ecb8bf28eb 2670
Marko Mikulicic 0:c0ecb8bf28eb 2671 /* Assigns */
Marko Mikulicic 0:c0ecb8bf28eb 2672 TOK_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 2673 TOK_REM_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 2674 TOK_MUL_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 2675 TOK_DIV_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 2676 TOK_XOR_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 2677 TOK_PLUS_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 2678 TOK_MINUS_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 2679 TOK_OR_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 2680 TOK_AND_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 2681 TOK_LSHIFT_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 2682 TOK_RSHIFT_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 2683 TOK_URSHIFT_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 2684 TOK_AND,
Marko Mikulicic 0:c0ecb8bf28eb 2685 TOK_LOGICAL_OR,
Marko Mikulicic 0:c0ecb8bf28eb 2686 TOK_PLUS,
Marko Mikulicic 0:c0ecb8bf28eb 2687 TOK_MINUS,
Marko Mikulicic 0:c0ecb8bf28eb 2688 TOK_PLUS_PLUS,
Marko Mikulicic 0:c0ecb8bf28eb 2689 TOK_MINUS_MINUS,
Marko Mikulicic 0:c0ecb8bf28eb 2690 TOK_LOGICAL_AND,
Marko Mikulicic 0:c0ecb8bf28eb 2691 TOK_OR,
Marko Mikulicic 0:c0ecb8bf28eb 2692 TOK_QUESTION,
Marko Mikulicic 0:c0ecb8bf28eb 2693 TOK_TILDA,
Marko Mikulicic 0:c0ecb8bf28eb 2694 TOK_REM,
Marko Mikulicic 0:c0ecb8bf28eb 2695 TOK_MUL,
Marko Mikulicic 0:c0ecb8bf28eb 2696 TOK_DIV,
Marko Mikulicic 0:c0ecb8bf28eb 2697 TOK_XOR,
Marko Mikulicic 0:c0ecb8bf28eb 2698
Marko Mikulicic 0:c0ecb8bf28eb 2699 /* Relational ops, must go in this order */
Marko Mikulicic 0:c0ecb8bf28eb 2700 TOK_LE,
Marko Mikulicic 0:c0ecb8bf28eb 2701 TOK_LT,
Marko Mikulicic 0:c0ecb8bf28eb 2702 TOK_GE,
Marko Mikulicic 0:c0ecb8bf28eb 2703 TOK_GT,
Marko Mikulicic 0:c0ecb8bf28eb 2704 TOK_LSHIFT,
Marko Mikulicic 0:c0ecb8bf28eb 2705 TOK_RSHIFT,
Marko Mikulicic 0:c0ecb8bf28eb 2706 TOK_URSHIFT,
Marko Mikulicic 0:c0ecb8bf28eb 2707 TOK_NOT,
Marko Mikulicic 0:c0ecb8bf28eb 2708
Marko Mikulicic 0:c0ecb8bf28eb 2709 /* Keywords. must be in the same order as tokenizer.c::s_keywords array */
Marko Mikulicic 0:c0ecb8bf28eb 2710 TOK_BREAK,
Marko Mikulicic 0:c0ecb8bf28eb 2711 TOK_CASE,
Marko Mikulicic 0:c0ecb8bf28eb 2712 TOK_CATCH,
Marko Mikulicic 0:c0ecb8bf28eb 2713 TOK_CONTINUE,
Marko Mikulicic 0:c0ecb8bf28eb 2714 TOK_DEBUGGER,
Marko Mikulicic 0:c0ecb8bf28eb 2715 TOK_DEFAULT,
Marko Mikulicic 0:c0ecb8bf28eb 2716 TOK_DELETE,
Marko Mikulicic 0:c0ecb8bf28eb 2717 TOK_DO,
Marko Mikulicic 0:c0ecb8bf28eb 2718 TOK_ELSE,
Marko Mikulicic 0:c0ecb8bf28eb 2719 TOK_FALSE,
Marko Mikulicic 0:c0ecb8bf28eb 2720 TOK_FINALLY,
Marko Mikulicic 0:c0ecb8bf28eb 2721 TOK_FOR,
Marko Mikulicic 0:c0ecb8bf28eb 2722 TOK_FUNCTION,
Marko Mikulicic 0:c0ecb8bf28eb 2723 TOK_IF,
Marko Mikulicic 0:c0ecb8bf28eb 2724 TOK_IN,
Marko Mikulicic 0:c0ecb8bf28eb 2725 TOK_INSTANCEOF,
Marko Mikulicic 0:c0ecb8bf28eb 2726 TOK_NEW,
Marko Mikulicic 0:c0ecb8bf28eb 2727 TOK_NULL,
Marko Mikulicic 0:c0ecb8bf28eb 2728 TOK_RETURN,
Marko Mikulicic 0:c0ecb8bf28eb 2729 TOK_SWITCH,
Marko Mikulicic 0:c0ecb8bf28eb 2730 TOK_THIS,
Marko Mikulicic 0:c0ecb8bf28eb 2731 TOK_THROW,
Marko Mikulicic 0:c0ecb8bf28eb 2732 TOK_TRUE,
Marko Mikulicic 0:c0ecb8bf28eb 2733 TOK_TRY,
Marko Mikulicic 0:c0ecb8bf28eb 2734 TOK_TYPEOF,
Marko Mikulicic 0:c0ecb8bf28eb 2735 TOK_VAR,
Marko Mikulicic 0:c0ecb8bf28eb 2736 TOK_VOID,
Marko Mikulicic 0:c0ecb8bf28eb 2737 TOK_WHILE,
Marko Mikulicic 0:c0ecb8bf28eb 2738 TOK_WITH,
Marko Mikulicic 0:c0ecb8bf28eb 2739
Marko Mikulicic 0:c0ecb8bf28eb 2740 /* TODO(lsm): process these reserved words too */
Marko Mikulicic 0:c0ecb8bf28eb 2741 TOK_CLASS,
Marko Mikulicic 0:c0ecb8bf28eb 2742 TOK_ENUM,
Marko Mikulicic 0:c0ecb8bf28eb 2743 TOK_EXTENDS,
Marko Mikulicic 0:c0ecb8bf28eb 2744 TOK_SUPER,
Marko Mikulicic 0:c0ecb8bf28eb 2745 TOK_CONST,
Marko Mikulicic 0:c0ecb8bf28eb 2746 TOK_EXPORT,
Marko Mikulicic 0:c0ecb8bf28eb 2747 TOK_IMPORT,
Marko Mikulicic 0:c0ecb8bf28eb 2748 TOK_IMPLEMENTS,
Marko Mikulicic 0:c0ecb8bf28eb 2749 TOK_LET,
Marko Mikulicic 0:c0ecb8bf28eb 2750 TOK_PRIVATE,
Marko Mikulicic 0:c0ecb8bf28eb 2751 TOK_PUBLIC,
Marko Mikulicic 0:c0ecb8bf28eb 2752 TOK_INTERFACE,
Marko Mikulicic 0:c0ecb8bf28eb 2753 TOK_PACKAGE,
Marko Mikulicic 0:c0ecb8bf28eb 2754 TOK_PROTECTED,
Marko Mikulicic 0:c0ecb8bf28eb 2755 TOK_STATIC,
Marko Mikulicic 0:c0ecb8bf28eb 2756 TOK_YIELD,
Marko Mikulicic 0:c0ecb8bf28eb 2757
Marko Mikulicic 0:c0ecb8bf28eb 2758 NUM_TOKENS
Marko Mikulicic 0:c0ecb8bf28eb 2759 };
Marko Mikulicic 0:c0ecb8bf28eb 2760
Marko Mikulicic 0:c0ecb8bf28eb 2761 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 2762 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 2763 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 2764
Marko Mikulicic 0:c0ecb8bf28eb 2765 V7_PRIVATE int skip_to_next_tok(const char **ptr, const char *src_end);
Marko Mikulicic 0:c0ecb8bf28eb 2766 V7_PRIVATE enum v7_tok get_tok(const char **s, const char *src_end, double *n,
Marko Mikulicic 0:c0ecb8bf28eb 2767 enum v7_tok prev_tok);
Marko Mikulicic 0:c0ecb8bf28eb 2768 V7_PRIVATE int is_reserved_word_token(enum v7_tok tok);
Marko Mikulicic 0:c0ecb8bf28eb 2769
Marko Mikulicic 0:c0ecb8bf28eb 2770 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 2771 }
Marko Mikulicic 0:c0ecb8bf28eb 2772 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 2773
Marko Mikulicic 0:c0ecb8bf28eb 2774 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 2775
Marko Mikulicic 0:c0ecb8bf28eb 2776 #endif /* CS_V7_SRC_TOKENIZER_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 2777 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 2778 #line 1 "v7/src/opcodes.h"
Marko Mikulicic 0:c0ecb8bf28eb 2779 #endif
Marko Mikulicic 0:c0ecb8bf28eb 2780 /*
Marko Mikulicic 0:c0ecb8bf28eb 2781 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 2782 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 2783 */
Marko Mikulicic 0:c0ecb8bf28eb 2784
Marko Mikulicic 0:c0ecb8bf28eb 2785 #ifndef CS_V7_SRC_OPCODES_H_
Marko Mikulicic 0:c0ecb8bf28eb 2786 #define CS_V7_SRC_OPCODES_H_
Marko Mikulicic 0:c0ecb8bf28eb 2787
Marko Mikulicic 0:c0ecb8bf28eb 2788 /*
Marko Mikulicic 0:c0ecb8bf28eb 2789 * ==== Instructions
Marko Mikulicic 0:c0ecb8bf28eb 2790 *
Marko Mikulicic 0:c0ecb8bf28eb 2791 * Bytecode instructions consist of 1-byte opcode, optionally followed by N
Marko Mikulicic 0:c0ecb8bf28eb 2792 * bytes of arguments.
Marko Mikulicic 0:c0ecb8bf28eb 2793 *
Marko Mikulicic 0:c0ecb8bf28eb 2794 * Opcodes that accept an index in the literal table (PUSH_LIT, GET_VAR,
Marko Mikulicic 0:c0ecb8bf28eb 2795 * SET_VAR, ...) also accept inline literals. In order to distinguish indices in
Marko Mikulicic 0:c0ecb8bf28eb 2796 * the literals table and the inline literals, indices 0 and 1 are reserved as
Marko Mikulicic 0:c0ecb8bf28eb 2797 * type tags for inline literals:
Marko Mikulicic 0:c0ecb8bf28eb 2798 *
Marko Mikulicic 0:c0ecb8bf28eb 2799 * if 0, the following bytes encode a string literal
Marko Mikulicic 0:c0ecb8bf28eb 2800 * if 1, they encode a number (textual, like in the AST)
Marko Mikulicic 0:c0ecb8bf28eb 2801 *
Marko Mikulicic 0:c0ecb8bf28eb 2802 * (see enum bcode_inline_lit_type_tag)
Marko Mikulicic 0:c0ecb8bf28eb 2803 *
Marko Mikulicic 0:c0ecb8bf28eb 2804 *
Marko Mikulicic 0:c0ecb8bf28eb 2805 * Stack diagrams follow the syntax and semantics of:
Marko Mikulicic 0:c0ecb8bf28eb 2806 *
Marko Mikulicic 0:c0ecb8bf28eb 2807 * http://everything2.com/title/Forth+stack+diagrams[Forth stack diagrams].
Marko Mikulicic 0:c0ecb8bf28eb 2808 *
Marko Mikulicic 0:c0ecb8bf28eb 2809 * We use the following extension in the terminology:
Marko Mikulicic 0:c0ecb8bf28eb 2810 *
Marko Mikulicic 0:c0ecb8bf28eb 2811 * `T`: "Try stack".
Marko Mikulicic 0:c0ecb8bf28eb 2812 * `A`: opcode arguments.
Marko Mikulicic 0:c0ecb8bf28eb 2813 * `S`: stash register (one element stack).
Marko Mikulicic 0:c0ecb8bf28eb 2814 *
Marko Mikulicic 0:c0ecb8bf28eb 2815 */
Marko Mikulicic 0:c0ecb8bf28eb 2816 enum opcode {
Marko Mikulicic 0:c0ecb8bf28eb 2817 /*
Marko Mikulicic 0:c0ecb8bf28eb 2818 * Removes an item from the top of the stack. It is undefined what happens if
Marko Mikulicic 0:c0ecb8bf28eb 2819 * the stack is empty.
Marko Mikulicic 0:c0ecb8bf28eb 2820 *
Marko Mikulicic 0:c0ecb8bf28eb 2821 * `( a -- )`
Marko Mikulicic 0:c0ecb8bf28eb 2822 */
Marko Mikulicic 0:c0ecb8bf28eb 2823 OP_DROP,
Marko Mikulicic 0:c0ecb8bf28eb 2824 /*
Marko Mikulicic 0:c0ecb8bf28eb 2825 * Duplicates a value on top of the stack.
Marko Mikulicic 0:c0ecb8bf28eb 2826 *
Marko Mikulicic 0:c0ecb8bf28eb 2827 * `( a -- a a)`
Marko Mikulicic 0:c0ecb8bf28eb 2828 */
Marko Mikulicic 0:c0ecb8bf28eb 2829 OP_DUP,
Marko Mikulicic 0:c0ecb8bf28eb 2830 /*
Marko Mikulicic 0:c0ecb8bf28eb 2831 * Duplicates 2 values from the top of the stack in the same order.
Marko Mikulicic 0:c0ecb8bf28eb 2832 *
Marko Mikulicic 0:c0ecb8bf28eb 2833 * `( a b -- a b a b)`
Marko Mikulicic 0:c0ecb8bf28eb 2834 */
Marko Mikulicic 0:c0ecb8bf28eb 2835 OP_2DUP,
Marko Mikulicic 0:c0ecb8bf28eb 2836 /*
Marko Mikulicic 0:c0ecb8bf28eb 2837 * Swap the top two items on the stack.
Marko Mikulicic 0:c0ecb8bf28eb 2838 *
Marko Mikulicic 0:c0ecb8bf28eb 2839 * `( a b -- b a )`
Marko Mikulicic 0:c0ecb8bf28eb 2840 */
Marko Mikulicic 0:c0ecb8bf28eb 2841 OP_SWAP,
Marko Mikulicic 0:c0ecb8bf28eb 2842 /*
Marko Mikulicic 0:c0ecb8bf28eb 2843 * Copy current top of the stack to the temporary stash register.
Marko Mikulicic 0:c0ecb8bf28eb 2844 *
Marko Mikulicic 0:c0ecb8bf28eb 2845 * The content of the stash register will be cleared in the event of an
Marko Mikulicic 0:c0ecb8bf28eb 2846 * exception.
Marko Mikulicic 0:c0ecb8bf28eb 2847 *
Marko Mikulicic 0:c0ecb8bf28eb 2848 * `( a S: b -- a S: a)` saves TOS to stash reg
Marko Mikulicic 0:c0ecb8bf28eb 2849 */
Marko Mikulicic 0:c0ecb8bf28eb 2850 OP_STASH,
Marko Mikulicic 0:c0ecb8bf28eb 2851 /*
Marko Mikulicic 0:c0ecb8bf28eb 2852 * Replace the top of the stack with the content of the temporary stash
Marko Mikulicic 0:c0ecb8bf28eb 2853 * register.
Marko Mikulicic 0:c0ecb8bf28eb 2854 *
Marko Mikulicic 0:c0ecb8bf28eb 2855 * The stash register is cleared afterwards.
Marko Mikulicic 0:c0ecb8bf28eb 2856 *
Marko Mikulicic 0:c0ecb8bf28eb 2857 * `( a S: b -- b S: nil )` replaces tos with stash reg
Marko Mikulicic 0:c0ecb8bf28eb 2858 */
Marko Mikulicic 0:c0ecb8bf28eb 2859 OP_UNSTASH,
Marko Mikulicic 0:c0ecb8bf28eb 2860
Marko Mikulicic 0:c0ecb8bf28eb 2861 /*
Marko Mikulicic 0:c0ecb8bf28eb 2862 * Effectively drops the last-but-one element from stack
Marko Mikulicic 0:c0ecb8bf28eb 2863 *
Marko Mikulicic 0:c0ecb8bf28eb 2864 * `( a b -- b )`
Marko Mikulicic 0:c0ecb8bf28eb 2865 */
Marko Mikulicic 0:c0ecb8bf28eb 2866 OP_SWAP_DROP,
Marko Mikulicic 0:c0ecb8bf28eb 2867
Marko Mikulicic 0:c0ecb8bf28eb 2868 /*
Marko Mikulicic 0:c0ecb8bf28eb 2869 * Pushes `undefined` onto the stack.
Marko Mikulicic 0:c0ecb8bf28eb 2870 *
Marko Mikulicic 0:c0ecb8bf28eb 2871 * `( -- undefined )`
Marko Mikulicic 0:c0ecb8bf28eb 2872 */
Marko Mikulicic 0:c0ecb8bf28eb 2873 OP_PUSH_UNDEFINED,
Marko Mikulicic 0:c0ecb8bf28eb 2874 /*
Marko Mikulicic 0:c0ecb8bf28eb 2875 * Pushes `null` onto the stack.
Marko Mikulicic 0:c0ecb8bf28eb 2876 *
Marko Mikulicic 0:c0ecb8bf28eb 2877 * `( -- null )`
Marko Mikulicic 0:c0ecb8bf28eb 2878 */
Marko Mikulicic 0:c0ecb8bf28eb 2879 OP_PUSH_NULL,
Marko Mikulicic 0:c0ecb8bf28eb 2880 /*
Marko Mikulicic 0:c0ecb8bf28eb 2881 * Pushes current value of `this` onto the stack.
Marko Mikulicic 0:c0ecb8bf28eb 2882 *
Marko Mikulicic 0:c0ecb8bf28eb 2883 * `( -- this )`
Marko Mikulicic 0:c0ecb8bf28eb 2884 */
Marko Mikulicic 0:c0ecb8bf28eb 2885 OP_PUSH_THIS,
Marko Mikulicic 0:c0ecb8bf28eb 2886 /*
Marko Mikulicic 0:c0ecb8bf28eb 2887 * Pushes `true` onto the stack.
Marko Mikulicic 0:c0ecb8bf28eb 2888 *
Marko Mikulicic 0:c0ecb8bf28eb 2889 * `( -- true )`
Marko Mikulicic 0:c0ecb8bf28eb 2890 */
Marko Mikulicic 0:c0ecb8bf28eb 2891 OP_PUSH_TRUE,
Marko Mikulicic 0:c0ecb8bf28eb 2892 /*
Marko Mikulicic 0:c0ecb8bf28eb 2893 * Pushes `false` onto the stack.
Marko Mikulicic 0:c0ecb8bf28eb 2894 *
Marko Mikulicic 0:c0ecb8bf28eb 2895 * `( -- false )`
Marko Mikulicic 0:c0ecb8bf28eb 2896 */
Marko Mikulicic 0:c0ecb8bf28eb 2897 OP_PUSH_FALSE,
Marko Mikulicic 0:c0ecb8bf28eb 2898 /*
Marko Mikulicic 0:c0ecb8bf28eb 2899 * Pushes `0` onto the stack.
Marko Mikulicic 0:c0ecb8bf28eb 2900 *
Marko Mikulicic 0:c0ecb8bf28eb 2901 * `( -- 0 )`
Marko Mikulicic 0:c0ecb8bf28eb 2902 */
Marko Mikulicic 0:c0ecb8bf28eb 2903 OP_PUSH_ZERO,
Marko Mikulicic 0:c0ecb8bf28eb 2904 /*
Marko Mikulicic 0:c0ecb8bf28eb 2905 * Pushes `1` onto the stack.
Marko Mikulicic 0:c0ecb8bf28eb 2906 *
Marko Mikulicic 0:c0ecb8bf28eb 2907 * `( -- 1 )`
Marko Mikulicic 0:c0ecb8bf28eb 2908 */
Marko Mikulicic 0:c0ecb8bf28eb 2909 OP_PUSH_ONE,
Marko Mikulicic 0:c0ecb8bf28eb 2910
Marko Mikulicic 0:c0ecb8bf28eb 2911 /*
Marko Mikulicic 0:c0ecb8bf28eb 2912 * Pushes a value from literals table onto the stack.
Marko Mikulicic 0:c0ecb8bf28eb 2913 *
Marko Mikulicic 0:c0ecb8bf28eb 2914 * The opcode takes a varint operand interpreted as an index in the current
Marko Mikulicic 0:c0ecb8bf28eb 2915 * literal table (see lit table).
Marko Mikulicic 0:c0ecb8bf28eb 2916 *
Marko Mikulicic 0:c0ecb8bf28eb 2917 * ( -- a )
Marko Mikulicic 0:c0ecb8bf28eb 2918 */
Marko Mikulicic 0:c0ecb8bf28eb 2919 OP_PUSH_LIT,
Marko Mikulicic 0:c0ecb8bf28eb 2920
Marko Mikulicic 0:c0ecb8bf28eb 2921 OP_NOT,
Marko Mikulicic 0:c0ecb8bf28eb 2922 OP_LOGICAL_NOT,
Marko Mikulicic 0:c0ecb8bf28eb 2923
Marko Mikulicic 0:c0ecb8bf28eb 2924 /*
Marko Mikulicic 0:c0ecb8bf28eb 2925 * Takes a number from the top of the stack, inverts the sign and pushes it
Marko Mikulicic 0:c0ecb8bf28eb 2926 * back.
Marko Mikulicic 0:c0ecb8bf28eb 2927 *
Marko Mikulicic 0:c0ecb8bf28eb 2928 * `( a -- -a )`
Marko Mikulicic 0:c0ecb8bf28eb 2929 */
Marko Mikulicic 0:c0ecb8bf28eb 2930 OP_NEG,
Marko Mikulicic 0:c0ecb8bf28eb 2931 /*
Marko Mikulicic 0:c0ecb8bf28eb 2932 * Takes a number from the top of the stack pushes the evaluation of
Marko Mikulicic 0:c0ecb8bf28eb 2933 * `Number()`.
Marko Mikulicic 0:c0ecb8bf28eb 2934 *
Marko Mikulicic 0:c0ecb8bf28eb 2935 * `( a -- Number(a) )`
Marko Mikulicic 0:c0ecb8bf28eb 2936 */
Marko Mikulicic 0:c0ecb8bf28eb 2937 OP_POS,
Marko Mikulicic 0:c0ecb8bf28eb 2938
Marko Mikulicic 0:c0ecb8bf28eb 2939 /*
Marko Mikulicic 0:c0ecb8bf28eb 2940 * Takes 2 values from the top of the stack and performs addition operation:
Marko Mikulicic 0:c0ecb8bf28eb 2941 * If any of the two values is not `undefined`, number or boolean, both values
Marko Mikulicic 0:c0ecb8bf28eb 2942 * are converted into strings and concatenated.
Marko Mikulicic 0:c0ecb8bf28eb 2943 * Otherwise, both values are treated as numbers:
Marko Mikulicic 0:c0ecb8bf28eb 2944 * * `undefined` is converted into NaN
Marko Mikulicic 0:c0ecb8bf28eb 2945 * * `true` is converted into 1
Marko Mikulicic 0:c0ecb8bf28eb 2946 * * `false` is converted into 0
Marko Mikulicic 0:c0ecb8bf28eb 2947 *
Marko Mikulicic 0:c0ecb8bf28eb 2948 * Result is pushed back onto the stack.
Marko Mikulicic 0:c0ecb8bf28eb 2949 *
Marko Mikulicic 0:c0ecb8bf28eb 2950 * TODO: make it behave exactly like JavaScript's `+` operator.
Marko Mikulicic 0:c0ecb8bf28eb 2951 *
Marko Mikulicic 0:c0ecb8bf28eb 2952 * `( a b -- a+b )`
Marko Mikulicic 0:c0ecb8bf28eb 2953 */
Marko Mikulicic 0:c0ecb8bf28eb 2954 OP_ADD,
Marko Mikulicic 0:c0ecb8bf28eb 2955 OP_SUB, /* ( a b -- a-b ) */
Marko Mikulicic 0:c0ecb8bf28eb 2956 OP_REM, /* ( a b -- a%b ) */
Marko Mikulicic 0:c0ecb8bf28eb 2957 OP_MUL, /* ( a b -- a*b ) */
Marko Mikulicic 0:c0ecb8bf28eb 2958 OP_DIV, /* ( a b -- a/b ) */
Marko Mikulicic 0:c0ecb8bf28eb 2959 OP_LSHIFT, /* ( a b -- a<<b ) */
Marko Mikulicic 0:c0ecb8bf28eb 2960 OP_RSHIFT, /* ( a b -- a>>b ) */
Marko Mikulicic 0:c0ecb8bf28eb 2961 OP_URSHIFT, /* ( a b -- a>>>b ) */
Marko Mikulicic 0:c0ecb8bf28eb 2962 OP_OR, /* ( a b -- a|b ) */
Marko Mikulicic 0:c0ecb8bf28eb 2963 OP_XOR, /* ( a b -- a^b ) */
Marko Mikulicic 0:c0ecb8bf28eb 2964 OP_AND, /* ( a b -- a&b ) */
Marko Mikulicic 0:c0ecb8bf28eb 2965
Marko Mikulicic 0:c0ecb8bf28eb 2966 /*
Marko Mikulicic 0:c0ecb8bf28eb 2967 * Takes two numbers form the top of the stack and pushes `true` if they are
Marko Mikulicic 0:c0ecb8bf28eb 2968 * equal, or `false` if they are not equal.
Marko Mikulicic 0:c0ecb8bf28eb 2969 *
Marko Mikulicic 0:c0ecb8bf28eb 2970 * ( a b -- a===b )
Marko Mikulicic 0:c0ecb8bf28eb 2971 */
Marko Mikulicic 0:c0ecb8bf28eb 2972 OP_EQ_EQ,
Marko Mikulicic 0:c0ecb8bf28eb 2973 OP_EQ, /* ( a b -- a==b ) */
Marko Mikulicic 0:c0ecb8bf28eb 2974 OP_NE, /* ( a b -- a!=b ) */
Marko Mikulicic 0:c0ecb8bf28eb 2975 OP_NE_NE, /* ( a b -- a!==b ) */
Marko Mikulicic 0:c0ecb8bf28eb 2976 OP_LT, /* ( a b -- a<b ) */
Marko Mikulicic 0:c0ecb8bf28eb 2977 OP_LE, /* ( a b -- a<=b ) */
Marko Mikulicic 0:c0ecb8bf28eb 2978 OP_GT, /* ( a b -- a>b ) */
Marko Mikulicic 0:c0ecb8bf28eb 2979 OP_GE, /* ( a b -- a>=b ) */
Marko Mikulicic 0:c0ecb8bf28eb 2980 OP_INSTANCEOF,
Marko Mikulicic 0:c0ecb8bf28eb 2981
Marko Mikulicic 0:c0ecb8bf28eb 2982 OP_TYPEOF,
Marko Mikulicic 0:c0ecb8bf28eb 2983
Marko Mikulicic 0:c0ecb8bf28eb 2984 OP_IN,
Marko Mikulicic 0:c0ecb8bf28eb 2985 /*
Marko Mikulicic 0:c0ecb8bf28eb 2986 * Takes 2 values from the stack, treats the top of the stack as property name
Marko Mikulicic 0:c0ecb8bf28eb 2987 * and the next value must be an object, an array or a string.
Marko Mikulicic 0:c0ecb8bf28eb 2988 * If it's an object, pushes the value of its named property onto the stack.
Marko Mikulicic 0:c0ecb8bf28eb 2989 * If it's an array or a string, returns a value at a given position.
Marko Mikulicic 0:c0ecb8bf28eb 2990 */
Marko Mikulicic 0:c0ecb8bf28eb 2991 OP_GET,
Marko Mikulicic 0:c0ecb8bf28eb 2992 /*
Marko Mikulicic 0:c0ecb8bf28eb 2993 * Takes 3 items from the stack: value, property name, object. Sets the given
Marko Mikulicic 0:c0ecb8bf28eb 2994 * property of a given object to a given value, pushes value back onto the
Marko Mikulicic 0:c0ecb8bf28eb 2995 *stack.
Marko Mikulicic 0:c0ecb8bf28eb 2996 *
Marko Mikulicic 0:c0ecb8bf28eb 2997 * `( a b c -- a[b]=c )`
Marko Mikulicic 0:c0ecb8bf28eb 2998 */
Marko Mikulicic 0:c0ecb8bf28eb 2999 OP_SET,
Marko Mikulicic 0:c0ecb8bf28eb 3000 /*
Marko Mikulicic 0:c0ecb8bf28eb 3001 * Takes 1 value from the stack and a varint argument -- index of the var name
Marko Mikulicic 0:c0ecb8bf28eb 3002 * in the literals table. Tries to find the variable in the current scope
Marko Mikulicic 0:c0ecb8bf28eb 3003 * chain and assign the value to it. If the varialble is not found -- creates
Marko Mikulicic 0:c0ecb8bf28eb 3004 * a new one in the global scope. Pushes the value back to the stack.
Marko Mikulicic 0:c0ecb8bf28eb 3005 *
Marko Mikulicic 0:c0ecb8bf28eb 3006 * `( a -- a )`
Marko Mikulicic 0:c0ecb8bf28eb 3007 */
Marko Mikulicic 0:c0ecb8bf28eb 3008 OP_SET_VAR,
Marko Mikulicic 0:c0ecb8bf28eb 3009 /*
Marko Mikulicic 0:c0ecb8bf28eb 3010 * Takes a varint argument -- index of the var name in the literals table.
Marko Mikulicic 0:c0ecb8bf28eb 3011 * Looks up that variable in the scope chain and pushes its value onto the
Marko Mikulicic 0:c0ecb8bf28eb 3012 * stack.
Marko Mikulicic 0:c0ecb8bf28eb 3013 *
Marko Mikulicic 0:c0ecb8bf28eb 3014 * `( -- a )`
Marko Mikulicic 0:c0ecb8bf28eb 3015 */
Marko Mikulicic 0:c0ecb8bf28eb 3016 OP_GET_VAR,
Marko Mikulicic 0:c0ecb8bf28eb 3017
Marko Mikulicic 0:c0ecb8bf28eb 3018 /*
Marko Mikulicic 0:c0ecb8bf28eb 3019 * Like OP_GET_VAR but returns undefined
Marko Mikulicic 0:c0ecb8bf28eb 3020 * instead of throwing reference error.
Marko Mikulicic 0:c0ecb8bf28eb 3021 *
Marko Mikulicic 0:c0ecb8bf28eb 3022 * `( -- a )`
Marko Mikulicic 0:c0ecb8bf28eb 3023 */
Marko Mikulicic 0:c0ecb8bf28eb 3024 OP_SAFE_GET_VAR,
Marko Mikulicic 0:c0ecb8bf28eb 3025
Marko Mikulicic 0:c0ecb8bf28eb 3026 /*
Marko Mikulicic 0:c0ecb8bf28eb 3027 * ==== Jumps
Marko Mikulicic 0:c0ecb8bf28eb 3028 *
Marko Mikulicic 0:c0ecb8bf28eb 3029 * All jump instructions take one 4-byte argument: offset to jump to. Offset
Marko Mikulicic 0:c0ecb8bf28eb 3030 *is a
Marko Mikulicic 0:c0ecb8bf28eb 3031 * index of the byte in the instruction stream, starting with 0. No byte order
Marko Mikulicic 0:c0ecb8bf28eb 3032 * conversion is applied.
Marko Mikulicic 0:c0ecb8bf28eb 3033 *
Marko Mikulicic 0:c0ecb8bf28eb 3034 * TODO: specify byte order for the offset.
Marko Mikulicic 0:c0ecb8bf28eb 3035 */
Marko Mikulicic 0:c0ecb8bf28eb 3036
Marko Mikulicic 0:c0ecb8bf28eb 3037 /*
Marko Mikulicic 0:c0ecb8bf28eb 3038 * Unconditiona jump.
Marko Mikulicic 0:c0ecb8bf28eb 3039 */
Marko Mikulicic 0:c0ecb8bf28eb 3040 OP_JMP,
Marko Mikulicic 0:c0ecb8bf28eb 3041 /*
Marko Mikulicic 0:c0ecb8bf28eb 3042 * Takes one value from the stack and performs a jump if conversion of that
Marko Mikulicic 0:c0ecb8bf28eb 3043 * value to boolean results in `true`.
Marko Mikulicic 0:c0ecb8bf28eb 3044 *
Marko Mikulicic 0:c0ecb8bf28eb 3045 * `( a -- )`
Marko Mikulicic 0:c0ecb8bf28eb 3046 */
Marko Mikulicic 0:c0ecb8bf28eb 3047 OP_JMP_TRUE,
Marko Mikulicic 0:c0ecb8bf28eb 3048 /*
Marko Mikulicic 0:c0ecb8bf28eb 3049 * Takes one value from the stack and performs a jump if conversion of that
Marko Mikulicic 0:c0ecb8bf28eb 3050 * value to boolean results in `false`.
Marko Mikulicic 0:c0ecb8bf28eb 3051 *
Marko Mikulicic 0:c0ecb8bf28eb 3052 * `( a -- )`
Marko Mikulicic 0:c0ecb8bf28eb 3053 */
Marko Mikulicic 0:c0ecb8bf28eb 3054 OP_JMP_FALSE,
Marko Mikulicic 0:c0ecb8bf28eb 3055 /*
Marko Mikulicic 0:c0ecb8bf28eb 3056 * Like OP_JMP_TRUE but if the branch
Marko Mikulicic 0:c0ecb8bf28eb 3057 * is taken it also drops another stack element:
Marko Mikulicic 0:c0ecb8bf28eb 3058 *
Marko Mikulicic 0:c0ecb8bf28eb 3059 * if `b` is true: `( a b -- )`
Marko Mikulicic 0:c0ecb8bf28eb 3060 * if `b` is false: `( a b -- a )`
Marko Mikulicic 0:c0ecb8bf28eb 3061 */
Marko Mikulicic 0:c0ecb8bf28eb 3062 OP_JMP_TRUE_DROP,
Marko Mikulicic 0:c0ecb8bf28eb 3063
Marko Mikulicic 0:c0ecb8bf28eb 3064 /*
Marko Mikulicic 0:c0ecb8bf28eb 3065 * Conditional jump on the v7->is_continuing flag.
Marko Mikulicic 0:c0ecb8bf28eb 3066 * Clears the flag once executed.
Marko Mikulicic 0:c0ecb8bf28eb 3067 *
Marko Mikulicic 0:c0ecb8bf28eb 3068 * `( -- )`
Marko Mikulicic 0:c0ecb8bf28eb 3069 */
Marko Mikulicic 0:c0ecb8bf28eb 3070 OP_JMP_IF_CONTINUE,
Marko Mikulicic 0:c0ecb8bf28eb 3071
Marko Mikulicic 0:c0ecb8bf28eb 3072 /*
Marko Mikulicic 0:c0ecb8bf28eb 3073 * Constructs a new empty object and pushes it onto the stack.
Marko Mikulicic 0:c0ecb8bf28eb 3074 *
Marko Mikulicic 0:c0ecb8bf28eb 3075 * `( -- {} )`
Marko Mikulicic 0:c0ecb8bf28eb 3076 */
Marko Mikulicic 0:c0ecb8bf28eb 3077 OP_CREATE_OBJ,
Marko Mikulicic 0:c0ecb8bf28eb 3078 /*
Marko Mikulicic 0:c0ecb8bf28eb 3079 * Constructs a new empty array and pushes it onto the stack.
Marko Mikulicic 0:c0ecb8bf28eb 3080 *
Marko Mikulicic 0:c0ecb8bf28eb 3081 * `( -- [] )`
Marko Mikulicic 0:c0ecb8bf28eb 3082 */
Marko Mikulicic 0:c0ecb8bf28eb 3083 OP_CREATE_ARR,
Marko Mikulicic 0:c0ecb8bf28eb 3084
Marko Mikulicic 0:c0ecb8bf28eb 3085 /*
Marko Mikulicic 0:c0ecb8bf28eb 3086 * Allocates the iteration context (for `OP_NEXT_PROP`) from heap and pushes
Marko Mikulicic 0:c0ecb8bf28eb 3087 * a foreign pointer to it on stack. The allocated data is stored as "user
Marko Mikulicic 0:c0ecb8bf28eb 3088 * data" of the object, and it will be reclaimed automatically when the
Marko Mikulicic 0:c0ecb8bf28eb 3089 * object gets garbage-collected.
Marko Mikulicic 0:c0ecb8bf28eb 3090 *
Marko Mikulicic 0:c0ecb8bf28eb 3091 * `( -- ctx )`
Marko Mikulicic 0:c0ecb8bf28eb 3092 */
Marko Mikulicic 0:c0ecb8bf28eb 3093 OP_PUSH_PROP_ITER_CTX,
Marko Mikulicic 0:c0ecb8bf28eb 3094
Marko Mikulicic 0:c0ecb8bf28eb 3095 /*
Marko Mikulicic 0:c0ecb8bf28eb 3096 * Yields the next property name.
Marko Mikulicic 0:c0ecb8bf28eb 3097 * Used in the for..in construct.
Marko Mikulicic 0:c0ecb8bf28eb 3098 *
Marko Mikulicic 0:c0ecb8bf28eb 3099 * The first evaluation must receive `null` as handle.
Marko Mikulicic 0:c0ecb8bf28eb 3100 * Subsequent evaluations will either:
Marko Mikulicic 0:c0ecb8bf28eb 3101 *
Marko Mikulicic 0:c0ecb8bf28eb 3102 * a) produce a new handle, the key and true value:
Marko Mikulicic 0:c0ecb8bf28eb 3103 *
Marko Mikulicic 0:c0ecb8bf28eb 3104 * `( o h -- o h' key true)`
Marko Mikulicic 0:c0ecb8bf28eb 3105 *
Marko Mikulicic 0:c0ecb8bf28eb 3106 * b) produce a false value only, indicating no more properties:
Marko Mikulicic 0:c0ecb8bf28eb 3107 *
Marko Mikulicic 0:c0ecb8bf28eb 3108 * `( o h -- false)`
Marko Mikulicic 0:c0ecb8bf28eb 3109 */
Marko Mikulicic 0:c0ecb8bf28eb 3110 OP_NEXT_PROP,
Marko Mikulicic 0:c0ecb8bf28eb 3111
Marko Mikulicic 0:c0ecb8bf28eb 3112 /*
Marko Mikulicic 0:c0ecb8bf28eb 3113 * Copies the function object at TOS and assigns current scope
Marko Mikulicic 0:c0ecb8bf28eb 3114 * in func->scope.
Marko Mikulicic 0:c0ecb8bf28eb 3115 *
Marko Mikulicic 0:c0ecb8bf28eb 3116 * `( a -- a )`
Marko Mikulicic 0:c0ecb8bf28eb 3117 */
Marko Mikulicic 0:c0ecb8bf28eb 3118 OP_FUNC_LIT,
Marko Mikulicic 0:c0ecb8bf28eb 3119 /*
Marko Mikulicic 0:c0ecb8bf28eb 3120 * Takes the number of arguments as parameter.
Marko Mikulicic 0:c0ecb8bf28eb 3121 *
Marko Mikulicic 0:c0ecb8bf28eb 3122 * Pops N function arguments from stack, then pops function, then pops `this`.
Marko Mikulicic 0:c0ecb8bf28eb 3123 * Calls a function and populates TOS with the returned value.
Marko Mikulicic 0:c0ecb8bf28eb 3124 *
Marko Mikulicic 0:c0ecb8bf28eb 3125 * `( this f a0 a1 ... aN -- f(a0,a1,...) )`
Marko Mikulicic 0:c0ecb8bf28eb 3126 */
Marko Mikulicic 0:c0ecb8bf28eb 3127 OP_CALL,
Marko Mikulicic 0:c0ecb8bf28eb 3128 OP_NEW,
Marko Mikulicic 0:c0ecb8bf28eb 3129 /*
Marko Mikulicic 0:c0ecb8bf28eb 3130 * Checks that TOS is a callable and if not saves an exception
Marko Mikulicic 0:c0ecb8bf28eb 3131 * that will will be thrown by CALL after all arguments have been evaluated.
Marko Mikulicic 0:c0ecb8bf28eb 3132 */
Marko Mikulicic 0:c0ecb8bf28eb 3133 OP_CHECK_CALL,
Marko Mikulicic 0:c0ecb8bf28eb 3134 /*
Marko Mikulicic 0:c0ecb8bf28eb 3135 * Returns the current function.
Marko Mikulicic 0:c0ecb8bf28eb 3136 *
Marko Mikulicic 0:c0ecb8bf28eb 3137 * It has no stack side effects. The function upon return will leave the
Marko Mikulicic 0:c0ecb8bf28eb 3138 * return value on the stack. The return value must be pushed on the stack
Marko Mikulicic 0:c0ecb8bf28eb 3139 * prior to invoking a RET.
Marko Mikulicic 0:c0ecb8bf28eb 3140 *
Marko Mikulicic 0:c0ecb8bf28eb 3141 * `( -- )`
Marko Mikulicic 0:c0ecb8bf28eb 3142 */
Marko Mikulicic 0:c0ecb8bf28eb 3143 OP_RET,
Marko Mikulicic 0:c0ecb8bf28eb 3144
Marko Mikulicic 0:c0ecb8bf28eb 3145 /*
Marko Mikulicic 0:c0ecb8bf28eb 3146 * Deletes the property of given name `p` from the given object `o`. Returns
Marko Mikulicic 0:c0ecb8bf28eb 3147 * boolean value `a`.
Marko Mikulicic 0:c0ecb8bf28eb 3148 *
Marko Mikulicic 0:c0ecb8bf28eb 3149 * `( o p -- a )`
Marko Mikulicic 0:c0ecb8bf28eb 3150 */
Marko Mikulicic 0:c0ecb8bf28eb 3151 OP_DELETE,
Marko Mikulicic 0:c0ecb8bf28eb 3152
Marko Mikulicic 0:c0ecb8bf28eb 3153 /*
Marko Mikulicic 0:c0ecb8bf28eb 3154 * Like `OP_DELETE`, but uses the current scope as an object to delete
Marko Mikulicic 0:c0ecb8bf28eb 3155 * a property from.
Marko Mikulicic 0:c0ecb8bf28eb 3156 *
Marko Mikulicic 0:c0ecb8bf28eb 3157 * `( p -- a )`
Marko Mikulicic 0:c0ecb8bf28eb 3158 */
Marko Mikulicic 0:c0ecb8bf28eb 3159 OP_DELETE_VAR,
Marko Mikulicic 0:c0ecb8bf28eb 3160
Marko Mikulicic 0:c0ecb8bf28eb 3161 /*
Marko Mikulicic 0:c0ecb8bf28eb 3162 * Pushes a value (bcode offset of `catch` block) from opcode argument to
Marko Mikulicic 0:c0ecb8bf28eb 3163 * "try stack".
Marko Mikulicic 0:c0ecb8bf28eb 3164 *
Marko Mikulicic 0:c0ecb8bf28eb 3165 * Used in the beginning of the `try` block.
Marko Mikulicic 0:c0ecb8bf28eb 3166 *
Marko Mikulicic 0:c0ecb8bf28eb 3167 * `( A: a -- T: a )`
Marko Mikulicic 0:c0ecb8bf28eb 3168 */
Marko Mikulicic 0:c0ecb8bf28eb 3169 OP_TRY_PUSH_CATCH,
Marko Mikulicic 0:c0ecb8bf28eb 3170
Marko Mikulicic 0:c0ecb8bf28eb 3171 /*
Marko Mikulicic 0:c0ecb8bf28eb 3172 * Pushes a value (bcode offset of `finally` block) from opcode argument to
Marko Mikulicic 0:c0ecb8bf28eb 3173 * "try stack".
Marko Mikulicic 0:c0ecb8bf28eb 3174 *
Marko Mikulicic 0:c0ecb8bf28eb 3175 * Used in the beginning of the `try` block.
Marko Mikulicic 0:c0ecb8bf28eb 3176 *
Marko Mikulicic 0:c0ecb8bf28eb 3177 * `( A: a -- T: a )`
Marko Mikulicic 0:c0ecb8bf28eb 3178 *
Marko Mikulicic 0:c0ecb8bf28eb 3179 * TODO: implement me
Marko Mikulicic 0:c0ecb8bf28eb 3180 */
Marko Mikulicic 0:c0ecb8bf28eb 3181 OP_TRY_PUSH_FINALLY,
Marko Mikulicic 0:c0ecb8bf28eb 3182
Marko Mikulicic 0:c0ecb8bf28eb 3183 /*
Marko Mikulicic 0:c0ecb8bf28eb 3184 * Pushes a value (bcode offset of a label) from opcode argument to
Marko Mikulicic 0:c0ecb8bf28eb 3185 * "try stack".
Marko Mikulicic 0:c0ecb8bf28eb 3186 *
Marko Mikulicic 0:c0ecb8bf28eb 3187 * Used at the beginning of loops that contain break or continue.
Marko Mikulicic 0:c0ecb8bf28eb 3188 * Possible optimisation: don't emit if we can ensure that no break or
Marko Mikulicic 0:c0ecb8bf28eb 3189 * continue statement is used.
Marko Mikulicic 0:c0ecb8bf28eb 3190 *
Marko Mikulicic 0:c0ecb8bf28eb 3191 * `( A: a -- T: a )`
Marko Mikulicic 0:c0ecb8bf28eb 3192 */
Marko Mikulicic 0:c0ecb8bf28eb 3193 OP_TRY_PUSH_LOOP,
Marko Mikulicic 0:c0ecb8bf28eb 3194
Marko Mikulicic 0:c0ecb8bf28eb 3195 /*
Marko Mikulicic 0:c0ecb8bf28eb 3196 * Pushes a value (bcode offset of a label) from opcode argument to
Marko Mikulicic 0:c0ecb8bf28eb 3197 * "try stack".
Marko Mikulicic 0:c0ecb8bf28eb 3198 *
Marko Mikulicic 0:c0ecb8bf28eb 3199 * Used at the beginning of switch statements.
Marko Mikulicic 0:c0ecb8bf28eb 3200 *
Marko Mikulicic 0:c0ecb8bf28eb 3201 * `( A: a -- T: a )`
Marko Mikulicic 0:c0ecb8bf28eb 3202 */
Marko Mikulicic 0:c0ecb8bf28eb 3203 OP_TRY_PUSH_SWITCH,
Marko Mikulicic 0:c0ecb8bf28eb 3204
Marko Mikulicic 0:c0ecb8bf28eb 3205 /*
Marko Mikulicic 0:c0ecb8bf28eb 3206 * Pops a value (bcode offset of `finally` or `catch` block) from "try
Marko Mikulicic 0:c0ecb8bf28eb 3207 * stack", and discards it
Marko Mikulicic 0:c0ecb8bf28eb 3208 *
Marko Mikulicic 0:c0ecb8bf28eb 3209 * Used in the end of the `try` block, as well as in the beginning of the
Marko Mikulicic 0:c0ecb8bf28eb 3210 * `catch` and `finally` blocks
Marko Mikulicic 0:c0ecb8bf28eb 3211 *
Marko Mikulicic 0:c0ecb8bf28eb 3212 * `( T: a -- T: )`
Marko Mikulicic 0:c0ecb8bf28eb 3213 */
Marko Mikulicic 0:c0ecb8bf28eb 3214 OP_TRY_POP,
Marko Mikulicic 0:c0ecb8bf28eb 3215
Marko Mikulicic 0:c0ecb8bf28eb 3216 /*
Marko Mikulicic 0:c0ecb8bf28eb 3217 * Used in the end of the `finally` block:
Marko Mikulicic 0:c0ecb8bf28eb 3218 *
Marko Mikulicic 0:c0ecb8bf28eb 3219 * - if some value is currently being thrown, keep throwing it.
Marko Mikulicic 0:c0ecb8bf28eb 3220 * If eventually we encounter `catch` block, the thrown value gets
Marko Mikulicic 0:c0ecb8bf28eb 3221 * populated on TOS:
Marko Mikulicic 0:c0ecb8bf28eb 3222 *
Marko Mikulicic 0:c0ecb8bf28eb 3223 * `( -- a )`
Marko Mikulicic 0:c0ecb8bf28eb 3224 *
Marko Mikulicic 0:c0ecb8bf28eb 3225 * - if there is some pending value to return, keep returning it.
Marko Mikulicic 0:c0ecb8bf28eb 3226 * If we encounter no further `finally` blocks, then the returned value
Marko Mikulicic 0:c0ecb8bf28eb 3227 * gets populated on TOS:
Marko Mikulicic 0:c0ecb8bf28eb 3228 *
Marko Mikulicic 0:c0ecb8bf28eb 3229 * `( -- a )`
Marko Mikulicic 0:c0ecb8bf28eb 3230 *
Marko Mikulicic 0:c0ecb8bf28eb 3231 * And return is performed.
Marko Mikulicic 0:c0ecb8bf28eb 3232 *
Marko Mikulicic 0:c0ecb8bf28eb 3233 * - otherwise, do nothing
Marko Mikulicic 0:c0ecb8bf28eb 3234 */
Marko Mikulicic 0:c0ecb8bf28eb 3235 OP_AFTER_FINALLY,
Marko Mikulicic 0:c0ecb8bf28eb 3236
Marko Mikulicic 0:c0ecb8bf28eb 3237 /*
Marko Mikulicic 0:c0ecb8bf28eb 3238 * Throw value from TOS. First of all, it pops the value and saves it into
Marko Mikulicic 0:c0ecb8bf28eb 3239 * `v7->vals.thrown_error`:
Marko Mikulicic 0:c0ecb8bf28eb 3240 *
Marko Mikulicic 0:c0ecb8bf28eb 3241 * `( a -- )`
Marko Mikulicic 0:c0ecb8bf28eb 3242 *
Marko Mikulicic 0:c0ecb8bf28eb 3243 * Then unwinds stack looking for the first `catch` or `finally` blocks.
Marko Mikulicic 0:c0ecb8bf28eb 3244 *
Marko Mikulicic 0:c0ecb8bf28eb 3245 * - if `finally` is found, thrown value is kept into `v7->vals.thrown_error`.
Marko Mikulicic 0:c0ecb8bf28eb 3246 * - if `catch` is found, thrown value is pushed back to the stack:
Marko Mikulicic 0:c0ecb8bf28eb 3247 * `( -- a )`
Marko Mikulicic 0:c0ecb8bf28eb 3248 * - otherwise, thrown value is kept into `v7->vals.thrown_error`
Marko Mikulicic 0:c0ecb8bf28eb 3249 */
Marko Mikulicic 0:c0ecb8bf28eb 3250 OP_THROW,
Marko Mikulicic 0:c0ecb8bf28eb 3251
Marko Mikulicic 0:c0ecb8bf28eb 3252 /*
Marko Mikulicic 0:c0ecb8bf28eb 3253 * Unwind to next break entry in the try stack, evaluating
Marko Mikulicic 0:c0ecb8bf28eb 3254 * all finally blocks on its way up.
Marko Mikulicic 0:c0ecb8bf28eb 3255 *
Marko Mikulicic 0:c0ecb8bf28eb 3256 * `( -- )`
Marko Mikulicic 0:c0ecb8bf28eb 3257 */
Marko Mikulicic 0:c0ecb8bf28eb 3258 OP_BREAK,
Marko Mikulicic 0:c0ecb8bf28eb 3259
Marko Mikulicic 0:c0ecb8bf28eb 3260 /*
Marko Mikulicic 0:c0ecb8bf28eb 3261 * Like OP_BREAK, but sets the v7->is_continuing flag
Marko Mikulicic 0:c0ecb8bf28eb 3262 * which will cause OP_JMP_IF_CONTINUE to restart the loop.
Marko Mikulicic 0:c0ecb8bf28eb 3263 *
Marko Mikulicic 0:c0ecb8bf28eb 3264 * `( -- )`
Marko Mikulicic 0:c0ecb8bf28eb 3265 */
Marko Mikulicic 0:c0ecb8bf28eb 3266 OP_CONTINUE,
Marko Mikulicic 0:c0ecb8bf28eb 3267
Marko Mikulicic 0:c0ecb8bf28eb 3268 /*
Marko Mikulicic 0:c0ecb8bf28eb 3269 * Used when we enter the `catch` block. Takes a varint argument -- index of
Marko Mikulicic 0:c0ecb8bf28eb 3270 * the exception variable name in the literals table.
Marko Mikulicic 0:c0ecb8bf28eb 3271 *
Marko Mikulicic 0:c0ecb8bf28eb 3272 * Pops the exception value from the stack, creates a private frame,
Marko Mikulicic 0:c0ecb8bf28eb 3273 * sets exception property on it with the given name. pushes this
Marko Mikulicic 0:c0ecb8bf28eb 3274 * private frame to call stack.
Marko Mikulicic 0:c0ecb8bf28eb 3275 *
Marko Mikulicic 0:c0ecb8bf28eb 3276 * `( e -- )`
Marko Mikulicic 0:c0ecb8bf28eb 3277 */
Marko Mikulicic 0:c0ecb8bf28eb 3278 OP_ENTER_CATCH,
Marko Mikulicic 0:c0ecb8bf28eb 3279
Marko Mikulicic 0:c0ecb8bf28eb 3280 /*
Marko Mikulicic 0:c0ecb8bf28eb 3281 * Ued when we exit from the `catch` block. Merely pops the private frame
Marko Mikulicic 0:c0ecb8bf28eb 3282 * from the call stack.
Marko Mikulicic 0:c0ecb8bf28eb 3283 *
Marko Mikulicic 0:c0ecb8bf28eb 3284 * `( -- )`
Marko Mikulicic 0:c0ecb8bf28eb 3285 */
Marko Mikulicic 0:c0ecb8bf28eb 3286 OP_EXIT_CATCH,
Marko Mikulicic 0:c0ecb8bf28eb 3287
Marko Mikulicic 0:c0ecb8bf28eb 3288 OP_MAX,
Marko Mikulicic 0:c0ecb8bf28eb 3289 };
Marko Mikulicic 0:c0ecb8bf28eb 3290
Marko Mikulicic 0:c0ecb8bf28eb 3291 #define _OP_LINE_NO 0x80
Marko Mikulicic 0:c0ecb8bf28eb 3292
Marko Mikulicic 0:c0ecb8bf28eb 3293 #endif /* CS_V7_SRC_OPCODES_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 3294 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 3295 #line 1 "v7/src/core.h"
Marko Mikulicic 0:c0ecb8bf28eb 3296 #endif
Marko Mikulicic 0:c0ecb8bf28eb 3297 /*
Marko Mikulicic 0:c0ecb8bf28eb 3298 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 3299 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 3300 */
Marko Mikulicic 0:c0ecb8bf28eb 3301
Marko Mikulicic 0:c0ecb8bf28eb 3302 #ifndef CS_V7_SRC_CORE_H_
Marko Mikulicic 0:c0ecb8bf28eb 3303 #define CS_V7_SRC_CORE_H_
Marko Mikulicic 0:c0ecb8bf28eb 3304
Marko Mikulicic 0:c0ecb8bf28eb 3305 /* Amalgamated: #include "v7/src/core_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 3306
Marko Mikulicic 0:c0ecb8bf28eb 3307 /* Amalgamated: #include "common/mbuf.h" */
Marko Mikulicic 0:c0ecb8bf28eb 3308 /* Amalgamated: #include "v7/src/std_error.h" */
Marko Mikulicic 0:c0ecb8bf28eb 3309 /* Amalgamated: #include "v7/src/mm.h" */
Marko Mikulicic 0:c0ecb8bf28eb 3310 /* Amalgamated: #include "v7/src/parser.h" */
Marko Mikulicic 0:c0ecb8bf28eb 3311 /* Amalgamated: #include "v7/src/object_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 3312 /* Amalgamated: #include "v7/src/tokenizer.h" */
Marko Mikulicic 0:c0ecb8bf28eb 3313 /* Amalgamated: #include "v7/src/opcodes.h" */
Marko Mikulicic 0:c0ecb8bf28eb 3314
Marko Mikulicic 0:c0ecb8bf28eb 3315 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 3316 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 3317 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 3318
Marko Mikulicic 0:c0ecb8bf28eb 3319 typedef uint64_t val_t;
Marko Mikulicic 0:c0ecb8bf28eb 3320
Marko Mikulicic 0:c0ecb8bf28eb 3321 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 3322
Marko Mikulicic 0:c0ecb8bf28eb 3323 typedef unsigned short entity_id_t;
Marko Mikulicic 0:c0ecb8bf28eb 3324 typedef unsigned char entity_id_part_t;
Marko Mikulicic 0:c0ecb8bf28eb 3325
Marko Mikulicic 0:c0ecb8bf28eb 3326 /*
Marko Mikulicic 0:c0ecb8bf28eb 3327 * Magic numbers that are stored in various objects in order to identify their
Marko Mikulicic 0:c0ecb8bf28eb 3328 * type in runtime
Marko Mikulicic 0:c0ecb8bf28eb 3329 */
Marko Mikulicic 0:c0ecb8bf28eb 3330 #define V7_ENTITY_ID_PROP 0xe9a1
Marko Mikulicic 0:c0ecb8bf28eb 3331 #define V7_ENTITY_ID_PART_OBJ 0x57
Marko Mikulicic 0:c0ecb8bf28eb 3332 #define V7_ENTITY_ID_PART_GEN_OBJ 0x31
Marko Mikulicic 0:c0ecb8bf28eb 3333 #define V7_ENTITY_ID_PART_JS_FUNC 0x0d
Marko Mikulicic 0:c0ecb8bf28eb 3334
Marko Mikulicic 0:c0ecb8bf28eb 3335 #define V7_ENTITY_ID_NONE 0xa5a5
Marko Mikulicic 0:c0ecb8bf28eb 3336 #define V7_ENTITY_ID_PART_NONE 0xa5
Marko Mikulicic 0:c0ecb8bf28eb 3337
Marko Mikulicic 0:c0ecb8bf28eb 3338 #endif
Marko Mikulicic 0:c0ecb8bf28eb 3339
Marko Mikulicic 0:c0ecb8bf28eb 3340 /*
Marko Mikulicic 0:c0ecb8bf28eb 3341 * Double-precision floating-point number, IEEE 754
Marko Mikulicic 0:c0ecb8bf28eb 3342 *
Marko Mikulicic 0:c0ecb8bf28eb 3343 * 64 bit (8 bytes) in total
Marko Mikulicic 0:c0ecb8bf28eb 3344 * 1 bit sign
Marko Mikulicic 0:c0ecb8bf28eb 3345 * 11 bits exponent
Marko Mikulicic 0:c0ecb8bf28eb 3346 * 52 bits mantissa
Marko Mikulicic 0:c0ecb8bf28eb 3347 * 7 6 5 4 3 2 1 0
Marko Mikulicic 0:c0ecb8bf28eb 3348 * seeeeeee|eeeemmmm|mmmmmmmm|mmmmmmmm|mmmmmmmm|mmmmmmmm|mmmmmmmm|mmmmmmmm
Marko Mikulicic 0:c0ecb8bf28eb 3349 *
Marko Mikulicic 0:c0ecb8bf28eb 3350 * If an exponent is all-1 and mantissa is all-0, then it is an INFINITY:
Marko Mikulicic 0:c0ecb8bf28eb 3351 * 11111111|11110000|00000000|00000000|00000000|00000000|00000000|00000000
Marko Mikulicic 0:c0ecb8bf28eb 3352 *
Marko Mikulicic 0:c0ecb8bf28eb 3353 * If an exponent is all-1 and mantissa's MSB is 1, it is a quiet NaN:
Marko Mikulicic 0:c0ecb8bf28eb 3354 * 11111111|11111000|00000000|00000000|00000000|00000000|00000000|00000000
Marko Mikulicic 0:c0ecb8bf28eb 3355 *
Marko Mikulicic 0:c0ecb8bf28eb 3356 * V7 NaN-packing:
Marko Mikulicic 0:c0ecb8bf28eb 3357 * sign and exponent is 0xfff
Marko Mikulicic 0:c0ecb8bf28eb 3358 * 4 bits specify type (tag), must be non-zero
Marko Mikulicic 0:c0ecb8bf28eb 3359 * 48 bits specify value
Marko Mikulicic 0:c0ecb8bf28eb 3360 *
Marko Mikulicic 0:c0ecb8bf28eb 3361 * 11111111|1111tttt|vvvvvvvv|vvvvvvvv|vvvvvvvv|vvvvvvvv|vvvvvvvv|vvvvvvvv
Marko Mikulicic 0:c0ecb8bf28eb 3362 * NaN marker |type| 48-bit placeholder for values: pointers, strings
Marko Mikulicic 0:c0ecb8bf28eb 3363 *
Marko Mikulicic 0:c0ecb8bf28eb 3364 * On 64-bit platforms, pointers are really 48 bit only, so they can fit,
Marko Mikulicic 0:c0ecb8bf28eb 3365 * provided they are sign extended
Marko Mikulicic 0:c0ecb8bf28eb 3366 */
Marko Mikulicic 0:c0ecb8bf28eb 3367
Marko Mikulicic 0:c0ecb8bf28eb 3368 /*
Marko Mikulicic 0:c0ecb8bf28eb 3369 * A tag is made of the sign bit and the 4 lower order bits of byte 6.
Marko Mikulicic 0:c0ecb8bf28eb 3370 * So in total we have 32 possible tags.
Marko Mikulicic 0:c0ecb8bf28eb 3371 *
Marko Mikulicic 0:c0ecb8bf28eb 3372 * Tag (1,0) however cannot hold a zero payload otherwise it's interpreted as an
Marko Mikulicic 0:c0ecb8bf28eb 3373 * INFINITY; for simplicity we're just not going to use that combination.
Marko Mikulicic 0:c0ecb8bf28eb 3374 */
Marko Mikulicic 0:c0ecb8bf28eb 3375 #define MAKE_TAG(s, t) \
Marko Mikulicic 0:c0ecb8bf28eb 3376 ((uint64_t)(s) << 63 | (uint64_t) 0x7ff0 << 48 | (uint64_t)(t) << 48)
Marko Mikulicic 0:c0ecb8bf28eb 3377
Marko Mikulicic 0:c0ecb8bf28eb 3378 #define V7_TAG_OBJECT MAKE_TAG(1, 0xF)
Marko Mikulicic 0:c0ecb8bf28eb 3379 #define V7_TAG_FOREIGN MAKE_TAG(1, 0xE)
Marko Mikulicic 0:c0ecb8bf28eb 3380 #define V7_TAG_UNDEFINED MAKE_TAG(1, 0xD)
Marko Mikulicic 0:c0ecb8bf28eb 3381 #define V7_TAG_BOOLEAN MAKE_TAG(1, 0xC)
Marko Mikulicic 0:c0ecb8bf28eb 3382 #define V7_TAG_NAN MAKE_TAG(1, 0xB)
Marko Mikulicic 0:c0ecb8bf28eb 3383 #define V7_TAG_STRING_I MAKE_TAG(1, 0xA) /* Inlined string len < 5 */
Marko Mikulicic 0:c0ecb8bf28eb 3384 #define V7_TAG_STRING_5 MAKE_TAG(1, 0x9) /* Inlined string len 5 */
Marko Mikulicic 0:c0ecb8bf28eb 3385 #define V7_TAG_STRING_O MAKE_TAG(1, 0x8) /* Owned string */
Marko Mikulicic 0:c0ecb8bf28eb 3386 #define V7_TAG_STRING_F MAKE_TAG(1, 0x7) /* Foreign string */
Marko Mikulicic 0:c0ecb8bf28eb 3387 #define V7_TAG_STRING_C MAKE_TAG(1, 0x6) /* String chunk */
Marko Mikulicic 0:c0ecb8bf28eb 3388 #define V7_TAG_FUNCTION MAKE_TAG(1, 0x5) /* JavaScript function */
Marko Mikulicic 0:c0ecb8bf28eb 3389 #define V7_TAG_CFUNCTION MAKE_TAG(1, 0x4) /* C function */
Marko Mikulicic 0:c0ecb8bf28eb 3390 #define V7_TAG_STRING_D MAKE_TAG(1, 0x3) /* Dictionary string */
Marko Mikulicic 0:c0ecb8bf28eb 3391 #define V7_TAG_REGEXP MAKE_TAG(1, 0x2) /* Regex */
Marko Mikulicic 0:c0ecb8bf28eb 3392 #define V7_TAG_NOVALUE MAKE_TAG(1, 0x1) /* Sentinel for no value */
Marko Mikulicic 0:c0ecb8bf28eb 3393 #define V7_TAG_MASK MAKE_TAG(1, 0xF)
Marko Mikulicic 0:c0ecb8bf28eb 3394
Marko Mikulicic 0:c0ecb8bf28eb 3395 #define _V7_NULL V7_TAG_FOREIGN
Marko Mikulicic 0:c0ecb8bf28eb 3396 #define _V7_UNDEFINED V7_TAG_UNDEFINED
Marko Mikulicic 0:c0ecb8bf28eb 3397
Marko Mikulicic 0:c0ecb8bf28eb 3398 V7_STATIC_ASSERT(_V7_NULL == V7_NULL, public_V7_NULL_is_wrong);
Marko Mikulicic 0:c0ecb8bf28eb 3399 V7_STATIC_ASSERT(_V7_UNDEFINED == V7_UNDEFINED, public_V7_UNDEFINED_is_wrong);
Marko Mikulicic 0:c0ecb8bf28eb 3400
Marko Mikulicic 0:c0ecb8bf28eb 3401 /*
Marko Mikulicic 0:c0ecb8bf28eb 3402 * Object attributes bitmask
Marko Mikulicic 0:c0ecb8bf28eb 3403 */
Marko Mikulicic 0:c0ecb8bf28eb 3404 typedef unsigned char v7_obj_attr_t;
Marko Mikulicic 0:c0ecb8bf28eb 3405 #define V7_OBJ_NOT_EXTENSIBLE (1 << 0) /* TODO(lsm): store this in LSB */
Marko Mikulicic 0:c0ecb8bf28eb 3406 #define V7_OBJ_DENSE_ARRAY (1 << 1) /* TODO(mkm): store in some tag */
Marko Mikulicic 0:c0ecb8bf28eb 3407 #define V7_OBJ_FUNCTION (1 << 2) /* function object */
Marko Mikulicic 0:c0ecb8bf28eb 3408 #define V7_OBJ_OFF_HEAP (1 << 3) /* object not managed by V7 HEAP */
Marko Mikulicic 0:c0ecb8bf28eb 3409 #define V7_OBJ_HAS_DESTRUCTOR (1 << 4) /* has user data */
Marko Mikulicic 0:c0ecb8bf28eb 3410 #define V7_OBJ_PROXY (1 << 5) /* it's a Proxy object */
Marko Mikulicic 0:c0ecb8bf28eb 3411
Marko Mikulicic 0:c0ecb8bf28eb 3412 /*
Marko Mikulicic 0:c0ecb8bf28eb 3413 * JavaScript value is either a primitive, or an object.
Marko Mikulicic 0:c0ecb8bf28eb 3414 * There are 5 primitive types: Undefined, Null, Boolean, Number, String.
Marko Mikulicic 0:c0ecb8bf28eb 3415 * Non-primitive type is an Object type. There are several classes of Objects,
Marko Mikulicic 0:c0ecb8bf28eb 3416 * see description of `struct v7_generic_object` below for more details.
Marko Mikulicic 0:c0ecb8bf28eb 3417 * This enumeration combines types and object classes in one enumeration.
Marko Mikulicic 0:c0ecb8bf28eb 3418 * NOTE(lsm): compile with `-fshort-enums` to reduce sizeof(enum v7_type) to 1.
Marko Mikulicic 0:c0ecb8bf28eb 3419 */
Marko Mikulicic 0:c0ecb8bf28eb 3420 enum v7_type {
Marko Mikulicic 0:c0ecb8bf28eb 3421 /* Primitive types */
Marko Mikulicic 0:c0ecb8bf28eb 3422 V7_TYPE_UNDEFINED,
Marko Mikulicic 0:c0ecb8bf28eb 3423 V7_TYPE_NULL,
Marko Mikulicic 0:c0ecb8bf28eb 3424 V7_TYPE_BOOLEAN,
Marko Mikulicic 0:c0ecb8bf28eb 3425 V7_TYPE_NUMBER,
Marko Mikulicic 0:c0ecb8bf28eb 3426 V7_TYPE_STRING,
Marko Mikulicic 0:c0ecb8bf28eb 3427 V7_TYPE_FOREIGN,
Marko Mikulicic 0:c0ecb8bf28eb 3428 V7_TYPE_CFUNCTION,
Marko Mikulicic 0:c0ecb8bf28eb 3429
Marko Mikulicic 0:c0ecb8bf28eb 3430 /* Different classes of Object type */
Marko Mikulicic 0:c0ecb8bf28eb 3431 V7_TYPE_GENERIC_OBJECT,
Marko Mikulicic 0:c0ecb8bf28eb 3432 V7_TYPE_BOOLEAN_OBJECT,
Marko Mikulicic 0:c0ecb8bf28eb 3433 V7_TYPE_STRING_OBJECT,
Marko Mikulicic 0:c0ecb8bf28eb 3434 V7_TYPE_NUMBER_OBJECT,
Marko Mikulicic 0:c0ecb8bf28eb 3435 V7_TYPE_FUNCTION_OBJECT,
Marko Mikulicic 0:c0ecb8bf28eb 3436 V7_TYPE_CFUNCTION_OBJECT,
Marko Mikulicic 0:c0ecb8bf28eb 3437 V7_TYPE_REGEXP_OBJECT,
Marko Mikulicic 0:c0ecb8bf28eb 3438 V7_TYPE_ARRAY_OBJECT,
Marko Mikulicic 0:c0ecb8bf28eb 3439 V7_TYPE_DATE_OBJECT,
Marko Mikulicic 0:c0ecb8bf28eb 3440 V7_TYPE_ERROR_OBJECT,
Marko Mikulicic 0:c0ecb8bf28eb 3441 V7_TYPE_MAX_OBJECT_TYPE,
Marko Mikulicic 0:c0ecb8bf28eb 3442 V7_NUM_TYPES
Marko Mikulicic 0:c0ecb8bf28eb 3443 };
Marko Mikulicic 0:c0ecb8bf28eb 3444
Marko Mikulicic 0:c0ecb8bf28eb 3445 /*
Marko Mikulicic 0:c0ecb8bf28eb 3446 * Call frame type mask: we have a "class hierarchy" of the call frames, see
Marko Mikulicic 0:c0ecb8bf28eb 3447 * `struct v7_call_frame_base`, and the `type_mask` field represents the exact
Marko Mikulicic 0:c0ecb8bf28eb 3448 * frame type.
Marko Mikulicic 0:c0ecb8bf28eb 3449 *
Marko Mikulicic 0:c0ecb8bf28eb 3450 * Possible values are:
Marko Mikulicic 0:c0ecb8bf28eb 3451 *
Marko Mikulicic 0:c0ecb8bf28eb 3452 * - `V7_CALL_FRAME_MASK_PRIVATE | V7_CALL_FRAME_MASK_BCODE`: the most popular
Marko Mikulicic 0:c0ecb8bf28eb 3453 * frame type: call frame for bcode execution, either top-level code or JS
Marko Mikulicic 0:c0ecb8bf28eb 3454 * function.
Marko Mikulicic 0:c0ecb8bf28eb 3455 * - `V7_CALL_FRAME_MASK_PRIVATE`: used for `catch` clauses only: the variables
Marko Mikulicic 0:c0ecb8bf28eb 3456 * we create in `catch` clause should not be visible from the outside of the
Marko Mikulicic 0:c0ecb8bf28eb 3457 * clause, so we have to create a separate scope object for it.
Marko Mikulicic 0:c0ecb8bf28eb 3458 * - `V7_CALL_FRAME_MASK_CFUNC`: call frame for C function.
Marko Mikulicic 0:c0ecb8bf28eb 3459 */
Marko Mikulicic 0:c0ecb8bf28eb 3460 typedef uint8_t v7_call_frame_mask_t;
Marko Mikulicic 0:c0ecb8bf28eb 3461 #define V7_CALL_FRAME_MASK_BCODE (1 << 0)
Marko Mikulicic 0:c0ecb8bf28eb 3462 #define V7_CALL_FRAME_MASK_PRIVATE (1 << 1)
Marko Mikulicic 0:c0ecb8bf28eb 3463 #define V7_CALL_FRAME_MASK_CFUNC (1 << 2)
Marko Mikulicic 0:c0ecb8bf28eb 3464
Marko Mikulicic 0:c0ecb8bf28eb 3465 /*
Marko Mikulicic 0:c0ecb8bf28eb 3466 * Base of the call frame; includes the pointer to the previous frame,
Marko Mikulicic 0:c0ecb8bf28eb 3467 * and the frame type.
Marko Mikulicic 0:c0ecb8bf28eb 3468 *
Marko Mikulicic 0:c0ecb8bf28eb 3469 * In order to save memory, it also contains some bitfields which actually
Marko Mikulicic 0:c0ecb8bf28eb 3470 * belong to some "sub-structures".
Marko Mikulicic 0:c0ecb8bf28eb 3471 *
Marko Mikulicic 0:c0ecb8bf28eb 3472 * The hierarchy is as follows:
Marko Mikulicic 0:c0ecb8bf28eb 3473 *
Marko Mikulicic 0:c0ecb8bf28eb 3474 * - v7_call_frame_base
Marko Mikulicic 0:c0ecb8bf28eb 3475 * - v7_call_frame_private
Marko Mikulicic 0:c0ecb8bf28eb 3476 * - v7_call_frame_bcode
Marko Mikulicic 0:c0ecb8bf28eb 3477 * - v7_call_frame_cfunc
Marko Mikulicic 0:c0ecb8bf28eb 3478 */
Marko Mikulicic 0:c0ecb8bf28eb 3479 struct v7_call_frame_base {
Marko Mikulicic 0:c0ecb8bf28eb 3480 struct v7_call_frame_base *prev;
Marko Mikulicic 0:c0ecb8bf28eb 3481
Marko Mikulicic 0:c0ecb8bf28eb 3482 /* See comment for `v7_call_frame_mask_t` */
Marko Mikulicic 0:c0ecb8bf28eb 3483 v7_call_frame_mask_t type_mask : 3;
Marko Mikulicic 0:c0ecb8bf28eb 3484
Marko Mikulicic 0:c0ecb8bf28eb 3485 /* Belongs to `struct v7_call_frame_private` */
Marko Mikulicic 0:c0ecb8bf28eb 3486 unsigned int line_no : 16;
Marko Mikulicic 0:c0ecb8bf28eb 3487
Marko Mikulicic 0:c0ecb8bf28eb 3488 /* Belongs to `struct v7_call_frame_bcode` */
Marko Mikulicic 0:c0ecb8bf28eb 3489 unsigned is_constructor : 1;
Marko Mikulicic 0:c0ecb8bf28eb 3490
Marko Mikulicic 0:c0ecb8bf28eb 3491 /* Belongs to `struct v7_call_frame_bcode` */
Marko Mikulicic 0:c0ecb8bf28eb 3492 unsigned int is_thrown : 1;
Marko Mikulicic 0:c0ecb8bf28eb 3493 };
Marko Mikulicic 0:c0ecb8bf28eb 3494
Marko Mikulicic 0:c0ecb8bf28eb 3495 /*
Marko Mikulicic 0:c0ecb8bf28eb 3496 * "private" call frame, used in `catch` blocks, merely for using a separate
Marko Mikulicic 0:c0ecb8bf28eb 3497 * scope object there. It is also a "base class" for the bcode call frame,
Marko Mikulicic 0:c0ecb8bf28eb 3498 * see `struct v7_call_frame_bcode`.
Marko Mikulicic 0:c0ecb8bf28eb 3499 *
Marko Mikulicic 0:c0ecb8bf28eb 3500 * TODO(dfrank): probably implement it differently, so that we can get rid of
Marko Mikulicic 0:c0ecb8bf28eb 3501 * the separate "private" frames whatsoever (and just include it into struct
Marko Mikulicic 0:c0ecb8bf28eb 3502 * v7_call_frame_bcode )
Marko Mikulicic 0:c0ecb8bf28eb 3503 */
Marko Mikulicic 0:c0ecb8bf28eb 3504 struct v7_call_frame_private {
Marko Mikulicic 0:c0ecb8bf28eb 3505 struct v7_call_frame_base base;
Marko Mikulicic 0:c0ecb8bf28eb 3506 size_t stack_size;
Marko Mikulicic 0:c0ecb8bf28eb 3507 struct {
Marko Mikulicic 0:c0ecb8bf28eb 3508 /*
Marko Mikulicic 0:c0ecb8bf28eb 3509 * Current execution scope. Initially, it is equal to the `global_object`;
Marko Mikulicic 0:c0ecb8bf28eb 3510 * and at each function call, it is augmented by the new scope object, which
Marko Mikulicic 0:c0ecb8bf28eb 3511 * has the previous value as a prototype.
Marko Mikulicic 0:c0ecb8bf28eb 3512 */
Marko Mikulicic 0:c0ecb8bf28eb 3513 val_t scope;
Marko Mikulicic 0:c0ecb8bf28eb 3514
Marko Mikulicic 0:c0ecb8bf28eb 3515 val_t try_stack;
Marko Mikulicic 0:c0ecb8bf28eb 3516 } vals;
Marko Mikulicic 0:c0ecb8bf28eb 3517 };
Marko Mikulicic 0:c0ecb8bf28eb 3518
Marko Mikulicic 0:c0ecb8bf28eb 3519 /*
Marko Mikulicic 0:c0ecb8bf28eb 3520 * "bcode" call frame, augments "private" frame with `bcode` and the position
Marko Mikulicic 0:c0ecb8bf28eb 3521 * in it, and `this` object. It is the primary frame type, used when executing
Marko Mikulicic 0:c0ecb8bf28eb 3522 * a bcode script or calling a function.
Marko Mikulicic 0:c0ecb8bf28eb 3523 */
Marko Mikulicic 0:c0ecb8bf28eb 3524 struct v7_call_frame_bcode {
Marko Mikulicic 0:c0ecb8bf28eb 3525 struct v7_call_frame_private base;
Marko Mikulicic 0:c0ecb8bf28eb 3526 struct {
Marko Mikulicic 0:c0ecb8bf28eb 3527 val_t this_obj;
Marko Mikulicic 0:c0ecb8bf28eb 3528 val_t thrown_error;
Marko Mikulicic 0:c0ecb8bf28eb 3529 } vals;
Marko Mikulicic 0:c0ecb8bf28eb 3530 struct bcode *bcode;
Marko Mikulicic 0:c0ecb8bf28eb 3531 char *bcode_ops;
Marko Mikulicic 0:c0ecb8bf28eb 3532 };
Marko Mikulicic 0:c0ecb8bf28eb 3533
Marko Mikulicic 0:c0ecb8bf28eb 3534 /*
Marko Mikulicic 0:c0ecb8bf28eb 3535 * "cfunc" call frame, used when calling cfunctions.
Marko Mikulicic 0:c0ecb8bf28eb 3536 */
Marko Mikulicic 0:c0ecb8bf28eb 3537 struct v7_call_frame_cfunc {
Marko Mikulicic 0:c0ecb8bf28eb 3538 struct v7_call_frame_base base;
Marko Mikulicic 0:c0ecb8bf28eb 3539
Marko Mikulicic 0:c0ecb8bf28eb 3540 struct {
Marko Mikulicic 0:c0ecb8bf28eb 3541 val_t this_obj;
Marko Mikulicic 0:c0ecb8bf28eb 3542 } vals;
Marko Mikulicic 0:c0ecb8bf28eb 3543
Marko Mikulicic 0:c0ecb8bf28eb 3544 v7_cfunction_t *cfunc;
Marko Mikulicic 0:c0ecb8bf28eb 3545 };
Marko Mikulicic 0:c0ecb8bf28eb 3546
Marko Mikulicic 0:c0ecb8bf28eb 3547 /*
Marko Mikulicic 0:c0ecb8bf28eb 3548 * This structure groups together all val_t logical members
Marko Mikulicic 0:c0ecb8bf28eb 3549 * of struct v7 so that GC and freeze logic can easily access all
Marko Mikulicic 0:c0ecb8bf28eb 3550 * of them together. This structure must contain only val_t members.
Marko Mikulicic 0:c0ecb8bf28eb 3551 */
Marko Mikulicic 0:c0ecb8bf28eb 3552 struct v7_vals {
Marko Mikulicic 0:c0ecb8bf28eb 3553 val_t global_object;
Marko Mikulicic 0:c0ecb8bf28eb 3554
Marko Mikulicic 0:c0ecb8bf28eb 3555 val_t arguments; /* arguments of current call */
Marko Mikulicic 0:c0ecb8bf28eb 3556
Marko Mikulicic 0:c0ecb8bf28eb 3557 val_t object_prototype;
Marko Mikulicic 0:c0ecb8bf28eb 3558 val_t array_prototype;
Marko Mikulicic 0:c0ecb8bf28eb 3559 val_t boolean_prototype;
Marko Mikulicic 0:c0ecb8bf28eb 3560 val_t error_prototype;
Marko Mikulicic 0:c0ecb8bf28eb 3561 val_t string_prototype;
Marko Mikulicic 0:c0ecb8bf28eb 3562 val_t regexp_prototype;
Marko Mikulicic 0:c0ecb8bf28eb 3563 val_t number_prototype;
Marko Mikulicic 0:c0ecb8bf28eb 3564 val_t date_prototype;
Marko Mikulicic 0:c0ecb8bf28eb 3565 val_t function_prototype;
Marko Mikulicic 0:c0ecb8bf28eb 3566 val_t proxy_prototype;
Marko Mikulicic 0:c0ecb8bf28eb 3567
Marko Mikulicic 0:c0ecb8bf28eb 3568 /*
Marko Mikulicic 0:c0ecb8bf28eb 3569 * temporary register for `OP_STASH` and `OP_UNSTASH` instructions. Valid if
Marko Mikulicic 0:c0ecb8bf28eb 3570 * `v7->is_stashed` is non-zero
Marko Mikulicic 0:c0ecb8bf28eb 3571 */
Marko Mikulicic 0:c0ecb8bf28eb 3572 val_t stash;
Marko Mikulicic 0:c0ecb8bf28eb 3573
Marko Mikulicic 0:c0ecb8bf28eb 3574 val_t error_objects[ERROR_CTOR_MAX];
Marko Mikulicic 0:c0ecb8bf28eb 3575
Marko Mikulicic 0:c0ecb8bf28eb 3576 /*
Marko Mikulicic 0:c0ecb8bf28eb 3577 * Value that is being thrown. Valid if `is_thrown` is non-zero (see below)
Marko Mikulicic 0:c0ecb8bf28eb 3578 */
Marko Mikulicic 0:c0ecb8bf28eb 3579 val_t thrown_error;
Marko Mikulicic 0:c0ecb8bf28eb 3580
Marko Mikulicic 0:c0ecb8bf28eb 3581 /*
Marko Mikulicic 0:c0ecb8bf28eb 3582 * value that is going to be returned. Needed when some `finally` block needs
Marko Mikulicic 0:c0ecb8bf28eb 3583 * to be executed after `return my_value;` was issued. Used in bcode.
Marko Mikulicic 0:c0ecb8bf28eb 3584 * See also `is_returned` below
Marko Mikulicic 0:c0ecb8bf28eb 3585 */
Marko Mikulicic 0:c0ecb8bf28eb 3586 val_t returned_value;
Marko Mikulicic 0:c0ecb8bf28eb 3587
Marko Mikulicic 0:c0ecb8bf28eb 3588 val_t last_name[2]; /* used for error reporting */
Marko Mikulicic 0:c0ecb8bf28eb 3589 /* most recent OP_CHECK_CALL exceptions, to be thrown by OP_CALL|OP_NEW */
Marko Mikulicic 0:c0ecb8bf28eb 3590 val_t call_check_ex;
Marko Mikulicic 0:c0ecb8bf28eb 3591 };
Marko Mikulicic 0:c0ecb8bf28eb 3592
Marko Mikulicic 0:c0ecb8bf28eb 3593 struct v7 {
Marko Mikulicic 0:c0ecb8bf28eb 3594 struct v7_vals vals;
Marko Mikulicic 0:c0ecb8bf28eb 3595
Marko Mikulicic 0:c0ecb8bf28eb 3596 /*
Marko Mikulicic 0:c0ecb8bf28eb 3597 * Stack of call frames.
Marko Mikulicic 0:c0ecb8bf28eb 3598 *
Marko Mikulicic 0:c0ecb8bf28eb 3599 * Execution contexts are contained in two chains:
Marko Mikulicic 0:c0ecb8bf28eb 3600 * - Stack of call frames: to allow returning, throwing, and stack trace
Marko Mikulicic 0:c0ecb8bf28eb 3601 * generation;
Marko Mikulicic 0:c0ecb8bf28eb 3602 * - In the lexical scope via their prototype chain (to allow variable
Marko Mikulicic 0:c0ecb8bf28eb 3603 * lookup), see `struct v7_call_frame_private::scope`.
Marko Mikulicic 0:c0ecb8bf28eb 3604 *
Marko Mikulicic 0:c0ecb8bf28eb 3605 * Execution contexts should be allocated on heap, because they might not be
Marko Mikulicic 0:c0ecb8bf28eb 3606 * on a call stack but still referenced (closures).
Marko Mikulicic 0:c0ecb8bf28eb 3607 *
Marko Mikulicic 0:c0ecb8bf28eb 3608 * New call frame is created every time some top-level code is evaluated,
Marko Mikulicic 0:c0ecb8bf28eb 3609 * or some code is being `eval`-d, or some function is called, either JS
Marko Mikulicic 0:c0ecb8bf28eb 3610 * function or C function (although the call frame types are different for
Marko Mikulicic 0:c0ecb8bf28eb 3611 * JS functions and cfunctions, see `struct v7_call_frame_base` and its
Marko Mikulicic 0:c0ecb8bf28eb 3612 * sub-structures)
Marko Mikulicic 0:c0ecb8bf28eb 3613 *
Marko Mikulicic 0:c0ecb8bf28eb 3614 * When no code is being evaluated at the moment, `call_stack` is `NULL`.
Marko Mikulicic 0:c0ecb8bf28eb 3615 *
Marko Mikulicic 0:c0ecb8bf28eb 3616 * See comment for `struct v7_call_frame_base` for some more details.
Marko Mikulicic 0:c0ecb8bf28eb 3617 */
Marko Mikulicic 0:c0ecb8bf28eb 3618 struct v7_call_frame_base *call_stack;
Marko Mikulicic 0:c0ecb8bf28eb 3619
Marko Mikulicic 0:c0ecb8bf28eb 3620 /*
Marko Mikulicic 0:c0ecb8bf28eb 3621 * Bcode executes until it reaches `bottom_call_frame`. When some top-level
Marko Mikulicic 0:c0ecb8bf28eb 3622 * or `eval`-d code starts execution, the `bottom_call_frame` is set to the
Marko Mikulicic 0:c0ecb8bf28eb 3623 * call frame which was just created for the execution.
Marko Mikulicic 0:c0ecb8bf28eb 3624 */
Marko Mikulicic 0:c0ecb8bf28eb 3625 struct v7_call_frame_base *bottom_call_frame;
Marko Mikulicic 0:c0ecb8bf28eb 3626
Marko Mikulicic 0:c0ecb8bf28eb 3627 struct mbuf stack; /* value stack for bcode interpreter */
Marko Mikulicic 0:c0ecb8bf28eb 3628
Marko Mikulicic 0:c0ecb8bf28eb 3629 struct mbuf owned_strings; /* Sequence of (varint len, char data[]) */
Marko Mikulicic 0:c0ecb8bf28eb 3630 struct mbuf foreign_strings; /* Sequence of (varint len, char *data) */
Marko Mikulicic 0:c0ecb8bf28eb 3631
Marko Mikulicic 0:c0ecb8bf28eb 3632 struct mbuf tmp_stack; /* Stack of val_t* elements, used as root set */
Marko Mikulicic 0:c0ecb8bf28eb 3633 int need_gc; /* Set to true to trigger GC when safe */
Marko Mikulicic 0:c0ecb8bf28eb 3634
Marko Mikulicic 0:c0ecb8bf28eb 3635 struct gc_arena generic_object_arena;
Marko Mikulicic 0:c0ecb8bf28eb 3636 struct gc_arena function_arena;
Marko Mikulicic 0:c0ecb8bf28eb 3637 struct gc_arena property_arena;
Marko Mikulicic 0:c0ecb8bf28eb 3638 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 3639 size_t function_arena_ast_size;
Marko Mikulicic 0:c0ecb8bf28eb 3640 size_t bcode_ops_size;
Marko Mikulicic 0:c0ecb8bf28eb 3641 size_t bcode_lit_total_size;
Marko Mikulicic 0:c0ecb8bf28eb 3642 size_t bcode_lit_deser_size;
Marko Mikulicic 0:c0ecb8bf28eb 3643 #endif
Marko Mikulicic 0:c0ecb8bf28eb 3644 struct mbuf owned_values; /* buffer for GC roots owned by C code */
Marko Mikulicic 0:c0ecb8bf28eb 3645
Marko Mikulicic 0:c0ecb8bf28eb 3646 /*
Marko Mikulicic 0:c0ecb8bf28eb 3647 * Stack of the root bcodes being executed at the moment. Note that when some
Marko Mikulicic 0:c0ecb8bf28eb 3648 * regular JS function is called inside `eval_bcode()`, the function's bcode
Marko Mikulicic 0:c0ecb8bf28eb 3649 * is NOT added here. Buf if some cfunction is called, which in turn calls
Marko Mikulicic 0:c0ecb8bf28eb 3650 * `b_exec()` (or `b_apply()`) recursively, the new bcode is added to this
Marko Mikulicic 0:c0ecb8bf28eb 3651 * stack.
Marko Mikulicic 0:c0ecb8bf28eb 3652 */
Marko Mikulicic 0:c0ecb8bf28eb 3653 struct mbuf act_bcodes;
Marko Mikulicic 0:c0ecb8bf28eb 3654
Marko Mikulicic 0:c0ecb8bf28eb 3655 char error_msg[80]; /* Exception message */
Marko Mikulicic 0:c0ecb8bf28eb 3656
Marko Mikulicic 0:c0ecb8bf28eb 3657 struct mbuf json_visited_stack; /* Detecting cycle in to_json */
Marko Mikulicic 0:c0ecb8bf28eb 3658
Marko Mikulicic 0:c0ecb8bf28eb 3659 /* Parser state */
Marko Mikulicic 0:c0ecb8bf28eb 3660 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 3661 struct v7_pstate pstate; /* Parsing state */
Marko Mikulicic 0:c0ecb8bf28eb 3662 enum v7_tok cur_tok; /* Current token */
Marko Mikulicic 0:c0ecb8bf28eb 3663 const char *tok; /* Parsed terminal token (ident, number, string) */
Marko Mikulicic 0:c0ecb8bf28eb 3664 unsigned long tok_len; /* Length of the parsed terminal token */
Marko Mikulicic 0:c0ecb8bf28eb 3665 size_t last_var_node; /* Offset of last var node or function/script node */
Marko Mikulicic 0:c0ecb8bf28eb 3666 int after_newline; /* True if the cur_tok starts a new line */
Marko Mikulicic 0:c0ecb8bf28eb 3667 double cur_tok_dbl; /* When tokenizing, parser stores TOK_NUMBER here */
Marko Mikulicic 0:c0ecb8bf28eb 3668
Marko Mikulicic 0:c0ecb8bf28eb 3669 /*
Marko Mikulicic 0:c0ecb8bf28eb 3670 * Current linenumber. Currently it is used by parser, compiler and bcode
Marko Mikulicic 0:c0ecb8bf28eb 3671 * evaluator.
Marko Mikulicic 0:c0ecb8bf28eb 3672 *
Marko Mikulicic 0:c0ecb8bf28eb 3673 * - Parser: it's the last line_no emitted to AST
Marko Mikulicic 0:c0ecb8bf28eb 3674 * - Compiler: it's the last line_no emitted to bcode
Marko Mikulicic 0:c0ecb8bf28eb 3675 */
Marko Mikulicic 0:c0ecb8bf28eb 3676 int line_no;
Marko Mikulicic 0:c0ecb8bf28eb 3677 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 3678
Marko Mikulicic 0:c0ecb8bf28eb 3679 /* singleton, pointer because of amalgamation */
Marko Mikulicic 0:c0ecb8bf28eb 3680 struct v7_property *cur_dense_prop;
Marko Mikulicic 0:c0ecb8bf28eb 3681
Marko Mikulicic 0:c0ecb8bf28eb 3682 volatile int interrupted;
Marko Mikulicic 0:c0ecb8bf28eb 3683 #ifdef V7_STACK_SIZE
Marko Mikulicic 0:c0ecb8bf28eb 3684 void *sp_limit;
Marko Mikulicic 0:c0ecb8bf28eb 3685 void *sp_lwm;
Marko Mikulicic 0:c0ecb8bf28eb 3686 #endif
Marko Mikulicic 0:c0ecb8bf28eb 3687
Marko Mikulicic 0:c0ecb8bf28eb 3688 #if defined(V7_CYG_PROFILE_ON)
Marko Mikulicic 0:c0ecb8bf28eb 3689 /* linked list of v7 contexts, needed by cyg_profile hooks */
Marko Mikulicic 0:c0ecb8bf28eb 3690 struct v7 *next_v7;
Marko Mikulicic 0:c0ecb8bf28eb 3691
Marko Mikulicic 0:c0ecb8bf28eb 3692 #if defined(V7_ENABLE_STACK_TRACKING)
Marko Mikulicic 0:c0ecb8bf28eb 3693 /* linked list of stack tracking contexts */
Marko Mikulicic 0:c0ecb8bf28eb 3694 struct stack_track_ctx *stack_track_ctx;
Marko Mikulicic 0:c0ecb8bf28eb 3695
Marko Mikulicic 0:c0ecb8bf28eb 3696 int stack_stat[V7_STACK_STATS_CNT];
Marko Mikulicic 0:c0ecb8bf28eb 3697 #endif
Marko Mikulicic 0:c0ecb8bf28eb 3698
Marko Mikulicic 0:c0ecb8bf28eb 3699 #endif
Marko Mikulicic 0:c0ecb8bf28eb 3700
Marko Mikulicic 0:c0ecb8bf28eb 3701 #ifdef V7_MALLOC_GC
Marko Mikulicic 0:c0ecb8bf28eb 3702 struct mbuf malloc_trace;
Marko Mikulicic 0:c0ecb8bf28eb 3703 #endif
Marko Mikulicic 0:c0ecb8bf28eb 3704
Marko Mikulicic 0:c0ecb8bf28eb 3705 /*
Marko Mikulicic 0:c0ecb8bf28eb 3706 * TODO(imax): remove V7_DISABLE_STR_ALLOC_SEQ knob after 2015/12/01 if there
Marko Mikulicic 0:c0ecb8bf28eb 3707 * are no issues.
Marko Mikulicic 0:c0ecb8bf28eb 3708 */
Marko Mikulicic 0:c0ecb8bf28eb 3709 #ifndef V7_DISABLE_STR_ALLOC_SEQ
Marko Mikulicic 0:c0ecb8bf28eb 3710 uint16_t gc_next_asn; /* Next sequence number to use. */
Marko Mikulicic 0:c0ecb8bf28eb 3711 uint16_t gc_min_asn; /* Minimal sequence number currently in use. */
Marko Mikulicic 0:c0ecb8bf28eb 3712 #endif
Marko Mikulicic 0:c0ecb8bf28eb 3713
Marko Mikulicic 0:c0ecb8bf28eb 3714 #if defined(V7_TRACK_MAX_PARSER_STACK_SIZE)
Marko Mikulicic 0:c0ecb8bf28eb 3715 size_t parser_stack_data_max_size;
Marko Mikulicic 0:c0ecb8bf28eb 3716 size_t parser_stack_ret_max_size;
Marko Mikulicic 0:c0ecb8bf28eb 3717 size_t parser_stack_data_max_len;
Marko Mikulicic 0:c0ecb8bf28eb 3718 size_t parser_stack_ret_max_len;
Marko Mikulicic 0:c0ecb8bf28eb 3719 #endif
Marko Mikulicic 0:c0ecb8bf28eb 3720
Marko Mikulicic 0:c0ecb8bf28eb 3721 #ifdef V7_FREEZE
Marko Mikulicic 0:c0ecb8bf28eb 3722 FILE *freeze_file;
Marko Mikulicic 0:c0ecb8bf28eb 3723 #endif
Marko Mikulicic 0:c0ecb8bf28eb 3724
Marko Mikulicic 0:c0ecb8bf28eb 3725 /*
Marko Mikulicic 0:c0ecb8bf28eb 3726 * true if exception is currently being created. Needed to avoid recursive
Marko Mikulicic 0:c0ecb8bf28eb 3727 * exception creation
Marko Mikulicic 0:c0ecb8bf28eb 3728 */
Marko Mikulicic 0:c0ecb8bf28eb 3729 unsigned int creating_exception : 1;
Marko Mikulicic 0:c0ecb8bf28eb 3730 /* while true, GC is inhibited */
Marko Mikulicic 0:c0ecb8bf28eb 3731 unsigned int inhibit_gc : 1;
Marko Mikulicic 0:c0ecb8bf28eb 3732 /* true if `thrown_error` is valid */
Marko Mikulicic 0:c0ecb8bf28eb 3733 unsigned int is_thrown : 1;
Marko Mikulicic 0:c0ecb8bf28eb 3734 /* true if `returned_value` is valid */
Marko Mikulicic 0:c0ecb8bf28eb 3735 unsigned int is_returned : 1;
Marko Mikulicic 0:c0ecb8bf28eb 3736 /* true if a finally block is executing while breaking */
Marko Mikulicic 0:c0ecb8bf28eb 3737 unsigned int is_breaking : 1;
Marko Mikulicic 0:c0ecb8bf28eb 3738 /* true when a continue OP is executed, reset by `OP_JMP_IF_CONTINUE` */
Marko Mikulicic 0:c0ecb8bf28eb 3739 unsigned int is_continuing : 1;
Marko Mikulicic 0:c0ecb8bf28eb 3740 /* true if some value is currently stashed (`v7->vals.stash`) */
Marko Mikulicic 0:c0ecb8bf28eb 3741 unsigned int is_stashed : 1;
Marko Mikulicic 0:c0ecb8bf28eb 3742 /* true if last emitted statement does not affect data stack */
Marko Mikulicic 0:c0ecb8bf28eb 3743 unsigned int is_stack_neutral : 1;
Marko Mikulicic 0:c0ecb8bf28eb 3744 /* true if precompiling; affects compiler bcode choices */
Marko Mikulicic 0:c0ecb8bf28eb 3745 unsigned int is_precompiling : 1;
Marko Mikulicic 0:c0ecb8bf28eb 3746
Marko Mikulicic 0:c0ecb8bf28eb 3747 enum opcode last_ops[2]; /* trace of last ops, used for error reporting */
Marko Mikulicic 0:c0ecb8bf28eb 3748 };
Marko Mikulicic 0:c0ecb8bf28eb 3749
Marko Mikulicic 0:c0ecb8bf28eb 3750 struct v7_property {
Marko Mikulicic 0:c0ecb8bf28eb 3751 struct v7_property *
Marko Mikulicic 0:c0ecb8bf28eb 3752 next; /* Linkage in struct v7_generic_object::properties */
Marko Mikulicic 0:c0ecb8bf28eb 3753 v7_prop_attr_t attributes;
Marko Mikulicic 0:c0ecb8bf28eb 3754 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 3755 entity_id_t entity_id;
Marko Mikulicic 0:c0ecb8bf28eb 3756 #endif
Marko Mikulicic 0:c0ecb8bf28eb 3757 val_t name; /* Property name (a string) */
Marko Mikulicic 0:c0ecb8bf28eb 3758 val_t value; /* Property value */
Marko Mikulicic 0:c0ecb8bf28eb 3759 };
Marko Mikulicic 0:c0ecb8bf28eb 3760
Marko Mikulicic 0:c0ecb8bf28eb 3761 /*
Marko Mikulicic 0:c0ecb8bf28eb 3762 * "base object": structure which is shared between objects and functions.
Marko Mikulicic 0:c0ecb8bf28eb 3763 */
Marko Mikulicic 0:c0ecb8bf28eb 3764 struct v7_object {
Marko Mikulicic 0:c0ecb8bf28eb 3765 /* First HIDDEN property in a chain is an internal object value */
Marko Mikulicic 0:c0ecb8bf28eb 3766 struct v7_property *properties;
Marko Mikulicic 0:c0ecb8bf28eb 3767 v7_obj_attr_t attributes;
Marko Mikulicic 0:c0ecb8bf28eb 3768 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 3769 entity_id_part_t entity_id_base;
Marko Mikulicic 0:c0ecb8bf28eb 3770 entity_id_part_t entity_id_spec;
Marko Mikulicic 0:c0ecb8bf28eb 3771 #endif
Marko Mikulicic 0:c0ecb8bf28eb 3772 };
Marko Mikulicic 0:c0ecb8bf28eb 3773
Marko Mikulicic 0:c0ecb8bf28eb 3774 /*
Marko Mikulicic 0:c0ecb8bf28eb 3775 * An object is an unordered collection of properties.
Marko Mikulicic 0:c0ecb8bf28eb 3776 * A function stored in a property of an object is called a method.
Marko Mikulicic 0:c0ecb8bf28eb 3777 * A property has a name, a value, and set of attributes.
Marko Mikulicic 0:c0ecb8bf28eb 3778 * Attributes are: ReadOnly, DontEnum, DontDelete, Internal.
Marko Mikulicic 0:c0ecb8bf28eb 3779 *
Marko Mikulicic 0:c0ecb8bf28eb 3780 * A constructor is a function that creates and initializes objects.
Marko Mikulicic 0:c0ecb8bf28eb 3781 * Each constructor has an associated prototype object that is used for
Marko Mikulicic 0:c0ecb8bf28eb 3782 * inheritance and shared properties. When a constructor creates an object,
Marko Mikulicic 0:c0ecb8bf28eb 3783 * the new object references the constructor’s prototype.
Marko Mikulicic 0:c0ecb8bf28eb 3784 *
Marko Mikulicic 0:c0ecb8bf28eb 3785 * Objects could be a "generic objects" which is a collection of properties,
Marko Mikulicic 0:c0ecb8bf28eb 3786 * or a "typed object" which also hold an internal value like String or Number.
Marko Mikulicic 0:c0ecb8bf28eb 3787 * Those values are implicit, unnamed properties of the respective types,
Marko Mikulicic 0:c0ecb8bf28eb 3788 * and can be coerced into primitive types by calling a respective constructor
Marko Mikulicic 0:c0ecb8bf28eb 3789 * as a function:
Marko Mikulicic 0:c0ecb8bf28eb 3790 * var a = new Number(123);
Marko Mikulicic 0:c0ecb8bf28eb 3791 * typeof(a) == 'object';
Marko Mikulicic 0:c0ecb8bf28eb 3792 * typeof(Number(a)) == 'number';
Marko Mikulicic 0:c0ecb8bf28eb 3793 */
Marko Mikulicic 0:c0ecb8bf28eb 3794 struct v7_generic_object {
Marko Mikulicic 0:c0ecb8bf28eb 3795 /*
Marko Mikulicic 0:c0ecb8bf28eb 3796 * This has to be the first field so that objects can be managed by the GC.
Marko Mikulicic 0:c0ecb8bf28eb 3797 */
Marko Mikulicic 0:c0ecb8bf28eb 3798 struct v7_object base;
Marko Mikulicic 0:c0ecb8bf28eb 3799 struct v7_object *prototype;
Marko Mikulicic 0:c0ecb8bf28eb 3800 };
Marko Mikulicic 0:c0ecb8bf28eb 3801
Marko Mikulicic 0:c0ecb8bf28eb 3802 /*
Marko Mikulicic 0:c0ecb8bf28eb 3803 * Variables are function-scoped and are hoisted.
Marko Mikulicic 0:c0ecb8bf28eb 3804 * Lexical scoping & closures: each function has a chain of scopes, defined
Marko Mikulicic 0:c0ecb8bf28eb 3805 * by the lexicographic order of function definitions.
Marko Mikulicic 0:c0ecb8bf28eb 3806 * Scope is different from the execution context.
Marko Mikulicic 0:c0ecb8bf28eb 3807 * Execution context carries "variable object" which is variable/value
Marko Mikulicic 0:c0ecb8bf28eb 3808 * mapping for all variables defined in a function, and `this` object.
Marko Mikulicic 0:c0ecb8bf28eb 3809 * If function is not called as a method, then `this` is a global object.
Marko Mikulicic 0:c0ecb8bf28eb 3810 * Otherwise, `this` is an object that contains called method.
Marko Mikulicic 0:c0ecb8bf28eb 3811 * New execution context is created each time a function call is performed.
Marko Mikulicic 0:c0ecb8bf28eb 3812 * Passing arguments through recursion is done using execution context, e.g.
Marko Mikulicic 0:c0ecb8bf28eb 3813 *
Marko Mikulicic 0:c0ecb8bf28eb 3814 * var factorial = function(num) {
Marko Mikulicic 0:c0ecb8bf28eb 3815 * return num < 2 ? 1 : num * factorial(num - 1);
Marko Mikulicic 0:c0ecb8bf28eb 3816 * };
Marko Mikulicic 0:c0ecb8bf28eb 3817 *
Marko Mikulicic 0:c0ecb8bf28eb 3818 * Here, recursion calls the same function `factorial` several times. Execution
Marko Mikulicic 0:c0ecb8bf28eb 3819 * contexts for each call form a stack. Each context has different variable
Marko Mikulicic 0:c0ecb8bf28eb 3820 * object, `vars`, with different values of `num`.
Marko Mikulicic 0:c0ecb8bf28eb 3821 */
Marko Mikulicic 0:c0ecb8bf28eb 3822
Marko Mikulicic 0:c0ecb8bf28eb 3823 struct v7_js_function {
Marko Mikulicic 0:c0ecb8bf28eb 3824 /*
Marko Mikulicic 0:c0ecb8bf28eb 3825 * Functions are objects. This has to be the first field so that function
Marko Mikulicic 0:c0ecb8bf28eb 3826 * objects can be managed by the GC.
Marko Mikulicic 0:c0ecb8bf28eb 3827 */
Marko Mikulicic 0:c0ecb8bf28eb 3828 struct v7_object base;
Marko Mikulicic 0:c0ecb8bf28eb 3829 struct v7_generic_object *scope; /* lexical scope of the closure */
Marko Mikulicic 0:c0ecb8bf28eb 3830
Marko Mikulicic 0:c0ecb8bf28eb 3831 /* bytecode, might be shared between functions */
Marko Mikulicic 0:c0ecb8bf28eb 3832 struct bcode *bcode;
Marko Mikulicic 0:c0ecb8bf28eb 3833 };
Marko Mikulicic 0:c0ecb8bf28eb 3834
Marko Mikulicic 0:c0ecb8bf28eb 3835 struct v7_regexp {
Marko Mikulicic 0:c0ecb8bf28eb 3836 val_t regexp_string;
Marko Mikulicic 0:c0ecb8bf28eb 3837 struct slre_prog *compiled_regexp;
Marko Mikulicic 0:c0ecb8bf28eb 3838 long lastIndex;
Marko Mikulicic 0:c0ecb8bf28eb 3839 };
Marko Mikulicic 0:c0ecb8bf28eb 3840
Marko Mikulicic 0:c0ecb8bf28eb 3841 /* Vector, describes some memory location pointed by `p` with length `len` */
Marko Mikulicic 0:c0ecb8bf28eb 3842 struct v7_vec {
Marko Mikulicic 0:c0ecb8bf28eb 3843 char *p;
Marko Mikulicic 0:c0ecb8bf28eb 3844 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 3845 };
Marko Mikulicic 0:c0ecb8bf28eb 3846
Marko Mikulicic 0:c0ecb8bf28eb 3847 /*
Marko Mikulicic 0:c0ecb8bf28eb 3848 * Constant vector, describes some const memory location pointed by `p` with
Marko Mikulicic 0:c0ecb8bf28eb 3849 * length `len`
Marko Mikulicic 0:c0ecb8bf28eb 3850 */
Marko Mikulicic 0:c0ecb8bf28eb 3851 struct v7_vec_const {
Marko Mikulicic 0:c0ecb8bf28eb 3852 const char *p;
Marko Mikulicic 0:c0ecb8bf28eb 3853 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 3854 };
Marko Mikulicic 0:c0ecb8bf28eb 3855
Marko Mikulicic 0:c0ecb8bf28eb 3856 #define V7_VEC(str) \
Marko Mikulicic 0:c0ecb8bf28eb 3857 { (str), sizeof(str) - 1 }
Marko Mikulicic 0:c0ecb8bf28eb 3858
Marko Mikulicic 0:c0ecb8bf28eb 3859 /*
Marko Mikulicic 0:c0ecb8bf28eb 3860 * Returns current execution scope.
Marko Mikulicic 0:c0ecb8bf28eb 3861 *
Marko Mikulicic 0:c0ecb8bf28eb 3862 * See comment for `struct v7_call_frame_private::vals::scope`
Marko Mikulicic 0:c0ecb8bf28eb 3863 */
Marko Mikulicic 0:c0ecb8bf28eb 3864 V7_PRIVATE v7_val_t get_scope(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 3865
Marko Mikulicic 0:c0ecb8bf28eb 3866 /*
Marko Mikulicic 0:c0ecb8bf28eb 3867 * Returns 1 if currently executing bcode in the "strict mode", 0 otherwise
Marko Mikulicic 0:c0ecb8bf28eb 3868 */
Marko Mikulicic 0:c0ecb8bf28eb 3869 V7_PRIVATE uint8_t is_strict_mode(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 3870
Marko Mikulicic 0:c0ecb8bf28eb 3871 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 3872 }
Marko Mikulicic 0:c0ecb8bf28eb 3873 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 3874
Marko Mikulicic 0:c0ecb8bf28eb 3875 #endif /* CS_V7_SRC_CORE_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 3876 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 3877 #line 1 "v7/src/primitive_public.h"
Marko Mikulicic 0:c0ecb8bf28eb 3878 #endif
Marko Mikulicic 0:c0ecb8bf28eb 3879 /*
Marko Mikulicic 0:c0ecb8bf28eb 3880 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 3881 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 3882 */
Marko Mikulicic 0:c0ecb8bf28eb 3883
Marko Mikulicic 0:c0ecb8bf28eb 3884 /*
Marko Mikulicic 0:c0ecb8bf28eb 3885 * === Primitives
Marko Mikulicic 0:c0ecb8bf28eb 3886 *
Marko Mikulicic 0:c0ecb8bf28eb 3887 * All primitive values but strings.
Marko Mikulicic 0:c0ecb8bf28eb 3888 *
Marko Mikulicic 0:c0ecb8bf28eb 3889 * "foreign" values are also here, see `v7_mk_foreign()`.
Marko Mikulicic 0:c0ecb8bf28eb 3890 */
Marko Mikulicic 0:c0ecb8bf28eb 3891
Marko Mikulicic 0:c0ecb8bf28eb 3892 #ifndef CS_V7_SRC_PRIMITIVE_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 3893 #define CS_V7_SRC_PRIMITIVE_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 3894
Marko Mikulicic 0:c0ecb8bf28eb 3895 /* Amalgamated: #include "v7/src/core_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 3896
Marko Mikulicic 0:c0ecb8bf28eb 3897 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 3898 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 3899 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 3900
Marko Mikulicic 0:c0ecb8bf28eb 3901 /* Make numeric primitive value */
Marko Mikulicic 0:c0ecb8bf28eb 3902 NOINSTR v7_val_t v7_mk_number(struct v7 *v7, double num);
Marko Mikulicic 0:c0ecb8bf28eb 3903
Marko Mikulicic 0:c0ecb8bf28eb 3904 /*
Marko Mikulicic 0:c0ecb8bf28eb 3905 * Returns number value stored in `v7_val_t` as `double`.
Marko Mikulicic 0:c0ecb8bf28eb 3906 *
Marko Mikulicic 0:c0ecb8bf28eb 3907 * Returns NaN for non-numbers.
Marko Mikulicic 0:c0ecb8bf28eb 3908 */
Marko Mikulicic 0:c0ecb8bf28eb 3909 NOINSTR double v7_get_double(struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 3910
Marko Mikulicic 0:c0ecb8bf28eb 3911 /*
Marko Mikulicic 0:c0ecb8bf28eb 3912 * Returns number value stored in `v7_val_t` as `int`. If the number value is
Marko Mikulicic 0:c0ecb8bf28eb 3913 * not an integer, the fraction part will be discarded.
Marko Mikulicic 0:c0ecb8bf28eb 3914 *
Marko Mikulicic 0:c0ecb8bf28eb 3915 * If the given value is a non-number, or NaN, the result is undefined.
Marko Mikulicic 0:c0ecb8bf28eb 3916 */
Marko Mikulicic 0:c0ecb8bf28eb 3917 NOINSTR int v7_get_int(struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 3918
Marko Mikulicic 0:c0ecb8bf28eb 3919 /* Returns true if given value is a primitive number value */
Marko Mikulicic 0:c0ecb8bf28eb 3920 int v7_is_number(v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 3921
Marko Mikulicic 0:c0ecb8bf28eb 3922 /* Make boolean primitive value (either `true` or `false`) */
Marko Mikulicic 0:c0ecb8bf28eb 3923 NOINSTR v7_val_t v7_mk_boolean(struct v7 *v7, int is_true);
Marko Mikulicic 0:c0ecb8bf28eb 3924
Marko Mikulicic 0:c0ecb8bf28eb 3925 /*
Marko Mikulicic 0:c0ecb8bf28eb 3926 * Returns boolean stored in `v7_val_t`:
Marko Mikulicic 0:c0ecb8bf28eb 3927 * 0 for `false` or non-boolean, non-0 for `true`
Marko Mikulicic 0:c0ecb8bf28eb 3928 */
Marko Mikulicic 0:c0ecb8bf28eb 3929 NOINSTR int v7_get_bool(struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 3930
Marko Mikulicic 0:c0ecb8bf28eb 3931 /* Returns true if given value is a primitive boolean value */
Marko Mikulicic 0:c0ecb8bf28eb 3932 int v7_is_boolean(v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 3933
Marko Mikulicic 0:c0ecb8bf28eb 3934 /*
Marko Mikulicic 0:c0ecb8bf28eb 3935 * Make `null` primitive value.
Marko Mikulicic 0:c0ecb8bf28eb 3936 *
Marko Mikulicic 0:c0ecb8bf28eb 3937 * NOTE: this function is deprecated and will be removed in future releases.
Marko Mikulicic 0:c0ecb8bf28eb 3938 * Use `V7_NULL` instead.
Marko Mikulicic 0:c0ecb8bf28eb 3939 */
Marko Mikulicic 0:c0ecb8bf28eb 3940 NOINSTR v7_val_t v7_mk_null(void);
Marko Mikulicic 0:c0ecb8bf28eb 3941
Marko Mikulicic 0:c0ecb8bf28eb 3942 /* Returns true if given value is a primitive `null` value */
Marko Mikulicic 0:c0ecb8bf28eb 3943 int v7_is_null(v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 3944
Marko Mikulicic 0:c0ecb8bf28eb 3945 /*
Marko Mikulicic 0:c0ecb8bf28eb 3946 * Make `undefined` primitive value.
Marko Mikulicic 0:c0ecb8bf28eb 3947 *
Marko Mikulicic 0:c0ecb8bf28eb 3948 * NOTE: this function is deprecated and will be removed in future releases.
Marko Mikulicic 0:c0ecb8bf28eb 3949 * Use `V7_UNDEFINED` instead.
Marko Mikulicic 0:c0ecb8bf28eb 3950 */
Marko Mikulicic 0:c0ecb8bf28eb 3951 NOINSTR v7_val_t v7_mk_undefined(void);
Marko Mikulicic 0:c0ecb8bf28eb 3952
Marko Mikulicic 0:c0ecb8bf28eb 3953 /* Returns true if given value is a primitive `undefined` value */
Marko Mikulicic 0:c0ecb8bf28eb 3954 int v7_is_undefined(v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 3955
Marko Mikulicic 0:c0ecb8bf28eb 3956 /*
Marko Mikulicic 0:c0ecb8bf28eb 3957 * Make JavaScript value that holds C/C++ `void *` pointer.
Marko Mikulicic 0:c0ecb8bf28eb 3958 *
Marko Mikulicic 0:c0ecb8bf28eb 3959 * A foreign value is completely opaque and JS code cannot do anything useful
Marko Mikulicic 0:c0ecb8bf28eb 3960 * with it except holding it in properties and passing it around.
Marko Mikulicic 0:c0ecb8bf28eb 3961 * It behaves like a sealed object with no properties.
Marko Mikulicic 0:c0ecb8bf28eb 3962 *
Marko Mikulicic 0:c0ecb8bf28eb 3963 * NOTE:
Marko Mikulicic 0:c0ecb8bf28eb 3964 * Only valid pointers (as defined by each supported architecture) will fully
Marko Mikulicic 0:c0ecb8bf28eb 3965 * preserved. In particular, all supported 64-bit architectures (x86_64, ARM-64)
Marko Mikulicic 0:c0ecb8bf28eb 3966 * actually define a 48-bit virtual address space.
Marko Mikulicic 0:c0ecb8bf28eb 3967 * Foreign values will be sign-extended as required, i.e creating a foreign
Marko Mikulicic 0:c0ecb8bf28eb 3968 * value of something like `(void *) -1` will work as expected. This is
Marko Mikulicic 0:c0ecb8bf28eb 3969 * important because in some 64-bit OSs (e.g. Solaris) the user stack grows
Marko Mikulicic 0:c0ecb8bf28eb 3970 * downwards from the end of the address space.
Marko Mikulicic 0:c0ecb8bf28eb 3971 *
Marko Mikulicic 0:c0ecb8bf28eb 3972 * If you need to store exactly sizeof(void*) bytes of raw data where
Marko Mikulicic 0:c0ecb8bf28eb 3973 * `sizeof(void*)` >= 8, please use byte arrays instead.
Marko Mikulicic 0:c0ecb8bf28eb 3974 */
Marko Mikulicic 0:c0ecb8bf28eb 3975 NOINSTR v7_val_t v7_mk_foreign(struct v7 *v7, void *ptr);
Marko Mikulicic 0:c0ecb8bf28eb 3976
Marko Mikulicic 0:c0ecb8bf28eb 3977 /*
Marko Mikulicic 0:c0ecb8bf28eb 3978 * Returns `void *` pointer stored in `v7_val_t`.
Marko Mikulicic 0:c0ecb8bf28eb 3979 *
Marko Mikulicic 0:c0ecb8bf28eb 3980 * Returns NULL if the value is not a foreign pointer.
Marko Mikulicic 0:c0ecb8bf28eb 3981 */
Marko Mikulicic 0:c0ecb8bf28eb 3982 NOINSTR void *v7_get_ptr(struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 3983
Marko Mikulicic 0:c0ecb8bf28eb 3984 /* Returns true if given value holds `void *` pointer */
Marko Mikulicic 0:c0ecb8bf28eb 3985 int v7_is_foreign(v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 3986
Marko Mikulicic 0:c0ecb8bf28eb 3987 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 3988 }
Marko Mikulicic 0:c0ecb8bf28eb 3989 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 3990
Marko Mikulicic 0:c0ecb8bf28eb 3991 #endif /* CS_V7_SRC_PRIMITIVE_PUBLIC_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 3992 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 3993 #line 1 "v7/src/primitive.h"
Marko Mikulicic 0:c0ecb8bf28eb 3994 #endif
Marko Mikulicic 0:c0ecb8bf28eb 3995 /*
Marko Mikulicic 0:c0ecb8bf28eb 3996 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 3997 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 3998 */
Marko Mikulicic 0:c0ecb8bf28eb 3999
Marko Mikulicic 0:c0ecb8bf28eb 4000 #ifndef CS_V7_SRC_PRIMITIVE_H_
Marko Mikulicic 0:c0ecb8bf28eb 4001 #define CS_V7_SRC_PRIMITIVE_H_
Marko Mikulicic 0:c0ecb8bf28eb 4002
Marko Mikulicic 0:c0ecb8bf28eb 4003 /* Amalgamated: #include "v7/src/primitive_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4004
Marko Mikulicic 0:c0ecb8bf28eb 4005 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4006
Marko Mikulicic 0:c0ecb8bf28eb 4007 /* Returns true if given value is a number, not NaN and not Infinity. */
Marko Mikulicic 0:c0ecb8bf28eb 4008 V7_PRIVATE int is_finite(struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 4009
Marko Mikulicic 0:c0ecb8bf28eb 4010 V7_PRIVATE val_t pointer_to_value(void *p);
Marko Mikulicic 0:c0ecb8bf28eb 4011 V7_PRIVATE void *get_ptr(val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 4012
Marko Mikulicic 0:c0ecb8bf28eb 4013 #endif /* CS_V7_SRC_PRIMITIVE_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 4014 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 4015 #line 1 "v7/src/string_public.h"
Marko Mikulicic 0:c0ecb8bf28eb 4016 #endif
Marko Mikulicic 0:c0ecb8bf28eb 4017 /*
Marko Mikulicic 0:c0ecb8bf28eb 4018 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 4019 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 4020 */
Marko Mikulicic 0:c0ecb8bf28eb 4021
Marko Mikulicic 0:c0ecb8bf28eb 4022 /*
Marko Mikulicic 0:c0ecb8bf28eb 4023 * === Strings
Marko Mikulicic 0:c0ecb8bf28eb 4024 */
Marko Mikulicic 0:c0ecb8bf28eb 4025
Marko Mikulicic 0:c0ecb8bf28eb 4026 #ifndef CS_V7_SRC_STRING_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 4027 #define CS_V7_SRC_STRING_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 4028
Marko Mikulicic 0:c0ecb8bf28eb 4029 /* Amalgamated: #include "v7/src/core_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4030
Marko Mikulicic 0:c0ecb8bf28eb 4031 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4032 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 4033 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4034
Marko Mikulicic 0:c0ecb8bf28eb 4035 /*
Marko Mikulicic 0:c0ecb8bf28eb 4036 * Creates a string primitive value.
Marko Mikulicic 0:c0ecb8bf28eb 4037 * `str` must point to the utf8 string of length `len`.
Marko Mikulicic 0:c0ecb8bf28eb 4038 * If `len` is ~0, `str` is assumed to be NUL-terminated and `strlen(str)` is
Marko Mikulicic 0:c0ecb8bf28eb 4039 * used.
Marko Mikulicic 0:c0ecb8bf28eb 4040 *
Marko Mikulicic 0:c0ecb8bf28eb 4041 * If `copy` is non-zero, the string data is copied and owned by the GC. The
Marko Mikulicic 0:c0ecb8bf28eb 4042 * caller can free the string data afterwards. Otherwise (`copy` is zero), the
Marko Mikulicic 0:c0ecb8bf28eb 4043 * caller owns the string data, and is responsible for not freeing it while it
Marko Mikulicic 0:c0ecb8bf28eb 4044 * is used.
Marko Mikulicic 0:c0ecb8bf28eb 4045 */
Marko Mikulicic 0:c0ecb8bf28eb 4046 v7_val_t v7_mk_string(struct v7 *v7, const char *str, size_t len, int copy);
Marko Mikulicic 0:c0ecb8bf28eb 4047
Marko Mikulicic 0:c0ecb8bf28eb 4048 /* Returns true if given value is a primitive string value */
Marko Mikulicic 0:c0ecb8bf28eb 4049 int v7_is_string(v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 4050
Marko Mikulicic 0:c0ecb8bf28eb 4051 /*
Marko Mikulicic 0:c0ecb8bf28eb 4052 * Returns a pointer to the string stored in `v7_val_t`.
Marko Mikulicic 0:c0ecb8bf28eb 4053 *
Marko Mikulicic 0:c0ecb8bf28eb 4054 * String length returned in `len`, which is allowed to be NULL. Returns NULL
Marko Mikulicic 0:c0ecb8bf28eb 4055 * if the value is not a string.
Marko Mikulicic 0:c0ecb8bf28eb 4056 *
Marko Mikulicic 0:c0ecb8bf28eb 4057 * JS strings can contain embedded NUL chars and may or may not be NUL
Marko Mikulicic 0:c0ecb8bf28eb 4058 * terminated.
Marko Mikulicic 0:c0ecb8bf28eb 4059 *
Marko Mikulicic 0:c0ecb8bf28eb 4060 * CAUTION: creating new JavaScript object, array, or string may kick in a
Marko Mikulicic 0:c0ecb8bf28eb 4061 * garbage collector, which in turn may relocate string data and invalidate
Marko Mikulicic 0:c0ecb8bf28eb 4062 * pointer returned by `v7_get_string()`.
Marko Mikulicic 0:c0ecb8bf28eb 4063 *
Marko Mikulicic 0:c0ecb8bf28eb 4064 * Short JS strings are embedded inside the `v7_val_t` value itself. This is why
Marko Mikulicic 0:c0ecb8bf28eb 4065 * a pointer to a `v7_val_t` is required. It also means that the string data
Marko Mikulicic 0:c0ecb8bf28eb 4066 * will become invalid once that `v7_val_t` value goes out of scope.
Marko Mikulicic 0:c0ecb8bf28eb 4067 */
Marko Mikulicic 0:c0ecb8bf28eb 4068 const char *v7_get_string(struct v7 *v7, v7_val_t *v, size_t *len);
Marko Mikulicic 0:c0ecb8bf28eb 4069
Marko Mikulicic 0:c0ecb8bf28eb 4070 /*
Marko Mikulicic 0:c0ecb8bf28eb 4071 * Returns a pointer to the string stored in `v7_val_t`.
Marko Mikulicic 0:c0ecb8bf28eb 4072 *
Marko Mikulicic 0:c0ecb8bf28eb 4073 * Returns NULL if the value is not a string or if the string is not compatible
Marko Mikulicic 0:c0ecb8bf28eb 4074 * with a C string.
Marko Mikulicic 0:c0ecb8bf28eb 4075 *
Marko Mikulicic 0:c0ecb8bf28eb 4076 * C compatible strings contain exactly one NUL char, in terminal position.
Marko Mikulicic 0:c0ecb8bf28eb 4077 *
Marko Mikulicic 0:c0ecb8bf28eb 4078 * All strings owned by the V7 engine (see `v7_mk_string()`) are guaranteed to
Marko Mikulicic 0:c0ecb8bf28eb 4079 * be NUL terminated. Out of these, those that don't include embedded NUL chars
Marko Mikulicic 0:c0ecb8bf28eb 4080 * are guaranteed to be C compatible.
Marko Mikulicic 0:c0ecb8bf28eb 4081 */
Marko Mikulicic 0:c0ecb8bf28eb 4082 const char *v7_get_cstring(struct v7 *v7, v7_val_t *v);
Marko Mikulicic 0:c0ecb8bf28eb 4083
Marko Mikulicic 0:c0ecb8bf28eb 4084 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4085 }
Marko Mikulicic 0:c0ecb8bf28eb 4086 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4087
Marko Mikulicic 0:c0ecb8bf28eb 4088 #endif /* CS_V7_SRC_STRING_PUBLIC_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 4089 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 4090 #line 1 "v7/src/string.h"
Marko Mikulicic 0:c0ecb8bf28eb 4091 #endif
Marko Mikulicic 0:c0ecb8bf28eb 4092 /*
Marko Mikulicic 0:c0ecb8bf28eb 4093 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 4094 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 4095 */
Marko Mikulicic 0:c0ecb8bf28eb 4096
Marko Mikulicic 0:c0ecb8bf28eb 4097 #ifndef CS_V7_SRC_STRING_H_
Marko Mikulicic 0:c0ecb8bf28eb 4098 #define CS_V7_SRC_STRING_H_
Marko Mikulicic 0:c0ecb8bf28eb 4099
Marko Mikulicic 0:c0ecb8bf28eb 4100 /* Amalgamated: #include "v7/src/string_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4101
Marko Mikulicic 0:c0ecb8bf28eb 4102 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4103
Marko Mikulicic 0:c0ecb8bf28eb 4104 /*
Marko Mikulicic 0:c0ecb8bf28eb 4105 * Size of the extra space for strings mbuf that is needed to avoid frequent
Marko Mikulicic 0:c0ecb8bf28eb 4106 * reallocations
Marko Mikulicic 0:c0ecb8bf28eb 4107 */
Marko Mikulicic 0:c0ecb8bf28eb 4108 #define _V7_STRING_BUF_RESERVE 500
Marko Mikulicic 0:c0ecb8bf28eb 4109
Marko Mikulicic 0:c0ecb8bf28eb 4110 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4111 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 4112 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4113
Marko Mikulicic 0:c0ecb8bf28eb 4114 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4115 V7_PRIVATE enum v7_err v7_char_code_at(struct v7 *v7, v7_val_t s, v7_val_t at,
Marko Mikulicic 0:c0ecb8bf28eb 4116 double *res);
Marko Mikulicic 0:c0ecb8bf28eb 4117 V7_PRIVATE int s_cmp(struct v7 *, val_t a, val_t b);
Marko Mikulicic 0:c0ecb8bf28eb 4118 V7_PRIVATE val_t s_concat(struct v7 *, val_t, val_t);
Marko Mikulicic 0:c0ecb8bf28eb 4119
Marko Mikulicic 0:c0ecb8bf28eb 4120 /*
Marko Mikulicic 0:c0ecb8bf28eb 4121 * Convert a C string to to an unsigned integer.
Marko Mikulicic 0:c0ecb8bf28eb 4122 * `ok` will be set to true if the string conforms to
Marko Mikulicic 0:c0ecb8bf28eb 4123 * an unsigned long.
Marko Mikulicic 0:c0ecb8bf28eb 4124 */
Marko Mikulicic 0:c0ecb8bf28eb 4125 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4126 V7_PRIVATE enum v7_err str_to_ulong(struct v7 *v7, val_t v, int *ok,
Marko Mikulicic 0:c0ecb8bf28eb 4127 unsigned long *res);
Marko Mikulicic 0:c0ecb8bf28eb 4128
Marko Mikulicic 0:c0ecb8bf28eb 4129 /*
Marko Mikulicic 0:c0ecb8bf28eb 4130 * Convert a V7 string to to an unsigned integer.
Marko Mikulicic 0:c0ecb8bf28eb 4131 * `ok` will be set to true if the string conforms to
Marko Mikulicic 0:c0ecb8bf28eb 4132 * an unsigned long.
Marko Mikulicic 0:c0ecb8bf28eb 4133 *
Marko Mikulicic 0:c0ecb8bf28eb 4134 * Use it if only you need strong conformity of the value to an integer;
Marko Mikulicic 0:c0ecb8bf28eb 4135 * otherwise, use `to_long()` or `to_number_v()` instead.
Marko Mikulicic 0:c0ecb8bf28eb 4136 */
Marko Mikulicic 0:c0ecb8bf28eb 4137 V7_PRIVATE unsigned long cstr_to_ulong(const char *s, size_t len, int *ok);
Marko Mikulicic 0:c0ecb8bf28eb 4138
Marko Mikulicic 0:c0ecb8bf28eb 4139 enum embstr_flags {
Marko Mikulicic 0:c0ecb8bf28eb 4140 EMBSTR_ZERO_TERM = (1 << 0),
Marko Mikulicic 0:c0ecb8bf28eb 4141 EMBSTR_UNESCAPE = (1 << 1),
Marko Mikulicic 0:c0ecb8bf28eb 4142 };
Marko Mikulicic 0:c0ecb8bf28eb 4143
Marko Mikulicic 0:c0ecb8bf28eb 4144 V7_PRIVATE void embed_string(struct mbuf *m, size_t offset, const char *p,
Marko Mikulicic 0:c0ecb8bf28eb 4145 size_t len, uint8_t /*enum embstr_flags*/ flags);
Marko Mikulicic 0:c0ecb8bf28eb 4146
Marko Mikulicic 0:c0ecb8bf28eb 4147 V7_PRIVATE size_t unescape(const char *s, size_t len, char *to);
Marko Mikulicic 0:c0ecb8bf28eb 4148
Marko Mikulicic 0:c0ecb8bf28eb 4149 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4150 }
Marko Mikulicic 0:c0ecb8bf28eb 4151 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4152
Marko Mikulicic 0:c0ecb8bf28eb 4153 #endif /* CS_V7_SRC_STRING_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 4154 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 4155 #line 1 "v7/src/exceptions_public.h"
Marko Mikulicic 0:c0ecb8bf28eb 4156 #endif
Marko Mikulicic 0:c0ecb8bf28eb 4157 /*
Marko Mikulicic 0:c0ecb8bf28eb 4158 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 4159 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 4160 */
Marko Mikulicic 0:c0ecb8bf28eb 4161
Marko Mikulicic 0:c0ecb8bf28eb 4162 /*
Marko Mikulicic 0:c0ecb8bf28eb 4163 * === Exceptions
Marko Mikulicic 0:c0ecb8bf28eb 4164 */
Marko Mikulicic 0:c0ecb8bf28eb 4165
Marko Mikulicic 0:c0ecb8bf28eb 4166 #ifndef CS_V7_SRC_EXCEPTIONS_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 4167 #define CS_V7_SRC_EXCEPTIONS_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 4168
Marko Mikulicic 0:c0ecb8bf28eb 4169 /* Amalgamated: #include "v7/src/core_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4170
Marko Mikulicic 0:c0ecb8bf28eb 4171 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4172 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 4173 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4174
Marko Mikulicic 0:c0ecb8bf28eb 4175 /* Throw an exception with an already existing value. */
Marko Mikulicic 0:c0ecb8bf28eb 4176 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4177 enum v7_err v7_throw(struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 4178
Marko Mikulicic 0:c0ecb8bf28eb 4179 /*
Marko Mikulicic 0:c0ecb8bf28eb 4180 * Throw an exception with given formatted message.
Marko Mikulicic 0:c0ecb8bf28eb 4181 *
Marko Mikulicic 0:c0ecb8bf28eb 4182 * Pass "Error" as typ for a generic error.
Marko Mikulicic 0:c0ecb8bf28eb 4183 */
Marko Mikulicic 0:c0ecb8bf28eb 4184 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4185 enum v7_err v7_throwf(struct v7 *v7, const char *typ, const char *err_fmt, ...);
Marko Mikulicic 0:c0ecb8bf28eb 4186
Marko Mikulicic 0:c0ecb8bf28eb 4187 /*
Marko Mikulicic 0:c0ecb8bf28eb 4188 * Rethrow the currently thrown object. In fact, it just returns
Marko Mikulicic 0:c0ecb8bf28eb 4189 * V7_EXEC_EXCEPTION.
Marko Mikulicic 0:c0ecb8bf28eb 4190 */
Marko Mikulicic 0:c0ecb8bf28eb 4191 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4192 enum v7_err v7_rethrow(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 4193
Marko Mikulicic 0:c0ecb8bf28eb 4194 /*
Marko Mikulicic 0:c0ecb8bf28eb 4195 * Returns the value that is being thrown at the moment, or `undefined` if
Marko Mikulicic 0:c0ecb8bf28eb 4196 * nothing is being thrown. If `is_thrown` is not `NULL`, it will be set
Marko Mikulicic 0:c0ecb8bf28eb 4197 * to either 0 or 1, depending on whether something is thrown at the moment.
Marko Mikulicic 0:c0ecb8bf28eb 4198 */
Marko Mikulicic 0:c0ecb8bf28eb 4199 v7_val_t v7_get_thrown_value(struct v7 *v7, unsigned char *is_thrown);
Marko Mikulicic 0:c0ecb8bf28eb 4200
Marko Mikulicic 0:c0ecb8bf28eb 4201 /* Clears currently thrown value, if any. */
Marko Mikulicic 0:c0ecb8bf28eb 4202 void v7_clear_thrown_value(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 4203
Marko Mikulicic 0:c0ecb8bf28eb 4204 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4205 }
Marko Mikulicic 0:c0ecb8bf28eb 4206 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4207
Marko Mikulicic 0:c0ecb8bf28eb 4208 #endif /* CS_V7_SRC_EXCEPTIONS_PUBLIC_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 4209 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 4210 #line 1 "v7/src/exceptions.h"
Marko Mikulicic 0:c0ecb8bf28eb 4211 #endif
Marko Mikulicic 0:c0ecb8bf28eb 4212 /*
Marko Mikulicic 0:c0ecb8bf28eb 4213 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 4214 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 4215 */
Marko Mikulicic 0:c0ecb8bf28eb 4216
Marko Mikulicic 0:c0ecb8bf28eb 4217 #ifndef CS_V7_SRC_EXCEPTIONS_H_
Marko Mikulicic 0:c0ecb8bf28eb 4218 #define CS_V7_SRC_EXCEPTIONS_H_
Marko Mikulicic 0:c0ecb8bf28eb 4219
Marko Mikulicic 0:c0ecb8bf28eb 4220 /* Amalgamated: #include "v7/src/exceptions_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4221
Marko Mikulicic 0:c0ecb8bf28eb 4222 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4223
Marko Mikulicic 0:c0ecb8bf28eb 4224 /*
Marko Mikulicic 0:c0ecb8bf28eb 4225 * Try to perform some arbitrary call, and if the result is other than `V7_OK`,
Marko Mikulicic 0:c0ecb8bf28eb 4226 * "throws" an error with `V7_THROW()`
Marko Mikulicic 0:c0ecb8bf28eb 4227 */
Marko Mikulicic 0:c0ecb8bf28eb 4228 #define V7_TRY2(call, clean_label) \
Marko Mikulicic 0:c0ecb8bf28eb 4229 do { \
Marko Mikulicic 0:c0ecb8bf28eb 4230 enum v7_err _e = call; \
Marko Mikulicic 0:c0ecb8bf28eb 4231 V7_CHECK2(_e == V7_OK, _e, clean_label); \
Marko Mikulicic 0:c0ecb8bf28eb 4232 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 4233
Marko Mikulicic 0:c0ecb8bf28eb 4234 /*
Marko Mikulicic 0:c0ecb8bf28eb 4235 * Sets return value to the provided one, and `goto`s `clean`.
Marko Mikulicic 0:c0ecb8bf28eb 4236 *
Marko Mikulicic 0:c0ecb8bf28eb 4237 * For this to work, you should have local `enum v7_err rcode` variable,
Marko Mikulicic 0:c0ecb8bf28eb 4238 * and a `clean` label.
Marko Mikulicic 0:c0ecb8bf28eb 4239 */
Marko Mikulicic 0:c0ecb8bf28eb 4240 #define V7_THROW2(err_code, clean_label) \
Marko Mikulicic 0:c0ecb8bf28eb 4241 do { \
Marko Mikulicic 0:c0ecb8bf28eb 4242 (void) v7; \
Marko Mikulicic 0:c0ecb8bf28eb 4243 rcode = (err_code); \
Marko Mikulicic 0:c0ecb8bf28eb 4244 assert(rcode != V7_OK); \
Marko Mikulicic 0:c0ecb8bf28eb 4245 assert(!v7_is_undefined(v7->vals.thrown_error) && v7->is_thrown); \
Marko Mikulicic 0:c0ecb8bf28eb 4246 goto clean_label; \
Marko Mikulicic 0:c0ecb8bf28eb 4247 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 4248
Marko Mikulicic 0:c0ecb8bf28eb 4249 /*
Marko Mikulicic 0:c0ecb8bf28eb 4250 * Checks provided condition `cond`, and if it's false, then "throws"
Marko Mikulicic 0:c0ecb8bf28eb 4251 * provided `err_code` (see `V7_THROW()`)
Marko Mikulicic 0:c0ecb8bf28eb 4252 */
Marko Mikulicic 0:c0ecb8bf28eb 4253 #define V7_CHECK2(cond, err_code, clean_label) \
Marko Mikulicic 0:c0ecb8bf28eb 4254 do { \
Marko Mikulicic 0:c0ecb8bf28eb 4255 if (!(cond)) { \
Marko Mikulicic 0:c0ecb8bf28eb 4256 V7_THROW2(err_code, clean_label); \
Marko Mikulicic 0:c0ecb8bf28eb 4257 } \
Marko Mikulicic 0:c0ecb8bf28eb 4258 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 4259
Marko Mikulicic 0:c0ecb8bf28eb 4260 /*
Marko Mikulicic 0:c0ecb8bf28eb 4261 * Checks provided condition `cond`, and if it's false, then "throws"
Marko Mikulicic 0:c0ecb8bf28eb 4262 * internal error
Marko Mikulicic 0:c0ecb8bf28eb 4263 *
Marko Mikulicic 0:c0ecb8bf28eb 4264 * TODO(dfrank): it would be good to have formatted string: then, we can
Marko Mikulicic 0:c0ecb8bf28eb 4265 * specify file and line.
Marko Mikulicic 0:c0ecb8bf28eb 4266 */
Marko Mikulicic 0:c0ecb8bf28eb 4267 #define V7_CHECK_INTERNAL2(cond, clean_label) \
Marko Mikulicic 0:c0ecb8bf28eb 4268 do { \
Marko Mikulicic 0:c0ecb8bf28eb 4269 if (!(cond)) { \
Marko Mikulicic 0:c0ecb8bf28eb 4270 enum v7_err __rcode = v7_throwf(v7, "Error", "Internal error"); \
Marko Mikulicic 0:c0ecb8bf28eb 4271 (void) __rcode; \
Marko Mikulicic 0:c0ecb8bf28eb 4272 V7_THROW2(V7_INTERNAL_ERROR, clean_label); \
Marko Mikulicic 0:c0ecb8bf28eb 4273 } \
Marko Mikulicic 0:c0ecb8bf28eb 4274 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 4275
Marko Mikulicic 0:c0ecb8bf28eb 4276 /*
Marko Mikulicic 0:c0ecb8bf28eb 4277 * Shortcuts for the macros above, but they assume the clean label `clean`.
Marko Mikulicic 0:c0ecb8bf28eb 4278 */
Marko Mikulicic 0:c0ecb8bf28eb 4279
Marko Mikulicic 0:c0ecb8bf28eb 4280 #define V7_TRY(call) V7_TRY2(call, clean)
Marko Mikulicic 0:c0ecb8bf28eb 4281 #define V7_THROW(err_code) V7_THROW2(err_code, clean)
Marko Mikulicic 0:c0ecb8bf28eb 4282 #define V7_CHECK(cond, err_code) V7_CHECK2(cond, err_code, clean)
Marko Mikulicic 0:c0ecb8bf28eb 4283 #define V7_CHECK_INTERNAL(cond) V7_CHECK_INTERNAL2(cond, clean)
Marko Mikulicic 0:c0ecb8bf28eb 4284
Marko Mikulicic 0:c0ecb8bf28eb 4285 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4286 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 4287 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4288
Marko Mikulicic 0:c0ecb8bf28eb 4289 /*
Marko Mikulicic 0:c0ecb8bf28eb 4290 * At the moment, most of the exception-related functions are public, and are
Marko Mikulicic 0:c0ecb8bf28eb 4291 * declared in `exceptions_public.h`
Marko Mikulicic 0:c0ecb8bf28eb 4292 */
Marko Mikulicic 0:c0ecb8bf28eb 4293
Marko Mikulicic 0:c0ecb8bf28eb 4294 /*
Marko Mikulicic 0:c0ecb8bf28eb 4295 * Create an instance of the exception with type `typ` (see `TYPE_ERROR`,
Marko Mikulicic 0:c0ecb8bf28eb 4296 * `SYNTAX_ERROR`, etc), and message `msg`.
Marko Mikulicic 0:c0ecb8bf28eb 4297 */
Marko Mikulicic 0:c0ecb8bf28eb 4298 V7_PRIVATE enum v7_err create_exception(struct v7 *v7, const char *typ,
Marko Mikulicic 0:c0ecb8bf28eb 4299 const char *msg, val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 4300
Marko Mikulicic 0:c0ecb8bf28eb 4301 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4302 }
Marko Mikulicic 0:c0ecb8bf28eb 4303 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4304
Marko Mikulicic 0:c0ecb8bf28eb 4305 #endif /* CS_V7_SRC_EXCEPTIONS_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 4306 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 4307 #line 1 "v7/src/object.h"
Marko Mikulicic 0:c0ecb8bf28eb 4308 #endif
Marko Mikulicic 0:c0ecb8bf28eb 4309 /*
Marko Mikulicic 0:c0ecb8bf28eb 4310 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 4311 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 4312 */
Marko Mikulicic 0:c0ecb8bf28eb 4313
Marko Mikulicic 0:c0ecb8bf28eb 4314 #ifndef CS_V7_SRC_OBJECT_H_
Marko Mikulicic 0:c0ecb8bf28eb 4315 #define CS_V7_SRC_OBJECT_H_
Marko Mikulicic 0:c0ecb8bf28eb 4316
Marko Mikulicic 0:c0ecb8bf28eb 4317 /* Amalgamated: #include "v7/src/object_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4318
Marko Mikulicic 0:c0ecb8bf28eb 4319 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4320 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4321
Marko Mikulicic 0:c0ecb8bf28eb 4322 V7_PRIVATE val_t mk_object(struct v7 *v7, val_t prototype);
Marko Mikulicic 0:c0ecb8bf28eb 4323 V7_PRIVATE val_t v7_object_to_value(struct v7_object *o);
Marko Mikulicic 0:c0ecb8bf28eb 4324 V7_PRIVATE struct v7_generic_object *get_generic_object_struct(val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 4325
Marko Mikulicic 0:c0ecb8bf28eb 4326 /*
Marko Mikulicic 0:c0ecb8bf28eb 4327 * Returns pointer to the struct representing an object.
Marko Mikulicic 0:c0ecb8bf28eb 4328 * Given value must be an object (the caller can verify it
Marko Mikulicic 0:c0ecb8bf28eb 4329 * by calling `v7_is_object()`)
Marko Mikulicic 0:c0ecb8bf28eb 4330 */
Marko Mikulicic 0:c0ecb8bf28eb 4331 V7_PRIVATE struct v7_object *get_object_struct(v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 4332
Marko Mikulicic 0:c0ecb8bf28eb 4333 /*
Marko Mikulicic 0:c0ecb8bf28eb 4334 * Return true if given value is a JavaScript object (will return
Marko Mikulicic 0:c0ecb8bf28eb 4335 * false for function)
Marko Mikulicic 0:c0ecb8bf28eb 4336 */
Marko Mikulicic 0:c0ecb8bf28eb 4337 V7_PRIVATE int v7_is_generic_object(v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 4338
Marko Mikulicic 0:c0ecb8bf28eb 4339 V7_PRIVATE struct v7_property *v7_mk_property(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 4340
Marko Mikulicic 0:c0ecb8bf28eb 4341 V7_PRIVATE struct v7_property *v7_get_own_property2(struct v7 *v7, val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 4342 const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 4343 size_t len,
Marko Mikulicic 0:c0ecb8bf28eb 4344 v7_prop_attr_t attrs);
Marko Mikulicic 0:c0ecb8bf28eb 4345
Marko Mikulicic 0:c0ecb8bf28eb 4346 V7_PRIVATE struct v7_property *v7_get_own_property(struct v7 *v7, val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 4347 const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 4348 size_t len);
Marko Mikulicic 0:c0ecb8bf28eb 4349
Marko Mikulicic 0:c0ecb8bf28eb 4350 /*
Marko Mikulicic 0:c0ecb8bf28eb 4351 * If `len` is -1/MAXUINT/~0, then `name` must be 0-terminated
Marko Mikulicic 0:c0ecb8bf28eb 4352 *
Marko Mikulicic 0:c0ecb8bf28eb 4353 * Returns a pointer to the property structure, given an object and a name of
Marko Mikulicic 0:c0ecb8bf28eb 4354 * the property as a pointer to string buffer and length.
Marko Mikulicic 0:c0ecb8bf28eb 4355 *
Marko Mikulicic 0:c0ecb8bf28eb 4356 * See also `v7_get_property_v`
Marko Mikulicic 0:c0ecb8bf28eb 4357 */
Marko Mikulicic 0:c0ecb8bf28eb 4358 V7_PRIVATE struct v7_property *v7_get_property(struct v7 *v7, val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 4359 const char *name, size_t len);
Marko Mikulicic 0:c0ecb8bf28eb 4360
Marko Mikulicic 0:c0ecb8bf28eb 4361 /*
Marko Mikulicic 0:c0ecb8bf28eb 4362 * Just like `v7_get_property`, but takes name as a `v7_val_t`
Marko Mikulicic 0:c0ecb8bf28eb 4363 */
Marko Mikulicic 0:c0ecb8bf28eb 4364 V7_PRIVATE enum v7_err v7_get_property_v(struct v7 *v7, val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 4365 v7_val_t name,
Marko Mikulicic 0:c0ecb8bf28eb 4366 struct v7_property **res);
Marko Mikulicic 0:c0ecb8bf28eb 4367
Marko Mikulicic 0:c0ecb8bf28eb 4368 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4369 V7_PRIVATE enum v7_err v7_get_throwing_v(struct v7 *v7, v7_val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 4370 v7_val_t name, v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 4371
Marko Mikulicic 0:c0ecb8bf28eb 4372 V7_PRIVATE void v7_destroy_property(struct v7_property **p);
Marko Mikulicic 0:c0ecb8bf28eb 4373
Marko Mikulicic 0:c0ecb8bf28eb 4374 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4375 V7_PRIVATE enum v7_err v7_invoke_setter(struct v7 *v7, struct v7_property *prop,
Marko Mikulicic 0:c0ecb8bf28eb 4376 val_t obj, val_t val);
Marko Mikulicic 0:c0ecb8bf28eb 4377
Marko Mikulicic 0:c0ecb8bf28eb 4378 /*
Marko Mikulicic 0:c0ecb8bf28eb 4379 * Like `set_property`, but takes property name as a `val_t`
Marko Mikulicic 0:c0ecb8bf28eb 4380 */
Marko Mikulicic 0:c0ecb8bf28eb 4381 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4382 V7_PRIVATE enum v7_err set_property_v(struct v7 *v7, val_t obj, val_t name,
Marko Mikulicic 0:c0ecb8bf28eb 4383 val_t val, struct v7_property **res);
Marko Mikulicic 0:c0ecb8bf28eb 4384
Marko Mikulicic 0:c0ecb8bf28eb 4385 /*
Marko Mikulicic 0:c0ecb8bf28eb 4386 * Like JavaScript assignment: set a property with given `name` + `len` at
Marko Mikulicic 0:c0ecb8bf28eb 4387 * the object `obj` to value `val`. Returns a property through the `res`
Marko Mikulicic 0:c0ecb8bf28eb 4388 * (which may be `NULL` if return value is not required)
Marko Mikulicic 0:c0ecb8bf28eb 4389 */
Marko Mikulicic 0:c0ecb8bf28eb 4390 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4391 V7_PRIVATE enum v7_err set_property(struct v7 *v7, val_t obj, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 4392 size_t len, v7_val_t val,
Marko Mikulicic 0:c0ecb8bf28eb 4393 struct v7_property **res);
Marko Mikulicic 0:c0ecb8bf28eb 4394
Marko Mikulicic 0:c0ecb8bf28eb 4395 /*
Marko Mikulicic 0:c0ecb8bf28eb 4396 * Like `def_property()`, but takes property name as a `val_t`
Marko Mikulicic 0:c0ecb8bf28eb 4397 */
Marko Mikulicic 0:c0ecb8bf28eb 4398 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4399 V7_PRIVATE enum v7_err def_property_v(struct v7 *v7, val_t obj, val_t name,
Marko Mikulicic 0:c0ecb8bf28eb 4400 v7_prop_attr_desc_t attrs_desc, val_t val,
Marko Mikulicic 0:c0ecb8bf28eb 4401 uint8_t as_assign,
Marko Mikulicic 0:c0ecb8bf28eb 4402 struct v7_property **res);
Marko Mikulicic 0:c0ecb8bf28eb 4403
Marko Mikulicic 0:c0ecb8bf28eb 4404 /*
Marko Mikulicic 0:c0ecb8bf28eb 4405 * Define object property, similar to JavaScript `Object.defineProperty()`.
Marko Mikulicic 0:c0ecb8bf28eb 4406 *
Marko Mikulicic 0:c0ecb8bf28eb 4407 * Just like public `v7_def()`, but returns `enum v7_err`, and therefore can
Marko Mikulicic 0:c0ecb8bf28eb 4408 * throw.
Marko Mikulicic 0:c0ecb8bf28eb 4409 *
Marko Mikulicic 0:c0ecb8bf28eb 4410 * Additionally, takes param `as_assign`: if it is non-zero, it behaves
Marko Mikulicic 0:c0ecb8bf28eb 4411 * similarly to plain JavaScript assignment in terms of some exception-related
Marko Mikulicic 0:c0ecb8bf28eb 4412 * corner cases.
Marko Mikulicic 0:c0ecb8bf28eb 4413 *
Marko Mikulicic 0:c0ecb8bf28eb 4414 * `res` may be `NULL`.
Marko Mikulicic 0:c0ecb8bf28eb 4415 */
Marko Mikulicic 0:c0ecb8bf28eb 4416 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4417 V7_PRIVATE enum v7_err def_property(struct v7 *v7, val_t obj, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 4418 size_t len, v7_prop_attr_desc_t attrs_desc,
Marko Mikulicic 0:c0ecb8bf28eb 4419 v7_val_t val, uint8_t as_assign,
Marko Mikulicic 0:c0ecb8bf28eb 4420 struct v7_property **res);
Marko Mikulicic 0:c0ecb8bf28eb 4421
Marko Mikulicic 0:c0ecb8bf28eb 4422 V7_PRIVATE int set_method(struct v7 *v7, val_t obj, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 4423 v7_cfunction_t *func, int num_args);
Marko Mikulicic 0:c0ecb8bf28eb 4424
Marko Mikulicic 0:c0ecb8bf28eb 4425 V7_PRIVATE int set_cfunc_prop(struct v7 *v7, val_t o, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 4426 v7_cfunction_t *func);
Marko Mikulicic 0:c0ecb8bf28eb 4427
Marko Mikulicic 0:c0ecb8bf28eb 4428 /* Return address of property value or NULL if the passed property is NULL */
Marko Mikulicic 0:c0ecb8bf28eb 4429 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4430 V7_PRIVATE enum v7_err v7_property_value(struct v7 *v7, val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 4431 struct v7_property *p, val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 4432
Marko Mikulicic 0:c0ecb8bf28eb 4433 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 4434 /*
Marko Mikulicic 0:c0ecb8bf28eb 4435 * Additional context for property iteration of a proxied object, see
Marko Mikulicic 0:c0ecb8bf28eb 4436 * `v7_next_prop()`.
Marko Mikulicic 0:c0ecb8bf28eb 4437 */
Marko Mikulicic 0:c0ecb8bf28eb 4438 struct prop_iter_proxy_ctx {
Marko Mikulicic 0:c0ecb8bf28eb 4439 /* Proxy target object */
Marko Mikulicic 0:c0ecb8bf28eb 4440 v7_val_t target_obj;
Marko Mikulicic 0:c0ecb8bf28eb 4441 /* Proxy handler object */
Marko Mikulicic 0:c0ecb8bf28eb 4442 v7_val_t handler_obj;
Marko Mikulicic 0:c0ecb8bf28eb 4443
Marko Mikulicic 0:c0ecb8bf28eb 4444 /*
Marko Mikulicic 0:c0ecb8bf28eb 4445 * array returned by the `ownKeys` callback, valid if only `has_own_keys` is
Marko Mikulicic 0:c0ecb8bf28eb 4446 * set
Marko Mikulicic 0:c0ecb8bf28eb 4447 */
Marko Mikulicic 0:c0ecb8bf28eb 4448 v7_val_t own_keys;
Marko Mikulicic 0:c0ecb8bf28eb 4449 /*
Marko Mikulicic 0:c0ecb8bf28eb 4450 * callback to get property descriptor, one of these:
Marko Mikulicic 0:c0ecb8bf28eb 4451 * - a JS or cfunction `getOwnPropertyDescriptor`
Marko Mikulicic 0:c0ecb8bf28eb 4452 * (if `has_get_own_prop_desc_C` is not set);
Marko Mikulicic 0:c0ecb8bf28eb 4453 * - a C callback `v7_get_own_prop_desc_cb_t`.
Marko Mikulicic 0:c0ecb8bf28eb 4454 * (if `has_get_own_prop_desc_C` is set);
Marko Mikulicic 0:c0ecb8bf28eb 4455 */
Marko Mikulicic 0:c0ecb8bf28eb 4456 v7_val_t get_own_prop_desc;
Marko Mikulicic 0:c0ecb8bf28eb 4457
Marko Mikulicic 0:c0ecb8bf28eb 4458 /*
Marko Mikulicic 0:c0ecb8bf28eb 4459 * if `has_own_keys` is set, `own_key_idx` represents next index in the
Marko Mikulicic 0:c0ecb8bf28eb 4460 * `own_keys` array
Marko Mikulicic 0:c0ecb8bf28eb 4461 */
Marko Mikulicic 0:c0ecb8bf28eb 4462 unsigned own_key_idx : 29;
Marko Mikulicic 0:c0ecb8bf28eb 4463
Marko Mikulicic 0:c0ecb8bf28eb 4464 /* if set, `own_keys` is valid */
Marko Mikulicic 0:c0ecb8bf28eb 4465 unsigned has_own_keys : 1;
Marko Mikulicic 0:c0ecb8bf28eb 4466 /* if set, `get_own_prop_desc` is valid */
Marko Mikulicic 0:c0ecb8bf28eb 4467 unsigned has_get_own_prop_desc : 1;
Marko Mikulicic 0:c0ecb8bf28eb 4468 /*
Marko Mikulicic 0:c0ecb8bf28eb 4469 * if set, `get_own_prop_desc` is a C callback `has_get_own_prop_desc_C`, not
Marko Mikulicic 0:c0ecb8bf28eb 4470 * a JS callback
Marko Mikulicic 0:c0ecb8bf28eb 4471 */
Marko Mikulicic 0:c0ecb8bf28eb 4472 unsigned has_get_own_prop_desc_C : 1;
Marko Mikulicic 0:c0ecb8bf28eb 4473 };
Marko Mikulicic 0:c0ecb8bf28eb 4474 #endif
Marko Mikulicic 0:c0ecb8bf28eb 4475
Marko Mikulicic 0:c0ecb8bf28eb 4476 /*
Marko Mikulicic 0:c0ecb8bf28eb 4477 * Like public function `v7_init_prop_iter_ctx()`, but it takes additional
Marko Mikulicic 0:c0ecb8bf28eb 4478 * argument `proxy_transp`; if it is zero, and the given `obj` is a Proxy, it
Marko Mikulicic 0:c0ecb8bf28eb 4479 * will iterate the properties of the proxy itself, not the Proxy's target.
Marko Mikulicic 0:c0ecb8bf28eb 4480 */
Marko Mikulicic 0:c0ecb8bf28eb 4481 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4482 V7_PRIVATE enum v7_err init_prop_iter_ctx(struct v7 *v7, v7_val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 4483 int proxy_transp,
Marko Mikulicic 0:c0ecb8bf28eb 4484 struct prop_iter_ctx *ctx);
Marko Mikulicic 0:c0ecb8bf28eb 4485
Marko Mikulicic 0:c0ecb8bf28eb 4486 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4487 V7_PRIVATE enum v7_err next_prop(struct v7 *v7, struct prop_iter_ctx *ctx,
Marko Mikulicic 0:c0ecb8bf28eb 4488 v7_val_t *name, v7_val_t *value,
Marko Mikulicic 0:c0ecb8bf28eb 4489 v7_prop_attr_t *attrs, int *ok);
Marko Mikulicic 0:c0ecb8bf28eb 4490
Marko Mikulicic 0:c0ecb8bf28eb 4491 /*
Marko Mikulicic 0:c0ecb8bf28eb 4492 * Set new prototype `proto` for the given object `obj`. Returns `0` at
Marko Mikulicic 0:c0ecb8bf28eb 4493 * success, `-1` at failure (it may fail if given `obj` is a function object:
Marko Mikulicic 0:c0ecb8bf28eb 4494 * it's impossible to change function object's prototype)
Marko Mikulicic 0:c0ecb8bf28eb 4495 */
Marko Mikulicic 0:c0ecb8bf28eb 4496 V7_PRIVATE int obj_prototype_set(struct v7 *v7, struct v7_object *obj,
Marko Mikulicic 0:c0ecb8bf28eb 4497 struct v7_object *proto);
Marko Mikulicic 0:c0ecb8bf28eb 4498
Marko Mikulicic 0:c0ecb8bf28eb 4499 /*
Marko Mikulicic 0:c0ecb8bf28eb 4500 * Given a pointer to the object structure, returns a
Marko Mikulicic 0:c0ecb8bf28eb 4501 * pointer to the prototype object, or `NULL` if there is
Marko Mikulicic 0:c0ecb8bf28eb 4502 * no prototype.
Marko Mikulicic 0:c0ecb8bf28eb 4503 */
Marko Mikulicic 0:c0ecb8bf28eb 4504 V7_PRIVATE struct v7_object *obj_prototype(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 4505 struct v7_object *obj);
Marko Mikulicic 0:c0ecb8bf28eb 4506
Marko Mikulicic 0:c0ecb8bf28eb 4507 V7_PRIVATE int is_prototype_of(struct v7 *v7, val_t o, val_t p);
Marko Mikulicic 0:c0ecb8bf28eb 4508
Marko Mikulicic 0:c0ecb8bf28eb 4509 /* Get the property holding user data and destructor, or NULL */
Marko Mikulicic 0:c0ecb8bf28eb 4510 V7_PRIVATE struct v7_property *get_user_data_property(v7_val_t obj);
Marko Mikulicic 0:c0ecb8bf28eb 4511
Marko Mikulicic 0:c0ecb8bf28eb 4512 #endif /* CS_V7_SRC_OBJECT_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 4513 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 4514 #line 1 "v7/src/exec_public.h"
Marko Mikulicic 0:c0ecb8bf28eb 4515 #endif
Marko Mikulicic 0:c0ecb8bf28eb 4516 /*
Marko Mikulicic 0:c0ecb8bf28eb 4517 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 4518 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 4519 */
Marko Mikulicic 0:c0ecb8bf28eb 4520
Marko Mikulicic 0:c0ecb8bf28eb 4521 /*
Marko Mikulicic 0:c0ecb8bf28eb 4522 * === Execution of JavaScript code
Marko Mikulicic 0:c0ecb8bf28eb 4523 */
Marko Mikulicic 0:c0ecb8bf28eb 4524
Marko Mikulicic 0:c0ecb8bf28eb 4525 #ifndef CS_V7_SRC_EXEC_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 4526 #define CS_V7_SRC_EXEC_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 4527
Marko Mikulicic 0:c0ecb8bf28eb 4528 /* Amalgamated: #include "v7/src/core_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4529
Marko Mikulicic 0:c0ecb8bf28eb 4530 /*
Marko Mikulicic 0:c0ecb8bf28eb 4531 * Execute JavaScript `js_code`. The result of evaluation is stored in
Marko Mikulicic 0:c0ecb8bf28eb 4532 * the `result` variable.
Marko Mikulicic 0:c0ecb8bf28eb 4533 *
Marko Mikulicic 0:c0ecb8bf28eb 4534 * Return:
Marko Mikulicic 0:c0ecb8bf28eb 4535 *
Marko Mikulicic 0:c0ecb8bf28eb 4536 * - V7_OK on success. `result` contains the result of execution.
Marko Mikulicic 0:c0ecb8bf28eb 4537 * - V7_SYNTAX_ERROR if `js_code` in not a valid code. `result` is undefined.
Marko Mikulicic 0:c0ecb8bf28eb 4538 * - V7_EXEC_EXCEPTION if `js_code` threw an exception. `result` stores
Marko Mikulicic 0:c0ecb8bf28eb 4539 * an exception object.
Marko Mikulicic 0:c0ecb8bf28eb 4540 * - V7_AST_TOO_LARGE if `js_code` contains an AST segment longer than 16 bit.
Marko Mikulicic 0:c0ecb8bf28eb 4541 * `result` is undefined. To avoid this error, build V7 with V7_LARGE_AST.
Marko Mikulicic 0:c0ecb8bf28eb 4542 */
Marko Mikulicic 0:c0ecb8bf28eb 4543 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4544 enum v7_err v7_exec(struct v7 *v7, const char *js_code, v7_val_t *result);
Marko Mikulicic 0:c0ecb8bf28eb 4545
Marko Mikulicic 0:c0ecb8bf28eb 4546 /*
Marko Mikulicic 0:c0ecb8bf28eb 4547 * Options for `v7_exec_opt()`. To get default options, like `v7_exec()` uses,
Marko Mikulicic 0:c0ecb8bf28eb 4548 * just zero out this struct.
Marko Mikulicic 0:c0ecb8bf28eb 4549 */
Marko Mikulicic 0:c0ecb8bf28eb 4550 struct v7_exec_opts {
Marko Mikulicic 0:c0ecb8bf28eb 4551 /* Filename, used for stack traces only */
Marko Mikulicic 0:c0ecb8bf28eb 4552 const char *filename;
Marko Mikulicic 0:c0ecb8bf28eb 4553
Marko Mikulicic 0:c0ecb8bf28eb 4554 /*
Marko Mikulicic 0:c0ecb8bf28eb 4555 * Object to be used as `this`. Note: when it is zeroed out, i.e. it's a
Marko Mikulicic 0:c0ecb8bf28eb 4556 * number `0`, the `undefined` value is assumed. It means that it's
Marko Mikulicic 0:c0ecb8bf28eb 4557 * impossible to actually use the number `0` as `this` object, but it makes
Marko Mikulicic 0:c0ecb8bf28eb 4558 * little sense anyway.
Marko Mikulicic 0:c0ecb8bf28eb 4559 */
Marko Mikulicic 0:c0ecb8bf28eb 4560 v7_val_t this_obj;
Marko Mikulicic 0:c0ecb8bf28eb 4561
Marko Mikulicic 0:c0ecb8bf28eb 4562 /* Whether the given `js_code` should be interpreted as JSON, not JS code */
Marko Mikulicic 0:c0ecb8bf28eb 4563 unsigned is_json : 1;
Marko Mikulicic 0:c0ecb8bf28eb 4564 };
Marko Mikulicic 0:c0ecb8bf28eb 4565
Marko Mikulicic 0:c0ecb8bf28eb 4566 /*
Marko Mikulicic 0:c0ecb8bf28eb 4567 * Customizable version of `v7_exec()`: allows to specify various options, see
Marko Mikulicic 0:c0ecb8bf28eb 4568 * `struct v7_exec_opts`.
Marko Mikulicic 0:c0ecb8bf28eb 4569 */
Marko Mikulicic 0:c0ecb8bf28eb 4570 enum v7_err v7_exec_opt(struct v7 *v7, const char *js_code,
Marko Mikulicic 0:c0ecb8bf28eb 4571 const struct v7_exec_opts *opts, v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 4572
Marko Mikulicic 0:c0ecb8bf28eb 4573 /*
Marko Mikulicic 0:c0ecb8bf28eb 4574 * Same as `v7_exec()`, but loads source code from `path` file.
Marko Mikulicic 0:c0ecb8bf28eb 4575 */
Marko Mikulicic 0:c0ecb8bf28eb 4576 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4577 enum v7_err v7_exec_file(struct v7 *v7, const char *path, v7_val_t *result);
Marko Mikulicic 0:c0ecb8bf28eb 4578
Marko Mikulicic 0:c0ecb8bf28eb 4579 /*
Marko Mikulicic 0:c0ecb8bf28eb 4580 * Parse `str` and store corresponding JavaScript object in `res` variable.
Marko Mikulicic 0:c0ecb8bf28eb 4581 * String `str` should be '\0'-terminated.
Marko Mikulicic 0:c0ecb8bf28eb 4582 * Return value and semantic is the same as for `v7_exec()`.
Marko Mikulicic 0:c0ecb8bf28eb 4583 */
Marko Mikulicic 0:c0ecb8bf28eb 4584 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4585 enum v7_err v7_parse_json(struct v7 *v7, const char *str, v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 4586
Marko Mikulicic 0:c0ecb8bf28eb 4587 /*
Marko Mikulicic 0:c0ecb8bf28eb 4588 * Same as `v7_parse_json()`, but loads JSON string from `path`.
Marko Mikulicic 0:c0ecb8bf28eb 4589 */
Marko Mikulicic 0:c0ecb8bf28eb 4590 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4591 enum v7_err v7_parse_json_file(struct v7 *v7, const char *path, v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 4592
Marko Mikulicic 0:c0ecb8bf28eb 4593 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 4594
Marko Mikulicic 0:c0ecb8bf28eb 4595 /*
Marko Mikulicic 0:c0ecb8bf28eb 4596 * Compile JavaScript code `js_code` into the byte code and write generated
Marko Mikulicic 0:c0ecb8bf28eb 4597 * byte code into opened file stream `fp`. If `generate_binary_output` is 0,
Marko Mikulicic 0:c0ecb8bf28eb 4598 * then generated byte code is in human-readable text format. Otherwise, it is
Marko Mikulicic 0:c0ecb8bf28eb 4599 * in the binary format, suitable for execution by V7 instance.
Marko Mikulicic 0:c0ecb8bf28eb 4600 * NOTE: `fp` must be a valid, opened, writable file stream.
Marko Mikulicic 0:c0ecb8bf28eb 4601 */
Marko Mikulicic 0:c0ecb8bf28eb 4602 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4603 enum v7_err v7_compile(const char *js_code, int generate_binary_output,
Marko Mikulicic 0:c0ecb8bf28eb 4604 int use_bcode, FILE *fp);
Marko Mikulicic 0:c0ecb8bf28eb 4605
Marko Mikulicic 0:c0ecb8bf28eb 4606 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 4607
Marko Mikulicic 0:c0ecb8bf28eb 4608 /*
Marko Mikulicic 0:c0ecb8bf28eb 4609 * Call function `func` with arguments `args`, using `this_obj` as `this`.
Marko Mikulicic 0:c0ecb8bf28eb 4610 * `args` should be an array containing arguments or `undefined`.
Marko Mikulicic 0:c0ecb8bf28eb 4611 *
Marko Mikulicic 0:c0ecb8bf28eb 4612 * `res` can be `NULL` if return value is not required.
Marko Mikulicic 0:c0ecb8bf28eb 4613 */
Marko Mikulicic 0:c0ecb8bf28eb 4614 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4615 enum v7_err v7_apply(struct v7 *v7, v7_val_t func, v7_val_t this_obj,
Marko Mikulicic 0:c0ecb8bf28eb 4616 v7_val_t args, v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 4617
Marko Mikulicic 0:c0ecb8bf28eb 4618 #endif /* CS_V7_SRC_EXEC_PUBLIC_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 4619 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 4620 #line 1 "v7/src/exec.h"
Marko Mikulicic 0:c0ecb8bf28eb 4621 #endif
Marko Mikulicic 0:c0ecb8bf28eb 4622 /*
Marko Mikulicic 0:c0ecb8bf28eb 4623 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 4624 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 4625 */
Marko Mikulicic 0:c0ecb8bf28eb 4626
Marko Mikulicic 0:c0ecb8bf28eb 4627 #ifndef CS_V7_SRC_EXEC_H_
Marko Mikulicic 0:c0ecb8bf28eb 4628 #define CS_V7_SRC_EXEC_H_
Marko Mikulicic 0:c0ecb8bf28eb 4629
Marko Mikulicic 0:c0ecb8bf28eb 4630 /* Amalgamated: #include "v7/src/exec_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4631
Marko Mikulicic 0:c0ecb8bf28eb 4632 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4633
Marko Mikulicic 0:c0ecb8bf28eb 4634 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 4635
Marko Mikulicic 0:c0ecb8bf28eb 4636 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4637 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 4638 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4639
Marko Mikulicic 0:c0ecb8bf28eb 4640 /*
Marko Mikulicic 0:c0ecb8bf28eb 4641 * At the moment, all exec-related functions are public, and are declared in
Marko Mikulicic 0:c0ecb8bf28eb 4642 * `exec_public.h`
Marko Mikulicic 0:c0ecb8bf28eb 4643 */
Marko Mikulicic 0:c0ecb8bf28eb 4644
Marko Mikulicic 0:c0ecb8bf28eb 4645 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4646 enum v7_err _v7_compile(const char *js_code, size_t js_code_size,
Marko Mikulicic 0:c0ecb8bf28eb 4647 int generate_binary_output, int use_bcode, FILE *fp);
Marko Mikulicic 0:c0ecb8bf28eb 4648
Marko Mikulicic 0:c0ecb8bf28eb 4649 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4650 }
Marko Mikulicic 0:c0ecb8bf28eb 4651 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4652
Marko Mikulicic 0:c0ecb8bf28eb 4653 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 4654
Marko Mikulicic 0:c0ecb8bf28eb 4655 #endif /* CS_V7_SRC_EXEC_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 4656 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 4657 #line 1 "v7/src/array_public.h"
Marko Mikulicic 0:c0ecb8bf28eb 4658 #endif
Marko Mikulicic 0:c0ecb8bf28eb 4659 /*
Marko Mikulicic 0:c0ecb8bf28eb 4660 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 4661 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 4662 */
Marko Mikulicic 0:c0ecb8bf28eb 4663
Marko Mikulicic 0:c0ecb8bf28eb 4664 /*
Marko Mikulicic 0:c0ecb8bf28eb 4665 * === Arrays
Marko Mikulicic 0:c0ecb8bf28eb 4666 */
Marko Mikulicic 0:c0ecb8bf28eb 4667
Marko Mikulicic 0:c0ecb8bf28eb 4668 #ifndef CS_V7_SRC_ARRAY_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 4669 #define CS_V7_SRC_ARRAY_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 4670
Marko Mikulicic 0:c0ecb8bf28eb 4671 /* Amalgamated: #include "v7/src/core_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4672
Marko Mikulicic 0:c0ecb8bf28eb 4673 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4674 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 4675 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4676
Marko Mikulicic 0:c0ecb8bf28eb 4677 /* Make an empty array object */
Marko Mikulicic 0:c0ecb8bf28eb 4678 v7_val_t v7_mk_array(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 4679
Marko Mikulicic 0:c0ecb8bf28eb 4680 /* Returns true if given value is an array object */
Marko Mikulicic 0:c0ecb8bf28eb 4681 int v7_is_array(struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 4682
Marko Mikulicic 0:c0ecb8bf28eb 4683 /* Returns length on an array. If `arr` is not an array, 0 is returned. */
Marko Mikulicic 0:c0ecb8bf28eb 4684 unsigned long v7_array_length(struct v7 *v7, v7_val_t arr);
Marko Mikulicic 0:c0ecb8bf28eb 4685
Marko Mikulicic 0:c0ecb8bf28eb 4686 /* Insert value `v` in array `arr` at the end of the array. */
Marko Mikulicic 0:c0ecb8bf28eb 4687 int v7_array_push(struct v7 *, v7_val_t arr, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 4688
Marko Mikulicic 0:c0ecb8bf28eb 4689 /*
Marko Mikulicic 0:c0ecb8bf28eb 4690 * Like `v7_array_push()`, but "returns" value through the `res` pointer
Marko Mikulicic 0:c0ecb8bf28eb 4691 * argument. `res` is allowed to be `NULL`.
Marko Mikulicic 0:c0ecb8bf28eb 4692 *
Marko Mikulicic 0:c0ecb8bf28eb 4693 * Caller should check the error code returned, and if it's something other
Marko Mikulicic 0:c0ecb8bf28eb 4694 * than `V7_OK`, perform cleanup and return this code further.
Marko Mikulicic 0:c0ecb8bf28eb 4695 */
Marko Mikulicic 0:c0ecb8bf28eb 4696 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4697 enum v7_err v7_array_push_throwing(struct v7 *v7, v7_val_t arr, v7_val_t v,
Marko Mikulicic 0:c0ecb8bf28eb 4698 int *res);
Marko Mikulicic 0:c0ecb8bf28eb 4699
Marko Mikulicic 0:c0ecb8bf28eb 4700 /*
Marko Mikulicic 0:c0ecb8bf28eb 4701 * Return array member at index `index`. If `index` is out of bounds, undefined
Marko Mikulicic 0:c0ecb8bf28eb 4702 * is returned.
Marko Mikulicic 0:c0ecb8bf28eb 4703 */
Marko Mikulicic 0:c0ecb8bf28eb 4704 v7_val_t v7_array_get(struct v7 *, v7_val_t arr, unsigned long index);
Marko Mikulicic 0:c0ecb8bf28eb 4705
Marko Mikulicic 0:c0ecb8bf28eb 4706 /* Insert value `v` into `arr` at index `index`. */
Marko Mikulicic 0:c0ecb8bf28eb 4707 int v7_array_set(struct v7 *v7, v7_val_t arr, unsigned long index, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 4708
Marko Mikulicic 0:c0ecb8bf28eb 4709 /*
Marko Mikulicic 0:c0ecb8bf28eb 4710 * Like `v7_array_set()`, but "returns" value through the `res` pointer
Marko Mikulicic 0:c0ecb8bf28eb 4711 * argument. `res` is allowed to be `NULL`.
Marko Mikulicic 0:c0ecb8bf28eb 4712 *
Marko Mikulicic 0:c0ecb8bf28eb 4713 * Caller should check the error code returned, and if it's something other
Marko Mikulicic 0:c0ecb8bf28eb 4714 * than `V7_OK`, perform cleanup and return this code further.
Marko Mikulicic 0:c0ecb8bf28eb 4715 */
Marko Mikulicic 0:c0ecb8bf28eb 4716 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4717 enum v7_err v7_array_set_throwing(struct v7 *v7, v7_val_t arr,
Marko Mikulicic 0:c0ecb8bf28eb 4718 unsigned long index, v7_val_t v, int *res);
Marko Mikulicic 0:c0ecb8bf28eb 4719
Marko Mikulicic 0:c0ecb8bf28eb 4720 /* Delete value in array `arr` at index `index`, if it exists. */
Marko Mikulicic 0:c0ecb8bf28eb 4721 void v7_array_del(struct v7 *v7, v7_val_t arr, unsigned long index);
Marko Mikulicic 0:c0ecb8bf28eb 4722
Marko Mikulicic 0:c0ecb8bf28eb 4723 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4724 }
Marko Mikulicic 0:c0ecb8bf28eb 4725 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4726
Marko Mikulicic 0:c0ecb8bf28eb 4727 #endif /* CS_V7_SRC_ARRAY_PUBLIC_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 4728 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 4729 #line 1 "v7/src/array.h"
Marko Mikulicic 0:c0ecb8bf28eb 4730 #endif
Marko Mikulicic 0:c0ecb8bf28eb 4731 /*
Marko Mikulicic 0:c0ecb8bf28eb 4732 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 4733 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 4734 */
Marko Mikulicic 0:c0ecb8bf28eb 4735
Marko Mikulicic 0:c0ecb8bf28eb 4736 #ifndef CS_V7_SRC_ARRAY_H_
Marko Mikulicic 0:c0ecb8bf28eb 4737 #define CS_V7_SRC_ARRAY_H_
Marko Mikulicic 0:c0ecb8bf28eb 4738
Marko Mikulicic 0:c0ecb8bf28eb 4739 /* Amalgamated: #include "v7/src/array_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4740
Marko Mikulicic 0:c0ecb8bf28eb 4741 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4742
Marko Mikulicic 0:c0ecb8bf28eb 4743 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4744 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 4745 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4746
Marko Mikulicic 0:c0ecb8bf28eb 4747 V7_PRIVATE v7_val_t v7_mk_dense_array(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 4748 V7_PRIVATE val_t
Marko Mikulicic 0:c0ecb8bf28eb 4749 v7_array_get2(struct v7 *v7, v7_val_t arr, unsigned long index, int *has);
Marko Mikulicic 0:c0ecb8bf28eb 4750
Marko Mikulicic 0:c0ecb8bf28eb 4751 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4752 }
Marko Mikulicic 0:c0ecb8bf28eb 4753 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4754
Marko Mikulicic 0:c0ecb8bf28eb 4755 #endif /* CS_V7_SRC_ARRAY_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 4756 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 4757 #line 1 "v7/src/conversion_public.h"
Marko Mikulicic 0:c0ecb8bf28eb 4758 #endif
Marko Mikulicic 0:c0ecb8bf28eb 4759 /*
Marko Mikulicic 0:c0ecb8bf28eb 4760 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 4761 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 4762 */
Marko Mikulicic 0:c0ecb8bf28eb 4763
Marko Mikulicic 0:c0ecb8bf28eb 4764 /*
Marko Mikulicic 0:c0ecb8bf28eb 4765 * === Conversion
Marko Mikulicic 0:c0ecb8bf28eb 4766 */
Marko Mikulicic 0:c0ecb8bf28eb 4767
Marko Mikulicic 0:c0ecb8bf28eb 4768 #ifndef CS_V7_SRC_CONVERSION_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 4769 #define CS_V7_SRC_CONVERSION_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 4770
Marko Mikulicic 0:c0ecb8bf28eb 4771 /* Amalgamated: #include "v7/src/core_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4772
Marko Mikulicic 0:c0ecb8bf28eb 4773 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4774 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 4775 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4776
Marko Mikulicic 0:c0ecb8bf28eb 4777 /* Stringify mode, see `v7_stringify()` and `v7_stringify_throwing()` */
Marko Mikulicic 0:c0ecb8bf28eb 4778 enum v7_stringify_mode {
Marko Mikulicic 0:c0ecb8bf28eb 4779 V7_STRINGIFY_DEFAULT,
Marko Mikulicic 0:c0ecb8bf28eb 4780 V7_STRINGIFY_JSON,
Marko Mikulicic 0:c0ecb8bf28eb 4781 V7_STRINGIFY_DEBUG,
Marko Mikulicic 0:c0ecb8bf28eb 4782 };
Marko Mikulicic 0:c0ecb8bf28eb 4783
Marko Mikulicic 0:c0ecb8bf28eb 4784 /*
Marko Mikulicic 0:c0ecb8bf28eb 4785 * Generate string representation of the JavaScript value `val` into a buffer
Marko Mikulicic 0:c0ecb8bf28eb 4786 * `buf`, `len`. If `len` is too small to hold a generated string,
Marko Mikulicic 0:c0ecb8bf28eb 4787 * `v7_stringify()` allocates required memory. In that case, it is caller's
Marko Mikulicic 0:c0ecb8bf28eb 4788 * responsibility to free the allocated buffer. Generated string is guaranteed
Marko Mikulicic 0:c0ecb8bf28eb 4789 * to be 0-terminated.
Marko Mikulicic 0:c0ecb8bf28eb 4790 *
Marko Mikulicic 0:c0ecb8bf28eb 4791 * Available stringification modes are:
Marko Mikulicic 0:c0ecb8bf28eb 4792 *
Marko Mikulicic 0:c0ecb8bf28eb 4793 * - `V7_STRINGIFY_DEFAULT`:
Marko Mikulicic 0:c0ecb8bf28eb 4794 * Convert JS value to string, using common JavaScript semantics:
Marko Mikulicic 0:c0ecb8bf28eb 4795 * - If value is an object:
Marko Mikulicic 0:c0ecb8bf28eb 4796 * - call `toString()`;
Marko Mikulicic 0:c0ecb8bf28eb 4797 * - If `toString()` returned non-primitive value, call `valueOf()`;
Marko Mikulicic 0:c0ecb8bf28eb 4798 * - If `valueOf()` returned non-primitive value, throw `TypeError`.
Marko Mikulicic 0:c0ecb8bf28eb 4799 * - Now we have a primitive, and if it's not a string, then stringify it.
Marko Mikulicic 0:c0ecb8bf28eb 4800 *
Marko Mikulicic 0:c0ecb8bf28eb 4801 * - `V7_STRINGIFY_JSON`:
Marko Mikulicic 0:c0ecb8bf28eb 4802 * Generate JSON output
Marko Mikulicic 0:c0ecb8bf28eb 4803 *
Marko Mikulicic 0:c0ecb8bf28eb 4804 * - `V7_STRINGIFY_DEBUG`:
Marko Mikulicic 0:c0ecb8bf28eb 4805 * Mostly like JSON, but will not omit non-JSON objects like functions.
Marko Mikulicic 0:c0ecb8bf28eb 4806 *
Marko Mikulicic 0:c0ecb8bf28eb 4807 * Example code:
Marko Mikulicic 0:c0ecb8bf28eb 4808 *
Marko Mikulicic 0:c0ecb8bf28eb 4809 * char buf[100], *p;
Marko Mikulicic 0:c0ecb8bf28eb 4810 * p = v7_stringify(v7, obj, buf, sizeof(buf), V7_STRINGIFY_DEFAULT);
Marko Mikulicic 0:c0ecb8bf28eb 4811 * printf("JSON string: [%s]\n", p);
Marko Mikulicic 0:c0ecb8bf28eb 4812 * if (p != buf) {
Marko Mikulicic 0:c0ecb8bf28eb 4813 * free(p);
Marko Mikulicic 0:c0ecb8bf28eb 4814 * }
Marko Mikulicic 0:c0ecb8bf28eb 4815 */
Marko Mikulicic 0:c0ecb8bf28eb 4816 char *v7_stringify(struct v7 *v7, v7_val_t v, char *buf, size_t len,
Marko Mikulicic 0:c0ecb8bf28eb 4817 enum v7_stringify_mode mode);
Marko Mikulicic 0:c0ecb8bf28eb 4818
Marko Mikulicic 0:c0ecb8bf28eb 4819 /*
Marko Mikulicic 0:c0ecb8bf28eb 4820 * Like `v7_stringify()`, but "returns" value through the `res` pointer
Marko Mikulicic 0:c0ecb8bf28eb 4821 * argument. `res` must not be `NULL`.
Marko Mikulicic 0:c0ecb8bf28eb 4822 *
Marko Mikulicic 0:c0ecb8bf28eb 4823 * Caller should check the error code returned, and if it's something other
Marko Mikulicic 0:c0ecb8bf28eb 4824 * than `V7_OK`, perform cleanup and return this code further.
Marko Mikulicic 0:c0ecb8bf28eb 4825 */
Marko Mikulicic 0:c0ecb8bf28eb 4826 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4827 enum v7_err v7_stringify_throwing(struct v7 *v7, v7_val_t v, char *buf,
Marko Mikulicic 0:c0ecb8bf28eb 4828 size_t size, enum v7_stringify_mode mode,
Marko Mikulicic 0:c0ecb8bf28eb 4829 char **res);
Marko Mikulicic 0:c0ecb8bf28eb 4830
Marko Mikulicic 0:c0ecb8bf28eb 4831 /*
Marko Mikulicic 0:c0ecb8bf28eb 4832 * A shortcut for `v7_stringify()` with `V7_STRINGIFY_JSON`
Marko Mikulicic 0:c0ecb8bf28eb 4833 */
Marko Mikulicic 0:c0ecb8bf28eb 4834 #define v7_to_json(a, b, c, d) v7_stringify(a, b, c, d, V7_STRINGIFY_JSON)
Marko Mikulicic 0:c0ecb8bf28eb 4835
Marko Mikulicic 0:c0ecb8bf28eb 4836 /* Returns true if given value evaluates to true, as in `if (v)` statement. */
Marko Mikulicic 0:c0ecb8bf28eb 4837 int v7_is_truthy(struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 4838
Marko Mikulicic 0:c0ecb8bf28eb 4839 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4840 }
Marko Mikulicic 0:c0ecb8bf28eb 4841 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4842
Marko Mikulicic 0:c0ecb8bf28eb 4843 #endif /* CS_V7_SRC_CONVERSION_PUBLIC_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 4844 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 4845 #line 1 "v7/src/conversion.h"
Marko Mikulicic 0:c0ecb8bf28eb 4846 #endif
Marko Mikulicic 0:c0ecb8bf28eb 4847 /*
Marko Mikulicic 0:c0ecb8bf28eb 4848 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 4849 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 4850 */
Marko Mikulicic 0:c0ecb8bf28eb 4851
Marko Mikulicic 0:c0ecb8bf28eb 4852 #ifndef CS_V7_SRC_CONVERSION_H_
Marko Mikulicic 0:c0ecb8bf28eb 4853 #define CS_V7_SRC_CONVERSION_H_
Marko Mikulicic 0:c0ecb8bf28eb 4854
Marko Mikulicic 0:c0ecb8bf28eb 4855 /* Amalgamated: #include "v7/src/conversion_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4856
Marko Mikulicic 0:c0ecb8bf28eb 4857 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 4858
Marko Mikulicic 0:c0ecb8bf28eb 4859 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 4860 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 4861 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 4862
Marko Mikulicic 0:c0ecb8bf28eb 4863 /*
Marko Mikulicic 0:c0ecb8bf28eb 4864 * Conversion API
Marko Mikulicic 0:c0ecb8bf28eb 4865 * ==============
Marko Mikulicic 0:c0ecb8bf28eb 4866 *
Marko Mikulicic 0:c0ecb8bf28eb 4867 * - If you need to convert any JS value to string using common JavaScript
Marko Mikulicic 0:c0ecb8bf28eb 4868 * semantics, use `to_string()`, which can convert to both `v7_val_t` or your
Marko Mikulicic 0:c0ecb8bf28eb 4869 * C buffer.
Marko Mikulicic 0:c0ecb8bf28eb 4870 *
Marko Mikulicic 0:c0ecb8bf28eb 4871 * - If you need to convert any JS value to number using common JavaScript
Marko Mikulicic 0:c0ecb8bf28eb 4872 * semantics, use `to_number_v()`;
Marko Mikulicic 0:c0ecb8bf28eb 4873 *
Marko Mikulicic 0:c0ecb8bf28eb 4874 * - If you need to convert any JS value to primitive, without forcing it to
Marko Mikulicic 0:c0ecb8bf28eb 4875 * string or number, use `to_primitive()` (see comments for this function for
Marko Mikulicic 0:c0ecb8bf28eb 4876 * details);
Marko Mikulicic 0:c0ecb8bf28eb 4877 *
Marko Mikulicic 0:c0ecb8bf28eb 4878 * - If you have a primitive value, and you want to convert it to either string
Marko Mikulicic 0:c0ecb8bf28eb 4879 * or number, you can still use functions above: `to_string()` and
Marko Mikulicic 0:c0ecb8bf28eb 4880 * `to_number_v()`. But if you want to save a bit of work, use:
Marko Mikulicic 0:c0ecb8bf28eb 4881 * - `primitive_to_str()`
Marko Mikulicic 0:c0ecb8bf28eb 4882 * - `primitive_to_number()`
Marko Mikulicic 0:c0ecb8bf28eb 4883 *
Marko Mikulicic 0:c0ecb8bf28eb 4884 * In fact, these are a bit lower level functions, which are used by
Marko Mikulicic 0:c0ecb8bf28eb 4885 * `to_string()` and `to_number_v()` after converting value to
Marko Mikulicic 0:c0ecb8bf28eb 4886 * primitive.
Marko Mikulicic 0:c0ecb8bf28eb 4887 *
Marko Mikulicic 0:c0ecb8bf28eb 4888 * - If you want to call `valueOf()` on the object, use `obj_value_of()`;
Marko Mikulicic 0:c0ecb8bf28eb 4889 * - If you want to call `toString()` on the object, use `obj_to_string()`;
Marko Mikulicic 0:c0ecb8bf28eb 4890 *
Marko Mikulicic 0:c0ecb8bf28eb 4891 * - If you need to convert any JS value to boolean using common JavaScript
Marko Mikulicic 0:c0ecb8bf28eb 4892 * semantics (as in the expression `if (v)` or `Boolean(v)`), use
Marko Mikulicic 0:c0ecb8bf28eb 4893 * `to_boolean_v()`.
Marko Mikulicic 0:c0ecb8bf28eb 4894 *
Marko Mikulicic 0:c0ecb8bf28eb 4895 * - If you want to get the JSON representation of a value, use
Marko Mikulicic 0:c0ecb8bf28eb 4896 * `to_json_or_debug()`, passing `0` as `is_debug` : writes data to your C
Marko Mikulicic 0:c0ecb8bf28eb 4897 * buffer;
Marko Mikulicic 0:c0ecb8bf28eb 4898 *
Marko Mikulicic 0:c0ecb8bf28eb 4899 * - There is one more kind of representation: `DEBUG`. It's very similar to
Marko Mikulicic 0:c0ecb8bf28eb 4900 * JSON, but it will not omit non-JSON values, such as functions. Again, use
Marko Mikulicic 0:c0ecb8bf28eb 4901 * `to_json_or_debug()`, but pass `1` as `is_debug` this time: writes data to
Marko Mikulicic 0:c0ecb8bf28eb 4902 * your C buffer;
Marko Mikulicic 0:c0ecb8bf28eb 4903 *
Marko Mikulicic 0:c0ecb8bf28eb 4904 * Additionally, for any kind of to-string conversion into C buffer, you can
Marko Mikulicic 0:c0ecb8bf28eb 4905 * use a convenience wrapper function (mostly for public API), which can
Marko Mikulicic 0:c0ecb8bf28eb 4906 * allocate the buffer for you:
Marko Mikulicic 0:c0ecb8bf28eb 4907 *
Marko Mikulicic 0:c0ecb8bf28eb 4908 * - `v7_stringify_throwing()`;
Marko Mikulicic 0:c0ecb8bf28eb 4909 * - `v7_stringify()` : the same as above, but doesn't throw.
Marko Mikulicic 0:c0ecb8bf28eb 4910 *
Marko Mikulicic 0:c0ecb8bf28eb 4911 * There are a couple of more specific conversions, which I'd like to probably
Marko Mikulicic 0:c0ecb8bf28eb 4912 * refactor or remove in the future:
Marko Mikulicic 0:c0ecb8bf28eb 4913 *
Marko Mikulicic 0:c0ecb8bf28eb 4914 * - `to_long()` : if given value is `undefined`, returns provided default
Marko Mikulicic 0:c0ecb8bf28eb 4915 * value; otherwise, converts value to number, and then truncates to `long`.
Marko Mikulicic 0:c0ecb8bf28eb 4916 * - `str_to_ulong()` : converts the value to string, and tries to parse it as
Marko Mikulicic 0:c0ecb8bf28eb 4917 * an integer. Use it if only you need strong conformity ov the value to an
Marko Mikulicic 0:c0ecb8bf28eb 4918 * integer (currently, it's used only when examining keys of array object)
Marko Mikulicic 0:c0ecb8bf28eb 4919 *
Marko Mikulicic 0:c0ecb8bf28eb 4920 * ----------------------------------------------------------------------------
Marko Mikulicic 0:c0ecb8bf28eb 4921 *
Marko Mikulicic 0:c0ecb8bf28eb 4922 * TODO(dfrank):
Marko Mikulicic 0:c0ecb8bf28eb 4923 * - Rename functions like `v7_get_double(v7, )`, `get_object_struct()` to
Marko Mikulicic 0:c0ecb8bf28eb 4924 *something
Marko Mikulicic 0:c0ecb8bf28eb 4925 * that will clearly identify that they convert to some C entity, not
Marko Mikulicic 0:c0ecb8bf28eb 4926 * `v7_val_t`
Marko Mikulicic 0:c0ecb8bf28eb 4927 * - Maybe make `to_string()` private? But then, there will be no way
Marko Mikulicic 0:c0ecb8bf28eb 4928 * in public API to convert value to `v7_val_t` string, so, for now
Marko Mikulicic 0:c0ecb8bf28eb 4929 * it's here.
Marko Mikulicic 0:c0ecb8bf28eb 4930 * - When we agree on what goes to public API, and what does not, write
Marko Mikulicic 0:c0ecb8bf28eb 4931 * similar conversion guide for public API (in `conversion_public.h`)
Marko Mikulicic 0:c0ecb8bf28eb 4932 */
Marko Mikulicic 0:c0ecb8bf28eb 4933
Marko Mikulicic 0:c0ecb8bf28eb 4934 /*
Marko Mikulicic 0:c0ecb8bf28eb 4935 * Convert any JS value to number, using common JavaScript semantics:
Marko Mikulicic 0:c0ecb8bf28eb 4936 *
Marko Mikulicic 0:c0ecb8bf28eb 4937 * - If value is an object:
Marko Mikulicic 0:c0ecb8bf28eb 4938 * - call `valueOf()`;
Marko Mikulicic 0:c0ecb8bf28eb 4939 * - If `valueOf()` returned non-primitive value, call `toString()`;
Marko Mikulicic 0:c0ecb8bf28eb 4940 * - If `toString()` returned non-primitive value, throw `TypeError`.
Marko Mikulicic 0:c0ecb8bf28eb 4941 * - Now we have a primitive, and if it's not a number, then:
Marko Mikulicic 0:c0ecb8bf28eb 4942 * - If `undefined`, return `NaN`
Marko Mikulicic 0:c0ecb8bf28eb 4943 * - If `null`, return 0.0
Marko Mikulicic 0:c0ecb8bf28eb 4944 * - If boolean, return either 1 or 0
Marko Mikulicic 0:c0ecb8bf28eb 4945 * - If string, try to parse it.
Marko Mikulicic 0:c0ecb8bf28eb 4946 */
Marko Mikulicic 0:c0ecb8bf28eb 4947 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4948 V7_PRIVATE enum v7_err to_number_v(struct v7 *v7, v7_val_t v, v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 4949
Marko Mikulicic 0:c0ecb8bf28eb 4950 /*
Marko Mikulicic 0:c0ecb8bf28eb 4951 * Convert any JS value to string, using common JavaScript semantics,
Marko Mikulicic 0:c0ecb8bf28eb 4952 * see `v7_stringify()` and `V7_STRINGIFY_DEFAULT`.
Marko Mikulicic 0:c0ecb8bf28eb 4953 *
Marko Mikulicic 0:c0ecb8bf28eb 4954 * This function can return multiple things:
Marko Mikulicic 0:c0ecb8bf28eb 4955 *
Marko Mikulicic 0:c0ecb8bf28eb 4956 * - String as a `v7_val_t` (if `res` is not `NULL`)
Marko Mikulicic 0:c0ecb8bf28eb 4957 * - String copied to buffer `buf` with max size `buf_size` (if `buf` is not
Marko Mikulicic 0:c0ecb8bf28eb 4958 * `NULL`)
Marko Mikulicic 0:c0ecb8bf28eb 4959 * - Length of actual string, independently of `buf_size` (if `res_len` is not
Marko Mikulicic 0:c0ecb8bf28eb 4960 * `NULL`)
Marko Mikulicic 0:c0ecb8bf28eb 4961 *
Marko Mikulicic 0:c0ecb8bf28eb 4962 * The rationale of having multiple formats of returned value is the following:
Marko Mikulicic 0:c0ecb8bf28eb 4963 *
Marko Mikulicic 0:c0ecb8bf28eb 4964 * Initially, to-string conversion always returned `v7_val_t`. But it turned
Marko Mikulicic 0:c0ecb8bf28eb 4965 * out that there are situations where such an approach adds useless pressure
Marko Mikulicic 0:c0ecb8bf28eb 4966 * on GC: e.g. when converting `undefined` to string, and the caller actually
Marko Mikulicic 0:c0ecb8bf28eb 4967 * needs a C buffer, not a `v7_val_t`.
Marko Mikulicic 0:c0ecb8bf28eb 4968 *
Marko Mikulicic 0:c0ecb8bf28eb 4969 * Always returning string through `buf`+`buf_size` is bad as well: if we
Marko Mikulicic 0:c0ecb8bf28eb 4970 * convert from object to string, and either `toString()` or `valueOf()`
Marko Mikulicic 0:c0ecb8bf28eb 4971 * returned string, then we'd have to get string data from it, write to buffer,
Marko Mikulicic 0:c0ecb8bf28eb 4972 * and if caller actually need `v7_val_t`, then it will have to create new
Marko Mikulicic 0:c0ecb8bf28eb 4973 * instance of the same string: again, useless GC pressure.
Marko Mikulicic 0:c0ecb8bf28eb 4974 *
Marko Mikulicic 0:c0ecb8bf28eb 4975 * So, we have to use the combined approach. This function will make minimal
Marko Mikulicic 0:c0ecb8bf28eb 4976 * work depending on give `res` and `buf`.
Marko Mikulicic 0:c0ecb8bf28eb 4977 */
Marko Mikulicic 0:c0ecb8bf28eb 4978 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 4979 V7_PRIVATE enum v7_err to_string(struct v7 *v7, v7_val_t v, v7_val_t *res,
Marko Mikulicic 0:c0ecb8bf28eb 4980 char *buf, size_t buf_size, size_t *res_len);
Marko Mikulicic 0:c0ecb8bf28eb 4981
Marko Mikulicic 0:c0ecb8bf28eb 4982 /*
Marko Mikulicic 0:c0ecb8bf28eb 4983 * Convert value to primitive, if it's not already.
Marko Mikulicic 0:c0ecb8bf28eb 4984 *
Marko Mikulicic 0:c0ecb8bf28eb 4985 * For object-to-primitive conversion, each object in JavaScript has two
Marko Mikulicic 0:c0ecb8bf28eb 4986 * methods: `toString()` and `valueOf()`.
Marko Mikulicic 0:c0ecb8bf28eb 4987 *
Marko Mikulicic 0:c0ecb8bf28eb 4988 * When converting object to string, JavaScript does the following:
Marko Mikulicic 0:c0ecb8bf28eb 4989 * - call `toString()`;
Marko Mikulicic 0:c0ecb8bf28eb 4990 * - If `toString()` returned non-primitive value, call `valueOf()`;
Marko Mikulicic 0:c0ecb8bf28eb 4991 * - If `valueOf()` returned non-primitive value, throw `TypeError`.
Marko Mikulicic 0:c0ecb8bf28eb 4992 *
Marko Mikulicic 0:c0ecb8bf28eb 4993 * When converting object to number, JavaScript calls the same functions,
Marko Mikulicic 0:c0ecb8bf28eb 4994 * but in reverse:
Marko Mikulicic 0:c0ecb8bf28eb 4995 * - call `valueOf()`;
Marko Mikulicic 0:c0ecb8bf28eb 4996 * - If `valueOf()` returned non-primitive value, call `toString()`;
Marko Mikulicic 0:c0ecb8bf28eb 4997 * - If `toString()` returned non-primitive value, throw `TypeError`.
Marko Mikulicic 0:c0ecb8bf28eb 4998 *
Marko Mikulicic 0:c0ecb8bf28eb 4999 * This function `to_primitive()` performs either type of conversion,
Marko Mikulicic 0:c0ecb8bf28eb 5000 * depending on the `hint` argument (see `enum to_primitive_hint`).
Marko Mikulicic 0:c0ecb8bf28eb 5001 */
Marko Mikulicic 0:c0ecb8bf28eb 5002 enum to_primitive_hint {
Marko Mikulicic 0:c0ecb8bf28eb 5003 /* Call `valueOf()` first, then `toString()` if needed */
Marko Mikulicic 0:c0ecb8bf28eb 5004 V7_TO_PRIMITIVE_HINT_NUMBER,
Marko Mikulicic 0:c0ecb8bf28eb 5005
Marko Mikulicic 0:c0ecb8bf28eb 5006 /* Call `toString()` first, then `valueOf()` if needed */
Marko Mikulicic 0:c0ecb8bf28eb 5007 V7_TO_PRIMITIVE_HINT_STRING,
Marko Mikulicic 0:c0ecb8bf28eb 5008
Marko Mikulicic 0:c0ecb8bf28eb 5009 /* STRING for Date, NUMBER for everything else */
Marko Mikulicic 0:c0ecb8bf28eb 5010 V7_TO_PRIMITIVE_HINT_AUTO,
Marko Mikulicic 0:c0ecb8bf28eb 5011 };
Marko Mikulicic 0:c0ecb8bf28eb 5012 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 5013 enum v7_err to_primitive(struct v7 *v7, v7_val_t v, enum to_primitive_hint hint,
Marko Mikulicic 0:c0ecb8bf28eb 5014 v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 5015
Marko Mikulicic 0:c0ecb8bf28eb 5016 /*
Marko Mikulicic 0:c0ecb8bf28eb 5017 * Convert primitive value to string, using common JavaScript semantics. If
Marko Mikulicic 0:c0ecb8bf28eb 5018 * you need to convert any value to string (either object or primitive),
Marko Mikulicic 0:c0ecb8bf28eb 5019 * see `to_string()` or `v7_stringify_throwing()`.
Marko Mikulicic 0:c0ecb8bf28eb 5020 *
Marko Mikulicic 0:c0ecb8bf28eb 5021 * This function can return multiple things:
Marko Mikulicic 0:c0ecb8bf28eb 5022 *
Marko Mikulicic 0:c0ecb8bf28eb 5023 * - String as a `v7_val_t` (if `res` is not `NULL`)
Marko Mikulicic 0:c0ecb8bf28eb 5024 * - String copied to buffer `buf` with max size `buf_size` (if `buf` is not
Marko Mikulicic 0:c0ecb8bf28eb 5025 * `NULL`)
Marko Mikulicic 0:c0ecb8bf28eb 5026 * - Length of actual string, independently of `buf_size` (if `res_len` is not
Marko Mikulicic 0:c0ecb8bf28eb 5027 * `NULL`)
Marko Mikulicic 0:c0ecb8bf28eb 5028 */
Marko Mikulicic 0:c0ecb8bf28eb 5029 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 5030 V7_PRIVATE enum v7_err primitive_to_str(struct v7 *v7, val_t v, val_t *res,
Marko Mikulicic 0:c0ecb8bf28eb 5031 char *buf, size_t buf_size,
Marko Mikulicic 0:c0ecb8bf28eb 5032 size_t *res_len);
Marko Mikulicic 0:c0ecb8bf28eb 5033
Marko Mikulicic 0:c0ecb8bf28eb 5034 /*
Marko Mikulicic 0:c0ecb8bf28eb 5035 * Convert primitive value to number, using common JavaScript semantics. If you
Marko Mikulicic 0:c0ecb8bf28eb 5036 * need to convert any value to number (either object or primitive), see
Marko Mikulicic 0:c0ecb8bf28eb 5037 * `to_number_v()`
Marko Mikulicic 0:c0ecb8bf28eb 5038 */
Marko Mikulicic 0:c0ecb8bf28eb 5039 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 5040 V7_PRIVATE enum v7_err primitive_to_number(struct v7 *v7, val_t v, val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 5041
Marko Mikulicic 0:c0ecb8bf28eb 5042 /*
Marko Mikulicic 0:c0ecb8bf28eb 5043 * Convert value to JSON or "debug" representation, depending on whether
Marko Mikulicic 0:c0ecb8bf28eb 5044 * `is_debug` is non-zero. The "debug" is the same as JSON, but non-JSON values
Marko Mikulicic 0:c0ecb8bf28eb 5045 * (functions, `undefined`, etc) will not be omitted.
Marko Mikulicic 0:c0ecb8bf28eb 5046 *
Marko Mikulicic 0:c0ecb8bf28eb 5047 * See also `v7_stringify()`, `v7_stringify_throwing()`.
Marko Mikulicic 0:c0ecb8bf28eb 5048 */
Marko Mikulicic 0:c0ecb8bf28eb 5049 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 5050 V7_PRIVATE enum v7_err to_json_or_debug(struct v7 *v7, val_t v, char *buf,
Marko Mikulicic 0:c0ecb8bf28eb 5051 size_t size, size_t *res_len,
Marko Mikulicic 0:c0ecb8bf28eb 5052 uint8_t is_debug);
Marko Mikulicic 0:c0ecb8bf28eb 5053
Marko Mikulicic 0:c0ecb8bf28eb 5054 /*
Marko Mikulicic 0:c0ecb8bf28eb 5055 * Calls `valueOf()` on given object `v`
Marko Mikulicic 0:c0ecb8bf28eb 5056 */
Marko Mikulicic 0:c0ecb8bf28eb 5057 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 5058 V7_PRIVATE enum v7_err obj_value_of(struct v7 *v7, val_t v, val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 5059
Marko Mikulicic 0:c0ecb8bf28eb 5060 /*
Marko Mikulicic 0:c0ecb8bf28eb 5061 * Calls `toString()` on given object `v`
Marko Mikulicic 0:c0ecb8bf28eb 5062 */
Marko Mikulicic 0:c0ecb8bf28eb 5063 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 5064 V7_PRIVATE enum v7_err obj_to_string(struct v7 *v7, val_t v, val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 5065
Marko Mikulicic 0:c0ecb8bf28eb 5066 /*
Marko Mikulicic 0:c0ecb8bf28eb 5067 * If given value is `undefined`, returns `default_value`; otherwise,
Marko Mikulicic 0:c0ecb8bf28eb 5068 * converts value to number, and then truncates to `long`.
Marko Mikulicic 0:c0ecb8bf28eb 5069 */
Marko Mikulicic 0:c0ecb8bf28eb 5070 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 5071 V7_PRIVATE enum v7_err to_long(struct v7 *v7, val_t v, long default_value,
Marko Mikulicic 0:c0ecb8bf28eb 5072 long *res);
Marko Mikulicic 0:c0ecb8bf28eb 5073
Marko Mikulicic 0:c0ecb8bf28eb 5074 /*
Marko Mikulicic 0:c0ecb8bf28eb 5075 * Converts value to boolean as in the expression `if (v)` or `Boolean(v)`.
Marko Mikulicic 0:c0ecb8bf28eb 5076 *
Marko Mikulicic 0:c0ecb8bf28eb 5077 * NOTE: it can't throw (even if the given value is an object with `valueOf()`
Marko Mikulicic 0:c0ecb8bf28eb 5078 * that throws), so it returns `val_t` directly.
Marko Mikulicic 0:c0ecb8bf28eb 5079 */
Marko Mikulicic 0:c0ecb8bf28eb 5080 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 5081 V7_PRIVATE val_t to_boolean_v(struct v7 *v7, val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 5082
Marko Mikulicic 0:c0ecb8bf28eb 5083 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 5084 }
Marko Mikulicic 0:c0ecb8bf28eb 5085 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 5086
Marko Mikulicic 0:c0ecb8bf28eb 5087 #endif /* CS_V7_SRC_CONVERSION_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 5088 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 5089 #line 1 "v7/src/varint.h"
Marko Mikulicic 0:c0ecb8bf28eb 5090 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5091 /*
Marko Mikulicic 0:c0ecb8bf28eb 5092 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 5093 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 5094 */
Marko Mikulicic 0:c0ecb8bf28eb 5095
Marko Mikulicic 0:c0ecb8bf28eb 5096 #ifndef CS_V7_SRC_VARINT_H_
Marko Mikulicic 0:c0ecb8bf28eb 5097 #define CS_V7_SRC_VARINT_H_
Marko Mikulicic 0:c0ecb8bf28eb 5098
Marko Mikulicic 0:c0ecb8bf28eb 5099 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5100
Marko Mikulicic 0:c0ecb8bf28eb 5101 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 5102 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 5103 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 5104
Marko Mikulicic 0:c0ecb8bf28eb 5105 V7_PRIVATE int encode_varint(size_t len, unsigned char *p);
Marko Mikulicic 0:c0ecb8bf28eb 5106 V7_PRIVATE size_t decode_varint(const unsigned char *p, int *llen);
Marko Mikulicic 0:c0ecb8bf28eb 5107 V7_PRIVATE int calc_llen(size_t len);
Marko Mikulicic 0:c0ecb8bf28eb 5108
Marko Mikulicic 0:c0ecb8bf28eb 5109 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 5110 }
Marko Mikulicic 0:c0ecb8bf28eb 5111 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 5112
Marko Mikulicic 0:c0ecb8bf28eb 5113 #endif /* CS_V7_SRC_VARINT_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 5114 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 5115 #line 1 "common/cs_strtod.h"
Marko Mikulicic 0:c0ecb8bf28eb 5116 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5117 /*
Marko Mikulicic 0:c0ecb8bf28eb 5118 * Copyright (c) 2014-2016 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 5119 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 5120 */
Marko Mikulicic 0:c0ecb8bf28eb 5121
Marko Mikulicic 0:c0ecb8bf28eb 5122 #ifndef CS_COMMON_CS_STRTOD_H_
Marko Mikulicic 0:c0ecb8bf28eb 5123 #define CS_COMMON_CS_STRTOD_H_
Marko Mikulicic 0:c0ecb8bf28eb 5124
Marko Mikulicic 0:c0ecb8bf28eb 5125 double cs_strtod(const char *str, char **endptr);
Marko Mikulicic 0:c0ecb8bf28eb 5126
Marko Mikulicic 0:c0ecb8bf28eb 5127 #endif /* CS_COMMON_CS_STRTOD_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 5128 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 5129 #line 1 "v7/src/ast.h"
Marko Mikulicic 0:c0ecb8bf28eb 5130 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5131 /*
Marko Mikulicic 0:c0ecb8bf28eb 5132 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 5133 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 5134 */
Marko Mikulicic 0:c0ecb8bf28eb 5135
Marko Mikulicic 0:c0ecb8bf28eb 5136 #ifndef CS_V7_SRC_AST_H_
Marko Mikulicic 0:c0ecb8bf28eb 5137 #define CS_V7_SRC_AST_H_
Marko Mikulicic 0:c0ecb8bf28eb 5138
Marko Mikulicic 0:c0ecb8bf28eb 5139 #include <stdio.h>
Marko Mikulicic 0:c0ecb8bf28eb 5140 /* Amalgamated: #include "common/mbuf.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5141 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5142 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5143
Marko Mikulicic 0:c0ecb8bf28eb 5144 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 5145
Marko Mikulicic 0:c0ecb8bf28eb 5146 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 5147 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 5148 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 5149
Marko Mikulicic 0:c0ecb8bf28eb 5150 #define BIN_AST_SIGNATURE "V\007ASTV10"
Marko Mikulicic 0:c0ecb8bf28eb 5151
Marko Mikulicic 0:c0ecb8bf28eb 5152 enum ast_tag {
Marko Mikulicic 0:c0ecb8bf28eb 5153 AST_NOP,
Marko Mikulicic 0:c0ecb8bf28eb 5154 AST_SCRIPT,
Marko Mikulicic 0:c0ecb8bf28eb 5155 AST_VAR,
Marko Mikulicic 0:c0ecb8bf28eb 5156 AST_VAR_DECL,
Marko Mikulicic 0:c0ecb8bf28eb 5157 AST_FUNC_DECL,
Marko Mikulicic 0:c0ecb8bf28eb 5158 AST_IF,
Marko Mikulicic 0:c0ecb8bf28eb 5159 AST_FUNC,
Marko Mikulicic 0:c0ecb8bf28eb 5160
Marko Mikulicic 0:c0ecb8bf28eb 5161 AST_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 5162 AST_REM_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 5163 AST_MUL_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 5164 AST_DIV_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 5165 AST_XOR_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 5166 AST_PLUS_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 5167 AST_MINUS_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 5168 AST_OR_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 5169 AST_AND_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 5170 AST_LSHIFT_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 5171 AST_RSHIFT_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 5172 AST_URSHIFT_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 5173
Marko Mikulicic 0:c0ecb8bf28eb 5174 AST_NUM,
Marko Mikulicic 0:c0ecb8bf28eb 5175 AST_IDENT,
Marko Mikulicic 0:c0ecb8bf28eb 5176 AST_STRING,
Marko Mikulicic 0:c0ecb8bf28eb 5177 AST_REGEX,
Marko Mikulicic 0:c0ecb8bf28eb 5178 AST_LABEL,
Marko Mikulicic 0:c0ecb8bf28eb 5179
Marko Mikulicic 0:c0ecb8bf28eb 5180 AST_SEQ,
Marko Mikulicic 0:c0ecb8bf28eb 5181 AST_WHILE,
Marko Mikulicic 0:c0ecb8bf28eb 5182 AST_DOWHILE,
Marko Mikulicic 0:c0ecb8bf28eb 5183 AST_FOR,
Marko Mikulicic 0:c0ecb8bf28eb 5184 AST_FOR_IN,
Marko Mikulicic 0:c0ecb8bf28eb 5185 AST_COND,
Marko Mikulicic 0:c0ecb8bf28eb 5186
Marko Mikulicic 0:c0ecb8bf28eb 5187 AST_DEBUGGER,
Marko Mikulicic 0:c0ecb8bf28eb 5188 AST_BREAK,
Marko Mikulicic 0:c0ecb8bf28eb 5189 AST_LABELED_BREAK,
Marko Mikulicic 0:c0ecb8bf28eb 5190 AST_CONTINUE,
Marko Mikulicic 0:c0ecb8bf28eb 5191 AST_LABELED_CONTINUE,
Marko Mikulicic 0:c0ecb8bf28eb 5192 AST_RETURN,
Marko Mikulicic 0:c0ecb8bf28eb 5193 AST_VALUE_RETURN,
Marko Mikulicic 0:c0ecb8bf28eb 5194 AST_THROW,
Marko Mikulicic 0:c0ecb8bf28eb 5195
Marko Mikulicic 0:c0ecb8bf28eb 5196 AST_TRY,
Marko Mikulicic 0:c0ecb8bf28eb 5197 AST_SWITCH,
Marko Mikulicic 0:c0ecb8bf28eb 5198 AST_CASE,
Marko Mikulicic 0:c0ecb8bf28eb 5199 AST_DEFAULT,
Marko Mikulicic 0:c0ecb8bf28eb 5200 AST_WITH,
Marko Mikulicic 0:c0ecb8bf28eb 5201
Marko Mikulicic 0:c0ecb8bf28eb 5202 AST_LOGICAL_OR,
Marko Mikulicic 0:c0ecb8bf28eb 5203 AST_LOGICAL_AND,
Marko Mikulicic 0:c0ecb8bf28eb 5204 AST_OR,
Marko Mikulicic 0:c0ecb8bf28eb 5205 AST_XOR,
Marko Mikulicic 0:c0ecb8bf28eb 5206 AST_AND,
Marko Mikulicic 0:c0ecb8bf28eb 5207
Marko Mikulicic 0:c0ecb8bf28eb 5208 AST_EQ,
Marko Mikulicic 0:c0ecb8bf28eb 5209 AST_EQ_EQ,
Marko Mikulicic 0:c0ecb8bf28eb 5210 AST_NE,
Marko Mikulicic 0:c0ecb8bf28eb 5211 AST_NE_NE,
Marko Mikulicic 0:c0ecb8bf28eb 5212
Marko Mikulicic 0:c0ecb8bf28eb 5213 AST_LE,
Marko Mikulicic 0:c0ecb8bf28eb 5214 AST_LT,
Marko Mikulicic 0:c0ecb8bf28eb 5215 AST_GE,
Marko Mikulicic 0:c0ecb8bf28eb 5216 AST_GT,
Marko Mikulicic 0:c0ecb8bf28eb 5217 AST_IN,
Marko Mikulicic 0:c0ecb8bf28eb 5218 AST_INSTANCEOF,
Marko Mikulicic 0:c0ecb8bf28eb 5219
Marko Mikulicic 0:c0ecb8bf28eb 5220 AST_LSHIFT,
Marko Mikulicic 0:c0ecb8bf28eb 5221 AST_RSHIFT,
Marko Mikulicic 0:c0ecb8bf28eb 5222 AST_URSHIFT,
Marko Mikulicic 0:c0ecb8bf28eb 5223
Marko Mikulicic 0:c0ecb8bf28eb 5224 AST_ADD,
Marko Mikulicic 0:c0ecb8bf28eb 5225 AST_SUB,
Marko Mikulicic 0:c0ecb8bf28eb 5226
Marko Mikulicic 0:c0ecb8bf28eb 5227 AST_REM,
Marko Mikulicic 0:c0ecb8bf28eb 5228 AST_MUL,
Marko Mikulicic 0:c0ecb8bf28eb 5229 AST_DIV,
Marko Mikulicic 0:c0ecb8bf28eb 5230
Marko Mikulicic 0:c0ecb8bf28eb 5231 AST_POSITIVE,
Marko Mikulicic 0:c0ecb8bf28eb 5232 AST_NEGATIVE,
Marko Mikulicic 0:c0ecb8bf28eb 5233 AST_NOT,
Marko Mikulicic 0:c0ecb8bf28eb 5234 AST_LOGICAL_NOT,
Marko Mikulicic 0:c0ecb8bf28eb 5235 AST_VOID,
Marko Mikulicic 0:c0ecb8bf28eb 5236 AST_DELETE,
Marko Mikulicic 0:c0ecb8bf28eb 5237 AST_TYPEOF,
Marko Mikulicic 0:c0ecb8bf28eb 5238 AST_PREINC,
Marko Mikulicic 0:c0ecb8bf28eb 5239 AST_PREDEC,
Marko Mikulicic 0:c0ecb8bf28eb 5240
Marko Mikulicic 0:c0ecb8bf28eb 5241 AST_POSTINC,
Marko Mikulicic 0:c0ecb8bf28eb 5242 AST_POSTDEC,
Marko Mikulicic 0:c0ecb8bf28eb 5243
Marko Mikulicic 0:c0ecb8bf28eb 5244 AST_MEMBER,
Marko Mikulicic 0:c0ecb8bf28eb 5245 AST_INDEX,
Marko Mikulicic 0:c0ecb8bf28eb 5246 AST_CALL,
Marko Mikulicic 0:c0ecb8bf28eb 5247
Marko Mikulicic 0:c0ecb8bf28eb 5248 AST_NEW,
Marko Mikulicic 0:c0ecb8bf28eb 5249
Marko Mikulicic 0:c0ecb8bf28eb 5250 AST_ARRAY,
Marko Mikulicic 0:c0ecb8bf28eb 5251 AST_OBJECT,
Marko Mikulicic 0:c0ecb8bf28eb 5252 AST_PROP,
Marko Mikulicic 0:c0ecb8bf28eb 5253 AST_GETTER,
Marko Mikulicic 0:c0ecb8bf28eb 5254 AST_SETTER,
Marko Mikulicic 0:c0ecb8bf28eb 5255
Marko Mikulicic 0:c0ecb8bf28eb 5256 AST_THIS,
Marko Mikulicic 0:c0ecb8bf28eb 5257 AST_TRUE,
Marko Mikulicic 0:c0ecb8bf28eb 5258 AST_FALSE,
Marko Mikulicic 0:c0ecb8bf28eb 5259 AST_NULL,
Marko Mikulicic 0:c0ecb8bf28eb 5260 AST_UNDEFINED,
Marko Mikulicic 0:c0ecb8bf28eb 5261
Marko Mikulicic 0:c0ecb8bf28eb 5262 AST_USE_STRICT,
Marko Mikulicic 0:c0ecb8bf28eb 5263
Marko Mikulicic 0:c0ecb8bf28eb 5264 AST_MAX_TAG
Marko Mikulicic 0:c0ecb8bf28eb 5265 };
Marko Mikulicic 0:c0ecb8bf28eb 5266
Marko Mikulicic 0:c0ecb8bf28eb 5267 struct ast {
Marko Mikulicic 0:c0ecb8bf28eb 5268 struct mbuf mbuf;
Marko Mikulicic 0:c0ecb8bf28eb 5269 int refcnt;
Marko Mikulicic 0:c0ecb8bf28eb 5270 int has_overflow;
Marko Mikulicic 0:c0ecb8bf28eb 5271 };
Marko Mikulicic 0:c0ecb8bf28eb 5272
Marko Mikulicic 0:c0ecb8bf28eb 5273 typedef unsigned long ast_off_t;
Marko Mikulicic 0:c0ecb8bf28eb 5274
Marko Mikulicic 0:c0ecb8bf28eb 5275 #if __GNUC__ >= 4 && __GNUC_MINOR__ >= 8
Marko Mikulicic 0:c0ecb8bf28eb 5276 #define GCC_HAS_PRAGMA_DIAGNOSTIC
Marko Mikulicic 0:c0ecb8bf28eb 5277 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5278
Marko Mikulicic 0:c0ecb8bf28eb 5279 #ifdef GCC_HAS_PRAGMA_DIAGNOSTIC
Marko Mikulicic 0:c0ecb8bf28eb 5280 /*
Marko Mikulicic 0:c0ecb8bf28eb 5281 * TODO(mkm): GCC complains that bitfields on char are not standard
Marko Mikulicic 0:c0ecb8bf28eb 5282 */
Marko Mikulicic 0:c0ecb8bf28eb 5283 #pragma GCC diagnostic push
Marko Mikulicic 0:c0ecb8bf28eb 5284 #pragma GCC diagnostic ignored "-Wpedantic"
Marko Mikulicic 0:c0ecb8bf28eb 5285 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5286 struct ast_node_def {
Marko Mikulicic 0:c0ecb8bf28eb 5287 #ifndef V7_DISABLE_AST_TAG_NAMES
Marko Mikulicic 0:c0ecb8bf28eb 5288 const char *name; /* tag name, for debugging and serialization */
Marko Mikulicic 0:c0ecb8bf28eb 5289 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5290 unsigned char has_varint : 1; /* has a varint body */
Marko Mikulicic 0:c0ecb8bf28eb 5291 unsigned char has_inlined : 1; /* inlined data whose size is in varint fld */
Marko Mikulicic 0:c0ecb8bf28eb 5292 unsigned char num_skips : 3; /* number of skips */
Marko Mikulicic 0:c0ecb8bf28eb 5293 unsigned char num_subtrees : 3; /* number of fixed subtrees */
Marko Mikulicic 0:c0ecb8bf28eb 5294 };
Marko Mikulicic 0:c0ecb8bf28eb 5295 extern const struct ast_node_def ast_node_defs[];
Marko Mikulicic 0:c0ecb8bf28eb 5296 #if V7_ENABLE_FOOTPRINT_REPORT
Marko Mikulicic 0:c0ecb8bf28eb 5297 extern const size_t ast_node_defs_size;
Marko Mikulicic 0:c0ecb8bf28eb 5298 extern const size_t ast_node_defs_count;
Marko Mikulicic 0:c0ecb8bf28eb 5299 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5300 #ifdef GCC_HAS_PRAGMA_DIAGNOSTIC
Marko Mikulicic 0:c0ecb8bf28eb 5301 #pragma GCC diagnostic pop
Marko Mikulicic 0:c0ecb8bf28eb 5302 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5303
Marko Mikulicic 0:c0ecb8bf28eb 5304 enum ast_which_skip {
Marko Mikulicic 0:c0ecb8bf28eb 5305 AST_END_SKIP = 0,
Marko Mikulicic 0:c0ecb8bf28eb 5306 AST_VAR_NEXT_SKIP = 1,
Marko Mikulicic 0:c0ecb8bf28eb 5307 AST_SCRIPT_FIRST_VAR_SKIP = AST_VAR_NEXT_SKIP,
Marko Mikulicic 0:c0ecb8bf28eb 5308 AST_FOR_BODY_SKIP = 1,
Marko Mikulicic 0:c0ecb8bf28eb 5309 AST_DO_WHILE_COND_SKIP = 1,
Marko Mikulicic 0:c0ecb8bf28eb 5310 AST_END_IF_TRUE_SKIP = 1,
Marko Mikulicic 0:c0ecb8bf28eb 5311 AST_TRY_CATCH_SKIP = 1,
Marko Mikulicic 0:c0ecb8bf28eb 5312 AST_TRY_FINALLY_SKIP = 2,
Marko Mikulicic 0:c0ecb8bf28eb 5313 AST_FUNC_FIRST_VAR_SKIP = AST_VAR_NEXT_SKIP,
Marko Mikulicic 0:c0ecb8bf28eb 5314 AST_FUNC_BODY_SKIP = 2,
Marko Mikulicic 0:c0ecb8bf28eb 5315 AST_SWITCH_DEFAULT_SKIP = 1
Marko Mikulicic 0:c0ecb8bf28eb 5316 };
Marko Mikulicic 0:c0ecb8bf28eb 5317
Marko Mikulicic 0:c0ecb8bf28eb 5318 V7_PRIVATE void ast_init(struct ast *, size_t);
Marko Mikulicic 0:c0ecb8bf28eb 5319 V7_PRIVATE void ast_optimize(struct ast *);
Marko Mikulicic 0:c0ecb8bf28eb 5320 V7_PRIVATE void ast_free(struct ast *);
Marko Mikulicic 0:c0ecb8bf28eb 5321
Marko Mikulicic 0:c0ecb8bf28eb 5322 /*
Marko Mikulicic 0:c0ecb8bf28eb 5323 * Begins an AST node by inserting a tag to the AST at the given offset.
Marko Mikulicic 0:c0ecb8bf28eb 5324 *
Marko Mikulicic 0:c0ecb8bf28eb 5325 * It also allocates space for the fixed_size payload and the space for
Marko Mikulicic 0:c0ecb8bf28eb 5326 * the skips.
Marko Mikulicic 0:c0ecb8bf28eb 5327 *
Marko Mikulicic 0:c0ecb8bf28eb 5328 * The caller is responsible for appending children.
Marko Mikulicic 0:c0ecb8bf28eb 5329 *
Marko Mikulicic 0:c0ecb8bf28eb 5330 * Returns the offset of the node payload (one byte after the tag).
Marko Mikulicic 0:c0ecb8bf28eb 5331 * This offset can be passed to `ast_set_skip`.
Marko Mikulicic 0:c0ecb8bf28eb 5332 */
Marko Mikulicic 0:c0ecb8bf28eb 5333 V7_PRIVATE ast_off_t
Marko Mikulicic 0:c0ecb8bf28eb 5334 ast_insert_node(struct ast *a, ast_off_t pos, enum ast_tag tag);
Marko Mikulicic 0:c0ecb8bf28eb 5335
Marko Mikulicic 0:c0ecb8bf28eb 5336 /*
Marko Mikulicic 0:c0ecb8bf28eb 5337 * Modify tag which is already added to buffer. Keeps `AST_TAG_LINENO_PRESENT`
Marko Mikulicic 0:c0ecb8bf28eb 5338 * flag.
Marko Mikulicic 0:c0ecb8bf28eb 5339 */
Marko Mikulicic 0:c0ecb8bf28eb 5340 V7_PRIVATE void ast_modify_tag(struct ast *a, ast_off_t tag_off,
Marko Mikulicic 0:c0ecb8bf28eb 5341 enum ast_tag tag);
Marko Mikulicic 0:c0ecb8bf28eb 5342
Marko Mikulicic 0:c0ecb8bf28eb 5343 #ifndef V7_DISABLE_LINE_NUMBERS
Marko Mikulicic 0:c0ecb8bf28eb 5344 /*
Marko Mikulicic 0:c0ecb8bf28eb 5345 * Add line_no varint after all skips of the tag at the offset `tag_off`, and
Marko Mikulicic 0:c0ecb8bf28eb 5346 * marks the tag byte.
Marko Mikulicic 0:c0ecb8bf28eb 5347 *
Marko Mikulicic 0:c0ecb8bf28eb 5348 * Byte at the offset `tag_off` should be a valid tag.
Marko Mikulicic 0:c0ecb8bf28eb 5349 */
Marko Mikulicic 0:c0ecb8bf28eb 5350 V7_PRIVATE void ast_add_line_no(struct ast *a, ast_off_t tag_off, int line_no);
Marko Mikulicic 0:c0ecb8bf28eb 5351 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5352
Marko Mikulicic 0:c0ecb8bf28eb 5353 /*
Marko Mikulicic 0:c0ecb8bf28eb 5354 * Patches a given skip slot for an already emitted node with the
Marko Mikulicic 0:c0ecb8bf28eb 5355 * current write cursor position (e.g. AST length).
Marko Mikulicic 0:c0ecb8bf28eb 5356 *
Marko Mikulicic 0:c0ecb8bf28eb 5357 * This is intended to be invoked when a node with a variable number
Marko Mikulicic 0:c0ecb8bf28eb 5358 * of child subtrees is closed, or when the consumers need a shortcut
Marko Mikulicic 0:c0ecb8bf28eb 5359 * to the next sibling.
Marko Mikulicic 0:c0ecb8bf28eb 5360 *
Marko Mikulicic 0:c0ecb8bf28eb 5361 * Each node type has a different number and semantic for skips,
Marko Mikulicic 0:c0ecb8bf28eb 5362 * all of them defined in the `ast_which_skip` enum.
Marko Mikulicic 0:c0ecb8bf28eb 5363 * All nodes having a variable number of child subtrees must define
Marko Mikulicic 0:c0ecb8bf28eb 5364 * at least the `AST_END_SKIP` skip, which effectively skips a node
Marko Mikulicic 0:c0ecb8bf28eb 5365 * boundary.
Marko Mikulicic 0:c0ecb8bf28eb 5366 *
Marko Mikulicic 0:c0ecb8bf28eb 5367 * Every tree reader can assume this and safely skip unknown nodes.
Marko Mikulicic 0:c0ecb8bf28eb 5368 *
Marko Mikulicic 0:c0ecb8bf28eb 5369 * `pos` should be an offset of the byte right after a tag.
Marko Mikulicic 0:c0ecb8bf28eb 5370 */
Marko Mikulicic 0:c0ecb8bf28eb 5371 V7_PRIVATE ast_off_t
Marko Mikulicic 0:c0ecb8bf28eb 5372 ast_set_skip(struct ast *a, ast_off_t pos, enum ast_which_skip skip);
Marko Mikulicic 0:c0ecb8bf28eb 5373
Marko Mikulicic 0:c0ecb8bf28eb 5374 /*
Marko Mikulicic 0:c0ecb8bf28eb 5375 * Patches a given skip slot for an already emitted node with the value
Marko Mikulicic 0:c0ecb8bf28eb 5376 * (stored as delta relative to the `pos` node) of the `where` argument.
Marko Mikulicic 0:c0ecb8bf28eb 5377 */
Marko Mikulicic 0:c0ecb8bf28eb 5378 V7_PRIVATE ast_off_t ast_modify_skip(struct ast *a, ast_off_t pos,
Marko Mikulicic 0:c0ecb8bf28eb 5379 ast_off_t where, enum ast_which_skip skip);
Marko Mikulicic 0:c0ecb8bf28eb 5380
Marko Mikulicic 0:c0ecb8bf28eb 5381 /*
Marko Mikulicic 0:c0ecb8bf28eb 5382 * Returns the offset in AST to which the given `skip` points.
Marko Mikulicic 0:c0ecb8bf28eb 5383 *
Marko Mikulicic 0:c0ecb8bf28eb 5384 * `pos` should be an offset of the byte right after a tag.
Marko Mikulicic 0:c0ecb8bf28eb 5385 */
Marko Mikulicic 0:c0ecb8bf28eb 5386 V7_PRIVATE ast_off_t
Marko Mikulicic 0:c0ecb8bf28eb 5387 ast_get_skip(struct ast *a, ast_off_t pos, enum ast_which_skip skip);
Marko Mikulicic 0:c0ecb8bf28eb 5388
Marko Mikulicic 0:c0ecb8bf28eb 5389 /*
Marko Mikulicic 0:c0ecb8bf28eb 5390 * Returns the tag from the offset `ppos`, and shifts `ppos` by 1.
Marko Mikulicic 0:c0ecb8bf28eb 5391 */
Marko Mikulicic 0:c0ecb8bf28eb 5392 V7_PRIVATE enum ast_tag ast_fetch_tag(struct ast *a, ast_off_t *ppos);
Marko Mikulicic 0:c0ecb8bf28eb 5393
Marko Mikulicic 0:c0ecb8bf28eb 5394 /*
Marko Mikulicic 0:c0ecb8bf28eb 5395 * Moves the cursor to the tag's varint and inlined data (if there are any, see
Marko Mikulicic 0:c0ecb8bf28eb 5396 * `struct ast_node_def::has_varint` and `struct ast_node_def::has_inlined`).
Marko Mikulicic 0:c0ecb8bf28eb 5397 *
Marko Mikulicic 0:c0ecb8bf28eb 5398 * Technically, it skips node's "skips" and line number data, if either is
Marko Mikulicic 0:c0ecb8bf28eb 5399 * present.
Marko Mikulicic 0:c0ecb8bf28eb 5400 *
Marko Mikulicic 0:c0ecb8bf28eb 5401 * Assumes a cursor (`ppos`) positioned right after a tag.
Marko Mikulicic 0:c0ecb8bf28eb 5402 */
Marko Mikulicic 0:c0ecb8bf28eb 5403 V7_PRIVATE void ast_move_to_inlined_data(struct ast *a, ast_off_t *ppos);
Marko Mikulicic 0:c0ecb8bf28eb 5404
Marko Mikulicic 0:c0ecb8bf28eb 5405 /*
Marko Mikulicic 0:c0ecb8bf28eb 5406 * Moves the cursor to the tag's subtrees (if there are any,
Marko Mikulicic 0:c0ecb8bf28eb 5407 * see `struct ast_node_def::num_subtrees`), or to the next node in case the
Marko Mikulicic 0:c0ecb8bf28eb 5408 * current node has no subtrees.
Marko Mikulicic 0:c0ecb8bf28eb 5409 *
Marko Mikulicic 0:c0ecb8bf28eb 5410 * Technically, it skips node's "skips", line number data, and inlined data, if
Marko Mikulicic 0:c0ecb8bf28eb 5411 * either is present.
Marko Mikulicic 0:c0ecb8bf28eb 5412 *
Marko Mikulicic 0:c0ecb8bf28eb 5413 * Assumes a cursor (`ppos`) positioned right after a tag.
Marko Mikulicic 0:c0ecb8bf28eb 5414 */
Marko Mikulicic 0:c0ecb8bf28eb 5415 V7_PRIVATE void ast_move_to_children(struct ast *a, ast_off_t *ppos);
Marko Mikulicic 0:c0ecb8bf28eb 5416
Marko Mikulicic 0:c0ecb8bf28eb 5417 /* Helper to add a node with inlined data. */
Marko Mikulicic 0:c0ecb8bf28eb 5418 V7_PRIVATE ast_off_t ast_insert_inlined_node(struct ast *a, ast_off_t pos,
Marko Mikulicic 0:c0ecb8bf28eb 5419 enum ast_tag tag, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 5420 size_t len);
Marko Mikulicic 0:c0ecb8bf28eb 5421
Marko Mikulicic 0:c0ecb8bf28eb 5422 /*
Marko Mikulicic 0:c0ecb8bf28eb 5423 * Returns the line number encoded in the node, or `0` in case of none is
Marko Mikulicic 0:c0ecb8bf28eb 5424 * encoded.
Marko Mikulicic 0:c0ecb8bf28eb 5425 *
Marko Mikulicic 0:c0ecb8bf28eb 5426 * `pos` should be an offset of the byte right after a tag.
Marko Mikulicic 0:c0ecb8bf28eb 5427 */
Marko Mikulicic 0:c0ecb8bf28eb 5428 V7_PRIVATE int ast_get_line_no(struct ast *a, ast_off_t pos);
Marko Mikulicic 0:c0ecb8bf28eb 5429
Marko Mikulicic 0:c0ecb8bf28eb 5430 /*
Marko Mikulicic 0:c0ecb8bf28eb 5431 * `pos` should be an offset of the byte right after a tag
Marko Mikulicic 0:c0ecb8bf28eb 5432 */
Marko Mikulicic 0:c0ecb8bf28eb 5433 V7_PRIVATE char *ast_get_inlined_data(struct ast *a, ast_off_t pos, size_t *n);
Marko Mikulicic 0:c0ecb8bf28eb 5434
Marko Mikulicic 0:c0ecb8bf28eb 5435 /*
Marko Mikulicic 0:c0ecb8bf28eb 5436 * Returns the `double` number inlined in the node
Marko Mikulicic 0:c0ecb8bf28eb 5437 */
Marko Mikulicic 0:c0ecb8bf28eb 5438 V7_PRIVATE double ast_get_num(struct ast *a, ast_off_t pos);
Marko Mikulicic 0:c0ecb8bf28eb 5439
Marko Mikulicic 0:c0ecb8bf28eb 5440 /*
Marko Mikulicic 0:c0ecb8bf28eb 5441 * Skips the node and all its subnodes.
Marko Mikulicic 0:c0ecb8bf28eb 5442 *
Marko Mikulicic 0:c0ecb8bf28eb 5443 * Cursor (`ppos`) should be at the tag byte
Marko Mikulicic 0:c0ecb8bf28eb 5444 */
Marko Mikulicic 0:c0ecb8bf28eb 5445 V7_PRIVATE void ast_skip_tree(struct ast *a, ast_off_t *ppos);
Marko Mikulicic 0:c0ecb8bf28eb 5446
Marko Mikulicic 0:c0ecb8bf28eb 5447 V7_PRIVATE void ast_dump_tree(FILE *fp, struct ast *a, ast_off_t *ppos,
Marko Mikulicic 0:c0ecb8bf28eb 5448 int depth);
Marko Mikulicic 0:c0ecb8bf28eb 5449
Marko Mikulicic 0:c0ecb8bf28eb 5450 V7_PRIVATE void release_ast(struct v7 *v7, struct ast *a);
Marko Mikulicic 0:c0ecb8bf28eb 5451
Marko Mikulicic 0:c0ecb8bf28eb 5452 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 5453 }
Marko Mikulicic 0:c0ecb8bf28eb 5454 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 5455
Marko Mikulicic 0:c0ecb8bf28eb 5456 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 5457
Marko Mikulicic 0:c0ecb8bf28eb 5458 #endif /* CS_V7_SRC_AST_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 5459 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 5460 #line 1 "v7/src/bcode.h"
Marko Mikulicic 0:c0ecb8bf28eb 5461 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5462 /*
Marko Mikulicic 0:c0ecb8bf28eb 5463 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 5464 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 5465 */
Marko Mikulicic 0:c0ecb8bf28eb 5466
Marko Mikulicic 0:c0ecb8bf28eb 5467 #ifndef CS_V7_SRC_BCODE_H_
Marko Mikulicic 0:c0ecb8bf28eb 5468 #define CS_V7_SRC_BCODE_H_
Marko Mikulicic 0:c0ecb8bf28eb 5469
Marko Mikulicic 0:c0ecb8bf28eb 5470 #define BIN_BCODE_SIGNATURE "V\007BCODE:"
Marko Mikulicic 0:c0ecb8bf28eb 5471
Marko Mikulicic 0:c0ecb8bf28eb 5472 #if !defined(V7_NAMES_CNT_WIDTH)
Marko Mikulicic 0:c0ecb8bf28eb 5473 #define V7_NAMES_CNT_WIDTH 10
Marko Mikulicic 0:c0ecb8bf28eb 5474 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5475
Marko Mikulicic 0:c0ecb8bf28eb 5476 #if !defined(V7_ARGS_CNT_WIDTH)
Marko Mikulicic 0:c0ecb8bf28eb 5477 #define V7_ARGS_CNT_WIDTH 8
Marko Mikulicic 0:c0ecb8bf28eb 5478 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5479
Marko Mikulicic 0:c0ecb8bf28eb 5480 #define V7_NAMES_CNT_MAX ((1 << V7_NAMES_CNT_WIDTH) - 1)
Marko Mikulicic 0:c0ecb8bf28eb 5481 #define V7_ARGS_CNT_MAX ((1 << V7_ARGS_CNT_WIDTH) - 1)
Marko Mikulicic 0:c0ecb8bf28eb 5482
Marko Mikulicic 0:c0ecb8bf28eb 5483 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5484 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5485 /* Amalgamated: #include "v7/src/opcodes.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5486 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5487 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5488 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5489 /* Amalgamated: #include "common/mbuf.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5490
Marko Mikulicic 0:c0ecb8bf28eb 5491 enum bcode_inline_lit_type_tag {
Marko Mikulicic 0:c0ecb8bf28eb 5492 BCODE_INLINE_STRING_TYPE_TAG = 0,
Marko Mikulicic 0:c0ecb8bf28eb 5493 BCODE_INLINE_NUMBER_TYPE_TAG,
Marko Mikulicic 0:c0ecb8bf28eb 5494 BCODE_INLINE_FUNC_TYPE_TAG,
Marko Mikulicic 0:c0ecb8bf28eb 5495 BCODE_INLINE_REGEXP_TYPE_TAG,
Marko Mikulicic 0:c0ecb8bf28eb 5496
Marko Mikulicic 0:c0ecb8bf28eb 5497 BCODE_MAX_INLINE_TYPE_TAG
Marko Mikulicic 0:c0ecb8bf28eb 5498 };
Marko Mikulicic 0:c0ecb8bf28eb 5499
Marko Mikulicic 0:c0ecb8bf28eb 5500 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 5501 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 5502 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 5503
Marko Mikulicic 0:c0ecb8bf28eb 5504 typedef uint32_t bcode_off_t;
Marko Mikulicic 0:c0ecb8bf28eb 5505
Marko Mikulicic 0:c0ecb8bf28eb 5506 /*
Marko Mikulicic 0:c0ecb8bf28eb 5507 * Each JS function will have one bcode structure
Marko Mikulicic 0:c0ecb8bf28eb 5508 * containing the instruction stream, a literal table, and function
Marko Mikulicic 0:c0ecb8bf28eb 5509 * metadata.
Marko Mikulicic 0:c0ecb8bf28eb 5510 * Instructions contain references to literals (strings, constants, etc)
Marko Mikulicic 0:c0ecb8bf28eb 5511 *
Marko Mikulicic 0:c0ecb8bf28eb 5512 * The bcode struct can be shared between function instances
Marko Mikulicic 0:c0ecb8bf28eb 5513 * and keeps a reference count used to free it in the function destructor.
Marko Mikulicic 0:c0ecb8bf28eb 5514 */
Marko Mikulicic 0:c0ecb8bf28eb 5515 struct bcode {
Marko Mikulicic 0:c0ecb8bf28eb 5516 /*
Marko Mikulicic 0:c0ecb8bf28eb 5517 * Names + instruction opcode.
Marko Mikulicic 0:c0ecb8bf28eb 5518 * Names are null-terminates strings. For function's bcode, there are:
Marko Mikulicic 0:c0ecb8bf28eb 5519 * - function name (for anonymous function, the name is still present: an
Marko Mikulicic 0:c0ecb8bf28eb 5520 * empty string);
Marko Mikulicic 0:c0ecb8bf28eb 5521 * - arg names (a number of args is determined by `args_cnt`, see below);
Marko Mikulicic 0:c0ecb8bf28eb 5522 * - local names (a number or locals can be calculated:
Marko Mikulicic 0:c0ecb8bf28eb 5523 * `(names_cnt - args_cnt - 1)`).
Marko Mikulicic 0:c0ecb8bf28eb 5524 *
Marko Mikulicic 0:c0ecb8bf28eb 5525 * For script's bcode, there are just local names.
Marko Mikulicic 0:c0ecb8bf28eb 5526 */
Marko Mikulicic 0:c0ecb8bf28eb 5527 struct v7_vec ops;
Marko Mikulicic 0:c0ecb8bf28eb 5528
Marko Mikulicic 0:c0ecb8bf28eb 5529 /* Literal table */
Marko Mikulicic 0:c0ecb8bf28eb 5530 struct v7_vec lit;
Marko Mikulicic 0:c0ecb8bf28eb 5531
Marko Mikulicic 0:c0ecb8bf28eb 5532 #ifndef V7_DISABLE_FILENAMES
Marko Mikulicic 0:c0ecb8bf28eb 5533 /* Name of the file from which this bcode was generated (used for debug) */
Marko Mikulicic 0:c0ecb8bf28eb 5534 void *filename;
Marko Mikulicic 0:c0ecb8bf28eb 5535 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5536
Marko Mikulicic 0:c0ecb8bf28eb 5537 /* Reference count */
Marko Mikulicic 0:c0ecb8bf28eb 5538 uint8_t refcnt;
Marko Mikulicic 0:c0ecb8bf28eb 5539
Marko Mikulicic 0:c0ecb8bf28eb 5540 /* Total number of null-terminated strings in the beginning of `ops` */
Marko Mikulicic 0:c0ecb8bf28eb 5541 unsigned int names_cnt : V7_NAMES_CNT_WIDTH;
Marko Mikulicic 0:c0ecb8bf28eb 5542
Marko Mikulicic 0:c0ecb8bf28eb 5543 /* Number of args (should be <= `(names_cnt + 1)`) */
Marko Mikulicic 0:c0ecb8bf28eb 5544 unsigned int args_cnt : V7_ARGS_CNT_WIDTH;
Marko Mikulicic 0:c0ecb8bf28eb 5545
Marko Mikulicic 0:c0ecb8bf28eb 5546 unsigned int strict_mode : 1;
Marko Mikulicic 0:c0ecb8bf28eb 5547 /*
Marko Mikulicic 0:c0ecb8bf28eb 5548 * If true this structure lives on read only memory, either
Marko Mikulicic 0:c0ecb8bf28eb 5549 * mmapped or constant data section.
Marko Mikulicic 0:c0ecb8bf28eb 5550 */
Marko Mikulicic 0:c0ecb8bf28eb 5551 unsigned int frozen : 1;
Marko Mikulicic 0:c0ecb8bf28eb 5552
Marko Mikulicic 0:c0ecb8bf28eb 5553 /* If set, `ops.buf` points to ROM, so we shouldn't free it */
Marko Mikulicic 0:c0ecb8bf28eb 5554 unsigned int ops_in_rom : 1;
Marko Mikulicic 0:c0ecb8bf28eb 5555 /* Set for deserialized bcode. Used for metrics only */
Marko Mikulicic 0:c0ecb8bf28eb 5556 unsigned int deserialized : 1;
Marko Mikulicic 0:c0ecb8bf28eb 5557
Marko Mikulicic 0:c0ecb8bf28eb 5558 /* Set when `ops` contains function name as the first `name` */
Marko Mikulicic 0:c0ecb8bf28eb 5559 unsigned int func_name_present : 1;
Marko Mikulicic 0:c0ecb8bf28eb 5560
Marko Mikulicic 0:c0ecb8bf28eb 5561 #ifndef V7_DISABLE_FILENAMES
Marko Mikulicic 0:c0ecb8bf28eb 5562 /* If set, `filename` points to ROM, so we shouldn't free it */
Marko Mikulicic 0:c0ecb8bf28eb 5563 unsigned int filename_in_rom : 1;
Marko Mikulicic 0:c0ecb8bf28eb 5564 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5565 };
Marko Mikulicic 0:c0ecb8bf28eb 5566
Marko Mikulicic 0:c0ecb8bf28eb 5567 /*
Marko Mikulicic 0:c0ecb8bf28eb 5568 * Bcode builder context: it contains mutable mbufs for opcodes and literals,
Marko Mikulicic 0:c0ecb8bf28eb 5569 * whereas the bcode itself contains just vectors (`struct v7_vec`).
Marko Mikulicic 0:c0ecb8bf28eb 5570 */
Marko Mikulicic 0:c0ecb8bf28eb 5571 struct bcode_builder {
Marko Mikulicic 0:c0ecb8bf28eb 5572 struct v7 *v7;
Marko Mikulicic 0:c0ecb8bf28eb 5573 struct bcode *bcode;
Marko Mikulicic 0:c0ecb8bf28eb 5574
Marko Mikulicic 0:c0ecb8bf28eb 5575 struct mbuf ops; /* names + instruction opcode */
Marko Mikulicic 0:c0ecb8bf28eb 5576 struct mbuf lit; /* literal table */
Marko Mikulicic 0:c0ecb8bf28eb 5577 };
Marko Mikulicic 0:c0ecb8bf28eb 5578
Marko Mikulicic 0:c0ecb8bf28eb 5579 V7_PRIVATE void bcode_builder_init(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 5580 struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 5581 struct bcode *bcode);
Marko Mikulicic 0:c0ecb8bf28eb 5582 V7_PRIVATE void bcode_builder_finalize(struct bcode_builder *bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 5583
Marko Mikulicic 0:c0ecb8bf28eb 5584 /*
Marko Mikulicic 0:c0ecb8bf28eb 5585 * Note: `filename` must be either:
Marko Mikulicic 0:c0ecb8bf28eb 5586 *
Marko Mikulicic 0:c0ecb8bf28eb 5587 * - `NULL`. In this case, `filename_in_rom` is ignored.
Marko Mikulicic 0:c0ecb8bf28eb 5588 * - A pointer to ROM (or to any other unmanaged memory). `filename_in_rom`
Marko Mikulicic 0:c0ecb8bf28eb 5589 * must be set to 1.
Marko Mikulicic 0:c0ecb8bf28eb 5590 * - A pointer returned by `shdata_create()`, i.e. a pointer to shared data.
Marko Mikulicic 0:c0ecb8bf28eb 5591 *
Marko Mikulicic 0:c0ecb8bf28eb 5592 * If you need to copy filename from another bcode, just pass NULL initially,
Marko Mikulicic 0:c0ecb8bf28eb 5593 * and after bcode is initialized, call `bcode_copy_filename_from()`.
Marko Mikulicic 0:c0ecb8bf28eb 5594 *
Marko Mikulicic 0:c0ecb8bf28eb 5595 * To get later a proper null-terminated filename string from bcode, use
Marko Mikulicic 0:c0ecb8bf28eb 5596 * `bcode_get_filename()`.
Marko Mikulicic 0:c0ecb8bf28eb 5597 */
Marko Mikulicic 0:c0ecb8bf28eb 5598 V7_PRIVATE void bcode_init(struct bcode *bcode, uint8_t strict_mode,
Marko Mikulicic 0:c0ecb8bf28eb 5599 void *filename, uint8_t filename_in_rom);
Marko Mikulicic 0:c0ecb8bf28eb 5600 V7_PRIVATE void bcode_free(struct v7 *v7, struct bcode *bcode);
Marko Mikulicic 0:c0ecb8bf28eb 5601 V7_PRIVATE void release_bcode(struct v7 *v7, struct bcode *bcode);
Marko Mikulicic 0:c0ecb8bf28eb 5602 V7_PRIVATE void retain_bcode(struct v7 *v7, struct bcode *bcode);
Marko Mikulicic 0:c0ecb8bf28eb 5603
Marko Mikulicic 0:c0ecb8bf28eb 5604 #ifndef V7_DISABLE_FILENAMES
Marko Mikulicic 0:c0ecb8bf28eb 5605 /*
Marko Mikulicic 0:c0ecb8bf28eb 5606 * Return a pointer to null-terminated filename string
Marko Mikulicic 0:c0ecb8bf28eb 5607 */
Marko Mikulicic 0:c0ecb8bf28eb 5608 V7_PRIVATE const char *bcode_get_filename(struct bcode *bcode);
Marko Mikulicic 0:c0ecb8bf28eb 5609 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5610
Marko Mikulicic 0:c0ecb8bf28eb 5611 /*
Marko Mikulicic 0:c0ecb8bf28eb 5612 * Copy filename from `src` to `dst`. If source filename is a pointer to ROM,
Marko Mikulicic 0:c0ecb8bf28eb 5613 * then just the pointer is copied; otherwise, appropriate shdata pointer is
Marko Mikulicic 0:c0ecb8bf28eb 5614 * retained.
Marko Mikulicic 0:c0ecb8bf28eb 5615 */
Marko Mikulicic 0:c0ecb8bf28eb 5616 V7_PRIVATE void bcode_copy_filename_from(struct bcode *dst, struct bcode *src);
Marko Mikulicic 0:c0ecb8bf28eb 5617
Marko Mikulicic 0:c0ecb8bf28eb 5618 /*
Marko Mikulicic 0:c0ecb8bf28eb 5619 * Serialize a bcode structure.
Marko Mikulicic 0:c0ecb8bf28eb 5620 *
Marko Mikulicic 0:c0ecb8bf28eb 5621 * All literals, including functions, are inlined into `ops` data; see
Marko Mikulicic 0:c0ecb8bf28eb 5622 * the serialization logic in `bcode_op_lit()`.
Marko Mikulicic 0:c0ecb8bf28eb 5623 *
Marko Mikulicic 0:c0ecb8bf28eb 5624 * The root bcode looks just like a regular function.
Marko Mikulicic 0:c0ecb8bf28eb 5625 *
Marko Mikulicic 0:c0ecb8bf28eb 5626 * This function is used only internally, but used in a complicated mix of
Marko Mikulicic 0:c0ecb8bf28eb 5627 * configurations, hence the commented V7_PRIVATE
Marko Mikulicic 0:c0ecb8bf28eb 5628 */
Marko Mikulicic 0:c0ecb8bf28eb 5629 /*V7_PRIVATE*/ void bcode_serialize(struct v7 *v7, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 5630 FILE *f);
Marko Mikulicic 0:c0ecb8bf28eb 5631
Marko Mikulicic 0:c0ecb8bf28eb 5632 V7_PRIVATE void bcode_deserialize(struct v7 *v7, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 5633 const char *data);
Marko Mikulicic 0:c0ecb8bf28eb 5634
Marko Mikulicic 0:c0ecb8bf28eb 5635 #ifdef V7_BCODE_DUMP
Marko Mikulicic 0:c0ecb8bf28eb 5636 V7_PRIVATE void dump_bcode(struct v7 *v7, FILE *, struct bcode *);
Marko Mikulicic 0:c0ecb8bf28eb 5637 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5638
Marko Mikulicic 0:c0ecb8bf28eb 5639 /* mode of literal storage: in literal table or inlined in `ops` */
Marko Mikulicic 0:c0ecb8bf28eb 5640 enum lit_mode {
Marko Mikulicic 0:c0ecb8bf28eb 5641 /* literal stored in table, index is in `lit_t::lit_idx` */
Marko Mikulicic 0:c0ecb8bf28eb 5642 LIT_MODE__TABLE,
Marko Mikulicic 0:c0ecb8bf28eb 5643 /* literal should be inlined in `ops`, value is in `lit_t::inline_val` */
Marko Mikulicic 0:c0ecb8bf28eb 5644 LIT_MODE__INLINED,
Marko Mikulicic 0:c0ecb8bf28eb 5645 };
Marko Mikulicic 0:c0ecb8bf28eb 5646
Marko Mikulicic 0:c0ecb8bf28eb 5647 /*
Marko Mikulicic 0:c0ecb8bf28eb 5648 * Result of the addition of literal value to bcode (see `bcode_add_lit()`).
Marko Mikulicic 0:c0ecb8bf28eb 5649 * There are two possible cases:
Marko Mikulicic 0:c0ecb8bf28eb 5650 *
Marko Mikulicic 0:c0ecb8bf28eb 5651 * - Literal is added to the literal table. In this case, `mode ==
Marko Mikulicic 0:c0ecb8bf28eb 5652 * LIT_MODE__TABLE`, and the index of the literal is stored in `lit_idx`
Marko Mikulicic 0:c0ecb8bf28eb 5653 * - Literal is not added anywhere, and should be inlined into `ops`. In this
Marko Mikulicic 0:c0ecb8bf28eb 5654 * case, `mode == LIT_MODE__INLINED`, and the value to inline is stored in
Marko Mikulicic 0:c0ecb8bf28eb 5655 * `inline_val`.
Marko Mikulicic 0:c0ecb8bf28eb 5656 *
Marko Mikulicic 0:c0ecb8bf28eb 5657 * It's `bcode_op_lit()` who handles both of these cases.
Marko Mikulicic 0:c0ecb8bf28eb 5658 */
Marko Mikulicic 0:c0ecb8bf28eb 5659 typedef struct {
Marko Mikulicic 0:c0ecb8bf28eb 5660 union {
Marko Mikulicic 0:c0ecb8bf28eb 5661 /*
Marko Mikulicic 0:c0ecb8bf28eb 5662 * index in literal table;
Marko Mikulicic 0:c0ecb8bf28eb 5663 * NOTE: valid if only `mode == LIT_MODE__TABLE`
Marko Mikulicic 0:c0ecb8bf28eb 5664 */
Marko Mikulicic 0:c0ecb8bf28eb 5665 size_t lit_idx;
Marko Mikulicic 0:c0ecb8bf28eb 5666
Marko Mikulicic 0:c0ecb8bf28eb 5667 /*
Marko Mikulicic 0:c0ecb8bf28eb 5668 * value to be inlined into `ops`;
Marko Mikulicic 0:c0ecb8bf28eb 5669 * NOTE: valid if only `mode == LIT_MODE__INLINED`
Marko Mikulicic 0:c0ecb8bf28eb 5670 */
Marko Mikulicic 0:c0ecb8bf28eb 5671 v7_val_t inline_val;
Marko Mikulicic 0:c0ecb8bf28eb 5672 } v; /* anonymous unions are a c11 feature */
Marko Mikulicic 0:c0ecb8bf28eb 5673
Marko Mikulicic 0:c0ecb8bf28eb 5674 /*
Marko Mikulicic 0:c0ecb8bf28eb 5675 * mode of literal storage (see `enum lit_mode`)
Marko Mikulicic 0:c0ecb8bf28eb 5676 * NOTE: we need one more bit, because enum can be signed
Marko Mikulicic 0:c0ecb8bf28eb 5677 * on some compilers (e.g. msvc) and thus will get signextended
Marko Mikulicic 0:c0ecb8bf28eb 5678 * when moved to a `enum lit_mode` variable basically corrupting
Marko Mikulicic 0:c0ecb8bf28eb 5679 * the value. See https://github.com/cesanta/v7/issues/551
Marko Mikulicic 0:c0ecb8bf28eb 5680 */
Marko Mikulicic 0:c0ecb8bf28eb 5681 enum lit_mode mode : 2;
Marko Mikulicic 0:c0ecb8bf28eb 5682 } lit_t;
Marko Mikulicic 0:c0ecb8bf28eb 5683
Marko Mikulicic 0:c0ecb8bf28eb 5684 V7_PRIVATE void bcode_op(struct bcode_builder *bbuilder, uint8_t op);
Marko Mikulicic 0:c0ecb8bf28eb 5685
Marko Mikulicic 0:c0ecb8bf28eb 5686 #ifndef V7_DISABLE_LINE_NUMBERS
Marko Mikulicic 0:c0ecb8bf28eb 5687 V7_PRIVATE void bcode_append_lineno(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 5688 int line_no);
Marko Mikulicic 0:c0ecb8bf28eb 5689 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5690
Marko Mikulicic 0:c0ecb8bf28eb 5691 /*
Marko Mikulicic 0:c0ecb8bf28eb 5692 * Add a literal to the bcode literal table, or just decide that the literal
Marko Mikulicic 0:c0ecb8bf28eb 5693 * should be inlined into `ops`. See `lit_t` for details.
Marko Mikulicic 0:c0ecb8bf28eb 5694 */
Marko Mikulicic 0:c0ecb8bf28eb 5695 V7_PRIVATE
Marko Mikulicic 0:c0ecb8bf28eb 5696 lit_t bcode_add_lit(struct bcode_builder *bbuilder, v7_val_t val);
Marko Mikulicic 0:c0ecb8bf28eb 5697
Marko Mikulicic 0:c0ecb8bf28eb 5698 /* disabled because of short lits */
Marko Mikulicic 0:c0ecb8bf28eb 5699 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 5700 V7_PRIVATE v7_val_t bcode_get_lit(struct bcode *bcode, size_t idx);
Marko Mikulicic 0:c0ecb8bf28eb 5701 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5702
Marko Mikulicic 0:c0ecb8bf28eb 5703 /*
Marko Mikulicic 0:c0ecb8bf28eb 5704 * Emit an opcode `op`, and handle the literal `lit` (see `bcode_add_lit()`,
Marko Mikulicic 0:c0ecb8bf28eb 5705 * `lit_t`). Depending on the literal storage mode (see `enum lit_mode`), this
Marko Mikulicic 0:c0ecb8bf28eb 5706 * function either emits literal table index or inlines the literal directly
Marko Mikulicic 0:c0ecb8bf28eb 5707 * into `ops.`
Marko Mikulicic 0:c0ecb8bf28eb 5708 */
Marko Mikulicic 0:c0ecb8bf28eb 5709 V7_PRIVATE void bcode_op_lit(struct bcode_builder *bbuilder, enum opcode op,
Marko Mikulicic 0:c0ecb8bf28eb 5710 lit_t lit);
Marko Mikulicic 0:c0ecb8bf28eb 5711
Marko Mikulicic 0:c0ecb8bf28eb 5712 /* Helper function, equivalent of `bcode_op_lit(bbuilder, OP_PUSH_LIT, lit)` */
Marko Mikulicic 0:c0ecb8bf28eb 5713 V7_PRIVATE void bcode_push_lit(struct bcode_builder *bbuilder, lit_t lit);
Marko Mikulicic 0:c0ecb8bf28eb 5714
Marko Mikulicic 0:c0ecb8bf28eb 5715 /*
Marko Mikulicic 0:c0ecb8bf28eb 5716 * Add name to bcode. If `idx` is null, a name is appended to the end of the
Marko Mikulicic 0:c0ecb8bf28eb 5717 * `bcode->ops.buf`. If `idx` is provided, it should point to the index at
Marko Mikulicic 0:c0ecb8bf28eb 5718 * which new name should be inserted; and it is updated by the
Marko Mikulicic 0:c0ecb8bf28eb 5719 * `bcode_add_name()` to point right after newly added name.
Marko Mikulicic 0:c0ecb8bf28eb 5720 *
Marko Mikulicic 0:c0ecb8bf28eb 5721 * This function is used only internally, but used in a complicated mix of
Marko Mikulicic 0:c0ecb8bf28eb 5722 * configurations, hence the commented V7_PRIVATE
Marko Mikulicic 0:c0ecb8bf28eb 5723 */
Marko Mikulicic 0:c0ecb8bf28eb 5724 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 5725 /*V7_PRIVATE*/ enum v7_err
Marko Mikulicic 0:c0ecb8bf28eb 5726 bcode_add_name(struct bcode_builder *bbuilder, const char *p, size_t len,
Marko Mikulicic 0:c0ecb8bf28eb 5727 size_t *idx);
Marko Mikulicic 0:c0ecb8bf28eb 5728
Marko Mikulicic 0:c0ecb8bf28eb 5729 /*
Marko Mikulicic 0:c0ecb8bf28eb 5730 * Takes a pointer to the beginning of `ops` buffer and names count, returns
Marko Mikulicic 0:c0ecb8bf28eb 5731 * a pointer where actual opcodes begin (i.e. skips names).
Marko Mikulicic 0:c0ecb8bf28eb 5732 *
Marko Mikulicic 0:c0ecb8bf28eb 5733 * It takes two distinct arguments instead of just `struct bcode` pointer,
Marko Mikulicic 0:c0ecb8bf28eb 5734 * because during bcode building `ops` is stored in builder.
Marko Mikulicic 0:c0ecb8bf28eb 5735 *
Marko Mikulicic 0:c0ecb8bf28eb 5736 * This function is used only internally, but used in a complicated mix of
Marko Mikulicic 0:c0ecb8bf28eb 5737 * configurations, hence the commented V7_PRIVATE
Marko Mikulicic 0:c0ecb8bf28eb 5738 */
Marko Mikulicic 0:c0ecb8bf28eb 5739 /*V7_PRIVATE*/ char *bcode_end_names(char *ops, size_t names_cnt);
Marko Mikulicic 0:c0ecb8bf28eb 5740
Marko Mikulicic 0:c0ecb8bf28eb 5741 /*
Marko Mikulicic 0:c0ecb8bf28eb 5742 * Given a pointer to `ops` (which should be `bcode->ops` or a pointer returned
Marko Mikulicic 0:c0ecb8bf28eb 5743 * from previous invocation of `bcode_next_name()`), yields a name string via
Marko Mikulicic 0:c0ecb8bf28eb 5744 * arguments `pname`, `plen`.
Marko Mikulicic 0:c0ecb8bf28eb 5745 *
Marko Mikulicic 0:c0ecb8bf28eb 5746 * Returns a pointer that should be given to `bcode_next_name()` to get a next
Marko Mikulicic 0:c0ecb8bf28eb 5747 * string (Whether there is a next string should be determined via the
Marko Mikulicic 0:c0ecb8bf28eb 5748 * `names_cnt`; since if there are no more names, this function will return an
Marko Mikulicic 0:c0ecb8bf28eb 5749 * invalid non-null pointer as next name pointer)
Marko Mikulicic 0:c0ecb8bf28eb 5750 */
Marko Mikulicic 0:c0ecb8bf28eb 5751 V7_PRIVATE char *bcode_next_name(char *ops, char **pname, size_t *plen);
Marko Mikulicic 0:c0ecb8bf28eb 5752
Marko Mikulicic 0:c0ecb8bf28eb 5753 /*
Marko Mikulicic 0:c0ecb8bf28eb 5754 * Like `bcode_next_name()`, but instead of yielding a C string, it yields a
Marko Mikulicic 0:c0ecb8bf28eb 5755 * `val_t` value (via `res`).
Marko Mikulicic 0:c0ecb8bf28eb 5756 */
Marko Mikulicic 0:c0ecb8bf28eb 5757 V7_PRIVATE char *bcode_next_name_v(struct v7 *v7, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 5758 char *ops, val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 5759
Marko Mikulicic 0:c0ecb8bf28eb 5760 V7_PRIVATE bcode_off_t bcode_pos(struct bcode_builder *bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 5761
Marko Mikulicic 0:c0ecb8bf28eb 5762 V7_PRIVATE bcode_off_t bcode_add_target(struct bcode_builder *bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 5763 /*
Marko Mikulicic 0:c0ecb8bf28eb 5764 * This function is used only internally, but used in a complicated mix of
Marko Mikulicic 0:c0ecb8bf28eb 5765 * configurations, hence the commented V7_PRIVATE
Marko Mikulicic 0:c0ecb8bf28eb 5766 */
Marko Mikulicic 0:c0ecb8bf28eb 5767 /*V7_PRIVATE*/ bcode_off_t bcode_op_target(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 5768 uint8_t op);
Marko Mikulicic 0:c0ecb8bf28eb 5769 /*V7_PRIVATE*/ void bcode_patch_target(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 5770 bcode_off_t label, bcode_off_t target);
Marko Mikulicic 0:c0ecb8bf28eb 5771
Marko Mikulicic 0:c0ecb8bf28eb 5772 V7_PRIVATE void bcode_add_varint(struct bcode_builder *bbuilder, size_t value);
Marko Mikulicic 0:c0ecb8bf28eb 5773 /*
Marko Mikulicic 0:c0ecb8bf28eb 5774 * Reads varint-encoded integer from the provided pointer, and adjusts
Marko Mikulicic 0:c0ecb8bf28eb 5775 * the pointer appropriately
Marko Mikulicic 0:c0ecb8bf28eb 5776 */
Marko Mikulicic 0:c0ecb8bf28eb 5777 V7_PRIVATE size_t bcode_get_varint(char **ops);
Marko Mikulicic 0:c0ecb8bf28eb 5778
Marko Mikulicic 0:c0ecb8bf28eb 5779 /*
Marko Mikulicic 0:c0ecb8bf28eb 5780 * Decode a literal value from a string of opcodes and update the cursor to
Marko Mikulicic 0:c0ecb8bf28eb 5781 * point past it
Marko Mikulicic 0:c0ecb8bf28eb 5782 */
Marko Mikulicic 0:c0ecb8bf28eb 5783 V7_PRIVATE
Marko Mikulicic 0:c0ecb8bf28eb 5784 v7_val_t bcode_decode_lit(struct v7 *v7, struct bcode *bcode, char **ops);
Marko Mikulicic 0:c0ecb8bf28eb 5785
Marko Mikulicic 0:c0ecb8bf28eb 5786 #if defined(V7_BCODE_DUMP) || defined(V7_BCODE_TRACE)
Marko Mikulicic 0:c0ecb8bf28eb 5787 V7_PRIVATE void dump_op(struct v7 *v7, FILE *f, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 5788 char **ops);
Marko Mikulicic 0:c0ecb8bf28eb 5789 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5790
Marko Mikulicic 0:c0ecb8bf28eb 5791 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 5792 }
Marko Mikulicic 0:c0ecb8bf28eb 5793 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 5794
Marko Mikulicic 0:c0ecb8bf28eb 5795 #endif /* CS_V7_SRC_BCODE_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 5796 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 5797 #line 1 "v7/src/gc_public.h"
Marko Mikulicic 0:c0ecb8bf28eb 5798 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5799 /*
Marko Mikulicic 0:c0ecb8bf28eb 5800 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 5801 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 5802 */
Marko Mikulicic 0:c0ecb8bf28eb 5803
Marko Mikulicic 0:c0ecb8bf28eb 5804 /*
Marko Mikulicic 0:c0ecb8bf28eb 5805 * === Garbage Collector
Marko Mikulicic 0:c0ecb8bf28eb 5806 */
Marko Mikulicic 0:c0ecb8bf28eb 5807
Marko Mikulicic 0:c0ecb8bf28eb 5808 #ifndef CS_V7_SRC_GC_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 5809 #define CS_V7_SRC_GC_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 5810
Marko Mikulicic 0:c0ecb8bf28eb 5811 /* Amalgamated: #include "v7/src/core_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5812
Marko Mikulicic 0:c0ecb8bf28eb 5813 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 5814 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 5815 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 5816
Marko Mikulicic 0:c0ecb8bf28eb 5817 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 5818
Marko Mikulicic 0:c0ecb8bf28eb 5819 /* Heap metric id, see `v7_heap_stat()` */
Marko Mikulicic 0:c0ecb8bf28eb 5820 enum v7_heap_stat_what {
Marko Mikulicic 0:c0ecb8bf28eb 5821 V7_HEAP_STAT_HEAP_SIZE,
Marko Mikulicic 0:c0ecb8bf28eb 5822 V7_HEAP_STAT_HEAP_USED,
Marko Mikulicic 0:c0ecb8bf28eb 5823 V7_HEAP_STAT_STRING_HEAP_RESERVED,
Marko Mikulicic 0:c0ecb8bf28eb 5824 V7_HEAP_STAT_STRING_HEAP_USED,
Marko Mikulicic 0:c0ecb8bf28eb 5825 V7_HEAP_STAT_OBJ_HEAP_MAX,
Marko Mikulicic 0:c0ecb8bf28eb 5826 V7_HEAP_STAT_OBJ_HEAP_FREE,
Marko Mikulicic 0:c0ecb8bf28eb 5827 V7_HEAP_STAT_OBJ_HEAP_CELL_SIZE,
Marko Mikulicic 0:c0ecb8bf28eb 5828 V7_HEAP_STAT_FUNC_HEAP_MAX,
Marko Mikulicic 0:c0ecb8bf28eb 5829 V7_HEAP_STAT_FUNC_HEAP_FREE,
Marko Mikulicic 0:c0ecb8bf28eb 5830 V7_HEAP_STAT_FUNC_HEAP_CELL_SIZE,
Marko Mikulicic 0:c0ecb8bf28eb 5831 V7_HEAP_STAT_PROP_HEAP_MAX,
Marko Mikulicic 0:c0ecb8bf28eb 5832 V7_HEAP_STAT_PROP_HEAP_FREE,
Marko Mikulicic 0:c0ecb8bf28eb 5833 V7_HEAP_STAT_PROP_HEAP_CELL_SIZE,
Marko Mikulicic 0:c0ecb8bf28eb 5834 V7_HEAP_STAT_FUNC_AST_SIZE,
Marko Mikulicic 0:c0ecb8bf28eb 5835 V7_HEAP_STAT_BCODE_OPS_SIZE,
Marko Mikulicic 0:c0ecb8bf28eb 5836 V7_HEAP_STAT_BCODE_LIT_TOTAL_SIZE,
Marko Mikulicic 0:c0ecb8bf28eb 5837 V7_HEAP_STAT_BCODE_LIT_DESER_SIZE,
Marko Mikulicic 0:c0ecb8bf28eb 5838 V7_HEAP_STAT_FUNC_OWNED,
Marko Mikulicic 0:c0ecb8bf28eb 5839 V7_HEAP_STAT_FUNC_OWNED_MAX
Marko Mikulicic 0:c0ecb8bf28eb 5840 };
Marko Mikulicic 0:c0ecb8bf28eb 5841
Marko Mikulicic 0:c0ecb8bf28eb 5842 /* Returns a given heap statistics */
Marko Mikulicic 0:c0ecb8bf28eb 5843 int v7_heap_stat(struct v7 *v7, enum v7_heap_stat_what what);
Marko Mikulicic 0:c0ecb8bf28eb 5844 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5845
Marko Mikulicic 0:c0ecb8bf28eb 5846 /*
Marko Mikulicic 0:c0ecb8bf28eb 5847 * Perform garbage collection.
Marko Mikulicic 0:c0ecb8bf28eb 5848 * Pass true to full in order to reclaim unused heap back to the OS.
Marko Mikulicic 0:c0ecb8bf28eb 5849 */
Marko Mikulicic 0:c0ecb8bf28eb 5850 void v7_gc(struct v7 *v7, int full);
Marko Mikulicic 0:c0ecb8bf28eb 5851
Marko Mikulicic 0:c0ecb8bf28eb 5852 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 5853 }
Marko Mikulicic 0:c0ecb8bf28eb 5854 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 5855
Marko Mikulicic 0:c0ecb8bf28eb 5856 #endif /* CS_V7_SRC_GC_PUBLIC_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 5857 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 5858 #line 1 "v7/src/gc.h"
Marko Mikulicic 0:c0ecb8bf28eb 5859 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5860 /*
Marko Mikulicic 0:c0ecb8bf28eb 5861 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 5862 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 5863 */
Marko Mikulicic 0:c0ecb8bf28eb 5864
Marko Mikulicic 0:c0ecb8bf28eb 5865 #ifndef CS_V7_SRC_GC_H_
Marko Mikulicic 0:c0ecb8bf28eb 5866 #define CS_V7_SRC_GC_H_
Marko Mikulicic 0:c0ecb8bf28eb 5867
Marko Mikulicic 0:c0ecb8bf28eb 5868 /* Amalgamated: #include "v7/src/gc_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5869
Marko Mikulicic 0:c0ecb8bf28eb 5870 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5871 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5872
Marko Mikulicic 0:c0ecb8bf28eb 5873 /*
Marko Mikulicic 0:c0ecb8bf28eb 5874 * Macros for marking reachable things: use bit 0.
Marko Mikulicic 0:c0ecb8bf28eb 5875 */
Marko Mikulicic 0:c0ecb8bf28eb 5876 #define MARK(p) (((struct gc_cell *) (p))->head.word |= 1)
Marko Mikulicic 0:c0ecb8bf28eb 5877 #define UNMARK(p) (((struct gc_cell *) (p))->head.word &= ~1)
Marko Mikulicic 0:c0ecb8bf28eb 5878 #define MARKED(p) (((struct gc_cell *) (p))->head.word & 1)
Marko Mikulicic 0:c0ecb8bf28eb 5879
Marko Mikulicic 0:c0ecb8bf28eb 5880 /*
Marko Mikulicic 0:c0ecb8bf28eb 5881 * Similar to `MARK()` / `UNMARK()` / `MARKED()`, but `.._FREE` counterparts
Marko Mikulicic 0:c0ecb8bf28eb 5882 * are intended to mark free cells (as opposed to used ones), so they use
Marko Mikulicic 0:c0ecb8bf28eb 5883 * bit 1.
Marko Mikulicic 0:c0ecb8bf28eb 5884 */
Marko Mikulicic 0:c0ecb8bf28eb 5885 #define MARK_FREE(p) (((struct gc_cell *) (p))->head.word |= 2)
Marko Mikulicic 0:c0ecb8bf28eb 5886 #define UNMARK_FREE(p) (((struct gc_cell *) (p))->head.word &= ~2)
Marko Mikulicic 0:c0ecb8bf28eb 5887 #define MARKED_FREE(p) (((struct gc_cell *) (p))->head.word & 2)
Marko Mikulicic 0:c0ecb8bf28eb 5888
Marko Mikulicic 0:c0ecb8bf28eb 5889 /*
Marko Mikulicic 0:c0ecb8bf28eb 5890 * performs arithmetics on gc_cell pointers as if they were arena->cell_size
Marko Mikulicic 0:c0ecb8bf28eb 5891 * bytes wide
Marko Mikulicic 0:c0ecb8bf28eb 5892 */
Marko Mikulicic 0:c0ecb8bf28eb 5893 #define GC_CELL_OP(arena, cell, op, arg) \
Marko Mikulicic 0:c0ecb8bf28eb 5894 ((struct gc_cell *) (((char *) (cell)) op((arg) * (arena)->cell_size)))
Marko Mikulicic 0:c0ecb8bf28eb 5895
Marko Mikulicic 0:c0ecb8bf28eb 5896 struct gc_tmp_frame {
Marko Mikulicic 0:c0ecb8bf28eb 5897 struct v7 *v7;
Marko Mikulicic 0:c0ecb8bf28eb 5898 size_t pos;
Marko Mikulicic 0:c0ecb8bf28eb 5899 };
Marko Mikulicic 0:c0ecb8bf28eb 5900
Marko Mikulicic 0:c0ecb8bf28eb 5901 struct gc_cell {
Marko Mikulicic 0:c0ecb8bf28eb 5902 union {
Marko Mikulicic 0:c0ecb8bf28eb 5903 struct gc_cell *link;
Marko Mikulicic 0:c0ecb8bf28eb 5904 uintptr_t word;
Marko Mikulicic 0:c0ecb8bf28eb 5905 } head;
Marko Mikulicic 0:c0ecb8bf28eb 5906 };
Marko Mikulicic 0:c0ecb8bf28eb 5907
Marko Mikulicic 0:c0ecb8bf28eb 5908 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 5909 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 5910 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 5911
Marko Mikulicic 0:c0ecb8bf28eb 5912 V7_PRIVATE struct v7_generic_object *new_generic_object(struct v7 *);
Marko Mikulicic 0:c0ecb8bf28eb 5913 V7_PRIVATE struct v7_property *new_property(struct v7 *);
Marko Mikulicic 0:c0ecb8bf28eb 5914 V7_PRIVATE struct v7_js_function *new_function(struct v7 *);
Marko Mikulicic 0:c0ecb8bf28eb 5915
Marko Mikulicic 0:c0ecb8bf28eb 5916 V7_PRIVATE void gc_mark(struct v7 *, val_t);
Marko Mikulicic 0:c0ecb8bf28eb 5917
Marko Mikulicic 0:c0ecb8bf28eb 5918 V7_PRIVATE void gc_arena_init(struct gc_arena *, size_t, size_t, size_t,
Marko Mikulicic 0:c0ecb8bf28eb 5919 const char *);
Marko Mikulicic 0:c0ecb8bf28eb 5920 V7_PRIVATE void gc_arena_destroy(struct v7 *, struct gc_arena *a);
Marko Mikulicic 0:c0ecb8bf28eb 5921 V7_PRIVATE void gc_sweep(struct v7 *, struct gc_arena *, size_t);
Marko Mikulicic 0:c0ecb8bf28eb 5922 V7_PRIVATE void *gc_alloc_cell(struct v7 *, struct gc_arena *);
Marko Mikulicic 0:c0ecb8bf28eb 5923
Marko Mikulicic 0:c0ecb8bf28eb 5924 V7_PRIVATE struct gc_tmp_frame new_tmp_frame(struct v7 *);
Marko Mikulicic 0:c0ecb8bf28eb 5925 V7_PRIVATE void tmp_frame_cleanup(struct gc_tmp_frame *);
Marko Mikulicic 0:c0ecb8bf28eb 5926 V7_PRIVATE void tmp_stack_push(struct gc_tmp_frame *, val_t *);
Marko Mikulicic 0:c0ecb8bf28eb 5927
Marko Mikulicic 0:c0ecb8bf28eb 5928 V7_PRIVATE void compute_need_gc(struct v7 *);
Marko Mikulicic 0:c0ecb8bf28eb 5929 /* perform gc if not inhibited */
Marko Mikulicic 0:c0ecb8bf28eb 5930 V7_PRIVATE int maybe_gc(struct v7 *);
Marko Mikulicic 0:c0ecb8bf28eb 5931
Marko Mikulicic 0:c0ecb8bf28eb 5932 #ifndef V7_DISABLE_STR_ALLOC_SEQ
Marko Mikulicic 0:c0ecb8bf28eb 5933 V7_PRIVATE uint16_t
Marko Mikulicic 0:c0ecb8bf28eb 5934 gc_next_allocation_seqn(struct v7 *v7, const char *str, size_t len);
Marko Mikulicic 0:c0ecb8bf28eb 5935 V7_PRIVATE int gc_is_valid_allocation_seqn(struct v7 *v7, uint16_t n);
Marko Mikulicic 0:c0ecb8bf28eb 5936 V7_PRIVATE void gc_check_valid_allocation_seqn(struct v7 *v7, uint16_t n);
Marko Mikulicic 0:c0ecb8bf28eb 5937 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5938
Marko Mikulicic 0:c0ecb8bf28eb 5939 V7_PRIVATE uint64_t gc_string_val_to_offset(val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 5940
Marko Mikulicic 0:c0ecb8bf28eb 5941 /* return 0 if v is an object/function with a bad pointer */
Marko Mikulicic 0:c0ecb8bf28eb 5942 V7_PRIVATE int gc_check_val(struct v7 *v7, val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 5943
Marko Mikulicic 0:c0ecb8bf28eb 5944 /* checks whether a pointer is within the ranges of an arena */
Marko Mikulicic 0:c0ecb8bf28eb 5945 V7_PRIVATE int gc_check_ptr(const struct gc_arena *a, const void *p);
Marko Mikulicic 0:c0ecb8bf28eb 5946
Marko Mikulicic 0:c0ecb8bf28eb 5947 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 5948 V7_PRIVATE size_t gc_arena_size(struct gc_arena *);
Marko Mikulicic 0:c0ecb8bf28eb 5949 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5950
Marko Mikulicic 0:c0ecb8bf28eb 5951 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 5952 }
Marko Mikulicic 0:c0ecb8bf28eb 5953 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 5954
Marko Mikulicic 0:c0ecb8bf28eb 5955 #endif /* CS_V7_SRC_GC_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 5956 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 5957 #line 1 "v7/src/regexp_public.h"
Marko Mikulicic 0:c0ecb8bf28eb 5958 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5959 /*
Marko Mikulicic 0:c0ecb8bf28eb 5960 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 5961 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 5962 */
Marko Mikulicic 0:c0ecb8bf28eb 5963
Marko Mikulicic 0:c0ecb8bf28eb 5964 /*
Marko Mikulicic 0:c0ecb8bf28eb 5965 * === RegExp
Marko Mikulicic 0:c0ecb8bf28eb 5966 */
Marko Mikulicic 0:c0ecb8bf28eb 5967
Marko Mikulicic 0:c0ecb8bf28eb 5968 #ifndef CS_V7_SRC_REGEXP_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 5969 #define CS_V7_SRC_REGEXP_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 5970
Marko Mikulicic 0:c0ecb8bf28eb 5971 /* Amalgamated: #include "v7/src/core_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 5972
Marko Mikulicic 0:c0ecb8bf28eb 5973 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 5974 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 5975 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 5976
Marko Mikulicic 0:c0ecb8bf28eb 5977 /*
Marko Mikulicic 0:c0ecb8bf28eb 5978 * Make RegExp object.
Marko Mikulicic 0:c0ecb8bf28eb 5979 * `regex`, `regex_len` specify a pattern, `flags` and `flags_len` specify
Marko Mikulicic 0:c0ecb8bf28eb 5980 * flags. Both utf8 encoded. For example, `regex` is `(.+)`, `flags` is `gi`.
Marko Mikulicic 0:c0ecb8bf28eb 5981 * If `regex_len` is ~0, `regex` is assumed to be NUL-terminated and
Marko Mikulicic 0:c0ecb8bf28eb 5982 * `strlen(regex)` is used.
Marko Mikulicic 0:c0ecb8bf28eb 5983 */
Marko Mikulicic 0:c0ecb8bf28eb 5984 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 5985 enum v7_err v7_mk_regexp(struct v7 *v7, const char *regex, size_t regex_len,
Marko Mikulicic 0:c0ecb8bf28eb 5986 const char *flags, size_t flags_len, v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 5987
Marko Mikulicic 0:c0ecb8bf28eb 5988 /* Returns true if given value is a JavaScript RegExp object*/
Marko Mikulicic 0:c0ecb8bf28eb 5989 int v7_is_regexp(struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 5990
Marko Mikulicic 0:c0ecb8bf28eb 5991 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 5992 }
Marko Mikulicic 0:c0ecb8bf28eb 5993 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 5994
Marko Mikulicic 0:c0ecb8bf28eb 5995 #endif /* CS_V7_SRC_REGEXP_PUBLIC_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 5996 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 5997 #line 1 "v7/src/regexp.h"
Marko Mikulicic 0:c0ecb8bf28eb 5998 #endif
Marko Mikulicic 0:c0ecb8bf28eb 5999 /*
Marko Mikulicic 0:c0ecb8bf28eb 6000 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6001 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6002 */
Marko Mikulicic 0:c0ecb8bf28eb 6003
Marko Mikulicic 0:c0ecb8bf28eb 6004 #ifndef CS_V7_SRC_REGEXP_H_
Marko Mikulicic 0:c0ecb8bf28eb 6005 #define CS_V7_SRC_REGEXP_H_
Marko Mikulicic 0:c0ecb8bf28eb 6006
Marko Mikulicic 0:c0ecb8bf28eb 6007 /* Amalgamated: #include "v7/src/regexp_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6008
Marko Mikulicic 0:c0ecb8bf28eb 6009 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6010
Marko Mikulicic 0:c0ecb8bf28eb 6011 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 6012
Marko Mikulicic 0:c0ecb8bf28eb 6013 /*
Marko Mikulicic 0:c0ecb8bf28eb 6014 * Maximum number of flags returned by get_regexp_flags_str().
Marko Mikulicic 0:c0ecb8bf28eb 6015 * NOTE: does not include null-terminate byte.
Marko Mikulicic 0:c0ecb8bf28eb 6016 */
Marko Mikulicic 0:c0ecb8bf28eb 6017 #define _V7_REGEXP_MAX_FLAGS_LEN 3
Marko Mikulicic 0:c0ecb8bf28eb 6018
Marko Mikulicic 0:c0ecb8bf28eb 6019 struct v7_regexp;
Marko Mikulicic 0:c0ecb8bf28eb 6020
Marko Mikulicic 0:c0ecb8bf28eb 6021 V7_PRIVATE struct v7_regexp *v7_get_regexp_struct(struct v7 *, v7_val_t);
Marko Mikulicic 0:c0ecb8bf28eb 6022
Marko Mikulicic 0:c0ecb8bf28eb 6023 /*
Marko Mikulicic 0:c0ecb8bf28eb 6024 * Generates a string containing regexp flags, e.g. "gi".
Marko Mikulicic 0:c0ecb8bf28eb 6025 *
Marko Mikulicic 0:c0ecb8bf28eb 6026 * `buf` should point to a buffer of minimum `_V7_REGEXP_MAX_FLAGS_LEN` bytes.
Marko Mikulicic 0:c0ecb8bf28eb 6027 * Returns length of the resulted string (saved into `buf`)
Marko Mikulicic 0:c0ecb8bf28eb 6028 */
Marko Mikulicic 0:c0ecb8bf28eb 6029 V7_PRIVATE size_t
Marko Mikulicic 0:c0ecb8bf28eb 6030 get_regexp_flags_str(struct v7 *v7, struct v7_regexp *rp, char *buf);
Marko Mikulicic 0:c0ecb8bf28eb 6031 #endif /* V7_ENABLE__RegExp */
Marko Mikulicic 0:c0ecb8bf28eb 6032
Marko Mikulicic 0:c0ecb8bf28eb 6033 #endif /* CS_V7_SRC_REGEXP_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6034 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6035 #line 1 "v7/src/function_public.h"
Marko Mikulicic 0:c0ecb8bf28eb 6036 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6037 /*
Marko Mikulicic 0:c0ecb8bf28eb 6038 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6039 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6040 */
Marko Mikulicic 0:c0ecb8bf28eb 6041
Marko Mikulicic 0:c0ecb8bf28eb 6042 /*
Marko Mikulicic 0:c0ecb8bf28eb 6043 * === Functions
Marko Mikulicic 0:c0ecb8bf28eb 6044 */
Marko Mikulicic 0:c0ecb8bf28eb 6045
Marko Mikulicic 0:c0ecb8bf28eb 6046 #ifndef CS_V7_SRC_FUNCTION_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 6047 #define CS_V7_SRC_FUNCTION_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 6048
Marko Mikulicic 0:c0ecb8bf28eb 6049 /* Amalgamated: #include "v7/src/core_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6050
Marko Mikulicic 0:c0ecb8bf28eb 6051 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6052 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 6053 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6054
Marko Mikulicic 0:c0ecb8bf28eb 6055 /*
Marko Mikulicic 0:c0ecb8bf28eb 6056 * Make a JS function object backed by a cfunction.
Marko Mikulicic 0:c0ecb8bf28eb 6057 *
Marko Mikulicic 0:c0ecb8bf28eb 6058 * `func` is a C callback.
Marko Mikulicic 0:c0ecb8bf28eb 6059 *
Marko Mikulicic 0:c0ecb8bf28eb 6060 * A function object is JS object having the Function prototype that holds a
Marko Mikulicic 0:c0ecb8bf28eb 6061 * cfunction value in a hidden property.
Marko Mikulicic 0:c0ecb8bf28eb 6062 *
Marko Mikulicic 0:c0ecb8bf28eb 6063 * The function object will have a `prototype` property holding an object that
Marko Mikulicic 0:c0ecb8bf28eb 6064 * will be used as the prototype of objects created when calling the function
Marko Mikulicic 0:c0ecb8bf28eb 6065 * with the `new` operator.
Marko Mikulicic 0:c0ecb8bf28eb 6066 */
Marko Mikulicic 0:c0ecb8bf28eb 6067 v7_val_t v7_mk_function(struct v7 *, v7_cfunction_t *func);
Marko Mikulicic 0:c0ecb8bf28eb 6068
Marko Mikulicic 0:c0ecb8bf28eb 6069 /*
Marko Mikulicic 0:c0ecb8bf28eb 6070 * Make f a JS function with specified prototype `proto`, so that the resulting
Marko Mikulicic 0:c0ecb8bf28eb 6071 * function is better suited for the usage as a constructor.
Marko Mikulicic 0:c0ecb8bf28eb 6072 */
Marko Mikulicic 0:c0ecb8bf28eb 6073 v7_val_t v7_mk_function_with_proto(struct v7 *v7, v7_cfunction_t *f,
Marko Mikulicic 0:c0ecb8bf28eb 6074 v7_val_t proto);
Marko Mikulicic 0:c0ecb8bf28eb 6075
Marko Mikulicic 0:c0ecb8bf28eb 6076 /*
Marko Mikulicic 0:c0ecb8bf28eb 6077 * Make a JS value that holds C/C++ callback pointer.
Marko Mikulicic 0:c0ecb8bf28eb 6078 *
Marko Mikulicic 0:c0ecb8bf28eb 6079 * CAUTION: This is a low-level function value. It's not a real object and
Marko Mikulicic 0:c0ecb8bf28eb 6080 * cannot hold user defined properties. You should use `v7_mk_function` unless
Marko Mikulicic 0:c0ecb8bf28eb 6081 * you know what you're doing.
Marko Mikulicic 0:c0ecb8bf28eb 6082 */
Marko Mikulicic 0:c0ecb8bf28eb 6083 v7_val_t v7_mk_cfunction(v7_cfunction_t *func);
Marko Mikulicic 0:c0ecb8bf28eb 6084
Marko Mikulicic 0:c0ecb8bf28eb 6085 /*
Marko Mikulicic 0:c0ecb8bf28eb 6086 * Returns true if given value is callable (i.e. it's either a JS function or
Marko Mikulicic 0:c0ecb8bf28eb 6087 * cfunction)
Marko Mikulicic 0:c0ecb8bf28eb 6088 */
Marko Mikulicic 0:c0ecb8bf28eb 6089 int v7_is_callable(struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 6090
Marko Mikulicic 0:c0ecb8bf28eb 6091 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6092 }
Marko Mikulicic 0:c0ecb8bf28eb 6093 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6094
Marko Mikulicic 0:c0ecb8bf28eb 6095 #endif /* CS_V7_SRC_FUNCTION_PUBLIC_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6096 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6097 #line 1 "v7/src/function.h"
Marko Mikulicic 0:c0ecb8bf28eb 6098 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6099 /*
Marko Mikulicic 0:c0ecb8bf28eb 6100 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6101 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6102 */
Marko Mikulicic 0:c0ecb8bf28eb 6103
Marko Mikulicic 0:c0ecb8bf28eb 6104 #ifndef CS_V7_SRC_FUNCTION_H_
Marko Mikulicic 0:c0ecb8bf28eb 6105 #define CS_V7_SRC_FUNCTION_H_
Marko Mikulicic 0:c0ecb8bf28eb 6106
Marko Mikulicic 0:c0ecb8bf28eb 6107 /* Amalgamated: #include "v7/src/function_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6108
Marko Mikulicic 0:c0ecb8bf28eb 6109 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6110 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6111
Marko Mikulicic 0:c0ecb8bf28eb 6112 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6113 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 6114 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6115
Marko Mikulicic 0:c0ecb8bf28eb 6116 V7_PRIVATE struct v7_js_function *get_js_function_struct(val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 6117 V7_PRIVATE val_t
Marko Mikulicic 0:c0ecb8bf28eb 6118 mk_js_function(struct v7 *v7, struct v7_generic_object *scope, val_t proto);
Marko Mikulicic 0:c0ecb8bf28eb 6119 V7_PRIVATE int is_js_function(val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 6120 V7_PRIVATE v7_val_t mk_cfunction_lite(v7_cfunction_t *f);
Marko Mikulicic 0:c0ecb8bf28eb 6121
Marko Mikulicic 0:c0ecb8bf28eb 6122 /* Returns true if given value holds a pointer to C callback */
Marko Mikulicic 0:c0ecb8bf28eb 6123 V7_PRIVATE int is_cfunction_lite(v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 6124
Marko Mikulicic 0:c0ecb8bf28eb 6125 /* Returns true if given value holds an object which represents C callback */
Marko Mikulicic 0:c0ecb8bf28eb 6126 V7_PRIVATE int is_cfunction_obj(struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 6127
Marko Mikulicic 0:c0ecb8bf28eb 6128 /*
Marko Mikulicic 0:c0ecb8bf28eb 6129 * Returns `v7_cfunction_t *` callback pointer stored in `v7_val_t`, or NULL
Marko Mikulicic 0:c0ecb8bf28eb 6130 * if given value is neither cfunction pointer nor cfunction object.
Marko Mikulicic 0:c0ecb8bf28eb 6131 */
Marko Mikulicic 0:c0ecb8bf28eb 6132 V7_PRIVATE v7_cfunction_t *get_cfunction_ptr(struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 6133
Marko Mikulicic 0:c0ecb8bf28eb 6134 /*
Marko Mikulicic 0:c0ecb8bf28eb 6135 * Like v7_mk_function but also sets the function's `length` property.
Marko Mikulicic 0:c0ecb8bf28eb 6136 *
Marko Mikulicic 0:c0ecb8bf28eb 6137 * The `length` property is useful for introspection and the stdlib defines it
Marko Mikulicic 0:c0ecb8bf28eb 6138 * for many core functions mostly because the ECMA test suite requires it and we
Marko Mikulicic 0:c0ecb8bf28eb 6139 * don't want to skip otherwise useful tests just because the `length` property
Marko Mikulicic 0:c0ecb8bf28eb 6140 * check fails early in the test. User defined functions don't need to specify
Marko Mikulicic 0:c0ecb8bf28eb 6141 * the length and passing -1 is a safe choice, as it will also reduce the
Marko Mikulicic 0:c0ecb8bf28eb 6142 * footprint.
Marko Mikulicic 0:c0ecb8bf28eb 6143 *
Marko Mikulicic 0:c0ecb8bf28eb 6144 * The subtle difference between set `length` explicitly to 0 rather than
Marko Mikulicic 0:c0ecb8bf28eb 6145 * just defaulting the `0` value from the prototype is that in the former case
Marko Mikulicic 0:c0ecb8bf28eb 6146 * the property cannot be change since it's read only. This again, is important
Marko Mikulicic 0:c0ecb8bf28eb 6147 * only for ecma compliance and your user code might or might not find this
Marko Mikulicic 0:c0ecb8bf28eb 6148 * relevant.
Marko Mikulicic 0:c0ecb8bf28eb 6149 *
Marko Mikulicic 0:c0ecb8bf28eb 6150 * NODO(lsm): please don't combine v7_mk_function_arg and v7_mk_function
Marko Mikulicic 0:c0ecb8bf28eb 6151 * into one function. Currently `num_args` is useful only internally. External
Marko Mikulicic 0:c0ecb8bf28eb 6152 * users can just use `v7_def` to set the length.
Marko Mikulicic 0:c0ecb8bf28eb 6153 */
Marko Mikulicic 0:c0ecb8bf28eb 6154 V7_PRIVATE
Marko Mikulicic 0:c0ecb8bf28eb 6155 v7_val_t mk_cfunction_obj(struct v7 *v7, v7_cfunction_t *func, int num_args);
Marko Mikulicic 0:c0ecb8bf28eb 6156
Marko Mikulicic 0:c0ecb8bf28eb 6157 /*
Marko Mikulicic 0:c0ecb8bf28eb 6158 * Like v7_mk_function_with_proto but also sets the function's `length`
Marko Mikulicic 0:c0ecb8bf28eb 6159 *property.
Marko Mikulicic 0:c0ecb8bf28eb 6160 *
Marko Mikulicic 0:c0ecb8bf28eb 6161 * NODO(lsm): please don't combine mk_cfunction_obj_with_proto and
Marko Mikulicic 0:c0ecb8bf28eb 6162 * v7_mk_function_with_proto.
Marko Mikulicic 0:c0ecb8bf28eb 6163 * into one function. Currently `num_args` is useful only internally. External
Marko Mikulicic 0:c0ecb8bf28eb 6164 * users can just use `v7_def` to set the length.
Marko Mikulicic 0:c0ecb8bf28eb 6165 */
Marko Mikulicic 0:c0ecb8bf28eb 6166 V7_PRIVATE
Marko Mikulicic 0:c0ecb8bf28eb 6167 v7_val_t mk_cfunction_obj_with_proto(struct v7 *v7, v7_cfunction_t *f,
Marko Mikulicic 0:c0ecb8bf28eb 6168 int num_args, v7_val_t proto);
Marko Mikulicic 0:c0ecb8bf28eb 6169
Marko Mikulicic 0:c0ecb8bf28eb 6170 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6171 }
Marko Mikulicic 0:c0ecb8bf28eb 6172 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6173
Marko Mikulicic 0:c0ecb8bf28eb 6174 #endif /* CS_V7_SRC_FUNCTION_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6175 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6176 #line 1 "v7/src/util_public.h"
Marko Mikulicic 0:c0ecb8bf28eb 6177 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6178 /*
Marko Mikulicic 0:c0ecb8bf28eb 6179 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6180 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6181 */
Marko Mikulicic 0:c0ecb8bf28eb 6182
Marko Mikulicic 0:c0ecb8bf28eb 6183 /*
Marko Mikulicic 0:c0ecb8bf28eb 6184 * === Utility functions
Marko Mikulicic 0:c0ecb8bf28eb 6185 */
Marko Mikulicic 0:c0ecb8bf28eb 6186
Marko Mikulicic 0:c0ecb8bf28eb 6187 #ifndef CS_V7_SRC_UTIL_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 6188 #define CS_V7_SRC_UTIL_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 6189
Marko Mikulicic 0:c0ecb8bf28eb 6190 /* Amalgamated: #include "v7/src/core_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6191
Marko Mikulicic 0:c0ecb8bf28eb 6192 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6193 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 6194 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6195
Marko Mikulicic 0:c0ecb8bf28eb 6196 /* Output a string representation of the value to stdout.
Marko Mikulicic 0:c0ecb8bf28eb 6197 * V7_STRINGIFY_DEBUG mode is used. */
Marko Mikulicic 0:c0ecb8bf28eb 6198 void v7_print(struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 6199
Marko Mikulicic 0:c0ecb8bf28eb 6200 /* Output a string representation of the value to stdout followed by a newline.
Marko Mikulicic 0:c0ecb8bf28eb 6201 * V7_STRINGIFY_DEBUG mode is used. */
Marko Mikulicic 0:c0ecb8bf28eb 6202 void v7_println(struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 6203
Marko Mikulicic 0:c0ecb8bf28eb 6204 /* Output a string representation of the value to a file.
Marko Mikulicic 0:c0ecb8bf28eb 6205 * V7_STRINGIFY_DEBUG mode is used. */
Marko Mikulicic 0:c0ecb8bf28eb 6206 void v7_fprint(FILE *f, struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 6207
Marko Mikulicic 0:c0ecb8bf28eb 6208 /* Output a string representation of the value to a file followed by a newline.
Marko Mikulicic 0:c0ecb8bf28eb 6209 * V7_STRINGIFY_DEBUG mode is used. */
Marko Mikulicic 0:c0ecb8bf28eb 6210 void v7_fprintln(FILE *f, struct v7 *v7, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 6211
Marko Mikulicic 0:c0ecb8bf28eb 6212 /* Output stack trace recorded in the exception `e` to file `f` */
Marko Mikulicic 0:c0ecb8bf28eb 6213 void v7_fprint_stack_trace(FILE *f, struct v7 *v7, v7_val_t e);
Marko Mikulicic 0:c0ecb8bf28eb 6214
Marko Mikulicic 0:c0ecb8bf28eb 6215 /* Output error object message and possibly stack trace to f */
Marko Mikulicic 0:c0ecb8bf28eb 6216 void v7_print_error(FILE *f, struct v7 *v7, const char *ctx, v7_val_t e);
Marko Mikulicic 0:c0ecb8bf28eb 6217
Marko Mikulicic 0:c0ecb8bf28eb 6218 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 6219
Marko Mikulicic 0:c0ecb8bf28eb 6220 struct v7_property;
Marko Mikulicic 0:c0ecb8bf28eb 6221
Marko Mikulicic 0:c0ecb8bf28eb 6222 /*
Marko Mikulicic 0:c0ecb8bf28eb 6223 * C callback, analogue of JS callback `getOwnPropertyDescriptor()`.
Marko Mikulicic 0:c0ecb8bf28eb 6224 * Callbacks of this type are used for C API only, see `m7_mk_proxy()`.
Marko Mikulicic 0:c0ecb8bf28eb 6225 *
Marko Mikulicic 0:c0ecb8bf28eb 6226 * `name` is the name of the property, and the function should fill `attrs` and
Marko Mikulicic 0:c0ecb8bf28eb 6227 * `value` with the property data. Before this callback is called, `attrs` is
Marko Mikulicic 0:c0ecb8bf28eb 6228 * set to 0, and `value` is `V7_UNDEFINED`.
Marko Mikulicic 0:c0ecb8bf28eb 6229 *
Marko Mikulicic 0:c0ecb8bf28eb 6230 * It should return non-zero if the property should be considered existing, or
Marko Mikulicic 0:c0ecb8bf28eb 6231 * zero otherwise.
Marko Mikulicic 0:c0ecb8bf28eb 6232 *
Marko Mikulicic 0:c0ecb8bf28eb 6233 * You can inspect the property attributes with the `V7_PROP_ATTR_IS_*` macros.
Marko Mikulicic 0:c0ecb8bf28eb 6234 */
Marko Mikulicic 0:c0ecb8bf28eb 6235 typedef int(v7_get_own_prop_desc_cb_t)(struct v7 *v7, v7_val_t target,
Marko Mikulicic 0:c0ecb8bf28eb 6236 v7_val_t name, v7_prop_attr_t *attrs,
Marko Mikulicic 0:c0ecb8bf28eb 6237 v7_val_t *value);
Marko Mikulicic 0:c0ecb8bf28eb 6238
Marko Mikulicic 0:c0ecb8bf28eb 6239 /* Handler for `v7_mk_proxy()`; each item is a cfunction */
Marko Mikulicic 0:c0ecb8bf28eb 6240 typedef struct {
Marko Mikulicic 0:c0ecb8bf28eb 6241 v7_cfunction_t *get;
Marko Mikulicic 0:c0ecb8bf28eb 6242 v7_cfunction_t *set;
Marko Mikulicic 0:c0ecb8bf28eb 6243 v7_cfunction_t *own_keys;
Marko Mikulicic 0:c0ecb8bf28eb 6244 v7_get_own_prop_desc_cb_t *get_own_prop_desc;
Marko Mikulicic 0:c0ecb8bf28eb 6245 } v7_proxy_hnd_t;
Marko Mikulicic 0:c0ecb8bf28eb 6246
Marko Mikulicic 0:c0ecb8bf28eb 6247 /*
Marko Mikulicic 0:c0ecb8bf28eb 6248 * Create a Proxy object, see:
Marko Mikulicic 0:c0ecb8bf28eb 6249 * https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Proxy
Marko Mikulicic 0:c0ecb8bf28eb 6250 *
Marko Mikulicic 0:c0ecb8bf28eb 6251 * Only two traps are implemented so far: `get()` and `set()`. Note that
Marko Mikulicic 0:c0ecb8bf28eb 6252 * `Object.defineProperty()` bypasses the `set()` trap.
Marko Mikulicic 0:c0ecb8bf28eb 6253 *
Marko Mikulicic 0:c0ecb8bf28eb 6254 * If `target` is not an object, the empty object will be used, so it's safe
Marko Mikulicic 0:c0ecb8bf28eb 6255 * to pass `V7_UNDEFINED` as `target`.
Marko Mikulicic 0:c0ecb8bf28eb 6256 */
Marko Mikulicic 0:c0ecb8bf28eb 6257 v7_val_t v7_mk_proxy(struct v7 *v7, v7_val_t target,
Marko Mikulicic 0:c0ecb8bf28eb 6258 const v7_proxy_hnd_t *handler);
Marko Mikulicic 0:c0ecb8bf28eb 6259
Marko Mikulicic 0:c0ecb8bf28eb 6260 #endif /* V7_ENABLE__Proxy */
Marko Mikulicic 0:c0ecb8bf28eb 6261
Marko Mikulicic 0:c0ecb8bf28eb 6262 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6263 }
Marko Mikulicic 0:c0ecb8bf28eb 6264 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6265
Marko Mikulicic 0:c0ecb8bf28eb 6266 #endif /* CS_V7_SRC_UTIL_PUBLIC_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6267 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6268 #line 1 "v7/src/util.h"
Marko Mikulicic 0:c0ecb8bf28eb 6269 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6270 /*
Marko Mikulicic 0:c0ecb8bf28eb 6271 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6272 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6273 */
Marko Mikulicic 0:c0ecb8bf28eb 6274
Marko Mikulicic 0:c0ecb8bf28eb 6275 #ifndef CS_V7_SRC_UTIL_H_
Marko Mikulicic 0:c0ecb8bf28eb 6276 #define CS_V7_SRC_UTIL_H_
Marko Mikulicic 0:c0ecb8bf28eb 6277
Marko Mikulicic 0:c0ecb8bf28eb 6278 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6279 /* Amalgamated: #include "v7/src/util_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6280
Marko Mikulicic 0:c0ecb8bf28eb 6281 struct bcode;
Marko Mikulicic 0:c0ecb8bf28eb 6282
Marko Mikulicic 0:c0ecb8bf28eb 6283 V7_PRIVATE enum v7_type val_type(struct v7 *v7, val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 6284
Marko Mikulicic 0:c0ecb8bf28eb 6285 #ifndef V7_DISABLE_LINE_NUMBERS
Marko Mikulicic 0:c0ecb8bf28eb 6286 V7_PRIVATE uint8_t msb_lsb_swap(uint8_t b);
Marko Mikulicic 0:c0ecb8bf28eb 6287 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6288
Marko Mikulicic 0:c0ecb8bf28eb 6289 /*
Marko Mikulicic 0:c0ecb8bf28eb 6290 * At the moment, all other utility functions are public, and are declared in
Marko Mikulicic 0:c0ecb8bf28eb 6291 * `util_public.h`
Marko Mikulicic 0:c0ecb8bf28eb 6292 */
Marko Mikulicic 0:c0ecb8bf28eb 6293
Marko Mikulicic 0:c0ecb8bf28eb 6294 #endif /* CS_V7_SRC_UTIL_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6295 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6296 #line 1 "v7/src/shdata.h"
Marko Mikulicic 0:c0ecb8bf28eb 6297 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6298 /*
Marko Mikulicic 0:c0ecb8bf28eb 6299 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6300 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6301 */
Marko Mikulicic 0:c0ecb8bf28eb 6302
Marko Mikulicic 0:c0ecb8bf28eb 6303 /*
Marko Mikulicic 0:c0ecb8bf28eb 6304 * shdata (stands for "shared data") is a simple module that allows to have
Marko Mikulicic 0:c0ecb8bf28eb 6305 * reference count for an arbitrary payload data, which will be freed as
Marko Mikulicic 0:c0ecb8bf28eb 6306 * necessary. A poor man's shared_ptr.
Marko Mikulicic 0:c0ecb8bf28eb 6307 */
Marko Mikulicic 0:c0ecb8bf28eb 6308
Marko Mikulicic 0:c0ecb8bf28eb 6309 #ifndef CS_V7_SRC_SHDATA_H_
Marko Mikulicic 0:c0ecb8bf28eb 6310 #define CS_V7_SRC_SHDATA_H_
Marko Mikulicic 0:c0ecb8bf28eb 6311
Marko Mikulicic 0:c0ecb8bf28eb 6312 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6313
Marko Mikulicic 0:c0ecb8bf28eb 6314 #if !defined(V7_DISABLE_FILENAMES) && !defined(V7_DISABLE_LINE_NUMBERS)
Marko Mikulicic 0:c0ecb8bf28eb 6315 struct shdata {
Marko Mikulicic 0:c0ecb8bf28eb 6316 /* Reference count */
Marko Mikulicic 0:c0ecb8bf28eb 6317 uint8_t refcnt;
Marko Mikulicic 0:c0ecb8bf28eb 6318
Marko Mikulicic 0:c0ecb8bf28eb 6319 /*
Marko Mikulicic 0:c0ecb8bf28eb 6320 * Note: we'd use `unsigned char payload[];` here, but we can't, since this
Marko Mikulicic 0:c0ecb8bf28eb 6321 * feature was introduced in C99 only
Marko Mikulicic 0:c0ecb8bf28eb 6322 */
Marko Mikulicic 0:c0ecb8bf28eb 6323 };
Marko Mikulicic 0:c0ecb8bf28eb 6324
Marko Mikulicic 0:c0ecb8bf28eb 6325 /*
Marko Mikulicic 0:c0ecb8bf28eb 6326 * Allocate memory chunk of appropriate size, copy given `payload` data there,
Marko Mikulicic 0:c0ecb8bf28eb 6327 * retain (`shdata_retain()`), and return it.
Marko Mikulicic 0:c0ecb8bf28eb 6328 */
Marko Mikulicic 0:c0ecb8bf28eb 6329 V7_PRIVATE struct shdata *shdata_create(const void *payload, size_t size);
Marko Mikulicic 0:c0ecb8bf28eb 6330
Marko Mikulicic 0:c0ecb8bf28eb 6331 V7_PRIVATE struct shdata *shdata_create_from_string(const char *src);
Marko Mikulicic 0:c0ecb8bf28eb 6332
Marko Mikulicic 0:c0ecb8bf28eb 6333 /*
Marko Mikulicic 0:c0ecb8bf28eb 6334 * Increment reference count for the given shared data
Marko Mikulicic 0:c0ecb8bf28eb 6335 */
Marko Mikulicic 0:c0ecb8bf28eb 6336 V7_PRIVATE void shdata_retain(struct shdata *p);
Marko Mikulicic 0:c0ecb8bf28eb 6337
Marko Mikulicic 0:c0ecb8bf28eb 6338 /*
Marko Mikulicic 0:c0ecb8bf28eb 6339 * Decrement reference count for the given shared data
Marko Mikulicic 0:c0ecb8bf28eb 6340 */
Marko Mikulicic 0:c0ecb8bf28eb 6341 V7_PRIVATE void shdata_release(struct shdata *p);
Marko Mikulicic 0:c0ecb8bf28eb 6342
Marko Mikulicic 0:c0ecb8bf28eb 6343 /*
Marko Mikulicic 0:c0ecb8bf28eb 6344 * Get payload data
Marko Mikulicic 0:c0ecb8bf28eb 6345 */
Marko Mikulicic 0:c0ecb8bf28eb 6346 V7_PRIVATE void *shdata_get_payload(struct shdata *p);
Marko Mikulicic 0:c0ecb8bf28eb 6347
Marko Mikulicic 0:c0ecb8bf28eb 6348 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6349 #endif /* CS_V7_SRC_SHDATA_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6350 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6351 #line 1 "v7/src/eval.h"
Marko Mikulicic 0:c0ecb8bf28eb 6352 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6353 /*
Marko Mikulicic 0:c0ecb8bf28eb 6354 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6355 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6356 */
Marko Mikulicic 0:c0ecb8bf28eb 6357
Marko Mikulicic 0:c0ecb8bf28eb 6358 #ifndef CS_V7_SRC_EVAL_H_
Marko Mikulicic 0:c0ecb8bf28eb 6359 #define CS_V7_SRC_EVAL_H_
Marko Mikulicic 0:c0ecb8bf28eb 6360
Marko Mikulicic 0:c0ecb8bf28eb 6361 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6362 /* Amalgamated: #include "v7/src/bcode.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6363
Marko Mikulicic 0:c0ecb8bf28eb 6364 struct v7_call_frame_base;
Marko Mikulicic 0:c0ecb8bf28eb 6365
Marko Mikulicic 0:c0ecb8bf28eb 6366 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6367 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 6368 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6369
Marko Mikulicic 0:c0ecb8bf28eb 6370 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 6371 V7_PRIVATE enum v7_err eval_bcode(struct v7 *v7, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 6372 val_t this_object, uint8_t reset_line_no,
Marko Mikulicic 0:c0ecb8bf28eb 6373 val_t *_res);
Marko Mikulicic 0:c0ecb8bf28eb 6374
Marko Mikulicic 0:c0ecb8bf28eb 6375 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 6376 V7_PRIVATE enum v7_err b_apply(struct v7 *v7, v7_val_t func, v7_val_t this_obj,
Marko Mikulicic 0:c0ecb8bf28eb 6377 v7_val_t args, uint8_t is_constructor,
Marko Mikulicic 0:c0ecb8bf28eb 6378 v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 6379
Marko Mikulicic 0:c0ecb8bf28eb 6380 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 6381 V7_PRIVATE enum v7_err b_exec(struct v7 *v7, const char *src, size_t src_len,
Marko Mikulicic 0:c0ecb8bf28eb 6382 const char *filename, val_t func, val_t args,
Marko Mikulicic 0:c0ecb8bf28eb 6383 val_t this_object, int is_json, int fr,
Marko Mikulicic 0:c0ecb8bf28eb 6384 uint8_t is_constructor, val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 6385
Marko Mikulicic 0:c0ecb8bf28eb 6386 /*
Marko Mikulicic 0:c0ecb8bf28eb 6387 * Try to find the call frame whose `type_mask` intersects with the given
Marko Mikulicic 0:c0ecb8bf28eb 6388 * `type_mask`.
Marko Mikulicic 0:c0ecb8bf28eb 6389 *
Marko Mikulicic 0:c0ecb8bf28eb 6390 * Start from the top call frame, and go deeper until the matching frame is
Marko Mikulicic 0:c0ecb8bf28eb 6391 * found, or there's no more call frames. If the needed frame was not found,
Marko Mikulicic 0:c0ecb8bf28eb 6392 * returns `NULL`.
Marko Mikulicic 0:c0ecb8bf28eb 6393 */
Marko Mikulicic 0:c0ecb8bf28eb 6394 V7_PRIVATE struct v7_call_frame_base *find_call_frame(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 6395 uint8_t type_mask);
Marko Mikulicic 0:c0ecb8bf28eb 6396
Marko Mikulicic 0:c0ecb8bf28eb 6397 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6398 }
Marko Mikulicic 0:c0ecb8bf28eb 6399 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6400
Marko Mikulicic 0:c0ecb8bf28eb 6401 #endif /* CS_V7_SRC_EVAL_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6402 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6403 #line 1 "v7/src/compiler.h"
Marko Mikulicic 0:c0ecb8bf28eb 6404 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6405 /*
Marko Mikulicic 0:c0ecb8bf28eb 6406 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6407 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6408 */
Marko Mikulicic 0:c0ecb8bf28eb 6409
Marko Mikulicic 0:c0ecb8bf28eb 6410 #ifndef CS_V7_SRC_COMPILER_H_
Marko Mikulicic 0:c0ecb8bf28eb 6411 #define CS_V7_SRC_COMPILER_H_
Marko Mikulicic 0:c0ecb8bf28eb 6412
Marko Mikulicic 0:c0ecb8bf28eb 6413 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6414 /* Amalgamated: #include "v7/src/bcode.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6415 /* Amalgamated: #include "v7/src/ast.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6416
Marko Mikulicic 0:c0ecb8bf28eb 6417 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 6418
Marko Mikulicic 0:c0ecb8bf28eb 6419 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6420 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 6421 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6422
Marko Mikulicic 0:c0ecb8bf28eb 6423 V7_PRIVATE enum v7_err compile_script(struct v7 *v7, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 6424 struct bcode *bcode);
Marko Mikulicic 0:c0ecb8bf28eb 6425
Marko Mikulicic 0:c0ecb8bf28eb 6426 V7_PRIVATE enum v7_err compile_expr(struct v7 *v7, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 6427 ast_off_t *ppos, struct bcode *bcode);
Marko Mikulicic 0:c0ecb8bf28eb 6428
Marko Mikulicic 0:c0ecb8bf28eb 6429 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6430 }
Marko Mikulicic 0:c0ecb8bf28eb 6431 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6432
Marko Mikulicic 0:c0ecb8bf28eb 6433 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 6434
Marko Mikulicic 0:c0ecb8bf28eb 6435 #endif /* CS_V7_SRC_COMPILER_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6436 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6437 #line 1 "v7/src/cyg_profile.h"
Marko Mikulicic 0:c0ecb8bf28eb 6438 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6439 /*
Marko Mikulicic 0:c0ecb8bf28eb 6440 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6441 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6442 */
Marko Mikulicic 0:c0ecb8bf28eb 6443
Marko Mikulicic 0:c0ecb8bf28eb 6444 #ifndef CS_V7_SRC_CYG_PROFILE_H_
Marko Mikulicic 0:c0ecb8bf28eb 6445 #define CS_V7_SRC_CYG_PROFILE_H_
Marko Mikulicic 0:c0ecb8bf28eb 6446
Marko Mikulicic 0:c0ecb8bf28eb 6447 /*
Marko Mikulicic 0:c0ecb8bf28eb 6448 * This file contains GCC/clang instrumentation callbacks, as well as
Marko Mikulicic 0:c0ecb8bf28eb 6449 * accompanying code. The actual code in these callbacks depends on enabled
Marko Mikulicic 0:c0ecb8bf28eb 6450 * features. See cyg_profile.c for some implementation details rationale.
Marko Mikulicic 0:c0ecb8bf28eb 6451 */
Marko Mikulicic 0:c0ecb8bf28eb 6452
Marko Mikulicic 0:c0ecb8bf28eb 6453 struct v7;
Marko Mikulicic 0:c0ecb8bf28eb 6454
Marko Mikulicic 0:c0ecb8bf28eb 6455 #if defined(V7_ENABLE_STACK_TRACKING)
Marko Mikulicic 0:c0ecb8bf28eb 6456
Marko Mikulicic 0:c0ecb8bf28eb 6457 /*
Marko Mikulicic 0:c0ecb8bf28eb 6458 * Stack-tracking functionality:
Marko Mikulicic 0:c0ecb8bf28eb 6459 *
Marko Mikulicic 0:c0ecb8bf28eb 6460 * The idea is that the caller should allocate `struct stack_track_ctx`
Marko Mikulicic 0:c0ecb8bf28eb 6461 * (typically on stack) in the function to track the stack usage of, and call
Marko Mikulicic 0:c0ecb8bf28eb 6462 * `v7_stack_track_start()` in the beginning.
Marko Mikulicic 0:c0ecb8bf28eb 6463 *
Marko Mikulicic 0:c0ecb8bf28eb 6464 * Before quitting current stack frame (for example, before returning from
Marko Mikulicic 0:c0ecb8bf28eb 6465 * function), call `v7_stack_track_end()`, which returns the maximum stack
Marko Mikulicic 0:c0ecb8bf28eb 6466 * consumed size.
Marko Mikulicic 0:c0ecb8bf28eb 6467 *
Marko Mikulicic 0:c0ecb8bf28eb 6468 * These calls can be nested: for example, we may track the stack usage of the
Marko Mikulicic 0:c0ecb8bf28eb 6469 * whole application by using these functions in `main()`, as well as track
Marko Mikulicic 0:c0ecb8bf28eb 6470 * stack usage of any nested functions.
Marko Mikulicic 0:c0ecb8bf28eb 6471 *
Marko Mikulicic 0:c0ecb8bf28eb 6472 * Just to stress: both `v7_stack_track_start()` / `v7_stack_track_end()`
Marko Mikulicic 0:c0ecb8bf28eb 6473 * should be called for the same instance of `struct stack_track_ctx` in the
Marko Mikulicic 0:c0ecb8bf28eb 6474 * same stack frame.
Marko Mikulicic 0:c0ecb8bf28eb 6475 */
Marko Mikulicic 0:c0ecb8bf28eb 6476
Marko Mikulicic 0:c0ecb8bf28eb 6477 /* stack tracking context */
Marko Mikulicic 0:c0ecb8bf28eb 6478 struct stack_track_ctx {
Marko Mikulicic 0:c0ecb8bf28eb 6479 struct stack_track_ctx *next;
Marko Mikulicic 0:c0ecb8bf28eb 6480 void *start;
Marko Mikulicic 0:c0ecb8bf28eb 6481 void *max;
Marko Mikulicic 0:c0ecb8bf28eb 6482 };
Marko Mikulicic 0:c0ecb8bf28eb 6483
Marko Mikulicic 0:c0ecb8bf28eb 6484 /* see explanation above */
Marko Mikulicic 0:c0ecb8bf28eb 6485 void v7_stack_track_start(struct v7 *v7, struct stack_track_ctx *ctx);
Marko Mikulicic 0:c0ecb8bf28eb 6486 /* see explanation above */
Marko Mikulicic 0:c0ecb8bf28eb 6487 int v7_stack_track_end(struct v7 *v7, struct stack_track_ctx *ctx);
Marko Mikulicic 0:c0ecb8bf28eb 6488
Marko Mikulicic 0:c0ecb8bf28eb 6489 void v7_stack_stat_clean(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 6490
Marko Mikulicic 0:c0ecb8bf28eb 6491 #endif /* V7_ENABLE_STACK_TRACKING */
Marko Mikulicic 0:c0ecb8bf28eb 6492
Marko Mikulicic 0:c0ecb8bf28eb 6493 #endif /* CS_V7_SRC_CYG_PROFILE_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6494 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6495 #line 1 "v7/builtin/builtin.h"
Marko Mikulicic 0:c0ecb8bf28eb 6496 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6497 /*
Marko Mikulicic 0:c0ecb8bf28eb 6498 * Copyright (c) 2015 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6499 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6500 */
Marko Mikulicic 0:c0ecb8bf28eb 6501
Marko Mikulicic 0:c0ecb8bf28eb 6502 /*
Marko Mikulicic 0:c0ecb8bf28eb 6503 * === Non-Standard API
Marko Mikulicic 0:c0ecb8bf28eb 6504 *
Marko Mikulicic 0:c0ecb8bf28eb 6505 * V7 has several non-standard extensions for `String.prototype` in
Marko Mikulicic 0:c0ecb8bf28eb 6506 * order to give a compact and fast API to access raw data obtained from
Marko Mikulicic 0:c0ecb8bf28eb 6507 * File, Socket, and hardware input/output such as I2C.
Marko Mikulicic 0:c0ecb8bf28eb 6508 * V7 IO API functions return
Marko Mikulicic 0:c0ecb8bf28eb 6509 * string data as a result of read operations, and that string data is a
Marko Mikulicic 0:c0ecb8bf28eb 6510 * raw byte array. ECMA6 provides `ArrayBuffer` and `DataView` API for dealing
Marko Mikulicic 0:c0ecb8bf28eb 6511 * with raw bytes, because strings in JavaScript are Unicode. That standard
Marko Mikulicic 0:c0ecb8bf28eb 6512 * API is too bloated for the embedded use, and does not allow to use handy
Marko Mikulicic 0:c0ecb8bf28eb 6513 * String API (e.g. `.match()`) against data.
Marko Mikulicic 0:c0ecb8bf28eb 6514 *
Marko Mikulicic 0:c0ecb8bf28eb 6515 * V7 internally stores strings as byte arrays. All strings created by the
Marko Mikulicic 0:c0ecb8bf28eb 6516 * String API are UTF8 encoded. Strings that are the result of
Marko Mikulicic 0:c0ecb8bf28eb 6517 * input/output API calls might not be a valid UTF8 strings, but nevertheless
Marko Mikulicic 0:c0ecb8bf28eb 6518 * they are represented as strings, and the following API allows to access
Marko Mikulicic 0:c0ecb8bf28eb 6519 * underlying byte sequence:
Marko Mikulicic 0:c0ecb8bf28eb 6520 *
Marko Mikulicic 0:c0ecb8bf28eb 6521 * ==== String.prototype.at(position) -> number or NaN
Marko Mikulicic 0:c0ecb8bf28eb 6522 * Return byte at index
Marko Mikulicic 0:c0ecb8bf28eb 6523 * `position`. Byte value is in 0,255 range. If `position` is out of bounds
Marko Mikulicic 0:c0ecb8bf28eb 6524 * (either negative or larger then the byte array length), NaN is returned.
Marko Mikulicic 0:c0ecb8bf28eb 6525 * Example: `"ы".at(0)` returns 0xd1.
Marko Mikulicic 0:c0ecb8bf28eb 6526 *
Marko Mikulicic 0:c0ecb8bf28eb 6527 * ==== String.prototype.blen -> number
Marko Mikulicic 0:c0ecb8bf28eb 6528 * Return string length in bytes.
Marko Mikulicic 0:c0ecb8bf28eb 6529 * Example: `"ы".blen` returns 2. Note that `"ы".length` is 1, since that
Marko Mikulicic 0:c0ecb8bf28eb 6530 * string consists of a single Unicode character (2-byte).
Marko Mikulicic 0:c0ecb8bf28eb 6531 *
Marko Mikulicic 0:c0ecb8bf28eb 6532 * === Builtin API
Marko Mikulicic 0:c0ecb8bf28eb 6533 *
Marko Mikulicic 0:c0ecb8bf28eb 6534 * Builtin API provides additional JavaScript interfaces available for V7
Marko Mikulicic 0:c0ecb8bf28eb 6535 * scripts.
Marko Mikulicic 0:c0ecb8bf28eb 6536 * File API is a wrapper around standard C calls `fopen()`, `fclose()`,
Marko Mikulicic 0:c0ecb8bf28eb 6537 * `fread()`, `fwrite()`, `rename()`, `remove()`.
Marko Mikulicic 0:c0ecb8bf28eb 6538 * Crypto API provides functions for base64, md5, and sha1 encoding/decoding.
Marko Mikulicic 0:c0ecb8bf28eb 6539 * Socket API provides low-level socket API.
Marko Mikulicic 0:c0ecb8bf28eb 6540 *
Marko Mikulicic 0:c0ecb8bf28eb 6541 * ==== File.eval(file_name)
Marko Mikulicic 0:c0ecb8bf28eb 6542 * Parse and run `file_name`.
Marko Mikulicic 0:c0ecb8bf28eb 6543 * Throws an exception if the file doesn't exist, cannot be parsed or if the
Marko Mikulicic 0:c0ecb8bf28eb 6544 * script throws any exception.
Marko Mikulicic 0:c0ecb8bf28eb 6545 *
Marko Mikulicic 0:c0ecb8bf28eb 6546 * ==== File.read(file_name) -> string or undefined
Marko Mikulicic 0:c0ecb8bf28eb 6547 * Read file `file_name` and return a string with a file content.
Marko Mikulicic 0:c0ecb8bf28eb 6548 * On any error, return `undefined` as a result.
Marko Mikulicic 0:c0ecb8bf28eb 6549 *
Marko Mikulicic 0:c0ecb8bf28eb 6550 * ==== File.write(file_name, str) -> true or false
Marko Mikulicic 0:c0ecb8bf28eb 6551 * Write string `str` to a file `file_name`. Return `true` on success,
Marko Mikulicic 0:c0ecb8bf28eb 6552 * `false` on error.
Marko Mikulicic 0:c0ecb8bf28eb 6553 *
Marko Mikulicic 0:c0ecb8bf28eb 6554 * ==== File.open(file_name [, mode]) -> file_object or null
Marko Mikulicic 0:c0ecb8bf28eb 6555 * Open a file `path`. For
Marko Mikulicic 0:c0ecb8bf28eb 6556 * list of valid `mode` values, see `fopen()` documentation. If `mode` is
Marko Mikulicic 0:c0ecb8bf28eb 6557 * not specified, mode `rb` is used, i.e. file is opened in read-only mode.
Marko Mikulicic 0:c0ecb8bf28eb 6558 * Return an opened file object, or null on error. Example:
Marko Mikulicic 0:c0ecb8bf28eb 6559 * `var f = File.open('/etc/passwd'); f.close();`
Marko Mikulicic 0:c0ecb8bf28eb 6560 *
Marko Mikulicic 0:c0ecb8bf28eb 6561 * ==== file_obj.close() -> undefined
Marko Mikulicic 0:c0ecb8bf28eb 6562 * Close opened file object.
Marko Mikulicic 0:c0ecb8bf28eb 6563 * NOTE: it is user's responsibility to close all opened file streams. V7
Marko Mikulicic 0:c0ecb8bf28eb 6564 * does not do that automatically.
Marko Mikulicic 0:c0ecb8bf28eb 6565 *
Marko Mikulicic 0:c0ecb8bf28eb 6566 * ==== file_obj.read() -> string
Marko Mikulicic 0:c0ecb8bf28eb 6567 * Read portion of data from
Marko Mikulicic 0:c0ecb8bf28eb 6568 * an opened file stream. Return string with data, or empty string on EOF
Marko Mikulicic 0:c0ecb8bf28eb 6569 * or error.
Marko Mikulicic 0:c0ecb8bf28eb 6570 *
Marko Mikulicic 0:c0ecb8bf28eb 6571 * ==== file_obj.write(str) -> num_bytes_written
Marko Mikulicic 0:c0ecb8bf28eb 6572 * Write string `str` to the opened file object. Return number of bytes written.
Marko Mikulicic 0:c0ecb8bf28eb 6573 *
Marko Mikulicic 0:c0ecb8bf28eb 6574 * ==== File.rename(old_name, new_name) -> errno
Marko Mikulicic 0:c0ecb8bf28eb 6575 * Rename file `old_name` to
Marko Mikulicic 0:c0ecb8bf28eb 6576 * `new_name`. Return 0 on success, or `errno` value on error.
Marko Mikulicic 0:c0ecb8bf28eb 6577 *
Marko Mikulicic 0:c0ecb8bf28eb 6578 * ==== File.list(dir_name) -> array_of_names
Marko Mikulicic 0:c0ecb8bf28eb 6579 * Return a list of files in a given directory, or `undefined` on error.
Marko Mikulicic 0:c0ecb8bf28eb 6580 *
Marko Mikulicic 0:c0ecb8bf28eb 6581 * ==== File.remove(file_name) -> errno
Marko Mikulicic 0:c0ecb8bf28eb 6582 * Delete file `file_name`.
Marko Mikulicic 0:c0ecb8bf28eb 6583 * Return 0 on success, or `errno` value on error.
Marko Mikulicic 0:c0ecb8bf28eb 6584 *
Marko Mikulicic 0:c0ecb8bf28eb 6585 * ==== Crypto.base64_encode(str)
Marko Mikulicic 0:c0ecb8bf28eb 6586 * Base64-encode input string `str` and return encoded string.
Marko Mikulicic 0:c0ecb8bf28eb 6587 *
Marko Mikulicic 0:c0ecb8bf28eb 6588 * ==== Crypto.base64_decode(str)
Marko Mikulicic 0:c0ecb8bf28eb 6589 * Base64-decode input string `str` and return decoded string.
Marko Mikulicic 0:c0ecb8bf28eb 6590 *
Marko Mikulicic 0:c0ecb8bf28eb 6591 * ==== Crypto.md5(str), Crypto.md5_hex(str)
Marko Mikulicic 0:c0ecb8bf28eb 6592 * Generate MD5 hash from input string `str`. Return 16-byte hash (`md5()`),
Marko Mikulicic 0:c0ecb8bf28eb 6593 * or stringified hexadecimal representation of the hash (`md5_hex`).
Marko Mikulicic 0:c0ecb8bf28eb 6594 *
Marko Mikulicic 0:c0ecb8bf28eb 6595 * ==== Crypto.sha1(str), Crypto.sha1_hex(str)
Marko Mikulicic 0:c0ecb8bf28eb 6596 * Generate SHA1 hash from input string `str`. Return 20-byte hash (`sha1()`),
Marko Mikulicic 0:c0ecb8bf28eb 6597 * or stringified hexadecimal representation of the hash (`sha1_hex`).
Marko Mikulicic 0:c0ecb8bf28eb 6598 *
Marko Mikulicic 0:c0ecb8bf28eb 6599 * ==== Socket.connect(host, port [, is_udp]) -> socket_obj
Marko Mikulicic 0:c0ecb8bf28eb 6600 * Connect to a given host. `host` can be a string IP address, or a host name.
Marko Mikulicic 0:c0ecb8bf28eb 6601 * Optional `is_udp` parameter, if true, indicates that socket should be UDP.
Marko Mikulicic 0:c0ecb8bf28eb 6602 * Return socket object on success, null on error.
Marko Mikulicic 0:c0ecb8bf28eb 6603 *
Marko Mikulicic 0:c0ecb8bf28eb 6604 * ==== Socket.listen(port [, ip_address [,is_udp]]) -> socket_obj
Marko Mikulicic 0:c0ecb8bf28eb 6605 * Create a listening socket on a given port. Optional `ip_address` argument
Marko Mikulicic 0:c0ecb8bf28eb 6606 * specifies and IP address to bind to. Optional `is_udp` parameter, if true,
Marko Mikulicic 0:c0ecb8bf28eb 6607 * indicates that socket should be UDP. Return socket object on success,
Marko Mikulicic 0:c0ecb8bf28eb 6608 * null on error.
Marko Mikulicic 0:c0ecb8bf28eb 6609 *
Marko Mikulicic 0:c0ecb8bf28eb 6610 * ==== socket_obj.accept() -> socket_obj
Marko Mikulicic 0:c0ecb8bf28eb 6611 * Sleep until new incoming connection is arrived. Return accepted socket
Marko Mikulicic 0:c0ecb8bf28eb 6612 * object on success, or `null` on error.
Marko Mikulicic 0:c0ecb8bf28eb 6613 *
Marko Mikulicic 0:c0ecb8bf28eb 6614 * ==== socket_obj.close() -> numeric_errno
Marko Mikulicic 0:c0ecb8bf28eb 6615 * Close socket object. Return 0 on success, or system errno on error.
Marko Mikulicic 0:c0ecb8bf28eb 6616 *
Marko Mikulicic 0:c0ecb8bf28eb 6617 * ==== socket_obj.recv() -> string
Marko Mikulicic 0:c0ecb8bf28eb 6618 * Read data from socket. Return data string, or empty string if peer has
Marko Mikulicic 0:c0ecb8bf28eb 6619 * disconnected, or `null` on error.
Marko Mikulicic 0:c0ecb8bf28eb 6620 *
Marko Mikulicic 0:c0ecb8bf28eb 6621 * ==== socket_obj.recvAll() -> string
Marko Mikulicic 0:c0ecb8bf28eb 6622 * Same as `recv()`, but keeps reading data until socket is closed.
Marko Mikulicic 0:c0ecb8bf28eb 6623 *
Marko Mikulicic 0:c0ecb8bf28eb 6624 * ==== sock.send(string) -> num_bytes_sent
Marko Mikulicic 0:c0ecb8bf28eb 6625 * Send string to the socket. Return number of bytes sent, or 0 on error.
Marko Mikulicic 0:c0ecb8bf28eb 6626 * Simple HTTP client example:
Marko Mikulicic 0:c0ecb8bf28eb 6627 *
Marko Mikulicic 0:c0ecb8bf28eb 6628 * var s = Socket.connect("google.com", 80);
Marko Mikulicic 0:c0ecb8bf28eb 6629 * s.send("GET / HTTP/1.0\n\n");
Marko Mikulicic 0:c0ecb8bf28eb 6630 * var reply = s.recv();
Marko Mikulicic 0:c0ecb8bf28eb 6631 */
Marko Mikulicic 0:c0ecb8bf28eb 6632
Marko Mikulicic 0:c0ecb8bf28eb 6633 #ifndef CS_V7_BUILTIN_BUILTIN_H_
Marko Mikulicic 0:c0ecb8bf28eb 6634 #define CS_V7_BUILTIN_BUILTIN_H_
Marko Mikulicic 0:c0ecb8bf28eb 6635
Marko Mikulicic 0:c0ecb8bf28eb 6636 struct v7;
Marko Mikulicic 0:c0ecb8bf28eb 6637
Marko Mikulicic 0:c0ecb8bf28eb 6638 void init_file(struct v7 *);
Marko Mikulicic 0:c0ecb8bf28eb 6639 void init_socket(struct v7 *);
Marko Mikulicic 0:c0ecb8bf28eb 6640 void init_crypto(struct v7 *);
Marko Mikulicic 0:c0ecb8bf28eb 6641
Marko Mikulicic 0:c0ecb8bf28eb 6642 #endif /* CS_V7_BUILTIN_BUILTIN_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6643 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6644 #line 1 "v7/src/slre.h"
Marko Mikulicic 0:c0ecb8bf28eb 6645 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6646 /*
Marko Mikulicic 0:c0ecb8bf28eb 6647 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6648 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6649 *
Marko Mikulicic 0:c0ecb8bf28eb 6650 * This software is dual-licensed: you can redistribute it and/or modify
Marko Mikulicic 0:c0ecb8bf28eb 6651 * it under the terms of the GNU General Public License version 2 as
Marko Mikulicic 0:c0ecb8bf28eb 6652 * published by the Free Software Foundation. For the terms of this
Marko Mikulicic 0:c0ecb8bf28eb 6653 * license, see <http://www.gnu.org/licenses/>.
Marko Mikulicic 0:c0ecb8bf28eb 6654 *
Marko Mikulicic 0:c0ecb8bf28eb 6655 * You are free to use this software under the terms of the GNU General
Marko Mikulicic 0:c0ecb8bf28eb 6656 * Public License, but WITHOUT ANY WARRANTY; without even the implied
Marko Mikulicic 0:c0ecb8bf28eb 6657 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Marko Mikulicic 0:c0ecb8bf28eb 6658 * See the GNU General Public License for more details.
Marko Mikulicic 0:c0ecb8bf28eb 6659 *
Marko Mikulicic 0:c0ecb8bf28eb 6660 * Alternatively, you can license this software under a commercial
Marko Mikulicic 0:c0ecb8bf28eb 6661 * license, as set out in <https://www.cesanta.com/license>.
Marko Mikulicic 0:c0ecb8bf28eb 6662 */
Marko Mikulicic 0:c0ecb8bf28eb 6663
Marko Mikulicic 0:c0ecb8bf28eb 6664 #ifndef CS_V7_SRC_SLRE_H_
Marko Mikulicic 0:c0ecb8bf28eb 6665 #define CS_V7_SRC_SLRE_H_
Marko Mikulicic 0:c0ecb8bf28eb 6666
Marko Mikulicic 0:c0ecb8bf28eb 6667 /* Return codes for slre_compile() */
Marko Mikulicic 0:c0ecb8bf28eb 6668 enum slre_error {
Marko Mikulicic 0:c0ecb8bf28eb 6669 SLRE_OK,
Marko Mikulicic 0:c0ecb8bf28eb 6670 SLRE_INVALID_DEC_DIGIT,
Marko Mikulicic 0:c0ecb8bf28eb 6671 SLRE_INVALID_HEX_DIGIT,
Marko Mikulicic 0:c0ecb8bf28eb 6672 SLRE_INVALID_ESC_CHAR,
Marko Mikulicic 0:c0ecb8bf28eb 6673 SLRE_UNTERM_ESC_SEQ,
Marko Mikulicic 0:c0ecb8bf28eb 6674 SLRE_SYNTAX_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 6675 SLRE_UNMATCH_LBR,
Marko Mikulicic 0:c0ecb8bf28eb 6676 SLRE_UNMATCH_RBR,
Marko Mikulicic 0:c0ecb8bf28eb 6677 SLRE_NUM_OVERFLOW,
Marko Mikulicic 0:c0ecb8bf28eb 6678 SLRE_INF_LOOP_M_EMP_STR,
Marko Mikulicic 0:c0ecb8bf28eb 6679 SLRE_TOO_MANY_CHARSETS,
Marko Mikulicic 0:c0ecb8bf28eb 6680 SLRE_INV_CHARSET_RANGE,
Marko Mikulicic 0:c0ecb8bf28eb 6681 SLRE_CHARSET_TOO_LARGE,
Marko Mikulicic 0:c0ecb8bf28eb 6682 SLRE_MALFORMED_CHARSET,
Marko Mikulicic 0:c0ecb8bf28eb 6683 SLRE_INVALID_BACK_REFERENCE,
Marko Mikulicic 0:c0ecb8bf28eb 6684 SLRE_TOO_MANY_CAPTURES,
Marko Mikulicic 0:c0ecb8bf28eb 6685 SLRE_INVALID_QUANTIFIER,
Marko Mikulicic 0:c0ecb8bf28eb 6686 SLRE_BAD_CHAR_AFTER_USD
Marko Mikulicic 0:c0ecb8bf28eb 6687 };
Marko Mikulicic 0:c0ecb8bf28eb 6688
Marko Mikulicic 0:c0ecb8bf28eb 6689 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 6690
Marko Mikulicic 0:c0ecb8bf28eb 6691 #ifdef __cplusplus
Marko Mikulicic 0:c0ecb8bf28eb 6692 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 6693 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6694
Marko Mikulicic 0:c0ecb8bf28eb 6695 /* Regex flags */
Marko Mikulicic 0:c0ecb8bf28eb 6696 #define SLRE_FLAG_G 1 /* Global - match in the whole string */
Marko Mikulicic 0:c0ecb8bf28eb 6697 #define SLRE_FLAG_I 2 /* Ignore case */
Marko Mikulicic 0:c0ecb8bf28eb 6698 #define SLRE_FLAG_M 4 /* Multiline */
Marko Mikulicic 0:c0ecb8bf28eb 6699 #define SLRE_FLAG_RE 8 /* flag RegExp/String */
Marko Mikulicic 0:c0ecb8bf28eb 6700
Marko Mikulicic 0:c0ecb8bf28eb 6701 /* Describes single capture */
Marko Mikulicic 0:c0ecb8bf28eb 6702 struct slre_cap {
Marko Mikulicic 0:c0ecb8bf28eb 6703 const char *start; /* points to the beginning of the capture group */
Marko Mikulicic 0:c0ecb8bf28eb 6704 const char *end; /* points to the end of the capture group */
Marko Mikulicic 0:c0ecb8bf28eb 6705 };
Marko Mikulicic 0:c0ecb8bf28eb 6706
Marko Mikulicic 0:c0ecb8bf28eb 6707 /* Describes all captures */
Marko Mikulicic 0:c0ecb8bf28eb 6708 #define SLRE_MAX_CAPS 32
Marko Mikulicic 0:c0ecb8bf28eb 6709 struct slre_loot {
Marko Mikulicic 0:c0ecb8bf28eb 6710 int num_captures;
Marko Mikulicic 0:c0ecb8bf28eb 6711 struct slre_cap caps[SLRE_MAX_CAPS];
Marko Mikulicic 0:c0ecb8bf28eb 6712 };
Marko Mikulicic 0:c0ecb8bf28eb 6713
Marko Mikulicic 0:c0ecb8bf28eb 6714 /* Opaque structure that holds compiled regular expression */
Marko Mikulicic 0:c0ecb8bf28eb 6715 struct slre_prog;
Marko Mikulicic 0:c0ecb8bf28eb 6716
Marko Mikulicic 0:c0ecb8bf28eb 6717 int slre_compile(const char *regexp, size_t regexp_len, const char *flags,
Marko Mikulicic 0:c0ecb8bf28eb 6718 size_t flags_len, struct slre_prog **, int is_regex);
Marko Mikulicic 0:c0ecb8bf28eb 6719 int slre_exec(struct slre_prog *prog, int flag_g, const char *start,
Marko Mikulicic 0:c0ecb8bf28eb 6720 const char *end, struct slre_loot *loot);
Marko Mikulicic 0:c0ecb8bf28eb 6721 void slre_free(struct slre_prog *prog);
Marko Mikulicic 0:c0ecb8bf28eb 6722
Marko Mikulicic 0:c0ecb8bf28eb 6723 int slre_match(const char *, size_t, const char *, size_t, const char *, size_t,
Marko Mikulicic 0:c0ecb8bf28eb 6724 struct slre_loot *);
Marko Mikulicic 0:c0ecb8bf28eb 6725 int slre_replace(struct slre_loot *loot, const char *src, size_t src_len,
Marko Mikulicic 0:c0ecb8bf28eb 6726 const char *replace, size_t rep_len, struct slre_loot *dst);
Marko Mikulicic 0:c0ecb8bf28eb 6727 int slre_get_flags(struct slre_prog *);
Marko Mikulicic 0:c0ecb8bf28eb 6728
Marko Mikulicic 0:c0ecb8bf28eb 6729 #ifdef __cplusplus
Marko Mikulicic 0:c0ecb8bf28eb 6730 }
Marko Mikulicic 0:c0ecb8bf28eb 6731 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6732
Marko Mikulicic 0:c0ecb8bf28eb 6733 #endif /* V7_ENABLE__RegExp */
Marko Mikulicic 0:c0ecb8bf28eb 6734
Marko Mikulicic 0:c0ecb8bf28eb 6735 #endif /* CS_V7_SRC_SLRE_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6736 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6737 #line 1 "v7/src/stdlib.h"
Marko Mikulicic 0:c0ecb8bf28eb 6738 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6739 /*
Marko Mikulicic 0:c0ecb8bf28eb 6740 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6741 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6742 */
Marko Mikulicic 0:c0ecb8bf28eb 6743
Marko Mikulicic 0:c0ecb8bf28eb 6744 #ifndef CS_V7_SRC_STDLIB_H_
Marko Mikulicic 0:c0ecb8bf28eb 6745 #define CS_V7_SRC_STDLIB_H_
Marko Mikulicic 0:c0ecb8bf28eb 6746
Marko Mikulicic 0:c0ecb8bf28eb 6747 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6748 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6749
Marko Mikulicic 0:c0ecb8bf28eb 6750 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6751 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 6752 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6753
Marko Mikulicic 0:c0ecb8bf28eb 6754 /*V7_PRIVATE*/ void init_stdlib(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 6755
Marko Mikulicic 0:c0ecb8bf28eb 6756 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 6757 V7_PRIVATE enum v7_err std_eval(struct v7 *v7, v7_val_t arg, v7_val_t this_obj,
Marko Mikulicic 0:c0ecb8bf28eb 6758 int is_json, v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 6759
Marko Mikulicic 0:c0ecb8bf28eb 6760 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6761 }
Marko Mikulicic 0:c0ecb8bf28eb 6762 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6763
Marko Mikulicic 0:c0ecb8bf28eb 6764 #endif /* CS_V7_SRC_STDLIB_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6765 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6766 #line 1 "v7/src/heapusage.h"
Marko Mikulicic 0:c0ecb8bf28eb 6767 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6768 /*
Marko Mikulicic 0:c0ecb8bf28eb 6769 * Copyright (c) 2014-2016 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6770 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6771 */
Marko Mikulicic 0:c0ecb8bf28eb 6772
Marko Mikulicic 0:c0ecb8bf28eb 6773 #ifndef CS_V7_SRC_HEAPUSAGE_H_
Marko Mikulicic 0:c0ecb8bf28eb 6774 #define CS_V7_SRC_HEAPUSAGE_H_
Marko Mikulicic 0:c0ecb8bf28eb 6775
Marko Mikulicic 0:c0ecb8bf28eb 6776 #if defined(V7_HEAPUSAGE_ENABLE)
Marko Mikulicic 0:c0ecb8bf28eb 6777
Marko Mikulicic 0:c0ecb8bf28eb 6778 extern volatile int heap_dont_count;
Marko Mikulicic 0:c0ecb8bf28eb 6779
Marko Mikulicic 0:c0ecb8bf28eb 6780 /*
Marko Mikulicic 0:c0ecb8bf28eb 6781 * Returns total heap-allocated size in bytes (without any overhead of the
Marko Mikulicic 0:c0ecb8bf28eb 6782 * heap implementation)
Marko Mikulicic 0:c0ecb8bf28eb 6783 */
Marko Mikulicic 0:c0ecb8bf28eb 6784 size_t heapusage_alloc_size(void);
Marko Mikulicic 0:c0ecb8bf28eb 6785
Marko Mikulicic 0:c0ecb8bf28eb 6786 /*
Marko Mikulicic 0:c0ecb8bf28eb 6787 * Returns number of active allocations
Marko Mikulicic 0:c0ecb8bf28eb 6788 */
Marko Mikulicic 0:c0ecb8bf28eb 6789 size_t heapusage_allocs_cnt(void);
Marko Mikulicic 0:c0ecb8bf28eb 6790
Marko Mikulicic 0:c0ecb8bf28eb 6791 /*
Marko Mikulicic 0:c0ecb8bf28eb 6792 * Must be called before allocating some memory that should not be indicated as
Marko Mikulicic 0:c0ecb8bf28eb 6793 * memory consumed for some particular operation: for example, when we
Marko Mikulicic 0:c0ecb8bf28eb 6794 * preallocate some GC buffer.
Marko Mikulicic 0:c0ecb8bf28eb 6795 */
Marko Mikulicic 0:c0ecb8bf28eb 6796 #define heapusage_dont_count(a) \
Marko Mikulicic 0:c0ecb8bf28eb 6797 do { \
Marko Mikulicic 0:c0ecb8bf28eb 6798 heap_dont_count = a; \
Marko Mikulicic 0:c0ecb8bf28eb 6799 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 6800
Marko Mikulicic 0:c0ecb8bf28eb 6801 #else /* V7_HEAPUSAGE_ENABLE */
Marko Mikulicic 0:c0ecb8bf28eb 6802
Marko Mikulicic 0:c0ecb8bf28eb 6803 #define heapusage_alloc_size() (0)
Marko Mikulicic 0:c0ecb8bf28eb 6804 #define heapusage_allocs_cnt() (0)
Marko Mikulicic 0:c0ecb8bf28eb 6805 #define heapusage_dont_count(a)
Marko Mikulicic 0:c0ecb8bf28eb 6806
Marko Mikulicic 0:c0ecb8bf28eb 6807 #endif /* V7_HEAPUSAGE_ENABLE */
Marko Mikulicic 0:c0ecb8bf28eb 6808
Marko Mikulicic 0:c0ecb8bf28eb 6809 #endif /* CS_V7_SRC_HEAPUSAGE_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6810 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6811 #line 1 "v7/src/std_proxy.h"
Marko Mikulicic 0:c0ecb8bf28eb 6812 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6813 /*
Marko Mikulicic 0:c0ecb8bf28eb 6814 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6815 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6816 */
Marko Mikulicic 0:c0ecb8bf28eb 6817
Marko Mikulicic 0:c0ecb8bf28eb 6818 #ifndef CS_V7_SRC_STD_PROXY_H_
Marko Mikulicic 0:c0ecb8bf28eb 6819 #define CS_V7_SRC_STD_PROXY_H_
Marko Mikulicic 0:c0ecb8bf28eb 6820
Marko Mikulicic 0:c0ecb8bf28eb 6821 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6822 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6823
Marko Mikulicic 0:c0ecb8bf28eb 6824 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 6825
Marko Mikulicic 0:c0ecb8bf28eb 6826 #define _V7_PROXY_TARGET_NAME "__tgt"
Marko Mikulicic 0:c0ecb8bf28eb 6827 #define _V7_PROXY_HANDLER_NAME "__hnd"
Marko Mikulicic 0:c0ecb8bf28eb 6828
Marko Mikulicic 0:c0ecb8bf28eb 6829 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6830 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 6831 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6832
Marko Mikulicic 0:c0ecb8bf28eb 6833 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 6834
Marko Mikulicic 0:c0ecb8bf28eb 6835 V7_PRIVATE enum v7_err Proxy_ctor(struct v7 *v7, v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 6836
Marko Mikulicic 0:c0ecb8bf28eb 6837 V7_PRIVATE void init_proxy(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 6838
Marko Mikulicic 0:c0ecb8bf28eb 6839 /*
Marko Mikulicic 0:c0ecb8bf28eb 6840 * Returns whether the given name is one of the special Proxy names
Marko Mikulicic 0:c0ecb8bf28eb 6841 * (_V7_PROXY_TARGET_NAME or _V7_PROXY_HANDLER_NAME)
Marko Mikulicic 0:c0ecb8bf28eb 6842 */
Marko Mikulicic 0:c0ecb8bf28eb 6843 V7_PRIVATE int is_special_proxy_name(const char *name, size_t name_len);
Marko Mikulicic 0:c0ecb8bf28eb 6844
Marko Mikulicic 0:c0ecb8bf28eb 6845 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6846
Marko Mikulicic 0:c0ecb8bf28eb 6847 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6848 }
Marko Mikulicic 0:c0ecb8bf28eb 6849 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6850
Marko Mikulicic 0:c0ecb8bf28eb 6851 #endif /* V7_ENABLE__Proxy */
Marko Mikulicic 0:c0ecb8bf28eb 6852
Marko Mikulicic 0:c0ecb8bf28eb 6853 #endif /* CS_V7_SRC_STD_PROXY_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6854 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6855 #line 1 "v7/src/freeze.h"
Marko Mikulicic 0:c0ecb8bf28eb 6856 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6857 /*
Marko Mikulicic 0:c0ecb8bf28eb 6858 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6859 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6860 */
Marko Mikulicic 0:c0ecb8bf28eb 6861
Marko Mikulicic 0:c0ecb8bf28eb 6862 #ifndef CS_V7_SRC_FREEZE_H_
Marko Mikulicic 0:c0ecb8bf28eb 6863 #define CS_V7_SRC_FREEZE_H_
Marko Mikulicic 0:c0ecb8bf28eb 6864
Marko Mikulicic 0:c0ecb8bf28eb 6865 #ifdef V7_FREEZE
Marko Mikulicic 0:c0ecb8bf28eb 6866
Marko Mikulicic 0:c0ecb8bf28eb 6867 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6868
Marko Mikulicic 0:c0ecb8bf28eb 6869 struct v7_property;
Marko Mikulicic 0:c0ecb8bf28eb 6870
Marko Mikulicic 0:c0ecb8bf28eb 6871 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6872 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 6873 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6874
Marko Mikulicic 0:c0ecb8bf28eb 6875 V7_PRIVATE void freeze(struct v7 *v7, char *filename);
Marko Mikulicic 0:c0ecb8bf28eb 6876 V7_PRIVATE void freeze_obj(struct v7 *v7, FILE *f, v7_val_t v);
Marko Mikulicic 0:c0ecb8bf28eb 6877 V7_PRIVATE void freeze_prop(struct v7 *v7, FILE *f, struct v7_property *prop);
Marko Mikulicic 0:c0ecb8bf28eb 6878
Marko Mikulicic 0:c0ecb8bf28eb 6879 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6880 }
Marko Mikulicic 0:c0ecb8bf28eb 6881 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6882
Marko Mikulicic 0:c0ecb8bf28eb 6883 #endif /* V7_FREEZE */
Marko Mikulicic 0:c0ecb8bf28eb 6884
Marko Mikulicic 0:c0ecb8bf28eb 6885 #endif /* CS_V7_SRC_FREEZE_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6886 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6887 #line 1 "v7/src/std_array.h"
Marko Mikulicic 0:c0ecb8bf28eb 6888 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6889 /*
Marko Mikulicic 0:c0ecb8bf28eb 6890 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6891 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6892 */
Marko Mikulicic 0:c0ecb8bf28eb 6893
Marko Mikulicic 0:c0ecb8bf28eb 6894 #ifndef CS_V7_SRC_STD_ARRAY_H_
Marko Mikulicic 0:c0ecb8bf28eb 6895 #define CS_V7_SRC_STD_ARRAY_H_
Marko Mikulicic 0:c0ecb8bf28eb 6896
Marko Mikulicic 0:c0ecb8bf28eb 6897 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6898
Marko Mikulicic 0:c0ecb8bf28eb 6899 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6900 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 6901 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6902
Marko Mikulicic 0:c0ecb8bf28eb 6903 V7_PRIVATE void init_array(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 6904
Marko Mikulicic 0:c0ecb8bf28eb 6905 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6906 }
Marko Mikulicic 0:c0ecb8bf28eb 6907 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6908
Marko Mikulicic 0:c0ecb8bf28eb 6909 #endif /* CS_V7_SRC_STD_ARRAY_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6910 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6911 #line 1 "v7/src/std_boolean.h"
Marko Mikulicic 0:c0ecb8bf28eb 6912 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6913 /*
Marko Mikulicic 0:c0ecb8bf28eb 6914 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6915 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6916 */
Marko Mikulicic 0:c0ecb8bf28eb 6917
Marko Mikulicic 0:c0ecb8bf28eb 6918 #ifndef CS_V7_SRC_STD_BOOLEAN_H_
Marko Mikulicic 0:c0ecb8bf28eb 6919 #define CS_V7_SRC_STD_BOOLEAN_H_
Marko Mikulicic 0:c0ecb8bf28eb 6920
Marko Mikulicic 0:c0ecb8bf28eb 6921 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6922
Marko Mikulicic 0:c0ecb8bf28eb 6923 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6924 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 6925 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6926
Marko Mikulicic 0:c0ecb8bf28eb 6927 V7_PRIVATE void init_boolean(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 6928
Marko Mikulicic 0:c0ecb8bf28eb 6929 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6930 }
Marko Mikulicic 0:c0ecb8bf28eb 6931 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6932
Marko Mikulicic 0:c0ecb8bf28eb 6933 #endif /* CS_V7_SRC_STD_BOOLEAN_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6934 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6935 #line 1 "v7/src/std_date.h"
Marko Mikulicic 0:c0ecb8bf28eb 6936 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6937 /*
Marko Mikulicic 0:c0ecb8bf28eb 6938 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6939 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6940 */
Marko Mikulicic 0:c0ecb8bf28eb 6941
Marko Mikulicic 0:c0ecb8bf28eb 6942 #ifndef CS_V7_SRC_STD_DATE_H_
Marko Mikulicic 0:c0ecb8bf28eb 6943 #define CS_V7_SRC_STD_DATE_H_
Marko Mikulicic 0:c0ecb8bf28eb 6944
Marko Mikulicic 0:c0ecb8bf28eb 6945 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6946
Marko Mikulicic 0:c0ecb8bf28eb 6947 #if V7_ENABLE__Date
Marko Mikulicic 0:c0ecb8bf28eb 6948
Marko Mikulicic 0:c0ecb8bf28eb 6949 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6950 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 6951 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6952
Marko Mikulicic 0:c0ecb8bf28eb 6953 V7_PRIVATE void init_date(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 6954
Marko Mikulicic 0:c0ecb8bf28eb 6955 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6956 }
Marko Mikulicic 0:c0ecb8bf28eb 6957 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6958
Marko Mikulicic 0:c0ecb8bf28eb 6959 #endif /* V7_ENABLE__Date */
Marko Mikulicic 0:c0ecb8bf28eb 6960 #endif /* CS_V7_SRC_STD_DATE_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6961 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6962 #line 1 "v7/src/std_function.h"
Marko Mikulicic 0:c0ecb8bf28eb 6963 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6964 /*
Marko Mikulicic 0:c0ecb8bf28eb 6965 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6966 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6967 */
Marko Mikulicic 0:c0ecb8bf28eb 6968
Marko Mikulicic 0:c0ecb8bf28eb 6969 #ifndef CS_V7_SRC_STD_FUNCTION_H_
Marko Mikulicic 0:c0ecb8bf28eb 6970 #define CS_V7_SRC_STD_FUNCTION_H_
Marko Mikulicic 0:c0ecb8bf28eb 6971
Marko Mikulicic 0:c0ecb8bf28eb 6972 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6973
Marko Mikulicic 0:c0ecb8bf28eb 6974 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6975 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 6976 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6977
Marko Mikulicic 0:c0ecb8bf28eb 6978 V7_PRIVATE void init_function(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 6979
Marko Mikulicic 0:c0ecb8bf28eb 6980 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6981 }
Marko Mikulicic 0:c0ecb8bf28eb 6982 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 6983
Marko Mikulicic 0:c0ecb8bf28eb 6984 #endif /* CS_V7_SRC_STD_FUNCTION_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 6985 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 6986 #line 1 "v7/src/std_json.h"
Marko Mikulicic 0:c0ecb8bf28eb 6987 #endif
Marko Mikulicic 0:c0ecb8bf28eb 6988 /*
Marko Mikulicic 0:c0ecb8bf28eb 6989 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 6990 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 6991 */
Marko Mikulicic 0:c0ecb8bf28eb 6992
Marko Mikulicic 0:c0ecb8bf28eb 6993 #ifndef CS_V7_SRC_STD_JSON_H_
Marko Mikulicic 0:c0ecb8bf28eb 6994 #define CS_V7_SRC_STD_JSON_H_
Marko Mikulicic 0:c0ecb8bf28eb 6995
Marko Mikulicic 0:c0ecb8bf28eb 6996 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 6997
Marko Mikulicic 0:c0ecb8bf28eb 6998 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 6999 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 7000 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7001
Marko Mikulicic 0:c0ecb8bf28eb 7002 V7_PRIVATE void init_json(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 7003
Marko Mikulicic 0:c0ecb8bf28eb 7004 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7005 }
Marko Mikulicic 0:c0ecb8bf28eb 7006 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7007
Marko Mikulicic 0:c0ecb8bf28eb 7008 #endif /* CS_V7_SRC_STD_JSON_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 7009 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 7010 #line 1 "v7/src/std_math.h"
Marko Mikulicic 0:c0ecb8bf28eb 7011 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7012 /*
Marko Mikulicic 0:c0ecb8bf28eb 7013 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 7014 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 7015 */
Marko Mikulicic 0:c0ecb8bf28eb 7016
Marko Mikulicic 0:c0ecb8bf28eb 7017 #ifndef CS_V7_SRC_STD_MATH_H_
Marko Mikulicic 0:c0ecb8bf28eb 7018 #define CS_V7_SRC_STD_MATH_H_
Marko Mikulicic 0:c0ecb8bf28eb 7019
Marko Mikulicic 0:c0ecb8bf28eb 7020 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7021
Marko Mikulicic 0:c0ecb8bf28eb 7022 #if V7_ENABLE__Math
Marko Mikulicic 0:c0ecb8bf28eb 7023
Marko Mikulicic 0:c0ecb8bf28eb 7024 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7025 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 7026 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7027
Marko Mikulicic 0:c0ecb8bf28eb 7028 V7_PRIVATE void init_math(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 7029
Marko Mikulicic 0:c0ecb8bf28eb 7030 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7031 }
Marko Mikulicic 0:c0ecb8bf28eb 7032 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7033
Marko Mikulicic 0:c0ecb8bf28eb 7034 #endif /* V7_ENABLE__Math */
Marko Mikulicic 0:c0ecb8bf28eb 7035 #endif /* CS_V7_SRC_STD_MATH_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 7036 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 7037 #line 1 "v7/src/std_number.h"
Marko Mikulicic 0:c0ecb8bf28eb 7038 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7039 /*
Marko Mikulicic 0:c0ecb8bf28eb 7040 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 7041 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 7042 */
Marko Mikulicic 0:c0ecb8bf28eb 7043
Marko Mikulicic 0:c0ecb8bf28eb 7044 #ifndef CS_V7_SRC_STD_NUMBER_H_
Marko Mikulicic 0:c0ecb8bf28eb 7045 #define CS_V7_SRC_STD_NUMBER_H_
Marko Mikulicic 0:c0ecb8bf28eb 7046
Marko Mikulicic 0:c0ecb8bf28eb 7047 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7048
Marko Mikulicic 0:c0ecb8bf28eb 7049 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7050 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 7051 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7052
Marko Mikulicic 0:c0ecb8bf28eb 7053 V7_PRIVATE void init_number(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 7054
Marko Mikulicic 0:c0ecb8bf28eb 7055 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7056 }
Marko Mikulicic 0:c0ecb8bf28eb 7057 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7058
Marko Mikulicic 0:c0ecb8bf28eb 7059 #endif /* CS_V7_SRC_STD_NUMBER_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 7060 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 7061 #line 1 "v7/src/std_object.h"
Marko Mikulicic 0:c0ecb8bf28eb 7062 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7063 /*
Marko Mikulicic 0:c0ecb8bf28eb 7064 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 7065 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 7066 */
Marko Mikulicic 0:c0ecb8bf28eb 7067
Marko Mikulicic 0:c0ecb8bf28eb 7068 #ifndef CS_V7_SRC_STD_OBJECT_H_
Marko Mikulicic 0:c0ecb8bf28eb 7069 #define CS_V7_SRC_STD_OBJECT_H_
Marko Mikulicic 0:c0ecb8bf28eb 7070
Marko Mikulicic 0:c0ecb8bf28eb 7071 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7072 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7073
Marko Mikulicic 0:c0ecb8bf28eb 7074 struct v7;
Marko Mikulicic 0:c0ecb8bf28eb 7075
Marko Mikulicic 0:c0ecb8bf28eb 7076 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7077 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 7078 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7079
Marko Mikulicic 0:c0ecb8bf28eb 7080 V7_PRIVATE void init_object(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 7081
Marko Mikulicic 0:c0ecb8bf28eb 7082 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 7083 V7_PRIVATE enum v7_err Obj_valueOf(struct v7 *v7, v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 7084
Marko Mikulicic 0:c0ecb8bf28eb 7085 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7086 }
Marko Mikulicic 0:c0ecb8bf28eb 7087 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7088
Marko Mikulicic 0:c0ecb8bf28eb 7089 #endif /* CS_V7_SRC_STD_OBJECT_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 7090 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 7091 #line 1 "v7/src/std_regex.h"
Marko Mikulicic 0:c0ecb8bf28eb 7092 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7093 /*
Marko Mikulicic 0:c0ecb8bf28eb 7094 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 7095 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 7096 */
Marko Mikulicic 0:c0ecb8bf28eb 7097
Marko Mikulicic 0:c0ecb8bf28eb 7098 #ifndef CS_V7_SRC_STD_REGEX_H_
Marko Mikulicic 0:c0ecb8bf28eb 7099 #define CS_V7_SRC_STD_REGEX_H_
Marko Mikulicic 0:c0ecb8bf28eb 7100
Marko Mikulicic 0:c0ecb8bf28eb 7101 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7102 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7103
Marko Mikulicic 0:c0ecb8bf28eb 7104 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 7105
Marko Mikulicic 0:c0ecb8bf28eb 7106 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7107 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 7108 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7109
Marko Mikulicic 0:c0ecb8bf28eb 7110 V7_PRIVATE enum v7_err Regex_ctor(struct v7 *v7, v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 7111 V7_PRIVATE enum v7_err rx_exec(struct v7 *v7, v7_val_t rx, v7_val_t vstr,
Marko Mikulicic 0:c0ecb8bf28eb 7112 int lind, v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 7113
Marko Mikulicic 0:c0ecb8bf28eb 7114 V7_PRIVATE void init_regex(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 7115
Marko Mikulicic 0:c0ecb8bf28eb 7116 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7117 }
Marko Mikulicic 0:c0ecb8bf28eb 7118 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7119
Marko Mikulicic 0:c0ecb8bf28eb 7120 #endif /* V7_ENABLE__RegExp */
Marko Mikulicic 0:c0ecb8bf28eb 7121
Marko Mikulicic 0:c0ecb8bf28eb 7122 #endif /* CS_V7_SRC_STD_REGEX_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 7123 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 7124 #line 1 "v7/src/std_string.h"
Marko Mikulicic 0:c0ecb8bf28eb 7125 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7126 /*
Marko Mikulicic 0:c0ecb8bf28eb 7127 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 7128 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 7129 */
Marko Mikulicic 0:c0ecb8bf28eb 7130
Marko Mikulicic 0:c0ecb8bf28eb 7131 #ifndef CS_V7_SRC_STD_STRING_H_
Marko Mikulicic 0:c0ecb8bf28eb 7132 #define CS_V7_SRC_STD_STRING_H_
Marko Mikulicic 0:c0ecb8bf28eb 7133
Marko Mikulicic 0:c0ecb8bf28eb 7134 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7135 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7136
Marko Mikulicic 0:c0ecb8bf28eb 7137 /* Max captures for String.replace() */
Marko Mikulicic 0:c0ecb8bf28eb 7138 #define V7_RE_MAX_REPL_SUB 20
Marko Mikulicic 0:c0ecb8bf28eb 7139
Marko Mikulicic 0:c0ecb8bf28eb 7140 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7141 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 7142 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7143
Marko Mikulicic 0:c0ecb8bf28eb 7144 V7_PRIVATE void init_string(struct v7 *v7);
Marko Mikulicic 0:c0ecb8bf28eb 7145
Marko Mikulicic 0:c0ecb8bf28eb 7146 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7147 }
Marko Mikulicic 0:c0ecb8bf28eb 7148 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7149
Marko Mikulicic 0:c0ecb8bf28eb 7150 #endif /* CS_V7_SRC_STD_STRING_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 7151 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 7152 #line 1 "v7/src/js_stdlib.h"
Marko Mikulicic 0:c0ecb8bf28eb 7153 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7154 /*
Marko Mikulicic 0:c0ecb8bf28eb 7155 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 7156 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 7157 */
Marko Mikulicic 0:c0ecb8bf28eb 7158
Marko Mikulicic 0:c0ecb8bf28eb 7159 #ifndef CS_V7_SRC_JS_STDLIB_H_
Marko Mikulicic 0:c0ecb8bf28eb 7160 #define CS_V7_SRC_JS_STDLIB_H_
Marko Mikulicic 0:c0ecb8bf28eb 7161
Marko Mikulicic 0:c0ecb8bf28eb 7162 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7163
Marko Mikulicic 0:c0ecb8bf28eb 7164 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7165 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 7166 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7167
Marko Mikulicic 0:c0ecb8bf28eb 7168 V7_PRIVATE void init_js_stdlib(struct v7 *);
Marko Mikulicic 0:c0ecb8bf28eb 7169
Marko Mikulicic 0:c0ecb8bf28eb 7170 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7171 }
Marko Mikulicic 0:c0ecb8bf28eb 7172 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7173
Marko Mikulicic 0:c0ecb8bf28eb 7174 #endif /* CS_V7_SRC_JS_STDLIB_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 7175 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 7176 #line 1 "v7/src/main_public.h"
Marko Mikulicic 0:c0ecb8bf28eb 7177 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7178 /*
Marko Mikulicic 0:c0ecb8bf28eb 7179 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 7180 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 7181 */
Marko Mikulicic 0:c0ecb8bf28eb 7182
Marko Mikulicic 0:c0ecb8bf28eb 7183 /*
Marko Mikulicic 0:c0ecb8bf28eb 7184 * === v7 main()
Marko Mikulicic 0:c0ecb8bf28eb 7185 */
Marko Mikulicic 0:c0ecb8bf28eb 7186
Marko Mikulicic 0:c0ecb8bf28eb 7187 #ifndef CS_V7_SRC_MAIN_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 7188 #define CS_V7_SRC_MAIN_PUBLIC_H_
Marko Mikulicic 0:c0ecb8bf28eb 7189
Marko Mikulicic 0:c0ecb8bf28eb 7190 /* Amalgamated: #include "v7/src/core_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7191
Marko Mikulicic 0:c0ecb8bf28eb 7192 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7193 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 7194 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7195
Marko Mikulicic 0:c0ecb8bf28eb 7196 /*
Marko Mikulicic 0:c0ecb8bf28eb 7197 * V7 executable main function.
Marko Mikulicic 0:c0ecb8bf28eb 7198 *
Marko Mikulicic 0:c0ecb8bf28eb 7199 * There are various callbacks available:
Marko Mikulicic 0:c0ecb8bf28eb 7200 *
Marko Mikulicic 0:c0ecb8bf28eb 7201 * `pre_freeze_init()` and `pre_init()` are optional intialization functions,
Marko Mikulicic 0:c0ecb8bf28eb 7202 * aimed to export any extra functionality into vanilla v7 engine. They are
Marko Mikulicic 0:c0ecb8bf28eb 7203 * called after v7 initialization, before executing given files or inline
Marko Mikulicic 0:c0ecb8bf28eb 7204 * expressions. `pre_freeze_init()` is called before "freezing" v7 state;
Marko Mikulicic 0:c0ecb8bf28eb 7205 * whereas `pre_init` called afterwards.
Marko Mikulicic 0:c0ecb8bf28eb 7206 *
Marko Mikulicic 0:c0ecb8bf28eb 7207 * `post_init()`, if provided, is called after executing files and expressions,
Marko Mikulicic 0:c0ecb8bf28eb 7208 * before destroying v7 instance and exiting.
Marko Mikulicic 0:c0ecb8bf28eb 7209 */
Marko Mikulicic 0:c0ecb8bf28eb 7210 int v7_main(int argc, char *argv[], void (*pre_freeze_init)(struct v7 *),
Marko Mikulicic 0:c0ecb8bf28eb 7211 void (*pre_init)(struct v7 *), void (*post_init)(struct v7 *));
Marko Mikulicic 0:c0ecb8bf28eb 7212
Marko Mikulicic 0:c0ecb8bf28eb 7213 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 7214 }
Marko Mikulicic 0:c0ecb8bf28eb 7215 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 7216
Marko Mikulicic 0:c0ecb8bf28eb 7217 #endif /* CS_V7_SRC_MAIN_PUBLIC_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 7218 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 7219 #line 1 "v7/src/main.h"
Marko Mikulicic 0:c0ecb8bf28eb 7220 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7221 /*
Marko Mikulicic 0:c0ecb8bf28eb 7222 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 7223 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 7224 */
Marko Mikulicic 0:c0ecb8bf28eb 7225
Marko Mikulicic 0:c0ecb8bf28eb 7226 #ifndef CS_V7_SRC_MAIN_H_
Marko Mikulicic 0:c0ecb8bf28eb 7227 #define CS_V7_SRC_MAIN_H_
Marko Mikulicic 0:c0ecb8bf28eb 7228
Marko Mikulicic 0:c0ecb8bf28eb 7229 /* Amalgamated: #include "v7/src/main_public.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7230
Marko Mikulicic 0:c0ecb8bf28eb 7231 #endif /* CS_V7_SRC_MAIN_H_ */
Marko Mikulicic 0:c0ecb8bf28eb 7232 #ifndef V7_EXPORT_INTERNAL_HEADERS
Marko Mikulicic 0:c0ecb8bf28eb 7233 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 7234 #line 1 "common/mbuf.c"
Marko Mikulicic 0:c0ecb8bf28eb 7235 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7236 /*
Marko Mikulicic 0:c0ecb8bf28eb 7237 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 7238 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 7239 */
Marko Mikulicic 0:c0ecb8bf28eb 7240
Marko Mikulicic 0:c0ecb8bf28eb 7241 #ifndef EXCLUDE_COMMON
Marko Mikulicic 0:c0ecb8bf28eb 7242
Marko Mikulicic 0:c0ecb8bf28eb 7243 #include <assert.h>
Marko Mikulicic 0:c0ecb8bf28eb 7244 #include <string.h>
Marko Mikulicic 0:c0ecb8bf28eb 7245 /* Amalgamated: #include "common/mbuf.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7246
Marko Mikulicic 0:c0ecb8bf28eb 7247 #ifndef MBUF_REALLOC
Marko Mikulicic 0:c0ecb8bf28eb 7248 #define MBUF_REALLOC realloc
Marko Mikulicic 0:c0ecb8bf28eb 7249 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7250
Marko Mikulicic 0:c0ecb8bf28eb 7251 #ifndef MBUF_FREE
Marko Mikulicic 0:c0ecb8bf28eb 7252 #define MBUF_FREE free
Marko Mikulicic 0:c0ecb8bf28eb 7253 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7254
Marko Mikulicic 0:c0ecb8bf28eb 7255 void mbuf_init(struct mbuf *mbuf, size_t initial_size) {
Marko Mikulicic 0:c0ecb8bf28eb 7256 mbuf->len = mbuf->size = 0;
Marko Mikulicic 0:c0ecb8bf28eb 7257 mbuf->buf = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 7258 mbuf_resize(mbuf, initial_size);
Marko Mikulicic 0:c0ecb8bf28eb 7259 }
Marko Mikulicic 0:c0ecb8bf28eb 7260
Marko Mikulicic 0:c0ecb8bf28eb 7261 void mbuf_free(struct mbuf *mbuf) {
Marko Mikulicic 0:c0ecb8bf28eb 7262 if (mbuf->buf != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 7263 MBUF_FREE(mbuf->buf);
Marko Mikulicic 0:c0ecb8bf28eb 7264 mbuf_init(mbuf, 0);
Marko Mikulicic 0:c0ecb8bf28eb 7265 }
Marko Mikulicic 0:c0ecb8bf28eb 7266 }
Marko Mikulicic 0:c0ecb8bf28eb 7267
Marko Mikulicic 0:c0ecb8bf28eb 7268 void mbuf_resize(struct mbuf *a, size_t new_size) {
Marko Mikulicic 0:c0ecb8bf28eb 7269 if (new_size > a->size || (new_size < a->size && new_size >= a->len)) {
Marko Mikulicic 0:c0ecb8bf28eb 7270 char *buf = (char *) MBUF_REALLOC(a->buf, new_size);
Marko Mikulicic 0:c0ecb8bf28eb 7271 /*
Marko Mikulicic 0:c0ecb8bf28eb 7272 * In case realloc fails, there's not much we can do, except keep things as
Marko Mikulicic 0:c0ecb8bf28eb 7273 * they are. Note that NULL is a valid return value from realloc when
Marko Mikulicic 0:c0ecb8bf28eb 7274 * size == 0, but that is covered too.
Marko Mikulicic 0:c0ecb8bf28eb 7275 */
Marko Mikulicic 0:c0ecb8bf28eb 7276 if (buf == NULL && new_size != 0) return;
Marko Mikulicic 0:c0ecb8bf28eb 7277 a->buf = buf;
Marko Mikulicic 0:c0ecb8bf28eb 7278 a->size = new_size;
Marko Mikulicic 0:c0ecb8bf28eb 7279 }
Marko Mikulicic 0:c0ecb8bf28eb 7280 }
Marko Mikulicic 0:c0ecb8bf28eb 7281
Marko Mikulicic 0:c0ecb8bf28eb 7282 void mbuf_trim(struct mbuf *mbuf) {
Marko Mikulicic 0:c0ecb8bf28eb 7283 mbuf_resize(mbuf, mbuf->len);
Marko Mikulicic 0:c0ecb8bf28eb 7284 }
Marko Mikulicic 0:c0ecb8bf28eb 7285
Marko Mikulicic 0:c0ecb8bf28eb 7286 size_t mbuf_insert(struct mbuf *a, size_t off, const void *buf, size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 7287 char *p = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 7288
Marko Mikulicic 0:c0ecb8bf28eb 7289 assert(a != NULL);
Marko Mikulicic 0:c0ecb8bf28eb 7290 assert(a->len <= a->size);
Marko Mikulicic 0:c0ecb8bf28eb 7291 assert(off <= a->len);
Marko Mikulicic 0:c0ecb8bf28eb 7292
Marko Mikulicic 0:c0ecb8bf28eb 7293 /* check overflow */
Marko Mikulicic 0:c0ecb8bf28eb 7294 if (~(size_t) 0 - (size_t) a->buf < len) return 0;
Marko Mikulicic 0:c0ecb8bf28eb 7295
Marko Mikulicic 0:c0ecb8bf28eb 7296 if (a->len + len <= a->size) {
Marko Mikulicic 0:c0ecb8bf28eb 7297 memmove(a->buf + off + len, a->buf + off, a->len - off);
Marko Mikulicic 0:c0ecb8bf28eb 7298 if (buf != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 7299 memcpy(a->buf + off, buf, len);
Marko Mikulicic 0:c0ecb8bf28eb 7300 }
Marko Mikulicic 0:c0ecb8bf28eb 7301 a->len += len;
Marko Mikulicic 0:c0ecb8bf28eb 7302 } else {
Marko Mikulicic 0:c0ecb8bf28eb 7303 size_t new_size = (size_t)((a->len + len) * MBUF_SIZE_MULTIPLIER);
Marko Mikulicic 0:c0ecb8bf28eb 7304 if ((p = (char *) MBUF_REALLOC(a->buf, new_size)) != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 7305 a->buf = p;
Marko Mikulicic 0:c0ecb8bf28eb 7306 memmove(a->buf + off + len, a->buf + off, a->len - off);
Marko Mikulicic 0:c0ecb8bf28eb 7307 if (buf != NULL) memcpy(a->buf + off, buf, len);
Marko Mikulicic 0:c0ecb8bf28eb 7308 a->len += len;
Marko Mikulicic 0:c0ecb8bf28eb 7309 a->size = new_size;
Marko Mikulicic 0:c0ecb8bf28eb 7310 } else {
Marko Mikulicic 0:c0ecb8bf28eb 7311 len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 7312 }
Marko Mikulicic 0:c0ecb8bf28eb 7313 }
Marko Mikulicic 0:c0ecb8bf28eb 7314
Marko Mikulicic 0:c0ecb8bf28eb 7315 return len;
Marko Mikulicic 0:c0ecb8bf28eb 7316 }
Marko Mikulicic 0:c0ecb8bf28eb 7317
Marko Mikulicic 0:c0ecb8bf28eb 7318 size_t mbuf_append(struct mbuf *a, const void *buf, size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 7319 return mbuf_insert(a, a->len, buf, len);
Marko Mikulicic 0:c0ecb8bf28eb 7320 }
Marko Mikulicic 0:c0ecb8bf28eb 7321
Marko Mikulicic 0:c0ecb8bf28eb 7322 void mbuf_remove(struct mbuf *mb, size_t n) {
Marko Mikulicic 0:c0ecb8bf28eb 7323 if (n > 0 && n <= mb->len) {
Marko Mikulicic 0:c0ecb8bf28eb 7324 memmove(mb->buf, mb->buf + n, mb->len - n);
Marko Mikulicic 0:c0ecb8bf28eb 7325 mb->len -= n;
Marko Mikulicic 0:c0ecb8bf28eb 7326 }
Marko Mikulicic 0:c0ecb8bf28eb 7327 }
Marko Mikulicic 0:c0ecb8bf28eb 7328
Marko Mikulicic 0:c0ecb8bf28eb 7329 #endif /* EXCLUDE_COMMON */
Marko Mikulicic 0:c0ecb8bf28eb 7330 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 7331 #line 1 "common/str_util.c"
Marko Mikulicic 0:c0ecb8bf28eb 7332 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7333 /*
Marko Mikulicic 0:c0ecb8bf28eb 7334 * Copyright (c) 2015 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 7335 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 7336 */
Marko Mikulicic 0:c0ecb8bf28eb 7337
Marko Mikulicic 0:c0ecb8bf28eb 7338 #ifndef EXCLUDE_COMMON
Marko Mikulicic 0:c0ecb8bf28eb 7339
Marko Mikulicic 0:c0ecb8bf28eb 7340 /* Amalgamated: #include "common/platform.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7341 /* Amalgamated: #include "common/str_util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7342
Marko Mikulicic 0:c0ecb8bf28eb 7343 size_t c_strnlen(const char *s, size_t maxlen) {
Marko Mikulicic 0:c0ecb8bf28eb 7344 size_t l = 0;
Marko Mikulicic 0:c0ecb8bf28eb 7345 for (; l < maxlen && s[l] != '\0'; l++) {
Marko Mikulicic 0:c0ecb8bf28eb 7346 }
Marko Mikulicic 0:c0ecb8bf28eb 7347 return l;
Marko Mikulicic 0:c0ecb8bf28eb 7348 }
Marko Mikulicic 0:c0ecb8bf28eb 7349
Marko Mikulicic 0:c0ecb8bf28eb 7350 #define C_SNPRINTF_APPEND_CHAR(ch) \
Marko Mikulicic 0:c0ecb8bf28eb 7351 do { \
Marko Mikulicic 0:c0ecb8bf28eb 7352 if (i < (int) buf_size) buf[i] = ch; \
Marko Mikulicic 0:c0ecb8bf28eb 7353 i++; \
Marko Mikulicic 0:c0ecb8bf28eb 7354 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 7355
Marko Mikulicic 0:c0ecb8bf28eb 7356 #define C_SNPRINTF_FLAG_ZERO 1
Marko Mikulicic 0:c0ecb8bf28eb 7357
Marko Mikulicic 0:c0ecb8bf28eb 7358 #ifdef C_DISABLE_BUILTIN_SNPRINTF
Marko Mikulicic 0:c0ecb8bf28eb 7359 int c_vsnprintf(char *buf, size_t buf_size, const char *fmt, va_list ap) {
Marko Mikulicic 0:c0ecb8bf28eb 7360 return vsnprintf(buf, buf_size, fmt, ap);
Marko Mikulicic 0:c0ecb8bf28eb 7361 }
Marko Mikulicic 0:c0ecb8bf28eb 7362 #else
Marko Mikulicic 0:c0ecb8bf28eb 7363 static int c_itoa(char *buf, size_t buf_size, int64_t num, int base, int flags,
Marko Mikulicic 0:c0ecb8bf28eb 7364 int field_width) {
Marko Mikulicic 0:c0ecb8bf28eb 7365 char tmp[40];
Marko Mikulicic 0:c0ecb8bf28eb 7366 int i = 0, k = 0, neg = 0;
Marko Mikulicic 0:c0ecb8bf28eb 7367
Marko Mikulicic 0:c0ecb8bf28eb 7368 if (num < 0) {
Marko Mikulicic 0:c0ecb8bf28eb 7369 neg++;
Marko Mikulicic 0:c0ecb8bf28eb 7370 num = -num;
Marko Mikulicic 0:c0ecb8bf28eb 7371 }
Marko Mikulicic 0:c0ecb8bf28eb 7372
Marko Mikulicic 0:c0ecb8bf28eb 7373 /* Print into temporary buffer - in reverse order */
Marko Mikulicic 0:c0ecb8bf28eb 7374 do {
Marko Mikulicic 0:c0ecb8bf28eb 7375 int rem = num % base;
Marko Mikulicic 0:c0ecb8bf28eb 7376 if (rem < 10) {
Marko Mikulicic 0:c0ecb8bf28eb 7377 tmp[k++] = '0' + rem;
Marko Mikulicic 0:c0ecb8bf28eb 7378 } else {
Marko Mikulicic 0:c0ecb8bf28eb 7379 tmp[k++] = 'a' + (rem - 10);
Marko Mikulicic 0:c0ecb8bf28eb 7380 }
Marko Mikulicic 0:c0ecb8bf28eb 7381 num /= base;
Marko Mikulicic 0:c0ecb8bf28eb 7382 } while (num > 0);
Marko Mikulicic 0:c0ecb8bf28eb 7383
Marko Mikulicic 0:c0ecb8bf28eb 7384 /* Zero padding */
Marko Mikulicic 0:c0ecb8bf28eb 7385 if (flags && C_SNPRINTF_FLAG_ZERO) {
Marko Mikulicic 0:c0ecb8bf28eb 7386 while (k < field_width && k < (int) sizeof(tmp) - 1) {
Marko Mikulicic 0:c0ecb8bf28eb 7387 tmp[k++] = '0';
Marko Mikulicic 0:c0ecb8bf28eb 7388 }
Marko Mikulicic 0:c0ecb8bf28eb 7389 }
Marko Mikulicic 0:c0ecb8bf28eb 7390
Marko Mikulicic 0:c0ecb8bf28eb 7391 /* And sign */
Marko Mikulicic 0:c0ecb8bf28eb 7392 if (neg) {
Marko Mikulicic 0:c0ecb8bf28eb 7393 tmp[k++] = '-';
Marko Mikulicic 0:c0ecb8bf28eb 7394 }
Marko Mikulicic 0:c0ecb8bf28eb 7395
Marko Mikulicic 0:c0ecb8bf28eb 7396 /* Now output */
Marko Mikulicic 0:c0ecb8bf28eb 7397 while (--k >= 0) {
Marko Mikulicic 0:c0ecb8bf28eb 7398 C_SNPRINTF_APPEND_CHAR(tmp[k]);
Marko Mikulicic 0:c0ecb8bf28eb 7399 }
Marko Mikulicic 0:c0ecb8bf28eb 7400
Marko Mikulicic 0:c0ecb8bf28eb 7401 return i;
Marko Mikulicic 0:c0ecb8bf28eb 7402 }
Marko Mikulicic 0:c0ecb8bf28eb 7403
Marko Mikulicic 0:c0ecb8bf28eb 7404 int c_vsnprintf(char *buf, size_t buf_size, const char *fmt, va_list ap) {
Marko Mikulicic 0:c0ecb8bf28eb 7405 int ch, i = 0, len_mod, flags, precision, field_width;
Marko Mikulicic 0:c0ecb8bf28eb 7406
Marko Mikulicic 0:c0ecb8bf28eb 7407 while ((ch = *fmt++) != '\0') {
Marko Mikulicic 0:c0ecb8bf28eb 7408 if (ch != '%') {
Marko Mikulicic 0:c0ecb8bf28eb 7409 C_SNPRINTF_APPEND_CHAR(ch);
Marko Mikulicic 0:c0ecb8bf28eb 7410 } else {
Marko Mikulicic 0:c0ecb8bf28eb 7411 /*
Marko Mikulicic 0:c0ecb8bf28eb 7412 * Conversion specification:
Marko Mikulicic 0:c0ecb8bf28eb 7413 * zero or more flags (one of: # 0 - <space> + ')
Marko Mikulicic 0:c0ecb8bf28eb 7414 * an optional minimum field width (digits)
Marko Mikulicic 0:c0ecb8bf28eb 7415 * an optional precision (. followed by digits, or *)
Marko Mikulicic 0:c0ecb8bf28eb 7416 * an optional length modifier (one of: hh h l ll L q j z t)
Marko Mikulicic 0:c0ecb8bf28eb 7417 * 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 7418 */
Marko Mikulicic 0:c0ecb8bf28eb 7419 flags = field_width = precision = len_mod = 0;
Marko Mikulicic 0:c0ecb8bf28eb 7420
Marko Mikulicic 0:c0ecb8bf28eb 7421 /* Flags. only zero-pad flag is supported. */
Marko Mikulicic 0:c0ecb8bf28eb 7422 if (*fmt == '0') {
Marko Mikulicic 0:c0ecb8bf28eb 7423 flags |= C_SNPRINTF_FLAG_ZERO;
Marko Mikulicic 0:c0ecb8bf28eb 7424 }
Marko Mikulicic 0:c0ecb8bf28eb 7425
Marko Mikulicic 0:c0ecb8bf28eb 7426 /* Field width */
Marko Mikulicic 0:c0ecb8bf28eb 7427 while (*fmt >= '0' && *fmt <= '9') {
Marko Mikulicic 0:c0ecb8bf28eb 7428 field_width *= 10;
Marko Mikulicic 0:c0ecb8bf28eb 7429 field_width += *fmt++ - '0';
Marko Mikulicic 0:c0ecb8bf28eb 7430 }
Marko Mikulicic 0:c0ecb8bf28eb 7431 /* Dynamic field width */
Marko Mikulicic 0:c0ecb8bf28eb 7432 if (*fmt == '*') {
Marko Mikulicic 0:c0ecb8bf28eb 7433 field_width = va_arg(ap, int);
Marko Mikulicic 0:c0ecb8bf28eb 7434 fmt++;
Marko Mikulicic 0:c0ecb8bf28eb 7435 }
Marko Mikulicic 0:c0ecb8bf28eb 7436
Marko Mikulicic 0:c0ecb8bf28eb 7437 /* Precision */
Marko Mikulicic 0:c0ecb8bf28eb 7438 if (*fmt == '.') {
Marko Mikulicic 0:c0ecb8bf28eb 7439 fmt++;
Marko Mikulicic 0:c0ecb8bf28eb 7440 if (*fmt == '*') {
Marko Mikulicic 0:c0ecb8bf28eb 7441 precision = va_arg(ap, int);
Marko Mikulicic 0:c0ecb8bf28eb 7442 fmt++;
Marko Mikulicic 0:c0ecb8bf28eb 7443 } else {
Marko Mikulicic 0:c0ecb8bf28eb 7444 while (*fmt >= '0' && *fmt <= '9') {
Marko Mikulicic 0:c0ecb8bf28eb 7445 precision *= 10;
Marko Mikulicic 0:c0ecb8bf28eb 7446 precision += *fmt++ - '0';
Marko Mikulicic 0:c0ecb8bf28eb 7447 }
Marko Mikulicic 0:c0ecb8bf28eb 7448 }
Marko Mikulicic 0:c0ecb8bf28eb 7449 }
Marko Mikulicic 0:c0ecb8bf28eb 7450
Marko Mikulicic 0:c0ecb8bf28eb 7451 /* Length modifier */
Marko Mikulicic 0:c0ecb8bf28eb 7452 switch (*fmt) {
Marko Mikulicic 0:c0ecb8bf28eb 7453 case 'h':
Marko Mikulicic 0:c0ecb8bf28eb 7454 case 'l':
Marko Mikulicic 0:c0ecb8bf28eb 7455 case 'L':
Marko Mikulicic 0:c0ecb8bf28eb 7456 case 'I':
Marko Mikulicic 0:c0ecb8bf28eb 7457 case 'q':
Marko Mikulicic 0:c0ecb8bf28eb 7458 case 'j':
Marko Mikulicic 0:c0ecb8bf28eb 7459 case 'z':
Marko Mikulicic 0:c0ecb8bf28eb 7460 case 't':
Marko Mikulicic 0:c0ecb8bf28eb 7461 len_mod = *fmt++;
Marko Mikulicic 0:c0ecb8bf28eb 7462 if (*fmt == 'h') {
Marko Mikulicic 0:c0ecb8bf28eb 7463 len_mod = 'H';
Marko Mikulicic 0:c0ecb8bf28eb 7464 fmt++;
Marko Mikulicic 0:c0ecb8bf28eb 7465 }
Marko Mikulicic 0:c0ecb8bf28eb 7466 if (*fmt == 'l') {
Marko Mikulicic 0:c0ecb8bf28eb 7467 len_mod = 'q';
Marko Mikulicic 0:c0ecb8bf28eb 7468 fmt++;
Marko Mikulicic 0:c0ecb8bf28eb 7469 }
Marko Mikulicic 0:c0ecb8bf28eb 7470 break;
Marko Mikulicic 0:c0ecb8bf28eb 7471 }
Marko Mikulicic 0:c0ecb8bf28eb 7472
Marko Mikulicic 0:c0ecb8bf28eb 7473 ch = *fmt++;
Marko Mikulicic 0:c0ecb8bf28eb 7474 if (ch == 's') {
Marko Mikulicic 0:c0ecb8bf28eb 7475 const char *s = va_arg(ap, const char *); /* Always fetch parameter */
Marko Mikulicic 0:c0ecb8bf28eb 7476 int j;
Marko Mikulicic 0:c0ecb8bf28eb 7477 int pad = field_width - (precision >= 0 ? c_strnlen(s, precision) : 0);
Marko Mikulicic 0:c0ecb8bf28eb 7478 for (j = 0; j < pad; j++) {
Marko Mikulicic 0:c0ecb8bf28eb 7479 C_SNPRINTF_APPEND_CHAR(' ');
Marko Mikulicic 0:c0ecb8bf28eb 7480 }
Marko Mikulicic 0:c0ecb8bf28eb 7481
Marko Mikulicic 0:c0ecb8bf28eb 7482 /* `s` may be NULL in case of %.*s */
Marko Mikulicic 0:c0ecb8bf28eb 7483 if (s != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 7484 /* Ignore negative and 0 precisions */
Marko Mikulicic 0:c0ecb8bf28eb 7485 for (j = 0; (precision <= 0 || j < precision) && s[j] != '\0'; j++) {
Marko Mikulicic 0:c0ecb8bf28eb 7486 C_SNPRINTF_APPEND_CHAR(s[j]);
Marko Mikulicic 0:c0ecb8bf28eb 7487 }
Marko Mikulicic 0:c0ecb8bf28eb 7488 }
Marko Mikulicic 0:c0ecb8bf28eb 7489 } else if (ch == 'c') {
Marko Mikulicic 0:c0ecb8bf28eb 7490 ch = va_arg(ap, int); /* Always fetch parameter */
Marko Mikulicic 0:c0ecb8bf28eb 7491 C_SNPRINTF_APPEND_CHAR(ch);
Marko Mikulicic 0:c0ecb8bf28eb 7492 } else if (ch == 'd' && len_mod == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 7493 i += c_itoa(buf + i, buf_size - i, va_arg(ap, int), 10, flags,
Marko Mikulicic 0:c0ecb8bf28eb 7494 field_width);
Marko Mikulicic 0:c0ecb8bf28eb 7495 } else if (ch == 'd' && len_mod == 'l') {
Marko Mikulicic 0:c0ecb8bf28eb 7496 i += c_itoa(buf + i, buf_size - i, va_arg(ap, long), 10, flags,
Marko Mikulicic 0:c0ecb8bf28eb 7497 field_width);
Marko Mikulicic 0:c0ecb8bf28eb 7498 #ifdef SSIZE_MAX
Marko Mikulicic 0:c0ecb8bf28eb 7499 } else if (ch == 'd' && len_mod == 'z') {
Marko Mikulicic 0:c0ecb8bf28eb 7500 i += c_itoa(buf + i, buf_size - i, va_arg(ap, ssize_t), 10, flags,
Marko Mikulicic 0:c0ecb8bf28eb 7501 field_width);
Marko Mikulicic 0:c0ecb8bf28eb 7502 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7503 } else if (ch == 'd' && len_mod == 'q') {
Marko Mikulicic 0:c0ecb8bf28eb 7504 i += c_itoa(buf + i, buf_size - i, va_arg(ap, int64_t), 10, flags,
Marko Mikulicic 0:c0ecb8bf28eb 7505 field_width);
Marko Mikulicic 0:c0ecb8bf28eb 7506 } else if ((ch == 'x' || ch == 'u') && len_mod == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 7507 i += c_itoa(buf + i, buf_size - i, va_arg(ap, unsigned),
Marko Mikulicic 0:c0ecb8bf28eb 7508 ch == 'x' ? 16 : 10, flags, field_width);
Marko Mikulicic 0:c0ecb8bf28eb 7509 } else if ((ch == 'x' || ch == 'u') && len_mod == 'l') {
Marko Mikulicic 0:c0ecb8bf28eb 7510 i += c_itoa(buf + i, buf_size - i, va_arg(ap, unsigned long),
Marko Mikulicic 0:c0ecb8bf28eb 7511 ch == 'x' ? 16 : 10, flags, field_width);
Marko Mikulicic 0:c0ecb8bf28eb 7512 } else if ((ch == 'x' || ch == 'u') && len_mod == 'z') {
Marko Mikulicic 0:c0ecb8bf28eb 7513 i += c_itoa(buf + i, buf_size - i, va_arg(ap, size_t),
Marko Mikulicic 0:c0ecb8bf28eb 7514 ch == 'x' ? 16 : 10, flags, field_width);
Marko Mikulicic 0:c0ecb8bf28eb 7515 } else if (ch == 'p') {
Marko Mikulicic 0:c0ecb8bf28eb 7516 unsigned long num = (unsigned long) (uintptr_t) va_arg(ap, void *);
Marko Mikulicic 0:c0ecb8bf28eb 7517 C_SNPRINTF_APPEND_CHAR('0');
Marko Mikulicic 0:c0ecb8bf28eb 7518 C_SNPRINTF_APPEND_CHAR('x');
Marko Mikulicic 0:c0ecb8bf28eb 7519 i += c_itoa(buf + i, buf_size - i, num, 16, flags, 0);
Marko Mikulicic 0:c0ecb8bf28eb 7520 } else {
Marko Mikulicic 0:c0ecb8bf28eb 7521 #ifndef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 7522 /*
Marko Mikulicic 0:c0ecb8bf28eb 7523 * TODO(lsm): abort is not nice in a library, remove it
Marko Mikulicic 0:c0ecb8bf28eb 7524 * Also, ESP8266 SDK doesn't have it
Marko Mikulicic 0:c0ecb8bf28eb 7525 */
Marko Mikulicic 0:c0ecb8bf28eb 7526 abort();
Marko Mikulicic 0:c0ecb8bf28eb 7527 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7528 }
Marko Mikulicic 0:c0ecb8bf28eb 7529 }
Marko Mikulicic 0:c0ecb8bf28eb 7530 }
Marko Mikulicic 0:c0ecb8bf28eb 7531
Marko Mikulicic 0:c0ecb8bf28eb 7532 /* Zero-terminate the result */
Marko Mikulicic 0:c0ecb8bf28eb 7533 if (buf_size > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 7534 buf[i < (int) buf_size ? i : (int) buf_size - 1] = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 7535 }
Marko Mikulicic 0:c0ecb8bf28eb 7536
Marko Mikulicic 0:c0ecb8bf28eb 7537 return i;
Marko Mikulicic 0:c0ecb8bf28eb 7538 }
Marko Mikulicic 0:c0ecb8bf28eb 7539 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7540
Marko Mikulicic 0:c0ecb8bf28eb 7541 int c_snprintf(char *buf, size_t buf_size, const char *fmt, ...) {
Marko Mikulicic 0:c0ecb8bf28eb 7542 int result;
Marko Mikulicic 0:c0ecb8bf28eb 7543 va_list ap;
Marko Mikulicic 0:c0ecb8bf28eb 7544 va_start(ap, fmt);
Marko Mikulicic 0:c0ecb8bf28eb 7545 result = c_vsnprintf(buf, buf_size, fmt, ap);
Marko Mikulicic 0:c0ecb8bf28eb 7546 va_end(ap);
Marko Mikulicic 0:c0ecb8bf28eb 7547 return result;
Marko Mikulicic 0:c0ecb8bf28eb 7548 }
Marko Mikulicic 0:c0ecb8bf28eb 7549
Marko Mikulicic 0:c0ecb8bf28eb 7550 #ifdef _WIN32
Marko Mikulicic 0:c0ecb8bf28eb 7551 int to_wchar(const char *path, wchar_t *wbuf, size_t wbuf_len) {
Marko Mikulicic 0:c0ecb8bf28eb 7552 int ret;
Marko Mikulicic 0:c0ecb8bf28eb 7553 char buf[MAX_PATH * 2], buf2[MAX_PATH * 2], *p;
Marko Mikulicic 0:c0ecb8bf28eb 7554
Marko Mikulicic 0:c0ecb8bf28eb 7555 strncpy(buf, path, sizeof(buf));
Marko Mikulicic 0:c0ecb8bf28eb 7556 buf[sizeof(buf) - 1] = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 7557
Marko Mikulicic 0:c0ecb8bf28eb 7558 /* Trim trailing slashes. Leave backslash for paths like "X:\" */
Marko Mikulicic 0:c0ecb8bf28eb 7559 p = buf + strlen(buf) - 1;
Marko Mikulicic 0:c0ecb8bf28eb 7560 while (p > buf && p[-1] != ':' && (p[0] == '\\' || p[0] == '/')) *p-- = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 7561
Marko Mikulicic 0:c0ecb8bf28eb 7562 memset(wbuf, 0, wbuf_len * sizeof(wchar_t));
Marko Mikulicic 0:c0ecb8bf28eb 7563 ret = MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (int) wbuf_len);
Marko Mikulicic 0:c0ecb8bf28eb 7564
Marko Mikulicic 0:c0ecb8bf28eb 7565 /*
Marko Mikulicic 0:c0ecb8bf28eb 7566 * Convert back to Unicode. If doubly-converted string does not match the
Marko Mikulicic 0:c0ecb8bf28eb 7567 * original, something is fishy, reject.
Marko Mikulicic 0:c0ecb8bf28eb 7568 */
Marko Mikulicic 0:c0ecb8bf28eb 7569 WideCharToMultiByte(CP_UTF8, 0, wbuf, (int) wbuf_len, buf2, sizeof(buf2),
Marko Mikulicic 0:c0ecb8bf28eb 7570 NULL, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 7571 if (strcmp(buf, buf2) != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 7572 wbuf[0] = L'\0';
Marko Mikulicic 0:c0ecb8bf28eb 7573 ret = 0;
Marko Mikulicic 0:c0ecb8bf28eb 7574 }
Marko Mikulicic 0:c0ecb8bf28eb 7575
Marko Mikulicic 0:c0ecb8bf28eb 7576 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 7577 }
Marko Mikulicic 0:c0ecb8bf28eb 7578 #endif /* _WIN32 */
Marko Mikulicic 0:c0ecb8bf28eb 7579
Marko Mikulicic 0:c0ecb8bf28eb 7580 /* The simplest O(mn) algorithm. Better implementation are GPLed */
Marko Mikulicic 0:c0ecb8bf28eb 7581 const char *c_strnstr(const char *s, const char *find, size_t slen) {
Marko Mikulicic 0:c0ecb8bf28eb 7582 size_t find_length = strlen(find);
Marko Mikulicic 0:c0ecb8bf28eb 7583 size_t i;
Marko Mikulicic 0:c0ecb8bf28eb 7584
Marko Mikulicic 0:c0ecb8bf28eb 7585 for (i = 0; i < slen; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 7586 if (i + find_length > slen) {
Marko Mikulicic 0:c0ecb8bf28eb 7587 return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 7588 }
Marko Mikulicic 0:c0ecb8bf28eb 7589
Marko Mikulicic 0:c0ecb8bf28eb 7590 if (strncmp(&s[i], find, find_length) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 7591 return &s[i];
Marko Mikulicic 0:c0ecb8bf28eb 7592 }
Marko Mikulicic 0:c0ecb8bf28eb 7593 }
Marko Mikulicic 0:c0ecb8bf28eb 7594
Marko Mikulicic 0:c0ecb8bf28eb 7595 return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 7596 }
Marko Mikulicic 0:c0ecb8bf28eb 7597
Marko Mikulicic 0:c0ecb8bf28eb 7598 #endif /* EXCLUDE_COMMON */
Marko Mikulicic 0:c0ecb8bf28eb 7599 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 7600 #line 1 "common/utf.c"
Marko Mikulicic 0:c0ecb8bf28eb 7601 #endif
Marko Mikulicic 0:c0ecb8bf28eb 7602 /*
Marko Mikulicic 0:c0ecb8bf28eb 7603 * The authors of this software are Rob Pike and Ken Thompson.
Marko Mikulicic 0:c0ecb8bf28eb 7604 * Copyright (c) 2002 by Lucent Technologies.
Marko Mikulicic 0:c0ecb8bf28eb 7605 * Permission to use, copy, modify, and distribute this software for any
Marko Mikulicic 0:c0ecb8bf28eb 7606 * purpose without fee is hereby granted, provided that this entire notice
Marko Mikulicic 0:c0ecb8bf28eb 7607 * is included in all copies of any software which is or includes a copy
Marko Mikulicic 0:c0ecb8bf28eb 7608 * or modification of this software and in all copies of the supporting
Marko Mikulicic 0:c0ecb8bf28eb 7609 * documentation for such software.
Marko Mikulicic 0:c0ecb8bf28eb 7610 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
Marko Mikulicic 0:c0ecb8bf28eb 7611 * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE
Marko Mikulicic 0:c0ecb8bf28eb 7612 * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
Marko Mikulicic 0:c0ecb8bf28eb 7613 * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
Marko Mikulicic 0:c0ecb8bf28eb 7614 */
Marko Mikulicic 0:c0ecb8bf28eb 7615
Marko Mikulicic 0:c0ecb8bf28eb 7616 #ifndef EXCLUDE_COMMON
Marko Mikulicic 0:c0ecb8bf28eb 7617
Marko Mikulicic 0:c0ecb8bf28eb 7618 /* clang-format off */
Marko Mikulicic 0:c0ecb8bf28eb 7619
Marko Mikulicic 0:c0ecb8bf28eb 7620 #include <stdarg.h>
Marko Mikulicic 0:c0ecb8bf28eb 7621 #include <string.h>
Marko Mikulicic 0:c0ecb8bf28eb 7622 /* Amalgamated: #include "common/platform.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7623 /* Amalgamated: #include "common/utf.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7624
Marko Mikulicic 0:c0ecb8bf28eb 7625 #if CS_ENABLE_UTF8
Marko Mikulicic 0:c0ecb8bf28eb 7626 enum {
Marko Mikulicic 0:c0ecb8bf28eb 7627 Bit1 = 7,
Marko Mikulicic 0:c0ecb8bf28eb 7628 Bitx = 6,
Marko Mikulicic 0:c0ecb8bf28eb 7629 Bit2 = 5,
Marko Mikulicic 0:c0ecb8bf28eb 7630 Bit3 = 4,
Marko Mikulicic 0:c0ecb8bf28eb 7631 Bit4 = 3,
Marko Mikulicic 0:c0ecb8bf28eb 7632 Bit5 = 2,
Marko Mikulicic 0:c0ecb8bf28eb 7633
Marko Mikulicic 0:c0ecb8bf28eb 7634 T1 = ((1 << (Bit1 + 1)) - 1) ^ 0xFF, /* 0000 0000 */
Marko Mikulicic 0:c0ecb8bf28eb 7635 Tx = ((1 << (Bitx + 1)) - 1) ^ 0xFF, /* 1000 0000 */
Marko Mikulicic 0:c0ecb8bf28eb 7636 T2 = ((1 << (Bit2 + 1)) - 1) ^ 0xFF, /* 1100 0000 */
Marko Mikulicic 0:c0ecb8bf28eb 7637 T3 = ((1 << (Bit3 + 1)) - 1) ^ 0xFF, /* 1110 0000 */
Marko Mikulicic 0:c0ecb8bf28eb 7638 T4 = ((1 << (Bit4 + 1)) - 1) ^ 0xFF, /* 1111 0000 */
Marko Mikulicic 0:c0ecb8bf28eb 7639 T5 = ((1 << (Bit5 + 1)) - 1) ^ 0xFF, /* 1111 1000 */
Marko Mikulicic 0:c0ecb8bf28eb 7640
Marko Mikulicic 0:c0ecb8bf28eb 7641 Rune1 = (1 << (Bit1 + 0 * Bitx)) - 1, /* 0000 0000 0000 0000 0111 1111 */
Marko Mikulicic 0:c0ecb8bf28eb 7642 Rune2 = (1 << (Bit2 + 1 * Bitx)) - 1, /* 0000 0000 0000 0111 1111 1111 */
Marko Mikulicic 0:c0ecb8bf28eb 7643 Rune3 = (1 << (Bit3 + 2 * Bitx)) - 1, /* 0000 0000 1111 1111 1111 1111 */
Marko Mikulicic 0:c0ecb8bf28eb 7644 Rune4 = (1 << (Bit4 + 3 * Bitx)) - 1, /* 0011 1111 1111 1111 1111 1111 */
Marko Mikulicic 0:c0ecb8bf28eb 7645
Marko Mikulicic 0:c0ecb8bf28eb 7646 Maskx = (1 << Bitx) - 1, /* 0011 1111 */
Marko Mikulicic 0:c0ecb8bf28eb 7647 Testx = Maskx ^ 0xFF, /* 1100 0000 */
Marko Mikulicic 0:c0ecb8bf28eb 7648
Marko Mikulicic 0:c0ecb8bf28eb 7649 Bad = Runeerror
Marko Mikulicic 0:c0ecb8bf28eb 7650 };
Marko Mikulicic 0:c0ecb8bf28eb 7651
Marko Mikulicic 0:c0ecb8bf28eb 7652 int chartorune(Rune *rune, const char *str) {
Marko Mikulicic 0:c0ecb8bf28eb 7653 int c, c1, c2 /* , c3 */;
Marko Mikulicic 0:c0ecb8bf28eb 7654 unsigned short l;
Marko Mikulicic 0:c0ecb8bf28eb 7655
Marko Mikulicic 0:c0ecb8bf28eb 7656 /*
Marko Mikulicic 0:c0ecb8bf28eb 7657 * one character sequence
Marko Mikulicic 0:c0ecb8bf28eb 7658 * 00000-0007F => T1
Marko Mikulicic 0:c0ecb8bf28eb 7659 */
Marko Mikulicic 0:c0ecb8bf28eb 7660 c = *(uchar *) str;
Marko Mikulicic 0:c0ecb8bf28eb 7661 if (c < Tx) {
Marko Mikulicic 0:c0ecb8bf28eb 7662 *rune = c;
Marko Mikulicic 0:c0ecb8bf28eb 7663 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 7664 }
Marko Mikulicic 0:c0ecb8bf28eb 7665
Marko Mikulicic 0:c0ecb8bf28eb 7666 /*
Marko Mikulicic 0:c0ecb8bf28eb 7667 * two character sequence
Marko Mikulicic 0:c0ecb8bf28eb 7668 * 0080-07FF => T2 Tx
Marko Mikulicic 0:c0ecb8bf28eb 7669 */
Marko Mikulicic 0:c0ecb8bf28eb 7670 c1 = *(uchar *) (str + 1) ^ Tx;
Marko Mikulicic 0:c0ecb8bf28eb 7671 if (c1 & Testx) goto bad;
Marko Mikulicic 0:c0ecb8bf28eb 7672 if (c < T3) {
Marko Mikulicic 0:c0ecb8bf28eb 7673 if (c < T2) goto bad;
Marko Mikulicic 0:c0ecb8bf28eb 7674 l = ((c << Bitx) | c1) & Rune2;
Marko Mikulicic 0:c0ecb8bf28eb 7675 if (l <= Rune1) goto bad;
Marko Mikulicic 0:c0ecb8bf28eb 7676 *rune = l;
Marko Mikulicic 0:c0ecb8bf28eb 7677 return 2;
Marko Mikulicic 0:c0ecb8bf28eb 7678 }
Marko Mikulicic 0:c0ecb8bf28eb 7679
Marko Mikulicic 0:c0ecb8bf28eb 7680 /*
Marko Mikulicic 0:c0ecb8bf28eb 7681 * three character sequence
Marko Mikulicic 0:c0ecb8bf28eb 7682 * 0800-FFFF => T3 Tx Tx
Marko Mikulicic 0:c0ecb8bf28eb 7683 */
Marko Mikulicic 0:c0ecb8bf28eb 7684 c2 = *(uchar *) (str + 2) ^ Tx;
Marko Mikulicic 0:c0ecb8bf28eb 7685 if (c2 & Testx) goto bad;
Marko Mikulicic 0:c0ecb8bf28eb 7686 if (c < T4) {
Marko Mikulicic 0:c0ecb8bf28eb 7687 l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3;
Marko Mikulicic 0:c0ecb8bf28eb 7688 if (l <= Rune2) goto bad;
Marko Mikulicic 0:c0ecb8bf28eb 7689 *rune = l;
Marko Mikulicic 0:c0ecb8bf28eb 7690 return 3;
Marko Mikulicic 0:c0ecb8bf28eb 7691 }
Marko Mikulicic 0:c0ecb8bf28eb 7692
Marko Mikulicic 0:c0ecb8bf28eb 7693 /*
Marko Mikulicic 0:c0ecb8bf28eb 7694 * four character sequence
Marko Mikulicic 0:c0ecb8bf28eb 7695 * 10000-10FFFF => T4 Tx Tx Tx
Marko Mikulicic 0:c0ecb8bf28eb 7696 */
Marko Mikulicic 0:c0ecb8bf28eb 7697 /* if(UTFmax >= 4) {
Marko Mikulicic 0:c0ecb8bf28eb 7698 c3 = *(uchar*)(str+3) ^ Tx;
Marko Mikulicic 0:c0ecb8bf28eb 7699 if(c3 & Testx)
Marko Mikulicic 0:c0ecb8bf28eb 7700 goto bad;
Marko Mikulicic 0:c0ecb8bf28eb 7701 if(c < T5) {
Marko Mikulicic 0:c0ecb8bf28eb 7702 l = ((((((c << Bitx) | c1) << Bitx) | c2) << Bitx) | c3) &
Marko Mikulicic 0:c0ecb8bf28eb 7703 Rune4;
Marko Mikulicic 0:c0ecb8bf28eb 7704 if(l <= Rune3)
Marko Mikulicic 0:c0ecb8bf28eb 7705 goto bad;
Marko Mikulicic 0:c0ecb8bf28eb 7706 if(l > Runemax)
Marko Mikulicic 0:c0ecb8bf28eb 7707 goto bad;
Marko Mikulicic 0:c0ecb8bf28eb 7708 *rune = l;
Marko Mikulicic 0:c0ecb8bf28eb 7709 return 4;
Marko Mikulicic 0:c0ecb8bf28eb 7710 }
Marko Mikulicic 0:c0ecb8bf28eb 7711 } */
Marko Mikulicic 0:c0ecb8bf28eb 7712
Marko Mikulicic 0:c0ecb8bf28eb 7713 /*
Marko Mikulicic 0:c0ecb8bf28eb 7714 * bad decoding
Marko Mikulicic 0:c0ecb8bf28eb 7715 */
Marko Mikulicic 0:c0ecb8bf28eb 7716 bad:
Marko Mikulicic 0:c0ecb8bf28eb 7717 *rune = Bad;
Marko Mikulicic 0:c0ecb8bf28eb 7718 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 7719 }
Marko Mikulicic 0:c0ecb8bf28eb 7720
Marko Mikulicic 0:c0ecb8bf28eb 7721 int runetochar(char *str, Rune *rune) {
Marko Mikulicic 0:c0ecb8bf28eb 7722 unsigned short c;
Marko Mikulicic 0:c0ecb8bf28eb 7723
Marko Mikulicic 0:c0ecb8bf28eb 7724 /*
Marko Mikulicic 0:c0ecb8bf28eb 7725 * one character sequence
Marko Mikulicic 0:c0ecb8bf28eb 7726 * 00000-0007F => 00-7F
Marko Mikulicic 0:c0ecb8bf28eb 7727 */
Marko Mikulicic 0:c0ecb8bf28eb 7728 c = *rune;
Marko Mikulicic 0:c0ecb8bf28eb 7729 if (c <= Rune1) {
Marko Mikulicic 0:c0ecb8bf28eb 7730 str[0] = c;
Marko Mikulicic 0:c0ecb8bf28eb 7731 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 7732 }
Marko Mikulicic 0:c0ecb8bf28eb 7733
Marko Mikulicic 0:c0ecb8bf28eb 7734 /*
Marko Mikulicic 0:c0ecb8bf28eb 7735 * two character sequence
Marko Mikulicic 0:c0ecb8bf28eb 7736 * 00080-007FF => T2 Tx
Marko Mikulicic 0:c0ecb8bf28eb 7737 */
Marko Mikulicic 0:c0ecb8bf28eb 7738 if (c <= Rune2) {
Marko Mikulicic 0:c0ecb8bf28eb 7739 str[0] = T2 | (c >> 1 * Bitx);
Marko Mikulicic 0:c0ecb8bf28eb 7740 str[1] = Tx | (c & Maskx);
Marko Mikulicic 0:c0ecb8bf28eb 7741 return 2;
Marko Mikulicic 0:c0ecb8bf28eb 7742 }
Marko Mikulicic 0:c0ecb8bf28eb 7743
Marko Mikulicic 0:c0ecb8bf28eb 7744 /*
Marko Mikulicic 0:c0ecb8bf28eb 7745 * three character sequence
Marko Mikulicic 0:c0ecb8bf28eb 7746 * 00800-0FFFF => T3 Tx Tx
Marko Mikulicic 0:c0ecb8bf28eb 7747 */
Marko Mikulicic 0:c0ecb8bf28eb 7748 /* if(c > Runemax)
Marko Mikulicic 0:c0ecb8bf28eb 7749 c = Runeerror; */
Marko Mikulicic 0:c0ecb8bf28eb 7750 /* if(c <= Rune3) { */
Marko Mikulicic 0:c0ecb8bf28eb 7751 str[0] = T3 | (c >> 2 * Bitx);
Marko Mikulicic 0:c0ecb8bf28eb 7752 str[1] = Tx | ((c >> 1 * Bitx) & Maskx);
Marko Mikulicic 0:c0ecb8bf28eb 7753 str[2] = Tx | (c & Maskx);
Marko Mikulicic 0:c0ecb8bf28eb 7754 return 3;
Marko Mikulicic 0:c0ecb8bf28eb 7755 /* } */
Marko Mikulicic 0:c0ecb8bf28eb 7756
Marko Mikulicic 0:c0ecb8bf28eb 7757 /*
Marko Mikulicic 0:c0ecb8bf28eb 7758 * four character sequence
Marko Mikulicic 0:c0ecb8bf28eb 7759 * 010000-1FFFFF => T4 Tx Tx Tx
Marko Mikulicic 0:c0ecb8bf28eb 7760 */
Marko Mikulicic 0:c0ecb8bf28eb 7761 /* str[0] = T4 | (c >> 3*Bitx);
Marko Mikulicic 0:c0ecb8bf28eb 7762 str[1] = Tx | ((c >> 2*Bitx) & Maskx);
Marko Mikulicic 0:c0ecb8bf28eb 7763 str[2] = Tx | ((c >> 1*Bitx) & Maskx);
Marko Mikulicic 0:c0ecb8bf28eb 7764 str[3] = Tx | (c & Maskx);
Marko Mikulicic 0:c0ecb8bf28eb 7765 return 4; */
Marko Mikulicic 0:c0ecb8bf28eb 7766 }
Marko Mikulicic 0:c0ecb8bf28eb 7767
Marko Mikulicic 0:c0ecb8bf28eb 7768 int fullrune(const char *str, int n) {
Marko Mikulicic 0:c0ecb8bf28eb 7769 int c;
Marko Mikulicic 0:c0ecb8bf28eb 7770
Marko Mikulicic 0:c0ecb8bf28eb 7771 if (n <= 0) return 0;
Marko Mikulicic 0:c0ecb8bf28eb 7772 c = *(uchar *) str;
Marko Mikulicic 0:c0ecb8bf28eb 7773 if (c < Tx) return 1;
Marko Mikulicic 0:c0ecb8bf28eb 7774 if (c < T3) return n >= 2;
Marko Mikulicic 0:c0ecb8bf28eb 7775 if (UTFmax == 3 || c < T4) return n >= 3;
Marko Mikulicic 0:c0ecb8bf28eb 7776 return n >= 4;
Marko Mikulicic 0:c0ecb8bf28eb 7777 }
Marko Mikulicic 0:c0ecb8bf28eb 7778
Marko Mikulicic 0:c0ecb8bf28eb 7779 int utfnlen(const char *s, long m) {
Marko Mikulicic 0:c0ecb8bf28eb 7780 int c;
Marko Mikulicic 0:c0ecb8bf28eb 7781 long n;
Marko Mikulicic 0:c0ecb8bf28eb 7782 Rune rune;
Marko Mikulicic 0:c0ecb8bf28eb 7783 const char *es;
Marko Mikulicic 0:c0ecb8bf28eb 7784
Marko Mikulicic 0:c0ecb8bf28eb 7785 es = s + m;
Marko Mikulicic 0:c0ecb8bf28eb 7786 for (n = 0; s < es; n++) {
Marko Mikulicic 0:c0ecb8bf28eb 7787 c = *(uchar *) s;
Marko Mikulicic 0:c0ecb8bf28eb 7788 if (c < Runeself) {
Marko Mikulicic 0:c0ecb8bf28eb 7789 s++;
Marko Mikulicic 0:c0ecb8bf28eb 7790 continue;
Marko Mikulicic 0:c0ecb8bf28eb 7791 }
Marko Mikulicic 0:c0ecb8bf28eb 7792 if (!fullrune(s, es - s)) break;
Marko Mikulicic 0:c0ecb8bf28eb 7793 s += chartorune(&rune, s);
Marko Mikulicic 0:c0ecb8bf28eb 7794 }
Marko Mikulicic 0:c0ecb8bf28eb 7795 return n;
Marko Mikulicic 0:c0ecb8bf28eb 7796 }
Marko Mikulicic 0:c0ecb8bf28eb 7797
Marko Mikulicic 0:c0ecb8bf28eb 7798 const char *utfnshift(const char *s, long m) {
Marko Mikulicic 0:c0ecb8bf28eb 7799 int c;
Marko Mikulicic 0:c0ecb8bf28eb 7800 long n;
Marko Mikulicic 0:c0ecb8bf28eb 7801 Rune rune;
Marko Mikulicic 0:c0ecb8bf28eb 7802
Marko Mikulicic 0:c0ecb8bf28eb 7803 for (n = 0; n < m; n++) {
Marko Mikulicic 0:c0ecb8bf28eb 7804 c = *(uchar *) s;
Marko Mikulicic 0:c0ecb8bf28eb 7805 if (c < Runeself) {
Marko Mikulicic 0:c0ecb8bf28eb 7806 s++;
Marko Mikulicic 0:c0ecb8bf28eb 7807 continue;
Marko Mikulicic 0:c0ecb8bf28eb 7808 }
Marko Mikulicic 0:c0ecb8bf28eb 7809 s += chartorune(&rune, s);
Marko Mikulicic 0:c0ecb8bf28eb 7810 }
Marko Mikulicic 0:c0ecb8bf28eb 7811 return s;
Marko Mikulicic 0:c0ecb8bf28eb 7812 }
Marko Mikulicic 0:c0ecb8bf28eb 7813
Marko Mikulicic 0:c0ecb8bf28eb 7814 /*
Marko Mikulicic 0:c0ecb8bf28eb 7815 * The authors of this software are Rob Pike and Ken Thompson.
Marko Mikulicic 0:c0ecb8bf28eb 7816 * Copyright (c) 2002 by Lucent Technologies.
Marko Mikulicic 0:c0ecb8bf28eb 7817 * Permission to use, copy, modify, and distribute this software for any
Marko Mikulicic 0:c0ecb8bf28eb 7818 * purpose without fee is hereby granted, provided that this entire notice
Marko Mikulicic 0:c0ecb8bf28eb 7819 * is included in all copies of any software which is or includes a copy
Marko Mikulicic 0:c0ecb8bf28eb 7820 * or modification of this software and in all copies of the supporting
Marko Mikulicic 0:c0ecb8bf28eb 7821 * documentation for such software.
Marko Mikulicic 0:c0ecb8bf28eb 7822 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
Marko Mikulicic 0:c0ecb8bf28eb 7823 * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE
Marko Mikulicic 0:c0ecb8bf28eb 7824 * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
Marko Mikulicic 0:c0ecb8bf28eb 7825 * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
Marko Mikulicic 0:c0ecb8bf28eb 7826 */
Marko Mikulicic 0:c0ecb8bf28eb 7827 #include <stdarg.h>
Marko Mikulicic 0:c0ecb8bf28eb 7828 #include <string.h>
Marko Mikulicic 0:c0ecb8bf28eb 7829 /* Amalgamated: #include "common/utf.h" */
Marko Mikulicic 0:c0ecb8bf28eb 7830
Marko Mikulicic 0:c0ecb8bf28eb 7831 /*
Marko Mikulicic 0:c0ecb8bf28eb 7832 * alpha ranges -
Marko Mikulicic 0:c0ecb8bf28eb 7833 * only covers ranges not in lower||upper
Marko Mikulicic 0:c0ecb8bf28eb 7834 */
Marko Mikulicic 0:c0ecb8bf28eb 7835 static Rune __alpha2[] = {
Marko Mikulicic 0:c0ecb8bf28eb 7836 0x00d8, 0x00f6, /* Ø - ö */
Marko Mikulicic 0:c0ecb8bf28eb 7837 0x00f8, 0x01f5, /* ø - ǵ */
Marko Mikulicic 0:c0ecb8bf28eb 7838 0x0250, 0x02a8, /* ɐ - ʨ */
Marko Mikulicic 0:c0ecb8bf28eb 7839 0x038e, 0x03a1, /* Ύ - Ρ */
Marko Mikulicic 0:c0ecb8bf28eb 7840 0x03a3, 0x03ce, /* Σ - ώ */
Marko Mikulicic 0:c0ecb8bf28eb 7841 0x03d0, 0x03d6, /* ϐ - ϖ */
Marko Mikulicic 0:c0ecb8bf28eb 7842 0x03e2, 0x03f3, /* Ϣ - ϳ */
Marko Mikulicic 0:c0ecb8bf28eb 7843 0x0490, 0x04c4, /* Ґ - ӄ */
Marko Mikulicic 0:c0ecb8bf28eb 7844 0x0561, 0x0587, /* ա - և */
Marko Mikulicic 0:c0ecb8bf28eb 7845 0x05d0, 0x05ea, /* א - ת */
Marko Mikulicic 0:c0ecb8bf28eb 7846 0x05f0, 0x05f2, /* װ - ײ */
Marko Mikulicic 0:c0ecb8bf28eb 7847 0x0621, 0x063a, /* ء - غ */
Marko Mikulicic 0:c0ecb8bf28eb 7848 0x0640, 0x064a, /* ـ - ي */
Marko Mikulicic 0:c0ecb8bf28eb 7849 0x0671, 0x06b7, /* ٱ - ڷ */
Marko Mikulicic 0:c0ecb8bf28eb 7850 0x06ba, 0x06be, /* ں - ھ */
Marko Mikulicic 0:c0ecb8bf28eb 7851 0x06c0, 0x06ce, /* ۀ - ێ */
Marko Mikulicic 0:c0ecb8bf28eb 7852 0x06d0, 0x06d3, /* ې - ۓ */
Marko Mikulicic 0:c0ecb8bf28eb 7853 0x0905, 0x0939, /* अ - ह */
Marko Mikulicic 0:c0ecb8bf28eb 7854 0x0958, 0x0961, /* क़ - ॡ */
Marko Mikulicic 0:c0ecb8bf28eb 7855 0x0985, 0x098c, /* অ - ঌ */
Marko Mikulicic 0:c0ecb8bf28eb 7856 0x098f, 0x0990, /* এ - ঐ */
Marko Mikulicic 0:c0ecb8bf28eb 7857 0x0993, 0x09a8, /* ও - ন */
Marko Mikulicic 0:c0ecb8bf28eb 7858 0x09aa, 0x09b0, /* প - র */
Marko Mikulicic 0:c0ecb8bf28eb 7859 0x09b6, 0x09b9, /* শ - হ */
Marko Mikulicic 0:c0ecb8bf28eb 7860 0x09dc, 0x09dd, /* ড় - ঢ় */
Marko Mikulicic 0:c0ecb8bf28eb 7861 0x09df, 0x09e1, /* য় - ৡ */
Marko Mikulicic 0:c0ecb8bf28eb 7862 0x09f0, 0x09f1, /* ৰ - ৱ */
Marko Mikulicic 0:c0ecb8bf28eb 7863 0x0a05, 0x0a0a, /* ਅ - ਊ */
Marko Mikulicic 0:c0ecb8bf28eb 7864 0x0a0f, 0x0a10, /* ਏ - ਐ */
Marko Mikulicic 0:c0ecb8bf28eb 7865 0x0a13, 0x0a28, /* ਓ - ਨ */
Marko Mikulicic 0:c0ecb8bf28eb 7866 0x0a2a, 0x0a30, /* ਪ - ਰ */
Marko Mikulicic 0:c0ecb8bf28eb 7867 0x0a32, 0x0a33, /* ਲ - ਲ਼ */
Marko Mikulicic 0:c0ecb8bf28eb 7868 0x0a35, 0x0a36, /* ਵ - ਸ਼ */
Marko Mikulicic 0:c0ecb8bf28eb 7869 0x0a38, 0x0a39, /* ਸ - ਹ */
Marko Mikulicic 0:c0ecb8bf28eb 7870 0x0a59, 0x0a5c, /* ਖ਼ - ੜ */
Marko Mikulicic 0:c0ecb8bf28eb 7871 0x0a85, 0x0a8b, /* અ - ઋ */
Marko Mikulicic 0:c0ecb8bf28eb 7872 0x0a8f, 0x0a91, /* એ - ઑ */
Marko Mikulicic 0:c0ecb8bf28eb 7873 0x0a93, 0x0aa8, /* ઓ - ન */
Marko Mikulicic 0:c0ecb8bf28eb 7874 0x0aaa, 0x0ab0, /* પ - ર */
Marko Mikulicic 0:c0ecb8bf28eb 7875 0x0ab2, 0x0ab3, /* લ - ળ */
Marko Mikulicic 0:c0ecb8bf28eb 7876 0x0ab5, 0x0ab9, /* વ - હ */
Marko Mikulicic 0:c0ecb8bf28eb 7877 0x0b05, 0x0b0c, /* ଅ - ଌ */
Marko Mikulicic 0:c0ecb8bf28eb 7878 0x0b0f, 0x0b10, /* ଏ - ଐ */
Marko Mikulicic 0:c0ecb8bf28eb 7879 0x0b13, 0x0b28, /* ଓ - ନ */
Marko Mikulicic 0:c0ecb8bf28eb 7880 0x0b2a, 0x0b30, /* ପ - ର */
Marko Mikulicic 0:c0ecb8bf28eb 7881 0x0b32, 0x0b33, /* ଲ - ଳ */
Marko Mikulicic 0:c0ecb8bf28eb 7882 0x0b36, 0x0b39, /* ଶ - ହ */
Marko Mikulicic 0:c0ecb8bf28eb 7883 0x0b5c, 0x0b5d, /* ଡ଼ - ଢ଼ */
Marko Mikulicic 0:c0ecb8bf28eb 7884 0x0b5f, 0x0b61, /* ୟ - ୡ */
Marko Mikulicic 0:c0ecb8bf28eb 7885 0x0b85, 0x0b8a, /* அ - ஊ */
Marko Mikulicic 0:c0ecb8bf28eb 7886 0x0b8e, 0x0b90, /* எ - ஐ */
Marko Mikulicic 0:c0ecb8bf28eb 7887 0x0b92, 0x0b95, /* ஒ - க */
Marko Mikulicic 0:c0ecb8bf28eb 7888 0x0b99, 0x0b9a, /* ங - ச */
Marko Mikulicic 0:c0ecb8bf28eb 7889 0x0b9e, 0x0b9f, /* ஞ - ட */
Marko Mikulicic 0:c0ecb8bf28eb 7890 0x0ba3, 0x0ba4, /* ண - த */
Marko Mikulicic 0:c0ecb8bf28eb 7891 0x0ba8, 0x0baa, /* ந - ப */
Marko Mikulicic 0:c0ecb8bf28eb 7892 0x0bae, 0x0bb5, /* ம - வ */
Marko Mikulicic 0:c0ecb8bf28eb 7893 0x0bb7, 0x0bb9, /* ஷ - ஹ */
Marko Mikulicic 0:c0ecb8bf28eb 7894 0x0c05, 0x0c0c, /* అ - ఌ */
Marko Mikulicic 0:c0ecb8bf28eb 7895 0x0c0e, 0x0c10, /* ఎ - ఐ */
Marko Mikulicic 0:c0ecb8bf28eb 7896 0x0c12, 0x0c28, /* ఒ - న */
Marko Mikulicic 0:c0ecb8bf28eb 7897 0x0c2a, 0x0c33, /* ప - ళ */
Marko Mikulicic 0:c0ecb8bf28eb 7898 0x0c35, 0x0c39, /* వ - హ */
Marko Mikulicic 0:c0ecb8bf28eb 7899 0x0c60, 0x0c61, /* ౠ - ౡ */
Marko Mikulicic 0:c0ecb8bf28eb 7900 0x0c85, 0x0c8c, /* ಅ - ಌ */
Marko Mikulicic 0:c0ecb8bf28eb 7901 0x0c8e, 0x0c90, /* ಎ - ಐ */
Marko Mikulicic 0:c0ecb8bf28eb 7902 0x0c92, 0x0ca8, /* ಒ - ನ */
Marko Mikulicic 0:c0ecb8bf28eb 7903 0x0caa, 0x0cb3, /* ಪ - ಳ */
Marko Mikulicic 0:c0ecb8bf28eb 7904 0x0cb5, 0x0cb9, /* ವ - ಹ */
Marko Mikulicic 0:c0ecb8bf28eb 7905 0x0ce0, 0x0ce1, /* ೠ - ೡ */
Marko Mikulicic 0:c0ecb8bf28eb 7906 0x0d05, 0x0d0c, /* അ - ഌ */
Marko Mikulicic 0:c0ecb8bf28eb 7907 0x0d0e, 0x0d10, /* എ - ഐ */
Marko Mikulicic 0:c0ecb8bf28eb 7908 0x0d12, 0x0d28, /* ഒ - ന */
Marko Mikulicic 0:c0ecb8bf28eb 7909 0x0d2a, 0x0d39, /* പ - ഹ */
Marko Mikulicic 0:c0ecb8bf28eb 7910 0x0d60, 0x0d61, /* ൠ - ൡ */
Marko Mikulicic 0:c0ecb8bf28eb 7911 0x0e01, 0x0e30, /* ก - ะ */
Marko Mikulicic 0:c0ecb8bf28eb 7912 0x0e32, 0x0e33, /* า - ำ */
Marko Mikulicic 0:c0ecb8bf28eb 7913 0x0e40, 0x0e46, /* เ - ๆ */
Marko Mikulicic 0:c0ecb8bf28eb 7914 0x0e5a, 0x0e5b, /* ๚ - ๛ */
Marko Mikulicic 0:c0ecb8bf28eb 7915 0x0e81, 0x0e82, /* ກ - ຂ */
Marko Mikulicic 0:c0ecb8bf28eb 7916 0x0e87, 0x0e88, /* ງ - ຈ */
Marko Mikulicic 0:c0ecb8bf28eb 7917 0x0e94, 0x0e97, /* ດ - ທ */
Marko Mikulicic 0:c0ecb8bf28eb 7918 0x0e99, 0x0e9f, /* ນ - ຟ */
Marko Mikulicic 0:c0ecb8bf28eb 7919 0x0ea1, 0x0ea3, /* ມ - ຣ */
Marko Mikulicic 0:c0ecb8bf28eb 7920 0x0eaa, 0x0eab, /* ສ - ຫ */
Marko Mikulicic 0:c0ecb8bf28eb 7921 0x0ead, 0x0eae, /* ອ - ຮ */
Marko Mikulicic 0:c0ecb8bf28eb 7922 0x0eb2, 0x0eb3, /* າ - ຳ */
Marko Mikulicic 0:c0ecb8bf28eb 7923 0x0ec0, 0x0ec4, /* ເ - ໄ */
Marko Mikulicic 0:c0ecb8bf28eb 7924 0x0edc, 0x0edd, /* ໜ - ໝ */
Marko Mikulicic 0:c0ecb8bf28eb 7925 0x0f18, 0x0f19, /* ༘ - ༙ */
Marko Mikulicic 0:c0ecb8bf28eb 7926 0x0f40, 0x0f47, /* ཀ - ཇ */
Marko Mikulicic 0:c0ecb8bf28eb 7927 0x0f49, 0x0f69, /* ཉ - ཀྵ */
Marko Mikulicic 0:c0ecb8bf28eb 7928 0x10d0, 0x10f6, /* ა - ჶ */
Marko Mikulicic 0:c0ecb8bf28eb 7929 0x1100, 0x1159, /* ᄀ - ᅙ */
Marko Mikulicic 0:c0ecb8bf28eb 7930 0x115f, 0x11a2, /* ᅟ - ᆢ */
Marko Mikulicic 0:c0ecb8bf28eb 7931 0x11a8, 0x11f9, /* ᆨ - ᇹ */
Marko Mikulicic 0:c0ecb8bf28eb 7932 0x1e00, 0x1e9b, /* Ḁ - ẛ */
Marko Mikulicic 0:c0ecb8bf28eb 7933 0x1f50, 0x1f57, /* ὐ - ὗ */
Marko Mikulicic 0:c0ecb8bf28eb 7934 0x1f80, 0x1fb4, /* ᾀ - ᾴ */
Marko Mikulicic 0:c0ecb8bf28eb 7935 0x1fb6, 0x1fbc, /* ᾶ - ᾼ */
Marko Mikulicic 0:c0ecb8bf28eb 7936 0x1fc2, 0x1fc4, /* ῂ - ῄ */
Marko Mikulicic 0:c0ecb8bf28eb 7937 0x1fc6, 0x1fcc, /* ῆ - ῌ */
Marko Mikulicic 0:c0ecb8bf28eb 7938 0x1fd0, 0x1fd3, /* ῐ - ΐ */
Marko Mikulicic 0:c0ecb8bf28eb 7939 0x1fd6, 0x1fdb, /* ῖ - Ί */
Marko Mikulicic 0:c0ecb8bf28eb 7940 0x1fe0, 0x1fec, /* ῠ - Ῥ */
Marko Mikulicic 0:c0ecb8bf28eb 7941 0x1ff2, 0x1ff4, /* ῲ - ῴ */
Marko Mikulicic 0:c0ecb8bf28eb 7942 0x1ff6, 0x1ffc, /* ῶ - ῼ */
Marko Mikulicic 0:c0ecb8bf28eb 7943 0x210a, 0x2113, /* ℊ - ℓ */
Marko Mikulicic 0:c0ecb8bf28eb 7944 0x2115, 0x211d, /* ℕ - ℝ */
Marko Mikulicic 0:c0ecb8bf28eb 7945 0x2120, 0x2122, /* ℠ - ™ */
Marko Mikulicic 0:c0ecb8bf28eb 7946 0x212a, 0x2131, /* K - ℱ */
Marko Mikulicic 0:c0ecb8bf28eb 7947 0x2133, 0x2138, /* ℳ - ℸ */
Marko Mikulicic 0:c0ecb8bf28eb 7948 0x3041, 0x3094, /* ぁ - ゔ */
Marko Mikulicic 0:c0ecb8bf28eb 7949 0x30a1, 0x30fa, /* ァ - ヺ */
Marko Mikulicic 0:c0ecb8bf28eb 7950 0x3105, 0x312c, /* ㄅ - ㄬ */
Marko Mikulicic 0:c0ecb8bf28eb 7951 0x3131, 0x318e, /* ㄱ - ㆎ */
Marko Mikulicic 0:c0ecb8bf28eb 7952 0x3192, 0x319f, /* ㆒ - ㆟ */
Marko Mikulicic 0:c0ecb8bf28eb 7953 0x3260, 0x327b, /* ㉠ - ㉻ */
Marko Mikulicic 0:c0ecb8bf28eb 7954 0x328a, 0x32b0, /* ㊊ - ㊰ */
Marko Mikulicic 0:c0ecb8bf28eb 7955 0x32d0, 0x32fe, /* ㋐ - ㋾ */
Marko Mikulicic 0:c0ecb8bf28eb 7956 0x3300, 0x3357, /* ㌀ - ㍗ */
Marko Mikulicic 0:c0ecb8bf28eb 7957 0x3371, 0x3376, /* ㍱ - ㍶ */
Marko Mikulicic 0:c0ecb8bf28eb 7958 0x337b, 0x3394, /* ㍻ - ㎔ */
Marko Mikulicic 0:c0ecb8bf28eb 7959 0x3399, 0x339e, /* ㎙ - ㎞ */
Marko Mikulicic 0:c0ecb8bf28eb 7960 0x33a9, 0x33ad, /* ㎩ - ㎭ */
Marko Mikulicic 0:c0ecb8bf28eb 7961 0x33b0, 0x33c1, /* ㎰ - ㏁ */
Marko Mikulicic 0:c0ecb8bf28eb 7962 0x33c3, 0x33c5, /* ㏃ - ㏅ */
Marko Mikulicic 0:c0ecb8bf28eb 7963 0x33c7, 0x33d7, /* ㏇ - ㏗ */
Marko Mikulicic 0:c0ecb8bf28eb 7964 0x33d9, 0x33dd, /* ㏙ - ㏝ */
Marko Mikulicic 0:c0ecb8bf28eb 7965 0x4e00, 0x9fff, /* 一 - 鿿 */
Marko Mikulicic 0:c0ecb8bf28eb 7966 0xac00, 0xd7a3, /* 가 - 힣 */
Marko Mikulicic 0:c0ecb8bf28eb 7967 0xf900, 0xfb06, /* 豈 - st */
Marko Mikulicic 0:c0ecb8bf28eb 7968 0xfb13, 0xfb17, /* ﬓ - ﬗ */
Marko Mikulicic 0:c0ecb8bf28eb 7969 0xfb1f, 0xfb28, /* ײַ - ﬨ */
Marko Mikulicic 0:c0ecb8bf28eb 7970 0xfb2a, 0xfb36, /* שׁ - זּ */
Marko Mikulicic 0:c0ecb8bf28eb 7971 0xfb38, 0xfb3c, /* טּ - לּ */
Marko Mikulicic 0:c0ecb8bf28eb 7972 0xfb40, 0xfb41, /* נּ - סּ */
Marko Mikulicic 0:c0ecb8bf28eb 7973 0xfb43, 0xfb44, /* ףּ - פּ */
Marko Mikulicic 0:c0ecb8bf28eb 7974 0xfb46, 0xfbb1, /* צּ - ﮱ */
Marko Mikulicic 0:c0ecb8bf28eb 7975 0xfbd3, 0xfd3d, /* ﯓ - ﴽ */
Marko Mikulicic 0:c0ecb8bf28eb 7976 0xfd50, 0xfd8f, /* ﵐ - ﶏ */
Marko Mikulicic 0:c0ecb8bf28eb 7977 0xfd92, 0xfdc7, /* ﶒ - ﷇ */
Marko Mikulicic 0:c0ecb8bf28eb 7978 0xfdf0, 0xfdf9, /* ﷰ - ﷹ */
Marko Mikulicic 0:c0ecb8bf28eb 7979 0xfe70, 0xfe72, /* ﹰ - ﹲ */
Marko Mikulicic 0:c0ecb8bf28eb 7980 0xfe76, 0xfefc, /* ﹶ - ﻼ */
Marko Mikulicic 0:c0ecb8bf28eb 7981 0xff66, 0xff6f, /* ヲ - ッ */
Marko Mikulicic 0:c0ecb8bf28eb 7982 0xff71, 0xff9d, /* ア - ン */
Marko Mikulicic 0:c0ecb8bf28eb 7983 0xffa0, 0xffbe, /* ᅠ - ᄒ */
Marko Mikulicic 0:c0ecb8bf28eb 7984 0xffc2, 0xffc7, /* ᅡ - ᅦ */
Marko Mikulicic 0:c0ecb8bf28eb 7985 0xffca, 0xffcf, /* ᅧ - ᅬ */
Marko Mikulicic 0:c0ecb8bf28eb 7986 0xffd2, 0xffd7, /* ᅭ - ᅲ */
Marko Mikulicic 0:c0ecb8bf28eb 7987 0xffda, 0xffdc, /* ᅳ - ᅵ */
Marko Mikulicic 0:c0ecb8bf28eb 7988 };
Marko Mikulicic 0:c0ecb8bf28eb 7989
Marko Mikulicic 0:c0ecb8bf28eb 7990 /*
Marko Mikulicic 0:c0ecb8bf28eb 7991 * alpha singlets -
Marko Mikulicic 0:c0ecb8bf28eb 7992 * only covers ranges not in lower||upper
Marko Mikulicic 0:c0ecb8bf28eb 7993 */
Marko Mikulicic 0:c0ecb8bf28eb 7994 static Rune __alpha1[] = {
Marko Mikulicic 0:c0ecb8bf28eb 7995 0x00aa, /* ª */
Marko Mikulicic 0:c0ecb8bf28eb 7996 0x00b5, /* µ */
Marko Mikulicic 0:c0ecb8bf28eb 7997 0x00ba, /* º */
Marko Mikulicic 0:c0ecb8bf28eb 7998 0x03da, /* Ϛ */
Marko Mikulicic 0:c0ecb8bf28eb 7999 0x03dc, /* Ϝ */
Marko Mikulicic 0:c0ecb8bf28eb 8000 0x03de, /* Ϟ */
Marko Mikulicic 0:c0ecb8bf28eb 8001 0x03e0, /* Ϡ */
Marko Mikulicic 0:c0ecb8bf28eb 8002 0x06d5, /* ە */
Marko Mikulicic 0:c0ecb8bf28eb 8003 0x09b2, /* ল */
Marko Mikulicic 0:c0ecb8bf28eb 8004 0x0a5e, /* ਫ਼ */
Marko Mikulicic 0:c0ecb8bf28eb 8005 0x0a8d, /* ઍ */
Marko Mikulicic 0:c0ecb8bf28eb 8006 0x0ae0, /* ૠ */
Marko Mikulicic 0:c0ecb8bf28eb 8007 0x0b9c, /* ஜ */
Marko Mikulicic 0:c0ecb8bf28eb 8008 0x0cde, /* ೞ */
Marko Mikulicic 0:c0ecb8bf28eb 8009 0x0e4f, /* ๏ */
Marko Mikulicic 0:c0ecb8bf28eb 8010 0x0e84, /* ຄ */
Marko Mikulicic 0:c0ecb8bf28eb 8011 0x0e8a, /* ຊ */
Marko Mikulicic 0:c0ecb8bf28eb 8012 0x0e8d, /* ຍ */
Marko Mikulicic 0:c0ecb8bf28eb 8013 0x0ea5, /* ລ */
Marko Mikulicic 0:c0ecb8bf28eb 8014 0x0ea7, /* ວ */
Marko Mikulicic 0:c0ecb8bf28eb 8015 0x0eb0, /* ະ */
Marko Mikulicic 0:c0ecb8bf28eb 8016 0x0ebd, /* ຽ */
Marko Mikulicic 0:c0ecb8bf28eb 8017 0x1fbe, /* ι */
Marko Mikulicic 0:c0ecb8bf28eb 8018 0x207f, /* ⁿ */
Marko Mikulicic 0:c0ecb8bf28eb 8019 0x20a8, /* ₨ */
Marko Mikulicic 0:c0ecb8bf28eb 8020 0x2102, /* ℂ */
Marko Mikulicic 0:c0ecb8bf28eb 8021 0x2107, /* ℇ */
Marko Mikulicic 0:c0ecb8bf28eb 8022 0x2124, /* ℤ */
Marko Mikulicic 0:c0ecb8bf28eb 8023 0x2126, /* Ω */
Marko Mikulicic 0:c0ecb8bf28eb 8024 0x2128, /* ℨ */
Marko Mikulicic 0:c0ecb8bf28eb 8025 0xfb3e, /* מּ */
Marko Mikulicic 0:c0ecb8bf28eb 8026 0xfe74, /* ﹴ */
Marko Mikulicic 0:c0ecb8bf28eb 8027 };
Marko Mikulicic 0:c0ecb8bf28eb 8028
Marko Mikulicic 0:c0ecb8bf28eb 8029 /*
Marko Mikulicic 0:c0ecb8bf28eb 8030 * space ranges
Marko Mikulicic 0:c0ecb8bf28eb 8031 */
Marko Mikulicic 0:c0ecb8bf28eb 8032 static Rune __space2[] = {
Marko Mikulicic 0:c0ecb8bf28eb 8033 0x0009, 0x000a, /* tab and newline */
Marko Mikulicic 0:c0ecb8bf28eb 8034 0x0020, 0x0020, /* space */
Marko Mikulicic 0:c0ecb8bf28eb 8035 0x00a0, 0x00a0, /*   */
Marko Mikulicic 0:c0ecb8bf28eb 8036 0x2000, 0x200b, /*   - ​ */
Marko Mikulicic 0:c0ecb8bf28eb 8037 0x2028, 0x2029, /* 
 - 
 */
Marko Mikulicic 0:c0ecb8bf28eb 8038 0x3000, 0x3000, /*   */
Marko Mikulicic 0:c0ecb8bf28eb 8039 0xfeff, 0xfeff, /*  */
Marko Mikulicic 0:c0ecb8bf28eb 8040 };
Marko Mikulicic 0:c0ecb8bf28eb 8041
Marko Mikulicic 0:c0ecb8bf28eb 8042 /*
Marko Mikulicic 0:c0ecb8bf28eb 8043 * lower case ranges
Marko Mikulicic 0:c0ecb8bf28eb 8044 * 3rd col is conversion excess 500
Marko Mikulicic 0:c0ecb8bf28eb 8045 */
Marko Mikulicic 0:c0ecb8bf28eb 8046 static Rune __toupper2[] = {
Marko Mikulicic 0:c0ecb8bf28eb 8047 0x0061, 0x007a, 468, /* a-z A-Z */
Marko Mikulicic 0:c0ecb8bf28eb 8048 0x00e0, 0x00f6, 468, /* à-ö À-Ö */
Marko Mikulicic 0:c0ecb8bf28eb 8049 0x00f8, 0x00fe, 468, /* ø-þ Ø-Þ */
Marko Mikulicic 0:c0ecb8bf28eb 8050 0x0256, 0x0257, 295, /* ɖ-ɗ Ɖ-Ɗ */
Marko Mikulicic 0:c0ecb8bf28eb 8051 0x0258, 0x0259, 298, /* ɘ-ə Ǝ-Ə */
Marko Mikulicic 0:c0ecb8bf28eb 8052 0x028a, 0x028b, 283, /* ʊ-ʋ Ʊ-Ʋ */
Marko Mikulicic 0:c0ecb8bf28eb 8053 0x03ad, 0x03af, 463, /* έ-ί Έ-Ί */
Marko Mikulicic 0:c0ecb8bf28eb 8054 0x03b1, 0x03c1, 468, /* α-ρ Α-Ρ */
Marko Mikulicic 0:c0ecb8bf28eb 8055 0x03c3, 0x03cb, 468, /* σ-ϋ Σ-Ϋ */
Marko Mikulicic 0:c0ecb8bf28eb 8056 0x03cd, 0x03ce, 437, /* ύ-ώ Ύ-Ώ */
Marko Mikulicic 0:c0ecb8bf28eb 8057 0x0430, 0x044f, 468, /* а-я А-Я */
Marko Mikulicic 0:c0ecb8bf28eb 8058 0x0451, 0x045c, 420, /* ё-ќ Ё-Ќ */
Marko Mikulicic 0:c0ecb8bf28eb 8059 0x045e, 0x045f, 420, /* ў-џ Ў-Џ */
Marko Mikulicic 0:c0ecb8bf28eb 8060 0x0561, 0x0586, 452, /* ա-ֆ Ա-Ֆ */
Marko Mikulicic 0:c0ecb8bf28eb 8061 0x1f00, 0x1f07, 508, /* ἀ-ἇ Ἀ-Ἇ */
Marko Mikulicic 0:c0ecb8bf28eb 8062 0x1f10, 0x1f15, 508, /* ἐ-ἕ Ἐ-Ἕ */
Marko Mikulicic 0:c0ecb8bf28eb 8063 0x1f20, 0x1f27, 508, /* ἠ-ἧ Ἠ-Ἧ */
Marko Mikulicic 0:c0ecb8bf28eb 8064 0x1f30, 0x1f37, 508, /* ἰ-ἷ Ἰ-Ἷ */
Marko Mikulicic 0:c0ecb8bf28eb 8065 0x1f40, 0x1f45, 508, /* ὀ-ὅ Ὀ-Ὅ */
Marko Mikulicic 0:c0ecb8bf28eb 8066 0x1f60, 0x1f67, 508, /* ὠ-ὧ Ὠ-Ὧ */
Marko Mikulicic 0:c0ecb8bf28eb 8067 0x1f70, 0x1f71, 574, /* ὰ-ά Ὰ-Ά */
Marko Mikulicic 0:c0ecb8bf28eb 8068 0x1f72, 0x1f75, 586, /* ὲ-ή Ὲ-Ή */
Marko Mikulicic 0:c0ecb8bf28eb 8069 0x1f76, 0x1f77, 600, /* ὶ-ί Ὶ-Ί */
Marko Mikulicic 0:c0ecb8bf28eb 8070 0x1f78, 0x1f79, 628, /* ὸ-ό Ὸ-Ό */
Marko Mikulicic 0:c0ecb8bf28eb 8071 0x1f7a, 0x1f7b, 612, /* ὺ-ύ Ὺ-Ύ */
Marko Mikulicic 0:c0ecb8bf28eb 8072 0x1f7c, 0x1f7d, 626, /* ὼ-ώ Ὼ-Ώ */
Marko Mikulicic 0:c0ecb8bf28eb 8073 0x1f80, 0x1f87, 508, /* ᾀ-ᾇ ᾈ-ᾏ */
Marko Mikulicic 0:c0ecb8bf28eb 8074 0x1f90, 0x1f97, 508, /* ᾐ-ᾗ ᾘ-ᾟ */
Marko Mikulicic 0:c0ecb8bf28eb 8075 0x1fa0, 0x1fa7, 508, /* ᾠ-ᾧ ᾨ-ᾯ */
Marko Mikulicic 0:c0ecb8bf28eb 8076 0x1fb0, 0x1fb1, 508, /* ᾰ-ᾱ Ᾰ-Ᾱ */
Marko Mikulicic 0:c0ecb8bf28eb 8077 0x1fd0, 0x1fd1, 508, /* ῐ-ῑ Ῐ-Ῑ */
Marko Mikulicic 0:c0ecb8bf28eb 8078 0x1fe0, 0x1fe1, 508, /* ῠ-ῡ Ῠ-Ῡ */
Marko Mikulicic 0:c0ecb8bf28eb 8079 0x2170, 0x217f, 484, /* ⅰ-ⅿ Ⅰ-Ⅿ */
Marko Mikulicic 0:c0ecb8bf28eb 8080 0x24d0, 0x24e9, 474, /* ⓐ-ⓩ Ⓐ-Ⓩ */
Marko Mikulicic 0:c0ecb8bf28eb 8081 0xff41, 0xff5a, 468, /* a-z A-Z */
Marko Mikulicic 0:c0ecb8bf28eb 8082 };
Marko Mikulicic 0:c0ecb8bf28eb 8083
Marko Mikulicic 0:c0ecb8bf28eb 8084 /*
Marko Mikulicic 0:c0ecb8bf28eb 8085 * lower case singlets
Marko Mikulicic 0:c0ecb8bf28eb 8086 * 2nd col is conversion excess 500
Marko Mikulicic 0:c0ecb8bf28eb 8087 */
Marko Mikulicic 0:c0ecb8bf28eb 8088 static Rune __toupper1[] = {
Marko Mikulicic 0:c0ecb8bf28eb 8089 0x00ff, 621, /* ÿ Ÿ */
Marko Mikulicic 0:c0ecb8bf28eb 8090 0x0101, 499, /* ā Ā */
Marko Mikulicic 0:c0ecb8bf28eb 8091 0x0103, 499, /* ă Ă */
Marko Mikulicic 0:c0ecb8bf28eb 8092 0x0105, 499, /* ą Ą */
Marko Mikulicic 0:c0ecb8bf28eb 8093 0x0107, 499, /* ć Ć */
Marko Mikulicic 0:c0ecb8bf28eb 8094 0x0109, 499, /* ĉ Ĉ */
Marko Mikulicic 0:c0ecb8bf28eb 8095 0x010b, 499, /* ċ Ċ */
Marko Mikulicic 0:c0ecb8bf28eb 8096 0x010d, 499, /* č Č */
Marko Mikulicic 0:c0ecb8bf28eb 8097 0x010f, 499, /* ď Ď */
Marko Mikulicic 0:c0ecb8bf28eb 8098 0x0111, 499, /* đ Đ */
Marko Mikulicic 0:c0ecb8bf28eb 8099 0x0113, 499, /* ē Ē */
Marko Mikulicic 0:c0ecb8bf28eb 8100 0x0115, 499, /* ĕ Ĕ */
Marko Mikulicic 0:c0ecb8bf28eb 8101 0x0117, 499, /* ė Ė */
Marko Mikulicic 0:c0ecb8bf28eb 8102 0x0119, 499, /* ę Ę */
Marko Mikulicic 0:c0ecb8bf28eb 8103 0x011b, 499, /* ě Ě */
Marko Mikulicic 0:c0ecb8bf28eb 8104 0x011d, 499, /* ĝ Ĝ */
Marko Mikulicic 0:c0ecb8bf28eb 8105 0x011f, 499, /* ğ Ğ */
Marko Mikulicic 0:c0ecb8bf28eb 8106 0x0121, 499, /* ġ Ġ */
Marko Mikulicic 0:c0ecb8bf28eb 8107 0x0123, 499, /* ģ Ģ */
Marko Mikulicic 0:c0ecb8bf28eb 8108 0x0125, 499, /* ĥ Ĥ */
Marko Mikulicic 0:c0ecb8bf28eb 8109 0x0127, 499, /* ħ Ħ */
Marko Mikulicic 0:c0ecb8bf28eb 8110 0x0129, 499, /* ĩ Ĩ */
Marko Mikulicic 0:c0ecb8bf28eb 8111 0x012b, 499, /* ī Ī */
Marko Mikulicic 0:c0ecb8bf28eb 8112 0x012d, 499, /* ĭ Ĭ */
Marko Mikulicic 0:c0ecb8bf28eb 8113 0x012f, 499, /* į Į */
Marko Mikulicic 0:c0ecb8bf28eb 8114 0x0131, 268, /* ı I */
Marko Mikulicic 0:c0ecb8bf28eb 8115 0x0133, 499, /* ij IJ */
Marko Mikulicic 0:c0ecb8bf28eb 8116 0x0135, 499, /* ĵ Ĵ */
Marko Mikulicic 0:c0ecb8bf28eb 8117 0x0137, 499, /* ķ Ķ */
Marko Mikulicic 0:c0ecb8bf28eb 8118 0x013a, 499, /* ĺ Ĺ */
Marko Mikulicic 0:c0ecb8bf28eb 8119 0x013c, 499, /* ļ Ļ */
Marko Mikulicic 0:c0ecb8bf28eb 8120 0x013e, 499, /* ľ Ľ */
Marko Mikulicic 0:c0ecb8bf28eb 8121 0x0140, 499, /* ŀ Ŀ */
Marko Mikulicic 0:c0ecb8bf28eb 8122 0x0142, 499, /* ł Ł */
Marko Mikulicic 0:c0ecb8bf28eb 8123 0x0144, 499, /* ń Ń */
Marko Mikulicic 0:c0ecb8bf28eb 8124 0x0146, 499, /* ņ Ņ */
Marko Mikulicic 0:c0ecb8bf28eb 8125 0x0148, 499, /* ň Ň */
Marko Mikulicic 0:c0ecb8bf28eb 8126 0x014b, 499, /* ŋ Ŋ */
Marko Mikulicic 0:c0ecb8bf28eb 8127 0x014d, 499, /* ō Ō */
Marko Mikulicic 0:c0ecb8bf28eb 8128 0x014f, 499, /* ŏ Ŏ */
Marko Mikulicic 0:c0ecb8bf28eb 8129 0x0151, 499, /* ő Ő */
Marko Mikulicic 0:c0ecb8bf28eb 8130 0x0153, 499, /* œ Œ */
Marko Mikulicic 0:c0ecb8bf28eb 8131 0x0155, 499, /* ŕ Ŕ */
Marko Mikulicic 0:c0ecb8bf28eb 8132 0x0157, 499, /* ŗ Ŗ */
Marko Mikulicic 0:c0ecb8bf28eb 8133 0x0159, 499, /* ř Ř */
Marko Mikulicic 0:c0ecb8bf28eb 8134 0x015b, 499, /* ś Ś */
Marko Mikulicic 0:c0ecb8bf28eb 8135 0x015d, 499, /* ŝ Ŝ */
Marko Mikulicic 0:c0ecb8bf28eb 8136 0x015f, 499, /* ş Ş */
Marko Mikulicic 0:c0ecb8bf28eb 8137 0x0161, 499, /* š Š */
Marko Mikulicic 0:c0ecb8bf28eb 8138 0x0163, 499, /* ţ Ţ */
Marko Mikulicic 0:c0ecb8bf28eb 8139 0x0165, 499, /* ť Ť */
Marko Mikulicic 0:c0ecb8bf28eb 8140 0x0167, 499, /* ŧ Ŧ */
Marko Mikulicic 0:c0ecb8bf28eb 8141 0x0169, 499, /* ũ Ũ */
Marko Mikulicic 0:c0ecb8bf28eb 8142 0x016b, 499, /* ū Ū */
Marko Mikulicic 0:c0ecb8bf28eb 8143 0x016d, 499, /* ŭ Ŭ */
Marko Mikulicic 0:c0ecb8bf28eb 8144 0x016f, 499, /* ů Ů */
Marko Mikulicic 0:c0ecb8bf28eb 8145 0x0171, 499, /* ű Ű */
Marko Mikulicic 0:c0ecb8bf28eb 8146 0x0173, 499, /* ų Ų */
Marko Mikulicic 0:c0ecb8bf28eb 8147 0x0175, 499, /* ŵ Ŵ */
Marko Mikulicic 0:c0ecb8bf28eb 8148 0x0177, 499, /* ŷ Ŷ */
Marko Mikulicic 0:c0ecb8bf28eb 8149 0x017a, 499, /* ź Ź */
Marko Mikulicic 0:c0ecb8bf28eb 8150 0x017c, 499, /* ż Ż */
Marko Mikulicic 0:c0ecb8bf28eb 8151 0x017e, 499, /* ž Ž */
Marko Mikulicic 0:c0ecb8bf28eb 8152 0x017f, 200, /* ſ S */
Marko Mikulicic 0:c0ecb8bf28eb 8153 0x0183, 499, /* ƃ Ƃ */
Marko Mikulicic 0:c0ecb8bf28eb 8154 0x0185, 499, /* ƅ Ƅ */
Marko Mikulicic 0:c0ecb8bf28eb 8155 0x0188, 499, /* ƈ Ƈ */
Marko Mikulicic 0:c0ecb8bf28eb 8156 0x018c, 499, /* ƌ Ƌ */
Marko Mikulicic 0:c0ecb8bf28eb 8157 0x0192, 499, /* ƒ Ƒ */
Marko Mikulicic 0:c0ecb8bf28eb 8158 0x0199, 499, /* ƙ Ƙ */
Marko Mikulicic 0:c0ecb8bf28eb 8159 0x01a1, 499, /* ơ Ơ */
Marko Mikulicic 0:c0ecb8bf28eb 8160 0x01a3, 499, /* ƣ Ƣ */
Marko Mikulicic 0:c0ecb8bf28eb 8161 0x01a5, 499, /* ƥ Ƥ */
Marko Mikulicic 0:c0ecb8bf28eb 8162 0x01a8, 499, /* ƨ Ƨ */
Marko Mikulicic 0:c0ecb8bf28eb 8163 0x01ad, 499, /* ƭ Ƭ */
Marko Mikulicic 0:c0ecb8bf28eb 8164 0x01b0, 499, /* ư Ư */
Marko Mikulicic 0:c0ecb8bf28eb 8165 0x01b4, 499, /* ƴ Ƴ */
Marko Mikulicic 0:c0ecb8bf28eb 8166 0x01b6, 499, /* ƶ Ƶ */
Marko Mikulicic 0:c0ecb8bf28eb 8167 0x01b9, 499, /* ƹ Ƹ */
Marko Mikulicic 0:c0ecb8bf28eb 8168 0x01bd, 499, /* ƽ Ƽ */
Marko Mikulicic 0:c0ecb8bf28eb 8169 0x01c5, 499, /* Dž DŽ */
Marko Mikulicic 0:c0ecb8bf28eb 8170 0x01c6, 498, /* dž DŽ */
Marko Mikulicic 0:c0ecb8bf28eb 8171 0x01c8, 499, /* Lj LJ */
Marko Mikulicic 0:c0ecb8bf28eb 8172 0x01c9, 498, /* lj LJ */
Marko Mikulicic 0:c0ecb8bf28eb 8173 0x01cb, 499, /* Nj NJ */
Marko Mikulicic 0:c0ecb8bf28eb 8174 0x01cc, 498, /* nj NJ */
Marko Mikulicic 0:c0ecb8bf28eb 8175 0x01ce, 499, /* ǎ Ǎ */
Marko Mikulicic 0:c0ecb8bf28eb 8176 0x01d0, 499, /* ǐ Ǐ */
Marko Mikulicic 0:c0ecb8bf28eb 8177 0x01d2, 499, /* ǒ Ǒ */
Marko Mikulicic 0:c0ecb8bf28eb 8178 0x01d4, 499, /* ǔ Ǔ */
Marko Mikulicic 0:c0ecb8bf28eb 8179 0x01d6, 499, /* ǖ Ǖ */
Marko Mikulicic 0:c0ecb8bf28eb 8180 0x01d8, 499, /* ǘ Ǘ */
Marko Mikulicic 0:c0ecb8bf28eb 8181 0x01da, 499, /* ǚ Ǚ */
Marko Mikulicic 0:c0ecb8bf28eb 8182 0x01dc, 499, /* ǜ Ǜ */
Marko Mikulicic 0:c0ecb8bf28eb 8183 0x01df, 499, /* ǟ Ǟ */
Marko Mikulicic 0:c0ecb8bf28eb 8184 0x01e1, 499, /* ǡ Ǡ */
Marko Mikulicic 0:c0ecb8bf28eb 8185 0x01e3, 499, /* ǣ Ǣ */
Marko Mikulicic 0:c0ecb8bf28eb 8186 0x01e5, 499, /* ǥ Ǥ */
Marko Mikulicic 0:c0ecb8bf28eb 8187 0x01e7, 499, /* ǧ Ǧ */
Marko Mikulicic 0:c0ecb8bf28eb 8188 0x01e9, 499, /* ǩ Ǩ */
Marko Mikulicic 0:c0ecb8bf28eb 8189 0x01eb, 499, /* ǫ Ǫ */
Marko Mikulicic 0:c0ecb8bf28eb 8190 0x01ed, 499, /* ǭ Ǭ */
Marko Mikulicic 0:c0ecb8bf28eb 8191 0x01ef, 499, /* ǯ Ǯ */
Marko Mikulicic 0:c0ecb8bf28eb 8192 0x01f2, 499, /* Dz DZ */
Marko Mikulicic 0:c0ecb8bf28eb 8193 0x01f3, 498, /* dz DZ */
Marko Mikulicic 0:c0ecb8bf28eb 8194 0x01f5, 499, /* ǵ Ǵ */
Marko Mikulicic 0:c0ecb8bf28eb 8195 0x01fb, 499, /* ǻ Ǻ */
Marko Mikulicic 0:c0ecb8bf28eb 8196 0x01fd, 499, /* ǽ Ǽ */
Marko Mikulicic 0:c0ecb8bf28eb 8197 0x01ff, 499, /* ǿ Ǿ */
Marko Mikulicic 0:c0ecb8bf28eb 8198 0x0201, 499, /* ȁ Ȁ */
Marko Mikulicic 0:c0ecb8bf28eb 8199 0x0203, 499, /* ȃ Ȃ */
Marko Mikulicic 0:c0ecb8bf28eb 8200 0x0205, 499, /* ȅ Ȅ */
Marko Mikulicic 0:c0ecb8bf28eb 8201 0x0207, 499, /* ȇ Ȇ */
Marko Mikulicic 0:c0ecb8bf28eb 8202 0x0209, 499, /* ȉ Ȉ */
Marko Mikulicic 0:c0ecb8bf28eb 8203 0x020b, 499, /* ȋ Ȋ */
Marko Mikulicic 0:c0ecb8bf28eb 8204 0x020d, 499, /* ȍ Ȍ */
Marko Mikulicic 0:c0ecb8bf28eb 8205 0x020f, 499, /* ȏ Ȏ */
Marko Mikulicic 0:c0ecb8bf28eb 8206 0x0211, 499, /* ȑ Ȑ */
Marko Mikulicic 0:c0ecb8bf28eb 8207 0x0213, 499, /* ȓ Ȓ */
Marko Mikulicic 0:c0ecb8bf28eb 8208 0x0215, 499, /* ȕ Ȕ */
Marko Mikulicic 0:c0ecb8bf28eb 8209 0x0217, 499, /* ȗ Ȗ */
Marko Mikulicic 0:c0ecb8bf28eb 8210 0x0253, 290, /* ɓ Ɓ */
Marko Mikulicic 0:c0ecb8bf28eb 8211 0x0254, 294, /* ɔ Ɔ */
Marko Mikulicic 0:c0ecb8bf28eb 8212 0x025b, 297, /* ɛ Ɛ */
Marko Mikulicic 0:c0ecb8bf28eb 8213 0x0260, 295, /* ɠ Ɠ */
Marko Mikulicic 0:c0ecb8bf28eb 8214 0x0263, 293, /* ɣ Ɣ */
Marko Mikulicic 0:c0ecb8bf28eb 8215 0x0268, 291, /* ɨ Ɨ */
Marko Mikulicic 0:c0ecb8bf28eb 8216 0x0269, 289, /* ɩ Ɩ */
Marko Mikulicic 0:c0ecb8bf28eb 8217 0x026f, 289, /* ɯ Ɯ */
Marko Mikulicic 0:c0ecb8bf28eb 8218 0x0272, 287, /* ɲ Ɲ */
Marko Mikulicic 0:c0ecb8bf28eb 8219 0x0283, 282, /* ʃ Ʃ */
Marko Mikulicic 0:c0ecb8bf28eb 8220 0x0288, 282, /* ʈ Ʈ */
Marko Mikulicic 0:c0ecb8bf28eb 8221 0x0292, 281, /* ʒ Ʒ */
Marko Mikulicic 0:c0ecb8bf28eb 8222 0x03ac, 462, /* ά Ά */
Marko Mikulicic 0:c0ecb8bf28eb 8223 0x03cc, 436, /* ό Ό */
Marko Mikulicic 0:c0ecb8bf28eb 8224 0x03d0, 438, /* ϐ Β */
Marko Mikulicic 0:c0ecb8bf28eb 8225 0x03d1, 443, /* ϑ Θ */
Marko Mikulicic 0:c0ecb8bf28eb 8226 0x03d5, 453, /* ϕ Φ */
Marko Mikulicic 0:c0ecb8bf28eb 8227 0x03d6, 446, /* ϖ Π */
Marko Mikulicic 0:c0ecb8bf28eb 8228 0x03e3, 499, /* ϣ Ϣ */
Marko Mikulicic 0:c0ecb8bf28eb 8229 0x03e5, 499, /* ϥ Ϥ */
Marko Mikulicic 0:c0ecb8bf28eb 8230 0x03e7, 499, /* ϧ Ϧ */
Marko Mikulicic 0:c0ecb8bf28eb 8231 0x03e9, 499, /* ϩ Ϩ */
Marko Mikulicic 0:c0ecb8bf28eb 8232 0x03eb, 499, /* ϫ Ϫ */
Marko Mikulicic 0:c0ecb8bf28eb 8233 0x03ed, 499, /* ϭ Ϭ */
Marko Mikulicic 0:c0ecb8bf28eb 8234 0x03ef, 499, /* ϯ Ϯ */
Marko Mikulicic 0:c0ecb8bf28eb 8235 0x03f0, 414, /* ϰ Κ */
Marko Mikulicic 0:c0ecb8bf28eb 8236 0x03f1, 420, /* ϱ Ρ */
Marko Mikulicic 0:c0ecb8bf28eb 8237 0x0461, 499, /* ѡ Ѡ */
Marko Mikulicic 0:c0ecb8bf28eb 8238 0x0463, 499, /* ѣ Ѣ */
Marko Mikulicic 0:c0ecb8bf28eb 8239 0x0465, 499, /* ѥ Ѥ */
Marko Mikulicic 0:c0ecb8bf28eb 8240 0x0467, 499, /* ѧ Ѧ */
Marko Mikulicic 0:c0ecb8bf28eb 8241 0x0469, 499, /* ѩ Ѩ */
Marko Mikulicic 0:c0ecb8bf28eb 8242 0x046b, 499, /* ѫ Ѫ */
Marko Mikulicic 0:c0ecb8bf28eb 8243 0x046d, 499, /* ѭ Ѭ */
Marko Mikulicic 0:c0ecb8bf28eb 8244 0x046f, 499, /* ѯ Ѯ */
Marko Mikulicic 0:c0ecb8bf28eb 8245 0x0471, 499, /* ѱ Ѱ */
Marko Mikulicic 0:c0ecb8bf28eb 8246 0x0473, 499, /* ѳ Ѳ */
Marko Mikulicic 0:c0ecb8bf28eb 8247 0x0475, 499, /* ѵ Ѵ */
Marko Mikulicic 0:c0ecb8bf28eb 8248 0x0477, 499, /* ѷ Ѷ */
Marko Mikulicic 0:c0ecb8bf28eb 8249 0x0479, 499, /* ѹ Ѹ */
Marko Mikulicic 0:c0ecb8bf28eb 8250 0x047b, 499, /* ѻ Ѻ */
Marko Mikulicic 0:c0ecb8bf28eb 8251 0x047d, 499, /* ѽ Ѽ */
Marko Mikulicic 0:c0ecb8bf28eb 8252 0x047f, 499, /* ѿ Ѿ */
Marko Mikulicic 0:c0ecb8bf28eb 8253 0x0481, 499, /* ҁ Ҁ */
Marko Mikulicic 0:c0ecb8bf28eb 8254 0x0491, 499, /* ґ Ґ */
Marko Mikulicic 0:c0ecb8bf28eb 8255 0x0493, 499, /* ғ Ғ */
Marko Mikulicic 0:c0ecb8bf28eb 8256 0x0495, 499, /* ҕ Ҕ */
Marko Mikulicic 0:c0ecb8bf28eb 8257 0x0497, 499, /* җ Җ */
Marko Mikulicic 0:c0ecb8bf28eb 8258 0x0499, 499, /* ҙ Ҙ */
Marko Mikulicic 0:c0ecb8bf28eb 8259 0x049b, 499, /* қ Қ */
Marko Mikulicic 0:c0ecb8bf28eb 8260 0x049d, 499, /* ҝ Ҝ */
Marko Mikulicic 0:c0ecb8bf28eb 8261 0x049f, 499, /* ҟ Ҟ */
Marko Mikulicic 0:c0ecb8bf28eb 8262 0x04a1, 499, /* ҡ Ҡ */
Marko Mikulicic 0:c0ecb8bf28eb 8263 0x04a3, 499, /* ң Ң */
Marko Mikulicic 0:c0ecb8bf28eb 8264 0x04a5, 499, /* ҥ Ҥ */
Marko Mikulicic 0:c0ecb8bf28eb 8265 0x04a7, 499, /* ҧ Ҧ */
Marko Mikulicic 0:c0ecb8bf28eb 8266 0x04a9, 499, /* ҩ Ҩ */
Marko Mikulicic 0:c0ecb8bf28eb 8267 0x04ab, 499, /* ҫ Ҫ */
Marko Mikulicic 0:c0ecb8bf28eb 8268 0x04ad, 499, /* ҭ Ҭ */
Marko Mikulicic 0:c0ecb8bf28eb 8269 0x04af, 499, /* ү Ү */
Marko Mikulicic 0:c0ecb8bf28eb 8270 0x04b1, 499, /* ұ Ұ */
Marko Mikulicic 0:c0ecb8bf28eb 8271 0x04b3, 499, /* ҳ Ҳ */
Marko Mikulicic 0:c0ecb8bf28eb 8272 0x04b5, 499, /* ҵ Ҵ */
Marko Mikulicic 0:c0ecb8bf28eb 8273 0x04b7, 499, /* ҷ Ҷ */
Marko Mikulicic 0:c0ecb8bf28eb 8274 0x04b9, 499, /* ҹ Ҹ */
Marko Mikulicic 0:c0ecb8bf28eb 8275 0x04bb, 499, /* һ Һ */
Marko Mikulicic 0:c0ecb8bf28eb 8276 0x04bd, 499, /* ҽ Ҽ */
Marko Mikulicic 0:c0ecb8bf28eb 8277 0x04bf, 499, /* ҿ Ҿ */
Marko Mikulicic 0:c0ecb8bf28eb 8278 0x04c2, 499, /* ӂ Ӂ */
Marko Mikulicic 0:c0ecb8bf28eb 8279 0x04c4, 499, /* ӄ Ӄ */
Marko Mikulicic 0:c0ecb8bf28eb 8280 0x04c8, 499, /* ӈ Ӈ */
Marko Mikulicic 0:c0ecb8bf28eb 8281 0x04cc, 499, /* ӌ Ӌ */
Marko Mikulicic 0:c0ecb8bf28eb 8282 0x04d1, 499, /* ӑ Ӑ */
Marko Mikulicic 0:c0ecb8bf28eb 8283 0x04d3, 499, /* ӓ Ӓ */
Marko Mikulicic 0:c0ecb8bf28eb 8284 0x04d5, 499, /* ӕ Ӕ */
Marko Mikulicic 0:c0ecb8bf28eb 8285 0x04d7, 499, /* ӗ Ӗ */
Marko Mikulicic 0:c0ecb8bf28eb 8286 0x04d9, 499, /* ә Ә */
Marko Mikulicic 0:c0ecb8bf28eb 8287 0x04db, 499, /* ӛ Ӛ */
Marko Mikulicic 0:c0ecb8bf28eb 8288 0x04dd, 499, /* ӝ Ӝ */
Marko Mikulicic 0:c0ecb8bf28eb 8289 0x04df, 499, /* ӟ Ӟ */
Marko Mikulicic 0:c0ecb8bf28eb 8290 0x04e1, 499, /* ӡ Ӡ */
Marko Mikulicic 0:c0ecb8bf28eb 8291 0x04e3, 499, /* ӣ Ӣ */
Marko Mikulicic 0:c0ecb8bf28eb 8292 0x04e5, 499, /* ӥ Ӥ */
Marko Mikulicic 0:c0ecb8bf28eb 8293 0x04e7, 499, /* ӧ Ӧ */
Marko Mikulicic 0:c0ecb8bf28eb 8294 0x04e9, 499, /* ө Ө */
Marko Mikulicic 0:c0ecb8bf28eb 8295 0x04eb, 499, /* ӫ Ӫ */
Marko Mikulicic 0:c0ecb8bf28eb 8296 0x04ef, 499, /* ӯ Ӯ */
Marko Mikulicic 0:c0ecb8bf28eb 8297 0x04f1, 499, /* ӱ Ӱ */
Marko Mikulicic 0:c0ecb8bf28eb 8298 0x04f3, 499, /* ӳ Ӳ */
Marko Mikulicic 0:c0ecb8bf28eb 8299 0x04f5, 499, /* ӵ Ӵ */
Marko Mikulicic 0:c0ecb8bf28eb 8300 0x04f9, 499, /* ӹ Ӹ */
Marko Mikulicic 0:c0ecb8bf28eb 8301 0x1e01, 499, /* ḁ Ḁ */
Marko Mikulicic 0:c0ecb8bf28eb 8302 0x1e03, 499, /* ḃ Ḃ */
Marko Mikulicic 0:c0ecb8bf28eb 8303 0x1e05, 499, /* ḅ Ḅ */
Marko Mikulicic 0:c0ecb8bf28eb 8304 0x1e07, 499, /* ḇ Ḇ */
Marko Mikulicic 0:c0ecb8bf28eb 8305 0x1e09, 499, /* ḉ Ḉ */
Marko Mikulicic 0:c0ecb8bf28eb 8306 0x1e0b, 499, /* ḋ Ḋ */
Marko Mikulicic 0:c0ecb8bf28eb 8307 0x1e0d, 499, /* ḍ Ḍ */
Marko Mikulicic 0:c0ecb8bf28eb 8308 0x1e0f, 499, /* ḏ Ḏ */
Marko Mikulicic 0:c0ecb8bf28eb 8309 0x1e11, 499, /* ḑ Ḑ */
Marko Mikulicic 0:c0ecb8bf28eb 8310 0x1e13, 499, /* ḓ Ḓ */
Marko Mikulicic 0:c0ecb8bf28eb 8311 0x1e15, 499, /* ḕ Ḕ */
Marko Mikulicic 0:c0ecb8bf28eb 8312 0x1e17, 499, /* ḗ Ḗ */
Marko Mikulicic 0:c0ecb8bf28eb 8313 0x1e19, 499, /* ḙ Ḙ */
Marko Mikulicic 0:c0ecb8bf28eb 8314 0x1e1b, 499, /* ḛ Ḛ */
Marko Mikulicic 0:c0ecb8bf28eb 8315 0x1e1d, 499, /* ḝ Ḝ */
Marko Mikulicic 0:c0ecb8bf28eb 8316 0x1e1f, 499, /* ḟ Ḟ */
Marko Mikulicic 0:c0ecb8bf28eb 8317 0x1e21, 499, /* ḡ Ḡ */
Marko Mikulicic 0:c0ecb8bf28eb 8318 0x1e23, 499, /* ḣ Ḣ */
Marko Mikulicic 0:c0ecb8bf28eb 8319 0x1e25, 499, /* ḥ Ḥ */
Marko Mikulicic 0:c0ecb8bf28eb 8320 0x1e27, 499, /* ḧ Ḧ */
Marko Mikulicic 0:c0ecb8bf28eb 8321 0x1e29, 499, /* ḩ Ḩ */
Marko Mikulicic 0:c0ecb8bf28eb 8322 0x1e2b, 499, /* ḫ Ḫ */
Marko Mikulicic 0:c0ecb8bf28eb 8323 0x1e2d, 499, /* ḭ Ḭ */
Marko Mikulicic 0:c0ecb8bf28eb 8324 0x1e2f, 499, /* ḯ Ḯ */
Marko Mikulicic 0:c0ecb8bf28eb 8325 0x1e31, 499, /* ḱ Ḱ */
Marko Mikulicic 0:c0ecb8bf28eb 8326 0x1e33, 499, /* ḳ Ḳ */
Marko Mikulicic 0:c0ecb8bf28eb 8327 0x1e35, 499, /* ḵ Ḵ */
Marko Mikulicic 0:c0ecb8bf28eb 8328 0x1e37, 499, /* ḷ Ḷ */
Marko Mikulicic 0:c0ecb8bf28eb 8329 0x1e39, 499, /* ḹ Ḹ */
Marko Mikulicic 0:c0ecb8bf28eb 8330 0x1e3b, 499, /* ḻ Ḻ */
Marko Mikulicic 0:c0ecb8bf28eb 8331 0x1e3d, 499, /* ḽ Ḽ */
Marko Mikulicic 0:c0ecb8bf28eb 8332 0x1e3f, 499, /* ḿ Ḿ */
Marko Mikulicic 0:c0ecb8bf28eb 8333 0x1e41, 499, /* ṁ Ṁ */
Marko Mikulicic 0:c0ecb8bf28eb 8334 0x1e43, 499, /* ṃ Ṃ */
Marko Mikulicic 0:c0ecb8bf28eb 8335 0x1e45, 499, /* ṅ Ṅ */
Marko Mikulicic 0:c0ecb8bf28eb 8336 0x1e47, 499, /* ṇ Ṇ */
Marko Mikulicic 0:c0ecb8bf28eb 8337 0x1e49, 499, /* ṉ Ṉ */
Marko Mikulicic 0:c0ecb8bf28eb 8338 0x1e4b, 499, /* ṋ Ṋ */
Marko Mikulicic 0:c0ecb8bf28eb 8339 0x1e4d, 499, /* ṍ Ṍ */
Marko Mikulicic 0:c0ecb8bf28eb 8340 0x1e4f, 499, /* ṏ Ṏ */
Marko Mikulicic 0:c0ecb8bf28eb 8341 0x1e51, 499, /* ṑ Ṑ */
Marko Mikulicic 0:c0ecb8bf28eb 8342 0x1e53, 499, /* ṓ Ṓ */
Marko Mikulicic 0:c0ecb8bf28eb 8343 0x1e55, 499, /* ṕ Ṕ */
Marko Mikulicic 0:c0ecb8bf28eb 8344 0x1e57, 499, /* ṗ Ṗ */
Marko Mikulicic 0:c0ecb8bf28eb 8345 0x1e59, 499, /* ṙ Ṙ */
Marko Mikulicic 0:c0ecb8bf28eb 8346 0x1e5b, 499, /* ṛ Ṛ */
Marko Mikulicic 0:c0ecb8bf28eb 8347 0x1e5d, 499, /* ṝ Ṝ */
Marko Mikulicic 0:c0ecb8bf28eb 8348 0x1e5f, 499, /* ṟ Ṟ */
Marko Mikulicic 0:c0ecb8bf28eb 8349 0x1e61, 499, /* ṡ Ṡ */
Marko Mikulicic 0:c0ecb8bf28eb 8350 0x1e63, 499, /* ṣ Ṣ */
Marko Mikulicic 0:c0ecb8bf28eb 8351 0x1e65, 499, /* ṥ Ṥ */
Marko Mikulicic 0:c0ecb8bf28eb 8352 0x1e67, 499, /* ṧ Ṧ */
Marko Mikulicic 0:c0ecb8bf28eb 8353 0x1e69, 499, /* ṩ Ṩ */
Marko Mikulicic 0:c0ecb8bf28eb 8354 0x1e6b, 499, /* ṫ Ṫ */
Marko Mikulicic 0:c0ecb8bf28eb 8355 0x1e6d, 499, /* ṭ Ṭ */
Marko Mikulicic 0:c0ecb8bf28eb 8356 0x1e6f, 499, /* ṯ Ṯ */
Marko Mikulicic 0:c0ecb8bf28eb 8357 0x1e71, 499, /* ṱ Ṱ */
Marko Mikulicic 0:c0ecb8bf28eb 8358 0x1e73, 499, /* ṳ Ṳ */
Marko Mikulicic 0:c0ecb8bf28eb 8359 0x1e75, 499, /* ṵ Ṵ */
Marko Mikulicic 0:c0ecb8bf28eb 8360 0x1e77, 499, /* ṷ Ṷ */
Marko Mikulicic 0:c0ecb8bf28eb 8361 0x1e79, 499, /* ṹ Ṹ */
Marko Mikulicic 0:c0ecb8bf28eb 8362 0x1e7b, 499, /* ṻ Ṻ */
Marko Mikulicic 0:c0ecb8bf28eb 8363 0x1e7d, 499, /* ṽ Ṽ */
Marko Mikulicic 0:c0ecb8bf28eb 8364 0x1e7f, 499, /* ṿ Ṿ */
Marko Mikulicic 0:c0ecb8bf28eb 8365 0x1e81, 499, /* ẁ Ẁ */
Marko Mikulicic 0:c0ecb8bf28eb 8366 0x1e83, 499, /* ẃ Ẃ */
Marko Mikulicic 0:c0ecb8bf28eb 8367 0x1e85, 499, /* ẅ Ẅ */
Marko Mikulicic 0:c0ecb8bf28eb 8368 0x1e87, 499, /* ẇ Ẇ */
Marko Mikulicic 0:c0ecb8bf28eb 8369 0x1e89, 499, /* ẉ Ẉ */
Marko Mikulicic 0:c0ecb8bf28eb 8370 0x1e8b, 499, /* ẋ Ẋ */
Marko Mikulicic 0:c0ecb8bf28eb 8371 0x1e8d, 499, /* ẍ Ẍ */
Marko Mikulicic 0:c0ecb8bf28eb 8372 0x1e8f, 499, /* ẏ Ẏ */
Marko Mikulicic 0:c0ecb8bf28eb 8373 0x1e91, 499, /* ẑ Ẑ */
Marko Mikulicic 0:c0ecb8bf28eb 8374 0x1e93, 499, /* ẓ Ẓ */
Marko Mikulicic 0:c0ecb8bf28eb 8375 0x1e95, 499, /* ẕ Ẕ */
Marko Mikulicic 0:c0ecb8bf28eb 8376 0x1ea1, 499, /* ạ Ạ */
Marko Mikulicic 0:c0ecb8bf28eb 8377 0x1ea3, 499, /* ả Ả */
Marko Mikulicic 0:c0ecb8bf28eb 8378 0x1ea5, 499, /* ấ Ấ */
Marko Mikulicic 0:c0ecb8bf28eb 8379 0x1ea7, 499, /* ầ Ầ */
Marko Mikulicic 0:c0ecb8bf28eb 8380 0x1ea9, 499, /* ẩ Ẩ */
Marko Mikulicic 0:c0ecb8bf28eb 8381 0x1eab, 499, /* ẫ Ẫ */
Marko Mikulicic 0:c0ecb8bf28eb 8382 0x1ead, 499, /* ậ Ậ */
Marko Mikulicic 0:c0ecb8bf28eb 8383 0x1eaf, 499, /* ắ Ắ */
Marko Mikulicic 0:c0ecb8bf28eb 8384 0x1eb1, 499, /* ằ Ằ */
Marko Mikulicic 0:c0ecb8bf28eb 8385 0x1eb3, 499, /* ẳ Ẳ */
Marko Mikulicic 0:c0ecb8bf28eb 8386 0x1eb5, 499, /* ẵ Ẵ */
Marko Mikulicic 0:c0ecb8bf28eb 8387 0x1eb7, 499, /* ặ Ặ */
Marko Mikulicic 0:c0ecb8bf28eb 8388 0x1eb9, 499, /* ẹ Ẹ */
Marko Mikulicic 0:c0ecb8bf28eb 8389 0x1ebb, 499, /* ẻ Ẻ */
Marko Mikulicic 0:c0ecb8bf28eb 8390 0x1ebd, 499, /* ẽ Ẽ */
Marko Mikulicic 0:c0ecb8bf28eb 8391 0x1ebf, 499, /* ế Ế */
Marko Mikulicic 0:c0ecb8bf28eb 8392 0x1ec1, 499, /* ề Ề */
Marko Mikulicic 0:c0ecb8bf28eb 8393 0x1ec3, 499, /* ể Ể */
Marko Mikulicic 0:c0ecb8bf28eb 8394 0x1ec5, 499, /* ễ Ễ */
Marko Mikulicic 0:c0ecb8bf28eb 8395 0x1ec7, 499, /* ệ Ệ */
Marko Mikulicic 0:c0ecb8bf28eb 8396 0x1ec9, 499, /* ỉ Ỉ */
Marko Mikulicic 0:c0ecb8bf28eb 8397 0x1ecb, 499, /* ị Ị */
Marko Mikulicic 0:c0ecb8bf28eb 8398 0x1ecd, 499, /* ọ Ọ */
Marko Mikulicic 0:c0ecb8bf28eb 8399 0x1ecf, 499, /* ỏ Ỏ */
Marko Mikulicic 0:c0ecb8bf28eb 8400 0x1ed1, 499, /* ố Ố */
Marko Mikulicic 0:c0ecb8bf28eb 8401 0x1ed3, 499, /* ồ Ồ */
Marko Mikulicic 0:c0ecb8bf28eb 8402 0x1ed5, 499, /* ổ Ổ */
Marko Mikulicic 0:c0ecb8bf28eb 8403 0x1ed7, 499, /* ỗ Ỗ */
Marko Mikulicic 0:c0ecb8bf28eb 8404 0x1ed9, 499, /* ộ Ộ */
Marko Mikulicic 0:c0ecb8bf28eb 8405 0x1edb, 499, /* ớ Ớ */
Marko Mikulicic 0:c0ecb8bf28eb 8406 0x1edd, 499, /* ờ Ờ */
Marko Mikulicic 0:c0ecb8bf28eb 8407 0x1edf, 499, /* ở Ở */
Marko Mikulicic 0:c0ecb8bf28eb 8408 0x1ee1, 499, /* ỡ Ỡ */
Marko Mikulicic 0:c0ecb8bf28eb 8409 0x1ee3, 499, /* ợ Ợ */
Marko Mikulicic 0:c0ecb8bf28eb 8410 0x1ee5, 499, /* ụ Ụ */
Marko Mikulicic 0:c0ecb8bf28eb 8411 0x1ee7, 499, /* ủ Ủ */
Marko Mikulicic 0:c0ecb8bf28eb 8412 0x1ee9, 499, /* ứ Ứ */
Marko Mikulicic 0:c0ecb8bf28eb 8413 0x1eeb, 499, /* ừ Ừ */
Marko Mikulicic 0:c0ecb8bf28eb 8414 0x1eed, 499, /* ử Ử */
Marko Mikulicic 0:c0ecb8bf28eb 8415 0x1eef, 499, /* ữ Ữ */
Marko Mikulicic 0:c0ecb8bf28eb 8416 0x1ef1, 499, /* ự Ự */
Marko Mikulicic 0:c0ecb8bf28eb 8417 0x1ef3, 499, /* ỳ Ỳ */
Marko Mikulicic 0:c0ecb8bf28eb 8418 0x1ef5, 499, /* ỵ Ỵ */
Marko Mikulicic 0:c0ecb8bf28eb 8419 0x1ef7, 499, /* ỷ Ỷ */
Marko Mikulicic 0:c0ecb8bf28eb 8420 0x1ef9, 499, /* ỹ Ỹ */
Marko Mikulicic 0:c0ecb8bf28eb 8421 0x1f51, 508, /* ὑ Ὑ */
Marko Mikulicic 0:c0ecb8bf28eb 8422 0x1f53, 508, /* ὓ Ὓ */
Marko Mikulicic 0:c0ecb8bf28eb 8423 0x1f55, 508, /* ὕ Ὕ */
Marko Mikulicic 0:c0ecb8bf28eb 8424 0x1f57, 508, /* ὗ Ὗ */
Marko Mikulicic 0:c0ecb8bf28eb 8425 0x1fb3, 509, /* ᾳ ᾼ */
Marko Mikulicic 0:c0ecb8bf28eb 8426 0x1fc3, 509, /* ῃ ῌ */
Marko Mikulicic 0:c0ecb8bf28eb 8427 0x1fe5, 507, /* ῥ Ῥ */
Marko Mikulicic 0:c0ecb8bf28eb 8428 0x1ff3, 509, /* ῳ ῼ */
Marko Mikulicic 0:c0ecb8bf28eb 8429 };
Marko Mikulicic 0:c0ecb8bf28eb 8430
Marko Mikulicic 0:c0ecb8bf28eb 8431 /*
Marko Mikulicic 0:c0ecb8bf28eb 8432 * upper case ranges
Marko Mikulicic 0:c0ecb8bf28eb 8433 * 3rd col is conversion excess 500
Marko Mikulicic 0:c0ecb8bf28eb 8434 */
Marko Mikulicic 0:c0ecb8bf28eb 8435 static Rune __tolower2[] = {
Marko Mikulicic 0:c0ecb8bf28eb 8436 0x0041, 0x005a, 532, /* A-Z a-z */
Marko Mikulicic 0:c0ecb8bf28eb 8437 0x00c0, 0x00d6, 532, /* À-Ö à-ö */
Marko Mikulicic 0:c0ecb8bf28eb 8438 0x00d8, 0x00de, 532, /* Ø-Þ ø-þ */
Marko Mikulicic 0:c0ecb8bf28eb 8439 0x0189, 0x018a, 705, /* Ɖ-Ɗ ɖ-ɗ */
Marko Mikulicic 0:c0ecb8bf28eb 8440 0x018e, 0x018f, 702, /* Ǝ-Ə ɘ-ə */
Marko Mikulicic 0:c0ecb8bf28eb 8441 0x01b1, 0x01b2, 717, /* Ʊ-Ʋ ʊ-ʋ */
Marko Mikulicic 0:c0ecb8bf28eb 8442 0x0388, 0x038a, 537, /* Έ-Ί έ-ί */
Marko Mikulicic 0:c0ecb8bf28eb 8443 0x038e, 0x038f, 563, /* Ύ-Ώ ύ-ώ */
Marko Mikulicic 0:c0ecb8bf28eb 8444 0x0391, 0x03a1, 532, /* Α-Ρ α-ρ */
Marko Mikulicic 0:c0ecb8bf28eb 8445 0x03a3, 0x03ab, 532, /* Σ-Ϋ σ-ϋ */
Marko Mikulicic 0:c0ecb8bf28eb 8446 0x0401, 0x040c, 580, /* Ё-Ќ ё-ќ */
Marko Mikulicic 0:c0ecb8bf28eb 8447 0x040e, 0x040f, 580, /* Ў-Џ ў-џ */
Marko Mikulicic 0:c0ecb8bf28eb 8448 0x0410, 0x042f, 532, /* А-Я а-я */
Marko Mikulicic 0:c0ecb8bf28eb 8449 0x0531, 0x0556, 548, /* Ա-Ֆ ա-ֆ */
Marko Mikulicic 0:c0ecb8bf28eb 8450 0x10a0, 0x10c5, 548, /* Ⴀ-Ⴥ ა-ჵ */
Marko Mikulicic 0:c0ecb8bf28eb 8451 0x1f08, 0x1f0f, 492, /* Ἀ-Ἇ ἀ-ἇ */
Marko Mikulicic 0:c0ecb8bf28eb 8452 0x1f18, 0x1f1d, 492, /* Ἐ-Ἕ ἐ-ἕ */
Marko Mikulicic 0:c0ecb8bf28eb 8453 0x1f28, 0x1f2f, 492, /* Ἠ-Ἧ ἠ-ἧ */
Marko Mikulicic 0:c0ecb8bf28eb 8454 0x1f38, 0x1f3f, 492, /* Ἰ-Ἷ ἰ-ἷ */
Marko Mikulicic 0:c0ecb8bf28eb 8455 0x1f48, 0x1f4d, 492, /* Ὀ-Ὅ ὀ-ὅ */
Marko Mikulicic 0:c0ecb8bf28eb 8456 0x1f68, 0x1f6f, 492, /* Ὠ-Ὧ ὠ-ὧ */
Marko Mikulicic 0:c0ecb8bf28eb 8457 0x1f88, 0x1f8f, 492, /* ᾈ-ᾏ ᾀ-ᾇ */
Marko Mikulicic 0:c0ecb8bf28eb 8458 0x1f98, 0x1f9f, 492, /* ᾘ-ᾟ ᾐ-ᾗ */
Marko Mikulicic 0:c0ecb8bf28eb 8459 0x1fa8, 0x1faf, 492, /* ᾨ-ᾯ ᾠ-ᾧ */
Marko Mikulicic 0:c0ecb8bf28eb 8460 0x1fb8, 0x1fb9, 492, /* Ᾰ-Ᾱ ᾰ-ᾱ */
Marko Mikulicic 0:c0ecb8bf28eb 8461 0x1fba, 0x1fbb, 426, /* Ὰ-Ά ὰ-ά */
Marko Mikulicic 0:c0ecb8bf28eb 8462 0x1fc8, 0x1fcb, 414, /* Ὲ-Ή ὲ-ή */
Marko Mikulicic 0:c0ecb8bf28eb 8463 0x1fd8, 0x1fd9, 492, /* Ῐ-Ῑ ῐ-ῑ */
Marko Mikulicic 0:c0ecb8bf28eb 8464 0x1fda, 0x1fdb, 400, /* Ὶ-Ί ὶ-ί */
Marko Mikulicic 0:c0ecb8bf28eb 8465 0x1fe8, 0x1fe9, 492, /* Ῠ-Ῡ ῠ-ῡ */
Marko Mikulicic 0:c0ecb8bf28eb 8466 0x1fea, 0x1feb, 388, /* Ὺ-Ύ ὺ-ύ */
Marko Mikulicic 0:c0ecb8bf28eb 8467 0x1ff8, 0x1ff9, 372, /* Ὸ-Ό ὸ-ό */
Marko Mikulicic 0:c0ecb8bf28eb 8468 0x1ffa, 0x1ffb, 374, /* Ὼ-Ώ ὼ-ώ */
Marko Mikulicic 0:c0ecb8bf28eb 8469 0x2160, 0x216f, 516, /* Ⅰ-Ⅿ ⅰ-ⅿ */
Marko Mikulicic 0:c0ecb8bf28eb 8470 0x24b6, 0x24cf, 526, /* Ⓐ-Ⓩ ⓐ-ⓩ */
Marko Mikulicic 0:c0ecb8bf28eb 8471 0xff21, 0xff3a, 532, /* A-Z a-z */
Marko Mikulicic 0:c0ecb8bf28eb 8472 };
Marko Mikulicic 0:c0ecb8bf28eb 8473
Marko Mikulicic 0:c0ecb8bf28eb 8474 /*
Marko Mikulicic 0:c0ecb8bf28eb 8475 * upper case singlets
Marko Mikulicic 0:c0ecb8bf28eb 8476 * 2nd col is conversion excess 500
Marko Mikulicic 0:c0ecb8bf28eb 8477 */
Marko Mikulicic 0:c0ecb8bf28eb 8478 static Rune __tolower1[] = {
Marko Mikulicic 0:c0ecb8bf28eb 8479 0x0100, 501, /* Ā ā */
Marko Mikulicic 0:c0ecb8bf28eb 8480 0x0102, 501, /* Ă ă */
Marko Mikulicic 0:c0ecb8bf28eb 8481 0x0104, 501, /* Ą ą */
Marko Mikulicic 0:c0ecb8bf28eb 8482 0x0106, 501, /* Ć ć */
Marko Mikulicic 0:c0ecb8bf28eb 8483 0x0108, 501, /* Ĉ ĉ */
Marko Mikulicic 0:c0ecb8bf28eb 8484 0x010a, 501, /* Ċ ċ */
Marko Mikulicic 0:c0ecb8bf28eb 8485 0x010c, 501, /* Č č */
Marko Mikulicic 0:c0ecb8bf28eb 8486 0x010e, 501, /* Ď ď */
Marko Mikulicic 0:c0ecb8bf28eb 8487 0x0110, 501, /* Đ đ */
Marko Mikulicic 0:c0ecb8bf28eb 8488 0x0112, 501, /* Ē ē */
Marko Mikulicic 0:c0ecb8bf28eb 8489 0x0114, 501, /* Ĕ ĕ */
Marko Mikulicic 0:c0ecb8bf28eb 8490 0x0116, 501, /* Ė ė */
Marko Mikulicic 0:c0ecb8bf28eb 8491 0x0118, 501, /* Ę ę */
Marko Mikulicic 0:c0ecb8bf28eb 8492 0x011a, 501, /* Ě ě */
Marko Mikulicic 0:c0ecb8bf28eb 8493 0x011c, 501, /* Ĝ ĝ */
Marko Mikulicic 0:c0ecb8bf28eb 8494 0x011e, 501, /* Ğ ğ */
Marko Mikulicic 0:c0ecb8bf28eb 8495 0x0120, 501, /* Ġ ġ */
Marko Mikulicic 0:c0ecb8bf28eb 8496 0x0122, 501, /* Ģ ģ */
Marko Mikulicic 0:c0ecb8bf28eb 8497 0x0124, 501, /* Ĥ ĥ */
Marko Mikulicic 0:c0ecb8bf28eb 8498 0x0126, 501, /* Ħ ħ */
Marko Mikulicic 0:c0ecb8bf28eb 8499 0x0128, 501, /* Ĩ ĩ */
Marko Mikulicic 0:c0ecb8bf28eb 8500 0x012a, 501, /* Ī ī */
Marko Mikulicic 0:c0ecb8bf28eb 8501 0x012c, 501, /* Ĭ ĭ */
Marko Mikulicic 0:c0ecb8bf28eb 8502 0x012e, 501, /* Į į */
Marko Mikulicic 0:c0ecb8bf28eb 8503 0x0130, 301, /* İ i */
Marko Mikulicic 0:c0ecb8bf28eb 8504 0x0132, 501, /* IJ ij */
Marko Mikulicic 0:c0ecb8bf28eb 8505 0x0134, 501, /* Ĵ ĵ */
Marko Mikulicic 0:c0ecb8bf28eb 8506 0x0136, 501, /* Ķ ķ */
Marko Mikulicic 0:c0ecb8bf28eb 8507 0x0139, 501, /* Ĺ ĺ */
Marko Mikulicic 0:c0ecb8bf28eb 8508 0x013b, 501, /* Ļ ļ */
Marko Mikulicic 0:c0ecb8bf28eb 8509 0x013d, 501, /* Ľ ľ */
Marko Mikulicic 0:c0ecb8bf28eb 8510 0x013f, 501, /* Ŀ ŀ */
Marko Mikulicic 0:c0ecb8bf28eb 8511 0x0141, 501, /* Ł ł */
Marko Mikulicic 0:c0ecb8bf28eb 8512 0x0143, 501, /* Ń ń */
Marko Mikulicic 0:c0ecb8bf28eb 8513 0x0145, 501, /* Ņ ņ */
Marko Mikulicic 0:c0ecb8bf28eb 8514 0x0147, 501, /* Ň ň */
Marko Mikulicic 0:c0ecb8bf28eb 8515 0x014a, 501, /* Ŋ ŋ */
Marko Mikulicic 0:c0ecb8bf28eb 8516 0x014c, 501, /* Ō ō */
Marko Mikulicic 0:c0ecb8bf28eb 8517 0x014e, 501, /* Ŏ ŏ */
Marko Mikulicic 0:c0ecb8bf28eb 8518 0x0150, 501, /* Ő ő */
Marko Mikulicic 0:c0ecb8bf28eb 8519 0x0152, 501, /* Œ œ */
Marko Mikulicic 0:c0ecb8bf28eb 8520 0x0154, 501, /* Ŕ ŕ */
Marko Mikulicic 0:c0ecb8bf28eb 8521 0x0156, 501, /* Ŗ ŗ */
Marko Mikulicic 0:c0ecb8bf28eb 8522 0x0158, 501, /* Ř ř */
Marko Mikulicic 0:c0ecb8bf28eb 8523 0x015a, 501, /* Ś ś */
Marko Mikulicic 0:c0ecb8bf28eb 8524 0x015c, 501, /* Ŝ ŝ */
Marko Mikulicic 0:c0ecb8bf28eb 8525 0x015e, 501, /* Ş ş */
Marko Mikulicic 0:c0ecb8bf28eb 8526 0x0160, 501, /* Š š */
Marko Mikulicic 0:c0ecb8bf28eb 8527 0x0162, 501, /* Ţ ţ */
Marko Mikulicic 0:c0ecb8bf28eb 8528 0x0164, 501, /* Ť ť */
Marko Mikulicic 0:c0ecb8bf28eb 8529 0x0166, 501, /* Ŧ ŧ */
Marko Mikulicic 0:c0ecb8bf28eb 8530 0x0168, 501, /* Ũ ũ */
Marko Mikulicic 0:c0ecb8bf28eb 8531 0x016a, 501, /* Ū ū */
Marko Mikulicic 0:c0ecb8bf28eb 8532 0x016c, 501, /* Ŭ ŭ */
Marko Mikulicic 0:c0ecb8bf28eb 8533 0x016e, 501, /* Ů ů */
Marko Mikulicic 0:c0ecb8bf28eb 8534 0x0170, 501, /* Ű ű */
Marko Mikulicic 0:c0ecb8bf28eb 8535 0x0172, 501, /* Ų ų */
Marko Mikulicic 0:c0ecb8bf28eb 8536 0x0174, 501, /* Ŵ ŵ */
Marko Mikulicic 0:c0ecb8bf28eb 8537 0x0176, 501, /* Ŷ ŷ */
Marko Mikulicic 0:c0ecb8bf28eb 8538 0x0178, 379, /* Ÿ ÿ */
Marko Mikulicic 0:c0ecb8bf28eb 8539 0x0179, 501, /* Ź ź */
Marko Mikulicic 0:c0ecb8bf28eb 8540 0x017b, 501, /* Ż ż */
Marko Mikulicic 0:c0ecb8bf28eb 8541 0x017d, 501, /* Ž ž */
Marko Mikulicic 0:c0ecb8bf28eb 8542 0x0181, 710, /* Ɓ ɓ */
Marko Mikulicic 0:c0ecb8bf28eb 8543 0x0182, 501, /* Ƃ ƃ */
Marko Mikulicic 0:c0ecb8bf28eb 8544 0x0184, 501, /* Ƅ ƅ */
Marko Mikulicic 0:c0ecb8bf28eb 8545 0x0186, 706, /* Ɔ ɔ */
Marko Mikulicic 0:c0ecb8bf28eb 8546 0x0187, 501, /* Ƈ ƈ */
Marko Mikulicic 0:c0ecb8bf28eb 8547 0x018b, 501, /* Ƌ ƌ */
Marko Mikulicic 0:c0ecb8bf28eb 8548 0x0190, 703, /* Ɛ ɛ */
Marko Mikulicic 0:c0ecb8bf28eb 8549 0x0191, 501, /* Ƒ ƒ */
Marko Mikulicic 0:c0ecb8bf28eb 8550 0x0193, 705, /* Ɠ ɠ */
Marko Mikulicic 0:c0ecb8bf28eb 8551 0x0194, 707, /* Ɣ ɣ */
Marko Mikulicic 0:c0ecb8bf28eb 8552 0x0196, 711, /* Ɩ ɩ */
Marko Mikulicic 0:c0ecb8bf28eb 8553 0x0197, 709, /* Ɨ ɨ */
Marko Mikulicic 0:c0ecb8bf28eb 8554 0x0198, 501, /* Ƙ ƙ */
Marko Mikulicic 0:c0ecb8bf28eb 8555 0x019c, 711, /* Ɯ ɯ */
Marko Mikulicic 0:c0ecb8bf28eb 8556 0x019d, 713, /* Ɲ ɲ */
Marko Mikulicic 0:c0ecb8bf28eb 8557 0x01a0, 501, /* Ơ ơ */
Marko Mikulicic 0:c0ecb8bf28eb 8558 0x01a2, 501, /* Ƣ ƣ */
Marko Mikulicic 0:c0ecb8bf28eb 8559 0x01a4, 501, /* Ƥ ƥ */
Marko Mikulicic 0:c0ecb8bf28eb 8560 0x01a7, 501, /* Ƨ ƨ */
Marko Mikulicic 0:c0ecb8bf28eb 8561 0x01a9, 718, /* Ʃ ʃ */
Marko Mikulicic 0:c0ecb8bf28eb 8562 0x01ac, 501, /* Ƭ ƭ */
Marko Mikulicic 0:c0ecb8bf28eb 8563 0x01ae, 718, /* Ʈ ʈ */
Marko Mikulicic 0:c0ecb8bf28eb 8564 0x01af, 501, /* Ư ư */
Marko Mikulicic 0:c0ecb8bf28eb 8565 0x01b3, 501, /* Ƴ ƴ */
Marko Mikulicic 0:c0ecb8bf28eb 8566 0x01b5, 501, /* Ƶ ƶ */
Marko Mikulicic 0:c0ecb8bf28eb 8567 0x01b7, 719, /* Ʒ ʒ */
Marko Mikulicic 0:c0ecb8bf28eb 8568 0x01b8, 501, /* Ƹ ƹ */
Marko Mikulicic 0:c0ecb8bf28eb 8569 0x01bc, 501, /* Ƽ ƽ */
Marko Mikulicic 0:c0ecb8bf28eb 8570 0x01c4, 502, /* DŽ dž */
Marko Mikulicic 0:c0ecb8bf28eb 8571 0x01c5, 501, /* Dž dž */
Marko Mikulicic 0:c0ecb8bf28eb 8572 0x01c7, 502, /* LJ lj */
Marko Mikulicic 0:c0ecb8bf28eb 8573 0x01c8, 501, /* Lj lj */
Marko Mikulicic 0:c0ecb8bf28eb 8574 0x01ca, 502, /* NJ nj */
Marko Mikulicic 0:c0ecb8bf28eb 8575 0x01cb, 501, /* Nj nj */
Marko Mikulicic 0:c0ecb8bf28eb 8576 0x01cd, 501, /* Ǎ ǎ */
Marko Mikulicic 0:c0ecb8bf28eb 8577 0x01cf, 501, /* Ǐ ǐ */
Marko Mikulicic 0:c0ecb8bf28eb 8578 0x01d1, 501, /* Ǒ ǒ */
Marko Mikulicic 0:c0ecb8bf28eb 8579 0x01d3, 501, /* Ǔ ǔ */
Marko Mikulicic 0:c0ecb8bf28eb 8580 0x01d5, 501, /* Ǖ ǖ */
Marko Mikulicic 0:c0ecb8bf28eb 8581 0x01d7, 501, /* Ǘ ǘ */
Marko Mikulicic 0:c0ecb8bf28eb 8582 0x01d9, 501, /* Ǚ ǚ */
Marko Mikulicic 0:c0ecb8bf28eb 8583 0x01db, 501, /* Ǜ ǜ */
Marko Mikulicic 0:c0ecb8bf28eb 8584 0x01de, 501, /* Ǟ ǟ */
Marko Mikulicic 0:c0ecb8bf28eb 8585 0x01e0, 501, /* Ǡ ǡ */
Marko Mikulicic 0:c0ecb8bf28eb 8586 0x01e2, 501, /* Ǣ ǣ */
Marko Mikulicic 0:c0ecb8bf28eb 8587 0x01e4, 501, /* Ǥ ǥ */
Marko Mikulicic 0:c0ecb8bf28eb 8588 0x01e6, 501, /* Ǧ ǧ */
Marko Mikulicic 0:c0ecb8bf28eb 8589 0x01e8, 501, /* Ǩ ǩ */
Marko Mikulicic 0:c0ecb8bf28eb 8590 0x01ea, 501, /* Ǫ ǫ */
Marko Mikulicic 0:c0ecb8bf28eb 8591 0x01ec, 501, /* Ǭ ǭ */
Marko Mikulicic 0:c0ecb8bf28eb 8592 0x01ee, 501, /* Ǯ ǯ */
Marko Mikulicic 0:c0ecb8bf28eb 8593 0x01f1, 502, /* DZ dz */
Marko Mikulicic 0:c0ecb8bf28eb 8594 0x01f2, 501, /* Dz dz */
Marko Mikulicic 0:c0ecb8bf28eb 8595 0x01f4, 501, /* Ǵ ǵ */
Marko Mikulicic 0:c0ecb8bf28eb 8596 0x01fa, 501, /* Ǻ ǻ */
Marko Mikulicic 0:c0ecb8bf28eb 8597 0x01fc, 501, /* Ǽ ǽ */
Marko Mikulicic 0:c0ecb8bf28eb 8598 0x01fe, 501, /* Ǿ ǿ */
Marko Mikulicic 0:c0ecb8bf28eb 8599 0x0200, 501, /* Ȁ ȁ */
Marko Mikulicic 0:c0ecb8bf28eb 8600 0x0202, 501, /* Ȃ ȃ */
Marko Mikulicic 0:c0ecb8bf28eb 8601 0x0204, 501, /* Ȅ ȅ */
Marko Mikulicic 0:c0ecb8bf28eb 8602 0x0206, 501, /* Ȇ ȇ */
Marko Mikulicic 0:c0ecb8bf28eb 8603 0x0208, 501, /* Ȉ ȉ */
Marko Mikulicic 0:c0ecb8bf28eb 8604 0x020a, 501, /* Ȋ ȋ */
Marko Mikulicic 0:c0ecb8bf28eb 8605 0x020c, 501, /* Ȍ ȍ */
Marko Mikulicic 0:c0ecb8bf28eb 8606 0x020e, 501, /* Ȏ ȏ */
Marko Mikulicic 0:c0ecb8bf28eb 8607 0x0210, 501, /* Ȑ ȑ */
Marko Mikulicic 0:c0ecb8bf28eb 8608 0x0212, 501, /* Ȓ ȓ */
Marko Mikulicic 0:c0ecb8bf28eb 8609 0x0214, 501, /* Ȕ ȕ */
Marko Mikulicic 0:c0ecb8bf28eb 8610 0x0216, 501, /* Ȗ ȗ */
Marko Mikulicic 0:c0ecb8bf28eb 8611 0x0386, 538, /* Ά ά */
Marko Mikulicic 0:c0ecb8bf28eb 8612 0x038c, 564, /* Ό ό */
Marko Mikulicic 0:c0ecb8bf28eb 8613 0x03e2, 501, /* Ϣ ϣ */
Marko Mikulicic 0:c0ecb8bf28eb 8614 0x03e4, 501, /* Ϥ ϥ */
Marko Mikulicic 0:c0ecb8bf28eb 8615 0x03e6, 501, /* Ϧ ϧ */
Marko Mikulicic 0:c0ecb8bf28eb 8616 0x03e8, 501, /* Ϩ ϩ */
Marko Mikulicic 0:c0ecb8bf28eb 8617 0x03ea, 501, /* Ϫ ϫ */
Marko Mikulicic 0:c0ecb8bf28eb 8618 0x03ec, 501, /* Ϭ ϭ */
Marko Mikulicic 0:c0ecb8bf28eb 8619 0x03ee, 501, /* Ϯ ϯ */
Marko Mikulicic 0:c0ecb8bf28eb 8620 0x0460, 501, /* Ѡ ѡ */
Marko Mikulicic 0:c0ecb8bf28eb 8621 0x0462, 501, /* Ѣ ѣ */
Marko Mikulicic 0:c0ecb8bf28eb 8622 0x0464, 501, /* Ѥ ѥ */
Marko Mikulicic 0:c0ecb8bf28eb 8623 0x0466, 501, /* Ѧ ѧ */
Marko Mikulicic 0:c0ecb8bf28eb 8624 0x0468, 501, /* Ѩ ѩ */
Marko Mikulicic 0:c0ecb8bf28eb 8625 0x046a, 501, /* Ѫ ѫ */
Marko Mikulicic 0:c0ecb8bf28eb 8626 0x046c, 501, /* Ѭ ѭ */
Marko Mikulicic 0:c0ecb8bf28eb 8627 0x046e, 501, /* Ѯ ѯ */
Marko Mikulicic 0:c0ecb8bf28eb 8628 0x0470, 501, /* Ѱ ѱ */
Marko Mikulicic 0:c0ecb8bf28eb 8629 0x0472, 501, /* Ѳ ѳ */
Marko Mikulicic 0:c0ecb8bf28eb 8630 0x0474, 501, /* Ѵ ѵ */
Marko Mikulicic 0:c0ecb8bf28eb 8631 0x0476, 501, /* Ѷ ѷ */
Marko Mikulicic 0:c0ecb8bf28eb 8632 0x0478, 501, /* Ѹ ѹ */
Marko Mikulicic 0:c0ecb8bf28eb 8633 0x047a, 501, /* Ѻ ѻ */
Marko Mikulicic 0:c0ecb8bf28eb 8634 0x047c, 501, /* Ѽ ѽ */
Marko Mikulicic 0:c0ecb8bf28eb 8635 0x047e, 501, /* Ѿ ѿ */
Marko Mikulicic 0:c0ecb8bf28eb 8636 0x0480, 501, /* Ҁ ҁ */
Marko Mikulicic 0:c0ecb8bf28eb 8637 0x0490, 501, /* Ґ ґ */
Marko Mikulicic 0:c0ecb8bf28eb 8638 0x0492, 501, /* Ғ ғ */
Marko Mikulicic 0:c0ecb8bf28eb 8639 0x0494, 501, /* Ҕ ҕ */
Marko Mikulicic 0:c0ecb8bf28eb 8640 0x0496, 501, /* Җ җ */
Marko Mikulicic 0:c0ecb8bf28eb 8641 0x0498, 501, /* Ҙ ҙ */
Marko Mikulicic 0:c0ecb8bf28eb 8642 0x049a, 501, /* Қ қ */
Marko Mikulicic 0:c0ecb8bf28eb 8643 0x049c, 501, /* Ҝ ҝ */
Marko Mikulicic 0:c0ecb8bf28eb 8644 0x049e, 501, /* Ҟ ҟ */
Marko Mikulicic 0:c0ecb8bf28eb 8645 0x04a0, 501, /* Ҡ ҡ */
Marko Mikulicic 0:c0ecb8bf28eb 8646 0x04a2, 501, /* Ң ң */
Marko Mikulicic 0:c0ecb8bf28eb 8647 0x04a4, 501, /* Ҥ ҥ */
Marko Mikulicic 0:c0ecb8bf28eb 8648 0x04a6, 501, /* Ҧ ҧ */
Marko Mikulicic 0:c0ecb8bf28eb 8649 0x04a8, 501, /* Ҩ ҩ */
Marko Mikulicic 0:c0ecb8bf28eb 8650 0x04aa, 501, /* Ҫ ҫ */
Marko Mikulicic 0:c0ecb8bf28eb 8651 0x04ac, 501, /* Ҭ ҭ */
Marko Mikulicic 0:c0ecb8bf28eb 8652 0x04ae, 501, /* Ү ү */
Marko Mikulicic 0:c0ecb8bf28eb 8653 0x04b0, 501, /* Ұ ұ */
Marko Mikulicic 0:c0ecb8bf28eb 8654 0x04b2, 501, /* Ҳ ҳ */
Marko Mikulicic 0:c0ecb8bf28eb 8655 0x04b4, 501, /* Ҵ ҵ */
Marko Mikulicic 0:c0ecb8bf28eb 8656 0x04b6, 501, /* Ҷ ҷ */
Marko Mikulicic 0:c0ecb8bf28eb 8657 0x04b8, 501, /* Ҹ ҹ */
Marko Mikulicic 0:c0ecb8bf28eb 8658 0x04ba, 501, /* Һ һ */
Marko Mikulicic 0:c0ecb8bf28eb 8659 0x04bc, 501, /* Ҽ ҽ */
Marko Mikulicic 0:c0ecb8bf28eb 8660 0x04be, 501, /* Ҿ ҿ */
Marko Mikulicic 0:c0ecb8bf28eb 8661 0x04c1, 501, /* Ӂ ӂ */
Marko Mikulicic 0:c0ecb8bf28eb 8662 0x04c3, 501, /* Ӄ ӄ */
Marko Mikulicic 0:c0ecb8bf28eb 8663 0x04c7, 501, /* Ӈ ӈ */
Marko Mikulicic 0:c0ecb8bf28eb 8664 0x04cb, 501, /* Ӌ ӌ */
Marko Mikulicic 0:c0ecb8bf28eb 8665 0x04d0, 501, /* Ӑ ӑ */
Marko Mikulicic 0:c0ecb8bf28eb 8666 0x04d2, 501, /* Ӓ ӓ */
Marko Mikulicic 0:c0ecb8bf28eb 8667 0x04d4, 501, /* Ӕ ӕ */
Marko Mikulicic 0:c0ecb8bf28eb 8668 0x04d6, 501, /* Ӗ ӗ */
Marko Mikulicic 0:c0ecb8bf28eb 8669 0x04d8, 501, /* Ә ә */
Marko Mikulicic 0:c0ecb8bf28eb 8670 0x04da, 501, /* Ӛ ӛ */
Marko Mikulicic 0:c0ecb8bf28eb 8671 0x04dc, 501, /* Ӝ ӝ */
Marko Mikulicic 0:c0ecb8bf28eb 8672 0x04de, 501, /* Ӟ ӟ */
Marko Mikulicic 0:c0ecb8bf28eb 8673 0x04e0, 501, /* Ӡ ӡ */
Marko Mikulicic 0:c0ecb8bf28eb 8674 0x04e2, 501, /* Ӣ ӣ */
Marko Mikulicic 0:c0ecb8bf28eb 8675 0x04e4, 501, /* Ӥ ӥ */
Marko Mikulicic 0:c0ecb8bf28eb 8676 0x04e6, 501, /* Ӧ ӧ */
Marko Mikulicic 0:c0ecb8bf28eb 8677 0x04e8, 501, /* Ө ө */
Marko Mikulicic 0:c0ecb8bf28eb 8678 0x04ea, 501, /* Ӫ ӫ */
Marko Mikulicic 0:c0ecb8bf28eb 8679 0x04ee, 501, /* Ӯ ӯ */
Marko Mikulicic 0:c0ecb8bf28eb 8680 0x04f0, 501, /* Ӱ ӱ */
Marko Mikulicic 0:c0ecb8bf28eb 8681 0x04f2, 501, /* Ӳ ӳ */
Marko Mikulicic 0:c0ecb8bf28eb 8682 0x04f4, 501, /* Ӵ ӵ */
Marko Mikulicic 0:c0ecb8bf28eb 8683 0x04f8, 501, /* Ӹ ӹ */
Marko Mikulicic 0:c0ecb8bf28eb 8684 0x1e00, 501, /* Ḁ ḁ */
Marko Mikulicic 0:c0ecb8bf28eb 8685 0x1e02, 501, /* Ḃ ḃ */
Marko Mikulicic 0:c0ecb8bf28eb 8686 0x1e04, 501, /* Ḅ ḅ */
Marko Mikulicic 0:c0ecb8bf28eb 8687 0x1e06, 501, /* Ḇ ḇ */
Marko Mikulicic 0:c0ecb8bf28eb 8688 0x1e08, 501, /* Ḉ ḉ */
Marko Mikulicic 0:c0ecb8bf28eb 8689 0x1e0a, 501, /* Ḋ ḋ */
Marko Mikulicic 0:c0ecb8bf28eb 8690 0x1e0c, 501, /* Ḍ ḍ */
Marko Mikulicic 0:c0ecb8bf28eb 8691 0x1e0e, 501, /* Ḏ ḏ */
Marko Mikulicic 0:c0ecb8bf28eb 8692 0x1e10, 501, /* Ḑ ḑ */
Marko Mikulicic 0:c0ecb8bf28eb 8693 0x1e12, 501, /* Ḓ ḓ */
Marko Mikulicic 0:c0ecb8bf28eb 8694 0x1e14, 501, /* Ḕ ḕ */
Marko Mikulicic 0:c0ecb8bf28eb 8695 0x1e16, 501, /* Ḗ ḗ */
Marko Mikulicic 0:c0ecb8bf28eb 8696 0x1e18, 501, /* Ḙ ḙ */
Marko Mikulicic 0:c0ecb8bf28eb 8697 0x1e1a, 501, /* Ḛ ḛ */
Marko Mikulicic 0:c0ecb8bf28eb 8698 0x1e1c, 501, /* Ḝ ḝ */
Marko Mikulicic 0:c0ecb8bf28eb 8699 0x1e1e, 501, /* Ḟ ḟ */
Marko Mikulicic 0:c0ecb8bf28eb 8700 0x1e20, 501, /* Ḡ ḡ */
Marko Mikulicic 0:c0ecb8bf28eb 8701 0x1e22, 501, /* Ḣ ḣ */
Marko Mikulicic 0:c0ecb8bf28eb 8702 0x1e24, 501, /* Ḥ ḥ */
Marko Mikulicic 0:c0ecb8bf28eb 8703 0x1e26, 501, /* Ḧ ḧ */
Marko Mikulicic 0:c0ecb8bf28eb 8704 0x1e28, 501, /* Ḩ ḩ */
Marko Mikulicic 0:c0ecb8bf28eb 8705 0x1e2a, 501, /* Ḫ ḫ */
Marko Mikulicic 0:c0ecb8bf28eb 8706 0x1e2c, 501, /* Ḭ ḭ */
Marko Mikulicic 0:c0ecb8bf28eb 8707 0x1e2e, 501, /* Ḯ ḯ */
Marko Mikulicic 0:c0ecb8bf28eb 8708 0x1e30, 501, /* Ḱ ḱ */
Marko Mikulicic 0:c0ecb8bf28eb 8709 0x1e32, 501, /* Ḳ ḳ */
Marko Mikulicic 0:c0ecb8bf28eb 8710 0x1e34, 501, /* Ḵ ḵ */
Marko Mikulicic 0:c0ecb8bf28eb 8711 0x1e36, 501, /* Ḷ ḷ */
Marko Mikulicic 0:c0ecb8bf28eb 8712 0x1e38, 501, /* Ḹ ḹ */
Marko Mikulicic 0:c0ecb8bf28eb 8713 0x1e3a, 501, /* Ḻ ḻ */
Marko Mikulicic 0:c0ecb8bf28eb 8714 0x1e3c, 501, /* Ḽ ḽ */
Marko Mikulicic 0:c0ecb8bf28eb 8715 0x1e3e, 501, /* Ḿ ḿ */
Marko Mikulicic 0:c0ecb8bf28eb 8716 0x1e40, 501, /* Ṁ ṁ */
Marko Mikulicic 0:c0ecb8bf28eb 8717 0x1e42, 501, /* Ṃ ṃ */
Marko Mikulicic 0:c0ecb8bf28eb 8718 0x1e44, 501, /* Ṅ ṅ */
Marko Mikulicic 0:c0ecb8bf28eb 8719 0x1e46, 501, /* Ṇ ṇ */
Marko Mikulicic 0:c0ecb8bf28eb 8720 0x1e48, 501, /* Ṉ ṉ */
Marko Mikulicic 0:c0ecb8bf28eb 8721 0x1e4a, 501, /* Ṋ ṋ */
Marko Mikulicic 0:c0ecb8bf28eb 8722 0x1e4c, 501, /* Ṍ ṍ */
Marko Mikulicic 0:c0ecb8bf28eb 8723 0x1e4e, 501, /* Ṏ ṏ */
Marko Mikulicic 0:c0ecb8bf28eb 8724 0x1e50, 501, /* Ṑ ṑ */
Marko Mikulicic 0:c0ecb8bf28eb 8725 0x1e52, 501, /* Ṓ ṓ */
Marko Mikulicic 0:c0ecb8bf28eb 8726 0x1e54, 501, /* Ṕ ṕ */
Marko Mikulicic 0:c0ecb8bf28eb 8727 0x1e56, 501, /* Ṗ ṗ */
Marko Mikulicic 0:c0ecb8bf28eb 8728 0x1e58, 501, /* Ṙ ṙ */
Marko Mikulicic 0:c0ecb8bf28eb 8729 0x1e5a, 501, /* Ṛ ṛ */
Marko Mikulicic 0:c0ecb8bf28eb 8730 0x1e5c, 501, /* Ṝ ṝ */
Marko Mikulicic 0:c0ecb8bf28eb 8731 0x1e5e, 501, /* Ṟ ṟ */
Marko Mikulicic 0:c0ecb8bf28eb 8732 0x1e60, 501, /* Ṡ ṡ */
Marko Mikulicic 0:c0ecb8bf28eb 8733 0x1e62, 501, /* Ṣ ṣ */
Marko Mikulicic 0:c0ecb8bf28eb 8734 0x1e64, 501, /* Ṥ ṥ */
Marko Mikulicic 0:c0ecb8bf28eb 8735 0x1e66, 501, /* Ṧ ṧ */
Marko Mikulicic 0:c0ecb8bf28eb 8736 0x1e68, 501, /* Ṩ ṩ */
Marko Mikulicic 0:c0ecb8bf28eb 8737 0x1e6a, 501, /* Ṫ ṫ */
Marko Mikulicic 0:c0ecb8bf28eb 8738 0x1e6c, 501, /* Ṭ ṭ */
Marko Mikulicic 0:c0ecb8bf28eb 8739 0x1e6e, 501, /* Ṯ ṯ */
Marko Mikulicic 0:c0ecb8bf28eb 8740 0x1e70, 501, /* Ṱ ṱ */
Marko Mikulicic 0:c0ecb8bf28eb 8741 0x1e72, 501, /* Ṳ ṳ */
Marko Mikulicic 0:c0ecb8bf28eb 8742 0x1e74, 501, /* Ṵ ṵ */
Marko Mikulicic 0:c0ecb8bf28eb 8743 0x1e76, 501, /* Ṷ ṷ */
Marko Mikulicic 0:c0ecb8bf28eb 8744 0x1e78, 501, /* Ṹ ṹ */
Marko Mikulicic 0:c0ecb8bf28eb 8745 0x1e7a, 501, /* Ṻ ṻ */
Marko Mikulicic 0:c0ecb8bf28eb 8746 0x1e7c, 501, /* Ṽ ṽ */
Marko Mikulicic 0:c0ecb8bf28eb 8747 0x1e7e, 501, /* Ṿ ṿ */
Marko Mikulicic 0:c0ecb8bf28eb 8748 0x1e80, 501, /* Ẁ ẁ */
Marko Mikulicic 0:c0ecb8bf28eb 8749 0x1e82, 501, /* Ẃ ẃ */
Marko Mikulicic 0:c0ecb8bf28eb 8750 0x1e84, 501, /* Ẅ ẅ */
Marko Mikulicic 0:c0ecb8bf28eb 8751 0x1e86, 501, /* Ẇ ẇ */
Marko Mikulicic 0:c0ecb8bf28eb 8752 0x1e88, 501, /* Ẉ ẉ */
Marko Mikulicic 0:c0ecb8bf28eb 8753 0x1e8a, 501, /* Ẋ ẋ */
Marko Mikulicic 0:c0ecb8bf28eb 8754 0x1e8c, 501, /* Ẍ ẍ */
Marko Mikulicic 0:c0ecb8bf28eb 8755 0x1e8e, 501, /* Ẏ ẏ */
Marko Mikulicic 0:c0ecb8bf28eb 8756 0x1e90, 501, /* Ẑ ẑ */
Marko Mikulicic 0:c0ecb8bf28eb 8757 0x1e92, 501, /* Ẓ ẓ */
Marko Mikulicic 0:c0ecb8bf28eb 8758 0x1e94, 501, /* Ẕ ẕ */
Marko Mikulicic 0:c0ecb8bf28eb 8759 0x1ea0, 501, /* Ạ ạ */
Marko Mikulicic 0:c0ecb8bf28eb 8760 0x1ea2, 501, /* Ả ả */
Marko Mikulicic 0:c0ecb8bf28eb 8761 0x1ea4, 501, /* Ấ ấ */
Marko Mikulicic 0:c0ecb8bf28eb 8762 0x1ea6, 501, /* Ầ ầ */
Marko Mikulicic 0:c0ecb8bf28eb 8763 0x1ea8, 501, /* Ẩ ẩ */
Marko Mikulicic 0:c0ecb8bf28eb 8764 0x1eaa, 501, /* Ẫ ẫ */
Marko Mikulicic 0:c0ecb8bf28eb 8765 0x1eac, 501, /* Ậ ậ */
Marko Mikulicic 0:c0ecb8bf28eb 8766 0x1eae, 501, /* Ắ ắ */
Marko Mikulicic 0:c0ecb8bf28eb 8767 0x1eb0, 501, /* Ằ ằ */
Marko Mikulicic 0:c0ecb8bf28eb 8768 0x1eb2, 501, /* Ẳ ẳ */
Marko Mikulicic 0:c0ecb8bf28eb 8769 0x1eb4, 501, /* Ẵ ẵ */
Marko Mikulicic 0:c0ecb8bf28eb 8770 0x1eb6, 501, /* Ặ ặ */
Marko Mikulicic 0:c0ecb8bf28eb 8771 0x1eb8, 501, /* Ẹ ẹ */
Marko Mikulicic 0:c0ecb8bf28eb 8772 0x1eba, 501, /* Ẻ ẻ */
Marko Mikulicic 0:c0ecb8bf28eb 8773 0x1ebc, 501, /* Ẽ ẽ */
Marko Mikulicic 0:c0ecb8bf28eb 8774 0x1ebe, 501, /* Ế ế */
Marko Mikulicic 0:c0ecb8bf28eb 8775 0x1ec0, 501, /* Ề ề */
Marko Mikulicic 0:c0ecb8bf28eb 8776 0x1ec2, 501, /* Ể ể */
Marko Mikulicic 0:c0ecb8bf28eb 8777 0x1ec4, 501, /* Ễ ễ */
Marko Mikulicic 0:c0ecb8bf28eb 8778 0x1ec6, 501, /* Ệ ệ */
Marko Mikulicic 0:c0ecb8bf28eb 8779 0x1ec8, 501, /* Ỉ ỉ */
Marko Mikulicic 0:c0ecb8bf28eb 8780 0x1eca, 501, /* Ị ị */
Marko Mikulicic 0:c0ecb8bf28eb 8781 0x1ecc, 501, /* Ọ ọ */
Marko Mikulicic 0:c0ecb8bf28eb 8782 0x1ece, 501, /* Ỏ ỏ */
Marko Mikulicic 0:c0ecb8bf28eb 8783 0x1ed0, 501, /* Ố ố */
Marko Mikulicic 0:c0ecb8bf28eb 8784 0x1ed2, 501, /* Ồ ồ */
Marko Mikulicic 0:c0ecb8bf28eb 8785 0x1ed4, 501, /* Ổ ổ */
Marko Mikulicic 0:c0ecb8bf28eb 8786 0x1ed6, 501, /* Ỗ ỗ */
Marko Mikulicic 0:c0ecb8bf28eb 8787 0x1ed8, 501, /* Ộ ộ */
Marko Mikulicic 0:c0ecb8bf28eb 8788 0x1eda, 501, /* Ớ ớ */
Marko Mikulicic 0:c0ecb8bf28eb 8789 0x1edc, 501, /* Ờ ờ */
Marko Mikulicic 0:c0ecb8bf28eb 8790 0x1ede, 501, /* Ở ở */
Marko Mikulicic 0:c0ecb8bf28eb 8791 0x1ee0, 501, /* Ỡ ỡ */
Marko Mikulicic 0:c0ecb8bf28eb 8792 0x1ee2, 501, /* Ợ ợ */
Marko Mikulicic 0:c0ecb8bf28eb 8793 0x1ee4, 501, /* Ụ ụ */
Marko Mikulicic 0:c0ecb8bf28eb 8794 0x1ee6, 501, /* Ủ ủ */
Marko Mikulicic 0:c0ecb8bf28eb 8795 0x1ee8, 501, /* Ứ ứ */
Marko Mikulicic 0:c0ecb8bf28eb 8796 0x1eea, 501, /* Ừ ừ */
Marko Mikulicic 0:c0ecb8bf28eb 8797 0x1eec, 501, /* Ử ử */
Marko Mikulicic 0:c0ecb8bf28eb 8798 0x1eee, 501, /* Ữ ữ */
Marko Mikulicic 0:c0ecb8bf28eb 8799 0x1ef0, 501, /* Ự ự */
Marko Mikulicic 0:c0ecb8bf28eb 8800 0x1ef2, 501, /* Ỳ ỳ */
Marko Mikulicic 0:c0ecb8bf28eb 8801 0x1ef4, 501, /* Ỵ ỵ */
Marko Mikulicic 0:c0ecb8bf28eb 8802 0x1ef6, 501, /* Ỷ ỷ */
Marko Mikulicic 0:c0ecb8bf28eb 8803 0x1ef8, 501, /* Ỹ ỹ */
Marko Mikulicic 0:c0ecb8bf28eb 8804 0x1f59, 492, /* Ὑ ὑ */
Marko Mikulicic 0:c0ecb8bf28eb 8805 0x1f5b, 492, /* Ὓ ὓ */
Marko Mikulicic 0:c0ecb8bf28eb 8806 0x1f5d, 492, /* Ὕ ὕ */
Marko Mikulicic 0:c0ecb8bf28eb 8807 0x1f5f, 492, /* Ὗ ὗ */
Marko Mikulicic 0:c0ecb8bf28eb 8808 0x1fbc, 491, /* ᾼ ᾳ */
Marko Mikulicic 0:c0ecb8bf28eb 8809 0x1fcc, 491, /* ῌ ῃ */
Marko Mikulicic 0:c0ecb8bf28eb 8810 0x1fec, 493, /* Ῥ ῥ */
Marko Mikulicic 0:c0ecb8bf28eb 8811 0x1ffc, 491, /* ῼ ῳ */
Marko Mikulicic 0:c0ecb8bf28eb 8812 };
Marko Mikulicic 0:c0ecb8bf28eb 8813
Marko Mikulicic 0:c0ecb8bf28eb 8814 static Rune *rune_bsearch(Rune c, Rune *t, int n, int ne) {
Marko Mikulicic 0:c0ecb8bf28eb 8815 Rune *p;
Marko Mikulicic 0:c0ecb8bf28eb 8816 int m;
Marko Mikulicic 0:c0ecb8bf28eb 8817
Marko Mikulicic 0:c0ecb8bf28eb 8818 while (n > 1) {
Marko Mikulicic 0:c0ecb8bf28eb 8819 m = n / 2;
Marko Mikulicic 0:c0ecb8bf28eb 8820 p = t + m * ne;
Marko Mikulicic 0:c0ecb8bf28eb 8821 if (c >= p[0]) {
Marko Mikulicic 0:c0ecb8bf28eb 8822 t = p;
Marko Mikulicic 0:c0ecb8bf28eb 8823 n = n - m;
Marko Mikulicic 0:c0ecb8bf28eb 8824 } else
Marko Mikulicic 0:c0ecb8bf28eb 8825 n = m;
Marko Mikulicic 0:c0ecb8bf28eb 8826 }
Marko Mikulicic 0:c0ecb8bf28eb 8827 if (n && c >= t[0]) return t;
Marko Mikulicic 0:c0ecb8bf28eb 8828 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 8829 }
Marko Mikulicic 0:c0ecb8bf28eb 8830
Marko Mikulicic 0:c0ecb8bf28eb 8831 Rune tolowerrune(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8832 Rune *p;
Marko Mikulicic 0:c0ecb8bf28eb 8833
Marko Mikulicic 0:c0ecb8bf28eb 8834 p = rune_bsearch(c, __tolower2, nelem(__tolower2) / 3, 3);
Marko Mikulicic 0:c0ecb8bf28eb 8835 if (p && c >= p[0] && c <= p[1]) return c + p[2] - 500;
Marko Mikulicic 0:c0ecb8bf28eb 8836 p = rune_bsearch(c, __tolower1, nelem(__tolower1) / 2, 2);
Marko Mikulicic 0:c0ecb8bf28eb 8837 if (p && c == p[0]) return c + p[1] - 500;
Marko Mikulicic 0:c0ecb8bf28eb 8838 return c;
Marko Mikulicic 0:c0ecb8bf28eb 8839 }
Marko Mikulicic 0:c0ecb8bf28eb 8840
Marko Mikulicic 0:c0ecb8bf28eb 8841 Rune toupperrune(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8842 Rune *p;
Marko Mikulicic 0:c0ecb8bf28eb 8843
Marko Mikulicic 0:c0ecb8bf28eb 8844 p = rune_bsearch(c, __toupper2, nelem(__toupper2) / 3, 3);
Marko Mikulicic 0:c0ecb8bf28eb 8845 if (p && c >= p[0] && c <= p[1]) return c + p[2] - 500;
Marko Mikulicic 0:c0ecb8bf28eb 8846 p = rune_bsearch(c, __toupper1, nelem(__toupper1) / 2, 2);
Marko Mikulicic 0:c0ecb8bf28eb 8847 if (p && c == p[0]) return c + p[1] - 500;
Marko Mikulicic 0:c0ecb8bf28eb 8848 return c;
Marko Mikulicic 0:c0ecb8bf28eb 8849 }
Marko Mikulicic 0:c0ecb8bf28eb 8850
Marko Mikulicic 0:c0ecb8bf28eb 8851 int islowerrune(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8852 Rune *p;
Marko Mikulicic 0:c0ecb8bf28eb 8853
Marko Mikulicic 0:c0ecb8bf28eb 8854 p = rune_bsearch(c, __toupper2, nelem(__toupper2) / 3, 3);
Marko Mikulicic 0:c0ecb8bf28eb 8855 if (p && c >= p[0] && c <= p[1]) return 1;
Marko Mikulicic 0:c0ecb8bf28eb 8856 p = rune_bsearch(c, __toupper1, nelem(__toupper1) / 2, 2);
Marko Mikulicic 0:c0ecb8bf28eb 8857 if (p && c == p[0]) return 1;
Marko Mikulicic 0:c0ecb8bf28eb 8858 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 8859 }
Marko Mikulicic 0:c0ecb8bf28eb 8860
Marko Mikulicic 0:c0ecb8bf28eb 8861 int isupperrune(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8862 Rune *p;
Marko Mikulicic 0:c0ecb8bf28eb 8863
Marko Mikulicic 0:c0ecb8bf28eb 8864 p = rune_bsearch(c, __tolower2, nelem(__tolower2) / 3, 3);
Marko Mikulicic 0:c0ecb8bf28eb 8865 if (p && c >= p[0] && c <= p[1]) return 1;
Marko Mikulicic 0:c0ecb8bf28eb 8866 p = rune_bsearch(c, __tolower1, nelem(__tolower1) / 2, 2);
Marko Mikulicic 0:c0ecb8bf28eb 8867 if (p && c == p[0]) return 1;
Marko Mikulicic 0:c0ecb8bf28eb 8868 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 8869 }
Marko Mikulicic 0:c0ecb8bf28eb 8870
Marko Mikulicic 0:c0ecb8bf28eb 8871 int isdigitrune(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8872 return c >= '0' && c <= '9';
Marko Mikulicic 0:c0ecb8bf28eb 8873 }
Marko Mikulicic 0:c0ecb8bf28eb 8874
Marko Mikulicic 0:c0ecb8bf28eb 8875 int isnewline(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8876 return c == 0xA || c == 0xD || c == 0x2028 || c == 0x2029;
Marko Mikulicic 0:c0ecb8bf28eb 8877 }
Marko Mikulicic 0:c0ecb8bf28eb 8878
Marko Mikulicic 0:c0ecb8bf28eb 8879 int iswordchar(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8880 return c == '_' || isdigitrune(c) || (c >= 'a' && c <= 'z') ||
Marko Mikulicic 0:c0ecb8bf28eb 8881 (c >= 'A' && c <= 'Z');
Marko Mikulicic 0:c0ecb8bf28eb 8882 }
Marko Mikulicic 0:c0ecb8bf28eb 8883
Marko Mikulicic 0:c0ecb8bf28eb 8884 int isalpharune(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8885 Rune *p;
Marko Mikulicic 0:c0ecb8bf28eb 8886
Marko Mikulicic 0:c0ecb8bf28eb 8887 if (isupperrune(c) || islowerrune(c)) return 1;
Marko Mikulicic 0:c0ecb8bf28eb 8888 p = rune_bsearch(c, __alpha2, nelem(__alpha2) / 2, 2);
Marko Mikulicic 0:c0ecb8bf28eb 8889 if (p && c >= p[0] && c <= p[1]) return 1;
Marko Mikulicic 0:c0ecb8bf28eb 8890 p = rune_bsearch(c, __alpha1, nelem(__alpha1), 1);
Marko Mikulicic 0:c0ecb8bf28eb 8891 if (p && c == p[0]) return 1;
Marko Mikulicic 0:c0ecb8bf28eb 8892 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 8893 }
Marko Mikulicic 0:c0ecb8bf28eb 8894
Marko Mikulicic 0:c0ecb8bf28eb 8895 int isspacerune(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8896 Rune *p;
Marko Mikulicic 0:c0ecb8bf28eb 8897
Marko Mikulicic 0:c0ecb8bf28eb 8898 p = rune_bsearch(c, __space2, nelem(__space2) / 2, 2);
Marko Mikulicic 0:c0ecb8bf28eb 8899 if (p && c >= p[0] && c <= p[1]) return 1;
Marko Mikulicic 0:c0ecb8bf28eb 8900 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 8901 }
Marko Mikulicic 0:c0ecb8bf28eb 8902
Marko Mikulicic 0:c0ecb8bf28eb 8903 #else /* CS_ENABLE_UTF8 */
Marko Mikulicic 0:c0ecb8bf28eb 8904
Marko Mikulicic 0:c0ecb8bf28eb 8905 int chartorune(Rune *rune, const char *str) {
Marko Mikulicic 0:c0ecb8bf28eb 8906 *rune = *(uchar *) str;
Marko Mikulicic 0:c0ecb8bf28eb 8907 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 8908 }
Marko Mikulicic 0:c0ecb8bf28eb 8909
Marko Mikulicic 0:c0ecb8bf28eb 8910 int fullrune(const char *str, int n) {
Marko Mikulicic 0:c0ecb8bf28eb 8911 (void) str;
Marko Mikulicic 0:c0ecb8bf28eb 8912 return (n <= 0) ? 0 : 1;
Marko Mikulicic 0:c0ecb8bf28eb 8913 }
Marko Mikulicic 0:c0ecb8bf28eb 8914
Marko Mikulicic 0:c0ecb8bf28eb 8915 int isdigitrune(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8916 return isdigit(c);
Marko Mikulicic 0:c0ecb8bf28eb 8917 }
Marko Mikulicic 0:c0ecb8bf28eb 8918
Marko Mikulicic 0:c0ecb8bf28eb 8919 int isnewline(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8920 return c == 0xA || c == 0xD || c == 0x2028 || c == 0x2029;
Marko Mikulicic 0:c0ecb8bf28eb 8921 }
Marko Mikulicic 0:c0ecb8bf28eb 8922
Marko Mikulicic 0:c0ecb8bf28eb 8923 int iswordchar(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8924 return c == '_' || isdigitrune(c) || (c >= 'a' && c <= 'z') ||
Marko Mikulicic 0:c0ecb8bf28eb 8925 (c >= 'A' && c <= 'Z');
Marko Mikulicic 0:c0ecb8bf28eb 8926 }
Marko Mikulicic 0:c0ecb8bf28eb 8927
Marko Mikulicic 0:c0ecb8bf28eb 8928 int isalpharune(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8929 return isalpha(c);
Marko Mikulicic 0:c0ecb8bf28eb 8930 }
Marko Mikulicic 0:c0ecb8bf28eb 8931 int islowerrune(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8932 return islower(c);
Marko Mikulicic 0:c0ecb8bf28eb 8933 }
Marko Mikulicic 0:c0ecb8bf28eb 8934 int isspacerune(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8935 return isspace(c);
Marko Mikulicic 0:c0ecb8bf28eb 8936 }
Marko Mikulicic 0:c0ecb8bf28eb 8937 int isupperrune(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8938 return isupper(c);
Marko Mikulicic 0:c0ecb8bf28eb 8939 }
Marko Mikulicic 0:c0ecb8bf28eb 8940
Marko Mikulicic 0:c0ecb8bf28eb 8941 int runetochar(char *str, Rune *rune) {
Marko Mikulicic 0:c0ecb8bf28eb 8942 str[0] = (char) *rune;
Marko Mikulicic 0:c0ecb8bf28eb 8943 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 8944 }
Marko Mikulicic 0:c0ecb8bf28eb 8945
Marko Mikulicic 0:c0ecb8bf28eb 8946 Rune tolowerrune(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8947 return tolower(c);
Marko Mikulicic 0:c0ecb8bf28eb 8948 }
Marko Mikulicic 0:c0ecb8bf28eb 8949 Rune toupperrune(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 8950 return toupper(c);
Marko Mikulicic 0:c0ecb8bf28eb 8951 }
Marko Mikulicic 0:c0ecb8bf28eb 8952 int utfnlen(const char *s, long m) {
Marko Mikulicic 0:c0ecb8bf28eb 8953 (void) s;
Marko Mikulicic 0:c0ecb8bf28eb 8954 return (int) c_strnlen(s, (size_t) m);
Marko Mikulicic 0:c0ecb8bf28eb 8955 }
Marko Mikulicic 0:c0ecb8bf28eb 8956
Marko Mikulicic 0:c0ecb8bf28eb 8957 const char *utfnshift(const char *s, long m) {
Marko Mikulicic 0:c0ecb8bf28eb 8958 return s + m;
Marko Mikulicic 0:c0ecb8bf28eb 8959 }
Marko Mikulicic 0:c0ecb8bf28eb 8960
Marko Mikulicic 0:c0ecb8bf28eb 8961 #endif /* CS_ENABLE_UTF8 */
Marko Mikulicic 0:c0ecb8bf28eb 8962
Marko Mikulicic 0:c0ecb8bf28eb 8963 #endif /* EXCLUDE_COMMON */
Marko Mikulicic 0:c0ecb8bf28eb 8964 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 8965 #line 1 "common/base64.c"
Marko Mikulicic 0:c0ecb8bf28eb 8966 #endif
Marko Mikulicic 0:c0ecb8bf28eb 8967 /*
Marko Mikulicic 0:c0ecb8bf28eb 8968 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 8969 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 8970 */
Marko Mikulicic 0:c0ecb8bf28eb 8971
Marko Mikulicic 0:c0ecb8bf28eb 8972 #ifndef EXCLUDE_COMMON
Marko Mikulicic 0:c0ecb8bf28eb 8973
Marko Mikulicic 0:c0ecb8bf28eb 8974 /* Amalgamated: #include "common/base64.h" */
Marko Mikulicic 0:c0ecb8bf28eb 8975 #include <string.h>
Marko Mikulicic 0:c0ecb8bf28eb 8976
Marko Mikulicic 0:c0ecb8bf28eb 8977 /* ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ */
Marko Mikulicic 0:c0ecb8bf28eb 8978
Marko Mikulicic 0:c0ecb8bf28eb 8979 #define NUM_UPPERCASES ('Z' - 'A' + 1)
Marko Mikulicic 0:c0ecb8bf28eb 8980 #define NUM_LETTERS (NUM_UPPERCASES * 2)
Marko Mikulicic 0:c0ecb8bf28eb 8981 #define NUM_DIGITS ('9' - '0' + 1)
Marko Mikulicic 0:c0ecb8bf28eb 8982
Marko Mikulicic 0:c0ecb8bf28eb 8983 /*
Marko Mikulicic 0:c0ecb8bf28eb 8984 * Emit a base64 code char.
Marko Mikulicic 0:c0ecb8bf28eb 8985 *
Marko Mikulicic 0:c0ecb8bf28eb 8986 * Doesn't use memory, thus it's safe to use to safely dump memory in crashdumps
Marko Mikulicic 0:c0ecb8bf28eb 8987 */
Marko Mikulicic 0:c0ecb8bf28eb 8988 static void cs_base64_emit_code(struct cs_base64_ctx *ctx, int v) {
Marko Mikulicic 0:c0ecb8bf28eb 8989 if (v < NUM_UPPERCASES) {
Marko Mikulicic 0:c0ecb8bf28eb 8990 ctx->b64_putc(v + 'A', ctx->user_data);
Marko Mikulicic 0:c0ecb8bf28eb 8991 } else if (v < (NUM_LETTERS)) {
Marko Mikulicic 0:c0ecb8bf28eb 8992 ctx->b64_putc(v - NUM_UPPERCASES + 'a', ctx->user_data);
Marko Mikulicic 0:c0ecb8bf28eb 8993 } else if (v < (NUM_LETTERS + NUM_DIGITS)) {
Marko Mikulicic 0:c0ecb8bf28eb 8994 ctx->b64_putc(v - NUM_LETTERS + '0', ctx->user_data);
Marko Mikulicic 0:c0ecb8bf28eb 8995 } else {
Marko Mikulicic 0:c0ecb8bf28eb 8996 ctx->b64_putc(v - NUM_LETTERS - NUM_DIGITS == 0 ? '+' : '/',
Marko Mikulicic 0:c0ecb8bf28eb 8997 ctx->user_data);
Marko Mikulicic 0:c0ecb8bf28eb 8998 }
Marko Mikulicic 0:c0ecb8bf28eb 8999 }
Marko Mikulicic 0:c0ecb8bf28eb 9000
Marko Mikulicic 0:c0ecb8bf28eb 9001 static void cs_base64_emit_chunk(struct cs_base64_ctx *ctx) {
Marko Mikulicic 0:c0ecb8bf28eb 9002 int a, b, c;
Marko Mikulicic 0:c0ecb8bf28eb 9003
Marko Mikulicic 0:c0ecb8bf28eb 9004 a = ctx->chunk[0];
Marko Mikulicic 0:c0ecb8bf28eb 9005 b = ctx->chunk[1];
Marko Mikulicic 0:c0ecb8bf28eb 9006 c = ctx->chunk[2];
Marko Mikulicic 0:c0ecb8bf28eb 9007
Marko Mikulicic 0:c0ecb8bf28eb 9008 cs_base64_emit_code(ctx, a >> 2);
Marko Mikulicic 0:c0ecb8bf28eb 9009 cs_base64_emit_code(ctx, ((a & 3) << 4) | (b >> 4));
Marko Mikulicic 0:c0ecb8bf28eb 9010 if (ctx->chunk_size > 1) {
Marko Mikulicic 0:c0ecb8bf28eb 9011 cs_base64_emit_code(ctx, (b & 15) << 2 | (c >> 6));
Marko Mikulicic 0:c0ecb8bf28eb 9012 }
Marko Mikulicic 0:c0ecb8bf28eb 9013 if (ctx->chunk_size > 2) {
Marko Mikulicic 0:c0ecb8bf28eb 9014 cs_base64_emit_code(ctx, c & 63);
Marko Mikulicic 0:c0ecb8bf28eb 9015 }
Marko Mikulicic 0:c0ecb8bf28eb 9016 }
Marko Mikulicic 0:c0ecb8bf28eb 9017
Marko Mikulicic 0:c0ecb8bf28eb 9018 void cs_base64_init(struct cs_base64_ctx *ctx, cs_base64_putc_t b64_putc,
Marko Mikulicic 0:c0ecb8bf28eb 9019 void *user_data) {
Marko Mikulicic 0:c0ecb8bf28eb 9020 ctx->chunk_size = 0;
Marko Mikulicic 0:c0ecb8bf28eb 9021 ctx->b64_putc = b64_putc;
Marko Mikulicic 0:c0ecb8bf28eb 9022 ctx->user_data = user_data;
Marko Mikulicic 0:c0ecb8bf28eb 9023 }
Marko Mikulicic 0:c0ecb8bf28eb 9024
Marko Mikulicic 0:c0ecb8bf28eb 9025 void cs_base64_update(struct cs_base64_ctx *ctx, const char *str, size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 9026 const unsigned char *src = (const unsigned char *) str;
Marko Mikulicic 0:c0ecb8bf28eb 9027 size_t i;
Marko Mikulicic 0:c0ecb8bf28eb 9028 for (i = 0; i < len; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 9029 ctx->chunk[ctx->chunk_size++] = src[i];
Marko Mikulicic 0:c0ecb8bf28eb 9030 if (ctx->chunk_size == 3) {
Marko Mikulicic 0:c0ecb8bf28eb 9031 cs_base64_emit_chunk(ctx);
Marko Mikulicic 0:c0ecb8bf28eb 9032 ctx->chunk_size = 0;
Marko Mikulicic 0:c0ecb8bf28eb 9033 }
Marko Mikulicic 0:c0ecb8bf28eb 9034 }
Marko Mikulicic 0:c0ecb8bf28eb 9035 }
Marko Mikulicic 0:c0ecb8bf28eb 9036
Marko Mikulicic 0:c0ecb8bf28eb 9037 void cs_base64_finish(struct cs_base64_ctx *ctx) {
Marko Mikulicic 0:c0ecb8bf28eb 9038 if (ctx->chunk_size > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 9039 int i;
Marko Mikulicic 0:c0ecb8bf28eb 9040 memset(&ctx->chunk[ctx->chunk_size], 0, 3 - ctx->chunk_size);
Marko Mikulicic 0:c0ecb8bf28eb 9041 cs_base64_emit_chunk(ctx);
Marko Mikulicic 0:c0ecb8bf28eb 9042 for (i = 0; i < (3 - ctx->chunk_size); i++) {
Marko Mikulicic 0:c0ecb8bf28eb 9043 ctx->b64_putc('=', ctx->user_data);
Marko Mikulicic 0:c0ecb8bf28eb 9044 }
Marko Mikulicic 0:c0ecb8bf28eb 9045 }
Marko Mikulicic 0:c0ecb8bf28eb 9046 }
Marko Mikulicic 0:c0ecb8bf28eb 9047
Marko Mikulicic 0:c0ecb8bf28eb 9048 #define BASE64_ENCODE_BODY \
Marko Mikulicic 0:c0ecb8bf28eb 9049 static const char *b64 = \
Marko Mikulicic 0:c0ecb8bf28eb 9050 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; \
Marko Mikulicic 0:c0ecb8bf28eb 9051 int i, j, a, b, c; \
Marko Mikulicic 0:c0ecb8bf28eb 9052 \
Marko Mikulicic 0:c0ecb8bf28eb 9053 for (i = j = 0; i < src_len; i += 3) { \
Marko Mikulicic 0:c0ecb8bf28eb 9054 a = src[i]; \
Marko Mikulicic 0:c0ecb8bf28eb 9055 b = i + 1 >= src_len ? 0 : src[i + 1]; \
Marko Mikulicic 0:c0ecb8bf28eb 9056 c = i + 2 >= src_len ? 0 : src[i + 2]; \
Marko Mikulicic 0:c0ecb8bf28eb 9057 \
Marko Mikulicic 0:c0ecb8bf28eb 9058 BASE64_OUT(b64[a >> 2]); \
Marko Mikulicic 0:c0ecb8bf28eb 9059 BASE64_OUT(b64[((a & 3) << 4) | (b >> 4)]); \
Marko Mikulicic 0:c0ecb8bf28eb 9060 if (i + 1 < src_len) { \
Marko Mikulicic 0:c0ecb8bf28eb 9061 BASE64_OUT(b64[(b & 15) << 2 | (c >> 6)]); \
Marko Mikulicic 0:c0ecb8bf28eb 9062 } \
Marko Mikulicic 0:c0ecb8bf28eb 9063 if (i + 2 < src_len) { \
Marko Mikulicic 0:c0ecb8bf28eb 9064 BASE64_OUT(b64[c & 63]); \
Marko Mikulicic 0:c0ecb8bf28eb 9065 } \
Marko Mikulicic 0:c0ecb8bf28eb 9066 } \
Marko Mikulicic 0:c0ecb8bf28eb 9067 \
Marko Mikulicic 0:c0ecb8bf28eb 9068 while (j % 4 != 0) { \
Marko Mikulicic 0:c0ecb8bf28eb 9069 BASE64_OUT('='); \
Marko Mikulicic 0:c0ecb8bf28eb 9070 } \
Marko Mikulicic 0:c0ecb8bf28eb 9071 BASE64_FLUSH()
Marko Mikulicic 0:c0ecb8bf28eb 9072
Marko Mikulicic 0:c0ecb8bf28eb 9073 #define BASE64_OUT(ch) \
Marko Mikulicic 0:c0ecb8bf28eb 9074 do { \
Marko Mikulicic 0:c0ecb8bf28eb 9075 dst[j++] = (ch); \
Marko Mikulicic 0:c0ecb8bf28eb 9076 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 9077
Marko Mikulicic 0:c0ecb8bf28eb 9078 #define BASE64_FLUSH() \
Marko Mikulicic 0:c0ecb8bf28eb 9079 do { \
Marko Mikulicic 0:c0ecb8bf28eb 9080 dst[j++] = '\0'; \
Marko Mikulicic 0:c0ecb8bf28eb 9081 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 9082
Marko Mikulicic 0:c0ecb8bf28eb 9083 void cs_base64_encode(const unsigned char *src, int src_len, char *dst) {
Marko Mikulicic 0:c0ecb8bf28eb 9084 BASE64_ENCODE_BODY;
Marko Mikulicic 0:c0ecb8bf28eb 9085 }
Marko Mikulicic 0:c0ecb8bf28eb 9086
Marko Mikulicic 0:c0ecb8bf28eb 9087 #undef BASE64_OUT
Marko Mikulicic 0:c0ecb8bf28eb 9088 #undef BASE64_FLUSH
Marko Mikulicic 0:c0ecb8bf28eb 9089
Marko Mikulicic 0:c0ecb8bf28eb 9090 #ifndef CS_DISABLE_STDIO
Marko Mikulicic 0:c0ecb8bf28eb 9091 #define BASE64_OUT(ch) \
Marko Mikulicic 0:c0ecb8bf28eb 9092 do { \
Marko Mikulicic 0:c0ecb8bf28eb 9093 fprintf(f, "%c", (ch)); \
Marko Mikulicic 0:c0ecb8bf28eb 9094 j++; \
Marko Mikulicic 0:c0ecb8bf28eb 9095 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 9096
Marko Mikulicic 0:c0ecb8bf28eb 9097 #define BASE64_FLUSH()
Marko Mikulicic 0:c0ecb8bf28eb 9098
Marko Mikulicic 0:c0ecb8bf28eb 9099 void cs_fprint_base64(FILE *f, const unsigned char *src, int src_len) {
Marko Mikulicic 0:c0ecb8bf28eb 9100 BASE64_ENCODE_BODY;
Marko Mikulicic 0:c0ecb8bf28eb 9101 }
Marko Mikulicic 0:c0ecb8bf28eb 9102
Marko Mikulicic 0:c0ecb8bf28eb 9103 #undef BASE64_OUT
Marko Mikulicic 0:c0ecb8bf28eb 9104 #undef BASE64_FLUSH
Marko Mikulicic 0:c0ecb8bf28eb 9105 #endif /* !CS_DISABLE_STDIO */
Marko Mikulicic 0:c0ecb8bf28eb 9106
Marko Mikulicic 0:c0ecb8bf28eb 9107 /* Convert one byte of encoded base64 input stream to 6-bit chunk */
Marko Mikulicic 0:c0ecb8bf28eb 9108 static unsigned char from_b64(unsigned char ch) {
Marko Mikulicic 0:c0ecb8bf28eb 9109 /* Inverse lookup map */
Marko Mikulicic 0:c0ecb8bf28eb 9110 static const unsigned char tab[128] = {
Marko Mikulicic 0:c0ecb8bf28eb 9111 255, 255, 255, 255,
Marko Mikulicic 0:c0ecb8bf28eb 9112 255, 255, 255, 255, /* 0 */
Marko Mikulicic 0:c0ecb8bf28eb 9113 255, 255, 255, 255,
Marko Mikulicic 0:c0ecb8bf28eb 9114 255, 255, 255, 255, /* 8 */
Marko Mikulicic 0:c0ecb8bf28eb 9115 255, 255, 255, 255,
Marko Mikulicic 0:c0ecb8bf28eb 9116 255, 255, 255, 255, /* 16 */
Marko Mikulicic 0:c0ecb8bf28eb 9117 255, 255, 255, 255,
Marko Mikulicic 0:c0ecb8bf28eb 9118 255, 255, 255, 255, /* 24 */
Marko Mikulicic 0:c0ecb8bf28eb 9119 255, 255, 255, 255,
Marko Mikulicic 0:c0ecb8bf28eb 9120 255, 255, 255, 255, /* 32 */
Marko Mikulicic 0:c0ecb8bf28eb 9121 255, 255, 255, 62,
Marko Mikulicic 0:c0ecb8bf28eb 9122 255, 255, 255, 63, /* 40 */
Marko Mikulicic 0:c0ecb8bf28eb 9123 52, 53, 54, 55,
Marko Mikulicic 0:c0ecb8bf28eb 9124 56, 57, 58, 59, /* 48 */
Marko Mikulicic 0:c0ecb8bf28eb 9125 60, 61, 255, 255,
Marko Mikulicic 0:c0ecb8bf28eb 9126 255, 200, 255, 255, /* 56 '=' is 200, on index 61 */
Marko Mikulicic 0:c0ecb8bf28eb 9127 255, 0, 1, 2,
Marko Mikulicic 0:c0ecb8bf28eb 9128 3, 4, 5, 6, /* 64 */
Marko Mikulicic 0:c0ecb8bf28eb 9129 7, 8, 9, 10,
Marko Mikulicic 0:c0ecb8bf28eb 9130 11, 12, 13, 14, /* 72 */
Marko Mikulicic 0:c0ecb8bf28eb 9131 15, 16, 17, 18,
Marko Mikulicic 0:c0ecb8bf28eb 9132 19, 20, 21, 22, /* 80 */
Marko Mikulicic 0:c0ecb8bf28eb 9133 23, 24, 25, 255,
Marko Mikulicic 0:c0ecb8bf28eb 9134 255, 255, 255, 255, /* 88 */
Marko Mikulicic 0:c0ecb8bf28eb 9135 255, 26, 27, 28,
Marko Mikulicic 0:c0ecb8bf28eb 9136 29, 30, 31, 32, /* 96 */
Marko Mikulicic 0:c0ecb8bf28eb 9137 33, 34, 35, 36,
Marko Mikulicic 0:c0ecb8bf28eb 9138 37, 38, 39, 40, /* 104 */
Marko Mikulicic 0:c0ecb8bf28eb 9139 41, 42, 43, 44,
Marko Mikulicic 0:c0ecb8bf28eb 9140 45, 46, 47, 48, /* 112 */
Marko Mikulicic 0:c0ecb8bf28eb 9141 49, 50, 51, 255,
Marko Mikulicic 0:c0ecb8bf28eb 9142 255, 255, 255, 255, /* 120 */
Marko Mikulicic 0:c0ecb8bf28eb 9143 };
Marko Mikulicic 0:c0ecb8bf28eb 9144 return tab[ch & 127];
Marko Mikulicic 0:c0ecb8bf28eb 9145 }
Marko Mikulicic 0:c0ecb8bf28eb 9146
Marko Mikulicic 0:c0ecb8bf28eb 9147 int cs_base64_decode(const unsigned char *s, int len, char *dst) {
Marko Mikulicic 0:c0ecb8bf28eb 9148 unsigned char a, b, c, d;
Marko Mikulicic 0:c0ecb8bf28eb 9149 int orig_len = len;
Marko Mikulicic 0:c0ecb8bf28eb 9150 while (len >= 4 && (a = from_b64(s[0])) != 255 &&
Marko Mikulicic 0:c0ecb8bf28eb 9151 (b = from_b64(s[1])) != 255 && (c = from_b64(s[2])) != 255 &&
Marko Mikulicic 0:c0ecb8bf28eb 9152 (d = from_b64(s[3])) != 255) {
Marko Mikulicic 0:c0ecb8bf28eb 9153 s += 4;
Marko Mikulicic 0:c0ecb8bf28eb 9154 len -= 4;
Marko Mikulicic 0:c0ecb8bf28eb 9155 if (a == 200 || b == 200) break; /* '=' can't be there */
Marko Mikulicic 0:c0ecb8bf28eb 9156 *dst++ = a << 2 | b >> 4;
Marko Mikulicic 0:c0ecb8bf28eb 9157 if (c == 200) break;
Marko Mikulicic 0:c0ecb8bf28eb 9158 *dst++ = b << 4 | c >> 2;
Marko Mikulicic 0:c0ecb8bf28eb 9159 if (d == 200) break;
Marko Mikulicic 0:c0ecb8bf28eb 9160 *dst++ = c << 6 | d;
Marko Mikulicic 0:c0ecb8bf28eb 9161 }
Marko Mikulicic 0:c0ecb8bf28eb 9162 *dst = 0;
Marko Mikulicic 0:c0ecb8bf28eb 9163 return orig_len - len;
Marko Mikulicic 0:c0ecb8bf28eb 9164 }
Marko Mikulicic 0:c0ecb8bf28eb 9165
Marko Mikulicic 0:c0ecb8bf28eb 9166 #endif /* EXCLUDE_COMMON */
Marko Mikulicic 0:c0ecb8bf28eb 9167 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 9168 #line 1 "common/md5.c"
Marko Mikulicic 0:c0ecb8bf28eb 9169 #endif
Marko Mikulicic 0:c0ecb8bf28eb 9170 /*
Marko Mikulicic 0:c0ecb8bf28eb 9171 * This code implements the MD5 message-digest algorithm.
Marko Mikulicic 0:c0ecb8bf28eb 9172 * The algorithm is due to Ron Rivest. This code was
Marko Mikulicic 0:c0ecb8bf28eb 9173 * written by Colin Plumb in 1993, no copyright is claimed.
Marko Mikulicic 0:c0ecb8bf28eb 9174 * This code is in the public domain; do with it what you wish.
Marko Mikulicic 0:c0ecb8bf28eb 9175 *
Marko Mikulicic 0:c0ecb8bf28eb 9176 * Equivalent code is available from RSA Data Security, Inc.
Marko Mikulicic 0:c0ecb8bf28eb 9177 * This code has been tested against that, and is equivalent,
Marko Mikulicic 0:c0ecb8bf28eb 9178 * except that you don't need to include two pages of legalese
Marko Mikulicic 0:c0ecb8bf28eb 9179 * with every copy.
Marko Mikulicic 0:c0ecb8bf28eb 9180 *
Marko Mikulicic 0:c0ecb8bf28eb 9181 * To compute the message digest of a chunk of bytes, declare an
Marko Mikulicic 0:c0ecb8bf28eb 9182 * MD5Context structure, pass it to MD5Init, call MD5Update as
Marko Mikulicic 0:c0ecb8bf28eb 9183 * needed on buffers full of bytes, and then call MD5Final, which
Marko Mikulicic 0:c0ecb8bf28eb 9184 * will fill a supplied 16-byte array with the digest.
Marko Mikulicic 0:c0ecb8bf28eb 9185 */
Marko Mikulicic 0:c0ecb8bf28eb 9186
Marko Mikulicic 0:c0ecb8bf28eb 9187 #if !defined(DISABLE_MD5) && !defined(EXCLUDE_COMMON)
Marko Mikulicic 0:c0ecb8bf28eb 9188
Marko Mikulicic 0:c0ecb8bf28eb 9189 /* Amalgamated: #include "common/md5.h" */
Marko Mikulicic 0:c0ecb8bf28eb 9190
Marko Mikulicic 0:c0ecb8bf28eb 9191 #ifndef CS_ENABLE_NATIVE_MD5
Marko Mikulicic 0:c0ecb8bf28eb 9192 static void byteReverse(unsigned char *buf, unsigned longs) {
Marko Mikulicic 0:c0ecb8bf28eb 9193 /* Forrest: MD5 expect LITTLE_ENDIAN, swap if BIG_ENDIAN */
Marko Mikulicic 0:c0ecb8bf28eb 9194 #if BYTE_ORDER == BIG_ENDIAN
Marko Mikulicic 0:c0ecb8bf28eb 9195 do {
Marko Mikulicic 0:c0ecb8bf28eb 9196 uint32_t t = (uint32_t)((unsigned) buf[3] << 8 | buf[2]) << 16 |
Marko Mikulicic 0:c0ecb8bf28eb 9197 ((unsigned) buf[1] << 8 | buf[0]);
Marko Mikulicic 0:c0ecb8bf28eb 9198 *(uint32_t *) buf = t;
Marko Mikulicic 0:c0ecb8bf28eb 9199 buf += 4;
Marko Mikulicic 0:c0ecb8bf28eb 9200 } while (--longs);
Marko Mikulicic 0:c0ecb8bf28eb 9201 #else
Marko Mikulicic 0:c0ecb8bf28eb 9202 (void) buf;
Marko Mikulicic 0:c0ecb8bf28eb 9203 (void) longs;
Marko Mikulicic 0:c0ecb8bf28eb 9204 #endif
Marko Mikulicic 0:c0ecb8bf28eb 9205 }
Marko Mikulicic 0:c0ecb8bf28eb 9206
Marko Mikulicic 0:c0ecb8bf28eb 9207 #define F1(x, y, z) (z ^ (x & (y ^ z)))
Marko Mikulicic 0:c0ecb8bf28eb 9208 #define F2(x, y, z) F1(z, x, y)
Marko Mikulicic 0:c0ecb8bf28eb 9209 #define F3(x, y, z) (x ^ y ^ z)
Marko Mikulicic 0:c0ecb8bf28eb 9210 #define F4(x, y, z) (y ^ (x | ~z))
Marko Mikulicic 0:c0ecb8bf28eb 9211
Marko Mikulicic 0:c0ecb8bf28eb 9212 #define MD5STEP(f, w, x, y, z, data, s) \
Marko Mikulicic 0:c0ecb8bf28eb 9213 (w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)
Marko Mikulicic 0:c0ecb8bf28eb 9214
Marko Mikulicic 0:c0ecb8bf28eb 9215 /*
Marko Mikulicic 0:c0ecb8bf28eb 9216 * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
Marko Mikulicic 0:c0ecb8bf28eb 9217 * initialization constants.
Marko Mikulicic 0:c0ecb8bf28eb 9218 */
Marko Mikulicic 0:c0ecb8bf28eb 9219 void MD5_Init(MD5_CTX *ctx) {
Marko Mikulicic 0:c0ecb8bf28eb 9220 ctx->buf[0] = 0x67452301;
Marko Mikulicic 0:c0ecb8bf28eb 9221 ctx->buf[1] = 0xefcdab89;
Marko Mikulicic 0:c0ecb8bf28eb 9222 ctx->buf[2] = 0x98badcfe;
Marko Mikulicic 0:c0ecb8bf28eb 9223 ctx->buf[3] = 0x10325476;
Marko Mikulicic 0:c0ecb8bf28eb 9224
Marko Mikulicic 0:c0ecb8bf28eb 9225 ctx->bits[0] = 0;
Marko Mikulicic 0:c0ecb8bf28eb 9226 ctx->bits[1] = 0;
Marko Mikulicic 0:c0ecb8bf28eb 9227 }
Marko Mikulicic 0:c0ecb8bf28eb 9228
Marko Mikulicic 0:c0ecb8bf28eb 9229 static void MD5Transform(uint32_t buf[4], uint32_t const in[16]) {
Marko Mikulicic 0:c0ecb8bf28eb 9230 register uint32_t a, b, c, d;
Marko Mikulicic 0:c0ecb8bf28eb 9231
Marko Mikulicic 0:c0ecb8bf28eb 9232 a = buf[0];
Marko Mikulicic 0:c0ecb8bf28eb 9233 b = buf[1];
Marko Mikulicic 0:c0ecb8bf28eb 9234 c = buf[2];
Marko Mikulicic 0:c0ecb8bf28eb 9235 d = buf[3];
Marko Mikulicic 0:c0ecb8bf28eb 9236
Marko Mikulicic 0:c0ecb8bf28eb 9237 MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
Marko Mikulicic 0:c0ecb8bf28eb 9238 MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
Marko Mikulicic 0:c0ecb8bf28eb 9239 MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
Marko Mikulicic 0:c0ecb8bf28eb 9240 MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
Marko Mikulicic 0:c0ecb8bf28eb 9241 MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
Marko Mikulicic 0:c0ecb8bf28eb 9242 MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
Marko Mikulicic 0:c0ecb8bf28eb 9243 MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
Marko Mikulicic 0:c0ecb8bf28eb 9244 MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
Marko Mikulicic 0:c0ecb8bf28eb 9245 MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
Marko Mikulicic 0:c0ecb8bf28eb 9246 MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
Marko Mikulicic 0:c0ecb8bf28eb 9247 MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
Marko Mikulicic 0:c0ecb8bf28eb 9248 MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
Marko Mikulicic 0:c0ecb8bf28eb 9249 MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
Marko Mikulicic 0:c0ecb8bf28eb 9250 MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
Marko Mikulicic 0:c0ecb8bf28eb 9251 MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
Marko Mikulicic 0:c0ecb8bf28eb 9252 MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
Marko Mikulicic 0:c0ecb8bf28eb 9253
Marko Mikulicic 0:c0ecb8bf28eb 9254 MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
Marko Mikulicic 0:c0ecb8bf28eb 9255 MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
Marko Mikulicic 0:c0ecb8bf28eb 9256 MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
Marko Mikulicic 0:c0ecb8bf28eb 9257 MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
Marko Mikulicic 0:c0ecb8bf28eb 9258 MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
Marko Mikulicic 0:c0ecb8bf28eb 9259 MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
Marko Mikulicic 0:c0ecb8bf28eb 9260 MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
Marko Mikulicic 0:c0ecb8bf28eb 9261 MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
Marko Mikulicic 0:c0ecb8bf28eb 9262 MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
Marko Mikulicic 0:c0ecb8bf28eb 9263 MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
Marko Mikulicic 0:c0ecb8bf28eb 9264 MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
Marko Mikulicic 0:c0ecb8bf28eb 9265 MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
Marko Mikulicic 0:c0ecb8bf28eb 9266 MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
Marko Mikulicic 0:c0ecb8bf28eb 9267 MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
Marko Mikulicic 0:c0ecb8bf28eb 9268 MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
Marko Mikulicic 0:c0ecb8bf28eb 9269 MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
Marko Mikulicic 0:c0ecb8bf28eb 9270
Marko Mikulicic 0:c0ecb8bf28eb 9271 MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
Marko Mikulicic 0:c0ecb8bf28eb 9272 MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
Marko Mikulicic 0:c0ecb8bf28eb 9273 MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
Marko Mikulicic 0:c0ecb8bf28eb 9274 MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
Marko Mikulicic 0:c0ecb8bf28eb 9275 MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
Marko Mikulicic 0:c0ecb8bf28eb 9276 MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
Marko Mikulicic 0:c0ecb8bf28eb 9277 MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
Marko Mikulicic 0:c0ecb8bf28eb 9278 MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
Marko Mikulicic 0:c0ecb8bf28eb 9279 MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
Marko Mikulicic 0:c0ecb8bf28eb 9280 MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
Marko Mikulicic 0:c0ecb8bf28eb 9281 MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
Marko Mikulicic 0:c0ecb8bf28eb 9282 MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
Marko Mikulicic 0:c0ecb8bf28eb 9283 MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
Marko Mikulicic 0:c0ecb8bf28eb 9284 MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
Marko Mikulicic 0:c0ecb8bf28eb 9285 MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
Marko Mikulicic 0:c0ecb8bf28eb 9286 MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
Marko Mikulicic 0:c0ecb8bf28eb 9287
Marko Mikulicic 0:c0ecb8bf28eb 9288 MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
Marko Mikulicic 0:c0ecb8bf28eb 9289 MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
Marko Mikulicic 0:c0ecb8bf28eb 9290 MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
Marko Mikulicic 0:c0ecb8bf28eb 9291 MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
Marko Mikulicic 0:c0ecb8bf28eb 9292 MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
Marko Mikulicic 0:c0ecb8bf28eb 9293 MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
Marko Mikulicic 0:c0ecb8bf28eb 9294 MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
Marko Mikulicic 0:c0ecb8bf28eb 9295 MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
Marko Mikulicic 0:c0ecb8bf28eb 9296 MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
Marko Mikulicic 0:c0ecb8bf28eb 9297 MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
Marko Mikulicic 0:c0ecb8bf28eb 9298 MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
Marko Mikulicic 0:c0ecb8bf28eb 9299 MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
Marko Mikulicic 0:c0ecb8bf28eb 9300 MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
Marko Mikulicic 0:c0ecb8bf28eb 9301 MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
Marko Mikulicic 0:c0ecb8bf28eb 9302 MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
Marko Mikulicic 0:c0ecb8bf28eb 9303 MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
Marko Mikulicic 0:c0ecb8bf28eb 9304
Marko Mikulicic 0:c0ecb8bf28eb 9305 buf[0] += a;
Marko Mikulicic 0:c0ecb8bf28eb 9306 buf[1] += b;
Marko Mikulicic 0:c0ecb8bf28eb 9307 buf[2] += c;
Marko Mikulicic 0:c0ecb8bf28eb 9308 buf[3] += d;
Marko Mikulicic 0:c0ecb8bf28eb 9309 }
Marko Mikulicic 0:c0ecb8bf28eb 9310
Marko Mikulicic 0:c0ecb8bf28eb 9311 void MD5_Update(MD5_CTX *ctx, const unsigned char *buf, size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 9312 uint32_t t;
Marko Mikulicic 0:c0ecb8bf28eb 9313
Marko Mikulicic 0:c0ecb8bf28eb 9314 t = ctx->bits[0];
Marko Mikulicic 0:c0ecb8bf28eb 9315 if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t) ctx->bits[1]++;
Marko Mikulicic 0:c0ecb8bf28eb 9316 ctx->bits[1] += (uint32_t) len >> 29;
Marko Mikulicic 0:c0ecb8bf28eb 9317
Marko Mikulicic 0:c0ecb8bf28eb 9318 t = (t >> 3) & 0x3f;
Marko Mikulicic 0:c0ecb8bf28eb 9319
Marko Mikulicic 0:c0ecb8bf28eb 9320 if (t) {
Marko Mikulicic 0:c0ecb8bf28eb 9321 unsigned char *p = (unsigned char *) ctx->in + t;
Marko Mikulicic 0:c0ecb8bf28eb 9322
Marko Mikulicic 0:c0ecb8bf28eb 9323 t = 64 - t;
Marko Mikulicic 0:c0ecb8bf28eb 9324 if (len < t) {
Marko Mikulicic 0:c0ecb8bf28eb 9325 memcpy(p, buf, len);
Marko Mikulicic 0:c0ecb8bf28eb 9326 return;
Marko Mikulicic 0:c0ecb8bf28eb 9327 }
Marko Mikulicic 0:c0ecb8bf28eb 9328 memcpy(p, buf, t);
Marko Mikulicic 0:c0ecb8bf28eb 9329 byteReverse(ctx->in, 16);
Marko Mikulicic 0:c0ecb8bf28eb 9330 MD5Transform(ctx->buf, (uint32_t *) ctx->in);
Marko Mikulicic 0:c0ecb8bf28eb 9331 buf += t;
Marko Mikulicic 0:c0ecb8bf28eb 9332 len -= t;
Marko Mikulicic 0:c0ecb8bf28eb 9333 }
Marko Mikulicic 0:c0ecb8bf28eb 9334
Marko Mikulicic 0:c0ecb8bf28eb 9335 while (len >= 64) {
Marko Mikulicic 0:c0ecb8bf28eb 9336 memcpy(ctx->in, buf, 64);
Marko Mikulicic 0:c0ecb8bf28eb 9337 byteReverse(ctx->in, 16);
Marko Mikulicic 0:c0ecb8bf28eb 9338 MD5Transform(ctx->buf, (uint32_t *) ctx->in);
Marko Mikulicic 0:c0ecb8bf28eb 9339 buf += 64;
Marko Mikulicic 0:c0ecb8bf28eb 9340 len -= 64;
Marko Mikulicic 0:c0ecb8bf28eb 9341 }
Marko Mikulicic 0:c0ecb8bf28eb 9342
Marko Mikulicic 0:c0ecb8bf28eb 9343 memcpy(ctx->in, buf, len);
Marko Mikulicic 0:c0ecb8bf28eb 9344 }
Marko Mikulicic 0:c0ecb8bf28eb 9345
Marko Mikulicic 0:c0ecb8bf28eb 9346 void MD5_Final(unsigned char digest[16], MD5_CTX *ctx) {
Marko Mikulicic 0:c0ecb8bf28eb 9347 unsigned count;
Marko Mikulicic 0:c0ecb8bf28eb 9348 unsigned char *p;
Marko Mikulicic 0:c0ecb8bf28eb 9349 uint32_t *a;
Marko Mikulicic 0:c0ecb8bf28eb 9350
Marko Mikulicic 0:c0ecb8bf28eb 9351 count = (ctx->bits[0] >> 3) & 0x3F;
Marko Mikulicic 0:c0ecb8bf28eb 9352
Marko Mikulicic 0:c0ecb8bf28eb 9353 p = ctx->in + count;
Marko Mikulicic 0:c0ecb8bf28eb 9354 *p++ = 0x80;
Marko Mikulicic 0:c0ecb8bf28eb 9355 count = 64 - 1 - count;
Marko Mikulicic 0:c0ecb8bf28eb 9356 if (count < 8) {
Marko Mikulicic 0:c0ecb8bf28eb 9357 memset(p, 0, count);
Marko Mikulicic 0:c0ecb8bf28eb 9358 byteReverse(ctx->in, 16);
Marko Mikulicic 0:c0ecb8bf28eb 9359 MD5Transform(ctx->buf, (uint32_t *) ctx->in);
Marko Mikulicic 0:c0ecb8bf28eb 9360 memset(ctx->in, 0, 56);
Marko Mikulicic 0:c0ecb8bf28eb 9361 } else {
Marko Mikulicic 0:c0ecb8bf28eb 9362 memset(p, 0, count - 8);
Marko Mikulicic 0:c0ecb8bf28eb 9363 }
Marko Mikulicic 0:c0ecb8bf28eb 9364 byteReverse(ctx->in, 14);
Marko Mikulicic 0:c0ecb8bf28eb 9365
Marko Mikulicic 0:c0ecb8bf28eb 9366 a = (uint32_t *) ctx->in;
Marko Mikulicic 0:c0ecb8bf28eb 9367 a[14] = ctx->bits[0];
Marko Mikulicic 0:c0ecb8bf28eb 9368 a[15] = ctx->bits[1];
Marko Mikulicic 0:c0ecb8bf28eb 9369
Marko Mikulicic 0:c0ecb8bf28eb 9370 MD5Transform(ctx->buf, (uint32_t *) ctx->in);
Marko Mikulicic 0:c0ecb8bf28eb 9371 byteReverse((unsigned char *) ctx->buf, 4);
Marko Mikulicic 0:c0ecb8bf28eb 9372 memcpy(digest, ctx->buf, 16);
Marko Mikulicic 0:c0ecb8bf28eb 9373 memset((char *) ctx, 0, sizeof(*ctx));
Marko Mikulicic 0:c0ecb8bf28eb 9374 }
Marko Mikulicic 0:c0ecb8bf28eb 9375 #endif /* CS_ENABLE_NATIVE_MD5 */
Marko Mikulicic 0:c0ecb8bf28eb 9376
Marko Mikulicic 0:c0ecb8bf28eb 9377 /*
Marko Mikulicic 0:c0ecb8bf28eb 9378 * Stringify binary data. Output buffer size must be 2 * size_of_input + 1
Marko Mikulicic 0:c0ecb8bf28eb 9379 * because each byte of input takes 2 bytes in string representation
Marko Mikulicic 0:c0ecb8bf28eb 9380 * plus 1 byte for the terminating \0 character.
Marko Mikulicic 0:c0ecb8bf28eb 9381 */
Marko Mikulicic 0:c0ecb8bf28eb 9382 void cs_to_hex(char *to, const unsigned char *p, size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 9383 static const char *hex = "0123456789abcdef";
Marko Mikulicic 0:c0ecb8bf28eb 9384
Marko Mikulicic 0:c0ecb8bf28eb 9385 for (; len--; p++) {
Marko Mikulicic 0:c0ecb8bf28eb 9386 *to++ = hex[p[0] >> 4];
Marko Mikulicic 0:c0ecb8bf28eb 9387 *to++ = hex[p[0] & 0x0f];
Marko Mikulicic 0:c0ecb8bf28eb 9388 }
Marko Mikulicic 0:c0ecb8bf28eb 9389 *to = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 9390 }
Marko Mikulicic 0:c0ecb8bf28eb 9391
Marko Mikulicic 0:c0ecb8bf28eb 9392 char *cs_md5(char buf[33], ...) {
Marko Mikulicic 0:c0ecb8bf28eb 9393 unsigned char hash[16];
Marko Mikulicic 0:c0ecb8bf28eb 9394 const unsigned char *p;
Marko Mikulicic 0:c0ecb8bf28eb 9395 va_list ap;
Marko Mikulicic 0:c0ecb8bf28eb 9396 MD5_CTX ctx;
Marko Mikulicic 0:c0ecb8bf28eb 9397
Marko Mikulicic 0:c0ecb8bf28eb 9398 MD5_Init(&ctx);
Marko Mikulicic 0:c0ecb8bf28eb 9399
Marko Mikulicic 0:c0ecb8bf28eb 9400 va_start(ap, buf);
Marko Mikulicic 0:c0ecb8bf28eb 9401 while ((p = va_arg(ap, const unsigned char *) ) != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 9402 size_t len = va_arg(ap, size_t);
Marko Mikulicic 0:c0ecb8bf28eb 9403 MD5_Update(&ctx, p, len);
Marko Mikulicic 0:c0ecb8bf28eb 9404 }
Marko Mikulicic 0:c0ecb8bf28eb 9405 va_end(ap);
Marko Mikulicic 0:c0ecb8bf28eb 9406
Marko Mikulicic 0:c0ecb8bf28eb 9407 MD5_Final(hash, &ctx);
Marko Mikulicic 0:c0ecb8bf28eb 9408 cs_to_hex(buf, hash, sizeof(hash));
Marko Mikulicic 0:c0ecb8bf28eb 9409
Marko Mikulicic 0:c0ecb8bf28eb 9410 return buf;
Marko Mikulicic 0:c0ecb8bf28eb 9411 }
Marko Mikulicic 0:c0ecb8bf28eb 9412
Marko Mikulicic 0:c0ecb8bf28eb 9413 #endif /* EXCLUDE_COMMON */
Marko Mikulicic 0:c0ecb8bf28eb 9414 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 9415 #line 1 "common/sha1.c"
Marko Mikulicic 0:c0ecb8bf28eb 9416 #endif
Marko Mikulicic 0:c0ecb8bf28eb 9417 /* Copyright(c) By Steve Reid <steve@edmweb.com> */
Marko Mikulicic 0:c0ecb8bf28eb 9418 /* 100% Public Domain */
Marko Mikulicic 0:c0ecb8bf28eb 9419
Marko Mikulicic 0:c0ecb8bf28eb 9420 #if !defined(DISABLE_SHA1) && !defined(EXCLUDE_COMMON)
Marko Mikulicic 0:c0ecb8bf28eb 9421
Marko Mikulicic 0:c0ecb8bf28eb 9422 /* Amalgamated: #include "common/sha1.h" */
Marko Mikulicic 0:c0ecb8bf28eb 9423
Marko Mikulicic 0:c0ecb8bf28eb 9424 #define SHA1HANDSOFF
Marko Mikulicic 0:c0ecb8bf28eb 9425 #if defined(__sun)
Marko Mikulicic 0:c0ecb8bf28eb 9426 /* Amalgamated: #include "common/solarisfixes.h" */
Marko Mikulicic 0:c0ecb8bf28eb 9427 #endif
Marko Mikulicic 0:c0ecb8bf28eb 9428
Marko Mikulicic 0:c0ecb8bf28eb 9429 union char64long16 {
Marko Mikulicic 0:c0ecb8bf28eb 9430 unsigned char c[64];
Marko Mikulicic 0:c0ecb8bf28eb 9431 uint32_t l[16];
Marko Mikulicic 0:c0ecb8bf28eb 9432 };
Marko Mikulicic 0:c0ecb8bf28eb 9433
Marko Mikulicic 0:c0ecb8bf28eb 9434 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
Marko Mikulicic 0:c0ecb8bf28eb 9435
Marko Mikulicic 0:c0ecb8bf28eb 9436 static uint32_t blk0(union char64long16 *block, int i) {
Marko Mikulicic 0:c0ecb8bf28eb 9437 /* Forrest: SHA expect BIG_ENDIAN, swap if LITTLE_ENDIAN */
Marko Mikulicic 0:c0ecb8bf28eb 9438 #if BYTE_ORDER == LITTLE_ENDIAN
Marko Mikulicic 0:c0ecb8bf28eb 9439 block->l[i] =
Marko Mikulicic 0:c0ecb8bf28eb 9440 (rol(block->l[i], 24) & 0xFF00FF00) | (rol(block->l[i], 8) & 0x00FF00FF);
Marko Mikulicic 0:c0ecb8bf28eb 9441 #endif
Marko Mikulicic 0:c0ecb8bf28eb 9442 return block->l[i];
Marko Mikulicic 0:c0ecb8bf28eb 9443 }
Marko Mikulicic 0:c0ecb8bf28eb 9444
Marko Mikulicic 0:c0ecb8bf28eb 9445 /* Avoid redefine warning (ARM /usr/include/sys/ucontext.h define R0~R4) */
Marko Mikulicic 0:c0ecb8bf28eb 9446 #undef blk
Marko Mikulicic 0:c0ecb8bf28eb 9447 #undef R0
Marko Mikulicic 0:c0ecb8bf28eb 9448 #undef R1
Marko Mikulicic 0:c0ecb8bf28eb 9449 #undef R2
Marko Mikulicic 0:c0ecb8bf28eb 9450 #undef R3
Marko Mikulicic 0:c0ecb8bf28eb 9451 #undef R4
Marko Mikulicic 0:c0ecb8bf28eb 9452
Marko Mikulicic 0:c0ecb8bf28eb 9453 #define blk(i) \
Marko Mikulicic 0:c0ecb8bf28eb 9454 (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] ^ \
Marko Mikulicic 0:c0ecb8bf28eb 9455 block->l[(i + 2) & 15] ^ block->l[i & 15], \
Marko Mikulicic 0:c0ecb8bf28eb 9456 1))
Marko Mikulicic 0:c0ecb8bf28eb 9457 #define R0(v, w, x, y, z, i) \
Marko Mikulicic 0:c0ecb8bf28eb 9458 z += ((w & (x ^ y)) ^ y) + blk0(block, i) + 0x5A827999 + rol(v, 5); \
Marko Mikulicic 0:c0ecb8bf28eb 9459 w = rol(w, 30);
Marko Mikulicic 0:c0ecb8bf28eb 9460 #define R1(v, w, x, y, z, i) \
Marko Mikulicic 0:c0ecb8bf28eb 9461 z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
Marko Mikulicic 0:c0ecb8bf28eb 9462 w = rol(w, 30);
Marko Mikulicic 0:c0ecb8bf28eb 9463 #define R2(v, w, x, y, z, i) \
Marko Mikulicic 0:c0ecb8bf28eb 9464 z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \
Marko Mikulicic 0:c0ecb8bf28eb 9465 w = rol(w, 30);
Marko Mikulicic 0:c0ecb8bf28eb 9466 #define R3(v, w, x, y, z, i) \
Marko Mikulicic 0:c0ecb8bf28eb 9467 z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
Marko Mikulicic 0:c0ecb8bf28eb 9468 w = rol(w, 30);
Marko Mikulicic 0:c0ecb8bf28eb 9469 #define R4(v, w, x, y, z, i) \
Marko Mikulicic 0:c0ecb8bf28eb 9470 z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
Marko Mikulicic 0:c0ecb8bf28eb 9471 w = rol(w, 30);
Marko Mikulicic 0:c0ecb8bf28eb 9472
Marko Mikulicic 0:c0ecb8bf28eb 9473 void cs_sha1_transform(uint32_t state[5], const unsigned char buffer[64]) {
Marko Mikulicic 0:c0ecb8bf28eb 9474 uint32_t a, b, c, d, e;
Marko Mikulicic 0:c0ecb8bf28eb 9475 union char64long16 block[1];
Marko Mikulicic 0:c0ecb8bf28eb 9476
Marko Mikulicic 0:c0ecb8bf28eb 9477 memcpy(block, buffer, 64);
Marko Mikulicic 0:c0ecb8bf28eb 9478 a = state[0];
Marko Mikulicic 0:c0ecb8bf28eb 9479 b = state[1];
Marko Mikulicic 0:c0ecb8bf28eb 9480 c = state[2];
Marko Mikulicic 0:c0ecb8bf28eb 9481 d = state[3];
Marko Mikulicic 0:c0ecb8bf28eb 9482 e = state[4];
Marko Mikulicic 0:c0ecb8bf28eb 9483 R0(a, b, c, d, e, 0);
Marko Mikulicic 0:c0ecb8bf28eb 9484 R0(e, a, b, c, d, 1);
Marko Mikulicic 0:c0ecb8bf28eb 9485 R0(d, e, a, b, c, 2);
Marko Mikulicic 0:c0ecb8bf28eb 9486 R0(c, d, e, a, b, 3);
Marko Mikulicic 0:c0ecb8bf28eb 9487 R0(b, c, d, e, a, 4);
Marko Mikulicic 0:c0ecb8bf28eb 9488 R0(a, b, c, d, e, 5);
Marko Mikulicic 0:c0ecb8bf28eb 9489 R0(e, a, b, c, d, 6);
Marko Mikulicic 0:c0ecb8bf28eb 9490 R0(d, e, a, b, c, 7);
Marko Mikulicic 0:c0ecb8bf28eb 9491 R0(c, d, e, a, b, 8);
Marko Mikulicic 0:c0ecb8bf28eb 9492 R0(b, c, d, e, a, 9);
Marko Mikulicic 0:c0ecb8bf28eb 9493 R0(a, b, c, d, e, 10);
Marko Mikulicic 0:c0ecb8bf28eb 9494 R0(e, a, b, c, d, 11);
Marko Mikulicic 0:c0ecb8bf28eb 9495 R0(d, e, a, b, c, 12);
Marko Mikulicic 0:c0ecb8bf28eb 9496 R0(c, d, e, a, b, 13);
Marko Mikulicic 0:c0ecb8bf28eb 9497 R0(b, c, d, e, a, 14);
Marko Mikulicic 0:c0ecb8bf28eb 9498 R0(a, b, c, d, e, 15);
Marko Mikulicic 0:c0ecb8bf28eb 9499 R1(e, a, b, c, d, 16);
Marko Mikulicic 0:c0ecb8bf28eb 9500 R1(d, e, a, b, c, 17);
Marko Mikulicic 0:c0ecb8bf28eb 9501 R1(c, d, e, a, b, 18);
Marko Mikulicic 0:c0ecb8bf28eb 9502 R1(b, c, d, e, a, 19);
Marko Mikulicic 0:c0ecb8bf28eb 9503 R2(a, b, c, d, e, 20);
Marko Mikulicic 0:c0ecb8bf28eb 9504 R2(e, a, b, c, d, 21);
Marko Mikulicic 0:c0ecb8bf28eb 9505 R2(d, e, a, b, c, 22);
Marko Mikulicic 0:c0ecb8bf28eb 9506 R2(c, d, e, a, b, 23);
Marko Mikulicic 0:c0ecb8bf28eb 9507 R2(b, c, d, e, a, 24);
Marko Mikulicic 0:c0ecb8bf28eb 9508 R2(a, b, c, d, e, 25);
Marko Mikulicic 0:c0ecb8bf28eb 9509 R2(e, a, b, c, d, 26);
Marko Mikulicic 0:c0ecb8bf28eb 9510 R2(d, e, a, b, c, 27);
Marko Mikulicic 0:c0ecb8bf28eb 9511 R2(c, d, e, a, b, 28);
Marko Mikulicic 0:c0ecb8bf28eb 9512 R2(b, c, d, e, a, 29);
Marko Mikulicic 0:c0ecb8bf28eb 9513 R2(a, b, c, d, e, 30);
Marko Mikulicic 0:c0ecb8bf28eb 9514 R2(e, a, b, c, d, 31);
Marko Mikulicic 0:c0ecb8bf28eb 9515 R2(d, e, a, b, c, 32);
Marko Mikulicic 0:c0ecb8bf28eb 9516 R2(c, d, e, a, b, 33);
Marko Mikulicic 0:c0ecb8bf28eb 9517 R2(b, c, d, e, a, 34);
Marko Mikulicic 0:c0ecb8bf28eb 9518 R2(a, b, c, d, e, 35);
Marko Mikulicic 0:c0ecb8bf28eb 9519 R2(e, a, b, c, d, 36);
Marko Mikulicic 0:c0ecb8bf28eb 9520 R2(d, e, a, b, c, 37);
Marko Mikulicic 0:c0ecb8bf28eb 9521 R2(c, d, e, a, b, 38);
Marko Mikulicic 0:c0ecb8bf28eb 9522 R2(b, c, d, e, a, 39);
Marko Mikulicic 0:c0ecb8bf28eb 9523 R3(a, b, c, d, e, 40);
Marko Mikulicic 0:c0ecb8bf28eb 9524 R3(e, a, b, c, d, 41);
Marko Mikulicic 0:c0ecb8bf28eb 9525 R3(d, e, a, b, c, 42);
Marko Mikulicic 0:c0ecb8bf28eb 9526 R3(c, d, e, a, b, 43);
Marko Mikulicic 0:c0ecb8bf28eb 9527 R3(b, c, d, e, a, 44);
Marko Mikulicic 0:c0ecb8bf28eb 9528 R3(a, b, c, d, e, 45);
Marko Mikulicic 0:c0ecb8bf28eb 9529 R3(e, a, b, c, d, 46);
Marko Mikulicic 0:c0ecb8bf28eb 9530 R3(d, e, a, b, c, 47);
Marko Mikulicic 0:c0ecb8bf28eb 9531 R3(c, d, e, a, b, 48);
Marko Mikulicic 0:c0ecb8bf28eb 9532 R3(b, c, d, e, a, 49);
Marko Mikulicic 0:c0ecb8bf28eb 9533 R3(a, b, c, d, e, 50);
Marko Mikulicic 0:c0ecb8bf28eb 9534 R3(e, a, b, c, d, 51);
Marko Mikulicic 0:c0ecb8bf28eb 9535 R3(d, e, a, b, c, 52);
Marko Mikulicic 0:c0ecb8bf28eb 9536 R3(c, d, e, a, b, 53);
Marko Mikulicic 0:c0ecb8bf28eb 9537 R3(b, c, d, e, a, 54);
Marko Mikulicic 0:c0ecb8bf28eb 9538 R3(a, b, c, d, e, 55);
Marko Mikulicic 0:c0ecb8bf28eb 9539 R3(e, a, b, c, d, 56);
Marko Mikulicic 0:c0ecb8bf28eb 9540 R3(d, e, a, b, c, 57);
Marko Mikulicic 0:c0ecb8bf28eb 9541 R3(c, d, e, a, b, 58);
Marko Mikulicic 0:c0ecb8bf28eb 9542 R3(b, c, d, e, a, 59);
Marko Mikulicic 0:c0ecb8bf28eb 9543 R4(a, b, c, d, e, 60);
Marko Mikulicic 0:c0ecb8bf28eb 9544 R4(e, a, b, c, d, 61);
Marko Mikulicic 0:c0ecb8bf28eb 9545 R4(d, e, a, b, c, 62);
Marko Mikulicic 0:c0ecb8bf28eb 9546 R4(c, d, e, a, b, 63);
Marko Mikulicic 0:c0ecb8bf28eb 9547 R4(b, c, d, e, a, 64);
Marko Mikulicic 0:c0ecb8bf28eb 9548 R4(a, b, c, d, e, 65);
Marko Mikulicic 0:c0ecb8bf28eb 9549 R4(e, a, b, c, d, 66);
Marko Mikulicic 0:c0ecb8bf28eb 9550 R4(d, e, a, b, c, 67);
Marko Mikulicic 0:c0ecb8bf28eb 9551 R4(c, d, e, a, b, 68);
Marko Mikulicic 0:c0ecb8bf28eb 9552 R4(b, c, d, e, a, 69);
Marko Mikulicic 0:c0ecb8bf28eb 9553 R4(a, b, c, d, e, 70);
Marko Mikulicic 0:c0ecb8bf28eb 9554 R4(e, a, b, c, d, 71);
Marko Mikulicic 0:c0ecb8bf28eb 9555 R4(d, e, a, b, c, 72);
Marko Mikulicic 0:c0ecb8bf28eb 9556 R4(c, d, e, a, b, 73);
Marko Mikulicic 0:c0ecb8bf28eb 9557 R4(b, c, d, e, a, 74);
Marko Mikulicic 0:c0ecb8bf28eb 9558 R4(a, b, c, d, e, 75);
Marko Mikulicic 0:c0ecb8bf28eb 9559 R4(e, a, b, c, d, 76);
Marko Mikulicic 0:c0ecb8bf28eb 9560 R4(d, e, a, b, c, 77);
Marko Mikulicic 0:c0ecb8bf28eb 9561 R4(c, d, e, a, b, 78);
Marko Mikulicic 0:c0ecb8bf28eb 9562 R4(b, c, d, e, a, 79);
Marko Mikulicic 0:c0ecb8bf28eb 9563 state[0] += a;
Marko Mikulicic 0:c0ecb8bf28eb 9564 state[1] += b;
Marko Mikulicic 0:c0ecb8bf28eb 9565 state[2] += c;
Marko Mikulicic 0:c0ecb8bf28eb 9566 state[3] += d;
Marko Mikulicic 0:c0ecb8bf28eb 9567 state[4] += e;
Marko Mikulicic 0:c0ecb8bf28eb 9568 /* Erase working structures. The order of operations is important,
Marko Mikulicic 0:c0ecb8bf28eb 9569 * used to ensure that compiler doesn't optimize those out. */
Marko Mikulicic 0:c0ecb8bf28eb 9570 memset(block, 0, sizeof(block));
Marko Mikulicic 0:c0ecb8bf28eb 9571 a = b = c = d = e = 0;
Marko Mikulicic 0:c0ecb8bf28eb 9572 (void) a;
Marko Mikulicic 0:c0ecb8bf28eb 9573 (void) b;
Marko Mikulicic 0:c0ecb8bf28eb 9574 (void) c;
Marko Mikulicic 0:c0ecb8bf28eb 9575 (void) d;
Marko Mikulicic 0:c0ecb8bf28eb 9576 (void) e;
Marko Mikulicic 0:c0ecb8bf28eb 9577 }
Marko Mikulicic 0:c0ecb8bf28eb 9578
Marko Mikulicic 0:c0ecb8bf28eb 9579 void cs_sha1_init(cs_sha1_ctx *context) {
Marko Mikulicic 0:c0ecb8bf28eb 9580 context->state[0] = 0x67452301;
Marko Mikulicic 0:c0ecb8bf28eb 9581 context->state[1] = 0xEFCDAB89;
Marko Mikulicic 0:c0ecb8bf28eb 9582 context->state[2] = 0x98BADCFE;
Marko Mikulicic 0:c0ecb8bf28eb 9583 context->state[3] = 0x10325476;
Marko Mikulicic 0:c0ecb8bf28eb 9584 context->state[4] = 0xC3D2E1F0;
Marko Mikulicic 0:c0ecb8bf28eb 9585 context->count[0] = context->count[1] = 0;
Marko Mikulicic 0:c0ecb8bf28eb 9586 }
Marko Mikulicic 0:c0ecb8bf28eb 9587
Marko Mikulicic 0:c0ecb8bf28eb 9588 void cs_sha1_update(cs_sha1_ctx *context, const unsigned char *data,
Marko Mikulicic 0:c0ecb8bf28eb 9589 uint32_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 9590 uint32_t i, j;
Marko Mikulicic 0:c0ecb8bf28eb 9591
Marko Mikulicic 0:c0ecb8bf28eb 9592 j = context->count[0];
Marko Mikulicic 0:c0ecb8bf28eb 9593 if ((context->count[0] += len << 3) < j) context->count[1]++;
Marko Mikulicic 0:c0ecb8bf28eb 9594 context->count[1] += (len >> 29);
Marko Mikulicic 0:c0ecb8bf28eb 9595 j = (j >> 3) & 63;
Marko Mikulicic 0:c0ecb8bf28eb 9596 if ((j + len) > 63) {
Marko Mikulicic 0:c0ecb8bf28eb 9597 memcpy(&context->buffer[j], data, (i = 64 - j));
Marko Mikulicic 0:c0ecb8bf28eb 9598 cs_sha1_transform(context->state, context->buffer);
Marko Mikulicic 0:c0ecb8bf28eb 9599 for (; i + 63 < len; i += 64) {
Marko Mikulicic 0:c0ecb8bf28eb 9600 cs_sha1_transform(context->state, &data[i]);
Marko Mikulicic 0:c0ecb8bf28eb 9601 }
Marko Mikulicic 0:c0ecb8bf28eb 9602 j = 0;
Marko Mikulicic 0:c0ecb8bf28eb 9603 } else
Marko Mikulicic 0:c0ecb8bf28eb 9604 i = 0;
Marko Mikulicic 0:c0ecb8bf28eb 9605 memcpy(&context->buffer[j], &data[i], len - i);
Marko Mikulicic 0:c0ecb8bf28eb 9606 }
Marko Mikulicic 0:c0ecb8bf28eb 9607
Marko Mikulicic 0:c0ecb8bf28eb 9608 void cs_sha1_final(unsigned char digest[20], cs_sha1_ctx *context) {
Marko Mikulicic 0:c0ecb8bf28eb 9609 unsigned i;
Marko Mikulicic 0:c0ecb8bf28eb 9610 unsigned char finalcount[8], c;
Marko Mikulicic 0:c0ecb8bf28eb 9611
Marko Mikulicic 0:c0ecb8bf28eb 9612 for (i = 0; i < 8; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 9613 finalcount[i] = (unsigned char) ((context->count[(i >= 4 ? 0 : 1)] >>
Marko Mikulicic 0:c0ecb8bf28eb 9614 ((3 - (i & 3)) * 8)) &
Marko Mikulicic 0:c0ecb8bf28eb 9615 255);
Marko Mikulicic 0:c0ecb8bf28eb 9616 }
Marko Mikulicic 0:c0ecb8bf28eb 9617 c = 0200;
Marko Mikulicic 0:c0ecb8bf28eb 9618 cs_sha1_update(context, &c, 1);
Marko Mikulicic 0:c0ecb8bf28eb 9619 while ((context->count[0] & 504) != 448) {
Marko Mikulicic 0:c0ecb8bf28eb 9620 c = 0000;
Marko Mikulicic 0:c0ecb8bf28eb 9621 cs_sha1_update(context, &c, 1);
Marko Mikulicic 0:c0ecb8bf28eb 9622 }
Marko Mikulicic 0:c0ecb8bf28eb 9623 cs_sha1_update(context, finalcount, 8);
Marko Mikulicic 0:c0ecb8bf28eb 9624 for (i = 0; i < 20; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 9625 digest[i] =
Marko Mikulicic 0:c0ecb8bf28eb 9626 (unsigned char) ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
Marko Mikulicic 0:c0ecb8bf28eb 9627 }
Marko Mikulicic 0:c0ecb8bf28eb 9628 memset(context, '\0', sizeof(*context));
Marko Mikulicic 0:c0ecb8bf28eb 9629 memset(&finalcount, '\0', sizeof(finalcount));
Marko Mikulicic 0:c0ecb8bf28eb 9630 }
Marko Mikulicic 0:c0ecb8bf28eb 9631
Marko Mikulicic 0:c0ecb8bf28eb 9632 void cs_hmac_sha1(const unsigned char *key, size_t keylen,
Marko Mikulicic 0:c0ecb8bf28eb 9633 const unsigned char *data, size_t datalen,
Marko Mikulicic 0:c0ecb8bf28eb 9634 unsigned char out[20]) {
Marko Mikulicic 0:c0ecb8bf28eb 9635 cs_sha1_ctx ctx;
Marko Mikulicic 0:c0ecb8bf28eb 9636 unsigned char buf1[64], buf2[64], tmp_key[20], i;
Marko Mikulicic 0:c0ecb8bf28eb 9637
Marko Mikulicic 0:c0ecb8bf28eb 9638 if (keylen > sizeof(buf1)) {
Marko Mikulicic 0:c0ecb8bf28eb 9639 cs_sha1_init(&ctx);
Marko Mikulicic 0:c0ecb8bf28eb 9640 cs_sha1_update(&ctx, key, keylen);
Marko Mikulicic 0:c0ecb8bf28eb 9641 cs_sha1_final(tmp_key, &ctx);
Marko Mikulicic 0:c0ecb8bf28eb 9642 key = tmp_key;
Marko Mikulicic 0:c0ecb8bf28eb 9643 keylen = sizeof(tmp_key);
Marko Mikulicic 0:c0ecb8bf28eb 9644 }
Marko Mikulicic 0:c0ecb8bf28eb 9645
Marko Mikulicic 0:c0ecb8bf28eb 9646 memset(buf1, 0, sizeof(buf1));
Marko Mikulicic 0:c0ecb8bf28eb 9647 memset(buf2, 0, sizeof(buf2));
Marko Mikulicic 0:c0ecb8bf28eb 9648 memcpy(buf1, key, keylen);
Marko Mikulicic 0:c0ecb8bf28eb 9649 memcpy(buf2, key, keylen);
Marko Mikulicic 0:c0ecb8bf28eb 9650
Marko Mikulicic 0:c0ecb8bf28eb 9651 for (i = 0; i < sizeof(buf1); i++) {
Marko Mikulicic 0:c0ecb8bf28eb 9652 buf1[i] ^= 0x36;
Marko Mikulicic 0:c0ecb8bf28eb 9653 buf2[i] ^= 0x5c;
Marko Mikulicic 0:c0ecb8bf28eb 9654 }
Marko Mikulicic 0:c0ecb8bf28eb 9655
Marko Mikulicic 0:c0ecb8bf28eb 9656 cs_sha1_init(&ctx);
Marko Mikulicic 0:c0ecb8bf28eb 9657 cs_sha1_update(&ctx, buf1, sizeof(buf1));
Marko Mikulicic 0:c0ecb8bf28eb 9658 cs_sha1_update(&ctx, data, datalen);
Marko Mikulicic 0:c0ecb8bf28eb 9659 cs_sha1_final(out, &ctx);
Marko Mikulicic 0:c0ecb8bf28eb 9660
Marko Mikulicic 0:c0ecb8bf28eb 9661 cs_sha1_init(&ctx);
Marko Mikulicic 0:c0ecb8bf28eb 9662 cs_sha1_update(&ctx, buf2, sizeof(buf2));
Marko Mikulicic 0:c0ecb8bf28eb 9663 cs_sha1_update(&ctx, out, 20);
Marko Mikulicic 0:c0ecb8bf28eb 9664 cs_sha1_final(out, &ctx);
Marko Mikulicic 0:c0ecb8bf28eb 9665 }
Marko Mikulicic 0:c0ecb8bf28eb 9666
Marko Mikulicic 0:c0ecb8bf28eb 9667 #endif /* EXCLUDE_COMMON */
Marko Mikulicic 0:c0ecb8bf28eb 9668 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 9669 #line 1 "common/cs_dirent.c"
Marko Mikulicic 0:c0ecb8bf28eb 9670 #endif
Marko Mikulicic 0:c0ecb8bf28eb 9671 /*
Marko Mikulicic 0:c0ecb8bf28eb 9672 * Copyright (c) 2015 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 9673 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 9674 */
Marko Mikulicic 0:c0ecb8bf28eb 9675
Marko Mikulicic 0:c0ecb8bf28eb 9676 #ifndef EXCLUDE_COMMON
Marko Mikulicic 0:c0ecb8bf28eb 9677
Marko Mikulicic 0:c0ecb8bf28eb 9678 /* Amalgamated: #include "common/cs_dirent.h" */
Marko Mikulicic 0:c0ecb8bf28eb 9679
Marko Mikulicic 0:c0ecb8bf28eb 9680 /*
Marko Mikulicic 0:c0ecb8bf28eb 9681 * This file contains POSIX opendir/closedir/readdir API implementation
Marko Mikulicic 0:c0ecb8bf28eb 9682 * for systems which do not natively support it (e.g. Windows).
Marko Mikulicic 0:c0ecb8bf28eb 9683 */
Marko Mikulicic 0:c0ecb8bf28eb 9684
Marko Mikulicic 0:c0ecb8bf28eb 9685 #ifndef MG_FREE
Marko Mikulicic 0:c0ecb8bf28eb 9686 #define MG_FREE free
Marko Mikulicic 0:c0ecb8bf28eb 9687 #endif
Marko Mikulicic 0:c0ecb8bf28eb 9688
Marko Mikulicic 0:c0ecb8bf28eb 9689 #ifndef MG_MALLOC
Marko Mikulicic 0:c0ecb8bf28eb 9690 #define MG_MALLOC malloc
Marko Mikulicic 0:c0ecb8bf28eb 9691 #endif
Marko Mikulicic 0:c0ecb8bf28eb 9692
Marko Mikulicic 0:c0ecb8bf28eb 9693 #ifdef _WIN32
Marko Mikulicic 0:c0ecb8bf28eb 9694 DIR *opendir(const char *name) {
Marko Mikulicic 0:c0ecb8bf28eb 9695 DIR *dir = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 9696 wchar_t wpath[MAX_PATH];
Marko Mikulicic 0:c0ecb8bf28eb 9697 DWORD attrs;
Marko Mikulicic 0:c0ecb8bf28eb 9698
Marko Mikulicic 0:c0ecb8bf28eb 9699 if (name == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 9700 SetLastError(ERROR_BAD_ARGUMENTS);
Marko Mikulicic 0:c0ecb8bf28eb 9701 } else if ((dir = (DIR *) MG_MALLOC(sizeof(*dir))) == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 9702 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
Marko Mikulicic 0:c0ecb8bf28eb 9703 } else {
Marko Mikulicic 0:c0ecb8bf28eb 9704 to_wchar(name, wpath, ARRAY_SIZE(wpath));
Marko Mikulicic 0:c0ecb8bf28eb 9705 attrs = GetFileAttributesW(wpath);
Marko Mikulicic 0:c0ecb8bf28eb 9706 if (attrs != 0xFFFFFFFF && (attrs & FILE_ATTRIBUTE_DIRECTORY)) {
Marko Mikulicic 0:c0ecb8bf28eb 9707 (void) wcscat(wpath, L"\\*");
Marko Mikulicic 0:c0ecb8bf28eb 9708 dir->handle = FindFirstFileW(wpath, &dir->info);
Marko Mikulicic 0:c0ecb8bf28eb 9709 dir->result.d_name[0] = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 9710 } else {
Marko Mikulicic 0:c0ecb8bf28eb 9711 MG_FREE(dir);
Marko Mikulicic 0:c0ecb8bf28eb 9712 dir = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 9713 }
Marko Mikulicic 0:c0ecb8bf28eb 9714 }
Marko Mikulicic 0:c0ecb8bf28eb 9715
Marko Mikulicic 0:c0ecb8bf28eb 9716 return dir;
Marko Mikulicic 0:c0ecb8bf28eb 9717 }
Marko Mikulicic 0:c0ecb8bf28eb 9718
Marko Mikulicic 0:c0ecb8bf28eb 9719 int closedir(DIR *dir) {
Marko Mikulicic 0:c0ecb8bf28eb 9720 int result = 0;
Marko Mikulicic 0:c0ecb8bf28eb 9721
Marko Mikulicic 0:c0ecb8bf28eb 9722 if (dir != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 9723 if (dir->handle != INVALID_HANDLE_VALUE)
Marko Mikulicic 0:c0ecb8bf28eb 9724 result = FindClose(dir->handle) ? 0 : -1;
Marko Mikulicic 0:c0ecb8bf28eb 9725 MG_FREE(dir);
Marko Mikulicic 0:c0ecb8bf28eb 9726 } else {
Marko Mikulicic 0:c0ecb8bf28eb 9727 result = -1;
Marko Mikulicic 0:c0ecb8bf28eb 9728 SetLastError(ERROR_BAD_ARGUMENTS);
Marko Mikulicic 0:c0ecb8bf28eb 9729 }
Marko Mikulicic 0:c0ecb8bf28eb 9730
Marko Mikulicic 0:c0ecb8bf28eb 9731 return result;
Marko Mikulicic 0:c0ecb8bf28eb 9732 }
Marko Mikulicic 0:c0ecb8bf28eb 9733
Marko Mikulicic 0:c0ecb8bf28eb 9734 struct dirent *readdir(DIR *dir) {
Marko Mikulicic 0:c0ecb8bf28eb 9735 struct dirent *result = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 9736
Marko Mikulicic 0:c0ecb8bf28eb 9737 if (dir) {
Marko Mikulicic 0:c0ecb8bf28eb 9738 if (dir->handle != INVALID_HANDLE_VALUE) {
Marko Mikulicic 0:c0ecb8bf28eb 9739 result = &dir->result;
Marko Mikulicic 0:c0ecb8bf28eb 9740 (void) WideCharToMultiByte(CP_UTF8, 0, dir->info.cFileName, -1,
Marko Mikulicic 0:c0ecb8bf28eb 9741 result->d_name, sizeof(result->d_name), NULL,
Marko Mikulicic 0:c0ecb8bf28eb 9742 NULL);
Marko Mikulicic 0:c0ecb8bf28eb 9743
Marko Mikulicic 0:c0ecb8bf28eb 9744 if (!FindNextFileW(dir->handle, &dir->info)) {
Marko Mikulicic 0:c0ecb8bf28eb 9745 (void) FindClose(dir->handle);
Marko Mikulicic 0:c0ecb8bf28eb 9746 dir->handle = INVALID_HANDLE_VALUE;
Marko Mikulicic 0:c0ecb8bf28eb 9747 }
Marko Mikulicic 0:c0ecb8bf28eb 9748
Marko Mikulicic 0:c0ecb8bf28eb 9749 } else {
Marko Mikulicic 0:c0ecb8bf28eb 9750 SetLastError(ERROR_FILE_NOT_FOUND);
Marko Mikulicic 0:c0ecb8bf28eb 9751 }
Marko Mikulicic 0:c0ecb8bf28eb 9752 } else {
Marko Mikulicic 0:c0ecb8bf28eb 9753 SetLastError(ERROR_BAD_ARGUMENTS);
Marko Mikulicic 0:c0ecb8bf28eb 9754 }
Marko Mikulicic 0:c0ecb8bf28eb 9755
Marko Mikulicic 0:c0ecb8bf28eb 9756 return result;
Marko Mikulicic 0:c0ecb8bf28eb 9757 }
Marko Mikulicic 0:c0ecb8bf28eb 9758 #endif
Marko Mikulicic 0:c0ecb8bf28eb 9759
Marko Mikulicic 0:c0ecb8bf28eb 9760 #ifdef CS_ENABLE_SPIFFS
Marko Mikulicic 0:c0ecb8bf28eb 9761
Marko Mikulicic 0:c0ecb8bf28eb 9762 DIR *opendir(const char *dir_name) {
Marko Mikulicic 0:c0ecb8bf28eb 9763 DIR *dir = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 9764 extern spiffs fs;
Marko Mikulicic 0:c0ecb8bf28eb 9765
Marko Mikulicic 0:c0ecb8bf28eb 9766 if (dir_name != NULL && (dir = (DIR *) malloc(sizeof(*dir))) != NULL &&
Marko Mikulicic 0:c0ecb8bf28eb 9767 SPIFFS_opendir(&fs, (char *) dir_name, &dir->dh) == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 9768 free(dir);
Marko Mikulicic 0:c0ecb8bf28eb 9769 dir = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 9770 }
Marko Mikulicic 0:c0ecb8bf28eb 9771
Marko Mikulicic 0:c0ecb8bf28eb 9772 return dir;
Marko Mikulicic 0:c0ecb8bf28eb 9773 }
Marko Mikulicic 0:c0ecb8bf28eb 9774
Marko Mikulicic 0:c0ecb8bf28eb 9775 int closedir(DIR *dir) {
Marko Mikulicic 0:c0ecb8bf28eb 9776 if (dir != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 9777 SPIFFS_closedir(&dir->dh);
Marko Mikulicic 0:c0ecb8bf28eb 9778 free(dir);
Marko Mikulicic 0:c0ecb8bf28eb 9779 }
Marko Mikulicic 0:c0ecb8bf28eb 9780 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 9781 }
Marko Mikulicic 0:c0ecb8bf28eb 9782
Marko Mikulicic 0:c0ecb8bf28eb 9783 struct dirent *readdir(DIR *dir) {
Marko Mikulicic 0:c0ecb8bf28eb 9784 return SPIFFS_readdir(&dir->dh, &dir->de);
Marko Mikulicic 0:c0ecb8bf28eb 9785 }
Marko Mikulicic 0:c0ecb8bf28eb 9786
Marko Mikulicic 0:c0ecb8bf28eb 9787 /* SPIFFs doesn't support directory operations */
Marko Mikulicic 0:c0ecb8bf28eb 9788 int rmdir(const char *path) {
Marko Mikulicic 0:c0ecb8bf28eb 9789 (void) path;
Marko Mikulicic 0:c0ecb8bf28eb 9790 return ENOTDIR;
Marko Mikulicic 0:c0ecb8bf28eb 9791 }
Marko Mikulicic 0:c0ecb8bf28eb 9792
Marko Mikulicic 0:c0ecb8bf28eb 9793 int mkdir(const char *path, mode_t mode) {
Marko Mikulicic 0:c0ecb8bf28eb 9794 (void) path;
Marko Mikulicic 0:c0ecb8bf28eb 9795 (void) mode;
Marko Mikulicic 0:c0ecb8bf28eb 9796 /* for spiffs supports only root dir, which comes from mongoose as '.' */
Marko Mikulicic 0:c0ecb8bf28eb 9797 return (strlen(path) == 1 && *path == '.') ? 0 : ENOTDIR;
Marko Mikulicic 0:c0ecb8bf28eb 9798 }
Marko Mikulicic 0:c0ecb8bf28eb 9799
Marko Mikulicic 0:c0ecb8bf28eb 9800 #endif /* CS_ENABLE_SPIFFS */
Marko Mikulicic 0:c0ecb8bf28eb 9801
Marko Mikulicic 0:c0ecb8bf28eb 9802 #endif /* EXCLUDE_COMMON */
Marko Mikulicic 0:c0ecb8bf28eb 9803
Marko Mikulicic 0:c0ecb8bf28eb 9804 /* ISO C requires a translation unit to contain at least one declaration */
Marko Mikulicic 0:c0ecb8bf28eb 9805 typedef int cs_dirent_dummy;
Marko Mikulicic 0:c0ecb8bf28eb 9806 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 9807 #line 1 "common/cs_file.c"
Marko Mikulicic 0:c0ecb8bf28eb 9808 #endif
Marko Mikulicic 0:c0ecb8bf28eb 9809 /*
Marko Mikulicic 0:c0ecb8bf28eb 9810 * Copyright (c) 2015 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 9811 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 9812 */
Marko Mikulicic 0:c0ecb8bf28eb 9813
Marko Mikulicic 0:c0ecb8bf28eb 9814 /* Amalgamated: #include "common/cs_file.h" */
Marko Mikulicic 0:c0ecb8bf28eb 9815
Marko Mikulicic 0:c0ecb8bf28eb 9816 #include <stdio.h>
Marko Mikulicic 0:c0ecb8bf28eb 9817 #include <stdlib.h>
Marko Mikulicic 0:c0ecb8bf28eb 9818
Marko Mikulicic 0:c0ecb8bf28eb 9819 #ifdef CS_MMAP
Marko Mikulicic 0:c0ecb8bf28eb 9820 #include <fcntl.h>
Marko Mikulicic 0:c0ecb8bf28eb 9821 #include <sys/mman.h>
Marko Mikulicic 0:c0ecb8bf28eb 9822 #include <sys/stat.h>
Marko Mikulicic 0:c0ecb8bf28eb 9823 #endif
Marko Mikulicic 0:c0ecb8bf28eb 9824
Marko Mikulicic 0:c0ecb8bf28eb 9825 #ifndef EXCLUDE_COMMON
Marko Mikulicic 0:c0ecb8bf28eb 9826 char *cs_read_file(const char *path, size_t *size) {
Marko Mikulicic 0:c0ecb8bf28eb 9827 FILE *fp;
Marko Mikulicic 0:c0ecb8bf28eb 9828 char *data = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 9829 if ((fp = fopen(path, "rb")) == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 9830 } else if (fseek(fp, 0, SEEK_END) != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 9831 fclose(fp);
Marko Mikulicic 0:c0ecb8bf28eb 9832 } else {
Marko Mikulicic 0:c0ecb8bf28eb 9833 *size = ftell(fp);
Marko Mikulicic 0:c0ecb8bf28eb 9834 data = (char *) malloc(*size + 1);
Marko Mikulicic 0:c0ecb8bf28eb 9835 if (data != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 9836 fseek(fp, 0, SEEK_SET); /* Some platforms might not have rewind(), Oo */
Marko Mikulicic 0:c0ecb8bf28eb 9837 if (fread(data, 1, *size, fp) != *size) {
Marko Mikulicic 0:c0ecb8bf28eb 9838 free(data);
Marko Mikulicic 0:c0ecb8bf28eb 9839 return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 9840 }
Marko Mikulicic 0:c0ecb8bf28eb 9841 data[*size] = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 9842 }
Marko Mikulicic 0:c0ecb8bf28eb 9843 fclose(fp);
Marko Mikulicic 0:c0ecb8bf28eb 9844 }
Marko Mikulicic 0:c0ecb8bf28eb 9845 return data;
Marko Mikulicic 0:c0ecb8bf28eb 9846 }
Marko Mikulicic 0:c0ecb8bf28eb 9847 #endif /* EXCLUDE_COMMON */
Marko Mikulicic 0:c0ecb8bf28eb 9848
Marko Mikulicic 0:c0ecb8bf28eb 9849 #ifdef CS_MMAP
Marko Mikulicic 0:c0ecb8bf28eb 9850 char *cs_mmap_file(const char *path, size_t *size) {
Marko Mikulicic 0:c0ecb8bf28eb 9851 char *r;
Marko Mikulicic 0:c0ecb8bf28eb 9852 int fd = open(path, O_RDONLY);
Marko Mikulicic 0:c0ecb8bf28eb 9853 struct stat st;
Marko Mikulicic 0:c0ecb8bf28eb 9854 if (fd == -1) return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 9855 fstat(fd, &st);
Marko Mikulicic 0:c0ecb8bf28eb 9856 *size = (size_t) st.st_size;
Marko Mikulicic 0:c0ecb8bf28eb 9857 r = (char *) mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
Marko Mikulicic 0:c0ecb8bf28eb 9858 if (r == MAP_FAILED) return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 9859 return r;
Marko Mikulicic 0:c0ecb8bf28eb 9860 }
Marko Mikulicic 0:c0ecb8bf28eb 9861 #endif
Marko Mikulicic 0:c0ecb8bf28eb 9862 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 9863 #line 1 "common/cs_strtod.c"
Marko Mikulicic 0:c0ecb8bf28eb 9864 #endif
Marko Mikulicic 0:c0ecb8bf28eb 9865 #include <ctype.h>
Marko Mikulicic 0:c0ecb8bf28eb 9866 #include <math.h>
Marko Mikulicic 0:c0ecb8bf28eb 9867
Marko Mikulicic 0:c0ecb8bf28eb 9868 #include <stdlib.h>
Marko Mikulicic 0:c0ecb8bf28eb 9869
Marko Mikulicic 0:c0ecb8bf28eb 9870 int cs_strncasecmp(const char *s1, const char *s2, size_t n) {
Marko Mikulicic 0:c0ecb8bf28eb 9871 if (n == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 9872 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 9873 }
Marko Mikulicic 0:c0ecb8bf28eb 9874
Marko Mikulicic 0:c0ecb8bf28eb 9875 while (n-- != 0 && tolower((int) *s1) == tolower((int) *s2)) {
Marko Mikulicic 0:c0ecb8bf28eb 9876 if (n == 0 || *s1 == '\0' || *s2 == '\0') {
Marko Mikulicic 0:c0ecb8bf28eb 9877 break;
Marko Mikulicic 0:c0ecb8bf28eb 9878 }
Marko Mikulicic 0:c0ecb8bf28eb 9879 s1++;
Marko Mikulicic 0:c0ecb8bf28eb 9880 s2++;
Marko Mikulicic 0:c0ecb8bf28eb 9881 }
Marko Mikulicic 0:c0ecb8bf28eb 9882
Marko Mikulicic 0:c0ecb8bf28eb 9883 return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2);
Marko Mikulicic 0:c0ecb8bf28eb 9884 }
Marko Mikulicic 0:c0ecb8bf28eb 9885
Marko Mikulicic 0:c0ecb8bf28eb 9886 /*
Marko Mikulicic 0:c0ecb8bf28eb 9887 * based on Source:
Marko Mikulicic 0:c0ecb8bf28eb 9888 * https://github.com/anakod/Sming/blob/master/Sming/system/stringconversion.cpp#L93
Marko Mikulicic 0:c0ecb8bf28eb 9889 */
Marko Mikulicic 0:c0ecb8bf28eb 9890
Marko Mikulicic 0:c0ecb8bf28eb 9891 double cs_strtod(const char *str, char **endptr) {
Marko Mikulicic 0:c0ecb8bf28eb 9892 double result = 0.0;
Marko Mikulicic 0:c0ecb8bf28eb 9893 char c;
Marko Mikulicic 0:c0ecb8bf28eb 9894 const char *str_start;
Marko Mikulicic 0:c0ecb8bf28eb 9895 struct {
Marko Mikulicic 0:c0ecb8bf28eb 9896 unsigned neg : 1; /* result is negative */
Marko Mikulicic 0:c0ecb8bf28eb 9897 unsigned decimals : 1; /* parsing decimal part */
Marko Mikulicic 0:c0ecb8bf28eb 9898 unsigned is_exp : 1; /* parsing exponent like e+5 */
Marko Mikulicic 0:c0ecb8bf28eb 9899 unsigned is_exp_neg : 1; /* exponent is negative */
Marko Mikulicic 0:c0ecb8bf28eb 9900 } flags = {0, 0, 0, 0};
Marko Mikulicic 0:c0ecb8bf28eb 9901
Marko Mikulicic 0:c0ecb8bf28eb 9902 while (isspace((int) *str)) {
Marko Mikulicic 0:c0ecb8bf28eb 9903 str++;
Marko Mikulicic 0:c0ecb8bf28eb 9904 }
Marko Mikulicic 0:c0ecb8bf28eb 9905
Marko Mikulicic 0:c0ecb8bf28eb 9906 if (*str == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 9907 /* only space in str? */
Marko Mikulicic 0:c0ecb8bf28eb 9908 if (endptr != 0) *endptr = (char *) str;
Marko Mikulicic 0:c0ecb8bf28eb 9909 return result;
Marko Mikulicic 0:c0ecb8bf28eb 9910 }
Marko Mikulicic 0:c0ecb8bf28eb 9911
Marko Mikulicic 0:c0ecb8bf28eb 9912 /* Handle leading plus/minus signs */
Marko Mikulicic 0:c0ecb8bf28eb 9913 while (*str == '-' || *str == '+') {
Marko Mikulicic 0:c0ecb8bf28eb 9914 if (*str == '-') {
Marko Mikulicic 0:c0ecb8bf28eb 9915 flags.neg = !flags.neg;
Marko Mikulicic 0:c0ecb8bf28eb 9916 }
Marko Mikulicic 0:c0ecb8bf28eb 9917 str++;
Marko Mikulicic 0:c0ecb8bf28eb 9918 }
Marko Mikulicic 0:c0ecb8bf28eb 9919
Marko Mikulicic 0:c0ecb8bf28eb 9920 if (cs_strncasecmp(str, "NaN", 3) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 9921 if (endptr != 0) *endptr = (char *) str + 3;
Marko Mikulicic 0:c0ecb8bf28eb 9922 return NAN;
Marko Mikulicic 0:c0ecb8bf28eb 9923 }
Marko Mikulicic 0:c0ecb8bf28eb 9924
Marko Mikulicic 0:c0ecb8bf28eb 9925 if (cs_strncasecmp(str, "INF", 3) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 9926 str += 3;
Marko Mikulicic 0:c0ecb8bf28eb 9927 if (cs_strncasecmp(str, "INITY", 5) == 0) str += 5;
Marko Mikulicic 0:c0ecb8bf28eb 9928 if (endptr != 0) *endptr = (char *) str;
Marko Mikulicic 0:c0ecb8bf28eb 9929 return flags.neg ? -INFINITY : INFINITY;
Marko Mikulicic 0:c0ecb8bf28eb 9930 }
Marko Mikulicic 0:c0ecb8bf28eb 9931
Marko Mikulicic 0:c0ecb8bf28eb 9932 str_start = str;
Marko Mikulicic 0:c0ecb8bf28eb 9933
Marko Mikulicic 0:c0ecb8bf28eb 9934 if (*str == '0' && (*(str + 1) == 'x' || *(str + 1) == 'X')) {
Marko Mikulicic 0:c0ecb8bf28eb 9935 /* base 16 */
Marko Mikulicic 0:c0ecb8bf28eb 9936 str += 2;
Marko Mikulicic 0:c0ecb8bf28eb 9937 while ((c = tolower((int) *str))) {
Marko Mikulicic 0:c0ecb8bf28eb 9938 int d;
Marko Mikulicic 0:c0ecb8bf28eb 9939 if (c >= '0' && c <= '9') {
Marko Mikulicic 0:c0ecb8bf28eb 9940 d = c - '0';
Marko Mikulicic 0:c0ecb8bf28eb 9941 } else if (c >= 'a' && c <= 'f') {
Marko Mikulicic 0:c0ecb8bf28eb 9942 d = 10 + (c - 'a');
Marko Mikulicic 0:c0ecb8bf28eb 9943 } else {
Marko Mikulicic 0:c0ecb8bf28eb 9944 break;
Marko Mikulicic 0:c0ecb8bf28eb 9945 }
Marko Mikulicic 0:c0ecb8bf28eb 9946 result = 16 * result + d;
Marko Mikulicic 0:c0ecb8bf28eb 9947 str++;
Marko Mikulicic 0:c0ecb8bf28eb 9948 }
Marko Mikulicic 0:c0ecb8bf28eb 9949 } else if (*str == '0' && (*(str + 1) == 'b' || *(str + 1) == 'B')) {
Marko Mikulicic 0:c0ecb8bf28eb 9950 /* base 2 */
Marko Mikulicic 0:c0ecb8bf28eb 9951 str += 2;
Marko Mikulicic 0:c0ecb8bf28eb 9952 while ((c = *str)) {
Marko Mikulicic 0:c0ecb8bf28eb 9953 int d = c - '0';
Marko Mikulicic 0:c0ecb8bf28eb 9954 if (c != '0' && c != '1') break;
Marko Mikulicic 0:c0ecb8bf28eb 9955 result = 2 * result + d;
Marko Mikulicic 0:c0ecb8bf28eb 9956 str++;
Marko Mikulicic 0:c0ecb8bf28eb 9957 }
Marko Mikulicic 0:c0ecb8bf28eb 9958 } else if (*str == '0' && *(str + 1) >= '0' && *(str + 1) <= '7') {
Marko Mikulicic 0:c0ecb8bf28eb 9959 /* base 8 */
Marko Mikulicic 0:c0ecb8bf28eb 9960 while ((c = *str)) {
Marko Mikulicic 0:c0ecb8bf28eb 9961 int d = c - '0';
Marko Mikulicic 0:c0ecb8bf28eb 9962 if (c < '0' || c > '7') {
Marko Mikulicic 0:c0ecb8bf28eb 9963 /* fallback to base 10 */
Marko Mikulicic 0:c0ecb8bf28eb 9964 str = str_start;
Marko Mikulicic 0:c0ecb8bf28eb 9965 break;
Marko Mikulicic 0:c0ecb8bf28eb 9966 }
Marko Mikulicic 0:c0ecb8bf28eb 9967 result = 8 * result + d;
Marko Mikulicic 0:c0ecb8bf28eb 9968 str++;
Marko Mikulicic 0:c0ecb8bf28eb 9969 }
Marko Mikulicic 0:c0ecb8bf28eb 9970 }
Marko Mikulicic 0:c0ecb8bf28eb 9971
Marko Mikulicic 0:c0ecb8bf28eb 9972 if (str == str_start) {
Marko Mikulicic 0:c0ecb8bf28eb 9973 /* base 10 */
Marko Mikulicic 0:c0ecb8bf28eb 9974
Marko Mikulicic 0:c0ecb8bf28eb 9975 /* exponent specified explicitly, like in 3e-5, exponent is -5 */
Marko Mikulicic 0:c0ecb8bf28eb 9976 int exp = 0;
Marko Mikulicic 0:c0ecb8bf28eb 9977 /* exponent calculated from dot, like in 1.23, exponent is -2 */
Marko Mikulicic 0:c0ecb8bf28eb 9978 int exp_dot = 0;
Marko Mikulicic 0:c0ecb8bf28eb 9979
Marko Mikulicic 0:c0ecb8bf28eb 9980 result = 0;
Marko Mikulicic 0:c0ecb8bf28eb 9981
Marko Mikulicic 0:c0ecb8bf28eb 9982 while ((c = *str)) {
Marko Mikulicic 0:c0ecb8bf28eb 9983 int d;
Marko Mikulicic 0:c0ecb8bf28eb 9984
Marko Mikulicic 0:c0ecb8bf28eb 9985 if (c == '.') {
Marko Mikulicic 0:c0ecb8bf28eb 9986 if (!flags.decimals) {
Marko Mikulicic 0:c0ecb8bf28eb 9987 /* going to parse decimal part */
Marko Mikulicic 0:c0ecb8bf28eb 9988 flags.decimals = 1;
Marko Mikulicic 0:c0ecb8bf28eb 9989 str++;
Marko Mikulicic 0:c0ecb8bf28eb 9990 continue;
Marko Mikulicic 0:c0ecb8bf28eb 9991 } else {
Marko Mikulicic 0:c0ecb8bf28eb 9992 /* non-expected dot: assume number data is over */
Marko Mikulicic 0:c0ecb8bf28eb 9993 break;
Marko Mikulicic 0:c0ecb8bf28eb 9994 }
Marko Mikulicic 0:c0ecb8bf28eb 9995 } else if (c == 'e' || c == 'E') {
Marko Mikulicic 0:c0ecb8bf28eb 9996 /* going to parse exponent part */
Marko Mikulicic 0:c0ecb8bf28eb 9997 flags.is_exp = 1;
Marko Mikulicic 0:c0ecb8bf28eb 9998 str++;
Marko Mikulicic 0:c0ecb8bf28eb 9999 c = *str;
Marko Mikulicic 0:c0ecb8bf28eb 10000
Marko Mikulicic 0:c0ecb8bf28eb 10001 /* check sign of the exponent */
Marko Mikulicic 0:c0ecb8bf28eb 10002 if (c == '-' || c == '+') {
Marko Mikulicic 0:c0ecb8bf28eb 10003 if (c == '-') {
Marko Mikulicic 0:c0ecb8bf28eb 10004 flags.is_exp_neg = 1;
Marko Mikulicic 0:c0ecb8bf28eb 10005 }
Marko Mikulicic 0:c0ecb8bf28eb 10006 str++;
Marko Mikulicic 0:c0ecb8bf28eb 10007 }
Marko Mikulicic 0:c0ecb8bf28eb 10008
Marko Mikulicic 0:c0ecb8bf28eb 10009 continue;
Marko Mikulicic 0:c0ecb8bf28eb 10010 }
Marko Mikulicic 0:c0ecb8bf28eb 10011
Marko Mikulicic 0:c0ecb8bf28eb 10012 d = c - '0';
Marko Mikulicic 0:c0ecb8bf28eb 10013 if (d < 0 || d > 9) {
Marko Mikulicic 0:c0ecb8bf28eb 10014 break;
Marko Mikulicic 0:c0ecb8bf28eb 10015 }
Marko Mikulicic 0:c0ecb8bf28eb 10016
Marko Mikulicic 0:c0ecb8bf28eb 10017 if (!flags.is_exp) {
Marko Mikulicic 0:c0ecb8bf28eb 10018 /* apply current digit to the result */
Marko Mikulicic 0:c0ecb8bf28eb 10019 result = 10 * result + d;
Marko Mikulicic 0:c0ecb8bf28eb 10020 if (flags.decimals) {
Marko Mikulicic 0:c0ecb8bf28eb 10021 exp_dot--;
Marko Mikulicic 0:c0ecb8bf28eb 10022 }
Marko Mikulicic 0:c0ecb8bf28eb 10023 } else {
Marko Mikulicic 0:c0ecb8bf28eb 10024 /* apply current digit to the exponent */
Marko Mikulicic 0:c0ecb8bf28eb 10025 if (flags.is_exp_neg) {
Marko Mikulicic 0:c0ecb8bf28eb 10026 if (exp > -1022) {
Marko Mikulicic 0:c0ecb8bf28eb 10027 exp = 10 * exp - d;
Marko Mikulicic 0:c0ecb8bf28eb 10028 }
Marko Mikulicic 0:c0ecb8bf28eb 10029 } else {
Marko Mikulicic 0:c0ecb8bf28eb 10030 if (exp < 1023) {
Marko Mikulicic 0:c0ecb8bf28eb 10031 exp = 10 * exp + d;
Marko Mikulicic 0:c0ecb8bf28eb 10032 }
Marko Mikulicic 0:c0ecb8bf28eb 10033 }
Marko Mikulicic 0:c0ecb8bf28eb 10034 }
Marko Mikulicic 0:c0ecb8bf28eb 10035
Marko Mikulicic 0:c0ecb8bf28eb 10036 str++;
Marko Mikulicic 0:c0ecb8bf28eb 10037 }
Marko Mikulicic 0:c0ecb8bf28eb 10038
Marko Mikulicic 0:c0ecb8bf28eb 10039 exp += exp_dot;
Marko Mikulicic 0:c0ecb8bf28eb 10040
Marko Mikulicic 0:c0ecb8bf28eb 10041 /*
Marko Mikulicic 0:c0ecb8bf28eb 10042 * TODO(dfrank): it probably makes sense not to adjust intermediate `double
Marko Mikulicic 0:c0ecb8bf28eb 10043 * result`, but build double number accordingly to IEEE 754 from taken
Marko Mikulicic 0:c0ecb8bf28eb 10044 * (integer) mantissa, exponent and sign. That would work faster, and we
Marko Mikulicic 0:c0ecb8bf28eb 10045 * can avoid any possible round errors.
Marko Mikulicic 0:c0ecb8bf28eb 10046 */
Marko Mikulicic 0:c0ecb8bf28eb 10047
Marko Mikulicic 0:c0ecb8bf28eb 10048 /* if exponent is non-zero, apply it */
Marko Mikulicic 0:c0ecb8bf28eb 10049 if (exp != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 10050 if (exp < 0) {
Marko Mikulicic 0:c0ecb8bf28eb 10051 while (exp++ != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 10052 result /= 10;
Marko Mikulicic 0:c0ecb8bf28eb 10053 }
Marko Mikulicic 0:c0ecb8bf28eb 10054 } else {
Marko Mikulicic 0:c0ecb8bf28eb 10055 while (exp-- != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 10056 result *= 10;
Marko Mikulicic 0:c0ecb8bf28eb 10057 }
Marko Mikulicic 0:c0ecb8bf28eb 10058 }
Marko Mikulicic 0:c0ecb8bf28eb 10059 }
Marko Mikulicic 0:c0ecb8bf28eb 10060 }
Marko Mikulicic 0:c0ecb8bf28eb 10061
Marko Mikulicic 0:c0ecb8bf28eb 10062 if (flags.neg) {
Marko Mikulicic 0:c0ecb8bf28eb 10063 result = -result;
Marko Mikulicic 0:c0ecb8bf28eb 10064 }
Marko Mikulicic 0:c0ecb8bf28eb 10065
Marko Mikulicic 0:c0ecb8bf28eb 10066 if (endptr != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 10067 *endptr = (char *) str;
Marko Mikulicic 0:c0ecb8bf28eb 10068 }
Marko Mikulicic 0:c0ecb8bf28eb 10069
Marko Mikulicic 0:c0ecb8bf28eb 10070 return result;
Marko Mikulicic 0:c0ecb8bf28eb 10071 }
Marko Mikulicic 0:c0ecb8bf28eb 10072 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 10073 #line 1 "common/coroutine.c"
Marko Mikulicic 0:c0ecb8bf28eb 10074 #endif
Marko Mikulicic 0:c0ecb8bf28eb 10075 /*
Marko Mikulicic 0:c0ecb8bf28eb 10076 * Copyright (c) 2015 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 10077 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 10078 */
Marko Mikulicic 0:c0ecb8bf28eb 10079
Marko Mikulicic 0:c0ecb8bf28eb 10080 /*
Marko Mikulicic 0:c0ecb8bf28eb 10081 * Module that provides generic macros and functions to implement "coroutines",
Marko Mikulicic 0:c0ecb8bf28eb 10082 * i.e. C code that uses `mbuf` as a stack for function calls.
Marko Mikulicic 0:c0ecb8bf28eb 10083 *
Marko Mikulicic 0:c0ecb8bf28eb 10084 * More info: see the design doc: https://goo.gl/kfcG61
Marko Mikulicic 0:c0ecb8bf28eb 10085 */
Marko Mikulicic 0:c0ecb8bf28eb 10086
Marko Mikulicic 0:c0ecb8bf28eb 10087 #include <string.h>
Marko Mikulicic 0:c0ecb8bf28eb 10088 #include <stdlib.h>
Marko Mikulicic 0:c0ecb8bf28eb 10089
Marko Mikulicic 0:c0ecb8bf28eb 10090 /* Amalgamated: #include "common/coroutine.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10091
Marko Mikulicic 0:c0ecb8bf28eb 10092 /*
Marko Mikulicic 0:c0ecb8bf28eb 10093 * Unwinds stack by 1 function. Used when we're returning from function and
Marko Mikulicic 0:c0ecb8bf28eb 10094 * when an exception is thrown.
Marko Mikulicic 0:c0ecb8bf28eb 10095 */
Marko Mikulicic 0:c0ecb8bf28eb 10096 static void _level_up(struct cr_ctx *p_ctx) {
Marko Mikulicic 0:c0ecb8bf28eb 10097 /* get size of current function's stack data */
Marko Mikulicic 0:c0ecb8bf28eb 10098 size_t locals_size = _CR_CURR_FUNC_LOCALS_SIZE(p_ctx);
Marko Mikulicic 0:c0ecb8bf28eb 10099
Marko Mikulicic 0:c0ecb8bf28eb 10100 /* check stacks underflow */
Marko Mikulicic 0:c0ecb8bf28eb 10101 if (_CR_STACK_FID_UND_CHECK(p_ctx, 1 /*fid*/)) {
Marko Mikulicic 0:c0ecb8bf28eb 10102 p_ctx->status = CR_RES__ERR_STACK_CALL_UNDERFLOW;
Marko Mikulicic 0:c0ecb8bf28eb 10103 return;
Marko Mikulicic 0:c0ecb8bf28eb 10104 } else if (_CR_STACK_DATA_UND_CHECK(p_ctx, locals_size)) {
Marko Mikulicic 0:c0ecb8bf28eb 10105 p_ctx->status = CR_RES__ERR_STACK_DATA_UNDERFLOW;
Marko Mikulicic 0:c0ecb8bf28eb 10106 return;
Marko Mikulicic 0:c0ecb8bf28eb 10107 }
Marko Mikulicic 0:c0ecb8bf28eb 10108
Marko Mikulicic 0:c0ecb8bf28eb 10109 /* decrement stacks */
Marko Mikulicic 0:c0ecb8bf28eb 10110 _CR_STACK_DATA_FREE(p_ctx, locals_size);
Marko Mikulicic 0:c0ecb8bf28eb 10111 _CR_STACK_FID_FREE(p_ctx, 1 /*fid*/);
Marko Mikulicic 0:c0ecb8bf28eb 10112 p_ctx->stack_ret.len = p_ctx->cur_fid_idx;
Marko Mikulicic 0:c0ecb8bf28eb 10113
Marko Mikulicic 0:c0ecb8bf28eb 10114 /* if we have exception marker here, adjust cur_fid_idx */
Marko Mikulicic 0:c0ecb8bf28eb 10115 while (CR_CURR_FUNC_C(p_ctx) == CR_FID__TRY_MARKER) {
Marko Mikulicic 0:c0ecb8bf28eb 10116 /* check for stack underflow */
Marko Mikulicic 0:c0ecb8bf28eb 10117 if (_CR_STACK_FID_UND_CHECK(p_ctx, _CR_TRY_SIZE)) {
Marko Mikulicic 0:c0ecb8bf28eb 10118 p_ctx->status = CR_RES__ERR_STACK_CALL_UNDERFLOW;
Marko Mikulicic 0:c0ecb8bf28eb 10119 return;
Marko Mikulicic 0:c0ecb8bf28eb 10120 }
Marko Mikulicic 0:c0ecb8bf28eb 10121 _CR_STACK_FID_FREE(p_ctx, _CR_TRY_SIZE);
Marko Mikulicic 0:c0ecb8bf28eb 10122 }
Marko Mikulicic 0:c0ecb8bf28eb 10123 }
Marko Mikulicic 0:c0ecb8bf28eb 10124
Marko Mikulicic 0:c0ecb8bf28eb 10125 enum cr_status cr_on_iter_begin(struct cr_ctx *p_ctx) {
Marko Mikulicic 0:c0ecb8bf28eb 10126 if (p_ctx->status != CR_RES__OK) {
Marko Mikulicic 0:c0ecb8bf28eb 10127 goto out;
Marko Mikulicic 0:c0ecb8bf28eb 10128 } else if (p_ctx->called_fid != CR_FID__NONE) {
Marko Mikulicic 0:c0ecb8bf28eb 10129 /* need to call new function */
Marko Mikulicic 0:c0ecb8bf28eb 10130
Marko Mikulicic 0:c0ecb8bf28eb 10131 size_t locals_size = p_ctx->p_func_descrs[p_ctx->called_fid].locals_size;
Marko Mikulicic 0:c0ecb8bf28eb 10132 /*
Marko Mikulicic 0:c0ecb8bf28eb 10133 * increment stack pointers
Marko Mikulicic 0:c0ecb8bf28eb 10134 */
Marko Mikulicic 0:c0ecb8bf28eb 10135 /* make sure this function has correct `struct cr_func_desc` entry */
Marko Mikulicic 0:c0ecb8bf28eb 10136 assert(locals_size == p_ctx->call_locals_size);
Marko Mikulicic 0:c0ecb8bf28eb 10137 /*
Marko Mikulicic 0:c0ecb8bf28eb 10138 * make sure we haven't mistakenly included "zero-sized" `.._arg_t`
Marko Mikulicic 0:c0ecb8bf28eb 10139 * structure in `.._locals_t` struct
Marko Mikulicic 0:c0ecb8bf28eb 10140 *
Marko Mikulicic 0:c0ecb8bf28eb 10141 * By "zero-sized" I mean `cr_zero_size_type_t`.
Marko Mikulicic 0:c0ecb8bf28eb 10142 */
Marko Mikulicic 0:c0ecb8bf28eb 10143 assert(locals_size < sizeof(cr_zero_size_type_t));
Marko Mikulicic 0:c0ecb8bf28eb 10144
Marko Mikulicic 0:c0ecb8bf28eb 10145 _CR_STACK_DATA_ALLOC(p_ctx, locals_size);
Marko Mikulicic 0:c0ecb8bf28eb 10146 _CR_STACK_RET_ALLOC(p_ctx, 1 /*fid*/);
Marko Mikulicic 0:c0ecb8bf28eb 10147 p_ctx->cur_fid_idx = p_ctx->stack_ret.len;
Marko Mikulicic 0:c0ecb8bf28eb 10148
Marko Mikulicic 0:c0ecb8bf28eb 10149 /* copy arguments to our "stack" (and advance locals stack pointer) */
Marko Mikulicic 0:c0ecb8bf28eb 10150 memcpy(p_ctx->stack_data.buf + p_ctx->stack_data.len - locals_size,
Marko Mikulicic 0:c0ecb8bf28eb 10151 p_ctx->p_arg_retval, p_ctx->call_arg_size);
Marko Mikulicic 0:c0ecb8bf28eb 10152
Marko Mikulicic 0:c0ecb8bf28eb 10153 /* set function id */
Marko Mikulicic 0:c0ecb8bf28eb 10154 CR_CURR_FUNC_C(p_ctx) = p_ctx->called_fid;
Marko Mikulicic 0:c0ecb8bf28eb 10155
Marko Mikulicic 0:c0ecb8bf28eb 10156 /* clear called_fid */
Marko Mikulicic 0:c0ecb8bf28eb 10157 p_ctx->called_fid = CR_FID__NONE;
Marko Mikulicic 0:c0ecb8bf28eb 10158
Marko Mikulicic 0:c0ecb8bf28eb 10159 } else if (p_ctx->need_return) {
Marko Mikulicic 0:c0ecb8bf28eb 10160 /* need to return from the currently running function */
Marko Mikulicic 0:c0ecb8bf28eb 10161
Marko Mikulicic 0:c0ecb8bf28eb 10162 _level_up(p_ctx);
Marko Mikulicic 0:c0ecb8bf28eb 10163 if (p_ctx->status != CR_RES__OK) {
Marko Mikulicic 0:c0ecb8bf28eb 10164 goto out;
Marko Mikulicic 0:c0ecb8bf28eb 10165 }
Marko Mikulicic 0:c0ecb8bf28eb 10166
Marko Mikulicic 0:c0ecb8bf28eb 10167 p_ctx->need_return = 0;
Marko Mikulicic 0:c0ecb8bf28eb 10168
Marko Mikulicic 0:c0ecb8bf28eb 10169 } else if (p_ctx->need_yield) {
Marko Mikulicic 0:c0ecb8bf28eb 10170 /* need to yield */
Marko Mikulicic 0:c0ecb8bf28eb 10171
Marko Mikulicic 0:c0ecb8bf28eb 10172 p_ctx->need_yield = 0;
Marko Mikulicic 0:c0ecb8bf28eb 10173 p_ctx->status = CR_RES__OK_YIELDED;
Marko Mikulicic 0:c0ecb8bf28eb 10174 goto out;
Marko Mikulicic 0:c0ecb8bf28eb 10175
Marko Mikulicic 0:c0ecb8bf28eb 10176 } else if (p_ctx->thrown_exc != CR_EXC_ID__NONE) {
Marko Mikulicic 0:c0ecb8bf28eb 10177 /* exception was thrown */
Marko Mikulicic 0:c0ecb8bf28eb 10178
Marko Mikulicic 0:c0ecb8bf28eb 10179 /* unwind stack until we reach the bottom, or find some try-catch blocks */
Marko Mikulicic 0:c0ecb8bf28eb 10180 do {
Marko Mikulicic 0:c0ecb8bf28eb 10181 _level_up(p_ctx);
Marko Mikulicic 0:c0ecb8bf28eb 10182 if (p_ctx->status != CR_RES__OK) {
Marko Mikulicic 0:c0ecb8bf28eb 10183 goto out;
Marko Mikulicic 0:c0ecb8bf28eb 10184 }
Marko Mikulicic 0:c0ecb8bf28eb 10185
Marko Mikulicic 0:c0ecb8bf28eb 10186 if (_CR_TRY_MARKER(p_ctx) == CR_FID__TRY_MARKER) {
Marko Mikulicic 0:c0ecb8bf28eb 10187 /* we have some try-catch here, go to the first catch */
Marko Mikulicic 0:c0ecb8bf28eb 10188 CR_CURR_FUNC_C(p_ctx) = _CR_TRY_CATCH_FID(p_ctx);
Marko Mikulicic 0:c0ecb8bf28eb 10189 break;
Marko Mikulicic 0:c0ecb8bf28eb 10190 } else if (CR_CURR_FUNC_C(p_ctx) == CR_FID__NONE) {
Marko Mikulicic 0:c0ecb8bf28eb 10191 /* we've reached the bottom of the stack */
Marko Mikulicic 0:c0ecb8bf28eb 10192 p_ctx->status = CR_RES__ERR_UNCAUGHT_EXCEPTION;
Marko Mikulicic 0:c0ecb8bf28eb 10193 break;
Marko Mikulicic 0:c0ecb8bf28eb 10194 }
Marko Mikulicic 0:c0ecb8bf28eb 10195
Marko Mikulicic 0:c0ecb8bf28eb 10196 } while (1);
Marko Mikulicic 0:c0ecb8bf28eb 10197 }
Marko Mikulicic 0:c0ecb8bf28eb 10198
Marko Mikulicic 0:c0ecb8bf28eb 10199 /* remember pointer to current function's locals */
Marko Mikulicic 0:c0ecb8bf28eb 10200 _CR_CUR_FUNC_LOCALS_UPD(p_ctx);
Marko Mikulicic 0:c0ecb8bf28eb 10201
Marko Mikulicic 0:c0ecb8bf28eb 10202 out:
Marko Mikulicic 0:c0ecb8bf28eb 10203 return p_ctx->status;
Marko Mikulicic 0:c0ecb8bf28eb 10204 }
Marko Mikulicic 0:c0ecb8bf28eb 10205
Marko Mikulicic 0:c0ecb8bf28eb 10206 void cr_context_init(struct cr_ctx *p_ctx, union user_arg_ret *p_arg_retval,
Marko Mikulicic 0:c0ecb8bf28eb 10207 size_t arg_retval_size,
Marko Mikulicic 0:c0ecb8bf28eb 10208 const struct cr_func_desc *p_func_descrs) {
Marko Mikulicic 0:c0ecb8bf28eb 10209 /*
Marko Mikulicic 0:c0ecb8bf28eb 10210 * make sure we haven't mistakenly included "zero-sized" `.._arg_t`
Marko Mikulicic 0:c0ecb8bf28eb 10211 * structure in `union user_arg_ret`.
Marko Mikulicic 0:c0ecb8bf28eb 10212 *
Marko Mikulicic 0:c0ecb8bf28eb 10213 * By "zero-sized" I mean `cr_zero_size_type_t`.
Marko Mikulicic 0:c0ecb8bf28eb 10214 */
Marko Mikulicic 0:c0ecb8bf28eb 10215 assert(arg_retval_size < sizeof(cr_zero_size_type_t));
Marko Mikulicic 0:c0ecb8bf28eb 10216 #ifdef NDEBUG
Marko Mikulicic 0:c0ecb8bf28eb 10217 (void) arg_retval_size;
Marko Mikulicic 0:c0ecb8bf28eb 10218 #endif
Marko Mikulicic 0:c0ecb8bf28eb 10219
Marko Mikulicic 0:c0ecb8bf28eb 10220 memset(p_ctx, 0x00, sizeof(*p_ctx));
Marko Mikulicic 0:c0ecb8bf28eb 10221
Marko Mikulicic 0:c0ecb8bf28eb 10222 p_ctx->p_func_descrs = p_func_descrs;
Marko Mikulicic 0:c0ecb8bf28eb 10223 p_ctx->p_arg_retval = p_arg_retval;
Marko Mikulicic 0:c0ecb8bf28eb 10224
Marko Mikulicic 0:c0ecb8bf28eb 10225 mbuf_init(&p_ctx->stack_data, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10226 mbuf_init(&p_ctx->stack_ret, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10227
Marko Mikulicic 0:c0ecb8bf28eb 10228 mbuf_append(&p_ctx->stack_ret, NULL, 1 /*starting byte for CR_FID__NONE*/);
Marko Mikulicic 0:c0ecb8bf28eb 10229 p_ctx->cur_fid_idx = p_ctx->stack_ret.len;
Marko Mikulicic 0:c0ecb8bf28eb 10230
Marko Mikulicic 0:c0ecb8bf28eb 10231 _CR_CALL_PREPARE(p_ctx, CR_FID__NONE, 0, 0, CR_FID__NONE);
Marko Mikulicic 0:c0ecb8bf28eb 10232 }
Marko Mikulicic 0:c0ecb8bf28eb 10233
Marko Mikulicic 0:c0ecb8bf28eb 10234 void cr_context_free(struct cr_ctx *p_ctx) {
Marko Mikulicic 0:c0ecb8bf28eb 10235 mbuf_free(&p_ctx->stack_data);
Marko Mikulicic 0:c0ecb8bf28eb 10236 mbuf_free(&p_ctx->stack_ret);
Marko Mikulicic 0:c0ecb8bf28eb 10237 }
Marko Mikulicic 0:c0ecb8bf28eb 10238 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 10239 #line 1 "v7/builtin/file.c"
Marko Mikulicic 0:c0ecb8bf28eb 10240 #endif
Marko Mikulicic 0:c0ecb8bf28eb 10241 /*
Marko Mikulicic 0:c0ecb8bf28eb 10242 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 10243 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 10244 */
Marko Mikulicic 0:c0ecb8bf28eb 10245
Marko Mikulicic 0:c0ecb8bf28eb 10246 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10247 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10248 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10249 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10250 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10251 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10252 /* Amalgamated: #include "v7/src/exec.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10253 /* Amalgamated: #include "v7/src/array.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10254 /* Amalgamated: #include "common/mbuf.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10255 /* Amalgamated: #include "common/cs_file.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10256 /* Amalgamated: #include "v7/src/v7_features.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10257 /* Amalgamated: #include "common/cs_dirent.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10258
Marko Mikulicic 0:c0ecb8bf28eb 10259 #if defined(V7_ENABLE_FILE) && !defined(V7_NO_FS)
Marko Mikulicic 0:c0ecb8bf28eb 10260
Marko Mikulicic 0:c0ecb8bf28eb 10261 static const char s_fd_prop[] = "__fd";
Marko Mikulicic 0:c0ecb8bf28eb 10262
Marko Mikulicic 0:c0ecb8bf28eb 10263 #ifndef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 10264 static FILE *v7_val_to_file(struct v7 *v7, v7_val_t val) {
Marko Mikulicic 0:c0ecb8bf28eb 10265 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 10266 return (FILE *) v7_get_ptr(v7, val);
Marko Mikulicic 0:c0ecb8bf28eb 10267 }
Marko Mikulicic 0:c0ecb8bf28eb 10268
Marko Mikulicic 0:c0ecb8bf28eb 10269 static v7_val_t v7_file_to_val(struct v7 *v7, FILE *file) {
Marko Mikulicic 0:c0ecb8bf28eb 10270 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 10271 return v7_mk_foreign(v7, file);
Marko Mikulicic 0:c0ecb8bf28eb 10272 }
Marko Mikulicic 0:c0ecb8bf28eb 10273
Marko Mikulicic 0:c0ecb8bf28eb 10274 static int v7_is_file_type(v7_val_t val) {
Marko Mikulicic 0:c0ecb8bf28eb 10275 return v7_is_foreign(val);
Marko Mikulicic 0:c0ecb8bf28eb 10276 }
Marko Mikulicic 0:c0ecb8bf28eb 10277 #else
Marko Mikulicic 0:c0ecb8bf28eb 10278 FILE *v7_val_to_file(struct v7 *v7, v7_val_t val);
Marko Mikulicic 0:c0ecb8bf28eb 10279 v7_val_t v7_file_to_val(struct v7 *v7, FILE *file);
Marko Mikulicic 0:c0ecb8bf28eb 10280 int v7_is_file_type(v7_val_t val);
Marko Mikulicic 0:c0ecb8bf28eb 10281 #endif
Marko Mikulicic 0:c0ecb8bf28eb 10282
Marko Mikulicic 0:c0ecb8bf28eb 10283 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10284 V7_PRIVATE enum v7_err File_eval(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10285 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10286 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10287
Marko Mikulicic 0:c0ecb8bf28eb 10288 *res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 10289
Marko Mikulicic 0:c0ecb8bf28eb 10290 if (v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 10291 const char *s = v7_get_cstring(v7, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 10292 if (s == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 10293 rcode = v7_throwf(v7, "TypeError", "Invalid string");
Marko Mikulicic 0:c0ecb8bf28eb 10294 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 10295 }
Marko Mikulicic 0:c0ecb8bf28eb 10296
Marko Mikulicic 0:c0ecb8bf28eb 10297 v7_set_gc_enabled(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 10298 rcode = v7_exec_file(v7, s, res);
Marko Mikulicic 0:c0ecb8bf28eb 10299 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 10300 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 10301 }
Marko Mikulicic 0:c0ecb8bf28eb 10302 }
Marko Mikulicic 0:c0ecb8bf28eb 10303
Marko Mikulicic 0:c0ecb8bf28eb 10304 clean:
Marko Mikulicic 0:c0ecb8bf28eb 10305 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10306 }
Marko Mikulicic 0:c0ecb8bf28eb 10307
Marko Mikulicic 0:c0ecb8bf28eb 10308 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10309 V7_PRIVATE enum v7_err File_exists(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10310 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10311 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10312
Marko Mikulicic 0:c0ecb8bf28eb 10313 *res = v7_mk_boolean(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10314
Marko Mikulicic 0:c0ecb8bf28eb 10315 if (v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 10316 const char *fname = v7_get_cstring(v7, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 10317 if (fname != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 10318 struct stat st;
Marko Mikulicic 0:c0ecb8bf28eb 10319 if (stat(fname, &st) == 0) *res = v7_mk_boolean(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 10320 }
Marko Mikulicic 0:c0ecb8bf28eb 10321 }
Marko Mikulicic 0:c0ecb8bf28eb 10322
Marko Mikulicic 0:c0ecb8bf28eb 10323 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10324 }
Marko Mikulicic 0:c0ecb8bf28eb 10325
Marko Mikulicic 0:c0ecb8bf28eb 10326 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10327 static enum v7_err f_read(struct v7 *v7, int all, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10328 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10329 v7_val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 10330 v7_val_t arg0 = v7_get(v7, this_obj, s_fd_prop, sizeof(s_fd_prop) - 1);
Marko Mikulicic 0:c0ecb8bf28eb 10331
Marko Mikulicic 0:c0ecb8bf28eb 10332 if (v7_is_file_type(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 10333 struct mbuf m;
Marko Mikulicic 0:c0ecb8bf28eb 10334 char buf[BUFSIZ];
Marko Mikulicic 0:c0ecb8bf28eb 10335 int n;
Marko Mikulicic 0:c0ecb8bf28eb 10336 FILE *fp = v7_val_to_file(v7, arg0);
Marko Mikulicic 0:c0ecb8bf28eb 10337
Marko Mikulicic 0:c0ecb8bf28eb 10338 /* Read file contents into mbuf */
Marko Mikulicic 0:c0ecb8bf28eb 10339 mbuf_init(&m, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10340 while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 10341 mbuf_append(&m, buf, n);
Marko Mikulicic 0:c0ecb8bf28eb 10342 if (!all) {
Marko Mikulicic 0:c0ecb8bf28eb 10343 break;
Marko Mikulicic 0:c0ecb8bf28eb 10344 }
Marko Mikulicic 0:c0ecb8bf28eb 10345 }
Marko Mikulicic 0:c0ecb8bf28eb 10346
Marko Mikulicic 0:c0ecb8bf28eb 10347 if (m.len > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 10348 *res = v7_mk_string(v7, m.buf, m.len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 10349 mbuf_free(&m);
Marko Mikulicic 0:c0ecb8bf28eb 10350 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 10351 }
Marko Mikulicic 0:c0ecb8bf28eb 10352 }
Marko Mikulicic 0:c0ecb8bf28eb 10353 *res = v7_mk_string(v7, "", 0, 1);
Marko Mikulicic 0:c0ecb8bf28eb 10354
Marko Mikulicic 0:c0ecb8bf28eb 10355 clean:
Marko Mikulicic 0:c0ecb8bf28eb 10356 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10357 }
Marko Mikulicic 0:c0ecb8bf28eb 10358
Marko Mikulicic 0:c0ecb8bf28eb 10359 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10360 V7_PRIVATE enum v7_err File_obj_read(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10361 return f_read(v7, 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 10362 }
Marko Mikulicic 0:c0ecb8bf28eb 10363
Marko Mikulicic 0:c0ecb8bf28eb 10364 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10365 V7_PRIVATE enum v7_err File_obj_write(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10366 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10367 v7_val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 10368 v7_val_t arg0 = v7_get(v7, this_obj, s_fd_prop, sizeof(s_fd_prop) - 1);
Marko Mikulicic 0:c0ecb8bf28eb 10369 v7_val_t arg1 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10370 size_t n, sent = 0, len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 10371
Marko Mikulicic 0:c0ecb8bf28eb 10372 if (v7_is_file_type(arg0) && v7_is_string(arg1)) {
Marko Mikulicic 0:c0ecb8bf28eb 10373 const char *s = v7_get_string(v7, &arg1, &len);
Marko Mikulicic 0:c0ecb8bf28eb 10374 FILE *fp = v7_val_to_file(v7, arg0);
Marko Mikulicic 0:c0ecb8bf28eb 10375 while (sent < len && (n = fwrite(s + sent, 1, len - sent, fp)) > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 10376 sent += n;
Marko Mikulicic 0:c0ecb8bf28eb 10377 }
Marko Mikulicic 0:c0ecb8bf28eb 10378 }
Marko Mikulicic 0:c0ecb8bf28eb 10379
Marko Mikulicic 0:c0ecb8bf28eb 10380 *res = v7_mk_number(v7, sent);
Marko Mikulicic 0:c0ecb8bf28eb 10381
Marko Mikulicic 0:c0ecb8bf28eb 10382 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10383 }
Marko Mikulicic 0:c0ecb8bf28eb 10384
Marko Mikulicic 0:c0ecb8bf28eb 10385 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10386 V7_PRIVATE enum v7_err File_obj_close(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10387 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10388 v7_val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 10389 v7_val_t prop = v7_get(v7, this_obj, s_fd_prop, sizeof(s_fd_prop) - 1);
Marko Mikulicic 0:c0ecb8bf28eb 10390 int ires = -1;
Marko Mikulicic 0:c0ecb8bf28eb 10391
Marko Mikulicic 0:c0ecb8bf28eb 10392 if (v7_is_file_type(prop)) {
Marko Mikulicic 0:c0ecb8bf28eb 10393 ires = fclose(v7_val_to_file(v7, prop));
Marko Mikulicic 0:c0ecb8bf28eb 10394 }
Marko Mikulicic 0:c0ecb8bf28eb 10395
Marko Mikulicic 0:c0ecb8bf28eb 10396 *res = v7_mk_number(v7, ires);
Marko Mikulicic 0:c0ecb8bf28eb 10397
Marko Mikulicic 0:c0ecb8bf28eb 10398 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10399 }
Marko Mikulicic 0:c0ecb8bf28eb 10400
Marko Mikulicic 0:c0ecb8bf28eb 10401 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10402 V7_PRIVATE enum v7_err File_open(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10403 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10404 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10405 v7_val_t arg1 = v7_arg(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 10406 FILE *fp = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 10407
Marko Mikulicic 0:c0ecb8bf28eb 10408 if (v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 10409 const char *s1 = v7_get_cstring(v7, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 10410 const char *s2 = "rb"; /* Open files in read mode by default */
Marko Mikulicic 0:c0ecb8bf28eb 10411
Marko Mikulicic 0:c0ecb8bf28eb 10412 if (v7_is_string(arg1)) {
Marko Mikulicic 0:c0ecb8bf28eb 10413 s2 = v7_get_cstring(v7, &arg1);
Marko Mikulicic 0:c0ecb8bf28eb 10414 }
Marko Mikulicic 0:c0ecb8bf28eb 10415
Marko Mikulicic 0:c0ecb8bf28eb 10416 if (s1 == NULL || s2 == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 10417 *res = V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 10418 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 10419 }
Marko Mikulicic 0:c0ecb8bf28eb 10420
Marko Mikulicic 0:c0ecb8bf28eb 10421 fp = fopen(s1, s2);
Marko Mikulicic 0:c0ecb8bf28eb 10422 if (fp != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 10423 v7_val_t obj = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 10424 v7_val_t file_proto = v7_get(
Marko Mikulicic 0:c0ecb8bf28eb 10425 v7, v7_get(v7, v7_get_global(v7), "File", ~0), "prototype", ~0);
Marko Mikulicic 0:c0ecb8bf28eb 10426 v7_set_proto(v7, obj, file_proto);
Marko Mikulicic 0:c0ecb8bf28eb 10427 v7_def(v7, obj, s_fd_prop, sizeof(s_fd_prop) - 1, V7_DESC_ENUMERABLE(0),
Marko Mikulicic 0:c0ecb8bf28eb 10428 v7_file_to_val(v7, fp));
Marko Mikulicic 0:c0ecb8bf28eb 10429 *res = obj;
Marko Mikulicic 0:c0ecb8bf28eb 10430 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 10431 }
Marko Mikulicic 0:c0ecb8bf28eb 10432 }
Marko Mikulicic 0:c0ecb8bf28eb 10433
Marko Mikulicic 0:c0ecb8bf28eb 10434 *res = V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 10435
Marko Mikulicic 0:c0ecb8bf28eb 10436 clean:
Marko Mikulicic 0:c0ecb8bf28eb 10437 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10438 }
Marko Mikulicic 0:c0ecb8bf28eb 10439
Marko Mikulicic 0:c0ecb8bf28eb 10440 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10441 V7_PRIVATE enum v7_err File_read(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10442 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10443
Marko Mikulicic 0:c0ecb8bf28eb 10444 if (v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 10445 const char *path = v7_get_cstring(v7, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 10446 size_t size = 0;
Marko Mikulicic 0:c0ecb8bf28eb 10447 char *data = cs_read_file(path, &size);
Marko Mikulicic 0:c0ecb8bf28eb 10448 if (data != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 10449 *res = v7_mk_string(v7, data, size, 1);
Marko Mikulicic 0:c0ecb8bf28eb 10450 free(data);
Marko Mikulicic 0:c0ecb8bf28eb 10451 }
Marko Mikulicic 0:c0ecb8bf28eb 10452 }
Marko Mikulicic 0:c0ecb8bf28eb 10453
Marko Mikulicic 0:c0ecb8bf28eb 10454 return V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10455 }
Marko Mikulicic 0:c0ecb8bf28eb 10456
Marko Mikulicic 0:c0ecb8bf28eb 10457 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10458 V7_PRIVATE enum v7_err File_write(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10459 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10460 v7_val_t arg1 = v7_arg(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 10461 *res = v7_mk_boolean(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10462
Marko Mikulicic 0:c0ecb8bf28eb 10463 if (v7_is_string(arg0) && v7_is_string(arg1)) {
Marko Mikulicic 0:c0ecb8bf28eb 10464 const char *path = v7_get_cstring(v7, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 10465 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 10466 const char *buf = v7_get_string(v7, &arg1, &len);
Marko Mikulicic 0:c0ecb8bf28eb 10467 FILE *fp = fopen(path, "wb+");
Marko Mikulicic 0:c0ecb8bf28eb 10468 if (fp != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 10469 if (fwrite(buf, 1, len, fp) == len) {
Marko Mikulicic 0:c0ecb8bf28eb 10470 *res = v7_mk_boolean(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 10471 }
Marko Mikulicic 0:c0ecb8bf28eb 10472 fclose(fp);
Marko Mikulicic 0:c0ecb8bf28eb 10473 }
Marko Mikulicic 0:c0ecb8bf28eb 10474 }
Marko Mikulicic 0:c0ecb8bf28eb 10475
Marko Mikulicic 0:c0ecb8bf28eb 10476 return V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10477 }
Marko Mikulicic 0:c0ecb8bf28eb 10478
Marko Mikulicic 0:c0ecb8bf28eb 10479 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10480 V7_PRIVATE enum v7_err File_rename(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10481 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10482 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10483 v7_val_t arg1 = v7_arg(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 10484 int ires = -1;
Marko Mikulicic 0:c0ecb8bf28eb 10485
Marko Mikulicic 0:c0ecb8bf28eb 10486 if (v7_is_string(arg0) && v7_is_string(arg1)) {
Marko Mikulicic 0:c0ecb8bf28eb 10487 const char *from = v7_get_cstring(v7, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 10488 const char *to = v7_get_cstring(v7, &arg1);
Marko Mikulicic 0:c0ecb8bf28eb 10489 if (from == NULL || to == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 10490 *res = v7_mk_number(v7, ENOENT);
Marko Mikulicic 0:c0ecb8bf28eb 10491 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 10492 }
Marko Mikulicic 0:c0ecb8bf28eb 10493
Marko Mikulicic 0:c0ecb8bf28eb 10494 ires = rename(from, to);
Marko Mikulicic 0:c0ecb8bf28eb 10495 }
Marko Mikulicic 0:c0ecb8bf28eb 10496
Marko Mikulicic 0:c0ecb8bf28eb 10497 *res = v7_mk_number(v7, ires == 0 ? 0 : errno);
Marko Mikulicic 0:c0ecb8bf28eb 10498
Marko Mikulicic 0:c0ecb8bf28eb 10499 clean:
Marko Mikulicic 0:c0ecb8bf28eb 10500 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10501 }
Marko Mikulicic 0:c0ecb8bf28eb 10502
Marko Mikulicic 0:c0ecb8bf28eb 10503 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10504 V7_PRIVATE enum v7_err File_loadJSON(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10505 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10506 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10507
Marko Mikulicic 0:c0ecb8bf28eb 10508 *res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 10509
Marko Mikulicic 0:c0ecb8bf28eb 10510 if (v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 10511 const char *file_name = v7_get_cstring(v7, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 10512 if (file_name == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 10513 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 10514 }
Marko Mikulicic 0:c0ecb8bf28eb 10515
Marko Mikulicic 0:c0ecb8bf28eb 10516 rcode = v7_parse_json_file(v7, file_name, res);
Marko Mikulicic 0:c0ecb8bf28eb 10517 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 10518 /* swallow exception and return undefined */
Marko Mikulicic 0:c0ecb8bf28eb 10519 v7_clear_thrown_value(v7);
Marko Mikulicic 0:c0ecb8bf28eb 10520 rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10521 *res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 10522 }
Marko Mikulicic 0:c0ecb8bf28eb 10523 }
Marko Mikulicic 0:c0ecb8bf28eb 10524
Marko Mikulicic 0:c0ecb8bf28eb 10525 clean:
Marko Mikulicic 0:c0ecb8bf28eb 10526 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10527 }
Marko Mikulicic 0:c0ecb8bf28eb 10528
Marko Mikulicic 0:c0ecb8bf28eb 10529 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10530 V7_PRIVATE enum v7_err File_remove(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10531 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10532 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10533 int ires = -1;
Marko Mikulicic 0:c0ecb8bf28eb 10534
Marko Mikulicic 0:c0ecb8bf28eb 10535 if (v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 10536 const char *path = v7_get_cstring(v7, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 10537 if (path == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 10538 *res = v7_mk_number(v7, ENOENT);
Marko Mikulicic 0:c0ecb8bf28eb 10539 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 10540 }
Marko Mikulicic 0:c0ecb8bf28eb 10541 ires = remove(path);
Marko Mikulicic 0:c0ecb8bf28eb 10542 }
Marko Mikulicic 0:c0ecb8bf28eb 10543 *res = v7_mk_number(v7, ires == 0 ? 0 : errno);
Marko Mikulicic 0:c0ecb8bf28eb 10544
Marko Mikulicic 0:c0ecb8bf28eb 10545 clean:
Marko Mikulicic 0:c0ecb8bf28eb 10546 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10547 }
Marko Mikulicic 0:c0ecb8bf28eb 10548
Marko Mikulicic 0:c0ecb8bf28eb 10549 #if V7_ENABLE__File__list
Marko Mikulicic 0:c0ecb8bf28eb 10550 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10551 V7_PRIVATE enum v7_err File_list(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10552 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10553 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10554
Marko Mikulicic 0:c0ecb8bf28eb 10555 *res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 10556
Marko Mikulicic 0:c0ecb8bf28eb 10557 if (v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 10558 const char *path = v7_get_cstring(v7, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 10559 struct dirent *dp;
Marko Mikulicic 0:c0ecb8bf28eb 10560 DIR *dirp;
Marko Mikulicic 0:c0ecb8bf28eb 10561
Marko Mikulicic 0:c0ecb8bf28eb 10562 if (path == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 10563 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 10564 }
Marko Mikulicic 0:c0ecb8bf28eb 10565
Marko Mikulicic 0:c0ecb8bf28eb 10566 if ((dirp = (opendir(path))) != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 10567 *res = v7_mk_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 10568 while ((dp = readdir(dirp)) != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 10569 /* Do not show current and parent dirs */
Marko Mikulicic 0:c0ecb8bf28eb 10570 if (strcmp((const char *) dp->d_name, ".") == 0 ||
Marko Mikulicic 0:c0ecb8bf28eb 10571 strcmp((const char *) dp->d_name, "..") == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 10572 continue;
Marko Mikulicic 0:c0ecb8bf28eb 10573 }
Marko Mikulicic 0:c0ecb8bf28eb 10574 /* Add file name to the list */
Marko Mikulicic 0:c0ecb8bf28eb 10575 v7_array_push(v7, *res,
Marko Mikulicic 0:c0ecb8bf28eb 10576 v7_mk_string(v7, (const char *) dp->d_name,
Marko Mikulicic 0:c0ecb8bf28eb 10577 strlen((const char *) dp->d_name), 1));
Marko Mikulicic 0:c0ecb8bf28eb 10578 }
Marko Mikulicic 0:c0ecb8bf28eb 10579 closedir(dirp);
Marko Mikulicic 0:c0ecb8bf28eb 10580 }
Marko Mikulicic 0:c0ecb8bf28eb 10581 }
Marko Mikulicic 0:c0ecb8bf28eb 10582
Marko Mikulicic 0:c0ecb8bf28eb 10583 clean:
Marko Mikulicic 0:c0ecb8bf28eb 10584 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10585 }
Marko Mikulicic 0:c0ecb8bf28eb 10586 #endif /* V7_ENABLE__File__list */
Marko Mikulicic 0:c0ecb8bf28eb 10587
Marko Mikulicic 0:c0ecb8bf28eb 10588 void init_file(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 10589 v7_val_t file_obj = v7_mk_object(v7), file_proto = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 10590 v7_set(v7, v7_get_global(v7), "File", 4, file_obj);
Marko Mikulicic 0:c0ecb8bf28eb 10591 v7_set(v7, file_obj, "prototype", 9, file_proto);
Marko Mikulicic 0:c0ecb8bf28eb 10592
Marko Mikulicic 0:c0ecb8bf28eb 10593 v7_set_method(v7, file_obj, "eval", File_eval);
Marko Mikulicic 0:c0ecb8bf28eb 10594 v7_set_method(v7, file_obj, "exists", File_exists);
Marko Mikulicic 0:c0ecb8bf28eb 10595 v7_set_method(v7, file_obj, "remove", File_remove);
Marko Mikulicic 0:c0ecb8bf28eb 10596 v7_set_method(v7, file_obj, "rename", File_rename);
Marko Mikulicic 0:c0ecb8bf28eb 10597 v7_set_method(v7, file_obj, "open", File_open);
Marko Mikulicic 0:c0ecb8bf28eb 10598 v7_set_method(v7, file_obj, "read", File_read);
Marko Mikulicic 0:c0ecb8bf28eb 10599 v7_set_method(v7, file_obj, "write", File_write);
Marko Mikulicic 0:c0ecb8bf28eb 10600 v7_set_method(v7, file_obj, "loadJSON", File_loadJSON);
Marko Mikulicic 0:c0ecb8bf28eb 10601 #if V7_ENABLE__File__list
Marko Mikulicic 0:c0ecb8bf28eb 10602 v7_set_method(v7, file_obj, "list", File_list);
Marko Mikulicic 0:c0ecb8bf28eb 10603 #endif
Marko Mikulicic 0:c0ecb8bf28eb 10604
Marko Mikulicic 0:c0ecb8bf28eb 10605 v7_set_method(v7, file_proto, "close", File_obj_close);
Marko Mikulicic 0:c0ecb8bf28eb 10606 v7_set_method(v7, file_proto, "read", File_obj_read);
Marko Mikulicic 0:c0ecb8bf28eb 10607 v7_set_method(v7, file_proto, "write", File_obj_write);
Marko Mikulicic 0:c0ecb8bf28eb 10608
Marko Mikulicic 0:c0ecb8bf28eb 10609 #if V7_ENABLE__File__require
Marko Mikulicic 0:c0ecb8bf28eb 10610 v7_def(v7, v7_get_global(v7), "_modcache", ~0, 0, v7_mk_object(v7));
Marko Mikulicic 0:c0ecb8bf28eb 10611 if (v7_exec(v7,
Marko Mikulicic 0:c0ecb8bf28eb 10612 "function require(m) { "
Marko Mikulicic 0:c0ecb8bf28eb 10613 " if (m in _modcache) { return _modcache[m]; }"
Marko Mikulicic 0:c0ecb8bf28eb 10614 " var module = {exports:{}};"
Marko Mikulicic 0:c0ecb8bf28eb 10615 " File.eval(m);"
Marko Mikulicic 0:c0ecb8bf28eb 10616 " return (_modcache[m] = module.exports)"
Marko Mikulicic 0:c0ecb8bf28eb 10617 " }",
Marko Mikulicic 0:c0ecb8bf28eb 10618 NULL) != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 10619 /* TODO(mkm): percolate failure */
Marko Mikulicic 0:c0ecb8bf28eb 10620 }
Marko Mikulicic 0:c0ecb8bf28eb 10621 #endif
Marko Mikulicic 0:c0ecb8bf28eb 10622 }
Marko Mikulicic 0:c0ecb8bf28eb 10623 #else
Marko Mikulicic 0:c0ecb8bf28eb 10624 void init_file(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 10625 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 10626 }
Marko Mikulicic 0:c0ecb8bf28eb 10627 #endif /* NO_LIBC */
Marko Mikulicic 0:c0ecb8bf28eb 10628 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 10629 #line 1 "v7/builtin/socket.c"
Marko Mikulicic 0:c0ecb8bf28eb 10630 #endif
Marko Mikulicic 0:c0ecb8bf28eb 10631 /*
Marko Mikulicic 0:c0ecb8bf28eb 10632 * Copyright (c) 2015 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 10633 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 10634 */
Marko Mikulicic 0:c0ecb8bf28eb 10635
Marko Mikulicic 0:c0ecb8bf28eb 10636 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10637 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10638 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10639 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10640 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10641 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10642 /* Amalgamated: #include "common/mbuf.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10643 /* Amalgamated: #include "common/platform.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10644
Marko Mikulicic 0:c0ecb8bf28eb 10645 #ifdef V7_ENABLE_SOCKET
Marko Mikulicic 0:c0ecb8bf28eb 10646
Marko Mikulicic 0:c0ecb8bf28eb 10647 #ifdef __WATCOM__
Marko Mikulicic 0:c0ecb8bf28eb 10648 #define SOMAXCONN 128
Marko Mikulicic 0:c0ecb8bf28eb 10649 #endif
Marko Mikulicic 0:c0ecb8bf28eb 10650
Marko Mikulicic 0:c0ecb8bf28eb 10651 #ifndef RECV_BUF_SIZE
Marko Mikulicic 0:c0ecb8bf28eb 10652 #define RECV_BUF_SIZE 1024
Marko Mikulicic 0:c0ecb8bf28eb 10653 #endif
Marko Mikulicic 0:c0ecb8bf28eb 10654
Marko Mikulicic 0:c0ecb8bf28eb 10655 static const char s_sock_prop[] = "__sock";
Marko Mikulicic 0:c0ecb8bf28eb 10656
Marko Mikulicic 0:c0ecb8bf28eb 10657 static uint32_t s_resolve(struct v7 *v7, v7_val_t ip_address) {
Marko Mikulicic 0:c0ecb8bf28eb 10658 size_t n;
Marko Mikulicic 0:c0ecb8bf28eb 10659 const char *s = v7_get_string(v7, &ip_address, &n);
Marko Mikulicic 0:c0ecb8bf28eb 10660 struct hostent *he = gethostbyname(s);
Marko Mikulicic 0:c0ecb8bf28eb 10661 return he == NULL ? 0 : *(uint32_t *) he->h_addr_list[0];
Marko Mikulicic 0:c0ecb8bf28eb 10662 }
Marko Mikulicic 0:c0ecb8bf28eb 10663
Marko Mikulicic 0:c0ecb8bf28eb 10664 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10665 static enum v7_err s_fd_to_sock_obj(struct v7 *v7, sock_t fd, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10666 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10667 v7_val_t sock_proto =
Marko Mikulicic 0:c0ecb8bf28eb 10668 v7_get(v7, v7_get(v7, v7_get_global(v7), "Socket", ~0), "prototype", ~0);
Marko Mikulicic 0:c0ecb8bf28eb 10669
Marko Mikulicic 0:c0ecb8bf28eb 10670 *res = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 10671 v7_set_proto(v7, *res, sock_proto);
Marko Mikulicic 0:c0ecb8bf28eb 10672 v7_def(v7, *res, s_sock_prop, sizeof(s_sock_prop) - 1, V7_DESC_ENUMERABLE(0),
Marko Mikulicic 0:c0ecb8bf28eb 10673 v7_mk_number(v7, fd));
Marko Mikulicic 0:c0ecb8bf28eb 10674
Marko Mikulicic 0:c0ecb8bf28eb 10675 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10676 }
Marko Mikulicic 0:c0ecb8bf28eb 10677
Marko Mikulicic 0:c0ecb8bf28eb 10678 /* Socket.connect(host, port [, is_udp]) -> socket_object */
Marko Mikulicic 0:c0ecb8bf28eb 10679 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10680 V7_PRIVATE enum v7_err Socket_connect(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10681 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10682 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10683 v7_val_t arg1 = v7_arg(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 10684 v7_val_t arg2 = v7_arg(v7, 2);
Marko Mikulicic 0:c0ecb8bf28eb 10685
Marko Mikulicic 0:c0ecb8bf28eb 10686 if (v7_is_number(arg1) && v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 10687 struct sockaddr_in sin;
Marko Mikulicic 0:c0ecb8bf28eb 10688 sock_t sock =
Marko Mikulicic 0:c0ecb8bf28eb 10689 socket(AF_INET, v7_is_truthy(v7, arg2) ? SOCK_DGRAM : SOCK_STREAM, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10690 memset(&sin, 0, sizeof(sin));
Marko Mikulicic 0:c0ecb8bf28eb 10691 sin.sin_family = AF_INET;
Marko Mikulicic 0:c0ecb8bf28eb 10692 sin.sin_addr.s_addr = s_resolve(v7, arg0);
Marko Mikulicic 0:c0ecb8bf28eb 10693 sin.sin_port = htons((uint16_t) v7_get_double(v7, arg1));
Marko Mikulicic 0:c0ecb8bf28eb 10694 if (connect(sock, (struct sockaddr *) &sin, sizeof(sin)) != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 10695 closesocket(sock);
Marko Mikulicic 0:c0ecb8bf28eb 10696 } else {
Marko Mikulicic 0:c0ecb8bf28eb 10697 rcode = s_fd_to_sock_obj(v7, sock, res);
Marko Mikulicic 0:c0ecb8bf28eb 10698 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 10699 }
Marko Mikulicic 0:c0ecb8bf28eb 10700 }
Marko Mikulicic 0:c0ecb8bf28eb 10701
Marko Mikulicic 0:c0ecb8bf28eb 10702 *res = V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 10703
Marko Mikulicic 0:c0ecb8bf28eb 10704 clean:
Marko Mikulicic 0:c0ecb8bf28eb 10705 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10706 }
Marko Mikulicic 0:c0ecb8bf28eb 10707
Marko Mikulicic 0:c0ecb8bf28eb 10708 /* Socket.listen(port [, ip_address [,is_udp]]) -> sock */
Marko Mikulicic 0:c0ecb8bf28eb 10709 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10710 V7_PRIVATE enum v7_err Socket_listen(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10711 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10712 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10713 v7_val_t arg1 = v7_arg(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 10714 v7_val_t arg2 = v7_arg(v7, 2);
Marko Mikulicic 0:c0ecb8bf28eb 10715
Marko Mikulicic 0:c0ecb8bf28eb 10716 if (v7_is_number(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 10717 struct sockaddr_in sin;
Marko Mikulicic 0:c0ecb8bf28eb 10718 int on = 1;
Marko Mikulicic 0:c0ecb8bf28eb 10719 sock_t sock =
Marko Mikulicic 0:c0ecb8bf28eb 10720 socket(AF_INET, v7_is_truthy(v7, arg2) ? SOCK_DGRAM : SOCK_STREAM, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10721 memset(&sin, 0, sizeof(sin));
Marko Mikulicic 0:c0ecb8bf28eb 10722 sin.sin_family = AF_INET;
Marko Mikulicic 0:c0ecb8bf28eb 10723 sin.sin_port = htons((uint16_t) v7_get_double(v7, arg0));
Marko Mikulicic 0:c0ecb8bf28eb 10724 if (v7_is_string(arg1)) {
Marko Mikulicic 0:c0ecb8bf28eb 10725 sin.sin_addr.s_addr = s_resolve(v7, arg1);
Marko Mikulicic 0:c0ecb8bf28eb 10726 }
Marko Mikulicic 0:c0ecb8bf28eb 10727
Marko Mikulicic 0:c0ecb8bf28eb 10728 #if defined(_WIN32) && defined(SO_EXCLUSIVEADDRUSE)
Marko Mikulicic 0:c0ecb8bf28eb 10729 /* "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE" http://goo.gl/RmrFTm */
Marko Mikulicic 0:c0ecb8bf28eb 10730 setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (void *) &on, sizeof(on));
Marko Mikulicic 0:c0ecb8bf28eb 10731 #endif
Marko Mikulicic 0:c0ecb8bf28eb 10732
Marko Mikulicic 0:c0ecb8bf28eb 10733 #if !defined(_WIN32) || defined(SO_EXCLUSIVEADDRUSE)
Marko Mikulicic 0:c0ecb8bf28eb 10734 /*
Marko Mikulicic 0:c0ecb8bf28eb 10735 * SO_RESUSEADDR is not enabled on Windows because the semantics of
Marko Mikulicic 0:c0ecb8bf28eb 10736 * SO_REUSEADDR on UNIX and Windows is different. On Windows,
Marko Mikulicic 0:c0ecb8bf28eb 10737 * SO_REUSEADDR allows to bind a socket to a port without error even if
Marko Mikulicic 0:c0ecb8bf28eb 10738 * the port is already open by another program. This is not the behavior
Marko Mikulicic 0:c0ecb8bf28eb 10739 * SO_REUSEADDR was designed for, and leads to hard-to-track failure
Marko Mikulicic 0:c0ecb8bf28eb 10740 * scenarios. Therefore, SO_REUSEADDR was disabled on Windows unless
Marko Mikulicic 0:c0ecb8bf28eb 10741 * SO_EXCLUSIVEADDRUSE is supported and set on a socket.
Marko Mikulicic 0:c0ecb8bf28eb 10742 */
Marko Mikulicic 0:c0ecb8bf28eb 10743 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &on, sizeof(on));
Marko Mikulicic 0:c0ecb8bf28eb 10744 #endif
Marko Mikulicic 0:c0ecb8bf28eb 10745
Marko Mikulicic 0:c0ecb8bf28eb 10746 if (bind(sock, (struct sockaddr *) &sin, sizeof(sin)) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 10747 listen(sock, SOMAXCONN);
Marko Mikulicic 0:c0ecb8bf28eb 10748 rcode = s_fd_to_sock_obj(v7, sock, res);
Marko Mikulicic 0:c0ecb8bf28eb 10749 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 10750 } else {
Marko Mikulicic 0:c0ecb8bf28eb 10751 closesocket(sock);
Marko Mikulicic 0:c0ecb8bf28eb 10752 }
Marko Mikulicic 0:c0ecb8bf28eb 10753 }
Marko Mikulicic 0:c0ecb8bf28eb 10754
Marko Mikulicic 0:c0ecb8bf28eb 10755 *res = V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 10756
Marko Mikulicic 0:c0ecb8bf28eb 10757 clean:
Marko Mikulicic 0:c0ecb8bf28eb 10758 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10759 }
Marko Mikulicic 0:c0ecb8bf28eb 10760
Marko Mikulicic 0:c0ecb8bf28eb 10761 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10762 V7_PRIVATE enum v7_err Socket_accept(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10763 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10764 v7_val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 10765 v7_val_t prop = v7_get(v7, this_obj, s_sock_prop, sizeof(s_sock_prop) - 1);
Marko Mikulicic 0:c0ecb8bf28eb 10766
Marko Mikulicic 0:c0ecb8bf28eb 10767 if (v7_is_number(prop)) {
Marko Mikulicic 0:c0ecb8bf28eb 10768 struct sockaddr_in sin;
Marko Mikulicic 0:c0ecb8bf28eb 10769 socklen_t len = sizeof(sin);
Marko Mikulicic 0:c0ecb8bf28eb 10770 sock_t sock = (sock_t) v7_get_double(v7, prop);
Marko Mikulicic 0:c0ecb8bf28eb 10771 sock_t fd = accept(sock, (struct sockaddr *) &sin, &len);
Marko Mikulicic 0:c0ecb8bf28eb 10772 if (fd != INVALID_SOCKET) {
Marko Mikulicic 0:c0ecb8bf28eb 10773 rcode = s_fd_to_sock_obj(v7, fd, res);
Marko Mikulicic 0:c0ecb8bf28eb 10774 if (rcode == V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 10775 char *remote_host = inet_ntoa(sin.sin_addr);
Marko Mikulicic 0:c0ecb8bf28eb 10776 v7_set(v7, *res, "remoteHost", ~0,
Marko Mikulicic 0:c0ecb8bf28eb 10777 v7_mk_string(v7, remote_host, ~0, 1));
Marko Mikulicic 0:c0ecb8bf28eb 10778 }
Marko Mikulicic 0:c0ecb8bf28eb 10779 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 10780 }
Marko Mikulicic 0:c0ecb8bf28eb 10781 }
Marko Mikulicic 0:c0ecb8bf28eb 10782 *res = V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 10783
Marko Mikulicic 0:c0ecb8bf28eb 10784 clean:
Marko Mikulicic 0:c0ecb8bf28eb 10785 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10786 }
Marko Mikulicic 0:c0ecb8bf28eb 10787
Marko Mikulicic 0:c0ecb8bf28eb 10788 /* sock.close() -> errno */
Marko Mikulicic 0:c0ecb8bf28eb 10789 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10790 V7_PRIVATE enum v7_err Socket_close(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10791 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10792 v7_val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 10793 v7_val_t prop = v7_get(v7, this_obj, s_sock_prop, sizeof(s_sock_prop) - 1);
Marko Mikulicic 0:c0ecb8bf28eb 10794 *res = v7_mk_number(v7, closesocket((sock_t) v7_get_double(v7, prop)));
Marko Mikulicic 0:c0ecb8bf28eb 10795
Marko Mikulicic 0:c0ecb8bf28eb 10796 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10797 }
Marko Mikulicic 0:c0ecb8bf28eb 10798
Marko Mikulicic 0:c0ecb8bf28eb 10799 /* sock.recv() -> string */
Marko Mikulicic 0:c0ecb8bf28eb 10800 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10801 static enum v7_err s_recv(struct v7 *v7, int all, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10802 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10803 v7_val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 10804 v7_val_t prop = v7_get(v7, this_obj, s_sock_prop, sizeof(s_sock_prop) - 1);
Marko Mikulicic 0:c0ecb8bf28eb 10805
Marko Mikulicic 0:c0ecb8bf28eb 10806 if (v7_is_number(prop)) {
Marko Mikulicic 0:c0ecb8bf28eb 10807 char buf[RECV_BUF_SIZE];
Marko Mikulicic 0:c0ecb8bf28eb 10808 sock_t sock = (sock_t) v7_get_double(v7, prop);
Marko Mikulicic 0:c0ecb8bf28eb 10809 struct mbuf m;
Marko Mikulicic 0:c0ecb8bf28eb 10810 int n;
Marko Mikulicic 0:c0ecb8bf28eb 10811
Marko Mikulicic 0:c0ecb8bf28eb 10812 mbuf_init(&m, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10813 while ((n = recv(sock, buf, sizeof(buf), 0)) > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 10814 mbuf_append(&m, buf, n);
Marko Mikulicic 0:c0ecb8bf28eb 10815 if (!all) {
Marko Mikulicic 0:c0ecb8bf28eb 10816 break;
Marko Mikulicic 0:c0ecb8bf28eb 10817 }
Marko Mikulicic 0:c0ecb8bf28eb 10818 }
Marko Mikulicic 0:c0ecb8bf28eb 10819
Marko Mikulicic 0:c0ecb8bf28eb 10820 if (n <= 0) {
Marko Mikulicic 0:c0ecb8bf28eb 10821 closesocket(sock);
Marko Mikulicic 0:c0ecb8bf28eb 10822 v7_def(v7, this_obj, s_sock_prop, sizeof(s_sock_prop) - 1,
Marko Mikulicic 0:c0ecb8bf28eb 10823 V7_DESC_ENUMERABLE(0), v7_mk_number(v7, INVALID_SOCKET));
Marko Mikulicic 0:c0ecb8bf28eb 10824 }
Marko Mikulicic 0:c0ecb8bf28eb 10825
Marko Mikulicic 0:c0ecb8bf28eb 10826 if (m.len > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 10827 *res = v7_mk_string(v7, m.buf, m.len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 10828 mbuf_free(&m);
Marko Mikulicic 0:c0ecb8bf28eb 10829 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 10830 }
Marko Mikulicic 0:c0ecb8bf28eb 10831 }
Marko Mikulicic 0:c0ecb8bf28eb 10832
Marko Mikulicic 0:c0ecb8bf28eb 10833 *res = V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 10834
Marko Mikulicic 0:c0ecb8bf28eb 10835 clean:
Marko Mikulicic 0:c0ecb8bf28eb 10836 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10837 }
Marko Mikulicic 0:c0ecb8bf28eb 10838
Marko Mikulicic 0:c0ecb8bf28eb 10839 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10840 V7_PRIVATE enum v7_err Socket_recvAll(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10841 return s_recv(v7, 1, res);
Marko Mikulicic 0:c0ecb8bf28eb 10842 }
Marko Mikulicic 0:c0ecb8bf28eb 10843
Marko Mikulicic 0:c0ecb8bf28eb 10844 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10845 V7_PRIVATE enum v7_err Socket_recv(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10846 return s_recv(v7, 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 10847 }
Marko Mikulicic 0:c0ecb8bf28eb 10848
Marko Mikulicic 0:c0ecb8bf28eb 10849 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10850 V7_PRIVATE enum v7_err Socket_send(struct v7 *v7, 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 arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10854 v7_val_t prop = v7_get(v7, this_obj, s_sock_prop, sizeof(s_sock_prop) - 1);
Marko Mikulicic 0:c0ecb8bf28eb 10855 size_t len, sent = 0;
Marko Mikulicic 0:c0ecb8bf28eb 10856
Marko Mikulicic 0:c0ecb8bf28eb 10857 if (v7_is_number(prop) && v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 10858 const char *s = v7_get_string(v7, &arg0, &len);
Marko Mikulicic 0:c0ecb8bf28eb 10859 sock_t sock = (sock_t) v7_get_double(v7, prop);
Marko Mikulicic 0:c0ecb8bf28eb 10860 int n;
Marko Mikulicic 0:c0ecb8bf28eb 10861
Marko Mikulicic 0:c0ecb8bf28eb 10862 while (sent < len && (n = send(sock, s + sent, len - sent, 0)) > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 10863 sent += n;
Marko Mikulicic 0:c0ecb8bf28eb 10864 }
Marko Mikulicic 0:c0ecb8bf28eb 10865 }
Marko Mikulicic 0:c0ecb8bf28eb 10866
Marko Mikulicic 0:c0ecb8bf28eb 10867 *res = v7_mk_number(v7, sent);
Marko Mikulicic 0:c0ecb8bf28eb 10868
Marko Mikulicic 0:c0ecb8bf28eb 10869 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10870 }
Marko Mikulicic 0:c0ecb8bf28eb 10871
Marko Mikulicic 0:c0ecb8bf28eb 10872 void init_socket(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 10873 v7_val_t socket_obj = v7_mk_object(v7), sock_proto = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 10874
Marko Mikulicic 0:c0ecb8bf28eb 10875 v7_set(v7, v7_get_global(v7), "Socket", 6, socket_obj);
Marko Mikulicic 0:c0ecb8bf28eb 10876 sock_proto = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 10877 v7_set(v7, socket_obj, "prototype", 9, sock_proto);
Marko Mikulicic 0:c0ecb8bf28eb 10878
Marko Mikulicic 0:c0ecb8bf28eb 10879 v7_set_method(v7, socket_obj, "connect", Socket_connect);
Marko Mikulicic 0:c0ecb8bf28eb 10880 v7_set_method(v7, socket_obj, "listen", Socket_listen);
Marko Mikulicic 0:c0ecb8bf28eb 10881
Marko Mikulicic 0:c0ecb8bf28eb 10882 v7_set_method(v7, sock_proto, "accept", Socket_accept);
Marko Mikulicic 0:c0ecb8bf28eb 10883 v7_set_method(v7, sock_proto, "send", Socket_send);
Marko Mikulicic 0:c0ecb8bf28eb 10884 v7_set_method(v7, sock_proto, "recv", Socket_recv);
Marko Mikulicic 0:c0ecb8bf28eb 10885 v7_set_method(v7, sock_proto, "recvAll", Socket_recvAll);
Marko Mikulicic 0:c0ecb8bf28eb 10886 v7_set_method(v7, sock_proto, "close", Socket_close);
Marko Mikulicic 0:c0ecb8bf28eb 10887
Marko Mikulicic 0:c0ecb8bf28eb 10888 #ifdef _WIN32
Marko Mikulicic 0:c0ecb8bf28eb 10889 {
Marko Mikulicic 0:c0ecb8bf28eb 10890 WSADATA data;
Marko Mikulicic 0:c0ecb8bf28eb 10891 WSAStartup(MAKEWORD(2, 2), &data);
Marko Mikulicic 0:c0ecb8bf28eb 10892 /* TODO(alashkin): add WSACleanup call */
Marko Mikulicic 0:c0ecb8bf28eb 10893 }
Marko Mikulicic 0:c0ecb8bf28eb 10894 #else
Marko Mikulicic 0:c0ecb8bf28eb 10895 signal(SIGPIPE, SIG_IGN);
Marko Mikulicic 0:c0ecb8bf28eb 10896 #endif
Marko Mikulicic 0:c0ecb8bf28eb 10897 }
Marko Mikulicic 0:c0ecb8bf28eb 10898 #else
Marko Mikulicic 0:c0ecb8bf28eb 10899 void init_socket(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 10900 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 10901 }
Marko Mikulicic 0:c0ecb8bf28eb 10902 #endif
Marko Mikulicic 0:c0ecb8bf28eb 10903 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 10904 #line 1 "v7/builtin/crypto.c"
Marko Mikulicic 0:c0ecb8bf28eb 10905 #endif
Marko Mikulicic 0:c0ecb8bf28eb 10906 /*
Marko Mikulicic 0:c0ecb8bf28eb 10907 * Copyright (c) 2015 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 10908 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 10909 */
Marko Mikulicic 0:c0ecb8bf28eb 10910
Marko Mikulicic 0:c0ecb8bf28eb 10911 #include <stdlib.h>
Marko Mikulicic 0:c0ecb8bf28eb 10912 #include <string.h>
Marko Mikulicic 0:c0ecb8bf28eb 10913
Marko Mikulicic 0:c0ecb8bf28eb 10914 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10915 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10916 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10917 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10918 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10919 /* Amalgamated: #include "common/md5.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10920 /* Amalgamated: #include "common/sha1.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10921 /* Amalgamated: #include "common/base64.h" */
Marko Mikulicic 0:c0ecb8bf28eb 10922
Marko Mikulicic 0:c0ecb8bf28eb 10923 #ifdef V7_ENABLE_CRYPTO
Marko Mikulicic 0:c0ecb8bf28eb 10924
Marko Mikulicic 0:c0ecb8bf28eb 10925 typedef void (*b64_func_t)(const unsigned char *, int, char *);
Marko Mikulicic 0:c0ecb8bf28eb 10926
Marko Mikulicic 0:c0ecb8bf28eb 10927 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10928 static enum v7_err b64_transform(struct v7 *v7, b64_func_t func, double mult,
Marko Mikulicic 0:c0ecb8bf28eb 10929 v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10930 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10931 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10932 *res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 10933
Marko Mikulicic 0:c0ecb8bf28eb 10934 if (v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 10935 size_t n;
Marko Mikulicic 0:c0ecb8bf28eb 10936 const char *s = v7_get_string(v7, &arg0, &n);
Marko Mikulicic 0:c0ecb8bf28eb 10937 char *buf = (char *) malloc(n * mult + 4);
Marko Mikulicic 0:c0ecb8bf28eb 10938 if (buf != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 10939 func((const unsigned char *) s, (int) n, buf);
Marko Mikulicic 0:c0ecb8bf28eb 10940 *res = v7_mk_string(v7, buf, strlen(buf), 1);
Marko Mikulicic 0:c0ecb8bf28eb 10941 free(buf);
Marko Mikulicic 0:c0ecb8bf28eb 10942 }
Marko Mikulicic 0:c0ecb8bf28eb 10943 }
Marko Mikulicic 0:c0ecb8bf28eb 10944
Marko Mikulicic 0:c0ecb8bf28eb 10945 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10946 }
Marko Mikulicic 0:c0ecb8bf28eb 10947
Marko Mikulicic 0:c0ecb8bf28eb 10948 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10949 V7_PRIVATE enum v7_err Crypto_base64_decode(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10950 return b64_transform(v7, (b64_func_t) cs_base64_decode, 0.75, res);
Marko Mikulicic 0:c0ecb8bf28eb 10951 }
Marko Mikulicic 0:c0ecb8bf28eb 10952
Marko Mikulicic 0:c0ecb8bf28eb 10953 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10954 V7_PRIVATE enum v7_err Crypto_base64_encode(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10955 return b64_transform(v7, cs_base64_encode, 1.5, res);
Marko Mikulicic 0:c0ecb8bf28eb 10956 }
Marko Mikulicic 0:c0ecb8bf28eb 10957
Marko Mikulicic 0:c0ecb8bf28eb 10958 static void v7_md5(const char *data, size_t len, char buf[16]) {
Marko Mikulicic 0:c0ecb8bf28eb 10959 MD5_CTX ctx;
Marko Mikulicic 0:c0ecb8bf28eb 10960 MD5_Init(&ctx);
Marko Mikulicic 0:c0ecb8bf28eb 10961 MD5_Update(&ctx, (unsigned char *) data, len);
Marko Mikulicic 0:c0ecb8bf28eb 10962 MD5_Final((unsigned char *) buf, &ctx);
Marko Mikulicic 0:c0ecb8bf28eb 10963 }
Marko Mikulicic 0:c0ecb8bf28eb 10964
Marko Mikulicic 0:c0ecb8bf28eb 10965 static void v7_sha1(const char *data, size_t len, char buf[20]) {
Marko Mikulicic 0:c0ecb8bf28eb 10966 cs_sha1_ctx ctx;
Marko Mikulicic 0:c0ecb8bf28eb 10967 cs_sha1_init(&ctx);
Marko Mikulicic 0:c0ecb8bf28eb 10968 cs_sha1_update(&ctx, (unsigned char *) data, len);
Marko Mikulicic 0:c0ecb8bf28eb 10969 cs_sha1_final((unsigned char *) buf, &ctx);
Marko Mikulicic 0:c0ecb8bf28eb 10970 }
Marko Mikulicic 0:c0ecb8bf28eb 10971
Marko Mikulicic 0:c0ecb8bf28eb 10972 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10973 V7_PRIVATE enum v7_err Crypto_md5(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10974 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10975 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10976
Marko Mikulicic 0:c0ecb8bf28eb 10977 if (v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 10978 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 10979 const char *data = v7_get_string(v7, &arg0, &len);
Marko Mikulicic 0:c0ecb8bf28eb 10980 char buf[16];
Marko Mikulicic 0:c0ecb8bf28eb 10981 v7_md5(data, len, buf);
Marko Mikulicic 0:c0ecb8bf28eb 10982 *res = v7_mk_string(v7, buf, sizeof(buf), 1);
Marko Mikulicic 0:c0ecb8bf28eb 10983 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 10984 }
Marko Mikulicic 0:c0ecb8bf28eb 10985
Marko Mikulicic 0:c0ecb8bf28eb 10986 *res = V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 10987
Marko Mikulicic 0:c0ecb8bf28eb 10988 clean:
Marko Mikulicic 0:c0ecb8bf28eb 10989 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 10990 }
Marko Mikulicic 0:c0ecb8bf28eb 10991
Marko Mikulicic 0:c0ecb8bf28eb 10992 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 10993 V7_PRIVATE enum v7_err Crypto_md5_hex(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 10994 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 10995 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 10996
Marko Mikulicic 0:c0ecb8bf28eb 10997 if (v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 10998 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 10999 const char *data = v7_get_string(v7, &arg0, &len);
Marko Mikulicic 0:c0ecb8bf28eb 11000 char hash[16], buf[sizeof(hash) * 2 + 1];
Marko Mikulicic 0:c0ecb8bf28eb 11001 v7_md5(data, len, hash);
Marko Mikulicic 0:c0ecb8bf28eb 11002 cs_to_hex(buf, (unsigned char *) hash, sizeof(hash));
Marko Mikulicic 0:c0ecb8bf28eb 11003 *res = v7_mk_string(v7, buf, sizeof(buf) - 1, 1);
Marko Mikulicic 0:c0ecb8bf28eb 11004 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 11005 }
Marko Mikulicic 0:c0ecb8bf28eb 11006 *res = V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 11007
Marko Mikulicic 0:c0ecb8bf28eb 11008 clean:
Marko Mikulicic 0:c0ecb8bf28eb 11009 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 11010 }
Marko Mikulicic 0:c0ecb8bf28eb 11011
Marko Mikulicic 0:c0ecb8bf28eb 11012 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 11013 V7_PRIVATE enum v7_err Crypto_sha1(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 11014 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 11015 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 11016
Marko Mikulicic 0:c0ecb8bf28eb 11017 if (v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 11018 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 11019 const char *data = v7_get_string(v7, &arg0, &len);
Marko Mikulicic 0:c0ecb8bf28eb 11020 char buf[20];
Marko Mikulicic 0:c0ecb8bf28eb 11021 v7_sha1(data, len, buf);
Marko Mikulicic 0:c0ecb8bf28eb 11022 *res = v7_mk_string(v7, buf, sizeof(buf), 1);
Marko Mikulicic 0:c0ecb8bf28eb 11023 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 11024 }
Marko Mikulicic 0:c0ecb8bf28eb 11025 *res = V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 11026
Marko Mikulicic 0:c0ecb8bf28eb 11027 clean:
Marko Mikulicic 0:c0ecb8bf28eb 11028 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 11029 }
Marko Mikulicic 0:c0ecb8bf28eb 11030
Marko Mikulicic 0:c0ecb8bf28eb 11031 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 11032 V7_PRIVATE enum v7_err Crypto_sha1_hex(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 11033 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 11034 v7_val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 11035
Marko Mikulicic 0:c0ecb8bf28eb 11036 if (v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 11037 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 11038 const char *data = v7_get_string(v7, &arg0, &len);
Marko Mikulicic 0:c0ecb8bf28eb 11039 char hash[20], buf[sizeof(hash) * 2 + 1];
Marko Mikulicic 0:c0ecb8bf28eb 11040 v7_sha1(data, len, hash);
Marko Mikulicic 0:c0ecb8bf28eb 11041 cs_to_hex(buf, (unsigned char *) hash, sizeof(hash));
Marko Mikulicic 0:c0ecb8bf28eb 11042 *res = v7_mk_string(v7, buf, sizeof(buf) - 1, 1);
Marko Mikulicic 0:c0ecb8bf28eb 11043 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 11044 }
Marko Mikulicic 0:c0ecb8bf28eb 11045 *res = V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 11046
Marko Mikulicic 0:c0ecb8bf28eb 11047 clean:
Marko Mikulicic 0:c0ecb8bf28eb 11048 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 11049 }
Marko Mikulicic 0:c0ecb8bf28eb 11050 #endif
Marko Mikulicic 0:c0ecb8bf28eb 11051
Marko Mikulicic 0:c0ecb8bf28eb 11052 void init_crypto(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 11053 #ifdef V7_ENABLE_CRYPTO
Marko Mikulicic 0:c0ecb8bf28eb 11054 v7_val_t obj = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 11055 v7_set(v7, v7_get_global(v7), "Crypto", 6, obj);
Marko Mikulicic 0:c0ecb8bf28eb 11056 v7_set_method(v7, obj, "md5", Crypto_md5);
Marko Mikulicic 0:c0ecb8bf28eb 11057 v7_set_method(v7, obj, "md5_hex", Crypto_md5_hex);
Marko Mikulicic 0:c0ecb8bf28eb 11058 v7_set_method(v7, obj, "sha1", Crypto_sha1);
Marko Mikulicic 0:c0ecb8bf28eb 11059 v7_set_method(v7, obj, "sha1_hex", Crypto_sha1_hex);
Marko Mikulicic 0:c0ecb8bf28eb 11060 v7_set_method(v7, obj, "base64_encode", Crypto_base64_encode);
Marko Mikulicic 0:c0ecb8bf28eb 11061 v7_set_method(v7, obj, "base64_decode", Crypto_base64_decode);
Marko Mikulicic 0:c0ecb8bf28eb 11062 #else
Marko Mikulicic 0:c0ecb8bf28eb 11063 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 11064 #endif
Marko Mikulicic 0:c0ecb8bf28eb 11065 }
Marko Mikulicic 0:c0ecb8bf28eb 11066 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 11067 #line 1 "v7/src/varint.c"
Marko Mikulicic 0:c0ecb8bf28eb 11068 #endif
Marko Mikulicic 0:c0ecb8bf28eb 11069 /*
Marko Mikulicic 0:c0ecb8bf28eb 11070 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 11071 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 11072 */
Marko Mikulicic 0:c0ecb8bf28eb 11073
Marko Mikulicic 0:c0ecb8bf28eb 11074 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 11075 /* Amalgamated: #include "v7/src/varint.h" */
Marko Mikulicic 0:c0ecb8bf28eb 11076
Marko Mikulicic 0:c0ecb8bf28eb 11077 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 11078 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 11079 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 11080
Marko Mikulicic 0:c0ecb8bf28eb 11081 /*
Marko Mikulicic 0:c0ecb8bf28eb 11082 * Strings in AST are encoded as tuples (length, string).
Marko Mikulicic 0:c0ecb8bf28eb 11083 * Length is variable-length: if high bit is set in a byte, next byte is used.
Marko Mikulicic 0:c0ecb8bf28eb 11084 * Maximum string length with such encoding is 2 ^ (7 * 4) == 256 MiB,
Marko Mikulicic 0:c0ecb8bf28eb 11085 * assuming that sizeof(size_t) == 4.
Marko Mikulicic 0:c0ecb8bf28eb 11086 * Small string length (less then 128 bytes) is encoded in 1 byte.
Marko Mikulicic 0:c0ecb8bf28eb 11087 */
Marko Mikulicic 0:c0ecb8bf28eb 11088 V7_PRIVATE size_t decode_varint(const unsigned char *p, int *llen) {
Marko Mikulicic 0:c0ecb8bf28eb 11089 size_t i = 0, string_len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 11090
Marko Mikulicic 0:c0ecb8bf28eb 11091 do {
Marko Mikulicic 0:c0ecb8bf28eb 11092 /*
Marko Mikulicic 0:c0ecb8bf28eb 11093 * Each byte of varint contains 7 bits, in little endian order.
Marko Mikulicic 0:c0ecb8bf28eb 11094 * MSB is a continuation bit: it tells whether next byte is used.
Marko Mikulicic 0:c0ecb8bf28eb 11095 */
Marko Mikulicic 0:c0ecb8bf28eb 11096 string_len |= (p[i] & 0x7f) << (7 * i);
Marko Mikulicic 0:c0ecb8bf28eb 11097 /*
Marko Mikulicic 0:c0ecb8bf28eb 11098 * First we increment i, then check whether it is within boundary and
Marko Mikulicic 0:c0ecb8bf28eb 11099 * whether decoded byte had continuation bit set.
Marko Mikulicic 0:c0ecb8bf28eb 11100 */
Marko Mikulicic 0:c0ecb8bf28eb 11101 } while (++i < sizeof(size_t) && (p[i - 1] & 0x80));
Marko Mikulicic 0:c0ecb8bf28eb 11102 *llen = i;
Marko Mikulicic 0:c0ecb8bf28eb 11103
Marko Mikulicic 0:c0ecb8bf28eb 11104 return string_len;
Marko Mikulicic 0:c0ecb8bf28eb 11105 }
Marko Mikulicic 0:c0ecb8bf28eb 11106
Marko Mikulicic 0:c0ecb8bf28eb 11107 /* Return number of bytes to store length */
Marko Mikulicic 0:c0ecb8bf28eb 11108 V7_PRIVATE int calc_llen(size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 11109 int n = 0;
Marko Mikulicic 0:c0ecb8bf28eb 11110
Marko Mikulicic 0:c0ecb8bf28eb 11111 do {
Marko Mikulicic 0:c0ecb8bf28eb 11112 n++;
Marko Mikulicic 0:c0ecb8bf28eb 11113 } while (len >>= 7);
Marko Mikulicic 0:c0ecb8bf28eb 11114
Marko Mikulicic 0:c0ecb8bf28eb 11115 return n;
Marko Mikulicic 0:c0ecb8bf28eb 11116 }
Marko Mikulicic 0:c0ecb8bf28eb 11117
Marko Mikulicic 0:c0ecb8bf28eb 11118 V7_PRIVATE int encode_varint(size_t len, unsigned char *p) {
Marko Mikulicic 0:c0ecb8bf28eb 11119 int i, llen = calc_llen(len);
Marko Mikulicic 0:c0ecb8bf28eb 11120
Marko Mikulicic 0:c0ecb8bf28eb 11121 for (i = 0; i < llen; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 11122 p[i] = (len & 0x7f) | (i < llen - 1 ? 0x80 : 0);
Marko Mikulicic 0:c0ecb8bf28eb 11123 len >>= 7;
Marko Mikulicic 0:c0ecb8bf28eb 11124 }
Marko Mikulicic 0:c0ecb8bf28eb 11125
Marko Mikulicic 0:c0ecb8bf28eb 11126 return llen;
Marko Mikulicic 0:c0ecb8bf28eb 11127 }
Marko Mikulicic 0:c0ecb8bf28eb 11128
Marko Mikulicic 0:c0ecb8bf28eb 11129 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 11130 }
Marko Mikulicic 0:c0ecb8bf28eb 11131 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 11132 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 11133 #line 1 "v7/src/tokenizer.c"
Marko Mikulicic 0:c0ecb8bf28eb 11134 #endif
Marko Mikulicic 0:c0ecb8bf28eb 11135 /*
Marko Mikulicic 0:c0ecb8bf28eb 11136 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 11137 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 11138 */
Marko Mikulicic 0:c0ecb8bf28eb 11139
Marko Mikulicic 0:c0ecb8bf28eb 11140 /* Amalgamated: #include "common/cs_strtod.h" */
Marko Mikulicic 0:c0ecb8bf28eb 11141 /* Amalgamated: #include "common/utf.h" */
Marko Mikulicic 0:c0ecb8bf28eb 11142
Marko Mikulicic 0:c0ecb8bf28eb 11143 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 11144 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 11145
Marko Mikulicic 0:c0ecb8bf28eb 11146 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 11147
Marko Mikulicic 0:c0ecb8bf28eb 11148 /*
Marko Mikulicic 0:c0ecb8bf28eb 11149 * NOTE(lsm): Must be in the same order as enum for keywords. See comment
Marko Mikulicic 0:c0ecb8bf28eb 11150 * for function get_tok() for rationale for that.
Marko Mikulicic 0:c0ecb8bf28eb 11151 */
Marko Mikulicic 0:c0ecb8bf28eb 11152 static const struct v7_vec_const s_keywords[] = {
Marko Mikulicic 0:c0ecb8bf28eb 11153 V7_VEC("break"), V7_VEC("case"), V7_VEC("catch"),
Marko Mikulicic 0:c0ecb8bf28eb 11154 V7_VEC("continue"), V7_VEC("debugger"), V7_VEC("default"),
Marko Mikulicic 0:c0ecb8bf28eb 11155 V7_VEC("delete"), V7_VEC("do"), V7_VEC("else"),
Marko Mikulicic 0:c0ecb8bf28eb 11156 V7_VEC("false"), V7_VEC("finally"), V7_VEC("for"),
Marko Mikulicic 0:c0ecb8bf28eb 11157 V7_VEC("function"), V7_VEC("if"), V7_VEC("in"),
Marko Mikulicic 0:c0ecb8bf28eb 11158 V7_VEC("instanceof"), V7_VEC("new"), V7_VEC("null"),
Marko Mikulicic 0:c0ecb8bf28eb 11159 V7_VEC("return"), V7_VEC("switch"), V7_VEC("this"),
Marko Mikulicic 0:c0ecb8bf28eb 11160 V7_VEC("throw"), V7_VEC("true"), V7_VEC("try"),
Marko Mikulicic 0:c0ecb8bf28eb 11161 V7_VEC("typeof"), V7_VEC("var"), V7_VEC("void"),
Marko Mikulicic 0:c0ecb8bf28eb 11162 V7_VEC("while"), V7_VEC("with")};
Marko Mikulicic 0:c0ecb8bf28eb 11163
Marko Mikulicic 0:c0ecb8bf28eb 11164 V7_PRIVATE int is_reserved_word_token(enum v7_tok tok) {
Marko Mikulicic 0:c0ecb8bf28eb 11165 return tok >= TOK_BREAK && tok <= TOK_WITH;
Marko Mikulicic 0:c0ecb8bf28eb 11166 }
Marko Mikulicic 0:c0ecb8bf28eb 11167
Marko Mikulicic 0:c0ecb8bf28eb 11168 /*
Marko Mikulicic 0:c0ecb8bf28eb 11169 * Move ptr to the next token, skipping comments and whitespaces.
Marko Mikulicic 0:c0ecb8bf28eb 11170 * Return number of new line characters detected.
Marko Mikulicic 0:c0ecb8bf28eb 11171 */
Marko Mikulicic 0:c0ecb8bf28eb 11172 V7_PRIVATE int skip_to_next_tok(const char **ptr, const char *src_end) {
Marko Mikulicic 0:c0ecb8bf28eb 11173 const char *s = *ptr, *p = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 11174 int num_lines = 0;
Marko Mikulicic 0:c0ecb8bf28eb 11175
Marko Mikulicic 0:c0ecb8bf28eb 11176 while (s != p && s < src_end && *s != '\0' &&
Marko Mikulicic 0:c0ecb8bf28eb 11177 (isspace((unsigned char) *s) || *s == '/')) {
Marko Mikulicic 0:c0ecb8bf28eb 11178 p = s;
Marko Mikulicic 0:c0ecb8bf28eb 11179 while (s < src_end && *s != '\0' && isspace((unsigned char) *s)) {
Marko Mikulicic 0:c0ecb8bf28eb 11180 if (*s == '\n') num_lines++;
Marko Mikulicic 0:c0ecb8bf28eb 11181 s++;
Marko Mikulicic 0:c0ecb8bf28eb 11182 }
Marko Mikulicic 0:c0ecb8bf28eb 11183 if ((s + 1) < src_end && s[0] == '/' && s[1] == '/') {
Marko Mikulicic 0:c0ecb8bf28eb 11184 s += 2;
Marko Mikulicic 0:c0ecb8bf28eb 11185 while (s < src_end && s[0] != '\0' && s[0] != '\n') s++;
Marko Mikulicic 0:c0ecb8bf28eb 11186 }
Marko Mikulicic 0:c0ecb8bf28eb 11187 if ((s + 1) < src_end && s[0] == '/' && s[1] == '*') {
Marko Mikulicic 0:c0ecb8bf28eb 11188 s += 2;
Marko Mikulicic 0:c0ecb8bf28eb 11189 while (s < src_end && s[0] != '\0' && !(s[-1] == '/' && s[-2] == '*')) {
Marko Mikulicic 0:c0ecb8bf28eb 11190 if (s[0] == '\n') num_lines++;
Marko Mikulicic 0:c0ecb8bf28eb 11191 s++;
Marko Mikulicic 0:c0ecb8bf28eb 11192 }
Marko Mikulicic 0:c0ecb8bf28eb 11193 }
Marko Mikulicic 0:c0ecb8bf28eb 11194 }
Marko Mikulicic 0:c0ecb8bf28eb 11195 *ptr = s;
Marko Mikulicic 0:c0ecb8bf28eb 11196
Marko Mikulicic 0:c0ecb8bf28eb 11197 return num_lines;
Marko Mikulicic 0:c0ecb8bf28eb 11198 }
Marko Mikulicic 0:c0ecb8bf28eb 11199
Marko Mikulicic 0:c0ecb8bf28eb 11200 /* Advance `s` pointer to the end of identifier */
Marko Mikulicic 0:c0ecb8bf28eb 11201 static void ident(const char **s, const char *src_end) {
Marko Mikulicic 0:c0ecb8bf28eb 11202 const unsigned char *p = (unsigned char *) *s;
Marko Mikulicic 0:c0ecb8bf28eb 11203 int n;
Marko Mikulicic 0:c0ecb8bf28eb 11204 Rune r;
Marko Mikulicic 0:c0ecb8bf28eb 11205
Marko Mikulicic 0:c0ecb8bf28eb 11206 while ((const char *) p < src_end && p[0] != '\0') {
Marko Mikulicic 0:c0ecb8bf28eb 11207 if (p[0] == '$' || p[0] == '_' || isalnum(p[0])) {
Marko Mikulicic 0:c0ecb8bf28eb 11208 /* $, _, or any alphanumeric are valid identifier characters */
Marko Mikulicic 0:c0ecb8bf28eb 11209 p++;
Marko Mikulicic 0:c0ecb8bf28eb 11210 } else if ((const char *) (p + 5) < src_end && p[0] == '\\' &&
Marko Mikulicic 0:c0ecb8bf28eb 11211 p[1] == 'u' && isxdigit(p[2]) && isxdigit(p[3]) &&
Marko Mikulicic 0:c0ecb8bf28eb 11212 isxdigit(p[4]) && isxdigit(p[5])) {
Marko Mikulicic 0:c0ecb8bf28eb 11213 /* Unicode escape, \uXXXX . Could be used like "var \u0078 = 1;" */
Marko Mikulicic 0:c0ecb8bf28eb 11214 p += 6;
Marko Mikulicic 0:c0ecb8bf28eb 11215 } else if ((n = chartorune(&r, (char *) p)) > 1 && isalpharune(r)) {
Marko Mikulicic 0:c0ecb8bf28eb 11216 /*
Marko Mikulicic 0:c0ecb8bf28eb 11217 * TODO(dfrank): the chartorune() call above can read `p` past the
Marko Mikulicic 0:c0ecb8bf28eb 11218 * src_end, so it might crash on incorrect code. The solution would be
Marko Mikulicic 0:c0ecb8bf28eb 11219 * to modify `chartorune()` to accept src_end argument as well.
Marko Mikulicic 0:c0ecb8bf28eb 11220 */
Marko Mikulicic 0:c0ecb8bf28eb 11221 /* Unicode alphanumeric character */
Marko Mikulicic 0:c0ecb8bf28eb 11222 p += n;
Marko Mikulicic 0:c0ecb8bf28eb 11223 } else {
Marko Mikulicic 0:c0ecb8bf28eb 11224 break;
Marko Mikulicic 0:c0ecb8bf28eb 11225 }
Marko Mikulicic 0:c0ecb8bf28eb 11226 }
Marko Mikulicic 0:c0ecb8bf28eb 11227
Marko Mikulicic 0:c0ecb8bf28eb 11228 *s = (char *) p;
Marko Mikulicic 0:c0ecb8bf28eb 11229 }
Marko Mikulicic 0:c0ecb8bf28eb 11230
Marko Mikulicic 0:c0ecb8bf28eb 11231 static enum v7_tok kw(const char *s, size_t len, int ntoks, enum v7_tok tok) {
Marko Mikulicic 0:c0ecb8bf28eb 11232 int i;
Marko Mikulicic 0:c0ecb8bf28eb 11233
Marko Mikulicic 0:c0ecb8bf28eb 11234 for (i = 0; i < ntoks; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 11235 if (s_keywords[(tok - TOK_BREAK) + i].len == len &&
Marko Mikulicic 0:c0ecb8bf28eb 11236 memcmp(s_keywords[(tok - TOK_BREAK) + i].p + 1, s + 1, len - 1) == 0)
Marko Mikulicic 0:c0ecb8bf28eb 11237 break;
Marko Mikulicic 0:c0ecb8bf28eb 11238 }
Marko Mikulicic 0:c0ecb8bf28eb 11239
Marko Mikulicic 0:c0ecb8bf28eb 11240 return i == ntoks ? TOK_IDENTIFIER : (enum v7_tok)(tok + i);
Marko Mikulicic 0:c0ecb8bf28eb 11241 }
Marko Mikulicic 0:c0ecb8bf28eb 11242
Marko Mikulicic 0:c0ecb8bf28eb 11243 static enum v7_tok punct1(const char **s, const char *src_end, int ch1,
Marko Mikulicic 0:c0ecb8bf28eb 11244 enum v7_tok tok1, enum v7_tok tok2) {
Marko Mikulicic 0:c0ecb8bf28eb 11245 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11246 if (*s < src_end && **s == ch1) {
Marko Mikulicic 0:c0ecb8bf28eb 11247 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11248 return tok1;
Marko Mikulicic 0:c0ecb8bf28eb 11249 } else {
Marko Mikulicic 0:c0ecb8bf28eb 11250 return tok2;
Marko Mikulicic 0:c0ecb8bf28eb 11251 }
Marko Mikulicic 0:c0ecb8bf28eb 11252 }
Marko Mikulicic 0:c0ecb8bf28eb 11253
Marko Mikulicic 0:c0ecb8bf28eb 11254 static enum v7_tok punct2(const char **s, const char *src_end, int ch1,
Marko Mikulicic 0:c0ecb8bf28eb 11255 enum v7_tok tok1, int ch2, enum v7_tok tok2,
Marko Mikulicic 0:c0ecb8bf28eb 11256 enum v7_tok tok3) {
Marko Mikulicic 0:c0ecb8bf28eb 11257 if ((*s + 2) < src_end && s[0][1] == ch1 && s[0][2] == ch2) {
Marko Mikulicic 0:c0ecb8bf28eb 11258 (*s) += 3;
Marko Mikulicic 0:c0ecb8bf28eb 11259 return tok2;
Marko Mikulicic 0:c0ecb8bf28eb 11260 }
Marko Mikulicic 0:c0ecb8bf28eb 11261
Marko Mikulicic 0:c0ecb8bf28eb 11262 return punct1(s, src_end, ch1, tok1, tok3);
Marko Mikulicic 0:c0ecb8bf28eb 11263 }
Marko Mikulicic 0:c0ecb8bf28eb 11264
Marko Mikulicic 0:c0ecb8bf28eb 11265 static enum v7_tok punct3(const char **s, const char *src_end, int ch1,
Marko Mikulicic 0:c0ecb8bf28eb 11266 enum v7_tok tok1, int ch2, enum v7_tok tok2,
Marko Mikulicic 0:c0ecb8bf28eb 11267 enum v7_tok tok3) {
Marko Mikulicic 0:c0ecb8bf28eb 11268 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11269 if (*s < src_end) {
Marko Mikulicic 0:c0ecb8bf28eb 11270 if (**s == ch1) {
Marko Mikulicic 0:c0ecb8bf28eb 11271 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11272 return tok1;
Marko Mikulicic 0:c0ecb8bf28eb 11273 } else if (**s == ch2) {
Marko Mikulicic 0:c0ecb8bf28eb 11274 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11275 return tok2;
Marko Mikulicic 0:c0ecb8bf28eb 11276 }
Marko Mikulicic 0:c0ecb8bf28eb 11277 }
Marko Mikulicic 0:c0ecb8bf28eb 11278 return tok3;
Marko Mikulicic 0:c0ecb8bf28eb 11279 }
Marko Mikulicic 0:c0ecb8bf28eb 11280
Marko Mikulicic 0:c0ecb8bf28eb 11281 static void parse_number(const char *s, const char **end, double *num) {
Marko Mikulicic 0:c0ecb8bf28eb 11282 *num = cs_strtod(s, (char **) end);
Marko Mikulicic 0:c0ecb8bf28eb 11283 }
Marko Mikulicic 0:c0ecb8bf28eb 11284
Marko Mikulicic 0:c0ecb8bf28eb 11285 static enum v7_tok parse_str_literal(const char **p, const char *src_end) {
Marko Mikulicic 0:c0ecb8bf28eb 11286 const char *s = *p;
Marko Mikulicic 0:c0ecb8bf28eb 11287 int quote = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 11288
Marko Mikulicic 0:c0ecb8bf28eb 11289 if (s < src_end) {
Marko Mikulicic 0:c0ecb8bf28eb 11290 quote = *s++;
Marko Mikulicic 0:c0ecb8bf28eb 11291 }
Marko Mikulicic 0:c0ecb8bf28eb 11292
Marko Mikulicic 0:c0ecb8bf28eb 11293 /* Scan string literal, handle escape sequences */
Marko Mikulicic 0:c0ecb8bf28eb 11294 for (; s < src_end && *s != '\0' && *s != quote; s++) {
Marko Mikulicic 0:c0ecb8bf28eb 11295 if (*s == '\\') {
Marko Mikulicic 0:c0ecb8bf28eb 11296 switch (s[1]) {
Marko Mikulicic 0:c0ecb8bf28eb 11297 case 'b':
Marko Mikulicic 0:c0ecb8bf28eb 11298 case 'f':
Marko Mikulicic 0:c0ecb8bf28eb 11299 case 'n':
Marko Mikulicic 0:c0ecb8bf28eb 11300 case 'r':
Marko Mikulicic 0:c0ecb8bf28eb 11301 case 't':
Marko Mikulicic 0:c0ecb8bf28eb 11302 case 'v':
Marko Mikulicic 0:c0ecb8bf28eb 11303 case '\\':
Marko Mikulicic 0:c0ecb8bf28eb 11304 s++;
Marko Mikulicic 0:c0ecb8bf28eb 11305 break;
Marko Mikulicic 0:c0ecb8bf28eb 11306 default:
Marko Mikulicic 0:c0ecb8bf28eb 11307 if (s[1] == quote) s++;
Marko Mikulicic 0:c0ecb8bf28eb 11308 break;
Marko Mikulicic 0:c0ecb8bf28eb 11309 }
Marko Mikulicic 0:c0ecb8bf28eb 11310 }
Marko Mikulicic 0:c0ecb8bf28eb 11311 }
Marko Mikulicic 0:c0ecb8bf28eb 11312
Marko Mikulicic 0:c0ecb8bf28eb 11313 if (s < src_end && *s == quote) {
Marko Mikulicic 0:c0ecb8bf28eb 11314 s++;
Marko Mikulicic 0:c0ecb8bf28eb 11315 *p = s;
Marko Mikulicic 0:c0ecb8bf28eb 11316 return TOK_STRING_LITERAL;
Marko Mikulicic 0:c0ecb8bf28eb 11317 } else {
Marko Mikulicic 0:c0ecb8bf28eb 11318 return TOK_END_OF_INPUT;
Marko Mikulicic 0:c0ecb8bf28eb 11319 }
Marko Mikulicic 0:c0ecb8bf28eb 11320 }
Marko Mikulicic 0:c0ecb8bf28eb 11321
Marko Mikulicic 0:c0ecb8bf28eb 11322 /*
Marko Mikulicic 0:c0ecb8bf28eb 11323 * This function is the heart of the tokenizer.
Marko Mikulicic 0:c0ecb8bf28eb 11324 * Organized as a giant switch statement.
Marko Mikulicic 0:c0ecb8bf28eb 11325 *
Marko Mikulicic 0:c0ecb8bf28eb 11326 * Switch statement is by the first character of the input stream. If first
Marko Mikulicic 0:c0ecb8bf28eb 11327 * character begins with a letter, it could be either keyword or identifier.
Marko Mikulicic 0:c0ecb8bf28eb 11328 * get_tok() calls ident() which shifts `s` pointer to the end of the word.
Marko Mikulicic 0:c0ecb8bf28eb 11329 * Now, tokenizer knows that the word begins at `p` and ends at `s`.
Marko Mikulicic 0:c0ecb8bf28eb 11330 * It calls function kw() to scan over the keywords that start with `p[0]`
Marko Mikulicic 0:c0ecb8bf28eb 11331 * letter. Therefore, keyword tokens and keyword strings must be in the
Marko Mikulicic 0:c0ecb8bf28eb 11332 * same order, to let kw() function work properly.
Marko Mikulicic 0:c0ecb8bf28eb 11333 * If kw() finds a keyword match, it returns keyword token.
Marko Mikulicic 0:c0ecb8bf28eb 11334 * Otherwise, it returns TOK_IDENTIFIER.
Marko Mikulicic 0:c0ecb8bf28eb 11335 * NOTE(lsm): `prev_tok` is a previously parsed token. It is needed for
Marko Mikulicic 0:c0ecb8bf28eb 11336 * correctly parsing regex literals.
Marko Mikulicic 0:c0ecb8bf28eb 11337 */
Marko Mikulicic 0:c0ecb8bf28eb 11338 V7_PRIVATE enum v7_tok get_tok(const char **s, const char *src_end, double *n,
Marko Mikulicic 0:c0ecb8bf28eb 11339 enum v7_tok prev_tok) {
Marko Mikulicic 0:c0ecb8bf28eb 11340 const char *p = *s;
Marko Mikulicic 0:c0ecb8bf28eb 11341
Marko Mikulicic 0:c0ecb8bf28eb 11342 if (p >= src_end) {
Marko Mikulicic 0:c0ecb8bf28eb 11343 return TOK_END_OF_INPUT;
Marko Mikulicic 0:c0ecb8bf28eb 11344 }
Marko Mikulicic 0:c0ecb8bf28eb 11345
Marko Mikulicic 0:c0ecb8bf28eb 11346 switch (*p) {
Marko Mikulicic 0:c0ecb8bf28eb 11347 /* Letters */
Marko Mikulicic 0:c0ecb8bf28eb 11348 case 'a':
Marko Mikulicic 0:c0ecb8bf28eb 11349 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11350 return TOK_IDENTIFIER;
Marko Mikulicic 0:c0ecb8bf28eb 11351 case 'b':
Marko Mikulicic 0:c0ecb8bf28eb 11352 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11353 return kw(p, *s - p, 1, TOK_BREAK);
Marko Mikulicic 0:c0ecb8bf28eb 11354 case 'c':
Marko Mikulicic 0:c0ecb8bf28eb 11355 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11356 return kw(p, *s - p, 3, TOK_CASE);
Marko Mikulicic 0:c0ecb8bf28eb 11357 case 'd':
Marko Mikulicic 0:c0ecb8bf28eb 11358 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11359 return kw(p, *s - p, 4, TOK_DEBUGGER);
Marko Mikulicic 0:c0ecb8bf28eb 11360 case 'e':
Marko Mikulicic 0:c0ecb8bf28eb 11361 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11362 return kw(p, *s - p, 1, TOK_ELSE);
Marko Mikulicic 0:c0ecb8bf28eb 11363 case 'f':
Marko Mikulicic 0:c0ecb8bf28eb 11364 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11365 return kw(p, *s - p, 4, TOK_FALSE);
Marko Mikulicic 0:c0ecb8bf28eb 11366 case 'g':
Marko Mikulicic 0:c0ecb8bf28eb 11367 case 'h':
Marko Mikulicic 0:c0ecb8bf28eb 11368 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11369 return TOK_IDENTIFIER;
Marko Mikulicic 0:c0ecb8bf28eb 11370 case 'i':
Marko Mikulicic 0:c0ecb8bf28eb 11371 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11372 return kw(p, *s - p, 3, TOK_IF);
Marko Mikulicic 0:c0ecb8bf28eb 11373 case 'j':
Marko Mikulicic 0:c0ecb8bf28eb 11374 case 'k':
Marko Mikulicic 0:c0ecb8bf28eb 11375 case 'l':
Marko Mikulicic 0:c0ecb8bf28eb 11376 case 'm':
Marko Mikulicic 0:c0ecb8bf28eb 11377 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11378 return TOK_IDENTIFIER;
Marko Mikulicic 0:c0ecb8bf28eb 11379 case 'n':
Marko Mikulicic 0:c0ecb8bf28eb 11380 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11381 return kw(p, *s - p, 2, TOK_NEW);
Marko Mikulicic 0:c0ecb8bf28eb 11382 case 'o':
Marko Mikulicic 0:c0ecb8bf28eb 11383 case 'p':
Marko Mikulicic 0:c0ecb8bf28eb 11384 case 'q':
Marko Mikulicic 0:c0ecb8bf28eb 11385 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11386 return TOK_IDENTIFIER;
Marko Mikulicic 0:c0ecb8bf28eb 11387 case 'r':
Marko Mikulicic 0:c0ecb8bf28eb 11388 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11389 return kw(p, *s - p, 1, TOK_RETURN);
Marko Mikulicic 0:c0ecb8bf28eb 11390 case 's':
Marko Mikulicic 0:c0ecb8bf28eb 11391 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11392 return kw(p, *s - p, 1, TOK_SWITCH);
Marko Mikulicic 0:c0ecb8bf28eb 11393 case 't':
Marko Mikulicic 0:c0ecb8bf28eb 11394 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11395 return kw(p, *s - p, 5, TOK_THIS);
Marko Mikulicic 0:c0ecb8bf28eb 11396 case 'u':
Marko Mikulicic 0:c0ecb8bf28eb 11397 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11398 return TOK_IDENTIFIER;
Marko Mikulicic 0:c0ecb8bf28eb 11399 case 'v':
Marko Mikulicic 0:c0ecb8bf28eb 11400 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11401 return kw(p, *s - p, 2, TOK_VAR);
Marko Mikulicic 0:c0ecb8bf28eb 11402 case 'w':
Marko Mikulicic 0:c0ecb8bf28eb 11403 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11404 return kw(p, *s - p, 2, TOK_WHILE);
Marko Mikulicic 0:c0ecb8bf28eb 11405 case 'x':
Marko Mikulicic 0:c0ecb8bf28eb 11406 case 'y':
Marko Mikulicic 0:c0ecb8bf28eb 11407 case 'z':
Marko Mikulicic 0:c0ecb8bf28eb 11408 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11409 return TOK_IDENTIFIER;
Marko Mikulicic 0:c0ecb8bf28eb 11410
Marko Mikulicic 0:c0ecb8bf28eb 11411 case '_':
Marko Mikulicic 0:c0ecb8bf28eb 11412 case '$':
Marko Mikulicic 0:c0ecb8bf28eb 11413 case 'A':
Marko Mikulicic 0:c0ecb8bf28eb 11414 case 'B':
Marko Mikulicic 0:c0ecb8bf28eb 11415 case 'C':
Marko Mikulicic 0:c0ecb8bf28eb 11416 case 'D':
Marko Mikulicic 0:c0ecb8bf28eb 11417 case 'E':
Marko Mikulicic 0:c0ecb8bf28eb 11418 case 'F':
Marko Mikulicic 0:c0ecb8bf28eb 11419 case 'G':
Marko Mikulicic 0:c0ecb8bf28eb 11420 case 'H':
Marko Mikulicic 0:c0ecb8bf28eb 11421 case 'I':
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 case 'N':
Marko Mikulicic 0:c0ecb8bf28eb 11427 case 'O':
Marko Mikulicic 0:c0ecb8bf28eb 11428 case 'P':
Marko Mikulicic 0:c0ecb8bf28eb 11429 case 'Q':
Marko Mikulicic 0:c0ecb8bf28eb 11430 case 'R':
Marko Mikulicic 0:c0ecb8bf28eb 11431 case 'S':
Marko Mikulicic 0:c0ecb8bf28eb 11432 case 'T':
Marko Mikulicic 0:c0ecb8bf28eb 11433 case 'U':
Marko Mikulicic 0:c0ecb8bf28eb 11434 case 'V':
Marko Mikulicic 0:c0ecb8bf28eb 11435 case 'W':
Marko Mikulicic 0:c0ecb8bf28eb 11436 case 'X':
Marko Mikulicic 0:c0ecb8bf28eb 11437 case 'Y':
Marko Mikulicic 0:c0ecb8bf28eb 11438 case 'Z':
Marko Mikulicic 0:c0ecb8bf28eb 11439 case '\\': /* Identifier may start with unicode escape sequence */
Marko Mikulicic 0:c0ecb8bf28eb 11440 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11441 return TOK_IDENTIFIER;
Marko Mikulicic 0:c0ecb8bf28eb 11442
Marko Mikulicic 0:c0ecb8bf28eb 11443 /* Numbers */
Marko Mikulicic 0:c0ecb8bf28eb 11444 case '0':
Marko Mikulicic 0:c0ecb8bf28eb 11445 case '1':
Marko Mikulicic 0:c0ecb8bf28eb 11446 case '2':
Marko Mikulicic 0:c0ecb8bf28eb 11447 case '3':
Marko Mikulicic 0:c0ecb8bf28eb 11448 case '4':
Marko Mikulicic 0:c0ecb8bf28eb 11449 case '5':
Marko Mikulicic 0:c0ecb8bf28eb 11450 case '6':
Marko Mikulicic 0:c0ecb8bf28eb 11451 case '7':
Marko Mikulicic 0:c0ecb8bf28eb 11452 case '8':
Marko Mikulicic 0:c0ecb8bf28eb 11453 case '9':
Marko Mikulicic 0:c0ecb8bf28eb 11454 parse_number(p, s, n);
Marko Mikulicic 0:c0ecb8bf28eb 11455 return TOK_NUMBER;
Marko Mikulicic 0:c0ecb8bf28eb 11456
Marko Mikulicic 0:c0ecb8bf28eb 11457 /* String literals */
Marko Mikulicic 0:c0ecb8bf28eb 11458 case '\'':
Marko Mikulicic 0:c0ecb8bf28eb 11459 case '"':
Marko Mikulicic 0:c0ecb8bf28eb 11460 return parse_str_literal(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11461
Marko Mikulicic 0:c0ecb8bf28eb 11462 /* Punctuators */
Marko Mikulicic 0:c0ecb8bf28eb 11463 case '=':
Marko Mikulicic 0:c0ecb8bf28eb 11464 return punct2(s, src_end, '=', TOK_EQ, '=', TOK_EQ_EQ, TOK_ASSIGN);
Marko Mikulicic 0:c0ecb8bf28eb 11465 case '!':
Marko Mikulicic 0:c0ecb8bf28eb 11466 return punct2(s, src_end, '=', TOK_NE, '=', TOK_NE_NE, TOK_NOT);
Marko Mikulicic 0:c0ecb8bf28eb 11467
Marko Mikulicic 0:c0ecb8bf28eb 11468 case '%':
Marko Mikulicic 0:c0ecb8bf28eb 11469 return punct1(s, src_end, '=', TOK_REM_ASSIGN, TOK_REM);
Marko Mikulicic 0:c0ecb8bf28eb 11470 case '*':
Marko Mikulicic 0:c0ecb8bf28eb 11471 return punct1(s, src_end, '=', TOK_MUL_ASSIGN, TOK_MUL);
Marko Mikulicic 0:c0ecb8bf28eb 11472 case '/':
Marko Mikulicic 0:c0ecb8bf28eb 11473 /*
Marko Mikulicic 0:c0ecb8bf28eb 11474 * TOK_DIV, TOK_DIV_ASSIGN, and TOK_REGEX_LITERAL start with `/` char.
Marko Mikulicic 0:c0ecb8bf28eb 11475 * Division can happen after an expression.
Marko Mikulicic 0:c0ecb8bf28eb 11476 * In expressions like this:
Marko Mikulicic 0:c0ecb8bf28eb 11477 * a /= b; c /= d;
Marko Mikulicic 0:c0ecb8bf28eb 11478 * things between slashes is NOT a regex literal.
Marko Mikulicic 0:c0ecb8bf28eb 11479 * The switch below catches all cases where division happens.
Marko Mikulicic 0:c0ecb8bf28eb 11480 */
Marko Mikulicic 0:c0ecb8bf28eb 11481 switch (prev_tok) {
Marko Mikulicic 0:c0ecb8bf28eb 11482 case TOK_CLOSE_CURLY:
Marko Mikulicic 0:c0ecb8bf28eb 11483 case TOK_CLOSE_PAREN:
Marko Mikulicic 0:c0ecb8bf28eb 11484 case TOK_CLOSE_BRACKET:
Marko Mikulicic 0:c0ecb8bf28eb 11485 case TOK_IDENTIFIER:
Marko Mikulicic 0:c0ecb8bf28eb 11486 case TOK_NUMBER:
Marko Mikulicic 0:c0ecb8bf28eb 11487 return punct1(s, src_end, '=', TOK_DIV_ASSIGN, TOK_DIV);
Marko Mikulicic 0:c0ecb8bf28eb 11488 default:
Marko Mikulicic 0:c0ecb8bf28eb 11489 /* Not a division - this is a regex. Scan until closing slash */
Marko Mikulicic 0:c0ecb8bf28eb 11490 for (p++; p < src_end && *p != '\0' && *p != '\n'; p++) {
Marko Mikulicic 0:c0ecb8bf28eb 11491 if (*p == '\\') {
Marko Mikulicic 0:c0ecb8bf28eb 11492 /* Skip escape sequence */
Marko Mikulicic 0:c0ecb8bf28eb 11493 p++;
Marko Mikulicic 0:c0ecb8bf28eb 11494 } else if (*p == '/') {
Marko Mikulicic 0:c0ecb8bf28eb 11495 /* This is a closing slash */
Marko Mikulicic 0:c0ecb8bf28eb 11496 p++;
Marko Mikulicic 0:c0ecb8bf28eb 11497 /* Skip regex flags */
Marko Mikulicic 0:c0ecb8bf28eb 11498 while (*p == 'g' || *p == 'i' || *p == 'm') {
Marko Mikulicic 0:c0ecb8bf28eb 11499 p++;
Marko Mikulicic 0:c0ecb8bf28eb 11500 }
Marko Mikulicic 0:c0ecb8bf28eb 11501 *s = p;
Marko Mikulicic 0:c0ecb8bf28eb 11502 return TOK_REGEX_LITERAL;
Marko Mikulicic 0:c0ecb8bf28eb 11503 }
Marko Mikulicic 0:c0ecb8bf28eb 11504 }
Marko Mikulicic 0:c0ecb8bf28eb 11505 break;
Marko Mikulicic 0:c0ecb8bf28eb 11506 }
Marko Mikulicic 0:c0ecb8bf28eb 11507 return punct1(s, src_end, '=', TOK_DIV_ASSIGN, TOK_DIV);
Marko Mikulicic 0:c0ecb8bf28eb 11508 case '^':
Marko Mikulicic 0:c0ecb8bf28eb 11509 return punct1(s, src_end, '=', TOK_XOR_ASSIGN, TOK_XOR);
Marko Mikulicic 0:c0ecb8bf28eb 11510
Marko Mikulicic 0:c0ecb8bf28eb 11511 case '+':
Marko Mikulicic 0:c0ecb8bf28eb 11512 return punct3(s, src_end, '+', TOK_PLUS_PLUS, '=', TOK_PLUS_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 11513 TOK_PLUS);
Marko Mikulicic 0:c0ecb8bf28eb 11514 case '-':
Marko Mikulicic 0:c0ecb8bf28eb 11515 return punct3(s, src_end, '-', TOK_MINUS_MINUS, '=', TOK_MINUS_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 11516 TOK_MINUS);
Marko Mikulicic 0:c0ecb8bf28eb 11517 case '&':
Marko Mikulicic 0:c0ecb8bf28eb 11518 return punct3(s, src_end, '&', TOK_LOGICAL_AND, '=', TOK_AND_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 11519 TOK_AND);
Marko Mikulicic 0:c0ecb8bf28eb 11520 case '|':
Marko Mikulicic 0:c0ecb8bf28eb 11521 return punct3(s, src_end, '|', TOK_LOGICAL_OR, '=', TOK_OR_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 11522 TOK_OR);
Marko Mikulicic 0:c0ecb8bf28eb 11523
Marko Mikulicic 0:c0ecb8bf28eb 11524 case '<':
Marko Mikulicic 0:c0ecb8bf28eb 11525 if (*s + 1 < src_end && s[0][1] == '=') {
Marko Mikulicic 0:c0ecb8bf28eb 11526 (*s) += 2;
Marko Mikulicic 0:c0ecb8bf28eb 11527 return TOK_LE;
Marko Mikulicic 0:c0ecb8bf28eb 11528 }
Marko Mikulicic 0:c0ecb8bf28eb 11529 return punct2(s, src_end, '<', TOK_LSHIFT, '=', TOK_LSHIFT_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 11530 TOK_LT);
Marko Mikulicic 0:c0ecb8bf28eb 11531 case '>':
Marko Mikulicic 0:c0ecb8bf28eb 11532 if (*s + 1 < src_end && s[0][1] == '=') {
Marko Mikulicic 0:c0ecb8bf28eb 11533 (*s) += 2;
Marko Mikulicic 0:c0ecb8bf28eb 11534 return TOK_GE;
Marko Mikulicic 0:c0ecb8bf28eb 11535 }
Marko Mikulicic 0:c0ecb8bf28eb 11536 if (*s + 3 < src_end && s[0][1] == '>' && s[0][2] == '>' &&
Marko Mikulicic 0:c0ecb8bf28eb 11537 s[0][3] == '=') {
Marko Mikulicic 0:c0ecb8bf28eb 11538 (*s) += 4;
Marko Mikulicic 0:c0ecb8bf28eb 11539 return TOK_URSHIFT_ASSIGN;
Marko Mikulicic 0:c0ecb8bf28eb 11540 }
Marko Mikulicic 0:c0ecb8bf28eb 11541 if (*s + 2 < src_end && s[0][1] == '>' && s[0][2] == '>') {
Marko Mikulicic 0:c0ecb8bf28eb 11542 (*s) += 3;
Marko Mikulicic 0:c0ecb8bf28eb 11543 return TOK_URSHIFT;
Marko Mikulicic 0:c0ecb8bf28eb 11544 }
Marko Mikulicic 0:c0ecb8bf28eb 11545 return punct2(s, src_end, '>', TOK_RSHIFT, '=', TOK_RSHIFT_ASSIGN,
Marko Mikulicic 0:c0ecb8bf28eb 11546 TOK_GT);
Marko Mikulicic 0:c0ecb8bf28eb 11547
Marko Mikulicic 0:c0ecb8bf28eb 11548 case '{':
Marko Mikulicic 0:c0ecb8bf28eb 11549 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11550 return TOK_OPEN_CURLY;
Marko Mikulicic 0:c0ecb8bf28eb 11551 case '}':
Marko Mikulicic 0:c0ecb8bf28eb 11552 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11553 return TOK_CLOSE_CURLY;
Marko Mikulicic 0:c0ecb8bf28eb 11554 case '(':
Marko Mikulicic 0:c0ecb8bf28eb 11555 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11556 return TOK_OPEN_PAREN;
Marko Mikulicic 0:c0ecb8bf28eb 11557 case ')':
Marko Mikulicic 0:c0ecb8bf28eb 11558 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11559 return TOK_CLOSE_PAREN;
Marko Mikulicic 0:c0ecb8bf28eb 11560 case '[':
Marko Mikulicic 0:c0ecb8bf28eb 11561 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11562 return TOK_OPEN_BRACKET;
Marko Mikulicic 0:c0ecb8bf28eb 11563 case ']':
Marko Mikulicic 0:c0ecb8bf28eb 11564 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11565 return TOK_CLOSE_BRACKET;
Marko Mikulicic 0:c0ecb8bf28eb 11566 case '.':
Marko Mikulicic 0:c0ecb8bf28eb 11567 switch (*(*s + 1)) {
Marko Mikulicic 0:c0ecb8bf28eb 11568 /* Numbers */
Marko Mikulicic 0:c0ecb8bf28eb 11569 case '0':
Marko Mikulicic 0:c0ecb8bf28eb 11570 case '1':
Marko Mikulicic 0:c0ecb8bf28eb 11571 case '2':
Marko Mikulicic 0:c0ecb8bf28eb 11572 case '3':
Marko Mikulicic 0:c0ecb8bf28eb 11573 case '4':
Marko Mikulicic 0:c0ecb8bf28eb 11574 case '5':
Marko Mikulicic 0:c0ecb8bf28eb 11575 case '6':
Marko Mikulicic 0:c0ecb8bf28eb 11576 case '7':
Marko Mikulicic 0:c0ecb8bf28eb 11577 case '8':
Marko Mikulicic 0:c0ecb8bf28eb 11578 case '9':
Marko Mikulicic 0:c0ecb8bf28eb 11579 parse_number(p, s, n);
Marko Mikulicic 0:c0ecb8bf28eb 11580 return TOK_NUMBER;
Marko Mikulicic 0:c0ecb8bf28eb 11581 }
Marko Mikulicic 0:c0ecb8bf28eb 11582 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11583 return TOK_DOT;
Marko Mikulicic 0:c0ecb8bf28eb 11584 case ';':
Marko Mikulicic 0:c0ecb8bf28eb 11585 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11586 return TOK_SEMICOLON;
Marko Mikulicic 0:c0ecb8bf28eb 11587 case ':':
Marko Mikulicic 0:c0ecb8bf28eb 11588 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11589 return TOK_COLON;
Marko Mikulicic 0:c0ecb8bf28eb 11590 case '?':
Marko Mikulicic 0:c0ecb8bf28eb 11591 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11592 return TOK_QUESTION;
Marko Mikulicic 0:c0ecb8bf28eb 11593 case '~':
Marko Mikulicic 0:c0ecb8bf28eb 11594 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11595 return TOK_TILDA;
Marko Mikulicic 0:c0ecb8bf28eb 11596 case ',':
Marko Mikulicic 0:c0ecb8bf28eb 11597 (*s)++;
Marko Mikulicic 0:c0ecb8bf28eb 11598 return TOK_COMMA;
Marko Mikulicic 0:c0ecb8bf28eb 11599
Marko Mikulicic 0:c0ecb8bf28eb 11600 default: {
Marko Mikulicic 0:c0ecb8bf28eb 11601 /* Handle unicode variables */
Marko Mikulicic 0:c0ecb8bf28eb 11602 Rune r;
Marko Mikulicic 0:c0ecb8bf28eb 11603 if (chartorune(&r, *s) > 1 && isalpharune(r)) {
Marko Mikulicic 0:c0ecb8bf28eb 11604 ident(s, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11605 return TOK_IDENTIFIER;
Marko Mikulicic 0:c0ecb8bf28eb 11606 }
Marko Mikulicic 0:c0ecb8bf28eb 11607 return TOK_END_OF_INPUT;
Marko Mikulicic 0:c0ecb8bf28eb 11608 }
Marko Mikulicic 0:c0ecb8bf28eb 11609 }
Marko Mikulicic 0:c0ecb8bf28eb 11610 }
Marko Mikulicic 0:c0ecb8bf28eb 11611
Marko Mikulicic 0:c0ecb8bf28eb 11612 #ifdef TEST_RUN
Marko Mikulicic 0:c0ecb8bf28eb 11613 int main(void) {
Marko Mikulicic 0:c0ecb8bf28eb 11614 const char *src =
Marko Mikulicic 0:c0ecb8bf28eb 11615 "for (var fo++ = -1; /= <= 1.17; x<<) { == <<=, 'x')} "
Marko Mikulicic 0:c0ecb8bf28eb 11616 "Infinity %=x<<=2";
Marko Mikulicic 0:c0ecb8bf28eb 11617 const char *src_end = src + strlen(src);
Marko Mikulicic 0:c0ecb8bf28eb 11618 enum v7_tok tok;
Marko Mikulicic 0:c0ecb8bf28eb 11619 double num;
Marko Mikulicic 0:c0ecb8bf28eb 11620 const char *p = src;
Marko Mikulicic 0:c0ecb8bf28eb 11621
Marko Mikulicic 0:c0ecb8bf28eb 11622 skip_to_next_tok(&src, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11623 while ((tok = get_tok(&src, src_end, &num)) != TOK_END_OF_INPUT) {
Marko Mikulicic 0:c0ecb8bf28eb 11624 printf("%d [%.*s]\n", tok, (int) (src - p), p);
Marko Mikulicic 0:c0ecb8bf28eb 11625 skip_to_next_tok(&src, src_end);
Marko Mikulicic 0:c0ecb8bf28eb 11626 p = src;
Marko Mikulicic 0:c0ecb8bf28eb 11627 }
Marko Mikulicic 0:c0ecb8bf28eb 11628 printf("%d [%.*s]\n", tok, (int) (src - p), p);
Marko Mikulicic 0:c0ecb8bf28eb 11629
Marko Mikulicic 0:c0ecb8bf28eb 11630 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 11631 }
Marko Mikulicic 0:c0ecb8bf28eb 11632 #endif
Marko Mikulicic 0:c0ecb8bf28eb 11633
Marko Mikulicic 0:c0ecb8bf28eb 11634 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 11635 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 11636 #line 1 "v7/src/ast.c"
Marko Mikulicic 0:c0ecb8bf28eb 11637 #endif
Marko Mikulicic 0:c0ecb8bf28eb 11638 /*
Marko Mikulicic 0:c0ecb8bf28eb 11639 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 11640 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 11641 */
Marko Mikulicic 0:c0ecb8bf28eb 11642
Marko Mikulicic 0:c0ecb8bf28eb 11643 /* Amalgamated: #include "common/cs_strtod.h" */
Marko Mikulicic 0:c0ecb8bf28eb 11644 /* Amalgamated: #include "common/mbuf.h" */
Marko Mikulicic 0:c0ecb8bf28eb 11645
Marko Mikulicic 0:c0ecb8bf28eb 11646 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 11647 /* Amalgamated: #include "v7/src/varint.h" */
Marko Mikulicic 0:c0ecb8bf28eb 11648 /* Amalgamated: #include "v7/src/ast.h" */
Marko Mikulicic 0:c0ecb8bf28eb 11649 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 11650 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 11651 /* Amalgamated: #include "common/str_util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 11652
Marko Mikulicic 0:c0ecb8bf28eb 11653 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 11654
Marko Mikulicic 0:c0ecb8bf28eb 11655 #ifdef V7_LARGE_AST
Marko Mikulicic 0:c0ecb8bf28eb 11656 typedef uint32_t ast_skip_t;
Marko Mikulicic 0:c0ecb8bf28eb 11657 #else
Marko Mikulicic 0:c0ecb8bf28eb 11658 typedef uint16_t ast_skip_t;
Marko Mikulicic 0:c0ecb8bf28eb 11659 #define AST_SKIP_MAX UINT16_MAX
Marko Mikulicic 0:c0ecb8bf28eb 11660 #endif
Marko Mikulicic 0:c0ecb8bf28eb 11661
Marko Mikulicic 0:c0ecb8bf28eb 11662 #ifndef V7_DISABLE_AST_TAG_NAMES
Marko Mikulicic 0:c0ecb8bf28eb 11663 #define AST_ENTRY(name, has_varint, has_inlined, num_skips, num_subtrees) \
Marko Mikulicic 0:c0ecb8bf28eb 11664 { (name), (has_varint), (has_inlined), (num_skips), (num_subtrees) }
Marko Mikulicic 0:c0ecb8bf28eb 11665 #else
Marko Mikulicic 0:c0ecb8bf28eb 11666 #define AST_ENTRY(name, has_varint, has_inlined, num_skips, num_subtrees) \
Marko Mikulicic 0:c0ecb8bf28eb 11667 { (has_varint), (has_inlined), (num_skips), (num_subtrees) }
Marko Mikulicic 0:c0ecb8bf28eb 11668 #endif
Marko Mikulicic 0:c0ecb8bf28eb 11669
Marko Mikulicic 0:c0ecb8bf28eb 11670 /*
Marko Mikulicic 0:c0ecb8bf28eb 11671 * The structure of AST nodes cannot be described in portable ANSI C,
Marko Mikulicic 0:c0ecb8bf28eb 11672 * since they are variable length and packed (unaligned).
Marko Mikulicic 0:c0ecb8bf28eb 11673 *
Marko Mikulicic 0:c0ecb8bf28eb 11674 * Here each node's body is described with a pseudo-C structure notation.
Marko Mikulicic 0:c0ecb8bf28eb 11675 * The pseudo type `child` represents a variable length byte sequence
Marko Mikulicic 0:c0ecb8bf28eb 11676 * representing a fully serialized child node.
Marko Mikulicic 0:c0ecb8bf28eb 11677 *
Marko Mikulicic 0:c0ecb8bf28eb 11678 * `child body[]` represents a sequence of such subtrees.
Marko Mikulicic 0:c0ecb8bf28eb 11679 *
Marko Mikulicic 0:c0ecb8bf28eb 11680 * Pseudo-labels, such as `end:` represent the targets of skip fields
Marko Mikulicic 0:c0ecb8bf28eb 11681 * with the same name (e.g. `ast_skip_t end`).
Marko Mikulicic 0:c0ecb8bf28eb 11682 *
Marko Mikulicic 0:c0ecb8bf28eb 11683 * Skips allow skipping a subtree or sequence of subtrees.
Marko Mikulicic 0:c0ecb8bf28eb 11684 *
Marko Mikulicic 0:c0ecb8bf28eb 11685 * Sequences of subtrees (i.e. `child []`) have to be terminated by a skip:
Marko Mikulicic 0:c0ecb8bf28eb 11686 * they don't have a termination tag; all nodes whose position is before the
Marko Mikulicic 0:c0ecb8bf28eb 11687 * skip are part of the sequence.
Marko Mikulicic 0:c0ecb8bf28eb 11688 *
Marko Mikulicic 0:c0ecb8bf28eb 11689 * Skips are encoded as network-byte-order 16-bit offsets counted from the
Marko Mikulicic 0:c0ecb8bf28eb 11690 * first byte of the node body (i.e. not counting the tag itself).
Marko Mikulicic 0:c0ecb8bf28eb 11691 * This currently limits the the maximum size of a function body to 64k.
Marko Mikulicic 0:c0ecb8bf28eb 11692 *
Marko Mikulicic 0:c0ecb8bf28eb 11693 * Notes:
Marko Mikulicic 0:c0ecb8bf28eb 11694 *
Marko Mikulicic 0:c0ecb8bf28eb 11695 * - Some nodes contain skips just for performance or because it simplifies
Marko Mikulicic 0:c0ecb8bf28eb 11696 * the implementation of the interpreter. For example, technically, the FOR
Marko Mikulicic 0:c0ecb8bf28eb 11697 * node doesn't need the `body` skip in order to be correctly traversed.
Marko Mikulicic 0:c0ecb8bf28eb 11698 * However, being able to quickly skip the `iter` expression is useful
Marko Mikulicic 0:c0ecb8bf28eb 11699 * also because it allows the interpreter to avoid traversing the expression
Marko Mikulicic 0:c0ecb8bf28eb 11700 * subtree without evaluating it, just in order to find the next subtree.
Marko Mikulicic 0:c0ecb8bf28eb 11701 *
Marko Mikulicic 0:c0ecb8bf28eb 11702 * - The name `skip` was chosen because `offset` was too overloaded in general
Marko Mikulicic 0:c0ecb8bf28eb 11703 * and label` is part of our domain model (i.e. JS has a label AST node type).
Marko Mikulicic 0:c0ecb8bf28eb 11704 *
Marko Mikulicic 0:c0ecb8bf28eb 11705 *
Marko Mikulicic 0:c0ecb8bf28eb 11706 * So, each node has a mandatory field: *tag* (see `enum ast_tag`), and a
Marko Mikulicic 0:c0ecb8bf28eb 11707 * number of optional fields. Whether the node has one or another optional
Marko Mikulicic 0:c0ecb8bf28eb 11708 * field is determined by the *node descriptor*: `struct ast_node_def`. For
Marko Mikulicic 0:c0ecb8bf28eb 11709 * each node type (i.e. for each element of `enum ast_tag`) there is a
Marko Mikulicic 0:c0ecb8bf28eb 11710 * corresponding descriptor: see `ast_node_defs`.
Marko Mikulicic 0:c0ecb8bf28eb 11711 *
Marko Mikulicic 0:c0ecb8bf28eb 11712 * Optional fields are:
Marko Mikulicic 0:c0ecb8bf28eb 11713 *
Marko Mikulicic 0:c0ecb8bf28eb 11714 * - *varint*: a varint-encoded number. At the moment, this field is only used
Marko Mikulicic 0:c0ecb8bf28eb 11715 * together with the next field: inlined data, and a varint number determines
Marko Mikulicic 0:c0ecb8bf28eb 11716 * the inlined data length.
Marko Mikulicic 0:c0ecb8bf28eb 11717 * - *inlined data*: a node-specific data. Size of it is determined by the
Marko Mikulicic 0:c0ecb8bf28eb 11718 * previous field: varint.
Marko Mikulicic 0:c0ecb8bf28eb 11719 * - *skips*: as explained above, these are integer offsets, encoded in
Marko Mikulicic 0:c0ecb8bf28eb 11720 * big-endian. The number of skips is determined by the node descriptor
Marko Mikulicic 0:c0ecb8bf28eb 11721 * (`struct ast_node_def`). The size of each skip is either 16 or 32 bits,
Marko Mikulicic 0:c0ecb8bf28eb 11722 * depending on whether the macro `V7_LARGE_AST` is set. The order of skips
Marko Mikulicic 0:c0ecb8bf28eb 11723 * is determined by the `enum ast_which_skip`. See examples below for
Marko Mikulicic 0:c0ecb8bf28eb 11724 * clarity.
Marko Mikulicic 0:c0ecb8bf28eb 11725 * - *subtrees*: child nodes. Some nodes have fixed number of child nodes; in
Marko Mikulicic 0:c0ecb8bf28eb 11726 * this case, the descriptor has non-zero field `num_subtrees`. Otherwise,
Marko Mikulicic 0:c0ecb8bf28eb 11727 * `num_subtrees` is zero, and consumer handles child nodes one by one, until
Marko Mikulicic 0:c0ecb8bf28eb 11728 * the end of the node is reached (end of the node is determined by the `end`
Marko Mikulicic 0:c0ecb8bf28eb 11729 * skip)
Marko Mikulicic 0:c0ecb8bf28eb 11730 *
Marko Mikulicic 0:c0ecb8bf28eb 11731 *
Marko Mikulicic 0:c0ecb8bf28eb 11732 * Examples:
Marko Mikulicic 0:c0ecb8bf28eb 11733 *
Marko Mikulicic 0:c0ecb8bf28eb 11734 * Let's start from the very easy example script: "300;"
Marko Mikulicic 0:c0ecb8bf28eb 11735 *
Marko Mikulicic 0:c0ecb8bf28eb 11736 * Tree looks as follows:
Marko Mikulicic 0:c0ecb8bf28eb 11737 *
Marko Mikulicic 0:c0ecb8bf28eb 11738 * $ ./v7 -e "300;" -t
Marko Mikulicic 0:c0ecb8bf28eb 11739 * SCRIPT
Marko Mikulicic 0:c0ecb8bf28eb 11740 * /- [...] -/
Marko Mikulicic 0:c0ecb8bf28eb 11741 * NUM 300
Marko Mikulicic 0:c0ecb8bf28eb 11742 *
Marko Mikulicic 0:c0ecb8bf28eb 11743 * Binary data is:
Marko Mikulicic 0:c0ecb8bf28eb 11744 *
Marko Mikulicic 0:c0ecb8bf28eb 11745 * $ ./v7 -e "300;" -b | od -A n -t x1
Marko Mikulicic 0:c0ecb8bf28eb 11746 * 56 07 41 53 54 56 31 30 00 01 00 09 00 00 13 03
Marko Mikulicic 0:c0ecb8bf28eb 11747 * 33 30 30
Marko Mikulicic 0:c0ecb8bf28eb 11748 *
Marko Mikulicic 0:c0ecb8bf28eb 11749 * Let's break it down and examine:
Marko Mikulicic 0:c0ecb8bf28eb 11750 *
Marko Mikulicic 0:c0ecb8bf28eb 11751 * - 56 07 41 53 54 56 31 30 00
Marko Mikulicic 0:c0ecb8bf28eb 11752 * Just a format prefix:
Marko Mikulicic 0:c0ecb8bf28eb 11753 * Null-terminated string: `"V\007ASTV10"` (see `BIN_AST_SIGNATURE`)
Marko Mikulicic 0:c0ecb8bf28eb 11754 * - 01
Marko Mikulicic 0:c0ecb8bf28eb 11755 * AST tag: `AST_SCRIPT`. As you see in `ast_node_defs` below, node of
Marko Mikulicic 0:c0ecb8bf28eb 11756 * this type has neither *varint* nor *inlined data* fields, but it has
Marko Mikulicic 0:c0ecb8bf28eb 11757 * 2 skips: `end` and `next`. `end` is a skip to the end of the current
Marko Mikulicic 0:c0ecb8bf28eb 11758 * node (`SCRIPT`), and `next` will be explained below.
Marko Mikulicic 0:c0ecb8bf28eb 11759 *
Marko Mikulicic 0:c0ecb8bf28eb 11760 * The size of each skip depends on whether `V7_LARGE_AST` is defined.
Marko Mikulicic 0:c0ecb8bf28eb 11761 * If it is, then size is 32 bit, otherwise it's 16 bit. In this
Marko Mikulicic 0:c0ecb8bf28eb 11762 * example, we have 16-bit skips.
Marko Mikulicic 0:c0ecb8bf28eb 11763 *
Marko Mikulicic 0:c0ecb8bf28eb 11764 * The order of skips is determined by the `enum ast_which_skip`. If you
Marko Mikulicic 0:c0ecb8bf28eb 11765 * check, you'll see that `AST_END_SKIP` is 0, and `AST_VAR_NEXT_SKIP`
Marko Mikulicic 0:c0ecb8bf28eb 11766 * is 1. So, `end` skip fill be the first, and `next` will be the second:
Marko Mikulicic 0:c0ecb8bf28eb 11767 * - 00 09
Marko Mikulicic 0:c0ecb8bf28eb 11768 * `end` skip: 9 bytes. It's the size of the whole `SCRIPT` data. So, if
Marko Mikulicic 0:c0ecb8bf28eb 11769 * we have an index of the `ASC_SCRIPT` tag, we can just add this skip
Marko Mikulicic 0:c0ecb8bf28eb 11770 * (9) to this index, and therefore skip over the whole node.
Marko Mikulicic 0:c0ecb8bf28eb 11771 * - 00 00
Marko Mikulicic 0:c0ecb8bf28eb 11772 * `next` skip. `next` actually means "next variable node": since
Marko Mikulicic 0:c0ecb8bf28eb 11773 * variables are hoisted in JavaScript, when the interpreter starts
Marko Mikulicic 0:c0ecb8bf28eb 11774 * executing a top-level code or any function, it needs to get a list of
Marko Mikulicic 0:c0ecb8bf28eb 11775 * all defined variables. The `SCRIPT` node has a "skip" to the first
Marko Mikulicic 0:c0ecb8bf28eb 11776 * `var` or `function` declaration, which, in turn, has a "skip" to the
Marko Mikulicic 0:c0ecb8bf28eb 11777 * next one, etc. If there is no next `var` declaration, then 0 is
Marko Mikulicic 0:c0ecb8bf28eb 11778 * stored.
Marko Mikulicic 0:c0ecb8bf28eb 11779 *
Marko Mikulicic 0:c0ecb8bf28eb 11780 * In our super-simple script, we have no `var` neither `function`
Marko Mikulicic 0:c0ecb8bf28eb 11781 * declarations, so, this skip is 0.
Marko Mikulicic 0:c0ecb8bf28eb 11782 *
Marko Mikulicic 0:c0ecb8bf28eb 11783 * Now, the body of our SCRIPT node goes, which contains child nodes:
Marko Mikulicic 0:c0ecb8bf28eb 11784 *
Marko Mikulicic 0:c0ecb8bf28eb 11785 * - 13
Marko Mikulicic 0:c0ecb8bf28eb 11786 * AST tag: `AST_NUM`. Look at the `ast_node_defs`, and we'll see that
Marko Mikulicic 0:c0ecb8bf28eb 11787 * nodes of this type don't have any skips, but they do have the varint
Marko Mikulicic 0:c0ecb8bf28eb 11788 * field and the inlined data. Here we go:
Marko Mikulicic 0:c0ecb8bf28eb 11789 * - 03
Marko Mikulicic 0:c0ecb8bf28eb 11790 * Varint value: 3
Marko Mikulicic 0:c0ecb8bf28eb 11791 * - 33 30 30
Marko Mikulicic 0:c0ecb8bf28eb 11792 * UTF-8 string "300"
Marko Mikulicic 0:c0ecb8bf28eb 11793 *
Marko Mikulicic 0:c0ecb8bf28eb 11794 * ---------------
Marko Mikulicic 0:c0ecb8bf28eb 11795 *
Marko Mikulicic 0:c0ecb8bf28eb 11796 * The next example is a bit more interesting:
Marko Mikulicic 0:c0ecb8bf28eb 11797 *
Marko Mikulicic 0:c0ecb8bf28eb 11798 * var foo,
Marko Mikulicic 0:c0ecb8bf28eb 11799 * bar = 1;
Marko Mikulicic 0:c0ecb8bf28eb 11800 * foo = 3;
Marko Mikulicic 0:c0ecb8bf28eb 11801 * var baz = 4;
Marko Mikulicic 0:c0ecb8bf28eb 11802 *
Marko Mikulicic 0:c0ecb8bf28eb 11803 * Tree:
Marko Mikulicic 0:c0ecb8bf28eb 11804 *
Marko Mikulicic 0:c0ecb8bf28eb 11805 * $ ./v7 -e 'var foo, bar=1; foo=3; var baz = 4;' -t
Marko Mikulicic 0:c0ecb8bf28eb 11806 * SCRIPT
Marko Mikulicic 0:c0ecb8bf28eb 11807 * /- [...] -/
Marko Mikulicic 0:c0ecb8bf28eb 11808 * VAR
Marko Mikulicic 0:c0ecb8bf28eb 11809 * /- [...] -/
Marko Mikulicic 0:c0ecb8bf28eb 11810 * VAR_DECL foo
Marko Mikulicic 0:c0ecb8bf28eb 11811 * NOP
Marko Mikulicic 0:c0ecb8bf28eb 11812 * VAR_DECL bar
Marko Mikulicic 0:c0ecb8bf28eb 11813 * NUM 1
Marko Mikulicic 0:c0ecb8bf28eb 11814 * ASSIGN
Marko Mikulicic 0:c0ecb8bf28eb 11815 * IDENT foo
Marko Mikulicic 0:c0ecb8bf28eb 11816 * NUM 3
Marko Mikulicic 0:c0ecb8bf28eb 11817 * VAR
Marko Mikulicic 0:c0ecb8bf28eb 11818 * /- [...] -/
Marko Mikulicic 0:c0ecb8bf28eb 11819 * VAR_DECL baz
Marko Mikulicic 0:c0ecb8bf28eb 11820 * NUM 4
Marko Mikulicic 0:c0ecb8bf28eb 11821 *
Marko Mikulicic 0:c0ecb8bf28eb 11822 * Binary:
Marko Mikulicic 0:c0ecb8bf28eb 11823 *
Marko Mikulicic 0:c0ecb8bf28eb 11824 * $ ./v7 -e 'var foo, bar=1; foo=3; var baz = 4;' -b | od -A n -t x1
Marko Mikulicic 0:c0ecb8bf28eb 11825 * 56 07 41 53 54 56 31 30 00 01 00 2d 00 05 02 00
Marko Mikulicic 0:c0ecb8bf28eb 11826 * 12 00 1c 03 03 66 6f 6f 00 03 03 62 61 72 13 01
Marko Mikulicic 0:c0ecb8bf28eb 11827 * 31 07 14 03 66 6f 6f 13 01 33 02 00 0c 00 00 03
Marko Mikulicic 0:c0ecb8bf28eb 11828 * 03 62 61 7a 13 01 34
Marko Mikulicic 0:c0ecb8bf28eb 11829 *
Marko Mikulicic 0:c0ecb8bf28eb 11830 * Break it down:
Marko Mikulicic 0:c0ecb8bf28eb 11831 *
Marko Mikulicic 0:c0ecb8bf28eb 11832 * - 56 07 41 53 54 56 31 30 00
Marko Mikulicic 0:c0ecb8bf28eb 11833 * `"V\007ASTV10"`
Marko Mikulicic 0:c0ecb8bf28eb 11834 * - 01: AST tag: `AST_SCRIPT`
Marko Mikulicic 0:c0ecb8bf28eb 11835 * - 00 2d: `end` skip: 0x2d = 45 bytes
Marko Mikulicic 0:c0ecb8bf28eb 11836 * - 00 05: `next` skip: an offset from `AST_SCRIPT` byte to the first
Marko Mikulicic 0:c0ecb8bf28eb 11837 * `var` declaration.
Marko Mikulicic 0:c0ecb8bf28eb 11838 *
Marko Mikulicic 0:c0ecb8bf28eb 11839 * Now, body of the SCRIPT node begins, which contains child nodes,
Marko Mikulicic 0:c0ecb8bf28eb 11840 * and the first node is the var declaration `var foo, bar=1;`:
Marko Mikulicic 0:c0ecb8bf28eb 11841 *
Marko Mikulicic 0:c0ecb8bf28eb 11842 * SCRIPT node body: {{{
Marko Mikulicic 0:c0ecb8bf28eb 11843 * - 02: AST tag: `AST_VAR`
Marko Mikulicic 0:c0ecb8bf28eb 11844 * - 00 12: `end` skip: 18 bytes from tag byte to the end of current node
Marko Mikulicic 0:c0ecb8bf28eb 11845 * - 00 1c: `next` skip: 28 bytes from tag byte to the next `var` node
Marko Mikulicic 0:c0ecb8bf28eb 11846 *
Marko Mikulicic 0:c0ecb8bf28eb 11847 * The VAR node contains arbitrary number of child nodes, so, consumer
Marko Mikulicic 0:c0ecb8bf28eb 11848 * takes advantage of the `end` skip.
Marko Mikulicic 0:c0ecb8bf28eb 11849 *
Marko Mikulicic 0:c0ecb8bf28eb 11850 * VAR node body: {{{
Marko Mikulicic 0:c0ecb8bf28eb 11851 * - 03: AST tag: `AST_VAR_DECL`
Marko Mikulicic 0:c0ecb8bf28eb 11852 * - 03: Varint value: 3 (the length of the inlined data: a variable
Marko Mikulicic 0:c0ecb8bf28eb 11853 *name)
Marko Mikulicic 0:c0ecb8bf28eb 11854 * - 66 6f 6f: UTF-8 string: "foo"
Marko Mikulicic 0:c0ecb8bf28eb 11855 * - 00: AST tag: `AST_NOP`
Marko Mikulicic 0:c0ecb8bf28eb 11856 * Since we haven't provided any value to store into `foo`, NOP
Marko Mikulicic 0:c0ecb8bf28eb 11857 * without any additional data is stored in AST.
Marko Mikulicic 0:c0ecb8bf28eb 11858 *
Marko Mikulicic 0:c0ecb8bf28eb 11859 * - 03: AST tag: `AST_VAR_DECL`
Marko Mikulicic 0:c0ecb8bf28eb 11860 * - 03: Varint value: 3 (the length of the inlined data: a variable
Marko Mikulicic 0:c0ecb8bf28eb 11861 *name)
Marko Mikulicic 0:c0ecb8bf28eb 11862 * - 62 61 72: UTF-8 string: "bar"
Marko Mikulicic 0:c0ecb8bf28eb 11863 * - 13: AST tag: `AST_NUM`
Marko Mikulicic 0:c0ecb8bf28eb 11864 * - 01: Varint value: 1
Marko Mikulicic 0:c0ecb8bf28eb 11865 * - 31: UTF-8 string "1"
Marko Mikulicic 0:c0ecb8bf28eb 11866 * VAR body end }}}
Marko Mikulicic 0:c0ecb8bf28eb 11867 *
Marko Mikulicic 0:c0ecb8bf28eb 11868 * - 07: AST tag: `AST_ASSIGN`
Marko Mikulicic 0:c0ecb8bf28eb 11869 *
Marko Mikulicic 0:c0ecb8bf28eb 11870 * The ASSIGN node has fixed number of subrees: 2 (lvalue and rvalue),
Marko Mikulicic 0:c0ecb8bf28eb 11871 * so there's no `end` skip.
Marko Mikulicic 0:c0ecb8bf28eb 11872 *
Marko Mikulicic 0:c0ecb8bf28eb 11873 * ASSIGN node body: {{{
Marko Mikulicic 0:c0ecb8bf28eb 11874 * - 14: AST tag: `AST_IDENT`
Marko Mikulicic 0:c0ecb8bf28eb 11875 * - 03: Varint value: 3
Marko Mikulicic 0:c0ecb8bf28eb 11876 * - 66 6f 6f: UTF-8 string: "foo"
Marko Mikulicic 0:c0ecb8bf28eb 11877 *
Marko Mikulicic 0:c0ecb8bf28eb 11878 * - 13: AST tag: `AST_NUM`
Marko Mikulicic 0:c0ecb8bf28eb 11879 * - 01: Varint value: 1
Marko Mikulicic 0:c0ecb8bf28eb 11880 * - 33: UTF-8 string: "3"
Marko Mikulicic 0:c0ecb8bf28eb 11881 * ASSIGN body end }}}
Marko Mikulicic 0:c0ecb8bf28eb 11882 *
Marko Mikulicic 0:c0ecb8bf28eb 11883 * - 02: AST tag: `AST_VAR`
Marko Mikulicic 0:c0ecb8bf28eb 11884 * - 00 0c: `end` skip: 12 bytes from tag byte to the end of current node
Marko Mikulicic 0:c0ecb8bf28eb 11885 * - 00 00: `next` skip: no more `var` nodes
Marko Mikulicic 0:c0ecb8bf28eb 11886 *
Marko Mikulicic 0:c0ecb8bf28eb 11887 * VAR node body: {{{
Marko Mikulicic 0:c0ecb8bf28eb 11888 * - 03: AST tag: `AST_VAR_DECL`
Marko Mikulicic 0:c0ecb8bf28eb 11889 * - 03: Varint value: 3 (the length of the inlined data: a variable
Marko Mikulicic 0:c0ecb8bf28eb 11890 *name)
Marko Mikulicic 0:c0ecb8bf28eb 11891 * - 62 61 7a: UTF-8 string: "baz"
Marko Mikulicic 0:c0ecb8bf28eb 11892 * - 13: AST tag: `AST_NUM`
Marko Mikulicic 0:c0ecb8bf28eb 11893 * - 01: Varint value: 1
Marko Mikulicic 0:c0ecb8bf28eb 11894 * - 34: UTF-8 string "4"
Marko Mikulicic 0:c0ecb8bf28eb 11895 * VAR body end }}}
Marko Mikulicic 0:c0ecb8bf28eb 11896 * SCRIPT body end }}}
Marko Mikulicic 0:c0ecb8bf28eb 11897 *
Marko Mikulicic 0:c0ecb8bf28eb 11898 * --------------------------
Marko Mikulicic 0:c0ecb8bf28eb 11899 */
Marko Mikulicic 0:c0ecb8bf28eb 11900
Marko Mikulicic 0:c0ecb8bf28eb 11901 const struct ast_node_def ast_node_defs[] = {
Marko Mikulicic 0:c0ecb8bf28eb 11902 AST_ENTRY("NOP", 0, 0, 0, 0), /* struct {} */
Marko Mikulicic 0:c0ecb8bf28eb 11903
Marko Mikulicic 0:c0ecb8bf28eb 11904 /*
Marko Mikulicic 0:c0ecb8bf28eb 11905 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 11906 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 11907 * ast_skip_t first_var;
Marko Mikulicic 0:c0ecb8bf28eb 11908 * child body[];
Marko Mikulicic 0:c0ecb8bf28eb 11909 * end:
Marko Mikulicic 0:c0ecb8bf28eb 11910 * }
Marko Mikulicic 0:c0ecb8bf28eb 11911 */
Marko Mikulicic 0:c0ecb8bf28eb 11912 AST_ENTRY("SCRIPT", 0, 0, 2, 0),
Marko Mikulicic 0:c0ecb8bf28eb 11913 /*
Marko Mikulicic 0:c0ecb8bf28eb 11914 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 11915 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 11916 * ast_skip_t next;
Marko Mikulicic 0:c0ecb8bf28eb 11917 * child decls[];
Marko Mikulicic 0:c0ecb8bf28eb 11918 * end:
Marko Mikulicic 0:c0ecb8bf28eb 11919 * }
Marko Mikulicic 0:c0ecb8bf28eb 11920 */
Marko Mikulicic 0:c0ecb8bf28eb 11921 AST_ENTRY("VAR", 0, 0, 2, 0),
Marko Mikulicic 0:c0ecb8bf28eb 11922 /*
Marko Mikulicic 0:c0ecb8bf28eb 11923 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 11924 * varint len;
Marko Mikulicic 0:c0ecb8bf28eb 11925 * char name[len];
Marko Mikulicic 0:c0ecb8bf28eb 11926 * child expr;
Marko Mikulicic 0:c0ecb8bf28eb 11927 * }
Marko Mikulicic 0:c0ecb8bf28eb 11928 */
Marko Mikulicic 0:c0ecb8bf28eb 11929 AST_ENTRY("VAR_DECL", 1, 1, 0, 1),
Marko Mikulicic 0:c0ecb8bf28eb 11930 /*
Marko Mikulicic 0:c0ecb8bf28eb 11931 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 11932 * varint len;
Marko Mikulicic 0:c0ecb8bf28eb 11933 * char name[len];
Marko Mikulicic 0:c0ecb8bf28eb 11934 * child expr;
Marko Mikulicic 0:c0ecb8bf28eb 11935 * }
Marko Mikulicic 0:c0ecb8bf28eb 11936 */
Marko Mikulicic 0:c0ecb8bf28eb 11937 AST_ENTRY("FUNC_DECL", 1, 1, 0, 1),
Marko Mikulicic 0:c0ecb8bf28eb 11938 /*
Marko Mikulicic 0:c0ecb8bf28eb 11939 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 11940 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 11941 * ast_skip_t end_true;
Marko Mikulicic 0:c0ecb8bf28eb 11942 * child cond;
Marko Mikulicic 0:c0ecb8bf28eb 11943 * child iftrue[];
Marko Mikulicic 0:c0ecb8bf28eb 11944 * end_true:
Marko Mikulicic 0:c0ecb8bf28eb 11945 * child iffalse[];
Marko Mikulicic 0:c0ecb8bf28eb 11946 * end:
Marko Mikulicic 0:c0ecb8bf28eb 11947 * }
Marko Mikulicic 0:c0ecb8bf28eb 11948 */
Marko Mikulicic 0:c0ecb8bf28eb 11949 AST_ENTRY("IF", 0, 0, 2, 1),
Marko Mikulicic 0:c0ecb8bf28eb 11950 /*
Marko Mikulicic 0:c0ecb8bf28eb 11951 * TODO(mkm) distinguish function expressions
Marko Mikulicic 0:c0ecb8bf28eb 11952 * from function statements.
Marko Mikulicic 0:c0ecb8bf28eb 11953 * Function statements behave like vars and need a
Marko Mikulicic 0:c0ecb8bf28eb 11954 * next field for hoisting.
Marko Mikulicic 0:c0ecb8bf28eb 11955 * We can also ignore the name for function expressions
Marko Mikulicic 0:c0ecb8bf28eb 11956 * if it's only needed for debugging.
Marko Mikulicic 0:c0ecb8bf28eb 11957 *
Marko Mikulicic 0:c0ecb8bf28eb 11958 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 11959 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 11960 * ast_skip_t first_var;
Marko Mikulicic 0:c0ecb8bf28eb 11961 * ast_skip_t body;
Marko Mikulicic 0:c0ecb8bf28eb 11962 * child name;
Marko Mikulicic 0:c0ecb8bf28eb 11963 * child params[];
Marko Mikulicic 0:c0ecb8bf28eb 11964 * body:
Marko Mikulicic 0:c0ecb8bf28eb 11965 * child body[];
Marko Mikulicic 0:c0ecb8bf28eb 11966 * end:
Marko Mikulicic 0:c0ecb8bf28eb 11967 * }
Marko Mikulicic 0:c0ecb8bf28eb 11968 */
Marko Mikulicic 0:c0ecb8bf28eb 11969 AST_ENTRY("FUNC", 0, 0, 3, 1),
Marko Mikulicic 0:c0ecb8bf28eb 11970 AST_ENTRY("ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 11971 AST_ENTRY("REM_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 11972 AST_ENTRY("MUL_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 11973 AST_ENTRY("DIV_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 11974 AST_ENTRY("XOR_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 11975 AST_ENTRY("PLUS_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 11976 AST_ENTRY("MINUS_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 11977 AST_ENTRY("OR_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 11978 AST_ENTRY("AND_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 11979 AST_ENTRY("LSHIFT_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 11980 AST_ENTRY("RSHIFT_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 11981 AST_ENTRY("URSHIFT_ASSIGN", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 11982 AST_ENTRY("NUM", 1, 1, 0, 0), /* struct { varint len, char s[len]; } */
Marko Mikulicic 0:c0ecb8bf28eb 11983 AST_ENTRY("IDENT", 1, 1, 0, 0), /* struct { varint len, char s[len]; } */
Marko Mikulicic 0:c0ecb8bf28eb 11984 AST_ENTRY("STRING", 1, 1, 0, 0), /* struct { varint len, char s[len]; } */
Marko Mikulicic 0:c0ecb8bf28eb 11985 AST_ENTRY("REGEX", 1, 1, 0, 0), /* struct { varint len, char s[len]; } */
Marko Mikulicic 0:c0ecb8bf28eb 11986 AST_ENTRY("LABEL", 1, 1, 0, 0), /* struct { varint len, char s[len]; } */
Marko Mikulicic 0:c0ecb8bf28eb 11987
Marko Mikulicic 0:c0ecb8bf28eb 11988 /*
Marko Mikulicic 0:c0ecb8bf28eb 11989 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 11990 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 11991 * child body[];
Marko Mikulicic 0:c0ecb8bf28eb 11992 * end:
Marko Mikulicic 0:c0ecb8bf28eb 11993 * }
Marko Mikulicic 0:c0ecb8bf28eb 11994 */
Marko Mikulicic 0:c0ecb8bf28eb 11995 AST_ENTRY("SEQ", 0, 0, 1, 0),
Marko Mikulicic 0:c0ecb8bf28eb 11996 /*
Marko Mikulicic 0:c0ecb8bf28eb 11997 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 11998 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 11999 * child cond;
Marko Mikulicic 0:c0ecb8bf28eb 12000 * child body[];
Marko Mikulicic 0:c0ecb8bf28eb 12001 * end:
Marko Mikulicic 0:c0ecb8bf28eb 12002 * }
Marko Mikulicic 0:c0ecb8bf28eb 12003 */
Marko Mikulicic 0:c0ecb8bf28eb 12004 AST_ENTRY("WHILE", 0, 0, 1, 1),
Marko Mikulicic 0:c0ecb8bf28eb 12005 /*
Marko Mikulicic 0:c0ecb8bf28eb 12006 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12007 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 12008 * ast_skip_t cond;
Marko Mikulicic 0:c0ecb8bf28eb 12009 * child body[];
Marko Mikulicic 0:c0ecb8bf28eb 12010 * cond:
Marko Mikulicic 0:c0ecb8bf28eb 12011 * child cond;
Marko Mikulicic 0:c0ecb8bf28eb 12012 * end:
Marko Mikulicic 0:c0ecb8bf28eb 12013 * }
Marko Mikulicic 0:c0ecb8bf28eb 12014 */
Marko Mikulicic 0:c0ecb8bf28eb 12015 AST_ENTRY("DOWHILE", 0, 0, 2, 0),
Marko Mikulicic 0:c0ecb8bf28eb 12016 /*
Marko Mikulicic 0:c0ecb8bf28eb 12017 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12018 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 12019 * ast_skip_t body;
Marko Mikulicic 0:c0ecb8bf28eb 12020 * child init;
Marko Mikulicic 0:c0ecb8bf28eb 12021 * child cond;
Marko Mikulicic 0:c0ecb8bf28eb 12022 * child iter;
Marko Mikulicic 0:c0ecb8bf28eb 12023 * body:
Marko Mikulicic 0:c0ecb8bf28eb 12024 * child body[];
Marko Mikulicic 0:c0ecb8bf28eb 12025 * end:
Marko Mikulicic 0:c0ecb8bf28eb 12026 * }
Marko Mikulicic 0:c0ecb8bf28eb 12027 */
Marko Mikulicic 0:c0ecb8bf28eb 12028 AST_ENTRY("FOR", 0, 0, 2, 3),
Marko Mikulicic 0:c0ecb8bf28eb 12029 /*
Marko Mikulicic 0:c0ecb8bf28eb 12030 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12031 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 12032 * ast_skip_t dummy; // allows to quickly promote a for to a for in
Marko Mikulicic 0:c0ecb8bf28eb 12033 * child var;
Marko Mikulicic 0:c0ecb8bf28eb 12034 * child expr;
Marko Mikulicic 0:c0ecb8bf28eb 12035 * child dummy;
Marko Mikulicic 0:c0ecb8bf28eb 12036 * child body[];
Marko Mikulicic 0:c0ecb8bf28eb 12037 * end:
Marko Mikulicic 0:c0ecb8bf28eb 12038 * }
Marko Mikulicic 0:c0ecb8bf28eb 12039 */
Marko Mikulicic 0:c0ecb8bf28eb 12040 AST_ENTRY("FOR_IN", 0, 0, 2, 3),
Marko Mikulicic 0:c0ecb8bf28eb 12041 AST_ENTRY("COND", 0, 0, 0, 3), /* struct { child cond, iftrue, iffalse; } */
Marko Mikulicic 0:c0ecb8bf28eb 12042 AST_ENTRY("DEBUGGER", 0, 0, 0, 0), /* struct {} */
Marko Mikulicic 0:c0ecb8bf28eb 12043 AST_ENTRY("BREAK", 0, 0, 0, 0), /* struct {} */
Marko Mikulicic 0:c0ecb8bf28eb 12044
Marko Mikulicic 0:c0ecb8bf28eb 12045 /*
Marko Mikulicic 0:c0ecb8bf28eb 12046 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12047 * child label; // TODO(mkm): inline
Marko Mikulicic 0:c0ecb8bf28eb 12048 * }
Marko Mikulicic 0:c0ecb8bf28eb 12049 */
Marko Mikulicic 0:c0ecb8bf28eb 12050 AST_ENTRY("LAB_BREAK", 0, 0, 0, 1),
Marko Mikulicic 0:c0ecb8bf28eb 12051 AST_ENTRY("CONTINUE", 0, 0, 0, 0), /* struct {} */
Marko Mikulicic 0:c0ecb8bf28eb 12052
Marko Mikulicic 0:c0ecb8bf28eb 12053 /*
Marko Mikulicic 0:c0ecb8bf28eb 12054 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12055 * child label; // TODO(mkm): inline
Marko Mikulicic 0:c0ecb8bf28eb 12056 * }
Marko Mikulicic 0:c0ecb8bf28eb 12057 */
Marko Mikulicic 0:c0ecb8bf28eb 12058 AST_ENTRY("LAB_CONTINUE", 0, 0, 0, 1),
Marko Mikulicic 0:c0ecb8bf28eb 12059 AST_ENTRY("RETURN", 0, 0, 0, 0), /* struct {} */
Marko Mikulicic 0:c0ecb8bf28eb 12060 AST_ENTRY("VAL_RETURN", 0, 0, 0, 1), /* struct { child expr; } */
Marko Mikulicic 0:c0ecb8bf28eb 12061 AST_ENTRY("THROW", 0, 0, 0, 1), /* struct { child expr; } */
Marko Mikulicic 0:c0ecb8bf28eb 12062
Marko Mikulicic 0:c0ecb8bf28eb 12063 /*
Marko Mikulicic 0:c0ecb8bf28eb 12064 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12065 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 12066 * ast_skip_t catch;
Marko Mikulicic 0:c0ecb8bf28eb 12067 * ast_skip_t finally;
Marko Mikulicic 0:c0ecb8bf28eb 12068 * child try[];
Marko Mikulicic 0:c0ecb8bf28eb 12069 * catch:
Marko Mikulicic 0:c0ecb8bf28eb 12070 * child var; // TODO(mkm): inline
Marko Mikulicic 0:c0ecb8bf28eb 12071 * child catch[];
Marko Mikulicic 0:c0ecb8bf28eb 12072 * finally:
Marko Mikulicic 0:c0ecb8bf28eb 12073 * child finally[];
Marko Mikulicic 0:c0ecb8bf28eb 12074 * end:
Marko Mikulicic 0:c0ecb8bf28eb 12075 * }
Marko Mikulicic 0:c0ecb8bf28eb 12076 */
Marko Mikulicic 0:c0ecb8bf28eb 12077 AST_ENTRY("TRY", 0, 0, 3, 1),
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 def;
Marko Mikulicic 0:c0ecb8bf28eb 12082 * child expr;
Marko Mikulicic 0:c0ecb8bf28eb 12083 * child cases[];
Marko Mikulicic 0:c0ecb8bf28eb 12084 * def:
Marko Mikulicic 0:c0ecb8bf28eb 12085 * child default?; // optional
Marko Mikulicic 0:c0ecb8bf28eb 12086 * end:
Marko Mikulicic 0:c0ecb8bf28eb 12087 * }
Marko Mikulicic 0:c0ecb8bf28eb 12088 */
Marko Mikulicic 0:c0ecb8bf28eb 12089 AST_ENTRY("SWITCH", 0, 0, 2, 1),
Marko Mikulicic 0:c0ecb8bf28eb 12090 /*
Marko Mikulicic 0:c0ecb8bf28eb 12091 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12092 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 12093 * child val;
Marko Mikulicic 0:c0ecb8bf28eb 12094 * child stmts[];
Marko Mikulicic 0:c0ecb8bf28eb 12095 * end:
Marko Mikulicic 0:c0ecb8bf28eb 12096 * }
Marko Mikulicic 0:c0ecb8bf28eb 12097 */
Marko Mikulicic 0:c0ecb8bf28eb 12098 AST_ENTRY("CASE", 0, 0, 1, 1),
Marko Mikulicic 0:c0ecb8bf28eb 12099 /*
Marko Mikulicic 0:c0ecb8bf28eb 12100 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12101 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 12102 * child stmts[];
Marko Mikulicic 0:c0ecb8bf28eb 12103 * end:
Marko Mikulicic 0:c0ecb8bf28eb 12104 * }
Marko Mikulicic 0:c0ecb8bf28eb 12105 */
Marko Mikulicic 0:c0ecb8bf28eb 12106 AST_ENTRY("DEFAULT", 0, 0, 1, 0),
Marko Mikulicic 0:c0ecb8bf28eb 12107 /*
Marko Mikulicic 0:c0ecb8bf28eb 12108 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12109 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 12110 * child expr;
Marko Mikulicic 0:c0ecb8bf28eb 12111 * child body[];
Marko Mikulicic 0:c0ecb8bf28eb 12112 * end:
Marko Mikulicic 0:c0ecb8bf28eb 12113 * }
Marko Mikulicic 0:c0ecb8bf28eb 12114 */
Marko Mikulicic 0:c0ecb8bf28eb 12115 AST_ENTRY("WITH", 0, 0, 1, 1),
Marko Mikulicic 0:c0ecb8bf28eb 12116 AST_ENTRY("LOG_OR", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12117 AST_ENTRY("LOG_AND", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12118 AST_ENTRY("OR", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12119 AST_ENTRY("XOR", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12120 AST_ENTRY("AND", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12121 AST_ENTRY("EQ", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12122 AST_ENTRY("EQ_EQ", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12123 AST_ENTRY("NE", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12124 AST_ENTRY("NE_NE", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12125 AST_ENTRY("LE", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12126 AST_ENTRY("LT", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12127 AST_ENTRY("GE", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12128 AST_ENTRY("GT", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12129 AST_ENTRY("IN", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12130 AST_ENTRY("INSTANCEOF", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12131 AST_ENTRY("LSHIFT", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12132 AST_ENTRY("RSHIFT", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12133 AST_ENTRY("URSHIFT", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12134 AST_ENTRY("ADD", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12135 AST_ENTRY("SUB", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12136 AST_ENTRY("REM", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12137 AST_ENTRY("MUL", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12138 AST_ENTRY("DIV", 0, 0, 0, 2), /* struct { child left, right; } */
Marko Mikulicic 0:c0ecb8bf28eb 12139 AST_ENTRY("POS", 0, 0, 0, 1), /* struct { child expr; } */
Marko Mikulicic 0:c0ecb8bf28eb 12140 AST_ENTRY("NEG", 0, 0, 0, 1), /* struct { child expr; } */
Marko Mikulicic 0:c0ecb8bf28eb 12141 AST_ENTRY("NOT", 0, 0, 0, 1), /* struct { child expr; } */
Marko Mikulicic 0:c0ecb8bf28eb 12142 AST_ENTRY("LOGICAL_NOT", 0, 0, 0, 1), /* struct { child expr; } */
Marko Mikulicic 0:c0ecb8bf28eb 12143 AST_ENTRY("VOID", 0, 0, 0, 1), /* struct { child expr; } */
Marko Mikulicic 0:c0ecb8bf28eb 12144 AST_ENTRY("DELETE", 0, 0, 0, 1), /* struct { child expr; } */
Marko Mikulicic 0:c0ecb8bf28eb 12145 AST_ENTRY("TYPEOF", 0, 0, 0, 1), /* struct { child expr; } */
Marko Mikulicic 0:c0ecb8bf28eb 12146 AST_ENTRY("PREINC", 0, 0, 0, 1), /* struct { child expr; } */
Marko Mikulicic 0:c0ecb8bf28eb 12147 AST_ENTRY("PREDEC", 0, 0, 0, 1), /* struct { child expr; } */
Marko Mikulicic 0:c0ecb8bf28eb 12148 AST_ENTRY("POSTINC", 0, 0, 0, 1), /* struct { child expr; } */
Marko Mikulicic 0:c0ecb8bf28eb 12149 AST_ENTRY("POSTDEC", 0, 0, 0, 1), /* struct { child expr; } */
Marko Mikulicic 0:c0ecb8bf28eb 12150
Marko Mikulicic 0:c0ecb8bf28eb 12151 /*
Marko Mikulicic 0:c0ecb8bf28eb 12152 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12153 * varint len;
Marko Mikulicic 0:c0ecb8bf28eb 12154 * char ident[len];
Marko Mikulicic 0:c0ecb8bf28eb 12155 * child expr;
Marko Mikulicic 0:c0ecb8bf28eb 12156 * }
Marko Mikulicic 0:c0ecb8bf28eb 12157 */
Marko Mikulicic 0:c0ecb8bf28eb 12158 AST_ENTRY("MEMBER", 1, 1, 0, 1),
Marko Mikulicic 0:c0ecb8bf28eb 12159 /*
Marko Mikulicic 0:c0ecb8bf28eb 12160 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12161 * child expr;
Marko Mikulicic 0:c0ecb8bf28eb 12162 * child index;
Marko Mikulicic 0:c0ecb8bf28eb 12163 * }
Marko Mikulicic 0:c0ecb8bf28eb 12164 */
Marko Mikulicic 0:c0ecb8bf28eb 12165 AST_ENTRY("INDEX", 0, 0, 0, 2),
Marko Mikulicic 0:c0ecb8bf28eb 12166 /*
Marko Mikulicic 0:c0ecb8bf28eb 12167 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12168 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 12169 * child expr;
Marko Mikulicic 0:c0ecb8bf28eb 12170 * child args[];
Marko Mikulicic 0:c0ecb8bf28eb 12171 * end:
Marko Mikulicic 0:c0ecb8bf28eb 12172 * }
Marko Mikulicic 0:c0ecb8bf28eb 12173 */
Marko Mikulicic 0:c0ecb8bf28eb 12174 AST_ENTRY("CALL", 0, 0, 1, 1),
Marko Mikulicic 0:c0ecb8bf28eb 12175 /*
Marko Mikulicic 0:c0ecb8bf28eb 12176 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12177 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 12178 * child expr;
Marko Mikulicic 0:c0ecb8bf28eb 12179 * child args[];
Marko Mikulicic 0:c0ecb8bf28eb 12180 * end:
Marko Mikulicic 0:c0ecb8bf28eb 12181 * }
Marko Mikulicic 0:c0ecb8bf28eb 12182 */
Marko Mikulicic 0:c0ecb8bf28eb 12183 AST_ENTRY("NEW", 0, 0, 1, 1),
Marko Mikulicic 0:c0ecb8bf28eb 12184 /*
Marko Mikulicic 0:c0ecb8bf28eb 12185 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12186 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 12187 * child elements[];
Marko Mikulicic 0:c0ecb8bf28eb 12188 * end:
Marko Mikulicic 0:c0ecb8bf28eb 12189 * }
Marko Mikulicic 0:c0ecb8bf28eb 12190 */
Marko Mikulicic 0:c0ecb8bf28eb 12191 AST_ENTRY("ARRAY", 0, 0, 1, 0),
Marko Mikulicic 0:c0ecb8bf28eb 12192 /*
Marko Mikulicic 0:c0ecb8bf28eb 12193 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12194 * ast_skip_t end;
Marko Mikulicic 0:c0ecb8bf28eb 12195 * child props[];
Marko Mikulicic 0:c0ecb8bf28eb 12196 * end:
Marko Mikulicic 0:c0ecb8bf28eb 12197 * }
Marko Mikulicic 0:c0ecb8bf28eb 12198 */
Marko Mikulicic 0:c0ecb8bf28eb 12199 AST_ENTRY("OBJECT", 0, 0, 1, 0),
Marko Mikulicic 0:c0ecb8bf28eb 12200 /*
Marko Mikulicic 0:c0ecb8bf28eb 12201 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12202 * varint len;
Marko Mikulicic 0:c0ecb8bf28eb 12203 * char name[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("PROP", 1, 1, 0, 1),
Marko Mikulicic 0:c0ecb8bf28eb 12208 /*
Marko Mikulicic 0:c0ecb8bf28eb 12209 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12210 * child func;
Marko Mikulicic 0:c0ecb8bf28eb 12211 * }
Marko Mikulicic 0:c0ecb8bf28eb 12212 */
Marko Mikulicic 0:c0ecb8bf28eb 12213 AST_ENTRY("GETTER", 0, 0, 0, 1),
Marko Mikulicic 0:c0ecb8bf28eb 12214 /*
Marko Mikulicic 0:c0ecb8bf28eb 12215 * struct {
Marko Mikulicic 0:c0ecb8bf28eb 12216 * child func;
Marko Mikulicic 0:c0ecb8bf28eb 12217 * end:
Marko Mikulicic 0:c0ecb8bf28eb 12218 * }
Marko Mikulicic 0:c0ecb8bf28eb 12219 */
Marko Mikulicic 0:c0ecb8bf28eb 12220 AST_ENTRY("SETTER", 0, 0, 0, 1),
Marko Mikulicic 0:c0ecb8bf28eb 12221 AST_ENTRY("THIS", 0, 0, 0, 0), /* struct {} */
Marko Mikulicic 0:c0ecb8bf28eb 12222 AST_ENTRY("TRUE", 0, 0, 0, 0), /* struct {} */
Marko Mikulicic 0:c0ecb8bf28eb 12223 AST_ENTRY("FALSE", 0, 0, 0, 0), /* struct {} */
Marko Mikulicic 0:c0ecb8bf28eb 12224 AST_ENTRY("NULL", 0, 0, 0, 0), /* struct {} */
Marko Mikulicic 0:c0ecb8bf28eb 12225 AST_ENTRY("UNDEF", 0, 0, 0, 0), /* struct {} */
Marko Mikulicic 0:c0ecb8bf28eb 12226 AST_ENTRY("USE_STRICT", 0, 0, 0, 0), /* struct {} */
Marko Mikulicic 0:c0ecb8bf28eb 12227 };
Marko Mikulicic 0:c0ecb8bf28eb 12228
Marko Mikulicic 0:c0ecb8bf28eb 12229 /*
Marko Mikulicic 0:c0ecb8bf28eb 12230 * A flag which is used to mark node's tag byte if the node has line number
Marko Mikulicic 0:c0ecb8bf28eb 12231 * data encoded (varint after skips). See `ast_get_line_no()`.
Marko Mikulicic 0:c0ecb8bf28eb 12232 */
Marko Mikulicic 0:c0ecb8bf28eb 12233 #define AST_TAG_LINENO_PRESENT 0x80
Marko Mikulicic 0:c0ecb8bf28eb 12234
Marko Mikulicic 0:c0ecb8bf28eb 12235 V7_STATIC_ASSERT(AST_MAX_TAG < 256, ast_tag_should_fit_in_char);
Marko Mikulicic 0:c0ecb8bf28eb 12236 V7_STATIC_ASSERT(AST_MAX_TAG == ARRAY_SIZE(ast_node_defs), bad_node_defs);
Marko Mikulicic 0:c0ecb8bf28eb 12237 V7_STATIC_ASSERT(AST_MAX_TAG <= AST_TAG_LINENO_PRESENT, bad_AST_LINE_NO);
Marko Mikulicic 0:c0ecb8bf28eb 12238
Marko Mikulicic 0:c0ecb8bf28eb 12239 #if V7_ENABLE_FOOTPRINT_REPORT
Marko Mikulicic 0:c0ecb8bf28eb 12240 const size_t ast_node_defs_size = sizeof(ast_node_defs);
Marko Mikulicic 0:c0ecb8bf28eb 12241 const size_t ast_node_defs_count = ARRAY_SIZE(ast_node_defs);
Marko Mikulicic 0:c0ecb8bf28eb 12242 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12243
Marko Mikulicic 0:c0ecb8bf28eb 12244 /*
Marko Mikulicic 0:c0ecb8bf28eb 12245 * Converts a given byte `t` (which should be read from the AST data buffer)
Marko Mikulicic 0:c0ecb8bf28eb 12246 * into `enum ast_tag`. This function is needed because tag might be marked
Marko Mikulicic 0:c0ecb8bf28eb 12247 * with the `AST_TAG_LINENO_PRESENT` flag; the returned tag is always unmarked,
Marko Mikulicic 0:c0ecb8bf28eb 12248 * and if the flag was indeed set, `lineno_present` is set to 1; otherwise
Marko Mikulicic 0:c0ecb8bf28eb 12249 * it is set to 0.
Marko Mikulicic 0:c0ecb8bf28eb 12250 *
Marko Mikulicic 0:c0ecb8bf28eb 12251 * `lineno_present` is allowed to be NULL, if the caller doesn't care of the
Marko Mikulicic 0:c0ecb8bf28eb 12252 * line number presence.
Marko Mikulicic 0:c0ecb8bf28eb 12253 */
Marko Mikulicic 0:c0ecb8bf28eb 12254 static enum ast_tag uint8_to_tag(uint8_t t, uint8_t *lineno_present) {
Marko Mikulicic 0:c0ecb8bf28eb 12255 if (t & AST_TAG_LINENO_PRESENT) {
Marko Mikulicic 0:c0ecb8bf28eb 12256 t &= ~AST_TAG_LINENO_PRESENT;
Marko Mikulicic 0:c0ecb8bf28eb 12257 if (lineno_present != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 12258 *lineno_present = 1;
Marko Mikulicic 0:c0ecb8bf28eb 12259 }
Marko Mikulicic 0:c0ecb8bf28eb 12260 } else if (lineno_present != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 12261 *lineno_present = 0;
Marko Mikulicic 0:c0ecb8bf28eb 12262 }
Marko Mikulicic 0:c0ecb8bf28eb 12263 return (enum ast_tag) t;
Marko Mikulicic 0:c0ecb8bf28eb 12264 }
Marko Mikulicic 0:c0ecb8bf28eb 12265
Marko Mikulicic 0:c0ecb8bf28eb 12266 V7_PRIVATE ast_off_t
Marko Mikulicic 0:c0ecb8bf28eb 12267 ast_insert_node(struct ast *a, ast_off_t pos, enum ast_tag tag) {
Marko Mikulicic 0:c0ecb8bf28eb 12268 uint8_t t = (uint8_t) tag;
Marko Mikulicic 0:c0ecb8bf28eb 12269 const struct ast_node_def *d = &ast_node_defs[tag];
Marko Mikulicic 0:c0ecb8bf28eb 12270 ast_off_t cur = pos;
Marko Mikulicic 0:c0ecb8bf28eb 12271
Marko Mikulicic 0:c0ecb8bf28eb 12272 assert(tag < AST_MAX_TAG);
Marko Mikulicic 0:c0ecb8bf28eb 12273
Marko Mikulicic 0:c0ecb8bf28eb 12274 mbuf_insert(&a->mbuf, cur, (char *) &t, sizeof(t));
Marko Mikulicic 0:c0ecb8bf28eb 12275 cur += sizeof(t);
Marko Mikulicic 0:c0ecb8bf28eb 12276
Marko Mikulicic 0:c0ecb8bf28eb 12277 mbuf_insert(&a->mbuf, cur, NULL, sizeof(ast_skip_t) * d->num_skips);
Marko Mikulicic 0:c0ecb8bf28eb 12278 cur += sizeof(ast_skip_t) * d->num_skips;
Marko Mikulicic 0:c0ecb8bf28eb 12279
Marko Mikulicic 0:c0ecb8bf28eb 12280 if (d->num_skips) {
Marko Mikulicic 0:c0ecb8bf28eb 12281 ast_set_skip(a, pos + 1, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 12282 }
Marko Mikulicic 0:c0ecb8bf28eb 12283
Marko Mikulicic 0:c0ecb8bf28eb 12284 return pos + 1;
Marko Mikulicic 0:c0ecb8bf28eb 12285 }
Marko Mikulicic 0:c0ecb8bf28eb 12286
Marko Mikulicic 0:c0ecb8bf28eb 12287 V7_PRIVATE void ast_modify_tag(struct ast *a, ast_off_t tag_off,
Marko Mikulicic 0:c0ecb8bf28eb 12288 enum ast_tag tag) {
Marko Mikulicic 0:c0ecb8bf28eb 12289 a->mbuf.buf[tag_off] = tag | (a->mbuf.buf[tag_off] & 0x80);
Marko Mikulicic 0:c0ecb8bf28eb 12290 }
Marko Mikulicic 0:c0ecb8bf28eb 12291
Marko Mikulicic 0:c0ecb8bf28eb 12292 #ifndef V7_DISABLE_LINE_NUMBERS
Marko Mikulicic 0:c0ecb8bf28eb 12293 V7_PRIVATE void ast_add_line_no(struct ast *a, ast_off_t tag_off, int line_no) {
Marko Mikulicic 0:c0ecb8bf28eb 12294 ast_off_t ln_off = tag_off + 1 /* tag byte */;
Marko Mikulicic 0:c0ecb8bf28eb 12295 int llen = calc_llen(line_no);
Marko Mikulicic 0:c0ecb8bf28eb 12296
Marko Mikulicic 0:c0ecb8bf28eb 12297 ast_move_to_inlined_data(a, &ln_off);
Marko Mikulicic 0:c0ecb8bf28eb 12298 mbuf_insert(&a->mbuf, ln_off, NULL, llen);
Marko Mikulicic 0:c0ecb8bf28eb 12299 encode_varint(line_no, (unsigned char *) (a->mbuf.buf + ln_off));
Marko Mikulicic 0:c0ecb8bf28eb 12300
Marko Mikulicic 0:c0ecb8bf28eb 12301 assert(a->mbuf.buf[tag_off] < AST_MAX_TAG);
Marko Mikulicic 0:c0ecb8bf28eb 12302 a->mbuf.buf[tag_off] |= AST_TAG_LINENO_PRESENT;
Marko Mikulicic 0:c0ecb8bf28eb 12303 }
Marko Mikulicic 0:c0ecb8bf28eb 12304 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12305
Marko Mikulicic 0:c0ecb8bf28eb 12306 V7_PRIVATE ast_off_t
Marko Mikulicic 0:c0ecb8bf28eb 12307 ast_set_skip(struct ast *a, ast_off_t pos, enum ast_which_skip skip) {
Marko Mikulicic 0:c0ecb8bf28eb 12308 return ast_modify_skip(a, pos, a->mbuf.len, skip);
Marko Mikulicic 0:c0ecb8bf28eb 12309 }
Marko Mikulicic 0:c0ecb8bf28eb 12310
Marko Mikulicic 0:c0ecb8bf28eb 12311 V7_PRIVATE ast_off_t ast_modify_skip(struct ast *a, ast_off_t pos,
Marko Mikulicic 0:c0ecb8bf28eb 12312 ast_off_t where,
Marko Mikulicic 0:c0ecb8bf28eb 12313 enum ast_which_skip skip) {
Marko Mikulicic 0:c0ecb8bf28eb 12314 uint8_t *p = (uint8_t *) a->mbuf.buf + pos + skip * sizeof(ast_skip_t);
Marko Mikulicic 0:c0ecb8bf28eb 12315 ast_skip_t delta = where - pos;
Marko Mikulicic 0:c0ecb8bf28eb 12316 #ifndef NDEBUG
Marko Mikulicic 0:c0ecb8bf28eb 12317 enum ast_tag tag = uint8_to_tag(*(a->mbuf.buf + pos - 1), NULL);
Marko Mikulicic 0:c0ecb8bf28eb 12318 const struct ast_node_def *def = &ast_node_defs[tag];
Marko Mikulicic 0:c0ecb8bf28eb 12319 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12320 assert(pos <= where);
Marko Mikulicic 0:c0ecb8bf28eb 12321
Marko Mikulicic 0:c0ecb8bf28eb 12322 #ifndef V7_LARGE_AST
Marko Mikulicic 0:c0ecb8bf28eb 12323 /* the value of delta overflowed, therefore the ast is not useable */
Marko Mikulicic 0:c0ecb8bf28eb 12324 if (where - pos > AST_SKIP_MAX) {
Marko Mikulicic 0:c0ecb8bf28eb 12325 a->has_overflow = 1;
Marko Mikulicic 0:c0ecb8bf28eb 12326 }
Marko Mikulicic 0:c0ecb8bf28eb 12327 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12328
Marko Mikulicic 0:c0ecb8bf28eb 12329 /* assertion, to be optimizable out */
Marko Mikulicic 0:c0ecb8bf28eb 12330 assert((int) skip < def->num_skips);
Marko Mikulicic 0:c0ecb8bf28eb 12331
Marko Mikulicic 0:c0ecb8bf28eb 12332 #ifdef V7_LARGE_AST
Marko Mikulicic 0:c0ecb8bf28eb 12333 p[0] = delta >> 24;
Marko Mikulicic 0:c0ecb8bf28eb 12334 p[1] = delta >> 16 & 0xff;
Marko Mikulicic 0:c0ecb8bf28eb 12335 p[2] = delta >> 8 & 0xff;
Marko Mikulicic 0:c0ecb8bf28eb 12336 p[3] = delta & 0xff;
Marko Mikulicic 0:c0ecb8bf28eb 12337 #else
Marko Mikulicic 0:c0ecb8bf28eb 12338 p[0] = delta >> 8;
Marko Mikulicic 0:c0ecb8bf28eb 12339 p[1] = delta & 0xff;
Marko Mikulicic 0:c0ecb8bf28eb 12340 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12341 return where;
Marko Mikulicic 0:c0ecb8bf28eb 12342 }
Marko Mikulicic 0:c0ecb8bf28eb 12343
Marko Mikulicic 0:c0ecb8bf28eb 12344 V7_PRIVATE ast_off_t
Marko Mikulicic 0:c0ecb8bf28eb 12345 ast_get_skip(struct ast *a, ast_off_t pos, enum ast_which_skip skip) {
Marko Mikulicic 0:c0ecb8bf28eb 12346 uint8_t *p;
Marko Mikulicic 0:c0ecb8bf28eb 12347 assert(pos + skip * sizeof(ast_skip_t) < a->mbuf.len);
Marko Mikulicic 0:c0ecb8bf28eb 12348
Marko Mikulicic 0:c0ecb8bf28eb 12349 p = (uint8_t *) a->mbuf.buf + pos + skip * sizeof(ast_skip_t);
Marko Mikulicic 0:c0ecb8bf28eb 12350 #ifdef V7_LARGE_AST
Marko Mikulicic 0:c0ecb8bf28eb 12351 return pos + (p[3] | p[2] << 8 | p[1] << 16 | p[0] << 24);
Marko Mikulicic 0:c0ecb8bf28eb 12352 #else
Marko Mikulicic 0:c0ecb8bf28eb 12353 return pos + (p[1] | p[0] << 8);
Marko Mikulicic 0:c0ecb8bf28eb 12354 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12355 }
Marko Mikulicic 0:c0ecb8bf28eb 12356
Marko Mikulicic 0:c0ecb8bf28eb 12357 V7_PRIVATE enum ast_tag ast_fetch_tag(struct ast *a, ast_off_t *ppos) {
Marko Mikulicic 0:c0ecb8bf28eb 12358 enum ast_tag ret;
Marko Mikulicic 0:c0ecb8bf28eb 12359 assert(*ppos < a->mbuf.len);
Marko Mikulicic 0:c0ecb8bf28eb 12360
Marko Mikulicic 0:c0ecb8bf28eb 12361 ret = uint8_to_tag(*(a->mbuf.buf + (*ppos)++), NULL);
Marko Mikulicic 0:c0ecb8bf28eb 12362
Marko Mikulicic 0:c0ecb8bf28eb 12363 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 12364 }
Marko Mikulicic 0:c0ecb8bf28eb 12365
Marko Mikulicic 0:c0ecb8bf28eb 12366 V7_PRIVATE void ast_move_to_children(struct ast *a, ast_off_t *ppos) {
Marko Mikulicic 0:c0ecb8bf28eb 12367 enum ast_tag tag = uint8_to_tag(*(a->mbuf.buf + *ppos - 1), NULL);
Marko Mikulicic 0:c0ecb8bf28eb 12368 const struct ast_node_def *def = &ast_node_defs[tag];
Marko Mikulicic 0:c0ecb8bf28eb 12369 assert(*ppos - 1 < a->mbuf.len);
Marko Mikulicic 0:c0ecb8bf28eb 12370
Marko Mikulicic 0:c0ecb8bf28eb 12371 ast_move_to_inlined_data(a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 12372
Marko Mikulicic 0:c0ecb8bf28eb 12373 /* skip varint + inline data, if present */
Marko Mikulicic 0:c0ecb8bf28eb 12374 if (def->has_varint) {
Marko Mikulicic 0:c0ecb8bf28eb 12375 int llen;
Marko Mikulicic 0:c0ecb8bf28eb 12376 size_t slen = decode_varint((unsigned char *) a->mbuf.buf + *ppos, &llen);
Marko Mikulicic 0:c0ecb8bf28eb 12377 *ppos += llen;
Marko Mikulicic 0:c0ecb8bf28eb 12378 if (def->has_inlined) {
Marko Mikulicic 0:c0ecb8bf28eb 12379 *ppos += slen;
Marko Mikulicic 0:c0ecb8bf28eb 12380 }
Marko Mikulicic 0:c0ecb8bf28eb 12381 }
Marko Mikulicic 0:c0ecb8bf28eb 12382 }
Marko Mikulicic 0:c0ecb8bf28eb 12383
Marko Mikulicic 0:c0ecb8bf28eb 12384 V7_PRIVATE ast_off_t ast_insert_inlined_node(struct ast *a, ast_off_t pos,
Marko Mikulicic 0:c0ecb8bf28eb 12385 enum ast_tag tag, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 12386 size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 12387 const struct ast_node_def *d = &ast_node_defs[tag];
Marko Mikulicic 0:c0ecb8bf28eb 12388
Marko Mikulicic 0:c0ecb8bf28eb 12389 ast_off_t offset = ast_insert_node(a, pos, tag);
Marko Mikulicic 0:c0ecb8bf28eb 12390
Marko Mikulicic 0:c0ecb8bf28eb 12391 assert(d->has_inlined);
Marko Mikulicic 0:c0ecb8bf28eb 12392
Marko Mikulicic 0:c0ecb8bf28eb 12393 embed_string(&a->mbuf, offset + sizeof(ast_skip_t) * d->num_skips, name, len,
Marko Mikulicic 0:c0ecb8bf28eb 12394 EMBSTR_UNESCAPE);
Marko Mikulicic 0:c0ecb8bf28eb 12395
Marko Mikulicic 0:c0ecb8bf28eb 12396 return offset;
Marko Mikulicic 0:c0ecb8bf28eb 12397 }
Marko Mikulicic 0:c0ecb8bf28eb 12398
Marko Mikulicic 0:c0ecb8bf28eb 12399 V7_PRIVATE int ast_get_line_no(struct ast *a, ast_off_t pos) {
Marko Mikulicic 0:c0ecb8bf28eb 12400 /*
Marko Mikulicic 0:c0ecb8bf28eb 12401 * by default we'll return 0, meaning that the AST node does not contain line
Marko Mikulicic 0:c0ecb8bf28eb 12402 * number data
Marko Mikulicic 0:c0ecb8bf28eb 12403 */
Marko Mikulicic 0:c0ecb8bf28eb 12404 int ret = 0;
Marko Mikulicic 0:c0ecb8bf28eb 12405
Marko Mikulicic 0:c0ecb8bf28eb 12406 #ifndef V7_DISABLE_LINE_NUMBERS
Marko Mikulicic 0:c0ecb8bf28eb 12407 uint8_t lineno_present;
Marko Mikulicic 0:c0ecb8bf28eb 12408 enum ast_tag tag = uint8_to_tag(*(a->mbuf.buf + pos - 1), &lineno_present);
Marko Mikulicic 0:c0ecb8bf28eb 12409
Marko Mikulicic 0:c0ecb8bf28eb 12410 if (lineno_present) {
Marko Mikulicic 0:c0ecb8bf28eb 12411 /* line number is present, so, let's decode it */
Marko Mikulicic 0:c0ecb8bf28eb 12412 int llen;
Marko Mikulicic 0:c0ecb8bf28eb 12413
Marko Mikulicic 0:c0ecb8bf28eb 12414 /* skip skips */
Marko Mikulicic 0:c0ecb8bf28eb 12415 pos += ast_node_defs[tag].num_skips * sizeof(ast_skip_t);
Marko Mikulicic 0:c0ecb8bf28eb 12416
Marko Mikulicic 0:c0ecb8bf28eb 12417 /* get line number */
Marko Mikulicic 0:c0ecb8bf28eb 12418 ret = decode_varint((unsigned char *) a->mbuf.buf + pos, &llen);
Marko Mikulicic 0:c0ecb8bf28eb 12419 }
Marko Mikulicic 0:c0ecb8bf28eb 12420 #else
Marko Mikulicic 0:c0ecb8bf28eb 12421 (void) a;
Marko Mikulicic 0:c0ecb8bf28eb 12422 (void) pos;
Marko Mikulicic 0:c0ecb8bf28eb 12423 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12424
Marko Mikulicic 0:c0ecb8bf28eb 12425 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 12426 }
Marko Mikulicic 0:c0ecb8bf28eb 12427
Marko Mikulicic 0:c0ecb8bf28eb 12428 V7_PRIVATE void ast_move_to_inlined_data(struct ast *a, ast_off_t *ppos) {
Marko Mikulicic 0:c0ecb8bf28eb 12429 uint8_t lineno_present = 0;
Marko Mikulicic 0:c0ecb8bf28eb 12430 enum ast_tag tag = uint8_to_tag(*(a->mbuf.buf + *ppos - 1), &lineno_present);
Marko Mikulicic 0:c0ecb8bf28eb 12431 const struct ast_node_def *def = &ast_node_defs[tag];
Marko Mikulicic 0:c0ecb8bf28eb 12432 assert(*ppos - 1 < a->mbuf.len);
Marko Mikulicic 0:c0ecb8bf28eb 12433
Marko Mikulicic 0:c0ecb8bf28eb 12434 /* skip skips */
Marko Mikulicic 0:c0ecb8bf28eb 12435 *ppos += def->num_skips * sizeof(ast_skip_t);
Marko Mikulicic 0:c0ecb8bf28eb 12436
Marko Mikulicic 0:c0ecb8bf28eb 12437 /* skip line_no, if present */
Marko Mikulicic 0:c0ecb8bf28eb 12438 if (lineno_present) {
Marko Mikulicic 0:c0ecb8bf28eb 12439 int llen;
Marko Mikulicic 0:c0ecb8bf28eb 12440 int line_no = decode_varint((unsigned char *) a->mbuf.buf + *ppos, &llen);
Marko Mikulicic 0:c0ecb8bf28eb 12441 *ppos += llen;
Marko Mikulicic 0:c0ecb8bf28eb 12442
Marko Mikulicic 0:c0ecb8bf28eb 12443 (void) line_no;
Marko Mikulicic 0:c0ecb8bf28eb 12444 }
Marko Mikulicic 0:c0ecb8bf28eb 12445 }
Marko Mikulicic 0:c0ecb8bf28eb 12446
Marko Mikulicic 0:c0ecb8bf28eb 12447 V7_PRIVATE char *ast_get_inlined_data(struct ast *a, ast_off_t pos, size_t *n) {
Marko Mikulicic 0:c0ecb8bf28eb 12448 int llen;
Marko Mikulicic 0:c0ecb8bf28eb 12449 assert(pos < a->mbuf.len);
Marko Mikulicic 0:c0ecb8bf28eb 12450
Marko Mikulicic 0:c0ecb8bf28eb 12451 ast_move_to_inlined_data(a, &pos);
Marko Mikulicic 0:c0ecb8bf28eb 12452
Marko Mikulicic 0:c0ecb8bf28eb 12453 *n = decode_varint((unsigned char *) a->mbuf.buf + pos, &llen);
Marko Mikulicic 0:c0ecb8bf28eb 12454 return a->mbuf.buf + pos + llen;
Marko Mikulicic 0:c0ecb8bf28eb 12455 }
Marko Mikulicic 0:c0ecb8bf28eb 12456
Marko Mikulicic 0:c0ecb8bf28eb 12457 V7_PRIVATE double ast_get_num(struct ast *a, ast_off_t pos) {
Marko Mikulicic 0:c0ecb8bf28eb 12458 double ret;
Marko Mikulicic 0:c0ecb8bf28eb 12459 char *str;
Marko Mikulicic 0:c0ecb8bf28eb 12460 size_t str_len;
Marko Mikulicic 0:c0ecb8bf28eb 12461 char buf[12];
Marko Mikulicic 0:c0ecb8bf28eb 12462 char *p = buf;
Marko Mikulicic 0:c0ecb8bf28eb 12463 str = ast_get_inlined_data(a, pos, &str_len);
Marko Mikulicic 0:c0ecb8bf28eb 12464 assert(str + str_len <= a->mbuf.buf + a->mbuf.len);
Marko Mikulicic 0:c0ecb8bf28eb 12465
Marko Mikulicic 0:c0ecb8bf28eb 12466 if (str_len > sizeof(buf) - 1) {
Marko Mikulicic 0:c0ecb8bf28eb 12467 p = (char *) malloc(str_len + 1);
Marko Mikulicic 0:c0ecb8bf28eb 12468 }
Marko Mikulicic 0:c0ecb8bf28eb 12469 strncpy(p, str, str_len);
Marko Mikulicic 0:c0ecb8bf28eb 12470 p[str_len] = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 12471 ret = cs_strtod(p, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 12472 if (p != buf) free(p);
Marko Mikulicic 0:c0ecb8bf28eb 12473 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 12474 }
Marko Mikulicic 0:c0ecb8bf28eb 12475
Marko Mikulicic 0:c0ecb8bf28eb 12476 #ifndef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 12477 static void comment_at_depth(FILE *fp, const char *fmt, int depth, ...) {
Marko Mikulicic 0:c0ecb8bf28eb 12478 int i;
Marko Mikulicic 0:c0ecb8bf28eb 12479 STATIC char buf[256];
Marko Mikulicic 0:c0ecb8bf28eb 12480 va_list ap;
Marko Mikulicic 0:c0ecb8bf28eb 12481 va_start(ap, depth);
Marko Mikulicic 0:c0ecb8bf28eb 12482
Marko Mikulicic 0:c0ecb8bf28eb 12483 c_vsnprintf(buf, sizeof(buf), fmt, ap);
Marko Mikulicic 0:c0ecb8bf28eb 12484
Marko Mikulicic 0:c0ecb8bf28eb 12485 for (i = 0; i < depth; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 12486 fprintf(fp, " ");
Marko Mikulicic 0:c0ecb8bf28eb 12487 }
Marko Mikulicic 0:c0ecb8bf28eb 12488 fprintf(fp, "/* [%s] */\n", buf);
Marko Mikulicic 0:c0ecb8bf28eb 12489 }
Marko Mikulicic 0:c0ecb8bf28eb 12490 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12491
Marko Mikulicic 0:c0ecb8bf28eb 12492 V7_PRIVATE void ast_skip_tree(struct ast *a, ast_off_t *ppos) {
Marko Mikulicic 0:c0ecb8bf28eb 12493 enum ast_tag tag = ast_fetch_tag(a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 12494 const struct ast_node_def *def = &ast_node_defs[tag];
Marko Mikulicic 0:c0ecb8bf28eb 12495 ast_off_t skips = *ppos;
Marko Mikulicic 0:c0ecb8bf28eb 12496 int i;
Marko Mikulicic 0:c0ecb8bf28eb 12497 ast_move_to_children(a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 12498
Marko Mikulicic 0:c0ecb8bf28eb 12499 for (i = 0; i < def->num_subtrees; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 12500 ast_skip_tree(a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 12501 }
Marko Mikulicic 0:c0ecb8bf28eb 12502
Marko Mikulicic 0:c0ecb8bf28eb 12503 if (def->num_skips > AST_END_SKIP) {
Marko Mikulicic 0:c0ecb8bf28eb 12504 ast_off_t end = ast_get_skip(a, skips, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 12505
Marko Mikulicic 0:c0ecb8bf28eb 12506 while (*ppos < end) {
Marko Mikulicic 0:c0ecb8bf28eb 12507 ast_skip_tree(a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 12508 }
Marko Mikulicic 0:c0ecb8bf28eb 12509 }
Marko Mikulicic 0:c0ecb8bf28eb 12510 }
Marko Mikulicic 0:c0ecb8bf28eb 12511
Marko Mikulicic 0:c0ecb8bf28eb 12512 #ifndef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 12513 V7_PRIVATE void ast_dump_tree(FILE *fp, struct ast *a, ast_off_t *ppos,
Marko Mikulicic 0:c0ecb8bf28eb 12514 int depth) {
Marko Mikulicic 0:c0ecb8bf28eb 12515 enum ast_tag tag = ast_fetch_tag(a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 12516 const struct ast_node_def *def = &ast_node_defs[tag];
Marko Mikulicic 0:c0ecb8bf28eb 12517 ast_off_t skips = *ppos;
Marko Mikulicic 0:c0ecb8bf28eb 12518 size_t slen;
Marko Mikulicic 0:c0ecb8bf28eb 12519 int i, llen;
Marko Mikulicic 0:c0ecb8bf28eb 12520
Marko Mikulicic 0:c0ecb8bf28eb 12521 for (i = 0; i < depth; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 12522 fprintf(fp, " ");
Marko Mikulicic 0:c0ecb8bf28eb 12523 }
Marko Mikulicic 0:c0ecb8bf28eb 12524
Marko Mikulicic 0:c0ecb8bf28eb 12525 #ifndef V7_DISABLE_AST_TAG_NAMES
Marko Mikulicic 0:c0ecb8bf28eb 12526 fprintf(fp, "%s", def->name);
Marko Mikulicic 0:c0ecb8bf28eb 12527 #else
Marko Mikulicic 0:c0ecb8bf28eb 12528 fprintf(fp, "TAG_%d", tag);
Marko Mikulicic 0:c0ecb8bf28eb 12529 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12530
Marko Mikulicic 0:c0ecb8bf28eb 12531 if (def->has_inlined) {
Marko Mikulicic 0:c0ecb8bf28eb 12532 ast_off_t pos_tmp = *ppos;
Marko Mikulicic 0:c0ecb8bf28eb 12533 ast_move_to_inlined_data(a, &pos_tmp);
Marko Mikulicic 0:c0ecb8bf28eb 12534
Marko Mikulicic 0:c0ecb8bf28eb 12535 slen = decode_varint((unsigned char *) a->mbuf.buf + pos_tmp, &llen);
Marko Mikulicic 0:c0ecb8bf28eb 12536 fprintf(fp, " %.*s\n", (int) slen, a->mbuf.buf + pos_tmp + llen);
Marko Mikulicic 0:c0ecb8bf28eb 12537 } else {
Marko Mikulicic 0:c0ecb8bf28eb 12538 fprintf(fp, "\n");
Marko Mikulicic 0:c0ecb8bf28eb 12539 }
Marko Mikulicic 0:c0ecb8bf28eb 12540
Marko Mikulicic 0:c0ecb8bf28eb 12541 ast_move_to_children(a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 12542
Marko Mikulicic 0:c0ecb8bf28eb 12543 for (i = 0; i < def->num_subtrees; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 12544 ast_dump_tree(fp, a, ppos, depth + 1);
Marko Mikulicic 0:c0ecb8bf28eb 12545 }
Marko Mikulicic 0:c0ecb8bf28eb 12546
Marko Mikulicic 0:c0ecb8bf28eb 12547 if (ast_node_defs[tag].num_skips) {
Marko Mikulicic 0:c0ecb8bf28eb 12548 /*
Marko Mikulicic 0:c0ecb8bf28eb 12549 * first skip always encodes end of the last children sequence.
Marko Mikulicic 0:c0ecb8bf28eb 12550 * so unless we care how the subtree sequences are grouped together
Marko Mikulicic 0:c0ecb8bf28eb 12551 * (and we currently don't) we can just read until the end of that skip.
Marko Mikulicic 0:c0ecb8bf28eb 12552 */
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 comment_at_depth(fp, "...", depth + 1);
Marko Mikulicic 0:c0ecb8bf28eb 12556 while (*ppos < end) {
Marko Mikulicic 0:c0ecb8bf28eb 12557 int s;
Marko Mikulicic 0:c0ecb8bf28eb 12558 for (s = ast_node_defs[tag].num_skips - 1; s > 0; s--) {
Marko Mikulicic 0:c0ecb8bf28eb 12559 if (*ppos == ast_get_skip(a, skips, (enum ast_which_skip) s)) {
Marko Mikulicic 0:c0ecb8bf28eb 12560 comment_at_depth(fp, "%d ->", depth + 1, s);
Marko Mikulicic 0:c0ecb8bf28eb 12561 break;
Marko Mikulicic 0:c0ecb8bf28eb 12562 }
Marko Mikulicic 0:c0ecb8bf28eb 12563 }
Marko Mikulicic 0:c0ecb8bf28eb 12564 ast_dump_tree(fp, a, ppos, depth + 1);
Marko Mikulicic 0:c0ecb8bf28eb 12565 }
Marko Mikulicic 0:c0ecb8bf28eb 12566 }
Marko Mikulicic 0:c0ecb8bf28eb 12567 }
Marko Mikulicic 0:c0ecb8bf28eb 12568 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12569
Marko Mikulicic 0:c0ecb8bf28eb 12570 V7_PRIVATE void ast_init(struct ast *ast, size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 12571 mbuf_init(&ast->mbuf, len);
Marko Mikulicic 0:c0ecb8bf28eb 12572 ast->refcnt = 0;
Marko Mikulicic 0:c0ecb8bf28eb 12573 ast->has_overflow = 0;
Marko Mikulicic 0:c0ecb8bf28eb 12574 }
Marko Mikulicic 0:c0ecb8bf28eb 12575
Marko Mikulicic 0:c0ecb8bf28eb 12576 V7_PRIVATE void ast_optimize(struct ast *ast) {
Marko Mikulicic 0:c0ecb8bf28eb 12577 /*
Marko Mikulicic 0:c0ecb8bf28eb 12578 * leave one trailing byte so that literals can be
Marko Mikulicic 0:c0ecb8bf28eb 12579 * null terminated on the fly.
Marko Mikulicic 0:c0ecb8bf28eb 12580 */
Marko Mikulicic 0:c0ecb8bf28eb 12581 mbuf_resize(&ast->mbuf, ast->mbuf.len + 1);
Marko Mikulicic 0:c0ecb8bf28eb 12582 }
Marko Mikulicic 0:c0ecb8bf28eb 12583
Marko Mikulicic 0:c0ecb8bf28eb 12584 V7_PRIVATE void ast_free(struct ast *ast) {
Marko Mikulicic 0:c0ecb8bf28eb 12585 mbuf_free(&ast->mbuf);
Marko Mikulicic 0:c0ecb8bf28eb 12586 ast->refcnt = 0;
Marko Mikulicic 0:c0ecb8bf28eb 12587 ast->has_overflow = 0;
Marko Mikulicic 0:c0ecb8bf28eb 12588 }
Marko Mikulicic 0:c0ecb8bf28eb 12589
Marko Mikulicic 0:c0ecb8bf28eb 12590 V7_PRIVATE void release_ast(struct v7 *v7, struct ast *a) {
Marko Mikulicic 0:c0ecb8bf28eb 12591 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 12592
Marko Mikulicic 0:c0ecb8bf28eb 12593 if (a->refcnt != 0) a->refcnt--;
Marko Mikulicic 0:c0ecb8bf28eb 12594
Marko Mikulicic 0:c0ecb8bf28eb 12595 if (a->refcnt == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 12596 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 12597 v7->function_arena_ast_size -= a->mbuf.size;
Marko Mikulicic 0:c0ecb8bf28eb 12598 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12599 ast_free(a);
Marko Mikulicic 0:c0ecb8bf28eb 12600 free(a);
Marko Mikulicic 0:c0ecb8bf28eb 12601 }
Marko Mikulicic 0:c0ecb8bf28eb 12602 }
Marko Mikulicic 0:c0ecb8bf28eb 12603
Marko Mikulicic 0:c0ecb8bf28eb 12604 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 12605 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 12606 #line 1 "v7/src/bcode.c"
Marko Mikulicic 0:c0ecb8bf28eb 12607 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12608 /*
Marko Mikulicic 0:c0ecb8bf28eb 12609 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 12610 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 12611 */
Marko Mikulicic 0:c0ecb8bf28eb 12612
Marko Mikulicic 0:c0ecb8bf28eb 12613 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 12614 /* Amalgamated: #include "v7/src/bcode.h" */
Marko Mikulicic 0:c0ecb8bf28eb 12615 /* Amalgamated: #include "v7/src/varint.h" */
Marko Mikulicic 0:c0ecb8bf28eb 12616 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 12617 /* Amalgamated: #include "v7/src/gc.h" */
Marko Mikulicic 0:c0ecb8bf28eb 12618 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 12619 /* Amalgamated: #include "v7/src/regexp.h" */
Marko Mikulicic 0:c0ecb8bf28eb 12620 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 12621 /* Amalgamated: #include "v7/src/util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 12622 /* Amalgamated: #include "v7/src/shdata.h" */
Marko Mikulicic 0:c0ecb8bf28eb 12623
Marko Mikulicic 0:c0ecb8bf28eb 12624 /*
Marko Mikulicic 0:c0ecb8bf28eb 12625 * TODO(dfrank): implement `bcode_serialize_*` more generically, so that they
Marko Mikulicic 0:c0ecb8bf28eb 12626 * can write to buffer instead of a `FILE`. Then, remove a need for mmap here.
Marko Mikulicic 0:c0ecb8bf28eb 12627 */
Marko Mikulicic 0:c0ecb8bf28eb 12628 #if CS_PLATFORM == CS_P_UNIX
Marko Mikulicic 0:c0ecb8bf28eb 12629 #include <sys/mman.h>
Marko Mikulicic 0:c0ecb8bf28eb 12630 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12631
Marko Mikulicic 0:c0ecb8bf28eb 12632 #if defined(V7_BCODE_DUMP) || defined(V7_BCODE_TRACE)
Marko Mikulicic 0:c0ecb8bf28eb 12633 /* clang-format off */
Marko Mikulicic 0:c0ecb8bf28eb 12634 static const char *op_names[] = {
Marko Mikulicic 0:c0ecb8bf28eb 12635 "DROP",
Marko Mikulicic 0:c0ecb8bf28eb 12636 "DUP",
Marko Mikulicic 0:c0ecb8bf28eb 12637 "2DUP",
Marko Mikulicic 0:c0ecb8bf28eb 12638 "SWAP",
Marko Mikulicic 0:c0ecb8bf28eb 12639 "STASH",
Marko Mikulicic 0:c0ecb8bf28eb 12640 "UNSTASH",
Marko Mikulicic 0:c0ecb8bf28eb 12641 "SWAP_DROP",
Marko Mikulicic 0:c0ecb8bf28eb 12642 "PUSH_UNDEFINED",
Marko Mikulicic 0:c0ecb8bf28eb 12643 "PUSH_NULL",
Marko Mikulicic 0:c0ecb8bf28eb 12644 "PUSH_THIS",
Marko Mikulicic 0:c0ecb8bf28eb 12645 "PUSH_TRUE",
Marko Mikulicic 0:c0ecb8bf28eb 12646 "PUSH_FALSE",
Marko Mikulicic 0:c0ecb8bf28eb 12647 "PUSH_ZERO",
Marko Mikulicic 0:c0ecb8bf28eb 12648 "PUSH_ONE",
Marko Mikulicic 0:c0ecb8bf28eb 12649 "PUSH_LIT",
Marko Mikulicic 0:c0ecb8bf28eb 12650 "NOT",
Marko Mikulicic 0:c0ecb8bf28eb 12651 "LOGICAL_NOT",
Marko Mikulicic 0:c0ecb8bf28eb 12652 "NEG",
Marko Mikulicic 0:c0ecb8bf28eb 12653 "POS",
Marko Mikulicic 0:c0ecb8bf28eb 12654 "ADD",
Marko Mikulicic 0:c0ecb8bf28eb 12655 "SUB",
Marko Mikulicic 0:c0ecb8bf28eb 12656 "REM",
Marko Mikulicic 0:c0ecb8bf28eb 12657 "MUL",
Marko Mikulicic 0:c0ecb8bf28eb 12658 "DIV",
Marko Mikulicic 0:c0ecb8bf28eb 12659 "LSHIFT",
Marko Mikulicic 0:c0ecb8bf28eb 12660 "RSHIFT",
Marko Mikulicic 0:c0ecb8bf28eb 12661 "URSHIFT",
Marko Mikulicic 0:c0ecb8bf28eb 12662 "OR",
Marko Mikulicic 0:c0ecb8bf28eb 12663 "XOR",
Marko Mikulicic 0:c0ecb8bf28eb 12664 "AND",
Marko Mikulicic 0:c0ecb8bf28eb 12665 "EQ_EQ",
Marko Mikulicic 0:c0ecb8bf28eb 12666 "EQ",
Marko Mikulicic 0:c0ecb8bf28eb 12667 "NE",
Marko Mikulicic 0:c0ecb8bf28eb 12668 "NE_NE",
Marko Mikulicic 0:c0ecb8bf28eb 12669 "LT",
Marko Mikulicic 0:c0ecb8bf28eb 12670 "LE",
Marko Mikulicic 0:c0ecb8bf28eb 12671 "GT",
Marko Mikulicic 0:c0ecb8bf28eb 12672 "GE",
Marko Mikulicic 0:c0ecb8bf28eb 12673 "INSTANCEOF",
Marko Mikulicic 0:c0ecb8bf28eb 12674 "TYPEOF",
Marko Mikulicic 0:c0ecb8bf28eb 12675 "IN",
Marko Mikulicic 0:c0ecb8bf28eb 12676 "GET",
Marko Mikulicic 0:c0ecb8bf28eb 12677 "SET",
Marko Mikulicic 0:c0ecb8bf28eb 12678 "SET_VAR",
Marko Mikulicic 0:c0ecb8bf28eb 12679 "GET_VAR",
Marko Mikulicic 0:c0ecb8bf28eb 12680 "SAFE_GET_VAR",
Marko Mikulicic 0:c0ecb8bf28eb 12681 "JMP",
Marko Mikulicic 0:c0ecb8bf28eb 12682 "JMP_TRUE",
Marko Mikulicic 0:c0ecb8bf28eb 12683 "JMP_FALSE",
Marko Mikulicic 0:c0ecb8bf28eb 12684 "JMP_TRUE_DROP",
Marko Mikulicic 0:c0ecb8bf28eb 12685 "JMP_IF_CONTINUE",
Marko Mikulicic 0:c0ecb8bf28eb 12686 "CREATE_OBJ",
Marko Mikulicic 0:c0ecb8bf28eb 12687 "CREATE_ARR",
Marko Mikulicic 0:c0ecb8bf28eb 12688 "PUSH_PROP_ITER_CTX",
Marko Mikulicic 0:c0ecb8bf28eb 12689 "NEXT_PROP",
Marko Mikulicic 0:c0ecb8bf28eb 12690 "FUNC_LIT",
Marko Mikulicic 0:c0ecb8bf28eb 12691 "CALL",
Marko Mikulicic 0:c0ecb8bf28eb 12692 "NEW",
Marko Mikulicic 0:c0ecb8bf28eb 12693 "CHECK_CALL",
Marko Mikulicic 0:c0ecb8bf28eb 12694 "RET",
Marko Mikulicic 0:c0ecb8bf28eb 12695 "DELETE",
Marko Mikulicic 0:c0ecb8bf28eb 12696 "DELETE_VAR",
Marko Mikulicic 0:c0ecb8bf28eb 12697 "TRY_PUSH_CATCH",
Marko Mikulicic 0:c0ecb8bf28eb 12698 "TRY_PUSH_FINALLY",
Marko Mikulicic 0:c0ecb8bf28eb 12699 "TRY_PUSH_LOOP",
Marko Mikulicic 0:c0ecb8bf28eb 12700 "TRY_PUSH_SWITCH",
Marko Mikulicic 0:c0ecb8bf28eb 12701 "TRY_POP",
Marko Mikulicic 0:c0ecb8bf28eb 12702 "AFTER_FINALLY",
Marko Mikulicic 0:c0ecb8bf28eb 12703 "THROW",
Marko Mikulicic 0:c0ecb8bf28eb 12704 "BREAK",
Marko Mikulicic 0:c0ecb8bf28eb 12705 "CONTINUE",
Marko Mikulicic 0:c0ecb8bf28eb 12706 "ENTER_CATCH",
Marko Mikulicic 0:c0ecb8bf28eb 12707 "EXIT_CATCH",
Marko Mikulicic 0:c0ecb8bf28eb 12708 };
Marko Mikulicic 0:c0ecb8bf28eb 12709 /* clang-format on */
Marko Mikulicic 0:c0ecb8bf28eb 12710
Marko Mikulicic 0:c0ecb8bf28eb 12711 V7_STATIC_ASSERT(OP_MAX == ARRAY_SIZE(op_names), bad_op_names);
Marko Mikulicic 0:c0ecb8bf28eb 12712 V7_STATIC_ASSERT(OP_MAX <= _OP_LINE_NO, bad_OP_LINE_NO);
Marko Mikulicic 0:c0ecb8bf28eb 12713 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12714
Marko Mikulicic 0:c0ecb8bf28eb 12715 static void bcode_serialize_func(struct v7 *v7, struct bcode *bcode, FILE *out);
Marko Mikulicic 0:c0ecb8bf28eb 12716
Marko Mikulicic 0:c0ecb8bf28eb 12717 static size_t bcode_ops_append(struct bcode_builder *bbuilder, const void *buf,
Marko Mikulicic 0:c0ecb8bf28eb 12718 size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 12719 size_t ret;
Marko Mikulicic 0:c0ecb8bf28eb 12720 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 12721 bbuilder->v7->bcode_ops_size -= bbuilder->ops.len;
Marko Mikulicic 0:c0ecb8bf28eb 12722 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12723 ret = mbuf_append(&bbuilder->ops, buf, len);
Marko Mikulicic 0:c0ecb8bf28eb 12724 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 12725 bbuilder->v7->bcode_ops_size += bbuilder->ops.len;
Marko Mikulicic 0:c0ecb8bf28eb 12726 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12727 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 12728 }
Marko Mikulicic 0:c0ecb8bf28eb 12729
Marko Mikulicic 0:c0ecb8bf28eb 12730 /*
Marko Mikulicic 0:c0ecb8bf28eb 12731 * Initialize bcode builder. The `bcode` should be already initialized by the
Marko Mikulicic 0:c0ecb8bf28eb 12732 * caller, and should be empty (i.e. should not own any ops, literals, etc)
Marko Mikulicic 0:c0ecb8bf28eb 12733 *
Marko Mikulicic 0:c0ecb8bf28eb 12734 * TODO(dfrank) : probably make `bcode_builder_init()` to initialize `bcode`
Marko Mikulicic 0:c0ecb8bf28eb 12735 * as well
Marko Mikulicic 0:c0ecb8bf28eb 12736 */
Marko Mikulicic 0:c0ecb8bf28eb 12737 V7_PRIVATE void bcode_builder_init(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 12738 struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 12739 struct bcode *bcode) {
Marko Mikulicic 0:c0ecb8bf28eb 12740 memset(bbuilder, 0x00, sizeof(*bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 12741 bbuilder->v7 = v7;
Marko Mikulicic 0:c0ecb8bf28eb 12742 bbuilder->bcode = bcode;
Marko Mikulicic 0:c0ecb8bf28eb 12743
Marko Mikulicic 0:c0ecb8bf28eb 12744 mbuf_init(&bbuilder->ops, 0);
Marko Mikulicic 0:c0ecb8bf28eb 12745 mbuf_init(&bbuilder->lit, 0);
Marko Mikulicic 0:c0ecb8bf28eb 12746 }
Marko Mikulicic 0:c0ecb8bf28eb 12747
Marko Mikulicic 0:c0ecb8bf28eb 12748 /*
Marko Mikulicic 0:c0ecb8bf28eb 12749 * Finalize bcode builder: propagate data to the bcode and transfer the
Marko Mikulicic 0:c0ecb8bf28eb 12750 * ownership from builder to bcode
Marko Mikulicic 0:c0ecb8bf28eb 12751 */
Marko Mikulicic 0:c0ecb8bf28eb 12752 V7_PRIVATE void bcode_builder_finalize(struct bcode_builder *bbuilder) {
Marko Mikulicic 0:c0ecb8bf28eb 12753 mbuf_trim(&bbuilder->ops);
Marko Mikulicic 0:c0ecb8bf28eb 12754 bbuilder->bcode->ops.p = bbuilder->ops.buf;
Marko Mikulicic 0:c0ecb8bf28eb 12755 bbuilder->bcode->ops.len = bbuilder->ops.len;
Marko Mikulicic 0:c0ecb8bf28eb 12756 mbuf_init(&bbuilder->ops, 0);
Marko Mikulicic 0:c0ecb8bf28eb 12757
Marko Mikulicic 0:c0ecb8bf28eb 12758 mbuf_trim(&bbuilder->lit);
Marko Mikulicic 0:c0ecb8bf28eb 12759 bbuilder->bcode->lit.p = bbuilder->lit.buf;
Marko Mikulicic 0:c0ecb8bf28eb 12760 bbuilder->bcode->lit.len = bbuilder->lit.len;
Marko Mikulicic 0:c0ecb8bf28eb 12761 mbuf_init(&bbuilder->lit, 0);
Marko Mikulicic 0:c0ecb8bf28eb 12762
Marko Mikulicic 0:c0ecb8bf28eb 12763 memset(bbuilder, 0x00, sizeof(*bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 12764 }
Marko Mikulicic 0:c0ecb8bf28eb 12765
Marko Mikulicic 0:c0ecb8bf28eb 12766 #if defined(V7_BCODE_DUMP) || defined(V7_BCODE_TRACE)
Marko Mikulicic 0:c0ecb8bf28eb 12767 V7_PRIVATE void dump_op(struct v7 *v7, FILE *f, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 12768 char **ops) {
Marko Mikulicic 0:c0ecb8bf28eb 12769 char *p = *ops;
Marko Mikulicic 0:c0ecb8bf28eb 12770
Marko Mikulicic 0:c0ecb8bf28eb 12771 assert(*p < OP_MAX);
Marko Mikulicic 0:c0ecb8bf28eb 12772 fprintf(f, "%zu: %s", (size_t)(p - bcode->ops.p), op_names[(uint8_t) *p]);
Marko Mikulicic 0:c0ecb8bf28eb 12773 switch (*p) {
Marko Mikulicic 0:c0ecb8bf28eb 12774 case OP_PUSH_LIT:
Marko Mikulicic 0:c0ecb8bf28eb 12775 case OP_SAFE_GET_VAR:
Marko Mikulicic 0:c0ecb8bf28eb 12776 case OP_GET_VAR:
Marko Mikulicic 0:c0ecb8bf28eb 12777 case OP_SET_VAR: {
Marko Mikulicic 0:c0ecb8bf28eb 12778 size_t idx = bcode_get_varint(&p);
Marko Mikulicic 0:c0ecb8bf28eb 12779 fprintf(f, "(%lu): ", (unsigned long) idx);
Marko Mikulicic 0:c0ecb8bf28eb 12780 v7_fprint(f, v7, ((val_t *) bcode->lit.p)[idx]);
Marko Mikulicic 0:c0ecb8bf28eb 12781 break;
Marko Mikulicic 0:c0ecb8bf28eb 12782 }
Marko Mikulicic 0:c0ecb8bf28eb 12783 case OP_CALL:
Marko Mikulicic 0:c0ecb8bf28eb 12784 case OP_NEW:
Marko Mikulicic 0:c0ecb8bf28eb 12785 p++;
Marko Mikulicic 0:c0ecb8bf28eb 12786 fprintf(f, "(%d)", *p);
Marko Mikulicic 0:c0ecb8bf28eb 12787 break;
Marko Mikulicic 0:c0ecb8bf28eb 12788 case OP_JMP:
Marko Mikulicic 0:c0ecb8bf28eb 12789 case OP_JMP_FALSE:
Marko Mikulicic 0:c0ecb8bf28eb 12790 case OP_JMP_TRUE:
Marko Mikulicic 0:c0ecb8bf28eb 12791 case OP_JMP_TRUE_DROP:
Marko Mikulicic 0:c0ecb8bf28eb 12792 case OP_JMP_IF_CONTINUE:
Marko Mikulicic 0:c0ecb8bf28eb 12793 case OP_TRY_PUSH_CATCH:
Marko Mikulicic 0:c0ecb8bf28eb 12794 case OP_TRY_PUSH_FINALLY:
Marko Mikulicic 0:c0ecb8bf28eb 12795 case OP_TRY_PUSH_LOOP:
Marko Mikulicic 0:c0ecb8bf28eb 12796 case OP_TRY_PUSH_SWITCH: {
Marko Mikulicic 0:c0ecb8bf28eb 12797 bcode_off_t target;
Marko Mikulicic 0:c0ecb8bf28eb 12798 p++;
Marko Mikulicic 0:c0ecb8bf28eb 12799 memcpy(&target, p, sizeof(target));
Marko Mikulicic 0:c0ecb8bf28eb 12800 fprintf(f, "(%lu)", (unsigned long) target);
Marko Mikulicic 0:c0ecb8bf28eb 12801 p += sizeof(target) - 1;
Marko Mikulicic 0:c0ecb8bf28eb 12802 break;
Marko Mikulicic 0:c0ecb8bf28eb 12803 }
Marko Mikulicic 0:c0ecb8bf28eb 12804 default:
Marko Mikulicic 0:c0ecb8bf28eb 12805 break;
Marko Mikulicic 0:c0ecb8bf28eb 12806 }
Marko Mikulicic 0:c0ecb8bf28eb 12807 fprintf(f, "\n");
Marko Mikulicic 0:c0ecb8bf28eb 12808 *ops = p;
Marko Mikulicic 0:c0ecb8bf28eb 12809 }
Marko Mikulicic 0:c0ecb8bf28eb 12810 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12811
Marko Mikulicic 0:c0ecb8bf28eb 12812 #ifdef V7_BCODE_DUMP
Marko Mikulicic 0:c0ecb8bf28eb 12813 V7_PRIVATE void dump_bcode(struct v7 *v7, FILE *f, struct bcode *bcode) {
Marko Mikulicic 0:c0ecb8bf28eb 12814 char *p = bcode_end_names(bcode->ops.p, bcode->names_cnt);
Marko Mikulicic 0:c0ecb8bf28eb 12815 char *end = bcode->ops.p + bcode->ops.len;
Marko Mikulicic 0:c0ecb8bf28eb 12816 for (; p < end; p++) {
Marko Mikulicic 0:c0ecb8bf28eb 12817 dump_op(v7, f, bcode, &p);
Marko Mikulicic 0:c0ecb8bf28eb 12818 }
Marko Mikulicic 0:c0ecb8bf28eb 12819 }
Marko Mikulicic 0:c0ecb8bf28eb 12820 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12821
Marko Mikulicic 0:c0ecb8bf28eb 12822 V7_PRIVATE void bcode_init(struct bcode *bcode, uint8_t strict_mode,
Marko Mikulicic 0:c0ecb8bf28eb 12823 void *filename, uint8_t filename_in_rom) {
Marko Mikulicic 0:c0ecb8bf28eb 12824 memset(bcode, 0x00, sizeof(*bcode));
Marko Mikulicic 0:c0ecb8bf28eb 12825 bcode->refcnt = 0;
Marko Mikulicic 0:c0ecb8bf28eb 12826 bcode->args_cnt = 0;
Marko Mikulicic 0:c0ecb8bf28eb 12827 bcode->strict_mode = strict_mode;
Marko Mikulicic 0:c0ecb8bf28eb 12828 #ifndef V7_DISABLE_FILENAMES
Marko Mikulicic 0:c0ecb8bf28eb 12829 bcode->filename = filename;
Marko Mikulicic 0:c0ecb8bf28eb 12830 bcode->filename_in_rom = filename_in_rom;
Marko Mikulicic 0:c0ecb8bf28eb 12831 #else
Marko Mikulicic 0:c0ecb8bf28eb 12832 (void) filename;
Marko Mikulicic 0:c0ecb8bf28eb 12833 (void) filename_in_rom;
Marko Mikulicic 0:c0ecb8bf28eb 12834 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12835 }
Marko Mikulicic 0:c0ecb8bf28eb 12836
Marko Mikulicic 0:c0ecb8bf28eb 12837 V7_PRIVATE void bcode_free(struct v7 *v7, struct bcode *bcode) {
Marko Mikulicic 0:c0ecb8bf28eb 12838 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 12839 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 12840 if (!bcode->ops_in_rom) {
Marko Mikulicic 0:c0ecb8bf28eb 12841 v7->bcode_ops_size -= bcode->ops.len;
Marko Mikulicic 0:c0ecb8bf28eb 12842 }
Marko Mikulicic 0:c0ecb8bf28eb 12843
Marko Mikulicic 0:c0ecb8bf28eb 12844 v7->bcode_lit_total_size -= bcode->lit.len;
Marko Mikulicic 0:c0ecb8bf28eb 12845 if (bcode->deserialized) {
Marko Mikulicic 0:c0ecb8bf28eb 12846 v7->bcode_lit_deser_size -= bcode->lit.len;
Marko Mikulicic 0:c0ecb8bf28eb 12847 }
Marko Mikulicic 0:c0ecb8bf28eb 12848 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12849
Marko Mikulicic 0:c0ecb8bf28eb 12850 if (!bcode->ops_in_rom) {
Marko Mikulicic 0:c0ecb8bf28eb 12851 free(bcode->ops.p);
Marko Mikulicic 0:c0ecb8bf28eb 12852 }
Marko Mikulicic 0:c0ecb8bf28eb 12853 memset(&bcode->ops, 0x00, sizeof(bcode->ops));
Marko Mikulicic 0:c0ecb8bf28eb 12854
Marko Mikulicic 0:c0ecb8bf28eb 12855 free(bcode->lit.p);
Marko Mikulicic 0:c0ecb8bf28eb 12856 memset(&bcode->lit, 0x00, sizeof(bcode->lit));
Marko Mikulicic 0:c0ecb8bf28eb 12857
Marko Mikulicic 0:c0ecb8bf28eb 12858 #ifndef V7_DISABLE_FILENAMES
Marko Mikulicic 0:c0ecb8bf28eb 12859 if (!bcode->filename_in_rom && bcode->filename != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 12860 shdata_release((struct shdata *) bcode->filename);
Marko Mikulicic 0:c0ecb8bf28eb 12861 bcode->filename = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 12862 }
Marko Mikulicic 0:c0ecb8bf28eb 12863 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12864
Marko Mikulicic 0:c0ecb8bf28eb 12865 bcode->refcnt = 0;
Marko Mikulicic 0:c0ecb8bf28eb 12866 }
Marko Mikulicic 0:c0ecb8bf28eb 12867
Marko Mikulicic 0:c0ecb8bf28eb 12868 V7_PRIVATE void retain_bcode(struct v7 *v7, struct bcode *b) {
Marko Mikulicic 0:c0ecb8bf28eb 12869 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 12870 if (!b->frozen) {
Marko Mikulicic 0:c0ecb8bf28eb 12871 b->refcnt++;
Marko Mikulicic 0:c0ecb8bf28eb 12872 }
Marko Mikulicic 0:c0ecb8bf28eb 12873 }
Marko Mikulicic 0:c0ecb8bf28eb 12874
Marko Mikulicic 0:c0ecb8bf28eb 12875 V7_PRIVATE void release_bcode(struct v7 *v7, struct bcode *b) {
Marko Mikulicic 0:c0ecb8bf28eb 12876 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 12877 if (b->frozen) return;
Marko Mikulicic 0:c0ecb8bf28eb 12878
Marko Mikulicic 0:c0ecb8bf28eb 12879 assert(b->refcnt > 0);
Marko Mikulicic 0:c0ecb8bf28eb 12880 if (b->refcnt != 0) b->refcnt--;
Marko Mikulicic 0:c0ecb8bf28eb 12881
Marko Mikulicic 0:c0ecb8bf28eb 12882 if (b->refcnt == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 12883 bcode_free(v7, b);
Marko Mikulicic 0:c0ecb8bf28eb 12884 free(b);
Marko Mikulicic 0:c0ecb8bf28eb 12885 }
Marko Mikulicic 0:c0ecb8bf28eb 12886 }
Marko Mikulicic 0:c0ecb8bf28eb 12887
Marko Mikulicic 0:c0ecb8bf28eb 12888 #ifndef V7_DISABLE_FILENAMES
Marko Mikulicic 0:c0ecb8bf28eb 12889 V7_PRIVATE const char *bcode_get_filename(struct bcode *bcode) {
Marko Mikulicic 0:c0ecb8bf28eb 12890 const char *ret = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 12891 if (bcode->filename_in_rom) {
Marko Mikulicic 0:c0ecb8bf28eb 12892 ret = (const char *) bcode->filename;
Marko Mikulicic 0:c0ecb8bf28eb 12893 } else if (bcode->filename != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 12894 ret = (const char *) shdata_get_payload((struct shdata *) bcode->filename);
Marko Mikulicic 0:c0ecb8bf28eb 12895 }
Marko Mikulicic 0:c0ecb8bf28eb 12896 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 12897 }
Marko Mikulicic 0:c0ecb8bf28eb 12898 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12899
Marko Mikulicic 0:c0ecb8bf28eb 12900 V7_PRIVATE void bcode_copy_filename_from(struct bcode *dst, struct bcode *src) {
Marko Mikulicic 0:c0ecb8bf28eb 12901 #ifndef V7_DISABLE_FILENAMES
Marko Mikulicic 0:c0ecb8bf28eb 12902 dst->filename_in_rom = src->filename_in_rom;
Marko Mikulicic 0:c0ecb8bf28eb 12903 dst->filename = src->filename;
Marko Mikulicic 0:c0ecb8bf28eb 12904
Marko Mikulicic 0:c0ecb8bf28eb 12905 if (src->filename != NULL && !src->filename_in_rom) {
Marko Mikulicic 0:c0ecb8bf28eb 12906 shdata_retain((struct shdata *) dst->filename);
Marko Mikulicic 0:c0ecb8bf28eb 12907 }
Marko Mikulicic 0:c0ecb8bf28eb 12908 #else
Marko Mikulicic 0:c0ecb8bf28eb 12909 (void) dst;
Marko Mikulicic 0:c0ecb8bf28eb 12910 (void) src;
Marko Mikulicic 0:c0ecb8bf28eb 12911 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12912 }
Marko Mikulicic 0:c0ecb8bf28eb 12913
Marko Mikulicic 0:c0ecb8bf28eb 12914 V7_PRIVATE void bcode_op(struct bcode_builder *bbuilder, uint8_t op) {
Marko Mikulicic 0:c0ecb8bf28eb 12915 bcode_ops_append(bbuilder, &op, 1);
Marko Mikulicic 0:c0ecb8bf28eb 12916 }
Marko Mikulicic 0:c0ecb8bf28eb 12917
Marko Mikulicic 0:c0ecb8bf28eb 12918 #ifndef V7_DISABLE_LINE_NUMBERS
Marko Mikulicic 0:c0ecb8bf28eb 12919 V7_PRIVATE void bcode_append_lineno(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 12920 int line_no) {
Marko Mikulicic 0:c0ecb8bf28eb 12921 int offset = bbuilder->ops.len;
Marko Mikulicic 0:c0ecb8bf28eb 12922 bcode_add_varint(bbuilder, (line_no << 1) | 1);
Marko Mikulicic 0:c0ecb8bf28eb 12923 bbuilder->ops.buf[offset] = msb_lsb_swap(bbuilder->ops.buf[offset]);
Marko Mikulicic 0:c0ecb8bf28eb 12924 assert(bbuilder->ops.buf[offset] & _OP_LINE_NO);
Marko Mikulicic 0:c0ecb8bf28eb 12925 }
Marko Mikulicic 0:c0ecb8bf28eb 12926 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12927
Marko Mikulicic 0:c0ecb8bf28eb 12928 /*
Marko Mikulicic 0:c0ecb8bf28eb 12929 * Appends varint-encoded integer to the `ops` mbuf
Marko Mikulicic 0:c0ecb8bf28eb 12930 */
Marko Mikulicic 0:c0ecb8bf28eb 12931 V7_PRIVATE void bcode_add_varint(struct bcode_builder *bbuilder, size_t value) {
Marko Mikulicic 0:c0ecb8bf28eb 12932 int k = calc_llen(value); /* Calculate how many bytes length takes */
Marko Mikulicic 0:c0ecb8bf28eb 12933 int offset = bbuilder->ops.len;
Marko Mikulicic 0:c0ecb8bf28eb 12934
Marko Mikulicic 0:c0ecb8bf28eb 12935 /* Allocate buffer */
Marko Mikulicic 0:c0ecb8bf28eb 12936 bcode_ops_append(bbuilder, NULL, k);
Marko Mikulicic 0:c0ecb8bf28eb 12937
Marko Mikulicic 0:c0ecb8bf28eb 12938 /* Write value */
Marko Mikulicic 0:c0ecb8bf28eb 12939 encode_varint(value, (unsigned char *) bbuilder->ops.buf + offset);
Marko Mikulicic 0:c0ecb8bf28eb 12940 }
Marko Mikulicic 0:c0ecb8bf28eb 12941
Marko Mikulicic 0:c0ecb8bf28eb 12942 V7_PRIVATE size_t bcode_get_varint(char **ops) {
Marko Mikulicic 0:c0ecb8bf28eb 12943 size_t ret = 0;
Marko Mikulicic 0:c0ecb8bf28eb 12944 int len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 12945 (*ops)++;
Marko Mikulicic 0:c0ecb8bf28eb 12946 ret = decode_varint((unsigned char *) *ops, &len);
Marko Mikulicic 0:c0ecb8bf28eb 12947 *ops += len - 1;
Marko Mikulicic 0:c0ecb8bf28eb 12948 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 12949 }
Marko Mikulicic 0:c0ecb8bf28eb 12950
Marko Mikulicic 0:c0ecb8bf28eb 12951 static int bcode_is_inline_string(struct v7 *v7, val_t val) {
Marko Mikulicic 0:c0ecb8bf28eb 12952 uint64_t tag = val & V7_TAG_MASK;
Marko Mikulicic 0:c0ecb8bf28eb 12953 if (v7->is_precompiling && v7_is_string(val)) {
Marko Mikulicic 0:c0ecb8bf28eb 12954 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 12955 }
Marko Mikulicic 0:c0ecb8bf28eb 12956 return tag == V7_TAG_STRING_I || tag == V7_TAG_STRING_5;
Marko Mikulicic 0:c0ecb8bf28eb 12957 }
Marko Mikulicic 0:c0ecb8bf28eb 12958
Marko Mikulicic 0:c0ecb8bf28eb 12959 static int bcode_is_inline_func(struct v7 *v7, val_t val) {
Marko Mikulicic 0:c0ecb8bf28eb 12960 return (v7->is_precompiling && is_js_function(val));
Marko Mikulicic 0:c0ecb8bf28eb 12961 }
Marko Mikulicic 0:c0ecb8bf28eb 12962
Marko Mikulicic 0:c0ecb8bf28eb 12963 static int bcode_is_inline_regexp(struct v7 *v7, val_t val) {
Marko Mikulicic 0:c0ecb8bf28eb 12964 return (v7->is_precompiling && v7_is_regexp(v7, val));
Marko Mikulicic 0:c0ecb8bf28eb 12965 }
Marko Mikulicic 0:c0ecb8bf28eb 12966
Marko Mikulicic 0:c0ecb8bf28eb 12967 V7_PRIVATE lit_t bcode_add_lit(struct bcode_builder *bbuilder, val_t val) {
Marko Mikulicic 0:c0ecb8bf28eb 12968 lit_t lit;
Marko Mikulicic 0:c0ecb8bf28eb 12969 memset(&lit, 0, sizeof(lit));
Marko Mikulicic 0:c0ecb8bf28eb 12970
Marko Mikulicic 0:c0ecb8bf28eb 12971 if (bcode_is_inline_string(bbuilder->v7, val) ||
Marko Mikulicic 0:c0ecb8bf28eb 12972 bcode_is_inline_func(bbuilder->v7, val) || v7_is_number(val) ||
Marko Mikulicic 0:c0ecb8bf28eb 12973 bcode_is_inline_regexp(bbuilder->v7, val)) {
Marko Mikulicic 0:c0ecb8bf28eb 12974 /* literal should be inlined (it's `bcode_op_lit()` who does this) */
Marko Mikulicic 0:c0ecb8bf28eb 12975 lit.mode = LIT_MODE__INLINED;
Marko Mikulicic 0:c0ecb8bf28eb 12976 lit.v.inline_val = val;
Marko Mikulicic 0:c0ecb8bf28eb 12977 } else {
Marko Mikulicic 0:c0ecb8bf28eb 12978 /* literal will now be added to the literal table */
Marko Mikulicic 0:c0ecb8bf28eb 12979 lit.mode = LIT_MODE__TABLE;
Marko Mikulicic 0:c0ecb8bf28eb 12980 lit.v.lit_idx = bbuilder->lit.len / sizeof(val);
Marko Mikulicic 0:c0ecb8bf28eb 12981
Marko Mikulicic 0:c0ecb8bf28eb 12982 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 12983 bbuilder->v7->bcode_lit_total_size -= bbuilder->lit.len;
Marko Mikulicic 0:c0ecb8bf28eb 12984 if (bbuilder->bcode->deserialized) {
Marko Mikulicic 0:c0ecb8bf28eb 12985 bbuilder->v7->bcode_lit_deser_size -= bbuilder->lit.len;
Marko Mikulicic 0:c0ecb8bf28eb 12986 }
Marko Mikulicic 0:c0ecb8bf28eb 12987 #endif
Marko Mikulicic 0:c0ecb8bf28eb 12988
Marko Mikulicic 0:c0ecb8bf28eb 12989 mbuf_append(&bbuilder->lit, &val, sizeof(val));
Marko Mikulicic 0:c0ecb8bf28eb 12990
Marko Mikulicic 0:c0ecb8bf28eb 12991 /*
Marko Mikulicic 0:c0ecb8bf28eb 12992 * immediately propagate current lit buffer to the bcode, so that GC will
Marko Mikulicic 0:c0ecb8bf28eb 12993 * be aware of it
Marko Mikulicic 0:c0ecb8bf28eb 12994 */
Marko Mikulicic 0:c0ecb8bf28eb 12995 bbuilder->bcode->lit.p = bbuilder->lit.buf;
Marko Mikulicic 0:c0ecb8bf28eb 12996 bbuilder->bcode->lit.len = bbuilder->lit.len;
Marko Mikulicic 0:c0ecb8bf28eb 12997
Marko Mikulicic 0:c0ecb8bf28eb 12998 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 12999 bbuilder->v7->bcode_lit_total_size += bbuilder->lit.len;
Marko Mikulicic 0:c0ecb8bf28eb 13000 if (bbuilder->bcode->deserialized) {
Marko Mikulicic 0:c0ecb8bf28eb 13001 bbuilder->v7->bcode_lit_deser_size += bbuilder->lit.len;
Marko Mikulicic 0:c0ecb8bf28eb 13002 }
Marko Mikulicic 0:c0ecb8bf28eb 13003 #endif
Marko Mikulicic 0:c0ecb8bf28eb 13004 }
Marko Mikulicic 0:c0ecb8bf28eb 13005 return lit;
Marko Mikulicic 0:c0ecb8bf28eb 13006 }
Marko Mikulicic 0:c0ecb8bf28eb 13007
Marko Mikulicic 0:c0ecb8bf28eb 13008 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 13009 V7_PRIVATE v7_val_t bcode_get_lit(struct bcode *bcode, size_t idx) {
Marko Mikulicic 0:c0ecb8bf28eb 13010 val_t ret;
Marko Mikulicic 0:c0ecb8bf28eb 13011 memcpy(&ret, bcode->lit.p + (size_t) idx * sizeof(ret), sizeof(ret));
Marko Mikulicic 0:c0ecb8bf28eb 13012 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 13013 }
Marko Mikulicic 0:c0ecb8bf28eb 13014 #endif
Marko Mikulicic 0:c0ecb8bf28eb 13015
Marko Mikulicic 0:c0ecb8bf28eb 13016 static const char *bcode_deserialize_func(struct v7 *v7, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 13017 const char *data);
Marko Mikulicic 0:c0ecb8bf28eb 13018
Marko Mikulicic 0:c0ecb8bf28eb 13019 V7_PRIVATE v7_val_t
Marko Mikulicic 0:c0ecb8bf28eb 13020 bcode_decode_lit(struct v7 *v7, struct bcode *bcode, char **ops) {
Marko Mikulicic 0:c0ecb8bf28eb 13021 struct v7_vec *vec = &bcode->lit;
Marko Mikulicic 0:c0ecb8bf28eb 13022 size_t idx = bcode_get_varint(ops);
Marko Mikulicic 0:c0ecb8bf28eb 13023 switch (idx) {
Marko Mikulicic 0:c0ecb8bf28eb 13024 case BCODE_INLINE_STRING_TYPE_TAG: {
Marko Mikulicic 0:c0ecb8bf28eb 13025 val_t res;
Marko Mikulicic 0:c0ecb8bf28eb 13026 size_t len = bcode_get_varint(ops);
Marko Mikulicic 0:c0ecb8bf28eb 13027 res = v7_mk_string(
Marko Mikulicic 0:c0ecb8bf28eb 13028 v7, (const char *) *ops + 1 /*skip BCODE_INLINE_STRING_TYPE_TAG*/,
Marko Mikulicic 0:c0ecb8bf28eb 13029 len, !bcode->ops_in_rom);
Marko Mikulicic 0:c0ecb8bf28eb 13030 *ops += len + 1;
Marko Mikulicic 0:c0ecb8bf28eb 13031 return res;
Marko Mikulicic 0:c0ecb8bf28eb 13032 }
Marko Mikulicic 0:c0ecb8bf28eb 13033 case BCODE_INLINE_NUMBER_TYPE_TAG: {
Marko Mikulicic 0:c0ecb8bf28eb 13034 val_t res;
Marko Mikulicic 0:c0ecb8bf28eb 13035 memcpy(&res, *ops + 1 /*skip BCODE_INLINE_NUMBER_TYPE_TAG*/, sizeof(res));
Marko Mikulicic 0:c0ecb8bf28eb 13036 *ops += sizeof(res);
Marko Mikulicic 0:c0ecb8bf28eb 13037 return res;
Marko Mikulicic 0:c0ecb8bf28eb 13038 }
Marko Mikulicic 0:c0ecb8bf28eb 13039 case BCODE_INLINE_FUNC_TYPE_TAG: {
Marko Mikulicic 0:c0ecb8bf28eb 13040 /*
Marko Mikulicic 0:c0ecb8bf28eb 13041 * Create half-done function: without scope but _with_ prototype. Scope
Marko Mikulicic 0:c0ecb8bf28eb 13042 * will be set by `bcode_instantiate_function()`.
Marko Mikulicic 0:c0ecb8bf28eb 13043 *
Marko Mikulicic 0:c0ecb8bf28eb 13044 * The fact that the prototype is already set will make
Marko Mikulicic 0:c0ecb8bf28eb 13045 * `bcode_instantiate_function()` just set scope on this function,
Marko Mikulicic 0:c0ecb8bf28eb 13046 * instead of creating a new one.
Marko Mikulicic 0:c0ecb8bf28eb 13047 */
Marko Mikulicic 0:c0ecb8bf28eb 13048 val_t res = mk_js_function(v7, NULL, v7_mk_object(v7));
Marko Mikulicic 0:c0ecb8bf28eb 13049
Marko Mikulicic 0:c0ecb8bf28eb 13050 /* Create bcode in this half-done function */
Marko Mikulicic 0:c0ecb8bf28eb 13051 struct v7_js_function *func = get_js_function_struct(res);
Marko Mikulicic 0:c0ecb8bf28eb 13052
Marko Mikulicic 0:c0ecb8bf28eb 13053 func->bcode = (struct bcode *) calloc(1, sizeof(*func->bcode));
Marko Mikulicic 0:c0ecb8bf28eb 13054 bcode_init(func->bcode, bcode->strict_mode, NULL /* will be set below */,
Marko Mikulicic 0:c0ecb8bf28eb 13055 0);
Marko Mikulicic 0:c0ecb8bf28eb 13056 bcode_copy_filename_from(func->bcode, bcode);
Marko Mikulicic 0:c0ecb8bf28eb 13057 retain_bcode(v7, func->bcode);
Marko Mikulicic 0:c0ecb8bf28eb 13058
Marko Mikulicic 0:c0ecb8bf28eb 13059 /* deserialize the function's bcode from `ops` */
Marko Mikulicic 0:c0ecb8bf28eb 13060 *ops = (char *) bcode_deserialize_func(
Marko Mikulicic 0:c0ecb8bf28eb 13061 v7, func->bcode, *ops + 1 /*skip BCODE_INLINE_FUNC_TYPE_TAG*/);
Marko Mikulicic 0:c0ecb8bf28eb 13062
Marko Mikulicic 0:c0ecb8bf28eb 13063 /* decrement *ops, because it will be incremented by `eval_bcode` soon */
Marko Mikulicic 0:c0ecb8bf28eb 13064 *ops -= 1;
Marko Mikulicic 0:c0ecb8bf28eb 13065
Marko Mikulicic 0:c0ecb8bf28eb 13066 return res;
Marko Mikulicic 0:c0ecb8bf28eb 13067 }
Marko Mikulicic 0:c0ecb8bf28eb 13068 case BCODE_INLINE_REGEXP_TYPE_TAG: {
Marko Mikulicic 0:c0ecb8bf28eb 13069 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 13070 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 13071 val_t res;
Marko Mikulicic 0:c0ecb8bf28eb 13072 size_t len_src, len_flags;
Marko Mikulicic 0:c0ecb8bf28eb 13073 char *buf_src, *buf_flags;
Marko Mikulicic 0:c0ecb8bf28eb 13074
Marko Mikulicic 0:c0ecb8bf28eb 13075 len_src = bcode_get_varint(ops);
Marko Mikulicic 0:c0ecb8bf28eb 13076 buf_src = *ops + 1;
Marko Mikulicic 0:c0ecb8bf28eb 13077 *ops += len_src + 1 /* nul term */;
Marko Mikulicic 0:c0ecb8bf28eb 13078
Marko Mikulicic 0:c0ecb8bf28eb 13079 len_flags = bcode_get_varint(ops);
Marko Mikulicic 0:c0ecb8bf28eb 13080 buf_flags = *ops + 1;
Marko Mikulicic 0:c0ecb8bf28eb 13081 *ops += len_flags + 1 /* nul term */;
Marko Mikulicic 0:c0ecb8bf28eb 13082
Marko Mikulicic 0:c0ecb8bf28eb 13083 rcode = v7_mk_regexp(v7, buf_src, len_src, buf_flags, len_flags, &res);
Marko Mikulicic 0:c0ecb8bf28eb 13084 assert(rcode == V7_OK);
Marko Mikulicic 0:c0ecb8bf28eb 13085 (void) rcode;
Marko Mikulicic 0:c0ecb8bf28eb 13086
Marko Mikulicic 0:c0ecb8bf28eb 13087 return res;
Marko Mikulicic 0:c0ecb8bf28eb 13088 #else
Marko Mikulicic 0:c0ecb8bf28eb 13089 fprintf(stderr, "Firmware is built without -DV7_ENABLE__RegExp\n");
Marko Mikulicic 0:c0ecb8bf28eb 13090 abort();
Marko Mikulicic 0:c0ecb8bf28eb 13091 #endif
Marko Mikulicic 0:c0ecb8bf28eb 13092 }
Marko Mikulicic 0:c0ecb8bf28eb 13093 default:
Marko Mikulicic 0:c0ecb8bf28eb 13094 return ((val_t *) vec->p)[idx - BCODE_MAX_INLINE_TYPE_TAG];
Marko Mikulicic 0:c0ecb8bf28eb 13095 }
Marko Mikulicic 0:c0ecb8bf28eb 13096 }
Marko Mikulicic 0:c0ecb8bf28eb 13097
Marko Mikulicic 0:c0ecb8bf28eb 13098 V7_PRIVATE void bcode_op_lit(struct bcode_builder *bbuilder, enum opcode op,
Marko Mikulicic 0:c0ecb8bf28eb 13099 lit_t lit) {
Marko Mikulicic 0:c0ecb8bf28eb 13100 bcode_op(bbuilder, op);
Marko Mikulicic 0:c0ecb8bf28eb 13101
Marko Mikulicic 0:c0ecb8bf28eb 13102 switch (lit.mode) {
Marko Mikulicic 0:c0ecb8bf28eb 13103 case LIT_MODE__TABLE:
Marko Mikulicic 0:c0ecb8bf28eb 13104 bcode_add_varint(bbuilder, lit.v.lit_idx + BCODE_MAX_INLINE_TYPE_TAG);
Marko Mikulicic 0:c0ecb8bf28eb 13105 break;
Marko Mikulicic 0:c0ecb8bf28eb 13106
Marko Mikulicic 0:c0ecb8bf28eb 13107 case LIT_MODE__INLINED:
Marko Mikulicic 0:c0ecb8bf28eb 13108 if (v7_is_string(lit.v.inline_val)) {
Marko Mikulicic 0:c0ecb8bf28eb 13109 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 13110 const char *s = v7_get_string(bbuilder->v7, &lit.v.inline_val, &len);
Marko Mikulicic 0:c0ecb8bf28eb 13111 bcode_add_varint(bbuilder, BCODE_INLINE_STRING_TYPE_TAG);
Marko Mikulicic 0:c0ecb8bf28eb 13112 bcode_add_varint(bbuilder, len);
Marko Mikulicic 0:c0ecb8bf28eb 13113 bcode_ops_append(bbuilder, s, len + 1 /* nul term */);
Marko Mikulicic 0:c0ecb8bf28eb 13114 } else if (v7_is_number(lit.v.inline_val)) {
Marko Mikulicic 0:c0ecb8bf28eb 13115 bcode_add_varint(bbuilder, BCODE_INLINE_NUMBER_TYPE_TAG);
Marko Mikulicic 0:c0ecb8bf28eb 13116 /*
Marko Mikulicic 0:c0ecb8bf28eb 13117 * TODO(dfrank): we can save some memory by storing string
Marko Mikulicic 0:c0ecb8bf28eb 13118 * representation of a number here, instead of wasting 8 bytes for each
Marko Mikulicic 0:c0ecb8bf28eb 13119 * number.
Marko Mikulicic 0:c0ecb8bf28eb 13120 *
Marko Mikulicic 0:c0ecb8bf28eb 13121 * Alternatively, we can add more tags for integers, like
Marko Mikulicic 0:c0ecb8bf28eb 13122 * `BCODE_INLINE_S08_TYPE_TAG`, `BCODE_INLINE_S16_TYPE_TAG`, etc, since
Marko Mikulicic 0:c0ecb8bf28eb 13123 * integers are the most common numbers for sure.
Marko Mikulicic 0:c0ecb8bf28eb 13124 */
Marko Mikulicic 0:c0ecb8bf28eb 13125 bcode_ops_append(bbuilder, &lit.v.inline_val, sizeof(lit.v.inline_val));
Marko Mikulicic 0:c0ecb8bf28eb 13126 } else if (is_js_function(lit.v.inline_val)) {
Marko Mikulicic 0:c0ecb8bf28eb 13127 /*
Marko Mikulicic 0:c0ecb8bf28eb 13128 * TODO(dfrank): implement `bcode_serialize_*` more generically, so
Marko Mikulicic 0:c0ecb8bf28eb 13129 * that they can write to buffer instead of a `FILE`. Then, remove this
Marko Mikulicic 0:c0ecb8bf28eb 13130 * workaround with `CS_PLATFORM == CS_P_UNIX`, `tmpfile()`, etc.
Marko Mikulicic 0:c0ecb8bf28eb 13131 */
Marko Mikulicic 0:c0ecb8bf28eb 13132 #if CS_PLATFORM == CS_P_UNIX
Marko Mikulicic 0:c0ecb8bf28eb 13133 struct v7_js_function *func;
Marko Mikulicic 0:c0ecb8bf28eb 13134 FILE *fp = tmpfile();
Marko Mikulicic 0:c0ecb8bf28eb 13135 long len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 13136 char *p;
Marko Mikulicic 0:c0ecb8bf28eb 13137
Marko Mikulicic 0:c0ecb8bf28eb 13138 func = get_js_function_struct(lit.v.inline_val);
Marko Mikulicic 0:c0ecb8bf28eb 13139
Marko Mikulicic 0:c0ecb8bf28eb 13140 /* we inline functions if only we're precompiling */
Marko Mikulicic 0:c0ecb8bf28eb 13141 assert(bbuilder->v7->is_precompiling);
Marko Mikulicic 0:c0ecb8bf28eb 13142
Marko Mikulicic 0:c0ecb8bf28eb 13143 bcode_add_varint(bbuilder, BCODE_INLINE_FUNC_TYPE_TAG);
Marko Mikulicic 0:c0ecb8bf28eb 13144 bcode_serialize_func(bbuilder->v7, func->bcode, fp);
Marko Mikulicic 0:c0ecb8bf28eb 13145
Marko Mikulicic 0:c0ecb8bf28eb 13146 fflush(fp);
Marko Mikulicic 0:c0ecb8bf28eb 13147
Marko Mikulicic 0:c0ecb8bf28eb 13148 len = ftell(fp);
Marko Mikulicic 0:c0ecb8bf28eb 13149
Marko Mikulicic 0:c0ecb8bf28eb 13150 p = (char *) mmap(NULL, len, PROT_WRITE, MAP_PRIVATE, fileno(fp), 0);
Marko Mikulicic 0:c0ecb8bf28eb 13151
Marko Mikulicic 0:c0ecb8bf28eb 13152 bcode_ops_append(bbuilder, p, len);
Marko Mikulicic 0:c0ecb8bf28eb 13153
Marko Mikulicic 0:c0ecb8bf28eb 13154 fclose(fp);
Marko Mikulicic 0:c0ecb8bf28eb 13155 #endif
Marko Mikulicic 0:c0ecb8bf28eb 13156 } else if (v7_is_regexp(bbuilder->v7, lit.v.inline_val)) {
Marko Mikulicic 0:c0ecb8bf28eb 13157 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 13158 struct v7_regexp *rp =
Marko Mikulicic 0:c0ecb8bf28eb 13159 v7_get_regexp_struct(bbuilder->v7, lit.v.inline_val);
Marko Mikulicic 0:c0ecb8bf28eb 13160 bcode_add_varint(bbuilder, BCODE_INLINE_REGEXP_TYPE_TAG);
Marko Mikulicic 0:c0ecb8bf28eb 13161
Marko Mikulicic 0:c0ecb8bf28eb 13162 /* append regexp source */
Marko Mikulicic 0:c0ecb8bf28eb 13163 {
Marko Mikulicic 0:c0ecb8bf28eb 13164 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 13165 const char *buf =
Marko Mikulicic 0:c0ecb8bf28eb 13166 v7_get_string(bbuilder->v7, &rp->regexp_string, &len);
Marko Mikulicic 0:c0ecb8bf28eb 13167 bcode_add_varint(bbuilder, len);
Marko Mikulicic 0:c0ecb8bf28eb 13168 bcode_ops_append(bbuilder, buf, len + 1 /* nul term */);
Marko Mikulicic 0:c0ecb8bf28eb 13169 }
Marko Mikulicic 0:c0ecb8bf28eb 13170
Marko Mikulicic 0:c0ecb8bf28eb 13171 /* append regexp flags */
Marko Mikulicic 0:c0ecb8bf28eb 13172 {
Marko Mikulicic 0:c0ecb8bf28eb 13173 char buf[_V7_REGEXP_MAX_FLAGS_LEN + 1 /* nul term */];
Marko Mikulicic 0:c0ecb8bf28eb 13174 size_t len = get_regexp_flags_str(bbuilder->v7, rp, buf);
Marko Mikulicic 0:c0ecb8bf28eb 13175 bcode_add_varint(bbuilder, len);
Marko Mikulicic 0:c0ecb8bf28eb 13176 bcode_ops_append(bbuilder, buf, len + 1 /* nul term */);
Marko Mikulicic 0:c0ecb8bf28eb 13177 }
Marko Mikulicic 0:c0ecb8bf28eb 13178 #else
Marko Mikulicic 0:c0ecb8bf28eb 13179 fprintf(stderr, "Firmware is built without -DV7_ENABLE__RegExp\n");
Marko Mikulicic 0:c0ecb8bf28eb 13180 abort();
Marko Mikulicic 0:c0ecb8bf28eb 13181 #endif
Marko Mikulicic 0:c0ecb8bf28eb 13182 } else {
Marko Mikulicic 0:c0ecb8bf28eb 13183 /* invalid type of inlined value */
Marko Mikulicic 0:c0ecb8bf28eb 13184 abort();
Marko Mikulicic 0:c0ecb8bf28eb 13185 }
Marko Mikulicic 0:c0ecb8bf28eb 13186 break;
Marko Mikulicic 0:c0ecb8bf28eb 13187
Marko Mikulicic 0:c0ecb8bf28eb 13188 default:
Marko Mikulicic 0:c0ecb8bf28eb 13189 /* invalid literal mode */
Marko Mikulicic 0:c0ecb8bf28eb 13190 abort();
Marko Mikulicic 0:c0ecb8bf28eb 13191 break;
Marko Mikulicic 0:c0ecb8bf28eb 13192 }
Marko Mikulicic 0:c0ecb8bf28eb 13193 }
Marko Mikulicic 0:c0ecb8bf28eb 13194
Marko Mikulicic 0:c0ecb8bf28eb 13195 V7_PRIVATE void bcode_push_lit(struct bcode_builder *bbuilder, lit_t lit) {
Marko Mikulicic 0:c0ecb8bf28eb 13196 bcode_op_lit(bbuilder, OP_PUSH_LIT, lit);
Marko Mikulicic 0:c0ecb8bf28eb 13197 }
Marko Mikulicic 0:c0ecb8bf28eb 13198
Marko Mikulicic 0:c0ecb8bf28eb 13199 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 13200 /*V7_PRIVATE*/ enum v7_err
Marko Mikulicic 0:c0ecb8bf28eb 13201 bcode_add_name(struct bcode_builder *bbuilder, const char *p, size_t len,
Marko Mikulicic 0:c0ecb8bf28eb 13202 size_t *idx) {
Marko Mikulicic 0:c0ecb8bf28eb 13203 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 13204 int llen;
Marko Mikulicic 0:c0ecb8bf28eb 13205 size_t ops_index;
Marko Mikulicic 0:c0ecb8bf28eb 13206
Marko Mikulicic 0:c0ecb8bf28eb 13207 /*
Marko Mikulicic 0:c0ecb8bf28eb 13208 * if name length is not provided, assume it's null-terminated and calculate
Marko Mikulicic 0:c0ecb8bf28eb 13209 * it
Marko Mikulicic 0:c0ecb8bf28eb 13210 */
Marko Mikulicic 0:c0ecb8bf28eb 13211 if (len == ~((size_t) 0)) {
Marko Mikulicic 0:c0ecb8bf28eb 13212 len = strlen(p);
Marko Mikulicic 0:c0ecb8bf28eb 13213 }
Marko Mikulicic 0:c0ecb8bf28eb 13214
Marko Mikulicic 0:c0ecb8bf28eb 13215 /* index at which to put name. If not provided, we'll append at the end */
Marko Mikulicic 0:c0ecb8bf28eb 13216 if (idx != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 13217 ops_index = *idx;
Marko Mikulicic 0:c0ecb8bf28eb 13218 } else {
Marko Mikulicic 0:c0ecb8bf28eb 13219 ops_index = bbuilder->ops.len;
Marko Mikulicic 0:c0ecb8bf28eb 13220 }
Marko Mikulicic 0:c0ecb8bf28eb 13221
Marko Mikulicic 0:c0ecb8bf28eb 13222 /* calculate how much varint len will take */
Marko Mikulicic 0:c0ecb8bf28eb 13223 llen = calc_llen(len);
Marko Mikulicic 0:c0ecb8bf28eb 13224
Marko Mikulicic 0:c0ecb8bf28eb 13225 /* reserve space in `ops` buffer */
Marko Mikulicic 0:c0ecb8bf28eb 13226 mbuf_insert(&bbuilder->ops, ops_index, NULL, llen + len + 1 /*null-term*/);
Marko Mikulicic 0:c0ecb8bf28eb 13227
Marko Mikulicic 0:c0ecb8bf28eb 13228 {
Marko Mikulicic 0:c0ecb8bf28eb 13229 char *ops = bbuilder->ops.buf + ops_index;
Marko Mikulicic 0:c0ecb8bf28eb 13230
Marko Mikulicic 0:c0ecb8bf28eb 13231 /* put varint len */
Marko Mikulicic 0:c0ecb8bf28eb 13232 ops += encode_varint(len, (unsigned char *) ops);
Marko Mikulicic 0:c0ecb8bf28eb 13233
Marko Mikulicic 0:c0ecb8bf28eb 13234 /* put string */
Marko Mikulicic 0:c0ecb8bf28eb 13235 memcpy(ops, p, len);
Marko Mikulicic 0:c0ecb8bf28eb 13236 ops += len;
Marko Mikulicic 0:c0ecb8bf28eb 13237
Marko Mikulicic 0:c0ecb8bf28eb 13238 /* null-terminate */
Marko Mikulicic 0:c0ecb8bf28eb 13239 *ops++ = 0x00;
Marko Mikulicic 0:c0ecb8bf28eb 13240
Marko Mikulicic 0:c0ecb8bf28eb 13241 if (idx != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 13242 *idx = ops - bbuilder->ops.buf;
Marko Mikulicic 0:c0ecb8bf28eb 13243 }
Marko Mikulicic 0:c0ecb8bf28eb 13244 }
Marko Mikulicic 0:c0ecb8bf28eb 13245
Marko Mikulicic 0:c0ecb8bf28eb 13246 /* maintain total number of names */
Marko Mikulicic 0:c0ecb8bf28eb 13247 if (bbuilder->bcode->names_cnt < V7_NAMES_CNT_MAX) {
Marko Mikulicic 0:c0ecb8bf28eb 13248 bbuilder->bcode->names_cnt++;
Marko Mikulicic 0:c0ecb8bf28eb 13249 } else {
Marko Mikulicic 0:c0ecb8bf28eb 13250 rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "Too many local variables");
Marko Mikulicic 0:c0ecb8bf28eb 13251 }
Marko Mikulicic 0:c0ecb8bf28eb 13252
Marko Mikulicic 0:c0ecb8bf28eb 13253 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 13254 }
Marko Mikulicic 0:c0ecb8bf28eb 13255
Marko Mikulicic 0:c0ecb8bf28eb 13256 /*V7_PRIVATE*/ char *bcode_end_names(char *ops, size_t names_cnt) {
Marko Mikulicic 0:c0ecb8bf28eb 13257 while (names_cnt--) {
Marko Mikulicic 0:c0ecb8bf28eb 13258 ops = bcode_next_name(ops, NULL, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 13259 }
Marko Mikulicic 0:c0ecb8bf28eb 13260 return ops;
Marko Mikulicic 0:c0ecb8bf28eb 13261 }
Marko Mikulicic 0:c0ecb8bf28eb 13262
Marko Mikulicic 0:c0ecb8bf28eb 13263 V7_PRIVATE char *bcode_next_name(char *ops, char **pname, size_t *plen) {
Marko Mikulicic 0:c0ecb8bf28eb 13264 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 13265 int llen;
Marko Mikulicic 0:c0ecb8bf28eb 13266
Marko Mikulicic 0:c0ecb8bf28eb 13267 len = decode_varint((unsigned char *) ops, &llen);
Marko Mikulicic 0:c0ecb8bf28eb 13268
Marko Mikulicic 0:c0ecb8bf28eb 13269 ops += llen;
Marko Mikulicic 0:c0ecb8bf28eb 13270
Marko Mikulicic 0:c0ecb8bf28eb 13271 if (pname != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 13272 *pname = ops;
Marko Mikulicic 0:c0ecb8bf28eb 13273 }
Marko Mikulicic 0:c0ecb8bf28eb 13274
Marko Mikulicic 0:c0ecb8bf28eb 13275 if (plen != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 13276 *plen = len;
Marko Mikulicic 0:c0ecb8bf28eb 13277 }
Marko Mikulicic 0:c0ecb8bf28eb 13278
Marko Mikulicic 0:c0ecb8bf28eb 13279 ops += len + 1 /*null-terminator*/;
Marko Mikulicic 0:c0ecb8bf28eb 13280 return ops;
Marko Mikulicic 0:c0ecb8bf28eb 13281 }
Marko Mikulicic 0:c0ecb8bf28eb 13282
Marko Mikulicic 0:c0ecb8bf28eb 13283 V7_PRIVATE char *bcode_next_name_v(struct v7 *v7, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 13284 char *ops, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 13285 char *name;
Marko Mikulicic 0:c0ecb8bf28eb 13286 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 13287
Marko Mikulicic 0:c0ecb8bf28eb 13288 ops = bcode_next_name(ops, &name, &len);
Marko Mikulicic 0:c0ecb8bf28eb 13289
Marko Mikulicic 0:c0ecb8bf28eb 13290 /*
Marko Mikulicic 0:c0ecb8bf28eb 13291 * If `ops` is in RAM, we create owned string, since the string may outlive
Marko Mikulicic 0:c0ecb8bf28eb 13292 * bcode. Otherwise (`ops` is in ROM), we create foreign string.
Marko Mikulicic 0:c0ecb8bf28eb 13293 */
Marko Mikulicic 0:c0ecb8bf28eb 13294 *res = v7_mk_string(v7, name, len, !bcode->ops_in_rom);
Marko Mikulicic 0:c0ecb8bf28eb 13295
Marko Mikulicic 0:c0ecb8bf28eb 13296 return ops;
Marko Mikulicic 0:c0ecb8bf28eb 13297 }
Marko Mikulicic 0:c0ecb8bf28eb 13298
Marko Mikulicic 0:c0ecb8bf28eb 13299 V7_PRIVATE bcode_off_t bcode_pos(struct bcode_builder *bbuilder) {
Marko Mikulicic 0:c0ecb8bf28eb 13300 return bbuilder->ops.len;
Marko Mikulicic 0:c0ecb8bf28eb 13301 }
Marko Mikulicic 0:c0ecb8bf28eb 13302
Marko Mikulicic 0:c0ecb8bf28eb 13303 /*
Marko Mikulicic 0:c0ecb8bf28eb 13304 * Appends a branch target and returns its location.
Marko Mikulicic 0:c0ecb8bf28eb 13305 * This location can be updated with bcode_patch_target.
Marko Mikulicic 0:c0ecb8bf28eb 13306 * To be issued following a JMP_* bytecode
Marko Mikulicic 0:c0ecb8bf28eb 13307 */
Marko Mikulicic 0:c0ecb8bf28eb 13308 V7_PRIVATE bcode_off_t bcode_add_target(struct bcode_builder *bbuilder) {
Marko Mikulicic 0:c0ecb8bf28eb 13309 bcode_off_t pos = bcode_pos(bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 13310 bcode_off_t zero = 0;
Marko Mikulicic 0:c0ecb8bf28eb 13311 bcode_ops_append(bbuilder, &zero, sizeof(bcode_off_t));
Marko Mikulicic 0:c0ecb8bf28eb 13312 return pos;
Marko Mikulicic 0:c0ecb8bf28eb 13313 }
Marko Mikulicic 0:c0ecb8bf28eb 13314
Marko Mikulicic 0:c0ecb8bf28eb 13315 /*
Marko Mikulicic 0:c0ecb8bf28eb 13316 * Appends an op requiring a branch target. See bcode_add_target.
Marko Mikulicic 0:c0ecb8bf28eb 13317 *
Marko Mikulicic 0:c0ecb8bf28eb 13318 * This function is used only internally, but used in a complicated mix of
Marko Mikulicic 0:c0ecb8bf28eb 13319 * configurations, hence the commented V7_PRIVATE
Marko Mikulicic 0:c0ecb8bf28eb 13320 */
Marko Mikulicic 0:c0ecb8bf28eb 13321 /*V7_PRIVATE*/ bcode_off_t bcode_op_target(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 13322 uint8_t op) {
Marko Mikulicic 0:c0ecb8bf28eb 13323 bcode_op(bbuilder, op);
Marko Mikulicic 0:c0ecb8bf28eb 13324 return bcode_add_target(bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 13325 }
Marko Mikulicic 0:c0ecb8bf28eb 13326
Marko Mikulicic 0:c0ecb8bf28eb 13327 /*V7_PRIVATE*/ void bcode_patch_target(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 13328 bcode_off_t label, bcode_off_t target) {
Marko Mikulicic 0:c0ecb8bf28eb 13329 memcpy(bbuilder->ops.buf + label, &target, sizeof(target));
Marko Mikulicic 0:c0ecb8bf28eb 13330 }
Marko Mikulicic 0:c0ecb8bf28eb 13331
Marko Mikulicic 0:c0ecb8bf28eb 13332 /*V7_PRIVATE*/ void bcode_serialize(struct v7 *v7, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 13333 FILE *out) {
Marko Mikulicic 0:c0ecb8bf28eb 13334 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 13335 (void) bcode;
Marko Mikulicic 0:c0ecb8bf28eb 13336
Marko Mikulicic 0:c0ecb8bf28eb 13337 fwrite(BIN_BCODE_SIGNATURE, sizeof(BIN_BCODE_SIGNATURE), 1, out);
Marko Mikulicic 0:c0ecb8bf28eb 13338 bcode_serialize_func(v7, bcode, out);
Marko Mikulicic 0:c0ecb8bf28eb 13339 }
Marko Mikulicic 0:c0ecb8bf28eb 13340
Marko Mikulicic 0:c0ecb8bf28eb 13341 static void bcode_serialize_varint(int n, FILE *out) {
Marko Mikulicic 0:c0ecb8bf28eb 13342 unsigned char buf[8];
Marko Mikulicic 0:c0ecb8bf28eb 13343 int k = calc_llen(n);
Marko Mikulicic 0:c0ecb8bf28eb 13344 encode_varint(n, buf);
Marko Mikulicic 0:c0ecb8bf28eb 13345 fwrite(buf, k, 1, out);
Marko Mikulicic 0:c0ecb8bf28eb 13346 }
Marko Mikulicic 0:c0ecb8bf28eb 13347
Marko Mikulicic 0:c0ecb8bf28eb 13348 static void bcode_serialize_func(struct v7 *v7, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 13349 FILE *out) {
Marko Mikulicic 0:c0ecb8bf28eb 13350 struct v7_vec *vec;
Marko Mikulicic 0:c0ecb8bf28eb 13351 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 13352
Marko Mikulicic 0:c0ecb8bf28eb 13353 /*
Marko Mikulicic 0:c0ecb8bf28eb 13354 * All literals should be inlined into `ops`, so we expect literals table
Marko Mikulicic 0:c0ecb8bf28eb 13355 * to be empty here
Marko Mikulicic 0:c0ecb8bf28eb 13356 */
Marko Mikulicic 0:c0ecb8bf28eb 13357 assert(bcode->lit.len == 0);
Marko Mikulicic 0:c0ecb8bf28eb 13358
Marko Mikulicic 0:c0ecb8bf28eb 13359 /* args_cnt */
Marko Mikulicic 0:c0ecb8bf28eb 13360 bcode_serialize_varint(bcode->args_cnt, out);
Marko Mikulicic 0:c0ecb8bf28eb 13361
Marko Mikulicic 0:c0ecb8bf28eb 13362 /* names_cnt */
Marko Mikulicic 0:c0ecb8bf28eb 13363 bcode_serialize_varint(bcode->names_cnt, out);
Marko Mikulicic 0:c0ecb8bf28eb 13364
Marko Mikulicic 0:c0ecb8bf28eb 13365 /* func_name_present */
Marko Mikulicic 0:c0ecb8bf28eb 13366 bcode_serialize_varint(bcode->func_name_present, out);
Marko Mikulicic 0:c0ecb8bf28eb 13367
Marko Mikulicic 0:c0ecb8bf28eb 13368 /*
Marko Mikulicic 0:c0ecb8bf28eb 13369 * bcode:
Marko Mikulicic 0:c0ecb8bf28eb 13370 * <varint> // opcodes length
Marko Mikulicic 0:c0ecb8bf28eb 13371 * <opcode>*
Marko Mikulicic 0:c0ecb8bf28eb 13372 */
Marko Mikulicic 0:c0ecb8bf28eb 13373 vec = &bcode->ops;
Marko Mikulicic 0:c0ecb8bf28eb 13374 bcode_serialize_varint(vec->len, out);
Marko Mikulicic 0:c0ecb8bf28eb 13375 fwrite(vec->p, vec->len, 1, out);
Marko Mikulicic 0:c0ecb8bf28eb 13376 }
Marko Mikulicic 0:c0ecb8bf28eb 13377
Marko Mikulicic 0:c0ecb8bf28eb 13378 static size_t bcode_deserialize_varint(const char **data) {
Marko Mikulicic 0:c0ecb8bf28eb 13379 size_t ret = 0;
Marko Mikulicic 0:c0ecb8bf28eb 13380 int len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 13381 ret = decode_varint((const unsigned char *) (*data), &len);
Marko Mikulicic 0:c0ecb8bf28eb 13382 *data += len;
Marko Mikulicic 0:c0ecb8bf28eb 13383 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 13384 }
Marko Mikulicic 0:c0ecb8bf28eb 13385
Marko Mikulicic 0:c0ecb8bf28eb 13386 static const char *bcode_deserialize_func(struct v7 *v7, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 13387 const char *data) {
Marko Mikulicic 0:c0ecb8bf28eb 13388 size_t size;
Marko Mikulicic 0:c0ecb8bf28eb 13389 struct bcode_builder bbuilder;
Marko Mikulicic 0:c0ecb8bf28eb 13390
Marko Mikulicic 0:c0ecb8bf28eb 13391 bcode_builder_init(v7, &bbuilder, bcode);
Marko Mikulicic 0:c0ecb8bf28eb 13392
Marko Mikulicic 0:c0ecb8bf28eb 13393 /*
Marko Mikulicic 0:c0ecb8bf28eb 13394 * before deserializing, set the corresponding flag, so that metrics will be
Marko Mikulicic 0:c0ecb8bf28eb 13395 * updated accordingly
Marko Mikulicic 0:c0ecb8bf28eb 13396 */
Marko Mikulicic 0:c0ecb8bf28eb 13397 bcode->deserialized = 1;
Marko Mikulicic 0:c0ecb8bf28eb 13398
Marko Mikulicic 0:c0ecb8bf28eb 13399 /*
Marko Mikulicic 0:c0ecb8bf28eb 13400 * In serialized functions, all literals are inlined into `ops`, so we don't
Marko Mikulicic 0:c0ecb8bf28eb 13401 * deserialize them here in any way
Marko Mikulicic 0:c0ecb8bf28eb 13402 */
Marko Mikulicic 0:c0ecb8bf28eb 13403
Marko Mikulicic 0:c0ecb8bf28eb 13404 /* get number of args */
Marko Mikulicic 0:c0ecb8bf28eb 13405 bcode->args_cnt = bcode_deserialize_varint(&data);
Marko Mikulicic 0:c0ecb8bf28eb 13406
Marko Mikulicic 0:c0ecb8bf28eb 13407 /* get number of names */
Marko Mikulicic 0:c0ecb8bf28eb 13408 bcode->names_cnt = bcode_deserialize_varint(&data);
Marko Mikulicic 0:c0ecb8bf28eb 13409
Marko Mikulicic 0:c0ecb8bf28eb 13410 /* get whether the function name is present in `names` */
Marko Mikulicic 0:c0ecb8bf28eb 13411 bcode->func_name_present = bcode_deserialize_varint(&data);
Marko Mikulicic 0:c0ecb8bf28eb 13412
Marko Mikulicic 0:c0ecb8bf28eb 13413 /* get opcode size */
Marko Mikulicic 0:c0ecb8bf28eb 13414 size = bcode_deserialize_varint(&data);
Marko Mikulicic 0:c0ecb8bf28eb 13415
Marko Mikulicic 0:c0ecb8bf28eb 13416 bbuilder.ops.buf = (char *) data;
Marko Mikulicic 0:c0ecb8bf28eb 13417 bbuilder.ops.size = size;
Marko Mikulicic 0:c0ecb8bf28eb 13418 bbuilder.ops.len = size;
Marko Mikulicic 0:c0ecb8bf28eb 13419
Marko Mikulicic 0:c0ecb8bf28eb 13420 bcode->ops_in_rom = 1;
Marko Mikulicic 0:c0ecb8bf28eb 13421
Marko Mikulicic 0:c0ecb8bf28eb 13422 data += size;
Marko Mikulicic 0:c0ecb8bf28eb 13423
Marko Mikulicic 0:c0ecb8bf28eb 13424 bcode_builder_finalize(&bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 13425 return data;
Marko Mikulicic 0:c0ecb8bf28eb 13426 }
Marko Mikulicic 0:c0ecb8bf28eb 13427
Marko Mikulicic 0:c0ecb8bf28eb 13428 V7_PRIVATE void bcode_deserialize(struct v7 *v7, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 13429 const char *data) {
Marko Mikulicic 0:c0ecb8bf28eb 13430 data = bcode_deserialize_func(v7, bcode, data);
Marko Mikulicic 0:c0ecb8bf28eb 13431 }
Marko Mikulicic 0:c0ecb8bf28eb 13432 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 13433 #line 1 "v7/src/eval.c"
Marko Mikulicic 0:c0ecb8bf28eb 13434 #endif
Marko Mikulicic 0:c0ecb8bf28eb 13435 /*
Marko Mikulicic 0:c0ecb8bf28eb 13436 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 13437 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 13438 */
Marko Mikulicic 0:c0ecb8bf28eb 13439
Marko Mikulicic 0:c0ecb8bf28eb 13440 /* Amalgamated: #include "common/str_util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13441 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13442 /* Amalgamated: #include "v7/src/eval.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13443 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13444 /* Amalgamated: #include "v7/src/array.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13445 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13446 /* Amalgamated: #include "v7/src/gc.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13447 /* Amalgamated: #include "v7/src/compiler.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13448 /* Amalgamated: #include "v7/src/cyg_profile.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13449 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13450 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13451 /* Amalgamated: #include "v7/src/util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13452 /* Amalgamated: #include "v7/src/shdata.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13453 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13454 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13455 /* Amalgamated: #include "v7/src/varint.h" */
Marko Mikulicic 0:c0ecb8bf28eb 13456
Marko Mikulicic 0:c0ecb8bf28eb 13457 /*
Marko Mikulicic 0:c0ecb8bf28eb 13458 * Bcode offsets in "try stack" are stored in JS numbers, i.e. in `double`s.
Marko Mikulicic 0:c0ecb8bf28eb 13459 * Apart from the offset itself, we also need some additional data:
Marko Mikulicic 0:c0ecb8bf28eb 13460 *
Marko Mikulicic 0:c0ecb8bf28eb 13461 * - type of the block that offset represents (`catch`, `finally`, `switch`,
Marko Mikulicic 0:c0ecb8bf28eb 13462 * or some loop)
Marko Mikulicic 0:c0ecb8bf28eb 13463 * - size of the stack when the block is created (needed when throwing, since
Marko Mikulicic 0:c0ecb8bf28eb 13464 * if exception is thrown from the middle of the expression, the stack may
Marko Mikulicic 0:c0ecb8bf28eb 13465 * have any arbitrary length)
Marko Mikulicic 0:c0ecb8bf28eb 13466 *
Marko Mikulicic 0:c0ecb8bf28eb 13467 * We bake all this data into integer part of the double (53 bits) :
Marko Mikulicic 0:c0ecb8bf28eb 13468 *
Marko Mikulicic 0:c0ecb8bf28eb 13469 * - 32 bits: bcode offset
Marko Mikulicic 0:c0ecb8bf28eb 13470 * - 3 bits: "tag": the type of the block
Marko Mikulicic 0:c0ecb8bf28eb 13471 * - 16 bits: stack size
Marko Mikulicic 0:c0ecb8bf28eb 13472 */
Marko Mikulicic 0:c0ecb8bf28eb 13473
Marko Mikulicic 0:c0ecb8bf28eb 13474 /*
Marko Mikulicic 0:c0ecb8bf28eb 13475 * Widths of data parts
Marko Mikulicic 0:c0ecb8bf28eb 13476 */
Marko Mikulicic 0:c0ecb8bf28eb 13477 #define LBLOCK_OFFSET_WIDTH 32
Marko Mikulicic 0:c0ecb8bf28eb 13478 #define LBLOCK_TAG_WIDTH 3
Marko Mikulicic 0:c0ecb8bf28eb 13479 #define LBLOCK_STACK_SIZE_WIDTH 16
Marko Mikulicic 0:c0ecb8bf28eb 13480
Marko Mikulicic 0:c0ecb8bf28eb 13481 /*
Marko Mikulicic 0:c0ecb8bf28eb 13482 * Shifts of data parts
Marko Mikulicic 0:c0ecb8bf28eb 13483 */
Marko Mikulicic 0:c0ecb8bf28eb 13484 #define LBLOCK_OFFSET_SHIFT (0)
Marko Mikulicic 0:c0ecb8bf28eb 13485 #define LBLOCK_TAG_SHIFT (LBLOCK_OFFSET_SHIFT + LBLOCK_OFFSET_WIDTH)
Marko Mikulicic 0:c0ecb8bf28eb 13486 #define LBLOCK_STACK_SIZE_SHIFT (LBLOCK_TAG_SHIFT + LBLOCK_TAG_WIDTH)
Marko Mikulicic 0:c0ecb8bf28eb 13487 #define LBLOCK_TOTAL_WIDTH (LBLOCK_STACK_SIZE_SHIFT + LBLOCK_STACK_SIZE_WIDTH)
Marko Mikulicic 0:c0ecb8bf28eb 13488
Marko Mikulicic 0:c0ecb8bf28eb 13489 /*
Marko Mikulicic 0:c0ecb8bf28eb 13490 * Masks of data parts
Marko Mikulicic 0:c0ecb8bf28eb 13491 */
Marko Mikulicic 0:c0ecb8bf28eb 13492 #define LBLOCK_OFFSET_MASK \
Marko Mikulicic 0:c0ecb8bf28eb 13493 ((int64_t)(((int64_t) 1 << LBLOCK_OFFSET_WIDTH) - 1) << LBLOCK_OFFSET_SHIFT)
Marko Mikulicic 0:c0ecb8bf28eb 13494 #define LBLOCK_TAG_MASK \
Marko Mikulicic 0:c0ecb8bf28eb 13495 ((int64_t)(((int64_t) 1 << LBLOCK_TAG_WIDTH) - 1) << LBLOCK_TAG_SHIFT)
Marko Mikulicic 0:c0ecb8bf28eb 13496 #define LBLOCK_STACK_SIZE_MASK \
Marko Mikulicic 0:c0ecb8bf28eb 13497 ((int64_t)(((int64_t) 1 << LBLOCK_STACK_SIZE_WIDTH) - 1) \
Marko Mikulicic 0:c0ecb8bf28eb 13498 << LBLOCK_STACK_SIZE_SHIFT)
Marko Mikulicic 0:c0ecb8bf28eb 13499
Marko Mikulicic 0:c0ecb8bf28eb 13500 /*
Marko Mikulicic 0:c0ecb8bf28eb 13501 * Self-check: make sure all the data can fit into double's mantissa
Marko Mikulicic 0:c0ecb8bf28eb 13502 */
Marko Mikulicic 0:c0ecb8bf28eb 13503 #if (LBLOCK_TOTAL_WIDTH > 53)
Marko Mikulicic 0:c0ecb8bf28eb 13504 #error lblock width is too large, it can't fit into double's mantissa
Marko Mikulicic 0:c0ecb8bf28eb 13505 #endif
Marko Mikulicic 0:c0ecb8bf28eb 13506
Marko Mikulicic 0:c0ecb8bf28eb 13507 /*
Marko Mikulicic 0:c0ecb8bf28eb 13508 * Tags that are used for bcode offsets in "try stack"
Marko Mikulicic 0:c0ecb8bf28eb 13509 */
Marko Mikulicic 0:c0ecb8bf28eb 13510 #define LBLOCK_TAG_CATCH ((int64_t) 0x01 << LBLOCK_TAG_SHIFT)
Marko Mikulicic 0:c0ecb8bf28eb 13511 #define LBLOCK_TAG_FINALLY ((int64_t) 0x02 << LBLOCK_TAG_SHIFT)
Marko Mikulicic 0:c0ecb8bf28eb 13512 #define LBLOCK_TAG_LOOP ((int64_t) 0x03 << LBLOCK_TAG_SHIFT)
Marko Mikulicic 0:c0ecb8bf28eb 13513 #define LBLOCK_TAG_SWITCH ((int64_t) 0x04 << LBLOCK_TAG_SHIFT)
Marko Mikulicic 0:c0ecb8bf28eb 13514
Marko Mikulicic 0:c0ecb8bf28eb 13515 /*
Marko Mikulicic 0:c0ecb8bf28eb 13516 * Yields 32-bit bcode offset value
Marko Mikulicic 0:c0ecb8bf28eb 13517 */
Marko Mikulicic 0:c0ecb8bf28eb 13518 #define LBLOCK_OFFSET(v) \
Marko Mikulicic 0:c0ecb8bf28eb 13519 ((bcode_off_t)(((v) &LBLOCK_OFFSET_MASK) >> LBLOCK_OFFSET_SHIFT))
Marko Mikulicic 0:c0ecb8bf28eb 13520
Marko Mikulicic 0:c0ecb8bf28eb 13521 /*
Marko Mikulicic 0:c0ecb8bf28eb 13522 * Yields tag value (unshifted, to be compared with macros like
Marko Mikulicic 0:c0ecb8bf28eb 13523 * `LBLOCK_TAG_CATCH`, etc)
Marko Mikulicic 0:c0ecb8bf28eb 13524 */
Marko Mikulicic 0:c0ecb8bf28eb 13525 #define LBLOCK_TAG(v) ((v) &LBLOCK_TAG_MASK)
Marko Mikulicic 0:c0ecb8bf28eb 13526
Marko Mikulicic 0:c0ecb8bf28eb 13527 /*
Marko Mikulicic 0:c0ecb8bf28eb 13528 * Yields stack size
Marko Mikulicic 0:c0ecb8bf28eb 13529 */
Marko Mikulicic 0:c0ecb8bf28eb 13530 #define LBLOCK_STACK_SIZE(v) \
Marko Mikulicic 0:c0ecb8bf28eb 13531 (((v) &LBLOCK_STACK_SIZE_MASK) >> LBLOCK_STACK_SIZE_SHIFT)
Marko Mikulicic 0:c0ecb8bf28eb 13532
Marko Mikulicic 0:c0ecb8bf28eb 13533 /*
Marko Mikulicic 0:c0ecb8bf28eb 13534 * Yields `int64_t` value to be stored as a JavaScript number
Marko Mikulicic 0:c0ecb8bf28eb 13535 */
Marko Mikulicic 0:c0ecb8bf28eb 13536 #define LBLOCK_ITEM_CREATE(offset, tag, stack_size) \
Marko Mikulicic 0:c0ecb8bf28eb 13537 ((int64_t)(offset) | (tag) | \
Marko Mikulicic 0:c0ecb8bf28eb 13538 (((int64_t)(stack_size)) << LBLOCK_STACK_SIZE_SHIFT))
Marko Mikulicic 0:c0ecb8bf28eb 13539
Marko Mikulicic 0:c0ecb8bf28eb 13540 /*
Marko Mikulicic 0:c0ecb8bf28eb 13541 * make sure `bcode_off_t` is just 32-bit, so that it can fit in double
Marko Mikulicic 0:c0ecb8bf28eb 13542 * with 3-bit tag
Marko Mikulicic 0:c0ecb8bf28eb 13543 */
Marko Mikulicic 0:c0ecb8bf28eb 13544 V7_STATIC_ASSERT((sizeof(bcode_off_t) * 8) == LBLOCK_OFFSET_WIDTH,
Marko Mikulicic 0:c0ecb8bf28eb 13545 wrong_size_of_bcode_off_t);
Marko Mikulicic 0:c0ecb8bf28eb 13546
Marko Mikulicic 0:c0ecb8bf28eb 13547 #define PUSH(v) stack_push(&v7->stack, v)
Marko Mikulicic 0:c0ecb8bf28eb 13548 #define POP() stack_pop(&v7->stack)
Marko Mikulicic 0:c0ecb8bf28eb 13549 #define TOS() stack_tos(&v7->stack)
Marko Mikulicic 0:c0ecb8bf28eb 13550 #define SP() stack_sp(&v7->stack)
Marko Mikulicic 0:c0ecb8bf28eb 13551
Marko Mikulicic 0:c0ecb8bf28eb 13552 /*
Marko Mikulicic 0:c0ecb8bf28eb 13553 * Local-to-function block types that we might want to consider when unwinding
Marko Mikulicic 0:c0ecb8bf28eb 13554 * stack for whatever reason. see `unwind_local_blocks_stack()`.
Marko Mikulicic 0:c0ecb8bf28eb 13555 */
Marko Mikulicic 0:c0ecb8bf28eb 13556 enum local_block {
Marko Mikulicic 0:c0ecb8bf28eb 13557 LOCAL_BLOCK_NONE = (0),
Marko Mikulicic 0:c0ecb8bf28eb 13558 LOCAL_BLOCK_CATCH = (1 << 0),
Marko Mikulicic 0:c0ecb8bf28eb 13559 LOCAL_BLOCK_FINALLY = (1 << 1),
Marko Mikulicic 0:c0ecb8bf28eb 13560 LOCAL_BLOCK_LOOP = (1 << 2),
Marko Mikulicic 0:c0ecb8bf28eb 13561 LOCAL_BLOCK_SWITCH = (1 << 3),
Marko Mikulicic 0:c0ecb8bf28eb 13562 };
Marko Mikulicic 0:c0ecb8bf28eb 13563
Marko Mikulicic 0:c0ecb8bf28eb 13564 /*
Marko Mikulicic 0:c0ecb8bf28eb 13565 * Like `V7_TRY()`, but to be used inside `eval_bcode()` only: you should
Marko Mikulicic 0:c0ecb8bf28eb 13566 * wrap all calls to cfunctions into `BTRY()` instead of `V7_TRY()`.
Marko Mikulicic 0:c0ecb8bf28eb 13567 *
Marko Mikulicic 0:c0ecb8bf28eb 13568 * If the provided function returns something other than `V7_OK`, this macro
Marko Mikulicic 0:c0ecb8bf28eb 13569 * calls `bcode_perform_throw`, which performs bcode stack unwinding.
Marko Mikulicic 0:c0ecb8bf28eb 13570 */
Marko Mikulicic 0:c0ecb8bf28eb 13571 #define BTRY(call) \
Marko Mikulicic 0:c0ecb8bf28eb 13572 do { \
Marko Mikulicic 0:c0ecb8bf28eb 13573 enum v7_err _e = call; \
Marko Mikulicic 0:c0ecb8bf28eb 13574 (void) _you_should_use_BTRY_in_eval_bcode_only; \
Marko Mikulicic 0:c0ecb8bf28eb 13575 if (_e != V7_OK) { \
Marko Mikulicic 0:c0ecb8bf28eb 13576 V7_TRY(bcode_perform_throw(v7, &r, 0 /*don't take value from stack*/)); \
Marko Mikulicic 0:c0ecb8bf28eb 13577 goto op_done; \
Marko Mikulicic 0:c0ecb8bf28eb 13578 } \
Marko Mikulicic 0:c0ecb8bf28eb 13579 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 13580
Marko Mikulicic 0:c0ecb8bf28eb 13581 V7_PRIVATE void stack_push(struct mbuf *s, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 13582 mbuf_append(s, &v, sizeof(v));
Marko Mikulicic 0:c0ecb8bf28eb 13583 }
Marko Mikulicic 0:c0ecb8bf28eb 13584
Marko Mikulicic 0:c0ecb8bf28eb 13585 V7_PRIVATE val_t stack_pop(struct mbuf *s) {
Marko Mikulicic 0:c0ecb8bf28eb 13586 assert(s->len >= sizeof(val_t));
Marko Mikulicic 0:c0ecb8bf28eb 13587 s->len -= sizeof(val_t);
Marko Mikulicic 0:c0ecb8bf28eb 13588 return *(val_t *) (s->buf + s->len);
Marko Mikulicic 0:c0ecb8bf28eb 13589 }
Marko Mikulicic 0:c0ecb8bf28eb 13590
Marko Mikulicic 0:c0ecb8bf28eb 13591 V7_PRIVATE val_t stack_tos(struct mbuf *s) {
Marko Mikulicic 0:c0ecb8bf28eb 13592 assert(s->len >= sizeof(val_t));
Marko Mikulicic 0:c0ecb8bf28eb 13593 return *(val_t *) (s->buf + s->len - sizeof(val_t));
Marko Mikulicic 0:c0ecb8bf28eb 13594 }
Marko Mikulicic 0:c0ecb8bf28eb 13595
Marko Mikulicic 0:c0ecb8bf28eb 13596 #ifdef V7_BCODE_TRACE_STACK
Marko Mikulicic 0:c0ecb8bf28eb 13597 V7_PRIVATE val_t stack_at(struct mbuf *s, size_t idx) {
Marko Mikulicic 0:c0ecb8bf28eb 13598 assert(s->len >= sizeof(val_t) * idx);
Marko Mikulicic 0:c0ecb8bf28eb 13599 return *(val_t *) (s->buf + s->len - sizeof(val_t) - idx * sizeof(val_t));
Marko Mikulicic 0:c0ecb8bf28eb 13600 }
Marko Mikulicic 0:c0ecb8bf28eb 13601 #endif
Marko Mikulicic 0:c0ecb8bf28eb 13602
Marko Mikulicic 0:c0ecb8bf28eb 13603 V7_PRIVATE int stack_sp(struct mbuf *s) {
Marko Mikulicic 0:c0ecb8bf28eb 13604 return s->len / sizeof(val_t);
Marko Mikulicic 0:c0ecb8bf28eb 13605 }
Marko Mikulicic 0:c0ecb8bf28eb 13606
Marko Mikulicic 0:c0ecb8bf28eb 13607 /*
Marko Mikulicic 0:c0ecb8bf28eb 13608 * Delete a property with name `name`, `len` from an object `obj`. If the
Marko Mikulicic 0:c0ecb8bf28eb 13609 * object does not contain own property with the given `name`, moves to `obj`'s
Marko Mikulicic 0:c0ecb8bf28eb 13610 * prototype, and so on.
Marko Mikulicic 0:c0ecb8bf28eb 13611 *
Marko Mikulicic 0:c0ecb8bf28eb 13612 * If the property is eventually found, it is deleted, and `0` is returned.
Marko Mikulicic 0:c0ecb8bf28eb 13613 * Otherwise, `-1` is returned.
Marko Mikulicic 0:c0ecb8bf28eb 13614 *
Marko Mikulicic 0:c0ecb8bf28eb 13615 * If `len` is -1/MAXUINT/~0, then `name` must be 0-terminated.
Marko Mikulicic 0:c0ecb8bf28eb 13616 *
Marko Mikulicic 0:c0ecb8bf28eb 13617 * See `v7_del()` as well.
Marko Mikulicic 0:c0ecb8bf28eb 13618 */
Marko Mikulicic 0:c0ecb8bf28eb 13619 static int del_property_deep(struct v7 *v7, val_t obj, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 13620 size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 13621 if (!v7_is_object(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 13622 return -1;
Marko Mikulicic 0:c0ecb8bf28eb 13623 }
Marko Mikulicic 0:c0ecb8bf28eb 13624 for (; obj != V7_NULL; obj = v7_get_proto(v7, obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 13625 int del_res;
Marko Mikulicic 0:c0ecb8bf28eb 13626 if ((del_res = v7_del(v7, obj, name, len)) != -1) {
Marko Mikulicic 0:c0ecb8bf28eb 13627 return del_res;
Marko Mikulicic 0:c0ecb8bf28eb 13628 }
Marko Mikulicic 0:c0ecb8bf28eb 13629 }
Marko Mikulicic 0:c0ecb8bf28eb 13630 return -1;
Marko Mikulicic 0:c0ecb8bf28eb 13631 }
Marko Mikulicic 0:c0ecb8bf28eb 13632
Marko Mikulicic 0:c0ecb8bf28eb 13633 /* Visual studio 2012+ has signbit() */
Marko Mikulicic 0:c0ecb8bf28eb 13634 #if defined(_MSC_VER) && _MSC_VER < 1700
Marko Mikulicic 0:c0ecb8bf28eb 13635 static int signbit(double x) {
Marko Mikulicic 0:c0ecb8bf28eb 13636 double s = _copysign(1, x);
Marko Mikulicic 0:c0ecb8bf28eb 13637 return s < 0;
Marko Mikulicic 0:c0ecb8bf28eb 13638 }
Marko Mikulicic 0:c0ecb8bf28eb 13639 #endif
Marko Mikulicic 0:c0ecb8bf28eb 13640
Marko Mikulicic 0:c0ecb8bf28eb 13641 static double b_int_bin_op(enum opcode op, double a, double b) {
Marko Mikulicic 0:c0ecb8bf28eb 13642 int32_t ia = isnan(a) || isinf(a) ? 0 : (int32_t)(int64_t) a;
Marko Mikulicic 0:c0ecb8bf28eb 13643 int32_t ib = isnan(b) || isinf(b) ? 0 : (int32_t)(int64_t) b;
Marko Mikulicic 0:c0ecb8bf28eb 13644
Marko Mikulicic 0:c0ecb8bf28eb 13645 switch (op) {
Marko Mikulicic 0:c0ecb8bf28eb 13646 case OP_LSHIFT:
Marko Mikulicic 0:c0ecb8bf28eb 13647 return (int32_t)((uint32_t) ia << ((uint32_t) ib & 31));
Marko Mikulicic 0:c0ecb8bf28eb 13648 case OP_RSHIFT:
Marko Mikulicic 0:c0ecb8bf28eb 13649 return ia >> ((uint32_t) ib & 31);
Marko Mikulicic 0:c0ecb8bf28eb 13650 case OP_URSHIFT:
Marko Mikulicic 0:c0ecb8bf28eb 13651 return (uint32_t) ia >> ((uint32_t) ib & 31);
Marko Mikulicic 0:c0ecb8bf28eb 13652 case OP_OR:
Marko Mikulicic 0:c0ecb8bf28eb 13653 return ia | ib;
Marko Mikulicic 0:c0ecb8bf28eb 13654 case OP_XOR:
Marko Mikulicic 0:c0ecb8bf28eb 13655 return ia ^ ib;
Marko Mikulicic 0:c0ecb8bf28eb 13656 case OP_AND:
Marko Mikulicic 0:c0ecb8bf28eb 13657 return ia & ib;
Marko Mikulicic 0:c0ecb8bf28eb 13658 default:
Marko Mikulicic 0:c0ecb8bf28eb 13659 assert(0);
Marko Mikulicic 0:c0ecb8bf28eb 13660 }
Marko Mikulicic 0:c0ecb8bf28eb 13661 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 13662 }
Marko Mikulicic 0:c0ecb8bf28eb 13663
Marko Mikulicic 0:c0ecb8bf28eb 13664 static double b_num_bin_op(enum opcode op, double a, double b) {
Marko Mikulicic 0:c0ecb8bf28eb 13665 /*
Marko Mikulicic 0:c0ecb8bf28eb 13666 * For certain operations, the result is always NaN if either of arguments
Marko Mikulicic 0:c0ecb8bf28eb 13667 * is NaN
Marko Mikulicic 0:c0ecb8bf28eb 13668 */
Marko Mikulicic 0:c0ecb8bf28eb 13669 switch (op) {
Marko Mikulicic 0:c0ecb8bf28eb 13670 case OP_ADD:
Marko Mikulicic 0:c0ecb8bf28eb 13671 case OP_SUB:
Marko Mikulicic 0:c0ecb8bf28eb 13672 case OP_MUL:
Marko Mikulicic 0:c0ecb8bf28eb 13673 case OP_DIV:
Marko Mikulicic 0:c0ecb8bf28eb 13674 case OP_REM:
Marko Mikulicic 0:c0ecb8bf28eb 13675 if (isnan(a) || isnan(b)) {
Marko Mikulicic 0:c0ecb8bf28eb 13676 return NAN;
Marko Mikulicic 0:c0ecb8bf28eb 13677 }
Marko Mikulicic 0:c0ecb8bf28eb 13678 break;
Marko Mikulicic 0:c0ecb8bf28eb 13679 default:
Marko Mikulicic 0:c0ecb8bf28eb 13680 break;
Marko Mikulicic 0:c0ecb8bf28eb 13681 }
Marko Mikulicic 0:c0ecb8bf28eb 13682
Marko Mikulicic 0:c0ecb8bf28eb 13683 switch (op) {
Marko Mikulicic 0:c0ecb8bf28eb 13684 case OP_ADD: /* simple fixed width nodes with no payload */
Marko Mikulicic 0:c0ecb8bf28eb 13685 return a + b;
Marko Mikulicic 0:c0ecb8bf28eb 13686 case OP_SUB:
Marko Mikulicic 0:c0ecb8bf28eb 13687 return a - b;
Marko Mikulicic 0:c0ecb8bf28eb 13688 case OP_REM:
Marko Mikulicic 0:c0ecb8bf28eb 13689 if (b == 0 || isnan(b) || isnan(a) || isinf(b) || isinf(a)) {
Marko Mikulicic 0:c0ecb8bf28eb 13690 return NAN;
Marko Mikulicic 0:c0ecb8bf28eb 13691 }
Marko Mikulicic 0:c0ecb8bf28eb 13692 return (int) a % (int) b;
Marko Mikulicic 0:c0ecb8bf28eb 13693 case OP_MUL:
Marko Mikulicic 0:c0ecb8bf28eb 13694 return a * b;
Marko Mikulicic 0:c0ecb8bf28eb 13695 case OP_DIV:
Marko Mikulicic 0:c0ecb8bf28eb 13696 if (b == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 13697 if (a == 0) return NAN;
Marko Mikulicic 0:c0ecb8bf28eb 13698 return (!signbit(a) == !signbit(b)) ? INFINITY : -INFINITY;
Marko Mikulicic 0:c0ecb8bf28eb 13699 }
Marko Mikulicic 0:c0ecb8bf28eb 13700 return a / b;
Marko Mikulicic 0:c0ecb8bf28eb 13701 case OP_LSHIFT:
Marko Mikulicic 0:c0ecb8bf28eb 13702 case OP_RSHIFT:
Marko Mikulicic 0:c0ecb8bf28eb 13703 case OP_URSHIFT:
Marko Mikulicic 0:c0ecb8bf28eb 13704 case OP_OR:
Marko Mikulicic 0:c0ecb8bf28eb 13705 case OP_XOR:
Marko Mikulicic 0:c0ecb8bf28eb 13706 case OP_AND:
Marko Mikulicic 0:c0ecb8bf28eb 13707 return b_int_bin_op(op, a, b);
Marko Mikulicic 0:c0ecb8bf28eb 13708 default:
Marko Mikulicic 0:c0ecb8bf28eb 13709 assert(0);
Marko Mikulicic 0:c0ecb8bf28eb 13710 }
Marko Mikulicic 0:c0ecb8bf28eb 13711 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 13712 }
Marko Mikulicic 0:c0ecb8bf28eb 13713
Marko Mikulicic 0:c0ecb8bf28eb 13714 static int b_bool_bin_op(enum opcode op, double a, double b) {
Marko Mikulicic 0:c0ecb8bf28eb 13715 #ifdef V7_BROKEN_NAN
Marko Mikulicic 0:c0ecb8bf28eb 13716 if (isnan(a) || isnan(b)) return op == OP_NE || op == OP_NE_NE;
Marko Mikulicic 0:c0ecb8bf28eb 13717 #endif
Marko Mikulicic 0:c0ecb8bf28eb 13718
Marko Mikulicic 0:c0ecb8bf28eb 13719 switch (op) {
Marko Mikulicic 0:c0ecb8bf28eb 13720 case OP_EQ:
Marko Mikulicic 0:c0ecb8bf28eb 13721 case OP_EQ_EQ:
Marko Mikulicic 0:c0ecb8bf28eb 13722 return a == b;
Marko Mikulicic 0:c0ecb8bf28eb 13723 case OP_NE:
Marko Mikulicic 0:c0ecb8bf28eb 13724 case OP_NE_NE:
Marko Mikulicic 0:c0ecb8bf28eb 13725 return a != b;
Marko Mikulicic 0:c0ecb8bf28eb 13726 case OP_LT:
Marko Mikulicic 0:c0ecb8bf28eb 13727 return a < b;
Marko Mikulicic 0:c0ecb8bf28eb 13728 case OP_LE:
Marko Mikulicic 0:c0ecb8bf28eb 13729 return a <= b;
Marko Mikulicic 0:c0ecb8bf28eb 13730 case OP_GT:
Marko Mikulicic 0:c0ecb8bf28eb 13731 return a > b;
Marko Mikulicic 0:c0ecb8bf28eb 13732 case OP_GE:
Marko Mikulicic 0:c0ecb8bf28eb 13733 return a >= b;
Marko Mikulicic 0:c0ecb8bf28eb 13734 default:
Marko Mikulicic 0:c0ecb8bf28eb 13735 assert(0);
Marko Mikulicic 0:c0ecb8bf28eb 13736 }
Marko Mikulicic 0:c0ecb8bf28eb 13737 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 13738 }
Marko Mikulicic 0:c0ecb8bf28eb 13739
Marko Mikulicic 0:c0ecb8bf28eb 13740 static bcode_off_t bcode_get_target(char **ops) {
Marko Mikulicic 0:c0ecb8bf28eb 13741 bcode_off_t target;
Marko Mikulicic 0:c0ecb8bf28eb 13742 (*ops)++;
Marko Mikulicic 0:c0ecb8bf28eb 13743 memcpy(&target, *ops, sizeof(target));
Marko Mikulicic 0:c0ecb8bf28eb 13744 *ops += sizeof(target) - 1;
Marko Mikulicic 0:c0ecb8bf28eb 13745 return target;
Marko Mikulicic 0:c0ecb8bf28eb 13746 }
Marko Mikulicic 0:c0ecb8bf28eb 13747
Marko Mikulicic 0:c0ecb8bf28eb 13748 struct bcode_registers {
Marko Mikulicic 0:c0ecb8bf28eb 13749 /*
Marko Mikulicic 0:c0ecb8bf28eb 13750 * TODO(dfrank): make it contain `struct v7_call_frame_bcode *`
Marko Mikulicic 0:c0ecb8bf28eb 13751 * and use `bcode_ops` in-place, or probably drop the `bcode_registers`
Marko Mikulicic 0:c0ecb8bf28eb 13752 * whatsoever
Marko Mikulicic 0:c0ecb8bf28eb 13753 */
Marko Mikulicic 0:c0ecb8bf28eb 13754 struct bcode *bcode;
Marko Mikulicic 0:c0ecb8bf28eb 13755 char *ops;
Marko Mikulicic 0:c0ecb8bf28eb 13756 char *end;
Marko Mikulicic 0:c0ecb8bf28eb 13757 unsigned int need_inc_ops : 1;
Marko Mikulicic 0:c0ecb8bf28eb 13758 };
Marko Mikulicic 0:c0ecb8bf28eb 13759
Marko Mikulicic 0:c0ecb8bf28eb 13760 /*
Marko Mikulicic 0:c0ecb8bf28eb 13761 * If returning from function implicitly, then set return value to `undefined`.
Marko Mikulicic 0:c0ecb8bf28eb 13762 *
Marko Mikulicic 0:c0ecb8bf28eb 13763 * And if function was called as a constructor, then make sure returned
Marko Mikulicic 0:c0ecb8bf28eb 13764 * value is an object.
Marko Mikulicic 0:c0ecb8bf28eb 13765 */
Marko Mikulicic 0:c0ecb8bf28eb 13766 static void bcode_adjust_retval(struct v7 *v7, uint8_t is_explicit_return) {
Marko Mikulicic 0:c0ecb8bf28eb 13767 if (!is_explicit_return) {
Marko Mikulicic 0:c0ecb8bf28eb 13768 /* returning implicitly: set return value to `undefined` */
Marko Mikulicic 0:c0ecb8bf28eb 13769 POP();
Marko Mikulicic 0:c0ecb8bf28eb 13770 PUSH(V7_UNDEFINED);
Marko Mikulicic 0:c0ecb8bf28eb 13771 }
Marko Mikulicic 0:c0ecb8bf28eb 13772
Marko Mikulicic 0:c0ecb8bf28eb 13773 if (v7->call_stack->is_constructor && !v7_is_object(TOS())) {
Marko Mikulicic 0:c0ecb8bf28eb 13774 /* constructor is going to return non-object: replace it with `this` */
Marko Mikulicic 0:c0ecb8bf28eb 13775 POP();
Marko Mikulicic 0:c0ecb8bf28eb 13776 PUSH(v7_get_this(v7));
Marko Mikulicic 0:c0ecb8bf28eb 13777 }
Marko Mikulicic 0:c0ecb8bf28eb 13778 }
Marko Mikulicic 0:c0ecb8bf28eb 13779
Marko Mikulicic 0:c0ecb8bf28eb 13780 static void bcode_restore_registers(struct v7 *v7, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 13781 struct bcode_registers *r) {
Marko Mikulicic 0:c0ecb8bf28eb 13782 r->bcode = bcode;
Marko Mikulicic 0:c0ecb8bf28eb 13783 r->ops = bcode->ops.p;
Marko Mikulicic 0:c0ecb8bf28eb 13784 r->end = r->ops + bcode->ops.len;
Marko Mikulicic 0:c0ecb8bf28eb 13785
Marko Mikulicic 0:c0ecb8bf28eb 13786 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 13787 }
Marko Mikulicic 0:c0ecb8bf28eb 13788
Marko Mikulicic 0:c0ecb8bf28eb 13789 V7_PRIVATE struct v7_call_frame_base *find_call_frame(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 13790 uint8_t type_mask) {
Marko Mikulicic 0:c0ecb8bf28eb 13791 struct v7_call_frame_base *ret = v7->call_stack;
Marko Mikulicic 0:c0ecb8bf28eb 13792
Marko Mikulicic 0:c0ecb8bf28eb 13793 while (ret != NULL && !(ret->type_mask & type_mask)) {
Marko Mikulicic 0:c0ecb8bf28eb 13794 ret = ret->prev;
Marko Mikulicic 0:c0ecb8bf28eb 13795 }
Marko Mikulicic 0:c0ecb8bf28eb 13796
Marko Mikulicic 0:c0ecb8bf28eb 13797 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 13798 }
Marko Mikulicic 0:c0ecb8bf28eb 13799
Marko Mikulicic 0:c0ecb8bf28eb 13800 static struct v7_call_frame_private *find_call_frame_private(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 13801 return (struct v7_call_frame_private *) find_call_frame(
Marko Mikulicic 0:c0ecb8bf28eb 13802 v7, V7_CALL_FRAME_MASK_PRIVATE);
Marko Mikulicic 0:c0ecb8bf28eb 13803 }
Marko Mikulicic 0:c0ecb8bf28eb 13804
Marko Mikulicic 0:c0ecb8bf28eb 13805 static struct v7_call_frame_bcode *find_call_frame_bcode(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 13806 return (struct v7_call_frame_bcode *) find_call_frame(
Marko Mikulicic 0:c0ecb8bf28eb 13807 v7, V7_CALL_FRAME_MASK_BCODE);
Marko Mikulicic 0:c0ecb8bf28eb 13808 }
Marko Mikulicic 0:c0ecb8bf28eb 13809
Marko Mikulicic 0:c0ecb8bf28eb 13810 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 13811 static struct v7_call_frame_cfunc *find_call_frame_cfunc(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 13812 return (struct v7_call_frame_cfunc *) find_call_frame(
Marko Mikulicic 0:c0ecb8bf28eb 13813 v7, V7_CALL_FRAME_MASK_CFUNC);
Marko Mikulicic 0:c0ecb8bf28eb 13814 }
Marko Mikulicic 0:c0ecb8bf28eb 13815 #endif
Marko Mikulicic 0:c0ecb8bf28eb 13816
Marko Mikulicic 0:c0ecb8bf28eb 13817 static struct v7_call_frame_base *create_call_frame(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 13818 size_t size) {
Marko Mikulicic 0:c0ecb8bf28eb 13819 struct v7_call_frame_base *call_frame_base = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 13820
Marko Mikulicic 0:c0ecb8bf28eb 13821 call_frame_base = (struct v7_call_frame_base *) calloc(1, size);
Marko Mikulicic 0:c0ecb8bf28eb 13822
Marko Mikulicic 0:c0ecb8bf28eb 13823 /* save previous call frame */
Marko Mikulicic 0:c0ecb8bf28eb 13824 call_frame_base->prev = v7->call_stack;
Marko Mikulicic 0:c0ecb8bf28eb 13825
Marko Mikulicic 0:c0ecb8bf28eb 13826 /* by default, inherit line_no from the previous frame */
Marko Mikulicic 0:c0ecb8bf28eb 13827 if (v7->call_stack != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 13828 call_frame_base->line_no = v7->call_stack->line_no;
Marko Mikulicic 0:c0ecb8bf28eb 13829 }
Marko Mikulicic 0:c0ecb8bf28eb 13830
Marko Mikulicic 0:c0ecb8bf28eb 13831 return call_frame_base;
Marko Mikulicic 0:c0ecb8bf28eb 13832 }
Marko Mikulicic 0:c0ecb8bf28eb 13833
Marko Mikulicic 0:c0ecb8bf28eb 13834 static void init_call_frame_private(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 13835 struct v7_call_frame_private *call_frame,
Marko Mikulicic 0:c0ecb8bf28eb 13836 val_t scope) {
Marko Mikulicic 0:c0ecb8bf28eb 13837 /* make a snapshot of the current state */
Marko Mikulicic 0:c0ecb8bf28eb 13838 {
Marko Mikulicic 0:c0ecb8bf28eb 13839 struct v7_call_frame_private *cf = find_call_frame_private(v7);
Marko Mikulicic 0:c0ecb8bf28eb 13840 if (cf != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 13841 cf->stack_size = v7->stack.len;
Marko Mikulicic 0:c0ecb8bf28eb 13842 }
Marko Mikulicic 0:c0ecb8bf28eb 13843 }
Marko Mikulicic 0:c0ecb8bf28eb 13844
Marko Mikulicic 0:c0ecb8bf28eb 13845 /* set a type flag */
Marko Mikulicic 0:c0ecb8bf28eb 13846 call_frame->base.type_mask |= V7_CALL_FRAME_MASK_PRIVATE;
Marko Mikulicic 0:c0ecb8bf28eb 13847
Marko Mikulicic 0:c0ecb8bf28eb 13848 /* fill the new frame with data */
Marko Mikulicic 0:c0ecb8bf28eb 13849 call_frame->vals.scope = scope;
Marko Mikulicic 0:c0ecb8bf28eb 13850 /* `try_stack` will be lazily created in `eval_try_push()`*/
Marko Mikulicic 0:c0ecb8bf28eb 13851 call_frame->vals.try_stack = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 13852 }
Marko Mikulicic 0:c0ecb8bf28eb 13853
Marko Mikulicic 0:c0ecb8bf28eb 13854 static void init_call_frame_bcode(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 13855 struct v7_call_frame_bcode *call_frame,
Marko Mikulicic 0:c0ecb8bf28eb 13856 char *prev_bcode_ops, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 13857 val_t this_obj, val_t scope,
Marko Mikulicic 0:c0ecb8bf28eb 13858 uint8_t is_constructor) {
Marko Mikulicic 0:c0ecb8bf28eb 13859 init_call_frame_private(v7, &call_frame->base, scope);
Marko Mikulicic 0:c0ecb8bf28eb 13860
Marko Mikulicic 0:c0ecb8bf28eb 13861 /* make a snapshot of the current state */
Marko Mikulicic 0:c0ecb8bf28eb 13862 {
Marko Mikulicic 0:c0ecb8bf28eb 13863 struct v7_call_frame_bcode *cf = find_call_frame_bcode(v7);
Marko Mikulicic 0:c0ecb8bf28eb 13864 if (cf != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 13865 cf->bcode_ops = prev_bcode_ops;
Marko Mikulicic 0:c0ecb8bf28eb 13866
Marko Mikulicic 0:c0ecb8bf28eb 13867 /* remember thrown value */
Marko Mikulicic 0:c0ecb8bf28eb 13868 cf->vals.thrown_error = v7->vals.thrown_error;
Marko Mikulicic 0:c0ecb8bf28eb 13869 cf->base.base.is_thrown = v7->is_thrown;
Marko Mikulicic 0:c0ecb8bf28eb 13870 }
Marko Mikulicic 0:c0ecb8bf28eb 13871 }
Marko Mikulicic 0:c0ecb8bf28eb 13872
Marko Mikulicic 0:c0ecb8bf28eb 13873 /* set a type flag */
Marko Mikulicic 0:c0ecb8bf28eb 13874 call_frame->base.base.type_mask |= V7_CALL_FRAME_MASK_BCODE;
Marko Mikulicic 0:c0ecb8bf28eb 13875
Marko Mikulicic 0:c0ecb8bf28eb 13876 /* fill the new frame with data */
Marko Mikulicic 0:c0ecb8bf28eb 13877 call_frame->bcode = bcode;
Marko Mikulicic 0:c0ecb8bf28eb 13878 call_frame->vals.this_obj = this_obj;
Marko Mikulicic 0:c0ecb8bf28eb 13879 call_frame->base.base.is_constructor = is_constructor;
Marko Mikulicic 0:c0ecb8bf28eb 13880 }
Marko Mikulicic 0:c0ecb8bf28eb 13881
Marko Mikulicic 0:c0ecb8bf28eb 13882 /*
Marko Mikulicic 0:c0ecb8bf28eb 13883 * Create new bcode call frame object and fill it with data
Marko Mikulicic 0:c0ecb8bf28eb 13884 */
Marko Mikulicic 0:c0ecb8bf28eb 13885 static void append_call_frame_bcode(struct v7 *v7, char *prev_bcode_ops,
Marko Mikulicic 0:c0ecb8bf28eb 13886 struct bcode *bcode, val_t this_obj,
Marko Mikulicic 0:c0ecb8bf28eb 13887 val_t scope, uint8_t is_constructor) {
Marko Mikulicic 0:c0ecb8bf28eb 13888 struct v7_call_frame_bcode *call_frame =
Marko Mikulicic 0:c0ecb8bf28eb 13889 (struct v7_call_frame_bcode *) create_call_frame(v7, sizeof(*call_frame));
Marko Mikulicic 0:c0ecb8bf28eb 13890
Marko Mikulicic 0:c0ecb8bf28eb 13891 init_call_frame_bcode(v7, call_frame, prev_bcode_ops, bcode, this_obj, scope,
Marko Mikulicic 0:c0ecb8bf28eb 13892 is_constructor);
Marko Mikulicic 0:c0ecb8bf28eb 13893
Marko Mikulicic 0:c0ecb8bf28eb 13894 v7->call_stack = &call_frame->base.base;
Marko Mikulicic 0:c0ecb8bf28eb 13895 }
Marko Mikulicic 0:c0ecb8bf28eb 13896
Marko Mikulicic 0:c0ecb8bf28eb 13897 static void append_call_frame_private(struct v7 *v7, val_t scope) {
Marko Mikulicic 0:c0ecb8bf28eb 13898 struct v7_call_frame_private *call_frame =
Marko Mikulicic 0:c0ecb8bf28eb 13899 (struct v7_call_frame_private *) create_call_frame(v7,
Marko Mikulicic 0:c0ecb8bf28eb 13900 sizeof(*call_frame));
Marko Mikulicic 0:c0ecb8bf28eb 13901 init_call_frame_private(v7, call_frame, scope);
Marko Mikulicic 0:c0ecb8bf28eb 13902
Marko Mikulicic 0:c0ecb8bf28eb 13903 v7->call_stack = &call_frame->base;
Marko Mikulicic 0:c0ecb8bf28eb 13904 }
Marko Mikulicic 0:c0ecb8bf28eb 13905
Marko Mikulicic 0:c0ecb8bf28eb 13906 static void append_call_frame_cfunc(struct v7 *v7, val_t this_obj,
Marko Mikulicic 0:c0ecb8bf28eb 13907 v7_cfunction_t *cfunc) {
Marko Mikulicic 0:c0ecb8bf28eb 13908 struct v7_call_frame_cfunc *call_frame =
Marko Mikulicic 0:c0ecb8bf28eb 13909 (struct v7_call_frame_cfunc *) create_call_frame(v7, sizeof(*call_frame));
Marko Mikulicic 0:c0ecb8bf28eb 13910
Marko Mikulicic 0:c0ecb8bf28eb 13911 /* set a type flag */
Marko Mikulicic 0:c0ecb8bf28eb 13912 call_frame->base.type_mask |= V7_CALL_FRAME_MASK_CFUNC;
Marko Mikulicic 0:c0ecb8bf28eb 13913
Marko Mikulicic 0:c0ecb8bf28eb 13914 /* fill the new frame with data */
Marko Mikulicic 0:c0ecb8bf28eb 13915 call_frame->cfunc = cfunc;
Marko Mikulicic 0:c0ecb8bf28eb 13916 call_frame->vals.this_obj = this_obj;
Marko Mikulicic 0:c0ecb8bf28eb 13917
Marko Mikulicic 0:c0ecb8bf28eb 13918 v7->call_stack = &call_frame->base;
Marko Mikulicic 0:c0ecb8bf28eb 13919 }
Marko Mikulicic 0:c0ecb8bf28eb 13920
Marko Mikulicic 0:c0ecb8bf28eb 13921 /*
Marko Mikulicic 0:c0ecb8bf28eb 13922 * The caller's bcode object is needed because we have to restore literals
Marko Mikulicic 0:c0ecb8bf28eb 13923 * and `end` registers.
Marko Mikulicic 0:c0ecb8bf28eb 13924 *
Marko Mikulicic 0:c0ecb8bf28eb 13925 * TODO(mkm): put this state on a return stack
Marko Mikulicic 0:c0ecb8bf28eb 13926 *
Marko Mikulicic 0:c0ecb8bf28eb 13927 * Caller of bcode_perform_call is responsible for owning `call_frame`
Marko Mikulicic 0:c0ecb8bf28eb 13928 */
Marko Mikulicic 0:c0ecb8bf28eb 13929 static enum v7_err bcode_perform_call(struct v7 *v7, v7_val_t scope_frame,
Marko Mikulicic 0:c0ecb8bf28eb 13930 struct v7_js_function *func,
Marko Mikulicic 0:c0ecb8bf28eb 13931 struct bcode_registers *r,
Marko Mikulicic 0:c0ecb8bf28eb 13932 val_t this_object, char *ops,
Marko Mikulicic 0:c0ecb8bf28eb 13933 uint8_t is_constructor) {
Marko Mikulicic 0:c0ecb8bf28eb 13934 /* new scope_frame will inherit from the function's scope */
Marko Mikulicic 0:c0ecb8bf28eb 13935 obj_prototype_set(v7, get_object_struct(scope_frame), &func->scope->base);
Marko Mikulicic 0:c0ecb8bf28eb 13936
Marko Mikulicic 0:c0ecb8bf28eb 13937 /* create new `call_frame` which will replace `v7->call_stack` */
Marko Mikulicic 0:c0ecb8bf28eb 13938 append_call_frame_bcode(v7, r->ops + 1, func->bcode, this_object, scope_frame,
Marko Mikulicic 0:c0ecb8bf28eb 13939 is_constructor);
Marko Mikulicic 0:c0ecb8bf28eb 13940
Marko Mikulicic 0:c0ecb8bf28eb 13941 bcode_restore_registers(v7, func->bcode, r);
Marko Mikulicic 0:c0ecb8bf28eb 13942
Marko Mikulicic 0:c0ecb8bf28eb 13943 /* adjust `ops` since names were already read from it */
Marko Mikulicic 0:c0ecb8bf28eb 13944 r->ops = ops;
Marko Mikulicic 0:c0ecb8bf28eb 13945
Marko Mikulicic 0:c0ecb8bf28eb 13946 /* `ops` already points to the needed instruction, no need to increment it */
Marko Mikulicic 0:c0ecb8bf28eb 13947 r->need_inc_ops = 0;
Marko Mikulicic 0:c0ecb8bf28eb 13948
Marko Mikulicic 0:c0ecb8bf28eb 13949 return V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 13950 }
Marko Mikulicic 0:c0ecb8bf28eb 13951
Marko Mikulicic 0:c0ecb8bf28eb 13952 /*
Marko Mikulicic 0:c0ecb8bf28eb 13953 * Apply data from the "private" call frame, typically after some other frame
Marko Mikulicic 0:c0ecb8bf28eb 13954 * was just unwound.
Marko Mikulicic 0:c0ecb8bf28eb 13955 *
Marko Mikulicic 0:c0ecb8bf28eb 13956 * The `call_frame` may actually be `NULL`, if the top frame was unwound.
Marko Mikulicic 0:c0ecb8bf28eb 13957 */
Marko Mikulicic 0:c0ecb8bf28eb 13958 static void apply_frame_private(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 13959 struct v7_call_frame_private *call_frame) {
Marko Mikulicic 0:c0ecb8bf28eb 13960 /*
Marko Mikulicic 0:c0ecb8bf28eb 13961 * Adjust data stack length (restore saved).
Marko Mikulicic 0:c0ecb8bf28eb 13962 *
Marko Mikulicic 0:c0ecb8bf28eb 13963 * If `call_frame` is NULL, it means that the last call frame was just
Marko Mikulicic 0:c0ecb8bf28eb 13964 * unwound, and hence the data stack size should be 0.
Marko Mikulicic 0:c0ecb8bf28eb 13965 */
Marko Mikulicic 0:c0ecb8bf28eb 13966 size_t stack_size = (call_frame != NULL ? call_frame->stack_size : 0);
Marko Mikulicic 0:c0ecb8bf28eb 13967 assert(stack_size <= v7->stack.len);
Marko Mikulicic 0:c0ecb8bf28eb 13968 v7->stack.len = stack_size;
Marko Mikulicic 0:c0ecb8bf28eb 13969 }
Marko Mikulicic 0:c0ecb8bf28eb 13970
Marko Mikulicic 0:c0ecb8bf28eb 13971 /*
Marko Mikulicic 0:c0ecb8bf28eb 13972 * Apply data from the "bcode" call frame, typically after some other frame
Marko Mikulicic 0:c0ecb8bf28eb 13973 * was just unwound.
Marko Mikulicic 0:c0ecb8bf28eb 13974 *
Marko Mikulicic 0:c0ecb8bf28eb 13975 * The `call_frame` may actually be `NULL`, if the top frame was unwound; but
Marko Mikulicic 0:c0ecb8bf28eb 13976 * in this case, `r` must be `NULL` too, by design. See inline comment below.
Marko Mikulicic 0:c0ecb8bf28eb 13977 */
Marko Mikulicic 0:c0ecb8bf28eb 13978 static void apply_frame_bcode(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 13979 struct v7_call_frame_bcode *call_frame,
Marko Mikulicic 0:c0ecb8bf28eb 13980 struct bcode_registers *r) {
Marko Mikulicic 0:c0ecb8bf28eb 13981 if (r != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 13982 /*
Marko Mikulicic 0:c0ecb8bf28eb 13983 * Note: if `r` is non-NULL, then `call_frame` should be non-NULL as well,
Marko Mikulicic 0:c0ecb8bf28eb 13984 * by design. If this invariant is violated, it means that
Marko Mikulicic 0:c0ecb8bf28eb 13985 * `unwind_stack_1level()` is misused.
Marko Mikulicic 0:c0ecb8bf28eb 13986 */
Marko Mikulicic 0:c0ecb8bf28eb 13987 assert(call_frame != NULL);
Marko Mikulicic 0:c0ecb8bf28eb 13988
Marko Mikulicic 0:c0ecb8bf28eb 13989 bcode_restore_registers(v7, call_frame->bcode, r);
Marko Mikulicic 0:c0ecb8bf28eb 13990 r->ops = call_frame->bcode_ops;
Marko Mikulicic 0:c0ecb8bf28eb 13991
Marko Mikulicic 0:c0ecb8bf28eb 13992 /*
Marko Mikulicic 0:c0ecb8bf28eb 13993 * restore thrown value if only there's no new thrown value
Marko Mikulicic 0:c0ecb8bf28eb 13994 * (otherwise, the new one overrides the previous one)
Marko Mikulicic 0:c0ecb8bf28eb 13995 */
Marko Mikulicic 0:c0ecb8bf28eb 13996 if (!v7->is_thrown) {
Marko Mikulicic 0:c0ecb8bf28eb 13997 v7->vals.thrown_error = call_frame->vals.thrown_error;
Marko Mikulicic 0:c0ecb8bf28eb 13998 v7->is_thrown = call_frame->base.base.is_thrown;
Marko Mikulicic 0:c0ecb8bf28eb 13999 }
Marko Mikulicic 0:c0ecb8bf28eb 14000 }
Marko Mikulicic 0:c0ecb8bf28eb 14001 }
Marko Mikulicic 0:c0ecb8bf28eb 14002
Marko Mikulicic 0:c0ecb8bf28eb 14003 /*
Marko Mikulicic 0:c0ecb8bf28eb 14004 * Unwinds `call_stack` by 1 frame.
Marko Mikulicic 0:c0ecb8bf28eb 14005 *
Marko Mikulicic 0:c0ecb8bf28eb 14006 * Returns the type of the unwound frame
Marko Mikulicic 0:c0ecb8bf28eb 14007 */
Marko Mikulicic 0:c0ecb8bf28eb 14008 static v7_call_frame_mask_t unwind_stack_1level(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 14009 struct bcode_registers *r) {
Marko Mikulicic 0:c0ecb8bf28eb 14010 v7_call_frame_mask_t type_mask;
Marko Mikulicic 0:c0ecb8bf28eb 14011 #ifdef V7_BCODE_TRACE
Marko Mikulicic 0:c0ecb8bf28eb 14012 fprintf(stderr, "unwinding stack by 1 level\n");
Marko Mikulicic 0:c0ecb8bf28eb 14013 #endif
Marko Mikulicic 0:c0ecb8bf28eb 14014
Marko Mikulicic 0:c0ecb8bf28eb 14015 type_mask = v7->call_stack->type_mask;
Marko Mikulicic 0:c0ecb8bf28eb 14016
Marko Mikulicic 0:c0ecb8bf28eb 14017 /* drop the top frame */
Marko Mikulicic 0:c0ecb8bf28eb 14018 {
Marko Mikulicic 0:c0ecb8bf28eb 14019 struct v7_call_frame_base *tmp = v7->call_stack;
Marko Mikulicic 0:c0ecb8bf28eb 14020 v7->call_stack = v7->call_stack->prev;
Marko Mikulicic 0:c0ecb8bf28eb 14021 free(tmp);
Marko Mikulicic 0:c0ecb8bf28eb 14022 }
Marko Mikulicic 0:c0ecb8bf28eb 14023
Marko Mikulicic 0:c0ecb8bf28eb 14024 /*
Marko Mikulicic 0:c0ecb8bf28eb 14025 * depending on the unwound frame type, apply data from the top call frame(s)
Marko Mikulicic 0:c0ecb8bf28eb 14026 * which are still alive (if any)
Marko Mikulicic 0:c0ecb8bf28eb 14027 */
Marko Mikulicic 0:c0ecb8bf28eb 14028
Marko Mikulicic 0:c0ecb8bf28eb 14029 if (type_mask & V7_CALL_FRAME_MASK_PRIVATE) {
Marko Mikulicic 0:c0ecb8bf28eb 14030 apply_frame_private(v7, find_call_frame_private(v7));
Marko Mikulicic 0:c0ecb8bf28eb 14031 }
Marko Mikulicic 0:c0ecb8bf28eb 14032
Marko Mikulicic 0:c0ecb8bf28eb 14033 if (type_mask & V7_CALL_FRAME_MASK_BCODE) {
Marko Mikulicic 0:c0ecb8bf28eb 14034 apply_frame_bcode(v7, find_call_frame_bcode(v7), r);
Marko Mikulicic 0:c0ecb8bf28eb 14035 }
Marko Mikulicic 0:c0ecb8bf28eb 14036
Marko Mikulicic 0:c0ecb8bf28eb 14037 if (type_mask & V7_CALL_FRAME_MASK_CFUNC) {
Marko Mikulicic 0:c0ecb8bf28eb 14038 /* Nothing to do here at the moment */
Marko Mikulicic 0:c0ecb8bf28eb 14039 }
Marko Mikulicic 0:c0ecb8bf28eb 14040
Marko Mikulicic 0:c0ecb8bf28eb 14041 return type_mask;
Marko Mikulicic 0:c0ecb8bf28eb 14042 }
Marko Mikulicic 0:c0ecb8bf28eb 14043
Marko Mikulicic 0:c0ecb8bf28eb 14044 /*
Marko Mikulicic 0:c0ecb8bf28eb 14045 * Unwinds local "try stack" (i.e. local-to-current-function stack of nested
Marko Mikulicic 0:c0ecb8bf28eb 14046 * `try` blocks), looking for local-to-function blocks.
Marko Mikulicic 0:c0ecb8bf28eb 14047 *
Marko Mikulicic 0:c0ecb8bf28eb 14048 * Block types of interest are specified with `wanted_blocks_mask`: it's a
Marko Mikulicic 0:c0ecb8bf28eb 14049 * bitmask of `enum local_block` values.
Marko Mikulicic 0:c0ecb8bf28eb 14050 *
Marko Mikulicic 0:c0ecb8bf28eb 14051 * Only blocks of specified types will be considered, others will be dropped.
Marko Mikulicic 0:c0ecb8bf28eb 14052 *
Marko Mikulicic 0:c0ecb8bf28eb 14053 * If `restore_stack_size` is non-zero, the `v7->stack.len` will be restored
Marko Mikulicic 0:c0ecb8bf28eb 14054 * to the value saved when the block was created. This is useful when throwing,
Marko Mikulicic 0:c0ecb8bf28eb 14055 * since if we throw from the middle of the expression, the stack could have
Marko Mikulicic 0:c0ecb8bf28eb 14056 * any size. But you probably shouldn't set this flag when breaking and
Marko Mikulicic 0:c0ecb8bf28eb 14057 * returning, since it may hide real bugs in the opcode.
Marko Mikulicic 0:c0ecb8bf28eb 14058 *
Marko Mikulicic 0:c0ecb8bf28eb 14059 * Returns id of the block type that control was transferred into, or
Marko Mikulicic 0:c0ecb8bf28eb 14060 * `LOCAL_BLOCK_NONE` if no appropriate block was found. Note: returned value
Marko Mikulicic 0:c0ecb8bf28eb 14061 * contains at most 1 block bit; it can't contain multiple bits.
Marko Mikulicic 0:c0ecb8bf28eb 14062 */
Marko Mikulicic 0:c0ecb8bf28eb 14063 static enum local_block unwind_local_blocks_stack(
Marko Mikulicic 0:c0ecb8bf28eb 14064 struct v7 *v7, struct bcode_registers *r, unsigned int wanted_blocks_mask,
Marko Mikulicic 0:c0ecb8bf28eb 14065 uint8_t restore_stack_size) {
Marko Mikulicic 0:c0ecb8bf28eb 14066 val_t arr = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 14067 struct gc_tmp_frame tf = new_tmp_frame(v7);
Marko Mikulicic 0:c0ecb8bf28eb 14068 enum local_block found_block = LOCAL_BLOCK_NONE;
Marko Mikulicic 0:c0ecb8bf28eb 14069 unsigned long length;
Marko Mikulicic 0:c0ecb8bf28eb 14070
Marko Mikulicic 0:c0ecb8bf28eb 14071 tmp_stack_push(&tf, &arr);
Marko Mikulicic 0:c0ecb8bf28eb 14072
Marko Mikulicic 0:c0ecb8bf28eb 14073 arr = find_call_frame_private(v7)->vals.try_stack;
Marko Mikulicic 0:c0ecb8bf28eb 14074 if (v7_is_array(v7, arr)) {
Marko Mikulicic 0:c0ecb8bf28eb 14075 /*
Marko Mikulicic 0:c0ecb8bf28eb 14076 * pop latest element from "try stack", loop until we need to transfer
Marko Mikulicic 0:c0ecb8bf28eb 14077 * control there
Marko Mikulicic 0:c0ecb8bf28eb 14078 */
Marko Mikulicic 0:c0ecb8bf28eb 14079 while ((length = v7_array_length(v7, arr)) > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 14080 /* get latest offset from the "try stack" */
Marko Mikulicic 0:c0ecb8bf28eb 14081 int64_t offset = v7_get_double(v7, v7_array_get(v7, arr, length - 1));
Marko Mikulicic 0:c0ecb8bf28eb 14082 enum local_block cur_block = LOCAL_BLOCK_NONE;
Marko Mikulicic 0:c0ecb8bf28eb 14083
Marko Mikulicic 0:c0ecb8bf28eb 14084 /* get id of the current block type */
Marko Mikulicic 0:c0ecb8bf28eb 14085 switch (LBLOCK_TAG(offset)) {
Marko Mikulicic 0:c0ecb8bf28eb 14086 case LBLOCK_TAG_CATCH:
Marko Mikulicic 0:c0ecb8bf28eb 14087 cur_block = LOCAL_BLOCK_CATCH;
Marko Mikulicic 0:c0ecb8bf28eb 14088 break;
Marko Mikulicic 0:c0ecb8bf28eb 14089 case LBLOCK_TAG_FINALLY:
Marko Mikulicic 0:c0ecb8bf28eb 14090 cur_block = LOCAL_BLOCK_FINALLY;
Marko Mikulicic 0:c0ecb8bf28eb 14091 break;
Marko Mikulicic 0:c0ecb8bf28eb 14092 case LBLOCK_TAG_LOOP:
Marko Mikulicic 0:c0ecb8bf28eb 14093 cur_block = LOCAL_BLOCK_LOOP;
Marko Mikulicic 0:c0ecb8bf28eb 14094 break;
Marko Mikulicic 0:c0ecb8bf28eb 14095 case LBLOCK_TAG_SWITCH:
Marko Mikulicic 0:c0ecb8bf28eb 14096 cur_block = LOCAL_BLOCK_SWITCH;
Marko Mikulicic 0:c0ecb8bf28eb 14097 break;
Marko Mikulicic 0:c0ecb8bf28eb 14098 default:
Marko Mikulicic 0:c0ecb8bf28eb 14099 assert(0);
Marko Mikulicic 0:c0ecb8bf28eb 14100 break;
Marko Mikulicic 0:c0ecb8bf28eb 14101 }
Marko Mikulicic 0:c0ecb8bf28eb 14102
Marko Mikulicic 0:c0ecb8bf28eb 14103 if (cur_block & wanted_blocks_mask) {
Marko Mikulicic 0:c0ecb8bf28eb 14104 /* need to transfer control to this offset */
Marko Mikulicic 0:c0ecb8bf28eb 14105 r->ops = r->bcode->ops.p + LBLOCK_OFFSET(offset);
Marko Mikulicic 0:c0ecb8bf28eb 14106 #ifdef V7_BCODE_TRACE
Marko Mikulicic 0:c0ecb8bf28eb 14107 fprintf(stderr, "transferring to block #%d: %u\n", (int) cur_block,
Marko Mikulicic 0:c0ecb8bf28eb 14108 (unsigned int) LBLOCK_OFFSET(offset));
Marko Mikulicic 0:c0ecb8bf28eb 14109 #endif
Marko Mikulicic 0:c0ecb8bf28eb 14110 found_block = cur_block;
Marko Mikulicic 0:c0ecb8bf28eb 14111 /* if needed, restore stack size to the saved value */
Marko Mikulicic 0:c0ecb8bf28eb 14112 if (restore_stack_size) {
Marko Mikulicic 0:c0ecb8bf28eb 14113 v7->stack.len = LBLOCK_STACK_SIZE(offset);
Marko Mikulicic 0:c0ecb8bf28eb 14114 }
Marko Mikulicic 0:c0ecb8bf28eb 14115 break;
Marko Mikulicic 0:c0ecb8bf28eb 14116 } else {
Marko Mikulicic 0:c0ecb8bf28eb 14117 #ifdef V7_BCODE_TRACE
Marko Mikulicic 0:c0ecb8bf28eb 14118 fprintf(stderr, "skipped block #%d: %u\n", (int) cur_block,
Marko Mikulicic 0:c0ecb8bf28eb 14119 (unsigned int) LBLOCK_OFFSET(offset));
Marko Mikulicic 0:c0ecb8bf28eb 14120 #endif
Marko Mikulicic 0:c0ecb8bf28eb 14121 /*
Marko Mikulicic 0:c0ecb8bf28eb 14122 * since we don't need to control transfer there, just pop
Marko Mikulicic 0:c0ecb8bf28eb 14123 * it from the "try stack"
Marko Mikulicic 0:c0ecb8bf28eb 14124 */
Marko Mikulicic 0:c0ecb8bf28eb 14125 v7_array_del(v7, arr, length - 1);
Marko Mikulicic 0:c0ecb8bf28eb 14126 }
Marko Mikulicic 0:c0ecb8bf28eb 14127 }
Marko Mikulicic 0:c0ecb8bf28eb 14128 }
Marko Mikulicic 0:c0ecb8bf28eb 14129
Marko Mikulicic 0:c0ecb8bf28eb 14130 tmp_frame_cleanup(&tf);
Marko Mikulicic 0:c0ecb8bf28eb 14131 return found_block;
Marko Mikulicic 0:c0ecb8bf28eb 14132 }
Marko Mikulicic 0:c0ecb8bf28eb 14133
Marko Mikulicic 0:c0ecb8bf28eb 14134 /*
Marko Mikulicic 0:c0ecb8bf28eb 14135 * Perform break, if there is a `finally` block in effect, transfer
Marko Mikulicic 0:c0ecb8bf28eb 14136 * control there.
Marko Mikulicic 0:c0ecb8bf28eb 14137 */
Marko Mikulicic 0:c0ecb8bf28eb 14138 static void bcode_perform_break(struct v7 *v7, struct bcode_registers *r) {
Marko Mikulicic 0:c0ecb8bf28eb 14139 enum local_block found;
Marko Mikulicic 0:c0ecb8bf28eb 14140 unsigned int mask;
Marko Mikulicic 0:c0ecb8bf28eb 14141 v7->is_breaking = 0;
Marko Mikulicic 0:c0ecb8bf28eb 14142 if (v7->is_continuing) {
Marko Mikulicic 0:c0ecb8bf28eb 14143 mask = LOCAL_BLOCK_LOOP;
Marko Mikulicic 0:c0ecb8bf28eb 14144 } else {
Marko Mikulicic 0:c0ecb8bf28eb 14145 mask = LOCAL_BLOCK_LOOP | LOCAL_BLOCK_SWITCH;
Marko Mikulicic 0:c0ecb8bf28eb 14146 }
Marko Mikulicic 0:c0ecb8bf28eb 14147
Marko Mikulicic 0:c0ecb8bf28eb 14148 /*
Marko Mikulicic 0:c0ecb8bf28eb 14149 * Keep unwinding until we find local block of interest. We should not
Marko Mikulicic 0:c0ecb8bf28eb 14150 * encounter any "function" frames; only "private" frames are allowed.
Marko Mikulicic 0:c0ecb8bf28eb 14151 */
Marko Mikulicic 0:c0ecb8bf28eb 14152 for (;;) {
Marko Mikulicic 0:c0ecb8bf28eb 14153 /*
Marko Mikulicic 0:c0ecb8bf28eb 14154 * Try to unwind local "try stack", considering only `finally` and `break`.
Marko Mikulicic 0:c0ecb8bf28eb 14155 */
Marko Mikulicic 0:c0ecb8bf28eb 14156 found = unwind_local_blocks_stack(v7, r, mask | LOCAL_BLOCK_FINALLY, 0);
Marko Mikulicic 0:c0ecb8bf28eb 14157 if (found == LOCAL_BLOCK_NONE) {
Marko Mikulicic 0:c0ecb8bf28eb 14158 /*
Marko Mikulicic 0:c0ecb8bf28eb 14159 * no blocks found: this may happen if only the `break` or `continue` has
Marko Mikulicic 0:c0ecb8bf28eb 14160 * occurred inside "private" frame. So, unwind this frame, make sure it
Marko Mikulicic 0:c0ecb8bf28eb 14161 * is indeed a "private" frame, and keep unwinding local blocks.
Marko Mikulicic 0:c0ecb8bf28eb 14162 */
Marko Mikulicic 0:c0ecb8bf28eb 14163 v7_call_frame_mask_t frame_type_mask = unwind_stack_1level(v7, r);
Marko Mikulicic 0:c0ecb8bf28eb 14164 assert(frame_type_mask == V7_CALL_FRAME_MASK_PRIVATE);
Marko Mikulicic 0:c0ecb8bf28eb 14165 (void) frame_type_mask;
Marko Mikulicic 0:c0ecb8bf28eb 14166 } else {
Marko Mikulicic 0:c0ecb8bf28eb 14167 /* found some block to transfer control into, stop unwinding */
Marko Mikulicic 0:c0ecb8bf28eb 14168 break;
Marko Mikulicic 0:c0ecb8bf28eb 14169 }
Marko Mikulicic 0:c0ecb8bf28eb 14170 }
Marko Mikulicic 0:c0ecb8bf28eb 14171
Marko Mikulicic 0:c0ecb8bf28eb 14172 /*
Marko Mikulicic 0:c0ecb8bf28eb 14173 * upon exit of a finally block we'll reenter here if is_breaking is true.
Marko Mikulicic 0:c0ecb8bf28eb 14174 * See OP_AFTER_FINALLY.
Marko Mikulicic 0:c0ecb8bf28eb 14175 */
Marko Mikulicic 0:c0ecb8bf28eb 14176 if (found == LOCAL_BLOCK_FINALLY) {
Marko Mikulicic 0:c0ecb8bf28eb 14177 v7->is_breaking = 1;
Marko Mikulicic 0:c0ecb8bf28eb 14178 }
Marko Mikulicic 0:c0ecb8bf28eb 14179
Marko Mikulicic 0:c0ecb8bf28eb 14180 /* `ops` already points to the needed instruction, no need to increment it */
Marko Mikulicic 0:c0ecb8bf28eb 14181 r->need_inc_ops = 0;
Marko Mikulicic 0:c0ecb8bf28eb 14182 }
Marko Mikulicic 0:c0ecb8bf28eb 14183
Marko Mikulicic 0:c0ecb8bf28eb 14184 /*
Marko Mikulicic 0:c0ecb8bf28eb 14185 * Perform return, but if there is a `finally` block in effect, transfer
Marko Mikulicic 0:c0ecb8bf28eb 14186 * control there.
Marko Mikulicic 0:c0ecb8bf28eb 14187 *
Marko Mikulicic 0:c0ecb8bf28eb 14188 * If `take_retval` is non-zero, value to return will be popped from stack
Marko Mikulicic 0:c0ecb8bf28eb 14189 * (and saved into `v7->vals.returned_value`), otherwise, it won't ae affected.
Marko Mikulicic 0:c0ecb8bf28eb 14190 */
Marko Mikulicic 0:c0ecb8bf28eb 14191 static enum v7_err bcode_perform_return(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 14192 struct bcode_registers *r,
Marko Mikulicic 0:c0ecb8bf28eb 14193 int take_retval) {
Marko Mikulicic 0:c0ecb8bf28eb 14194 /*
Marko Mikulicic 0:c0ecb8bf28eb 14195 * We should either take retval from the stack, or some value should already
Marko Mikulicic 0:c0ecb8bf28eb 14196 * de pending to return
Marko Mikulicic 0:c0ecb8bf28eb 14197 */
Marko Mikulicic 0:c0ecb8bf28eb 14198 assert(take_retval || v7->is_returned);
Marko Mikulicic 0:c0ecb8bf28eb 14199
Marko Mikulicic 0:c0ecb8bf28eb 14200 if (take_retval) {
Marko Mikulicic 0:c0ecb8bf28eb 14201 /* taking return value from stack */
Marko Mikulicic 0:c0ecb8bf28eb 14202 v7->vals.returned_value = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14203 v7->is_returned = 1;
Marko Mikulicic 0:c0ecb8bf28eb 14204
Marko Mikulicic 0:c0ecb8bf28eb 14205 /*
Marko Mikulicic 0:c0ecb8bf28eb 14206 * returning (say, from `finally`) dismisses any errors that are eeing
Marko Mikulicic 0:c0ecb8bf28eb 14207 * thrown at the moment as well
Marko Mikulicic 0:c0ecb8bf28eb 14208 */
Marko Mikulicic 0:c0ecb8bf28eb 14209 v7->is_thrown = 0;
Marko Mikulicic 0:c0ecb8bf28eb 14210 v7->vals.thrown_error = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 14211 }
Marko Mikulicic 0:c0ecb8bf28eb 14212
Marko Mikulicic 0:c0ecb8bf28eb 14213 /*
Marko Mikulicic 0:c0ecb8bf28eb 14214 * Keep unwinding until we unwound "function" frame, or found some `finally`
Marko Mikulicic 0:c0ecb8bf28eb 14215 * block.
Marko Mikulicic 0:c0ecb8bf28eb 14216 */
Marko Mikulicic 0:c0ecb8bf28eb 14217 for (;;) {
Marko Mikulicic 0:c0ecb8bf28eb 14218 /* Try to unwind local "try stack", considering only `finally` blocks */
Marko Mikulicic 0:c0ecb8bf28eb 14219 if (unwind_local_blocks_stack(v7, r, (LOCAL_BLOCK_FINALLY), 0) ==
Marko Mikulicic 0:c0ecb8bf28eb 14220 LOCAL_BLOCK_NONE) {
Marko Mikulicic 0:c0ecb8bf28eb 14221 /*
Marko Mikulicic 0:c0ecb8bf28eb 14222 * no `finally` blocks were found, so, unwind stack by 1 level, and see
Marko Mikulicic 0:c0ecb8bf28eb 14223 * if it's a "function" frame. If not, will keep unwinding.
Marko Mikulicic 0:c0ecb8bf28eb 14224 */
Marko Mikulicic 0:c0ecb8bf28eb 14225 if (unwind_stack_1level(v7, r) & V7_CALL_FRAME_MASK_BCODE) {
Marko Mikulicic 0:c0ecb8bf28eb 14226 /*
Marko Mikulicic 0:c0ecb8bf28eb 14227 * unwound frame is a "function" frame, so, push returned value to
Marko Mikulicic 0:c0ecb8bf28eb 14228 * stack, and stop unwinding
Marko Mikulicic 0:c0ecb8bf28eb 14229 */
Marko Mikulicic 0:c0ecb8bf28eb 14230 PUSH(v7->vals.returned_value);
Marko Mikulicic 0:c0ecb8bf28eb 14231 v7->is_returned = 0;
Marko Mikulicic 0:c0ecb8bf28eb 14232 v7->vals.returned_value = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 14233
Marko Mikulicic 0:c0ecb8bf28eb 14234 break;
Marko Mikulicic 0:c0ecb8bf28eb 14235 }
Marko Mikulicic 0:c0ecb8bf28eb 14236 } else {
Marko Mikulicic 0:c0ecb8bf28eb 14237 /* found `finally` block, so, stop unwinding */
Marko Mikulicic 0:c0ecb8bf28eb 14238 break;
Marko Mikulicic 0:c0ecb8bf28eb 14239 }
Marko Mikulicic 0:c0ecb8bf28eb 14240 }
Marko Mikulicic 0:c0ecb8bf28eb 14241
Marko Mikulicic 0:c0ecb8bf28eb 14242 /* `ops` already points to the needed instruction, no need to increment it */
Marko Mikulicic 0:c0ecb8bf28eb 14243 r->need_inc_ops = 0;
Marko Mikulicic 0:c0ecb8bf28eb 14244
Marko Mikulicic 0:c0ecb8bf28eb 14245 return V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 14246 }
Marko Mikulicic 0:c0ecb8bf28eb 14247
Marko Mikulicic 0:c0ecb8bf28eb 14248 /*
Marko Mikulicic 0:c0ecb8bf28eb 14249 * Perform throw inside `eval_bcode()`.
Marko Mikulicic 0:c0ecb8bf28eb 14250 *
Marko Mikulicic 0:c0ecb8bf28eb 14251 * If `take_thrown_value` is non-zero, value to return will be popped from
Marko Mikulicic 0:c0ecb8bf28eb 14252 * stack (and saved into `v7->vals.thrown_error`), otherwise, it won't be
Marko Mikulicic 0:c0ecb8bf28eb 14253 * affected.
Marko Mikulicic 0:c0ecb8bf28eb 14254 *
Marko Mikulicic 0:c0ecb8bf28eb 14255 * Returns `V7_OK` if thrown exception was caught, `V7_EXEC_EXCEPTION`
Marko Mikulicic 0:c0ecb8bf28eb 14256 * otherwise (in this case, evaluation of current script must be stopped)
Marko Mikulicic 0:c0ecb8bf28eb 14257 *
Marko Mikulicic 0:c0ecb8bf28eb 14258 * When calling this function from `eval_rcode()`, you should wrap this call
Marko Mikulicic 0:c0ecb8bf28eb 14259 * into the `V7_TRY()` macro.
Marko Mikulicic 0:c0ecb8bf28eb 14260 */
Marko Mikulicic 0:c0ecb8bf28eb 14261 static enum v7_err bcode_perform_throw(struct v7 *v7, struct bcode_registers *r,
Marko Mikulicic 0:c0ecb8bf28eb 14262 int take_thrown_value) {
Marko Mikulicic 0:c0ecb8bf28eb 14263 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 14264 enum local_block found;
Marko Mikulicic 0:c0ecb8bf28eb 14265
Marko Mikulicic 0:c0ecb8bf28eb 14266 assert(take_thrown_value || v7->is_thrown);
Marko Mikulicic 0:c0ecb8bf28eb 14267
Marko Mikulicic 0:c0ecb8bf28eb 14268 if (take_thrown_value) {
Marko Mikulicic 0:c0ecb8bf28eb 14269 v7->vals.thrown_error = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14270 v7->is_thrown = 1;
Marko Mikulicic 0:c0ecb8bf28eb 14271
Marko Mikulicic 0:c0ecb8bf28eb 14272 /* Throwing dismisses any pending return values */
Marko Mikulicic 0:c0ecb8bf28eb 14273 v7->is_returned = 0;
Marko Mikulicic 0:c0ecb8bf28eb 14274 v7->vals.returned_value = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 14275 }
Marko Mikulicic 0:c0ecb8bf28eb 14276
Marko Mikulicic 0:c0ecb8bf28eb 14277 while ((found = unwind_local_blocks_stack(
Marko Mikulicic 0:c0ecb8bf28eb 14278 v7, r, (LOCAL_BLOCK_CATCH | LOCAL_BLOCK_FINALLY), 1)) ==
Marko Mikulicic 0:c0ecb8bf28eb 14279 LOCAL_BLOCK_NONE) {
Marko Mikulicic 0:c0ecb8bf28eb 14280 if (v7->call_stack != v7->bottom_call_frame) {
Marko Mikulicic 0:c0ecb8bf28eb 14281 #ifdef V7_BCODE_TRACE
Marko Mikulicic 0:c0ecb8bf28eb 14282 fprintf(stderr, "not at the bottom of the stack, going to unwind..\n");
Marko Mikulicic 0:c0ecb8bf28eb 14283 #endif
Marko Mikulicic 0:c0ecb8bf28eb 14284 /* not reached bottom of the stack yet, keep unwinding */
Marko Mikulicic 0:c0ecb8bf28eb 14285 unwind_stack_1level(v7, r);
Marko Mikulicic 0:c0ecb8bf28eb 14286 } else {
Marko Mikulicic 0:c0ecb8bf28eb 14287 /* reached stack bottom: uncaught exception */
Marko Mikulicic 0:c0ecb8bf28eb 14288 #ifdef V7_BCODE_TRACE
Marko Mikulicic 0:c0ecb8bf28eb 14289 fprintf(stderr, "reached stack bottom: uncaught exception\n");
Marko Mikulicic 0:c0ecb8bf28eb 14290 #endif
Marko Mikulicic 0:c0ecb8bf28eb 14291 rcode = V7_EXEC_EXCEPTION;
Marko Mikulicic 0:c0ecb8bf28eb 14292 break;
Marko Mikulicic 0:c0ecb8bf28eb 14293 }
Marko Mikulicic 0:c0ecb8bf28eb 14294 }
Marko Mikulicic 0:c0ecb8bf28eb 14295
Marko Mikulicic 0:c0ecb8bf28eb 14296 if (found == LOCAL_BLOCK_CATCH) {
Marko Mikulicic 0:c0ecb8bf28eb 14297 /*
Marko Mikulicic 0:c0ecb8bf28eb 14298 * we're going to enter `catch` block, so, populate TOS with the thrown
Marko Mikulicic 0:c0ecb8bf28eb 14299 * value, and clear it in v7 context.
Marko Mikulicic 0:c0ecb8bf28eb 14300 */
Marko Mikulicic 0:c0ecb8bf28eb 14301 PUSH(v7->vals.thrown_error);
Marko Mikulicic 0:c0ecb8bf28eb 14302 v7->is_thrown = 0;
Marko Mikulicic 0:c0ecb8bf28eb 14303 v7->vals.thrown_error = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 14304 }
Marko Mikulicic 0:c0ecb8bf28eb 14305
Marko Mikulicic 0:c0ecb8bf28eb 14306 /* `ops` already points to the needed instruction, no need to increment it */
Marko Mikulicic 0:c0ecb8bf28eb 14307 r->need_inc_ops = 0;
Marko Mikulicic 0:c0ecb8bf28eb 14308
Marko Mikulicic 0:c0ecb8bf28eb 14309 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 14310 }
Marko Mikulicic 0:c0ecb8bf28eb 14311
Marko Mikulicic 0:c0ecb8bf28eb 14312 /*
Marko Mikulicic 0:c0ecb8bf28eb 14313 * Throws reference error from `eval_bcode()`. Always wrap a call to this
Marko Mikulicic 0:c0ecb8bf28eb 14314 * function into `V7_TRY()`.
Marko Mikulicic 0:c0ecb8bf28eb 14315 */
Marko Mikulicic 0:c0ecb8bf28eb 14316 static enum v7_err bcode_throw_reference_error(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 14317 struct bcode_registers *r,
Marko Mikulicic 0:c0ecb8bf28eb 14318 val_t var_name) {
Marko Mikulicic 0:c0ecb8bf28eb 14319 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 14320 const char *s;
Marko Mikulicic 0:c0ecb8bf28eb 14321 size_t name_len;
Marko Mikulicic 0:c0ecb8bf28eb 14322
Marko Mikulicic 0:c0ecb8bf28eb 14323 assert(v7_is_string(var_name));
Marko Mikulicic 0:c0ecb8bf28eb 14324 s = v7_get_string(v7, &var_name, &name_len);
Marko Mikulicic 0:c0ecb8bf28eb 14325
Marko Mikulicic 0:c0ecb8bf28eb 14326 rcode = v7_throwf(v7, REFERENCE_ERROR, "[%.*s] is not defined",
Marko Mikulicic 0:c0ecb8bf28eb 14327 (int) name_len, s);
Marko Mikulicic 0:c0ecb8bf28eb 14328 (void) rcode;
Marko Mikulicic 0:c0ecb8bf28eb 14329 return bcode_perform_throw(v7, r, 0);
Marko Mikulicic 0:c0ecb8bf28eb 14330 }
Marko Mikulicic 0:c0ecb8bf28eb 14331
Marko Mikulicic 0:c0ecb8bf28eb 14332 /*
Marko Mikulicic 0:c0ecb8bf28eb 14333 * Takes a half-done function (either from literal table or deserialized from
Marko Mikulicic 0:c0ecb8bf28eb 14334 * `ops` inlined data), and returns a ready-to-use function.
Marko Mikulicic 0:c0ecb8bf28eb 14335 *
Marko Mikulicic 0:c0ecb8bf28eb 14336 * The actual behaviour depends on whether the half-done function has
Marko Mikulicic 0:c0ecb8bf28eb 14337 * `prototype` defined. If there's no prototype (i.e. it's `undefined`), then
Marko Mikulicic 0:c0ecb8bf28eb 14338 * the new function is created, with bcode from a given one. If, however,
Marko Mikulicic 0:c0ecb8bf28eb 14339 * the prototype is defined, it means that the function was just deserialized
Marko Mikulicic 0:c0ecb8bf28eb 14340 * from `ops`, so we only need to set `scope` on it.
Marko Mikulicic 0:c0ecb8bf28eb 14341 *
Marko Mikulicic 0:c0ecb8bf28eb 14342 * Assumes `func` is owned by the caller.
Marko Mikulicic 0:c0ecb8bf28eb 14343 */
Marko Mikulicic 0:c0ecb8bf28eb 14344 static val_t bcode_instantiate_function(struct v7 *v7, val_t func) {
Marko Mikulicic 0:c0ecb8bf28eb 14345 val_t res;
Marko Mikulicic 0:c0ecb8bf28eb 14346 struct v7_generic_object *scope;
Marko Mikulicic 0:c0ecb8bf28eb 14347 struct v7_js_function *f;
Marko Mikulicic 0:c0ecb8bf28eb 14348 assert(is_js_function(func));
Marko Mikulicic 0:c0ecb8bf28eb 14349 f = get_js_function_struct(func);
Marko Mikulicic 0:c0ecb8bf28eb 14350
Marko Mikulicic 0:c0ecb8bf28eb 14351 scope = get_generic_object_struct(get_scope(v7));
Marko Mikulicic 0:c0ecb8bf28eb 14352
Marko Mikulicic 0:c0ecb8bf28eb 14353 if (v7_is_undefined(v7_get(v7, func, "prototype", 9))) {
Marko Mikulicic 0:c0ecb8bf28eb 14354 /*
Marko Mikulicic 0:c0ecb8bf28eb 14355 * Function's `prototype` is `undefined`: it means that the function is
Marko Mikulicic 0:c0ecb8bf28eb 14356 * created by the compiler and is stored in the literal table. We have to
Marko Mikulicic 0:c0ecb8bf28eb 14357 * create completely new function
Marko Mikulicic 0:c0ecb8bf28eb 14358 */
Marko Mikulicic 0:c0ecb8bf28eb 14359 struct v7_js_function *rf;
Marko Mikulicic 0:c0ecb8bf28eb 14360
Marko Mikulicic 0:c0ecb8bf28eb 14361 res = mk_js_function(v7, scope, v7_mk_object(v7));
Marko Mikulicic 0:c0ecb8bf28eb 14362
Marko Mikulicic 0:c0ecb8bf28eb 14363 /* Copy and retain bcode */
Marko Mikulicic 0:c0ecb8bf28eb 14364 rf = get_js_function_struct(res);
Marko Mikulicic 0:c0ecb8bf28eb 14365 rf->bcode = f->bcode;
Marko Mikulicic 0:c0ecb8bf28eb 14366 retain_bcode(v7, rf->bcode);
Marko Mikulicic 0:c0ecb8bf28eb 14367 } else {
Marko Mikulicic 0:c0ecb8bf28eb 14368 /*
Marko Mikulicic 0:c0ecb8bf28eb 14369 * Function's `prototype` is NOT `undefined`: it means that the function is
Marko Mikulicic 0:c0ecb8bf28eb 14370 * deserialized from inline `ops` data, and we just need to set scope on
Marko Mikulicic 0:c0ecb8bf28eb 14371 * it.
Marko Mikulicic 0:c0ecb8bf28eb 14372 */
Marko Mikulicic 0:c0ecb8bf28eb 14373 res = func;
Marko Mikulicic 0:c0ecb8bf28eb 14374 f->scope = scope;
Marko Mikulicic 0:c0ecb8bf28eb 14375 }
Marko Mikulicic 0:c0ecb8bf28eb 14376
Marko Mikulicic 0:c0ecb8bf28eb 14377 return res;
Marko Mikulicic 0:c0ecb8bf28eb 14378 }
Marko Mikulicic 0:c0ecb8bf28eb 14379
Marko Mikulicic 0:c0ecb8bf28eb 14380 /**
Marko Mikulicic 0:c0ecb8bf28eb 14381 * Call C function `func` with given `this_object` and array of arguments
Marko Mikulicic 0:c0ecb8bf28eb 14382 * `args`. `func` should be a C function pointer, not C function object.
Marko Mikulicic 0:c0ecb8bf28eb 14383 */
Marko Mikulicic 0:c0ecb8bf28eb 14384 static enum v7_err call_cfunction(struct v7 *v7, val_t func, val_t this_object,
Marko Mikulicic 0:c0ecb8bf28eb 14385 val_t args, uint8_t is_constructor,
Marko Mikulicic 0:c0ecb8bf28eb 14386 val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 14387 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 14388 uint8_t saved_inhibit_gc = v7->inhibit_gc;
Marko Mikulicic 0:c0ecb8bf28eb 14389 val_t saved_arguments = v7->vals.arguments;
Marko Mikulicic 0:c0ecb8bf28eb 14390 struct gc_tmp_frame tf = new_tmp_frame(v7);
Marko Mikulicic 0:c0ecb8bf28eb 14391 v7_cfunction_t *cfunc = get_cfunction_ptr(v7, func);
Marko Mikulicic 0:c0ecb8bf28eb 14392
Marko Mikulicic 0:c0ecb8bf28eb 14393 *res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 14394
Marko Mikulicic 0:c0ecb8bf28eb 14395 tmp_stack_push(&tf, &saved_arguments);
Marko Mikulicic 0:c0ecb8bf28eb 14396
Marko Mikulicic 0:c0ecb8bf28eb 14397 append_call_frame_cfunc(v7, this_object, cfunc);
Marko Mikulicic 0:c0ecb8bf28eb 14398
Marko Mikulicic 0:c0ecb8bf28eb 14399 /*
Marko Mikulicic 0:c0ecb8bf28eb 14400 * prepare cfunction environment
Marko Mikulicic 0:c0ecb8bf28eb 14401 */
Marko Mikulicic 0:c0ecb8bf28eb 14402 v7->inhibit_gc = 1;
Marko Mikulicic 0:c0ecb8bf28eb 14403 v7->vals.arguments = args;
Marko Mikulicic 0:c0ecb8bf28eb 14404
Marko Mikulicic 0:c0ecb8bf28eb 14405 /* call C function */
Marko Mikulicic 0:c0ecb8bf28eb 14406 rcode = cfunc(v7, res);
Marko Mikulicic 0:c0ecb8bf28eb 14407 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 14408 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 14409 }
Marko Mikulicic 0:c0ecb8bf28eb 14410
Marko Mikulicic 0:c0ecb8bf28eb 14411 if (is_constructor && !v7_is_object(*res)) {
Marko Mikulicic 0:c0ecb8bf28eb 14412 /* constructor returned non-object: replace it with `this` */
Marko Mikulicic 0:c0ecb8bf28eb 14413 *res = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 14414 }
Marko Mikulicic 0:c0ecb8bf28eb 14415
Marko Mikulicic 0:c0ecb8bf28eb 14416 clean:
Marko Mikulicic 0:c0ecb8bf28eb 14417 v7->vals.arguments = saved_arguments;
Marko Mikulicic 0:c0ecb8bf28eb 14418 v7->inhibit_gc = saved_inhibit_gc;
Marko Mikulicic 0:c0ecb8bf28eb 14419
Marko Mikulicic 0:c0ecb8bf28eb 14420 unwind_stack_1level(v7, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 14421
Marko Mikulicic 0:c0ecb8bf28eb 14422 tmp_frame_cleanup(&tf);
Marko Mikulicic 0:c0ecb8bf28eb 14423 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 14424 }
Marko Mikulicic 0:c0ecb8bf28eb 14425
Marko Mikulicic 0:c0ecb8bf28eb 14426 /*
Marko Mikulicic 0:c0ecb8bf28eb 14427 * Evaluate `OP_TRY_PUSH_CATCH` or `OP_TRY_PUSH_FINALLY`: Take an offset (from
Marko Mikulicic 0:c0ecb8bf28eb 14428 * the parameter of opcode) and push it onto "try stack"
Marko Mikulicic 0:c0ecb8bf28eb 14429 */
Marko Mikulicic 0:c0ecb8bf28eb 14430 static void eval_try_push(struct v7 *v7, enum opcode op,
Marko Mikulicic 0:c0ecb8bf28eb 14431 struct bcode_registers *r) {
Marko Mikulicic 0:c0ecb8bf28eb 14432 val_t arr = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 14433 struct gc_tmp_frame tf = new_tmp_frame(v7);
Marko Mikulicic 0:c0ecb8bf28eb 14434 bcode_off_t target;
Marko Mikulicic 0:c0ecb8bf28eb 14435 int64_t offset_tag = 0;
Marko Mikulicic 0:c0ecb8bf28eb 14436
Marko Mikulicic 0:c0ecb8bf28eb 14437 tmp_stack_push(&tf, &arr);
Marko Mikulicic 0:c0ecb8bf28eb 14438
Marko Mikulicic 0:c0ecb8bf28eb 14439 /* make sure "try stack" array exists */
Marko Mikulicic 0:c0ecb8bf28eb 14440 arr = find_call_frame_private(v7)->vals.try_stack;
Marko Mikulicic 0:c0ecb8bf28eb 14441 if (!v7_is_array(v7, arr)) {
Marko Mikulicic 0:c0ecb8bf28eb 14442 arr = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 14443 find_call_frame_private(v7)->vals.try_stack = arr;
Marko Mikulicic 0:c0ecb8bf28eb 14444 }
Marko Mikulicic 0:c0ecb8bf28eb 14445
Marko Mikulicic 0:c0ecb8bf28eb 14446 /*
Marko Mikulicic 0:c0ecb8bf28eb 14447 * push the target address at the end of the "try stack" array
Marko Mikulicic 0:c0ecb8bf28eb 14448 */
Marko Mikulicic 0:c0ecb8bf28eb 14449 switch (op) {
Marko Mikulicic 0:c0ecb8bf28eb 14450 case OP_TRY_PUSH_CATCH:
Marko Mikulicic 0:c0ecb8bf28eb 14451 offset_tag = LBLOCK_TAG_CATCH;
Marko Mikulicic 0:c0ecb8bf28eb 14452 break;
Marko Mikulicic 0:c0ecb8bf28eb 14453 case OP_TRY_PUSH_FINALLY:
Marko Mikulicic 0:c0ecb8bf28eb 14454 offset_tag = LBLOCK_TAG_FINALLY;
Marko Mikulicic 0:c0ecb8bf28eb 14455 break;
Marko Mikulicic 0:c0ecb8bf28eb 14456 case OP_TRY_PUSH_LOOP:
Marko Mikulicic 0:c0ecb8bf28eb 14457 offset_tag = LBLOCK_TAG_LOOP;
Marko Mikulicic 0:c0ecb8bf28eb 14458 break;
Marko Mikulicic 0:c0ecb8bf28eb 14459 case OP_TRY_PUSH_SWITCH:
Marko Mikulicic 0:c0ecb8bf28eb 14460 offset_tag = LBLOCK_TAG_SWITCH;
Marko Mikulicic 0:c0ecb8bf28eb 14461 break;
Marko Mikulicic 0:c0ecb8bf28eb 14462 default:
Marko Mikulicic 0:c0ecb8bf28eb 14463 assert(0);
Marko Mikulicic 0:c0ecb8bf28eb 14464 break;
Marko Mikulicic 0:c0ecb8bf28eb 14465 }
Marko Mikulicic 0:c0ecb8bf28eb 14466 target = bcode_get_target(&r->ops);
Marko Mikulicic 0:c0ecb8bf28eb 14467 v7_array_push(v7, arr, v7_mk_number(v7, LBLOCK_ITEM_CREATE(target, offset_tag,
Marko Mikulicic 0:c0ecb8bf28eb 14468 v7->stack.len)));
Marko Mikulicic 0:c0ecb8bf28eb 14469
Marko Mikulicic 0:c0ecb8bf28eb 14470 tmp_frame_cleanup(&tf);
Marko Mikulicic 0:c0ecb8bf28eb 14471 }
Marko Mikulicic 0:c0ecb8bf28eb 14472
Marko Mikulicic 0:c0ecb8bf28eb 14473 /*
Marko Mikulicic 0:c0ecb8bf28eb 14474 * Evaluate `OP_TRY_POP`: just pop latest item from "try stack", ignoring it
Marko Mikulicic 0:c0ecb8bf28eb 14475 */
Marko Mikulicic 0:c0ecb8bf28eb 14476 static enum v7_err eval_try_pop(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 14477 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 14478 val_t arr = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 14479 unsigned long length;
Marko Mikulicic 0:c0ecb8bf28eb 14480 struct gc_tmp_frame tf = new_tmp_frame(v7);
Marko Mikulicic 0:c0ecb8bf28eb 14481
Marko Mikulicic 0:c0ecb8bf28eb 14482 tmp_stack_push(&tf, &arr);
Marko Mikulicic 0:c0ecb8bf28eb 14483
Marko Mikulicic 0:c0ecb8bf28eb 14484 /* get "try stack" array, which must be defined and must not be emtpy */
Marko Mikulicic 0:c0ecb8bf28eb 14485 arr = find_call_frame_private(v7)->vals.try_stack;
Marko Mikulicic 0:c0ecb8bf28eb 14486 if (!v7_is_array(v7, arr)) {
Marko Mikulicic 0:c0ecb8bf28eb 14487 rcode = v7_throwf(v7, "Error", "TRY_POP when try_stack is not an array");
Marko Mikulicic 0:c0ecb8bf28eb 14488 V7_TRY(V7_INTERNAL_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 14489 }
Marko Mikulicic 0:c0ecb8bf28eb 14490
Marko Mikulicic 0:c0ecb8bf28eb 14491 length = v7_array_length(v7, arr);
Marko Mikulicic 0:c0ecb8bf28eb 14492 if (length == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 14493 rcode = v7_throwf(v7, "Error", "TRY_POP when try_stack is empty");
Marko Mikulicic 0:c0ecb8bf28eb 14494 V7_TRY(V7_INTERNAL_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 14495 }
Marko Mikulicic 0:c0ecb8bf28eb 14496
Marko Mikulicic 0:c0ecb8bf28eb 14497 /* delete the latest element of this array */
Marko Mikulicic 0:c0ecb8bf28eb 14498 v7_array_del(v7, arr, length - 1);
Marko Mikulicic 0:c0ecb8bf28eb 14499
Marko Mikulicic 0:c0ecb8bf28eb 14500 clean:
Marko Mikulicic 0:c0ecb8bf28eb 14501 tmp_frame_cleanup(&tf);
Marko Mikulicic 0:c0ecb8bf28eb 14502 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 14503 }
Marko Mikulicic 0:c0ecb8bf28eb 14504
Marko Mikulicic 0:c0ecb8bf28eb 14505 static void own_bcode(struct v7 *v7, struct bcode *p) {
Marko Mikulicic 0:c0ecb8bf28eb 14506 mbuf_append(&v7->act_bcodes, &p, sizeof(p));
Marko Mikulicic 0:c0ecb8bf28eb 14507 }
Marko Mikulicic 0:c0ecb8bf28eb 14508
Marko Mikulicic 0:c0ecb8bf28eb 14509 static void disown_bcode(struct v7 *v7, struct bcode *p) {
Marko Mikulicic 0:c0ecb8bf28eb 14510 #ifndef NDEBUG
Marko Mikulicic 0:c0ecb8bf28eb 14511 struct bcode **vp =
Marko Mikulicic 0:c0ecb8bf28eb 14512 (struct bcode **) (v7->act_bcodes.buf + v7->act_bcodes.len - sizeof(p));
Marko Mikulicic 0:c0ecb8bf28eb 14513
Marko Mikulicic 0:c0ecb8bf28eb 14514 /* given `p` should be the last item */
Marko Mikulicic 0:c0ecb8bf28eb 14515 assert(*vp == p);
Marko Mikulicic 0:c0ecb8bf28eb 14516 #endif
Marko Mikulicic 0:c0ecb8bf28eb 14517 v7->act_bcodes.len -= sizeof(p);
Marko Mikulicic 0:c0ecb8bf28eb 14518 }
Marko Mikulicic 0:c0ecb8bf28eb 14519
Marko Mikulicic 0:c0ecb8bf28eb 14520 /* Keeps track of last evaluated bcodes in order to improve error reporting */
Marko Mikulicic 0:c0ecb8bf28eb 14521 static void push_bcode_history(struct v7 *v7, enum opcode op) {
Marko Mikulicic 0:c0ecb8bf28eb 14522 size_t i;
Marko Mikulicic 0:c0ecb8bf28eb 14523
Marko Mikulicic 0:c0ecb8bf28eb 14524 if (op == OP_CHECK_CALL || op == OP_CALL || op == OP_NEW) return;
Marko Mikulicic 0:c0ecb8bf28eb 14525
Marko Mikulicic 0:c0ecb8bf28eb 14526 for (i = ARRAY_SIZE(v7->last_ops) - 1; i > 0; i--) {
Marko Mikulicic 0:c0ecb8bf28eb 14527 v7->last_ops[i] = v7->last_ops[i - 1];
Marko Mikulicic 0:c0ecb8bf28eb 14528 }
Marko Mikulicic 0:c0ecb8bf28eb 14529 v7->last_ops[0] = op;
Marko Mikulicic 0:c0ecb8bf28eb 14530 }
Marko Mikulicic 0:c0ecb8bf28eb 14531
Marko Mikulicic 0:c0ecb8bf28eb 14532 #ifndef V7_DISABLE_CALL_ERROR_CONTEXT
Marko Mikulicic 0:c0ecb8bf28eb 14533 static void reset_last_name(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 14534 v7->vals.last_name[0] = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 14535 v7->vals.last_name[1] = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 14536 }
Marko Mikulicic 0:c0ecb8bf28eb 14537 #else
Marko Mikulicic 0:c0ecb8bf28eb 14538 static void reset_last_name(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 14539 /* should be inlined out */
Marko Mikulicic 0:c0ecb8bf28eb 14540 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 14541 }
Marko Mikulicic 0:c0ecb8bf28eb 14542 #endif
Marko Mikulicic 0:c0ecb8bf28eb 14543
Marko Mikulicic 0:c0ecb8bf28eb 14544 static void prop_iter_ctx_dtor(struct v7 *v7, void *ud) {
Marko Mikulicic 0:c0ecb8bf28eb 14545 struct prop_iter_ctx *ctx = (struct prop_iter_ctx *) ud;
Marko Mikulicic 0:c0ecb8bf28eb 14546 v7_destruct_prop_iter_ctx(v7, ctx);
Marko Mikulicic 0:c0ecb8bf28eb 14547 free(ctx);
Marko Mikulicic 0:c0ecb8bf28eb 14548 }
Marko Mikulicic 0:c0ecb8bf28eb 14549
Marko Mikulicic 0:c0ecb8bf28eb 14550 /*
Marko Mikulicic 0:c0ecb8bf28eb 14551 * Evaluates given `bcode`. If `reset_line_no` is non-zero, the line number
Marko Mikulicic 0:c0ecb8bf28eb 14552 * is initially reset to 1; otherwise, it is inherited from the previous call
Marko Mikulicic 0:c0ecb8bf28eb 14553 * frame.
Marko Mikulicic 0:c0ecb8bf28eb 14554 */
Marko Mikulicic 0:c0ecb8bf28eb 14555 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 14556 V7_PRIVATE enum v7_err eval_bcode(struct v7 *v7, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 14557 val_t this_object, uint8_t reset_line_no,
Marko Mikulicic 0:c0ecb8bf28eb 14558 val_t *_res) {
Marko Mikulicic 0:c0ecb8bf28eb 14559 struct bcode_registers r;
Marko Mikulicic 0:c0ecb8bf28eb 14560 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 14561 struct v7_call_frame_base *saved_bottom_call_frame = v7->bottom_call_frame;
Marko Mikulicic 0:c0ecb8bf28eb 14562
Marko Mikulicic 0:c0ecb8bf28eb 14563 /*
Marko Mikulicic 0:c0ecb8bf28eb 14564 * Dummy variable just to enforce that `BTRY()` macro is used only inside the
Marko Mikulicic 0:c0ecb8bf28eb 14565 * `eval_bcode()` function
Marko Mikulicic 0:c0ecb8bf28eb 14566 */
Marko Mikulicic 0:c0ecb8bf28eb 14567 uint8_t _you_should_use_BTRY_in_eval_bcode_only = 0;
Marko Mikulicic 0:c0ecb8bf28eb 14568
Marko Mikulicic 0:c0ecb8bf28eb 14569 char buf[512];
Marko Mikulicic 0:c0ecb8bf28eb 14570
Marko Mikulicic 0:c0ecb8bf28eb 14571 val_t res = V7_UNDEFINED, v1 = V7_UNDEFINED, v2 = V7_UNDEFINED,
Marko Mikulicic 0:c0ecb8bf28eb 14572 v3 = V7_UNDEFINED, v4 = V7_UNDEFINED, scope_frame = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 14573 struct gc_tmp_frame tf = new_tmp_frame(v7);
Marko Mikulicic 0:c0ecb8bf28eb 14574
Marko Mikulicic 0:c0ecb8bf28eb 14575 append_call_frame_bcode(v7, NULL, bcode, this_object, get_scope(v7), 0);
Marko Mikulicic 0:c0ecb8bf28eb 14576
Marko Mikulicic 0:c0ecb8bf28eb 14577 if (reset_line_no) {
Marko Mikulicic 0:c0ecb8bf28eb 14578 v7->call_stack->line_no = 1;
Marko Mikulicic 0:c0ecb8bf28eb 14579 }
Marko Mikulicic 0:c0ecb8bf28eb 14580
Marko Mikulicic 0:c0ecb8bf28eb 14581 /*
Marko Mikulicic 0:c0ecb8bf28eb 14582 * Set current call stack as the "bottom" call stack, so that bcode evaluator
Marko Mikulicic 0:c0ecb8bf28eb 14583 * will exit when it reaches this "bottom"
Marko Mikulicic 0:c0ecb8bf28eb 14584 */
Marko Mikulicic 0:c0ecb8bf28eb 14585 v7->bottom_call_frame = v7->call_stack;
Marko Mikulicic 0:c0ecb8bf28eb 14586
Marko Mikulicic 0:c0ecb8bf28eb 14587 bcode_restore_registers(v7, bcode, &r);
Marko Mikulicic 0:c0ecb8bf28eb 14588
Marko Mikulicic 0:c0ecb8bf28eb 14589 tmp_stack_push(&tf, &res);
Marko Mikulicic 0:c0ecb8bf28eb 14590 tmp_stack_push(&tf, &v1);
Marko Mikulicic 0:c0ecb8bf28eb 14591 tmp_stack_push(&tf, &v2);
Marko Mikulicic 0:c0ecb8bf28eb 14592 tmp_stack_push(&tf, &v3);
Marko Mikulicic 0:c0ecb8bf28eb 14593 tmp_stack_push(&tf, &v4);
Marko Mikulicic 0:c0ecb8bf28eb 14594 tmp_stack_push(&tf, &scope_frame);
Marko Mikulicic 0:c0ecb8bf28eb 14595
Marko Mikulicic 0:c0ecb8bf28eb 14596 /*
Marko Mikulicic 0:c0ecb8bf28eb 14597 * populate local variables on current scope, making them undeletable
Marko Mikulicic 0:c0ecb8bf28eb 14598 * (since they're defined with `var`)
Marko Mikulicic 0:c0ecb8bf28eb 14599 */
Marko Mikulicic 0:c0ecb8bf28eb 14600 {
Marko Mikulicic 0:c0ecb8bf28eb 14601 size_t i;
Marko Mikulicic 0:c0ecb8bf28eb 14602 for (i = 0; i < bcode->names_cnt; ++i) {
Marko Mikulicic 0:c0ecb8bf28eb 14603 r.ops = bcode_next_name_v(v7, bcode, r.ops, &v1);
Marko Mikulicic 0:c0ecb8bf28eb 14604
Marko Mikulicic 0:c0ecb8bf28eb 14605 /* set undeletable property on current scope */
Marko Mikulicic 0:c0ecb8bf28eb 14606 V7_TRY(def_property_v(v7, get_scope(v7), v1, V7_DESC_CONFIGURABLE(0),
Marko Mikulicic 0:c0ecb8bf28eb 14607 V7_UNDEFINED, 1 /*as_assign*/, NULL));
Marko Mikulicic 0:c0ecb8bf28eb 14608 }
Marko Mikulicic 0:c0ecb8bf28eb 14609 }
Marko Mikulicic 0:c0ecb8bf28eb 14610
Marko Mikulicic 0:c0ecb8bf28eb 14611 restart:
Marko Mikulicic 0:c0ecb8bf28eb 14612 while (r.ops < r.end && rcode == V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 14613 enum opcode op = (enum opcode) * r.ops;
Marko Mikulicic 0:c0ecb8bf28eb 14614
Marko Mikulicic 0:c0ecb8bf28eb 14615 #ifndef V7_DISABLE_LINE_NUMBERS
Marko Mikulicic 0:c0ecb8bf28eb 14616 if ((uint8_t) op >= _OP_LINE_NO) {
Marko Mikulicic 0:c0ecb8bf28eb 14617 unsigned char buf[sizeof(size_t)];
Marko Mikulicic 0:c0ecb8bf28eb 14618 int len;
Marko Mikulicic 0:c0ecb8bf28eb 14619 size_t max_llen = sizeof(buf);
Marko Mikulicic 0:c0ecb8bf28eb 14620
Marko Mikulicic 0:c0ecb8bf28eb 14621 /* ASAN doesn't like out of bound reads */
Marko Mikulicic 0:c0ecb8bf28eb 14622 if (r.ops + max_llen > r.end) {
Marko Mikulicic 0:c0ecb8bf28eb 14623 max_llen = r.end - r.ops;
Marko Mikulicic 0:c0ecb8bf28eb 14624 }
Marko Mikulicic 0:c0ecb8bf28eb 14625
Marko Mikulicic 0:c0ecb8bf28eb 14626 /*
Marko Mikulicic 0:c0ecb8bf28eb 14627 * before we decode varint, we'll have to swap MSB and LSB, but we can't
Marko Mikulicic 0:c0ecb8bf28eb 14628 * do it in place since we're decoding from constant memory, so, we also
Marko Mikulicic 0:c0ecb8bf28eb 14629 * have to copy the data to the temp buffer first. 4 bytes should be
Marko Mikulicic 0:c0ecb8bf28eb 14630 * enough for everyone's line number.
Marko Mikulicic 0:c0ecb8bf28eb 14631 */
Marko Mikulicic 0:c0ecb8bf28eb 14632 memcpy(buf, r.ops, max_llen);
Marko Mikulicic 0:c0ecb8bf28eb 14633 buf[0] = msb_lsb_swap(buf[0]);
Marko Mikulicic 0:c0ecb8bf28eb 14634
Marko Mikulicic 0:c0ecb8bf28eb 14635 v7->call_stack->line_no = decode_varint(buf, &len) >> 1;
Marko Mikulicic 0:c0ecb8bf28eb 14636 assert((size_t) len <= sizeof(buf));
Marko Mikulicic 0:c0ecb8bf28eb 14637 r.ops += len;
Marko Mikulicic 0:c0ecb8bf28eb 14638
Marko Mikulicic 0:c0ecb8bf28eb 14639 continue;
Marko Mikulicic 0:c0ecb8bf28eb 14640 }
Marko Mikulicic 0:c0ecb8bf28eb 14641 #endif
Marko Mikulicic 0:c0ecb8bf28eb 14642
Marko Mikulicic 0:c0ecb8bf28eb 14643 push_bcode_history(v7, op);
Marko Mikulicic 0:c0ecb8bf28eb 14644
Marko Mikulicic 0:c0ecb8bf28eb 14645 if (v7->need_gc) {
Marko Mikulicic 0:c0ecb8bf28eb 14646 if (maybe_gc(v7)) {
Marko Mikulicic 0:c0ecb8bf28eb 14647 v7->need_gc = 0;
Marko Mikulicic 0:c0ecb8bf28eb 14648 }
Marko Mikulicic 0:c0ecb8bf28eb 14649 }
Marko Mikulicic 0:c0ecb8bf28eb 14650
Marko Mikulicic 0:c0ecb8bf28eb 14651 r.need_inc_ops = 1;
Marko Mikulicic 0:c0ecb8bf28eb 14652 #ifdef V7_BCODE_TRACE
Marko Mikulicic 0:c0ecb8bf28eb 14653 {
Marko Mikulicic 0:c0ecb8bf28eb 14654 char *dops = r.ops;
Marko Mikulicic 0:c0ecb8bf28eb 14655 fprintf(stderr, "eval ");
Marko Mikulicic 0:c0ecb8bf28eb 14656 dump_op(v7, stderr, r.bcode, &dops);
Marko Mikulicic 0:c0ecb8bf28eb 14657 }
Marko Mikulicic 0:c0ecb8bf28eb 14658 #endif
Marko Mikulicic 0:c0ecb8bf28eb 14659
Marko Mikulicic 0:c0ecb8bf28eb 14660 switch (op) {
Marko Mikulicic 0:c0ecb8bf28eb 14661 case OP_DROP:
Marko Mikulicic 0:c0ecb8bf28eb 14662 POP();
Marko Mikulicic 0:c0ecb8bf28eb 14663 break;
Marko Mikulicic 0:c0ecb8bf28eb 14664 case OP_DUP:
Marko Mikulicic 0:c0ecb8bf28eb 14665 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14666 PUSH(v1);
Marko Mikulicic 0:c0ecb8bf28eb 14667 PUSH(v1);
Marko Mikulicic 0:c0ecb8bf28eb 14668 break;
Marko Mikulicic 0:c0ecb8bf28eb 14669 case OP_2DUP:
Marko Mikulicic 0:c0ecb8bf28eb 14670 v2 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14671 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14672 PUSH(v1);
Marko Mikulicic 0:c0ecb8bf28eb 14673 PUSH(v2);
Marko Mikulicic 0:c0ecb8bf28eb 14674 PUSH(v1);
Marko Mikulicic 0:c0ecb8bf28eb 14675 PUSH(v2);
Marko Mikulicic 0:c0ecb8bf28eb 14676 break;
Marko Mikulicic 0:c0ecb8bf28eb 14677 case OP_SWAP:
Marko Mikulicic 0:c0ecb8bf28eb 14678 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14679 v2 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14680 PUSH(v1);
Marko Mikulicic 0:c0ecb8bf28eb 14681 PUSH(v2);
Marko Mikulicic 0:c0ecb8bf28eb 14682 break;
Marko Mikulicic 0:c0ecb8bf28eb 14683 case OP_STASH:
Marko Mikulicic 0:c0ecb8bf28eb 14684 assert(!v7->is_stashed);
Marko Mikulicic 0:c0ecb8bf28eb 14685 v7->vals.stash = TOS();
Marko Mikulicic 0:c0ecb8bf28eb 14686 v7->is_stashed = 1;
Marko Mikulicic 0:c0ecb8bf28eb 14687 break;
Marko Mikulicic 0:c0ecb8bf28eb 14688 case OP_UNSTASH:
Marko Mikulicic 0:c0ecb8bf28eb 14689 assert(v7->is_stashed);
Marko Mikulicic 0:c0ecb8bf28eb 14690 POP();
Marko Mikulicic 0:c0ecb8bf28eb 14691 PUSH(v7->vals.stash);
Marko Mikulicic 0:c0ecb8bf28eb 14692 v7->vals.stash = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 14693 v7->is_stashed = 0;
Marko Mikulicic 0:c0ecb8bf28eb 14694 break;
Marko Mikulicic 0:c0ecb8bf28eb 14695
Marko Mikulicic 0:c0ecb8bf28eb 14696 case OP_SWAP_DROP:
Marko Mikulicic 0:c0ecb8bf28eb 14697 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14698 POP();
Marko Mikulicic 0:c0ecb8bf28eb 14699 PUSH(v1);
Marko Mikulicic 0:c0ecb8bf28eb 14700 break;
Marko Mikulicic 0:c0ecb8bf28eb 14701
Marko Mikulicic 0:c0ecb8bf28eb 14702 case OP_PUSH_UNDEFINED:
Marko Mikulicic 0:c0ecb8bf28eb 14703 PUSH(V7_UNDEFINED);
Marko Mikulicic 0:c0ecb8bf28eb 14704 break;
Marko Mikulicic 0:c0ecb8bf28eb 14705 case OP_PUSH_NULL:
Marko Mikulicic 0:c0ecb8bf28eb 14706 PUSH(V7_NULL);
Marko Mikulicic 0:c0ecb8bf28eb 14707 break;
Marko Mikulicic 0:c0ecb8bf28eb 14708 case OP_PUSH_THIS:
Marko Mikulicic 0:c0ecb8bf28eb 14709 PUSH(v7_get_this(v7));
Marko Mikulicic 0:c0ecb8bf28eb 14710 reset_last_name(v7);
Marko Mikulicic 0:c0ecb8bf28eb 14711 break;
Marko Mikulicic 0:c0ecb8bf28eb 14712 case OP_PUSH_TRUE:
Marko Mikulicic 0:c0ecb8bf28eb 14713 PUSH(v7_mk_boolean(v7, 1));
Marko Mikulicic 0:c0ecb8bf28eb 14714 reset_last_name(v7);
Marko Mikulicic 0:c0ecb8bf28eb 14715 break;
Marko Mikulicic 0:c0ecb8bf28eb 14716 case OP_PUSH_FALSE:
Marko Mikulicic 0:c0ecb8bf28eb 14717 PUSH(v7_mk_boolean(v7, 0));
Marko Mikulicic 0:c0ecb8bf28eb 14718 reset_last_name(v7);
Marko Mikulicic 0:c0ecb8bf28eb 14719 break;
Marko Mikulicic 0:c0ecb8bf28eb 14720 case OP_PUSH_ZERO:
Marko Mikulicic 0:c0ecb8bf28eb 14721 PUSH(v7_mk_number(v7, 0));
Marko Mikulicic 0:c0ecb8bf28eb 14722 reset_last_name(v7);
Marko Mikulicic 0:c0ecb8bf28eb 14723 break;
Marko Mikulicic 0:c0ecb8bf28eb 14724 case OP_PUSH_ONE:
Marko Mikulicic 0:c0ecb8bf28eb 14725 PUSH(v7_mk_number(v7, 1));
Marko Mikulicic 0:c0ecb8bf28eb 14726 reset_last_name(v7);
Marko Mikulicic 0:c0ecb8bf28eb 14727 break;
Marko Mikulicic 0:c0ecb8bf28eb 14728 case OP_PUSH_LIT: {
Marko Mikulicic 0:c0ecb8bf28eb 14729 PUSH(bcode_decode_lit(v7, r.bcode, &r.ops));
Marko Mikulicic 0:c0ecb8bf28eb 14730 #ifndef V7_DISABLE_CALL_ERROR_CONTEXT
Marko Mikulicic 0:c0ecb8bf28eb 14731 /* name tracking */
Marko Mikulicic 0:c0ecb8bf28eb 14732 if (!v7_is_string(TOS())) {
Marko Mikulicic 0:c0ecb8bf28eb 14733 reset_last_name(v7);
Marko Mikulicic 0:c0ecb8bf28eb 14734 }
Marko Mikulicic 0:c0ecb8bf28eb 14735 #endif
Marko Mikulicic 0:c0ecb8bf28eb 14736 break;
Marko Mikulicic 0:c0ecb8bf28eb 14737 }
Marko Mikulicic 0:c0ecb8bf28eb 14738 case OP_LOGICAL_NOT:
Marko Mikulicic 0:c0ecb8bf28eb 14739 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14740 PUSH(v7_mk_boolean(v7, !v7_is_truthy(v7, v1)));
Marko Mikulicic 0:c0ecb8bf28eb 14741 break;
Marko Mikulicic 0:c0ecb8bf28eb 14742 case OP_NOT: {
Marko Mikulicic 0:c0ecb8bf28eb 14743 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14744 BTRY(to_number_v(v7, v1, &v1));
Marko Mikulicic 0:c0ecb8bf28eb 14745 PUSH(v7_mk_number(v7, ~(int32_t) v7_get_double(v7, v1)));
Marko Mikulicic 0:c0ecb8bf28eb 14746 break;
Marko Mikulicic 0:c0ecb8bf28eb 14747 }
Marko Mikulicic 0:c0ecb8bf28eb 14748 case OP_NEG: {
Marko Mikulicic 0:c0ecb8bf28eb 14749 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14750 BTRY(to_number_v(v7, v1, &v1));
Marko Mikulicic 0:c0ecb8bf28eb 14751 PUSH(v7_mk_number(v7, -v7_get_double(v7, v1)));
Marko Mikulicic 0:c0ecb8bf28eb 14752 break;
Marko Mikulicic 0:c0ecb8bf28eb 14753 }
Marko Mikulicic 0:c0ecb8bf28eb 14754 case OP_POS: {
Marko Mikulicic 0:c0ecb8bf28eb 14755 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14756 BTRY(to_number_v(v7, v1, &v1));
Marko Mikulicic 0:c0ecb8bf28eb 14757 PUSH(v1);
Marko Mikulicic 0:c0ecb8bf28eb 14758 break;
Marko Mikulicic 0:c0ecb8bf28eb 14759 }
Marko Mikulicic 0:c0ecb8bf28eb 14760 case OP_ADD: {
Marko Mikulicic 0:c0ecb8bf28eb 14761 v2 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14762 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14763
Marko Mikulicic 0:c0ecb8bf28eb 14764 /*
Marko Mikulicic 0:c0ecb8bf28eb 14765 * If either operand is an object, convert both of them to primitives
Marko Mikulicic 0:c0ecb8bf28eb 14766 */
Marko Mikulicic 0:c0ecb8bf28eb 14767 if (v7_is_object(v1) || v7_is_object(v2)) {
Marko Mikulicic 0:c0ecb8bf28eb 14768 BTRY(to_primitive(v7, v1, V7_TO_PRIMITIVE_HINT_AUTO, &v1));
Marko Mikulicic 0:c0ecb8bf28eb 14769 BTRY(to_primitive(v7, v2, V7_TO_PRIMITIVE_HINT_AUTO, &v2));
Marko Mikulicic 0:c0ecb8bf28eb 14770 }
Marko Mikulicic 0:c0ecb8bf28eb 14771
Marko Mikulicic 0:c0ecb8bf28eb 14772 if (v7_is_string(v1) || v7_is_string(v2)) {
Marko Mikulicic 0:c0ecb8bf28eb 14773 /* Convert both operands to strings, and concatenate */
Marko Mikulicic 0:c0ecb8bf28eb 14774
Marko Mikulicic 0:c0ecb8bf28eb 14775 BTRY(primitive_to_str(v7, v1, &v1, NULL, 0, NULL));
Marko Mikulicic 0:c0ecb8bf28eb 14776 BTRY(primitive_to_str(v7, v2, &v2, NULL, 0, NULL));
Marko Mikulicic 0:c0ecb8bf28eb 14777
Marko Mikulicic 0:c0ecb8bf28eb 14778 PUSH(s_concat(v7, v1, v2));
Marko Mikulicic 0:c0ecb8bf28eb 14779 } else {
Marko Mikulicic 0:c0ecb8bf28eb 14780 /* Convert both operands to numbers, and sum */
Marko Mikulicic 0:c0ecb8bf28eb 14781
Marko Mikulicic 0:c0ecb8bf28eb 14782 BTRY(primitive_to_number(v7, v1, &v1));
Marko Mikulicic 0:c0ecb8bf28eb 14783 BTRY(primitive_to_number(v7, v2, &v2));
Marko Mikulicic 0:c0ecb8bf28eb 14784
Marko Mikulicic 0:c0ecb8bf28eb 14785 PUSH(v7_mk_number(v7, b_num_bin_op(op, v7_get_double(v7, v1),
Marko Mikulicic 0:c0ecb8bf28eb 14786 v7_get_double(v7, v2))));
Marko Mikulicic 0:c0ecb8bf28eb 14787 }
Marko Mikulicic 0:c0ecb8bf28eb 14788 break;
Marko Mikulicic 0:c0ecb8bf28eb 14789 }
Marko Mikulicic 0:c0ecb8bf28eb 14790 case OP_SUB:
Marko Mikulicic 0:c0ecb8bf28eb 14791 case OP_REM:
Marko Mikulicic 0:c0ecb8bf28eb 14792 case OP_MUL:
Marko Mikulicic 0:c0ecb8bf28eb 14793 case OP_DIV:
Marko Mikulicic 0:c0ecb8bf28eb 14794 case OP_LSHIFT:
Marko Mikulicic 0:c0ecb8bf28eb 14795 case OP_RSHIFT:
Marko Mikulicic 0:c0ecb8bf28eb 14796 case OP_URSHIFT:
Marko Mikulicic 0:c0ecb8bf28eb 14797 case OP_OR:
Marko Mikulicic 0:c0ecb8bf28eb 14798 case OP_XOR:
Marko Mikulicic 0:c0ecb8bf28eb 14799 case OP_AND: {
Marko Mikulicic 0:c0ecb8bf28eb 14800 v2 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14801 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14802
Marko Mikulicic 0:c0ecb8bf28eb 14803 BTRY(to_number_v(v7, v1, &v1));
Marko Mikulicic 0:c0ecb8bf28eb 14804 BTRY(to_number_v(v7, v2, &v2));
Marko Mikulicic 0:c0ecb8bf28eb 14805
Marko Mikulicic 0:c0ecb8bf28eb 14806 PUSH(v7_mk_number(v7, b_num_bin_op(op, v7_get_double(v7, v1),
Marko Mikulicic 0:c0ecb8bf28eb 14807 v7_get_double(v7, v2))));
Marko Mikulicic 0:c0ecb8bf28eb 14808 break;
Marko Mikulicic 0:c0ecb8bf28eb 14809 }
Marko Mikulicic 0:c0ecb8bf28eb 14810 case OP_EQ_EQ: {
Marko Mikulicic 0:c0ecb8bf28eb 14811 v2 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14812 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14813 if (v7_is_string(v1) && v7_is_string(v2)) {
Marko Mikulicic 0:c0ecb8bf28eb 14814 res = v7_mk_boolean(v7, s_cmp(v7, v1, v2) == 0);
Marko Mikulicic 0:c0ecb8bf28eb 14815 } else if (v1 == v2 && v1 == V7_TAG_NAN) {
Marko Mikulicic 0:c0ecb8bf28eb 14816 res = v7_mk_boolean(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 14817 } else {
Marko Mikulicic 0:c0ecb8bf28eb 14818 res = v7_mk_boolean(v7, v1 == v2);
Marko Mikulicic 0:c0ecb8bf28eb 14819 }
Marko Mikulicic 0:c0ecb8bf28eb 14820 PUSH(res);
Marko Mikulicic 0:c0ecb8bf28eb 14821 break;
Marko Mikulicic 0:c0ecb8bf28eb 14822 }
Marko Mikulicic 0:c0ecb8bf28eb 14823 case OP_NE_NE: {
Marko Mikulicic 0:c0ecb8bf28eb 14824 v2 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14825 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14826 if (v7_is_string(v1) && v7_is_string(v2)) {
Marko Mikulicic 0:c0ecb8bf28eb 14827 res = v7_mk_boolean(v7, s_cmp(v7, v1, v2) != 0);
Marko Mikulicic 0:c0ecb8bf28eb 14828 } else if (v1 == v2 && v1 == V7_TAG_NAN) {
Marko Mikulicic 0:c0ecb8bf28eb 14829 res = v7_mk_boolean(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 14830 } else {
Marko Mikulicic 0:c0ecb8bf28eb 14831 res = v7_mk_boolean(v7, v1 != v2);
Marko Mikulicic 0:c0ecb8bf28eb 14832 }
Marko Mikulicic 0:c0ecb8bf28eb 14833 PUSH(res);
Marko Mikulicic 0:c0ecb8bf28eb 14834 break;
Marko Mikulicic 0:c0ecb8bf28eb 14835 }
Marko Mikulicic 0:c0ecb8bf28eb 14836 case OP_EQ:
Marko Mikulicic 0:c0ecb8bf28eb 14837 case OP_NE: {
Marko Mikulicic 0:c0ecb8bf28eb 14838 v2 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14839 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14840 /*
Marko Mikulicic 0:c0ecb8bf28eb 14841 * TODO(dfrank) : it's not really correct. Fix it accordingly to
Marko Mikulicic 0:c0ecb8bf28eb 14842 * the p. 4.9 of The Definitive Guide (page 71)
Marko Mikulicic 0:c0ecb8bf28eb 14843 */
Marko Mikulicic 0:c0ecb8bf28eb 14844 if (((v7_is_object(v1) || v7_is_object(v2)) && v1 == v2)) {
Marko Mikulicic 0:c0ecb8bf28eb 14845 res = v7_mk_boolean(v7, op == OP_EQ);
Marko Mikulicic 0:c0ecb8bf28eb 14846 PUSH(res);
Marko Mikulicic 0:c0ecb8bf28eb 14847 break;
Marko Mikulicic 0:c0ecb8bf28eb 14848 } else if (v7_is_undefined(v1) || v7_is_null(v1)) {
Marko Mikulicic 0:c0ecb8bf28eb 14849 res = v7_mk_boolean(
Marko Mikulicic 0:c0ecb8bf28eb 14850 v7, (op != OP_EQ) ^ (v7_is_undefined(v2) || v7_is_null(v2)));
Marko Mikulicic 0:c0ecb8bf28eb 14851 PUSH(res);
Marko Mikulicic 0:c0ecb8bf28eb 14852 break;
Marko Mikulicic 0:c0ecb8bf28eb 14853 } else if (v7_is_undefined(v2) || v7_is_null(v2)) {
Marko Mikulicic 0:c0ecb8bf28eb 14854 res = v7_mk_boolean(
Marko Mikulicic 0:c0ecb8bf28eb 14855 v7, (op != OP_EQ) ^ (v7_is_undefined(v1) || v7_is_null(v1)));
Marko Mikulicic 0:c0ecb8bf28eb 14856 PUSH(res);
Marko Mikulicic 0:c0ecb8bf28eb 14857 break;
Marko Mikulicic 0:c0ecb8bf28eb 14858 }
Marko Mikulicic 0:c0ecb8bf28eb 14859
Marko Mikulicic 0:c0ecb8bf28eb 14860 if (v7_is_string(v1) && v7_is_string(v2)) {
Marko Mikulicic 0:c0ecb8bf28eb 14861 int cmp = s_cmp(v7, v1, v2);
Marko Mikulicic 0:c0ecb8bf28eb 14862 switch (op) {
Marko Mikulicic 0:c0ecb8bf28eb 14863 case OP_EQ:
Marko Mikulicic 0:c0ecb8bf28eb 14864 res = v7_mk_boolean(v7, cmp == 0);
Marko Mikulicic 0:c0ecb8bf28eb 14865 break;
Marko Mikulicic 0:c0ecb8bf28eb 14866 case OP_NE:
Marko Mikulicic 0:c0ecb8bf28eb 14867 res = v7_mk_boolean(v7, cmp != 0);
Marko Mikulicic 0:c0ecb8bf28eb 14868 break;
Marko Mikulicic 0:c0ecb8bf28eb 14869 default:
Marko Mikulicic 0:c0ecb8bf28eb 14870 /* should never be here */
Marko Mikulicic 0:c0ecb8bf28eb 14871 assert(0);
Marko Mikulicic 0:c0ecb8bf28eb 14872 }
Marko Mikulicic 0:c0ecb8bf28eb 14873 } else {
Marko Mikulicic 0:c0ecb8bf28eb 14874 /* Convert both operands to numbers */
Marko Mikulicic 0:c0ecb8bf28eb 14875
Marko Mikulicic 0:c0ecb8bf28eb 14876 BTRY(to_number_v(v7, v1, &v1));
Marko Mikulicic 0:c0ecb8bf28eb 14877 BTRY(to_number_v(v7, v2, &v2));
Marko Mikulicic 0:c0ecb8bf28eb 14878
Marko Mikulicic 0:c0ecb8bf28eb 14879 res = v7_mk_boolean(v7, b_bool_bin_op(op, v7_get_double(v7, v1),
Marko Mikulicic 0:c0ecb8bf28eb 14880 v7_get_double(v7, 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_LT:
Marko Mikulicic 0:c0ecb8bf28eb 14886 case OP_LE:
Marko Mikulicic 0:c0ecb8bf28eb 14887 case OP_GT:
Marko Mikulicic 0:c0ecb8bf28eb 14888 case OP_GE: {
Marko Mikulicic 0:c0ecb8bf28eb 14889 v2 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14890 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14891 BTRY(to_primitive(v7, v1, V7_TO_PRIMITIVE_HINT_NUMBER, &v1));
Marko Mikulicic 0:c0ecb8bf28eb 14892 BTRY(to_primitive(v7, v2, V7_TO_PRIMITIVE_HINT_NUMBER, &v2));
Marko Mikulicic 0:c0ecb8bf28eb 14893
Marko Mikulicic 0:c0ecb8bf28eb 14894 if (v7_is_string(v1) && v7_is_string(v2)) {
Marko Mikulicic 0:c0ecb8bf28eb 14895 int cmp = s_cmp(v7, v1, v2);
Marko Mikulicic 0:c0ecb8bf28eb 14896 switch (op) {
Marko Mikulicic 0:c0ecb8bf28eb 14897 case OP_LT:
Marko Mikulicic 0:c0ecb8bf28eb 14898 res = v7_mk_boolean(v7, cmp < 0);
Marko Mikulicic 0:c0ecb8bf28eb 14899 break;
Marko Mikulicic 0:c0ecb8bf28eb 14900 case OP_LE:
Marko Mikulicic 0:c0ecb8bf28eb 14901 res = v7_mk_boolean(v7, cmp <= 0);
Marko Mikulicic 0:c0ecb8bf28eb 14902 break;
Marko Mikulicic 0:c0ecb8bf28eb 14903 case OP_GT:
Marko Mikulicic 0:c0ecb8bf28eb 14904 res = v7_mk_boolean(v7, cmp > 0);
Marko Mikulicic 0:c0ecb8bf28eb 14905 break;
Marko Mikulicic 0:c0ecb8bf28eb 14906 case OP_GE:
Marko Mikulicic 0:c0ecb8bf28eb 14907 res = v7_mk_boolean(v7, cmp >= 0);
Marko Mikulicic 0:c0ecb8bf28eb 14908 break;
Marko Mikulicic 0:c0ecb8bf28eb 14909 default:
Marko Mikulicic 0:c0ecb8bf28eb 14910 /* should never be here */
Marko Mikulicic 0:c0ecb8bf28eb 14911 assert(0);
Marko Mikulicic 0:c0ecb8bf28eb 14912 }
Marko Mikulicic 0:c0ecb8bf28eb 14913 } else {
Marko Mikulicic 0:c0ecb8bf28eb 14914 /* Convert both operands to numbers */
Marko Mikulicic 0:c0ecb8bf28eb 14915
Marko Mikulicic 0:c0ecb8bf28eb 14916 BTRY(to_number_v(v7, v1, &v1));
Marko Mikulicic 0:c0ecb8bf28eb 14917 BTRY(to_number_v(v7, v2, &v2));
Marko Mikulicic 0:c0ecb8bf28eb 14918
Marko Mikulicic 0:c0ecb8bf28eb 14919 res = v7_mk_boolean(v7, b_bool_bin_op(op, v7_get_double(v7, v1),
Marko Mikulicic 0:c0ecb8bf28eb 14920 v7_get_double(v7, v2)));
Marko Mikulicic 0:c0ecb8bf28eb 14921 }
Marko Mikulicic 0:c0ecb8bf28eb 14922 PUSH(res);
Marko Mikulicic 0:c0ecb8bf28eb 14923 break;
Marko Mikulicic 0:c0ecb8bf28eb 14924 }
Marko Mikulicic 0:c0ecb8bf28eb 14925 case OP_INSTANCEOF: {
Marko Mikulicic 0:c0ecb8bf28eb 14926 v2 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14927 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14928 if (!v7_is_callable(v7, v2)) {
Marko Mikulicic 0:c0ecb8bf28eb 14929 BTRY(v7_throwf(v7, TYPE_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 14930 "Expecting a function in instanceof check"));
Marko Mikulicic 0:c0ecb8bf28eb 14931 goto op_done;
Marko Mikulicic 0:c0ecb8bf28eb 14932 } else {
Marko Mikulicic 0:c0ecb8bf28eb 14933 PUSH(v7_mk_boolean(
Marko Mikulicic 0:c0ecb8bf28eb 14934 v7, is_prototype_of(v7, v1, v7_get(v7, v2, "prototype", 9))));
Marko Mikulicic 0:c0ecb8bf28eb 14935 }
Marko Mikulicic 0:c0ecb8bf28eb 14936 break;
Marko Mikulicic 0:c0ecb8bf28eb 14937 }
Marko Mikulicic 0:c0ecb8bf28eb 14938 case OP_TYPEOF:
Marko Mikulicic 0:c0ecb8bf28eb 14939 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14940 switch (val_type(v7, v1)) {
Marko Mikulicic 0:c0ecb8bf28eb 14941 case V7_TYPE_NUMBER:
Marko Mikulicic 0:c0ecb8bf28eb 14942 res = v7_mk_string(v7, "number", 6, 1);
Marko Mikulicic 0:c0ecb8bf28eb 14943 break;
Marko Mikulicic 0:c0ecb8bf28eb 14944 case V7_TYPE_STRING:
Marko Mikulicic 0:c0ecb8bf28eb 14945 res = v7_mk_string(v7, "string", 6, 1);
Marko Mikulicic 0:c0ecb8bf28eb 14946 break;
Marko Mikulicic 0:c0ecb8bf28eb 14947 case V7_TYPE_BOOLEAN:
Marko Mikulicic 0:c0ecb8bf28eb 14948 res = v7_mk_string(v7, "boolean", 7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 14949 break;
Marko Mikulicic 0:c0ecb8bf28eb 14950 case V7_TYPE_FUNCTION_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 14951 case V7_TYPE_CFUNCTION_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 14952 case V7_TYPE_CFUNCTION:
Marko Mikulicic 0:c0ecb8bf28eb 14953 res = v7_mk_string(v7, "function", 8, 1);
Marko Mikulicic 0:c0ecb8bf28eb 14954 break;
Marko Mikulicic 0:c0ecb8bf28eb 14955 case V7_TYPE_UNDEFINED:
Marko Mikulicic 0:c0ecb8bf28eb 14956 res = v7_mk_string(v7, "undefined", 9, 1);
Marko Mikulicic 0:c0ecb8bf28eb 14957 break;
Marko Mikulicic 0:c0ecb8bf28eb 14958 default:
Marko Mikulicic 0:c0ecb8bf28eb 14959 res = v7_mk_string(v7, "object", 6, 1);
Marko Mikulicic 0:c0ecb8bf28eb 14960 break;
Marko Mikulicic 0:c0ecb8bf28eb 14961 }
Marko Mikulicic 0:c0ecb8bf28eb 14962 PUSH(res);
Marko Mikulicic 0:c0ecb8bf28eb 14963 break;
Marko Mikulicic 0:c0ecb8bf28eb 14964 case OP_IN: {
Marko Mikulicic 0:c0ecb8bf28eb 14965 struct v7_property *prop = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 14966 v2 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14967 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14968 BTRY(to_string(v7, v1, NULL, buf, sizeof(buf), NULL));
Marko Mikulicic 0:c0ecb8bf28eb 14969 prop = v7_get_property(v7, v2, buf, ~0);
Marko Mikulicic 0:c0ecb8bf28eb 14970 PUSH(v7_mk_boolean(v7, prop != NULL));
Marko Mikulicic 0:c0ecb8bf28eb 14971 } break;
Marko Mikulicic 0:c0ecb8bf28eb 14972 case OP_GET:
Marko Mikulicic 0:c0ecb8bf28eb 14973 v2 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14974 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14975 BTRY(v7_get_throwing_v(v7, v1, v2, &v3));
Marko Mikulicic 0:c0ecb8bf28eb 14976 PUSH(v3);
Marko Mikulicic 0:c0ecb8bf28eb 14977 #ifndef V7_DISABLE_CALL_ERROR_CONTEXT
Marko Mikulicic 0:c0ecb8bf28eb 14978 v7->vals.last_name[1] = v7->vals.last_name[0];
Marko Mikulicic 0:c0ecb8bf28eb 14979 v7->vals.last_name[0] = v2;
Marko Mikulicic 0:c0ecb8bf28eb 14980 #endif
Marko Mikulicic 0:c0ecb8bf28eb 14981 break;
Marko Mikulicic 0:c0ecb8bf28eb 14982 case OP_SET: {
Marko Mikulicic 0:c0ecb8bf28eb 14983 v3 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14984 v2 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14985 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 14986
Marko Mikulicic 0:c0ecb8bf28eb 14987 /* convert name to string, if it's not already */
Marko Mikulicic 0:c0ecb8bf28eb 14988 BTRY(to_string(v7, v2, &v2, NULL, 0, NULL));
Marko Mikulicic 0:c0ecb8bf28eb 14989
Marko Mikulicic 0:c0ecb8bf28eb 14990 /* set value */
Marko Mikulicic 0:c0ecb8bf28eb 14991 BTRY(set_property_v(v7, v1, v2, v3, NULL));
Marko Mikulicic 0:c0ecb8bf28eb 14992
Marko Mikulicic 0:c0ecb8bf28eb 14993 PUSH(v3);
Marko Mikulicic 0:c0ecb8bf28eb 14994 break;
Marko Mikulicic 0:c0ecb8bf28eb 14995 }
Marko Mikulicic 0:c0ecb8bf28eb 14996 case OP_GET_VAR:
Marko Mikulicic 0:c0ecb8bf28eb 14997 case OP_SAFE_GET_VAR: {
Marko Mikulicic 0:c0ecb8bf28eb 14998 struct v7_property *p = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 14999 assert(r.ops < r.end - 1);
Marko Mikulicic 0:c0ecb8bf28eb 15000 v1 = bcode_decode_lit(v7, r.bcode, &r.ops);
Marko Mikulicic 0:c0ecb8bf28eb 15001 BTRY(v7_get_property_v(v7, get_scope(v7), v1, &p));
Marko Mikulicic 0:c0ecb8bf28eb 15002 if (p == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 15003 if (op == OP_SAFE_GET_VAR) {
Marko Mikulicic 0:c0ecb8bf28eb 15004 PUSH(V7_UNDEFINED);
Marko Mikulicic 0:c0ecb8bf28eb 15005 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15006 /* variable does not exist: Reference Error */
Marko Mikulicic 0:c0ecb8bf28eb 15007 V7_TRY(bcode_throw_reference_error(v7, &r, v1));
Marko Mikulicic 0:c0ecb8bf28eb 15008 goto op_done;
Marko Mikulicic 0:c0ecb8bf28eb 15009 }
Marko Mikulicic 0:c0ecb8bf28eb 15010 break;
Marko Mikulicic 0:c0ecb8bf28eb 15011 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15012 BTRY(v7_property_value(v7, get_scope(v7), p, &v2));
Marko Mikulicic 0:c0ecb8bf28eb 15013 PUSH(v2);
Marko Mikulicic 0:c0ecb8bf28eb 15014 }
Marko Mikulicic 0:c0ecb8bf28eb 15015 #ifndef V7_DISABLE_CALL_ERROR_CONTEXT
Marko Mikulicic 0:c0ecb8bf28eb 15016 v7->vals.last_name[0] = v1;
Marko Mikulicic 0:c0ecb8bf28eb 15017 v7->vals.last_name[1] = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 15018 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15019 break;
Marko Mikulicic 0:c0ecb8bf28eb 15020 }
Marko Mikulicic 0:c0ecb8bf28eb 15021 case OP_SET_VAR: {
Marko Mikulicic 0:c0ecb8bf28eb 15022 struct v7_property *prop;
Marko Mikulicic 0:c0ecb8bf28eb 15023 v3 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15024 v2 = bcode_decode_lit(v7, r.bcode, &r.ops);
Marko Mikulicic 0:c0ecb8bf28eb 15025 v1 = get_scope(v7);
Marko Mikulicic 0:c0ecb8bf28eb 15026
Marko Mikulicic 0:c0ecb8bf28eb 15027 BTRY(to_string(v7, v2, NULL, buf, sizeof(buf), NULL));
Marko Mikulicic 0:c0ecb8bf28eb 15028 prop = v7_get_property(v7, v1, buf, strlen(buf));
Marko Mikulicic 0:c0ecb8bf28eb 15029 if (prop != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 15030 /* Property already exists: update its value */
Marko Mikulicic 0:c0ecb8bf28eb 15031 /*
Marko Mikulicic 0:c0ecb8bf28eb 15032 * TODO(dfrank): currently we can't use `def_property_v()` here,
Marko Mikulicic 0:c0ecb8bf28eb 15033 * because if the property was already found somewhere in the
Marko Mikulicic 0:c0ecb8bf28eb 15034 * prototype chain, then it should be updated, instead of creating a
Marko Mikulicic 0:c0ecb8bf28eb 15035 * new one on the top of the scope.
Marko Mikulicic 0:c0ecb8bf28eb 15036 *
Marko Mikulicic 0:c0ecb8bf28eb 15037 * Probably we need to make `def_property_v()` more generic and
Marko Mikulicic 0:c0ecb8bf28eb 15038 * use it here; or split `def_property_v()` into smaller pieces and
Marko Mikulicic 0:c0ecb8bf28eb 15039 * use one of them here.
Marko Mikulicic 0:c0ecb8bf28eb 15040 */
Marko Mikulicic 0:c0ecb8bf28eb 15041 if (!(prop->attributes & V7_PROPERTY_NON_WRITABLE)) {
Marko Mikulicic 0:c0ecb8bf28eb 15042 prop->value = v3;
Marko Mikulicic 0:c0ecb8bf28eb 15043 }
Marko Mikulicic 0:c0ecb8bf28eb 15044 } else if (!r.bcode->strict_mode) {
Marko Mikulicic 0:c0ecb8bf28eb 15045 /*
Marko Mikulicic 0:c0ecb8bf28eb 15046 * Property does not exist: since we're not in strict mode, let's
Marko Mikulicic 0:c0ecb8bf28eb 15047 * create new property at Global Object
Marko Mikulicic 0:c0ecb8bf28eb 15048 */
Marko Mikulicic 0:c0ecb8bf28eb 15049 BTRY(set_property_v(v7, v7_get_global(v7), v2, v3, NULL));
Marko Mikulicic 0:c0ecb8bf28eb 15050 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15051 /*
Marko Mikulicic 0:c0ecb8bf28eb 15052 * In strict mode, throw reference error instead of polluting Global
Marko Mikulicic 0:c0ecb8bf28eb 15053 * Object
Marko Mikulicic 0:c0ecb8bf28eb 15054 */
Marko Mikulicic 0:c0ecb8bf28eb 15055 V7_TRY(bcode_throw_reference_error(v7, &r, v2));
Marko Mikulicic 0:c0ecb8bf28eb 15056 goto op_done;
Marko Mikulicic 0:c0ecb8bf28eb 15057 }
Marko Mikulicic 0:c0ecb8bf28eb 15058 PUSH(v3);
Marko Mikulicic 0:c0ecb8bf28eb 15059 break;
Marko Mikulicic 0:c0ecb8bf28eb 15060 }
Marko Mikulicic 0:c0ecb8bf28eb 15061 case OP_JMP: {
Marko Mikulicic 0:c0ecb8bf28eb 15062 bcode_off_t target = bcode_get_target(&r.ops);
Marko Mikulicic 0:c0ecb8bf28eb 15063 r.ops = r.bcode->ops.p + target - 1;
Marko Mikulicic 0:c0ecb8bf28eb 15064 break;
Marko Mikulicic 0:c0ecb8bf28eb 15065 }
Marko Mikulicic 0:c0ecb8bf28eb 15066 case OP_JMP_FALSE: {
Marko Mikulicic 0:c0ecb8bf28eb 15067 bcode_off_t target = bcode_get_target(&r.ops);
Marko Mikulicic 0:c0ecb8bf28eb 15068 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15069 if (!v7_is_truthy(v7, v1)) {
Marko Mikulicic 0:c0ecb8bf28eb 15070 r.ops = r.bcode->ops.p + target - 1;
Marko Mikulicic 0:c0ecb8bf28eb 15071 }
Marko Mikulicic 0:c0ecb8bf28eb 15072 break;
Marko Mikulicic 0:c0ecb8bf28eb 15073 }
Marko Mikulicic 0:c0ecb8bf28eb 15074 case OP_JMP_TRUE: {
Marko Mikulicic 0:c0ecb8bf28eb 15075 bcode_off_t target = bcode_get_target(&r.ops);
Marko Mikulicic 0:c0ecb8bf28eb 15076 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15077 if (v7_is_truthy(v7, v1)) {
Marko Mikulicic 0:c0ecb8bf28eb 15078 r.ops = r.bcode->ops.p + target - 1;
Marko Mikulicic 0:c0ecb8bf28eb 15079 }
Marko Mikulicic 0:c0ecb8bf28eb 15080 break;
Marko Mikulicic 0:c0ecb8bf28eb 15081 }
Marko Mikulicic 0:c0ecb8bf28eb 15082 case OP_JMP_TRUE_DROP: {
Marko Mikulicic 0:c0ecb8bf28eb 15083 bcode_off_t target = bcode_get_target(&r.ops);
Marko Mikulicic 0:c0ecb8bf28eb 15084 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15085 if (v7_is_truthy(v7, v1)) {
Marko Mikulicic 0:c0ecb8bf28eb 15086 r.ops = r.bcode->ops.p + target - 1;
Marko Mikulicic 0:c0ecb8bf28eb 15087 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15088 POP();
Marko Mikulicic 0:c0ecb8bf28eb 15089 PUSH(v1);
Marko Mikulicic 0:c0ecb8bf28eb 15090 }
Marko Mikulicic 0:c0ecb8bf28eb 15091 break;
Marko Mikulicic 0:c0ecb8bf28eb 15092 }
Marko Mikulicic 0:c0ecb8bf28eb 15093 case OP_JMP_IF_CONTINUE: {
Marko Mikulicic 0:c0ecb8bf28eb 15094 bcode_off_t target = bcode_get_target(&r.ops);
Marko Mikulicic 0:c0ecb8bf28eb 15095 if (v7->is_continuing) {
Marko Mikulicic 0:c0ecb8bf28eb 15096 r.ops = r.bcode->ops.p + target - 1;
Marko Mikulicic 0:c0ecb8bf28eb 15097 }
Marko Mikulicic 0:c0ecb8bf28eb 15098 v7->is_continuing = 0;
Marko Mikulicic 0:c0ecb8bf28eb 15099 break;
Marko Mikulicic 0:c0ecb8bf28eb 15100 }
Marko Mikulicic 0:c0ecb8bf28eb 15101 case OP_CREATE_OBJ:
Marko Mikulicic 0:c0ecb8bf28eb 15102 PUSH(v7_mk_object(v7));
Marko Mikulicic 0:c0ecb8bf28eb 15103 break;
Marko Mikulicic 0:c0ecb8bf28eb 15104 case OP_CREATE_ARR:
Marko Mikulicic 0:c0ecb8bf28eb 15105 PUSH(v7_mk_array(v7));
Marko Mikulicic 0:c0ecb8bf28eb 15106 break;
Marko Mikulicic 0:c0ecb8bf28eb 15107 case OP_PUSH_PROP_ITER_CTX: {
Marko Mikulicic 0:c0ecb8bf28eb 15108 struct prop_iter_ctx *ctx =
Marko Mikulicic 0:c0ecb8bf28eb 15109 (struct prop_iter_ctx *) calloc(1, sizeof(*ctx));
Marko Mikulicic 0:c0ecb8bf28eb 15110 BTRY(init_prop_iter_ctx(v7, TOS(), 1, ctx));
Marko Mikulicic 0:c0ecb8bf28eb 15111 v1 = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 15112 v7_set_user_data(v7, v1, ctx);
Marko Mikulicic 0:c0ecb8bf28eb 15113 v7_set_destructor_cb(v7, v1, prop_iter_ctx_dtor);
Marko Mikulicic 0:c0ecb8bf28eb 15114 PUSH(v1);
Marko Mikulicic 0:c0ecb8bf28eb 15115 break;
Marko Mikulicic 0:c0ecb8bf28eb 15116 }
Marko Mikulicic 0:c0ecb8bf28eb 15117 case OP_NEXT_PROP: {
Marko Mikulicic 0:c0ecb8bf28eb 15118 struct prop_iter_ctx *ctx = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 15119 int ok = 0;
Marko Mikulicic 0:c0ecb8bf28eb 15120 v1 = POP(); /* ctx */
Marko Mikulicic 0:c0ecb8bf28eb 15121 v2 = POP(); /* object */
Marko Mikulicic 0:c0ecb8bf28eb 15122
Marko Mikulicic 0:c0ecb8bf28eb 15123 ctx = (struct prop_iter_ctx *) v7_get_user_data(v7, v1);
Marko Mikulicic 0:c0ecb8bf28eb 15124
Marko Mikulicic 0:c0ecb8bf28eb 15125 if (v7_is_object(v2)) {
Marko Mikulicic 0:c0ecb8bf28eb 15126 v7_prop_attr_t attrs;
Marko Mikulicic 0:c0ecb8bf28eb 15127
Marko Mikulicic 0:c0ecb8bf28eb 15128 do {
Marko Mikulicic 0:c0ecb8bf28eb 15129 /* iterate properties until we find a non-hidden enumerable one */
Marko Mikulicic 0:c0ecb8bf28eb 15130 do {
Marko Mikulicic 0:c0ecb8bf28eb 15131 BTRY(next_prop(v7, ctx, &res, NULL, &attrs, &ok));
Marko Mikulicic 0:c0ecb8bf28eb 15132 } while (ok && (attrs & (_V7_PROPERTY_HIDDEN |
Marko Mikulicic 0:c0ecb8bf28eb 15133 V7_PROPERTY_NON_ENUMERABLE)));
Marko Mikulicic 0:c0ecb8bf28eb 15134
Marko Mikulicic 0:c0ecb8bf28eb 15135 if (!ok) {
Marko Mikulicic 0:c0ecb8bf28eb 15136 /* no more properties in this object: proceed to the prototype */
Marko Mikulicic 0:c0ecb8bf28eb 15137 v2 = v7_get_proto(v7, v2);
Marko Mikulicic 0:c0ecb8bf28eb 15138 if (get_generic_object_struct(v2) != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 15139 /*
Marko Mikulicic 0:c0ecb8bf28eb 15140 * the prototype is a generic object, so, init the context for
Marko Mikulicic 0:c0ecb8bf28eb 15141 * props iteration
Marko Mikulicic 0:c0ecb8bf28eb 15142 */
Marko Mikulicic 0:c0ecb8bf28eb 15143 v7_destruct_prop_iter_ctx(v7, ctx);
Marko Mikulicic 0:c0ecb8bf28eb 15144 BTRY(init_prop_iter_ctx(v7, v2, 1, ctx));
Marko Mikulicic 0:c0ecb8bf28eb 15145 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15146 /*
Marko Mikulicic 0:c0ecb8bf28eb 15147 * we can't iterate the prototype's props, so, just stop
Marko Mikulicic 0:c0ecb8bf28eb 15148 * iteration.
Marko Mikulicic 0:c0ecb8bf28eb 15149 */
Marko Mikulicic 0:c0ecb8bf28eb 15150 ctx = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 15151 }
Marko Mikulicic 0:c0ecb8bf28eb 15152 }
Marko Mikulicic 0:c0ecb8bf28eb 15153 } while (!ok && ctx != NULL);
Marko Mikulicic 0:c0ecb8bf28eb 15154 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15155 /*
Marko Mikulicic 0:c0ecb8bf28eb 15156 * Not an object: reset the context.
Marko Mikulicic 0:c0ecb8bf28eb 15157 */
Marko Mikulicic 0:c0ecb8bf28eb 15158 ctx = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 15159 }
Marko Mikulicic 0:c0ecb8bf28eb 15160
Marko Mikulicic 0:c0ecb8bf28eb 15161 if (ctx == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 15162 PUSH(v7_mk_boolean(v7, 0));
Marko Mikulicic 0:c0ecb8bf28eb 15163
Marko Mikulicic 0:c0ecb8bf28eb 15164 /*
Marko Mikulicic 0:c0ecb8bf28eb 15165 * We could leave the context unfreed, and let the
Marko Mikulicic 0:c0ecb8bf28eb 15166 * `prop_iter_ctx_dtor()` free it when the v1 will be GC-d, but
Marko Mikulicic 0:c0ecb8bf28eb 15167 * let's do that earlier.
Marko Mikulicic 0:c0ecb8bf28eb 15168 */
Marko Mikulicic 0:c0ecb8bf28eb 15169 ctx = (struct prop_iter_ctx *) v7_get_user_data(v7, v1);
Marko Mikulicic 0:c0ecb8bf28eb 15170 v7_destruct_prop_iter_ctx(v7, ctx);
Marko Mikulicic 0:c0ecb8bf28eb 15171 free(ctx);
Marko Mikulicic 0:c0ecb8bf28eb 15172 v7_set_user_data(v7, v1, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 15173 v7_set_destructor_cb(v7, v1, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 15174 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15175 PUSH(v2);
Marko Mikulicic 0:c0ecb8bf28eb 15176 PUSH(v1);
Marko Mikulicic 0:c0ecb8bf28eb 15177 PUSH(res);
Marko Mikulicic 0:c0ecb8bf28eb 15178 PUSH(v7_mk_boolean(v7, 1));
Marko Mikulicic 0:c0ecb8bf28eb 15179 }
Marko Mikulicic 0:c0ecb8bf28eb 15180 break;
Marko Mikulicic 0:c0ecb8bf28eb 15181 }
Marko Mikulicic 0:c0ecb8bf28eb 15182 case OP_FUNC_LIT: {
Marko Mikulicic 0:c0ecb8bf28eb 15183 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15184 v2 = bcode_instantiate_function(v7, v1);
Marko Mikulicic 0:c0ecb8bf28eb 15185 PUSH(v2);
Marko Mikulicic 0:c0ecb8bf28eb 15186 break;
Marko Mikulicic 0:c0ecb8bf28eb 15187 }
Marko Mikulicic 0:c0ecb8bf28eb 15188 case OP_CHECK_CALL:
Marko Mikulicic 0:c0ecb8bf28eb 15189 v1 = TOS();
Marko Mikulicic 0:c0ecb8bf28eb 15190 if (!v7_is_callable(v7, v1)) {
Marko Mikulicic 0:c0ecb8bf28eb 15191 int arity = 0;
Marko Mikulicic 0:c0ecb8bf28eb 15192 enum v7_err ignore;
Marko Mikulicic 0:c0ecb8bf28eb 15193 /* tried to call non-function object: throw a TypeError */
Marko Mikulicic 0:c0ecb8bf28eb 15194
Marko Mikulicic 0:c0ecb8bf28eb 15195 #ifndef V7_DISABLE_CALL_ERROR_CONTEXT
Marko Mikulicic 0:c0ecb8bf28eb 15196 /*
Marko Mikulicic 0:c0ecb8bf28eb 15197 * try to provide some useful context for the error message
Marko Mikulicic 0:c0ecb8bf28eb 15198 * using a good-enough heuristics
Marko Mikulicic 0:c0ecb8bf28eb 15199 * but defer actual throw when process the incriminated call
Marko Mikulicic 0:c0ecb8bf28eb 15200 * in order to evaluate the arguments as required by the spec.
Marko Mikulicic 0:c0ecb8bf28eb 15201 */
Marko Mikulicic 0:c0ecb8bf28eb 15202 if (v7->last_ops[0] == OP_GET_VAR) {
Marko Mikulicic 0:c0ecb8bf28eb 15203 arity = 1;
Marko Mikulicic 0:c0ecb8bf28eb 15204 } else if (v7->last_ops[0] == OP_GET &&
Marko Mikulicic 0:c0ecb8bf28eb 15205 v7->last_ops[1] == OP_PUSH_LIT) {
Marko Mikulicic 0:c0ecb8bf28eb 15206 /*
Marko Mikulicic 0:c0ecb8bf28eb 15207 * OP_PUSH_LIT is used to both push property names for OP_GET
Marko Mikulicic 0:c0ecb8bf28eb 15208 * and for pushing actual literals. During PUSH_LIT push lit
Marko Mikulicic 0:c0ecb8bf28eb 15209 * evaluation we reset the last name variable in case the literal
Marko Mikulicic 0:c0ecb8bf28eb 15210 * is not a string, such as in `[].foo()`.
Marko Mikulicic 0:c0ecb8bf28eb 15211 * Unfortunately it doesn't handle `"foo".bar()`; could be
Marko Mikulicic 0:c0ecb8bf28eb 15212 * solved by adding another bytecode for property literals but
Marko Mikulicic 0:c0ecb8bf28eb 15213 * probably it doesn't matter much.
Marko Mikulicic 0:c0ecb8bf28eb 15214 */
Marko Mikulicic 0:c0ecb8bf28eb 15215 if (v7_is_undefined(v7->vals.last_name[1])) {
Marko Mikulicic 0:c0ecb8bf28eb 15216 arity = 1;
Marko Mikulicic 0:c0ecb8bf28eb 15217 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15218 arity = 2;
Marko Mikulicic 0:c0ecb8bf28eb 15219 }
Marko Mikulicic 0:c0ecb8bf28eb 15220 }
Marko Mikulicic 0:c0ecb8bf28eb 15221 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15222
Marko Mikulicic 0:c0ecb8bf28eb 15223 switch (arity) {
Marko Mikulicic 0:c0ecb8bf28eb 15224 case 0:
Marko Mikulicic 0:c0ecb8bf28eb 15225 ignore = v7_throwf(v7, TYPE_ERROR, "value is not a function");
Marko Mikulicic 0:c0ecb8bf28eb 15226 break;
Marko Mikulicic 0:c0ecb8bf28eb 15227 #ifndef V7_DISABLE_CALL_ERROR_CONTEXT
Marko Mikulicic 0:c0ecb8bf28eb 15228
Marko Mikulicic 0:c0ecb8bf28eb 15229 case 1:
Marko Mikulicic 0:c0ecb8bf28eb 15230 ignore = v7_throwf(v7, TYPE_ERROR, "%s is not a function",
Marko Mikulicic 0:c0ecb8bf28eb 15231 v7_get_cstring(v7, &v7->vals.last_name[0]));
Marko Mikulicic 0:c0ecb8bf28eb 15232 break;
Marko Mikulicic 0:c0ecb8bf28eb 15233 case 2:
Marko Mikulicic 0:c0ecb8bf28eb 15234 ignore = v7_throwf(v7, TYPE_ERROR, "%s.%s is not a function",
Marko Mikulicic 0:c0ecb8bf28eb 15235 v7_get_cstring(v7, &v7->vals.last_name[1]),
Marko Mikulicic 0:c0ecb8bf28eb 15236 v7_get_cstring(v7, &v7->vals.last_name[0]));
Marko Mikulicic 0:c0ecb8bf28eb 15237 break;
Marko Mikulicic 0:c0ecb8bf28eb 15238 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15239 };
Marko Mikulicic 0:c0ecb8bf28eb 15240
Marko Mikulicic 0:c0ecb8bf28eb 15241 v7->vals.call_check_ex = v7->vals.thrown_error;
Marko Mikulicic 0:c0ecb8bf28eb 15242 v7_clear_thrown_value(v7);
Marko Mikulicic 0:c0ecb8bf28eb 15243 (void) ignore;
Marko Mikulicic 0:c0ecb8bf28eb 15244 }
Marko Mikulicic 0:c0ecb8bf28eb 15245 break;
Marko Mikulicic 0:c0ecb8bf28eb 15246 case OP_CALL:
Marko Mikulicic 0:c0ecb8bf28eb 15247 case OP_NEW: {
Marko Mikulicic 0:c0ecb8bf28eb 15248 /* Naive implementation pending stack frame redesign */
Marko Mikulicic 0:c0ecb8bf28eb 15249 int args = (int) *(++r.ops);
Marko Mikulicic 0:c0ecb8bf28eb 15250 uint8_t is_constructor = (op == OP_NEW);
Marko Mikulicic 0:c0ecb8bf28eb 15251
Marko Mikulicic 0:c0ecb8bf28eb 15252 if (SP() < (args + 1 /*func*/ + 1 /*this*/)) {
Marko Mikulicic 0:c0ecb8bf28eb 15253 BTRY(v7_throwf(v7, INTERNAL_ERROR, "stack underflow"));
Marko Mikulicic 0:c0ecb8bf28eb 15254 goto op_done;
Marko Mikulicic 0:c0ecb8bf28eb 15255 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15256 v2 = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 15257 while (args > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 15258 BTRY(v7_array_set_throwing(v7, v2, --args, POP(), NULL));
Marko Mikulicic 0:c0ecb8bf28eb 15259 }
Marko Mikulicic 0:c0ecb8bf28eb 15260 /* pop function to call */
Marko Mikulicic 0:c0ecb8bf28eb 15261 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15262
Marko Mikulicic 0:c0ecb8bf28eb 15263 /* pop `this` */
Marko Mikulicic 0:c0ecb8bf28eb 15264 v3 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15265
Marko Mikulicic 0:c0ecb8bf28eb 15266 /*
Marko Mikulicic 0:c0ecb8bf28eb 15267 * adjust `this` if the function is called with the constructor
Marko Mikulicic 0:c0ecb8bf28eb 15268 * invocation pattern
Marko Mikulicic 0:c0ecb8bf28eb 15269 */
Marko Mikulicic 0:c0ecb8bf28eb 15270 if (is_constructor) {
Marko Mikulicic 0:c0ecb8bf28eb 15271 /*
Marko Mikulicic 0:c0ecb8bf28eb 15272 * The function is invoked as a constructor: we ignore `this`
Marko Mikulicic 0:c0ecb8bf28eb 15273 * value popped from stack, create new object and set prototype.
Marko Mikulicic 0:c0ecb8bf28eb 15274 */
Marko Mikulicic 0:c0ecb8bf28eb 15275
Marko Mikulicic 0:c0ecb8bf28eb 15276 /*
Marko Mikulicic 0:c0ecb8bf28eb 15277 * get "prototype" property from the constructor function,
Marko Mikulicic 0:c0ecb8bf28eb 15278 * and make sure it's an object
Marko Mikulicic 0:c0ecb8bf28eb 15279 */
Marko Mikulicic 0:c0ecb8bf28eb 15280 v4 = v7_get(v7, v1 /*func*/, "prototype", 9);
Marko Mikulicic 0:c0ecb8bf28eb 15281 if (!v7_is_object(v4)) {
Marko Mikulicic 0:c0ecb8bf28eb 15282 /* TODO(dfrank): box primitive value */
Marko Mikulicic 0:c0ecb8bf28eb 15283 BTRY(v7_throwf(
Marko Mikulicic 0:c0ecb8bf28eb 15284 v7, TYPE_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 15285 "Cannot set a primitive value as object prototype"));
Marko Mikulicic 0:c0ecb8bf28eb 15286 goto op_done;
Marko Mikulicic 0:c0ecb8bf28eb 15287 } else if (is_cfunction_lite(v4)) {
Marko Mikulicic 0:c0ecb8bf28eb 15288 /*
Marko Mikulicic 0:c0ecb8bf28eb 15289 * TODO(dfrank): maybe add support for a cfunction pointer to be
Marko Mikulicic 0:c0ecb8bf28eb 15290 * a prototype
Marko Mikulicic 0:c0ecb8bf28eb 15291 */
Marko Mikulicic 0:c0ecb8bf28eb 15292 BTRY(v7_throwf(v7, TYPE_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 15293 "Not implemented: cfunction as a prototype"));
Marko Mikulicic 0:c0ecb8bf28eb 15294 goto op_done;
Marko Mikulicic 0:c0ecb8bf28eb 15295 }
Marko Mikulicic 0:c0ecb8bf28eb 15296
Marko Mikulicic 0:c0ecb8bf28eb 15297 /* create an object with given prototype */
Marko Mikulicic 0:c0ecb8bf28eb 15298 v3 = mk_object(v7, v4 /*prototype*/);
Marko Mikulicic 0:c0ecb8bf28eb 15299 v4 = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 15300 }
Marko Mikulicic 0:c0ecb8bf28eb 15301
Marko Mikulicic 0:c0ecb8bf28eb 15302 if (!v7_is_callable(v7, v1)) {
Marko Mikulicic 0:c0ecb8bf28eb 15303 /* tried to call non-function object: throw a TypeError */
Marko Mikulicic 0:c0ecb8bf28eb 15304 BTRY(v7_throw(v7, v7->vals.call_check_ex));
Marko Mikulicic 0:c0ecb8bf28eb 15305 goto op_done;
Marko Mikulicic 0:c0ecb8bf28eb 15306 } else if (is_cfunction_lite(v1) || is_cfunction_obj(v7, v1)) {
Marko Mikulicic 0:c0ecb8bf28eb 15307 /* call cfunction */
Marko Mikulicic 0:c0ecb8bf28eb 15308
Marko Mikulicic 0:c0ecb8bf28eb 15309 /*
Marko Mikulicic 0:c0ecb8bf28eb 15310 * In "function invocation pattern", the `this` value popped from
Marko Mikulicic 0:c0ecb8bf28eb 15311 * stack is an `undefined`. And in non-strict mode, we should change
Marko Mikulicic 0:c0ecb8bf28eb 15312 * it to global object.
Marko Mikulicic 0:c0ecb8bf28eb 15313 */
Marko Mikulicic 0:c0ecb8bf28eb 15314 if (!is_constructor && !r.bcode->strict_mode &&
Marko Mikulicic 0:c0ecb8bf28eb 15315 v7_is_undefined(v3)) {
Marko Mikulicic 0:c0ecb8bf28eb 15316 v3 = v7->vals.global_object;
Marko Mikulicic 0:c0ecb8bf28eb 15317 }
Marko Mikulicic 0:c0ecb8bf28eb 15318
Marko Mikulicic 0:c0ecb8bf28eb 15319 BTRY(call_cfunction(v7, v1 /*func*/, v3 /*this*/, v2 /*args*/,
Marko Mikulicic 0:c0ecb8bf28eb 15320 is_constructor, &v4));
Marko Mikulicic 0:c0ecb8bf28eb 15321
Marko Mikulicic 0:c0ecb8bf28eb 15322 /* push value returned from C function to bcode stack */
Marko Mikulicic 0:c0ecb8bf28eb 15323 PUSH(v4);
Marko Mikulicic 0:c0ecb8bf28eb 15324
Marko Mikulicic 0:c0ecb8bf28eb 15325 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15326 char *ops;
Marko Mikulicic 0:c0ecb8bf28eb 15327 struct v7_js_function *func = get_js_function_struct(v1);
Marko Mikulicic 0:c0ecb8bf28eb 15328
Marko Mikulicic 0:c0ecb8bf28eb 15329 /*
Marko Mikulicic 0:c0ecb8bf28eb 15330 * In "function invocation pattern", the `this` value popped from
Marko Mikulicic 0:c0ecb8bf28eb 15331 * stack is an `undefined`. And in non-strict mode, we should change
Marko Mikulicic 0:c0ecb8bf28eb 15332 * it to global object.
Marko Mikulicic 0:c0ecb8bf28eb 15333 */
Marko Mikulicic 0:c0ecb8bf28eb 15334 if (!is_constructor && !func->bcode->strict_mode &&
Marko Mikulicic 0:c0ecb8bf28eb 15335 v7_is_undefined(v3)) {
Marko Mikulicic 0:c0ecb8bf28eb 15336 v3 = v7->vals.global_object;
Marko Mikulicic 0:c0ecb8bf28eb 15337 }
Marko Mikulicic 0:c0ecb8bf28eb 15338
Marko Mikulicic 0:c0ecb8bf28eb 15339 scope_frame = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 15340
Marko Mikulicic 0:c0ecb8bf28eb 15341 /*
Marko Mikulicic 0:c0ecb8bf28eb 15342 * Before actual opcodes, `ops` contains one or more
Marko Mikulicic 0:c0ecb8bf28eb 15343 * null-terminated strings: first of all, the function name (if the
Marko Mikulicic 0:c0ecb8bf28eb 15344 * function is anonymous, it's an empty string).
Marko Mikulicic 0:c0ecb8bf28eb 15345 *
Marko Mikulicic 0:c0ecb8bf28eb 15346 * Then, argument names follow. We know number of arguments, so, we
Marko Mikulicic 0:c0ecb8bf28eb 15347 * know how many names to take.
Marko Mikulicic 0:c0ecb8bf28eb 15348 *
Marko Mikulicic 0:c0ecb8bf28eb 15349 * And then, local variable names follow. We know total number of
Marko Mikulicic 0:c0ecb8bf28eb 15350 * strings (`names_cnt`), so, again, we know how many names to
Marko Mikulicic 0:c0ecb8bf28eb 15351 * take.
Marko Mikulicic 0:c0ecb8bf28eb 15352 */
Marko Mikulicic 0:c0ecb8bf28eb 15353
Marko Mikulicic 0:c0ecb8bf28eb 15354 ops = func->bcode->ops.p;
Marko Mikulicic 0:c0ecb8bf28eb 15355
Marko Mikulicic 0:c0ecb8bf28eb 15356 /* populate function itself */
Marko Mikulicic 0:c0ecb8bf28eb 15357 ops = bcode_next_name_v(v7, func->bcode, ops, &v4);
Marko Mikulicic 0:c0ecb8bf28eb 15358 BTRY(def_property_v(v7, scope_frame, v4, V7_DESC_CONFIGURABLE(0),
Marko Mikulicic 0:c0ecb8bf28eb 15359 v1, 0 /*not assign*/, NULL));
Marko Mikulicic 0:c0ecb8bf28eb 15360
Marko Mikulicic 0:c0ecb8bf28eb 15361 /* populate arguments */
Marko Mikulicic 0:c0ecb8bf28eb 15362 {
Marko Mikulicic 0:c0ecb8bf28eb 15363 int arg_num;
Marko Mikulicic 0:c0ecb8bf28eb 15364 for (arg_num = 0; arg_num < func->bcode->args_cnt; ++arg_num) {
Marko Mikulicic 0:c0ecb8bf28eb 15365 ops = bcode_next_name_v(v7, func->bcode, ops, &v4);
Marko Mikulicic 0:c0ecb8bf28eb 15366 BTRY(def_property_v(
Marko Mikulicic 0:c0ecb8bf28eb 15367 v7, scope_frame, v4, V7_DESC_CONFIGURABLE(0),
Marko Mikulicic 0:c0ecb8bf28eb 15368 v7_array_get(v7, v2, arg_num), 0 /*not assign*/, NULL));
Marko Mikulicic 0:c0ecb8bf28eb 15369 }
Marko Mikulicic 0:c0ecb8bf28eb 15370 }
Marko Mikulicic 0:c0ecb8bf28eb 15371
Marko Mikulicic 0:c0ecb8bf28eb 15372 /* populate `arguments` object */
Marko Mikulicic 0:c0ecb8bf28eb 15373
Marko Mikulicic 0:c0ecb8bf28eb 15374 /*
Marko Mikulicic 0:c0ecb8bf28eb 15375 * TODO(dfrank): it's actually much more complicated than that:
Marko Mikulicic 0:c0ecb8bf28eb 15376 * it's not an array, it's an array-like object. More, in
Marko Mikulicic 0:c0ecb8bf28eb 15377 * non-strict mode, elements of `arguments` object are just aliases
Marko Mikulicic 0:c0ecb8bf28eb 15378 * for actual arguments, so this one:
Marko Mikulicic 0:c0ecb8bf28eb 15379 *
Marko Mikulicic 0:c0ecb8bf28eb 15380 * `(function(a){arguments[0]=2; return a;})(1);`
Marko Mikulicic 0:c0ecb8bf28eb 15381 *
Marko Mikulicic 0:c0ecb8bf28eb 15382 * should yield 2. Currently, it yields 1.
Marko Mikulicic 0:c0ecb8bf28eb 15383 */
Marko Mikulicic 0:c0ecb8bf28eb 15384 v7_def(v7, scope_frame, "arguments", 9, V7_DESC_CONFIGURABLE(0),
Marko Mikulicic 0:c0ecb8bf28eb 15385 v2);
Marko Mikulicic 0:c0ecb8bf28eb 15386
Marko Mikulicic 0:c0ecb8bf28eb 15387 /* populate local variables */
Marko Mikulicic 0:c0ecb8bf28eb 15388 {
Marko Mikulicic 0:c0ecb8bf28eb 15389 uint8_t loc_num;
Marko Mikulicic 0:c0ecb8bf28eb 15390 uint8_t loc_cnt = func->bcode->names_cnt - func->bcode->args_cnt -
Marko Mikulicic 0:c0ecb8bf28eb 15391 1 /*func name*/;
Marko Mikulicic 0:c0ecb8bf28eb 15392 for (loc_num = 0; loc_num < loc_cnt; ++loc_num) {
Marko Mikulicic 0:c0ecb8bf28eb 15393 ops = bcode_next_name_v(v7, func->bcode, ops, &v4);
Marko Mikulicic 0:c0ecb8bf28eb 15394 BTRY(def_property_v(v7, scope_frame, v4,
Marko Mikulicic 0:c0ecb8bf28eb 15395 V7_DESC_CONFIGURABLE(0), V7_UNDEFINED,
Marko Mikulicic 0:c0ecb8bf28eb 15396 0 /*not assign*/, NULL));
Marko Mikulicic 0:c0ecb8bf28eb 15397 }
Marko Mikulicic 0:c0ecb8bf28eb 15398 }
Marko Mikulicic 0:c0ecb8bf28eb 15399
Marko Mikulicic 0:c0ecb8bf28eb 15400 /* transfer control to the function */
Marko Mikulicic 0:c0ecb8bf28eb 15401 V7_TRY(bcode_perform_call(v7, scope_frame, func, &r, v3 /*this*/,
Marko Mikulicic 0:c0ecb8bf28eb 15402 ops, is_constructor));
Marko Mikulicic 0:c0ecb8bf28eb 15403
Marko Mikulicic 0:c0ecb8bf28eb 15404 scope_frame = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 15405 }
Marko Mikulicic 0:c0ecb8bf28eb 15406 }
Marko Mikulicic 0:c0ecb8bf28eb 15407 break;
Marko Mikulicic 0:c0ecb8bf28eb 15408 }
Marko Mikulicic 0:c0ecb8bf28eb 15409 case OP_RET:
Marko Mikulicic 0:c0ecb8bf28eb 15410 bcode_adjust_retval(v7, 1 /*explicit return*/);
Marko Mikulicic 0:c0ecb8bf28eb 15411 V7_TRY(bcode_perform_return(v7, &r, 1 /*take value from stack*/));
Marko Mikulicic 0:c0ecb8bf28eb 15412 break;
Marko Mikulicic 0:c0ecb8bf28eb 15413 case OP_DELETE:
Marko Mikulicic 0:c0ecb8bf28eb 15414 case OP_DELETE_VAR: {
Marko Mikulicic 0:c0ecb8bf28eb 15415 size_t name_len;
Marko Mikulicic 0:c0ecb8bf28eb 15416 struct v7_property *prop;
Marko Mikulicic 0:c0ecb8bf28eb 15417
Marko Mikulicic 0:c0ecb8bf28eb 15418 res = v7_mk_boolean(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 15419
Marko Mikulicic 0:c0ecb8bf28eb 15420 /* pop property name to delete */
Marko Mikulicic 0:c0ecb8bf28eb 15421 v2 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15422
Marko Mikulicic 0:c0ecb8bf28eb 15423 if (op == OP_DELETE) {
Marko Mikulicic 0:c0ecb8bf28eb 15424 /* pop object to delete the property from */
Marko Mikulicic 0:c0ecb8bf28eb 15425 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15426 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15427 /* use scope as an object to delete the property from */
Marko Mikulicic 0:c0ecb8bf28eb 15428 v1 = get_scope(v7);
Marko Mikulicic 0:c0ecb8bf28eb 15429 }
Marko Mikulicic 0:c0ecb8bf28eb 15430
Marko Mikulicic 0:c0ecb8bf28eb 15431 if (!v7_is_object(v1)) {
Marko Mikulicic 0:c0ecb8bf28eb 15432 /*
Marko Mikulicic 0:c0ecb8bf28eb 15433 * the "object" to delete a property from is not actually an object
Marko Mikulicic 0:c0ecb8bf28eb 15434 * (at least this can happen with cfunction pointers), will just
Marko Mikulicic 0:c0ecb8bf28eb 15435 * return `true`
Marko Mikulicic 0:c0ecb8bf28eb 15436 */
Marko Mikulicic 0:c0ecb8bf28eb 15437 goto delete_clean;
Marko Mikulicic 0:c0ecb8bf28eb 15438 }
Marko Mikulicic 0:c0ecb8bf28eb 15439
Marko Mikulicic 0:c0ecb8bf28eb 15440 BTRY(to_string(v7, v2, NULL, buf, sizeof(buf), &name_len));
Marko Mikulicic 0:c0ecb8bf28eb 15441
Marko Mikulicic 0:c0ecb8bf28eb 15442 prop = v7_get_property(v7, v1, buf, name_len);
Marko Mikulicic 0:c0ecb8bf28eb 15443 if (prop == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 15444 /* not found a property; will just return `true` */
Marko Mikulicic 0:c0ecb8bf28eb 15445 goto delete_clean;
Marko Mikulicic 0:c0ecb8bf28eb 15446 }
Marko Mikulicic 0:c0ecb8bf28eb 15447
Marko Mikulicic 0:c0ecb8bf28eb 15448 /* found needed property */
Marko Mikulicic 0:c0ecb8bf28eb 15449
Marko Mikulicic 0:c0ecb8bf28eb 15450 if (prop->attributes & V7_PROPERTY_NON_CONFIGURABLE) {
Marko Mikulicic 0:c0ecb8bf28eb 15451 /*
Marko Mikulicic 0:c0ecb8bf28eb 15452 * this property is undeletable. In non-strict mode, we just
Marko Mikulicic 0:c0ecb8bf28eb 15453 * return `false`; otherwise, we throw.
Marko Mikulicic 0:c0ecb8bf28eb 15454 */
Marko Mikulicic 0:c0ecb8bf28eb 15455 if (!r.bcode->strict_mode) {
Marko Mikulicic 0:c0ecb8bf28eb 15456 res = v7_mk_boolean(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 15457 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15458 BTRY(v7_throwf(v7, TYPE_ERROR, "Cannot delete property '%s'", buf));
Marko Mikulicic 0:c0ecb8bf28eb 15459 goto op_done;
Marko Mikulicic 0:c0ecb8bf28eb 15460 }
Marko Mikulicic 0:c0ecb8bf28eb 15461 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15462 /*
Marko Mikulicic 0:c0ecb8bf28eb 15463 * delete property: when we operate on the current scope, we should
Marko Mikulicic 0:c0ecb8bf28eb 15464 * walk the prototype chain when deleting property.
Marko Mikulicic 0:c0ecb8bf28eb 15465 *
Marko Mikulicic 0:c0ecb8bf28eb 15466 * But when we operate on a "real" object, we should delete own
Marko Mikulicic 0:c0ecb8bf28eb 15467 * properties only.
Marko Mikulicic 0:c0ecb8bf28eb 15468 */
Marko Mikulicic 0:c0ecb8bf28eb 15469 if (op == OP_DELETE) {
Marko Mikulicic 0:c0ecb8bf28eb 15470 v7_del(v7, v1, buf, name_len);
Marko Mikulicic 0:c0ecb8bf28eb 15471 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15472 del_property_deep(v7, v1, buf, name_len);
Marko Mikulicic 0:c0ecb8bf28eb 15473 }
Marko Mikulicic 0:c0ecb8bf28eb 15474 }
Marko Mikulicic 0:c0ecb8bf28eb 15475
Marko Mikulicic 0:c0ecb8bf28eb 15476 delete_clean:
Marko Mikulicic 0:c0ecb8bf28eb 15477 PUSH(res);
Marko Mikulicic 0:c0ecb8bf28eb 15478 break;
Marko Mikulicic 0:c0ecb8bf28eb 15479 }
Marko Mikulicic 0:c0ecb8bf28eb 15480 case OP_TRY_PUSH_CATCH:
Marko Mikulicic 0:c0ecb8bf28eb 15481 case OP_TRY_PUSH_FINALLY:
Marko Mikulicic 0:c0ecb8bf28eb 15482 case OP_TRY_PUSH_LOOP:
Marko Mikulicic 0:c0ecb8bf28eb 15483 case OP_TRY_PUSH_SWITCH:
Marko Mikulicic 0:c0ecb8bf28eb 15484 eval_try_push(v7, op, &r);
Marko Mikulicic 0:c0ecb8bf28eb 15485 break;
Marko Mikulicic 0:c0ecb8bf28eb 15486 case OP_TRY_POP:
Marko Mikulicic 0:c0ecb8bf28eb 15487 V7_TRY(eval_try_pop(v7));
Marko Mikulicic 0:c0ecb8bf28eb 15488 break;
Marko Mikulicic 0:c0ecb8bf28eb 15489 case OP_AFTER_FINALLY:
Marko Mikulicic 0:c0ecb8bf28eb 15490 /*
Marko Mikulicic 0:c0ecb8bf28eb 15491 * exited from `finally` block: if some value is currently being
Marko Mikulicic 0:c0ecb8bf28eb 15492 * returned, continue returning it.
Marko Mikulicic 0:c0ecb8bf28eb 15493 *
Marko Mikulicic 0:c0ecb8bf28eb 15494 * Likewise, if some value is currently being thrown, continue
Marko Mikulicic 0:c0ecb8bf28eb 15495 * unwinding stack.
Marko Mikulicic 0:c0ecb8bf28eb 15496 */
Marko Mikulicic 0:c0ecb8bf28eb 15497 if (v7->is_thrown) {
Marko Mikulicic 0:c0ecb8bf28eb 15498 V7_TRY(
Marko Mikulicic 0:c0ecb8bf28eb 15499 bcode_perform_throw(v7, &r, 0 /*don't take value from stack*/));
Marko Mikulicic 0:c0ecb8bf28eb 15500 goto op_done;
Marko Mikulicic 0:c0ecb8bf28eb 15501 } else if (v7->is_returned) {
Marko Mikulicic 0:c0ecb8bf28eb 15502 V7_TRY(
Marko Mikulicic 0:c0ecb8bf28eb 15503 bcode_perform_return(v7, &r, 0 /*don't take value from stack*/));
Marko Mikulicic 0:c0ecb8bf28eb 15504 break;
Marko Mikulicic 0:c0ecb8bf28eb 15505 } else if (v7->is_breaking) {
Marko Mikulicic 0:c0ecb8bf28eb 15506 bcode_perform_break(v7, &r);
Marko Mikulicic 0:c0ecb8bf28eb 15507 }
Marko Mikulicic 0:c0ecb8bf28eb 15508 break;
Marko Mikulicic 0:c0ecb8bf28eb 15509 case OP_THROW:
Marko Mikulicic 0:c0ecb8bf28eb 15510 V7_TRY(bcode_perform_throw(v7, &r, 1 /*take thrown value*/));
Marko Mikulicic 0:c0ecb8bf28eb 15511 goto op_done;
Marko Mikulicic 0:c0ecb8bf28eb 15512 case OP_BREAK:
Marko Mikulicic 0:c0ecb8bf28eb 15513 bcode_perform_break(v7, &r);
Marko Mikulicic 0:c0ecb8bf28eb 15514 break;
Marko Mikulicic 0:c0ecb8bf28eb 15515 case OP_CONTINUE:
Marko Mikulicic 0:c0ecb8bf28eb 15516 v7->is_continuing = 1;
Marko Mikulicic 0:c0ecb8bf28eb 15517 bcode_perform_break(v7, &r);
Marko Mikulicic 0:c0ecb8bf28eb 15518 break;
Marko Mikulicic 0:c0ecb8bf28eb 15519 case OP_ENTER_CATCH: {
Marko Mikulicic 0:c0ecb8bf28eb 15520 /* pop thrown value from stack */
Marko Mikulicic 0:c0ecb8bf28eb 15521 v1 = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15522 /* get the name of the thrown value */
Marko Mikulicic 0:c0ecb8bf28eb 15523 v2 = bcode_decode_lit(v7, r.bcode, &r.ops);
Marko Mikulicic 0:c0ecb8bf28eb 15524
Marko Mikulicic 0:c0ecb8bf28eb 15525 /*
Marko Mikulicic 0:c0ecb8bf28eb 15526 * create a new stack frame (a "private" one), and set exception
Marko Mikulicic 0:c0ecb8bf28eb 15527 * property on it
Marko Mikulicic 0:c0ecb8bf28eb 15528 */
Marko Mikulicic 0:c0ecb8bf28eb 15529 scope_frame = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 15530 BTRY(set_property_v(v7, scope_frame, v2, v1, NULL));
Marko Mikulicic 0:c0ecb8bf28eb 15531
Marko Mikulicic 0:c0ecb8bf28eb 15532 /* Push this "private" frame on the call stack */
Marko Mikulicic 0:c0ecb8bf28eb 15533
Marko Mikulicic 0:c0ecb8bf28eb 15534 /* new scope_frame will inherit from the current scope */
Marko Mikulicic 0:c0ecb8bf28eb 15535
Marko Mikulicic 0:c0ecb8bf28eb 15536 obj_prototype_set(v7, get_object_struct(scope_frame),
Marko Mikulicic 0:c0ecb8bf28eb 15537 get_object_struct(get_scope(v7)));
Marko Mikulicic 0:c0ecb8bf28eb 15538
Marko Mikulicic 0:c0ecb8bf28eb 15539 /*
Marko Mikulicic 0:c0ecb8bf28eb 15540 * Create new `call_frame` which will replace `v7->call_stack`.
Marko Mikulicic 0:c0ecb8bf28eb 15541 */
Marko Mikulicic 0:c0ecb8bf28eb 15542 append_call_frame_private(v7, scope_frame);
Marko Mikulicic 0:c0ecb8bf28eb 15543
Marko Mikulicic 0:c0ecb8bf28eb 15544 break;
Marko Mikulicic 0:c0ecb8bf28eb 15545 }
Marko Mikulicic 0:c0ecb8bf28eb 15546 case OP_EXIT_CATCH: {
Marko Mikulicic 0:c0ecb8bf28eb 15547 v7_call_frame_mask_t frame_type_mask;
Marko Mikulicic 0:c0ecb8bf28eb 15548 /* unwind 1 frame */
Marko Mikulicic 0:c0ecb8bf28eb 15549 frame_type_mask = unwind_stack_1level(v7, &r);
Marko Mikulicic 0:c0ecb8bf28eb 15550 /* make sure the unwound frame is a "private" frame */
Marko Mikulicic 0:c0ecb8bf28eb 15551 assert(frame_type_mask == V7_CALL_FRAME_MASK_PRIVATE);
Marko Mikulicic 0:c0ecb8bf28eb 15552 #if defined(NDEBUG)
Marko Mikulicic 0:c0ecb8bf28eb 15553 (void) frame_type_mask;
Marko Mikulicic 0:c0ecb8bf28eb 15554 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15555 break;
Marko Mikulicic 0:c0ecb8bf28eb 15556 }
Marko Mikulicic 0:c0ecb8bf28eb 15557 default:
Marko Mikulicic 0:c0ecb8bf28eb 15558 BTRY(v7_throwf(v7, INTERNAL_ERROR, "Unknown opcode: %d", (int) op));
Marko Mikulicic 0:c0ecb8bf28eb 15559 goto op_done;
Marko Mikulicic 0:c0ecb8bf28eb 15560 }
Marko Mikulicic 0:c0ecb8bf28eb 15561
Marko Mikulicic 0:c0ecb8bf28eb 15562 op_done:
Marko Mikulicic 0:c0ecb8bf28eb 15563 #ifdef V7_BCODE_TRACE
Marko Mikulicic 0:c0ecb8bf28eb 15564 /* print current stack state */
Marko Mikulicic 0:c0ecb8bf28eb 15565 {
Marko Mikulicic 0:c0ecb8bf28eb 15566 char buf[40];
Marko Mikulicic 0:c0ecb8bf28eb 15567 char *str = v7_stringify(v7, TOS(), buf, sizeof(buf), V7_STRINGIFY_DEBUG);
Marko Mikulicic 0:c0ecb8bf28eb 15568 fprintf(stderr, " stack size: %u, TOS: '%s'\n",
Marko Mikulicic 0:c0ecb8bf28eb 15569 (unsigned int) (v7->stack.len / sizeof(val_t)), str);
Marko Mikulicic 0:c0ecb8bf28eb 15570 if (str != buf) {
Marko Mikulicic 0:c0ecb8bf28eb 15571 free(str);
Marko Mikulicic 0:c0ecb8bf28eb 15572 }
Marko Mikulicic 0:c0ecb8bf28eb 15573
Marko Mikulicic 0:c0ecb8bf28eb 15574 #ifdef V7_BCODE_TRACE_STACK
Marko Mikulicic 0:c0ecb8bf28eb 15575 {
Marko Mikulicic 0:c0ecb8bf28eb 15576 size_t i;
Marko Mikulicic 0:c0ecb8bf28eb 15577 for (i = 0; i < (v7->stack.len / sizeof(val_t)); i++) {
Marko Mikulicic 0:c0ecb8bf28eb 15578 char *str = v7_stringify(v7, stack_at(&v7->stack, i), buf,
Marko Mikulicic 0:c0ecb8bf28eb 15579 sizeof(buf), V7_STRINGIFY_DEBUG);
Marko Mikulicic 0:c0ecb8bf28eb 15580
Marko Mikulicic 0:c0ecb8bf28eb 15581 fprintf(stderr, " #: '%s'\n", str);
Marko Mikulicic 0:c0ecb8bf28eb 15582
Marko Mikulicic 0:c0ecb8bf28eb 15583 if (str != buf) {
Marko Mikulicic 0:c0ecb8bf28eb 15584 free(str);
Marko Mikulicic 0:c0ecb8bf28eb 15585 }
Marko Mikulicic 0:c0ecb8bf28eb 15586 }
Marko Mikulicic 0:c0ecb8bf28eb 15587 }
Marko Mikulicic 0:c0ecb8bf28eb 15588 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15589 }
Marko Mikulicic 0:c0ecb8bf28eb 15590 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15591 if (r.need_inc_ops) {
Marko Mikulicic 0:c0ecb8bf28eb 15592 r.ops++;
Marko Mikulicic 0:c0ecb8bf28eb 15593 }
Marko Mikulicic 0:c0ecb8bf28eb 15594 }
Marko Mikulicic 0:c0ecb8bf28eb 15595
Marko Mikulicic 0:c0ecb8bf28eb 15596 /* implicit return */
Marko Mikulicic 0:c0ecb8bf28eb 15597 if (v7->call_stack != v7->bottom_call_frame) {
Marko Mikulicic 0:c0ecb8bf28eb 15598 #ifdef V7_BCODE_TRACE
Marko Mikulicic 0:c0ecb8bf28eb 15599 fprintf(stderr, "return implicitly\n");
Marko Mikulicic 0:c0ecb8bf28eb 15600 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15601 bcode_adjust_retval(v7, 0 /*implicit return*/);
Marko Mikulicic 0:c0ecb8bf28eb 15602 V7_TRY(bcode_perform_return(v7, &r, 1));
Marko Mikulicic 0:c0ecb8bf28eb 15603 goto restart;
Marko Mikulicic 0:c0ecb8bf28eb 15604 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15605 #ifdef V7_BCODE_TRACE
Marko Mikulicic 0:c0ecb8bf28eb 15606 const char *s = (get_scope(v7) != v7->vals.global_object)
Marko Mikulicic 0:c0ecb8bf28eb 15607 ? "not global object"
Marko Mikulicic 0:c0ecb8bf28eb 15608 : "global object";
Marko Mikulicic 0:c0ecb8bf28eb 15609 fprintf(stderr, "reached bottom_call_frame (%s)\n", s);
Marko Mikulicic 0:c0ecb8bf28eb 15610 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15611 }
Marko Mikulicic 0:c0ecb8bf28eb 15612
Marko Mikulicic 0:c0ecb8bf28eb 15613 clean:
Marko Mikulicic 0:c0ecb8bf28eb 15614
Marko Mikulicic 0:c0ecb8bf28eb 15615 if (rcode == V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 15616 /*
Marko Mikulicic 0:c0ecb8bf28eb 15617 * bcode evaluated successfully. Make sure try stack is empty.
Marko Mikulicic 0:c0ecb8bf28eb 15618 * (data stack will be checked below, in `clean`)
Marko Mikulicic 0:c0ecb8bf28eb 15619 */
Marko Mikulicic 0:c0ecb8bf28eb 15620 #ifndef NDEBUG
Marko Mikulicic 0:c0ecb8bf28eb 15621 {
Marko Mikulicic 0:c0ecb8bf28eb 15622 unsigned long try_stack_len =
Marko Mikulicic 0:c0ecb8bf28eb 15623 v7_array_length(v7, find_call_frame_private(v7)->vals.try_stack);
Marko Mikulicic 0:c0ecb8bf28eb 15624 if (try_stack_len != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 15625 fprintf(stderr, "try_stack_len=%lu, should be 0\n", try_stack_len);
Marko Mikulicic 0:c0ecb8bf28eb 15626 }
Marko Mikulicic 0:c0ecb8bf28eb 15627 assert(try_stack_len == 0);
Marko Mikulicic 0:c0ecb8bf28eb 15628 }
Marko Mikulicic 0:c0ecb8bf28eb 15629 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15630
Marko Mikulicic 0:c0ecb8bf28eb 15631 /* get the value returned from the evaluated script */
Marko Mikulicic 0:c0ecb8bf28eb 15632 *_res = POP();
Marko Mikulicic 0:c0ecb8bf28eb 15633 }
Marko Mikulicic 0:c0ecb8bf28eb 15634
Marko Mikulicic 0:c0ecb8bf28eb 15635 assert(v7->bottom_call_frame == v7->call_stack);
Marko Mikulicic 0:c0ecb8bf28eb 15636 unwind_stack_1level(v7, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 15637
Marko Mikulicic 0:c0ecb8bf28eb 15638 v7->bottom_call_frame = saved_bottom_call_frame;
Marko Mikulicic 0:c0ecb8bf28eb 15639
Marko Mikulicic 0:c0ecb8bf28eb 15640 tmp_frame_cleanup(&tf);
Marko Mikulicic 0:c0ecb8bf28eb 15641 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 15642 }
Marko Mikulicic 0:c0ecb8bf28eb 15643
Marko Mikulicic 0:c0ecb8bf28eb 15644 /*
Marko Mikulicic 0:c0ecb8bf28eb 15645 * TODO(dfrank) this function is probably too overloaded: it handles both
Marko Mikulicic 0:c0ecb8bf28eb 15646 * `v7_exec` and `v7_apply`. Read below why it's written this way, but it's
Marko Mikulicic 0:c0ecb8bf28eb 15647 * probably a good idea to factor out common functionality in some other
Marko Mikulicic 0:c0ecb8bf28eb 15648 * function.
Marko Mikulicic 0:c0ecb8bf28eb 15649 *
Marko Mikulicic 0:c0ecb8bf28eb 15650 * If `src` is not `NULL`, then we behave in favour of `v7_exec`: parse,
Marko Mikulicic 0:c0ecb8bf28eb 15651 * compile, and evaluate the script. The `func` and `args` are ignored.
Marko Mikulicic 0:c0ecb8bf28eb 15652 *
Marko Mikulicic 0:c0ecb8bf28eb 15653 * If, however, `src` is `NULL`, then we behave in favour of `v7_apply`: we
Marko Mikulicic 0:c0ecb8bf28eb 15654 * call the provided `func` with `args`. But unlike interpreter, we can't just
Marko Mikulicic 0:c0ecb8bf28eb 15655 * call the provided function: we need to setup environment for this call.
Marko Mikulicic 0:c0ecb8bf28eb 15656 *
Marko Mikulicic 0:c0ecb8bf28eb 15657 * Currently, we just quickly generate the "wrapper" bcode for the function.
Marko Mikulicic 0:c0ecb8bf28eb 15658 * This wrapper bcode looks like this:
Marko Mikulicic 0:c0ecb8bf28eb 15659 *
Marko Mikulicic 0:c0ecb8bf28eb 15660 * OP_PUSH_UNDEFINED
Marko Mikulicic 0:c0ecb8bf28eb 15661 * OP_PUSH_LIT # push this
Marko Mikulicic 0:c0ecb8bf28eb 15662 * OP_PUSH_LIT # push function
Marko Mikulicic 0:c0ecb8bf28eb 15663 * OP_PUSH_LIT # push arg1
Marko Mikulicic 0:c0ecb8bf28eb 15664 * OP_PUSH_LIT # push arg2
Marko Mikulicic 0:c0ecb8bf28eb 15665 * ...
Marko Mikulicic 0:c0ecb8bf28eb 15666 * OP_PUSH_LIT # push argN
Marko Mikulicic 0:c0ecb8bf28eb 15667 * OP_CALL(N) # call function with N arguments
Marko Mikulicic 0:c0ecb8bf28eb 15668 * OP_SWAP_DROP
Marko Mikulicic 0:c0ecb8bf28eb 15669 *
Marko Mikulicic 0:c0ecb8bf28eb 15670 * and then, bcode evaluator proceeds with this code.
Marko Mikulicic 0:c0ecb8bf28eb 15671 *
Marko Mikulicic 0:c0ecb8bf28eb 15672 * In fact, both cases (eval or apply) are quite similar: we should prepare
Marko Mikulicic 0:c0ecb8bf28eb 15673 * environment for the bcode evaluation in exactly the same way, and the only
Marko Mikulicic 0:c0ecb8bf28eb 15674 * different part is where we get the bcode from. This is why that
Marko Mikulicic 0:c0ecb8bf28eb 15675 * functionality is baked in the single function, but it would be good to make
Marko Mikulicic 0:c0ecb8bf28eb 15676 * it suck less.
Marko Mikulicic 0:c0ecb8bf28eb 15677 */
Marko Mikulicic 0:c0ecb8bf28eb 15678 V7_PRIVATE enum v7_err b_exec(struct v7 *v7, const char *src, size_t src_len,
Marko Mikulicic 0:c0ecb8bf28eb 15679 const char *filename, val_t func, val_t args,
Marko Mikulicic 0:c0ecb8bf28eb 15680 val_t this_object, int is_json, int fr,
Marko Mikulicic 0:c0ecb8bf28eb 15681 uint8_t is_constructor, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 15682 #if defined(V7_BCODE_TRACE_SRC)
Marko Mikulicic 0:c0ecb8bf28eb 15683 fprintf(stderr, "src:'%s'\n", src);
Marko Mikulicic 0:c0ecb8bf28eb 15684 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15685
Marko Mikulicic 0:c0ecb8bf28eb 15686 /* TODO(mkm): use GC pool */
Marko Mikulicic 0:c0ecb8bf28eb 15687 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 15688 struct ast *a = (struct ast *) malloc(sizeof(struct ast));
Marko Mikulicic 0:c0ecb8bf28eb 15689 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15690 size_t saved_stack_len = v7->stack.len;
Marko Mikulicic 0:c0ecb8bf28eb 15691 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 15692 val_t _res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 15693 struct gc_tmp_frame tf = new_tmp_frame(v7);
Marko Mikulicic 0:c0ecb8bf28eb 15694 struct bcode *bcode = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 15695 #if defined(V7_ENABLE_STACK_TRACKING)
Marko Mikulicic 0:c0ecb8bf28eb 15696 struct stack_track_ctx stack_track_ctx;
Marko Mikulicic 0:c0ecb8bf28eb 15697 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15698 struct {
Marko Mikulicic 0:c0ecb8bf28eb 15699 unsigned noopt : 1;
Marko Mikulicic 0:c0ecb8bf28eb 15700 unsigned line_no_reset : 1;
Marko Mikulicic 0:c0ecb8bf28eb 15701 } flags = {0, 0};
Marko Mikulicic 0:c0ecb8bf28eb 15702
Marko Mikulicic 0:c0ecb8bf28eb 15703 (void) filename;
Marko Mikulicic 0:c0ecb8bf28eb 15704
Marko Mikulicic 0:c0ecb8bf28eb 15705 #if defined(V7_ENABLE_STACK_TRACKING)
Marko Mikulicic 0:c0ecb8bf28eb 15706 v7_stack_track_start(v7, &stack_track_ctx);
Marko Mikulicic 0:c0ecb8bf28eb 15707 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15708
Marko Mikulicic 0:c0ecb8bf28eb 15709 tmp_stack_push(&tf, &func);
Marko Mikulicic 0:c0ecb8bf28eb 15710 tmp_stack_push(&tf, &args);
Marko Mikulicic 0:c0ecb8bf28eb 15711 tmp_stack_push(&tf, &this_object);
Marko Mikulicic 0:c0ecb8bf28eb 15712 tmp_stack_push(&tf, &_res);
Marko Mikulicic 0:c0ecb8bf28eb 15713
Marko Mikulicic 0:c0ecb8bf28eb 15714 /* init new bcode */
Marko Mikulicic 0:c0ecb8bf28eb 15715 bcode = (struct bcode *) calloc(1, sizeof(*bcode));
Marko Mikulicic 0:c0ecb8bf28eb 15716
Marko Mikulicic 0:c0ecb8bf28eb 15717 bcode_init(bcode,
Marko Mikulicic 0:c0ecb8bf28eb 15718 #ifndef V7_FORCE_STRICT_MODE
Marko Mikulicic 0:c0ecb8bf28eb 15719 0,
Marko Mikulicic 0:c0ecb8bf28eb 15720 #else
Marko Mikulicic 0:c0ecb8bf28eb 15721 1,
Marko Mikulicic 0:c0ecb8bf28eb 15722 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15723 #ifndef V7_DISABLE_FILENAMES
Marko Mikulicic 0:c0ecb8bf28eb 15724 filename ? shdata_create_from_string(filename) : NULL,
Marko Mikulicic 0:c0ecb8bf28eb 15725 #else
Marko Mikulicic 0:c0ecb8bf28eb 15726 NULL,
Marko Mikulicic 0:c0ecb8bf28eb 15727 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15728 0 /*filename not in ROM*/
Marko Mikulicic 0:c0ecb8bf28eb 15729 );
Marko Mikulicic 0:c0ecb8bf28eb 15730
Marko Mikulicic 0:c0ecb8bf28eb 15731 retain_bcode(v7, bcode);
Marko Mikulicic 0:c0ecb8bf28eb 15732 own_bcode(v7, bcode);
Marko Mikulicic 0:c0ecb8bf28eb 15733
Marko Mikulicic 0:c0ecb8bf28eb 15734 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 15735 ast_init(a, 0);
Marko Mikulicic 0:c0ecb8bf28eb 15736 a->refcnt = 1;
Marko Mikulicic 0:c0ecb8bf28eb 15737 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15738
Marko Mikulicic 0:c0ecb8bf28eb 15739 if (src != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 15740 /* Caller provided some source code, so, handle it somehow */
Marko Mikulicic 0:c0ecb8bf28eb 15741
Marko Mikulicic 0:c0ecb8bf28eb 15742 flags.line_no_reset = 1;
Marko Mikulicic 0:c0ecb8bf28eb 15743
Marko Mikulicic 0:c0ecb8bf28eb 15744 if (src_len >= sizeof(BIN_BCODE_SIGNATURE) &&
Marko Mikulicic 0:c0ecb8bf28eb 15745 strncmp(BIN_BCODE_SIGNATURE, src, sizeof(BIN_BCODE_SIGNATURE)) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 15746 /* we have a serialized bcode */
Marko Mikulicic 0:c0ecb8bf28eb 15747
Marko Mikulicic 0:c0ecb8bf28eb 15748 bcode_deserialize(v7, bcode, src + sizeof(BIN_BCODE_SIGNATURE));
Marko Mikulicic 0:c0ecb8bf28eb 15749
Marko Mikulicic 0:c0ecb8bf28eb 15750 /*
Marko Mikulicic 0:c0ecb8bf28eb 15751 * Currently, we only support serialized bcode that is stored in some
Marko Mikulicic 0:c0ecb8bf28eb 15752 * mmapped memory. Otherwise, we don't yet have any mechanism to free
Marko Mikulicic 0:c0ecb8bf28eb 15753 * this memory at the appropriate time.
Marko Mikulicic 0:c0ecb8bf28eb 15754 */
Marko Mikulicic 0:c0ecb8bf28eb 15755
Marko Mikulicic 0:c0ecb8bf28eb 15756 /*
Marko Mikulicic 0:c0ecb8bf28eb 15757 * TODO(dfrank): currently, we remove this assert, and introduce memory
Marko Mikulicic 0:c0ecb8bf28eb 15758 * leak. We need to support that properly.
Marko Mikulicic 0:c0ecb8bf28eb 15759 */
Marko Mikulicic 0:c0ecb8bf28eb 15760 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 15761 assert(fr == 0);
Marko Mikulicic 0:c0ecb8bf28eb 15762 #else
Marko Mikulicic 0:c0ecb8bf28eb 15763 if (fr) {
Marko Mikulicic 0:c0ecb8bf28eb 15764 fr = 0;
Marko Mikulicic 0:c0ecb8bf28eb 15765 }
Marko Mikulicic 0:c0ecb8bf28eb 15766 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15767 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15768 /* Maybe regular JavaScript source or binary AST data */
Marko Mikulicic 0:c0ecb8bf28eb 15769 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 15770
Marko Mikulicic 0:c0ecb8bf28eb 15771 if (src_len >= sizeof(BIN_AST_SIGNATURE) &&
Marko Mikulicic 0:c0ecb8bf28eb 15772 strncmp(BIN_AST_SIGNATURE, src, sizeof(BIN_AST_SIGNATURE)) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 15773 /* we have binary AST data */
Marko Mikulicic 0:c0ecb8bf28eb 15774
Marko Mikulicic 0:c0ecb8bf28eb 15775 if (fr == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 15776 /* Unmanaged memory, usually rom or mmapped flash */
Marko Mikulicic 0:c0ecb8bf28eb 15777 mbuf_free(&a->mbuf);
Marko Mikulicic 0:c0ecb8bf28eb 15778 a->mbuf.buf = (char *) (src + sizeof(BIN_AST_SIGNATURE));
Marko Mikulicic 0:c0ecb8bf28eb 15779 a->mbuf.size = a->mbuf.len = src_len - sizeof(BIN_AST_SIGNATURE);
Marko Mikulicic 0:c0ecb8bf28eb 15780 a->refcnt++; /* prevent freeing */
Marko Mikulicic 0:c0ecb8bf28eb 15781 flags.noopt = 1;
Marko Mikulicic 0:c0ecb8bf28eb 15782 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15783 mbuf_append(&a->mbuf, src + sizeof(BIN_AST_SIGNATURE),
Marko Mikulicic 0:c0ecb8bf28eb 15784 src_len - sizeof(BIN_AST_SIGNATURE));
Marko Mikulicic 0:c0ecb8bf28eb 15785 }
Marko Mikulicic 0:c0ecb8bf28eb 15786 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15787 /* we have regular JavaScript source, so, parse it */
Marko Mikulicic 0:c0ecb8bf28eb 15788 V7_TRY(parse(v7, a, src, src_len, is_json));
Marko Mikulicic 0:c0ecb8bf28eb 15789 }
Marko Mikulicic 0:c0ecb8bf28eb 15790
Marko Mikulicic 0:c0ecb8bf28eb 15791 /* we now have binary AST, let's compile it */
Marko Mikulicic 0:c0ecb8bf28eb 15792
Marko Mikulicic 0:c0ecb8bf28eb 15793 if (!flags.noopt) {
Marko Mikulicic 0:c0ecb8bf28eb 15794 ast_optimize(a);
Marko Mikulicic 0:c0ecb8bf28eb 15795 }
Marko Mikulicic 0:c0ecb8bf28eb 15796 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 15797 v7->function_arena_ast_size += a->mbuf.size;
Marko Mikulicic 0:c0ecb8bf28eb 15798 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15799
Marko Mikulicic 0:c0ecb8bf28eb 15800 if (v7_is_undefined(this_object)) {
Marko Mikulicic 0:c0ecb8bf28eb 15801 this_object = v7->vals.global_object;
Marko Mikulicic 0:c0ecb8bf28eb 15802 }
Marko Mikulicic 0:c0ecb8bf28eb 15803
Marko Mikulicic 0:c0ecb8bf28eb 15804 if (!is_json) {
Marko Mikulicic 0:c0ecb8bf28eb 15805 V7_TRY(compile_script(v7, a, bcode));
Marko Mikulicic 0:c0ecb8bf28eb 15806 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15807 ast_off_t pos = 0;
Marko Mikulicic 0:c0ecb8bf28eb 15808 V7_TRY(compile_expr(v7, a, &pos, bcode));
Marko Mikulicic 0:c0ecb8bf28eb 15809 }
Marko Mikulicic 0:c0ecb8bf28eb 15810 #else /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 15811 (void) is_json;
Marko Mikulicic 0:c0ecb8bf28eb 15812 /* Parsing JavaScript code is disabled */
Marko Mikulicic 0:c0ecb8bf28eb 15813 rcode = v7_throwf(v7, SYNTAX_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 15814 "Parsing JS code is disabled by V7_NO_COMPILER");
Marko Mikulicic 0:c0ecb8bf28eb 15815 V7_THROW(V7_SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 15816 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 15817 }
Marko Mikulicic 0:c0ecb8bf28eb 15818
Marko Mikulicic 0:c0ecb8bf28eb 15819 } else if (is_js_function(func)) {
Marko Mikulicic 0:c0ecb8bf28eb 15820 /*
Marko Mikulicic 0:c0ecb8bf28eb 15821 * Caller did not provide source code, so, assume we should call
Marko Mikulicic 0:c0ecb8bf28eb 15822 * provided function. Here, we prepare "wrapper" bcode.
Marko Mikulicic 0:c0ecb8bf28eb 15823 */
Marko Mikulicic 0:c0ecb8bf28eb 15824
Marko Mikulicic 0:c0ecb8bf28eb 15825 struct bcode_builder bbuilder;
Marko Mikulicic 0:c0ecb8bf28eb 15826 lit_t lit;
Marko Mikulicic 0:c0ecb8bf28eb 15827 int args_cnt = v7_array_length(v7, args);
Marko Mikulicic 0:c0ecb8bf28eb 15828
Marko Mikulicic 0:c0ecb8bf28eb 15829 bcode_builder_init(v7, &bbuilder, bcode);
Marko Mikulicic 0:c0ecb8bf28eb 15830
Marko Mikulicic 0:c0ecb8bf28eb 15831 bcode_op(&bbuilder, OP_PUSH_UNDEFINED);
Marko Mikulicic 0:c0ecb8bf28eb 15832
Marko Mikulicic 0:c0ecb8bf28eb 15833 /* push `this` */
Marko Mikulicic 0:c0ecb8bf28eb 15834 lit = bcode_add_lit(&bbuilder, this_object);
Marko Mikulicic 0:c0ecb8bf28eb 15835 bcode_push_lit(&bbuilder, lit);
Marko Mikulicic 0:c0ecb8bf28eb 15836
Marko Mikulicic 0:c0ecb8bf28eb 15837 /* push func literal */
Marko Mikulicic 0:c0ecb8bf28eb 15838 lit = bcode_add_lit(&bbuilder, func);
Marko Mikulicic 0:c0ecb8bf28eb 15839 bcode_push_lit(&bbuilder, lit);
Marko Mikulicic 0:c0ecb8bf28eb 15840
Marko Mikulicic 0:c0ecb8bf28eb 15841 /* push args */
Marko Mikulicic 0:c0ecb8bf28eb 15842 {
Marko Mikulicic 0:c0ecb8bf28eb 15843 int i;
Marko Mikulicic 0:c0ecb8bf28eb 15844 for (i = 0; i < args_cnt; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 15845 lit = bcode_add_lit(&bbuilder, v7_array_get(v7, args, i));
Marko Mikulicic 0:c0ecb8bf28eb 15846 bcode_push_lit(&bbuilder, lit);
Marko Mikulicic 0:c0ecb8bf28eb 15847 }
Marko Mikulicic 0:c0ecb8bf28eb 15848 }
Marko Mikulicic 0:c0ecb8bf28eb 15849
Marko Mikulicic 0:c0ecb8bf28eb 15850 bcode_op(&bbuilder, OP_CALL);
Marko Mikulicic 0:c0ecb8bf28eb 15851 /* TODO(dfrank): check if args <= 0x7f */
Marko Mikulicic 0:c0ecb8bf28eb 15852 bcode_op(&bbuilder, (uint8_t) args_cnt);
Marko Mikulicic 0:c0ecb8bf28eb 15853
Marko Mikulicic 0:c0ecb8bf28eb 15854 bcode_op(&bbuilder, OP_SWAP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 15855
Marko Mikulicic 0:c0ecb8bf28eb 15856 bcode_builder_finalize(&bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 15857 } else if (is_cfunction_lite(func) || is_cfunction_obj(v7, func)) {
Marko Mikulicic 0:c0ecb8bf28eb 15858 /* call cfunction */
Marko Mikulicic 0:c0ecb8bf28eb 15859
Marko Mikulicic 0:c0ecb8bf28eb 15860 V7_TRY(call_cfunction(v7, func, this_object, args, is_constructor, &_res));
Marko Mikulicic 0:c0ecb8bf28eb 15861
Marko Mikulicic 0:c0ecb8bf28eb 15862 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 15863 } else {
Marko Mikulicic 0:c0ecb8bf28eb 15864 /* value is not a function */
Marko Mikulicic 0:c0ecb8bf28eb 15865 V7_TRY(v7_throwf(v7, TYPE_ERROR, "value is not a function"));
Marko Mikulicic 0:c0ecb8bf28eb 15866 }
Marko Mikulicic 0:c0ecb8bf28eb 15867
Marko Mikulicic 0:c0ecb8bf28eb 15868 /* We now have bcode to evaluate; proceed to it */
Marko Mikulicic 0:c0ecb8bf28eb 15869
Marko Mikulicic 0:c0ecb8bf28eb 15870 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 15871 /*
Marko Mikulicic 0:c0ecb8bf28eb 15872 * Before we evaluate bcode, we can safely release AST since it's not needed
Marko Mikulicic 0:c0ecb8bf28eb 15873 * anymore. Note that there's no leak here: if we `goto clean` from somewhere
Marko Mikulicic 0:c0ecb8bf28eb 15874 * above, we'll anyway release the AST under `clean` as well.
Marko Mikulicic 0:c0ecb8bf28eb 15875 */
Marko Mikulicic 0:c0ecb8bf28eb 15876 release_ast(v7, a);
Marko Mikulicic 0:c0ecb8bf28eb 15877 a = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 15878 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 15879
Marko Mikulicic 0:c0ecb8bf28eb 15880 /* Evaluate bcode */
Marko Mikulicic 0:c0ecb8bf28eb 15881 V7_TRY(eval_bcode(v7, bcode, this_object, flags.line_no_reset, &_res));
Marko Mikulicic 0:c0ecb8bf28eb 15882
Marko Mikulicic 0:c0ecb8bf28eb 15883 clean:
Marko Mikulicic 0:c0ecb8bf28eb 15884
Marko Mikulicic 0:c0ecb8bf28eb 15885 /* free `src` if needed */
Marko Mikulicic 0:c0ecb8bf28eb 15886 /*
Marko Mikulicic 0:c0ecb8bf28eb 15887 * TODO(dfrank) : free it above, just after parsing, and make sure you use
Marko Mikulicic 0:c0ecb8bf28eb 15888 * V7_TRY2() with custom label instead of V7_TRY()
Marko Mikulicic 0:c0ecb8bf28eb 15889 */
Marko Mikulicic 0:c0ecb8bf28eb 15890 if (src != NULL && fr) {
Marko Mikulicic 0:c0ecb8bf28eb 15891 free((void *) src);
Marko Mikulicic 0:c0ecb8bf28eb 15892 }
Marko Mikulicic 0:c0ecb8bf28eb 15893
Marko Mikulicic 0:c0ecb8bf28eb 15894 /* disown and release current bcode */
Marko Mikulicic 0:c0ecb8bf28eb 15895 disown_bcode(v7, bcode);
Marko Mikulicic 0:c0ecb8bf28eb 15896 release_bcode(v7, bcode);
Marko Mikulicic 0:c0ecb8bf28eb 15897 bcode = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 15898
Marko Mikulicic 0:c0ecb8bf28eb 15899 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 15900 /* some exception happened. */
Marko Mikulicic 0:c0ecb8bf28eb 15901 _res = v7->vals.thrown_error;
Marko Mikulicic 0:c0ecb8bf28eb 15902
Marko Mikulicic 0:c0ecb8bf28eb 15903 /*
Marko Mikulicic 0:c0ecb8bf28eb 15904 * if this is a top-level bcode, clear thrown error from the v7 context
Marko Mikulicic 0:c0ecb8bf28eb 15905 *
Marko Mikulicic 0:c0ecb8bf28eb 15906 * TODO(dfrank): do we really need to do this?
Marko Mikulicic 0:c0ecb8bf28eb 15907 *
Marko Mikulicic 0:c0ecb8bf28eb 15908 * If we don't clear the error, then we should clear it manually after each
Marko Mikulicic 0:c0ecb8bf28eb 15909 * call to v7_exec() or friends; otherwise, all the following calls will
Marko Mikulicic 0:c0ecb8bf28eb 15910 * see this error.
Marko Mikulicic 0:c0ecb8bf28eb 15911 *
Marko Mikulicic 0:c0ecb8bf28eb 15912 * On the other hand, user would still need to clear the error if he calls
Marko Mikulicic 0:c0ecb8bf28eb 15913 * v7_exec() from some cfunction. So, currently, sometimes we don't need
Marko Mikulicic 0:c0ecb8bf28eb 15914 * to clear the error, and sometimes we do, which is confusing.
Marko Mikulicic 0:c0ecb8bf28eb 15915 */
Marko Mikulicic 0:c0ecb8bf28eb 15916 if (v7->act_bcodes.len == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 15917 v7->vals.thrown_error = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 15918 v7->is_thrown = 0;
Marko Mikulicic 0:c0ecb8bf28eb 15919 }
Marko Mikulicic 0:c0ecb8bf28eb 15920 }
Marko Mikulicic 0:c0ecb8bf28eb 15921
Marko Mikulicic 0:c0ecb8bf28eb 15922 /*
Marko Mikulicic 0:c0ecb8bf28eb 15923 * Data stack should have the same length as it was before evaluating script.
Marko Mikulicic 0:c0ecb8bf28eb 15924 */
Marko Mikulicic 0:c0ecb8bf28eb 15925 if (v7->stack.len != saved_stack_len) {
Marko Mikulicic 0:c0ecb8bf28eb 15926 fprintf(stderr, "len=%d, saved=%d\n", (int) v7->stack.len,
Marko Mikulicic 0:c0ecb8bf28eb 15927 (int) saved_stack_len);
Marko Mikulicic 0:c0ecb8bf28eb 15928 }
Marko Mikulicic 0:c0ecb8bf28eb 15929 assert(v7->stack.len == saved_stack_len);
Marko Mikulicic 0:c0ecb8bf28eb 15930
Marko Mikulicic 0:c0ecb8bf28eb 15931 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 15932 /*
Marko Mikulicic 0:c0ecb8bf28eb 15933 * release AST if needed (normally, it's already released above, before
Marko Mikulicic 0:c0ecb8bf28eb 15934 * bcode evaluation)
Marko Mikulicic 0:c0ecb8bf28eb 15935 */
Marko Mikulicic 0:c0ecb8bf28eb 15936 if (a != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 15937 release_ast(v7, a);
Marko Mikulicic 0:c0ecb8bf28eb 15938 a = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 15939 }
Marko Mikulicic 0:c0ecb8bf28eb 15940 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 15941
Marko Mikulicic 0:c0ecb8bf28eb 15942 if (is_constructor && !v7_is_object(_res)) {
Marko Mikulicic 0:c0ecb8bf28eb 15943 /* constructor returned non-object: replace it with `this` */
Marko Mikulicic 0:c0ecb8bf28eb 15944 _res = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 15945 }
Marko Mikulicic 0:c0ecb8bf28eb 15946
Marko Mikulicic 0:c0ecb8bf28eb 15947 /* Provide the caller with the result, if asked to do so */
Marko Mikulicic 0:c0ecb8bf28eb 15948 if (res != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 15949 *res = _res;
Marko Mikulicic 0:c0ecb8bf28eb 15950 }
Marko Mikulicic 0:c0ecb8bf28eb 15951
Marko Mikulicic 0:c0ecb8bf28eb 15952 #if defined(V7_ENABLE_STACK_TRACKING)
Marko Mikulicic 0:c0ecb8bf28eb 15953 {
Marko Mikulicic 0:c0ecb8bf28eb 15954 int diff = v7_stack_track_end(v7, &stack_track_ctx);
Marko Mikulicic 0:c0ecb8bf28eb 15955 if (diff > v7->stack_stat[V7_STACK_STAT_EXEC]) {
Marko Mikulicic 0:c0ecb8bf28eb 15956 v7->stack_stat[V7_STACK_STAT_EXEC] = diff;
Marko Mikulicic 0:c0ecb8bf28eb 15957 }
Marko Mikulicic 0:c0ecb8bf28eb 15958 }
Marko Mikulicic 0:c0ecb8bf28eb 15959 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15960
Marko Mikulicic 0:c0ecb8bf28eb 15961 tmp_frame_cleanup(&tf);
Marko Mikulicic 0:c0ecb8bf28eb 15962 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 15963 }
Marko Mikulicic 0:c0ecb8bf28eb 15964
Marko Mikulicic 0:c0ecb8bf28eb 15965 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 15966 V7_PRIVATE enum v7_err b_apply(struct v7 *v7, v7_val_t func, v7_val_t this_obj,
Marko Mikulicic 0:c0ecb8bf28eb 15967 v7_val_t args, uint8_t is_constructor,
Marko Mikulicic 0:c0ecb8bf28eb 15968 v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 15969 return b_exec(v7, NULL, 0, NULL, func, args, this_obj, 0, 0, is_constructor,
Marko Mikulicic 0:c0ecb8bf28eb 15970 res);
Marko Mikulicic 0:c0ecb8bf28eb 15971 }
Marko Mikulicic 0:c0ecb8bf28eb 15972 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 15973 #line 1 "v7/src/core.c"
Marko Mikulicic 0:c0ecb8bf28eb 15974 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15975 /*
Marko Mikulicic 0:c0ecb8bf28eb 15976 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 15977 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 15978 */
Marko Mikulicic 0:c0ecb8bf28eb 15979
Marko Mikulicic 0:c0ecb8bf28eb 15980 /* Amalgamated: #include "v7/builtin/builtin.h" */
Marko Mikulicic 0:c0ecb8bf28eb 15981 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 15982 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 15983 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 15984 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 15985 /* Amalgamated: #include "v7/src/array.h" */
Marko Mikulicic 0:c0ecb8bf28eb 15986 /* Amalgamated: #include "v7/src/slre.h" */
Marko Mikulicic 0:c0ecb8bf28eb 15987 /* Amalgamated: #include "v7/src/bcode.h" */
Marko Mikulicic 0:c0ecb8bf28eb 15988 /* Amalgamated: #include "v7/src/stdlib.h" */
Marko Mikulicic 0:c0ecb8bf28eb 15989 /* Amalgamated: #include "v7/src/gc.h" */
Marko Mikulicic 0:c0ecb8bf28eb 15990 /* Amalgamated: #include "v7/src/heapusage.h" */
Marko Mikulicic 0:c0ecb8bf28eb 15991 /* Amalgamated: #include "v7/src/eval.h" */
Marko Mikulicic 0:c0ecb8bf28eb 15992
Marko Mikulicic 0:c0ecb8bf28eb 15993 #ifdef V7_THAW
Marko Mikulicic 0:c0ecb8bf28eb 15994 extern struct v7_vals *fr_vals;
Marko Mikulicic 0:c0ecb8bf28eb 15995 #endif
Marko Mikulicic 0:c0ecb8bf28eb 15996
Marko Mikulicic 0:c0ecb8bf28eb 15997 #ifdef HAS_V7_INFINITY
Marko Mikulicic 0:c0ecb8bf28eb 15998 double _v7_infinity;
Marko Mikulicic 0:c0ecb8bf28eb 15999 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16000
Marko Mikulicic 0:c0ecb8bf28eb 16001 #ifdef HAS_V7_NAN
Marko Mikulicic 0:c0ecb8bf28eb 16002 double _v7_nan;
Marko Mikulicic 0:c0ecb8bf28eb 16003 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16004
Marko Mikulicic 0:c0ecb8bf28eb 16005 #if defined(V7_CYG_PROFILE_ON)
Marko Mikulicic 0:c0ecb8bf28eb 16006 struct v7 *v7_head = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 16007 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16008
Marko Mikulicic 0:c0ecb8bf28eb 16009 static void generic_object_destructor(struct v7 *v7, void *ptr) {
Marko Mikulicic 0:c0ecb8bf28eb 16010 struct v7_generic_object *o = (struct v7_generic_object *) ptr;
Marko Mikulicic 0:c0ecb8bf28eb 16011 struct v7_property *p;
Marko Mikulicic 0:c0ecb8bf28eb 16012 struct mbuf *abuf;
Marko Mikulicic 0:c0ecb8bf28eb 16013
Marko Mikulicic 0:c0ecb8bf28eb 16014 /* TODO(mkm): make regexp use user data API */
Marko Mikulicic 0:c0ecb8bf28eb 16015 p = v7_get_own_property2(v7, v7_object_to_value(&o->base), "", 0,
Marko Mikulicic 0:c0ecb8bf28eb 16016 _V7_PROPERTY_HIDDEN);
Marko Mikulicic 0:c0ecb8bf28eb 16017
Marko Mikulicic 0:c0ecb8bf28eb 16018 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 16019 if (p != NULL && (p->value & V7_TAG_MASK) == V7_TAG_REGEXP) {
Marko Mikulicic 0:c0ecb8bf28eb 16020 struct v7_regexp *rp = (struct v7_regexp *) get_ptr(p->value);
Marko Mikulicic 0:c0ecb8bf28eb 16021 v7_disown(v7, &rp->regexp_string);
Marko Mikulicic 0:c0ecb8bf28eb 16022 slre_free(rp->compiled_regexp);
Marko Mikulicic 0:c0ecb8bf28eb 16023 free(rp);
Marko Mikulicic 0:c0ecb8bf28eb 16024 }
Marko Mikulicic 0:c0ecb8bf28eb 16025 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16026
Marko Mikulicic 0:c0ecb8bf28eb 16027 if (o->base.attributes & V7_OBJ_DENSE_ARRAY) {
Marko Mikulicic 0:c0ecb8bf28eb 16028 if (p != NULL &&
Marko Mikulicic 0:c0ecb8bf28eb 16029 ((abuf = (struct mbuf *) v7_get_ptr(v7, p->value)) != NULL)) {
Marko Mikulicic 0:c0ecb8bf28eb 16030 mbuf_free(abuf);
Marko Mikulicic 0:c0ecb8bf28eb 16031 free(abuf);
Marko Mikulicic 0:c0ecb8bf28eb 16032 }
Marko Mikulicic 0:c0ecb8bf28eb 16033 }
Marko Mikulicic 0:c0ecb8bf28eb 16034
Marko Mikulicic 0:c0ecb8bf28eb 16035 if (o->base.attributes & V7_OBJ_HAS_DESTRUCTOR) {
Marko Mikulicic 0:c0ecb8bf28eb 16036 struct v7_property *p;
Marko Mikulicic 0:c0ecb8bf28eb 16037 for (p = o->base.properties; p != NULL; p = p->next) {
Marko Mikulicic 0:c0ecb8bf28eb 16038 if (p->attributes & _V7_PROPERTY_USER_DATA_AND_DESTRUCTOR) {
Marko Mikulicic 0:c0ecb8bf28eb 16039 if (v7_is_foreign(p->name)) {
Marko Mikulicic 0:c0ecb8bf28eb 16040 v7_destructor_cb_t *cb =
Marko Mikulicic 0:c0ecb8bf28eb 16041 (v7_destructor_cb_t *) v7_get_ptr(v7, p->name);
Marko Mikulicic 0:c0ecb8bf28eb 16042 cb(v7, v7_get_ptr(v7, p->value));
Marko Mikulicic 0:c0ecb8bf28eb 16043 }
Marko Mikulicic 0:c0ecb8bf28eb 16044 break;
Marko Mikulicic 0:c0ecb8bf28eb 16045 }
Marko Mikulicic 0:c0ecb8bf28eb 16046 }
Marko Mikulicic 0:c0ecb8bf28eb 16047 }
Marko Mikulicic 0:c0ecb8bf28eb 16048
Marko Mikulicic 0:c0ecb8bf28eb 16049 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 16050 o->base.entity_id_base = V7_ENTITY_ID_PART_NONE;
Marko Mikulicic 0:c0ecb8bf28eb 16051 o->base.entity_id_spec = V7_ENTITY_ID_PART_NONE;
Marko Mikulicic 0:c0ecb8bf28eb 16052 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16053 }
Marko Mikulicic 0:c0ecb8bf28eb 16054
Marko Mikulicic 0:c0ecb8bf28eb 16055 static void function_destructor(struct v7 *v7, void *ptr) {
Marko Mikulicic 0:c0ecb8bf28eb 16056 struct v7_js_function *f = (struct v7_js_function *) ptr;
Marko Mikulicic 0:c0ecb8bf28eb 16057 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 16058 if (f == NULL) return;
Marko Mikulicic 0:c0ecb8bf28eb 16059
Marko Mikulicic 0:c0ecb8bf28eb 16060 if (f->bcode != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 16061 release_bcode(v7, f->bcode);
Marko Mikulicic 0:c0ecb8bf28eb 16062 }
Marko Mikulicic 0:c0ecb8bf28eb 16063
Marko Mikulicic 0:c0ecb8bf28eb 16064 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 16065 f->base.entity_id_base = V7_ENTITY_ID_PART_NONE;
Marko Mikulicic 0:c0ecb8bf28eb 16066 f->base.entity_id_spec = V7_ENTITY_ID_PART_NONE;
Marko Mikulicic 0:c0ecb8bf28eb 16067 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16068 }
Marko Mikulicic 0:c0ecb8bf28eb 16069
Marko Mikulicic 0:c0ecb8bf28eb 16070 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 16071 static void property_destructor(struct v7 *v7, void *ptr) {
Marko Mikulicic 0:c0ecb8bf28eb 16072 struct v7_property *p = (struct v7_property *) ptr;
Marko Mikulicic 0:c0ecb8bf28eb 16073 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 16074 if (p == NULL) return;
Marko Mikulicic 0:c0ecb8bf28eb 16075
Marko Mikulicic 0:c0ecb8bf28eb 16076 p->entity_id = V7_ENTITY_ID_NONE;
Marko Mikulicic 0:c0ecb8bf28eb 16077 }
Marko Mikulicic 0:c0ecb8bf28eb 16078 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16079
Marko Mikulicic 0:c0ecb8bf28eb 16080 struct v7 *v7_create(void) {
Marko Mikulicic 0:c0ecb8bf28eb 16081 struct v7_create_opts opts;
Marko Mikulicic 0:c0ecb8bf28eb 16082 memset(&opts, 0, sizeof(opts));
Marko Mikulicic 0:c0ecb8bf28eb 16083 return v7_create_opt(opts);
Marko Mikulicic 0:c0ecb8bf28eb 16084 }
Marko Mikulicic 0:c0ecb8bf28eb 16085
Marko Mikulicic 0:c0ecb8bf28eb 16086 struct v7 *v7_create_opt(struct v7_create_opts opts) {
Marko Mikulicic 0:c0ecb8bf28eb 16087 struct v7 *v7 = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 16088 char z = 0;
Marko Mikulicic 0:c0ecb8bf28eb 16089
Marko Mikulicic 0:c0ecb8bf28eb 16090 #if defined(HAS_V7_INFINITY) || defined(HAS_V7_NAN)
Marko Mikulicic 0:c0ecb8bf28eb 16091 double zero = 0.0;
Marko Mikulicic 0:c0ecb8bf28eb 16092 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16093
Marko Mikulicic 0:c0ecb8bf28eb 16094 #ifdef HAS_V7_INFINITY
Marko Mikulicic 0:c0ecb8bf28eb 16095 _v7_infinity = 1.0 / zero;
Marko Mikulicic 0:c0ecb8bf28eb 16096 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16097 #ifdef HAS_V7_NAN
Marko Mikulicic 0:c0ecb8bf28eb 16098 _v7_nan = zero / zero;
Marko Mikulicic 0:c0ecb8bf28eb 16099 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16100
Marko Mikulicic 0:c0ecb8bf28eb 16101 if (opts.object_arena_size == 0) opts.object_arena_size = 200;
Marko Mikulicic 0:c0ecb8bf28eb 16102 if (opts.function_arena_size == 0) opts.function_arena_size = 100;
Marko Mikulicic 0:c0ecb8bf28eb 16103 if (opts.property_arena_size == 0) opts.property_arena_size = 400;
Marko Mikulicic 0:c0ecb8bf28eb 16104
Marko Mikulicic 0:c0ecb8bf28eb 16105 if ((v7 = (struct v7 *) calloc(1, sizeof(*v7))) != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 16106 #ifdef V7_STACK_SIZE
Marko Mikulicic 0:c0ecb8bf28eb 16107 v7->sp_limit = (void *) ((uintptr_t) opts.c_stack_base - (V7_STACK_SIZE));
Marko Mikulicic 0:c0ecb8bf28eb 16108 v7->sp_lwm = opts.c_stack_base;
Marko Mikulicic 0:c0ecb8bf28eb 16109 #ifdef V7_STACK_GUARD_MIN_SIZE
Marko Mikulicic 0:c0ecb8bf28eb 16110 v7_sp_limit = v7->sp_limit;
Marko Mikulicic 0:c0ecb8bf28eb 16111 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16112 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16113
Marko Mikulicic 0:c0ecb8bf28eb 16114 #if defined(V7_CYG_PROFILE_ON)
Marko Mikulicic 0:c0ecb8bf28eb 16115 v7->next_v7 = v7_head;
Marko Mikulicic 0:c0ecb8bf28eb 16116 v7_head = v7;
Marko Mikulicic 0:c0ecb8bf28eb 16117 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16118
Marko Mikulicic 0:c0ecb8bf28eb 16119 #ifndef V7_DISABLE_STR_ALLOC_SEQ
Marko Mikulicic 0:c0ecb8bf28eb 16120 v7->gc_next_asn = 0;
Marko Mikulicic 0:c0ecb8bf28eb 16121 v7->gc_min_asn = 0;
Marko Mikulicic 0:c0ecb8bf28eb 16122 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16123
Marko Mikulicic 0:c0ecb8bf28eb 16124 v7->cur_dense_prop =
Marko Mikulicic 0:c0ecb8bf28eb 16125 (struct v7_property *) calloc(1, sizeof(struct v7_property));
Marko Mikulicic 0:c0ecb8bf28eb 16126 gc_arena_init(&v7->generic_object_arena, sizeof(struct v7_generic_object),
Marko Mikulicic 0:c0ecb8bf28eb 16127 opts.object_arena_size, 10, "object");
Marko Mikulicic 0:c0ecb8bf28eb 16128 v7->generic_object_arena.destructor = generic_object_destructor;
Marko Mikulicic 0:c0ecb8bf28eb 16129 gc_arena_init(&v7->function_arena, sizeof(struct v7_js_function),
Marko Mikulicic 0:c0ecb8bf28eb 16130 opts.function_arena_size, 10, "function");
Marko Mikulicic 0:c0ecb8bf28eb 16131 v7->function_arena.destructor = function_destructor;
Marko Mikulicic 0:c0ecb8bf28eb 16132 gc_arena_init(&v7->property_arena, sizeof(struct v7_property),
Marko Mikulicic 0:c0ecb8bf28eb 16133 opts.property_arena_size, 10, "property");
Marko Mikulicic 0:c0ecb8bf28eb 16134 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 16135 v7->property_arena.destructor = property_destructor;
Marko Mikulicic 0:c0ecb8bf28eb 16136 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16137
Marko Mikulicic 0:c0ecb8bf28eb 16138 /*
Marko Mikulicic 0:c0ecb8bf28eb 16139 * The compacting GC exploits the null terminator of the previous
Marko Mikulicic 0:c0ecb8bf28eb 16140 * string as marker.
Marko Mikulicic 0:c0ecb8bf28eb 16141 */
Marko Mikulicic 0:c0ecb8bf28eb 16142 mbuf_append(&v7->owned_strings, &z, 1);
Marko Mikulicic 0:c0ecb8bf28eb 16143
Marko Mikulicic 0:c0ecb8bf28eb 16144 v7->inhibit_gc = 1;
Marko Mikulicic 0:c0ecb8bf28eb 16145 v7->vals.thrown_error = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 16146
Marko Mikulicic 0:c0ecb8bf28eb 16147 v7->call_stack = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 16148 v7->bottom_call_frame = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 16149
Marko Mikulicic 0:c0ecb8bf28eb 16150 #if defined(V7_THAW) && !defined(V7_FREEZE_NOT_READONLY)
Marko Mikulicic 0:c0ecb8bf28eb 16151 {
Marko Mikulicic 0:c0ecb8bf28eb 16152 struct v7_generic_object *obj;
Marko Mikulicic 0:c0ecb8bf28eb 16153 v7->vals = *fr_vals;
Marko Mikulicic 0:c0ecb8bf28eb 16154 v7->vals.global_object = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 16155
Marko Mikulicic 0:c0ecb8bf28eb 16156 /*
Marko Mikulicic 0:c0ecb8bf28eb 16157 * The global object has to be mutable.
Marko Mikulicic 0:c0ecb8bf28eb 16158 */
Marko Mikulicic 0:c0ecb8bf28eb 16159 obj = get_generic_object_struct(v7->vals.global_object);
Marko Mikulicic 0:c0ecb8bf28eb 16160 *obj = *get_generic_object_struct(fr_vals->global_object);
Marko Mikulicic 0:c0ecb8bf28eb 16161 obj->base.attributes &= ~(V7_OBJ_NOT_EXTENSIBLE | V7_OBJ_OFF_HEAP);
Marko Mikulicic 0:c0ecb8bf28eb 16162 v7_set(v7, v7->vals.global_object, "global", 6, v7->vals.global_object);
Marko Mikulicic 0:c0ecb8bf28eb 16163 }
Marko Mikulicic 0:c0ecb8bf28eb 16164 #else
Marko Mikulicic 0:c0ecb8bf28eb 16165 init_stdlib(v7);
Marko Mikulicic 0:c0ecb8bf28eb 16166 init_file(v7);
Marko Mikulicic 0:c0ecb8bf28eb 16167 init_crypto(v7);
Marko Mikulicic 0:c0ecb8bf28eb 16168 init_socket(v7);
Marko Mikulicic 0:c0ecb8bf28eb 16169 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16170
Marko Mikulicic 0:c0ecb8bf28eb 16171 v7->inhibit_gc = 0;
Marko Mikulicic 0:c0ecb8bf28eb 16172 }
Marko Mikulicic 0:c0ecb8bf28eb 16173
Marko Mikulicic 0:c0ecb8bf28eb 16174 return v7;
Marko Mikulicic 0:c0ecb8bf28eb 16175 }
Marko Mikulicic 0:c0ecb8bf28eb 16176
Marko Mikulicic 0:c0ecb8bf28eb 16177 val_t v7_get_global(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 16178 return v7->vals.global_object;
Marko Mikulicic 0:c0ecb8bf28eb 16179 }
Marko Mikulicic 0:c0ecb8bf28eb 16180
Marko Mikulicic 0:c0ecb8bf28eb 16181 void v7_destroy(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 16182 if (v7 == NULL) return;
Marko Mikulicic 0:c0ecb8bf28eb 16183 gc_arena_destroy(v7, &v7->generic_object_arena);
Marko Mikulicic 0:c0ecb8bf28eb 16184 gc_arena_destroy(v7, &v7->function_arena);
Marko Mikulicic 0:c0ecb8bf28eb 16185 gc_arena_destroy(v7, &v7->property_arena);
Marko Mikulicic 0:c0ecb8bf28eb 16186
Marko Mikulicic 0:c0ecb8bf28eb 16187 mbuf_free(&v7->owned_strings);
Marko Mikulicic 0:c0ecb8bf28eb 16188 mbuf_free(&v7->owned_values);
Marko Mikulicic 0:c0ecb8bf28eb 16189 mbuf_free(&v7->foreign_strings);
Marko Mikulicic 0:c0ecb8bf28eb 16190 mbuf_free(&v7->json_visited_stack);
Marko Mikulicic 0:c0ecb8bf28eb 16191 mbuf_free(&v7->tmp_stack);
Marko Mikulicic 0:c0ecb8bf28eb 16192 mbuf_free(&v7->act_bcodes);
Marko Mikulicic 0:c0ecb8bf28eb 16193 mbuf_free(&v7->stack);
Marko Mikulicic 0:c0ecb8bf28eb 16194
Marko Mikulicic 0:c0ecb8bf28eb 16195 #if defined(V7_CYG_PROFILE_ON)
Marko Mikulicic 0:c0ecb8bf28eb 16196 /* delete this v7 */
Marko Mikulicic 0:c0ecb8bf28eb 16197 {
Marko Mikulicic 0:c0ecb8bf28eb 16198 struct v7 *v, **prevp = &v7_head;
Marko Mikulicic 0:c0ecb8bf28eb 16199 for (v = v7_head; v != NULL; prevp = &v->next_v7, v = v->next_v7) {
Marko Mikulicic 0:c0ecb8bf28eb 16200 if (v == v7) {
Marko Mikulicic 0:c0ecb8bf28eb 16201 *prevp = v->next_v7;
Marko Mikulicic 0:c0ecb8bf28eb 16202 break;
Marko Mikulicic 0:c0ecb8bf28eb 16203 }
Marko Mikulicic 0:c0ecb8bf28eb 16204 }
Marko Mikulicic 0:c0ecb8bf28eb 16205 }
Marko Mikulicic 0:c0ecb8bf28eb 16206 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16207
Marko Mikulicic 0:c0ecb8bf28eb 16208 free(v7->cur_dense_prop);
Marko Mikulicic 0:c0ecb8bf28eb 16209 free(v7);
Marko Mikulicic 0:c0ecb8bf28eb 16210 }
Marko Mikulicic 0:c0ecb8bf28eb 16211
Marko Mikulicic 0:c0ecb8bf28eb 16212 v7_val_t v7_get_this(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 16213 /*
Marko Mikulicic 0:c0ecb8bf28eb 16214 * By default, when there's no active call frame, will return Global Object
Marko Mikulicic 0:c0ecb8bf28eb 16215 */
Marko Mikulicic 0:c0ecb8bf28eb 16216 v7_val_t ret = v7->vals.global_object;
Marko Mikulicic 0:c0ecb8bf28eb 16217
Marko Mikulicic 0:c0ecb8bf28eb 16218 struct v7_call_frame_base *call_frame =
Marko Mikulicic 0:c0ecb8bf28eb 16219 find_call_frame(v7, V7_CALL_FRAME_MASK_BCODE | V7_CALL_FRAME_MASK_CFUNC);
Marko Mikulicic 0:c0ecb8bf28eb 16220
Marko Mikulicic 0:c0ecb8bf28eb 16221 if (call_frame != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 16222 if (call_frame->type_mask & V7_CALL_FRAME_MASK_BCODE) {
Marko Mikulicic 0:c0ecb8bf28eb 16223 ret = ((struct v7_call_frame_bcode *) call_frame)->vals.this_obj;
Marko Mikulicic 0:c0ecb8bf28eb 16224 } else if (call_frame->type_mask & V7_CALL_FRAME_MASK_CFUNC) {
Marko Mikulicic 0:c0ecb8bf28eb 16225 ret = ((struct v7_call_frame_cfunc *) call_frame)->vals.this_obj;
Marko Mikulicic 0:c0ecb8bf28eb 16226 } else {
Marko Mikulicic 0:c0ecb8bf28eb 16227 assert(0);
Marko Mikulicic 0:c0ecb8bf28eb 16228 }
Marko Mikulicic 0:c0ecb8bf28eb 16229 }
Marko Mikulicic 0:c0ecb8bf28eb 16230
Marko Mikulicic 0:c0ecb8bf28eb 16231 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 16232 }
Marko Mikulicic 0:c0ecb8bf28eb 16233
Marko Mikulicic 0:c0ecb8bf28eb 16234 V7_PRIVATE v7_val_t get_scope(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 16235 struct v7_call_frame_private *call_frame =
Marko Mikulicic 0:c0ecb8bf28eb 16236 (struct v7_call_frame_private *) find_call_frame(
Marko Mikulicic 0:c0ecb8bf28eb 16237 v7, V7_CALL_FRAME_MASK_PRIVATE);
Marko Mikulicic 0:c0ecb8bf28eb 16238
Marko Mikulicic 0:c0ecb8bf28eb 16239 if (call_frame != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 16240 return call_frame->vals.scope;
Marko Mikulicic 0:c0ecb8bf28eb 16241 } else {
Marko Mikulicic 0:c0ecb8bf28eb 16242 /* No active call frame, return global object */
Marko Mikulicic 0:c0ecb8bf28eb 16243 return v7->vals.global_object;
Marko Mikulicic 0:c0ecb8bf28eb 16244 }
Marko Mikulicic 0:c0ecb8bf28eb 16245 }
Marko Mikulicic 0:c0ecb8bf28eb 16246
Marko Mikulicic 0:c0ecb8bf28eb 16247 V7_PRIVATE uint8_t is_strict_mode(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 16248 struct v7_call_frame_bcode *call_frame =
Marko Mikulicic 0:c0ecb8bf28eb 16249 (struct v7_call_frame_bcode *) find_call_frame(v7,
Marko Mikulicic 0:c0ecb8bf28eb 16250 V7_CALL_FRAME_MASK_BCODE);
Marko Mikulicic 0:c0ecb8bf28eb 16251
Marko Mikulicic 0:c0ecb8bf28eb 16252 if (call_frame != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 16253 return call_frame->bcode->strict_mode;
Marko Mikulicic 0:c0ecb8bf28eb 16254 } else {
Marko Mikulicic 0:c0ecb8bf28eb 16255 /* No active call frame, assume no strict mode */
Marko Mikulicic 0:c0ecb8bf28eb 16256 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 16257 }
Marko Mikulicic 0:c0ecb8bf28eb 16258 }
Marko Mikulicic 0:c0ecb8bf28eb 16259
Marko Mikulicic 0:c0ecb8bf28eb 16260 v7_val_t v7_get_arguments(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 16261 return v7->vals.arguments;
Marko Mikulicic 0:c0ecb8bf28eb 16262 }
Marko Mikulicic 0:c0ecb8bf28eb 16263
Marko Mikulicic 0:c0ecb8bf28eb 16264 v7_val_t v7_arg(struct v7 *v7, unsigned long n) {
Marko Mikulicic 0:c0ecb8bf28eb 16265 return v7_array_get(v7, v7->vals.arguments, n);
Marko Mikulicic 0:c0ecb8bf28eb 16266 }
Marko Mikulicic 0:c0ecb8bf28eb 16267
Marko Mikulicic 0:c0ecb8bf28eb 16268 unsigned long v7_argc(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 16269 return v7_array_length(v7, v7->vals.arguments);
Marko Mikulicic 0:c0ecb8bf28eb 16270 }
Marko Mikulicic 0:c0ecb8bf28eb 16271
Marko Mikulicic 0:c0ecb8bf28eb 16272 void v7_own(struct v7 *v7, v7_val_t *v) {
Marko Mikulicic 0:c0ecb8bf28eb 16273 heapusage_dont_count(1);
Marko Mikulicic 0:c0ecb8bf28eb 16274 mbuf_append(&v7->owned_values, &v, sizeof(v));
Marko Mikulicic 0:c0ecb8bf28eb 16275 heapusage_dont_count(0);
Marko Mikulicic 0:c0ecb8bf28eb 16276 }
Marko Mikulicic 0:c0ecb8bf28eb 16277
Marko Mikulicic 0:c0ecb8bf28eb 16278 int v7_disown(struct v7 *v7, v7_val_t *v) {
Marko Mikulicic 0:c0ecb8bf28eb 16279 v7_val_t **vp =
Marko Mikulicic 0:c0ecb8bf28eb 16280 (v7_val_t **) (v7->owned_values.buf + v7->owned_values.len - sizeof(v));
Marko Mikulicic 0:c0ecb8bf28eb 16281
Marko Mikulicic 0:c0ecb8bf28eb 16282 for (; (char *) vp >= v7->owned_values.buf; vp--) {
Marko Mikulicic 0:c0ecb8bf28eb 16283 if (*vp == v) {
Marko Mikulicic 0:c0ecb8bf28eb 16284 *vp = *(v7_val_t **) (v7->owned_values.buf + v7->owned_values.len -
Marko Mikulicic 0:c0ecb8bf28eb 16285 sizeof(v));
Marko Mikulicic 0:c0ecb8bf28eb 16286 v7->owned_values.len -= sizeof(v);
Marko Mikulicic 0:c0ecb8bf28eb 16287 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 16288 }
Marko Mikulicic 0:c0ecb8bf28eb 16289 }
Marko Mikulicic 0:c0ecb8bf28eb 16290
Marko Mikulicic 0:c0ecb8bf28eb 16291 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 16292 }
Marko Mikulicic 0:c0ecb8bf28eb 16293
Marko Mikulicic 0:c0ecb8bf28eb 16294 void v7_set_gc_enabled(struct v7 *v7, int enabled) {
Marko Mikulicic 0:c0ecb8bf28eb 16295 v7->inhibit_gc = !enabled;
Marko Mikulicic 0:c0ecb8bf28eb 16296 }
Marko Mikulicic 0:c0ecb8bf28eb 16297
Marko Mikulicic 0:c0ecb8bf28eb 16298 void v7_interrupt(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 16299 v7->interrupted = 1;
Marko Mikulicic 0:c0ecb8bf28eb 16300 }
Marko Mikulicic 0:c0ecb8bf28eb 16301
Marko Mikulicic 0:c0ecb8bf28eb 16302 const char *v7_get_parser_error(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 16303 return v7->error_msg;
Marko Mikulicic 0:c0ecb8bf28eb 16304 }
Marko Mikulicic 0:c0ecb8bf28eb 16305
Marko Mikulicic 0:c0ecb8bf28eb 16306 #if defined(V7_ENABLE_STACK_TRACKING)
Marko Mikulicic 0:c0ecb8bf28eb 16307
Marko Mikulicic 0:c0ecb8bf28eb 16308 int v7_stack_stat(struct v7 *v7, enum v7_stack_stat_what what) {
Marko Mikulicic 0:c0ecb8bf28eb 16309 assert(what < V7_STACK_STATS_CNT);
Marko Mikulicic 0:c0ecb8bf28eb 16310 return v7->stack_stat[what];
Marko Mikulicic 0:c0ecb8bf28eb 16311 }
Marko Mikulicic 0:c0ecb8bf28eb 16312
Marko Mikulicic 0:c0ecb8bf28eb 16313 void v7_stack_stat_clean(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 16314 memset(v7->stack_stat, 0x00, sizeof(v7->stack_stat));
Marko Mikulicic 0:c0ecb8bf28eb 16315 }
Marko Mikulicic 0:c0ecb8bf28eb 16316
Marko Mikulicic 0:c0ecb8bf28eb 16317 #endif /* V7_ENABLE_STACK_TRACKING */
Marko Mikulicic 0:c0ecb8bf28eb 16318 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 16319 #line 1 "v7/src/primitive.c"
Marko Mikulicic 0:c0ecb8bf28eb 16320 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16321 /*
Marko Mikulicic 0:c0ecb8bf28eb 16322 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 16323 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 16324 */
Marko Mikulicic 0:c0ecb8bf28eb 16325
Marko Mikulicic 0:c0ecb8bf28eb 16326 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16327 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16328 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16329
Marko Mikulicic 0:c0ecb8bf28eb 16330 /* Number {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 16331
Marko Mikulicic 0:c0ecb8bf28eb 16332 NOINSTR static v7_val_t mk_number(double v) {
Marko Mikulicic 0:c0ecb8bf28eb 16333 val_t res;
Marko Mikulicic 0:c0ecb8bf28eb 16334 /* not every NaN is a JS NaN */
Marko Mikulicic 0:c0ecb8bf28eb 16335 if (isnan(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 16336 res = V7_TAG_NAN;
Marko Mikulicic 0:c0ecb8bf28eb 16337 } else {
Marko Mikulicic 0:c0ecb8bf28eb 16338 union {
Marko Mikulicic 0:c0ecb8bf28eb 16339 double d;
Marko Mikulicic 0:c0ecb8bf28eb 16340 val_t r;
Marko Mikulicic 0:c0ecb8bf28eb 16341 } u;
Marko Mikulicic 0:c0ecb8bf28eb 16342 u.d = v;
Marko Mikulicic 0:c0ecb8bf28eb 16343 res = u.r;
Marko Mikulicic 0:c0ecb8bf28eb 16344 }
Marko Mikulicic 0:c0ecb8bf28eb 16345 return res;
Marko Mikulicic 0:c0ecb8bf28eb 16346 }
Marko Mikulicic 0:c0ecb8bf28eb 16347
Marko Mikulicic 0:c0ecb8bf28eb 16348 NOINSTR static double get_double(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16349 union {
Marko Mikulicic 0:c0ecb8bf28eb 16350 double d;
Marko Mikulicic 0:c0ecb8bf28eb 16351 val_t v;
Marko Mikulicic 0:c0ecb8bf28eb 16352 } u;
Marko Mikulicic 0:c0ecb8bf28eb 16353 u.v = v;
Marko Mikulicic 0:c0ecb8bf28eb 16354 /* Due to NaN packing, any non-numeric value is already a valid NaN value */
Marko Mikulicic 0:c0ecb8bf28eb 16355 return u.d;
Marko Mikulicic 0:c0ecb8bf28eb 16356 }
Marko Mikulicic 0:c0ecb8bf28eb 16357
Marko Mikulicic 0:c0ecb8bf28eb 16358 NOINSTR static v7_val_t mk_boolean(int v) {
Marko Mikulicic 0:c0ecb8bf28eb 16359 return (!!v) | V7_TAG_BOOLEAN;
Marko Mikulicic 0:c0ecb8bf28eb 16360 }
Marko Mikulicic 0:c0ecb8bf28eb 16361
Marko Mikulicic 0:c0ecb8bf28eb 16362 NOINSTR static int get_bool(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16363 if (v7_is_boolean(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 16364 return v & 1;
Marko Mikulicic 0:c0ecb8bf28eb 16365 } else {
Marko Mikulicic 0:c0ecb8bf28eb 16366 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 16367 }
Marko Mikulicic 0:c0ecb8bf28eb 16368 }
Marko Mikulicic 0:c0ecb8bf28eb 16369
Marko Mikulicic 0:c0ecb8bf28eb 16370 NOINSTR v7_val_t v7_mk_number(struct v7 *v7, double v) {
Marko Mikulicic 0:c0ecb8bf28eb 16371 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 16372 return mk_number(v);
Marko Mikulicic 0:c0ecb8bf28eb 16373 }
Marko Mikulicic 0:c0ecb8bf28eb 16374
Marko Mikulicic 0:c0ecb8bf28eb 16375 NOINSTR double v7_get_double(struct v7 *v7, v7_val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16376 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 16377 return get_double(v);
Marko Mikulicic 0:c0ecb8bf28eb 16378 }
Marko Mikulicic 0:c0ecb8bf28eb 16379
Marko Mikulicic 0:c0ecb8bf28eb 16380 NOINSTR int v7_get_int(struct v7 *v7, v7_val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16381 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 16382 return (int) get_double(v);
Marko Mikulicic 0:c0ecb8bf28eb 16383 }
Marko Mikulicic 0:c0ecb8bf28eb 16384
Marko Mikulicic 0:c0ecb8bf28eb 16385 int v7_is_number(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16386 return v == V7_TAG_NAN || !isnan(get_double(v));
Marko Mikulicic 0:c0ecb8bf28eb 16387 }
Marko Mikulicic 0:c0ecb8bf28eb 16388
Marko Mikulicic 0:c0ecb8bf28eb 16389 V7_PRIVATE int is_finite(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16390 return v7_is_number(v) && v != V7_TAG_NAN && !isinf(v7_get_double(v7, v));
Marko Mikulicic 0:c0ecb8bf28eb 16391 }
Marko Mikulicic 0:c0ecb8bf28eb 16392
Marko Mikulicic 0:c0ecb8bf28eb 16393 /* }}} Number */
Marko Mikulicic 0:c0ecb8bf28eb 16394
Marko Mikulicic 0:c0ecb8bf28eb 16395 /* Boolean {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 16396
Marko Mikulicic 0:c0ecb8bf28eb 16397 NOINSTR v7_val_t v7_mk_boolean(struct v7 *v7, int v) {
Marko Mikulicic 0:c0ecb8bf28eb 16398 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 16399 return mk_boolean(v);
Marko Mikulicic 0:c0ecb8bf28eb 16400 }
Marko Mikulicic 0:c0ecb8bf28eb 16401
Marko Mikulicic 0:c0ecb8bf28eb 16402 NOINSTR int v7_get_bool(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16403 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 16404 return get_bool(v);
Marko Mikulicic 0:c0ecb8bf28eb 16405 }
Marko Mikulicic 0:c0ecb8bf28eb 16406
Marko Mikulicic 0:c0ecb8bf28eb 16407 int v7_is_boolean(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16408 return (v & V7_TAG_MASK) == V7_TAG_BOOLEAN;
Marko Mikulicic 0:c0ecb8bf28eb 16409 }
Marko Mikulicic 0:c0ecb8bf28eb 16410
Marko Mikulicic 0:c0ecb8bf28eb 16411 /* }}} Boolean */
Marko Mikulicic 0:c0ecb8bf28eb 16412
Marko Mikulicic 0:c0ecb8bf28eb 16413 /* null {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 16414
Marko Mikulicic 0:c0ecb8bf28eb 16415 NOINSTR v7_val_t v7_mk_null(void) {
Marko Mikulicic 0:c0ecb8bf28eb 16416 return V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 16417 }
Marko Mikulicic 0:c0ecb8bf28eb 16418
Marko Mikulicic 0:c0ecb8bf28eb 16419 int v7_is_null(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16420 return v == V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 16421 }
Marko Mikulicic 0:c0ecb8bf28eb 16422
Marko Mikulicic 0:c0ecb8bf28eb 16423 /* }}} null */
Marko Mikulicic 0:c0ecb8bf28eb 16424
Marko Mikulicic 0:c0ecb8bf28eb 16425 /* undefined {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 16426
Marko Mikulicic 0:c0ecb8bf28eb 16427 NOINSTR v7_val_t v7_mk_undefined(void) {
Marko Mikulicic 0:c0ecb8bf28eb 16428 return V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 16429 }
Marko Mikulicic 0:c0ecb8bf28eb 16430
Marko Mikulicic 0:c0ecb8bf28eb 16431 int v7_is_undefined(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16432 return v == V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 16433 }
Marko Mikulicic 0:c0ecb8bf28eb 16434
Marko Mikulicic 0:c0ecb8bf28eb 16435 /* }}} undefined */
Marko Mikulicic 0:c0ecb8bf28eb 16436
Marko Mikulicic 0:c0ecb8bf28eb 16437 /* Foreign {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 16438
Marko Mikulicic 0:c0ecb8bf28eb 16439 V7_PRIVATE val_t pointer_to_value(void *p) {
Marko Mikulicic 0:c0ecb8bf28eb 16440 uint64_t n = ((uint64_t)(uintptr_t) p);
Marko Mikulicic 0:c0ecb8bf28eb 16441
Marko Mikulicic 0:c0ecb8bf28eb 16442 assert((n & V7_TAG_MASK) == 0 || (n & V7_TAG_MASK) == (~0 & V7_TAG_MASK));
Marko Mikulicic 0:c0ecb8bf28eb 16443 return n & ~V7_TAG_MASK;
Marko Mikulicic 0:c0ecb8bf28eb 16444 }
Marko Mikulicic 0:c0ecb8bf28eb 16445
Marko Mikulicic 0:c0ecb8bf28eb 16446 V7_PRIVATE void *get_ptr(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16447 return (void *) (uintptr_t)(v & 0xFFFFFFFFFFFFUL);
Marko Mikulicic 0:c0ecb8bf28eb 16448 }
Marko Mikulicic 0:c0ecb8bf28eb 16449
Marko Mikulicic 0:c0ecb8bf28eb 16450 NOINSTR void *v7_get_ptr(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16451 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 16452 if (!v7_is_foreign(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 16453 return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 16454 }
Marko Mikulicic 0:c0ecb8bf28eb 16455 return get_ptr(v);
Marko Mikulicic 0:c0ecb8bf28eb 16456 }
Marko Mikulicic 0:c0ecb8bf28eb 16457
Marko Mikulicic 0:c0ecb8bf28eb 16458 NOINSTR v7_val_t v7_mk_foreign(struct v7 *v7, void *p) {
Marko Mikulicic 0:c0ecb8bf28eb 16459 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 16460 return pointer_to_value(p) | V7_TAG_FOREIGN;
Marko Mikulicic 0:c0ecb8bf28eb 16461 }
Marko Mikulicic 0:c0ecb8bf28eb 16462
Marko Mikulicic 0:c0ecb8bf28eb 16463 int v7_is_foreign(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16464 return (v & V7_TAG_MASK) == V7_TAG_FOREIGN;
Marko Mikulicic 0:c0ecb8bf28eb 16465 }
Marko Mikulicic 0:c0ecb8bf28eb 16466
Marko Mikulicic 0:c0ecb8bf28eb 16467 /* }}} Foreign */
Marko Mikulicic 0:c0ecb8bf28eb 16468 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 16469 #line 1 "v7/src/function.c"
Marko Mikulicic 0:c0ecb8bf28eb 16470 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16471 /*
Marko Mikulicic 0:c0ecb8bf28eb 16472 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 16473 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 16474 */
Marko Mikulicic 0:c0ecb8bf28eb 16475
Marko Mikulicic 0:c0ecb8bf28eb 16476 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16477 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16478 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16479 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16480 /* Amalgamated: #include "v7/src/gc.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16481 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16482
Marko Mikulicic 0:c0ecb8bf28eb 16483 static val_t js_function_to_value(struct v7_js_function *o) {
Marko Mikulicic 0:c0ecb8bf28eb 16484 return pointer_to_value(o) | V7_TAG_FUNCTION;
Marko Mikulicic 0:c0ecb8bf28eb 16485 }
Marko Mikulicic 0:c0ecb8bf28eb 16486
Marko Mikulicic 0:c0ecb8bf28eb 16487 V7_PRIVATE struct v7_js_function *get_js_function_struct(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16488 struct v7_js_function *ret = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 16489 assert(is_js_function(v));
Marko Mikulicic 0:c0ecb8bf28eb 16490 ret = (struct v7_js_function *) get_ptr(v);
Marko Mikulicic 0:c0ecb8bf28eb 16491 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 16492 if (ret->base.entity_id_spec != V7_ENTITY_ID_PART_JS_FUNC) {
Marko Mikulicic 0:c0ecb8bf28eb 16493 fprintf(stderr, "entity_id: not a function!\n");
Marko Mikulicic 0:c0ecb8bf28eb 16494 abort();
Marko Mikulicic 0:c0ecb8bf28eb 16495 } else if (ret->base.entity_id_base != V7_ENTITY_ID_PART_OBJ) {
Marko Mikulicic 0:c0ecb8bf28eb 16496 fprintf(stderr, "entity_id: not an object!\n");
Marko Mikulicic 0:c0ecb8bf28eb 16497 abort();
Marko Mikulicic 0:c0ecb8bf28eb 16498 }
Marko Mikulicic 0:c0ecb8bf28eb 16499 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16500 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 16501 }
Marko Mikulicic 0:c0ecb8bf28eb 16502
Marko Mikulicic 0:c0ecb8bf28eb 16503 V7_PRIVATE
Marko Mikulicic 0:c0ecb8bf28eb 16504 val_t mk_js_function(struct v7 *v7, struct v7_generic_object *scope,
Marko Mikulicic 0:c0ecb8bf28eb 16505 val_t proto) {
Marko Mikulicic 0:c0ecb8bf28eb 16506 struct v7_js_function *f;
Marko Mikulicic 0:c0ecb8bf28eb 16507 val_t fval = V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 16508 struct gc_tmp_frame tf = new_tmp_frame(v7);
Marko Mikulicic 0:c0ecb8bf28eb 16509 tmp_stack_push(&tf, &proto);
Marko Mikulicic 0:c0ecb8bf28eb 16510 tmp_stack_push(&tf, &fval);
Marko Mikulicic 0:c0ecb8bf28eb 16511
Marko Mikulicic 0:c0ecb8bf28eb 16512 f = new_function(v7);
Marko Mikulicic 0:c0ecb8bf28eb 16513
Marko Mikulicic 0:c0ecb8bf28eb 16514 if (f == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 16515 /* fval is left `null` */
Marko Mikulicic 0:c0ecb8bf28eb 16516 goto cleanup;
Marko Mikulicic 0:c0ecb8bf28eb 16517 }
Marko Mikulicic 0:c0ecb8bf28eb 16518
Marko Mikulicic 0:c0ecb8bf28eb 16519 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 16520 f->base.entity_id_base = V7_ENTITY_ID_PART_OBJ;
Marko Mikulicic 0:c0ecb8bf28eb 16521 f->base.entity_id_spec = V7_ENTITY_ID_PART_JS_FUNC;
Marko Mikulicic 0:c0ecb8bf28eb 16522 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16523
Marko Mikulicic 0:c0ecb8bf28eb 16524 fval = js_function_to_value(f);
Marko Mikulicic 0:c0ecb8bf28eb 16525
Marko Mikulicic 0:c0ecb8bf28eb 16526 f->base.properties = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 16527 f->scope = scope;
Marko Mikulicic 0:c0ecb8bf28eb 16528
Marko Mikulicic 0:c0ecb8bf28eb 16529 /*
Marko Mikulicic 0:c0ecb8bf28eb 16530 * Before setting a `V7_OBJ_FUNCTION` flag, make sure we don't have
Marko Mikulicic 0:c0ecb8bf28eb 16531 * `V7_OBJ_DENSE_ARRAY` flag set
Marko Mikulicic 0:c0ecb8bf28eb 16532 */
Marko Mikulicic 0:c0ecb8bf28eb 16533 assert(!(f->base.attributes & V7_OBJ_DENSE_ARRAY));
Marko Mikulicic 0:c0ecb8bf28eb 16534 f->base.attributes |= V7_OBJ_FUNCTION;
Marko Mikulicic 0:c0ecb8bf28eb 16535
Marko Mikulicic 0:c0ecb8bf28eb 16536 /* TODO(mkm): lazily create these properties on first access */
Marko Mikulicic 0:c0ecb8bf28eb 16537 if (v7_is_object(proto)) {
Marko Mikulicic 0:c0ecb8bf28eb 16538 v7_def(v7, proto, "constructor", 11, V7_DESC_ENUMERABLE(0), fval);
Marko Mikulicic 0:c0ecb8bf28eb 16539 v7_def(v7, fval, "prototype", 9,
Marko Mikulicic 0:c0ecb8bf28eb 16540 V7_DESC_ENUMERABLE(0) | V7_DESC_CONFIGURABLE(0), proto);
Marko Mikulicic 0:c0ecb8bf28eb 16541 }
Marko Mikulicic 0:c0ecb8bf28eb 16542
Marko Mikulicic 0:c0ecb8bf28eb 16543 cleanup:
Marko Mikulicic 0:c0ecb8bf28eb 16544 tmp_frame_cleanup(&tf);
Marko Mikulicic 0:c0ecb8bf28eb 16545 return fval;
Marko Mikulicic 0:c0ecb8bf28eb 16546 }
Marko Mikulicic 0:c0ecb8bf28eb 16547
Marko Mikulicic 0:c0ecb8bf28eb 16548 V7_PRIVATE int is_js_function(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16549 return (v & V7_TAG_MASK) == V7_TAG_FUNCTION;
Marko Mikulicic 0:c0ecb8bf28eb 16550 }
Marko Mikulicic 0:c0ecb8bf28eb 16551
Marko Mikulicic 0:c0ecb8bf28eb 16552 V7_PRIVATE
Marko Mikulicic 0:c0ecb8bf28eb 16553 v7_val_t mk_cfunction_obj(struct v7 *v7, v7_cfunction_t *f, int num_args) {
Marko Mikulicic 0:c0ecb8bf28eb 16554 val_t obj = mk_object(v7, v7->vals.function_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 16555 struct gc_tmp_frame tf = new_tmp_frame(v7);
Marko Mikulicic 0:c0ecb8bf28eb 16556 tmp_stack_push(&tf, &obj);
Marko Mikulicic 0:c0ecb8bf28eb 16557 v7_def(v7, obj, "", 0, _V7_DESC_HIDDEN(1), v7_mk_cfunction(f));
Marko Mikulicic 0:c0ecb8bf28eb 16558 if (num_args >= 0) {
Marko Mikulicic 0:c0ecb8bf28eb 16559 v7_def(v7, obj, "length", 6, (V7_DESC_ENUMERABLE(0) | V7_DESC_WRITABLE(0) |
Marko Mikulicic 0:c0ecb8bf28eb 16560 V7_DESC_CONFIGURABLE(0)),
Marko Mikulicic 0:c0ecb8bf28eb 16561 v7_mk_number(v7, num_args));
Marko Mikulicic 0:c0ecb8bf28eb 16562 }
Marko Mikulicic 0:c0ecb8bf28eb 16563 tmp_frame_cleanup(&tf);
Marko Mikulicic 0:c0ecb8bf28eb 16564 return obj;
Marko Mikulicic 0:c0ecb8bf28eb 16565 }
Marko Mikulicic 0:c0ecb8bf28eb 16566
Marko Mikulicic 0:c0ecb8bf28eb 16567 V7_PRIVATE v7_val_t mk_cfunction_obj_with_proto(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 16568 v7_cfunction_t *f, int num_args,
Marko Mikulicic 0:c0ecb8bf28eb 16569 v7_val_t proto) {
Marko Mikulicic 0:c0ecb8bf28eb 16570 struct gc_tmp_frame tf = new_tmp_frame(v7);
Marko Mikulicic 0:c0ecb8bf28eb 16571 v7_val_t res = mk_cfunction_obj(v7, f, num_args);
Marko Mikulicic 0:c0ecb8bf28eb 16572
Marko Mikulicic 0:c0ecb8bf28eb 16573 tmp_stack_push(&tf, &res);
Marko Mikulicic 0:c0ecb8bf28eb 16574
Marko Mikulicic 0:c0ecb8bf28eb 16575 v7_def(v7, res, "prototype", 9, (V7_DESC_ENUMERABLE(0) | V7_DESC_WRITABLE(0) |
Marko Mikulicic 0:c0ecb8bf28eb 16576 V7_DESC_CONFIGURABLE(0)),
Marko Mikulicic 0:c0ecb8bf28eb 16577 proto);
Marko Mikulicic 0:c0ecb8bf28eb 16578 v7_def(v7, proto, "constructor", 11, V7_DESC_ENUMERABLE(0), res);
Marko Mikulicic 0:c0ecb8bf28eb 16579 tmp_frame_cleanup(&tf);
Marko Mikulicic 0:c0ecb8bf28eb 16580 return res;
Marko Mikulicic 0:c0ecb8bf28eb 16581 }
Marko Mikulicic 0:c0ecb8bf28eb 16582
Marko Mikulicic 0:c0ecb8bf28eb 16583 V7_PRIVATE v7_val_t mk_cfunction_lite(v7_cfunction_t *f) {
Marko Mikulicic 0:c0ecb8bf28eb 16584 union {
Marko Mikulicic 0:c0ecb8bf28eb 16585 void *p;
Marko Mikulicic 0:c0ecb8bf28eb 16586 v7_cfunction_t *f;
Marko Mikulicic 0:c0ecb8bf28eb 16587 } u;
Marko Mikulicic 0:c0ecb8bf28eb 16588 u.f = f;
Marko Mikulicic 0:c0ecb8bf28eb 16589 return pointer_to_value(u.p) | V7_TAG_CFUNCTION;
Marko Mikulicic 0:c0ecb8bf28eb 16590 }
Marko Mikulicic 0:c0ecb8bf28eb 16591
Marko Mikulicic 0:c0ecb8bf28eb 16592 V7_PRIVATE v7_cfunction_t *get_cfunction_ptr(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16593 v7_cfunction_t *ret = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 16594
Marko Mikulicic 0:c0ecb8bf28eb 16595 if (is_cfunction_lite(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 16596 /* Implementation is identical to get_ptr but is separate since
Marko Mikulicic 0:c0ecb8bf28eb 16597 * object pointers are not directly convertible to function pointers
Marko Mikulicic 0:c0ecb8bf28eb 16598 * according to ISO C and generates a warning in -Wpedantic mode. */
Marko Mikulicic 0:c0ecb8bf28eb 16599 ret = (v7_cfunction_t *) (uintptr_t)(v & 0xFFFFFFFFFFFFUL);
Marko Mikulicic 0:c0ecb8bf28eb 16600 } else {
Marko Mikulicic 0:c0ecb8bf28eb 16601 /* maybe cfunction object */
Marko Mikulicic 0:c0ecb8bf28eb 16602
Marko Mikulicic 0:c0ecb8bf28eb 16603 /* extract the hidden property from a cfunction_object */
Marko Mikulicic 0:c0ecb8bf28eb 16604 struct v7_property *p;
Marko Mikulicic 0:c0ecb8bf28eb 16605 p = v7_get_own_property2(v7, v, "", 0, _V7_PROPERTY_HIDDEN);
Marko Mikulicic 0:c0ecb8bf28eb 16606 if (p != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 16607 /* yes, it's cfunction object. Extract cfunction pointer from it */
Marko Mikulicic 0:c0ecb8bf28eb 16608 ret = get_cfunction_ptr(v7, p->value);
Marko Mikulicic 0:c0ecb8bf28eb 16609 }
Marko Mikulicic 0:c0ecb8bf28eb 16610 }
Marko Mikulicic 0:c0ecb8bf28eb 16611
Marko Mikulicic 0:c0ecb8bf28eb 16612 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 16613 }
Marko Mikulicic 0:c0ecb8bf28eb 16614
Marko Mikulicic 0:c0ecb8bf28eb 16615 V7_PRIVATE int is_cfunction_lite(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16616 return (v & V7_TAG_MASK) == V7_TAG_CFUNCTION;
Marko Mikulicic 0:c0ecb8bf28eb 16617 }
Marko Mikulicic 0:c0ecb8bf28eb 16618
Marko Mikulicic 0:c0ecb8bf28eb 16619 V7_PRIVATE int is_cfunction_obj(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16620 int ret = 0;
Marko Mikulicic 0:c0ecb8bf28eb 16621 if (v7_is_object(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 16622 /* extract the hidden property from a cfunction_object */
Marko Mikulicic 0:c0ecb8bf28eb 16623 struct v7_property *p;
Marko Mikulicic 0:c0ecb8bf28eb 16624 p = v7_get_own_property2(v7, v, "", 0, _V7_PROPERTY_HIDDEN);
Marko Mikulicic 0:c0ecb8bf28eb 16625 if (p != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 16626 v = p->value;
Marko Mikulicic 0:c0ecb8bf28eb 16627 }
Marko Mikulicic 0:c0ecb8bf28eb 16628
Marko Mikulicic 0:c0ecb8bf28eb 16629 ret = is_cfunction_lite(v);
Marko Mikulicic 0:c0ecb8bf28eb 16630 }
Marko Mikulicic 0:c0ecb8bf28eb 16631 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 16632 }
Marko Mikulicic 0:c0ecb8bf28eb 16633
Marko Mikulicic 0:c0ecb8bf28eb 16634 v7_val_t v7_mk_function(struct v7 *v7, v7_cfunction_t *f) {
Marko Mikulicic 0:c0ecb8bf28eb 16635 return mk_cfunction_obj(v7, f, -1);
Marko Mikulicic 0:c0ecb8bf28eb 16636 }
Marko Mikulicic 0:c0ecb8bf28eb 16637
Marko Mikulicic 0:c0ecb8bf28eb 16638 v7_val_t v7_mk_function_with_proto(struct v7 *v7, v7_cfunction_t *f,
Marko Mikulicic 0:c0ecb8bf28eb 16639 v7_val_t proto) {
Marko Mikulicic 0:c0ecb8bf28eb 16640 return mk_cfunction_obj_with_proto(v7, f, ~0, proto);
Marko Mikulicic 0:c0ecb8bf28eb 16641 }
Marko Mikulicic 0:c0ecb8bf28eb 16642
Marko Mikulicic 0:c0ecb8bf28eb 16643 v7_val_t v7_mk_cfunction(v7_cfunction_t *f) {
Marko Mikulicic 0:c0ecb8bf28eb 16644 return mk_cfunction_lite(f);
Marko Mikulicic 0:c0ecb8bf28eb 16645 }
Marko Mikulicic 0:c0ecb8bf28eb 16646
Marko Mikulicic 0:c0ecb8bf28eb 16647 int v7_is_callable(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16648 return is_js_function(v) || is_cfunction_lite(v) || is_cfunction_obj(v7, v);
Marko Mikulicic 0:c0ecb8bf28eb 16649 }
Marko Mikulicic 0:c0ecb8bf28eb 16650 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 16651 #line 1 "v7/src/exec.c"
Marko Mikulicic 0:c0ecb8bf28eb 16652 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16653 /*
Marko Mikulicic 0:c0ecb8bf28eb 16654 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 16655 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 16656 */
Marko Mikulicic 0:c0ecb8bf28eb 16657
Marko Mikulicic 0:c0ecb8bf28eb 16658 /* osdep.h must be included before `cs_file.h` TODO(dfrank) : fix this */
Marko Mikulicic 0:c0ecb8bf28eb 16659 /* Amalgamated: #include "common/cs_file.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16660 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16661 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16662 /* Amalgamated: #include "v7/src/eval.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16663 /* Amalgamated: #include "v7/src/exec.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16664 /* Amalgamated: #include "v7/src/ast.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16665 /* Amalgamated: #include "v7/src/compiler.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16666 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16667
Marko Mikulicic 0:c0ecb8bf28eb 16668 enum v7_err v7_exec(struct v7 *v7, const char *js_code, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 16669 return b_exec(v7, js_code, strlen(js_code), NULL, V7_UNDEFINED, V7_UNDEFINED,
Marko Mikulicic 0:c0ecb8bf28eb 16670 V7_UNDEFINED, 0, 0, 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 16671 }
Marko Mikulicic 0:c0ecb8bf28eb 16672
Marko Mikulicic 0:c0ecb8bf28eb 16673 enum v7_err v7_exec_opt(struct v7 *v7, const char *js_code,
Marko Mikulicic 0:c0ecb8bf28eb 16674 const struct v7_exec_opts *opts, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 16675 return b_exec(v7, js_code, strlen(js_code), opts->filename, V7_UNDEFINED,
Marko Mikulicic 0:c0ecb8bf28eb 16676 V7_UNDEFINED,
Marko Mikulicic 0:c0ecb8bf28eb 16677 (opts->this_obj == 0 ? V7_UNDEFINED : opts->this_obj),
Marko Mikulicic 0:c0ecb8bf28eb 16678 opts->is_json, 0, 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 16679 }
Marko Mikulicic 0:c0ecb8bf28eb 16680
Marko Mikulicic 0:c0ecb8bf28eb 16681 enum v7_err v7_parse_json(struct v7 *v7, const char *str, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 16682 return b_exec(v7, str, strlen(str), NULL, V7_UNDEFINED, V7_UNDEFINED,
Marko Mikulicic 0:c0ecb8bf28eb 16683 V7_UNDEFINED, 1, 0, 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 16684 }
Marko Mikulicic 0:c0ecb8bf28eb 16685
Marko Mikulicic 0:c0ecb8bf28eb 16686 #ifndef V7_NO_FS
Marko Mikulicic 0:c0ecb8bf28eb 16687 static enum v7_err exec_file(struct v7 *v7, const char *path, val_t *res,
Marko Mikulicic 0:c0ecb8bf28eb 16688 int is_json) {
Marko Mikulicic 0:c0ecb8bf28eb 16689 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 16690 char *p;
Marko Mikulicic 0:c0ecb8bf28eb 16691 size_t file_size;
Marko Mikulicic 0:c0ecb8bf28eb 16692 char *(*rd)(const char *, size_t *);
Marko Mikulicic 0:c0ecb8bf28eb 16693
Marko Mikulicic 0:c0ecb8bf28eb 16694 rd = cs_read_file;
Marko Mikulicic 0:c0ecb8bf28eb 16695 #ifdef V7_MMAP_EXEC
Marko Mikulicic 0:c0ecb8bf28eb 16696 rd = cs_mmap_file;
Marko Mikulicic 0:c0ecb8bf28eb 16697 #ifdef V7_MMAP_EXEC_ONLY
Marko Mikulicic 0:c0ecb8bf28eb 16698 #define I_STRINGIFY(x) #x
Marko Mikulicic 0:c0ecb8bf28eb 16699 #define I_STRINGIFY2(x) I_STRINGIFY(x)
Marko Mikulicic 0:c0ecb8bf28eb 16700
Marko Mikulicic 0:c0ecb8bf28eb 16701 /* use mmap only for .js files */
Marko Mikulicic 0:c0ecb8bf28eb 16702 if (strlen(path) <= 3 || strcmp(path + strlen(path) - 3, ".js") != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 16703 rd = cs_read_file;
Marko Mikulicic 0:c0ecb8bf28eb 16704 }
Marko Mikulicic 0:c0ecb8bf28eb 16705 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16706 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16707
Marko Mikulicic 0:c0ecb8bf28eb 16708 if ((p = rd(path, &file_size)) == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 16709 rcode = v7_throwf(v7, SYNTAX_ERROR, "cannot open [%s]", path);
Marko Mikulicic 0:c0ecb8bf28eb 16710 /*
Marko Mikulicic 0:c0ecb8bf28eb 16711 * In order to maintain compat with existing API, we should save the
Marko Mikulicic 0:c0ecb8bf28eb 16712 * current exception value into `*res`
Marko Mikulicic 0:c0ecb8bf28eb 16713 *
Marko Mikulicic 0:c0ecb8bf28eb 16714 * TODO(dfrank): probably change API: clients can use
Marko Mikulicic 0:c0ecb8bf28eb 16715 *`v7_get_thrown_value()` now.
Marko Mikulicic 0:c0ecb8bf28eb 16716 */
Marko Mikulicic 0:c0ecb8bf28eb 16717 if (res != NULL) *res = v7_get_thrown_value(v7, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 16718 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 16719 } else {
Marko Mikulicic 0:c0ecb8bf28eb 16720 #ifndef V7_MMAP_EXEC
Marko Mikulicic 0:c0ecb8bf28eb 16721 int fr = 1;
Marko Mikulicic 0:c0ecb8bf28eb 16722 #else
Marko Mikulicic 0:c0ecb8bf28eb 16723 int fr = 0;
Marko Mikulicic 0:c0ecb8bf28eb 16724 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16725 rcode = b_exec(v7, p, file_size, path, V7_UNDEFINED, V7_UNDEFINED,
Marko Mikulicic 0:c0ecb8bf28eb 16726 V7_UNDEFINED, is_json, fr, 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 16727 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 16728 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 16729 }
Marko Mikulicic 0:c0ecb8bf28eb 16730 }
Marko Mikulicic 0:c0ecb8bf28eb 16731
Marko Mikulicic 0:c0ecb8bf28eb 16732 clean:
Marko Mikulicic 0:c0ecb8bf28eb 16733 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 16734 }
Marko Mikulicic 0:c0ecb8bf28eb 16735
Marko Mikulicic 0:c0ecb8bf28eb 16736 enum v7_err v7_exec_file(struct v7 *v7, const char *path, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 16737 return exec_file(v7, path, res, 0);
Marko Mikulicic 0:c0ecb8bf28eb 16738 }
Marko Mikulicic 0:c0ecb8bf28eb 16739
Marko Mikulicic 0:c0ecb8bf28eb 16740 enum v7_err v7_parse_json_file(struct v7 *v7, const char *path, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 16741 return exec_file(v7, path, res, 1);
Marko Mikulicic 0:c0ecb8bf28eb 16742 }
Marko Mikulicic 0:c0ecb8bf28eb 16743 #endif /* V7_NO_FS */
Marko Mikulicic 0:c0ecb8bf28eb 16744
Marko Mikulicic 0:c0ecb8bf28eb 16745 enum v7_err v7_apply(struct v7 *v7, v7_val_t func, v7_val_t this_obj,
Marko Mikulicic 0:c0ecb8bf28eb 16746 v7_val_t args, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 16747 return b_apply(v7, func, this_obj, args, 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 16748 }
Marko Mikulicic 0:c0ecb8bf28eb 16749
Marko Mikulicic 0:c0ecb8bf28eb 16750 #ifndef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 16751 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 16752 enum v7_err _v7_compile(const char *src, size_t js_code_size, int binary,
Marko Mikulicic 0:c0ecb8bf28eb 16753 int use_bcode, FILE *fp) {
Marko Mikulicic 0:c0ecb8bf28eb 16754 struct ast ast;
Marko Mikulicic 0:c0ecb8bf28eb 16755 struct v7 *v7 = v7_create();
Marko Mikulicic 0:c0ecb8bf28eb 16756 ast_off_t pos = 0;
Marko Mikulicic 0:c0ecb8bf28eb 16757 enum v7_err err;
Marko Mikulicic 0:c0ecb8bf28eb 16758
Marko Mikulicic 0:c0ecb8bf28eb 16759 v7->is_precompiling = 1;
Marko Mikulicic 0:c0ecb8bf28eb 16760
Marko Mikulicic 0:c0ecb8bf28eb 16761 ast_init(&ast, 0);
Marko Mikulicic 0:c0ecb8bf28eb 16762 err = parse(v7, &ast, src, js_code_size, 0);
Marko Mikulicic 0:c0ecb8bf28eb 16763 if (err == V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 16764 if (use_bcode) {
Marko Mikulicic 0:c0ecb8bf28eb 16765 struct bcode bcode;
Marko Mikulicic 0:c0ecb8bf28eb 16766 /*
Marko Mikulicic 0:c0ecb8bf28eb 16767 * We don't set filename here, because the bcode will be just serialized
Marko Mikulicic 0:c0ecb8bf28eb 16768 * and then freed. We don't currently serialize filename. If we ever do,
Marko Mikulicic 0:c0ecb8bf28eb 16769 * we'll have to make `_v7_compile()` to also take a filename argument,
Marko Mikulicic 0:c0ecb8bf28eb 16770 * and use it here.
Marko Mikulicic 0:c0ecb8bf28eb 16771 */
Marko Mikulicic 0:c0ecb8bf28eb 16772 bcode_init(&bcode, 0, NULL, 0);
Marko Mikulicic 0:c0ecb8bf28eb 16773 err = compile_script(v7, &ast, &bcode);
Marko Mikulicic 0:c0ecb8bf28eb 16774 if (err != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 16775 goto cleanup_bcode;
Marko Mikulicic 0:c0ecb8bf28eb 16776 }
Marko Mikulicic 0:c0ecb8bf28eb 16777
Marko Mikulicic 0:c0ecb8bf28eb 16778 if (binary) {
Marko Mikulicic 0:c0ecb8bf28eb 16779 bcode_serialize(v7, &bcode, fp);
Marko Mikulicic 0:c0ecb8bf28eb 16780 } else {
Marko Mikulicic 0:c0ecb8bf28eb 16781 #ifdef V7_BCODE_DUMP
Marko Mikulicic 0:c0ecb8bf28eb 16782 dump_bcode(v7, fp, &bcode);
Marko Mikulicic 0:c0ecb8bf28eb 16783 #else
Marko Mikulicic 0:c0ecb8bf28eb 16784 fprintf(stderr, "build flag V7_BCODE_DUMP not enabled\n");
Marko Mikulicic 0:c0ecb8bf28eb 16785 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16786 }
Marko Mikulicic 0:c0ecb8bf28eb 16787 cleanup_bcode:
Marko Mikulicic 0:c0ecb8bf28eb 16788 bcode_free(v7, &bcode);
Marko Mikulicic 0:c0ecb8bf28eb 16789 } else {
Marko Mikulicic 0:c0ecb8bf28eb 16790 if (binary) {
Marko Mikulicic 0:c0ecb8bf28eb 16791 fwrite(BIN_AST_SIGNATURE, sizeof(BIN_AST_SIGNATURE), 1, fp);
Marko Mikulicic 0:c0ecb8bf28eb 16792 fwrite(ast.mbuf.buf, ast.mbuf.len, 1, fp);
Marko Mikulicic 0:c0ecb8bf28eb 16793 } else {
Marko Mikulicic 0:c0ecb8bf28eb 16794 ast_dump_tree(fp, &ast, &pos, 0);
Marko Mikulicic 0:c0ecb8bf28eb 16795 }
Marko Mikulicic 0:c0ecb8bf28eb 16796 }
Marko Mikulicic 0:c0ecb8bf28eb 16797 }
Marko Mikulicic 0:c0ecb8bf28eb 16798
Marko Mikulicic 0:c0ecb8bf28eb 16799 ast_free(&ast);
Marko Mikulicic 0:c0ecb8bf28eb 16800 v7_destroy(v7);
Marko Mikulicic 0:c0ecb8bf28eb 16801 return err;
Marko Mikulicic 0:c0ecb8bf28eb 16802 }
Marko Mikulicic 0:c0ecb8bf28eb 16803
Marko Mikulicic 0:c0ecb8bf28eb 16804 enum v7_err v7_compile(const char *src, int binary, int use_bcode, FILE *fp) {
Marko Mikulicic 0:c0ecb8bf28eb 16805 return _v7_compile(src, strlen(src), binary, use_bcode, fp);
Marko Mikulicic 0:c0ecb8bf28eb 16806 }
Marko Mikulicic 0:c0ecb8bf28eb 16807 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 16808 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16809 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 16810 #line 1 "v7/src/util.c"
Marko Mikulicic 0:c0ecb8bf28eb 16811 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16812 /*
Marko Mikulicic 0:c0ecb8bf28eb 16813 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 16814 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 16815 */
Marko Mikulicic 0:c0ecb8bf28eb 16816
Marko Mikulicic 0:c0ecb8bf28eb 16817 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16818 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16819 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16820 /* Amalgamated: #include "v7/src/util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16821 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16822 /* Amalgamated: #include "v7/src/array.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16823 /* Amalgamated: #include "v7/src/eval.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16824 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16825 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16826 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16827 /* Amalgamated: #include "v7/src/std_proxy.h" */
Marko Mikulicic 0:c0ecb8bf28eb 16828
Marko Mikulicic 0:c0ecb8bf28eb 16829 void v7_print(struct v7 *v7, v7_val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16830 v7_fprint(stdout, v7, v);
Marko Mikulicic 0:c0ecb8bf28eb 16831 }
Marko Mikulicic 0:c0ecb8bf28eb 16832
Marko Mikulicic 0:c0ecb8bf28eb 16833 void v7_fprint(FILE *f, struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16834 char buf[16];
Marko Mikulicic 0:c0ecb8bf28eb 16835 char *s = v7_stringify(v7, v, buf, sizeof(buf), V7_STRINGIFY_DEBUG);
Marko Mikulicic 0:c0ecb8bf28eb 16836 fprintf(f, "%s", s);
Marko Mikulicic 0:c0ecb8bf28eb 16837 if (buf != s) free(s);
Marko Mikulicic 0:c0ecb8bf28eb 16838 }
Marko Mikulicic 0:c0ecb8bf28eb 16839
Marko Mikulicic 0:c0ecb8bf28eb 16840 void v7_println(struct v7 *v7, v7_val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16841 v7_fprintln(stdout, v7, v);
Marko Mikulicic 0:c0ecb8bf28eb 16842 }
Marko Mikulicic 0:c0ecb8bf28eb 16843
Marko Mikulicic 0:c0ecb8bf28eb 16844 void v7_fprintln(FILE *f, struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16845 v7_fprint(f, v7, v);
Marko Mikulicic 0:c0ecb8bf28eb 16846 fprintf(f, ENDL);
Marko Mikulicic 0:c0ecb8bf28eb 16847 }
Marko Mikulicic 0:c0ecb8bf28eb 16848
Marko Mikulicic 0:c0ecb8bf28eb 16849 void v7_fprint_stack_trace(FILE *f, struct v7 *v7, val_t e) {
Marko Mikulicic 0:c0ecb8bf28eb 16850 size_t s;
Marko Mikulicic 0:c0ecb8bf28eb 16851 val_t strace_v = v7_get(v7, e, "stack", ~0);
Marko Mikulicic 0:c0ecb8bf28eb 16852 const char *strace = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 16853 if (v7_is_string(strace_v)) {
Marko Mikulicic 0:c0ecb8bf28eb 16854 strace = v7_get_string(v7, &strace_v, &s);
Marko Mikulicic 0:c0ecb8bf28eb 16855 fprintf(f, "%s\n", strace);
Marko Mikulicic 0:c0ecb8bf28eb 16856 }
Marko Mikulicic 0:c0ecb8bf28eb 16857 }
Marko Mikulicic 0:c0ecb8bf28eb 16858
Marko Mikulicic 0:c0ecb8bf28eb 16859 void v7_print_error(FILE *f, struct v7 *v7, const char *ctx, val_t e) {
Marko Mikulicic 0:c0ecb8bf28eb 16860 /* TODO(mkm): figure out if this is an error object and which kind */
Marko Mikulicic 0:c0ecb8bf28eb 16861 v7_val_t msg;
Marko Mikulicic 0:c0ecb8bf28eb 16862 if (v7_is_undefined(e)) {
Marko Mikulicic 0:c0ecb8bf28eb 16863 fprintf(f, "undefined error [%s]\n ", ctx);
Marko Mikulicic 0:c0ecb8bf28eb 16864 return;
Marko Mikulicic 0:c0ecb8bf28eb 16865 }
Marko Mikulicic 0:c0ecb8bf28eb 16866 msg = v7_get(v7, e, "message", ~0);
Marko Mikulicic 0:c0ecb8bf28eb 16867 if (v7_is_undefined(msg)) {
Marko Mikulicic 0:c0ecb8bf28eb 16868 msg = e;
Marko Mikulicic 0:c0ecb8bf28eb 16869 }
Marko Mikulicic 0:c0ecb8bf28eb 16870 fprintf(f, "Exec error [%s]: ", ctx);
Marko Mikulicic 0:c0ecb8bf28eb 16871 v7_fprintln(f, v7, msg);
Marko Mikulicic 0:c0ecb8bf28eb 16872 v7_fprint_stack_trace(f, v7, e);
Marko Mikulicic 0:c0ecb8bf28eb 16873 }
Marko Mikulicic 0:c0ecb8bf28eb 16874
Marko Mikulicic 0:c0ecb8bf28eb 16875 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 16876
Marko Mikulicic 0:c0ecb8bf28eb 16877 v7_val_t v7_mk_proxy(struct v7 *v7, v7_val_t target,
Marko Mikulicic 0:c0ecb8bf28eb 16878 const v7_proxy_hnd_t *handler) {
Marko Mikulicic 0:c0ecb8bf28eb 16879 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 16880 v7_val_t res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 16881 v7_val_t args = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 16882 v7_val_t handler_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 16883
Marko Mikulicic 0:c0ecb8bf28eb 16884 v7_own(v7, &res);
Marko Mikulicic 0:c0ecb8bf28eb 16885 v7_own(v7, &args);
Marko Mikulicic 0:c0ecb8bf28eb 16886 v7_own(v7, &handler_v);
Marko Mikulicic 0:c0ecb8bf28eb 16887 v7_own(v7, &target);
Marko Mikulicic 0:c0ecb8bf28eb 16888
Marko Mikulicic 0:c0ecb8bf28eb 16889 /* if target is not an object, create one */
Marko Mikulicic 0:c0ecb8bf28eb 16890 if (!v7_is_object(target)) {
Marko Mikulicic 0:c0ecb8bf28eb 16891 target = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 16892 }
Marko Mikulicic 0:c0ecb8bf28eb 16893
Marko Mikulicic 0:c0ecb8bf28eb 16894 /* prepare handler object with necessary properties */
Marko Mikulicic 0:c0ecb8bf28eb 16895 handler_v = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 16896 if (handler->get != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 16897 set_cfunc_prop(v7, handler_v, "get", handler->get);
Marko Mikulicic 0:c0ecb8bf28eb 16898 }
Marko Mikulicic 0:c0ecb8bf28eb 16899 if (handler->set != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 16900 set_cfunc_prop(v7, handler_v, "set", handler->set);
Marko Mikulicic 0:c0ecb8bf28eb 16901 }
Marko Mikulicic 0:c0ecb8bf28eb 16902 if (handler->own_keys != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 16903 set_cfunc_prop(v7, handler_v, "ownKeys", handler->own_keys);
Marko Mikulicic 0:c0ecb8bf28eb 16904 }
Marko Mikulicic 0:c0ecb8bf28eb 16905 if (handler->get_own_prop_desc != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 16906 v7_def(v7, handler_v, "_gpdc", ~0, V7_DESC_ENUMERABLE(0),
Marko Mikulicic 0:c0ecb8bf28eb 16907 v7_mk_foreign(v7, (void *) handler->get_own_prop_desc));
Marko Mikulicic 0:c0ecb8bf28eb 16908 }
Marko Mikulicic 0:c0ecb8bf28eb 16909
Marko Mikulicic 0:c0ecb8bf28eb 16910 /* prepare args */
Marko Mikulicic 0:c0ecb8bf28eb 16911 args = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 16912 v7_array_set(v7, args, 0, target);
Marko Mikulicic 0:c0ecb8bf28eb 16913 v7_array_set(v7, args, 1, handler_v);
Marko Mikulicic 0:c0ecb8bf28eb 16914
Marko Mikulicic 0:c0ecb8bf28eb 16915 /* call Proxy constructor */
Marko Mikulicic 0:c0ecb8bf28eb 16916 V7_TRY(b_apply(v7, v7_get(v7, v7->vals.global_object, "Proxy", ~0),
Marko Mikulicic 0:c0ecb8bf28eb 16917 v7_mk_object(v7), args, 1 /* as ctor */, &res));
Marko Mikulicic 0:c0ecb8bf28eb 16918
Marko Mikulicic 0:c0ecb8bf28eb 16919 clean:
Marko Mikulicic 0:c0ecb8bf28eb 16920 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 16921 fprintf(stderr, "error during v7_mk_proxy()");
Marko Mikulicic 0:c0ecb8bf28eb 16922 res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 16923 }
Marko Mikulicic 0:c0ecb8bf28eb 16924
Marko Mikulicic 0:c0ecb8bf28eb 16925 v7_disown(v7, &target);
Marko Mikulicic 0:c0ecb8bf28eb 16926 v7_disown(v7, &handler_v);
Marko Mikulicic 0:c0ecb8bf28eb 16927 v7_disown(v7, &args);
Marko Mikulicic 0:c0ecb8bf28eb 16928 v7_disown(v7, &res);
Marko Mikulicic 0:c0ecb8bf28eb 16929 return res;
Marko Mikulicic 0:c0ecb8bf28eb 16930 }
Marko Mikulicic 0:c0ecb8bf28eb 16931
Marko Mikulicic 0:c0ecb8bf28eb 16932 #endif /* V7_ENABLE__Proxy */
Marko Mikulicic 0:c0ecb8bf28eb 16933
Marko Mikulicic 0:c0ecb8bf28eb 16934 V7_PRIVATE enum v7_type val_type(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 16935 int tag;
Marko Mikulicic 0:c0ecb8bf28eb 16936 if (v7_is_number(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 16937 return V7_TYPE_NUMBER;
Marko Mikulicic 0:c0ecb8bf28eb 16938 }
Marko Mikulicic 0:c0ecb8bf28eb 16939 tag = (v & V7_TAG_MASK) >> 48;
Marko Mikulicic 0:c0ecb8bf28eb 16940 switch (tag) {
Marko Mikulicic 0:c0ecb8bf28eb 16941 case V7_TAG_FOREIGN >> 48:
Marko Mikulicic 0:c0ecb8bf28eb 16942 if (v7_is_null(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 16943 return V7_TYPE_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 16944 }
Marko Mikulicic 0:c0ecb8bf28eb 16945 return V7_TYPE_FOREIGN;
Marko Mikulicic 0:c0ecb8bf28eb 16946 case V7_TAG_UNDEFINED >> 48:
Marko Mikulicic 0:c0ecb8bf28eb 16947 return V7_TYPE_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 16948 case V7_TAG_OBJECT >> 48:
Marko Mikulicic 0:c0ecb8bf28eb 16949 if (v7_get_proto(v7, v) == v7->vals.array_prototype) {
Marko Mikulicic 0:c0ecb8bf28eb 16950 return V7_TYPE_ARRAY_OBJECT;
Marko Mikulicic 0:c0ecb8bf28eb 16951 } else if (v7_get_proto(v7, v) == v7->vals.boolean_prototype) {
Marko Mikulicic 0:c0ecb8bf28eb 16952 return V7_TYPE_BOOLEAN_OBJECT;
Marko Mikulicic 0:c0ecb8bf28eb 16953 } else if (v7_get_proto(v7, v) == v7->vals.string_prototype) {
Marko Mikulicic 0:c0ecb8bf28eb 16954 return V7_TYPE_STRING_OBJECT;
Marko Mikulicic 0:c0ecb8bf28eb 16955 } else if (v7_get_proto(v7, v) == v7->vals.number_prototype) {
Marko Mikulicic 0:c0ecb8bf28eb 16956 return V7_TYPE_NUMBER_OBJECT;
Marko Mikulicic 0:c0ecb8bf28eb 16957 } else if (v7_get_proto(v7, v) == v7->vals.function_prototype) {
Marko Mikulicic 0:c0ecb8bf28eb 16958 return V7_TYPE_CFUNCTION_OBJECT;
Marko Mikulicic 0:c0ecb8bf28eb 16959 } else if (v7_get_proto(v7, v) == v7->vals.date_prototype) {
Marko Mikulicic 0:c0ecb8bf28eb 16960 return V7_TYPE_DATE_OBJECT;
Marko Mikulicic 0:c0ecb8bf28eb 16961 } else {
Marko Mikulicic 0:c0ecb8bf28eb 16962 return V7_TYPE_GENERIC_OBJECT;
Marko Mikulicic 0:c0ecb8bf28eb 16963 }
Marko Mikulicic 0:c0ecb8bf28eb 16964 case V7_TAG_STRING_I >> 48:
Marko Mikulicic 0:c0ecb8bf28eb 16965 case V7_TAG_STRING_O >> 48:
Marko Mikulicic 0:c0ecb8bf28eb 16966 case V7_TAG_STRING_F >> 48:
Marko Mikulicic 0:c0ecb8bf28eb 16967 case V7_TAG_STRING_D >> 48:
Marko Mikulicic 0:c0ecb8bf28eb 16968 case V7_TAG_STRING_5 >> 48:
Marko Mikulicic 0:c0ecb8bf28eb 16969 return V7_TYPE_STRING;
Marko Mikulicic 0:c0ecb8bf28eb 16970 case V7_TAG_BOOLEAN >> 48:
Marko Mikulicic 0:c0ecb8bf28eb 16971 return V7_TYPE_BOOLEAN;
Marko Mikulicic 0:c0ecb8bf28eb 16972 case V7_TAG_FUNCTION >> 48:
Marko Mikulicic 0:c0ecb8bf28eb 16973 return V7_TYPE_FUNCTION_OBJECT;
Marko Mikulicic 0:c0ecb8bf28eb 16974 case V7_TAG_CFUNCTION >> 48:
Marko Mikulicic 0:c0ecb8bf28eb 16975 return V7_TYPE_CFUNCTION;
Marko Mikulicic 0:c0ecb8bf28eb 16976 case V7_TAG_REGEXP >> 48:
Marko Mikulicic 0:c0ecb8bf28eb 16977 return V7_TYPE_REGEXP_OBJECT;
Marko Mikulicic 0:c0ecb8bf28eb 16978 default:
Marko Mikulicic 0:c0ecb8bf28eb 16979 abort();
Marko Mikulicic 0:c0ecb8bf28eb 16980 return V7_TYPE_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 16981 }
Marko Mikulicic 0:c0ecb8bf28eb 16982 }
Marko Mikulicic 0:c0ecb8bf28eb 16983
Marko Mikulicic 0:c0ecb8bf28eb 16984 #ifndef V7_DISABLE_LINE_NUMBERS
Marko Mikulicic 0:c0ecb8bf28eb 16985 V7_PRIVATE uint8_t msb_lsb_swap(uint8_t b) {
Marko Mikulicic 0:c0ecb8bf28eb 16986 if ((b & 0x01) != (b >> 7)) {
Marko Mikulicic 0:c0ecb8bf28eb 16987 b ^= 0x81;
Marko Mikulicic 0:c0ecb8bf28eb 16988 }
Marko Mikulicic 0:c0ecb8bf28eb 16989 return b;
Marko Mikulicic 0:c0ecb8bf28eb 16990 }
Marko Mikulicic 0:c0ecb8bf28eb 16991 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16992 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 16993 #line 1 "v7/src/string.c"
Marko Mikulicic 0:c0ecb8bf28eb 16994 #endif
Marko Mikulicic 0:c0ecb8bf28eb 16995 /*
Marko Mikulicic 0:c0ecb8bf28eb 16996 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 16997 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 16998 */
Marko Mikulicic 0:c0ecb8bf28eb 16999
Marko Mikulicic 0:c0ecb8bf28eb 17000 /* Amalgamated: #include "common/utf.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17001 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17002 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17003 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17004 /* Amalgamated: #include "v7/src/varint.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17005 /* Amalgamated: #include "v7/src/gc.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17006 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17007 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17008 /* Amalgamated: #include "v7/src/slre.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17009 /* Amalgamated: #include "v7/src/heapusage.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17010
Marko Mikulicic 0:c0ecb8bf28eb 17011 /* TODO(lsm): NaN payload location depends on endianness, make crossplatform */
Marko Mikulicic 0:c0ecb8bf28eb 17012 #define GET_VAL_NAN_PAYLOAD(v) ((char *) &(v))
Marko Mikulicic 0:c0ecb8bf28eb 17013
Marko Mikulicic 0:c0ecb8bf28eb 17014 /*
Marko Mikulicic 0:c0ecb8bf28eb 17015 * Dictionary of read-only strings with length > 5.
Marko Mikulicic 0:c0ecb8bf28eb 17016 * NOTE(lsm): must be sorted lexicographically, because
Marko Mikulicic 0:c0ecb8bf28eb 17017 * v_find_string_in_dictionary performs binary search over this list.
Marko Mikulicic 0:c0ecb8bf28eb 17018 */
Marko Mikulicic 0:c0ecb8bf28eb 17019 /* clang-format off */
Marko Mikulicic 0:c0ecb8bf28eb 17020 static const struct v7_vec_const v_dictionary_strings[] = {
Marko Mikulicic 0:c0ecb8bf28eb 17021 V7_VEC(" is not a function"),
Marko Mikulicic 0:c0ecb8bf28eb 17022 V7_VEC("Boolean"),
Marko Mikulicic 0:c0ecb8bf28eb 17023 V7_VEC("Crypto"),
Marko Mikulicic 0:c0ecb8bf28eb 17024 V7_VEC("EvalError"),
Marko Mikulicic 0:c0ecb8bf28eb 17025 V7_VEC("Function"),
Marko Mikulicic 0:c0ecb8bf28eb 17026 V7_VEC("Infinity"),
Marko Mikulicic 0:c0ecb8bf28eb 17027 V7_VEC("InternalError"),
Marko Mikulicic 0:c0ecb8bf28eb 17028 V7_VEC("LOG10E"),
Marko Mikulicic 0:c0ecb8bf28eb 17029 V7_VEC("MAX_VALUE"),
Marko Mikulicic 0:c0ecb8bf28eb 17030 V7_VEC("MIN_VALUE"),
Marko Mikulicic 0:c0ecb8bf28eb 17031 V7_VEC("NEGATIVE_INFINITY"),
Marko Mikulicic 0:c0ecb8bf28eb 17032 V7_VEC("Number"),
Marko Mikulicic 0:c0ecb8bf28eb 17033 V7_VEC("Object"),
Marko Mikulicic 0:c0ecb8bf28eb 17034 V7_VEC("POSITIVE_INFINITY"),
Marko Mikulicic 0:c0ecb8bf28eb 17035 V7_VEC("RangeError"),
Marko Mikulicic 0:c0ecb8bf28eb 17036 V7_VEC("ReferenceError"),
Marko Mikulicic 0:c0ecb8bf28eb 17037 V7_VEC("RegExp"),
Marko Mikulicic 0:c0ecb8bf28eb 17038 V7_VEC("SQRT1_2"),
Marko Mikulicic 0:c0ecb8bf28eb 17039 V7_VEC("Socket"),
Marko Mikulicic 0:c0ecb8bf28eb 17040 V7_VEC("String"),
Marko Mikulicic 0:c0ecb8bf28eb 17041 V7_VEC("SyntaxError"),
Marko Mikulicic 0:c0ecb8bf28eb 17042 V7_VEC("TypeError"),
Marko Mikulicic 0:c0ecb8bf28eb 17043 V7_VEC("UBJSON"),
Marko Mikulicic 0:c0ecb8bf28eb 17044 V7_VEC("_modcache"),
Marko Mikulicic 0:c0ecb8bf28eb 17045 V7_VEC("accept"),
Marko Mikulicic 0:c0ecb8bf28eb 17046 V7_VEC("arguments"),
Marko Mikulicic 0:c0ecb8bf28eb 17047 V7_VEC("base64_decode"),
Marko Mikulicic 0:c0ecb8bf28eb 17048 V7_VEC("base64_encode"),
Marko Mikulicic 0:c0ecb8bf28eb 17049 V7_VEC("boolean"),
Marko Mikulicic 0:c0ecb8bf28eb 17050 V7_VEC("charAt"),
Marko Mikulicic 0:c0ecb8bf28eb 17051 V7_VEC("charCodeAt"),
Marko Mikulicic 0:c0ecb8bf28eb 17052 V7_VEC("concat"),
Marko Mikulicic 0:c0ecb8bf28eb 17053 V7_VEC("configurable"),
Marko Mikulicic 0:c0ecb8bf28eb 17054 V7_VEC("connect"),
Marko Mikulicic 0:c0ecb8bf28eb 17055 V7_VEC("constructor"),
Marko Mikulicic 0:c0ecb8bf28eb 17056 V7_VEC("create"),
Marko Mikulicic 0:c0ecb8bf28eb 17057 V7_VEC("defineProperties"),
Marko Mikulicic 0:c0ecb8bf28eb 17058 V7_VEC("defineProperty"),
Marko Mikulicic 0:c0ecb8bf28eb 17059 V7_VEC("every"),
Marko Mikulicic 0:c0ecb8bf28eb 17060 V7_VEC("exists"),
Marko Mikulicic 0:c0ecb8bf28eb 17061 V7_VEC("exports"),
Marko Mikulicic 0:c0ecb8bf28eb 17062 V7_VEC("filter"),
Marko Mikulicic 0:c0ecb8bf28eb 17063 V7_VEC("forEach"),
Marko Mikulicic 0:c0ecb8bf28eb 17064 V7_VEC("fromCharCode"),
Marko Mikulicic 0:c0ecb8bf28eb 17065 V7_VEC("function"),
Marko Mikulicic 0:c0ecb8bf28eb 17066 V7_VEC("getDate"),
Marko Mikulicic 0:c0ecb8bf28eb 17067 V7_VEC("getDay"),
Marko Mikulicic 0:c0ecb8bf28eb 17068 V7_VEC("getFullYear"),
Marko Mikulicic 0:c0ecb8bf28eb 17069 V7_VEC("getHours"),
Marko Mikulicic 0:c0ecb8bf28eb 17070 V7_VEC("getMilliseconds"),
Marko Mikulicic 0:c0ecb8bf28eb 17071 V7_VEC("getMinutes"),
Marko Mikulicic 0:c0ecb8bf28eb 17072 V7_VEC("getMonth"),
Marko Mikulicic 0:c0ecb8bf28eb 17073 V7_VEC("getOwnPropertyDescriptor"),
Marko Mikulicic 0:c0ecb8bf28eb 17074 V7_VEC("getOwnPropertyNames"),
Marko Mikulicic 0:c0ecb8bf28eb 17075 V7_VEC("getPrototypeOf"),
Marko Mikulicic 0:c0ecb8bf28eb 17076 V7_VEC("getSeconds"),
Marko Mikulicic 0:c0ecb8bf28eb 17077 V7_VEC("getTime"),
Marko Mikulicic 0:c0ecb8bf28eb 17078 V7_VEC("getTimezoneOffset"),
Marko Mikulicic 0:c0ecb8bf28eb 17079 V7_VEC("getUTCDate"),
Marko Mikulicic 0:c0ecb8bf28eb 17080 V7_VEC("getUTCDay"),
Marko Mikulicic 0:c0ecb8bf28eb 17081 V7_VEC("getUTCFullYear"),
Marko Mikulicic 0:c0ecb8bf28eb 17082 V7_VEC("getUTCHours"),
Marko Mikulicic 0:c0ecb8bf28eb 17083 V7_VEC("getUTCMilliseconds"),
Marko Mikulicic 0:c0ecb8bf28eb 17084 V7_VEC("getUTCMinutes"),
Marko Mikulicic 0:c0ecb8bf28eb 17085 V7_VEC("getUTCMonth"),
Marko Mikulicic 0:c0ecb8bf28eb 17086 V7_VEC("getUTCSeconds"),
Marko Mikulicic 0:c0ecb8bf28eb 17087 V7_VEC("global"),
Marko Mikulicic 0:c0ecb8bf28eb 17088 V7_VEC("hasOwnProperty"),
Marko Mikulicic 0:c0ecb8bf28eb 17089 V7_VEC("ignoreCase"),
Marko Mikulicic 0:c0ecb8bf28eb 17090 V7_VEC("indexOf"),
Marko Mikulicic 0:c0ecb8bf28eb 17091 V7_VEC("isArray"),
Marko Mikulicic 0:c0ecb8bf28eb 17092 V7_VEC("isExtensible"),
Marko Mikulicic 0:c0ecb8bf28eb 17093 V7_VEC("isFinite"),
Marko Mikulicic 0:c0ecb8bf28eb 17094 V7_VEC("isPrototypeOf"),
Marko Mikulicic 0:c0ecb8bf28eb 17095 V7_VEC("lastIndex"),
Marko Mikulicic 0:c0ecb8bf28eb 17096 V7_VEC("lastIndexOf"),
Marko Mikulicic 0:c0ecb8bf28eb 17097 V7_VEC("length"),
Marko Mikulicic 0:c0ecb8bf28eb 17098 V7_VEC("listen"),
Marko Mikulicic 0:c0ecb8bf28eb 17099 V7_VEC("loadJSON"),
Marko Mikulicic 0:c0ecb8bf28eb 17100 V7_VEC("localeCompare"),
Marko Mikulicic 0:c0ecb8bf28eb 17101 V7_VEC("md5_hex"),
Marko Mikulicic 0:c0ecb8bf28eb 17102 V7_VEC("module"),
Marko Mikulicic 0:c0ecb8bf28eb 17103 V7_VEC("multiline"),
Marko Mikulicic 0:c0ecb8bf28eb 17104 V7_VEC("number"),
Marko Mikulicic 0:c0ecb8bf28eb 17105 V7_VEC("parseFloat"),
Marko Mikulicic 0:c0ecb8bf28eb 17106 V7_VEC("parseInt"),
Marko Mikulicic 0:c0ecb8bf28eb 17107 V7_VEC("preventExtensions"),
Marko Mikulicic 0:c0ecb8bf28eb 17108 V7_VEC("propertyIsEnumerable"),
Marko Mikulicic 0:c0ecb8bf28eb 17109 V7_VEC("prototype"),
Marko Mikulicic 0:c0ecb8bf28eb 17110 V7_VEC("random"),
Marko Mikulicic 0:c0ecb8bf28eb 17111 V7_VEC("recvAll"),
Marko Mikulicic 0:c0ecb8bf28eb 17112 V7_VEC("reduce"),
Marko Mikulicic 0:c0ecb8bf28eb 17113 V7_VEC("remove"),
Marko Mikulicic 0:c0ecb8bf28eb 17114 V7_VEC("rename"),
Marko Mikulicic 0:c0ecb8bf28eb 17115 V7_VEC("render"),
Marko Mikulicic 0:c0ecb8bf28eb 17116 V7_VEC("replace"),
Marko Mikulicic 0:c0ecb8bf28eb 17117 V7_VEC("require"),
Marko Mikulicic 0:c0ecb8bf28eb 17118 V7_VEC("reverse"),
Marko Mikulicic 0:c0ecb8bf28eb 17119 V7_VEC("search"),
Marko Mikulicic 0:c0ecb8bf28eb 17120 V7_VEC("setDate"),
Marko Mikulicic 0:c0ecb8bf28eb 17121 V7_VEC("setFullYear"),
Marko Mikulicic 0:c0ecb8bf28eb 17122 V7_VEC("setHours"),
Marko Mikulicic 0:c0ecb8bf28eb 17123 V7_VEC("setMilliseconds"),
Marko Mikulicic 0:c0ecb8bf28eb 17124 V7_VEC("setMinutes"),
Marko Mikulicic 0:c0ecb8bf28eb 17125 V7_VEC("setMonth"),
Marko Mikulicic 0:c0ecb8bf28eb 17126 V7_VEC("setSeconds"),
Marko Mikulicic 0:c0ecb8bf28eb 17127 V7_VEC("setTime"),
Marko Mikulicic 0:c0ecb8bf28eb 17128 V7_VEC("setUTCDate"),
Marko Mikulicic 0:c0ecb8bf28eb 17129 V7_VEC("setUTCFullYear"),
Marko Mikulicic 0:c0ecb8bf28eb 17130 V7_VEC("setUTCHours"),
Marko Mikulicic 0:c0ecb8bf28eb 17131 V7_VEC("setUTCMilliseconds"),
Marko Mikulicic 0:c0ecb8bf28eb 17132 V7_VEC("setUTCMinutes"),
Marko Mikulicic 0:c0ecb8bf28eb 17133 V7_VEC("setUTCMonth"),
Marko Mikulicic 0:c0ecb8bf28eb 17134 V7_VEC("setUTCSeconds"),
Marko Mikulicic 0:c0ecb8bf28eb 17135 V7_VEC("sha1_hex"),
Marko Mikulicic 0:c0ecb8bf28eb 17136 V7_VEC("source"),
Marko Mikulicic 0:c0ecb8bf28eb 17137 V7_VEC("splice"),
Marko Mikulicic 0:c0ecb8bf28eb 17138 V7_VEC("string"),
Marko Mikulicic 0:c0ecb8bf28eb 17139 V7_VEC("stringify"),
Marko Mikulicic 0:c0ecb8bf28eb 17140 V7_VEC("substr"),
Marko Mikulicic 0:c0ecb8bf28eb 17141 V7_VEC("substring"),
Marko Mikulicic 0:c0ecb8bf28eb 17142 V7_VEC("toDateString"),
Marko Mikulicic 0:c0ecb8bf28eb 17143 V7_VEC("toExponential"),
Marko Mikulicic 0:c0ecb8bf28eb 17144 V7_VEC("toFixed"),
Marko Mikulicic 0:c0ecb8bf28eb 17145 V7_VEC("toISOString"),
Marko Mikulicic 0:c0ecb8bf28eb 17146 V7_VEC("toJSON"),
Marko Mikulicic 0:c0ecb8bf28eb 17147 V7_VEC("toLocaleDateString"),
Marko Mikulicic 0:c0ecb8bf28eb 17148 V7_VEC("toLocaleLowerCase"),
Marko Mikulicic 0:c0ecb8bf28eb 17149 V7_VEC("toLocaleString"),
Marko Mikulicic 0:c0ecb8bf28eb 17150 V7_VEC("toLocaleTimeString"),
Marko Mikulicic 0:c0ecb8bf28eb 17151 V7_VEC("toLocaleUpperCase"),
Marko Mikulicic 0:c0ecb8bf28eb 17152 V7_VEC("toLowerCase"),
Marko Mikulicic 0:c0ecb8bf28eb 17153 V7_VEC("toPrecision"),
Marko Mikulicic 0:c0ecb8bf28eb 17154 V7_VEC("toString"),
Marko Mikulicic 0:c0ecb8bf28eb 17155 V7_VEC("toTimeString"),
Marko Mikulicic 0:c0ecb8bf28eb 17156 V7_VEC("toUTCString"),
Marko Mikulicic 0:c0ecb8bf28eb 17157 V7_VEC("toUpperCase"),
Marko Mikulicic 0:c0ecb8bf28eb 17158 V7_VEC("valueOf"),
Marko Mikulicic 0:c0ecb8bf28eb 17159 V7_VEC("writable"),
Marko Mikulicic 0:c0ecb8bf28eb 17160 };
Marko Mikulicic 0:c0ecb8bf28eb 17161 /* clang-format on */
Marko Mikulicic 0:c0ecb8bf28eb 17162
Marko Mikulicic 0:c0ecb8bf28eb 17163 int nextesc(const char **p); /* from SLRE */
Marko Mikulicic 0:c0ecb8bf28eb 17164 V7_PRIVATE size_t unescape(const char *s, size_t len, char *to) {
Marko Mikulicic 0:c0ecb8bf28eb 17165 const char *end = s + len;
Marko Mikulicic 0:c0ecb8bf28eb 17166 size_t n = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17167 char tmp[4];
Marko Mikulicic 0:c0ecb8bf28eb 17168 Rune r;
Marko Mikulicic 0:c0ecb8bf28eb 17169
Marko Mikulicic 0:c0ecb8bf28eb 17170 while (s < end) {
Marko Mikulicic 0:c0ecb8bf28eb 17171 s += chartorune(&r, s);
Marko Mikulicic 0:c0ecb8bf28eb 17172 if (r == '\\' && s < end) {
Marko Mikulicic 0:c0ecb8bf28eb 17173 switch (*s) {
Marko Mikulicic 0:c0ecb8bf28eb 17174 case '"':
Marko Mikulicic 0:c0ecb8bf28eb 17175 s++, r = '"';
Marko Mikulicic 0:c0ecb8bf28eb 17176 break;
Marko Mikulicic 0:c0ecb8bf28eb 17177 case '\'':
Marko Mikulicic 0:c0ecb8bf28eb 17178 s++, r = '\'';
Marko Mikulicic 0:c0ecb8bf28eb 17179 break;
Marko Mikulicic 0:c0ecb8bf28eb 17180 case '\n':
Marko Mikulicic 0:c0ecb8bf28eb 17181 s++, r = '\n';
Marko Mikulicic 0:c0ecb8bf28eb 17182 break;
Marko Mikulicic 0:c0ecb8bf28eb 17183 default: {
Marko Mikulicic 0:c0ecb8bf28eb 17184 const char *tmp_s = s;
Marko Mikulicic 0:c0ecb8bf28eb 17185 int i = nextesc(&s);
Marko Mikulicic 0:c0ecb8bf28eb 17186 switch (i) {
Marko Mikulicic 0:c0ecb8bf28eb 17187 case -SLRE_INVALID_ESC_CHAR:
Marko Mikulicic 0:c0ecb8bf28eb 17188 r = '\\';
Marko Mikulicic 0:c0ecb8bf28eb 17189 s = tmp_s;
Marko Mikulicic 0:c0ecb8bf28eb 17190 n += runetochar(to == NULL ? tmp : to + n, &r);
Marko Mikulicic 0:c0ecb8bf28eb 17191 s += chartorune(&r, s);
Marko Mikulicic 0:c0ecb8bf28eb 17192 break;
Marko Mikulicic 0:c0ecb8bf28eb 17193 case -SLRE_INVALID_HEX_DIGIT:
Marko Mikulicic 0:c0ecb8bf28eb 17194 default:
Marko Mikulicic 0:c0ecb8bf28eb 17195 r = i;
Marko Mikulicic 0:c0ecb8bf28eb 17196 }
Marko Mikulicic 0:c0ecb8bf28eb 17197 }
Marko Mikulicic 0:c0ecb8bf28eb 17198 }
Marko Mikulicic 0:c0ecb8bf28eb 17199 }
Marko Mikulicic 0:c0ecb8bf28eb 17200 n += runetochar(to == NULL ? tmp : to + n, &r);
Marko Mikulicic 0:c0ecb8bf28eb 17201 }
Marko Mikulicic 0:c0ecb8bf28eb 17202
Marko Mikulicic 0:c0ecb8bf28eb 17203 return n;
Marko Mikulicic 0:c0ecb8bf28eb 17204 }
Marko Mikulicic 0:c0ecb8bf28eb 17205
Marko Mikulicic 0:c0ecb8bf28eb 17206 static int v_find_string_in_dictionary(const char *s, size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 17207 size_t start = 0, end = ARRAY_SIZE(v_dictionary_strings);
Marko Mikulicic 0:c0ecb8bf28eb 17208
Marko Mikulicic 0:c0ecb8bf28eb 17209 while (s != NULL && start < end) {
Marko Mikulicic 0:c0ecb8bf28eb 17210 size_t mid = start + (end - start) / 2;
Marko Mikulicic 0:c0ecb8bf28eb 17211 const struct v7_vec_const *v = &v_dictionary_strings[mid];
Marko Mikulicic 0:c0ecb8bf28eb 17212 size_t min_len = len < v->len ? len : v->len;
Marko Mikulicic 0:c0ecb8bf28eb 17213 int comparison_result = memcmp(s, v->p, min_len);
Marko Mikulicic 0:c0ecb8bf28eb 17214 if (comparison_result == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 17215 comparison_result = len - v->len;
Marko Mikulicic 0:c0ecb8bf28eb 17216 }
Marko Mikulicic 0:c0ecb8bf28eb 17217 if (comparison_result < 0) {
Marko Mikulicic 0:c0ecb8bf28eb 17218 end = mid;
Marko Mikulicic 0:c0ecb8bf28eb 17219 } else if (comparison_result > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 17220 start = mid + 1;
Marko Mikulicic 0:c0ecb8bf28eb 17221 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17222 return mid;
Marko Mikulicic 0:c0ecb8bf28eb 17223 }
Marko Mikulicic 0:c0ecb8bf28eb 17224 }
Marko Mikulicic 0:c0ecb8bf28eb 17225 return -1;
Marko Mikulicic 0:c0ecb8bf28eb 17226 }
Marko Mikulicic 0:c0ecb8bf28eb 17227
Marko Mikulicic 0:c0ecb8bf28eb 17228 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 17229 V7_PRIVATE enum v7_err v7_char_code_at(struct v7 *v7, val_t obj, val_t arg,
Marko Mikulicic 0:c0ecb8bf28eb 17230 double *res) {
Marko Mikulicic 0:c0ecb8bf28eb 17231 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 17232 size_t n;
Marko Mikulicic 0:c0ecb8bf28eb 17233 val_t s = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 17234 const char *p = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 17235 double at = v7_get_double(v7, arg);
Marko Mikulicic 0:c0ecb8bf28eb 17236
Marko Mikulicic 0:c0ecb8bf28eb 17237 *res = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17238
Marko Mikulicic 0:c0ecb8bf28eb 17239 rcode = to_string(v7, obj, &s, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 17240 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 17241 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17242 }
Marko Mikulicic 0:c0ecb8bf28eb 17243
Marko Mikulicic 0:c0ecb8bf28eb 17244 p = v7_get_string(v7, &s, &n);
Marko Mikulicic 0:c0ecb8bf28eb 17245
Marko Mikulicic 0:c0ecb8bf28eb 17246 n = utfnlen(p, n);
Marko Mikulicic 0:c0ecb8bf28eb 17247 if (v7_is_number(arg) && at >= 0 && at < n) {
Marko Mikulicic 0:c0ecb8bf28eb 17248 Rune r = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17249 p = utfnshift(p, at);
Marko Mikulicic 0:c0ecb8bf28eb 17250 chartorune(&r, (char *) p);
Marko Mikulicic 0:c0ecb8bf28eb 17251 *res = r;
Marko Mikulicic 0:c0ecb8bf28eb 17252 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17253 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17254 *res = NAN;
Marko Mikulicic 0:c0ecb8bf28eb 17255 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17256 }
Marko Mikulicic 0:c0ecb8bf28eb 17257
Marko Mikulicic 0:c0ecb8bf28eb 17258 clean:
Marko Mikulicic 0:c0ecb8bf28eb 17259 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 17260 }
Marko Mikulicic 0:c0ecb8bf28eb 17261
Marko Mikulicic 0:c0ecb8bf28eb 17262 V7_PRIVATE int s_cmp(struct v7 *v7, val_t a, val_t b) {
Marko Mikulicic 0:c0ecb8bf28eb 17263 size_t a_len, b_len;
Marko Mikulicic 0:c0ecb8bf28eb 17264 const char *a_ptr, *b_ptr;
Marko Mikulicic 0:c0ecb8bf28eb 17265
Marko Mikulicic 0:c0ecb8bf28eb 17266 a_ptr = v7_get_string(v7, &a, &a_len);
Marko Mikulicic 0:c0ecb8bf28eb 17267 b_ptr = v7_get_string(v7, &b, &b_len);
Marko Mikulicic 0:c0ecb8bf28eb 17268
Marko Mikulicic 0:c0ecb8bf28eb 17269 if (a_len == b_len) {
Marko Mikulicic 0:c0ecb8bf28eb 17270 return memcmp(a_ptr, b_ptr, a_len);
Marko Mikulicic 0:c0ecb8bf28eb 17271 }
Marko Mikulicic 0:c0ecb8bf28eb 17272 if (a_len > b_len) {
Marko Mikulicic 0:c0ecb8bf28eb 17273 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 17274 } else if (a_len < b_len) {
Marko Mikulicic 0:c0ecb8bf28eb 17275 return -1;
Marko Mikulicic 0:c0ecb8bf28eb 17276 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17277 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 17278 }
Marko Mikulicic 0:c0ecb8bf28eb 17279 }
Marko Mikulicic 0:c0ecb8bf28eb 17280
Marko Mikulicic 0:c0ecb8bf28eb 17281 V7_PRIVATE val_t s_concat(struct v7 *v7, val_t a, val_t b) {
Marko Mikulicic 0:c0ecb8bf28eb 17282 size_t a_len, b_len, res_len;
Marko Mikulicic 0:c0ecb8bf28eb 17283 const char *a_ptr, *b_ptr, *res_ptr;
Marko Mikulicic 0:c0ecb8bf28eb 17284 val_t res;
Marko Mikulicic 0:c0ecb8bf28eb 17285
Marko Mikulicic 0:c0ecb8bf28eb 17286 /* Find out lengths of both srtings */
Marko Mikulicic 0:c0ecb8bf28eb 17287 a_ptr = v7_get_string(v7, &a, &a_len);
Marko Mikulicic 0:c0ecb8bf28eb 17288 b_ptr = v7_get_string(v7, &b, &b_len);
Marko Mikulicic 0:c0ecb8bf28eb 17289
Marko Mikulicic 0:c0ecb8bf28eb 17290 /* Create an placeholder string */
Marko Mikulicic 0:c0ecb8bf28eb 17291 res = v7_mk_string(v7, NULL, a_len + b_len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 17292
Marko Mikulicic 0:c0ecb8bf28eb 17293 /* v7_mk_string() may have reallocated mbuf - revalidate pointers */
Marko Mikulicic 0:c0ecb8bf28eb 17294 a_ptr = v7_get_string(v7, &a, &a_len);
Marko Mikulicic 0:c0ecb8bf28eb 17295 b_ptr = v7_get_string(v7, &b, &b_len);
Marko Mikulicic 0:c0ecb8bf28eb 17296
Marko Mikulicic 0:c0ecb8bf28eb 17297 /* Copy strings into the placeholder */
Marko Mikulicic 0:c0ecb8bf28eb 17298 res_ptr = v7_get_string(v7, &res, &res_len);
Marko Mikulicic 0:c0ecb8bf28eb 17299 memcpy((char *) res_ptr, a_ptr, a_len);
Marko Mikulicic 0:c0ecb8bf28eb 17300 memcpy((char *) res_ptr + a_len, b_ptr, b_len);
Marko Mikulicic 0:c0ecb8bf28eb 17301
Marko Mikulicic 0:c0ecb8bf28eb 17302 return res;
Marko Mikulicic 0:c0ecb8bf28eb 17303 }
Marko Mikulicic 0:c0ecb8bf28eb 17304
Marko Mikulicic 0:c0ecb8bf28eb 17305 V7_PRIVATE unsigned long cstr_to_ulong(const char *s, size_t len, int *ok) {
Marko Mikulicic 0:c0ecb8bf28eb 17306 char *e;
Marko Mikulicic 0:c0ecb8bf28eb 17307 unsigned long res = strtoul(s, &e, 10);
Marko Mikulicic 0:c0ecb8bf28eb 17308 *ok = (e == s + len) && len != 0;
Marko Mikulicic 0:c0ecb8bf28eb 17309 return res;
Marko Mikulicic 0:c0ecb8bf28eb 17310 }
Marko Mikulicic 0:c0ecb8bf28eb 17311
Marko Mikulicic 0:c0ecb8bf28eb 17312 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 17313 V7_PRIVATE enum v7_err str_to_ulong(struct v7 *v7, val_t v, int *ok,
Marko Mikulicic 0:c0ecb8bf28eb 17314 unsigned long *res) {
Marko Mikulicic 0:c0ecb8bf28eb 17315 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 17316 char buf[100];
Marko Mikulicic 0:c0ecb8bf28eb 17317 size_t len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17318
Marko Mikulicic 0:c0ecb8bf28eb 17319 V7_TRY(to_string(v7, v, NULL, buf, sizeof(buf), &len));
Marko Mikulicic 0:c0ecb8bf28eb 17320
Marko Mikulicic 0:c0ecb8bf28eb 17321 *res = cstr_to_ulong(buf, len, ok);
Marko Mikulicic 0:c0ecb8bf28eb 17322
Marko Mikulicic 0:c0ecb8bf28eb 17323 clean:
Marko Mikulicic 0:c0ecb8bf28eb 17324 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 17325 }
Marko Mikulicic 0:c0ecb8bf28eb 17326
Marko Mikulicic 0:c0ecb8bf28eb 17327 /* Insert a string into mbuf at specified offset */
Marko Mikulicic 0:c0ecb8bf28eb 17328 V7_PRIVATE void embed_string(struct mbuf *m, size_t offset, const char *p,
Marko Mikulicic 0:c0ecb8bf28eb 17329 size_t len, uint8_t /*enum embstr_flags*/ flags) {
Marko Mikulicic 0:c0ecb8bf28eb 17330 char *old_base = m->buf;
Marko Mikulicic 0:c0ecb8bf28eb 17331 uint8_t p_backed_by_mbuf = p >= old_base && p < old_base + m->len;
Marko Mikulicic 0:c0ecb8bf28eb 17332 size_t n = (flags & EMBSTR_UNESCAPE) ? unescape(p, len, NULL) : len;
Marko Mikulicic 0:c0ecb8bf28eb 17333
Marko Mikulicic 0:c0ecb8bf28eb 17334 /* Calculate how many bytes length takes */
Marko Mikulicic 0:c0ecb8bf28eb 17335 int k = calc_llen(n);
Marko Mikulicic 0:c0ecb8bf28eb 17336
Marko Mikulicic 0:c0ecb8bf28eb 17337 /* total length: varing length + string len + zero-term */
Marko Mikulicic 0:c0ecb8bf28eb 17338 size_t tot_len = k + n + !!(flags & EMBSTR_ZERO_TERM);
Marko Mikulicic 0:c0ecb8bf28eb 17339
Marko Mikulicic 0:c0ecb8bf28eb 17340 /* Allocate buffer */
Marko Mikulicic 0:c0ecb8bf28eb 17341 heapusage_dont_count(1);
Marko Mikulicic 0:c0ecb8bf28eb 17342 mbuf_insert(m, offset, NULL, tot_len);
Marko Mikulicic 0:c0ecb8bf28eb 17343 heapusage_dont_count(0);
Marko Mikulicic 0:c0ecb8bf28eb 17344
Marko Mikulicic 0:c0ecb8bf28eb 17345 /* Fixup p if it was relocated by mbuf_insert() above */
Marko Mikulicic 0:c0ecb8bf28eb 17346 if (p_backed_by_mbuf) {
Marko Mikulicic 0:c0ecb8bf28eb 17347 p += m->buf - old_base;
Marko Mikulicic 0:c0ecb8bf28eb 17348 }
Marko Mikulicic 0:c0ecb8bf28eb 17349
Marko Mikulicic 0:c0ecb8bf28eb 17350 /* Write length */
Marko Mikulicic 0:c0ecb8bf28eb 17351 encode_varint(n, (unsigned char *) m->buf + offset);
Marko Mikulicic 0:c0ecb8bf28eb 17352
Marko Mikulicic 0:c0ecb8bf28eb 17353 /* Write string */
Marko Mikulicic 0:c0ecb8bf28eb 17354 if (p != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 17355 if (flags & EMBSTR_UNESCAPE) {
Marko Mikulicic 0:c0ecb8bf28eb 17356 unescape(p, len, m->buf + offset + k);
Marko Mikulicic 0:c0ecb8bf28eb 17357 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17358 memcpy(m->buf + offset + k, p, len);
Marko Mikulicic 0:c0ecb8bf28eb 17359 }
Marko Mikulicic 0:c0ecb8bf28eb 17360 }
Marko Mikulicic 0:c0ecb8bf28eb 17361
Marko Mikulicic 0:c0ecb8bf28eb 17362 /* add NULL-terminator if needed */
Marko Mikulicic 0:c0ecb8bf28eb 17363 if (flags & EMBSTR_ZERO_TERM) {
Marko Mikulicic 0:c0ecb8bf28eb 17364 m->buf[offset + tot_len - 1] = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 17365 }
Marko Mikulicic 0:c0ecb8bf28eb 17366 }
Marko Mikulicic 0:c0ecb8bf28eb 17367
Marko Mikulicic 0:c0ecb8bf28eb 17368 /* Create a string */
Marko Mikulicic 0:c0ecb8bf28eb 17369 v7_val_t v7_mk_string(struct v7 *v7, const char *p, size_t len, int copy) {
Marko Mikulicic 0:c0ecb8bf28eb 17370 struct mbuf *m = copy ? &v7->owned_strings : &v7->foreign_strings;
Marko Mikulicic 0:c0ecb8bf28eb 17371 val_t offset = m->len, tag = V7_TAG_STRING_F;
Marko Mikulicic 0:c0ecb8bf28eb 17372 int dict_index;
Marko Mikulicic 0:c0ecb8bf28eb 17373
Marko Mikulicic 0:c0ecb8bf28eb 17374 #ifdef V7_GC_AFTER_STRING_ALLOC
Marko Mikulicic 0:c0ecb8bf28eb 17375 v7->need_gc = 1;
Marko Mikulicic 0:c0ecb8bf28eb 17376 #endif
Marko Mikulicic 0:c0ecb8bf28eb 17377
Marko Mikulicic 0:c0ecb8bf28eb 17378 if (len == ~((size_t) 0)) len = strlen(p);
Marko Mikulicic 0:c0ecb8bf28eb 17379
Marko Mikulicic 0:c0ecb8bf28eb 17380 if (len <= 4) {
Marko Mikulicic 0:c0ecb8bf28eb 17381 char *s = GET_VAL_NAN_PAYLOAD(offset) + 1;
Marko Mikulicic 0:c0ecb8bf28eb 17382 offset = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17383 if (p != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 17384 memcpy(s, p, len);
Marko Mikulicic 0:c0ecb8bf28eb 17385 }
Marko Mikulicic 0:c0ecb8bf28eb 17386 s[-1] = len;
Marko Mikulicic 0:c0ecb8bf28eb 17387 tag = V7_TAG_STRING_I;
Marko Mikulicic 0:c0ecb8bf28eb 17388 } else if (len == 5) {
Marko Mikulicic 0:c0ecb8bf28eb 17389 char *s = GET_VAL_NAN_PAYLOAD(offset);
Marko Mikulicic 0:c0ecb8bf28eb 17390 offset = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17391 if (p != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 17392 memcpy(s, p, len);
Marko Mikulicic 0:c0ecb8bf28eb 17393 }
Marko Mikulicic 0:c0ecb8bf28eb 17394 tag = V7_TAG_STRING_5;
Marko Mikulicic 0:c0ecb8bf28eb 17395 } else if ((dict_index = v_find_string_in_dictionary(p, len)) >= 0) {
Marko Mikulicic 0:c0ecb8bf28eb 17396 offset = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17397 GET_VAL_NAN_PAYLOAD(offset)[0] = dict_index;
Marko Mikulicic 0:c0ecb8bf28eb 17398 tag = V7_TAG_STRING_D;
Marko Mikulicic 0:c0ecb8bf28eb 17399 } else if (copy) {
Marko Mikulicic 0:c0ecb8bf28eb 17400 compute_need_gc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 17401
Marko Mikulicic 0:c0ecb8bf28eb 17402 /*
Marko Mikulicic 0:c0ecb8bf28eb 17403 * Before embedding new string, check if the reallocation is needed. If
Marko Mikulicic 0:c0ecb8bf28eb 17404 * so, perform the reallocation by calling `mbuf_resize` manually, since we
Marko Mikulicic 0:c0ecb8bf28eb 17405 * need to preallocate some extra space (`_V7_STRING_BUF_RESERVE`)
Marko Mikulicic 0:c0ecb8bf28eb 17406 */
Marko Mikulicic 0:c0ecb8bf28eb 17407 if ((m->len + len) > m->size) {
Marko Mikulicic 0:c0ecb8bf28eb 17408 heapusage_dont_count(1);
Marko Mikulicic 0:c0ecb8bf28eb 17409 mbuf_resize(m, m->len + len + _V7_STRING_BUF_RESERVE);
Marko Mikulicic 0:c0ecb8bf28eb 17410 heapusage_dont_count(0);
Marko Mikulicic 0:c0ecb8bf28eb 17411 }
Marko Mikulicic 0:c0ecb8bf28eb 17412 embed_string(m, m->len, p, len, EMBSTR_ZERO_TERM);
Marko Mikulicic 0:c0ecb8bf28eb 17413 tag = V7_TAG_STRING_O;
Marko Mikulicic 0:c0ecb8bf28eb 17414 #ifndef V7_DISABLE_STR_ALLOC_SEQ
Marko Mikulicic 0:c0ecb8bf28eb 17415 /* TODO(imax): panic if offset >= 2^32. */
Marko Mikulicic 0:c0ecb8bf28eb 17416 offset |= ((val_t) gc_next_allocation_seqn(v7, p, len)) << 32;
Marko Mikulicic 0:c0ecb8bf28eb 17417 #endif
Marko Mikulicic 0:c0ecb8bf28eb 17418 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17419 /* foreign string */
Marko Mikulicic 0:c0ecb8bf28eb 17420 if (sizeof(void *) <= 4 && len <= UINT16_MAX) {
Marko Mikulicic 0:c0ecb8bf28eb 17421 /* small foreign strings can fit length and ptr in the val_t */
Marko Mikulicic 0:c0ecb8bf28eb 17422 offset = (uint64_t) len << 32 | (uint64_t)(uintptr_t) p;
Marko Mikulicic 0:c0ecb8bf28eb 17423 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17424 /* bigger strings need indirection that uses ram */
Marko Mikulicic 0:c0ecb8bf28eb 17425 size_t pos = m->len;
Marko Mikulicic 0:c0ecb8bf28eb 17426 int llen = calc_llen(len);
Marko Mikulicic 0:c0ecb8bf28eb 17427
Marko Mikulicic 0:c0ecb8bf28eb 17428 /* allocate space for len and ptr */
Marko Mikulicic 0:c0ecb8bf28eb 17429 heapusage_dont_count(1);
Marko Mikulicic 0:c0ecb8bf28eb 17430 mbuf_insert(m, pos, NULL, llen + sizeof(p));
Marko Mikulicic 0:c0ecb8bf28eb 17431 heapusage_dont_count(0);
Marko Mikulicic 0:c0ecb8bf28eb 17432
Marko Mikulicic 0:c0ecb8bf28eb 17433 encode_varint(len, (uint8_t *) (m->buf + pos));
Marko Mikulicic 0:c0ecb8bf28eb 17434 memcpy(m->buf + pos + llen, &p, sizeof(p));
Marko Mikulicic 0:c0ecb8bf28eb 17435 }
Marko Mikulicic 0:c0ecb8bf28eb 17436 tag = V7_TAG_STRING_F;
Marko Mikulicic 0:c0ecb8bf28eb 17437 }
Marko Mikulicic 0:c0ecb8bf28eb 17438
Marko Mikulicic 0:c0ecb8bf28eb 17439 /* NOTE(lsm): don't use pointer_to_value, 32-bit ptrs will truncate */
Marko Mikulicic 0:c0ecb8bf28eb 17440 return (offset & ~V7_TAG_MASK) | tag;
Marko Mikulicic 0:c0ecb8bf28eb 17441 }
Marko Mikulicic 0:c0ecb8bf28eb 17442
Marko Mikulicic 0:c0ecb8bf28eb 17443 int v7_is_string(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 17444 uint64_t t = v & V7_TAG_MASK;
Marko Mikulicic 0:c0ecb8bf28eb 17445 return t == V7_TAG_STRING_I || t == V7_TAG_STRING_F || t == V7_TAG_STRING_O ||
Marko Mikulicic 0:c0ecb8bf28eb 17446 t == V7_TAG_STRING_5 || t == V7_TAG_STRING_D;
Marko Mikulicic 0:c0ecb8bf28eb 17447 }
Marko Mikulicic 0:c0ecb8bf28eb 17448
Marko Mikulicic 0:c0ecb8bf28eb 17449 /* Get a pointer to string and string length. */
Marko Mikulicic 0:c0ecb8bf28eb 17450 const char *v7_get_string(struct v7 *v7, val_t *v, size_t *sizep) {
Marko Mikulicic 0:c0ecb8bf28eb 17451 uint64_t tag = v[0] & V7_TAG_MASK;
Marko Mikulicic 0:c0ecb8bf28eb 17452 const char *p = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 17453 int llen;
Marko Mikulicic 0:c0ecb8bf28eb 17454 size_t size = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17455
Marko Mikulicic 0:c0ecb8bf28eb 17456 if (!v7_is_string(*v)) {
Marko Mikulicic 0:c0ecb8bf28eb 17457 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17458 }
Marko Mikulicic 0:c0ecb8bf28eb 17459
Marko Mikulicic 0:c0ecb8bf28eb 17460 if (tag == V7_TAG_STRING_I) {
Marko Mikulicic 0:c0ecb8bf28eb 17461 p = GET_VAL_NAN_PAYLOAD(*v) + 1;
Marko Mikulicic 0:c0ecb8bf28eb 17462 size = p[-1];
Marko Mikulicic 0:c0ecb8bf28eb 17463 } else if (tag == V7_TAG_STRING_5) {
Marko Mikulicic 0:c0ecb8bf28eb 17464 p = GET_VAL_NAN_PAYLOAD(*v);
Marko Mikulicic 0:c0ecb8bf28eb 17465 size = 5;
Marko Mikulicic 0:c0ecb8bf28eb 17466 } else if (tag == V7_TAG_STRING_D) {
Marko Mikulicic 0:c0ecb8bf28eb 17467 int index = ((unsigned char *) GET_VAL_NAN_PAYLOAD(*v))[0];
Marko Mikulicic 0:c0ecb8bf28eb 17468 size = v_dictionary_strings[index].len;
Marko Mikulicic 0:c0ecb8bf28eb 17469 p = v_dictionary_strings[index].p;
Marko Mikulicic 0:c0ecb8bf28eb 17470 } else if (tag == V7_TAG_STRING_O) {
Marko Mikulicic 0:c0ecb8bf28eb 17471 size_t offset = (size_t) gc_string_val_to_offset(*v);
Marko Mikulicic 0:c0ecb8bf28eb 17472 char *s = v7->owned_strings.buf + offset;
Marko Mikulicic 0:c0ecb8bf28eb 17473
Marko Mikulicic 0:c0ecb8bf28eb 17474 #ifndef V7_DISABLE_STR_ALLOC_SEQ
Marko Mikulicic 0:c0ecb8bf28eb 17475 gc_check_valid_allocation_seqn(v7, (*v >> 32) & 0xFFFF);
Marko Mikulicic 0:c0ecb8bf28eb 17476 #endif
Marko Mikulicic 0:c0ecb8bf28eb 17477
Marko Mikulicic 0:c0ecb8bf28eb 17478 size = decode_varint((uint8_t *) s, &llen);
Marko Mikulicic 0:c0ecb8bf28eb 17479 p = s + llen;
Marko Mikulicic 0:c0ecb8bf28eb 17480 } else if (tag == V7_TAG_STRING_F) {
Marko Mikulicic 0:c0ecb8bf28eb 17481 /*
Marko Mikulicic 0:c0ecb8bf28eb 17482 * short foreign strings on <=32-bit machines can be encoded in a compact
Marko Mikulicic 0:c0ecb8bf28eb 17483 * form:
Marko Mikulicic 0:c0ecb8bf28eb 17484 *
Marko Mikulicic 0:c0ecb8bf28eb 17485 * 7 6 5 4 3 2 1 0
Marko Mikulicic 0:c0ecb8bf28eb 17486 * 11111111|1111tttt|llllllll|llllllll|ssssssss|ssssssss|ssssssss|ssssssss
Marko Mikulicic 0:c0ecb8bf28eb 17487 *
Marko Mikulicic 0:c0ecb8bf28eb 17488 * Strings longer than 2^26 will be indireceted through the foreign_strings
Marko Mikulicic 0:c0ecb8bf28eb 17489 * mbuf.
Marko Mikulicic 0:c0ecb8bf28eb 17490 *
Marko Mikulicic 0:c0ecb8bf28eb 17491 * We don't use a different tag to represent those two cases. Instead, all
Marko Mikulicic 0:c0ecb8bf28eb 17492 * foreign strings represented with the help of the foreign_strings mbuf
Marko Mikulicic 0:c0ecb8bf28eb 17493 * will have the upper 16-bits of the payload set to zero. This allows us to
Marko Mikulicic 0:c0ecb8bf28eb 17494 * represent up to 477 million foreign strings longer than 64k.
Marko Mikulicic 0:c0ecb8bf28eb 17495 */
Marko Mikulicic 0:c0ecb8bf28eb 17496 uint16_t len = (*v >> 32) & 0xFFFF;
Marko Mikulicic 0:c0ecb8bf28eb 17497 if (sizeof(void *) <= 4 && len != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 17498 size = (size_t) len;
Marko Mikulicic 0:c0ecb8bf28eb 17499 p = (const char *) (uintptr_t) *v;
Marko Mikulicic 0:c0ecb8bf28eb 17500 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17501 size_t offset = (size_t) gc_string_val_to_offset(*v);
Marko Mikulicic 0:c0ecb8bf28eb 17502 char *s = v7->foreign_strings.buf + offset;
Marko Mikulicic 0:c0ecb8bf28eb 17503
Marko Mikulicic 0:c0ecb8bf28eb 17504 size = decode_varint((uint8_t *) s, &llen);
Marko Mikulicic 0:c0ecb8bf28eb 17505 memcpy(&p, s + llen, sizeof(p));
Marko Mikulicic 0:c0ecb8bf28eb 17506 }
Marko Mikulicic 0:c0ecb8bf28eb 17507 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17508 assert(0);
Marko Mikulicic 0:c0ecb8bf28eb 17509 }
Marko Mikulicic 0:c0ecb8bf28eb 17510
Marko Mikulicic 0:c0ecb8bf28eb 17511 clean:
Marko Mikulicic 0:c0ecb8bf28eb 17512 if (sizep != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 17513 *sizep = size;
Marko Mikulicic 0:c0ecb8bf28eb 17514 }
Marko Mikulicic 0:c0ecb8bf28eb 17515 return p;
Marko Mikulicic 0:c0ecb8bf28eb 17516 }
Marko Mikulicic 0:c0ecb8bf28eb 17517
Marko Mikulicic 0:c0ecb8bf28eb 17518 const char *v7_get_cstring(struct v7 *v7, v7_val_t *value) {
Marko Mikulicic 0:c0ecb8bf28eb 17519 size_t size;
Marko Mikulicic 0:c0ecb8bf28eb 17520 const char *s = v7_get_string(v7, value, &size);
Marko Mikulicic 0:c0ecb8bf28eb 17521 if (s == NULL) return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 17522 if (s[size] != 0 || strlen(s) != size) {
Marko Mikulicic 0:c0ecb8bf28eb 17523 return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 17524 }
Marko Mikulicic 0:c0ecb8bf28eb 17525 return s;
Marko Mikulicic 0:c0ecb8bf28eb 17526 }
Marko Mikulicic 0:c0ecb8bf28eb 17527 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 17528 #line 1 "v7/src/array.c"
Marko Mikulicic 0:c0ecb8bf28eb 17529 #endif
Marko Mikulicic 0:c0ecb8bf28eb 17530 /*
Marko Mikulicic 0:c0ecb8bf28eb 17531 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 17532 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 17533 */
Marko Mikulicic 0:c0ecb8bf28eb 17534
Marko Mikulicic 0:c0ecb8bf28eb 17535 /* Amalgamated: #include "common/str_util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17536 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17537 /* Amalgamated: #include "v7/src/array.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17538 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17539 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17540 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17541 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17542 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17543
Marko Mikulicic 0:c0ecb8bf28eb 17544 /* like c_snprintf but returns `size` if write is truncated */
Marko Mikulicic 0:c0ecb8bf28eb 17545 static int v_sprintf_s(char *buf, size_t size, const char *fmt, ...) {
Marko Mikulicic 0:c0ecb8bf28eb 17546 size_t n;
Marko Mikulicic 0:c0ecb8bf28eb 17547 va_list ap;
Marko Mikulicic 0:c0ecb8bf28eb 17548 va_start(ap, fmt);
Marko Mikulicic 0:c0ecb8bf28eb 17549 n = c_vsnprintf(buf, size, fmt, ap);
Marko Mikulicic 0:c0ecb8bf28eb 17550 if (n > size) {
Marko Mikulicic 0:c0ecb8bf28eb 17551 return size;
Marko Mikulicic 0:c0ecb8bf28eb 17552 }
Marko Mikulicic 0:c0ecb8bf28eb 17553 return n;
Marko Mikulicic 0:c0ecb8bf28eb 17554 }
Marko Mikulicic 0:c0ecb8bf28eb 17555
Marko Mikulicic 0:c0ecb8bf28eb 17556 v7_val_t v7_mk_array(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 17557 val_t a = mk_object(v7, v7->vals.array_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 17558 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 17559 v7_def(v7, a, "", 0, _V7_DESC_HIDDEN(1), V7_NULL);
Marko Mikulicic 0:c0ecb8bf28eb 17560 #endif
Marko Mikulicic 0:c0ecb8bf28eb 17561 return a;
Marko Mikulicic 0:c0ecb8bf28eb 17562 }
Marko Mikulicic 0:c0ecb8bf28eb 17563
Marko Mikulicic 0:c0ecb8bf28eb 17564 int v7_is_array(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 17565 return v7_is_generic_object(v) &&
Marko Mikulicic 0:c0ecb8bf28eb 17566 is_prototype_of(v7, v, v7->vals.array_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 17567 }
Marko Mikulicic 0:c0ecb8bf28eb 17568
Marko Mikulicic 0:c0ecb8bf28eb 17569 /*
Marko Mikulicic 0:c0ecb8bf28eb 17570 * Dense arrays are backed by mbuf. Currently the array can only grow by
Marko Mikulicic 0:c0ecb8bf28eb 17571 * appending (i.e. setting an element whose index == array.length)
Marko Mikulicic 0:c0ecb8bf28eb 17572 *
Marko Mikulicic 0:c0ecb8bf28eb 17573 * TODO(mkm): automatically promote dense arrays to normal objects
Marko Mikulicic 0:c0ecb8bf28eb 17574 * when they are used as sparse arrays or to store arbitrary keys
Marko Mikulicic 0:c0ecb8bf28eb 17575 * (perhaps a hybrid approach)
Marko Mikulicic 0:c0ecb8bf28eb 17576 * TODO(mkm): small sparsness doesn't have to promote the array,
Marko Mikulicic 0:c0ecb8bf28eb 17577 * we can just fill empty slots with a tag. In JS missing array
Marko Mikulicic 0:c0ecb8bf28eb 17578 * indices are subtly different from indices with an undefined value
Marko Mikulicic 0:c0ecb8bf28eb 17579 * (key iteration).
Marko Mikulicic 0:c0ecb8bf28eb 17580 * TODO(mkm): change the interpreter so it can set elements in dense arrays
Marko Mikulicic 0:c0ecb8bf28eb 17581 */
Marko Mikulicic 0:c0ecb8bf28eb 17582 V7_PRIVATE val_t v7_mk_dense_array(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 17583 val_t a = v7_mk_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 17584 #ifdef V7_ENABLE_DENSE_ARRAYS
Marko Mikulicic 0:c0ecb8bf28eb 17585 v7_own(v7, &a);
Marko Mikulicic 0:c0ecb8bf28eb 17586 v7_def(v7, a, "", 0, _V7_DESC_HIDDEN(1), V7_NULL);
Marko Mikulicic 0:c0ecb8bf28eb 17587
Marko Mikulicic 0:c0ecb8bf28eb 17588 /*
Marko Mikulicic 0:c0ecb8bf28eb 17589 * Before setting a `V7_OBJ_DENSE_ARRAY` flag, make sure we don't have
Marko Mikulicic 0:c0ecb8bf28eb 17590 * `V7_OBJ_FUNCTION` flag set
Marko Mikulicic 0:c0ecb8bf28eb 17591 */
Marko Mikulicic 0:c0ecb8bf28eb 17592 assert(!(get_object_struct(a)->attributes & V7_OBJ_FUNCTION));
Marko Mikulicic 0:c0ecb8bf28eb 17593 get_object_struct(a)->attributes |= V7_OBJ_DENSE_ARRAY;
Marko Mikulicic 0:c0ecb8bf28eb 17594
Marko Mikulicic 0:c0ecb8bf28eb 17595 v7_disown(v7, &a);
Marko Mikulicic 0:c0ecb8bf28eb 17596 #endif
Marko Mikulicic 0:c0ecb8bf28eb 17597 return a;
Marko Mikulicic 0:c0ecb8bf28eb 17598 }
Marko Mikulicic 0:c0ecb8bf28eb 17599
Marko Mikulicic 0:c0ecb8bf28eb 17600 /* TODO_V7_ERR */
Marko Mikulicic 0:c0ecb8bf28eb 17601 val_t v7_array_get(struct v7 *v7, val_t arr, unsigned long index) {
Marko Mikulicic 0:c0ecb8bf28eb 17602 return v7_array_get2(v7, arr, index, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 17603 }
Marko Mikulicic 0:c0ecb8bf28eb 17604
Marko Mikulicic 0:c0ecb8bf28eb 17605 /* TODO_V7_ERR */
Marko Mikulicic 0:c0ecb8bf28eb 17606 val_t v7_array_get2(struct v7 *v7, val_t arr, unsigned long index, int *has) {
Marko Mikulicic 0:c0ecb8bf28eb 17607 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 17608 val_t res;
Marko Mikulicic 0:c0ecb8bf28eb 17609
Marko Mikulicic 0:c0ecb8bf28eb 17610 if (has != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 17611 *has = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17612 }
Marko Mikulicic 0:c0ecb8bf28eb 17613 if (v7_is_object(arr)) {
Marko Mikulicic 0:c0ecb8bf28eb 17614 if (get_object_struct(arr)->attributes & V7_OBJ_DENSE_ARRAY) {
Marko Mikulicic 0:c0ecb8bf28eb 17615 struct v7_property *p =
Marko Mikulicic 0:c0ecb8bf28eb 17616 v7_get_own_property2(v7, arr, "", 0, _V7_PROPERTY_HIDDEN);
Marko Mikulicic 0:c0ecb8bf28eb 17617 struct mbuf *abuf = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 17618 unsigned long len;
Marko Mikulicic 0:c0ecb8bf28eb 17619 if (p != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 17620 abuf = (struct mbuf *) v7_get_ptr(v7, p->value);
Marko Mikulicic 0:c0ecb8bf28eb 17621 }
Marko Mikulicic 0:c0ecb8bf28eb 17622 if (abuf == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 17623 res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 17624 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17625 }
Marko Mikulicic 0:c0ecb8bf28eb 17626 len = abuf->len / sizeof(val_t);
Marko Mikulicic 0:c0ecb8bf28eb 17627 if (index >= len) {
Marko Mikulicic 0:c0ecb8bf28eb 17628 res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 17629 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17630 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17631 memcpy(&res, abuf->buf + index * sizeof(val_t), sizeof(val_t));
Marko Mikulicic 0:c0ecb8bf28eb 17632 if (has != NULL && res != V7_TAG_NOVALUE) *has = 1;
Marko Mikulicic 0:c0ecb8bf28eb 17633 if (res == V7_TAG_NOVALUE) {
Marko Mikulicic 0:c0ecb8bf28eb 17634 res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 17635 }
Marko Mikulicic 0:c0ecb8bf28eb 17636 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17637 }
Marko Mikulicic 0:c0ecb8bf28eb 17638 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17639 struct v7_property *p;
Marko Mikulicic 0:c0ecb8bf28eb 17640 char buf[20];
Marko Mikulicic 0:c0ecb8bf28eb 17641 int n = v_sprintf_s(buf, sizeof(buf), "%lu", index);
Marko Mikulicic 0:c0ecb8bf28eb 17642 p = v7_get_property(v7, arr, buf, n);
Marko Mikulicic 0:c0ecb8bf28eb 17643 if (has != NULL && p != NULL) *has = 1;
Marko Mikulicic 0:c0ecb8bf28eb 17644 V7_TRY(v7_property_value(v7, arr, p, &res));
Marko Mikulicic 0:c0ecb8bf28eb 17645 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17646 }
Marko Mikulicic 0:c0ecb8bf28eb 17647 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17648 res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 17649 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17650 }
Marko Mikulicic 0:c0ecb8bf28eb 17651
Marko Mikulicic 0:c0ecb8bf28eb 17652 clean:
Marko Mikulicic 0:c0ecb8bf28eb 17653 (void) rcode;
Marko Mikulicic 0:c0ecb8bf28eb 17654 return res;
Marko Mikulicic 0:c0ecb8bf28eb 17655 }
Marko Mikulicic 0:c0ecb8bf28eb 17656
Marko Mikulicic 0:c0ecb8bf28eb 17657 #if V7_ENABLE_DENSE_ARRAYS
Marko Mikulicic 0:c0ecb8bf28eb 17658
Marko Mikulicic 0:c0ecb8bf28eb 17659 /* Create V7 strings for integers such as array indices */
Marko Mikulicic 0:c0ecb8bf28eb 17660 static val_t ulong_to_str(struct v7 *v7, unsigned long n) {
Marko Mikulicic 0:c0ecb8bf28eb 17661 char buf[100];
Marko Mikulicic 0:c0ecb8bf28eb 17662 int len;
Marko Mikulicic 0:c0ecb8bf28eb 17663 len = c_snprintf(buf, sizeof(buf), "%lu", n);
Marko Mikulicic 0:c0ecb8bf28eb 17664 return v7_mk_string(v7, buf, len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 17665 }
Marko Mikulicic 0:c0ecb8bf28eb 17666
Marko Mikulicic 0:c0ecb8bf28eb 17667 /*
Marko Mikulicic 0:c0ecb8bf28eb 17668 * Pack 15-bit length and 15 bit index, leaving 2 bits for tag. the LSB has to
Marko Mikulicic 0:c0ecb8bf28eb 17669 * be set to distinguish it from a prop pointer.
Marko Mikulicic 0:c0ecb8bf28eb 17670 * In alternative we just fetch the length from obj at each call to v7_next_prop
Marko Mikulicic 0:c0ecb8bf28eb 17671 * and just stuff the index here (e.g. on 8/16-bit platforms).
Marko Mikulicic 0:c0ecb8bf28eb 17672 * TODO(mkm): conditional for 16-bit platforms
Marko Mikulicic 0:c0ecb8bf28eb 17673 */
Marko Mikulicic 0:c0ecb8bf28eb 17674 #define PACK_ITER(len, idx) \
Marko Mikulicic 0:c0ecb8bf28eb 17675 ((struct v7_property *) ((len) << 17 | (idx) << 1 | 1))
Marko Mikulicic 0:c0ecb8bf28eb 17676
Marko Mikulicic 0:c0ecb8bf28eb 17677 #define UNPACK_ITER_LEN(p) (((uintptr_t) p) >> 17)
Marko Mikulicic 0:c0ecb8bf28eb 17678 #define UNPACK_ITER_IDX(p) ((((uintptr_t) p) >> 1) & 0x7FFF)
Marko Mikulicic 0:c0ecb8bf28eb 17679 #define IS_PACKED_ITER(p) ((uintptr_t) p & 1)
Marko Mikulicic 0:c0ecb8bf28eb 17680
Marko Mikulicic 0:c0ecb8bf28eb 17681 void *v7_next_prop(struct v7 *v7, val_t obj, void *h, val_t *name, val_t *val,
Marko Mikulicic 0:c0ecb8bf28eb 17682 v7_prop_attr_t *attrs) {
Marko Mikulicic 0:c0ecb8bf28eb 17683 struct v7_property *p = (struct v7_property *) h;
Marko Mikulicic 0:c0ecb8bf28eb 17684
Marko Mikulicic 0:c0ecb8bf28eb 17685 if (get_object_struct(obj)->attributes & V7_OBJ_DENSE_ARRAY) {
Marko Mikulicic 0:c0ecb8bf28eb 17686 /* This is a dense array. Find backing mbuf and fetch values from there */
Marko Mikulicic 0:c0ecb8bf28eb 17687 struct v7_property *hp =
Marko Mikulicic 0:c0ecb8bf28eb 17688 v7_get_own_property2(v7, obj, "", 0, _V7_PROPERTY_HIDDEN);
Marko Mikulicic 0:c0ecb8bf28eb 17689 struct mbuf *abuf = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 17690 unsigned long len, idx;
Marko Mikulicic 0:c0ecb8bf28eb 17691 if (hp != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 17692 abuf = (struct mbuf *) v7_get_ptr(v7, hp->value);
Marko Mikulicic 0:c0ecb8bf28eb 17693 }
Marko Mikulicic 0:c0ecb8bf28eb 17694 if (abuf == NULL) return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 17695 len = abuf->len / sizeof(val_t);
Marko Mikulicic 0:c0ecb8bf28eb 17696 if (len == 0) return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 17697 idx = (p == NULL) ? 0 : UNPACK_ITER_IDX(p) + 1;
Marko Mikulicic 0:c0ecb8bf28eb 17698 p = (idx == len) ? get_object_struct(obj)->properties : PACK_ITER(len, idx);
Marko Mikulicic 0:c0ecb8bf28eb 17699 if (val != NULL) *val = ((val_t *) abuf->buf)[idx];
Marko Mikulicic 0:c0ecb8bf28eb 17700 if (attrs != NULL) *attrs = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17701 if (name != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 17702 char buf[20];
Marko Mikulicic 0:c0ecb8bf28eb 17703 int n = v_sprintf_s(buf, sizeof(buf), "%lu", index);
Marko Mikulicic 0:c0ecb8bf28eb 17704 *name = v7_mk_string(v7, buf, n, 1);
Marko Mikulicic 0:c0ecb8bf28eb 17705 }
Marko Mikulicic 0:c0ecb8bf28eb 17706 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17707 /* Ordinary object */
Marko Mikulicic 0:c0ecb8bf28eb 17708 p = (p == NULL) ? get_object_struct(obj)->properties : p->next;
Marko Mikulicic 0:c0ecb8bf28eb 17709 if (p != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 17710 if (name != NULL) *name = p->name;
Marko Mikulicic 0:c0ecb8bf28eb 17711 if (val != NULL) *val = p->value;
Marko Mikulicic 0:c0ecb8bf28eb 17712 if (attrs != NULL) *attrs = p->attributes;
Marko Mikulicic 0:c0ecb8bf28eb 17713 }
Marko Mikulicic 0:c0ecb8bf28eb 17714 }
Marko Mikulicic 0:c0ecb8bf28eb 17715
Marko Mikulicic 0:c0ecb8bf28eb 17716 return p;
Marko Mikulicic 0:c0ecb8bf28eb 17717 }
Marko Mikulicic 0:c0ecb8bf28eb 17718
Marko Mikulicic 0:c0ecb8bf28eb 17719 V7_PRIVATE val_t
Marko Mikulicic 0:c0ecb8bf28eb 17720 v7_iter_get_value(struct v7 *v7, val_t obj, struct v7_property *p) {
Marko Mikulicic 0:c0ecb8bf28eb 17721 return IS_PACKED_ITER(p) ? v7_array_get(v7, obj, UNPACK_ITER_IDX(p))
Marko Mikulicic 0:c0ecb8bf28eb 17722 : p->value;
Marko Mikulicic 0:c0ecb8bf28eb 17723 }
Marko Mikulicic 0:c0ecb8bf28eb 17724
Marko Mikulicic 0:c0ecb8bf28eb 17725 V7_PRIVATE val_t v7_iter_get_name(struct v7 *v7, struct v7_property *p) {
Marko Mikulicic 0:c0ecb8bf28eb 17726 return IS_PACKED_ITER(p) ? ulong_to_str(v7, UNPACK_ITER_IDX(p)) : p->name;
Marko Mikulicic 0:c0ecb8bf28eb 17727 }
Marko Mikulicic 0:c0ecb8bf28eb 17728
Marko Mikulicic 0:c0ecb8bf28eb 17729 V7_PRIVATE uint8_t v7_iter_get_attrs(struct v7_property *p) {
Marko Mikulicic 0:c0ecb8bf28eb 17730 return IS_PACKED_ITER(p) ? 0 : p->attributes;
Marko Mikulicic 0:c0ecb8bf28eb 17731 }
Marko Mikulicic 0:c0ecb8bf28eb 17732
Marko Mikulicic 0:c0ecb8bf28eb 17733 /* return array index as number or undefined. works with iterators */
Marko Mikulicic 0:c0ecb8bf28eb 17734 V7_PRIVATE enum v7_err v7_iter_get_index(struct v7 *v7, struct v7_property *p,
Marko Mikulicic 0:c0ecb8bf28eb 17735 val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 17736 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 17737 int ok;
Marko Mikulicic 0:c0ecb8bf28eb 17738 unsigned long res;
Marko Mikulicic 0:c0ecb8bf28eb 17739 if (IS_PACKED_ITER(p)) {
Marko Mikulicic 0:c0ecb8bf28eb 17740 *res = v7_mk_number(v7, UNPACK_ITER_IDX(p));
Marko Mikulicic 0:c0ecb8bf28eb 17741 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17742 }
Marko Mikulicic 0:c0ecb8bf28eb 17743 V7_TRY(str_to_ulong(v7, p->name, &ok, &res));
Marko Mikulicic 0:c0ecb8bf28eb 17744 if (!ok || res >= UINT32_MAX) {
Marko Mikulicic 0:c0ecb8bf28eb 17745 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17746 }
Marko Mikulicic 0:c0ecb8bf28eb 17747 *res = v7_mk_number(v7, res);
Marko Mikulicic 0:c0ecb8bf28eb 17748 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17749
Marko Mikulicic 0:c0ecb8bf28eb 17750 clean:
Marko Mikulicic 0:c0ecb8bf28eb 17751 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 17752 }
Marko Mikulicic 0:c0ecb8bf28eb 17753 #endif
Marko Mikulicic 0:c0ecb8bf28eb 17754
Marko Mikulicic 0:c0ecb8bf28eb 17755 /* TODO_V7_ERR */
Marko Mikulicic 0:c0ecb8bf28eb 17756 unsigned long v7_array_length(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 17757 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 17758 struct v7_property *p;
Marko Mikulicic 0:c0ecb8bf28eb 17759 unsigned long len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17760
Marko Mikulicic 0:c0ecb8bf28eb 17761 if (!v7_is_object(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 17762 len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17763 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17764 }
Marko Mikulicic 0:c0ecb8bf28eb 17765
Marko Mikulicic 0:c0ecb8bf28eb 17766 #if V7_ENABLE_DENSE_ARRAYS
Marko Mikulicic 0:c0ecb8bf28eb 17767 if (get_object_struct(v)->attributes & V7_OBJ_DENSE_ARRAY) {
Marko Mikulicic 0:c0ecb8bf28eb 17768 struct v7_property *p =
Marko Mikulicic 0:c0ecb8bf28eb 17769 v7_get_own_property2(v7, v, "", 0, _V7_PROPERTY_HIDDEN);
Marko Mikulicic 0:c0ecb8bf28eb 17770 struct mbuf *abuf;
Marko Mikulicic 0:c0ecb8bf28eb 17771 if (p == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 17772 len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17773 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17774 }
Marko Mikulicic 0:c0ecb8bf28eb 17775 abuf = (struct mbuf *) v7_get_ptr(v7, p->value);
Marko Mikulicic 0:c0ecb8bf28eb 17776 if (abuf == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 17777 len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17778 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17779 }
Marko Mikulicic 0:c0ecb8bf28eb 17780 len = abuf->len / sizeof(val_t);
Marko Mikulicic 0:c0ecb8bf28eb 17781 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17782 }
Marko Mikulicic 0:c0ecb8bf28eb 17783 #endif
Marko Mikulicic 0:c0ecb8bf28eb 17784
Marko Mikulicic 0:c0ecb8bf28eb 17785 for (p = get_object_struct(v)->properties; p != NULL; p = p->next) {
Marko Mikulicic 0:c0ecb8bf28eb 17786 int ok = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17787 unsigned long n = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17788 V7_TRY(str_to_ulong(v7, p->name, &ok, &n));
Marko Mikulicic 0:c0ecb8bf28eb 17789 if (ok && n >= len && n < UINT32_MAX) {
Marko Mikulicic 0:c0ecb8bf28eb 17790 len = n + 1;
Marko Mikulicic 0:c0ecb8bf28eb 17791 }
Marko Mikulicic 0:c0ecb8bf28eb 17792 }
Marko Mikulicic 0:c0ecb8bf28eb 17793
Marko Mikulicic 0:c0ecb8bf28eb 17794 clean:
Marko Mikulicic 0:c0ecb8bf28eb 17795 (void) rcode;
Marko Mikulicic 0:c0ecb8bf28eb 17796 return len;
Marko Mikulicic 0:c0ecb8bf28eb 17797 }
Marko Mikulicic 0:c0ecb8bf28eb 17798
Marko Mikulicic 0:c0ecb8bf28eb 17799 int v7_array_set(struct v7 *v7, val_t arr, unsigned long index, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 17800 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 17801 uint8_t saved_is_thrown = 0;
Marko Mikulicic 0:c0ecb8bf28eb 17802 val_t saved_thrown = v7_get_thrown_value(v7, &saved_is_thrown);
Marko Mikulicic 0:c0ecb8bf28eb 17803 int ret = -1;
Marko Mikulicic 0:c0ecb8bf28eb 17804
Marko Mikulicic 0:c0ecb8bf28eb 17805 rcode = v7_array_set_throwing(v7, arr, index, v, &ret);
Marko Mikulicic 0:c0ecb8bf28eb 17806 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 17807 rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 17808 if (saved_is_thrown) {
Marko Mikulicic 0:c0ecb8bf28eb 17809 rcode = v7_throw(v7, saved_thrown);
Marko Mikulicic 0:c0ecb8bf28eb 17810 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17811 v7_clear_thrown_value(v7);
Marko Mikulicic 0:c0ecb8bf28eb 17812 }
Marko Mikulicic 0:c0ecb8bf28eb 17813 ret = -1;
Marko Mikulicic 0:c0ecb8bf28eb 17814 }
Marko Mikulicic 0:c0ecb8bf28eb 17815
Marko Mikulicic 0:c0ecb8bf28eb 17816 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 17817 }
Marko Mikulicic 0:c0ecb8bf28eb 17818
Marko Mikulicic 0:c0ecb8bf28eb 17819 enum v7_err v7_array_set_throwing(struct v7 *v7, val_t arr, unsigned long index,
Marko Mikulicic 0:c0ecb8bf28eb 17820 val_t v, int *res) {
Marko Mikulicic 0:c0ecb8bf28eb 17821 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 17822 int ires = -1;
Marko Mikulicic 0:c0ecb8bf28eb 17823
Marko Mikulicic 0:c0ecb8bf28eb 17824 if (v7_is_object(arr)) {
Marko Mikulicic 0:c0ecb8bf28eb 17825 if (get_object_struct(arr)->attributes & V7_OBJ_DENSE_ARRAY) {
Marko Mikulicic 0:c0ecb8bf28eb 17826 struct v7_property *p =
Marko Mikulicic 0:c0ecb8bf28eb 17827 v7_get_own_property2(v7, arr, "", 0, _V7_PROPERTY_HIDDEN);
Marko Mikulicic 0:c0ecb8bf28eb 17828 struct mbuf *abuf;
Marko Mikulicic 0:c0ecb8bf28eb 17829 unsigned long len;
Marko Mikulicic 0:c0ecb8bf28eb 17830 assert(p != NULL);
Marko Mikulicic 0:c0ecb8bf28eb 17831 abuf = (struct mbuf *) v7_get_ptr(v7, p->value);
Marko Mikulicic 0:c0ecb8bf28eb 17832
Marko Mikulicic 0:c0ecb8bf28eb 17833 if (get_object_struct(arr)->attributes & V7_OBJ_NOT_EXTENSIBLE) {
Marko Mikulicic 0:c0ecb8bf28eb 17834 if (is_strict_mode(v7)) {
Marko Mikulicic 0:c0ecb8bf28eb 17835 rcode = v7_throwf(v7, TYPE_ERROR, "Object is not extensible");
Marko Mikulicic 0:c0ecb8bf28eb 17836 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17837 }
Marko Mikulicic 0:c0ecb8bf28eb 17838
Marko Mikulicic 0:c0ecb8bf28eb 17839 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17840 }
Marko Mikulicic 0:c0ecb8bf28eb 17841
Marko Mikulicic 0:c0ecb8bf28eb 17842 if (abuf == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 17843 abuf = (struct mbuf *) malloc(sizeof(*abuf));
Marko Mikulicic 0:c0ecb8bf28eb 17844 mbuf_init(abuf, sizeof(val_t) * (index + 1));
Marko Mikulicic 0:c0ecb8bf28eb 17845 p->value = v7_mk_foreign(v7, abuf);
Marko Mikulicic 0:c0ecb8bf28eb 17846 }
Marko Mikulicic 0:c0ecb8bf28eb 17847 len = abuf->len / sizeof(val_t);
Marko Mikulicic 0:c0ecb8bf28eb 17848 /* TODO(mkm): possibly promote to sparse array */
Marko Mikulicic 0:c0ecb8bf28eb 17849 if (index > len) {
Marko Mikulicic 0:c0ecb8bf28eb 17850 unsigned long i;
Marko Mikulicic 0:c0ecb8bf28eb 17851 val_t s = V7_TAG_NOVALUE;
Marko Mikulicic 0:c0ecb8bf28eb 17852 for (i = len; i < index; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 17853 mbuf_append(abuf, (char *) &s, sizeof(val_t));
Marko Mikulicic 0:c0ecb8bf28eb 17854 }
Marko Mikulicic 0:c0ecb8bf28eb 17855 len = index;
Marko Mikulicic 0:c0ecb8bf28eb 17856 }
Marko Mikulicic 0:c0ecb8bf28eb 17857
Marko Mikulicic 0:c0ecb8bf28eb 17858 if (index == len) {
Marko Mikulicic 0:c0ecb8bf28eb 17859 mbuf_append(abuf, (char *) &v, sizeof(val_t));
Marko Mikulicic 0:c0ecb8bf28eb 17860 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17861 memcpy(abuf->buf + index * sizeof(val_t), &v, sizeof(val_t));
Marko Mikulicic 0:c0ecb8bf28eb 17862 }
Marko Mikulicic 0:c0ecb8bf28eb 17863 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17864 char buf[20];
Marko Mikulicic 0:c0ecb8bf28eb 17865 int n = v_sprintf_s(buf, sizeof(buf), "%lu", index);
Marko Mikulicic 0:c0ecb8bf28eb 17866 {
Marko Mikulicic 0:c0ecb8bf28eb 17867 struct v7_property *tmp = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 17868 rcode = set_property(v7, arr, buf, n, v, &tmp);
Marko Mikulicic 0:c0ecb8bf28eb 17869 ires = (tmp == NULL) ? -1 : 0;
Marko Mikulicic 0:c0ecb8bf28eb 17870 }
Marko Mikulicic 0:c0ecb8bf28eb 17871 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 17872 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 17873 }
Marko Mikulicic 0:c0ecb8bf28eb 17874 }
Marko Mikulicic 0:c0ecb8bf28eb 17875 }
Marko Mikulicic 0:c0ecb8bf28eb 17876
Marko Mikulicic 0:c0ecb8bf28eb 17877 clean:
Marko Mikulicic 0:c0ecb8bf28eb 17878 if (res != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 17879 *res = ires;
Marko Mikulicic 0:c0ecb8bf28eb 17880 }
Marko Mikulicic 0:c0ecb8bf28eb 17881 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 17882 }
Marko Mikulicic 0:c0ecb8bf28eb 17883
Marko Mikulicic 0:c0ecb8bf28eb 17884 void v7_array_del(struct v7 *v7, val_t arr, unsigned long index) {
Marko Mikulicic 0:c0ecb8bf28eb 17885 char buf[20];
Marko Mikulicic 0:c0ecb8bf28eb 17886 int n = v_sprintf_s(buf, sizeof(buf), "%lu", index);
Marko Mikulicic 0:c0ecb8bf28eb 17887 v7_del(v7, arr, buf, n);
Marko Mikulicic 0:c0ecb8bf28eb 17888 }
Marko Mikulicic 0:c0ecb8bf28eb 17889
Marko Mikulicic 0:c0ecb8bf28eb 17890 int v7_array_push(struct v7 *v7, v7_val_t arr, v7_val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 17891 return v7_array_set(v7, arr, v7_array_length(v7, arr), v);
Marko Mikulicic 0:c0ecb8bf28eb 17892 }
Marko Mikulicic 0:c0ecb8bf28eb 17893
Marko Mikulicic 0:c0ecb8bf28eb 17894 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 17895 enum v7_err v7_array_push_throwing(struct v7 *v7, v7_val_t arr, v7_val_t v,
Marko Mikulicic 0:c0ecb8bf28eb 17896 int *res) {
Marko Mikulicic 0:c0ecb8bf28eb 17897 return v7_array_set_throwing(v7, arr, v7_array_length(v7, arr), v, res);
Marko Mikulicic 0:c0ecb8bf28eb 17898 }
Marko Mikulicic 0:c0ecb8bf28eb 17899 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 17900 #line 1 "v7/src/object.c"
Marko Mikulicic 0:c0ecb8bf28eb 17901 #endif
Marko Mikulicic 0:c0ecb8bf28eb 17902 /*
Marko Mikulicic 0:c0ecb8bf28eb 17903 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 17904 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 17905 */
Marko Mikulicic 0:c0ecb8bf28eb 17906
Marko Mikulicic 0:c0ecb8bf28eb 17907 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17908 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17909 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17910 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17911 /* Amalgamated: #include "v7/src/gc.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17912 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17913 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17914 /* Amalgamated: #include "v7/src/array.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17915 /* Amalgamated: #include "v7/src/eval.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17916 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17917 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17918 /* Amalgamated: #include "v7/src/std_proxy.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17919 /* Amalgamated: #include "v7/src/util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 17920
Marko Mikulicic 0:c0ecb8bf28eb 17921 /*
Marko Mikulicic 0:c0ecb8bf28eb 17922 * Default property attributes (see `v7_prop_attr_t`)
Marko Mikulicic 0:c0ecb8bf28eb 17923 */
Marko Mikulicic 0:c0ecb8bf28eb 17924 #define V7_DEFAULT_PROPERTY_ATTRS 0
Marko Mikulicic 0:c0ecb8bf28eb 17925
Marko Mikulicic 0:c0ecb8bf28eb 17926 V7_PRIVATE val_t mk_object(struct v7 *v7, val_t prototype) {
Marko Mikulicic 0:c0ecb8bf28eb 17927 struct v7_generic_object *o = new_generic_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 17928 if (o == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 17929 return V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 17930 }
Marko Mikulicic 0:c0ecb8bf28eb 17931 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 17932 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 17933 o->base.entity_id_base = V7_ENTITY_ID_PART_OBJ;
Marko Mikulicic 0:c0ecb8bf28eb 17934 o->base.entity_id_spec = V7_ENTITY_ID_PART_GEN_OBJ;
Marko Mikulicic 0:c0ecb8bf28eb 17935 #endif
Marko Mikulicic 0:c0ecb8bf28eb 17936 o->base.properties = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 17937 obj_prototype_set(v7, &o->base, get_object_struct(prototype));
Marko Mikulicic 0:c0ecb8bf28eb 17938 return v7_object_to_value(&o->base);
Marko Mikulicic 0:c0ecb8bf28eb 17939 }
Marko Mikulicic 0:c0ecb8bf28eb 17940
Marko Mikulicic 0:c0ecb8bf28eb 17941 v7_val_t v7_mk_object(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 17942 return mk_object(v7, v7->vals.object_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 17943 }
Marko Mikulicic 0:c0ecb8bf28eb 17944
Marko Mikulicic 0:c0ecb8bf28eb 17945 V7_PRIVATE val_t v7_object_to_value(struct v7_object *o) {
Marko Mikulicic 0:c0ecb8bf28eb 17946 if (o == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 17947 return V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 17948 } else if (o->attributes & V7_OBJ_FUNCTION) {
Marko Mikulicic 0:c0ecb8bf28eb 17949 return pointer_to_value(o) | V7_TAG_FUNCTION;
Marko Mikulicic 0:c0ecb8bf28eb 17950 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17951 return pointer_to_value(o) | V7_TAG_OBJECT;
Marko Mikulicic 0:c0ecb8bf28eb 17952 }
Marko Mikulicic 0:c0ecb8bf28eb 17953 }
Marko Mikulicic 0:c0ecb8bf28eb 17954
Marko Mikulicic 0:c0ecb8bf28eb 17955 V7_PRIVATE struct v7_generic_object *get_generic_object_struct(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 17956 struct v7_generic_object *ret = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 17957 if (v7_is_null(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 17958 ret = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 17959 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17960 assert(v7_is_generic_object(v));
Marko Mikulicic 0:c0ecb8bf28eb 17961 ret = (struct v7_generic_object *) get_ptr(v);
Marko Mikulicic 0:c0ecb8bf28eb 17962 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 17963 if (ret->base.entity_id_base != V7_ENTITY_ID_PART_OBJ) {
Marko Mikulicic 0:c0ecb8bf28eb 17964 fprintf(stderr, "not a generic object!\n");
Marko Mikulicic 0:c0ecb8bf28eb 17965 abort();
Marko Mikulicic 0:c0ecb8bf28eb 17966 } else if (ret->base.entity_id_spec != V7_ENTITY_ID_PART_GEN_OBJ) {
Marko Mikulicic 0:c0ecb8bf28eb 17967 fprintf(stderr, "not an object (but is a generic object)!\n");
Marko Mikulicic 0:c0ecb8bf28eb 17968 abort();
Marko Mikulicic 0:c0ecb8bf28eb 17969 }
Marko Mikulicic 0:c0ecb8bf28eb 17970 #endif
Marko Mikulicic 0:c0ecb8bf28eb 17971 }
Marko Mikulicic 0:c0ecb8bf28eb 17972 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 17973 }
Marko Mikulicic 0:c0ecb8bf28eb 17974
Marko Mikulicic 0:c0ecb8bf28eb 17975 V7_PRIVATE struct v7_object *get_object_struct(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 17976 struct v7_object *ret = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 17977 if (v7_is_null(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 17978 ret = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 17979 } else {
Marko Mikulicic 0:c0ecb8bf28eb 17980 assert(v7_is_object(v));
Marko Mikulicic 0:c0ecb8bf28eb 17981 ret = (struct v7_object *) get_ptr(v);
Marko Mikulicic 0:c0ecb8bf28eb 17982 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 17983 if (ret->entity_id_base != V7_ENTITY_ID_PART_OBJ) {
Marko Mikulicic 0:c0ecb8bf28eb 17984 fprintf(stderr, "not an object!\n");
Marko Mikulicic 0:c0ecb8bf28eb 17985 abort();
Marko Mikulicic 0:c0ecb8bf28eb 17986 }
Marko Mikulicic 0:c0ecb8bf28eb 17987 #endif
Marko Mikulicic 0:c0ecb8bf28eb 17988 }
Marko Mikulicic 0:c0ecb8bf28eb 17989 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 17990 }
Marko Mikulicic 0:c0ecb8bf28eb 17991
Marko Mikulicic 0:c0ecb8bf28eb 17992 int v7_is_object(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 17993 return (v & V7_TAG_MASK) == V7_TAG_OBJECT ||
Marko Mikulicic 0:c0ecb8bf28eb 17994 (v & V7_TAG_MASK) == V7_TAG_FUNCTION;
Marko Mikulicic 0:c0ecb8bf28eb 17995 }
Marko Mikulicic 0:c0ecb8bf28eb 17996
Marko Mikulicic 0:c0ecb8bf28eb 17997 V7_PRIVATE int v7_is_generic_object(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 17998 return (v & V7_TAG_MASK) == V7_TAG_OBJECT;
Marko Mikulicic 0:c0ecb8bf28eb 17999 }
Marko Mikulicic 0:c0ecb8bf28eb 18000
Marko Mikulicic 0:c0ecb8bf28eb 18001 /* Object properties {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 18002
Marko Mikulicic 0:c0ecb8bf28eb 18003 V7_PRIVATE struct v7_property *v7_mk_property(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 18004 struct v7_property *p = new_property(v7);
Marko Mikulicic 0:c0ecb8bf28eb 18005 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 18006 p->entity_id = V7_ENTITY_ID_PROP;
Marko Mikulicic 0:c0ecb8bf28eb 18007 #endif
Marko Mikulicic 0:c0ecb8bf28eb 18008 p->next = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18009 p->name = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18010 p->value = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18011 p->attributes = 0;
Marko Mikulicic 0:c0ecb8bf28eb 18012 return p;
Marko Mikulicic 0:c0ecb8bf28eb 18013 }
Marko Mikulicic 0:c0ecb8bf28eb 18014
Marko Mikulicic 0:c0ecb8bf28eb 18015 V7_PRIVATE struct v7_property *v7_get_own_property2(struct v7 *v7, val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 18016 const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 18017 size_t len,
Marko Mikulicic 0:c0ecb8bf28eb 18018 v7_prop_attr_t attrs) {
Marko Mikulicic 0:c0ecb8bf28eb 18019 struct v7_property *p;
Marko Mikulicic 0:c0ecb8bf28eb 18020 struct v7_object *o;
Marko Mikulicic 0:c0ecb8bf28eb 18021 val_t ss;
Marko Mikulicic 0:c0ecb8bf28eb 18022 if (!v7_is_object(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 18023 return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18024 }
Marko Mikulicic 0:c0ecb8bf28eb 18025 if (len == (size_t) ~0) {
Marko Mikulicic 0:c0ecb8bf28eb 18026 len = strlen(name);
Marko Mikulicic 0:c0ecb8bf28eb 18027 }
Marko Mikulicic 0:c0ecb8bf28eb 18028
Marko Mikulicic 0:c0ecb8bf28eb 18029 o = get_object_struct(obj);
Marko Mikulicic 0:c0ecb8bf28eb 18030 /*
Marko Mikulicic 0:c0ecb8bf28eb 18031 * len check is needed to allow getting the mbuf from the hidden property.
Marko Mikulicic 0:c0ecb8bf28eb 18032 * TODO(mkm): however hidden properties cannot be safely represented with
Marko Mikulicic 0:c0ecb8bf28eb 18033 * a zero length string anyway, so this will change.
Marko Mikulicic 0:c0ecb8bf28eb 18034 */
Marko Mikulicic 0:c0ecb8bf28eb 18035 if (o->attributes & V7_OBJ_DENSE_ARRAY && len > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 18036 int ok, has;
Marko Mikulicic 0:c0ecb8bf28eb 18037 unsigned long i = cstr_to_ulong(name, len, &ok);
Marko Mikulicic 0:c0ecb8bf28eb 18038 if (ok) {
Marko Mikulicic 0:c0ecb8bf28eb 18039 v7->cur_dense_prop->value = v7_array_get2(v7, obj, i, &has);
Marko Mikulicic 0:c0ecb8bf28eb 18040 return has ? v7->cur_dense_prop : NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18041 }
Marko Mikulicic 0:c0ecb8bf28eb 18042 }
Marko Mikulicic 0:c0ecb8bf28eb 18043
Marko Mikulicic 0:c0ecb8bf28eb 18044 if (len <= 5) {
Marko Mikulicic 0:c0ecb8bf28eb 18045 ss = v7_mk_string(v7, name, len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 18046 for (p = o->properties; p != NULL; p = p->next) {
Marko Mikulicic 0:c0ecb8bf28eb 18047 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 18048 if (p->entity_id != V7_ENTITY_ID_PROP) {
Marko Mikulicic 0:c0ecb8bf28eb 18049 fprintf(stderr, "not a prop!=0x%x\n", p->entity_id);
Marko Mikulicic 0:c0ecb8bf28eb 18050 abort();
Marko Mikulicic 0:c0ecb8bf28eb 18051 }
Marko Mikulicic 0:c0ecb8bf28eb 18052 #endif
Marko Mikulicic 0:c0ecb8bf28eb 18053 if (p->name == ss && (attrs == 0 || (p->attributes & attrs))) {
Marko Mikulicic 0:c0ecb8bf28eb 18054 return p;
Marko Mikulicic 0:c0ecb8bf28eb 18055 }
Marko Mikulicic 0:c0ecb8bf28eb 18056 }
Marko Mikulicic 0:c0ecb8bf28eb 18057 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18058 for (p = o->properties; p != NULL; p = p->next) {
Marko Mikulicic 0:c0ecb8bf28eb 18059 size_t n;
Marko Mikulicic 0:c0ecb8bf28eb 18060 const char *s = v7_get_string(v7, &p->name, &n);
Marko Mikulicic 0:c0ecb8bf28eb 18061 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 18062 if (p->entity_id != V7_ENTITY_ID_PROP) {
Marko Mikulicic 0:c0ecb8bf28eb 18063 fprintf(stderr, "not a prop!=0x%x\n", p->entity_id);
Marko Mikulicic 0:c0ecb8bf28eb 18064 abort();
Marko Mikulicic 0:c0ecb8bf28eb 18065 }
Marko Mikulicic 0:c0ecb8bf28eb 18066 #endif
Marko Mikulicic 0:c0ecb8bf28eb 18067 if (n == len && strncmp(s, name, len) == 0 &&
Marko Mikulicic 0:c0ecb8bf28eb 18068 (attrs == 0 || (p->attributes & attrs))) {
Marko Mikulicic 0:c0ecb8bf28eb 18069 return p;
Marko Mikulicic 0:c0ecb8bf28eb 18070 }
Marko Mikulicic 0:c0ecb8bf28eb 18071 }
Marko Mikulicic 0:c0ecb8bf28eb 18072 }
Marko Mikulicic 0:c0ecb8bf28eb 18073 return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18074 }
Marko Mikulicic 0:c0ecb8bf28eb 18075
Marko Mikulicic 0:c0ecb8bf28eb 18076 V7_PRIVATE struct v7_property *v7_get_own_property(struct v7 *v7, val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 18077 const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 18078 size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 18079 return v7_get_own_property2(v7, obj, name, len, 0);
Marko Mikulicic 0:c0ecb8bf28eb 18080 }
Marko Mikulicic 0:c0ecb8bf28eb 18081
Marko Mikulicic 0:c0ecb8bf28eb 18082 V7_PRIVATE struct v7_property *v7_get_property(struct v7 *v7, val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 18083 const char *name, size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 18084 if (!v7_is_object(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 18085 return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18086 }
Marko Mikulicic 0:c0ecb8bf28eb 18087 for (; obj != V7_NULL; obj = v7_get_proto(v7, obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 18088 struct v7_property *prop;
Marko Mikulicic 0:c0ecb8bf28eb 18089 if ((prop = v7_get_own_property(v7, obj, name, len)) != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 18090 return prop;
Marko Mikulicic 0:c0ecb8bf28eb 18091 }
Marko Mikulicic 0:c0ecb8bf28eb 18092 }
Marko Mikulicic 0:c0ecb8bf28eb 18093 return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18094 }
Marko Mikulicic 0:c0ecb8bf28eb 18095
Marko Mikulicic 0:c0ecb8bf28eb 18096 V7_PRIVATE enum v7_err v7_get_property_v(struct v7 *v7, val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 18097 v7_val_t name,
Marko Mikulicic 0:c0ecb8bf28eb 18098 struct v7_property **res) {
Marko Mikulicic 0:c0ecb8bf28eb 18099 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18100 size_t name_len;
Marko Mikulicic 0:c0ecb8bf28eb 18101 STATIC char buf[8];
Marko Mikulicic 0:c0ecb8bf28eb 18102 const char *s = buf;
Marko Mikulicic 0:c0ecb8bf28eb 18103 uint8_t fr = 0;
Marko Mikulicic 0:c0ecb8bf28eb 18104
Marko Mikulicic 0:c0ecb8bf28eb 18105 if (v7_is_string(name)) {
Marko Mikulicic 0:c0ecb8bf28eb 18106 s = v7_get_string(v7, &name, &name_len);
Marko Mikulicic 0:c0ecb8bf28eb 18107 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18108 char *stmp;
Marko Mikulicic 0:c0ecb8bf28eb 18109 V7_TRY(v7_stringify_throwing(v7, name, buf, sizeof(buf),
Marko Mikulicic 0:c0ecb8bf28eb 18110 V7_STRINGIFY_DEFAULT, &stmp));
Marko Mikulicic 0:c0ecb8bf28eb 18111 s = stmp;
Marko Mikulicic 0:c0ecb8bf28eb 18112 if (s != buf) {
Marko Mikulicic 0:c0ecb8bf28eb 18113 fr = 1;
Marko Mikulicic 0:c0ecb8bf28eb 18114 }
Marko Mikulicic 0:c0ecb8bf28eb 18115 name_len = strlen(s);
Marko Mikulicic 0:c0ecb8bf28eb 18116 }
Marko Mikulicic 0:c0ecb8bf28eb 18117
Marko Mikulicic 0:c0ecb8bf28eb 18118 *res = v7_get_property(v7, obj, s, name_len);
Marko Mikulicic 0:c0ecb8bf28eb 18119
Marko Mikulicic 0:c0ecb8bf28eb 18120 clean:
Marko Mikulicic 0:c0ecb8bf28eb 18121 if (fr) {
Marko Mikulicic 0:c0ecb8bf28eb 18122 free((void *) s);
Marko Mikulicic 0:c0ecb8bf28eb 18123 }
Marko Mikulicic 0:c0ecb8bf28eb 18124 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 18125 }
Marko Mikulicic 0:c0ecb8bf28eb 18126
Marko Mikulicic 0:c0ecb8bf28eb 18127 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 18128 enum v7_err v7_get_throwing(struct v7 *v7, val_t obj, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 18129 size_t name_len, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 18130 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18131 val_t v = obj;
Marko Mikulicic 0:c0ecb8bf28eb 18132
Marko Mikulicic 0:c0ecb8bf28eb 18133 v7_own(v7, &v);
Marko Mikulicic 0:c0ecb8bf28eb 18134
Marko Mikulicic 0:c0ecb8bf28eb 18135 if (name_len == (size_t) ~0) {
Marko Mikulicic 0:c0ecb8bf28eb 18136 name_len = strlen(name);
Marko Mikulicic 0:c0ecb8bf28eb 18137 }
Marko Mikulicic 0:c0ecb8bf28eb 18138
Marko Mikulicic 0:c0ecb8bf28eb 18139 if (v7_is_string(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 18140 v = v7->vals.string_prototype;
Marko Mikulicic 0:c0ecb8bf28eb 18141 } else if (v7_is_number(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 18142 v = v7->vals.number_prototype;
Marko Mikulicic 0:c0ecb8bf28eb 18143 } else if (v7_is_boolean(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 18144 v = v7->vals.boolean_prototype;
Marko Mikulicic 0:c0ecb8bf28eb 18145 } else if (v7_is_undefined(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 18146 rcode =
Marko Mikulicic 0:c0ecb8bf28eb 18147 v7_throwf(v7, TYPE_ERROR, "cannot read property '%.*s' of undefined",
Marko Mikulicic 0:c0ecb8bf28eb 18148 (int) name_len, name);
Marko Mikulicic 0:c0ecb8bf28eb 18149 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18150 } else if (v7_is_null(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 18151 rcode = v7_throwf(v7, TYPE_ERROR, "cannot read property '%.*s' of null",
Marko Mikulicic 0:c0ecb8bf28eb 18152 (int) name_len, name);
Marko Mikulicic 0:c0ecb8bf28eb 18153 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18154 } else if (is_cfunction_lite(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 18155 v = v7->vals.function_prototype;
Marko Mikulicic 0:c0ecb8bf28eb 18156 }
Marko Mikulicic 0:c0ecb8bf28eb 18157
Marko Mikulicic 0:c0ecb8bf28eb 18158 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 18159 {
Marko Mikulicic 0:c0ecb8bf28eb 18160 struct v7_object *o = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18161 if (v7_is_object(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 18162 o = get_object_struct(obj);
Marko Mikulicic 0:c0ecb8bf28eb 18163 }
Marko Mikulicic 0:c0ecb8bf28eb 18164
Marko Mikulicic 0:c0ecb8bf28eb 18165 if (o != NULL && (o->attributes & V7_OBJ_PROXY) &&
Marko Mikulicic 0:c0ecb8bf28eb 18166 !is_special_proxy_name(name, name_len)) {
Marko Mikulicic 0:c0ecb8bf28eb 18167 /* we need to access the target object through a proxy */
Marko Mikulicic 0:c0ecb8bf28eb 18168
Marko Mikulicic 0:c0ecb8bf28eb 18169 val_t target_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18170 val_t handler_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18171 val_t name_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18172 val_t get_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18173 val_t get_args_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18174
Marko Mikulicic 0:c0ecb8bf28eb 18175 /*
Marko Mikulicic 0:c0ecb8bf28eb 18176 * we need to create a copy of the name, because the given `name` might
Marko Mikulicic 0:c0ecb8bf28eb 18177 * be returned by v7_get_string(), and any object creation might
Marko Mikulicic 0:c0ecb8bf28eb 18178 * invalidate this pointer. Below, we're going to create some objects.
Marko Mikulicic 0:c0ecb8bf28eb 18179 *
Marko Mikulicic 0:c0ecb8bf28eb 18180 * It would probably be cleaner to always create a copy before calling
Marko Mikulicic 0:c0ecb8bf28eb 18181 * v7_get_throwing if the name was returned by v7_get_string(), but that
Marko Mikulicic 0:c0ecb8bf28eb 18182 * would cause additional pressure on the heap, so let's not do that
Marko Mikulicic 0:c0ecb8bf28eb 18183 */
Marko Mikulicic 0:c0ecb8bf28eb 18184 char *name_copy = (char *) calloc(1, name_len + 1 /* null-term */);
Marko Mikulicic 0:c0ecb8bf28eb 18185 memcpy(name_copy, name, name_len);
Marko Mikulicic 0:c0ecb8bf28eb 18186
Marko Mikulicic 0:c0ecb8bf28eb 18187 v7_own(v7, &target_v);
Marko Mikulicic 0:c0ecb8bf28eb 18188 v7_own(v7, &handler_v);
Marko Mikulicic 0:c0ecb8bf28eb 18189 v7_own(v7, &name_v);
Marko Mikulicic 0:c0ecb8bf28eb 18190 v7_own(v7, &get_v);
Marko Mikulicic 0:c0ecb8bf28eb 18191 v7_own(v7, &get_args_v);
Marko Mikulicic 0:c0ecb8bf28eb 18192
Marko Mikulicic 0:c0ecb8bf28eb 18193 V7_TRY2(v7_get_throwing(v7, obj, _V7_PROXY_TARGET_NAME, ~0, &target_v),
Marko Mikulicic 0:c0ecb8bf28eb 18194 clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18195 V7_TRY2(v7_get_throwing(v7, obj, _V7_PROXY_HANDLER_NAME, ~0, &handler_v),
Marko Mikulicic 0:c0ecb8bf28eb 18196 clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18197 V7_TRY2(v7_get_throwing(v7, handler_v, "get", ~0, &get_v), clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18198
Marko Mikulicic 0:c0ecb8bf28eb 18199 if (v7_is_callable(v7, get_v)) {
Marko Mikulicic 0:c0ecb8bf28eb 18200 /* The `get` callback is actually callable, so, use it */
Marko Mikulicic 0:c0ecb8bf28eb 18201
Marko Mikulicic 0:c0ecb8bf28eb 18202 /* prepare arguments for the callback */
Marko Mikulicic 0:c0ecb8bf28eb 18203 get_args_v = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 18204 /*
Marko Mikulicic 0:c0ecb8bf28eb 18205 * TODO(dfrank): don't copy string in case we already have val_t (we
Marko Mikulicic 0:c0ecb8bf28eb 18206 * need some generic function which will take both `const char *` and
Marko Mikulicic 0:c0ecb8bf28eb 18207 * val_t)
Marko Mikulicic 0:c0ecb8bf28eb 18208 */
Marko Mikulicic 0:c0ecb8bf28eb 18209 v7_array_set(v7, get_args_v, 0, target_v);
Marko Mikulicic 0:c0ecb8bf28eb 18210 v7_array_set(v7, get_args_v, 1,
Marko Mikulicic 0:c0ecb8bf28eb 18211 v7_mk_string(v7, name_copy, name_len, 1));
Marko Mikulicic 0:c0ecb8bf28eb 18212
Marko Mikulicic 0:c0ecb8bf28eb 18213 /* call `get` callback */
Marko Mikulicic 0:c0ecb8bf28eb 18214 V7_TRY2(b_apply(v7, get_v, V7_UNDEFINED, get_args_v, 0, res),
Marko Mikulicic 0:c0ecb8bf28eb 18215 clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18216 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18217 /*
Marko Mikulicic 0:c0ecb8bf28eb 18218 * there's no `get` callback: then, get property from the target object
Marko Mikulicic 0:c0ecb8bf28eb 18219 * (not from the proxy object)
Marko Mikulicic 0:c0ecb8bf28eb 18220 */
Marko Mikulicic 0:c0ecb8bf28eb 18221 V7_TRY2(v7_get_throwing(v7, target_v, name_copy, name_len, res),
Marko Mikulicic 0:c0ecb8bf28eb 18222 clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18223 }
Marko Mikulicic 0:c0ecb8bf28eb 18224
Marko Mikulicic 0:c0ecb8bf28eb 18225 clean_proxy:
Marko Mikulicic 0:c0ecb8bf28eb 18226
Marko Mikulicic 0:c0ecb8bf28eb 18227 free(name_copy);
Marko Mikulicic 0:c0ecb8bf28eb 18228
Marko Mikulicic 0:c0ecb8bf28eb 18229 v7_disown(v7, &get_args_v);
Marko Mikulicic 0:c0ecb8bf28eb 18230 v7_disown(v7, &get_v);
Marko Mikulicic 0:c0ecb8bf28eb 18231 v7_disown(v7, &name_v);
Marko Mikulicic 0:c0ecb8bf28eb 18232 v7_disown(v7, &handler_v);
Marko Mikulicic 0:c0ecb8bf28eb 18233 v7_disown(v7, &target_v);
Marko Mikulicic 0:c0ecb8bf28eb 18234 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18235 }
Marko Mikulicic 0:c0ecb8bf28eb 18236 }
Marko Mikulicic 0:c0ecb8bf28eb 18237 #endif
Marko Mikulicic 0:c0ecb8bf28eb 18238
Marko Mikulicic 0:c0ecb8bf28eb 18239 /* regular (non-proxy) property access */
Marko Mikulicic 0:c0ecb8bf28eb 18240 V7_TRY(
Marko Mikulicic 0:c0ecb8bf28eb 18241 v7_property_value(v7, obj, v7_get_property(v7, v, name, name_len), res));
Marko Mikulicic 0:c0ecb8bf28eb 18242
Marko Mikulicic 0:c0ecb8bf28eb 18243 clean:
Marko Mikulicic 0:c0ecb8bf28eb 18244 v7_disown(v7, &v);
Marko Mikulicic 0:c0ecb8bf28eb 18245 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 18246 }
Marko Mikulicic 0:c0ecb8bf28eb 18247
Marko Mikulicic 0:c0ecb8bf28eb 18248 v7_val_t v7_get(struct v7 *v7, val_t obj, const char *name, size_t name_len) {
Marko Mikulicic 0:c0ecb8bf28eb 18249 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18250 uint8_t saved_is_thrown = 0;
Marko Mikulicic 0:c0ecb8bf28eb 18251 val_t saved_thrown = v7_get_thrown_value(v7, &saved_is_thrown);
Marko Mikulicic 0:c0ecb8bf28eb 18252 v7_val_t ret = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18253
Marko Mikulicic 0:c0ecb8bf28eb 18254 rcode = v7_get_throwing(v7, obj, name, name_len, &ret);
Marko Mikulicic 0:c0ecb8bf28eb 18255 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 18256 rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18257 if (saved_is_thrown) {
Marko Mikulicic 0:c0ecb8bf28eb 18258 rcode = v7_throw(v7, saved_thrown);
Marko Mikulicic 0:c0ecb8bf28eb 18259 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18260 v7_clear_thrown_value(v7);
Marko Mikulicic 0:c0ecb8bf28eb 18261 }
Marko Mikulicic 0:c0ecb8bf28eb 18262 ret = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18263 }
Marko Mikulicic 0:c0ecb8bf28eb 18264
Marko Mikulicic 0:c0ecb8bf28eb 18265 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 18266 }
Marko Mikulicic 0:c0ecb8bf28eb 18267
Marko Mikulicic 0:c0ecb8bf28eb 18268 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 18269 V7_PRIVATE enum v7_err v7_get_throwing_v(struct v7 *v7, v7_val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 18270 v7_val_t name, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 18271 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18272 size_t name_len;
Marko Mikulicic 0:c0ecb8bf28eb 18273 STATIC char buf[8];
Marko Mikulicic 0:c0ecb8bf28eb 18274 const char *s = buf;
Marko Mikulicic 0:c0ecb8bf28eb 18275 uint8_t fr = 0;
Marko Mikulicic 0:c0ecb8bf28eb 18276
Marko Mikulicic 0:c0ecb8bf28eb 18277 /* subscripting strings */
Marko Mikulicic 0:c0ecb8bf28eb 18278 if (v7_is_string(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 18279 char ch;
Marko Mikulicic 0:c0ecb8bf28eb 18280 double dch = 0;
Marko Mikulicic 0:c0ecb8bf28eb 18281
Marko Mikulicic 0:c0ecb8bf28eb 18282 rcode = v7_char_code_at(v7, obj, name, &dch);
Marko Mikulicic 0:c0ecb8bf28eb 18283 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 18284 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18285 }
Marko Mikulicic 0:c0ecb8bf28eb 18286
Marko Mikulicic 0:c0ecb8bf28eb 18287 if (!isnan(dch)) {
Marko Mikulicic 0:c0ecb8bf28eb 18288 ch = dch;
Marko Mikulicic 0:c0ecb8bf28eb 18289 *res = v7_mk_string(v7, &ch, 1, 1);
Marko Mikulicic 0:c0ecb8bf28eb 18290 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18291 }
Marko Mikulicic 0:c0ecb8bf28eb 18292 }
Marko Mikulicic 0:c0ecb8bf28eb 18293
Marko Mikulicic 0:c0ecb8bf28eb 18294 if (v7_is_string(name)) {
Marko Mikulicic 0:c0ecb8bf28eb 18295 s = v7_get_string(v7, &name, &name_len);
Marko Mikulicic 0:c0ecb8bf28eb 18296 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18297 char *stmp;
Marko Mikulicic 0:c0ecb8bf28eb 18298 V7_TRY(v7_stringify_throwing(v7, name, buf, sizeof(buf),
Marko Mikulicic 0:c0ecb8bf28eb 18299 V7_STRINGIFY_DEFAULT, &stmp));
Marko Mikulicic 0:c0ecb8bf28eb 18300 s = stmp;
Marko Mikulicic 0:c0ecb8bf28eb 18301 if (s != buf) {
Marko Mikulicic 0:c0ecb8bf28eb 18302 fr = 1;
Marko Mikulicic 0:c0ecb8bf28eb 18303 }
Marko Mikulicic 0:c0ecb8bf28eb 18304 name_len = strlen(s);
Marko Mikulicic 0:c0ecb8bf28eb 18305 }
Marko Mikulicic 0:c0ecb8bf28eb 18306 V7_TRY(v7_get_throwing(v7, obj, s, name_len, res));
Marko Mikulicic 0:c0ecb8bf28eb 18307
Marko Mikulicic 0:c0ecb8bf28eb 18308 clean:
Marko Mikulicic 0:c0ecb8bf28eb 18309 if (fr) {
Marko Mikulicic 0:c0ecb8bf28eb 18310 free((void *) s);
Marko Mikulicic 0:c0ecb8bf28eb 18311 }
Marko Mikulicic 0:c0ecb8bf28eb 18312 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 18313 }
Marko Mikulicic 0:c0ecb8bf28eb 18314
Marko Mikulicic 0:c0ecb8bf28eb 18315 V7_PRIVATE void v7_destroy_property(struct v7_property **p) {
Marko Mikulicic 0:c0ecb8bf28eb 18316 *p = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18317 }
Marko Mikulicic 0:c0ecb8bf28eb 18318
Marko Mikulicic 0:c0ecb8bf28eb 18319 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 18320 V7_PRIVATE enum v7_err v7_invoke_setter(struct v7 *v7, struct v7_property *prop,
Marko Mikulicic 0:c0ecb8bf28eb 18321 val_t obj, val_t val) {
Marko Mikulicic 0:c0ecb8bf28eb 18322 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18323 val_t setter = prop->value, args;
Marko Mikulicic 0:c0ecb8bf28eb 18324 v7_own(v7, &val);
Marko Mikulicic 0:c0ecb8bf28eb 18325 args = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 18326 v7_own(v7, &args);
Marko Mikulicic 0:c0ecb8bf28eb 18327 if (prop->attributes & V7_PROPERTY_GETTER) {
Marko Mikulicic 0:c0ecb8bf28eb 18328 setter = v7_array_get(v7, prop->value, 1);
Marko Mikulicic 0:c0ecb8bf28eb 18329 }
Marko Mikulicic 0:c0ecb8bf28eb 18330 v7_array_set(v7, args, 0, val);
Marko Mikulicic 0:c0ecb8bf28eb 18331 v7_disown(v7, &args);
Marko Mikulicic 0:c0ecb8bf28eb 18332 v7_disown(v7, &val);
Marko Mikulicic 0:c0ecb8bf28eb 18333 {
Marko Mikulicic 0:c0ecb8bf28eb 18334 val_t val = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18335 V7_TRY(b_apply(v7, setter, obj, args, 0, &val));
Marko Mikulicic 0:c0ecb8bf28eb 18336 }
Marko Mikulicic 0:c0ecb8bf28eb 18337
Marko Mikulicic 0:c0ecb8bf28eb 18338 clean:
Marko Mikulicic 0:c0ecb8bf28eb 18339 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 18340 }
Marko Mikulicic 0:c0ecb8bf28eb 18341
Marko Mikulicic 0:c0ecb8bf28eb 18342 static v7_prop_attr_t apply_attrs_desc(v7_prop_attr_desc_t attrs_desc,
Marko Mikulicic 0:c0ecb8bf28eb 18343 v7_prop_attr_t old_attrs) {
Marko Mikulicic 0:c0ecb8bf28eb 18344 v7_prop_attr_t ret = old_attrs;
Marko Mikulicic 0:c0ecb8bf28eb 18345 if (old_attrs & V7_PROPERTY_NON_CONFIGURABLE) {
Marko Mikulicic 0:c0ecb8bf28eb 18346 /*
Marko Mikulicic 0:c0ecb8bf28eb 18347 * The property is non-configurable: we can only change it from being
Marko Mikulicic 0:c0ecb8bf28eb 18348 * writable to non-writable
Marko Mikulicic 0:c0ecb8bf28eb 18349 */
Marko Mikulicic 0:c0ecb8bf28eb 18350
Marko Mikulicic 0:c0ecb8bf28eb 18351 if ((attrs_desc >> _V7_DESC_SHIFT) & V7_PROPERTY_NON_WRITABLE &&
Marko Mikulicic 0:c0ecb8bf28eb 18352 (attrs_desc & V7_PROPERTY_NON_WRITABLE)) {
Marko Mikulicic 0:c0ecb8bf28eb 18353 ret |= V7_PROPERTY_NON_WRITABLE;
Marko Mikulicic 0:c0ecb8bf28eb 18354 }
Marko Mikulicic 0:c0ecb8bf28eb 18355
Marko Mikulicic 0:c0ecb8bf28eb 18356 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18357 /* The property is configurable: we can change any attributes */
Marko Mikulicic 0:c0ecb8bf28eb 18358 ret = (old_attrs & ~(attrs_desc >> _V7_DESC_SHIFT)) |
Marko Mikulicic 0:c0ecb8bf28eb 18359 (attrs_desc & _V7_DESC_MASK);
Marko Mikulicic 0:c0ecb8bf28eb 18360 }
Marko Mikulicic 0:c0ecb8bf28eb 18361
Marko Mikulicic 0:c0ecb8bf28eb 18362 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 18363 }
Marko Mikulicic 0:c0ecb8bf28eb 18364
Marko Mikulicic 0:c0ecb8bf28eb 18365 int v7_def(struct v7 *v7, val_t obj, const char *name, size_t len,
Marko Mikulicic 0:c0ecb8bf28eb 18366 v7_prop_attr_desc_t attrs_desc, v7_val_t val) {
Marko Mikulicic 0:c0ecb8bf28eb 18367 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18368 uint8_t saved_is_thrown = 0;
Marko Mikulicic 0:c0ecb8bf28eb 18369 val_t saved_thrown = v7_get_thrown_value(v7, &saved_is_thrown);
Marko Mikulicic 0:c0ecb8bf28eb 18370 int ret = -1;
Marko Mikulicic 0:c0ecb8bf28eb 18371
Marko Mikulicic 0:c0ecb8bf28eb 18372 {
Marko Mikulicic 0:c0ecb8bf28eb 18373 struct v7_property *tmp = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18374 rcode = def_property(v7, obj, name, len, attrs_desc, val, 0 /*not assign*/,
Marko Mikulicic 0:c0ecb8bf28eb 18375 &tmp);
Marko Mikulicic 0:c0ecb8bf28eb 18376 ret = (tmp == NULL) ? -1 : 0;
Marko Mikulicic 0:c0ecb8bf28eb 18377 }
Marko Mikulicic 0:c0ecb8bf28eb 18378
Marko Mikulicic 0:c0ecb8bf28eb 18379 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 18380 rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18381 if (saved_is_thrown) {
Marko Mikulicic 0:c0ecb8bf28eb 18382 rcode = v7_throw(v7, saved_thrown);
Marko Mikulicic 0:c0ecb8bf28eb 18383 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18384 v7_clear_thrown_value(v7);
Marko Mikulicic 0:c0ecb8bf28eb 18385 }
Marko Mikulicic 0:c0ecb8bf28eb 18386 ret = -1;
Marko Mikulicic 0:c0ecb8bf28eb 18387 }
Marko Mikulicic 0:c0ecb8bf28eb 18388
Marko Mikulicic 0:c0ecb8bf28eb 18389 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 18390 }
Marko Mikulicic 0:c0ecb8bf28eb 18391
Marko Mikulicic 0:c0ecb8bf28eb 18392 int v7_set(struct v7 *v7, val_t obj, const char *name, size_t len,
Marko Mikulicic 0:c0ecb8bf28eb 18393 v7_val_t val) {
Marko Mikulicic 0:c0ecb8bf28eb 18394 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18395 uint8_t saved_is_thrown = 0;
Marko Mikulicic 0:c0ecb8bf28eb 18396 val_t saved_thrown = v7_get_thrown_value(v7, &saved_is_thrown);
Marko Mikulicic 0:c0ecb8bf28eb 18397 int ret = -1;
Marko Mikulicic 0:c0ecb8bf28eb 18398
Marko Mikulicic 0:c0ecb8bf28eb 18399 {
Marko Mikulicic 0:c0ecb8bf28eb 18400 struct v7_property *tmp = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18401 rcode = set_property(v7, obj, name, len, val, &tmp);
Marko Mikulicic 0:c0ecb8bf28eb 18402 ret = (tmp == NULL) ? -1 : 0;
Marko Mikulicic 0:c0ecb8bf28eb 18403 }
Marko Mikulicic 0:c0ecb8bf28eb 18404
Marko Mikulicic 0:c0ecb8bf28eb 18405 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 18406 rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18407 if (saved_is_thrown) {
Marko Mikulicic 0:c0ecb8bf28eb 18408 rcode = v7_throw(v7, saved_thrown);
Marko Mikulicic 0:c0ecb8bf28eb 18409 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18410 v7_clear_thrown_value(v7);
Marko Mikulicic 0:c0ecb8bf28eb 18411 }
Marko Mikulicic 0:c0ecb8bf28eb 18412 ret = -1;
Marko Mikulicic 0:c0ecb8bf28eb 18413 }
Marko Mikulicic 0:c0ecb8bf28eb 18414
Marko Mikulicic 0:c0ecb8bf28eb 18415 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 18416 }
Marko Mikulicic 0:c0ecb8bf28eb 18417
Marko Mikulicic 0:c0ecb8bf28eb 18418 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 18419 V7_PRIVATE enum v7_err set_property_v(struct v7 *v7, val_t obj, val_t name,
Marko Mikulicic 0:c0ecb8bf28eb 18420 val_t val, struct v7_property **res) {
Marko Mikulicic 0:c0ecb8bf28eb 18421 return def_property_v(v7, obj, name, 0, val, 1 /*as_assign*/, res);
Marko Mikulicic 0:c0ecb8bf28eb 18422 }
Marko Mikulicic 0:c0ecb8bf28eb 18423
Marko Mikulicic 0:c0ecb8bf28eb 18424 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 18425 V7_PRIVATE enum v7_err set_property(struct v7 *v7, val_t obj, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 18426 size_t len, v7_val_t val,
Marko Mikulicic 0:c0ecb8bf28eb 18427 struct v7_property **res) {
Marko Mikulicic 0:c0ecb8bf28eb 18428 return def_property(v7, obj, name, len, 0, val, 1 /*as_assign*/, res);
Marko Mikulicic 0:c0ecb8bf28eb 18429 }
Marko Mikulicic 0:c0ecb8bf28eb 18430
Marko Mikulicic 0:c0ecb8bf28eb 18431 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 18432 V7_PRIVATE enum v7_err def_property_v(struct v7 *v7, val_t obj, val_t name,
Marko Mikulicic 0:c0ecb8bf28eb 18433 v7_prop_attr_desc_t attrs_desc, val_t val,
Marko Mikulicic 0:c0ecb8bf28eb 18434 uint8_t as_assign,
Marko Mikulicic 0:c0ecb8bf28eb 18435 struct v7_property **res) {
Marko Mikulicic 0:c0ecb8bf28eb 18436 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18437 struct v7_property *prop = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18438 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 18439 const char *n = v7_get_string(v7, &name, &len);
Marko Mikulicic 0:c0ecb8bf28eb 18440
Marko Mikulicic 0:c0ecb8bf28eb 18441 v7_own(v7, &name);
Marko Mikulicic 0:c0ecb8bf28eb 18442 v7_own(v7, &val);
Marko Mikulicic 0:c0ecb8bf28eb 18443
Marko Mikulicic 0:c0ecb8bf28eb 18444 if (!v7_is_object(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 18445 prop = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18446 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18447 }
Marko Mikulicic 0:c0ecb8bf28eb 18448
Marko Mikulicic 0:c0ecb8bf28eb 18449 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 18450 if ((get_object_struct(obj)->attributes & V7_OBJ_PROXY) &&
Marko Mikulicic 0:c0ecb8bf28eb 18451 !is_special_proxy_name(n, len)) {
Marko Mikulicic 0:c0ecb8bf28eb 18452 /* we need to access the target object through a proxy */
Marko Mikulicic 0:c0ecb8bf28eb 18453
Marko Mikulicic 0:c0ecb8bf28eb 18454 val_t target_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18455 val_t handler_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18456 val_t set_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18457 val_t set_args_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18458
Marko Mikulicic 0:c0ecb8bf28eb 18459 v7_own(v7, &target_v);
Marko Mikulicic 0:c0ecb8bf28eb 18460 v7_own(v7, &handler_v);
Marko Mikulicic 0:c0ecb8bf28eb 18461 v7_own(v7, &set_v);
Marko Mikulicic 0:c0ecb8bf28eb 18462 v7_own(v7, &set_args_v);
Marko Mikulicic 0:c0ecb8bf28eb 18463
Marko Mikulicic 0:c0ecb8bf28eb 18464 V7_TRY2(v7_get_throwing(v7, obj, _V7_PROXY_TARGET_NAME, ~0, &target_v),
Marko Mikulicic 0:c0ecb8bf28eb 18465 clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18466 V7_TRY2(v7_get_throwing(v7, obj, _V7_PROXY_HANDLER_NAME, ~0, &handler_v),
Marko Mikulicic 0:c0ecb8bf28eb 18467 clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18468 /*
Marko Mikulicic 0:c0ecb8bf28eb 18469 * We'll consult "set" property in case of the plain assignment only;
Marko Mikulicic 0:c0ecb8bf28eb 18470 * Object.defineProperty() has its own trap `defineProperty` which is not
Marko Mikulicic 0:c0ecb8bf28eb 18471 * yet implemented in v7
Marko Mikulicic 0:c0ecb8bf28eb 18472 */
Marko Mikulicic 0:c0ecb8bf28eb 18473 if (as_assign) {
Marko Mikulicic 0:c0ecb8bf28eb 18474 V7_TRY2(v7_get_throwing(v7, handler_v, "set", ~0, &set_v), clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18475 }
Marko Mikulicic 0:c0ecb8bf28eb 18476
Marko Mikulicic 0:c0ecb8bf28eb 18477 if (v7_is_callable(v7, set_v)) {
Marko Mikulicic 0:c0ecb8bf28eb 18478 /* The `set` callback is actually callable, so, use it */
Marko Mikulicic 0:c0ecb8bf28eb 18479
Marko Mikulicic 0:c0ecb8bf28eb 18480 /* prepare arguments for the callback */
Marko Mikulicic 0:c0ecb8bf28eb 18481 set_args_v = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 18482 /*
Marko Mikulicic 0:c0ecb8bf28eb 18483 * TODO(dfrank): don't copy string in case we already have val_t
Marko Mikulicic 0:c0ecb8bf28eb 18484 * (we need some generic function which will take both const char * and
Marko Mikulicic 0:c0ecb8bf28eb 18485 * val_t for that)
Marko Mikulicic 0:c0ecb8bf28eb 18486 */
Marko Mikulicic 0:c0ecb8bf28eb 18487 v7_array_set(v7, set_args_v, 0, target_v);
Marko Mikulicic 0:c0ecb8bf28eb 18488 v7_array_set(v7, set_args_v, 1, name);
Marko Mikulicic 0:c0ecb8bf28eb 18489 v7_array_set(v7, set_args_v, 2, val);
Marko Mikulicic 0:c0ecb8bf28eb 18490
Marko Mikulicic 0:c0ecb8bf28eb 18491 /* call `set` callback */
Marko Mikulicic 0:c0ecb8bf28eb 18492 V7_TRY2(b_apply(v7, set_v, V7_UNDEFINED, set_args_v, 0, &val),
Marko Mikulicic 0:c0ecb8bf28eb 18493 clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18494
Marko Mikulicic 0:c0ecb8bf28eb 18495 /* in strict mode, we should throw if trap returned falsy value */
Marko Mikulicic 0:c0ecb8bf28eb 18496 if (is_strict_mode(v7) && !v7_is_truthy(v7, val)) {
Marko Mikulicic 0:c0ecb8bf28eb 18497 V7_THROW2(
Marko Mikulicic 0:c0ecb8bf28eb 18498 v7_throwf(v7, TYPE_ERROR, "Trap returned falsy for property '%s'",
Marko Mikulicic 0:c0ecb8bf28eb 18499 v7_get_string(v7, &name, NULL)),
Marko Mikulicic 0:c0ecb8bf28eb 18500 clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18501 }
Marko Mikulicic 0:c0ecb8bf28eb 18502
Marko Mikulicic 0:c0ecb8bf28eb 18503 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18504 /*
Marko Mikulicic 0:c0ecb8bf28eb 18505 * there's no `set` callback: then, set property on the target object
Marko Mikulicic 0:c0ecb8bf28eb 18506 * (not on the proxy object)
Marko Mikulicic 0:c0ecb8bf28eb 18507 */
Marko Mikulicic 0:c0ecb8bf28eb 18508 V7_TRY2(
Marko Mikulicic 0:c0ecb8bf28eb 18509 def_property_v(v7, target_v, name, attrs_desc, val, as_assign, res),
Marko Mikulicic 0:c0ecb8bf28eb 18510 clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18511 }
Marko Mikulicic 0:c0ecb8bf28eb 18512
Marko Mikulicic 0:c0ecb8bf28eb 18513 clean_proxy:
Marko Mikulicic 0:c0ecb8bf28eb 18514 v7_disown(v7, &set_args_v);
Marko Mikulicic 0:c0ecb8bf28eb 18515 v7_disown(v7, &set_v);
Marko Mikulicic 0:c0ecb8bf28eb 18516 v7_disown(v7, &handler_v);
Marko Mikulicic 0:c0ecb8bf28eb 18517 v7_disown(v7, &target_v);
Marko Mikulicic 0:c0ecb8bf28eb 18518 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18519 }
Marko Mikulicic 0:c0ecb8bf28eb 18520 #endif
Marko Mikulicic 0:c0ecb8bf28eb 18521
Marko Mikulicic 0:c0ecb8bf28eb 18522 /* regular (non-proxy) property access */
Marko Mikulicic 0:c0ecb8bf28eb 18523 prop = v7_get_own_property(v7, obj, n, len);
Marko Mikulicic 0:c0ecb8bf28eb 18524 if (prop == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 18525 /*
Marko Mikulicic 0:c0ecb8bf28eb 18526 * The own property with given `name` doesn't exist yet: try to create it,
Marko Mikulicic 0:c0ecb8bf28eb 18527 * set requested `name` and `attributes`, and append to the object's
Marko Mikulicic 0:c0ecb8bf28eb 18528 * properties
Marko Mikulicic 0:c0ecb8bf28eb 18529 */
Marko Mikulicic 0:c0ecb8bf28eb 18530
Marko Mikulicic 0:c0ecb8bf28eb 18531 /* make sure the object is extensible */
Marko Mikulicic 0:c0ecb8bf28eb 18532 if (get_object_struct(obj)->attributes & V7_OBJ_NOT_EXTENSIBLE) {
Marko Mikulicic 0:c0ecb8bf28eb 18533 /*
Marko Mikulicic 0:c0ecb8bf28eb 18534 * We should throw if we use `Object.defineProperty`, or if we're in
Marko Mikulicic 0:c0ecb8bf28eb 18535 * strict mode.
Marko Mikulicic 0:c0ecb8bf28eb 18536 */
Marko Mikulicic 0:c0ecb8bf28eb 18537 if (is_strict_mode(v7) || !as_assign) {
Marko Mikulicic 0:c0ecb8bf28eb 18538 V7_THROW(v7_throwf(v7, TYPE_ERROR, "Object is not extensible"));
Marko Mikulicic 0:c0ecb8bf28eb 18539 }
Marko Mikulicic 0:c0ecb8bf28eb 18540 prop = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18541 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18542 }
Marko Mikulicic 0:c0ecb8bf28eb 18543
Marko Mikulicic 0:c0ecb8bf28eb 18544 if ((prop = v7_mk_property(v7)) == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 18545 prop = NULL; /* LCOV_EXCL_LINE */
Marko Mikulicic 0:c0ecb8bf28eb 18546 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18547 }
Marko Mikulicic 0:c0ecb8bf28eb 18548 prop->name = name;
Marko Mikulicic 0:c0ecb8bf28eb 18549 prop->value = val;
Marko Mikulicic 0:c0ecb8bf28eb 18550 prop->attributes = apply_attrs_desc(attrs_desc, V7_DEFAULT_PROPERTY_ATTRS);
Marko Mikulicic 0:c0ecb8bf28eb 18551
Marko Mikulicic 0:c0ecb8bf28eb 18552 prop->next = get_object_struct(obj)->properties;
Marko Mikulicic 0:c0ecb8bf28eb 18553 get_object_struct(obj)->properties = prop;
Marko Mikulicic 0:c0ecb8bf28eb 18554 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18555 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18556 /* Property already exists */
Marko Mikulicic 0:c0ecb8bf28eb 18557
Marko Mikulicic 0:c0ecb8bf28eb 18558 if (prop->attributes & V7_PROPERTY_NON_WRITABLE) {
Marko Mikulicic 0:c0ecb8bf28eb 18559 /* The property is read-only */
Marko Mikulicic 0:c0ecb8bf28eb 18560
Marko Mikulicic 0:c0ecb8bf28eb 18561 if (as_assign) {
Marko Mikulicic 0:c0ecb8bf28eb 18562 /* Plain assignment: in strict mode throw, otherwise ignore */
Marko Mikulicic 0:c0ecb8bf28eb 18563 if (is_strict_mode(v7)) {
Marko Mikulicic 0:c0ecb8bf28eb 18564 V7_THROW(
Marko Mikulicic 0:c0ecb8bf28eb 18565 v7_throwf(v7, TYPE_ERROR, "Cannot assign to read-only property"));
Marko Mikulicic 0:c0ecb8bf28eb 18566 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18567 prop = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18568 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18569 }
Marko Mikulicic 0:c0ecb8bf28eb 18570 } else if (prop->attributes & V7_PROPERTY_NON_CONFIGURABLE) {
Marko Mikulicic 0:c0ecb8bf28eb 18571 /*
Marko Mikulicic 0:c0ecb8bf28eb 18572 * Use `Object.defineProperty` semantic, and the property is
Marko Mikulicic 0:c0ecb8bf28eb 18573 * non-configurable: if no value is provided, or if new value is equal
Marko Mikulicic 0:c0ecb8bf28eb 18574 * to the existing one, then just fall through to change attributes;
Marko Mikulicic 0:c0ecb8bf28eb 18575 * otherwise, throw.
Marko Mikulicic 0:c0ecb8bf28eb 18576 */
Marko Mikulicic 0:c0ecb8bf28eb 18577
Marko Mikulicic 0:c0ecb8bf28eb 18578 if (!(attrs_desc & V7_DESC_PRESERVE_VALUE)) {
Marko Mikulicic 0:c0ecb8bf28eb 18579 uint8_t equal = 0;
Marko Mikulicic 0:c0ecb8bf28eb 18580 if (v7_is_string(val) && v7_is_string(prop->value)) {
Marko Mikulicic 0:c0ecb8bf28eb 18581 equal = (s_cmp(v7, val, prop->value) == 0);
Marko Mikulicic 0:c0ecb8bf28eb 18582 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18583 equal = (val == prop->value);
Marko Mikulicic 0:c0ecb8bf28eb 18584 }
Marko Mikulicic 0:c0ecb8bf28eb 18585
Marko Mikulicic 0:c0ecb8bf28eb 18586 if (!equal) {
Marko Mikulicic 0:c0ecb8bf28eb 18587 /* Values are not equal: should throw */
Marko Mikulicic 0:c0ecb8bf28eb 18588 V7_THROW(v7_throwf(v7, TYPE_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 18589 "Cannot redefine read-only property"));
Marko Mikulicic 0:c0ecb8bf28eb 18590 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18591 /*
Marko Mikulicic 0:c0ecb8bf28eb 18592 * Values are equal. Will fall through so that attributes might
Marko Mikulicic 0:c0ecb8bf28eb 18593 * change.
Marko Mikulicic 0:c0ecb8bf28eb 18594 */
Marko Mikulicic 0:c0ecb8bf28eb 18595 }
Marko Mikulicic 0:c0ecb8bf28eb 18596 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18597 /*
Marko Mikulicic 0:c0ecb8bf28eb 18598 * No value is provided. Will fall through so that attributes might
Marko Mikulicic 0:c0ecb8bf28eb 18599 * change.
Marko Mikulicic 0:c0ecb8bf28eb 18600 */
Marko Mikulicic 0:c0ecb8bf28eb 18601 }
Marko Mikulicic 0:c0ecb8bf28eb 18602 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18603 /*
Marko Mikulicic 0:c0ecb8bf28eb 18604 * Use `Object.defineProperty` semantic, and the property is
Marko Mikulicic 0:c0ecb8bf28eb 18605 * configurable: will fall through and assign new value, effectively
Marko Mikulicic 0:c0ecb8bf28eb 18606 * ignoring non-writable flag. This is the same as making a property
Marko Mikulicic 0:c0ecb8bf28eb 18607 * writable, then assigning a new value, and making a property
Marko Mikulicic 0:c0ecb8bf28eb 18608 * non-writable again.
Marko Mikulicic 0:c0ecb8bf28eb 18609 */
Marko Mikulicic 0:c0ecb8bf28eb 18610 }
Marko Mikulicic 0:c0ecb8bf28eb 18611 } else if (prop->attributes & V7_PROPERTY_SETTER) {
Marko Mikulicic 0:c0ecb8bf28eb 18612 /* Invoke setter */
Marko Mikulicic 0:c0ecb8bf28eb 18613 V7_TRY(v7_invoke_setter(v7, prop, obj, val));
Marko Mikulicic 0:c0ecb8bf28eb 18614 prop = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18615 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18616 }
Marko Mikulicic 0:c0ecb8bf28eb 18617
Marko Mikulicic 0:c0ecb8bf28eb 18618 /* Set value and apply attrs delta */
Marko Mikulicic 0:c0ecb8bf28eb 18619 if (!(attrs_desc & V7_DESC_PRESERVE_VALUE)) {
Marko Mikulicic 0:c0ecb8bf28eb 18620 prop->value = val;
Marko Mikulicic 0:c0ecb8bf28eb 18621 }
Marko Mikulicic 0:c0ecb8bf28eb 18622 prop->attributes = apply_attrs_desc(attrs_desc, prop->attributes);
Marko Mikulicic 0:c0ecb8bf28eb 18623 }
Marko Mikulicic 0:c0ecb8bf28eb 18624
Marko Mikulicic 0:c0ecb8bf28eb 18625 clean:
Marko Mikulicic 0:c0ecb8bf28eb 18626
Marko Mikulicic 0:c0ecb8bf28eb 18627 if (res != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 18628 *res = prop;
Marko Mikulicic 0:c0ecb8bf28eb 18629 }
Marko Mikulicic 0:c0ecb8bf28eb 18630
Marko Mikulicic 0:c0ecb8bf28eb 18631 v7_disown(v7, &val);
Marko Mikulicic 0:c0ecb8bf28eb 18632 v7_disown(v7, &name);
Marko Mikulicic 0:c0ecb8bf28eb 18633
Marko Mikulicic 0:c0ecb8bf28eb 18634 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 18635 }
Marko Mikulicic 0:c0ecb8bf28eb 18636
Marko Mikulicic 0:c0ecb8bf28eb 18637 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 18638 V7_PRIVATE enum v7_err def_property(struct v7 *v7, val_t obj, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 18639 size_t len, v7_prop_attr_desc_t attrs_desc,
Marko Mikulicic 0:c0ecb8bf28eb 18640 v7_val_t val, uint8_t as_assign,
Marko Mikulicic 0:c0ecb8bf28eb 18641 struct v7_property **res) {
Marko Mikulicic 0:c0ecb8bf28eb 18642 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18643 val_t name_val = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18644
Marko Mikulicic 0:c0ecb8bf28eb 18645 v7_own(v7, &obj);
Marko Mikulicic 0:c0ecb8bf28eb 18646 v7_own(v7, &val);
Marko Mikulicic 0:c0ecb8bf28eb 18647 v7_own(v7, &name_val);
Marko Mikulicic 0:c0ecb8bf28eb 18648
Marko Mikulicic 0:c0ecb8bf28eb 18649 if (len == (size_t) ~0) {
Marko Mikulicic 0:c0ecb8bf28eb 18650 len = strlen(name);
Marko Mikulicic 0:c0ecb8bf28eb 18651 }
Marko Mikulicic 0:c0ecb8bf28eb 18652
Marko Mikulicic 0:c0ecb8bf28eb 18653 name_val = v7_mk_string(v7, name, len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 18654 V7_TRY(def_property_v(v7, obj, name_val, attrs_desc, val, as_assign, res));
Marko Mikulicic 0:c0ecb8bf28eb 18655
Marko Mikulicic 0:c0ecb8bf28eb 18656 clean:
Marko Mikulicic 0:c0ecb8bf28eb 18657 v7_disown(v7, &name_val);
Marko Mikulicic 0:c0ecb8bf28eb 18658 v7_disown(v7, &val);
Marko Mikulicic 0:c0ecb8bf28eb 18659 v7_disown(v7, &obj);
Marko Mikulicic 0:c0ecb8bf28eb 18660
Marko Mikulicic 0:c0ecb8bf28eb 18661 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 18662 }
Marko Mikulicic 0:c0ecb8bf28eb 18663
Marko Mikulicic 0:c0ecb8bf28eb 18664 V7_PRIVATE int set_method(struct v7 *v7, v7_val_t obj, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 18665 v7_cfunction_t *func, int num_args) {
Marko Mikulicic 0:c0ecb8bf28eb 18666 return v7_def(v7, obj, name, strlen(name), V7_DESC_ENUMERABLE(0),
Marko Mikulicic 0:c0ecb8bf28eb 18667 mk_cfunction_obj(v7, func, num_args));
Marko Mikulicic 0:c0ecb8bf28eb 18668 }
Marko Mikulicic 0:c0ecb8bf28eb 18669
Marko Mikulicic 0:c0ecb8bf28eb 18670 int v7_set_method(struct v7 *v7, v7_val_t obj, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 18671 v7_cfunction_t *func) {
Marko Mikulicic 0:c0ecb8bf28eb 18672 return set_method(v7, obj, name, func, ~0);
Marko Mikulicic 0:c0ecb8bf28eb 18673 }
Marko Mikulicic 0:c0ecb8bf28eb 18674
Marko Mikulicic 0:c0ecb8bf28eb 18675 V7_PRIVATE int set_cfunc_prop(struct v7 *v7, val_t o, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 18676 v7_cfunction_t *f) {
Marko Mikulicic 0:c0ecb8bf28eb 18677 return v7_def(v7, o, name, strlen(name), V7_DESC_ENUMERABLE(0),
Marko Mikulicic 0:c0ecb8bf28eb 18678 v7_mk_cfunction(f));
Marko Mikulicic 0:c0ecb8bf28eb 18679 }
Marko Mikulicic 0:c0ecb8bf28eb 18680
Marko Mikulicic 0:c0ecb8bf28eb 18681 /*
Marko Mikulicic 0:c0ecb8bf28eb 18682 * See comments in `object_public.h`
Marko Mikulicic 0:c0ecb8bf28eb 18683 */
Marko Mikulicic 0:c0ecb8bf28eb 18684 int v7_del(struct v7 *v7, val_t obj, const char *name, size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 18685 struct v7_property *prop, *prev;
Marko Mikulicic 0:c0ecb8bf28eb 18686
Marko Mikulicic 0:c0ecb8bf28eb 18687 if (!v7_is_object(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 18688 return -1;
Marko Mikulicic 0:c0ecb8bf28eb 18689 }
Marko Mikulicic 0:c0ecb8bf28eb 18690 if (len == (size_t) ~0) {
Marko Mikulicic 0:c0ecb8bf28eb 18691 len = strlen(name);
Marko Mikulicic 0:c0ecb8bf28eb 18692 }
Marko Mikulicic 0:c0ecb8bf28eb 18693 for (prev = NULL, prop = get_object_struct(obj)->properties; prop != NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18694 prev = prop, prop = prop->next) {
Marko Mikulicic 0:c0ecb8bf28eb 18695 size_t n;
Marko Mikulicic 0:c0ecb8bf28eb 18696 const char *s = v7_get_string(v7, &prop->name, &n);
Marko Mikulicic 0:c0ecb8bf28eb 18697 if (n == len && strncmp(s, name, len) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 18698 if (prev) {
Marko Mikulicic 0:c0ecb8bf28eb 18699 prev->next = prop->next;
Marko Mikulicic 0:c0ecb8bf28eb 18700 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18701 get_object_struct(obj)->properties = prop->next;
Marko Mikulicic 0:c0ecb8bf28eb 18702 }
Marko Mikulicic 0:c0ecb8bf28eb 18703 v7_destroy_property(&prop);
Marko Mikulicic 0:c0ecb8bf28eb 18704 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 18705 }
Marko Mikulicic 0:c0ecb8bf28eb 18706 }
Marko Mikulicic 0:c0ecb8bf28eb 18707 return -1;
Marko Mikulicic 0:c0ecb8bf28eb 18708 }
Marko Mikulicic 0:c0ecb8bf28eb 18709
Marko Mikulicic 0:c0ecb8bf28eb 18710 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 18711 V7_PRIVATE enum v7_err v7_property_value(struct v7 *v7, val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 18712 struct v7_property *p, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 18713 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18714 if (p == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 18715 *res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18716 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18717 }
Marko Mikulicic 0:c0ecb8bf28eb 18718 if (p->attributes & V7_PROPERTY_GETTER) {
Marko Mikulicic 0:c0ecb8bf28eb 18719 val_t getter = p->value;
Marko Mikulicic 0:c0ecb8bf28eb 18720 if (p->attributes & V7_PROPERTY_SETTER) {
Marko Mikulicic 0:c0ecb8bf28eb 18721 getter = v7_array_get(v7, p->value, 0);
Marko Mikulicic 0:c0ecb8bf28eb 18722 }
Marko Mikulicic 0:c0ecb8bf28eb 18723 {
Marko Mikulicic 0:c0ecb8bf28eb 18724 V7_TRY(b_apply(v7, getter, obj, V7_UNDEFINED, 0, res));
Marko Mikulicic 0:c0ecb8bf28eb 18725 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18726 }
Marko Mikulicic 0:c0ecb8bf28eb 18727 }
Marko Mikulicic 0:c0ecb8bf28eb 18728
Marko Mikulicic 0:c0ecb8bf28eb 18729 *res = p->value;
Marko Mikulicic 0:c0ecb8bf28eb 18730 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18731
Marko Mikulicic 0:c0ecb8bf28eb 18732 clean:
Marko Mikulicic 0:c0ecb8bf28eb 18733 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 18734 }
Marko Mikulicic 0:c0ecb8bf28eb 18735
Marko Mikulicic 0:c0ecb8bf28eb 18736 enum v7_err v7_init_prop_iter_ctx(struct v7 *v7, v7_val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 18737 struct prop_iter_ctx *ctx) {
Marko Mikulicic 0:c0ecb8bf28eb 18738 return init_prop_iter_ctx(v7, obj, 1 /*proxy-transparent*/, ctx);
Marko Mikulicic 0:c0ecb8bf28eb 18739 }
Marko Mikulicic 0:c0ecb8bf28eb 18740
Marko Mikulicic 0:c0ecb8bf28eb 18741 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 18742 V7_PRIVATE enum v7_err init_prop_iter_ctx(struct v7 *v7, v7_val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 18743 int proxy_transp,
Marko Mikulicic 0:c0ecb8bf28eb 18744 struct prop_iter_ctx *ctx) {
Marko Mikulicic 0:c0ecb8bf28eb 18745 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18746
Marko Mikulicic 0:c0ecb8bf28eb 18747 v7_own(v7, &obj);
Marko Mikulicic 0:c0ecb8bf28eb 18748
Marko Mikulicic 0:c0ecb8bf28eb 18749 memset(ctx, 0x00, sizeof(*ctx));
Marko Mikulicic 0:c0ecb8bf28eb 18750
Marko Mikulicic 0:c0ecb8bf28eb 18751 if (v7_is_object(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 18752 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 18753 if (proxy_transp && get_object_struct(obj)->attributes & V7_OBJ_PROXY) {
Marko Mikulicic 0:c0ecb8bf28eb 18754 v7_val_t ownKeys_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18755 v7_val_t args_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18756
Marko Mikulicic 0:c0ecb8bf28eb 18757 v7_own(v7, &ownKeys_v);
Marko Mikulicic 0:c0ecb8bf28eb 18758 v7_own(v7, &args_v);
Marko Mikulicic 0:c0ecb8bf28eb 18759
Marko Mikulicic 0:c0ecb8bf28eb 18760 ctx->proxy_ctx =
Marko Mikulicic 0:c0ecb8bf28eb 18761 (struct prop_iter_proxy_ctx *) calloc(1, sizeof(*ctx->proxy_ctx));
Marko Mikulicic 0:c0ecb8bf28eb 18762
Marko Mikulicic 0:c0ecb8bf28eb 18763 ctx->proxy_ctx->target_obj = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18764 ctx->proxy_ctx->handler_obj = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18765 ctx->proxy_ctx->own_keys = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18766 ctx->proxy_ctx->get_own_prop_desc = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18767
Marko Mikulicic 0:c0ecb8bf28eb 18768 v7_own(v7, &ctx->proxy_ctx->target_obj);
Marko Mikulicic 0:c0ecb8bf28eb 18769 v7_own(v7, &ctx->proxy_ctx->handler_obj);
Marko Mikulicic 0:c0ecb8bf28eb 18770 v7_own(v7, &ctx->proxy_ctx->own_keys);
Marko Mikulicic 0:c0ecb8bf28eb 18771 v7_own(v7, &ctx->proxy_ctx->get_own_prop_desc);
Marko Mikulicic 0:c0ecb8bf28eb 18772
Marko Mikulicic 0:c0ecb8bf28eb 18773 V7_TRY2(v7_get_throwing(v7, obj, _V7_PROXY_TARGET_NAME, ~0,
Marko Mikulicic 0:c0ecb8bf28eb 18774 &ctx->proxy_ctx->target_obj),
Marko Mikulicic 0:c0ecb8bf28eb 18775 clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18776 V7_TRY2(v7_get_throwing(v7, obj, _V7_PROXY_HANDLER_NAME, ~0,
Marko Mikulicic 0:c0ecb8bf28eb 18777 &ctx->proxy_ctx->handler_obj),
Marko Mikulicic 0:c0ecb8bf28eb 18778 clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18779
Marko Mikulicic 0:c0ecb8bf28eb 18780 V7_TRY2(v7_get_throwing(v7, ctx->proxy_ctx->handler_obj, "ownKeys", ~0,
Marko Mikulicic 0:c0ecb8bf28eb 18781 &ownKeys_v),
Marko Mikulicic 0:c0ecb8bf28eb 18782 clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18783
Marko Mikulicic 0:c0ecb8bf28eb 18784 if (v7_is_callable(v7, ownKeys_v)) {
Marko Mikulicic 0:c0ecb8bf28eb 18785 /* prepare arguments for the ownKeys callback */
Marko Mikulicic 0:c0ecb8bf28eb 18786 args_v = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 18787 v7_array_set(v7, args_v, 0, ctx->proxy_ctx->target_obj);
Marko Mikulicic 0:c0ecb8bf28eb 18788
Marko Mikulicic 0:c0ecb8bf28eb 18789 /* call `ownKeys` callback, and save the result in context */
Marko Mikulicic 0:c0ecb8bf28eb 18790 V7_TRY2(b_apply(v7, ownKeys_v, V7_UNDEFINED, args_v, 0,
Marko Mikulicic 0:c0ecb8bf28eb 18791 &ctx->proxy_ctx->own_keys),
Marko Mikulicic 0:c0ecb8bf28eb 18792 clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18793
Marko Mikulicic 0:c0ecb8bf28eb 18794 ctx->proxy_ctx->has_own_keys = 1;
Marko Mikulicic 0:c0ecb8bf28eb 18795 ctx->proxy_ctx->own_key_idx = 0;
Marko Mikulicic 0:c0ecb8bf28eb 18796
Marko Mikulicic 0:c0ecb8bf28eb 18797 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18798 /*
Marko Mikulicic 0:c0ecb8bf28eb 18799 * No ownKeys callback, so we'll iterate real properties of the target
Marko Mikulicic 0:c0ecb8bf28eb 18800 * object
Marko Mikulicic 0:c0ecb8bf28eb 18801 */
Marko Mikulicic 0:c0ecb8bf28eb 18802
Marko Mikulicic 0:c0ecb8bf28eb 18803 /*
Marko Mikulicic 0:c0ecb8bf28eb 18804 * TODO(dfrank): add support for the target object which is a proxy as
Marko Mikulicic 0:c0ecb8bf28eb 18805 * well
Marko Mikulicic 0:c0ecb8bf28eb 18806 */
Marko Mikulicic 0:c0ecb8bf28eb 18807 ctx->cur_prop =
Marko Mikulicic 0:c0ecb8bf28eb 18808 get_object_struct(ctx->proxy_ctx->target_obj)->properties;
Marko Mikulicic 0:c0ecb8bf28eb 18809 }
Marko Mikulicic 0:c0ecb8bf28eb 18810
Marko Mikulicic 0:c0ecb8bf28eb 18811 V7_TRY2(v7_get_throwing(v7, ctx->proxy_ctx->handler_obj, "_gpdc", ~0,
Marko Mikulicic 0:c0ecb8bf28eb 18812 &ctx->proxy_ctx->get_own_prop_desc),
Marko Mikulicic 0:c0ecb8bf28eb 18813 clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18814 if (v7_is_foreign(ctx->proxy_ctx->get_own_prop_desc)) {
Marko Mikulicic 0:c0ecb8bf28eb 18815 /*
Marko Mikulicic 0:c0ecb8bf28eb 18816 * C callback for getting property descriptor is provided: will use it
Marko Mikulicic 0:c0ecb8bf28eb 18817 */
Marko Mikulicic 0:c0ecb8bf28eb 18818 ctx->proxy_ctx->has_get_own_prop_desc = 1;
Marko Mikulicic 0:c0ecb8bf28eb 18819 ctx->proxy_ctx->has_get_own_prop_desc_C = 1;
Marko Mikulicic 0:c0ecb8bf28eb 18820 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18821 /*
Marko Mikulicic 0:c0ecb8bf28eb 18822 * No C callback for getting property descriptor is provided, let's
Marko Mikulicic 0:c0ecb8bf28eb 18823 * check if there is a JS one..
Marko Mikulicic 0:c0ecb8bf28eb 18824 */
Marko Mikulicic 0:c0ecb8bf28eb 18825 V7_TRY2(v7_get_throwing(v7, ctx->proxy_ctx->handler_obj,
Marko Mikulicic 0:c0ecb8bf28eb 18826 "getOwnPropertyDescriptor", ~0,
Marko Mikulicic 0:c0ecb8bf28eb 18827 &ctx->proxy_ctx->get_own_prop_desc),
Marko Mikulicic 0:c0ecb8bf28eb 18828 clean_proxy);
Marko Mikulicic 0:c0ecb8bf28eb 18829
Marko Mikulicic 0:c0ecb8bf28eb 18830 if (v7_is_callable(v7, ctx->proxy_ctx->get_own_prop_desc)) {
Marko Mikulicic 0:c0ecb8bf28eb 18831 /* Yes there is, we'll use it */
Marko Mikulicic 0:c0ecb8bf28eb 18832 ctx->proxy_ctx->has_get_own_prop_desc = 1;
Marko Mikulicic 0:c0ecb8bf28eb 18833 }
Marko Mikulicic 0:c0ecb8bf28eb 18834 }
Marko Mikulicic 0:c0ecb8bf28eb 18835
Marko Mikulicic 0:c0ecb8bf28eb 18836 clean_proxy:
Marko Mikulicic 0:c0ecb8bf28eb 18837 v7_disown(v7, &args_v);
Marko Mikulicic 0:c0ecb8bf28eb 18838 v7_disown(v7, &ownKeys_v);
Marko Mikulicic 0:c0ecb8bf28eb 18839
Marko Mikulicic 0:c0ecb8bf28eb 18840 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 18841 /* something went wrong, so, disown values in the context and free it */
Marko Mikulicic 0:c0ecb8bf28eb 18842 v7_disown(v7, &ctx->proxy_ctx->get_own_prop_desc);
Marko Mikulicic 0:c0ecb8bf28eb 18843 v7_disown(v7, &ctx->proxy_ctx->own_keys);
Marko Mikulicic 0:c0ecb8bf28eb 18844 v7_disown(v7, &ctx->proxy_ctx->handler_obj);
Marko Mikulicic 0:c0ecb8bf28eb 18845 v7_disown(v7, &ctx->proxy_ctx->target_obj);
Marko Mikulicic 0:c0ecb8bf28eb 18846
Marko Mikulicic 0:c0ecb8bf28eb 18847 free(ctx->proxy_ctx);
Marko Mikulicic 0:c0ecb8bf28eb 18848 ctx->proxy_ctx = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18849
Marko Mikulicic 0:c0ecb8bf28eb 18850 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 18851 }
Marko Mikulicic 0:c0ecb8bf28eb 18852 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18853 #else
Marko Mikulicic 0:c0ecb8bf28eb 18854 (void) proxy_transp;
Marko Mikulicic 0:c0ecb8bf28eb 18855 #endif
Marko Mikulicic 0:c0ecb8bf28eb 18856
Marko Mikulicic 0:c0ecb8bf28eb 18857 /* Object is not a proxy: we'll iterate real properties */
Marko Mikulicic 0:c0ecb8bf28eb 18858 ctx->cur_prop = get_object_struct(obj)->properties;
Marko Mikulicic 0:c0ecb8bf28eb 18859
Marko Mikulicic 0:c0ecb8bf28eb 18860 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 18861 }
Marko Mikulicic 0:c0ecb8bf28eb 18862 #endif
Marko Mikulicic 0:c0ecb8bf28eb 18863 }
Marko Mikulicic 0:c0ecb8bf28eb 18864
Marko Mikulicic 0:c0ecb8bf28eb 18865 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 18866 clean:
Marko Mikulicic 0:c0ecb8bf28eb 18867 #endif
Marko Mikulicic 0:c0ecb8bf28eb 18868 v7_disown(v7, &obj);
Marko Mikulicic 0:c0ecb8bf28eb 18869 if (rcode == V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 18870 ctx->init = 1;
Marko Mikulicic 0:c0ecb8bf28eb 18871 }
Marko Mikulicic 0:c0ecb8bf28eb 18872 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 18873 }
Marko Mikulicic 0:c0ecb8bf28eb 18874
Marko Mikulicic 0:c0ecb8bf28eb 18875 void v7_destruct_prop_iter_ctx(struct v7 *v7, struct prop_iter_ctx *ctx) {
Marko Mikulicic 0:c0ecb8bf28eb 18876 if (ctx->init) {
Marko Mikulicic 0:c0ecb8bf28eb 18877 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 18878 if (ctx->proxy_ctx != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 18879 v7_disown(v7, &ctx->proxy_ctx->target_obj);
Marko Mikulicic 0:c0ecb8bf28eb 18880 v7_disown(v7, &ctx->proxy_ctx->handler_obj);
Marko Mikulicic 0:c0ecb8bf28eb 18881 v7_disown(v7, &ctx->proxy_ctx->own_keys);
Marko Mikulicic 0:c0ecb8bf28eb 18882 v7_disown(v7, &ctx->proxy_ctx->get_own_prop_desc);
Marko Mikulicic 0:c0ecb8bf28eb 18883 }
Marko Mikulicic 0:c0ecb8bf28eb 18884 free(ctx->proxy_ctx);
Marko Mikulicic 0:c0ecb8bf28eb 18885 ctx->proxy_ctx = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18886 #else
Marko Mikulicic 0:c0ecb8bf28eb 18887 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 18888 #endif
Marko Mikulicic 0:c0ecb8bf28eb 18889 ctx->init = 0;
Marko Mikulicic 0:c0ecb8bf28eb 18890 }
Marko Mikulicic 0:c0ecb8bf28eb 18891 }
Marko Mikulicic 0:c0ecb8bf28eb 18892
Marko Mikulicic 0:c0ecb8bf28eb 18893 int v7_next_prop(struct v7 *v7, struct prop_iter_ctx *ctx, v7_val_t *name,
Marko Mikulicic 0:c0ecb8bf28eb 18894 v7_val_t *value, v7_prop_attr_t *attrs) {
Marko Mikulicic 0:c0ecb8bf28eb 18895 int ok = 0;
Marko Mikulicic 0:c0ecb8bf28eb 18896 if (next_prop(v7, ctx, name, value, attrs, &ok) != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 18897 fprintf(stderr, "next_prop failed\n");
Marko Mikulicic 0:c0ecb8bf28eb 18898 ok = 0;
Marko Mikulicic 0:c0ecb8bf28eb 18899 }
Marko Mikulicic 0:c0ecb8bf28eb 18900 return ok;
Marko Mikulicic 0:c0ecb8bf28eb 18901 }
Marko Mikulicic 0:c0ecb8bf28eb 18902
Marko Mikulicic 0:c0ecb8bf28eb 18903 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 18904 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 18905 static enum v7_err get_custom_prop_desc(struct v7 *v7, v7_val_t name,
Marko Mikulicic 0:c0ecb8bf28eb 18906 struct prop_iter_ctx *ctx,
Marko Mikulicic 0:c0ecb8bf28eb 18907 struct v7_property *res_prop, int *ok) {
Marko Mikulicic 0:c0ecb8bf28eb 18908 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18909
Marko Mikulicic 0:c0ecb8bf28eb 18910 v7_val_t args_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18911 v7_val_t desc_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18912 v7_val_t tmpflag_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18913
Marko Mikulicic 0:c0ecb8bf28eb 18914 v7_own(v7, &name);
Marko Mikulicic 0:c0ecb8bf28eb 18915 v7_own(v7, &args_v);
Marko Mikulicic 0:c0ecb8bf28eb 18916 v7_own(v7, &desc_v);
Marko Mikulicic 0:c0ecb8bf28eb 18917 v7_own(v7, &tmpflag_v);
Marko Mikulicic 0:c0ecb8bf28eb 18918
Marko Mikulicic 0:c0ecb8bf28eb 18919 *ok = 0;
Marko Mikulicic 0:c0ecb8bf28eb 18920
Marko Mikulicic 0:c0ecb8bf28eb 18921 if (ctx->proxy_ctx->has_get_own_prop_desc_C) {
Marko Mikulicic 0:c0ecb8bf28eb 18922 /*
Marko Mikulicic 0:c0ecb8bf28eb 18923 * There is a C callback which should fill the property descriptor
Marko Mikulicic 0:c0ecb8bf28eb 18924 * structure, see `v7_get_own_prop_desc_cb_t`
Marko Mikulicic 0:c0ecb8bf28eb 18925 */
Marko Mikulicic 0:c0ecb8bf28eb 18926 v7_get_own_prop_desc_cb_t *cb = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 18927 memset(res_prop, 0, sizeof(*res_prop));
Marko Mikulicic 0:c0ecb8bf28eb 18928 cb = (v7_get_own_prop_desc_cb_t *) v7_get_ptr(
Marko Mikulicic 0:c0ecb8bf28eb 18929 v7, ctx->proxy_ctx->get_own_prop_desc);
Marko Mikulicic 0:c0ecb8bf28eb 18930
Marko Mikulicic 0:c0ecb8bf28eb 18931 res_prop->attributes = 0;
Marko Mikulicic 0:c0ecb8bf28eb 18932 res_prop->value = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18933
Marko Mikulicic 0:c0ecb8bf28eb 18934 *ok = !!cb(v7, ctx->proxy_ctx->target_obj, name, &res_prop->attributes,
Marko Mikulicic 0:c0ecb8bf28eb 18935 &res_prop->value);
Marko Mikulicic 0:c0ecb8bf28eb 18936 } else {
Marko Mikulicic 0:c0ecb8bf28eb 18937 /* prepare arguments for the getOwnPropertyDescriptor callback */
Marko Mikulicic 0:c0ecb8bf28eb 18938 args_v = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 18939 v7_array_set(v7, args_v, 0, ctx->proxy_ctx->target_obj);
Marko Mikulicic 0:c0ecb8bf28eb 18940 v7_array_set(v7, args_v, 1, name);
Marko Mikulicic 0:c0ecb8bf28eb 18941
Marko Mikulicic 0:c0ecb8bf28eb 18942 /* call getOwnPropertyDescriptor callback */
Marko Mikulicic 0:c0ecb8bf28eb 18943 V7_TRY(b_apply(v7, ctx->proxy_ctx->get_own_prop_desc, V7_UNDEFINED, args_v,
Marko Mikulicic 0:c0ecb8bf28eb 18944 0, &desc_v));
Marko Mikulicic 0:c0ecb8bf28eb 18945
Marko Mikulicic 0:c0ecb8bf28eb 18946 if (v7_is_object(desc_v)) {
Marko Mikulicic 0:c0ecb8bf28eb 18947 res_prop->attributes = 0;
Marko Mikulicic 0:c0ecb8bf28eb 18948
Marko Mikulicic 0:c0ecb8bf28eb 18949 V7_TRY(v7_get_throwing(v7, desc_v, "writable", ~0, &tmpflag_v));
Marko Mikulicic 0:c0ecb8bf28eb 18950 if (!v7_is_truthy(v7, tmpflag_v)) {
Marko Mikulicic 0:c0ecb8bf28eb 18951 res_prop->attributes |= V7_PROPERTY_NON_WRITABLE;
Marko Mikulicic 0:c0ecb8bf28eb 18952 }
Marko Mikulicic 0:c0ecb8bf28eb 18953
Marko Mikulicic 0:c0ecb8bf28eb 18954 V7_TRY(v7_get_throwing(v7, desc_v, "configurable", ~0, &tmpflag_v));
Marko Mikulicic 0:c0ecb8bf28eb 18955 if (!v7_is_truthy(v7, tmpflag_v)) {
Marko Mikulicic 0:c0ecb8bf28eb 18956 res_prop->attributes |= V7_PROPERTY_NON_CONFIGURABLE;
Marko Mikulicic 0:c0ecb8bf28eb 18957 }
Marko Mikulicic 0:c0ecb8bf28eb 18958
Marko Mikulicic 0:c0ecb8bf28eb 18959 V7_TRY(v7_get_throwing(v7, desc_v, "enumerable", ~0, &tmpflag_v));
Marko Mikulicic 0:c0ecb8bf28eb 18960 if (!v7_is_truthy(v7, tmpflag_v)) {
Marko Mikulicic 0:c0ecb8bf28eb 18961 res_prop->attributes |= V7_PROPERTY_NON_ENUMERABLE;
Marko Mikulicic 0:c0ecb8bf28eb 18962 }
Marko Mikulicic 0:c0ecb8bf28eb 18963
Marko Mikulicic 0:c0ecb8bf28eb 18964 V7_TRY(v7_get_throwing(v7, desc_v, "value", ~0, &res_prop->value));
Marko Mikulicic 0:c0ecb8bf28eb 18965
Marko Mikulicic 0:c0ecb8bf28eb 18966 *ok = 1;
Marko Mikulicic 0:c0ecb8bf28eb 18967 }
Marko Mikulicic 0:c0ecb8bf28eb 18968 }
Marko Mikulicic 0:c0ecb8bf28eb 18969
Marko Mikulicic 0:c0ecb8bf28eb 18970 /* We always set the name in the property descriptor to the actual name */
Marko Mikulicic 0:c0ecb8bf28eb 18971 res_prop->name = name;
Marko Mikulicic 0:c0ecb8bf28eb 18972
Marko Mikulicic 0:c0ecb8bf28eb 18973 clean:
Marko Mikulicic 0:c0ecb8bf28eb 18974 v7_disown(v7, &tmpflag_v);
Marko Mikulicic 0:c0ecb8bf28eb 18975 v7_disown(v7, &desc_v);
Marko Mikulicic 0:c0ecb8bf28eb 18976 v7_disown(v7, &args_v);
Marko Mikulicic 0:c0ecb8bf28eb 18977 v7_disown(v7, &name);
Marko Mikulicic 0:c0ecb8bf28eb 18978
Marko Mikulicic 0:c0ecb8bf28eb 18979 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 18980 }
Marko Mikulicic 0:c0ecb8bf28eb 18981 #endif
Marko Mikulicic 0:c0ecb8bf28eb 18982
Marko Mikulicic 0:c0ecb8bf28eb 18983 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 18984 V7_PRIVATE enum v7_err next_prop(struct v7 *v7, struct prop_iter_ctx *ctx,
Marko Mikulicic 0:c0ecb8bf28eb 18985 v7_val_t *name, v7_val_t *value,
Marko Mikulicic 0:c0ecb8bf28eb 18986 v7_prop_attr_t *attrs, int *ok) {
Marko Mikulicic 0:c0ecb8bf28eb 18987 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 18988 struct v7_property p;
Marko Mikulicic 0:c0ecb8bf28eb 18989
Marko Mikulicic 0:c0ecb8bf28eb 18990 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 18991
Marko Mikulicic 0:c0ecb8bf28eb 18992 memset(&p, 0, sizeof(p));
Marko Mikulicic 0:c0ecb8bf28eb 18993 p.name = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18994 p.value = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 18995
Marko Mikulicic 0:c0ecb8bf28eb 18996 v7_own(v7, &p.name);
Marko Mikulicic 0:c0ecb8bf28eb 18997 v7_own(v7, &p.value);
Marko Mikulicic 0:c0ecb8bf28eb 18998
Marko Mikulicic 0:c0ecb8bf28eb 18999 assert(ctx->init);
Marko Mikulicic 0:c0ecb8bf28eb 19000
Marko Mikulicic 0:c0ecb8bf28eb 19001 *ok = 0;
Marko Mikulicic 0:c0ecb8bf28eb 19002
Marko Mikulicic 0:c0ecb8bf28eb 19003 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 19004 if (ctx->proxy_ctx == NULL || !ctx->proxy_ctx->has_own_keys) {
Marko Mikulicic 0:c0ecb8bf28eb 19005 /*
Marko Mikulicic 0:c0ecb8bf28eb 19006 * No `ownKeys` callback, so we'll iterate real properties of the object
Marko Mikulicic 0:c0ecb8bf28eb 19007 * (either the given object or, if it's a proxy, the proxy's target object)
Marko Mikulicic 0:c0ecb8bf28eb 19008 */
Marko Mikulicic 0:c0ecb8bf28eb 19009
Marko Mikulicic 0:c0ecb8bf28eb 19010 if (ctx->cur_prop != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 19011 if (ctx->proxy_ctx == NULL || !ctx->proxy_ctx->has_get_own_prop_desc) {
Marko Mikulicic 0:c0ecb8bf28eb 19012 /*
Marko Mikulicic 0:c0ecb8bf28eb 19013 * There is no `getOwnPropertyDescriptor` callback, so, use the current
Marko Mikulicic 0:c0ecb8bf28eb 19014 * real property
Marko Mikulicic 0:c0ecb8bf28eb 19015 */
Marko Mikulicic 0:c0ecb8bf28eb 19016 memcpy(&p, ctx->cur_prop, sizeof(p));
Marko Mikulicic 0:c0ecb8bf28eb 19017 *ok = 1;
Marko Mikulicic 0:c0ecb8bf28eb 19018 } else {
Marko Mikulicic 0:c0ecb8bf28eb 19019 /*
Marko Mikulicic 0:c0ecb8bf28eb 19020 * There is a `getOwnPropertyDescriptor` callback, so call it for the
Marko Mikulicic 0:c0ecb8bf28eb 19021 * name of the current real property
Marko Mikulicic 0:c0ecb8bf28eb 19022 */
Marko Mikulicic 0:c0ecb8bf28eb 19023 V7_TRY(get_custom_prop_desc(v7, ctx->cur_prop->name, ctx, &p, ok));
Marko Mikulicic 0:c0ecb8bf28eb 19024 }
Marko Mikulicic 0:c0ecb8bf28eb 19025
Marko Mikulicic 0:c0ecb8bf28eb 19026 ctx->cur_prop = ctx->cur_prop->next;
Marko Mikulicic 0:c0ecb8bf28eb 19027 }
Marko Mikulicic 0:c0ecb8bf28eb 19028 } else {
Marko Mikulicic 0:c0ecb8bf28eb 19029 /* We have custom own keys */
Marko Mikulicic 0:c0ecb8bf28eb 19030 v7_val_t cur_key = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 19031 size_t len = v7_array_length(v7, ctx->proxy_ctx->own_keys);
Marko Mikulicic 0:c0ecb8bf28eb 19032
Marko Mikulicic 0:c0ecb8bf28eb 19033 v7_own(v7, &cur_key);
Marko Mikulicic 0:c0ecb8bf28eb 19034
Marko Mikulicic 0:c0ecb8bf28eb 19035 /*
Marko Mikulicic 0:c0ecb8bf28eb 19036 * Iterate through the custom own keys until we can get the proper property
Marko Mikulicic 0:c0ecb8bf28eb 19037 * descriptor for the given key
Marko Mikulicic 0:c0ecb8bf28eb 19038 */
Marko Mikulicic 0:c0ecb8bf28eb 19039 while (!*ok && (size_t) ctx->proxy_ctx->own_key_idx < len) {
Marko Mikulicic 0:c0ecb8bf28eb 19040 cur_key = v7_array_get(v7, ctx->proxy_ctx->own_keys,
Marko Mikulicic 0:c0ecb8bf28eb 19041 ctx->proxy_ctx->own_key_idx);
Marko Mikulicic 0:c0ecb8bf28eb 19042 ctx->proxy_ctx->own_key_idx++;
Marko Mikulicic 0:c0ecb8bf28eb 19043
Marko Mikulicic 0:c0ecb8bf28eb 19044 if (ctx->proxy_ctx->has_get_own_prop_desc) {
Marko Mikulicic 0:c0ecb8bf28eb 19045 /*
Marko Mikulicic 0:c0ecb8bf28eb 19046 * There is a `getOwnPropertyDescriptor` callback, so, call it for the
Marko Mikulicic 0:c0ecb8bf28eb 19047 * current custom key and get all descriptor data from the object
Marko Mikulicic 0:c0ecb8bf28eb 19048 * returned. The `ok` variable will be updated appropriately (it will
Marko Mikulicic 0:c0ecb8bf28eb 19049 * be 0 if the callback did not return a proper descriptor)
Marko Mikulicic 0:c0ecb8bf28eb 19050 */
Marko Mikulicic 0:c0ecb8bf28eb 19051 V7_TRY2(get_custom_prop_desc(v7, cur_key, ctx, &p, ok), clean_custom);
Marko Mikulicic 0:c0ecb8bf28eb 19052 } else {
Marko Mikulicic 0:c0ecb8bf28eb 19053 /*
Marko Mikulicic 0:c0ecb8bf28eb 19054 * There is no `getOwnPropertyDescriptor` callback, so, try to get
Marko Mikulicic 0:c0ecb8bf28eb 19055 * real property with the name equal to the current key
Marko Mikulicic 0:c0ecb8bf28eb 19056 */
Marko Mikulicic 0:c0ecb8bf28eb 19057 size_t len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 19058 const char *name = v7_get_string(v7, &cur_key, &len);
Marko Mikulicic 0:c0ecb8bf28eb 19059
Marko Mikulicic 0:c0ecb8bf28eb 19060 struct v7_property *real_prop =
Marko Mikulicic 0:c0ecb8bf28eb 19061 v7_get_own_property(v7, ctx->proxy_ctx->target_obj, name, len);
Marko Mikulicic 0:c0ecb8bf28eb 19062 if (real_prop != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 19063 /* Property exists, so use data from its descriptor */
Marko Mikulicic 0:c0ecb8bf28eb 19064 memcpy(&p, real_prop, sizeof(p));
Marko Mikulicic 0:c0ecb8bf28eb 19065 *ok = 1;
Marko Mikulicic 0:c0ecb8bf28eb 19066 }
Marko Mikulicic 0:c0ecb8bf28eb 19067 }
Marko Mikulicic 0:c0ecb8bf28eb 19068 }
Marko Mikulicic 0:c0ecb8bf28eb 19069 clean_custom:
Marko Mikulicic 0:c0ecb8bf28eb 19070 v7_disown(v7, &cur_key);
Marko Mikulicic 0:c0ecb8bf28eb 19071 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 19072 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19073 }
Marko Mikulicic 0:c0ecb8bf28eb 19074 }
Marko Mikulicic 0:c0ecb8bf28eb 19075
Marko Mikulicic 0:c0ecb8bf28eb 19076 #else
Marko Mikulicic 0:c0ecb8bf28eb 19077 /*
Marko Mikulicic 0:c0ecb8bf28eb 19078 * Proxy is disabled: just get the next property
Marko Mikulicic 0:c0ecb8bf28eb 19079 */
Marko Mikulicic 0:c0ecb8bf28eb 19080 if (ctx->cur_prop != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 19081 memcpy(&p, ctx->cur_prop, sizeof(p));
Marko Mikulicic 0:c0ecb8bf28eb 19082 *ok = 1;
Marko Mikulicic 0:c0ecb8bf28eb 19083 ctx->cur_prop = ctx->cur_prop->next;
Marko Mikulicic 0:c0ecb8bf28eb 19084 }
Marko Mikulicic 0:c0ecb8bf28eb 19085 #endif
Marko Mikulicic 0:c0ecb8bf28eb 19086
Marko Mikulicic 0:c0ecb8bf28eb 19087 /* If we have a valid property descriptor, use data from it */
Marko Mikulicic 0:c0ecb8bf28eb 19088 if (*ok) {
Marko Mikulicic 0:c0ecb8bf28eb 19089 if (name != NULL) *name = p.name;
Marko Mikulicic 0:c0ecb8bf28eb 19090 if (value != NULL) *value = p.value;
Marko Mikulicic 0:c0ecb8bf28eb 19091 if (attrs != NULL) *attrs = p.attributes;
Marko Mikulicic 0:c0ecb8bf28eb 19092 }
Marko Mikulicic 0:c0ecb8bf28eb 19093
Marko Mikulicic 0:c0ecb8bf28eb 19094 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 19095 clean:
Marko Mikulicic 0:c0ecb8bf28eb 19096 #endif
Marko Mikulicic 0:c0ecb8bf28eb 19097 v7_disown(v7, &p.value);
Marko Mikulicic 0:c0ecb8bf28eb 19098 v7_disown(v7, &p.name);
Marko Mikulicic 0:c0ecb8bf28eb 19099 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 19100 }
Marko Mikulicic 0:c0ecb8bf28eb 19101
Marko Mikulicic 0:c0ecb8bf28eb 19102 /* }}} Object properties */
Marko Mikulicic 0:c0ecb8bf28eb 19103
Marko Mikulicic 0:c0ecb8bf28eb 19104 /* Object prototypes {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 19105
Marko Mikulicic 0:c0ecb8bf28eb 19106 V7_PRIVATE int obj_prototype_set(struct v7 *v7, struct v7_object *obj,
Marko Mikulicic 0:c0ecb8bf28eb 19107 struct v7_object *proto) {
Marko Mikulicic 0:c0ecb8bf28eb 19108 int ret = -1;
Marko Mikulicic 0:c0ecb8bf28eb 19109 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 19110
Marko Mikulicic 0:c0ecb8bf28eb 19111 if (obj->attributes & V7_OBJ_FUNCTION) {
Marko Mikulicic 0:c0ecb8bf28eb 19112 ret = -1;
Marko Mikulicic 0:c0ecb8bf28eb 19113 } else {
Marko Mikulicic 0:c0ecb8bf28eb 19114 ((struct v7_generic_object *) obj)->prototype = proto;
Marko Mikulicic 0:c0ecb8bf28eb 19115 ret = 0;
Marko Mikulicic 0:c0ecb8bf28eb 19116 }
Marko Mikulicic 0:c0ecb8bf28eb 19117
Marko Mikulicic 0:c0ecb8bf28eb 19118 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 19119 }
Marko Mikulicic 0:c0ecb8bf28eb 19120
Marko Mikulicic 0:c0ecb8bf28eb 19121 V7_PRIVATE struct v7_object *obj_prototype(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 19122 struct v7_object *obj) {
Marko Mikulicic 0:c0ecb8bf28eb 19123 if (obj->attributes & V7_OBJ_FUNCTION) {
Marko Mikulicic 0:c0ecb8bf28eb 19124 return get_object_struct(v7->vals.function_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 19125 } else {
Marko Mikulicic 0:c0ecb8bf28eb 19126 return ((struct v7_generic_object *) obj)->prototype;
Marko Mikulicic 0:c0ecb8bf28eb 19127 }
Marko Mikulicic 0:c0ecb8bf28eb 19128 }
Marko Mikulicic 0:c0ecb8bf28eb 19129
Marko Mikulicic 0:c0ecb8bf28eb 19130 V7_PRIVATE int is_prototype_of(struct v7 *v7, val_t o, val_t p) {
Marko Mikulicic 0:c0ecb8bf28eb 19131 if (!v7_is_object(o) || !v7_is_object(p)) {
Marko Mikulicic 0:c0ecb8bf28eb 19132 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 19133 }
Marko Mikulicic 0:c0ecb8bf28eb 19134
Marko Mikulicic 0:c0ecb8bf28eb 19135 /* walk the prototype chain */
Marko Mikulicic 0:c0ecb8bf28eb 19136 for (; !v7_is_null(o); o = v7_get_proto(v7, o)) {
Marko Mikulicic 0:c0ecb8bf28eb 19137 if (v7_get_proto(v7, o) == p) {
Marko Mikulicic 0:c0ecb8bf28eb 19138 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 19139 }
Marko Mikulicic 0:c0ecb8bf28eb 19140 }
Marko Mikulicic 0:c0ecb8bf28eb 19141 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 19142 }
Marko Mikulicic 0:c0ecb8bf28eb 19143
Marko Mikulicic 0:c0ecb8bf28eb 19144 int v7_is_instanceof(struct v7 *v7, val_t o, const char *c) {
Marko Mikulicic 0:c0ecb8bf28eb 19145 return v7_is_instanceof_v(v7, o, v7_get(v7, v7->vals.global_object, c, ~0));
Marko Mikulicic 0:c0ecb8bf28eb 19146 }
Marko Mikulicic 0:c0ecb8bf28eb 19147
Marko Mikulicic 0:c0ecb8bf28eb 19148 int v7_is_instanceof_v(struct v7 *v7, val_t o, val_t c) {
Marko Mikulicic 0:c0ecb8bf28eb 19149 return is_prototype_of(v7, o, v7_get(v7, c, "prototype", 9));
Marko Mikulicic 0:c0ecb8bf28eb 19150 }
Marko Mikulicic 0:c0ecb8bf28eb 19151
Marko Mikulicic 0:c0ecb8bf28eb 19152 v7_val_t v7_set_proto(struct v7 *v7, v7_val_t obj, v7_val_t proto) {
Marko Mikulicic 0:c0ecb8bf28eb 19153 if (v7_is_generic_object(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 19154 v7_val_t old_proto =
Marko Mikulicic 0:c0ecb8bf28eb 19155 v7_object_to_value(obj_prototype(v7, get_object_struct(obj)));
Marko Mikulicic 0:c0ecb8bf28eb 19156 obj_prototype_set(v7, get_object_struct(obj), get_object_struct(proto));
Marko Mikulicic 0:c0ecb8bf28eb 19157 return old_proto;
Marko Mikulicic 0:c0ecb8bf28eb 19158 } else {
Marko Mikulicic 0:c0ecb8bf28eb 19159 return V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 19160 }
Marko Mikulicic 0:c0ecb8bf28eb 19161 }
Marko Mikulicic 0:c0ecb8bf28eb 19162
Marko Mikulicic 0:c0ecb8bf28eb 19163 val_t v7_get_proto(struct v7 *v7, val_t obj) {
Marko Mikulicic 0:c0ecb8bf28eb 19164 /*
Marko Mikulicic 0:c0ecb8bf28eb 19165 * NOTE: we don't use v7_is_callable() here, because it involves walking
Marko Mikulicic 0:c0ecb8bf28eb 19166 * through the object's properties, which may be expensive. And it's done
Marko Mikulicic 0:c0ecb8bf28eb 19167 * anyway for cfunction objects as it would for any other generic objects by
Marko Mikulicic 0:c0ecb8bf28eb 19168 * the call to `obj_prototype()`.
Marko Mikulicic 0:c0ecb8bf28eb 19169 *
Marko Mikulicic 0:c0ecb8bf28eb 19170 * Since this function is called quite often (at least, GC walks the
Marko Mikulicic 0:c0ecb8bf28eb 19171 * prototype chain), it's better to just handle cfunction objects as generic
Marko Mikulicic 0:c0ecb8bf28eb 19172 * objects.
Marko Mikulicic 0:c0ecb8bf28eb 19173 */
Marko Mikulicic 0:c0ecb8bf28eb 19174 if (is_js_function(obj) || is_cfunction_lite(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 19175 return v7->vals.function_prototype;
Marko Mikulicic 0:c0ecb8bf28eb 19176 }
Marko Mikulicic 0:c0ecb8bf28eb 19177 return v7_object_to_value(obj_prototype(v7, get_object_struct(obj)));
Marko Mikulicic 0:c0ecb8bf28eb 19178 }
Marko Mikulicic 0:c0ecb8bf28eb 19179
Marko Mikulicic 0:c0ecb8bf28eb 19180 V7_PRIVATE struct v7_property *get_user_data_property(v7_val_t obj) {
Marko Mikulicic 0:c0ecb8bf28eb 19181 struct v7_property *p;
Marko Mikulicic 0:c0ecb8bf28eb 19182 struct v7_object *o;
Marko Mikulicic 0:c0ecb8bf28eb 19183 if (!v7_is_object(obj)) return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 19184 o = get_object_struct(obj);
Marko Mikulicic 0:c0ecb8bf28eb 19185
Marko Mikulicic 0:c0ecb8bf28eb 19186 for (p = o->properties; p != NULL; p = p->next) {
Marko Mikulicic 0:c0ecb8bf28eb 19187 if (p->attributes & _V7_PROPERTY_USER_DATA_AND_DESTRUCTOR) {
Marko Mikulicic 0:c0ecb8bf28eb 19188 return p;
Marko Mikulicic 0:c0ecb8bf28eb 19189 }
Marko Mikulicic 0:c0ecb8bf28eb 19190 }
Marko Mikulicic 0:c0ecb8bf28eb 19191
Marko Mikulicic 0:c0ecb8bf28eb 19192 return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 19193 }
Marko Mikulicic 0:c0ecb8bf28eb 19194
Marko Mikulicic 0:c0ecb8bf28eb 19195 /*
Marko Mikulicic 0:c0ecb8bf28eb 19196 * Returns the user data property structure associated with obj, or NULL if
Marko Mikulicic 0:c0ecb8bf28eb 19197 * `obj` is not an object.
Marko Mikulicic 0:c0ecb8bf28eb 19198 */
Marko Mikulicic 0:c0ecb8bf28eb 19199 static struct v7_property *get_or_create_user_data_property(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 19200 v7_val_t obj) {
Marko Mikulicic 0:c0ecb8bf28eb 19201 struct v7_property *p = get_user_data_property(obj);
Marko Mikulicic 0:c0ecb8bf28eb 19202 struct v7_object *o;
Marko Mikulicic 0:c0ecb8bf28eb 19203
Marko Mikulicic 0:c0ecb8bf28eb 19204 if (p != NULL) return p;
Marko Mikulicic 0:c0ecb8bf28eb 19205
Marko Mikulicic 0:c0ecb8bf28eb 19206 if (!v7_is_object(obj)) return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 19207 o = get_object_struct(obj);
Marko Mikulicic 0:c0ecb8bf28eb 19208 v7_own(v7, &obj);
Marko Mikulicic 0:c0ecb8bf28eb 19209 p = v7_mk_property(v7);
Marko Mikulicic 0:c0ecb8bf28eb 19210 v7_disown(v7, &obj);
Marko Mikulicic 0:c0ecb8bf28eb 19211
Marko Mikulicic 0:c0ecb8bf28eb 19212 p->attributes |= _V7_PROPERTY_USER_DATA_AND_DESTRUCTOR | _V7_PROPERTY_HIDDEN;
Marko Mikulicic 0:c0ecb8bf28eb 19213
Marko Mikulicic 0:c0ecb8bf28eb 19214 p->next = o->properties;
Marko Mikulicic 0:c0ecb8bf28eb 19215 o->properties = p;
Marko Mikulicic 0:c0ecb8bf28eb 19216
Marko Mikulicic 0:c0ecb8bf28eb 19217 return p;
Marko Mikulicic 0:c0ecb8bf28eb 19218 }
Marko Mikulicic 0:c0ecb8bf28eb 19219
Marko Mikulicic 0:c0ecb8bf28eb 19220 void v7_set_user_data(struct v7 *v7, v7_val_t obj, void *ud) {
Marko Mikulicic 0:c0ecb8bf28eb 19221 struct v7_property *p = get_or_create_user_data_property(v7, obj);
Marko Mikulicic 0:c0ecb8bf28eb 19222 if (p == NULL) return;
Marko Mikulicic 0:c0ecb8bf28eb 19223 p->value = v7_mk_foreign(v7, ud);
Marko Mikulicic 0:c0ecb8bf28eb 19224 }
Marko Mikulicic 0:c0ecb8bf28eb 19225
Marko Mikulicic 0:c0ecb8bf28eb 19226 void *v7_get_user_data(struct v7 *v7, v7_val_t obj) {
Marko Mikulicic 0:c0ecb8bf28eb 19227 struct v7_property *p = get_user_data_property(obj);
Marko Mikulicic 0:c0ecb8bf28eb 19228 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 19229 if (p == NULL) return NULL;
Marko Mikulicic 0:c0ecb8bf28eb 19230 return v7_get_ptr(v7, p->value);
Marko Mikulicic 0:c0ecb8bf28eb 19231 }
Marko Mikulicic 0:c0ecb8bf28eb 19232
Marko Mikulicic 0:c0ecb8bf28eb 19233 void v7_set_destructor_cb(struct v7 *v7, v7_val_t obj, v7_destructor_cb_t *d) {
Marko Mikulicic 0:c0ecb8bf28eb 19234 struct v7_property *p = get_or_create_user_data_property(v7, obj);
Marko Mikulicic 0:c0ecb8bf28eb 19235 struct v7_object *o;
Marko Mikulicic 0:c0ecb8bf28eb 19236 union {
Marko Mikulicic 0:c0ecb8bf28eb 19237 void *v;
Marko Mikulicic 0:c0ecb8bf28eb 19238 v7_destructor_cb_t *f;
Marko Mikulicic 0:c0ecb8bf28eb 19239 } fu;
Marko Mikulicic 0:c0ecb8bf28eb 19240
Marko Mikulicic 0:c0ecb8bf28eb 19241 if (p == NULL) return;
Marko Mikulicic 0:c0ecb8bf28eb 19242
Marko Mikulicic 0:c0ecb8bf28eb 19243 o = get_object_struct(obj);
Marko Mikulicic 0:c0ecb8bf28eb 19244 if (d != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 19245 o->attributes |= V7_OBJ_HAS_DESTRUCTOR;
Marko Mikulicic 0:c0ecb8bf28eb 19246 fu.f = d;
Marko Mikulicic 0:c0ecb8bf28eb 19247 p->name = v7_mk_foreign(v7, fu.v);
Marko Mikulicic 0:c0ecb8bf28eb 19248 } else {
Marko Mikulicic 0:c0ecb8bf28eb 19249 o->attributes &= ~V7_OBJ_HAS_DESTRUCTOR;
Marko Mikulicic 0:c0ecb8bf28eb 19250 p->name = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 19251 }
Marko Mikulicic 0:c0ecb8bf28eb 19252 }
Marko Mikulicic 0:c0ecb8bf28eb 19253
Marko Mikulicic 0:c0ecb8bf28eb 19254 /* }}} Object prototypes */
Marko Mikulicic 0:c0ecb8bf28eb 19255 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 19256 #line 1 "v7/src/regexp.c"
Marko Mikulicic 0:c0ecb8bf28eb 19257 #endif
Marko Mikulicic 0:c0ecb8bf28eb 19258 /*
Marko Mikulicic 0:c0ecb8bf28eb 19259 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 19260 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 19261 */
Marko Mikulicic 0:c0ecb8bf28eb 19262
Marko Mikulicic 0:c0ecb8bf28eb 19263 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19264 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19265 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19266 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19267 /* Amalgamated: #include "v7/src/regexp.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19268 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19269 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19270 /* Amalgamated: #include "v7/src/slre.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19271
Marko Mikulicic 0:c0ecb8bf28eb 19272 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 19273 enum v7_err v7_mk_regexp(struct v7 *v7, const char *re, size_t re_len,
Marko Mikulicic 0:c0ecb8bf28eb 19274 const char *flags, size_t flags_len, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 19275 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 19276 struct slre_prog *p = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 19277 struct v7_regexp *rp;
Marko Mikulicic 0:c0ecb8bf28eb 19278
Marko Mikulicic 0:c0ecb8bf28eb 19279 if (re_len == ~((size_t) 0)) re_len = strlen(re);
Marko Mikulicic 0:c0ecb8bf28eb 19280
Marko Mikulicic 0:c0ecb8bf28eb 19281 if (slre_compile(re, re_len, flags, flags_len, &p, 1) != SLRE_OK ||
Marko Mikulicic 0:c0ecb8bf28eb 19282 p == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 19283 rcode = v7_throwf(v7, TYPE_ERROR, "Invalid regex");
Marko Mikulicic 0:c0ecb8bf28eb 19284 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19285 } else {
Marko Mikulicic 0:c0ecb8bf28eb 19286 *res = mk_object(v7, v7->vals.regexp_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 19287 rp = (struct v7_regexp *) malloc(sizeof(*rp));
Marko Mikulicic 0:c0ecb8bf28eb 19288 rp->regexp_string = v7_mk_string(v7, re, re_len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 19289 v7_own(v7, &rp->regexp_string);
Marko Mikulicic 0:c0ecb8bf28eb 19290 rp->compiled_regexp = p;
Marko Mikulicic 0:c0ecb8bf28eb 19291 rp->lastIndex = 0;
Marko Mikulicic 0:c0ecb8bf28eb 19292
Marko Mikulicic 0:c0ecb8bf28eb 19293 v7_def(v7, *res, "", 0, _V7_DESC_HIDDEN(1),
Marko Mikulicic 0:c0ecb8bf28eb 19294 pointer_to_value(rp) | V7_TAG_REGEXP);
Marko Mikulicic 0:c0ecb8bf28eb 19295 }
Marko Mikulicic 0:c0ecb8bf28eb 19296
Marko Mikulicic 0:c0ecb8bf28eb 19297 clean:
Marko Mikulicic 0:c0ecb8bf28eb 19298 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 19299 }
Marko Mikulicic 0:c0ecb8bf28eb 19300
Marko Mikulicic 0:c0ecb8bf28eb 19301 V7_PRIVATE struct v7_regexp *v7_get_regexp_struct(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 19302 struct v7_property *p;
Marko Mikulicic 0:c0ecb8bf28eb 19303 int is = v7_is_regexp(v7, v);
Marko Mikulicic 0:c0ecb8bf28eb 19304 (void) is;
Marko Mikulicic 0:c0ecb8bf28eb 19305 assert(is == 1);
Marko Mikulicic 0:c0ecb8bf28eb 19306 /* TODO(mkm): make regexp use user data API */
Marko Mikulicic 0:c0ecb8bf28eb 19307 p = v7_get_own_property2(v7, v, "", 0, _V7_PROPERTY_HIDDEN);
Marko Mikulicic 0:c0ecb8bf28eb 19308 assert(p != NULL);
Marko Mikulicic 0:c0ecb8bf28eb 19309 return (struct v7_regexp *) get_ptr(p->value);
Marko Mikulicic 0:c0ecb8bf28eb 19310 }
Marko Mikulicic 0:c0ecb8bf28eb 19311
Marko Mikulicic 0:c0ecb8bf28eb 19312 int v7_is_regexp(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 19313 struct v7_property *p;
Marko Mikulicic 0:c0ecb8bf28eb 19314 if (!v7_is_generic_object(v)) return 0;
Marko Mikulicic 0:c0ecb8bf28eb 19315 /* TODO(mkm): make regexp use user data API */
Marko Mikulicic 0:c0ecb8bf28eb 19316 p = v7_get_own_property2(v7, v, "", 0, _V7_PROPERTY_HIDDEN);
Marko Mikulicic 0:c0ecb8bf28eb 19317 if (p == NULL) return 0;
Marko Mikulicic 0:c0ecb8bf28eb 19318 return (p->value & V7_TAG_MASK) == V7_TAG_REGEXP;
Marko Mikulicic 0:c0ecb8bf28eb 19319 }
Marko Mikulicic 0:c0ecb8bf28eb 19320
Marko Mikulicic 0:c0ecb8bf28eb 19321 V7_PRIVATE size_t
Marko Mikulicic 0:c0ecb8bf28eb 19322 get_regexp_flags_str(struct v7 *v7, struct v7_regexp *rp, char *buf) {
Marko Mikulicic 0:c0ecb8bf28eb 19323 int re_flags = slre_get_flags(rp->compiled_regexp);
Marko Mikulicic 0:c0ecb8bf28eb 19324 size_t n = 0;
Marko Mikulicic 0:c0ecb8bf28eb 19325
Marko Mikulicic 0:c0ecb8bf28eb 19326 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 19327 if (re_flags & SLRE_FLAG_G) buf[n++] = 'g';
Marko Mikulicic 0:c0ecb8bf28eb 19328 if (re_flags & SLRE_FLAG_I) buf[n++] = 'i';
Marko Mikulicic 0:c0ecb8bf28eb 19329 if (re_flags & SLRE_FLAG_M) buf[n++] = 'm';
Marko Mikulicic 0:c0ecb8bf28eb 19330
Marko Mikulicic 0:c0ecb8bf28eb 19331 assert(n <= _V7_REGEXP_MAX_FLAGS_LEN);
Marko Mikulicic 0:c0ecb8bf28eb 19332
Marko Mikulicic 0:c0ecb8bf28eb 19333 return n;
Marko Mikulicic 0:c0ecb8bf28eb 19334 }
Marko Mikulicic 0:c0ecb8bf28eb 19335
Marko Mikulicic 0:c0ecb8bf28eb 19336 #else /* V7_ENABLE__RegExp */
Marko Mikulicic 0:c0ecb8bf28eb 19337
Marko Mikulicic 0:c0ecb8bf28eb 19338 /*
Marko Mikulicic 0:c0ecb8bf28eb 19339 * Dummy implementation when RegExp support is disabled: just return 0
Marko Mikulicic 0:c0ecb8bf28eb 19340 */
Marko Mikulicic 0:c0ecb8bf28eb 19341 int v7_is_regexp(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 19342 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 19343 (void) v;
Marko Mikulicic 0:c0ecb8bf28eb 19344 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 19345 }
Marko Mikulicic 0:c0ecb8bf28eb 19346
Marko Mikulicic 0:c0ecb8bf28eb 19347 #endif /* V7_ENABLE__RegExp */
Marko Mikulicic 0:c0ecb8bf28eb 19348 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 19349 #line 1 "v7/src/exceptions.c"
Marko Mikulicic 0:c0ecb8bf28eb 19350 #endif
Marko Mikulicic 0:c0ecb8bf28eb 19351 /*
Marko Mikulicic 0:c0ecb8bf28eb 19352 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 19353 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 19354 */
Marko Mikulicic 0:c0ecb8bf28eb 19355
Marko Mikulicic 0:c0ecb8bf28eb 19356 /* Amalgamated: #include "common/str_util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19357 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19358 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19359 /* Amalgamated: #include "v7/src/array.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19360 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19361 /* Amalgamated: #include "v7/src/eval.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19362 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19363
Marko Mikulicic 0:c0ecb8bf28eb 19364 enum v7_err v7_throw(struct v7 *v7, v7_val_t val) {
Marko Mikulicic 0:c0ecb8bf28eb 19365 v7->vals.thrown_error = val;
Marko Mikulicic 0:c0ecb8bf28eb 19366 v7->is_thrown = 1;
Marko Mikulicic 0:c0ecb8bf28eb 19367 return V7_EXEC_EXCEPTION;
Marko Mikulicic 0:c0ecb8bf28eb 19368 }
Marko Mikulicic 0:c0ecb8bf28eb 19369
Marko Mikulicic 0:c0ecb8bf28eb 19370 void v7_clear_thrown_value(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 19371 v7->vals.thrown_error = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 19372 v7->is_thrown = 0;
Marko Mikulicic 0:c0ecb8bf28eb 19373 }
Marko Mikulicic 0:c0ecb8bf28eb 19374
Marko Mikulicic 0:c0ecb8bf28eb 19375 enum v7_err v7_throwf(struct v7 *v7, const char *typ, const char *err_fmt,
Marko Mikulicic 0:c0ecb8bf28eb 19376 ...) {
Marko Mikulicic 0:c0ecb8bf28eb 19377 /* TODO(dfrank) : get rid of v7->error_msg, allocate mem right here */
Marko Mikulicic 0:c0ecb8bf28eb 19378 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 19379 va_list ap;
Marko Mikulicic 0:c0ecb8bf28eb 19380 val_t e = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 19381 va_start(ap, err_fmt);
Marko Mikulicic 0:c0ecb8bf28eb 19382 c_vsnprintf(v7->error_msg, sizeof(v7->error_msg), err_fmt, ap);
Marko Mikulicic 0:c0ecb8bf28eb 19383 va_end(ap);
Marko Mikulicic 0:c0ecb8bf28eb 19384
Marko Mikulicic 0:c0ecb8bf28eb 19385 v7_own(v7, &e);
Marko Mikulicic 0:c0ecb8bf28eb 19386 rcode = create_exception(v7, typ, v7->error_msg, &e);
Marko Mikulicic 0:c0ecb8bf28eb 19387 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 19388 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19389 }
Marko Mikulicic 0:c0ecb8bf28eb 19390
Marko Mikulicic 0:c0ecb8bf28eb 19391 rcode = v7_throw(v7, e);
Marko Mikulicic 0:c0ecb8bf28eb 19392
Marko Mikulicic 0:c0ecb8bf28eb 19393 clean:
Marko Mikulicic 0:c0ecb8bf28eb 19394 v7_disown(v7, &e);
Marko Mikulicic 0:c0ecb8bf28eb 19395 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 19396 }
Marko Mikulicic 0:c0ecb8bf28eb 19397
Marko Mikulicic 0:c0ecb8bf28eb 19398 enum v7_err v7_rethrow(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 19399 assert(v7->is_thrown);
Marko Mikulicic 0:c0ecb8bf28eb 19400 #ifdef NDEBUG
Marko Mikulicic 0:c0ecb8bf28eb 19401 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 19402 #endif
Marko Mikulicic 0:c0ecb8bf28eb 19403 return V7_EXEC_EXCEPTION;
Marko Mikulicic 0:c0ecb8bf28eb 19404 }
Marko Mikulicic 0:c0ecb8bf28eb 19405
Marko Mikulicic 0:c0ecb8bf28eb 19406 v7_val_t v7_get_thrown_value(struct v7 *v7, uint8_t *is_thrown) {
Marko Mikulicic 0:c0ecb8bf28eb 19407 if (is_thrown != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 19408 *is_thrown = v7->is_thrown;
Marko Mikulicic 0:c0ecb8bf28eb 19409 }
Marko Mikulicic 0:c0ecb8bf28eb 19410 return v7->vals.thrown_error;
Marko Mikulicic 0:c0ecb8bf28eb 19411 }
Marko Mikulicic 0:c0ecb8bf28eb 19412
Marko Mikulicic 0:c0ecb8bf28eb 19413 /*
Marko Mikulicic 0:c0ecb8bf28eb 19414 * Create an instance of the exception with type `typ` (see `TYPE_ERROR`,
Marko Mikulicic 0:c0ecb8bf28eb 19415 * `SYNTAX_ERROR`, etc) and message `msg`.
Marko Mikulicic 0:c0ecb8bf28eb 19416 */
Marko Mikulicic 0:c0ecb8bf28eb 19417 V7_PRIVATE enum v7_err create_exception(struct v7 *v7, const char *typ,
Marko Mikulicic 0:c0ecb8bf28eb 19418 const char *msg, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 19419 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 19420 uint8_t saved_creating_exception = v7->creating_exception;
Marko Mikulicic 0:c0ecb8bf28eb 19421 val_t ctor_args = V7_UNDEFINED, ctor_func = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 19422 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 19423 assert(v7_is_undefined(v7->vals.thrown_error));
Marko Mikulicic 0:c0ecb8bf28eb 19424 #endif
Marko Mikulicic 0:c0ecb8bf28eb 19425
Marko Mikulicic 0:c0ecb8bf28eb 19426 *res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 19427
Marko Mikulicic 0:c0ecb8bf28eb 19428 v7_own(v7, &ctor_args);
Marko Mikulicic 0:c0ecb8bf28eb 19429 v7_own(v7, &ctor_func);
Marko Mikulicic 0:c0ecb8bf28eb 19430
Marko Mikulicic 0:c0ecb8bf28eb 19431 if (v7->creating_exception) {
Marko Mikulicic 0:c0ecb8bf28eb 19432 #ifndef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 19433 fprintf(stderr, "Exception creation throws an exception %s: %s\n", typ,
Marko Mikulicic 0:c0ecb8bf28eb 19434 msg);
Marko Mikulicic 0:c0ecb8bf28eb 19435 #endif
Marko Mikulicic 0:c0ecb8bf28eb 19436 } else {
Marko Mikulicic 0:c0ecb8bf28eb 19437 v7->creating_exception = 1;
Marko Mikulicic 0:c0ecb8bf28eb 19438
Marko Mikulicic 0:c0ecb8bf28eb 19439 /* Prepare arguments for the `Error` constructor */
Marko Mikulicic 0:c0ecb8bf28eb 19440 ctor_args = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 19441 v7_array_set(v7, ctor_args, 0, v7_mk_string(v7, msg, strlen(msg), 1));
Marko Mikulicic 0:c0ecb8bf28eb 19442
Marko Mikulicic 0:c0ecb8bf28eb 19443 /* Get constructor for the given error `typ` */
Marko Mikulicic 0:c0ecb8bf28eb 19444 ctor_func = v7_get(v7, v7->vals.global_object, typ, ~0);
Marko Mikulicic 0:c0ecb8bf28eb 19445 if (v7_is_undefined(ctor_func)) {
Marko Mikulicic 0:c0ecb8bf28eb 19446 fprintf(stderr, "cannot find exception %s\n", typ);
Marko Mikulicic 0:c0ecb8bf28eb 19447 }
Marko Mikulicic 0:c0ecb8bf28eb 19448
Marko Mikulicic 0:c0ecb8bf28eb 19449 /* Create an error object, with prototype from constructor function */
Marko Mikulicic 0:c0ecb8bf28eb 19450 *res = mk_object(v7, v7_get(v7, ctor_func, "prototype", 9));
Marko Mikulicic 0:c0ecb8bf28eb 19451
Marko Mikulicic 0:c0ecb8bf28eb 19452 /*
Marko Mikulicic 0:c0ecb8bf28eb 19453 * Finally, call the error constructor, passing an error object as `this`
Marko Mikulicic 0:c0ecb8bf28eb 19454 */
Marko Mikulicic 0:c0ecb8bf28eb 19455 V7_TRY(b_apply(v7, ctor_func, *res, ctor_args, 0, NULL));
Marko Mikulicic 0:c0ecb8bf28eb 19456 }
Marko Mikulicic 0:c0ecb8bf28eb 19457
Marko Mikulicic 0:c0ecb8bf28eb 19458 clean:
Marko Mikulicic 0:c0ecb8bf28eb 19459 v7->creating_exception = saved_creating_exception;
Marko Mikulicic 0:c0ecb8bf28eb 19460
Marko Mikulicic 0:c0ecb8bf28eb 19461 v7_disown(v7, &ctor_func);
Marko Mikulicic 0:c0ecb8bf28eb 19462 v7_disown(v7, &ctor_args);
Marko Mikulicic 0:c0ecb8bf28eb 19463
Marko Mikulicic 0:c0ecb8bf28eb 19464 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 19465 }
Marko Mikulicic 0:c0ecb8bf28eb 19466 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 19467 #line 1 "v7/src/conversion.c"
Marko Mikulicic 0:c0ecb8bf28eb 19468 #endif
Marko Mikulicic 0:c0ecb8bf28eb 19469 /*
Marko Mikulicic 0:c0ecb8bf28eb 19470 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 19471 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 19472 */
Marko Mikulicic 0:c0ecb8bf28eb 19473
Marko Mikulicic 0:c0ecb8bf28eb 19474 /* Amalgamated: #include "common/cs_strtod.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19475 /* Amalgamated: #include "common/str_util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19476
Marko Mikulicic 0:c0ecb8bf28eb 19477 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19478 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19479 /* Amalgamated: #include "v7/src/util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19480 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19481 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19482 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19483 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19484 /* Amalgamated: #include "v7/src/eval.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19485 /* Amalgamated: #include "v7/src/gc.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19486 /* Amalgamated: #include "v7/src/array.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19487 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 19488
Marko Mikulicic 0:c0ecb8bf28eb 19489 static void save_val(struct v7 *v7, const char *str, size_t str_len,
Marko Mikulicic 0:c0ecb8bf28eb 19490 val_t *dst_v, char *dst, size_t dst_size, int wanted_len,
Marko Mikulicic 0:c0ecb8bf28eb 19491 size_t *res_wanted_len) {
Marko Mikulicic 0:c0ecb8bf28eb 19492 if (dst_v != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 19493 *dst_v = v7_mk_string(v7, str, str_len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 19494 }
Marko Mikulicic 0:c0ecb8bf28eb 19495
Marko Mikulicic 0:c0ecb8bf28eb 19496 if (dst != NULL && dst_size > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 19497 size_t size = str_len + 1 /*null-term*/;
Marko Mikulicic 0:c0ecb8bf28eb 19498 if (size > dst_size) {
Marko Mikulicic 0:c0ecb8bf28eb 19499 size = dst_size;
Marko Mikulicic 0:c0ecb8bf28eb 19500 }
Marko Mikulicic 0:c0ecb8bf28eb 19501 memcpy(dst, str, size);
Marko Mikulicic 0:c0ecb8bf28eb 19502
Marko Mikulicic 0:c0ecb8bf28eb 19503 /* make sure we have null-term */
Marko Mikulicic 0:c0ecb8bf28eb 19504 dst[dst_size - 1] = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 19505 }
Marko Mikulicic 0:c0ecb8bf28eb 19506
Marko Mikulicic 0:c0ecb8bf28eb 19507 if (res_wanted_len != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 19508 *res_wanted_len = (wanted_len >= 0) ? (size_t) wanted_len : str_len;
Marko Mikulicic 0:c0ecb8bf28eb 19509 }
Marko Mikulicic 0:c0ecb8bf28eb 19510 }
Marko Mikulicic 0:c0ecb8bf28eb 19511
Marko Mikulicic 0:c0ecb8bf28eb 19512 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 19513 V7_PRIVATE enum v7_err primitive_to_str(struct v7 *v7, val_t v, val_t *res,
Marko Mikulicic 0:c0ecb8bf28eb 19514 char *buf, size_t buf_size,
Marko Mikulicic 0:c0ecb8bf28eb 19515 size_t *res_len) {
Marko Mikulicic 0:c0ecb8bf28eb 19516 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 19517 char tmp_buf[25];
Marko Mikulicic 0:c0ecb8bf28eb 19518 double num;
Marko Mikulicic 0:c0ecb8bf28eb 19519 size_t wanted_len;
Marko Mikulicic 0:c0ecb8bf28eb 19520
Marko Mikulicic 0:c0ecb8bf28eb 19521 assert(!v7_is_object(v));
Marko Mikulicic 0:c0ecb8bf28eb 19522
Marko Mikulicic 0:c0ecb8bf28eb 19523 memset(tmp_buf, 0x00, sizeof(tmp_buf));
Marko Mikulicic 0:c0ecb8bf28eb 19524
Marko Mikulicic 0:c0ecb8bf28eb 19525 v7_own(v7, &v);
Marko Mikulicic 0:c0ecb8bf28eb 19526
Marko Mikulicic 0:c0ecb8bf28eb 19527 switch (val_type(v7, v)) {
Marko Mikulicic 0:c0ecb8bf28eb 19528 case V7_TYPE_STRING: {
Marko Mikulicic 0:c0ecb8bf28eb 19529 /* if `res` provided, set it to source value */
Marko Mikulicic 0:c0ecb8bf28eb 19530 if (res != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 19531 *res = v;
Marko Mikulicic 0:c0ecb8bf28eb 19532 }
Marko Mikulicic 0:c0ecb8bf28eb 19533
Marko Mikulicic 0:c0ecb8bf28eb 19534 /* if buf provided, copy string data there */
Marko Mikulicic 0:c0ecb8bf28eb 19535 if (buf != NULL && buf_size > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 19536 size_t size;
Marko Mikulicic 0:c0ecb8bf28eb 19537 const char *str = v7_get_string(v7, &v, &size);
Marko Mikulicic 0:c0ecb8bf28eb 19538 size += 1 /*null-term*/;
Marko Mikulicic 0:c0ecb8bf28eb 19539
Marko Mikulicic 0:c0ecb8bf28eb 19540 if (size > buf_size) {
Marko Mikulicic 0:c0ecb8bf28eb 19541 size = buf_size;
Marko Mikulicic 0:c0ecb8bf28eb 19542 }
Marko Mikulicic 0:c0ecb8bf28eb 19543
Marko Mikulicic 0:c0ecb8bf28eb 19544 memcpy(buf, str, size);
Marko Mikulicic 0:c0ecb8bf28eb 19545
Marko Mikulicic 0:c0ecb8bf28eb 19546 /* make sure we have a null-term */
Marko Mikulicic 0:c0ecb8bf28eb 19547 buf[buf_size - 1] = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 19548 }
Marko Mikulicic 0:c0ecb8bf28eb 19549
Marko Mikulicic 0:c0ecb8bf28eb 19550 if (res_len != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 19551 v7_get_string(v7, &v, res_len);
Marko Mikulicic 0:c0ecb8bf28eb 19552 }
Marko Mikulicic 0:c0ecb8bf28eb 19553
Marko Mikulicic 0:c0ecb8bf28eb 19554 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19555 }
Marko Mikulicic 0:c0ecb8bf28eb 19556 case V7_TYPE_NULL:
Marko Mikulicic 0:c0ecb8bf28eb 19557 strncpy(tmp_buf, "null", sizeof(tmp_buf) - 1);
Marko Mikulicic 0:c0ecb8bf28eb 19558 save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, -1, res_len);
Marko Mikulicic 0:c0ecb8bf28eb 19559 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19560 case V7_TYPE_UNDEFINED:
Marko Mikulicic 0:c0ecb8bf28eb 19561 strncpy(tmp_buf, "undefined", sizeof(tmp_buf) - 1);
Marko Mikulicic 0:c0ecb8bf28eb 19562 save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, -1, res_len);
Marko Mikulicic 0:c0ecb8bf28eb 19563 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19564 case V7_TYPE_BOOLEAN:
Marko Mikulicic 0:c0ecb8bf28eb 19565 if (v7_get_bool(v7, v)) {
Marko Mikulicic 0:c0ecb8bf28eb 19566 strncpy(tmp_buf, "true", sizeof(tmp_buf) - 1);
Marko Mikulicic 0:c0ecb8bf28eb 19567 save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, -1, res_len);
Marko Mikulicic 0:c0ecb8bf28eb 19568 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19569 } else {
Marko Mikulicic 0:c0ecb8bf28eb 19570 strncpy(tmp_buf, "false", sizeof(tmp_buf) - 1);
Marko Mikulicic 0:c0ecb8bf28eb 19571 save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, -1, res_len);
Marko Mikulicic 0:c0ecb8bf28eb 19572 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19573 }
Marko Mikulicic 0:c0ecb8bf28eb 19574 case V7_TYPE_NUMBER:
Marko Mikulicic 0:c0ecb8bf28eb 19575 if (v == V7_TAG_NAN) {
Marko Mikulicic 0:c0ecb8bf28eb 19576 strncpy(tmp_buf, "NaN", sizeof(tmp_buf) - 1);
Marko Mikulicic 0:c0ecb8bf28eb 19577 save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, -1, res_len);
Marko Mikulicic 0:c0ecb8bf28eb 19578 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19579 }
Marko Mikulicic 0:c0ecb8bf28eb 19580 num = v7_get_double(v7, v);
Marko Mikulicic 0:c0ecb8bf28eb 19581 if (isinf(num)) {
Marko Mikulicic 0:c0ecb8bf28eb 19582 if (num < 0.0) {
Marko Mikulicic 0:c0ecb8bf28eb 19583 strncpy(tmp_buf, "-Infinity", sizeof(tmp_buf) - 1);
Marko Mikulicic 0:c0ecb8bf28eb 19584 } else {
Marko Mikulicic 0:c0ecb8bf28eb 19585 strncpy(tmp_buf, "Infinity", sizeof(tmp_buf) - 1);
Marko Mikulicic 0:c0ecb8bf28eb 19586 }
Marko Mikulicic 0:c0ecb8bf28eb 19587 save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, -1, res_len);
Marko Mikulicic 0:c0ecb8bf28eb 19588 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19589 }
Marko Mikulicic 0:c0ecb8bf28eb 19590 {
Marko Mikulicic 0:c0ecb8bf28eb 19591 const char *fmt = num > 1e10 ? "%.21g" : "%.10g";
Marko Mikulicic 0:c0ecb8bf28eb 19592 wanted_len = snprintf(tmp_buf, sizeof(tmp_buf), fmt, num);
Marko Mikulicic 0:c0ecb8bf28eb 19593 save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, wanted_len,
Marko Mikulicic 0:c0ecb8bf28eb 19594 res_len);
Marko Mikulicic 0:c0ecb8bf28eb 19595 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19596 }
Marko Mikulicic 0:c0ecb8bf28eb 19597 case V7_TYPE_CFUNCTION:
Marko Mikulicic 0:c0ecb8bf28eb 19598 #ifdef V7_UNIT_TEST
Marko Mikulicic 0:c0ecb8bf28eb 19599 wanted_len = c_snprintf(tmp_buf, sizeof(tmp_buf), "cfunc_xxxxxx");
Marko Mikulicic 0:c0ecb8bf28eb 19600 save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, wanted_len,
Marko Mikulicic 0:c0ecb8bf28eb 19601 res_len);
Marko Mikulicic 0:c0ecb8bf28eb 19602 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19603 #else
Marko Mikulicic 0:c0ecb8bf28eb 19604 wanted_len = c_snprintf(tmp_buf, sizeof(tmp_buf), "cfunc_%p", get_ptr(v));
Marko Mikulicic 0:c0ecb8bf28eb 19605 save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, wanted_len,
Marko Mikulicic 0:c0ecb8bf28eb 19606 res_len);
Marko Mikulicic 0:c0ecb8bf28eb 19607 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19608 #endif
Marko Mikulicic 0:c0ecb8bf28eb 19609 case V7_TYPE_FOREIGN:
Marko Mikulicic 0:c0ecb8bf28eb 19610 wanted_len = c_snprintf(tmp_buf, sizeof(tmp_buf), "[foreign_%p]",
Marko Mikulicic 0:c0ecb8bf28eb 19611 v7_get_ptr(v7, v));
Marko Mikulicic 0:c0ecb8bf28eb 19612 save_val(v7, tmp_buf, strlen(tmp_buf), res, buf, buf_size, wanted_len,
Marko Mikulicic 0:c0ecb8bf28eb 19613 res_len);
Marko Mikulicic 0:c0ecb8bf28eb 19614 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19615 default:
Marko Mikulicic 0:c0ecb8bf28eb 19616 abort();
Marko Mikulicic 0:c0ecb8bf28eb 19617 }
Marko Mikulicic 0:c0ecb8bf28eb 19618
Marko Mikulicic 0:c0ecb8bf28eb 19619 clean:
Marko Mikulicic 0:c0ecb8bf28eb 19620
Marko Mikulicic 0:c0ecb8bf28eb 19621 v7_disown(v7, &v);
Marko Mikulicic 0:c0ecb8bf28eb 19622 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 19623 }
Marko Mikulicic 0:c0ecb8bf28eb 19624
Marko Mikulicic 0:c0ecb8bf28eb 19625 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 19626 V7_PRIVATE enum v7_err primitive_to_number(struct v7 *v7, val_t v, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 19627 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 19628
Marko Mikulicic 0:c0ecb8bf28eb 19629 assert(!v7_is_object(v));
Marko Mikulicic 0:c0ecb8bf28eb 19630
Marko Mikulicic 0:c0ecb8bf28eb 19631 *res = v;
Marko Mikulicic 0:c0ecb8bf28eb 19632
Marko Mikulicic 0:c0ecb8bf28eb 19633 if (v7_is_number(*res)) {
Marko Mikulicic 0:c0ecb8bf28eb 19634 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19635 }
Marko Mikulicic 0:c0ecb8bf28eb 19636
Marko Mikulicic 0:c0ecb8bf28eb 19637 if (v7_is_undefined(*res)) {
Marko Mikulicic 0:c0ecb8bf28eb 19638 *res = V7_TAG_NAN;
Marko Mikulicic 0:c0ecb8bf28eb 19639 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19640 }
Marko Mikulicic 0:c0ecb8bf28eb 19641
Marko Mikulicic 0:c0ecb8bf28eb 19642 if (v7_is_null(*res)) {
Marko Mikulicic 0:c0ecb8bf28eb 19643 *res = v7_mk_number(v7, 0.0);
Marko Mikulicic 0:c0ecb8bf28eb 19644 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19645 }
Marko Mikulicic 0:c0ecb8bf28eb 19646
Marko Mikulicic 0:c0ecb8bf28eb 19647 if (v7_is_boolean(*res)) {
Marko Mikulicic 0:c0ecb8bf28eb 19648 *res = v7_mk_number(v7, !!v7_get_bool(v7, v));
Marko Mikulicic 0:c0ecb8bf28eb 19649 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19650 }
Marko Mikulicic 0:c0ecb8bf28eb 19651
Marko Mikulicic 0:c0ecb8bf28eb 19652 if (is_cfunction_lite(*res)) {
Marko Mikulicic 0:c0ecb8bf28eb 19653 *res = v7_mk_number(v7, 0.0);
Marko Mikulicic 0:c0ecb8bf28eb 19654 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19655 }
Marko Mikulicic 0:c0ecb8bf28eb 19656
Marko Mikulicic 0:c0ecb8bf28eb 19657 if (v7_is_string(*res)) {
Marko Mikulicic 0:c0ecb8bf28eb 19658 double d;
Marko Mikulicic 0:c0ecb8bf28eb 19659 size_t n;
Marko Mikulicic 0:c0ecb8bf28eb 19660 char *e, *s = (char *) v7_get_string(v7, res, &n);
Marko Mikulicic 0:c0ecb8bf28eb 19661 if (n != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 19662 d = cs_strtod(s, &e);
Marko Mikulicic 0:c0ecb8bf28eb 19663 if (e - n != s) {
Marko Mikulicic 0:c0ecb8bf28eb 19664 d = NAN;
Marko Mikulicic 0:c0ecb8bf28eb 19665 }
Marko Mikulicic 0:c0ecb8bf28eb 19666 } else {
Marko Mikulicic 0:c0ecb8bf28eb 19667 /* empty string: convert to 0 */
Marko Mikulicic 0:c0ecb8bf28eb 19668 d = 0.0;
Marko Mikulicic 0:c0ecb8bf28eb 19669 }
Marko Mikulicic 0:c0ecb8bf28eb 19670 *res = v7_mk_number(v7, d);
Marko Mikulicic 0:c0ecb8bf28eb 19671 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19672 }
Marko Mikulicic 0:c0ecb8bf28eb 19673
Marko Mikulicic 0:c0ecb8bf28eb 19674 assert(0);
Marko Mikulicic 0:c0ecb8bf28eb 19675
Marko Mikulicic 0:c0ecb8bf28eb 19676 clean:
Marko Mikulicic 0:c0ecb8bf28eb 19677 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 19678 }
Marko Mikulicic 0:c0ecb8bf28eb 19679
Marko Mikulicic 0:c0ecb8bf28eb 19680 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 19681 enum v7_err to_primitive(struct v7 *v7, val_t v, enum to_primitive_hint hint,
Marko Mikulicic 0:c0ecb8bf28eb 19682 val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 19683 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 19684 enum v7_err (*p_func)(struct v7 *v7, val_t v, val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 19685
Marko Mikulicic 0:c0ecb8bf28eb 19686 v7_own(v7, &v);
Marko Mikulicic 0:c0ecb8bf28eb 19687
Marko Mikulicic 0:c0ecb8bf28eb 19688 *res = v;
Marko Mikulicic 0:c0ecb8bf28eb 19689
Marko Mikulicic 0:c0ecb8bf28eb 19690 /*
Marko Mikulicic 0:c0ecb8bf28eb 19691 * If given value is an object, try to convert it to string by calling first
Marko Mikulicic 0:c0ecb8bf28eb 19692 * preferred function (`toString()` or `valueOf()`, depending on the `hint`
Marko Mikulicic 0:c0ecb8bf28eb 19693 * argument)
Marko Mikulicic 0:c0ecb8bf28eb 19694 */
Marko Mikulicic 0:c0ecb8bf28eb 19695 if (v7_is_object(*res)) {
Marko Mikulicic 0:c0ecb8bf28eb 19696 /* Handle special case for Date object */
Marko Mikulicic 0:c0ecb8bf28eb 19697 if (hint == V7_TO_PRIMITIVE_HINT_AUTO) {
Marko Mikulicic 0:c0ecb8bf28eb 19698 hint = (v7_get_proto(v7, *res) == v7->vals.date_prototype)
Marko Mikulicic 0:c0ecb8bf28eb 19699 ? V7_TO_PRIMITIVE_HINT_STRING
Marko Mikulicic 0:c0ecb8bf28eb 19700 : V7_TO_PRIMITIVE_HINT_NUMBER;
Marko Mikulicic 0:c0ecb8bf28eb 19701 }
Marko Mikulicic 0:c0ecb8bf28eb 19702
Marko Mikulicic 0:c0ecb8bf28eb 19703 p_func =
Marko Mikulicic 0:c0ecb8bf28eb 19704 (hint == V7_TO_PRIMITIVE_HINT_NUMBER) ? obj_value_of : obj_to_string;
Marko Mikulicic 0:c0ecb8bf28eb 19705 rcode = p_func(v7, *res, res);
Marko Mikulicic 0:c0ecb8bf28eb 19706 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 19707 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19708 }
Marko Mikulicic 0:c0ecb8bf28eb 19709
Marko Mikulicic 0:c0ecb8bf28eb 19710 /*
Marko Mikulicic 0:c0ecb8bf28eb 19711 * If returned value is still an object, get original argument value
Marko Mikulicic 0:c0ecb8bf28eb 19712 */
Marko Mikulicic 0:c0ecb8bf28eb 19713 if (v7_is_object(*res)) {
Marko Mikulicic 0:c0ecb8bf28eb 19714 *res = v;
Marko Mikulicic 0:c0ecb8bf28eb 19715 }
Marko Mikulicic 0:c0ecb8bf28eb 19716 }
Marko Mikulicic 0:c0ecb8bf28eb 19717
Marko Mikulicic 0:c0ecb8bf28eb 19718 /*
Marko Mikulicic 0:c0ecb8bf28eb 19719 * If the value is still an object, try to call second function (`valueOf()`
Marko Mikulicic 0:c0ecb8bf28eb 19720 * or `toString()`)
Marko Mikulicic 0:c0ecb8bf28eb 19721 */
Marko Mikulicic 0:c0ecb8bf28eb 19722 if (v7_is_object(*res)) {
Marko Mikulicic 0:c0ecb8bf28eb 19723 p_func =
Marko Mikulicic 0:c0ecb8bf28eb 19724 (hint == V7_TO_PRIMITIVE_HINT_NUMBER) ? obj_to_string : obj_value_of;
Marko Mikulicic 0:c0ecb8bf28eb 19725 rcode = p_func(v7, *res, res);
Marko Mikulicic 0:c0ecb8bf28eb 19726 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 19727 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19728 }
Marko Mikulicic 0:c0ecb8bf28eb 19729 }
Marko Mikulicic 0:c0ecb8bf28eb 19730
Marko Mikulicic 0:c0ecb8bf28eb 19731 /*
Marko Mikulicic 0:c0ecb8bf28eb 19732 * If the value is still an object, then throw.
Marko Mikulicic 0:c0ecb8bf28eb 19733 */
Marko Mikulicic 0:c0ecb8bf28eb 19734 if (v7_is_object(*res)) {
Marko Mikulicic 0:c0ecb8bf28eb 19735 rcode =
Marko Mikulicic 0:c0ecb8bf28eb 19736 v7_throwf(v7, TYPE_ERROR, "Cannot convert object to primitive value");
Marko Mikulicic 0:c0ecb8bf28eb 19737 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19738 }
Marko Mikulicic 0:c0ecb8bf28eb 19739
Marko Mikulicic 0:c0ecb8bf28eb 19740 clean:
Marko Mikulicic 0:c0ecb8bf28eb 19741 v7_disown(v7, &v);
Marko Mikulicic 0:c0ecb8bf28eb 19742 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 19743 }
Marko Mikulicic 0:c0ecb8bf28eb 19744
Marko Mikulicic 0:c0ecb8bf28eb 19745 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 19746 V7_PRIVATE enum v7_err to_string(struct v7 *v7, val_t v, val_t *res, char *buf,
Marko Mikulicic 0:c0ecb8bf28eb 19747 size_t buf_size, size_t *res_len) {
Marko Mikulicic 0:c0ecb8bf28eb 19748 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 19749
Marko Mikulicic 0:c0ecb8bf28eb 19750 v7_own(v7, &v);
Marko Mikulicic 0:c0ecb8bf28eb 19751
Marko Mikulicic 0:c0ecb8bf28eb 19752 /*
Marko Mikulicic 0:c0ecb8bf28eb 19753 * Convert value to primitive if needed, calling `toString()` first
Marko Mikulicic 0:c0ecb8bf28eb 19754 */
Marko Mikulicic 0:c0ecb8bf28eb 19755 V7_TRY(to_primitive(v7, v, V7_TO_PRIMITIVE_HINT_STRING, &v));
Marko Mikulicic 0:c0ecb8bf28eb 19756
Marko Mikulicic 0:c0ecb8bf28eb 19757 /*
Marko Mikulicic 0:c0ecb8bf28eb 19758 * Now, we're guaranteed to have a primitive here. Convert it to string.
Marko Mikulicic 0:c0ecb8bf28eb 19759 */
Marko Mikulicic 0:c0ecb8bf28eb 19760 V7_TRY(primitive_to_str(v7, v, res, buf, buf_size, res_len));
Marko Mikulicic 0:c0ecb8bf28eb 19761
Marko Mikulicic 0:c0ecb8bf28eb 19762 clean:
Marko Mikulicic 0:c0ecb8bf28eb 19763 v7_disown(v7, &v);
Marko Mikulicic 0:c0ecb8bf28eb 19764 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 19765 }
Marko Mikulicic 0:c0ecb8bf28eb 19766
Marko Mikulicic 0:c0ecb8bf28eb 19767 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 19768 V7_PRIVATE enum v7_err to_number_v(struct v7 *v7, val_t v, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 19769 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 19770
Marko Mikulicic 0:c0ecb8bf28eb 19771 *res = v;
Marko Mikulicic 0:c0ecb8bf28eb 19772
Marko Mikulicic 0:c0ecb8bf28eb 19773 /*
Marko Mikulicic 0:c0ecb8bf28eb 19774 * Convert value to primitive if needed, calling `valueOf()` first
Marko Mikulicic 0:c0ecb8bf28eb 19775 */
Marko Mikulicic 0:c0ecb8bf28eb 19776 rcode = to_primitive(v7, *res, V7_TO_PRIMITIVE_HINT_NUMBER, res);
Marko Mikulicic 0:c0ecb8bf28eb 19777 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 19778 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19779 }
Marko Mikulicic 0:c0ecb8bf28eb 19780
Marko Mikulicic 0:c0ecb8bf28eb 19781 /*
Marko Mikulicic 0:c0ecb8bf28eb 19782 * Now, we're guaranteed to have a primitive here. Convert it to number.
Marko Mikulicic 0:c0ecb8bf28eb 19783 */
Marko Mikulicic 0:c0ecb8bf28eb 19784 rcode = primitive_to_number(v7, *res, res);
Marko Mikulicic 0:c0ecb8bf28eb 19785 if (rcode != V7_OK) {
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 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 19791 }
Marko Mikulicic 0:c0ecb8bf28eb 19792
Marko Mikulicic 0:c0ecb8bf28eb 19793 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 19794 V7_PRIVATE enum v7_err to_long(struct v7 *v7, val_t v, long default_value,
Marko Mikulicic 0:c0ecb8bf28eb 19795 long *res) {
Marko Mikulicic 0:c0ecb8bf28eb 19796 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 19797 double d;
Marko Mikulicic 0:c0ecb8bf28eb 19798
Marko Mikulicic 0:c0ecb8bf28eb 19799 /* if value is `undefined`, just return `default_value` */
Marko Mikulicic 0:c0ecb8bf28eb 19800 if (v7_is_undefined(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 19801 *res = default_value;
Marko Mikulicic 0:c0ecb8bf28eb 19802 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19803 }
Marko Mikulicic 0:c0ecb8bf28eb 19804
Marko Mikulicic 0:c0ecb8bf28eb 19805 /* Try to convert value to number */
Marko Mikulicic 0:c0ecb8bf28eb 19806 rcode = to_number_v(v7, v, &v);
Marko Mikulicic 0:c0ecb8bf28eb 19807 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 19808 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19809 }
Marko Mikulicic 0:c0ecb8bf28eb 19810
Marko Mikulicic 0:c0ecb8bf28eb 19811 /*
Marko Mikulicic 0:c0ecb8bf28eb 19812 * Conversion to number succeeded, so, convert it to long
Marko Mikulicic 0:c0ecb8bf28eb 19813 */
Marko Mikulicic 0:c0ecb8bf28eb 19814
Marko Mikulicic 0:c0ecb8bf28eb 19815 d = v7_get_double(v7, v);
Marko Mikulicic 0:c0ecb8bf28eb 19816 /* We want to return LONG_MAX if d is positive Inf, thus d < 0 check */
Marko Mikulicic 0:c0ecb8bf28eb 19817 if (isnan(d) || (isinf(d) && d < 0)) {
Marko Mikulicic 0:c0ecb8bf28eb 19818 *res = 0;
Marko Mikulicic 0:c0ecb8bf28eb 19819 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19820 } else if (d > LONG_MAX) {
Marko Mikulicic 0:c0ecb8bf28eb 19821 *res = LONG_MAX;
Marko Mikulicic 0:c0ecb8bf28eb 19822 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19823 }
Marko Mikulicic 0:c0ecb8bf28eb 19824 *res = (long) d;
Marko Mikulicic 0:c0ecb8bf28eb 19825 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19826
Marko Mikulicic 0:c0ecb8bf28eb 19827 clean:
Marko Mikulicic 0:c0ecb8bf28eb 19828 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 19829 }
Marko Mikulicic 0:c0ecb8bf28eb 19830
Marko Mikulicic 0:c0ecb8bf28eb 19831 V7_PRIVATE enum v7_err obj_value_of(struct v7 *v7, val_t v, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 19832 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 19833 val_t func_valueOf = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 19834
Marko Mikulicic 0:c0ecb8bf28eb 19835 v7_own(v7, &func_valueOf);
Marko Mikulicic 0:c0ecb8bf28eb 19836 v7_own(v7, &v);
Marko Mikulicic 0:c0ecb8bf28eb 19837
Marko Mikulicic 0:c0ecb8bf28eb 19838 /*
Marko Mikulicic 0:c0ecb8bf28eb 19839 * TODO(dfrank): use `assert(v7_is_object(v))` instead, like `obj_to_string()`
Marko Mikulicic 0:c0ecb8bf28eb 19840 * does, and fix all callers to ensure it's an object before calling.
Marko Mikulicic 0:c0ecb8bf28eb 19841 *
Marko Mikulicic 0:c0ecb8bf28eb 19842 * Or, conversely, make `obj_to_string()` to accept objects.
Marko Mikulicic 0:c0ecb8bf28eb 19843 */
Marko Mikulicic 0:c0ecb8bf28eb 19844 if (!v7_is_object(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 19845 *res = v;
Marko Mikulicic 0:c0ecb8bf28eb 19846 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 19847 }
Marko Mikulicic 0:c0ecb8bf28eb 19848
Marko Mikulicic 0:c0ecb8bf28eb 19849 V7_TRY(v7_get_throwing(v7, v, "valueOf", 7, &func_valueOf));
Marko Mikulicic 0:c0ecb8bf28eb 19850
Marko Mikulicic 0:c0ecb8bf28eb 19851 if (v7_is_callable(v7, func_valueOf)) {
Marko Mikulicic 0:c0ecb8bf28eb 19852 V7_TRY(b_apply(v7, func_valueOf, v, V7_UNDEFINED, 0, res));
Marko Mikulicic 0:c0ecb8bf28eb 19853 }
Marko Mikulicic 0:c0ecb8bf28eb 19854
Marko Mikulicic 0:c0ecb8bf28eb 19855 clean:
Marko Mikulicic 0:c0ecb8bf28eb 19856 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 19857 *res = v;
Marko Mikulicic 0:c0ecb8bf28eb 19858 }
Marko Mikulicic 0:c0ecb8bf28eb 19859
Marko Mikulicic 0:c0ecb8bf28eb 19860 v7_disown(v7, &v);
Marko Mikulicic 0:c0ecb8bf28eb 19861 v7_disown(v7, &func_valueOf);
Marko Mikulicic 0:c0ecb8bf28eb 19862
Marko Mikulicic 0:c0ecb8bf28eb 19863 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 19864 }
Marko Mikulicic 0:c0ecb8bf28eb 19865
Marko Mikulicic 0:c0ecb8bf28eb 19866 /*
Marko Mikulicic 0:c0ecb8bf28eb 19867 * Caller should ensure that `v` is an object
Marko Mikulicic 0:c0ecb8bf28eb 19868 */
Marko Mikulicic 0:c0ecb8bf28eb 19869 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 19870 V7_PRIVATE enum v7_err obj_to_string(struct v7 *v7, val_t v, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 19871 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 19872 val_t to_string_func = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 19873
Marko Mikulicic 0:c0ecb8bf28eb 19874 /* Caller should ensure that `v` is an object */
Marko Mikulicic 0:c0ecb8bf28eb 19875 assert(v7_is_object(v));
Marko Mikulicic 0:c0ecb8bf28eb 19876
Marko Mikulicic 0:c0ecb8bf28eb 19877 v7_own(v7, &to_string_func);
Marko Mikulicic 0:c0ecb8bf28eb 19878 v7_own(v7, &v);
Marko Mikulicic 0:c0ecb8bf28eb 19879
Marko Mikulicic 0:c0ecb8bf28eb 19880 /*
Marko Mikulicic 0:c0ecb8bf28eb 19881 * If `toString` is callable, then call it; otherwise, just return source
Marko Mikulicic 0:c0ecb8bf28eb 19882 * value
Marko Mikulicic 0:c0ecb8bf28eb 19883 */
Marko Mikulicic 0:c0ecb8bf28eb 19884 V7_TRY(v7_get_throwing(v7, v, "toString", 8, &to_string_func));
Marko Mikulicic 0:c0ecb8bf28eb 19885 if (v7_is_callable(v7, to_string_func)) {
Marko Mikulicic 0:c0ecb8bf28eb 19886 V7_TRY(b_apply(v7, to_string_func, v, V7_UNDEFINED, 0, res));
Marko Mikulicic 0:c0ecb8bf28eb 19887 } else {
Marko Mikulicic 0:c0ecb8bf28eb 19888 *res = v;
Marko Mikulicic 0:c0ecb8bf28eb 19889 }
Marko Mikulicic 0:c0ecb8bf28eb 19890
Marko Mikulicic 0:c0ecb8bf28eb 19891 clean:
Marko Mikulicic 0:c0ecb8bf28eb 19892 v7_disown(v7, &v);
Marko Mikulicic 0:c0ecb8bf28eb 19893 v7_disown(v7, &to_string_func);
Marko Mikulicic 0:c0ecb8bf28eb 19894
Marko Mikulicic 0:c0ecb8bf28eb 19895 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 19896 }
Marko Mikulicic 0:c0ecb8bf28eb 19897
Marko Mikulicic 0:c0ecb8bf28eb 19898 static const char *hex_digits = "0123456789abcdef";
Marko Mikulicic 0:c0ecb8bf28eb 19899 static char *append_hex(char *buf, char *limit, uint8_t c) {
Marko Mikulicic 0:c0ecb8bf28eb 19900 if (buf < limit) *buf++ = 'u';
Marko Mikulicic 0:c0ecb8bf28eb 19901 if (buf < limit) *buf++ = '0';
Marko Mikulicic 0:c0ecb8bf28eb 19902 if (buf < limit) *buf++ = '0';
Marko Mikulicic 0:c0ecb8bf28eb 19903 if (buf < limit) *buf++ = hex_digits[(int) ((c >> 4) % 0xf)];
Marko Mikulicic 0:c0ecb8bf28eb 19904 if (buf < limit) *buf++ = hex_digits[(int) (c & 0xf)];
Marko Mikulicic 0:c0ecb8bf28eb 19905 return buf;
Marko Mikulicic 0:c0ecb8bf28eb 19906 }
Marko Mikulicic 0:c0ecb8bf28eb 19907
Marko Mikulicic 0:c0ecb8bf28eb 19908 /*
Marko Mikulicic 0:c0ecb8bf28eb 19909 * Appends quoted s to buf. Any double quote contained in s will be escaped.
Marko Mikulicic 0:c0ecb8bf28eb 19910 * Returns the number of characters that would have been added,
Marko Mikulicic 0:c0ecb8bf28eb 19911 * like snprintf.
Marko Mikulicic 0:c0ecb8bf28eb 19912 * If size is zero it doesn't output anything but keeps counting.
Marko Mikulicic 0:c0ecb8bf28eb 19913 */
Marko Mikulicic 0:c0ecb8bf28eb 19914 static int snquote(char *buf, size_t size, const char *s, size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 19915 char *limit = buf + size - 1;
Marko Mikulicic 0:c0ecb8bf28eb 19916 const char *end;
Marko Mikulicic 0:c0ecb8bf28eb 19917 /*
Marko Mikulicic 0:c0ecb8bf28eb 19918 * String single character escape sequence:
Marko Mikulicic 0:c0ecb8bf28eb 19919 * http://www.ecma-international.org/ecma-262/6.0/index.html#table-34
Marko Mikulicic 0:c0ecb8bf28eb 19920 *
Marko Mikulicic 0:c0ecb8bf28eb 19921 * 0x8 -> \b
Marko Mikulicic 0:c0ecb8bf28eb 19922 * 0x9 -> \t
Marko Mikulicic 0:c0ecb8bf28eb 19923 * 0xa -> \n
Marko Mikulicic 0:c0ecb8bf28eb 19924 * 0xb -> \v
Marko Mikulicic 0:c0ecb8bf28eb 19925 * 0xc -> \f
Marko Mikulicic 0:c0ecb8bf28eb 19926 * 0xd -> \r
Marko Mikulicic 0:c0ecb8bf28eb 19927 */
Marko Mikulicic 0:c0ecb8bf28eb 19928 const char *specials = "btnvfr";
Marko Mikulicic 0:c0ecb8bf28eb 19929 size_t i = 0;
Marko Mikulicic 0:c0ecb8bf28eb 19930
Marko Mikulicic 0:c0ecb8bf28eb 19931 i++;
Marko Mikulicic 0:c0ecb8bf28eb 19932 if (buf < limit) *buf++ = '"';
Marko Mikulicic 0:c0ecb8bf28eb 19933
Marko Mikulicic 0:c0ecb8bf28eb 19934 for (end = s + len; s < end; s++) {
Marko Mikulicic 0:c0ecb8bf28eb 19935 if (*s == '"' || *s == '\\') {
Marko Mikulicic 0:c0ecb8bf28eb 19936 i++;
Marko Mikulicic 0:c0ecb8bf28eb 19937 if (buf < limit) *buf++ = '\\';
Marko Mikulicic 0:c0ecb8bf28eb 19938 } else if (*s >= '\b' && *s <= '\r') {
Marko Mikulicic 0:c0ecb8bf28eb 19939 i += 2;
Marko Mikulicic 0:c0ecb8bf28eb 19940 if (buf < limit) *buf++ = '\\';
Marko Mikulicic 0:c0ecb8bf28eb 19941 if (buf < limit) *buf++ = specials[*s - '\b'];
Marko Mikulicic 0:c0ecb8bf28eb 19942 continue;
Marko Mikulicic 0:c0ecb8bf28eb 19943 } else if ((unsigned char) *s < '\b' || (*s > '\r' && *s < ' ')) {
Marko Mikulicic 0:c0ecb8bf28eb 19944 i += 6 /* \uXXXX */;
Marko Mikulicic 0:c0ecb8bf28eb 19945 if (buf < limit) *buf++ = '\\';
Marko Mikulicic 0:c0ecb8bf28eb 19946 buf = append_hex(buf, limit, (uint8_t) *s);
Marko Mikulicic 0:c0ecb8bf28eb 19947 continue;
Marko Mikulicic 0:c0ecb8bf28eb 19948 }
Marko Mikulicic 0:c0ecb8bf28eb 19949 i++;
Marko Mikulicic 0:c0ecb8bf28eb 19950 if (buf < limit) *buf++ = *s;
Marko Mikulicic 0:c0ecb8bf28eb 19951 }
Marko Mikulicic 0:c0ecb8bf28eb 19952
Marko Mikulicic 0:c0ecb8bf28eb 19953 i++;
Marko Mikulicic 0:c0ecb8bf28eb 19954 if (buf < limit) *buf++ = '"';
Marko Mikulicic 0:c0ecb8bf28eb 19955
Marko Mikulicic 0:c0ecb8bf28eb 19956 if (size != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 19957 *buf = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 19958 }
Marko Mikulicic 0:c0ecb8bf28eb 19959 return i;
Marko Mikulicic 0:c0ecb8bf28eb 19960 }
Marko Mikulicic 0:c0ecb8bf28eb 19961
Marko Mikulicic 0:c0ecb8bf28eb 19962 /*
Marko Mikulicic 0:c0ecb8bf28eb 19963 * Returns whether the value of given type should be skipped when generating
Marko Mikulicic 0:c0ecb8bf28eb 19964 * JSON output
Marko Mikulicic 0:c0ecb8bf28eb 19965 */
Marko Mikulicic 0:c0ecb8bf28eb 19966 static int should_skip_for_json(enum v7_type type) {
Marko Mikulicic 0:c0ecb8bf28eb 19967 int ret;
Marko Mikulicic 0:c0ecb8bf28eb 19968 switch (type) {
Marko Mikulicic 0:c0ecb8bf28eb 19969 /* All permitted values */
Marko Mikulicic 0:c0ecb8bf28eb 19970 case V7_TYPE_NULL:
Marko Mikulicic 0:c0ecb8bf28eb 19971 case V7_TYPE_BOOLEAN:
Marko Mikulicic 0:c0ecb8bf28eb 19972 case V7_TYPE_BOOLEAN_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 19973 case V7_TYPE_NUMBER:
Marko Mikulicic 0:c0ecb8bf28eb 19974 case V7_TYPE_NUMBER_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 19975 case V7_TYPE_STRING:
Marko Mikulicic 0:c0ecb8bf28eb 19976 case V7_TYPE_STRING_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 19977 case V7_TYPE_GENERIC_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 19978 case V7_TYPE_ARRAY_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 19979 case V7_TYPE_DATE_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 19980 case V7_TYPE_REGEXP_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 19981 case V7_TYPE_ERROR_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 19982 ret = 0;
Marko Mikulicic 0:c0ecb8bf28eb 19983 break;
Marko Mikulicic 0:c0ecb8bf28eb 19984 default:
Marko Mikulicic 0:c0ecb8bf28eb 19985 ret = 1;
Marko Mikulicic 0:c0ecb8bf28eb 19986 break;
Marko Mikulicic 0:c0ecb8bf28eb 19987 }
Marko Mikulicic 0:c0ecb8bf28eb 19988 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 19989 }
Marko Mikulicic 0:c0ecb8bf28eb 19990
Marko Mikulicic 0:c0ecb8bf28eb 19991 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 19992 V7_PRIVATE enum v7_err to_json_or_debug(struct v7 *v7, val_t v, char *buf,
Marko Mikulicic 0:c0ecb8bf28eb 19993 size_t size, size_t *res_len,
Marko Mikulicic 0:c0ecb8bf28eb 19994 uint8_t is_debug) {
Marko Mikulicic 0:c0ecb8bf28eb 19995 val_t el;
Marko Mikulicic 0:c0ecb8bf28eb 19996 char *vp;
Marko Mikulicic 0:c0ecb8bf28eb 19997 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 19998 size_t len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 19999 struct gc_tmp_frame tf = new_tmp_frame(v7);
Marko Mikulicic 0:c0ecb8bf28eb 20000
Marko Mikulicic 0:c0ecb8bf28eb 20001 tmp_stack_push(&tf, &v);
Marko Mikulicic 0:c0ecb8bf28eb 20002 tmp_stack_push(&tf, &el);
Marko Mikulicic 0:c0ecb8bf28eb 20003 /*
Marko Mikulicic 0:c0ecb8bf28eb 20004 * TODO(dfrank) : also push all `v7_val_t`s that are declared below
Marko Mikulicic 0:c0ecb8bf28eb 20005 */
Marko Mikulicic 0:c0ecb8bf28eb 20006
Marko Mikulicic 0:c0ecb8bf28eb 20007 if (size > 0) *buf = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 20008
Marko Mikulicic 0:c0ecb8bf28eb 20009 if (!is_debug && should_skip_for_json(val_type(v7, v))) {
Marko Mikulicic 0:c0ecb8bf28eb 20010 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 20011 }
Marko Mikulicic 0:c0ecb8bf28eb 20012
Marko Mikulicic 0:c0ecb8bf28eb 20013 for (vp = v7->json_visited_stack.buf;
Marko Mikulicic 0:c0ecb8bf28eb 20014 vp < v7->json_visited_stack.buf + v7->json_visited_stack.len;
Marko Mikulicic 0:c0ecb8bf28eb 20015 vp += sizeof(val_t)) {
Marko Mikulicic 0:c0ecb8bf28eb 20016 if (*(val_t *) vp == v) {
Marko Mikulicic 0:c0ecb8bf28eb 20017 strncpy(buf, "[Circular]", size);
Marko Mikulicic 0:c0ecb8bf28eb 20018 len = 10;
Marko Mikulicic 0:c0ecb8bf28eb 20019 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 20020 }
Marko Mikulicic 0:c0ecb8bf28eb 20021 }
Marko Mikulicic 0:c0ecb8bf28eb 20022
Marko Mikulicic 0:c0ecb8bf28eb 20023 switch (val_type(v7, v)) {
Marko Mikulicic 0:c0ecb8bf28eb 20024 case V7_TYPE_NULL:
Marko Mikulicic 0:c0ecb8bf28eb 20025 case V7_TYPE_BOOLEAN:
Marko Mikulicic 0:c0ecb8bf28eb 20026 case V7_TYPE_NUMBER:
Marko Mikulicic 0:c0ecb8bf28eb 20027 case V7_TYPE_UNDEFINED:
Marko Mikulicic 0:c0ecb8bf28eb 20028 case V7_TYPE_CFUNCTION:
Marko Mikulicic 0:c0ecb8bf28eb 20029 case V7_TYPE_FOREIGN:
Marko Mikulicic 0:c0ecb8bf28eb 20030 /* For those types, regular `primitive_to_str()` works */
Marko Mikulicic 0:c0ecb8bf28eb 20031 V7_TRY(primitive_to_str(v7, v, NULL, buf, size, &len));
Marko Mikulicic 0:c0ecb8bf28eb 20032 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 20033
Marko Mikulicic 0:c0ecb8bf28eb 20034 case V7_TYPE_STRING: {
Marko Mikulicic 0:c0ecb8bf28eb 20035 /*
Marko Mikulicic 0:c0ecb8bf28eb 20036 * For strings we can't just use `primitive_to_str()`, because we need
Marko Mikulicic 0:c0ecb8bf28eb 20037 * quoted value
Marko Mikulicic 0:c0ecb8bf28eb 20038 */
Marko Mikulicic 0:c0ecb8bf28eb 20039 size_t n;
Marko Mikulicic 0:c0ecb8bf28eb 20040 const char *str = v7_get_string(v7, &v, &n);
Marko Mikulicic 0:c0ecb8bf28eb 20041 len = snquote(buf, size, str, n);
Marko Mikulicic 0:c0ecb8bf28eb 20042 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 20043 }
Marko Mikulicic 0:c0ecb8bf28eb 20044
Marko Mikulicic 0:c0ecb8bf28eb 20045 case V7_TYPE_DATE_OBJECT: {
Marko Mikulicic 0:c0ecb8bf28eb 20046 v7_val_t func = V7_UNDEFINED, val = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 20047 V7_TRY(v7_get_throwing(v7, v, "toString", 8, &func));
Marko Mikulicic 0:c0ecb8bf28eb 20048 #if V7_ENABLE__Date__toJSON
Marko Mikulicic 0:c0ecb8bf28eb 20049 if (!is_debug) {
Marko Mikulicic 0:c0ecb8bf28eb 20050 V7_TRY(v7_get_throwing(v7, v, "toJSON", 6, &func));
Marko Mikulicic 0:c0ecb8bf28eb 20051 }
Marko Mikulicic 0:c0ecb8bf28eb 20052 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20053 V7_TRY(b_apply(v7, func, v, V7_UNDEFINED, 0, &val));
Marko Mikulicic 0:c0ecb8bf28eb 20054 V7_TRY(to_json_or_debug(v7, val, buf, size, &len, is_debug));
Marko Mikulicic 0:c0ecb8bf28eb 20055 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 20056 }
Marko Mikulicic 0:c0ecb8bf28eb 20057 case V7_TYPE_GENERIC_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 20058 case V7_TYPE_BOOLEAN_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 20059 case V7_TYPE_STRING_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 20060 case V7_TYPE_NUMBER_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 20061 case V7_TYPE_REGEXP_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 20062 case V7_TYPE_ERROR_OBJECT: {
Marko Mikulicic 0:c0ecb8bf28eb 20063 /* TODO(imax): make it return the desired size of the buffer */
Marko Mikulicic 0:c0ecb8bf28eb 20064 char *b = buf;
Marko Mikulicic 0:c0ecb8bf28eb 20065 v7_val_t name = V7_UNDEFINED, val = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 20066 v7_prop_attr_t attrs = 0;
Marko Mikulicic 0:c0ecb8bf28eb 20067 const char *pname;
Marko Mikulicic 0:c0ecb8bf28eb 20068 size_t nlen;
Marko Mikulicic 0:c0ecb8bf28eb 20069 int ok = 0;
Marko Mikulicic 0:c0ecb8bf28eb 20070 struct prop_iter_ctx ctx;
Marko Mikulicic 0:c0ecb8bf28eb 20071 memset(&ctx, 0, sizeof(ctx));
Marko Mikulicic 0:c0ecb8bf28eb 20072
Marko Mikulicic 0:c0ecb8bf28eb 20073 mbuf_append(&v7->json_visited_stack, (char *) &v, sizeof(v));
Marko Mikulicic 0:c0ecb8bf28eb 20074 b += c_snprintf(b, BUF_LEFT(size, b - buf), "{");
Marko Mikulicic 0:c0ecb8bf28eb 20075 V7_TRY2(init_prop_iter_ctx(v7, v, 1 /*proxy-transparent*/, &ctx),
Marko Mikulicic 0:c0ecb8bf28eb 20076 clean_iter);
Marko Mikulicic 0:c0ecb8bf28eb 20077 while (1) {
Marko Mikulicic 0:c0ecb8bf28eb 20078 size_t n;
Marko Mikulicic 0:c0ecb8bf28eb 20079 const char *s;
Marko Mikulicic 0:c0ecb8bf28eb 20080 V7_TRY2(next_prop(v7, &ctx, &name, &val, &attrs, &ok), clean_iter);
Marko Mikulicic 0:c0ecb8bf28eb 20081 if (!ok) {
Marko Mikulicic 0:c0ecb8bf28eb 20082 break;
Marko Mikulicic 0:c0ecb8bf28eb 20083 } else if (attrs & (_V7_PROPERTY_HIDDEN | V7_PROPERTY_NON_ENUMERABLE)) {
Marko Mikulicic 0:c0ecb8bf28eb 20084 continue;
Marko Mikulicic 0:c0ecb8bf28eb 20085 }
Marko Mikulicic 0:c0ecb8bf28eb 20086 pname = v7_get_string(v7, &name, &nlen);
Marko Mikulicic 0:c0ecb8bf28eb 20087 V7_TRY(v7_get_throwing(v7, v, pname, nlen, &val));
Marko Mikulicic 0:c0ecb8bf28eb 20088 if (!is_debug && should_skip_for_json(val_type(v7, val))) {
Marko Mikulicic 0:c0ecb8bf28eb 20089 continue;
Marko Mikulicic 0:c0ecb8bf28eb 20090 }
Marko Mikulicic 0:c0ecb8bf28eb 20091 if (b - buf != 1) { /* Not the first property to be printed */
Marko Mikulicic 0:c0ecb8bf28eb 20092 b += c_snprintf(b, BUF_LEFT(size, b - buf), ",");
Marko Mikulicic 0:c0ecb8bf28eb 20093 }
Marko Mikulicic 0:c0ecb8bf28eb 20094 s = v7_get_string(v7, &name, &n);
Marko Mikulicic 0:c0ecb8bf28eb 20095 b += c_snprintf(b, BUF_LEFT(size, b - buf), "\"%.*s\":", (int) n, s);
Marko Mikulicic 0:c0ecb8bf28eb 20096 {
Marko Mikulicic 0:c0ecb8bf28eb 20097 size_t tmp = 0;
Marko Mikulicic 0:c0ecb8bf28eb 20098 V7_TRY2(to_json_or_debug(v7, val, b, BUF_LEFT(size, b - buf), &tmp,
Marko Mikulicic 0:c0ecb8bf28eb 20099 is_debug),
Marko Mikulicic 0:c0ecb8bf28eb 20100 clean_iter);
Marko Mikulicic 0:c0ecb8bf28eb 20101 b += tmp;
Marko Mikulicic 0:c0ecb8bf28eb 20102 }
Marko Mikulicic 0:c0ecb8bf28eb 20103 }
Marko Mikulicic 0:c0ecb8bf28eb 20104 b += c_snprintf(b, BUF_LEFT(size, b - buf), "}");
Marko Mikulicic 0:c0ecb8bf28eb 20105 v7->json_visited_stack.len -= sizeof(v);
Marko Mikulicic 0:c0ecb8bf28eb 20106
Marko Mikulicic 0:c0ecb8bf28eb 20107 clean_iter:
Marko Mikulicic 0:c0ecb8bf28eb 20108 v7_destruct_prop_iter_ctx(v7, &ctx);
Marko Mikulicic 0:c0ecb8bf28eb 20109
Marko Mikulicic 0:c0ecb8bf28eb 20110 len = b - buf;
Marko Mikulicic 0:c0ecb8bf28eb 20111 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 20112 }
Marko Mikulicic 0:c0ecb8bf28eb 20113 case V7_TYPE_ARRAY_OBJECT: {
Marko Mikulicic 0:c0ecb8bf28eb 20114 int has;
Marko Mikulicic 0:c0ecb8bf28eb 20115 char *b = buf;
Marko Mikulicic 0:c0ecb8bf28eb 20116 size_t i, alen = v7_array_length(v7, v);
Marko Mikulicic 0:c0ecb8bf28eb 20117 mbuf_append(&v7->json_visited_stack, (char *) &v, sizeof(v));
Marko Mikulicic 0:c0ecb8bf28eb 20118 b += c_snprintf(b, BUF_LEFT(size, b - buf), "[");
Marko Mikulicic 0:c0ecb8bf28eb 20119 for (i = 0; i < alen; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 20120 el = v7_array_get2(v7, v, i, &has);
Marko Mikulicic 0:c0ecb8bf28eb 20121 if (has) {
Marko Mikulicic 0:c0ecb8bf28eb 20122 size_t tmp = 0;
Marko Mikulicic 0:c0ecb8bf28eb 20123 if (!is_debug && should_skip_for_json(val_type(v7, el))) {
Marko Mikulicic 0:c0ecb8bf28eb 20124 b += c_snprintf(b, BUF_LEFT(size, b - buf), "null");
Marko Mikulicic 0:c0ecb8bf28eb 20125 } else {
Marko Mikulicic 0:c0ecb8bf28eb 20126 V7_TRY(to_json_or_debug(v7, el, b, BUF_LEFT(size, b - buf), &tmp,
Marko Mikulicic 0:c0ecb8bf28eb 20127 is_debug));
Marko Mikulicic 0:c0ecb8bf28eb 20128 }
Marko Mikulicic 0:c0ecb8bf28eb 20129 b += tmp;
Marko Mikulicic 0:c0ecb8bf28eb 20130 }
Marko Mikulicic 0:c0ecb8bf28eb 20131 if (i != alen - 1) {
Marko Mikulicic 0:c0ecb8bf28eb 20132 b += c_snprintf(b, BUF_LEFT(size, b - buf), ",");
Marko Mikulicic 0:c0ecb8bf28eb 20133 }
Marko Mikulicic 0:c0ecb8bf28eb 20134 }
Marko Mikulicic 0:c0ecb8bf28eb 20135 b += c_snprintf(b, BUF_LEFT(size, b - buf), "]");
Marko Mikulicic 0:c0ecb8bf28eb 20136 v7->json_visited_stack.len -= sizeof(v);
Marko Mikulicic 0:c0ecb8bf28eb 20137 len = b - buf;
Marko Mikulicic 0:c0ecb8bf28eb 20138 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 20139 }
Marko Mikulicic 0:c0ecb8bf28eb 20140 case V7_TYPE_CFUNCTION_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 20141 V7_TRY(obj_value_of(v7, v, &v));
Marko Mikulicic 0:c0ecb8bf28eb 20142 len = c_snprintf(buf, size, "Function cfunc_%p", get_ptr(v));
Marko Mikulicic 0:c0ecb8bf28eb 20143 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 20144 case V7_TYPE_FUNCTION_OBJECT:
Marko Mikulicic 0:c0ecb8bf28eb 20145 V7_TRY(to_string(v7, v, NULL, buf, size, &len));
Marko Mikulicic 0:c0ecb8bf28eb 20146 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 20147
Marko Mikulicic 0:c0ecb8bf28eb 20148 case V7_TYPE_MAX_OBJECT_TYPE:
Marko Mikulicic 0:c0ecb8bf28eb 20149 case V7_NUM_TYPES:
Marko Mikulicic 0:c0ecb8bf28eb 20150 abort();
Marko Mikulicic 0:c0ecb8bf28eb 20151 }
Marko Mikulicic 0:c0ecb8bf28eb 20152
Marko Mikulicic 0:c0ecb8bf28eb 20153 abort();
Marko Mikulicic 0:c0ecb8bf28eb 20154
Marko Mikulicic 0:c0ecb8bf28eb 20155 len = 0; /* for compilers that don't know about abort() */
Marko Mikulicic 0:c0ecb8bf28eb 20156 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 20157
Marko Mikulicic 0:c0ecb8bf28eb 20158 clean:
Marko Mikulicic 0:c0ecb8bf28eb 20159 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 20160 len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 20161 }
Marko Mikulicic 0:c0ecb8bf28eb 20162 if (res_len != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 20163 *res_len = len;
Marko Mikulicic 0:c0ecb8bf28eb 20164 }
Marko Mikulicic 0:c0ecb8bf28eb 20165 tmp_frame_cleanup(&tf);
Marko Mikulicic 0:c0ecb8bf28eb 20166 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 20167 }
Marko Mikulicic 0:c0ecb8bf28eb 20168
Marko Mikulicic 0:c0ecb8bf28eb 20169 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 20170 V7_PRIVATE val_t to_boolean_v(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 20171 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 20172 int is_truthy;
Marko Mikulicic 0:c0ecb8bf28eb 20173
Marko Mikulicic 0:c0ecb8bf28eb 20174 is_truthy = ((v7_is_boolean(v) && v7_get_bool(v7, v)) ||
Marko Mikulicic 0:c0ecb8bf28eb 20175 (v7_is_number(v) && v7_get_double(v7, v) != 0.0) ||
Marko Mikulicic 0:c0ecb8bf28eb 20176 (v7_is_string(v) && v7_get_string(v7, &v, &len) && len > 0) ||
Marko Mikulicic 0:c0ecb8bf28eb 20177 (v7_is_object(v))) &&
Marko Mikulicic 0:c0ecb8bf28eb 20178 v != V7_TAG_NAN;
Marko Mikulicic 0:c0ecb8bf28eb 20179
Marko Mikulicic 0:c0ecb8bf28eb 20180 return v7_mk_boolean(v7, is_truthy);
Marko Mikulicic 0:c0ecb8bf28eb 20181 }
Marko Mikulicic 0:c0ecb8bf28eb 20182
Marko Mikulicic 0:c0ecb8bf28eb 20183 /*
Marko Mikulicic 0:c0ecb8bf28eb 20184 * v7_stringify allocates a new buffer if value representation doesn't fit into
Marko Mikulicic 0:c0ecb8bf28eb 20185 * buf. Caller is responsible for freeing that buffer.
Marko Mikulicic 0:c0ecb8bf28eb 20186 */
Marko Mikulicic 0:c0ecb8bf28eb 20187 char *v7_stringify(struct v7 *v7, val_t v, char *buf, size_t size,
Marko Mikulicic 0:c0ecb8bf28eb 20188 enum v7_stringify_mode mode) {
Marko Mikulicic 0:c0ecb8bf28eb 20189 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 20190 uint8_t saved_is_thrown = 0;
Marko Mikulicic 0:c0ecb8bf28eb 20191 val_t saved_thrown = v7_get_thrown_value(v7, &saved_is_thrown);
Marko Mikulicic 0:c0ecb8bf28eb 20192 char *ret = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 20193
Marko Mikulicic 0:c0ecb8bf28eb 20194 rcode = v7_stringify_throwing(v7, v, buf, size, mode, &ret);
Marko Mikulicic 0:c0ecb8bf28eb 20195 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 20196 rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 20197 if (saved_is_thrown) {
Marko Mikulicic 0:c0ecb8bf28eb 20198 rcode = v7_throw(v7, saved_thrown);
Marko Mikulicic 0:c0ecb8bf28eb 20199 } else {
Marko Mikulicic 0:c0ecb8bf28eb 20200 v7_clear_thrown_value(v7);
Marko Mikulicic 0:c0ecb8bf28eb 20201 }
Marko Mikulicic 0:c0ecb8bf28eb 20202
Marko Mikulicic 0:c0ecb8bf28eb 20203 buf[0] = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 20204 ret = buf;
Marko Mikulicic 0:c0ecb8bf28eb 20205 }
Marko Mikulicic 0:c0ecb8bf28eb 20206
Marko Mikulicic 0:c0ecb8bf28eb 20207 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 20208 }
Marko Mikulicic 0:c0ecb8bf28eb 20209
Marko Mikulicic 0:c0ecb8bf28eb 20210 enum v7_err v7_stringify_throwing(struct v7 *v7, val_t v, char *buf,
Marko Mikulicic 0:c0ecb8bf28eb 20211 size_t size, enum v7_stringify_mode mode,
Marko Mikulicic 0:c0ecb8bf28eb 20212 char **res) {
Marko Mikulicic 0:c0ecb8bf28eb 20213 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 20214 char *p = buf;
Marko Mikulicic 0:c0ecb8bf28eb 20215 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 20216
Marko Mikulicic 0:c0ecb8bf28eb 20217 switch (mode) {
Marko Mikulicic 0:c0ecb8bf28eb 20218 case V7_STRINGIFY_DEFAULT:
Marko Mikulicic 0:c0ecb8bf28eb 20219 V7_TRY(to_string(v7, v, NULL, buf, size, &len));
Marko Mikulicic 0:c0ecb8bf28eb 20220 break;
Marko Mikulicic 0:c0ecb8bf28eb 20221
Marko Mikulicic 0:c0ecb8bf28eb 20222 case V7_STRINGIFY_JSON:
Marko Mikulicic 0:c0ecb8bf28eb 20223 V7_TRY(to_json_or_debug(v7, v, buf, size, &len, 0));
Marko Mikulicic 0:c0ecb8bf28eb 20224 break;
Marko Mikulicic 0:c0ecb8bf28eb 20225
Marko Mikulicic 0:c0ecb8bf28eb 20226 case V7_STRINGIFY_DEBUG:
Marko Mikulicic 0:c0ecb8bf28eb 20227 V7_TRY(to_json_or_debug(v7, v, buf, size, &len, 1));
Marko Mikulicic 0:c0ecb8bf28eb 20228 break;
Marko Mikulicic 0:c0ecb8bf28eb 20229 }
Marko Mikulicic 0:c0ecb8bf28eb 20230
Marko Mikulicic 0:c0ecb8bf28eb 20231 /* fit null terminating byte */
Marko Mikulicic 0:c0ecb8bf28eb 20232 if (len >= size) {
Marko Mikulicic 0:c0ecb8bf28eb 20233 /* Buffer is not large enough. Allocate a bigger one */
Marko Mikulicic 0:c0ecb8bf28eb 20234 p = (char *) malloc(len + 1);
Marko Mikulicic 0:c0ecb8bf28eb 20235 V7_TRY(v7_stringify_throwing(v7, v, p, len + 1, mode, res));
Marko Mikulicic 0:c0ecb8bf28eb 20236 assert(*res == p);
Marko Mikulicic 0:c0ecb8bf28eb 20237 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 20238 } else {
Marko Mikulicic 0:c0ecb8bf28eb 20239 *res = p;
Marko Mikulicic 0:c0ecb8bf28eb 20240 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 20241 }
Marko Mikulicic 0:c0ecb8bf28eb 20242
Marko Mikulicic 0:c0ecb8bf28eb 20243 clean:
Marko Mikulicic 0:c0ecb8bf28eb 20244 /*
Marko Mikulicic 0:c0ecb8bf28eb 20245 * If we're going to throw, and we allocated a buffer, then free it.
Marko Mikulicic 0:c0ecb8bf28eb 20246 * But if we don't throw, then the caller will free it.
Marko Mikulicic 0:c0ecb8bf28eb 20247 */
Marko Mikulicic 0:c0ecb8bf28eb 20248 if (rcode != V7_OK && p != buf) {
Marko Mikulicic 0:c0ecb8bf28eb 20249 free(p);
Marko Mikulicic 0:c0ecb8bf28eb 20250 }
Marko Mikulicic 0:c0ecb8bf28eb 20251 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 20252 }
Marko Mikulicic 0:c0ecb8bf28eb 20253
Marko Mikulicic 0:c0ecb8bf28eb 20254 int v7_is_truthy(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 20255 return v7_get_bool(v7, to_boolean_v(v7, v));
Marko Mikulicic 0:c0ecb8bf28eb 20256 }
Marko Mikulicic 0:c0ecb8bf28eb 20257 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 20258 #line 1 "v7/src/shdata.c"
Marko Mikulicic 0:c0ecb8bf28eb 20259 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20260 /*
Marko Mikulicic 0:c0ecb8bf28eb 20261 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 20262 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 20263 */
Marko Mikulicic 0:c0ecb8bf28eb 20264
Marko Mikulicic 0:c0ecb8bf28eb 20265 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 20266 /* Amalgamated: #include "v7/src/shdata.h" */
Marko Mikulicic 0:c0ecb8bf28eb 20267
Marko Mikulicic 0:c0ecb8bf28eb 20268 #if !defined(V7_DISABLE_FILENAMES) && !defined(V7_DISABLE_LINE_NUMBERS)
Marko Mikulicic 0:c0ecb8bf28eb 20269 V7_PRIVATE struct shdata *shdata_create(const void *payload, size_t size) {
Marko Mikulicic 0:c0ecb8bf28eb 20270 struct shdata *ret =
Marko Mikulicic 0:c0ecb8bf28eb 20271 (struct shdata *) calloc(1, sizeof(struct shdata) + size);
Marko Mikulicic 0:c0ecb8bf28eb 20272 shdata_retain(ret);
Marko Mikulicic 0:c0ecb8bf28eb 20273 if (payload != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 20274 memcpy((char *) shdata_get_payload(ret), (char *) payload, size);
Marko Mikulicic 0:c0ecb8bf28eb 20275 }
Marko Mikulicic 0:c0ecb8bf28eb 20276 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 20277 }
Marko Mikulicic 0:c0ecb8bf28eb 20278
Marko Mikulicic 0:c0ecb8bf28eb 20279 V7_PRIVATE struct shdata *shdata_create_from_string(const char *src) {
Marko Mikulicic 0:c0ecb8bf28eb 20280 return shdata_create(src, strlen(src) + 1 /*null-term*/);
Marko Mikulicic 0:c0ecb8bf28eb 20281 }
Marko Mikulicic 0:c0ecb8bf28eb 20282
Marko Mikulicic 0:c0ecb8bf28eb 20283 V7_PRIVATE void shdata_retain(struct shdata *p) {
Marko Mikulicic 0:c0ecb8bf28eb 20284 p->refcnt++;
Marko Mikulicic 0:c0ecb8bf28eb 20285 assert(p->refcnt > 0);
Marko Mikulicic 0:c0ecb8bf28eb 20286 }
Marko Mikulicic 0:c0ecb8bf28eb 20287
Marko Mikulicic 0:c0ecb8bf28eb 20288 V7_PRIVATE void shdata_release(struct shdata *p) {
Marko Mikulicic 0:c0ecb8bf28eb 20289 assert(p->refcnt > 0);
Marko Mikulicic 0:c0ecb8bf28eb 20290 p->refcnt--;
Marko Mikulicic 0:c0ecb8bf28eb 20291 if (p->refcnt == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 20292 free(p);
Marko Mikulicic 0:c0ecb8bf28eb 20293 }
Marko Mikulicic 0:c0ecb8bf28eb 20294 }
Marko Mikulicic 0:c0ecb8bf28eb 20295
Marko Mikulicic 0:c0ecb8bf28eb 20296 V7_PRIVATE void *shdata_get_payload(struct shdata *p) {
Marko Mikulicic 0:c0ecb8bf28eb 20297 return (char *) p + sizeof(*p);
Marko Mikulicic 0:c0ecb8bf28eb 20298 }
Marko Mikulicic 0:c0ecb8bf28eb 20299 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20300 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 20301 #line 1 "v7/src/gc.c"
Marko Mikulicic 0:c0ecb8bf28eb 20302 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20303 /*
Marko Mikulicic 0:c0ecb8bf28eb 20304 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 20305 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 20306 */
Marko Mikulicic 0:c0ecb8bf28eb 20307
Marko Mikulicic 0:c0ecb8bf28eb 20308 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 20309 /* Amalgamated: #include "v7/src/bcode.h" */
Marko Mikulicic 0:c0ecb8bf28eb 20310 /* Amalgamated: #include "v7/src/varint.h" */
Marko Mikulicic 0:c0ecb8bf28eb 20311 /* Amalgamated: #include "v7/src/gc.h" */
Marko Mikulicic 0:c0ecb8bf28eb 20312 /* Amalgamated: #include "v7/src/freeze.h" */
Marko Mikulicic 0:c0ecb8bf28eb 20313 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 20314 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 20315 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 20316 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 20317 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 20318 /* Amalgamated: #include "v7/src/util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 20319 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 20320 /* Amalgamated: #include "v7/src/heapusage.h" */
Marko Mikulicic 0:c0ecb8bf28eb 20321
Marko Mikulicic 0:c0ecb8bf28eb 20322 #include <stdio.h>
Marko Mikulicic 0:c0ecb8bf28eb 20323
Marko Mikulicic 0:c0ecb8bf28eb 20324 #ifdef V7_STACK_GUARD_MIN_SIZE
Marko Mikulicic 0:c0ecb8bf28eb 20325 void *v7_sp_limit = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 20326 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20327
Marko Mikulicic 0:c0ecb8bf28eb 20328 void gc_mark_string(struct v7 *, val_t *);
Marko Mikulicic 0:c0ecb8bf28eb 20329
Marko Mikulicic 0:c0ecb8bf28eb 20330 static struct gc_block *gc_new_block(struct gc_arena *a, size_t size);
Marko Mikulicic 0:c0ecb8bf28eb 20331 static void gc_free_block(struct gc_block *b);
Marko Mikulicic 0:c0ecb8bf28eb 20332 static void gc_mark_mbuf_pt(struct v7 *v7, const struct mbuf *mbuf);
Marko Mikulicic 0:c0ecb8bf28eb 20333 static void gc_mark_mbuf_val(struct v7 *v7, const struct mbuf *mbuf);
Marko Mikulicic 0:c0ecb8bf28eb 20334 static void gc_mark_vec_val(struct v7 *v7, const struct v7_vec *vec);
Marko Mikulicic 0:c0ecb8bf28eb 20335
Marko Mikulicic 0:c0ecb8bf28eb 20336 V7_PRIVATE struct v7_generic_object *new_generic_object(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 20337 return (struct v7_generic_object *) gc_alloc_cell(v7,
Marko Mikulicic 0:c0ecb8bf28eb 20338 &v7->generic_object_arena);
Marko Mikulicic 0:c0ecb8bf28eb 20339 }
Marko Mikulicic 0:c0ecb8bf28eb 20340
Marko Mikulicic 0:c0ecb8bf28eb 20341 V7_PRIVATE struct v7_property *new_property(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 20342 return (struct v7_property *) gc_alloc_cell(v7, &v7->property_arena);
Marko Mikulicic 0:c0ecb8bf28eb 20343 }
Marko Mikulicic 0:c0ecb8bf28eb 20344
Marko Mikulicic 0:c0ecb8bf28eb 20345 V7_PRIVATE struct v7_js_function *new_function(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 20346 return (struct v7_js_function *) gc_alloc_cell(v7, &v7->function_arena);
Marko Mikulicic 0:c0ecb8bf28eb 20347 }
Marko Mikulicic 0:c0ecb8bf28eb 20348
Marko Mikulicic 0:c0ecb8bf28eb 20349 V7_PRIVATE struct gc_tmp_frame new_tmp_frame(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 20350 struct gc_tmp_frame frame;
Marko Mikulicic 0:c0ecb8bf28eb 20351 frame.v7 = v7;
Marko Mikulicic 0:c0ecb8bf28eb 20352 frame.pos = v7->tmp_stack.len;
Marko Mikulicic 0:c0ecb8bf28eb 20353 return frame;
Marko Mikulicic 0:c0ecb8bf28eb 20354 }
Marko Mikulicic 0:c0ecb8bf28eb 20355
Marko Mikulicic 0:c0ecb8bf28eb 20356 V7_PRIVATE void tmp_frame_cleanup(struct gc_tmp_frame *tf) {
Marko Mikulicic 0:c0ecb8bf28eb 20357 tf->v7->tmp_stack.len = tf->pos;
Marko Mikulicic 0:c0ecb8bf28eb 20358 }
Marko Mikulicic 0:c0ecb8bf28eb 20359
Marko Mikulicic 0:c0ecb8bf28eb 20360 /*
Marko Mikulicic 0:c0ecb8bf28eb 20361 * TODO(mkm): perhaps it's safer to keep val_t in the temporary
Marko Mikulicic 0:c0ecb8bf28eb 20362 * roots stack, instead of keeping val_t*, in order to be better
Marko Mikulicic 0:c0ecb8bf28eb 20363 * able to debug the relocating GC.
Marko Mikulicic 0:c0ecb8bf28eb 20364 */
Marko Mikulicic 0:c0ecb8bf28eb 20365 V7_PRIVATE void tmp_stack_push(struct gc_tmp_frame *tf, val_t *vp) {
Marko Mikulicic 0:c0ecb8bf28eb 20366 mbuf_append(&tf->v7->tmp_stack, (char *) &vp, sizeof(val_t *));
Marko Mikulicic 0:c0ecb8bf28eb 20367 }
Marko Mikulicic 0:c0ecb8bf28eb 20368
Marko Mikulicic 0:c0ecb8bf28eb 20369 /* Initializes a new arena. */
Marko Mikulicic 0:c0ecb8bf28eb 20370 V7_PRIVATE void gc_arena_init(struct gc_arena *a, size_t cell_size,
Marko Mikulicic 0:c0ecb8bf28eb 20371 size_t initial_size, size_t size_increment,
Marko Mikulicic 0:c0ecb8bf28eb 20372 const char *name) {
Marko Mikulicic 0:c0ecb8bf28eb 20373 assert(cell_size >= sizeof(uintptr_t));
Marko Mikulicic 0:c0ecb8bf28eb 20374
Marko Mikulicic 0:c0ecb8bf28eb 20375 memset(a, 0, sizeof(*a));
Marko Mikulicic 0:c0ecb8bf28eb 20376 a->cell_size = cell_size;
Marko Mikulicic 0:c0ecb8bf28eb 20377 a->name = name;
Marko Mikulicic 0:c0ecb8bf28eb 20378 a->size_increment = size_increment;
Marko Mikulicic 0:c0ecb8bf28eb 20379 a->blocks = gc_new_block(a, initial_size);
Marko Mikulicic 0:c0ecb8bf28eb 20380 }
Marko Mikulicic 0:c0ecb8bf28eb 20381
Marko Mikulicic 0:c0ecb8bf28eb 20382 V7_PRIVATE void gc_arena_destroy(struct v7 *v7, struct gc_arena *a) {
Marko Mikulicic 0:c0ecb8bf28eb 20383 struct gc_block *b;
Marko Mikulicic 0:c0ecb8bf28eb 20384
Marko Mikulicic 0:c0ecb8bf28eb 20385 if (a->blocks != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 20386 gc_sweep(v7, a, 0);
Marko Mikulicic 0:c0ecb8bf28eb 20387 for (b = a->blocks; b != NULL;) {
Marko Mikulicic 0:c0ecb8bf28eb 20388 struct gc_block *tmp;
Marko Mikulicic 0:c0ecb8bf28eb 20389 tmp = b;
Marko Mikulicic 0:c0ecb8bf28eb 20390 b = b->next;
Marko Mikulicic 0:c0ecb8bf28eb 20391 gc_free_block(tmp);
Marko Mikulicic 0:c0ecb8bf28eb 20392 }
Marko Mikulicic 0:c0ecb8bf28eb 20393 }
Marko Mikulicic 0:c0ecb8bf28eb 20394 }
Marko Mikulicic 0:c0ecb8bf28eb 20395
Marko Mikulicic 0:c0ecb8bf28eb 20396 static void gc_free_block(struct gc_block *b) {
Marko Mikulicic 0:c0ecb8bf28eb 20397 free(b->base);
Marko Mikulicic 0:c0ecb8bf28eb 20398 free(b);
Marko Mikulicic 0:c0ecb8bf28eb 20399 }
Marko Mikulicic 0:c0ecb8bf28eb 20400
Marko Mikulicic 0:c0ecb8bf28eb 20401 static struct gc_block *gc_new_block(struct gc_arena *a, size_t size) {
Marko Mikulicic 0:c0ecb8bf28eb 20402 struct gc_cell *cur;
Marko Mikulicic 0:c0ecb8bf28eb 20403 struct gc_block *b;
Marko Mikulicic 0:c0ecb8bf28eb 20404
Marko Mikulicic 0:c0ecb8bf28eb 20405 heapusage_dont_count(1);
Marko Mikulicic 0:c0ecb8bf28eb 20406 b = (struct gc_block *) calloc(1, sizeof(*b));
Marko Mikulicic 0:c0ecb8bf28eb 20407 heapusage_dont_count(0);
Marko Mikulicic 0:c0ecb8bf28eb 20408 if (b == NULL) abort();
Marko Mikulicic 0:c0ecb8bf28eb 20409
Marko Mikulicic 0:c0ecb8bf28eb 20410 b->size = size;
Marko Mikulicic 0:c0ecb8bf28eb 20411 heapusage_dont_count(1);
Marko Mikulicic 0:c0ecb8bf28eb 20412 b->base = (struct gc_cell *) calloc(a->cell_size, b->size);
Marko Mikulicic 0:c0ecb8bf28eb 20413 heapusage_dont_count(0);
Marko Mikulicic 0:c0ecb8bf28eb 20414 if (b->base == NULL) abort();
Marko Mikulicic 0:c0ecb8bf28eb 20415
Marko Mikulicic 0:c0ecb8bf28eb 20416 for (cur = GC_CELL_OP(a, b->base, +, 0);
Marko Mikulicic 0:c0ecb8bf28eb 20417 cur < GC_CELL_OP(a, b->base, +, b->size);
Marko Mikulicic 0:c0ecb8bf28eb 20418 cur = GC_CELL_OP(a, cur, +, 1)) {
Marko Mikulicic 0:c0ecb8bf28eb 20419 cur->head.link = a->free;
Marko Mikulicic 0:c0ecb8bf28eb 20420 a->free = cur;
Marko Mikulicic 0:c0ecb8bf28eb 20421 }
Marko Mikulicic 0:c0ecb8bf28eb 20422
Marko Mikulicic 0:c0ecb8bf28eb 20423 return b;
Marko Mikulicic 0:c0ecb8bf28eb 20424 }
Marko Mikulicic 0:c0ecb8bf28eb 20425
Marko Mikulicic 0:c0ecb8bf28eb 20426 V7_PRIVATE void *gc_alloc_cell(struct v7 *v7, struct gc_arena *a) {
Marko Mikulicic 0:c0ecb8bf28eb 20427 #if V7_MALLOC_GC
Marko Mikulicic 0:c0ecb8bf28eb 20428 struct gc_cell *r;
Marko Mikulicic 0:c0ecb8bf28eb 20429 maybe_gc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 20430 heapusage_dont_count(1);
Marko Mikulicic 0:c0ecb8bf28eb 20431 r = (struct gc_cell *) calloc(1, a->cell_size);
Marko Mikulicic 0:c0ecb8bf28eb 20432 heapusage_dont_count(0);
Marko Mikulicic 0:c0ecb8bf28eb 20433 mbuf_append(&v7->malloc_trace, &r, sizeof(r));
Marko Mikulicic 0:c0ecb8bf28eb 20434 return r;
Marko Mikulicic 0:c0ecb8bf28eb 20435 #else
Marko Mikulicic 0:c0ecb8bf28eb 20436 struct gc_cell *r;
Marko Mikulicic 0:c0ecb8bf28eb 20437 if (a->free == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 20438 if (!maybe_gc(v7)) {
Marko Mikulicic 0:c0ecb8bf28eb 20439 /* GC is inhibited, so, schedule invocation for later */
Marko Mikulicic 0:c0ecb8bf28eb 20440 v7->need_gc = 1;
Marko Mikulicic 0:c0ecb8bf28eb 20441 }
Marko Mikulicic 0:c0ecb8bf28eb 20442
Marko Mikulicic 0:c0ecb8bf28eb 20443 if (a->free == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 20444 struct gc_block *b = gc_new_block(a, a->size_increment);
Marko Mikulicic 0:c0ecb8bf28eb 20445 b->next = a->blocks;
Marko Mikulicic 0:c0ecb8bf28eb 20446 a->blocks = b;
Marko Mikulicic 0:c0ecb8bf28eb 20447 }
Marko Mikulicic 0:c0ecb8bf28eb 20448 }
Marko Mikulicic 0:c0ecb8bf28eb 20449 r = a->free;
Marko Mikulicic 0:c0ecb8bf28eb 20450
Marko Mikulicic 0:c0ecb8bf28eb 20451 UNMARK(r);
Marko Mikulicic 0:c0ecb8bf28eb 20452
Marko Mikulicic 0:c0ecb8bf28eb 20453 a->free = r->head.link;
Marko Mikulicic 0:c0ecb8bf28eb 20454
Marko Mikulicic 0:c0ecb8bf28eb 20455 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 20456 a->allocations++;
Marko Mikulicic 0:c0ecb8bf28eb 20457 a->alive++;
Marko Mikulicic 0:c0ecb8bf28eb 20458 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20459
Marko Mikulicic 0:c0ecb8bf28eb 20460 /*
Marko Mikulicic 0:c0ecb8bf28eb 20461 * TODO(mkm): minor opt possible since most of the fields
Marko Mikulicic 0:c0ecb8bf28eb 20462 * are overwritten downstream, but not worth the yak shave time
Marko Mikulicic 0:c0ecb8bf28eb 20463 * when fields are added to GC-able structures */
Marko Mikulicic 0:c0ecb8bf28eb 20464 memset(r, 0, a->cell_size);
Marko Mikulicic 0:c0ecb8bf28eb 20465 return (void *) r;
Marko Mikulicic 0:c0ecb8bf28eb 20466 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20467 }
Marko Mikulicic 0:c0ecb8bf28eb 20468
Marko Mikulicic 0:c0ecb8bf28eb 20469 #ifdef V7_MALLOC_GC
Marko Mikulicic 0:c0ecb8bf28eb 20470 /*
Marko Mikulicic 0:c0ecb8bf28eb 20471 * Scans trough the memory blocks registered in the malloc trace.
Marko Mikulicic 0:c0ecb8bf28eb 20472 * Free the unmarked ones and reset the mark on the rest.
Marko Mikulicic 0:c0ecb8bf28eb 20473 */
Marko Mikulicic 0:c0ecb8bf28eb 20474 void gc_sweep_malloc(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 20475 struct gc_cell **cur;
Marko Mikulicic 0:c0ecb8bf28eb 20476 for (cur = (struct gc_cell **) v7->malloc_trace.buf;
Marko Mikulicic 0:c0ecb8bf28eb 20477 cur < (struct gc_cell **) (v7->malloc_trace.buf + v7->malloc_trace.len);
Marko Mikulicic 0:c0ecb8bf28eb 20478 cur++) {
Marko Mikulicic 0:c0ecb8bf28eb 20479 if (*cur == NULL) continue;
Marko Mikulicic 0:c0ecb8bf28eb 20480
Marko Mikulicic 0:c0ecb8bf28eb 20481 if (MARKED(*cur)) {
Marko Mikulicic 0:c0ecb8bf28eb 20482 UNMARK(*cur);
Marko Mikulicic 0:c0ecb8bf28eb 20483 } else {
Marko Mikulicic 0:c0ecb8bf28eb 20484 free(*cur);
Marko Mikulicic 0:c0ecb8bf28eb 20485 /* TODO(mkm): compact malloc trace buffer */
Marko Mikulicic 0:c0ecb8bf28eb 20486 *cur = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 20487 }
Marko Mikulicic 0:c0ecb8bf28eb 20488 }
Marko Mikulicic 0:c0ecb8bf28eb 20489 }
Marko Mikulicic 0:c0ecb8bf28eb 20490 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20491
Marko Mikulicic 0:c0ecb8bf28eb 20492 /*
Marko Mikulicic 0:c0ecb8bf28eb 20493 * Scans the arena and add all unmarked cells to the free list.
Marko Mikulicic 0:c0ecb8bf28eb 20494 *
Marko Mikulicic 0:c0ecb8bf28eb 20495 * Empty blocks get deallocated. The head of the free list will contais cells
Marko Mikulicic 0:c0ecb8bf28eb 20496 * from the last (oldest) block. Cells will thus be allocated in block order.
Marko Mikulicic 0:c0ecb8bf28eb 20497 */
Marko Mikulicic 0:c0ecb8bf28eb 20498 void gc_sweep(struct v7 *v7, struct gc_arena *a, size_t start) {
Marko Mikulicic 0:c0ecb8bf28eb 20499 struct gc_block *b;
Marko Mikulicic 0:c0ecb8bf28eb 20500 struct gc_cell *cur;
Marko Mikulicic 0:c0ecb8bf28eb 20501 struct gc_block **prevp = &a->blocks;
Marko Mikulicic 0:c0ecb8bf28eb 20502 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 20503 a->alive = 0;
Marko Mikulicic 0:c0ecb8bf28eb 20504 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20505
Marko Mikulicic 0:c0ecb8bf28eb 20506 /*
Marko Mikulicic 0:c0ecb8bf28eb 20507 * Before we sweep, we should mark all free cells in a way that is
Marko Mikulicic 0:c0ecb8bf28eb 20508 * distinguishable from marked used cells.
Marko Mikulicic 0:c0ecb8bf28eb 20509 */
Marko Mikulicic 0:c0ecb8bf28eb 20510 {
Marko Mikulicic 0:c0ecb8bf28eb 20511 struct gc_cell *next;
Marko Mikulicic 0:c0ecb8bf28eb 20512 for (cur = a->free; cur != NULL; cur = next) {
Marko Mikulicic 0:c0ecb8bf28eb 20513 next = cur->head.link;
Marko Mikulicic 0:c0ecb8bf28eb 20514 MARK_FREE(cur);
Marko Mikulicic 0:c0ecb8bf28eb 20515 }
Marko Mikulicic 0:c0ecb8bf28eb 20516 }
Marko Mikulicic 0:c0ecb8bf28eb 20517
Marko Mikulicic 0:c0ecb8bf28eb 20518 /*
Marko Mikulicic 0:c0ecb8bf28eb 20519 * We'll rebuild the whole `free` list, so initially we just reset it
Marko Mikulicic 0:c0ecb8bf28eb 20520 */
Marko Mikulicic 0:c0ecb8bf28eb 20521 a->free = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 20522
Marko Mikulicic 0:c0ecb8bf28eb 20523 for (b = a->blocks; b != NULL;) {
Marko Mikulicic 0:c0ecb8bf28eb 20524 size_t freed_in_block = 0;
Marko Mikulicic 0:c0ecb8bf28eb 20525 /*
Marko Mikulicic 0:c0ecb8bf28eb 20526 * if it turns out that this block is 100% garbage
Marko Mikulicic 0:c0ecb8bf28eb 20527 * we can release the whole block, but the addition
Marko Mikulicic 0:c0ecb8bf28eb 20528 * of it's cells to the free list has to be undone.
Marko Mikulicic 0:c0ecb8bf28eb 20529 */
Marko Mikulicic 0:c0ecb8bf28eb 20530 struct gc_cell *prev_free = a->free;
Marko Mikulicic 0:c0ecb8bf28eb 20531
Marko Mikulicic 0:c0ecb8bf28eb 20532 for (cur = GC_CELL_OP(a, b->base, +, start);
Marko Mikulicic 0:c0ecb8bf28eb 20533 cur < GC_CELL_OP(a, b->base, +, b->size);
Marko Mikulicic 0:c0ecb8bf28eb 20534 cur = GC_CELL_OP(a, cur, +, 1)) {
Marko Mikulicic 0:c0ecb8bf28eb 20535 if (MARKED(cur)) {
Marko Mikulicic 0:c0ecb8bf28eb 20536 /* The cell is used and marked */
Marko Mikulicic 0:c0ecb8bf28eb 20537 UNMARK(cur);
Marko Mikulicic 0:c0ecb8bf28eb 20538 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 20539 a->alive++;
Marko Mikulicic 0:c0ecb8bf28eb 20540 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20541 } else {
Marko Mikulicic 0:c0ecb8bf28eb 20542 /*
Marko Mikulicic 0:c0ecb8bf28eb 20543 * The cell is either:
Marko Mikulicic 0:c0ecb8bf28eb 20544 * - free
Marko Mikulicic 0:c0ecb8bf28eb 20545 * - garbage that's about to be freed
Marko Mikulicic 0:c0ecb8bf28eb 20546 */
Marko Mikulicic 0:c0ecb8bf28eb 20547
Marko Mikulicic 0:c0ecb8bf28eb 20548 if (MARKED_FREE(cur)) {
Marko Mikulicic 0:c0ecb8bf28eb 20549 /* The cell is free, so, just unmark it */
Marko Mikulicic 0:c0ecb8bf28eb 20550 UNMARK_FREE(cur);
Marko Mikulicic 0:c0ecb8bf28eb 20551 } else {
Marko Mikulicic 0:c0ecb8bf28eb 20552 /*
Marko Mikulicic 0:c0ecb8bf28eb 20553 * The cell is used and should be freed: call the destructor and
Marko Mikulicic 0:c0ecb8bf28eb 20554 * reset the memory
Marko Mikulicic 0:c0ecb8bf28eb 20555 */
Marko Mikulicic 0:c0ecb8bf28eb 20556 if (a->destructor != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 20557 a->destructor(v7, cur);
Marko Mikulicic 0:c0ecb8bf28eb 20558 }
Marko Mikulicic 0:c0ecb8bf28eb 20559 memset(cur, 0, a->cell_size);
Marko Mikulicic 0:c0ecb8bf28eb 20560 }
Marko Mikulicic 0:c0ecb8bf28eb 20561
Marko Mikulicic 0:c0ecb8bf28eb 20562 /* Add this cell to the `free` list */
Marko Mikulicic 0:c0ecb8bf28eb 20563 cur->head.link = a->free;
Marko Mikulicic 0:c0ecb8bf28eb 20564 a->free = cur;
Marko Mikulicic 0:c0ecb8bf28eb 20565 freed_in_block++;
Marko Mikulicic 0:c0ecb8bf28eb 20566 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 20567 a->garbage++;
Marko Mikulicic 0:c0ecb8bf28eb 20568 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20569 }
Marko Mikulicic 0:c0ecb8bf28eb 20570 }
Marko Mikulicic 0:c0ecb8bf28eb 20571
Marko Mikulicic 0:c0ecb8bf28eb 20572 /*
Marko Mikulicic 0:c0ecb8bf28eb 20573 * don't free the initial block, which is at the tail
Marko Mikulicic 0:c0ecb8bf28eb 20574 * because it has a special size aimed at reducing waste
Marko Mikulicic 0:c0ecb8bf28eb 20575 * and simplifying initial startup. TODO(mkm): improve
Marko Mikulicic 0:c0ecb8bf28eb 20576 * */
Marko Mikulicic 0:c0ecb8bf28eb 20577 if (b->next != NULL && freed_in_block == b->size) {
Marko Mikulicic 0:c0ecb8bf28eb 20578 *prevp = b->next;
Marko Mikulicic 0:c0ecb8bf28eb 20579 gc_free_block(b);
Marko Mikulicic 0:c0ecb8bf28eb 20580 b = *prevp;
Marko Mikulicic 0:c0ecb8bf28eb 20581 a->free = prev_free;
Marko Mikulicic 0:c0ecb8bf28eb 20582 } else {
Marko Mikulicic 0:c0ecb8bf28eb 20583 prevp = &b->next;
Marko Mikulicic 0:c0ecb8bf28eb 20584 b = b->next;
Marko Mikulicic 0:c0ecb8bf28eb 20585 }
Marko Mikulicic 0:c0ecb8bf28eb 20586 }
Marko Mikulicic 0:c0ecb8bf28eb 20587 }
Marko Mikulicic 0:c0ecb8bf28eb 20588
Marko Mikulicic 0:c0ecb8bf28eb 20589 /*
Marko Mikulicic 0:c0ecb8bf28eb 20590 * dense arrays contain only one property pointing to an mbuf with array values.
Marko Mikulicic 0:c0ecb8bf28eb 20591 */
Marko Mikulicic 0:c0ecb8bf28eb 20592 V7_PRIVATE void gc_mark_dense_array(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 20593 struct v7_generic_object *obj) {
Marko Mikulicic 0:c0ecb8bf28eb 20594 val_t v;
Marko Mikulicic 0:c0ecb8bf28eb 20595 struct mbuf *mbuf;
Marko Mikulicic 0:c0ecb8bf28eb 20596 val_t *vp;
Marko Mikulicic 0:c0ecb8bf28eb 20597
Marko Mikulicic 0:c0ecb8bf28eb 20598 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 20599 /* TODO(mkm): use this when dense array promotion is implemented */
Marko Mikulicic 0:c0ecb8bf28eb 20600 v = obj->properties->value;
Marko Mikulicic 0:c0ecb8bf28eb 20601 #else
Marko Mikulicic 0:c0ecb8bf28eb 20602 v = v7_get(v7, v7_object_to_value(&obj->base), "", 0);
Marko Mikulicic 0:c0ecb8bf28eb 20603 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20604
Marko Mikulicic 0:c0ecb8bf28eb 20605 mbuf = (struct mbuf *) v7_get_ptr(v7, v);
Marko Mikulicic 0:c0ecb8bf28eb 20606
Marko Mikulicic 0:c0ecb8bf28eb 20607 /* function scope pointer is aliased to the object's prototype pointer */
Marko Mikulicic 0:c0ecb8bf28eb 20608 gc_mark(v7, v7_object_to_value(obj_prototype(v7, &obj->base)));
Marko Mikulicic 0:c0ecb8bf28eb 20609 MARK(obj);
Marko Mikulicic 0:c0ecb8bf28eb 20610
Marko Mikulicic 0:c0ecb8bf28eb 20611 if (mbuf == NULL) return;
Marko Mikulicic 0:c0ecb8bf28eb 20612 for (vp = (val_t *) mbuf->buf; (char *) vp < mbuf->buf + mbuf->len; vp++) {
Marko Mikulicic 0:c0ecb8bf28eb 20613 gc_mark(v7, *vp);
Marko Mikulicic 0:c0ecb8bf28eb 20614 gc_mark_string(v7, vp);
Marko Mikulicic 0:c0ecb8bf28eb 20615 }
Marko Mikulicic 0:c0ecb8bf28eb 20616 UNMARK(obj);
Marko Mikulicic 0:c0ecb8bf28eb 20617 }
Marko Mikulicic 0:c0ecb8bf28eb 20618
Marko Mikulicic 0:c0ecb8bf28eb 20619 V7_PRIVATE void gc_mark(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 20620 struct v7_object *obj_base;
Marko Mikulicic 0:c0ecb8bf28eb 20621 struct v7_property *prop;
Marko Mikulicic 0:c0ecb8bf28eb 20622 struct v7_property *next;
Marko Mikulicic 0:c0ecb8bf28eb 20623
Marko Mikulicic 0:c0ecb8bf28eb 20624 if (!v7_is_object(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 20625 return;
Marko Mikulicic 0:c0ecb8bf28eb 20626 }
Marko Mikulicic 0:c0ecb8bf28eb 20627 obj_base = get_object_struct(v);
Marko Mikulicic 0:c0ecb8bf28eb 20628
Marko Mikulicic 0:c0ecb8bf28eb 20629 /*
Marko Mikulicic 0:c0ecb8bf28eb 20630 * we ignore objects that are not managed by V7 heap, such as frozen
Marko Mikulicic 0:c0ecb8bf28eb 20631 * objects, especially when on flash.
Marko Mikulicic 0:c0ecb8bf28eb 20632 */
Marko Mikulicic 0:c0ecb8bf28eb 20633 if (obj_base->attributes & V7_OBJ_OFF_HEAP) {
Marko Mikulicic 0:c0ecb8bf28eb 20634 return;
Marko Mikulicic 0:c0ecb8bf28eb 20635 }
Marko Mikulicic 0:c0ecb8bf28eb 20636
Marko Mikulicic 0:c0ecb8bf28eb 20637 /*
Marko Mikulicic 0:c0ecb8bf28eb 20638 * we treat all object like things like objects but they might be functions,
Marko Mikulicic 0:c0ecb8bf28eb 20639 * gc_gheck_val checks the appropriate arena per actual value type.
Marko Mikulicic 0:c0ecb8bf28eb 20640 */
Marko Mikulicic 0:c0ecb8bf28eb 20641 if (!gc_check_val(v7, v)) {
Marko Mikulicic 0:c0ecb8bf28eb 20642 abort();
Marko Mikulicic 0:c0ecb8bf28eb 20643 }
Marko Mikulicic 0:c0ecb8bf28eb 20644
Marko Mikulicic 0:c0ecb8bf28eb 20645 if (MARKED(obj_base)) return;
Marko Mikulicic 0:c0ecb8bf28eb 20646
Marko Mikulicic 0:c0ecb8bf28eb 20647 #ifdef V7_FREEZE
Marko Mikulicic 0:c0ecb8bf28eb 20648 if (v7->freeze_file != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 20649 freeze_obj(v7, v7->freeze_file, v);
Marko Mikulicic 0:c0ecb8bf28eb 20650 }
Marko Mikulicic 0:c0ecb8bf28eb 20651 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20652
Marko Mikulicic 0:c0ecb8bf28eb 20653 if (obj_base->attributes & V7_OBJ_DENSE_ARRAY) {
Marko Mikulicic 0:c0ecb8bf28eb 20654 struct v7_generic_object *obj = get_generic_object_struct(v);
Marko Mikulicic 0:c0ecb8bf28eb 20655 gc_mark_dense_array(v7, obj);
Marko Mikulicic 0:c0ecb8bf28eb 20656 }
Marko Mikulicic 0:c0ecb8bf28eb 20657
Marko Mikulicic 0:c0ecb8bf28eb 20658 /* mark object itself, and its properties */
Marko Mikulicic 0:c0ecb8bf28eb 20659 for ((prop = obj_base->properties), MARK(obj_base); prop != NULL;
Marko Mikulicic 0:c0ecb8bf28eb 20660 prop = next) {
Marko Mikulicic 0:c0ecb8bf28eb 20661 if (prop->attributes & _V7_PROPERTY_OFF_HEAP) {
Marko Mikulicic 0:c0ecb8bf28eb 20662 break;
Marko Mikulicic 0:c0ecb8bf28eb 20663 }
Marko Mikulicic 0:c0ecb8bf28eb 20664
Marko Mikulicic 0:c0ecb8bf28eb 20665 if (!gc_check_ptr(&v7->property_arena, prop)) {
Marko Mikulicic 0:c0ecb8bf28eb 20666 abort();
Marko Mikulicic 0:c0ecb8bf28eb 20667 }
Marko Mikulicic 0:c0ecb8bf28eb 20668
Marko Mikulicic 0:c0ecb8bf28eb 20669 #ifdef V7_FREEZE
Marko Mikulicic 0:c0ecb8bf28eb 20670 if (v7->freeze_file != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 20671 freeze_prop(v7, v7->freeze_file, prop);
Marko Mikulicic 0:c0ecb8bf28eb 20672 }
Marko Mikulicic 0:c0ecb8bf28eb 20673 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20674
Marko Mikulicic 0:c0ecb8bf28eb 20675 gc_mark_string(v7, &prop->value);
Marko Mikulicic 0:c0ecb8bf28eb 20676 gc_mark_string(v7, &prop->name);
Marko Mikulicic 0:c0ecb8bf28eb 20677 gc_mark(v7, prop->value);
Marko Mikulicic 0:c0ecb8bf28eb 20678
Marko Mikulicic 0:c0ecb8bf28eb 20679 next = prop->next;
Marko Mikulicic 0:c0ecb8bf28eb 20680 MARK(prop);
Marko Mikulicic 0:c0ecb8bf28eb 20681 }
Marko Mikulicic 0:c0ecb8bf28eb 20682
Marko Mikulicic 0:c0ecb8bf28eb 20683 /* mark object's prototype */
Marko Mikulicic 0:c0ecb8bf28eb 20684 gc_mark(v7, v7_get_proto(v7, v));
Marko Mikulicic 0:c0ecb8bf28eb 20685
Marko Mikulicic 0:c0ecb8bf28eb 20686 if (is_js_function(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 20687 struct v7_js_function *func = get_js_function_struct(v);
Marko Mikulicic 0:c0ecb8bf28eb 20688
Marko Mikulicic 0:c0ecb8bf28eb 20689 /* mark function's scope */
Marko Mikulicic 0:c0ecb8bf28eb 20690 gc_mark(v7, v7_object_to_value(&func->scope->base));
Marko Mikulicic 0:c0ecb8bf28eb 20691
Marko Mikulicic 0:c0ecb8bf28eb 20692 if (func->bcode != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 20693 gc_mark_vec_val(v7, &func->bcode->lit);
Marko Mikulicic 0:c0ecb8bf28eb 20694 }
Marko Mikulicic 0:c0ecb8bf28eb 20695 }
Marko Mikulicic 0:c0ecb8bf28eb 20696 }
Marko Mikulicic 0:c0ecb8bf28eb 20697
Marko Mikulicic 0:c0ecb8bf28eb 20698 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 20699
Marko Mikulicic 0:c0ecb8bf28eb 20700 V7_PRIVATE size_t gc_arena_size(struct gc_arena *a) {
Marko Mikulicic 0:c0ecb8bf28eb 20701 size_t size = 0;
Marko Mikulicic 0:c0ecb8bf28eb 20702 struct gc_block *b;
Marko Mikulicic 0:c0ecb8bf28eb 20703 for (b = a->blocks; b != NULL; b = b->next) {
Marko Mikulicic 0:c0ecb8bf28eb 20704 size += b->size;
Marko Mikulicic 0:c0ecb8bf28eb 20705 }
Marko Mikulicic 0:c0ecb8bf28eb 20706 return size;
Marko Mikulicic 0:c0ecb8bf28eb 20707 }
Marko Mikulicic 0:c0ecb8bf28eb 20708
Marko Mikulicic 0:c0ecb8bf28eb 20709 /*
Marko Mikulicic 0:c0ecb8bf28eb 20710 * TODO(dfrank): move to core
Marko Mikulicic 0:c0ecb8bf28eb 20711 */
Marko Mikulicic 0:c0ecb8bf28eb 20712 int v7_heap_stat(struct v7 *v7, enum v7_heap_stat_what what) {
Marko Mikulicic 0:c0ecb8bf28eb 20713 switch (what) {
Marko Mikulicic 0:c0ecb8bf28eb 20714 case V7_HEAP_STAT_HEAP_SIZE:
Marko Mikulicic 0:c0ecb8bf28eb 20715 return gc_arena_size(&v7->generic_object_arena) *
Marko Mikulicic 0:c0ecb8bf28eb 20716 v7->generic_object_arena.cell_size +
Marko Mikulicic 0:c0ecb8bf28eb 20717 gc_arena_size(&v7->function_arena) * v7->function_arena.cell_size +
Marko Mikulicic 0:c0ecb8bf28eb 20718 gc_arena_size(&v7->property_arena) * v7->property_arena.cell_size;
Marko Mikulicic 0:c0ecb8bf28eb 20719 case V7_HEAP_STAT_HEAP_USED:
Marko Mikulicic 0:c0ecb8bf28eb 20720 return v7->generic_object_arena.alive *
Marko Mikulicic 0:c0ecb8bf28eb 20721 v7->generic_object_arena.cell_size +
Marko Mikulicic 0:c0ecb8bf28eb 20722 v7->function_arena.alive * v7->function_arena.cell_size +
Marko Mikulicic 0:c0ecb8bf28eb 20723 v7->property_arena.alive * v7->property_arena.cell_size;
Marko Mikulicic 0:c0ecb8bf28eb 20724 case V7_HEAP_STAT_STRING_HEAP_RESERVED:
Marko Mikulicic 0:c0ecb8bf28eb 20725 return v7->owned_strings.size;
Marko Mikulicic 0:c0ecb8bf28eb 20726 case V7_HEAP_STAT_STRING_HEAP_USED:
Marko Mikulicic 0:c0ecb8bf28eb 20727 return v7->owned_strings.len;
Marko Mikulicic 0:c0ecb8bf28eb 20728 case V7_HEAP_STAT_OBJ_HEAP_MAX:
Marko Mikulicic 0:c0ecb8bf28eb 20729 return gc_arena_size(&v7->generic_object_arena);
Marko Mikulicic 0:c0ecb8bf28eb 20730 case V7_HEAP_STAT_OBJ_HEAP_FREE:
Marko Mikulicic 0:c0ecb8bf28eb 20731 return gc_arena_size(&v7->generic_object_arena) -
Marko Mikulicic 0:c0ecb8bf28eb 20732 v7->generic_object_arena.alive;
Marko Mikulicic 0:c0ecb8bf28eb 20733 case V7_HEAP_STAT_OBJ_HEAP_CELL_SIZE:
Marko Mikulicic 0:c0ecb8bf28eb 20734 return v7->generic_object_arena.cell_size;
Marko Mikulicic 0:c0ecb8bf28eb 20735 case V7_HEAP_STAT_FUNC_HEAP_MAX:
Marko Mikulicic 0:c0ecb8bf28eb 20736 return gc_arena_size(&v7->function_arena);
Marko Mikulicic 0:c0ecb8bf28eb 20737 case V7_HEAP_STAT_FUNC_HEAP_FREE:
Marko Mikulicic 0:c0ecb8bf28eb 20738 return gc_arena_size(&v7->function_arena) - v7->function_arena.alive;
Marko Mikulicic 0:c0ecb8bf28eb 20739 case V7_HEAP_STAT_FUNC_HEAP_CELL_SIZE:
Marko Mikulicic 0:c0ecb8bf28eb 20740 return v7->function_arena.cell_size;
Marko Mikulicic 0:c0ecb8bf28eb 20741 case V7_HEAP_STAT_PROP_HEAP_MAX:
Marko Mikulicic 0:c0ecb8bf28eb 20742 return gc_arena_size(&v7->property_arena);
Marko Mikulicic 0:c0ecb8bf28eb 20743 case V7_HEAP_STAT_PROP_HEAP_FREE:
Marko Mikulicic 0:c0ecb8bf28eb 20744 return gc_arena_size(&v7->property_arena) - v7->property_arena.alive;
Marko Mikulicic 0:c0ecb8bf28eb 20745 case V7_HEAP_STAT_PROP_HEAP_CELL_SIZE:
Marko Mikulicic 0:c0ecb8bf28eb 20746 return v7->property_arena.cell_size;
Marko Mikulicic 0:c0ecb8bf28eb 20747 case V7_HEAP_STAT_FUNC_AST_SIZE:
Marko Mikulicic 0:c0ecb8bf28eb 20748 return v7->function_arena_ast_size;
Marko Mikulicic 0:c0ecb8bf28eb 20749 case V7_HEAP_STAT_BCODE_OPS_SIZE:
Marko Mikulicic 0:c0ecb8bf28eb 20750 return v7->bcode_ops_size;
Marko Mikulicic 0:c0ecb8bf28eb 20751 case V7_HEAP_STAT_BCODE_LIT_TOTAL_SIZE:
Marko Mikulicic 0:c0ecb8bf28eb 20752 return v7->bcode_lit_total_size;
Marko Mikulicic 0:c0ecb8bf28eb 20753 case V7_HEAP_STAT_BCODE_LIT_DESER_SIZE:
Marko Mikulicic 0:c0ecb8bf28eb 20754 return v7->bcode_lit_deser_size;
Marko Mikulicic 0:c0ecb8bf28eb 20755 case V7_HEAP_STAT_FUNC_OWNED:
Marko Mikulicic 0:c0ecb8bf28eb 20756 return v7->owned_values.len / sizeof(val_t *);
Marko Mikulicic 0:c0ecb8bf28eb 20757 case V7_HEAP_STAT_FUNC_OWNED_MAX:
Marko Mikulicic 0:c0ecb8bf28eb 20758 return v7->owned_values.size / sizeof(val_t *);
Marko Mikulicic 0:c0ecb8bf28eb 20759 }
Marko Mikulicic 0:c0ecb8bf28eb 20760
Marko Mikulicic 0:c0ecb8bf28eb 20761 return -1;
Marko Mikulicic 0:c0ecb8bf28eb 20762 }
Marko Mikulicic 0:c0ecb8bf28eb 20763 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20764
Marko Mikulicic 0:c0ecb8bf28eb 20765 V7_PRIVATE void gc_dump_arena_stats(const char *msg, struct gc_arena *a) {
Marko Mikulicic 0:c0ecb8bf28eb 20766 (void) msg;
Marko Mikulicic 0:c0ecb8bf28eb 20767 (void) a;
Marko Mikulicic 0:c0ecb8bf28eb 20768 #ifndef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 20769 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 20770 if (a->verbose) {
Marko Mikulicic 0:c0ecb8bf28eb 20771 fprintf(stderr, "%s: total allocations %lu, max %lu, alive %lu\n", msg,
Marko Mikulicic 0:c0ecb8bf28eb 20772 (long unsigned int) a->allocations,
Marko Mikulicic 0:c0ecb8bf28eb 20773 (long unsigned int) gc_arena_size(a), (long unsigned int) a->alive);
Marko Mikulicic 0:c0ecb8bf28eb 20774 }
Marko Mikulicic 0:c0ecb8bf28eb 20775 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20776 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20777 }
Marko Mikulicic 0:c0ecb8bf28eb 20778
Marko Mikulicic 0:c0ecb8bf28eb 20779 V7_PRIVATE uint64_t gc_string_val_to_offset(val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 20780 return (((uint64_t)(uintptr_t) get_ptr(v)) & ~V7_TAG_MASK)
Marko Mikulicic 0:c0ecb8bf28eb 20781 #ifndef V7_DISABLE_STR_ALLOC_SEQ
Marko Mikulicic 0:c0ecb8bf28eb 20782 & 0xFFFFFFFF
Marko Mikulicic 0:c0ecb8bf28eb 20783 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20784 ;
Marko Mikulicic 0:c0ecb8bf28eb 20785 }
Marko Mikulicic 0:c0ecb8bf28eb 20786
Marko Mikulicic 0:c0ecb8bf28eb 20787 V7_PRIVATE val_t gc_string_val_from_offset(uint64_t s) {
Marko Mikulicic 0:c0ecb8bf28eb 20788 return s | V7_TAG_STRING_O;
Marko Mikulicic 0:c0ecb8bf28eb 20789 }
Marko Mikulicic 0:c0ecb8bf28eb 20790
Marko Mikulicic 0:c0ecb8bf28eb 20791 #ifndef V7_DISABLE_STR_ALLOC_SEQ
Marko Mikulicic 0:c0ecb8bf28eb 20792
Marko Mikulicic 0:c0ecb8bf28eb 20793 static uint16_t next_asn(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 20794 if (v7->gc_next_asn == 0xFFFF) {
Marko Mikulicic 0:c0ecb8bf28eb 20795 /* Wrap around explicitly. */
Marko Mikulicic 0:c0ecb8bf28eb 20796 v7->gc_next_asn = 0;
Marko Mikulicic 0:c0ecb8bf28eb 20797 return 0xFFFF;
Marko Mikulicic 0:c0ecb8bf28eb 20798 }
Marko Mikulicic 0:c0ecb8bf28eb 20799 return v7->gc_next_asn++;
Marko Mikulicic 0:c0ecb8bf28eb 20800 }
Marko Mikulicic 0:c0ecb8bf28eb 20801
Marko Mikulicic 0:c0ecb8bf28eb 20802 uint16_t gc_next_allocation_seqn(struct v7 *v7, const char *str, size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 20803 uint16_t asn = next_asn(v7);
Marko Mikulicic 0:c0ecb8bf28eb 20804 (void) str;
Marko Mikulicic 0:c0ecb8bf28eb 20805 (void) len;
Marko Mikulicic 0:c0ecb8bf28eb 20806 #ifdef V7_GC_VERBOSE
Marko Mikulicic 0:c0ecb8bf28eb 20807 /*
Marko Mikulicic 0:c0ecb8bf28eb 20808 * ESP SDK printf cannot cope with null strings
Marko Mikulicic 0:c0ecb8bf28eb 20809 * as created by s_concat.
Marko Mikulicic 0:c0ecb8bf28eb 20810 */
Marko Mikulicic 0:c0ecb8bf28eb 20811 if (str == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 20812 fprintf(stderr, "GC ASN %d: <nil>\n", asn);
Marko Mikulicic 0:c0ecb8bf28eb 20813 } else {
Marko Mikulicic 0:c0ecb8bf28eb 20814 fprintf(stderr, "GC ASN %d: \"%.*s\"\n", asn, (int) len, str);
Marko Mikulicic 0:c0ecb8bf28eb 20815 }
Marko Mikulicic 0:c0ecb8bf28eb 20816 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20817 #ifdef V7_GC_PANIC_ON_ASN
Marko Mikulicic 0:c0ecb8bf28eb 20818 if (asn == (V7_GC_PANIC_ON_ASN)) {
Marko Mikulicic 0:c0ecb8bf28eb 20819 abort();
Marko Mikulicic 0:c0ecb8bf28eb 20820 }
Marko Mikulicic 0:c0ecb8bf28eb 20821 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20822 return asn;
Marko Mikulicic 0:c0ecb8bf28eb 20823 }
Marko Mikulicic 0:c0ecb8bf28eb 20824
Marko Mikulicic 0:c0ecb8bf28eb 20825 int gc_is_valid_allocation_seqn(struct v7 *v7, uint16_t n) {
Marko Mikulicic 0:c0ecb8bf28eb 20826 /*
Marko Mikulicic 0:c0ecb8bf28eb 20827 * This functions attempts to handle integer wraparound in a naive way and
Marko Mikulicic 0:c0ecb8bf28eb 20828 * will give false positives when more than 65536 strings are allocated
Marko Mikulicic 0:c0ecb8bf28eb 20829 * between GC runs.
Marko Mikulicic 0:c0ecb8bf28eb 20830 */
Marko Mikulicic 0:c0ecb8bf28eb 20831 int r = (n >= v7->gc_min_asn && n < v7->gc_next_asn) ||
Marko Mikulicic 0:c0ecb8bf28eb 20832 (v7->gc_min_asn > v7->gc_next_asn &&
Marko Mikulicic 0:c0ecb8bf28eb 20833 (n >= v7->gc_min_asn || n < v7->gc_next_asn));
Marko Mikulicic 0:c0ecb8bf28eb 20834 if (!r) {
Marko Mikulicic 0:c0ecb8bf28eb 20835 fprintf(stderr, "GC ASN %d is not in [%d,%d)\n", n, v7->gc_min_asn,
Marko Mikulicic 0:c0ecb8bf28eb 20836 v7->gc_next_asn);
Marko Mikulicic 0:c0ecb8bf28eb 20837 }
Marko Mikulicic 0:c0ecb8bf28eb 20838 return r;
Marko Mikulicic 0:c0ecb8bf28eb 20839 }
Marko Mikulicic 0:c0ecb8bf28eb 20840
Marko Mikulicic 0:c0ecb8bf28eb 20841 void gc_check_valid_allocation_seqn(struct v7 *v7, uint16_t n) {
Marko Mikulicic 0:c0ecb8bf28eb 20842 if (!gc_is_valid_allocation_seqn(v7, n)) {
Marko Mikulicic 0:c0ecb8bf28eb 20843 /*
Marko Mikulicic 0:c0ecb8bf28eb 20844 * TODO(dfrank) throw exception if V7_GC_ASN_PANIC is not defined.
Marko Mikulicic 0:c0ecb8bf28eb 20845 */
Marko Mikulicic 0:c0ecb8bf28eb 20846 #if 0 && !defined(V7_GC_ASN_PANIC)
Marko Mikulicic 0:c0ecb8bf28eb 20847 throw_exception(v7, INTERNAL_ERROR, "Invalid ASN: %d", (int) n);
Marko Mikulicic 0:c0ecb8bf28eb 20848 #else
Marko Mikulicic 0:c0ecb8bf28eb 20849 fprintf(stderr, "Invalid ASN: %d\n", (int) n);
Marko Mikulicic 0:c0ecb8bf28eb 20850 abort();
Marko Mikulicic 0:c0ecb8bf28eb 20851 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20852 }
Marko Mikulicic 0:c0ecb8bf28eb 20853 }
Marko Mikulicic 0:c0ecb8bf28eb 20854
Marko Mikulicic 0:c0ecb8bf28eb 20855 #endif /* V7_DISABLE_STR_ALLOC_SEQ */
Marko Mikulicic 0:c0ecb8bf28eb 20856
Marko Mikulicic 0:c0ecb8bf28eb 20857 /* Mark a string value */
Marko Mikulicic 0:c0ecb8bf28eb 20858 void gc_mark_string(struct v7 *v7, val_t *v) {
Marko Mikulicic 0:c0ecb8bf28eb 20859 val_t h, tmp = 0;
Marko Mikulicic 0:c0ecb8bf28eb 20860 char *s;
Marko Mikulicic 0:c0ecb8bf28eb 20861
Marko Mikulicic 0:c0ecb8bf28eb 20862 /* clang-format off */
Marko Mikulicic 0:c0ecb8bf28eb 20863
Marko Mikulicic 0:c0ecb8bf28eb 20864 /*
Marko Mikulicic 0:c0ecb8bf28eb 20865 * If a value points to an unmarked string we shall:
Marko Mikulicic 0:c0ecb8bf28eb 20866 * 1. save the first 6 bytes of the string
Marko Mikulicic 0:c0ecb8bf28eb 20867 * since we need to be able to distinguish real values from
Marko Mikulicic 0:c0ecb8bf28eb 20868 * the saved first 6 bytes of the string, we need to tag the chunk
Marko Mikulicic 0:c0ecb8bf28eb 20869 * as V7_TAG_STRING_C
Marko Mikulicic 0:c0ecb8bf28eb 20870 * 2. encode value's address (v) into the first 6 bytes of the string.
Marko Mikulicic 0:c0ecb8bf28eb 20871 * 3. put the saved 8 bytes (tag + chunk) back into the value.
Marko Mikulicic 0:c0ecb8bf28eb 20872 * 4. mark the string by putting '\1' in the NUL terminator of the previous
Marko Mikulicic 0:c0ecb8bf28eb 20873 * string chunk.
Marko Mikulicic 0:c0ecb8bf28eb 20874 *
Marko Mikulicic 0:c0ecb8bf28eb 20875 * If a value points to an already marked string we shall:
Marko Mikulicic 0:c0ecb8bf28eb 20876 * (0, <6 bytes of a pointer to a val_t>), hence we have to skip
Marko Mikulicic 0:c0ecb8bf28eb 20877 * the first byte. We tag the value pointer as a V7_TAG_FOREIGN
Marko Mikulicic 0:c0ecb8bf28eb 20878 * so that it won't be followed during recursive mark.
Marko Mikulicic 0:c0ecb8bf28eb 20879 *
Marko Mikulicic 0:c0ecb8bf28eb 20880 * ... the rest is the same
Marko Mikulicic 0:c0ecb8bf28eb 20881 *
Marko Mikulicic 0:c0ecb8bf28eb 20882 * Note: 64-bit pointers can be represented with 48-bits
Marko Mikulicic 0:c0ecb8bf28eb 20883 */
Marko Mikulicic 0:c0ecb8bf28eb 20884
Marko Mikulicic 0:c0ecb8bf28eb 20885 /* clang-format on */
Marko Mikulicic 0:c0ecb8bf28eb 20886
Marko Mikulicic 0:c0ecb8bf28eb 20887 if ((*v & V7_TAG_MASK) != V7_TAG_STRING_O) {
Marko Mikulicic 0:c0ecb8bf28eb 20888 return;
Marko Mikulicic 0:c0ecb8bf28eb 20889 }
Marko Mikulicic 0:c0ecb8bf28eb 20890
Marko Mikulicic 0:c0ecb8bf28eb 20891 #ifdef V7_FREEZE
Marko Mikulicic 0:c0ecb8bf28eb 20892 if (v7->freeze_file != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 20893 return;
Marko Mikulicic 0:c0ecb8bf28eb 20894 }
Marko Mikulicic 0:c0ecb8bf28eb 20895 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20896
Marko Mikulicic 0:c0ecb8bf28eb 20897 #ifdef V7_GC_VERBOSE
Marko Mikulicic 0:c0ecb8bf28eb 20898 {
Marko Mikulicic 0:c0ecb8bf28eb 20899 uint16_t asn = (*v >> 32) & 0xFFFF;
Marko Mikulicic 0:c0ecb8bf28eb 20900 size_t size;
Marko Mikulicic 0:c0ecb8bf28eb 20901 fprintf(stderr, "GC marking ASN %d: '%s'\n", asn,
Marko Mikulicic 0:c0ecb8bf28eb 20902 v7_get_string(v7, v, &size));
Marko Mikulicic 0:c0ecb8bf28eb 20903 }
Marko Mikulicic 0:c0ecb8bf28eb 20904 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20905
Marko Mikulicic 0:c0ecb8bf28eb 20906 #ifndef V7_DISABLE_STR_ALLOC_SEQ
Marko Mikulicic 0:c0ecb8bf28eb 20907 gc_check_valid_allocation_seqn(v7, (*v >> 32) & 0xFFFF);
Marko Mikulicic 0:c0ecb8bf28eb 20908 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20909
Marko Mikulicic 0:c0ecb8bf28eb 20910 s = v7->owned_strings.buf + gc_string_val_to_offset(*v);
Marko Mikulicic 0:c0ecb8bf28eb 20911 assert(s < v7->owned_strings.buf + v7->owned_strings.len);
Marko Mikulicic 0:c0ecb8bf28eb 20912 if (s[-1] == '\0') {
Marko Mikulicic 0:c0ecb8bf28eb 20913 memcpy(&tmp, s, sizeof(tmp) - 2);
Marko Mikulicic 0:c0ecb8bf28eb 20914 tmp |= V7_TAG_STRING_C;
Marko Mikulicic 0:c0ecb8bf28eb 20915 } else {
Marko Mikulicic 0:c0ecb8bf28eb 20916 memcpy(&tmp, s, sizeof(tmp) - 2);
Marko Mikulicic 0:c0ecb8bf28eb 20917 tmp |= V7_TAG_FOREIGN;
Marko Mikulicic 0:c0ecb8bf28eb 20918 }
Marko Mikulicic 0:c0ecb8bf28eb 20919
Marko Mikulicic 0:c0ecb8bf28eb 20920 h = (val_t)(uintptr_t) v;
Marko Mikulicic 0:c0ecb8bf28eb 20921 s[-1] = 1;
Marko Mikulicic 0:c0ecb8bf28eb 20922 memcpy(s, &h, sizeof(h) - 2);
Marko Mikulicic 0:c0ecb8bf28eb 20923 memcpy(v, &tmp, sizeof(tmp));
Marko Mikulicic 0:c0ecb8bf28eb 20924 }
Marko Mikulicic 0:c0ecb8bf28eb 20925
Marko Mikulicic 0:c0ecb8bf28eb 20926 void gc_compact_strings(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 20927 char *p = v7->owned_strings.buf + 1;
Marko Mikulicic 0:c0ecb8bf28eb 20928 uint64_t h, next, head = 1;
Marko Mikulicic 0:c0ecb8bf28eb 20929 int len, llen;
Marko Mikulicic 0:c0ecb8bf28eb 20930
Marko Mikulicic 0:c0ecb8bf28eb 20931 #ifndef V7_DISABLE_STR_ALLOC_SEQ
Marko Mikulicic 0:c0ecb8bf28eb 20932 v7->gc_min_asn = v7->gc_next_asn;
Marko Mikulicic 0:c0ecb8bf28eb 20933 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20934 while (p < v7->owned_strings.buf + v7->owned_strings.len) {
Marko Mikulicic 0:c0ecb8bf28eb 20935 if (p[-1] == '\1') {
Marko Mikulicic 0:c0ecb8bf28eb 20936 #ifndef V7_DISABLE_STR_ALLOC_SEQ
Marko Mikulicic 0:c0ecb8bf28eb 20937 /* Not using gc_next_allocation_seqn() as we don't have full string. */
Marko Mikulicic 0:c0ecb8bf28eb 20938 uint16_t asn = next_asn(v7);
Marko Mikulicic 0:c0ecb8bf28eb 20939 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20940 /* relocate and update ptrs */
Marko Mikulicic 0:c0ecb8bf28eb 20941 h = 0;
Marko Mikulicic 0:c0ecb8bf28eb 20942 memcpy(&h, p, sizeof(h) - 2);
Marko Mikulicic 0:c0ecb8bf28eb 20943
Marko Mikulicic 0:c0ecb8bf28eb 20944 /*
Marko Mikulicic 0:c0ecb8bf28eb 20945 * relocate pointers until we find the tail.
Marko Mikulicic 0:c0ecb8bf28eb 20946 * The tail is marked with V7_TAG_STRING_C,
Marko Mikulicic 0:c0ecb8bf28eb 20947 * while val_t link pointers are tagged with V7_TAG_FOREIGN
Marko Mikulicic 0:c0ecb8bf28eb 20948 */
Marko Mikulicic 0:c0ecb8bf28eb 20949 for (; (h & V7_TAG_MASK) != V7_TAG_STRING_C; h = next) {
Marko Mikulicic 0:c0ecb8bf28eb 20950 h &= ~V7_TAG_MASK;
Marko Mikulicic 0:c0ecb8bf28eb 20951 memcpy(&next, (char *) (uintptr_t) h, sizeof(h));
Marko Mikulicic 0:c0ecb8bf28eb 20952
Marko Mikulicic 0:c0ecb8bf28eb 20953 *(val_t *) (uintptr_t) h = gc_string_val_from_offset(head)
Marko Mikulicic 0:c0ecb8bf28eb 20954 #ifndef V7_DISABLE_STR_ALLOC_SEQ
Marko Mikulicic 0:c0ecb8bf28eb 20955 | ((val_t) asn << 32)
Marko Mikulicic 0:c0ecb8bf28eb 20956 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20957 ;
Marko Mikulicic 0:c0ecb8bf28eb 20958 }
Marko Mikulicic 0:c0ecb8bf28eb 20959 h &= ~V7_TAG_MASK;
Marko Mikulicic 0:c0ecb8bf28eb 20960
Marko Mikulicic 0:c0ecb8bf28eb 20961 /*
Marko Mikulicic 0:c0ecb8bf28eb 20962 * the tail contains the first 6 bytes we stole from
Marko Mikulicic 0:c0ecb8bf28eb 20963 * the actual string.
Marko Mikulicic 0:c0ecb8bf28eb 20964 */
Marko Mikulicic 0:c0ecb8bf28eb 20965 len = decode_varint((unsigned char *) &h, &llen);
Marko Mikulicic 0:c0ecb8bf28eb 20966 len += llen + 1;
Marko Mikulicic 0:c0ecb8bf28eb 20967
Marko Mikulicic 0:c0ecb8bf28eb 20968 /*
Marko Mikulicic 0:c0ecb8bf28eb 20969 * restore the saved 6 bytes
Marko Mikulicic 0:c0ecb8bf28eb 20970 * TODO(mkm): think about endianness
Marko Mikulicic 0:c0ecb8bf28eb 20971 */
Marko Mikulicic 0:c0ecb8bf28eb 20972 memcpy(p, &h, sizeof(h) - 2);
Marko Mikulicic 0:c0ecb8bf28eb 20973
Marko Mikulicic 0:c0ecb8bf28eb 20974 /*
Marko Mikulicic 0:c0ecb8bf28eb 20975 * and relocate the string data by packing it to the left.
Marko Mikulicic 0:c0ecb8bf28eb 20976 */
Marko Mikulicic 0:c0ecb8bf28eb 20977 memmove(v7->owned_strings.buf + head, p, len);
Marko Mikulicic 0:c0ecb8bf28eb 20978 v7->owned_strings.buf[head - 1] = 0x0;
Marko Mikulicic 0:c0ecb8bf28eb 20979 #if defined(V7_GC_VERBOSE) && !defined(V7_DISABLE_STR_ALLOC_SEQ)
Marko Mikulicic 0:c0ecb8bf28eb 20980 fprintf(stderr, "GC updated ASN %d: \"%.*s\"\n", asn, len - llen - 1,
Marko Mikulicic 0:c0ecb8bf28eb 20981 v7->owned_strings.buf + head + llen);
Marko Mikulicic 0:c0ecb8bf28eb 20982 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20983 p += len;
Marko Mikulicic 0:c0ecb8bf28eb 20984 head += len;
Marko Mikulicic 0:c0ecb8bf28eb 20985 } else {
Marko Mikulicic 0:c0ecb8bf28eb 20986 len = decode_varint((unsigned char *) p, &llen);
Marko Mikulicic 0:c0ecb8bf28eb 20987 len += llen + 1;
Marko Mikulicic 0:c0ecb8bf28eb 20988
Marko Mikulicic 0:c0ecb8bf28eb 20989 p += len;
Marko Mikulicic 0:c0ecb8bf28eb 20990 }
Marko Mikulicic 0:c0ecb8bf28eb 20991 }
Marko Mikulicic 0:c0ecb8bf28eb 20992
Marko Mikulicic 0:c0ecb8bf28eb 20993 #if defined(V7_GC_VERBOSE) && !defined(V7_DISABLE_STR_ALLOC_SEQ)
Marko Mikulicic 0:c0ecb8bf28eb 20994 fprintf(stderr, "GC valid ASN range: [%d,%d)\n", v7->gc_min_asn,
Marko Mikulicic 0:c0ecb8bf28eb 20995 v7->gc_next_asn);
Marko Mikulicic 0:c0ecb8bf28eb 20996 #endif
Marko Mikulicic 0:c0ecb8bf28eb 20997
Marko Mikulicic 0:c0ecb8bf28eb 20998 v7->owned_strings.len = head;
Marko Mikulicic 0:c0ecb8bf28eb 20999 }
Marko Mikulicic 0:c0ecb8bf28eb 21000
Marko Mikulicic 0:c0ecb8bf28eb 21001 void gc_dump_owned_strings(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 21002 size_t i;
Marko Mikulicic 0:c0ecb8bf28eb 21003 for (i = 0; i < v7->owned_strings.len; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 21004 if (isprint((unsigned char) v7->owned_strings.buf[i])) {
Marko Mikulicic 0:c0ecb8bf28eb 21005 fputc(v7->owned_strings.buf[i], stderr);
Marko Mikulicic 0:c0ecb8bf28eb 21006 } else {
Marko Mikulicic 0:c0ecb8bf28eb 21007 fputc('.', stderr);
Marko Mikulicic 0:c0ecb8bf28eb 21008 }
Marko Mikulicic 0:c0ecb8bf28eb 21009 }
Marko Mikulicic 0:c0ecb8bf28eb 21010 fputc('\n', stderr);
Marko Mikulicic 0:c0ecb8bf28eb 21011 }
Marko Mikulicic 0:c0ecb8bf28eb 21012
Marko Mikulicic 0:c0ecb8bf28eb 21013 /*
Marko Mikulicic 0:c0ecb8bf28eb 21014 * builting on gcc, tried out by redefining it.
Marko Mikulicic 0:c0ecb8bf28eb 21015 * Using null pointer as base can trigger undefined behavior, hence
Marko Mikulicic 0:c0ecb8bf28eb 21016 * a portable workaround that involves a valid yet dummy pointer.
Marko Mikulicic 0:c0ecb8bf28eb 21017 * It's meant to be used as a contant expression.
Marko Mikulicic 0:c0ecb8bf28eb 21018 */
Marko Mikulicic 0:c0ecb8bf28eb 21019 #ifndef offsetof
Marko Mikulicic 0:c0ecb8bf28eb 21020 #define offsetof(st, m) (((ptrdiff_t)(&((st *) 32)->m)) - 32)
Marko Mikulicic 0:c0ecb8bf28eb 21021 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21022
Marko Mikulicic 0:c0ecb8bf28eb 21023 V7_PRIVATE void compute_need_gc(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 21024 struct mbuf *m = &v7->owned_strings;
Marko Mikulicic 0:c0ecb8bf28eb 21025 if ((double) m->len / (double) m->size > 0.9) {
Marko Mikulicic 0:c0ecb8bf28eb 21026 v7->need_gc = 1;
Marko Mikulicic 0:c0ecb8bf28eb 21027 }
Marko Mikulicic 0:c0ecb8bf28eb 21028 /* TODO(mkm): check free heap */
Marko Mikulicic 0:c0ecb8bf28eb 21029 }
Marko Mikulicic 0:c0ecb8bf28eb 21030
Marko Mikulicic 0:c0ecb8bf28eb 21031 V7_PRIVATE int maybe_gc(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 21032 if (!v7->inhibit_gc) {
Marko Mikulicic 0:c0ecb8bf28eb 21033 v7_gc(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 21034 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 21035 }
Marko Mikulicic 0:c0ecb8bf28eb 21036 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 21037 }
Marko Mikulicic 0:c0ecb8bf28eb 21038 #if defined(V7_GC_VERBOSE)
Marko Mikulicic 0:c0ecb8bf28eb 21039 static int gc_pass = 0;
Marko Mikulicic 0:c0ecb8bf28eb 21040 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21041
Marko Mikulicic 0:c0ecb8bf28eb 21042 /*
Marko Mikulicic 0:c0ecb8bf28eb 21043 * mark an array of `val_t` values (*not pointers* to them)
Marko Mikulicic 0:c0ecb8bf28eb 21044 */
Marko Mikulicic 0:c0ecb8bf28eb 21045 static void gc_mark_val_array(struct v7 *v7, val_t *vals, size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 21046 val_t *vp;
Marko Mikulicic 0:c0ecb8bf28eb 21047 for (vp = vals; vp < vals + len; vp++) {
Marko Mikulicic 0:c0ecb8bf28eb 21048 gc_mark(v7, *vp);
Marko Mikulicic 0:c0ecb8bf28eb 21049 gc_mark_string(v7, vp);
Marko Mikulicic 0:c0ecb8bf28eb 21050 }
Marko Mikulicic 0:c0ecb8bf28eb 21051 }
Marko Mikulicic 0:c0ecb8bf28eb 21052
Marko Mikulicic 0:c0ecb8bf28eb 21053 /*
Marko Mikulicic 0:c0ecb8bf28eb 21054 * mark an mbuf containing *pointers* to `val_t` values
Marko Mikulicic 0:c0ecb8bf28eb 21055 */
Marko Mikulicic 0:c0ecb8bf28eb 21056 static void gc_mark_mbuf_pt(struct v7 *v7, const struct mbuf *mbuf) {
Marko Mikulicic 0:c0ecb8bf28eb 21057 val_t **vp;
Marko Mikulicic 0:c0ecb8bf28eb 21058 for (vp = (val_t **) mbuf->buf; (char *) vp < mbuf->buf + mbuf->len; vp++) {
Marko Mikulicic 0:c0ecb8bf28eb 21059 gc_mark(v7, **vp);
Marko Mikulicic 0:c0ecb8bf28eb 21060 gc_mark_string(v7, *vp);
Marko Mikulicic 0:c0ecb8bf28eb 21061 }
Marko Mikulicic 0:c0ecb8bf28eb 21062 }
Marko Mikulicic 0:c0ecb8bf28eb 21063
Marko Mikulicic 0:c0ecb8bf28eb 21064 /*
Marko Mikulicic 0:c0ecb8bf28eb 21065 * mark an mbuf containing `val_t` values (*not pointers* to them)
Marko Mikulicic 0:c0ecb8bf28eb 21066 */
Marko Mikulicic 0:c0ecb8bf28eb 21067 static void gc_mark_mbuf_val(struct v7 *v7, const struct mbuf *mbuf) {
Marko Mikulicic 0:c0ecb8bf28eb 21068 gc_mark_val_array(v7, (val_t *) mbuf->buf, mbuf->len / sizeof(val_t));
Marko Mikulicic 0:c0ecb8bf28eb 21069 }
Marko Mikulicic 0:c0ecb8bf28eb 21070
Marko Mikulicic 0:c0ecb8bf28eb 21071 /*
Marko Mikulicic 0:c0ecb8bf28eb 21072 * mark a vector containing `val_t` values (*not pointers* to them)
Marko Mikulicic 0:c0ecb8bf28eb 21073 */
Marko Mikulicic 0:c0ecb8bf28eb 21074 static void gc_mark_vec_val(struct v7 *v7, const struct v7_vec *vec) {
Marko Mikulicic 0:c0ecb8bf28eb 21075 gc_mark_val_array(v7, (val_t *) vec->p, vec->len / sizeof(val_t));
Marko Mikulicic 0:c0ecb8bf28eb 21076 }
Marko Mikulicic 0:c0ecb8bf28eb 21077
Marko Mikulicic 0:c0ecb8bf28eb 21078 /*
Marko Mikulicic 0:c0ecb8bf28eb 21079 * mark an mbuf containing foreign pointers to `struct bcode`
Marko Mikulicic 0:c0ecb8bf28eb 21080 */
Marko Mikulicic 0:c0ecb8bf28eb 21081 static void gc_mark_mbuf_bcode_pt(struct v7 *v7, const struct mbuf *mbuf) {
Marko Mikulicic 0:c0ecb8bf28eb 21082 struct bcode **vp;
Marko Mikulicic 0:c0ecb8bf28eb 21083 for (vp = (struct bcode **) mbuf->buf; (char *) vp < mbuf->buf + mbuf->len;
Marko Mikulicic 0:c0ecb8bf28eb 21084 vp++) {
Marko Mikulicic 0:c0ecb8bf28eb 21085 gc_mark_vec_val(v7, &(*vp)->lit);
Marko Mikulicic 0:c0ecb8bf28eb 21086 }
Marko Mikulicic 0:c0ecb8bf28eb 21087 }
Marko Mikulicic 0:c0ecb8bf28eb 21088
Marko Mikulicic 0:c0ecb8bf28eb 21089 static void gc_mark_call_stack_private(
Marko Mikulicic 0:c0ecb8bf28eb 21090 struct v7 *v7, struct v7_call_frame_private *call_stack) {
Marko Mikulicic 0:c0ecb8bf28eb 21091 gc_mark_val_array(v7, (val_t *) &call_stack->vals,
Marko Mikulicic 0:c0ecb8bf28eb 21092 sizeof(call_stack->vals) / sizeof(val_t));
Marko Mikulicic 0:c0ecb8bf28eb 21093 }
Marko Mikulicic 0:c0ecb8bf28eb 21094
Marko Mikulicic 0:c0ecb8bf28eb 21095 static void gc_mark_call_stack_cfunc(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 21096 struct v7_call_frame_cfunc *call_stack) {
Marko Mikulicic 0:c0ecb8bf28eb 21097 gc_mark_val_array(v7, (val_t *) &call_stack->vals,
Marko Mikulicic 0:c0ecb8bf28eb 21098 sizeof(call_stack->vals) / sizeof(val_t));
Marko Mikulicic 0:c0ecb8bf28eb 21099 }
Marko Mikulicic 0:c0ecb8bf28eb 21100
Marko Mikulicic 0:c0ecb8bf28eb 21101 static void gc_mark_call_stack_bcode(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 21102 struct v7_call_frame_bcode *call_stack) {
Marko Mikulicic 0:c0ecb8bf28eb 21103 gc_mark_val_array(v7, (val_t *) &call_stack->vals,
Marko Mikulicic 0:c0ecb8bf28eb 21104 sizeof(call_stack->vals) / sizeof(val_t));
Marko Mikulicic 0:c0ecb8bf28eb 21105 }
Marko Mikulicic 0:c0ecb8bf28eb 21106
Marko Mikulicic 0:c0ecb8bf28eb 21107 /*
Marko Mikulicic 0:c0ecb8bf28eb 21108 * mark `struct v7_call_frame` and all its back-linked frames
Marko Mikulicic 0:c0ecb8bf28eb 21109 */
Marko Mikulicic 0:c0ecb8bf28eb 21110 static void gc_mark_call_stack(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 21111 struct v7_call_frame_base *call_stack) {
Marko Mikulicic 0:c0ecb8bf28eb 21112 while (call_stack != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 21113 if (call_stack->type_mask & V7_CALL_FRAME_MASK_BCODE) {
Marko Mikulicic 0:c0ecb8bf28eb 21114 gc_mark_call_stack_bcode(v7, (struct v7_call_frame_bcode *) call_stack);
Marko Mikulicic 0:c0ecb8bf28eb 21115 }
Marko Mikulicic 0:c0ecb8bf28eb 21116
Marko Mikulicic 0:c0ecb8bf28eb 21117 if (call_stack->type_mask & V7_CALL_FRAME_MASK_PRIVATE) {
Marko Mikulicic 0:c0ecb8bf28eb 21118 gc_mark_call_stack_private(v7,
Marko Mikulicic 0:c0ecb8bf28eb 21119 (struct v7_call_frame_private *) call_stack);
Marko Mikulicic 0:c0ecb8bf28eb 21120 }
Marko Mikulicic 0:c0ecb8bf28eb 21121
Marko Mikulicic 0:c0ecb8bf28eb 21122 if (call_stack->type_mask & V7_CALL_FRAME_MASK_CFUNC) {
Marko Mikulicic 0:c0ecb8bf28eb 21123 gc_mark_call_stack_cfunc(v7, (struct v7_call_frame_cfunc *) call_stack);
Marko Mikulicic 0:c0ecb8bf28eb 21124 }
Marko Mikulicic 0:c0ecb8bf28eb 21125
Marko Mikulicic 0:c0ecb8bf28eb 21126 call_stack = call_stack->prev;
Marko Mikulicic 0:c0ecb8bf28eb 21127 }
Marko Mikulicic 0:c0ecb8bf28eb 21128 }
Marko Mikulicic 0:c0ecb8bf28eb 21129
Marko Mikulicic 0:c0ecb8bf28eb 21130 /* Perform garbage collection */
Marko Mikulicic 0:c0ecb8bf28eb 21131 void v7_gc(struct v7 *v7, int full) {
Marko Mikulicic 0:c0ecb8bf28eb 21132 #ifdef V7_DISABLE_GC
Marko Mikulicic 0:c0ecb8bf28eb 21133 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 21134 (void) full;
Marko Mikulicic 0:c0ecb8bf28eb 21135 return;
Marko Mikulicic 0:c0ecb8bf28eb 21136 #else
Marko Mikulicic 0:c0ecb8bf28eb 21137
Marko Mikulicic 0:c0ecb8bf28eb 21138 #if defined(V7_GC_VERBOSE)
Marko Mikulicic 0:c0ecb8bf28eb 21139 fprintf(stderr, "V7 GC pass %d\n", ++gc_pass);
Marko Mikulicic 0:c0ecb8bf28eb 21140 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21141
Marko Mikulicic 0:c0ecb8bf28eb 21142 gc_dump_arena_stats("Before GC objects", &v7->generic_object_arena);
Marko Mikulicic 0:c0ecb8bf28eb 21143 gc_dump_arena_stats("Before GC functions", &v7->function_arena);
Marko Mikulicic 0:c0ecb8bf28eb 21144 gc_dump_arena_stats("Before GC properties", &v7->property_arena);
Marko Mikulicic 0:c0ecb8bf28eb 21145
Marko Mikulicic 0:c0ecb8bf28eb 21146 gc_mark_call_stack(v7, v7->call_stack);
Marko Mikulicic 0:c0ecb8bf28eb 21147
Marko Mikulicic 0:c0ecb8bf28eb 21148 gc_mark_val_array(v7, (val_t *) &v7->vals, sizeof(v7->vals) / sizeof(val_t));
Marko Mikulicic 0:c0ecb8bf28eb 21149 /* mark all items on bcode stack */
Marko Mikulicic 0:c0ecb8bf28eb 21150 gc_mark_mbuf_val(v7, &v7->stack);
Marko Mikulicic 0:c0ecb8bf28eb 21151
Marko Mikulicic 0:c0ecb8bf28eb 21152 /* mark literals and names of all the active bcodes */
Marko Mikulicic 0:c0ecb8bf28eb 21153 gc_mark_mbuf_bcode_pt(v7, &v7->act_bcodes);
Marko Mikulicic 0:c0ecb8bf28eb 21154
Marko Mikulicic 0:c0ecb8bf28eb 21155 gc_mark_mbuf_pt(v7, &v7->tmp_stack);
Marko Mikulicic 0:c0ecb8bf28eb 21156 gc_mark_mbuf_pt(v7, &v7->owned_values);
Marko Mikulicic 0:c0ecb8bf28eb 21157
Marko Mikulicic 0:c0ecb8bf28eb 21158 gc_compact_strings(v7);
Marko Mikulicic 0:c0ecb8bf28eb 21159
Marko Mikulicic 0:c0ecb8bf28eb 21160 #ifdef V7_MALLOC_GC
Marko Mikulicic 0:c0ecb8bf28eb 21161 gc_sweep_malloc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 21162 #else
Marko Mikulicic 0:c0ecb8bf28eb 21163 gc_sweep(v7, &v7->generic_object_arena, 0);
Marko Mikulicic 0:c0ecb8bf28eb 21164 gc_sweep(v7, &v7->function_arena, 0);
Marko Mikulicic 0:c0ecb8bf28eb 21165 gc_sweep(v7, &v7->property_arena, 0);
Marko Mikulicic 0:c0ecb8bf28eb 21166 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21167
Marko Mikulicic 0:c0ecb8bf28eb 21168 gc_dump_arena_stats("After GC objects", &v7->generic_object_arena);
Marko Mikulicic 0:c0ecb8bf28eb 21169 gc_dump_arena_stats("After GC functions", &v7->function_arena);
Marko Mikulicic 0:c0ecb8bf28eb 21170 gc_dump_arena_stats("After GC properties", &v7->property_arena);
Marko Mikulicic 0:c0ecb8bf28eb 21171
Marko Mikulicic 0:c0ecb8bf28eb 21172 if (full) {
Marko Mikulicic 0:c0ecb8bf28eb 21173 /*
Marko Mikulicic 0:c0ecb8bf28eb 21174 * In case of full GC, we also resize strings buffer, but we still leave
Marko Mikulicic 0:c0ecb8bf28eb 21175 * some extra space (at most, `_V7_STRING_BUF_RESERVE`) in order to avoid
Marko Mikulicic 0:c0ecb8bf28eb 21176 * frequent reallocations
Marko Mikulicic 0:c0ecb8bf28eb 21177 */
Marko Mikulicic 0:c0ecb8bf28eb 21178 size_t trimmed_size = v7->owned_strings.len + _V7_STRING_BUF_RESERVE;
Marko Mikulicic 0:c0ecb8bf28eb 21179 if (trimmed_size < v7->owned_strings.size) {
Marko Mikulicic 0:c0ecb8bf28eb 21180 heapusage_dont_count(1);
Marko Mikulicic 0:c0ecb8bf28eb 21181 mbuf_resize(&v7->owned_strings, trimmed_size);
Marko Mikulicic 0:c0ecb8bf28eb 21182 heapusage_dont_count(0);
Marko Mikulicic 0:c0ecb8bf28eb 21183 }
Marko Mikulicic 0:c0ecb8bf28eb 21184 }
Marko Mikulicic 0:c0ecb8bf28eb 21185 #endif /* V7_DISABLE_GC */
Marko Mikulicic 0:c0ecb8bf28eb 21186 }
Marko Mikulicic 0:c0ecb8bf28eb 21187
Marko Mikulicic 0:c0ecb8bf28eb 21188 V7_PRIVATE int gc_check_val(struct v7 *v7, val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 21189 if (is_js_function(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 21190 return gc_check_ptr(&v7->function_arena, get_js_function_struct(v));
Marko Mikulicic 0:c0ecb8bf28eb 21191 } else if (v7_is_object(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 21192 return gc_check_ptr(&v7->generic_object_arena, get_object_struct(v));
Marko Mikulicic 0:c0ecb8bf28eb 21193 }
Marko Mikulicic 0:c0ecb8bf28eb 21194 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 21195 }
Marko Mikulicic 0:c0ecb8bf28eb 21196
Marko Mikulicic 0:c0ecb8bf28eb 21197 V7_PRIVATE int gc_check_ptr(const struct gc_arena *a, const void *ptr) {
Marko Mikulicic 0:c0ecb8bf28eb 21198 #ifdef V7_MALLOC_GC
Marko Mikulicic 0:c0ecb8bf28eb 21199 (void) a;
Marko Mikulicic 0:c0ecb8bf28eb 21200 (void) ptr;
Marko Mikulicic 0:c0ecb8bf28eb 21201 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 21202 #else
Marko Mikulicic 0:c0ecb8bf28eb 21203 const struct gc_cell *p = (const struct gc_cell *) ptr;
Marko Mikulicic 0:c0ecb8bf28eb 21204 struct gc_block *b;
Marko Mikulicic 0:c0ecb8bf28eb 21205 for (b = a->blocks; b != NULL; b = b->next) {
Marko Mikulicic 0:c0ecb8bf28eb 21206 if (p >= b->base && p < GC_CELL_OP(a, b->base, +, b->size)) {
Marko Mikulicic 0:c0ecb8bf28eb 21207 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 21208 }
Marko Mikulicic 0:c0ecb8bf28eb 21209 }
Marko Mikulicic 0:c0ecb8bf28eb 21210 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 21211 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21212 }
Marko Mikulicic 0:c0ecb8bf28eb 21213 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 21214 #line 1 "v7/src/freeze.c"
Marko Mikulicic 0:c0ecb8bf28eb 21215 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21216 /*
Marko Mikulicic 0:c0ecb8bf28eb 21217 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 21218 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 21219 */
Marko Mikulicic 0:c0ecb8bf28eb 21220
Marko Mikulicic 0:c0ecb8bf28eb 21221 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21222 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21223 /* Amalgamated: #include "v7/src/util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21224 /* Amalgamated: #include "v7/src/freeze.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21225 /* Amalgamated: #include "v7/src/bcode.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21226 /* Amalgamated: #include "v7/src/gc.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21227 /* Amalgamated: #include "common/base64.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21228 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21229
Marko Mikulicic 0:c0ecb8bf28eb 21230 #include <stdio.h>
Marko Mikulicic 0:c0ecb8bf28eb 21231
Marko Mikulicic 0:c0ecb8bf28eb 21232 #ifdef V7_FREEZE
Marko Mikulicic 0:c0ecb8bf28eb 21233
Marko Mikulicic 0:c0ecb8bf28eb 21234 V7_PRIVATE void freeze(struct v7 *v7, char *filename) {
Marko Mikulicic 0:c0ecb8bf28eb 21235 size_t i;
Marko Mikulicic 0:c0ecb8bf28eb 21236
Marko Mikulicic 0:c0ecb8bf28eb 21237 v7->freeze_file = fopen(filename, "w");
Marko Mikulicic 0:c0ecb8bf28eb 21238 assert(v7->freeze_file != NULL);
Marko Mikulicic 0:c0ecb8bf28eb 21239
Marko Mikulicic 0:c0ecb8bf28eb 21240 #ifndef V7_FREEZE_NOT_READONLY
Marko Mikulicic 0:c0ecb8bf28eb 21241 /*
Marko Mikulicic 0:c0ecb8bf28eb 21242 * We have to remove `global` from the global object since
Marko Mikulicic 0:c0ecb8bf28eb 21243 * when thawing global will actually be a new mutable object
Marko Mikulicic 0:c0ecb8bf28eb 21244 * living on the heap.
Marko Mikulicic 0:c0ecb8bf28eb 21245 */
Marko Mikulicic 0:c0ecb8bf28eb 21246 v7_del(v7, v7->vals.global_object, "global", 6);
Marko Mikulicic 0:c0ecb8bf28eb 21247 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21248
Marko Mikulicic 0:c0ecb8bf28eb 21249 for (i = 0; i < sizeof(v7->vals) / sizeof(val_t); i++) {
Marko Mikulicic 0:c0ecb8bf28eb 21250 val_t v = ((val_t *) &v7->vals)[i];
Marko Mikulicic 0:c0ecb8bf28eb 21251 fprintf(v7->freeze_file,
Marko Mikulicic 0:c0ecb8bf28eb 21252 "{\"type\":\"global\", \"idx\":%zu, \"value\":\"%p\"}\n", i,
Marko Mikulicic 0:c0ecb8bf28eb 21253 (void *) (v7_is_object(v) ? get_object_struct(v) : 0x0));
Marko Mikulicic 0:c0ecb8bf28eb 21254 }
Marko Mikulicic 0:c0ecb8bf28eb 21255
Marko Mikulicic 0:c0ecb8bf28eb 21256 /*
Marko Mikulicic 0:c0ecb8bf28eb 21257 * since v7->freeze_file is not NULL this will cause freeze_obj and
Marko Mikulicic 0:c0ecb8bf28eb 21258 * freeze_prop to be called for each reachable object and property.
Marko Mikulicic 0:c0ecb8bf28eb 21259 */
Marko Mikulicic 0:c0ecb8bf28eb 21260 v7_gc(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 21261 assert(v7->stack.len == 0);
Marko Mikulicic 0:c0ecb8bf28eb 21262
Marko Mikulicic 0:c0ecb8bf28eb 21263 fclose(v7->freeze_file);
Marko Mikulicic 0:c0ecb8bf28eb 21264 v7->freeze_file = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 21265 }
Marko Mikulicic 0:c0ecb8bf28eb 21266
Marko Mikulicic 0:c0ecb8bf28eb 21267 static char *freeze_vec(struct v7_vec *vec) {
Marko Mikulicic 0:c0ecb8bf28eb 21268 char *res = (char *) malloc(512 + vec->len);
Marko Mikulicic 0:c0ecb8bf28eb 21269 res[0] = '"';
Marko Mikulicic 0:c0ecb8bf28eb 21270 cs_base64_encode((const unsigned char *) vec->p, vec->len, &res[1]);
Marko Mikulicic 0:c0ecb8bf28eb 21271 strcat(res, "\"");
Marko Mikulicic 0:c0ecb8bf28eb 21272 return res;
Marko Mikulicic 0:c0ecb8bf28eb 21273 }
Marko Mikulicic 0:c0ecb8bf28eb 21274
Marko Mikulicic 0:c0ecb8bf28eb 21275 V7_PRIVATE void freeze_obj(struct v7 *v7, FILE *f, v7_val_t v) {
Marko Mikulicic 0:c0ecb8bf28eb 21276 struct v7_object *obj_base = get_object_struct(v);
Marko Mikulicic 0:c0ecb8bf28eb 21277 unsigned int attrs = V7_OBJ_OFF_HEAP;
Marko Mikulicic 0:c0ecb8bf28eb 21278
Marko Mikulicic 0:c0ecb8bf28eb 21279 #ifndef V7_FREEZE_NOT_READONLY
Marko Mikulicic 0:c0ecb8bf28eb 21280 attrs |= V7_OBJ_NOT_EXTENSIBLE;
Marko Mikulicic 0:c0ecb8bf28eb 21281 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21282
Marko Mikulicic 0:c0ecb8bf28eb 21283 if (is_js_function(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 21284 struct v7_js_function *func = get_js_function_struct(v);
Marko Mikulicic 0:c0ecb8bf28eb 21285 struct bcode *bcode = func->bcode;
Marko Mikulicic 0:c0ecb8bf28eb 21286 char *jops = freeze_vec(&bcode->ops);
Marko Mikulicic 0:c0ecb8bf28eb 21287 int i;
Marko Mikulicic 0:c0ecb8bf28eb 21288
Marko Mikulicic 0:c0ecb8bf28eb 21289 fprintf(f,
Marko Mikulicic 0:c0ecb8bf28eb 21290 "{\"type\":\"func\", \"addr\":\"%p\", \"props\":\"%p\", "
Marko Mikulicic 0:c0ecb8bf28eb 21291 "\"attrs\":%d, \"scope\":\"%p\", \"bcode\":\"%p\""
Marko Mikulicic 0:c0ecb8bf28eb 21292 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 21293 ", \"entity_id_base\":%d, \"entity_id_spec\":\"%d\" "
Marko Mikulicic 0:c0ecb8bf28eb 21294 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21295 "}\n",
Marko Mikulicic 0:c0ecb8bf28eb 21296 (void *) obj_base,
Marko Mikulicic 0:c0ecb8bf28eb 21297 (void *) ((uintptr_t) obj_base->properties & ~0x1),
Marko Mikulicic 0:c0ecb8bf28eb 21298 obj_base->attributes | attrs, (void *) func->scope, (void *) bcode
Marko Mikulicic 0:c0ecb8bf28eb 21299 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 21300 ,
Marko Mikulicic 0:c0ecb8bf28eb 21301 obj_base->entity_id_base, obj_base->entity_id_spec
Marko Mikulicic 0:c0ecb8bf28eb 21302 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21303 );
Marko Mikulicic 0:c0ecb8bf28eb 21304 fprintf(f,
Marko Mikulicic 0:c0ecb8bf28eb 21305 "{\"type\":\"bcode\", \"addr\":\"%p\", \"args_cnt\":%d, "
Marko Mikulicic 0:c0ecb8bf28eb 21306 "\"names_cnt\":%d, "
Marko Mikulicic 0:c0ecb8bf28eb 21307 "\"strict_mode\": %d, \"func_name_present\": %d, \"ops\":%s, "
Marko Mikulicic 0:c0ecb8bf28eb 21308 "\"lit\": [",
Marko Mikulicic 0:c0ecb8bf28eb 21309 (void *) bcode, bcode->args_cnt, bcode->names_cnt,
Marko Mikulicic 0:c0ecb8bf28eb 21310 bcode->strict_mode, bcode->func_name_present, jops);
Marko Mikulicic 0:c0ecb8bf28eb 21311
Marko Mikulicic 0:c0ecb8bf28eb 21312 for (i = 0; (size_t) i < bcode->lit.len / sizeof(val_t); i++) {
Marko Mikulicic 0:c0ecb8bf28eb 21313 val_t v = ((val_t *) bcode->lit.p)[i];
Marko Mikulicic 0:c0ecb8bf28eb 21314 const char *str;
Marko Mikulicic 0:c0ecb8bf28eb 21315
Marko Mikulicic 0:c0ecb8bf28eb 21316 if (((v & V7_TAG_MASK) == V7_TAG_STRING_O ||
Marko Mikulicic 0:c0ecb8bf28eb 21317 (v & V7_TAG_MASK) == V7_TAG_STRING_F) &&
Marko Mikulicic 0:c0ecb8bf28eb 21318 (str = v7_get_cstring(v7, &v)) != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 21319 fprintf(f, "{\"str\": \"%s\"}", str);
Marko Mikulicic 0:c0ecb8bf28eb 21320 } else {
Marko Mikulicic 0:c0ecb8bf28eb 21321 fprintf(f, "{\"val\": \"0x%" INT64_X_FMT "\"}", v);
Marko Mikulicic 0:c0ecb8bf28eb 21322 }
Marko Mikulicic 0:c0ecb8bf28eb 21323 if ((size_t) i != bcode->lit.len / sizeof(val_t) - 1) {
Marko Mikulicic 0:c0ecb8bf28eb 21324 fprintf(f, ",");
Marko Mikulicic 0:c0ecb8bf28eb 21325 }
Marko Mikulicic 0:c0ecb8bf28eb 21326 }
Marko Mikulicic 0:c0ecb8bf28eb 21327
Marko Mikulicic 0:c0ecb8bf28eb 21328 fprintf(f, "]}\n");
Marko Mikulicic 0:c0ecb8bf28eb 21329 free(jops);
Marko Mikulicic 0:c0ecb8bf28eb 21330 } else {
Marko Mikulicic 0:c0ecb8bf28eb 21331 struct v7_generic_object *gob = get_generic_object_struct(v);
Marko Mikulicic 0:c0ecb8bf28eb 21332 fprintf(f,
Marko Mikulicic 0:c0ecb8bf28eb 21333 "{\"type\":\"obj\", \"addr\":\"%p\", \"props\":\"%p\", "
Marko Mikulicic 0:c0ecb8bf28eb 21334 "\"attrs\":%d, \"proto\":\"%p\""
Marko Mikulicic 0:c0ecb8bf28eb 21335 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 21336 ", \"entity_id_base\":%d, \"entity_id_spec\":\"%d\" "
Marko Mikulicic 0:c0ecb8bf28eb 21337 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21338 "}\n",
Marko Mikulicic 0:c0ecb8bf28eb 21339 (void *) obj_base,
Marko Mikulicic 0:c0ecb8bf28eb 21340 (void *) ((uintptr_t) obj_base->properties & ~0x1),
Marko Mikulicic 0:c0ecb8bf28eb 21341 obj_base->attributes | attrs, (void *) gob->prototype
Marko Mikulicic 0:c0ecb8bf28eb 21342 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 21343 ,
Marko Mikulicic 0:c0ecb8bf28eb 21344 obj_base->entity_id_base, obj_base->entity_id_spec
Marko Mikulicic 0:c0ecb8bf28eb 21345 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21346 );
Marko Mikulicic 0:c0ecb8bf28eb 21347 }
Marko Mikulicic 0:c0ecb8bf28eb 21348 }
Marko Mikulicic 0:c0ecb8bf28eb 21349
Marko Mikulicic 0:c0ecb8bf28eb 21350 V7_PRIVATE void freeze_prop(struct v7 *v7, FILE *f, struct v7_property *prop) {
Marko Mikulicic 0:c0ecb8bf28eb 21351 unsigned int attrs = _V7_PROPERTY_OFF_HEAP;
Marko Mikulicic 0:c0ecb8bf28eb 21352 #ifndef V7_FREEZE_NOT_READONLY
Marko Mikulicic 0:c0ecb8bf28eb 21353 attrs |= V7_PROPERTY_NON_WRITABLE | V7_PROPERTY_NON_CONFIGURABLE;
Marko Mikulicic 0:c0ecb8bf28eb 21354 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21355
Marko Mikulicic 0:c0ecb8bf28eb 21356 fprintf(f,
Marko Mikulicic 0:c0ecb8bf28eb 21357 "{\"type\":\"prop\","
Marko Mikulicic 0:c0ecb8bf28eb 21358 " \"addr\":\"%p\","
Marko Mikulicic 0:c0ecb8bf28eb 21359 " \"next\":\"%p\","
Marko Mikulicic 0:c0ecb8bf28eb 21360 " \"attrs\":%d,"
Marko Mikulicic 0:c0ecb8bf28eb 21361 " \"name\":\"0x%" INT64_X_FMT
Marko Mikulicic 0:c0ecb8bf28eb 21362 "\","
Marko Mikulicic 0:c0ecb8bf28eb 21363 " \"value_type\":%d,"
Marko Mikulicic 0:c0ecb8bf28eb 21364 " \"value\":\"0x%" INT64_X_FMT
Marko Mikulicic 0:c0ecb8bf28eb 21365 "\","
Marko Mikulicic 0:c0ecb8bf28eb 21366 " \"name_str\":\"%s\""
Marko Mikulicic 0:c0ecb8bf28eb 21367 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 21368 ", \"entity_id\":\"%d\""
Marko Mikulicic 0:c0ecb8bf28eb 21369 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21370 "}\n",
Marko Mikulicic 0:c0ecb8bf28eb 21371 (void *) prop, (void *) prop->next, prop->attributes | attrs,
Marko Mikulicic 0:c0ecb8bf28eb 21372 prop->name, val_type(v7, prop->value), prop->value,
Marko Mikulicic 0:c0ecb8bf28eb 21373 v7_get_cstring(v7, &prop->name)
Marko Mikulicic 0:c0ecb8bf28eb 21374 #if defined(V7_ENABLE_ENTITY_IDS)
Marko Mikulicic 0:c0ecb8bf28eb 21375 ,
Marko Mikulicic 0:c0ecb8bf28eb 21376 prop->entity_id
Marko Mikulicic 0:c0ecb8bf28eb 21377 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21378 );
Marko Mikulicic 0:c0ecb8bf28eb 21379 }
Marko Mikulicic 0:c0ecb8bf28eb 21380
Marko Mikulicic 0:c0ecb8bf28eb 21381 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21382 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 21383 #line 1 "v7/src/parser.c"
Marko Mikulicic 0:c0ecb8bf28eb 21384 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21385 /*
Marko Mikulicic 0:c0ecb8bf28eb 21386 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 21387 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 21388 */
Marko Mikulicic 0:c0ecb8bf28eb 21389
Marko Mikulicic 0:c0ecb8bf28eb 21390 /* Amalgamated: #include "common/coroutine.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21391 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21392 /* Amalgamated: #include "v7/src/parser.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21393 /* Amalgamated: #include "v7/src/tokenizer.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21394 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21395 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21396 /* Amalgamated: #include "v7/src/ast.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21397 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21398 /* Amalgamated: #include "v7/src/cyg_profile.h" */
Marko Mikulicic 0:c0ecb8bf28eb 21399
Marko Mikulicic 0:c0ecb8bf28eb 21400 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 21401
Marko Mikulicic 0:c0ecb8bf28eb 21402 #define ACCEPT(t) (((v7)->cur_tok == (t)) ? next_tok((v7)), 1 : 0)
Marko Mikulicic 0:c0ecb8bf28eb 21403
Marko Mikulicic 0:c0ecb8bf28eb 21404 #define EXPECT(t) \
Marko Mikulicic 0:c0ecb8bf28eb 21405 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21406 if ((v7)->cur_tok != (t)) { \
Marko Mikulicic 0:c0ecb8bf28eb 21407 CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR); \
Marko Mikulicic 0:c0ecb8bf28eb 21408 } \
Marko Mikulicic 0:c0ecb8bf28eb 21409 next_tok(v7); \
Marko Mikulicic 0:c0ecb8bf28eb 21410 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21411
Marko Mikulicic 0:c0ecb8bf28eb 21412 #define PARSE_WITH_OPT_ARG(tag, arg_tag, arg_parser, label) \
Marko Mikulicic 0:c0ecb8bf28eb 21413 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21414 if (end_of_statement(v7) == V7_OK) { \
Marko Mikulicic 0:c0ecb8bf28eb 21415 add_node(v7, a, (tag)); \
Marko Mikulicic 0:c0ecb8bf28eb 21416 } else { \
Marko Mikulicic 0:c0ecb8bf28eb 21417 add_node(v7, a, (arg_tag)); \
Marko Mikulicic 0:c0ecb8bf28eb 21418 arg_parser(label); \
Marko Mikulicic 0:c0ecb8bf28eb 21419 } \
Marko Mikulicic 0:c0ecb8bf28eb 21420 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21421
Marko Mikulicic 0:c0ecb8bf28eb 21422 #define N (CR_ARG_RET_PT()->arg)
Marko Mikulicic 0:c0ecb8bf28eb 21423
Marko Mikulicic 0:c0ecb8bf28eb 21424 /*
Marko Mikulicic 0:c0ecb8bf28eb 21425 * User functions
Marko Mikulicic 0:c0ecb8bf28eb 21426 * (as well as other in-function entry points)
Marko Mikulicic 0:c0ecb8bf28eb 21427 */
Marko Mikulicic 0:c0ecb8bf28eb 21428 enum my_fid {
Marko Mikulicic 0:c0ecb8bf28eb 21429 fid_none = CR_FID__NONE,
Marko Mikulicic 0:c0ecb8bf28eb 21430
Marko Mikulicic 0:c0ecb8bf28eb 21431 /* parse_script function */
Marko Mikulicic 0:c0ecb8bf28eb 21432 fid_parse_script = CR_FID__USER,
Marko Mikulicic 0:c0ecb8bf28eb 21433 fid_p_script_1,
Marko Mikulicic 0:c0ecb8bf28eb 21434 fid_p_script_2,
Marko Mikulicic 0:c0ecb8bf28eb 21435 fid_p_script_3,
Marko Mikulicic 0:c0ecb8bf28eb 21436 fid_p_script_4,
Marko Mikulicic 0:c0ecb8bf28eb 21437
Marko Mikulicic 0:c0ecb8bf28eb 21438 /* parse_use_strict function */
Marko Mikulicic 0:c0ecb8bf28eb 21439 fid_parse_use_strict,
Marko Mikulicic 0:c0ecb8bf28eb 21440
Marko Mikulicic 0:c0ecb8bf28eb 21441 /* parse_body function */
Marko Mikulicic 0:c0ecb8bf28eb 21442 fid_parse_body,
Marko Mikulicic 0:c0ecb8bf28eb 21443 fid_p_body_1,
Marko Mikulicic 0:c0ecb8bf28eb 21444 fid_p_body_2,
Marko Mikulicic 0:c0ecb8bf28eb 21445
Marko Mikulicic 0:c0ecb8bf28eb 21446 /* parse_statement function */
Marko Mikulicic 0:c0ecb8bf28eb 21447 fid_parse_statement,
Marko Mikulicic 0:c0ecb8bf28eb 21448 fid_p_stat_1,
Marko Mikulicic 0:c0ecb8bf28eb 21449 fid_p_stat_2,
Marko Mikulicic 0:c0ecb8bf28eb 21450 fid_p_stat_3,
Marko Mikulicic 0:c0ecb8bf28eb 21451 fid_p_stat_4,
Marko Mikulicic 0:c0ecb8bf28eb 21452 fid_p_stat_5,
Marko Mikulicic 0:c0ecb8bf28eb 21453 fid_p_stat_6,
Marko Mikulicic 0:c0ecb8bf28eb 21454 fid_p_stat_7,
Marko Mikulicic 0:c0ecb8bf28eb 21455 fid_p_stat_8,
Marko Mikulicic 0:c0ecb8bf28eb 21456 fid_p_stat_9,
Marko Mikulicic 0:c0ecb8bf28eb 21457 fid_p_stat_10,
Marko Mikulicic 0:c0ecb8bf28eb 21458 fid_p_stat_11,
Marko Mikulicic 0:c0ecb8bf28eb 21459 fid_p_stat_12,
Marko Mikulicic 0:c0ecb8bf28eb 21460 fid_p_stat_13,
Marko Mikulicic 0:c0ecb8bf28eb 21461 fid_p_stat_14,
Marko Mikulicic 0:c0ecb8bf28eb 21462
Marko Mikulicic 0:c0ecb8bf28eb 21463 /* parse_expression function */
Marko Mikulicic 0:c0ecb8bf28eb 21464 fid_parse_expression,
Marko Mikulicic 0:c0ecb8bf28eb 21465 fid_p_expr_1,
Marko Mikulicic 0:c0ecb8bf28eb 21466
Marko Mikulicic 0:c0ecb8bf28eb 21467 /* parse_assign function */
Marko Mikulicic 0:c0ecb8bf28eb 21468 fid_parse_assign,
Marko Mikulicic 0:c0ecb8bf28eb 21469 fid_p_assign_1,
Marko Mikulicic 0:c0ecb8bf28eb 21470
Marko Mikulicic 0:c0ecb8bf28eb 21471 /* parse_binary function */
Marko Mikulicic 0:c0ecb8bf28eb 21472 fid_parse_binary,
Marko Mikulicic 0:c0ecb8bf28eb 21473 fid_p_binary_1,
Marko Mikulicic 0:c0ecb8bf28eb 21474 fid_p_binary_2,
Marko Mikulicic 0:c0ecb8bf28eb 21475 fid_p_binary_3,
Marko Mikulicic 0:c0ecb8bf28eb 21476 fid_p_binary_4,
Marko Mikulicic 0:c0ecb8bf28eb 21477 fid_p_binary_5,
Marko Mikulicic 0:c0ecb8bf28eb 21478 fid_p_binary_6,
Marko Mikulicic 0:c0ecb8bf28eb 21479
Marko Mikulicic 0:c0ecb8bf28eb 21480 /* parse_prefix function */
Marko Mikulicic 0:c0ecb8bf28eb 21481 fid_parse_prefix,
Marko Mikulicic 0:c0ecb8bf28eb 21482 fid_p_prefix_1,
Marko Mikulicic 0:c0ecb8bf28eb 21483
Marko Mikulicic 0:c0ecb8bf28eb 21484 /* parse_postfix function */
Marko Mikulicic 0:c0ecb8bf28eb 21485 fid_parse_postfix,
Marko Mikulicic 0:c0ecb8bf28eb 21486 fid_p_postfix_1,
Marko Mikulicic 0:c0ecb8bf28eb 21487
Marko Mikulicic 0:c0ecb8bf28eb 21488 /* parse_callexpr function */
Marko Mikulicic 0:c0ecb8bf28eb 21489 fid_parse_callexpr,
Marko Mikulicic 0:c0ecb8bf28eb 21490 fid_p_callexpr_1,
Marko Mikulicic 0:c0ecb8bf28eb 21491 fid_p_callexpr_2,
Marko Mikulicic 0:c0ecb8bf28eb 21492 fid_p_callexpr_3,
Marko Mikulicic 0:c0ecb8bf28eb 21493
Marko Mikulicic 0:c0ecb8bf28eb 21494 /* parse_newexpr function */
Marko Mikulicic 0:c0ecb8bf28eb 21495 fid_parse_newexpr,
Marko Mikulicic 0:c0ecb8bf28eb 21496 fid_p_newexpr_1,
Marko Mikulicic 0:c0ecb8bf28eb 21497 fid_p_newexpr_2,
Marko Mikulicic 0:c0ecb8bf28eb 21498 fid_p_newexpr_3,
Marko Mikulicic 0:c0ecb8bf28eb 21499 fid_p_newexpr_4,
Marko Mikulicic 0:c0ecb8bf28eb 21500
Marko Mikulicic 0:c0ecb8bf28eb 21501 /* parse_terminal function */
Marko Mikulicic 0:c0ecb8bf28eb 21502 fid_parse_terminal,
Marko Mikulicic 0:c0ecb8bf28eb 21503 fid_p_terminal_1,
Marko Mikulicic 0:c0ecb8bf28eb 21504 fid_p_terminal_2,
Marko Mikulicic 0:c0ecb8bf28eb 21505 fid_p_terminal_3,
Marko Mikulicic 0:c0ecb8bf28eb 21506 fid_p_terminal_4,
Marko Mikulicic 0:c0ecb8bf28eb 21507
Marko Mikulicic 0:c0ecb8bf28eb 21508 /* parse_block function */
Marko Mikulicic 0:c0ecb8bf28eb 21509 fid_parse_block,
Marko Mikulicic 0:c0ecb8bf28eb 21510 fid_p_block_1,
Marko Mikulicic 0:c0ecb8bf28eb 21511
Marko Mikulicic 0:c0ecb8bf28eb 21512 /* parse_if function */
Marko Mikulicic 0:c0ecb8bf28eb 21513 fid_parse_if,
Marko Mikulicic 0:c0ecb8bf28eb 21514 fid_p_if_1,
Marko Mikulicic 0:c0ecb8bf28eb 21515 fid_p_if_2,
Marko Mikulicic 0:c0ecb8bf28eb 21516 fid_p_if_3,
Marko Mikulicic 0:c0ecb8bf28eb 21517
Marko Mikulicic 0:c0ecb8bf28eb 21518 /* parse_while function */
Marko Mikulicic 0:c0ecb8bf28eb 21519 fid_parse_while,
Marko Mikulicic 0:c0ecb8bf28eb 21520 fid_p_while_1,
Marko Mikulicic 0:c0ecb8bf28eb 21521 fid_p_while_2,
Marko Mikulicic 0:c0ecb8bf28eb 21522
Marko Mikulicic 0:c0ecb8bf28eb 21523 /* parse_ident function */
Marko Mikulicic 0:c0ecb8bf28eb 21524 fid_parse_ident,
Marko Mikulicic 0:c0ecb8bf28eb 21525
Marko Mikulicic 0:c0ecb8bf28eb 21526 /* parse_ident_allow_reserved_words function */
Marko Mikulicic 0:c0ecb8bf28eb 21527 fid_parse_ident_allow_reserved_words,
Marko Mikulicic 0:c0ecb8bf28eb 21528 fid_p_ident_arw_1,
Marko Mikulicic 0:c0ecb8bf28eb 21529
Marko Mikulicic 0:c0ecb8bf28eb 21530 /* parse_funcdecl function */
Marko Mikulicic 0:c0ecb8bf28eb 21531 fid_parse_funcdecl,
Marko Mikulicic 0:c0ecb8bf28eb 21532 fid_p_funcdecl_1,
Marko Mikulicic 0:c0ecb8bf28eb 21533 fid_p_funcdecl_2,
Marko Mikulicic 0:c0ecb8bf28eb 21534 fid_p_funcdecl_3,
Marko Mikulicic 0:c0ecb8bf28eb 21535 fid_p_funcdecl_4,
Marko Mikulicic 0:c0ecb8bf28eb 21536 fid_p_funcdecl_5,
Marko Mikulicic 0:c0ecb8bf28eb 21537 fid_p_funcdecl_6,
Marko Mikulicic 0:c0ecb8bf28eb 21538 fid_p_funcdecl_7,
Marko Mikulicic 0:c0ecb8bf28eb 21539 fid_p_funcdecl_8,
Marko Mikulicic 0:c0ecb8bf28eb 21540 fid_p_funcdecl_9,
Marko Mikulicic 0:c0ecb8bf28eb 21541
Marko Mikulicic 0:c0ecb8bf28eb 21542 /* parse_arglist function */
Marko Mikulicic 0:c0ecb8bf28eb 21543 fid_parse_arglist,
Marko Mikulicic 0:c0ecb8bf28eb 21544 fid_p_arglist_1,
Marko Mikulicic 0:c0ecb8bf28eb 21545
Marko Mikulicic 0:c0ecb8bf28eb 21546 /* parse_member function */
Marko Mikulicic 0:c0ecb8bf28eb 21547 fid_parse_member,
Marko Mikulicic 0:c0ecb8bf28eb 21548 fid_p_member_1,
Marko Mikulicic 0:c0ecb8bf28eb 21549
Marko Mikulicic 0:c0ecb8bf28eb 21550 /* parse_memberexpr function */
Marko Mikulicic 0:c0ecb8bf28eb 21551 fid_parse_memberexpr,
Marko Mikulicic 0:c0ecb8bf28eb 21552 fid_p_memberexpr_1,
Marko Mikulicic 0:c0ecb8bf28eb 21553 fid_p_memberexpr_2,
Marko Mikulicic 0:c0ecb8bf28eb 21554
Marko Mikulicic 0:c0ecb8bf28eb 21555 /* parse_var function */
Marko Mikulicic 0:c0ecb8bf28eb 21556 fid_parse_var,
Marko Mikulicic 0:c0ecb8bf28eb 21557 fid_p_var_1,
Marko Mikulicic 0:c0ecb8bf28eb 21558
Marko Mikulicic 0:c0ecb8bf28eb 21559 /* parse_prop function */
Marko Mikulicic 0:c0ecb8bf28eb 21560 fid_parse_prop,
Marko Mikulicic 0:c0ecb8bf28eb 21561 #ifdef V7_ENABLE_JS_GETTERS
Marko Mikulicic 0:c0ecb8bf28eb 21562 fid_p_prop_1_getter,
Marko Mikulicic 0:c0ecb8bf28eb 21563 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21564 fid_p_prop_2,
Marko Mikulicic 0:c0ecb8bf28eb 21565 #ifdef V7_ENABLE_JS_SETTERS
Marko Mikulicic 0:c0ecb8bf28eb 21566 fid_p_prop_3_setter,
Marko Mikulicic 0:c0ecb8bf28eb 21567 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21568 fid_p_prop_4,
Marko Mikulicic 0:c0ecb8bf28eb 21569
Marko Mikulicic 0:c0ecb8bf28eb 21570 /* parse_dowhile function */
Marko Mikulicic 0:c0ecb8bf28eb 21571 fid_parse_dowhile,
Marko Mikulicic 0:c0ecb8bf28eb 21572 fid_p_dowhile_1,
Marko Mikulicic 0:c0ecb8bf28eb 21573 fid_p_dowhile_2,
Marko Mikulicic 0:c0ecb8bf28eb 21574
Marko Mikulicic 0:c0ecb8bf28eb 21575 /* parse_for function */
Marko Mikulicic 0:c0ecb8bf28eb 21576 fid_parse_for,
Marko Mikulicic 0:c0ecb8bf28eb 21577 fid_p_for_1,
Marko Mikulicic 0:c0ecb8bf28eb 21578 fid_p_for_2,
Marko Mikulicic 0:c0ecb8bf28eb 21579 fid_p_for_3,
Marko Mikulicic 0:c0ecb8bf28eb 21580 fid_p_for_4,
Marko Mikulicic 0:c0ecb8bf28eb 21581 fid_p_for_5,
Marko Mikulicic 0:c0ecb8bf28eb 21582 fid_p_for_6,
Marko Mikulicic 0:c0ecb8bf28eb 21583
Marko Mikulicic 0:c0ecb8bf28eb 21584 /* parse_try function */
Marko Mikulicic 0:c0ecb8bf28eb 21585 fid_parse_try,
Marko Mikulicic 0:c0ecb8bf28eb 21586 fid_p_try_1,
Marko Mikulicic 0:c0ecb8bf28eb 21587 fid_p_try_2,
Marko Mikulicic 0:c0ecb8bf28eb 21588 fid_p_try_3,
Marko Mikulicic 0:c0ecb8bf28eb 21589 fid_p_try_4,
Marko Mikulicic 0:c0ecb8bf28eb 21590
Marko Mikulicic 0:c0ecb8bf28eb 21591 /* parse_switch function */
Marko Mikulicic 0:c0ecb8bf28eb 21592 fid_parse_switch,
Marko Mikulicic 0:c0ecb8bf28eb 21593 fid_p_switch_1,
Marko Mikulicic 0:c0ecb8bf28eb 21594 fid_p_switch_2,
Marko Mikulicic 0:c0ecb8bf28eb 21595 fid_p_switch_3,
Marko Mikulicic 0:c0ecb8bf28eb 21596 fid_p_switch_4,
Marko Mikulicic 0:c0ecb8bf28eb 21597
Marko Mikulicic 0:c0ecb8bf28eb 21598 /* parse_with function */
Marko Mikulicic 0:c0ecb8bf28eb 21599 fid_parse_with,
Marko Mikulicic 0:c0ecb8bf28eb 21600 fid_p_with_1,
Marko Mikulicic 0:c0ecb8bf28eb 21601 fid_p_with_2,
Marko Mikulicic 0:c0ecb8bf28eb 21602
Marko Mikulicic 0:c0ecb8bf28eb 21603 MY_FID_CNT
Marko Mikulicic 0:c0ecb8bf28eb 21604 };
Marko Mikulicic 0:c0ecb8bf28eb 21605
Marko Mikulicic 0:c0ecb8bf28eb 21606 /*
Marko Mikulicic 0:c0ecb8bf28eb 21607 * User exception IDs. The first one should have value `CR_EXC_ID__USER`
Marko Mikulicic 0:c0ecb8bf28eb 21608 */
Marko Mikulicic 0:c0ecb8bf28eb 21609 enum parser_exc_id {
Marko Mikulicic 0:c0ecb8bf28eb 21610 PARSER_EXC_ID__NONE = CR_EXC_ID__NONE,
Marko Mikulicic 0:c0ecb8bf28eb 21611 PARSER_EXC_ID__SYNTAX_ERROR = CR_EXC_ID__USER,
Marko Mikulicic 0:c0ecb8bf28eb 21612 };
Marko Mikulicic 0:c0ecb8bf28eb 21613
Marko Mikulicic 0:c0ecb8bf28eb 21614 /* structures with locals and args {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21615
Marko Mikulicic 0:c0ecb8bf28eb 21616 /* parse_script {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21617
Marko Mikulicic 0:c0ecb8bf28eb 21618 /* parse_script's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 21619 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21620 typedef struct fid_parse_script_arg {
Marko Mikulicic 0:c0ecb8bf28eb 21621 } fid_parse_script_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21622 #else
Marko Mikulicic 0:c0ecb8bf28eb 21623 typedef cr_zero_size_type_t fid_parse_script_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21624 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21625
Marko Mikulicic 0:c0ecb8bf28eb 21626 /* parse_script's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 21627 typedef struct fid_parse_script_locals {
Marko Mikulicic 0:c0ecb8bf28eb 21628 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21629 struct fid_parse_script_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 21630 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21631
Marko Mikulicic 0:c0ecb8bf28eb 21632 ast_off_t start;
Marko Mikulicic 0:c0ecb8bf28eb 21633 ast_off_t outer_last_var_node;
Marko Mikulicic 0:c0ecb8bf28eb 21634 int saved_in_strict;
Marko Mikulicic 0:c0ecb8bf28eb 21635 } fid_parse_script_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21636
Marko Mikulicic 0:c0ecb8bf28eb 21637 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 21638
Marko Mikulicic 0:c0ecb8bf28eb 21639 /* parse_use_strict {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21640 /* parse_use_strict's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 21641 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21642 typedef struct fid_parse_use_strict_arg {
Marko Mikulicic 0:c0ecb8bf28eb 21643 } fid_parse_use_strict_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21644 #else
Marko Mikulicic 0:c0ecb8bf28eb 21645 typedef cr_zero_size_type_t fid_parse_use_strict_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21646 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21647
Marko Mikulicic 0:c0ecb8bf28eb 21648 /* parse_use_strict's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 21649 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21650 typedef struct fid_parse_use_strict_locals {
Marko Mikulicic 0:c0ecb8bf28eb 21651 struct fid_parse_use_strict_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 21652 } fid_parse_use_strict_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21653 #else
Marko Mikulicic 0:c0ecb8bf28eb 21654 typedef cr_zero_size_type_t fid_parse_use_strict_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21655 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21656
Marko Mikulicic 0:c0ecb8bf28eb 21657 #define CALL_PARSE_USE_STRICT(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 21658 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21659 CR_CALL(fid_parse_use_strict, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 21660 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21661
Marko Mikulicic 0:c0ecb8bf28eb 21662 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 21663
Marko Mikulicic 0:c0ecb8bf28eb 21664 /* parse_body {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21665 /* parse_body's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 21666 typedef struct fid_parse_body_arg { enum v7_tok end; } fid_parse_body_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21667
Marko Mikulicic 0:c0ecb8bf28eb 21668 /* parse_body's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 21669 typedef struct fid_parse_body_locals {
Marko Mikulicic 0:c0ecb8bf28eb 21670 struct fid_parse_body_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 21671
Marko Mikulicic 0:c0ecb8bf28eb 21672 ast_off_t start;
Marko Mikulicic 0:c0ecb8bf28eb 21673 } fid_parse_body_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21674
Marko Mikulicic 0:c0ecb8bf28eb 21675 #define CALL_PARSE_BODY(_end, _label) \
Marko Mikulicic 0:c0ecb8bf28eb 21676 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21677 N.fid_parse_body.end = (_end); \
Marko Mikulicic 0:c0ecb8bf28eb 21678 CR_CALL(fid_parse_body, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 21679 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21680 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 21681
Marko Mikulicic 0:c0ecb8bf28eb 21682 /* parse_statement {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21683 /* parse_statement's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 21684 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21685 typedef struct fid_parse_statement_arg {
Marko Mikulicic 0:c0ecb8bf28eb 21686 } fid_parse_statement_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21687 #else
Marko Mikulicic 0:c0ecb8bf28eb 21688 typedef cr_zero_size_type_t fid_parse_statement_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21689 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21690
Marko Mikulicic 0:c0ecb8bf28eb 21691 /* parse_statement's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 21692 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21693 typedef struct fid_parse_statement_locals {
Marko Mikulicic 0:c0ecb8bf28eb 21694 struct fid_parse_statement_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 21695 } fid_parse_statement_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21696 #else
Marko Mikulicic 0:c0ecb8bf28eb 21697 typedef cr_zero_size_type_t fid_parse_statement_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21698 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21699
Marko Mikulicic 0:c0ecb8bf28eb 21700 #define CALL_PARSE_STATEMENT(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 21701 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21702 CR_CALL(fid_parse_statement, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 21703 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21704 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 21705
Marko Mikulicic 0:c0ecb8bf28eb 21706 /* parse_expression {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21707 /* parse_expression's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 21708 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21709 typedef struct fid_parse_expression_arg {
Marko Mikulicic 0:c0ecb8bf28eb 21710 } fid_parse_expression_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21711 #else
Marko Mikulicic 0:c0ecb8bf28eb 21712 typedef cr_zero_size_type_t fid_parse_expression_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21713 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21714
Marko Mikulicic 0:c0ecb8bf28eb 21715 /* parse_expression's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 21716 typedef struct fid_parse_expression_locals {
Marko Mikulicic 0:c0ecb8bf28eb 21717 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21718 struct fid_parse_expression_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 21719 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21720
Marko Mikulicic 0:c0ecb8bf28eb 21721 ast_off_t pos;
Marko Mikulicic 0:c0ecb8bf28eb 21722 int group;
Marko Mikulicic 0:c0ecb8bf28eb 21723 } fid_parse_expression_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21724
Marko Mikulicic 0:c0ecb8bf28eb 21725 #define CALL_PARSE_EXPRESSION(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 21726 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21727 CR_CALL(fid_parse_expression, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 21728 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21729 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 21730
Marko Mikulicic 0:c0ecb8bf28eb 21731 /* parse_assign {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21732 /* parse_assign's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 21733 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21734 typedef struct fid_parse_assign_arg {
Marko Mikulicic 0:c0ecb8bf28eb 21735 } fid_parse_assign_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21736 #else
Marko Mikulicic 0:c0ecb8bf28eb 21737 typedef cr_zero_size_type_t fid_parse_assign_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21738 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21739
Marko Mikulicic 0:c0ecb8bf28eb 21740 /* parse_assign's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 21741 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21742 typedef struct fid_parse_assign_locals {
Marko Mikulicic 0:c0ecb8bf28eb 21743 struct fid_parse_assign_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 21744 } fid_parse_assign_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21745 #else
Marko Mikulicic 0:c0ecb8bf28eb 21746 typedef cr_zero_size_type_t fid_parse_assign_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21747 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21748
Marko Mikulicic 0:c0ecb8bf28eb 21749 #define CALL_PARSE_ASSIGN(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 21750 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21751 CR_CALL(fid_parse_assign, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 21752 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21753 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 21754
Marko Mikulicic 0:c0ecb8bf28eb 21755 /* parse_binary {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21756 /* parse_binary's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 21757 typedef struct fid_parse_binary_arg {
Marko Mikulicic 0:c0ecb8bf28eb 21758 ast_off_t pos;
Marko Mikulicic 0:c0ecb8bf28eb 21759 uint8_t min_level;
Marko Mikulicic 0:c0ecb8bf28eb 21760 } fid_parse_binary_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21761
Marko Mikulicic 0:c0ecb8bf28eb 21762 /* parse_binary's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 21763 typedef struct fid_parse_binary_locals {
Marko Mikulicic 0:c0ecb8bf28eb 21764 struct fid_parse_binary_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 21765
Marko Mikulicic 0:c0ecb8bf28eb 21766 uint8_t i;
Marko Mikulicic 0:c0ecb8bf28eb 21767 /* during iteration, it becomes negative, so should be signed */
Marko Mikulicic 0:c0ecb8bf28eb 21768 int8_t level;
Marko Mikulicic 0:c0ecb8bf28eb 21769 uint8_t /*enum v7_tok*/ tok;
Marko Mikulicic 0:c0ecb8bf28eb 21770 uint8_t /*enum ast_tag*/ ast;
Marko Mikulicic 0:c0ecb8bf28eb 21771 ast_off_t saved_mbuf_len;
Marko Mikulicic 0:c0ecb8bf28eb 21772 } fid_parse_binary_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21773
Marko Mikulicic 0:c0ecb8bf28eb 21774 #define CALL_PARSE_BINARY(_level, _pos, _label) \
Marko Mikulicic 0:c0ecb8bf28eb 21775 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21776 N.fid_parse_binary.min_level = (_level); \
Marko Mikulicic 0:c0ecb8bf28eb 21777 N.fid_parse_binary.pos = (_pos); \
Marko Mikulicic 0:c0ecb8bf28eb 21778 CR_CALL(fid_parse_binary, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 21779 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21780 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 21781
Marko Mikulicic 0:c0ecb8bf28eb 21782 /* parse_prefix {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21783 /* parse_prefix's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 21784 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21785 typedef struct fid_parse_prefix_arg {
Marko Mikulicic 0:c0ecb8bf28eb 21786 } fid_parse_prefix_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21787 #else
Marko Mikulicic 0:c0ecb8bf28eb 21788 typedef cr_zero_size_type_t fid_parse_prefix_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21789 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21790
Marko Mikulicic 0:c0ecb8bf28eb 21791 /* parse_prefix's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 21792 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21793 typedef struct fid_parse_prefix_locals {
Marko Mikulicic 0:c0ecb8bf28eb 21794 struct fid_parse_prefix_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 21795 } fid_parse_prefix_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21796 #else
Marko Mikulicic 0:c0ecb8bf28eb 21797 typedef cr_zero_size_type_t fid_parse_prefix_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21798 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21799
Marko Mikulicic 0:c0ecb8bf28eb 21800 #define CALL_PARSE_PREFIX(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 21801 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21802 CR_CALL(fid_parse_prefix, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 21803 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21804 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 21805
Marko Mikulicic 0:c0ecb8bf28eb 21806 /* parse_postfix {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21807 /* parse_postfix's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 21808 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21809 typedef struct fid_parse_postfix_arg {
Marko Mikulicic 0:c0ecb8bf28eb 21810 } fid_parse_postfix_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21811 #else
Marko Mikulicic 0:c0ecb8bf28eb 21812 typedef cr_zero_size_type_t fid_parse_postfix_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21813 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21814
Marko Mikulicic 0:c0ecb8bf28eb 21815 /* parse_postfix's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 21816 typedef struct fid_parse_postfix_locals {
Marko Mikulicic 0:c0ecb8bf28eb 21817 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21818 struct fid_parse_postfix_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 21819 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21820
Marko Mikulicic 0:c0ecb8bf28eb 21821 ast_off_t pos;
Marko Mikulicic 0:c0ecb8bf28eb 21822 } fid_parse_postfix_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21823
Marko Mikulicic 0:c0ecb8bf28eb 21824 #define CALL_PARSE_POSTFIX(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 21825 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21826 CR_CALL(fid_parse_postfix, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 21827 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21828 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 21829
Marko Mikulicic 0:c0ecb8bf28eb 21830 /* parse_callexpr {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21831 /* parse_callexpr's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 21832 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21833 typedef struct fid_parse_callexpr_arg {
Marko Mikulicic 0:c0ecb8bf28eb 21834 } fid_parse_callexpr_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21835 #else
Marko Mikulicic 0:c0ecb8bf28eb 21836 typedef cr_zero_size_type_t fid_parse_callexpr_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21837 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21838
Marko Mikulicic 0:c0ecb8bf28eb 21839 /* parse_callexpr's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 21840 typedef struct fid_parse_callexpr_locals {
Marko Mikulicic 0:c0ecb8bf28eb 21841 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21842 struct fid_parse_callexpr_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 21843 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21844
Marko Mikulicic 0:c0ecb8bf28eb 21845 ast_off_t pos;
Marko Mikulicic 0:c0ecb8bf28eb 21846 } fid_parse_callexpr_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21847
Marko Mikulicic 0:c0ecb8bf28eb 21848 #define CALL_PARSE_CALLEXPR(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 21849 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21850 CR_CALL(fid_parse_callexpr, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 21851 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21852 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 21853
Marko Mikulicic 0:c0ecb8bf28eb 21854 /* parse_newexpr {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21855 /* parse_newexpr's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 21856 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21857 typedef struct fid_parse_newexpr_arg {
Marko Mikulicic 0:c0ecb8bf28eb 21858 } fid_parse_newexpr_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21859 #else
Marko Mikulicic 0:c0ecb8bf28eb 21860 typedef cr_zero_size_type_t fid_parse_newexpr_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21861 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21862
Marko Mikulicic 0:c0ecb8bf28eb 21863 /* parse_newexpr's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 21864 typedef struct fid_parse_newexpr_locals {
Marko Mikulicic 0:c0ecb8bf28eb 21865 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21866 struct fid_parse_newexpr_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 21867 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21868
Marko Mikulicic 0:c0ecb8bf28eb 21869 ast_off_t start;
Marko Mikulicic 0:c0ecb8bf28eb 21870 } fid_parse_newexpr_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21871
Marko Mikulicic 0:c0ecb8bf28eb 21872 #define CALL_PARSE_NEWEXPR(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 21873 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21874 CR_CALL(fid_parse_newexpr, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 21875 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21876 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 21877
Marko Mikulicic 0:c0ecb8bf28eb 21878 /* parse_terminal {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21879 /* parse_terminal's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 21880 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21881 typedef struct fid_parse_terminal_arg {
Marko Mikulicic 0:c0ecb8bf28eb 21882 } fid_parse_terminal_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21883 #else
Marko Mikulicic 0:c0ecb8bf28eb 21884 typedef cr_zero_size_type_t fid_parse_terminal_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21885 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21886
Marko Mikulicic 0:c0ecb8bf28eb 21887 /* parse_terminal's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 21888 typedef struct fid_parse_terminal_locals {
Marko Mikulicic 0:c0ecb8bf28eb 21889 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21890 struct fid_parse_terminal_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 21891 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21892
Marko Mikulicic 0:c0ecb8bf28eb 21893 ast_off_t start;
Marko Mikulicic 0:c0ecb8bf28eb 21894 } fid_parse_terminal_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21895
Marko Mikulicic 0:c0ecb8bf28eb 21896 #define CALL_PARSE_TERMINAL(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 21897 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21898 CR_CALL(fid_parse_terminal, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 21899 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21900 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 21901
Marko Mikulicic 0:c0ecb8bf28eb 21902 /* parse_block {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21903 /* parse_block's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 21904 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21905 typedef struct fid_parse_block_arg {
Marko Mikulicic 0:c0ecb8bf28eb 21906 } fid_parse_block_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21907 #else
Marko Mikulicic 0:c0ecb8bf28eb 21908 typedef cr_zero_size_type_t fid_parse_block_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21909 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21910
Marko Mikulicic 0:c0ecb8bf28eb 21911 /* parse_block's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 21912 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21913 typedef struct fid_parse_block_locals {
Marko Mikulicic 0:c0ecb8bf28eb 21914 struct fid_parse_block_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 21915 } fid_parse_block_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21916 #else
Marko Mikulicic 0:c0ecb8bf28eb 21917 typedef cr_zero_size_type_t fid_parse_block_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21918 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21919
Marko Mikulicic 0:c0ecb8bf28eb 21920 #define CALL_PARSE_BLOCK(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 21921 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21922 CR_CALL(fid_parse_block, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 21923 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21924 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 21925
Marko Mikulicic 0:c0ecb8bf28eb 21926 /* parse_if {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21927 /* parse_if's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 21928 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21929 typedef struct fid_parse_if_arg {
Marko Mikulicic 0:c0ecb8bf28eb 21930 } fid_parse_if_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21931 #else
Marko Mikulicic 0:c0ecb8bf28eb 21932 typedef cr_zero_size_type_t fid_parse_if_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21933 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21934
Marko Mikulicic 0:c0ecb8bf28eb 21935 /* parse_if's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 21936 typedef struct fid_parse_if_locals {
Marko Mikulicic 0:c0ecb8bf28eb 21937 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21938 struct fid_parse_if_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 21939 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21940
Marko Mikulicic 0:c0ecb8bf28eb 21941 ast_off_t start;
Marko Mikulicic 0:c0ecb8bf28eb 21942 } fid_parse_if_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21943
Marko Mikulicic 0:c0ecb8bf28eb 21944 #define CALL_PARSE_IF(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 21945 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21946 CR_CALL(fid_parse_if, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 21947 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21948 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 21949
Marko Mikulicic 0:c0ecb8bf28eb 21950 /* parse_while {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21951 /* parse_while's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 21952 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21953 typedef struct fid_parse_while_arg {
Marko Mikulicic 0:c0ecb8bf28eb 21954 } fid_parse_while_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21955 #else
Marko Mikulicic 0:c0ecb8bf28eb 21956 typedef cr_zero_size_type_t fid_parse_while_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21957 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21958
Marko Mikulicic 0:c0ecb8bf28eb 21959 /* parse_while's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 21960 typedef struct fid_parse_while_locals {
Marko Mikulicic 0:c0ecb8bf28eb 21961 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21962 struct fid_parse_while_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 21963 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21964
Marko Mikulicic 0:c0ecb8bf28eb 21965 ast_off_t start;
Marko Mikulicic 0:c0ecb8bf28eb 21966 uint8_t saved_in_loop;
Marko Mikulicic 0:c0ecb8bf28eb 21967 } fid_parse_while_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21968
Marko Mikulicic 0:c0ecb8bf28eb 21969 #define CALL_PARSE_WHILE(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 21970 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21971 CR_CALL(fid_parse_while, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 21972 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21973 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 21974
Marko Mikulicic 0:c0ecb8bf28eb 21975 /* parse_ident {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 21976 /* parse_ident's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 21977 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21978 typedef struct fid_parse_ident_arg {
Marko Mikulicic 0:c0ecb8bf28eb 21979 } fid_parse_ident_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21980 #else
Marko Mikulicic 0:c0ecb8bf28eb 21981 typedef cr_zero_size_type_t fid_parse_ident_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 21982 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21983
Marko Mikulicic 0:c0ecb8bf28eb 21984 /* parse_ident's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 21985 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 21986 typedef struct fid_parse_ident_locals {
Marko Mikulicic 0:c0ecb8bf28eb 21987 struct fid_parse_ident_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 21988 } fid_parse_ident_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21989 #else
Marko Mikulicic 0:c0ecb8bf28eb 21990 typedef cr_zero_size_type_t fid_parse_ident_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 21991 #endif
Marko Mikulicic 0:c0ecb8bf28eb 21992
Marko Mikulicic 0:c0ecb8bf28eb 21993 #define CALL_PARSE_IDENT(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 21994 do { \
Marko Mikulicic 0:c0ecb8bf28eb 21995 CR_CALL(fid_parse_ident, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 21996 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 21997 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 21998
Marko Mikulicic 0:c0ecb8bf28eb 21999 /* parse_ident_allow_reserved_words {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 22000 /* parse_ident_allow_reserved_words's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 22001 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22002 typedef struct fid_parse_ident_allow_reserved_words_arg {
Marko Mikulicic 0:c0ecb8bf28eb 22003 } fid_parse_ident_allow_reserved_words_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22004 #else
Marko Mikulicic 0:c0ecb8bf28eb 22005 typedef cr_zero_size_type_t fid_parse_ident_allow_reserved_words_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22006 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22007
Marko Mikulicic 0:c0ecb8bf28eb 22008 /* parse_ident_allow_reserved_words's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 22009 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22010 typedef struct fid_parse_ident_allow_reserved_words_locals {
Marko Mikulicic 0:c0ecb8bf28eb 22011 struct fid_parse_ident_allow_reserved_words_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 22012 } fid_parse_ident_allow_reserved_words_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22013 #else
Marko Mikulicic 0:c0ecb8bf28eb 22014 typedef cr_zero_size_type_t fid_parse_ident_allow_reserved_words_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22015 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22016
Marko Mikulicic 0:c0ecb8bf28eb 22017 #define CALL_PARSE_IDENT_ALLOW_RESERVED_WORDS(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 22018 do { \
Marko Mikulicic 0:c0ecb8bf28eb 22019 CR_CALL(fid_parse_ident_allow_reserved_words, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 22020 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 22021 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 22022
Marko Mikulicic 0:c0ecb8bf28eb 22023 /* parse_funcdecl {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 22024 /* parse_funcdecl's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 22025 typedef struct fid_parse_funcdecl_arg {
Marko Mikulicic 0:c0ecb8bf28eb 22026 uint8_t require_named;
Marko Mikulicic 0:c0ecb8bf28eb 22027 uint8_t reserved_name;
Marko Mikulicic 0:c0ecb8bf28eb 22028 } fid_parse_funcdecl_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22029
Marko Mikulicic 0:c0ecb8bf28eb 22030 /* parse_funcdecl's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 22031 typedef struct fid_parse_funcdecl_locals {
Marko Mikulicic 0:c0ecb8bf28eb 22032 struct fid_parse_funcdecl_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 22033
Marko Mikulicic 0:c0ecb8bf28eb 22034 ast_off_t start;
Marko Mikulicic 0:c0ecb8bf28eb 22035 ast_off_t outer_last_var_node;
Marko Mikulicic 0:c0ecb8bf28eb 22036 uint8_t saved_in_function;
Marko Mikulicic 0:c0ecb8bf28eb 22037 uint8_t saved_in_strict;
Marko Mikulicic 0:c0ecb8bf28eb 22038 } fid_parse_funcdecl_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22039
Marko Mikulicic 0:c0ecb8bf28eb 22040 #define CALL_PARSE_FUNCDECL(_require_named, _reserved_name, _label) \
Marko Mikulicic 0:c0ecb8bf28eb 22041 do { \
Marko Mikulicic 0:c0ecb8bf28eb 22042 N.fid_parse_funcdecl.require_named = (_require_named); \
Marko Mikulicic 0:c0ecb8bf28eb 22043 N.fid_parse_funcdecl.reserved_name = (_reserved_name); \
Marko Mikulicic 0:c0ecb8bf28eb 22044 CR_CALL(fid_parse_funcdecl, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 22045 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 22046 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 22047
Marko Mikulicic 0:c0ecb8bf28eb 22048 /* parse_arglist {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 22049 /* parse_arglist's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 22050 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22051 typedef struct fid_parse_arglist_arg {
Marko Mikulicic 0:c0ecb8bf28eb 22052 } fid_parse_arglist_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22053 #else
Marko Mikulicic 0:c0ecb8bf28eb 22054 typedef cr_zero_size_type_t fid_parse_arglist_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22055 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22056
Marko Mikulicic 0:c0ecb8bf28eb 22057 /* parse_arglist's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 22058 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22059 typedef struct fid_parse_arglist_locals {
Marko Mikulicic 0:c0ecb8bf28eb 22060 struct fid_parse_arglist_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 22061 } fid_parse_arglist_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22062 #else
Marko Mikulicic 0:c0ecb8bf28eb 22063 typedef cr_zero_size_type_t fid_parse_arglist_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22064 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22065
Marko Mikulicic 0:c0ecb8bf28eb 22066 #define CALL_PARSE_ARGLIST(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 22067 do { \
Marko Mikulicic 0:c0ecb8bf28eb 22068 CR_CALL(fid_parse_arglist, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 22069 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 22070 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 22071
Marko Mikulicic 0:c0ecb8bf28eb 22072 /* parse_member {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 22073 /* parse_member's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 22074 typedef struct fid_parse_member_arg { ast_off_t pos; } fid_parse_member_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22075
Marko Mikulicic 0:c0ecb8bf28eb 22076 /* parse_member's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 22077 typedef struct fid_parse_member_locals {
Marko Mikulicic 0:c0ecb8bf28eb 22078 struct fid_parse_member_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 22079 } fid_parse_member_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22080
Marko Mikulicic 0:c0ecb8bf28eb 22081 #define CALL_PARSE_MEMBER(_pos, _label) \
Marko Mikulicic 0:c0ecb8bf28eb 22082 do { \
Marko Mikulicic 0:c0ecb8bf28eb 22083 N.fid_parse_member.pos = (_pos); \
Marko Mikulicic 0:c0ecb8bf28eb 22084 CR_CALL(fid_parse_member, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 22085 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 22086 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 22087
Marko Mikulicic 0:c0ecb8bf28eb 22088 /* parse_memberexpr {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 22089 /* parse_memberexpr's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 22090 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22091 typedef struct fid_parse_memberexpr_arg {
Marko Mikulicic 0:c0ecb8bf28eb 22092 } fid_parse_memberexpr_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22093 #else
Marko Mikulicic 0:c0ecb8bf28eb 22094 typedef cr_zero_size_type_t fid_parse_memberexpr_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22095 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22096
Marko Mikulicic 0:c0ecb8bf28eb 22097 /* parse_memberexpr's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 22098 typedef struct fid_parse_memberexpr_locals {
Marko Mikulicic 0:c0ecb8bf28eb 22099 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22100 struct fid_parse_memberexpr_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 22101 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22102
Marko Mikulicic 0:c0ecb8bf28eb 22103 ast_off_t pos;
Marko Mikulicic 0:c0ecb8bf28eb 22104 } fid_parse_memberexpr_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22105
Marko Mikulicic 0:c0ecb8bf28eb 22106 #define CALL_PARSE_MEMBEREXPR(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 22107 do { \
Marko Mikulicic 0:c0ecb8bf28eb 22108 CR_CALL(fid_parse_memberexpr, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 22109 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 22110 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 22111
Marko Mikulicic 0:c0ecb8bf28eb 22112 /* parse_var {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 22113 /* parse_var's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 22114 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22115 typedef struct fid_parse_var_arg {
Marko Mikulicic 0:c0ecb8bf28eb 22116 } fid_parse_var_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22117 #else
Marko Mikulicic 0:c0ecb8bf28eb 22118 typedef cr_zero_size_type_t fid_parse_var_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22119 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22120
Marko Mikulicic 0:c0ecb8bf28eb 22121 /* parse_var's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 22122 typedef struct fid_parse_var_locals {
Marko Mikulicic 0:c0ecb8bf28eb 22123 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22124 struct fid_parse_var_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 22125 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22126
Marko Mikulicic 0:c0ecb8bf28eb 22127 ast_off_t start;
Marko Mikulicic 0:c0ecb8bf28eb 22128 } fid_parse_var_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22129
Marko Mikulicic 0:c0ecb8bf28eb 22130 #define CALL_PARSE_VAR(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 22131 do { \
Marko Mikulicic 0:c0ecb8bf28eb 22132 CR_CALL(fid_parse_var, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 22133 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 22134 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 22135
Marko Mikulicic 0:c0ecb8bf28eb 22136 /* parse_prop {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 22137 /* parse_prop's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 22138 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22139 typedef struct fid_parse_prop_arg {
Marko Mikulicic 0:c0ecb8bf28eb 22140 } fid_parse_prop_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22141 #else
Marko Mikulicic 0:c0ecb8bf28eb 22142 typedef cr_zero_size_type_t fid_parse_prop_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22143 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22144
Marko Mikulicic 0:c0ecb8bf28eb 22145 /* parse_prop's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 22146 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22147 typedef struct fid_parse_prop_locals {
Marko Mikulicic 0:c0ecb8bf28eb 22148 struct fid_parse_prop_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 22149 } fid_parse_prop_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22150 #else
Marko Mikulicic 0:c0ecb8bf28eb 22151 typedef cr_zero_size_type_t fid_parse_prop_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22152 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22153
Marko Mikulicic 0:c0ecb8bf28eb 22154 #define CALL_PARSE_PROP(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 22155 do { \
Marko Mikulicic 0:c0ecb8bf28eb 22156 CR_CALL(fid_parse_prop, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 22157 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 22158 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 22159
Marko Mikulicic 0:c0ecb8bf28eb 22160 /* parse_dowhile {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 22161 /* parse_dowhile's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 22162 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22163 typedef struct fid_parse_dowhile_arg {
Marko Mikulicic 0:c0ecb8bf28eb 22164 } fid_parse_dowhile_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22165 #else
Marko Mikulicic 0:c0ecb8bf28eb 22166 typedef cr_zero_size_type_t fid_parse_dowhile_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22167 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22168
Marko Mikulicic 0:c0ecb8bf28eb 22169 /* parse_dowhile's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 22170 typedef struct fid_parse_dowhile_locals {
Marko Mikulicic 0:c0ecb8bf28eb 22171 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22172 struct fid_parse_dowhile_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 22173 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22174
Marko Mikulicic 0:c0ecb8bf28eb 22175 ast_off_t start;
Marko Mikulicic 0:c0ecb8bf28eb 22176 uint8_t saved_in_loop;
Marko Mikulicic 0:c0ecb8bf28eb 22177 } fid_parse_dowhile_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22178
Marko Mikulicic 0:c0ecb8bf28eb 22179 #define CALL_PARSE_DOWHILE(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 22180 do { \
Marko Mikulicic 0:c0ecb8bf28eb 22181 CR_CALL(fid_parse_dowhile, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 22182 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 22183 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 22184
Marko Mikulicic 0:c0ecb8bf28eb 22185 /* parse_for {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 22186 /* parse_for's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 22187 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22188 typedef struct fid_parse_for_arg {
Marko Mikulicic 0:c0ecb8bf28eb 22189 } fid_parse_for_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22190 #else
Marko Mikulicic 0:c0ecb8bf28eb 22191 typedef cr_zero_size_type_t fid_parse_for_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22192 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22193
Marko Mikulicic 0:c0ecb8bf28eb 22194 /* parse_for's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 22195 typedef struct fid_parse_for_locals {
Marko Mikulicic 0:c0ecb8bf28eb 22196 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22197 struct fid_parse_for_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 22198 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22199
Marko Mikulicic 0:c0ecb8bf28eb 22200 ast_off_t start;
Marko Mikulicic 0:c0ecb8bf28eb 22201 uint8_t saved_in_loop;
Marko Mikulicic 0:c0ecb8bf28eb 22202 } fid_parse_for_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22203
Marko Mikulicic 0:c0ecb8bf28eb 22204 #define CALL_PARSE_FOR(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 22205 do { \
Marko Mikulicic 0:c0ecb8bf28eb 22206 CR_CALL(fid_parse_for, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 22207 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 22208 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 22209
Marko Mikulicic 0:c0ecb8bf28eb 22210 /* parse_try {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 22211 /* parse_try's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 22212 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22213 typedef struct fid_parse_try_arg {
Marko Mikulicic 0:c0ecb8bf28eb 22214 } fid_parse_try_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22215 #else
Marko Mikulicic 0:c0ecb8bf28eb 22216 typedef cr_zero_size_type_t fid_parse_try_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22217 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22218
Marko Mikulicic 0:c0ecb8bf28eb 22219 /* parse_try's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 22220 typedef struct fid_parse_try_locals {
Marko Mikulicic 0:c0ecb8bf28eb 22221 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22222 struct fid_parse_try_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 22223 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22224
Marko Mikulicic 0:c0ecb8bf28eb 22225 ast_off_t start;
Marko Mikulicic 0:c0ecb8bf28eb 22226 uint8_t catch_or_finally;
Marko Mikulicic 0:c0ecb8bf28eb 22227 } fid_parse_try_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22228
Marko Mikulicic 0:c0ecb8bf28eb 22229 #define CALL_PARSE_TRY(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 22230 do { \
Marko Mikulicic 0:c0ecb8bf28eb 22231 CR_CALL(fid_parse_try, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 22232 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 22233 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 22234
Marko Mikulicic 0:c0ecb8bf28eb 22235 /* parse_switch {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 22236 /* parse_switch's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 22237 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22238 typedef struct fid_parse_switch_arg {
Marko Mikulicic 0:c0ecb8bf28eb 22239 } fid_parse_switch_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22240 #else
Marko Mikulicic 0:c0ecb8bf28eb 22241 typedef cr_zero_size_type_t fid_parse_switch_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22242 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22243
Marko Mikulicic 0:c0ecb8bf28eb 22244 /* parse_switch's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 22245 typedef struct fid_parse_switch_locals {
Marko Mikulicic 0:c0ecb8bf28eb 22246 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22247 struct fid_parse_switch_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 22248 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22249
Marko Mikulicic 0:c0ecb8bf28eb 22250 ast_off_t start;
Marko Mikulicic 0:c0ecb8bf28eb 22251 int saved_in_switch;
Marko Mikulicic 0:c0ecb8bf28eb 22252 ast_off_t case_start;
Marko Mikulicic 0:c0ecb8bf28eb 22253 } fid_parse_switch_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22254
Marko Mikulicic 0:c0ecb8bf28eb 22255 #define CALL_PARSE_SWITCH(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 22256 do { \
Marko Mikulicic 0:c0ecb8bf28eb 22257 CR_CALL(fid_parse_switch, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 22258 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 22259 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 22260
Marko Mikulicic 0:c0ecb8bf28eb 22261 /* parse_with {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 22262 /* parse_with's arguments */
Marko Mikulicic 0:c0ecb8bf28eb 22263 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22264 typedef struct fid_parse_with_arg {
Marko Mikulicic 0:c0ecb8bf28eb 22265 } fid_parse_with_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22266 #else
Marko Mikulicic 0:c0ecb8bf28eb 22267 typedef cr_zero_size_type_t fid_parse_with_arg_t;
Marko Mikulicic 0:c0ecb8bf28eb 22268 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22269
Marko Mikulicic 0:c0ecb8bf28eb 22270 /* parse_with's data on stack */
Marko Mikulicic 0:c0ecb8bf28eb 22271 typedef struct fid_parse_with_locals {
Marko Mikulicic 0:c0ecb8bf28eb 22272 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22273 struct fid_parse_with_arg arg;
Marko Mikulicic 0:c0ecb8bf28eb 22274 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22275
Marko Mikulicic 0:c0ecb8bf28eb 22276 ast_off_t start;
Marko Mikulicic 0:c0ecb8bf28eb 22277 } fid_parse_with_locals_t;
Marko Mikulicic 0:c0ecb8bf28eb 22278
Marko Mikulicic 0:c0ecb8bf28eb 22279 #define CALL_PARSE_WITH(_label) \
Marko Mikulicic 0:c0ecb8bf28eb 22280 do { \
Marko Mikulicic 0:c0ecb8bf28eb 22281 CR_CALL(fid_parse_with, _label); \
Marko Mikulicic 0:c0ecb8bf28eb 22282 } while (0)
Marko Mikulicic 0:c0ecb8bf28eb 22283 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 22284
Marko Mikulicic 0:c0ecb8bf28eb 22285 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 22286
Marko Mikulicic 0:c0ecb8bf28eb 22287 /*
Marko Mikulicic 0:c0ecb8bf28eb 22288 * Array of "function" descriptors. Each descriptor contains just a size
Marko Mikulicic 0:c0ecb8bf28eb 22289 * of "function"'s locals.
Marko Mikulicic 0:c0ecb8bf28eb 22290 */
Marko Mikulicic 0:c0ecb8bf28eb 22291 static const struct cr_func_desc _fid_descrs[MY_FID_CNT] = {
Marko Mikulicic 0:c0ecb8bf28eb 22292
Marko Mikulicic 0:c0ecb8bf28eb 22293 /* fid_none */
Marko Mikulicic 0:c0ecb8bf28eb 22294 {0},
Marko Mikulicic 0:c0ecb8bf28eb 22295
Marko Mikulicic 0:c0ecb8bf28eb 22296 /* fid_parse_script ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22297 /* fid_parse_script */
Marko Mikulicic 0:c0ecb8bf28eb 22298 {CR_LOCALS_SIZEOF(fid_parse_script_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22299 /* fid_p_script_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22300 {CR_LOCALS_SIZEOF(fid_parse_script_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22301 /* fid_p_script_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22302 {CR_LOCALS_SIZEOF(fid_parse_script_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22303 /* fid_p_script_3 */
Marko Mikulicic 0:c0ecb8bf28eb 22304 {CR_LOCALS_SIZEOF(fid_parse_script_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22305 /* fid_p_script_4 */
Marko Mikulicic 0:c0ecb8bf28eb 22306 {CR_LOCALS_SIZEOF(fid_parse_script_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22307
Marko Mikulicic 0:c0ecb8bf28eb 22308 /* fid_parse_use_strict ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22309 /* fid_parse_use_strict */
Marko Mikulicic 0:c0ecb8bf28eb 22310 {CR_LOCALS_SIZEOF(fid_parse_use_strict_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22311
Marko Mikulicic 0:c0ecb8bf28eb 22312 /* fid_parse_body ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22313 /* fid_parse_body */
Marko Mikulicic 0:c0ecb8bf28eb 22314 {CR_LOCALS_SIZEOF(fid_parse_body_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22315 /* fid_p_body_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22316 {CR_LOCALS_SIZEOF(fid_parse_body_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22317 /* fid_p_body_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22318 {CR_LOCALS_SIZEOF(fid_parse_body_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22319
Marko Mikulicic 0:c0ecb8bf28eb 22320 /* fid_parse_statement ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22321 /* fid_parse_statement */
Marko Mikulicic 0:c0ecb8bf28eb 22322 {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22323 /* fid_p_stat_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22324 {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22325 /* fid_p_stat_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22326 {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22327 /* fid_p_stat_3 */
Marko Mikulicic 0:c0ecb8bf28eb 22328 {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22329 /* fid_p_stat_4 */
Marko Mikulicic 0:c0ecb8bf28eb 22330 {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22331 /* fid_p_stat_5 */
Marko Mikulicic 0:c0ecb8bf28eb 22332 {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22333 /* fid_p_stat_6 */
Marko Mikulicic 0:c0ecb8bf28eb 22334 {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22335 /* fid_p_stat_7 */
Marko Mikulicic 0:c0ecb8bf28eb 22336 {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22337 /* fid_p_stat_8 */
Marko Mikulicic 0:c0ecb8bf28eb 22338 {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22339 /* fid_p_stat_9 */
Marko Mikulicic 0:c0ecb8bf28eb 22340 {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22341 /* fid_p_stat_10 */
Marko Mikulicic 0:c0ecb8bf28eb 22342 {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22343 /* fid_p_stat_11 */
Marko Mikulicic 0:c0ecb8bf28eb 22344 {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22345 /* fid_p_stat_12 */
Marko Mikulicic 0:c0ecb8bf28eb 22346 {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22347 /* fid_p_stat_13 */
Marko Mikulicic 0:c0ecb8bf28eb 22348 {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22349 /* fid_p_stat_14 */
Marko Mikulicic 0:c0ecb8bf28eb 22350 {CR_LOCALS_SIZEOF(fid_parse_statement_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22351
Marko Mikulicic 0:c0ecb8bf28eb 22352 /* fid_parse_expression ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22353 /* fid_parse_expression */
Marko Mikulicic 0:c0ecb8bf28eb 22354 {CR_LOCALS_SIZEOF(fid_parse_expression_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22355 /* fid_p_expr_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22356 {CR_LOCALS_SIZEOF(fid_parse_expression_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22357
Marko Mikulicic 0:c0ecb8bf28eb 22358 /* fid_parse_assign ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22359 /* fid_parse_assign */
Marko Mikulicic 0:c0ecb8bf28eb 22360 {CR_LOCALS_SIZEOF(fid_parse_assign_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22361 /* fid_p_assign_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22362 {CR_LOCALS_SIZEOF(fid_parse_assign_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22363
Marko Mikulicic 0:c0ecb8bf28eb 22364 /* fid_parse_binary ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22365 /* fid_parse_binary */
Marko Mikulicic 0:c0ecb8bf28eb 22366 {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22367 /* fid_p_binary_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22368 {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22369 /* fid_p_binary_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22370 {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22371 /* fid_p_binary_3 */
Marko Mikulicic 0:c0ecb8bf28eb 22372 {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22373 /* fid_p_binary_4 */
Marko Mikulicic 0:c0ecb8bf28eb 22374 {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22375 /* fid_p_binary_5 */
Marko Mikulicic 0:c0ecb8bf28eb 22376 {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22377 /* fid_p_binary_6 */
Marko Mikulicic 0:c0ecb8bf28eb 22378 {CR_LOCALS_SIZEOF(fid_parse_binary_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22379
Marko Mikulicic 0:c0ecb8bf28eb 22380 /* fid_parse_prefix ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22381 /* fid_parse_prefix */
Marko Mikulicic 0:c0ecb8bf28eb 22382 {CR_LOCALS_SIZEOF(fid_parse_prefix_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22383 /* fid_p_prefix_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22384 {CR_LOCALS_SIZEOF(fid_parse_prefix_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22385
Marko Mikulicic 0:c0ecb8bf28eb 22386 /* fid_parse_postfix ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22387 /* fid_parse_postfix */
Marko Mikulicic 0:c0ecb8bf28eb 22388 {CR_LOCALS_SIZEOF(fid_parse_postfix_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22389 /* fid_p_postfix_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22390 {CR_LOCALS_SIZEOF(fid_parse_postfix_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22391
Marko Mikulicic 0:c0ecb8bf28eb 22392 /* fid_parse_callexpr ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22393 /* fid_parse_callexpr */
Marko Mikulicic 0:c0ecb8bf28eb 22394 {CR_LOCALS_SIZEOF(fid_parse_callexpr_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22395 /* fid_p_callexpr_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22396 {CR_LOCALS_SIZEOF(fid_parse_callexpr_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22397 /* fid_p_callexpr_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22398 {CR_LOCALS_SIZEOF(fid_parse_callexpr_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22399 /* fid_p_callexpr_3 */
Marko Mikulicic 0:c0ecb8bf28eb 22400 {CR_LOCALS_SIZEOF(fid_parse_callexpr_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22401
Marko Mikulicic 0:c0ecb8bf28eb 22402 /* fid_parse_newexpr ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22403 /* fid_parse_newexpr */
Marko Mikulicic 0:c0ecb8bf28eb 22404 {CR_LOCALS_SIZEOF(fid_parse_newexpr_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22405 /* fid_p_newexpr_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22406 {CR_LOCALS_SIZEOF(fid_parse_newexpr_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22407 /* fid_p_newexpr_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22408 {CR_LOCALS_SIZEOF(fid_parse_newexpr_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22409 /* fid_p_newexpr_3 */
Marko Mikulicic 0:c0ecb8bf28eb 22410 {CR_LOCALS_SIZEOF(fid_parse_newexpr_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22411 /* fid_p_newexpr_4 */
Marko Mikulicic 0:c0ecb8bf28eb 22412 {CR_LOCALS_SIZEOF(fid_parse_newexpr_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22413
Marko Mikulicic 0:c0ecb8bf28eb 22414 /* fid_parse_terminal ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22415 /* fid_parse_terminal */
Marko Mikulicic 0:c0ecb8bf28eb 22416 {CR_LOCALS_SIZEOF(fid_parse_terminal_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22417 /* fid_p_terminal_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22418 {CR_LOCALS_SIZEOF(fid_parse_terminal_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22419 /* fid_p_terminal_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22420 {CR_LOCALS_SIZEOF(fid_parse_terminal_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22421 /* fid_p_terminal_3 */
Marko Mikulicic 0:c0ecb8bf28eb 22422 {CR_LOCALS_SIZEOF(fid_parse_terminal_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22423 /* fid_p_terminal_4 */
Marko Mikulicic 0:c0ecb8bf28eb 22424 {CR_LOCALS_SIZEOF(fid_parse_terminal_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22425
Marko Mikulicic 0:c0ecb8bf28eb 22426 /* fid_parse_block ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22427 /* fid_parse_block */
Marko Mikulicic 0:c0ecb8bf28eb 22428 {CR_LOCALS_SIZEOF(fid_parse_block_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22429 /* fid_p_block_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22430 {CR_LOCALS_SIZEOF(fid_parse_block_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22431
Marko Mikulicic 0:c0ecb8bf28eb 22432 /* fid_parse_if ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22433 /* fid_parse_if */
Marko Mikulicic 0:c0ecb8bf28eb 22434 {CR_LOCALS_SIZEOF(fid_parse_if_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22435 /* fid_p_if_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22436 {CR_LOCALS_SIZEOF(fid_parse_if_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22437 /* fid_p_if_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22438 {CR_LOCALS_SIZEOF(fid_parse_if_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22439 /* fid_p_if_3 */
Marko Mikulicic 0:c0ecb8bf28eb 22440 {CR_LOCALS_SIZEOF(fid_parse_if_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22441
Marko Mikulicic 0:c0ecb8bf28eb 22442 /* fid_parse_while ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22443 /* fid_parse_while */
Marko Mikulicic 0:c0ecb8bf28eb 22444 {CR_LOCALS_SIZEOF(fid_parse_while_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22445 /* fid_p_while_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22446 {CR_LOCALS_SIZEOF(fid_parse_while_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22447 /* fid_p_while_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22448 {CR_LOCALS_SIZEOF(fid_parse_while_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22449
Marko Mikulicic 0:c0ecb8bf28eb 22450 /* fid_parse_ident ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22451 /* fid_parse_ident */
Marko Mikulicic 0:c0ecb8bf28eb 22452 {CR_LOCALS_SIZEOF(fid_parse_ident_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22453
Marko Mikulicic 0:c0ecb8bf28eb 22454 /* fid_parse_ident_allow_reserved_words -------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22455 /* fid_parse_ident_allow_reserved_words */
Marko Mikulicic 0:c0ecb8bf28eb 22456 {CR_LOCALS_SIZEOF(fid_parse_ident_allow_reserved_words_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22457 /* fid_p_ident_allow_reserved_words_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22458 {CR_LOCALS_SIZEOF(fid_parse_ident_allow_reserved_words_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22459
Marko Mikulicic 0:c0ecb8bf28eb 22460 /* fid_parse_funcdecl ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22461 /* fid_parse_funcdecl */
Marko Mikulicic 0:c0ecb8bf28eb 22462 {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22463 /* fid_p_funcdecl_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22464 {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22465 /* fid_p_funcdecl_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22466 {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22467 /* fid_p_funcdecl_3 */
Marko Mikulicic 0:c0ecb8bf28eb 22468 {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22469 /* fid_p_funcdecl_4 */
Marko Mikulicic 0:c0ecb8bf28eb 22470 {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22471 /* fid_p_funcdecl_5 */
Marko Mikulicic 0:c0ecb8bf28eb 22472 {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22473 /* fid_p_funcdecl_6 */
Marko Mikulicic 0:c0ecb8bf28eb 22474 {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22475 /* fid_p_funcdecl_7 */
Marko Mikulicic 0:c0ecb8bf28eb 22476 {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22477 /* fid_p_funcdecl_8 */
Marko Mikulicic 0:c0ecb8bf28eb 22478 {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22479 /* fid_p_funcdecl_9 */
Marko Mikulicic 0:c0ecb8bf28eb 22480 {CR_LOCALS_SIZEOF(fid_parse_funcdecl_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22481
Marko Mikulicic 0:c0ecb8bf28eb 22482 /* fid_parse_arglist ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22483 /* fid_parse_arglist */
Marko Mikulicic 0:c0ecb8bf28eb 22484 {CR_LOCALS_SIZEOF(fid_parse_arglist_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22485 /* fid_p_arglist_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22486 {CR_LOCALS_SIZEOF(fid_parse_arglist_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22487
Marko Mikulicic 0:c0ecb8bf28eb 22488 /* fid_parse_member ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22489 /* fid_parse_member */
Marko Mikulicic 0:c0ecb8bf28eb 22490 {CR_LOCALS_SIZEOF(fid_parse_member_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22491 /* fid_p_member_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22492 {CR_LOCALS_SIZEOF(fid_parse_member_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22493
Marko Mikulicic 0:c0ecb8bf28eb 22494 /* fid_parse_memberexpr ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22495 /* fid_parse_memberexpr */
Marko Mikulicic 0:c0ecb8bf28eb 22496 {CR_LOCALS_SIZEOF(fid_parse_memberexpr_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22497 /* fid_p_memberexpr_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22498 {CR_LOCALS_SIZEOF(fid_parse_memberexpr_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22499 /* fid_p_memberexpr_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22500 {CR_LOCALS_SIZEOF(fid_parse_memberexpr_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22501
Marko Mikulicic 0:c0ecb8bf28eb 22502 /* fid_parse_var ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22503 /* fid_parse_var */
Marko Mikulicic 0:c0ecb8bf28eb 22504 {CR_LOCALS_SIZEOF(fid_parse_var_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22505 /* fid_p_var_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22506 {CR_LOCALS_SIZEOF(fid_parse_var_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22507
Marko Mikulicic 0:c0ecb8bf28eb 22508 /* fid_parse_prop ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22509 /* fid_parse_prop */
Marko Mikulicic 0:c0ecb8bf28eb 22510 {CR_LOCALS_SIZEOF(fid_parse_prop_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22511 #ifdef V7_ENABLE_JS_GETTERS
Marko Mikulicic 0:c0ecb8bf28eb 22512 /* fid_p_prop_1_getter */
Marko Mikulicic 0:c0ecb8bf28eb 22513 {CR_LOCALS_SIZEOF(fid_parse_prop_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22514 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22515 /* fid_p_prop_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22516 {CR_LOCALS_SIZEOF(fid_parse_prop_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22517 #ifdef V7_ENABLE_JS_SETTERS
Marko Mikulicic 0:c0ecb8bf28eb 22518 /* fid_p_prop_3_setter */
Marko Mikulicic 0:c0ecb8bf28eb 22519 {CR_LOCALS_SIZEOF(fid_parse_prop_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22520 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22521 /* fid_p_prop_4 */
Marko Mikulicic 0:c0ecb8bf28eb 22522 {CR_LOCALS_SIZEOF(fid_parse_prop_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22523
Marko Mikulicic 0:c0ecb8bf28eb 22524 /* fid_parse_dowhile ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22525 /* fid_parse_dowhile */
Marko Mikulicic 0:c0ecb8bf28eb 22526 {CR_LOCALS_SIZEOF(fid_parse_dowhile_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22527 /* fid_p_dowhile_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22528 {CR_LOCALS_SIZEOF(fid_parse_dowhile_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22529 /* fid_p_dowhile_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22530 {CR_LOCALS_SIZEOF(fid_parse_dowhile_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22531
Marko Mikulicic 0:c0ecb8bf28eb 22532 /* fid_parse_for ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22533 /* fid_parse_for */
Marko Mikulicic 0:c0ecb8bf28eb 22534 {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22535 /* fid_p_for_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22536 {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22537 /* fid_p_for_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22538 {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22539 /* fid_p_for_3 */
Marko Mikulicic 0:c0ecb8bf28eb 22540 {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22541 /* fid_p_for_4 */
Marko Mikulicic 0:c0ecb8bf28eb 22542 {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22543 /* fid_p_for_5 */
Marko Mikulicic 0:c0ecb8bf28eb 22544 {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22545 /* fid_p_for_6 */
Marko Mikulicic 0:c0ecb8bf28eb 22546 {CR_LOCALS_SIZEOF(fid_parse_for_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22547
Marko Mikulicic 0:c0ecb8bf28eb 22548 /* fid_parse_try ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22549 /* fid_parse_try */
Marko Mikulicic 0:c0ecb8bf28eb 22550 {CR_LOCALS_SIZEOF(fid_parse_try_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22551 /* fid_p_try_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22552 {CR_LOCALS_SIZEOF(fid_parse_try_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22553 /* fid_p_try_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22554 {CR_LOCALS_SIZEOF(fid_parse_try_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22555 /* fid_p_try_3 */
Marko Mikulicic 0:c0ecb8bf28eb 22556 {CR_LOCALS_SIZEOF(fid_parse_try_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22557 /* fid_p_try_4 */
Marko Mikulicic 0:c0ecb8bf28eb 22558 {CR_LOCALS_SIZEOF(fid_parse_try_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22559
Marko Mikulicic 0:c0ecb8bf28eb 22560 /* fid_parse_switch ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22561 /* fid_parse_switch */
Marko Mikulicic 0:c0ecb8bf28eb 22562 {CR_LOCALS_SIZEOF(fid_parse_switch_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22563 /* fid_p_switch_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22564 {CR_LOCALS_SIZEOF(fid_parse_switch_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22565 /* fid_p_switch_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22566 {CR_LOCALS_SIZEOF(fid_parse_switch_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22567 /* fid_p_switch_3 */
Marko Mikulicic 0:c0ecb8bf28eb 22568 {CR_LOCALS_SIZEOF(fid_parse_switch_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22569 /* fid_p_switch_4 */
Marko Mikulicic 0:c0ecb8bf28eb 22570 {CR_LOCALS_SIZEOF(fid_parse_switch_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22571
Marko Mikulicic 0:c0ecb8bf28eb 22572 /* fid_parse_with ----------------------------------------- */
Marko Mikulicic 0:c0ecb8bf28eb 22573 /* fid_parse_with */
Marko Mikulicic 0:c0ecb8bf28eb 22574 {CR_LOCALS_SIZEOF(fid_parse_with_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22575 /* fid_p_with_1 */
Marko Mikulicic 0:c0ecb8bf28eb 22576 {CR_LOCALS_SIZEOF(fid_parse_with_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22577 /* fid_p_with_2 */
Marko Mikulicic 0:c0ecb8bf28eb 22578 {CR_LOCALS_SIZEOF(fid_parse_with_locals_t)},
Marko Mikulicic 0:c0ecb8bf28eb 22579
Marko Mikulicic 0:c0ecb8bf28eb 22580 };
Marko Mikulicic 0:c0ecb8bf28eb 22581
Marko Mikulicic 0:c0ecb8bf28eb 22582 /*
Marko Mikulicic 0:c0ecb8bf28eb 22583 * Union of arguments and return values for all existing "functions".
Marko Mikulicic 0:c0ecb8bf28eb 22584 *
Marko Mikulicic 0:c0ecb8bf28eb 22585 * Used as an accumulator when we call function, return from function,
Marko Mikulicic 0:c0ecb8bf28eb 22586 * yield, or resume.
Marko Mikulicic 0:c0ecb8bf28eb 22587 */
Marko Mikulicic 0:c0ecb8bf28eb 22588 union user_arg_ret {
Marko Mikulicic 0:c0ecb8bf28eb 22589 /* arguments to the next function */
Marko Mikulicic 0:c0ecb8bf28eb 22590 union {
Marko Mikulicic 0:c0ecb8bf28eb 22591 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 22592 fid_parse_script_arg_t fid_parse_script;
Marko Mikulicic 0:c0ecb8bf28eb 22593 fid_parse_use_strict_arg_t fid_parse_use_strict;
Marko Mikulicic 0:c0ecb8bf28eb 22594 fid_parse_statement_arg_t fid_parse_statement;
Marko Mikulicic 0:c0ecb8bf28eb 22595 fid_parse_expression_arg_t fid_parse_expression;
Marko Mikulicic 0:c0ecb8bf28eb 22596 fid_parse_assign_arg_t fid_parse_assign;
Marko Mikulicic 0:c0ecb8bf28eb 22597 fid_parse_prefix_arg_t fid_parse_prefix;
Marko Mikulicic 0:c0ecb8bf28eb 22598 fid_parse_postfix_arg_t fid_parse_postfix;
Marko Mikulicic 0:c0ecb8bf28eb 22599 fid_parse_callexpr_arg_t fid_parse_callexpr;
Marko Mikulicic 0:c0ecb8bf28eb 22600 fid_parse_newexpr_arg_t fid_parse_newexpr;
Marko Mikulicic 0:c0ecb8bf28eb 22601 fid_parse_terminal_arg_t fid_parse_terminal;
Marko Mikulicic 0:c0ecb8bf28eb 22602 fid_parse_block_arg_t fid_parse_block;
Marko Mikulicic 0:c0ecb8bf28eb 22603 fid_parse_if_arg_t fid_parse_if;
Marko Mikulicic 0:c0ecb8bf28eb 22604 fid_parse_while_arg_t fid_parse_while;
Marko Mikulicic 0:c0ecb8bf28eb 22605 fid_parse_ident_arg_t fid_parse_ident;
Marko Mikulicic 0:c0ecb8bf28eb 22606 fid_parse_ident_allow_reserved_words_arg_t
Marko Mikulicic 0:c0ecb8bf28eb 22607 fid_parse_ident_allow_reserved_words;
Marko Mikulicic 0:c0ecb8bf28eb 22608 fid_parse_arglist_arg_t fid_parse_arglist;
Marko Mikulicic 0:c0ecb8bf28eb 22609 fid_parse_memberexpr_arg_t fid_parse_memberexpr;
Marko Mikulicic 0:c0ecb8bf28eb 22610 fid_parse_var_arg_t fid_parse_var;
Marko Mikulicic 0:c0ecb8bf28eb 22611 fid_parse_prop_arg_t fid_parse_prop;
Marko Mikulicic 0:c0ecb8bf28eb 22612 fid_parse_dowhile_arg_t fid_parse_dowhile;
Marko Mikulicic 0:c0ecb8bf28eb 22613 fid_parse_for_arg_t fid_parse_for;
Marko Mikulicic 0:c0ecb8bf28eb 22614 fid_parse_try_arg_t fid_parse_try;
Marko Mikulicic 0:c0ecb8bf28eb 22615 fid_parse_switch_arg_t fid_parse_switch;
Marko Mikulicic 0:c0ecb8bf28eb 22616 fid_parse_with_arg_t fid_parse_with;
Marko Mikulicic 0:c0ecb8bf28eb 22617 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22618 fid_parse_body_arg_t fid_parse_body;
Marko Mikulicic 0:c0ecb8bf28eb 22619 fid_parse_binary_arg_t fid_parse_binary;
Marko Mikulicic 0:c0ecb8bf28eb 22620 fid_parse_funcdecl_arg_t fid_parse_funcdecl;
Marko Mikulicic 0:c0ecb8bf28eb 22621 fid_parse_member_arg_t fid_parse_member;
Marko Mikulicic 0:c0ecb8bf28eb 22622 } arg;
Marko Mikulicic 0:c0ecb8bf28eb 22623
Marko Mikulicic 0:c0ecb8bf28eb 22624 /* value returned from function */
Marko Mikulicic 0:c0ecb8bf28eb 22625 /*
Marko Mikulicic 0:c0ecb8bf28eb 22626 union {
Marko Mikulicic 0:c0ecb8bf28eb 22627 } ret;
Marko Mikulicic 0:c0ecb8bf28eb 22628 */
Marko Mikulicic 0:c0ecb8bf28eb 22629 };
Marko Mikulicic 0:c0ecb8bf28eb 22630
Marko Mikulicic 0:c0ecb8bf28eb 22631 static enum v7_tok next_tok(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 22632 int prev_line_no = v7->pstate.prev_line_no;
Marko Mikulicic 0:c0ecb8bf28eb 22633 v7->pstate.prev_line_no = v7->pstate.line_no;
Marko Mikulicic 0:c0ecb8bf28eb 22634 v7->pstate.line_no += skip_to_next_tok(&v7->pstate.pc, v7->pstate.src_end);
Marko Mikulicic 0:c0ecb8bf28eb 22635 v7->after_newline = prev_line_no != v7->pstate.line_no;
Marko Mikulicic 0:c0ecb8bf28eb 22636 v7->tok = v7->pstate.pc;
Marko Mikulicic 0:c0ecb8bf28eb 22637 v7->cur_tok = get_tok(&v7->pstate.pc, v7->pstate.src_end, &v7->cur_tok_dbl,
Marko Mikulicic 0:c0ecb8bf28eb 22638 v7->cur_tok);
Marko Mikulicic 0:c0ecb8bf28eb 22639 v7->tok_len = v7->pstate.pc - v7->tok;
Marko Mikulicic 0:c0ecb8bf28eb 22640 v7->pstate.line_no += skip_to_next_tok(&v7->pstate.pc, v7->pstate.src_end);
Marko Mikulicic 0:c0ecb8bf28eb 22641 return v7->cur_tok;
Marko Mikulicic 0:c0ecb8bf28eb 22642 }
Marko Mikulicic 0:c0ecb8bf28eb 22643
Marko Mikulicic 0:c0ecb8bf28eb 22644 #ifndef V7_DISABLE_LINE_NUMBERS
Marko Mikulicic 0:c0ecb8bf28eb 22645 /*
Marko Mikulicic 0:c0ecb8bf28eb 22646 * Assumes `offset` points to the byte right after a tag
Marko Mikulicic 0:c0ecb8bf28eb 22647 */
Marko Mikulicic 0:c0ecb8bf28eb 22648 static void insert_line_no_if_changed(struct v7 *v7, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 22649 ast_off_t offset) {
Marko Mikulicic 0:c0ecb8bf28eb 22650 if (v7->pstate.prev_line_no != v7->line_no) {
Marko Mikulicic 0:c0ecb8bf28eb 22651 v7->line_no = v7->pstate.prev_line_no;
Marko Mikulicic 0:c0ecb8bf28eb 22652 ast_add_line_no(a, offset - 1, v7->line_no);
Marko Mikulicic 0:c0ecb8bf28eb 22653 } else {
Marko Mikulicic 0:c0ecb8bf28eb 22654 #if V7_AST_FORCE_LINE_NUMBERS
Marko Mikulicic 0:c0ecb8bf28eb 22655 /*
Marko Mikulicic 0:c0ecb8bf28eb 22656 * This mode is needed for debug only: to make sure AST consumers correctly
Marko Mikulicic 0:c0ecb8bf28eb 22657 * consume all nodes with line numbers data encoded
Marko Mikulicic 0:c0ecb8bf28eb 22658 */
Marko Mikulicic 0:c0ecb8bf28eb 22659 ast_add_line_no(a, offset - 1, 0);
Marko Mikulicic 0:c0ecb8bf28eb 22660 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22661 }
Marko Mikulicic 0:c0ecb8bf28eb 22662 }
Marko Mikulicic 0:c0ecb8bf28eb 22663 #else
Marko Mikulicic 0:c0ecb8bf28eb 22664 static void insert_line_no_if_changed(struct v7 *v7, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 22665 ast_off_t offset) {
Marko Mikulicic 0:c0ecb8bf28eb 22666 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 22667 (void) a;
Marko Mikulicic 0:c0ecb8bf28eb 22668 (void) offset;
Marko Mikulicic 0:c0ecb8bf28eb 22669 }
Marko Mikulicic 0:c0ecb8bf28eb 22670 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22671
Marko Mikulicic 0:c0ecb8bf28eb 22672 static ast_off_t insert_node(struct v7 *v7, struct ast *a, ast_off_t start,
Marko Mikulicic 0:c0ecb8bf28eb 22673 enum ast_tag tag) {
Marko Mikulicic 0:c0ecb8bf28eb 22674 ast_off_t ret = ast_insert_node(a, start, tag);
Marko Mikulicic 0:c0ecb8bf28eb 22675 insert_line_no_if_changed(v7, a, ret);
Marko Mikulicic 0:c0ecb8bf28eb 22676 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 22677 }
Marko Mikulicic 0:c0ecb8bf28eb 22678
Marko Mikulicic 0:c0ecb8bf28eb 22679 static ast_off_t add_node(struct v7 *v7, struct ast *a, enum ast_tag tag) {
Marko Mikulicic 0:c0ecb8bf28eb 22680 return insert_node(v7, a, a->mbuf.len, tag);
Marko Mikulicic 0:c0ecb8bf28eb 22681 }
Marko Mikulicic 0:c0ecb8bf28eb 22682
Marko Mikulicic 0:c0ecb8bf28eb 22683 static ast_off_t insert_inlined_node(struct v7 *v7, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 22684 ast_off_t start, enum ast_tag tag,
Marko Mikulicic 0:c0ecb8bf28eb 22685 const char *name, size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 22686 ast_off_t ret = ast_insert_inlined_node(a, start, tag, name, len);
Marko Mikulicic 0:c0ecb8bf28eb 22687 insert_line_no_if_changed(v7, a, ret);
Marko Mikulicic 0:c0ecb8bf28eb 22688 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 22689 }
Marko Mikulicic 0:c0ecb8bf28eb 22690
Marko Mikulicic 0:c0ecb8bf28eb 22691 static ast_off_t add_inlined_node(struct v7 *v7, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 22692 enum ast_tag tag, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 22693 size_t len) {
Marko Mikulicic 0:c0ecb8bf28eb 22694 return insert_inlined_node(v7, a, a->mbuf.len, tag, name, len);
Marko Mikulicic 0:c0ecb8bf28eb 22695 }
Marko Mikulicic 0:c0ecb8bf28eb 22696
Marko Mikulicic 0:c0ecb8bf28eb 22697 static unsigned long get_column(const char *code, const char *pos) {
Marko Mikulicic 0:c0ecb8bf28eb 22698 const char *p = pos;
Marko Mikulicic 0:c0ecb8bf28eb 22699 while (p > code && *p != '\n') {
Marko Mikulicic 0:c0ecb8bf28eb 22700 p--;
Marko Mikulicic 0:c0ecb8bf28eb 22701 }
Marko Mikulicic 0:c0ecb8bf28eb 22702 return p == code ? pos - p : pos - (p + 1);
Marko Mikulicic 0:c0ecb8bf28eb 22703 }
Marko Mikulicic 0:c0ecb8bf28eb 22704
Marko Mikulicic 0:c0ecb8bf28eb 22705 static enum v7_err end_of_statement(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 22706 if (v7->cur_tok == TOK_SEMICOLON || v7->cur_tok == TOK_END_OF_INPUT ||
Marko Mikulicic 0:c0ecb8bf28eb 22707 v7->cur_tok == TOK_CLOSE_CURLY || v7->after_newline) {
Marko Mikulicic 0:c0ecb8bf28eb 22708 return V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 22709 }
Marko Mikulicic 0:c0ecb8bf28eb 22710 return V7_SYNTAX_ERROR;
Marko Mikulicic 0:c0ecb8bf28eb 22711 }
Marko Mikulicic 0:c0ecb8bf28eb 22712
Marko Mikulicic 0:c0ecb8bf28eb 22713 static enum v7_tok lookahead(const struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 22714 const char *s = v7->pstate.pc;
Marko Mikulicic 0:c0ecb8bf28eb 22715 double d;
Marko Mikulicic 0:c0ecb8bf28eb 22716 return get_tok(&s, v7->pstate.src_end, &d, v7->cur_tok);
Marko Mikulicic 0:c0ecb8bf28eb 22717 }
Marko Mikulicic 0:c0ecb8bf28eb 22718
Marko Mikulicic 0:c0ecb8bf28eb 22719 static int parse_optional(struct v7 *v7, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 22720 enum v7_tok terminator) {
Marko Mikulicic 0:c0ecb8bf28eb 22721 if (v7->cur_tok != terminator) {
Marko Mikulicic 0:c0ecb8bf28eb 22722 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 22723 }
Marko Mikulicic 0:c0ecb8bf28eb 22724 add_node(v7, a, AST_NOP);
Marko Mikulicic 0:c0ecb8bf28eb 22725 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 22726 }
Marko Mikulicic 0:c0ecb8bf28eb 22727
Marko Mikulicic 0:c0ecb8bf28eb 22728 /*
Marko Mikulicic 0:c0ecb8bf28eb 22729 * On ESP8266 'levels' declaration have to be outside of 'parse_binary'
Marko Mikulicic 0:c0ecb8bf28eb 22730 * in order to prevent reboot on return from this function
Marko Mikulicic 0:c0ecb8bf28eb 22731 * TODO(alashkin): understand why
Marko Mikulicic 0:c0ecb8bf28eb 22732 */
Marko Mikulicic 0:c0ecb8bf28eb 22733 #define NONE \
Marko Mikulicic 0:c0ecb8bf28eb 22734 { (enum v7_tok) 0, (enum v7_tok) 0, (enum ast_tag) 0 }
Marko Mikulicic 0:c0ecb8bf28eb 22735
Marko Mikulicic 0:c0ecb8bf28eb 22736 static const struct {
Marko Mikulicic 0:c0ecb8bf28eb 22737 int len, left_to_right;
Marko Mikulicic 0:c0ecb8bf28eb 22738 struct {
Marko Mikulicic 0:c0ecb8bf28eb 22739 enum v7_tok start_tok, end_tok;
Marko Mikulicic 0:c0ecb8bf28eb 22740 enum ast_tag start_ast;
Marko Mikulicic 0:c0ecb8bf28eb 22741 } parts[2];
Marko Mikulicic 0:c0ecb8bf28eb 22742 } levels[] = {
Marko Mikulicic 0:c0ecb8bf28eb 22743 {1, 0, {{TOK_ASSIGN, TOK_URSHIFT_ASSIGN, AST_ASSIGN}, NONE}},
Marko Mikulicic 0:c0ecb8bf28eb 22744 {1, 0, {{TOK_QUESTION, TOK_QUESTION, AST_COND}, NONE}},
Marko Mikulicic 0:c0ecb8bf28eb 22745 {1, 1, {{TOK_LOGICAL_OR, TOK_LOGICAL_OR, AST_LOGICAL_OR}, NONE}},
Marko Mikulicic 0:c0ecb8bf28eb 22746 {1, 1, {{TOK_LOGICAL_AND, TOK_LOGICAL_AND, AST_LOGICAL_AND}, NONE}},
Marko Mikulicic 0:c0ecb8bf28eb 22747 {1, 1, {{TOK_OR, TOK_OR, AST_OR}, NONE}},
Marko Mikulicic 0:c0ecb8bf28eb 22748 {1, 1, {{TOK_XOR, TOK_XOR, AST_XOR}, NONE}},
Marko Mikulicic 0:c0ecb8bf28eb 22749 {1, 1, {{TOK_AND, TOK_AND, AST_AND}, NONE}},
Marko Mikulicic 0:c0ecb8bf28eb 22750 {1, 1, {{TOK_EQ, TOK_NE_NE, AST_EQ}, NONE}},
Marko Mikulicic 0:c0ecb8bf28eb 22751 {2, 1, {{TOK_LE, TOK_GT, AST_LE}, {TOK_IN, TOK_INSTANCEOF, AST_IN}}},
Marko Mikulicic 0:c0ecb8bf28eb 22752 {1, 1, {{TOK_LSHIFT, TOK_URSHIFT, AST_LSHIFT}, NONE}},
Marko Mikulicic 0:c0ecb8bf28eb 22753 {1, 1, {{TOK_PLUS, TOK_MINUS, AST_ADD}, NONE}},
Marko Mikulicic 0:c0ecb8bf28eb 22754 {1, 1, {{TOK_REM, TOK_DIV, AST_REM}, NONE}}};
Marko Mikulicic 0:c0ecb8bf28eb 22755
Marko Mikulicic 0:c0ecb8bf28eb 22756 enum cr_status parser_cr_exec(struct cr_ctx *p_ctx, struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 22757 struct ast *a) {
Marko Mikulicic 0:c0ecb8bf28eb 22758 enum cr_status rc = CR_RES__OK;
Marko Mikulicic 0:c0ecb8bf28eb 22759
Marko Mikulicic 0:c0ecb8bf28eb 22760 _cr_iter_begin:
Marko Mikulicic 0:c0ecb8bf28eb 22761
Marko Mikulicic 0:c0ecb8bf28eb 22762 rc = cr_on_iter_begin(p_ctx);
Marko Mikulicic 0:c0ecb8bf28eb 22763 if (rc != CR_RES__OK) {
Marko Mikulicic 0:c0ecb8bf28eb 22764 return rc;
Marko Mikulicic 0:c0ecb8bf28eb 22765 }
Marko Mikulicic 0:c0ecb8bf28eb 22766
Marko Mikulicic 0:c0ecb8bf28eb 22767 /*
Marko Mikulicic 0:c0ecb8bf28eb 22768 * dispatcher switch: depending on the fid, jump to the corresponding label
Marko Mikulicic 0:c0ecb8bf28eb 22769 */
Marko Mikulicic 0:c0ecb8bf28eb 22770 switch ((enum my_fid) CR_CURR_FUNC()) {
Marko Mikulicic 0:c0ecb8bf28eb 22771 CR_DEFINE_ENTRY_POINT(fid_none);
Marko Mikulicic 0:c0ecb8bf28eb 22772
Marko Mikulicic 0:c0ecb8bf28eb 22773 CR_DEFINE_ENTRY_POINT(fid_parse_script);
Marko Mikulicic 0:c0ecb8bf28eb 22774 CR_DEFINE_ENTRY_POINT(fid_p_script_1);
Marko Mikulicic 0:c0ecb8bf28eb 22775 CR_DEFINE_ENTRY_POINT(fid_p_script_2);
Marko Mikulicic 0:c0ecb8bf28eb 22776 CR_DEFINE_ENTRY_POINT(fid_p_script_3);
Marko Mikulicic 0:c0ecb8bf28eb 22777 CR_DEFINE_ENTRY_POINT(fid_p_script_4);
Marko Mikulicic 0:c0ecb8bf28eb 22778
Marko Mikulicic 0:c0ecb8bf28eb 22779 CR_DEFINE_ENTRY_POINT(fid_parse_use_strict);
Marko Mikulicic 0:c0ecb8bf28eb 22780
Marko Mikulicic 0:c0ecb8bf28eb 22781 CR_DEFINE_ENTRY_POINT(fid_parse_body);
Marko Mikulicic 0:c0ecb8bf28eb 22782 CR_DEFINE_ENTRY_POINT(fid_p_body_1);
Marko Mikulicic 0:c0ecb8bf28eb 22783 CR_DEFINE_ENTRY_POINT(fid_p_body_2);
Marko Mikulicic 0:c0ecb8bf28eb 22784
Marko Mikulicic 0:c0ecb8bf28eb 22785 CR_DEFINE_ENTRY_POINT(fid_parse_statement);
Marko Mikulicic 0:c0ecb8bf28eb 22786 CR_DEFINE_ENTRY_POINT(fid_p_stat_1);
Marko Mikulicic 0:c0ecb8bf28eb 22787 CR_DEFINE_ENTRY_POINT(fid_p_stat_2);
Marko Mikulicic 0:c0ecb8bf28eb 22788 CR_DEFINE_ENTRY_POINT(fid_p_stat_3);
Marko Mikulicic 0:c0ecb8bf28eb 22789 CR_DEFINE_ENTRY_POINT(fid_p_stat_4);
Marko Mikulicic 0:c0ecb8bf28eb 22790 CR_DEFINE_ENTRY_POINT(fid_p_stat_5);
Marko Mikulicic 0:c0ecb8bf28eb 22791 CR_DEFINE_ENTRY_POINT(fid_p_stat_6);
Marko Mikulicic 0:c0ecb8bf28eb 22792 CR_DEFINE_ENTRY_POINT(fid_p_stat_7);
Marko Mikulicic 0:c0ecb8bf28eb 22793 CR_DEFINE_ENTRY_POINT(fid_p_stat_8);
Marko Mikulicic 0:c0ecb8bf28eb 22794 CR_DEFINE_ENTRY_POINT(fid_p_stat_9);
Marko Mikulicic 0:c0ecb8bf28eb 22795 CR_DEFINE_ENTRY_POINT(fid_p_stat_10);
Marko Mikulicic 0:c0ecb8bf28eb 22796 CR_DEFINE_ENTRY_POINT(fid_p_stat_11);
Marko Mikulicic 0:c0ecb8bf28eb 22797 CR_DEFINE_ENTRY_POINT(fid_p_stat_12);
Marko Mikulicic 0:c0ecb8bf28eb 22798 CR_DEFINE_ENTRY_POINT(fid_p_stat_13);
Marko Mikulicic 0:c0ecb8bf28eb 22799 CR_DEFINE_ENTRY_POINT(fid_p_stat_14);
Marko Mikulicic 0:c0ecb8bf28eb 22800
Marko Mikulicic 0:c0ecb8bf28eb 22801 CR_DEFINE_ENTRY_POINT(fid_parse_expression);
Marko Mikulicic 0:c0ecb8bf28eb 22802 CR_DEFINE_ENTRY_POINT(fid_p_expr_1);
Marko Mikulicic 0:c0ecb8bf28eb 22803
Marko Mikulicic 0:c0ecb8bf28eb 22804 CR_DEFINE_ENTRY_POINT(fid_parse_assign);
Marko Mikulicic 0:c0ecb8bf28eb 22805 CR_DEFINE_ENTRY_POINT(fid_p_assign_1);
Marko Mikulicic 0:c0ecb8bf28eb 22806
Marko Mikulicic 0:c0ecb8bf28eb 22807 CR_DEFINE_ENTRY_POINT(fid_parse_binary);
Marko Mikulicic 0:c0ecb8bf28eb 22808 CR_DEFINE_ENTRY_POINT(fid_p_binary_2);
Marko Mikulicic 0:c0ecb8bf28eb 22809 CR_DEFINE_ENTRY_POINT(fid_p_binary_3);
Marko Mikulicic 0:c0ecb8bf28eb 22810 CR_DEFINE_ENTRY_POINT(fid_p_binary_4);
Marko Mikulicic 0:c0ecb8bf28eb 22811 CR_DEFINE_ENTRY_POINT(fid_p_binary_5);
Marko Mikulicic 0:c0ecb8bf28eb 22812 CR_DEFINE_ENTRY_POINT(fid_p_binary_6);
Marko Mikulicic 0:c0ecb8bf28eb 22813
Marko Mikulicic 0:c0ecb8bf28eb 22814 CR_DEFINE_ENTRY_POINT(fid_parse_prefix);
Marko Mikulicic 0:c0ecb8bf28eb 22815 CR_DEFINE_ENTRY_POINT(fid_p_prefix_1);
Marko Mikulicic 0:c0ecb8bf28eb 22816
Marko Mikulicic 0:c0ecb8bf28eb 22817 CR_DEFINE_ENTRY_POINT(fid_parse_postfix);
Marko Mikulicic 0:c0ecb8bf28eb 22818 CR_DEFINE_ENTRY_POINT(fid_p_postfix_1);
Marko Mikulicic 0:c0ecb8bf28eb 22819
Marko Mikulicic 0:c0ecb8bf28eb 22820 CR_DEFINE_ENTRY_POINT(fid_parse_callexpr);
Marko Mikulicic 0:c0ecb8bf28eb 22821 CR_DEFINE_ENTRY_POINT(fid_p_callexpr_1);
Marko Mikulicic 0:c0ecb8bf28eb 22822 CR_DEFINE_ENTRY_POINT(fid_p_callexpr_2);
Marko Mikulicic 0:c0ecb8bf28eb 22823 CR_DEFINE_ENTRY_POINT(fid_p_callexpr_3);
Marko Mikulicic 0:c0ecb8bf28eb 22824
Marko Mikulicic 0:c0ecb8bf28eb 22825 CR_DEFINE_ENTRY_POINT(fid_parse_newexpr);
Marko Mikulicic 0:c0ecb8bf28eb 22826 CR_DEFINE_ENTRY_POINT(fid_p_newexpr_1);
Marko Mikulicic 0:c0ecb8bf28eb 22827 CR_DEFINE_ENTRY_POINT(fid_p_newexpr_2);
Marko Mikulicic 0:c0ecb8bf28eb 22828 CR_DEFINE_ENTRY_POINT(fid_p_newexpr_3);
Marko Mikulicic 0:c0ecb8bf28eb 22829 CR_DEFINE_ENTRY_POINT(fid_p_newexpr_4);
Marko Mikulicic 0:c0ecb8bf28eb 22830
Marko Mikulicic 0:c0ecb8bf28eb 22831 CR_DEFINE_ENTRY_POINT(fid_parse_terminal);
Marko Mikulicic 0:c0ecb8bf28eb 22832 CR_DEFINE_ENTRY_POINT(fid_p_terminal_1);
Marko Mikulicic 0:c0ecb8bf28eb 22833 CR_DEFINE_ENTRY_POINT(fid_p_terminal_2);
Marko Mikulicic 0:c0ecb8bf28eb 22834 CR_DEFINE_ENTRY_POINT(fid_p_terminal_3);
Marko Mikulicic 0:c0ecb8bf28eb 22835 CR_DEFINE_ENTRY_POINT(fid_p_terminal_4);
Marko Mikulicic 0:c0ecb8bf28eb 22836
Marko Mikulicic 0:c0ecb8bf28eb 22837 CR_DEFINE_ENTRY_POINT(fid_parse_block);
Marko Mikulicic 0:c0ecb8bf28eb 22838 CR_DEFINE_ENTRY_POINT(fid_p_block_1);
Marko Mikulicic 0:c0ecb8bf28eb 22839
Marko Mikulicic 0:c0ecb8bf28eb 22840 CR_DEFINE_ENTRY_POINT(fid_parse_if);
Marko Mikulicic 0:c0ecb8bf28eb 22841 CR_DEFINE_ENTRY_POINT(fid_p_if_1);
Marko Mikulicic 0:c0ecb8bf28eb 22842 CR_DEFINE_ENTRY_POINT(fid_p_if_2);
Marko Mikulicic 0:c0ecb8bf28eb 22843 CR_DEFINE_ENTRY_POINT(fid_p_if_3);
Marko Mikulicic 0:c0ecb8bf28eb 22844
Marko Mikulicic 0:c0ecb8bf28eb 22845 CR_DEFINE_ENTRY_POINT(fid_parse_while);
Marko Mikulicic 0:c0ecb8bf28eb 22846 CR_DEFINE_ENTRY_POINT(fid_p_while_1);
Marko Mikulicic 0:c0ecb8bf28eb 22847 CR_DEFINE_ENTRY_POINT(fid_p_while_2);
Marko Mikulicic 0:c0ecb8bf28eb 22848
Marko Mikulicic 0:c0ecb8bf28eb 22849 CR_DEFINE_ENTRY_POINT(fid_parse_ident);
Marko Mikulicic 0:c0ecb8bf28eb 22850
Marko Mikulicic 0:c0ecb8bf28eb 22851 CR_DEFINE_ENTRY_POINT(fid_parse_ident_allow_reserved_words);
Marko Mikulicic 0:c0ecb8bf28eb 22852 CR_DEFINE_ENTRY_POINT(fid_p_ident_arw_1);
Marko Mikulicic 0:c0ecb8bf28eb 22853
Marko Mikulicic 0:c0ecb8bf28eb 22854 CR_DEFINE_ENTRY_POINT(fid_parse_funcdecl);
Marko Mikulicic 0:c0ecb8bf28eb 22855 CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_1);
Marko Mikulicic 0:c0ecb8bf28eb 22856 CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_2);
Marko Mikulicic 0:c0ecb8bf28eb 22857 CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_3);
Marko Mikulicic 0:c0ecb8bf28eb 22858 CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_4);
Marko Mikulicic 0:c0ecb8bf28eb 22859 CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_5);
Marko Mikulicic 0:c0ecb8bf28eb 22860 CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_6);
Marko Mikulicic 0:c0ecb8bf28eb 22861 CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_7);
Marko Mikulicic 0:c0ecb8bf28eb 22862 CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_8);
Marko Mikulicic 0:c0ecb8bf28eb 22863 CR_DEFINE_ENTRY_POINT(fid_p_funcdecl_9);
Marko Mikulicic 0:c0ecb8bf28eb 22864
Marko Mikulicic 0:c0ecb8bf28eb 22865 CR_DEFINE_ENTRY_POINT(fid_parse_arglist);
Marko Mikulicic 0:c0ecb8bf28eb 22866 CR_DEFINE_ENTRY_POINT(fid_p_arglist_1);
Marko Mikulicic 0:c0ecb8bf28eb 22867
Marko Mikulicic 0:c0ecb8bf28eb 22868 CR_DEFINE_ENTRY_POINT(fid_parse_member);
Marko Mikulicic 0:c0ecb8bf28eb 22869 CR_DEFINE_ENTRY_POINT(fid_p_member_1);
Marko Mikulicic 0:c0ecb8bf28eb 22870
Marko Mikulicic 0:c0ecb8bf28eb 22871 CR_DEFINE_ENTRY_POINT(fid_parse_memberexpr);
Marko Mikulicic 0:c0ecb8bf28eb 22872 CR_DEFINE_ENTRY_POINT(fid_p_memberexpr_1);
Marko Mikulicic 0:c0ecb8bf28eb 22873 CR_DEFINE_ENTRY_POINT(fid_p_memberexpr_2);
Marko Mikulicic 0:c0ecb8bf28eb 22874
Marko Mikulicic 0:c0ecb8bf28eb 22875 CR_DEFINE_ENTRY_POINT(fid_parse_var);
Marko Mikulicic 0:c0ecb8bf28eb 22876 CR_DEFINE_ENTRY_POINT(fid_p_var_1);
Marko Mikulicic 0:c0ecb8bf28eb 22877
Marko Mikulicic 0:c0ecb8bf28eb 22878 CR_DEFINE_ENTRY_POINT(fid_parse_prop);
Marko Mikulicic 0:c0ecb8bf28eb 22879 #ifdef V7_ENABLE_JS_GETTERS
Marko Mikulicic 0:c0ecb8bf28eb 22880 CR_DEFINE_ENTRY_POINT(fid_p_prop_1_getter);
Marko Mikulicic 0:c0ecb8bf28eb 22881 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22882 CR_DEFINE_ENTRY_POINT(fid_p_prop_2);
Marko Mikulicic 0:c0ecb8bf28eb 22883 #ifdef V7_ENABLE_JS_SETTERS
Marko Mikulicic 0:c0ecb8bf28eb 22884 CR_DEFINE_ENTRY_POINT(fid_p_prop_3_setter);
Marko Mikulicic 0:c0ecb8bf28eb 22885 #endif
Marko Mikulicic 0:c0ecb8bf28eb 22886 CR_DEFINE_ENTRY_POINT(fid_p_prop_4);
Marko Mikulicic 0:c0ecb8bf28eb 22887
Marko Mikulicic 0:c0ecb8bf28eb 22888 CR_DEFINE_ENTRY_POINT(fid_parse_dowhile);
Marko Mikulicic 0:c0ecb8bf28eb 22889 CR_DEFINE_ENTRY_POINT(fid_p_dowhile_1);
Marko Mikulicic 0:c0ecb8bf28eb 22890 CR_DEFINE_ENTRY_POINT(fid_p_dowhile_2);
Marko Mikulicic 0:c0ecb8bf28eb 22891
Marko Mikulicic 0:c0ecb8bf28eb 22892 CR_DEFINE_ENTRY_POINT(fid_parse_for);
Marko Mikulicic 0:c0ecb8bf28eb 22893 CR_DEFINE_ENTRY_POINT(fid_p_for_1);
Marko Mikulicic 0:c0ecb8bf28eb 22894 CR_DEFINE_ENTRY_POINT(fid_p_for_2);
Marko Mikulicic 0:c0ecb8bf28eb 22895 CR_DEFINE_ENTRY_POINT(fid_p_for_3);
Marko Mikulicic 0:c0ecb8bf28eb 22896 CR_DEFINE_ENTRY_POINT(fid_p_for_4);
Marko Mikulicic 0:c0ecb8bf28eb 22897 CR_DEFINE_ENTRY_POINT(fid_p_for_5);
Marko Mikulicic 0:c0ecb8bf28eb 22898 CR_DEFINE_ENTRY_POINT(fid_p_for_6);
Marko Mikulicic 0:c0ecb8bf28eb 22899
Marko Mikulicic 0:c0ecb8bf28eb 22900 CR_DEFINE_ENTRY_POINT(fid_parse_try);
Marko Mikulicic 0:c0ecb8bf28eb 22901 CR_DEFINE_ENTRY_POINT(fid_p_try_1);
Marko Mikulicic 0:c0ecb8bf28eb 22902 CR_DEFINE_ENTRY_POINT(fid_p_try_2);
Marko Mikulicic 0:c0ecb8bf28eb 22903 CR_DEFINE_ENTRY_POINT(fid_p_try_3);
Marko Mikulicic 0:c0ecb8bf28eb 22904 CR_DEFINE_ENTRY_POINT(fid_p_try_4);
Marko Mikulicic 0:c0ecb8bf28eb 22905
Marko Mikulicic 0:c0ecb8bf28eb 22906 CR_DEFINE_ENTRY_POINT(fid_parse_switch);
Marko Mikulicic 0:c0ecb8bf28eb 22907 CR_DEFINE_ENTRY_POINT(fid_p_switch_1);
Marko Mikulicic 0:c0ecb8bf28eb 22908 CR_DEFINE_ENTRY_POINT(fid_p_switch_2);
Marko Mikulicic 0:c0ecb8bf28eb 22909 CR_DEFINE_ENTRY_POINT(fid_p_switch_3);
Marko Mikulicic 0:c0ecb8bf28eb 22910 CR_DEFINE_ENTRY_POINT(fid_p_switch_4);
Marko Mikulicic 0:c0ecb8bf28eb 22911
Marko Mikulicic 0:c0ecb8bf28eb 22912 CR_DEFINE_ENTRY_POINT(fid_parse_with);
Marko Mikulicic 0:c0ecb8bf28eb 22913 CR_DEFINE_ENTRY_POINT(fid_p_with_1);
Marko Mikulicic 0:c0ecb8bf28eb 22914 CR_DEFINE_ENTRY_POINT(fid_p_with_2);
Marko Mikulicic 0:c0ecb8bf28eb 22915
Marko Mikulicic 0:c0ecb8bf28eb 22916 default:
Marko Mikulicic 0:c0ecb8bf28eb 22917 /* should never be here */
Marko Mikulicic 0:c0ecb8bf28eb 22918 printf("fatal: wrong func id: %d", CR_CURR_FUNC());
Marko Mikulicic 0:c0ecb8bf28eb 22919 break;
Marko Mikulicic 0:c0ecb8bf28eb 22920 };
Marko Mikulicic 0:c0ecb8bf28eb 22921
Marko Mikulicic 0:c0ecb8bf28eb 22922 /* static enum v7_err parse_script(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 22923 fid_parse_script :
Marko Mikulicic 0:c0ecb8bf28eb 22924 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 22925 #define L CR_CUR_LOCALS_PT(fid_parse_script_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 22926 {
Marko Mikulicic 0:c0ecb8bf28eb 22927 L->start = add_node(v7, a, AST_SCRIPT);
Marko Mikulicic 0:c0ecb8bf28eb 22928 L->outer_last_var_node = v7->last_var_node;
Marko Mikulicic 0:c0ecb8bf28eb 22929 L->saved_in_strict = v7->pstate.in_strict;
Marko Mikulicic 0:c0ecb8bf28eb 22930
Marko Mikulicic 0:c0ecb8bf28eb 22931 v7->last_var_node = L->start;
Marko Mikulicic 0:c0ecb8bf28eb 22932 ast_modify_skip(a, L->start, L->start, AST_FUNC_FIRST_VAR_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 22933
Marko Mikulicic 0:c0ecb8bf28eb 22934 CR_TRY(fid_p_script_1);
Marko Mikulicic 0:c0ecb8bf28eb 22935 {
Marko Mikulicic 0:c0ecb8bf28eb 22936 CALL_PARSE_USE_STRICT(fid_p_script_3);
Marko Mikulicic 0:c0ecb8bf28eb 22937 v7->pstate.in_strict = 1;
Marko Mikulicic 0:c0ecb8bf28eb 22938 }
Marko Mikulicic 0:c0ecb8bf28eb 22939 CR_CATCH(PARSER_EXC_ID__SYNTAX_ERROR, fid_p_script_1, fid_p_script_2);
Marko Mikulicic 0:c0ecb8bf28eb 22940 CR_ENDCATCH(fid_p_script_2);
Marko Mikulicic 0:c0ecb8bf28eb 22941
Marko Mikulicic 0:c0ecb8bf28eb 22942 CALL_PARSE_BODY(TOK_END_OF_INPUT, fid_p_script_4);
Marko Mikulicic 0:c0ecb8bf28eb 22943 ast_set_skip(a, L->start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 22944 v7->pstate.in_strict = L->saved_in_strict;
Marko Mikulicic 0:c0ecb8bf28eb 22945 v7->last_var_node = L->outer_last_var_node;
Marko Mikulicic 0:c0ecb8bf28eb 22946
Marko Mikulicic 0:c0ecb8bf28eb 22947 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 22948 }
Marko Mikulicic 0:c0ecb8bf28eb 22949
Marko Mikulicic 0:c0ecb8bf28eb 22950 /* static enum v7_err parse_use_strict(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 22951 fid_parse_use_strict :
Marko Mikulicic 0:c0ecb8bf28eb 22952 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 22953 #define L CR_CUR_LOCALS_PT(fid_parse_use_strict_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 22954 {
Marko Mikulicic 0:c0ecb8bf28eb 22955 if (v7->cur_tok == TOK_STRING_LITERAL &&
Marko Mikulicic 0:c0ecb8bf28eb 22956 (strncmp(v7->tok, "\"use strict\"", v7->tok_len) == 0 ||
Marko Mikulicic 0:c0ecb8bf28eb 22957 strncmp(v7->tok, "'use strict'", v7->tok_len) == 0)) {
Marko Mikulicic 0:c0ecb8bf28eb 22958 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 22959 add_node(v7, a, AST_USE_STRICT);
Marko Mikulicic 0:c0ecb8bf28eb 22960 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 22961 } else {
Marko Mikulicic 0:c0ecb8bf28eb 22962 CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 22963 }
Marko Mikulicic 0:c0ecb8bf28eb 22964 }
Marko Mikulicic 0:c0ecb8bf28eb 22965
Marko Mikulicic 0:c0ecb8bf28eb 22966 /*
Marko Mikulicic 0:c0ecb8bf28eb 22967 * static enum v7_err parse_body(struct v7 *v7, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 22968 * enum v7_tok end)
Marko Mikulicic 0:c0ecb8bf28eb 22969 */
Marko Mikulicic 0:c0ecb8bf28eb 22970 fid_parse_body :
Marko Mikulicic 0:c0ecb8bf28eb 22971 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 22972 #define L CR_CUR_LOCALS_PT(fid_parse_body_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 22973 {
Marko Mikulicic 0:c0ecb8bf28eb 22974 while (v7->cur_tok != L->arg.end) {
Marko Mikulicic 0:c0ecb8bf28eb 22975 if (ACCEPT(TOK_FUNCTION)) {
Marko Mikulicic 0:c0ecb8bf28eb 22976 if (v7->cur_tok != TOK_IDENTIFIER) {
Marko Mikulicic 0:c0ecb8bf28eb 22977 CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 22978 }
Marko Mikulicic 0:c0ecb8bf28eb 22979 L->start = add_node(v7, a, AST_VAR);
Marko Mikulicic 0:c0ecb8bf28eb 22980 ast_modify_skip(a, v7->last_var_node, L->start, AST_FUNC_FIRST_VAR_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 22981 /* zero out var node pointer */
Marko Mikulicic 0:c0ecb8bf28eb 22982 ast_modify_skip(a, L->start, L->start, AST_FUNC_FIRST_VAR_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 22983 v7->last_var_node = L->start;
Marko Mikulicic 0:c0ecb8bf28eb 22984 add_inlined_node(v7, a, AST_FUNC_DECL, v7->tok, v7->tok_len);
Marko Mikulicic 0:c0ecb8bf28eb 22985
Marko Mikulicic 0:c0ecb8bf28eb 22986 CALL_PARSE_FUNCDECL(1, 0, fid_p_body_1);
Marko Mikulicic 0:c0ecb8bf28eb 22987 ast_set_skip(a, L->start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 22988 } else {
Marko Mikulicic 0:c0ecb8bf28eb 22989 CALL_PARSE_STATEMENT(fid_p_body_2);
Marko Mikulicic 0:c0ecb8bf28eb 22990 }
Marko Mikulicic 0:c0ecb8bf28eb 22991 }
Marko Mikulicic 0:c0ecb8bf28eb 22992 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 22993 }
Marko Mikulicic 0:c0ecb8bf28eb 22994
Marko Mikulicic 0:c0ecb8bf28eb 22995 /* static enum v7_err parse_statement(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 22996 fid_parse_statement :
Marko Mikulicic 0:c0ecb8bf28eb 22997 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 22998 #define L CR_CUR_LOCALS_PT(fid_parse_statement_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 22999 {
Marko Mikulicic 0:c0ecb8bf28eb 23000 switch (v7->cur_tok) {
Marko Mikulicic 0:c0ecb8bf28eb 23001 case TOK_SEMICOLON:
Marko Mikulicic 0:c0ecb8bf28eb 23002 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23003 /* empty statement */
Marko Mikulicic 0:c0ecb8bf28eb 23004 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23005 case TOK_OPEN_CURLY: /* block */
Marko Mikulicic 0:c0ecb8bf28eb 23006 CALL_PARSE_BLOCK(fid_p_stat_3);
Marko Mikulicic 0:c0ecb8bf28eb 23007 /* returning because no semicolon required */
Marko Mikulicic 0:c0ecb8bf28eb 23008 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23009 case TOK_IF:
Marko Mikulicic 0:c0ecb8bf28eb 23010 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23011 CALL_PARSE_IF(fid_p_stat_4);
Marko Mikulicic 0:c0ecb8bf28eb 23012 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23013 case TOK_WHILE:
Marko Mikulicic 0:c0ecb8bf28eb 23014 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23015 CALL_PARSE_WHILE(fid_p_stat_5);
Marko Mikulicic 0:c0ecb8bf28eb 23016 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23017 case TOK_DO:
Marko Mikulicic 0:c0ecb8bf28eb 23018 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23019 CALL_PARSE_DOWHILE(fid_p_stat_10);
Marko Mikulicic 0:c0ecb8bf28eb 23020 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23021 case TOK_FOR:
Marko Mikulicic 0:c0ecb8bf28eb 23022 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23023 CALL_PARSE_FOR(fid_p_stat_11);
Marko Mikulicic 0:c0ecb8bf28eb 23024 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23025 case TOK_TRY:
Marko Mikulicic 0:c0ecb8bf28eb 23026 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23027 CALL_PARSE_TRY(fid_p_stat_12);
Marko Mikulicic 0:c0ecb8bf28eb 23028 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23029 case TOK_SWITCH:
Marko Mikulicic 0:c0ecb8bf28eb 23030 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23031 CALL_PARSE_SWITCH(fid_p_stat_13);
Marko Mikulicic 0:c0ecb8bf28eb 23032 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23033 case TOK_WITH:
Marko Mikulicic 0:c0ecb8bf28eb 23034 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23035 CALL_PARSE_WITH(fid_p_stat_14);
Marko Mikulicic 0:c0ecb8bf28eb 23036 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23037 case TOK_BREAK:
Marko Mikulicic 0:c0ecb8bf28eb 23038 if (!(v7->pstate.in_loop || v7->pstate.in_switch)) {
Marko Mikulicic 0:c0ecb8bf28eb 23039 CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 23040 }
Marko Mikulicic 0:c0ecb8bf28eb 23041 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23042 PARSE_WITH_OPT_ARG(AST_BREAK, AST_LABELED_BREAK, CALL_PARSE_IDENT,
Marko Mikulicic 0:c0ecb8bf28eb 23043 fid_p_stat_7);
Marko Mikulicic 0:c0ecb8bf28eb 23044 break;
Marko Mikulicic 0:c0ecb8bf28eb 23045 case TOK_CONTINUE:
Marko Mikulicic 0:c0ecb8bf28eb 23046 if (!v7->pstate.in_loop) {
Marko Mikulicic 0:c0ecb8bf28eb 23047 CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 23048 }
Marko Mikulicic 0:c0ecb8bf28eb 23049 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23050 PARSE_WITH_OPT_ARG(AST_CONTINUE, AST_LABELED_CONTINUE, CALL_PARSE_IDENT,
Marko Mikulicic 0:c0ecb8bf28eb 23051 fid_p_stat_8);
Marko Mikulicic 0:c0ecb8bf28eb 23052 break;
Marko Mikulicic 0:c0ecb8bf28eb 23053 case TOK_RETURN:
Marko Mikulicic 0:c0ecb8bf28eb 23054 if (!v7->pstate.in_function) {
Marko Mikulicic 0:c0ecb8bf28eb 23055 CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 23056 }
Marko Mikulicic 0:c0ecb8bf28eb 23057 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23058 PARSE_WITH_OPT_ARG(AST_RETURN, AST_VALUE_RETURN, CALL_PARSE_EXPRESSION,
Marko Mikulicic 0:c0ecb8bf28eb 23059 fid_p_stat_6);
Marko Mikulicic 0:c0ecb8bf28eb 23060 break;
Marko Mikulicic 0:c0ecb8bf28eb 23061 case TOK_THROW:
Marko Mikulicic 0:c0ecb8bf28eb 23062 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23063 add_node(v7, a, AST_THROW);
Marko Mikulicic 0:c0ecb8bf28eb 23064 CALL_PARSE_EXPRESSION(fid_p_stat_2);
Marko Mikulicic 0:c0ecb8bf28eb 23065 break;
Marko Mikulicic 0:c0ecb8bf28eb 23066 case TOK_DEBUGGER:
Marko Mikulicic 0:c0ecb8bf28eb 23067 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23068 add_node(v7, a, AST_DEBUGGER);
Marko Mikulicic 0:c0ecb8bf28eb 23069 break;
Marko Mikulicic 0:c0ecb8bf28eb 23070 case TOK_VAR:
Marko Mikulicic 0:c0ecb8bf28eb 23071 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23072 CALL_PARSE_VAR(fid_p_stat_9);
Marko Mikulicic 0:c0ecb8bf28eb 23073 break;
Marko Mikulicic 0:c0ecb8bf28eb 23074 case TOK_IDENTIFIER:
Marko Mikulicic 0:c0ecb8bf28eb 23075 if (lookahead(v7) == TOK_COLON) {
Marko Mikulicic 0:c0ecb8bf28eb 23076 add_inlined_node(v7, a, AST_LABEL, v7->tok, v7->tok_len);
Marko Mikulicic 0:c0ecb8bf28eb 23077 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23078 EXPECT(TOK_COLON);
Marko Mikulicic 0:c0ecb8bf28eb 23079 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23080 }
Marko Mikulicic 0:c0ecb8bf28eb 23081 /* fall through */
Marko Mikulicic 0:c0ecb8bf28eb 23082 default:
Marko Mikulicic 0:c0ecb8bf28eb 23083 CALL_PARSE_EXPRESSION(fid_p_stat_1);
Marko Mikulicic 0:c0ecb8bf28eb 23084 break;
Marko Mikulicic 0:c0ecb8bf28eb 23085 }
Marko Mikulicic 0:c0ecb8bf28eb 23086
Marko Mikulicic 0:c0ecb8bf28eb 23087 if (end_of_statement(v7) != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 23088 CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 23089 }
Marko Mikulicic 0:c0ecb8bf28eb 23090 ACCEPT(TOK_SEMICOLON); /* swallow optional semicolon */
Marko Mikulicic 0:c0ecb8bf28eb 23091 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23092 }
Marko Mikulicic 0:c0ecb8bf28eb 23093
Marko Mikulicic 0:c0ecb8bf28eb 23094 /* static enum v7_err parse_expression(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23095 fid_parse_expression :
Marko Mikulicic 0:c0ecb8bf28eb 23096 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23097 #define L CR_CUR_LOCALS_PT(fid_parse_expression_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23098 {
Marko Mikulicic 0:c0ecb8bf28eb 23099 L->pos = a->mbuf.len;
Marko Mikulicic 0:c0ecb8bf28eb 23100 L->group = 0;
Marko Mikulicic 0:c0ecb8bf28eb 23101 while (1) {
Marko Mikulicic 0:c0ecb8bf28eb 23102 CALL_PARSE_ASSIGN(fid_p_expr_1);
Marko Mikulicic 0:c0ecb8bf28eb 23103 if (ACCEPT(TOK_COMMA)) {
Marko Mikulicic 0:c0ecb8bf28eb 23104 L->group = 1;
Marko Mikulicic 0:c0ecb8bf28eb 23105 } else {
Marko Mikulicic 0:c0ecb8bf28eb 23106 break;
Marko Mikulicic 0:c0ecb8bf28eb 23107 }
Marko Mikulicic 0:c0ecb8bf28eb 23108 }
Marko Mikulicic 0:c0ecb8bf28eb 23109 if (L->group) {
Marko Mikulicic 0:c0ecb8bf28eb 23110 insert_node(v7, a, L->pos, AST_SEQ);
Marko Mikulicic 0:c0ecb8bf28eb 23111 }
Marko Mikulicic 0:c0ecb8bf28eb 23112 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23113 }
Marko Mikulicic 0:c0ecb8bf28eb 23114
Marko Mikulicic 0:c0ecb8bf28eb 23115 /* static enum v7_err parse_assign(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23116 fid_parse_assign :
Marko Mikulicic 0:c0ecb8bf28eb 23117 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23118 #define L CR_CUR_LOCALS_PT(fid_parse_assign_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23119 {
Marko Mikulicic 0:c0ecb8bf28eb 23120 CALL_PARSE_BINARY(0, a->mbuf.len, fid_p_assign_1);
Marko Mikulicic 0:c0ecb8bf28eb 23121 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23122 }
Marko Mikulicic 0:c0ecb8bf28eb 23123
Marko Mikulicic 0:c0ecb8bf28eb 23124 /*
Marko Mikulicic 0:c0ecb8bf28eb 23125 * static enum v7_err parse_binary(struct v7 *v7, struct ast *a, int level,
Marko Mikulicic 0:c0ecb8bf28eb 23126 * ast_off_t pos)
Marko Mikulicic 0:c0ecb8bf28eb 23127 */
Marko Mikulicic 0:c0ecb8bf28eb 23128 #if 1
Marko Mikulicic 0:c0ecb8bf28eb 23129 fid_parse_binary :
Marko Mikulicic 0:c0ecb8bf28eb 23130 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23131 #define L CR_CUR_LOCALS_PT(fid_parse_binary_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23132 {
Marko Mikulicic 0:c0ecb8bf28eb 23133 /*
Marko Mikulicic 0:c0ecb8bf28eb 23134 * Note: we use macro CUR_POS instead of a local variable, since this
Marko Mikulicic 0:c0ecb8bf28eb 23135 * function is called really a lot, so, each byte on stack frame counts.
Marko Mikulicic 0:c0ecb8bf28eb 23136 *
Marko Mikulicic 0:c0ecb8bf28eb 23137 * It will work a bit slower of course, but slowness is not a problem
Marko Mikulicic 0:c0ecb8bf28eb 23138 */
Marko Mikulicic 0:c0ecb8bf28eb 23139 #define CUR_POS ((L->level > L->arg.min_level) ? L->saved_mbuf_len : L->arg.pos)
Marko Mikulicic 0:c0ecb8bf28eb 23140 L->saved_mbuf_len = a->mbuf.len;
Marko Mikulicic 0:c0ecb8bf28eb 23141
Marko Mikulicic 0:c0ecb8bf28eb 23142 CALL_PARSE_PREFIX(fid_p_binary_6);
Marko Mikulicic 0:c0ecb8bf28eb 23143
Marko Mikulicic 0:c0ecb8bf28eb 23144 for (L->level = (int) ARRAY_SIZE(levels) - 1; L->level >= L->arg.min_level;
Marko Mikulicic 0:c0ecb8bf28eb 23145 L->level--) {
Marko Mikulicic 0:c0ecb8bf28eb 23146 for (L->i = 0; L->i < levels[L->level].len; L->i++) {
Marko Mikulicic 0:c0ecb8bf28eb 23147 L->tok = levels[L->level].parts[L->i].start_tok;
Marko Mikulicic 0:c0ecb8bf28eb 23148 L->ast = levels[L->level].parts[L->i].start_ast;
Marko Mikulicic 0:c0ecb8bf28eb 23149 do {
Marko Mikulicic 0:c0ecb8bf28eb 23150 if (v7->pstate.inhibit_in && L->tok == TOK_IN) {
Marko Mikulicic 0:c0ecb8bf28eb 23151 continue;
Marko Mikulicic 0:c0ecb8bf28eb 23152 }
Marko Mikulicic 0:c0ecb8bf28eb 23153
Marko Mikulicic 0:c0ecb8bf28eb 23154 /*
Marko Mikulicic 0:c0ecb8bf28eb 23155 * Ternary operator sits in the middle of the binary operator
Marko Mikulicic 0:c0ecb8bf28eb 23156 * precedence chain. Deal with it as an exception and don't break
Marko Mikulicic 0:c0ecb8bf28eb 23157 * the chain.
Marko Mikulicic 0:c0ecb8bf28eb 23158 */
Marko Mikulicic 0:c0ecb8bf28eb 23159 if (L->tok == TOK_QUESTION && v7->cur_tok == TOK_QUESTION) {
Marko Mikulicic 0:c0ecb8bf28eb 23160 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23161 CALL_PARSE_ASSIGN(fid_p_binary_2);
Marko Mikulicic 0:c0ecb8bf28eb 23162 EXPECT(TOK_COLON);
Marko Mikulicic 0:c0ecb8bf28eb 23163 CALL_PARSE_ASSIGN(fid_p_binary_3);
Marko Mikulicic 0:c0ecb8bf28eb 23164 insert_node(v7, a, CUR_POS, AST_COND);
Marko Mikulicic 0:c0ecb8bf28eb 23165 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23166 } else if (ACCEPT(L->tok)) {
Marko Mikulicic 0:c0ecb8bf28eb 23167 if (levels[L->level].left_to_right) {
Marko Mikulicic 0:c0ecb8bf28eb 23168 insert_node(v7, a, CUR_POS, (enum ast_tag) L->ast);
Marko Mikulicic 0:c0ecb8bf28eb 23169 CALL_PARSE_BINARY(L->level, CUR_POS, fid_p_binary_4);
Marko Mikulicic 0:c0ecb8bf28eb 23170 } else {
Marko Mikulicic 0:c0ecb8bf28eb 23171 CALL_PARSE_BINARY(L->level, a->mbuf.len, fid_p_binary_5);
Marko Mikulicic 0:c0ecb8bf28eb 23172 insert_node(v7, a, CUR_POS, (enum ast_tag) L->ast);
Marko Mikulicic 0:c0ecb8bf28eb 23173 }
Marko Mikulicic 0:c0ecb8bf28eb 23174 }
Marko Mikulicic 0:c0ecb8bf28eb 23175 } while (L->ast = (enum ast_tag)(L->ast + 1),
Marko Mikulicic 0:c0ecb8bf28eb 23176 L->tok < levels[L->level].parts[L->i].end_tok &&
Marko Mikulicic 0:c0ecb8bf28eb 23177 (L->tok = (enum v7_tok)(L->tok + 1)));
Marko Mikulicic 0:c0ecb8bf28eb 23178 }
Marko Mikulicic 0:c0ecb8bf28eb 23179 }
Marko Mikulicic 0:c0ecb8bf28eb 23180
Marko Mikulicic 0:c0ecb8bf28eb 23181 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23182 #undef CUR_POS
Marko Mikulicic 0:c0ecb8bf28eb 23183 }
Marko Mikulicic 0:c0ecb8bf28eb 23184 #endif
Marko Mikulicic 0:c0ecb8bf28eb 23185
Marko Mikulicic 0:c0ecb8bf28eb 23186 /* enum v7_err parse_prefix(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23187 fid_parse_prefix :
Marko Mikulicic 0:c0ecb8bf28eb 23188 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23189 #define L CR_CUR_LOCALS_PT(fid_parse_prefix_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23190 {
Marko Mikulicic 0:c0ecb8bf28eb 23191 for (;;) {
Marko Mikulicic 0:c0ecb8bf28eb 23192 switch (v7->cur_tok) {
Marko Mikulicic 0:c0ecb8bf28eb 23193 case TOK_PLUS:
Marko Mikulicic 0:c0ecb8bf28eb 23194 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23195 add_node(v7, a, AST_POSITIVE);
Marko Mikulicic 0:c0ecb8bf28eb 23196 break;
Marko Mikulicic 0:c0ecb8bf28eb 23197 case TOK_MINUS:
Marko Mikulicic 0:c0ecb8bf28eb 23198 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23199 add_node(v7, a, AST_NEGATIVE);
Marko Mikulicic 0:c0ecb8bf28eb 23200 break;
Marko Mikulicic 0:c0ecb8bf28eb 23201 case TOK_PLUS_PLUS:
Marko Mikulicic 0:c0ecb8bf28eb 23202 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23203 add_node(v7, a, AST_PREINC);
Marko Mikulicic 0:c0ecb8bf28eb 23204 break;
Marko Mikulicic 0:c0ecb8bf28eb 23205 case TOK_MINUS_MINUS:
Marko Mikulicic 0:c0ecb8bf28eb 23206 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23207 add_node(v7, a, AST_PREDEC);
Marko Mikulicic 0:c0ecb8bf28eb 23208 break;
Marko Mikulicic 0:c0ecb8bf28eb 23209 case TOK_TILDA:
Marko Mikulicic 0:c0ecb8bf28eb 23210 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23211 add_node(v7, a, AST_NOT);
Marko Mikulicic 0:c0ecb8bf28eb 23212 break;
Marko Mikulicic 0:c0ecb8bf28eb 23213 case TOK_NOT:
Marko Mikulicic 0:c0ecb8bf28eb 23214 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23215 add_node(v7, a, AST_LOGICAL_NOT);
Marko Mikulicic 0:c0ecb8bf28eb 23216 break;
Marko Mikulicic 0:c0ecb8bf28eb 23217 case TOK_VOID:
Marko Mikulicic 0:c0ecb8bf28eb 23218 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23219 add_node(v7, a, AST_VOID);
Marko Mikulicic 0:c0ecb8bf28eb 23220 break;
Marko Mikulicic 0:c0ecb8bf28eb 23221 case TOK_DELETE:
Marko Mikulicic 0:c0ecb8bf28eb 23222 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23223 add_node(v7, a, AST_DELETE);
Marko Mikulicic 0:c0ecb8bf28eb 23224 break;
Marko Mikulicic 0:c0ecb8bf28eb 23225 case TOK_TYPEOF:
Marko Mikulicic 0:c0ecb8bf28eb 23226 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23227 add_node(v7, a, AST_TYPEOF);
Marko Mikulicic 0:c0ecb8bf28eb 23228 break;
Marko Mikulicic 0:c0ecb8bf28eb 23229 default:
Marko Mikulicic 0:c0ecb8bf28eb 23230 CALL_PARSE_POSTFIX(fid_p_prefix_1);
Marko Mikulicic 0:c0ecb8bf28eb 23231 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23232 }
Marko Mikulicic 0:c0ecb8bf28eb 23233 }
Marko Mikulicic 0:c0ecb8bf28eb 23234 }
Marko Mikulicic 0:c0ecb8bf28eb 23235
Marko Mikulicic 0:c0ecb8bf28eb 23236 /* static enum v7_err parse_postfix(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23237 fid_parse_postfix :
Marko Mikulicic 0:c0ecb8bf28eb 23238 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23239 #define L CR_CUR_LOCALS_PT(fid_parse_postfix_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23240 {
Marko Mikulicic 0:c0ecb8bf28eb 23241 L->pos = a->mbuf.len;
Marko Mikulicic 0:c0ecb8bf28eb 23242 CALL_PARSE_CALLEXPR(fid_p_postfix_1);
Marko Mikulicic 0:c0ecb8bf28eb 23243
Marko Mikulicic 0:c0ecb8bf28eb 23244 if (v7->after_newline) {
Marko Mikulicic 0:c0ecb8bf28eb 23245 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23246 }
Marko Mikulicic 0:c0ecb8bf28eb 23247 switch (v7->cur_tok) {
Marko Mikulicic 0:c0ecb8bf28eb 23248 case TOK_PLUS_PLUS:
Marko Mikulicic 0:c0ecb8bf28eb 23249 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23250 insert_node(v7, a, L->pos, AST_POSTINC);
Marko Mikulicic 0:c0ecb8bf28eb 23251 break;
Marko Mikulicic 0:c0ecb8bf28eb 23252 case TOK_MINUS_MINUS:
Marko Mikulicic 0:c0ecb8bf28eb 23253 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23254 insert_node(v7, a, L->pos, AST_POSTDEC);
Marko Mikulicic 0:c0ecb8bf28eb 23255 break;
Marko Mikulicic 0:c0ecb8bf28eb 23256 default:
Marko Mikulicic 0:c0ecb8bf28eb 23257 break; /* nothing */
Marko Mikulicic 0:c0ecb8bf28eb 23258 }
Marko Mikulicic 0:c0ecb8bf28eb 23259 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23260 }
Marko Mikulicic 0:c0ecb8bf28eb 23261
Marko Mikulicic 0:c0ecb8bf28eb 23262 /* static enum v7_err parse_callexpr(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23263 fid_parse_callexpr :
Marko Mikulicic 0:c0ecb8bf28eb 23264 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23265 #define L CR_CUR_LOCALS_PT(fid_parse_callexpr_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23266 {
Marko Mikulicic 0:c0ecb8bf28eb 23267 L->pos = a->mbuf.len;
Marko Mikulicic 0:c0ecb8bf28eb 23268 CALL_PARSE_NEWEXPR(fid_p_callexpr_1);
Marko Mikulicic 0:c0ecb8bf28eb 23269
Marko Mikulicic 0:c0ecb8bf28eb 23270 for (;;) {
Marko Mikulicic 0:c0ecb8bf28eb 23271 switch (v7->cur_tok) {
Marko Mikulicic 0:c0ecb8bf28eb 23272 case TOK_DOT:
Marko Mikulicic 0:c0ecb8bf28eb 23273 case TOK_OPEN_BRACKET:
Marko Mikulicic 0:c0ecb8bf28eb 23274 CALL_PARSE_MEMBER(L->pos, fid_p_callexpr_3);
Marko Mikulicic 0:c0ecb8bf28eb 23275 break;
Marko Mikulicic 0:c0ecb8bf28eb 23276 case TOK_OPEN_PAREN:
Marko Mikulicic 0:c0ecb8bf28eb 23277 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23278 CALL_PARSE_ARGLIST(fid_p_callexpr_2);
Marko Mikulicic 0:c0ecb8bf28eb 23279 EXPECT(TOK_CLOSE_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23280 insert_node(v7, a, L->pos, AST_CALL);
Marko Mikulicic 0:c0ecb8bf28eb 23281 break;
Marko Mikulicic 0:c0ecb8bf28eb 23282 default:
Marko Mikulicic 0:c0ecb8bf28eb 23283 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23284 }
Marko Mikulicic 0:c0ecb8bf28eb 23285 }
Marko Mikulicic 0:c0ecb8bf28eb 23286 }
Marko Mikulicic 0:c0ecb8bf28eb 23287
Marko Mikulicic 0:c0ecb8bf28eb 23288 /* static enum v7_err parse_newexpr(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23289 fid_parse_newexpr :
Marko Mikulicic 0:c0ecb8bf28eb 23290 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23291 #define L CR_CUR_LOCALS_PT(fid_parse_newexpr_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23292 {
Marko Mikulicic 0:c0ecb8bf28eb 23293 switch (v7->cur_tok) {
Marko Mikulicic 0:c0ecb8bf28eb 23294 case TOK_NEW:
Marko Mikulicic 0:c0ecb8bf28eb 23295 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23296 L->start = add_node(v7, a, AST_NEW);
Marko Mikulicic 0:c0ecb8bf28eb 23297 CALL_PARSE_MEMBEREXPR(fid_p_newexpr_3);
Marko Mikulicic 0:c0ecb8bf28eb 23298 if (ACCEPT(TOK_OPEN_PAREN)) {
Marko Mikulicic 0:c0ecb8bf28eb 23299 CALL_PARSE_ARGLIST(fid_p_newexpr_4);
Marko Mikulicic 0:c0ecb8bf28eb 23300 EXPECT(TOK_CLOSE_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23301 }
Marko Mikulicic 0:c0ecb8bf28eb 23302 ast_set_skip(a, L->start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23303 break;
Marko Mikulicic 0:c0ecb8bf28eb 23304 case TOK_FUNCTION:
Marko Mikulicic 0:c0ecb8bf28eb 23305 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23306 CALL_PARSE_FUNCDECL(0, 0, fid_p_newexpr_2);
Marko Mikulicic 0:c0ecb8bf28eb 23307 break;
Marko Mikulicic 0:c0ecb8bf28eb 23308 default:
Marko Mikulicic 0:c0ecb8bf28eb 23309 CALL_PARSE_TERMINAL(fid_p_newexpr_1);
Marko Mikulicic 0:c0ecb8bf28eb 23310 break;
Marko Mikulicic 0:c0ecb8bf28eb 23311 }
Marko Mikulicic 0:c0ecb8bf28eb 23312 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23313 }
Marko Mikulicic 0:c0ecb8bf28eb 23314
Marko Mikulicic 0:c0ecb8bf28eb 23315 /* static enum v7_err parse_terminal(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23316 fid_parse_terminal :
Marko Mikulicic 0:c0ecb8bf28eb 23317 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23318 #define L CR_CUR_LOCALS_PT(fid_parse_terminal_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23319 {
Marko Mikulicic 0:c0ecb8bf28eb 23320 switch (v7->cur_tok) {
Marko Mikulicic 0:c0ecb8bf28eb 23321 case TOK_OPEN_PAREN:
Marko Mikulicic 0:c0ecb8bf28eb 23322 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23323 CALL_PARSE_EXPRESSION(fid_p_terminal_1);
Marko Mikulicic 0:c0ecb8bf28eb 23324 EXPECT(TOK_CLOSE_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23325 break;
Marko Mikulicic 0:c0ecb8bf28eb 23326 case TOK_OPEN_BRACKET:
Marko Mikulicic 0:c0ecb8bf28eb 23327 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23328 L->start = add_node(v7, a, AST_ARRAY);
Marko Mikulicic 0:c0ecb8bf28eb 23329 while (v7->cur_tok != TOK_CLOSE_BRACKET) {
Marko Mikulicic 0:c0ecb8bf28eb 23330 if (v7->cur_tok == TOK_COMMA) {
Marko Mikulicic 0:c0ecb8bf28eb 23331 /* Array literals allow missing elements, e.g. [,,1,] */
Marko Mikulicic 0:c0ecb8bf28eb 23332 add_node(v7, a, AST_NOP);
Marko Mikulicic 0:c0ecb8bf28eb 23333 } else {
Marko Mikulicic 0:c0ecb8bf28eb 23334 CALL_PARSE_ASSIGN(fid_p_terminal_2);
Marko Mikulicic 0:c0ecb8bf28eb 23335 }
Marko Mikulicic 0:c0ecb8bf28eb 23336 ACCEPT(TOK_COMMA);
Marko Mikulicic 0:c0ecb8bf28eb 23337 }
Marko Mikulicic 0:c0ecb8bf28eb 23338 EXPECT(TOK_CLOSE_BRACKET);
Marko Mikulicic 0:c0ecb8bf28eb 23339 ast_set_skip(a, L->start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23340 break;
Marko Mikulicic 0:c0ecb8bf28eb 23341 case TOK_OPEN_CURLY:
Marko Mikulicic 0:c0ecb8bf28eb 23342 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23343 L->start = add_node(v7, a, AST_OBJECT);
Marko Mikulicic 0:c0ecb8bf28eb 23344 if (v7->cur_tok != TOK_CLOSE_CURLY) {
Marko Mikulicic 0:c0ecb8bf28eb 23345 do {
Marko Mikulicic 0:c0ecb8bf28eb 23346 if (v7->cur_tok == TOK_CLOSE_CURLY) {
Marko Mikulicic 0:c0ecb8bf28eb 23347 break;
Marko Mikulicic 0:c0ecb8bf28eb 23348 }
Marko Mikulicic 0:c0ecb8bf28eb 23349 CALL_PARSE_PROP(fid_p_terminal_3);
Marko Mikulicic 0:c0ecb8bf28eb 23350 } while (ACCEPT(TOK_COMMA));
Marko Mikulicic 0:c0ecb8bf28eb 23351 }
Marko Mikulicic 0:c0ecb8bf28eb 23352 EXPECT(TOK_CLOSE_CURLY);
Marko Mikulicic 0:c0ecb8bf28eb 23353 ast_set_skip(a, L->start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23354 break;
Marko Mikulicic 0:c0ecb8bf28eb 23355 case TOK_THIS:
Marko Mikulicic 0:c0ecb8bf28eb 23356 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23357 add_node(v7, a, AST_THIS);
Marko Mikulicic 0:c0ecb8bf28eb 23358 break;
Marko Mikulicic 0:c0ecb8bf28eb 23359 case TOK_TRUE:
Marko Mikulicic 0:c0ecb8bf28eb 23360 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23361 add_node(v7, a, AST_TRUE);
Marko Mikulicic 0:c0ecb8bf28eb 23362 break;
Marko Mikulicic 0:c0ecb8bf28eb 23363 case TOK_FALSE:
Marko Mikulicic 0:c0ecb8bf28eb 23364 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23365 add_node(v7, a, AST_FALSE);
Marko Mikulicic 0:c0ecb8bf28eb 23366 break;
Marko Mikulicic 0:c0ecb8bf28eb 23367 case TOK_NULL:
Marko Mikulicic 0:c0ecb8bf28eb 23368 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23369 add_node(v7, a, AST_NULL);
Marko Mikulicic 0:c0ecb8bf28eb 23370 break;
Marko Mikulicic 0:c0ecb8bf28eb 23371 case TOK_STRING_LITERAL:
Marko Mikulicic 0:c0ecb8bf28eb 23372 add_inlined_node(v7, a, AST_STRING, v7->tok + 1, v7->tok_len - 2);
Marko Mikulicic 0:c0ecb8bf28eb 23373 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23374 break;
Marko Mikulicic 0:c0ecb8bf28eb 23375 case TOK_NUMBER:
Marko Mikulicic 0:c0ecb8bf28eb 23376 add_inlined_node(v7, a, AST_NUM, v7->tok, v7->tok_len);
Marko Mikulicic 0:c0ecb8bf28eb 23377 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23378 break;
Marko Mikulicic 0:c0ecb8bf28eb 23379 case TOK_REGEX_LITERAL:
Marko Mikulicic 0:c0ecb8bf28eb 23380 add_inlined_node(v7, a, AST_REGEX, v7->tok, v7->tok_len);
Marko Mikulicic 0:c0ecb8bf28eb 23381 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23382 break;
Marko Mikulicic 0:c0ecb8bf28eb 23383 case TOK_IDENTIFIER:
Marko Mikulicic 0:c0ecb8bf28eb 23384 if (v7->tok_len == 9 && strncmp(v7->tok, "undefined", v7->tok_len) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 23385 add_node(v7, a, AST_UNDEFINED);
Marko Mikulicic 0:c0ecb8bf28eb 23386 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23387 break;
Marko Mikulicic 0:c0ecb8bf28eb 23388 }
Marko Mikulicic 0:c0ecb8bf28eb 23389 /* fall through */
Marko Mikulicic 0:c0ecb8bf28eb 23390 default:
Marko Mikulicic 0:c0ecb8bf28eb 23391 CALL_PARSE_IDENT(fid_p_terminal_4);
Marko Mikulicic 0:c0ecb8bf28eb 23392 }
Marko Mikulicic 0:c0ecb8bf28eb 23393 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23394 }
Marko Mikulicic 0:c0ecb8bf28eb 23395
Marko Mikulicic 0:c0ecb8bf28eb 23396 /* static enum v7_err parse_block(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23397 fid_parse_block :
Marko Mikulicic 0:c0ecb8bf28eb 23398 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23399 #define L CR_CUR_LOCALS_PT(fid_parse_block_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23400 {
Marko Mikulicic 0:c0ecb8bf28eb 23401 EXPECT(TOK_OPEN_CURLY);
Marko Mikulicic 0:c0ecb8bf28eb 23402 CALL_PARSE_BODY(TOK_CLOSE_CURLY, fid_p_block_1);
Marko Mikulicic 0:c0ecb8bf28eb 23403 EXPECT(TOK_CLOSE_CURLY);
Marko Mikulicic 0:c0ecb8bf28eb 23404 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23405 }
Marko Mikulicic 0:c0ecb8bf28eb 23406
Marko Mikulicic 0:c0ecb8bf28eb 23407 /* static enum v7_err parse_if(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23408 fid_parse_if :
Marko Mikulicic 0:c0ecb8bf28eb 23409 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23410 #define L CR_CUR_LOCALS_PT(fid_parse_if_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23411 {
Marko Mikulicic 0:c0ecb8bf28eb 23412 L->start = add_node(v7, a, AST_IF);
Marko Mikulicic 0:c0ecb8bf28eb 23413 EXPECT(TOK_OPEN_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23414 CALL_PARSE_EXPRESSION(fid_p_if_1);
Marko Mikulicic 0:c0ecb8bf28eb 23415 EXPECT(TOK_CLOSE_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23416 CALL_PARSE_STATEMENT(fid_p_if_2);
Marko Mikulicic 0:c0ecb8bf28eb 23417 ast_set_skip(a, L->start, AST_END_IF_TRUE_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23418 if (ACCEPT(TOK_ELSE)) {
Marko Mikulicic 0:c0ecb8bf28eb 23419 CALL_PARSE_STATEMENT(fid_p_if_3);
Marko Mikulicic 0:c0ecb8bf28eb 23420 }
Marko Mikulicic 0:c0ecb8bf28eb 23421 ast_set_skip(a, L->start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23422 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23423 }
Marko Mikulicic 0:c0ecb8bf28eb 23424
Marko Mikulicic 0:c0ecb8bf28eb 23425 /* static enum v7_err parse_while(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23426 fid_parse_while :
Marko Mikulicic 0:c0ecb8bf28eb 23427 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23428 #define L CR_CUR_LOCALS_PT(fid_parse_while_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23429 {
Marko Mikulicic 0:c0ecb8bf28eb 23430 L->start = add_node(v7, a, AST_WHILE);
Marko Mikulicic 0:c0ecb8bf28eb 23431 L->saved_in_loop = v7->pstate.in_loop;
Marko Mikulicic 0:c0ecb8bf28eb 23432 EXPECT(TOK_OPEN_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23433 CALL_PARSE_EXPRESSION(fid_p_while_1);
Marko Mikulicic 0:c0ecb8bf28eb 23434 EXPECT(TOK_CLOSE_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23435 v7->pstate.in_loop = 1;
Marko Mikulicic 0:c0ecb8bf28eb 23436 CALL_PARSE_STATEMENT(fid_p_while_2);
Marko Mikulicic 0:c0ecb8bf28eb 23437 ast_set_skip(a, L->start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23438 v7->pstate.in_loop = L->saved_in_loop;
Marko Mikulicic 0:c0ecb8bf28eb 23439 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23440 }
Marko Mikulicic 0:c0ecb8bf28eb 23441
Marko Mikulicic 0:c0ecb8bf28eb 23442 /* static enum v7_err parse_ident(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23443 fid_parse_ident :
Marko Mikulicic 0:c0ecb8bf28eb 23444 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23445 #define L CR_CUR_LOCALS_PT(fid_parse_ident_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23446 {
Marko Mikulicic 0:c0ecb8bf28eb 23447 if (v7->cur_tok == TOK_IDENTIFIER) {
Marko Mikulicic 0:c0ecb8bf28eb 23448 add_inlined_node(v7, a, AST_IDENT, v7->tok, v7->tok_len);
Marko Mikulicic 0:c0ecb8bf28eb 23449 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23450 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23451 }
Marko Mikulicic 0:c0ecb8bf28eb 23452 CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 23453 }
Marko Mikulicic 0:c0ecb8bf28eb 23454
Marko Mikulicic 0:c0ecb8bf28eb 23455 /*
Marko Mikulicic 0:c0ecb8bf28eb 23456 * static enum v7_err parse_ident_allow_reserved_words(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 23457 * struct ast *a)
Marko Mikulicic 0:c0ecb8bf28eb 23458 *
Marko Mikulicic 0:c0ecb8bf28eb 23459 */
Marko Mikulicic 0:c0ecb8bf28eb 23460 fid_parse_ident_allow_reserved_words :
Marko Mikulicic 0:c0ecb8bf28eb 23461 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23462 #define L CR_CUR_LOCALS_PT(fid_parse_ident_allow_reserved_words_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23463 {
Marko Mikulicic 0:c0ecb8bf28eb 23464 /* Allow reserved words as property names. */
Marko Mikulicic 0:c0ecb8bf28eb 23465 if (is_reserved_word_token(v7->cur_tok)) {
Marko Mikulicic 0:c0ecb8bf28eb 23466 add_inlined_node(v7, a, AST_IDENT, v7->tok, v7->tok_len);
Marko Mikulicic 0:c0ecb8bf28eb 23467 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23468 } else {
Marko Mikulicic 0:c0ecb8bf28eb 23469 CALL_PARSE_IDENT(fid_p_ident_arw_1);
Marko Mikulicic 0:c0ecb8bf28eb 23470 }
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_funcdecl(struct v7 *, struct ast *, int, int) */
Marko Mikulicic 0:c0ecb8bf28eb 23475 fid_parse_funcdecl :
Marko Mikulicic 0:c0ecb8bf28eb 23476 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23477 #define L CR_CUR_LOCALS_PT(fid_parse_funcdecl_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23478 {
Marko Mikulicic 0:c0ecb8bf28eb 23479 L->start = add_node(v7, a, AST_FUNC);
Marko Mikulicic 0:c0ecb8bf28eb 23480 L->outer_last_var_node = v7->last_var_node;
Marko Mikulicic 0:c0ecb8bf28eb 23481 L->saved_in_function = v7->pstate.in_function;
Marko Mikulicic 0:c0ecb8bf28eb 23482 L->saved_in_strict = v7->pstate.in_strict;
Marko Mikulicic 0:c0ecb8bf28eb 23483
Marko Mikulicic 0:c0ecb8bf28eb 23484 v7->last_var_node = L->start;
Marko Mikulicic 0:c0ecb8bf28eb 23485 ast_modify_skip(a, L->start, L->start, AST_FUNC_FIRST_VAR_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23486
Marko Mikulicic 0:c0ecb8bf28eb 23487 CR_TRY(fid_p_funcdecl_2);
Marko Mikulicic 0:c0ecb8bf28eb 23488 {
Marko Mikulicic 0:c0ecb8bf28eb 23489 if (L->arg.reserved_name) {
Marko Mikulicic 0:c0ecb8bf28eb 23490 CALL_PARSE_IDENT_ALLOW_RESERVED_WORDS(fid_p_funcdecl_1);
Marko Mikulicic 0:c0ecb8bf28eb 23491 } else {
Marko Mikulicic 0:c0ecb8bf28eb 23492 CALL_PARSE_IDENT(fid_p_funcdecl_9);
Marko Mikulicic 0:c0ecb8bf28eb 23493 }
Marko Mikulicic 0:c0ecb8bf28eb 23494 }
Marko Mikulicic 0:c0ecb8bf28eb 23495 CR_CATCH(PARSER_EXC_ID__SYNTAX_ERROR, fid_p_funcdecl_2, fid_p_funcdecl_3);
Marko Mikulicic 0:c0ecb8bf28eb 23496 {
Marko Mikulicic 0:c0ecb8bf28eb 23497 if (L->arg.require_named) {
Marko Mikulicic 0:c0ecb8bf28eb 23498 /* function name is required, so, rethrow SYNTAX ERROR */
Marko Mikulicic 0:c0ecb8bf28eb 23499 CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 23500 } else {
Marko Mikulicic 0:c0ecb8bf28eb 23501 /* it's ok not to have a function name, just insert NOP */
Marko Mikulicic 0:c0ecb8bf28eb 23502 add_node(v7, a, AST_NOP);
Marko Mikulicic 0:c0ecb8bf28eb 23503 }
Marko Mikulicic 0:c0ecb8bf28eb 23504 }
Marko Mikulicic 0:c0ecb8bf28eb 23505 CR_ENDCATCH(fid_p_funcdecl_3);
Marko Mikulicic 0:c0ecb8bf28eb 23506
Marko Mikulicic 0:c0ecb8bf28eb 23507 EXPECT(TOK_OPEN_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23508 CALL_PARSE_ARGLIST(fid_p_funcdecl_4);
Marko Mikulicic 0:c0ecb8bf28eb 23509 EXPECT(TOK_CLOSE_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23510 ast_set_skip(a, L->start, AST_FUNC_BODY_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23511 v7->pstate.in_function = 1;
Marko Mikulicic 0:c0ecb8bf28eb 23512 EXPECT(TOK_OPEN_CURLY);
Marko Mikulicic 0:c0ecb8bf28eb 23513
Marko Mikulicic 0:c0ecb8bf28eb 23514 CR_TRY(fid_p_funcdecl_5);
Marko Mikulicic 0:c0ecb8bf28eb 23515 {
Marko Mikulicic 0:c0ecb8bf28eb 23516 CALL_PARSE_USE_STRICT(fid_p_funcdecl_7);
Marko Mikulicic 0:c0ecb8bf28eb 23517 v7->pstate.in_strict = 1;
Marko Mikulicic 0:c0ecb8bf28eb 23518 }
Marko Mikulicic 0:c0ecb8bf28eb 23519 CR_CATCH(PARSER_EXC_ID__SYNTAX_ERROR, fid_p_funcdecl_5, fid_p_funcdecl_6);
Marko Mikulicic 0:c0ecb8bf28eb 23520 CR_ENDCATCH(fid_p_funcdecl_6);
Marko Mikulicic 0:c0ecb8bf28eb 23521
Marko Mikulicic 0:c0ecb8bf28eb 23522 CALL_PARSE_BODY(TOK_CLOSE_CURLY, fid_p_funcdecl_8);
Marko Mikulicic 0:c0ecb8bf28eb 23523 EXPECT(TOK_CLOSE_CURLY);
Marko Mikulicic 0:c0ecb8bf28eb 23524 v7->pstate.in_strict = L->saved_in_strict;
Marko Mikulicic 0:c0ecb8bf28eb 23525 v7->pstate.in_function = L->saved_in_function;
Marko Mikulicic 0:c0ecb8bf28eb 23526 ast_set_skip(a, L->start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23527 v7->last_var_node = L->outer_last_var_node;
Marko Mikulicic 0:c0ecb8bf28eb 23528
Marko Mikulicic 0:c0ecb8bf28eb 23529 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23530 }
Marko Mikulicic 0:c0ecb8bf28eb 23531
Marko Mikulicic 0:c0ecb8bf28eb 23532 /* static enum v7_err parse_arglist(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23533 fid_parse_arglist :
Marko Mikulicic 0:c0ecb8bf28eb 23534 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23535 #define L CR_CUR_LOCALS_PT(fid_parse_arglist_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23536 {
Marko Mikulicic 0:c0ecb8bf28eb 23537 if (v7->cur_tok != TOK_CLOSE_PAREN) {
Marko Mikulicic 0:c0ecb8bf28eb 23538 do {
Marko Mikulicic 0:c0ecb8bf28eb 23539 CALL_PARSE_ASSIGN(fid_p_arglist_1);
Marko Mikulicic 0:c0ecb8bf28eb 23540 } while (ACCEPT(TOK_COMMA));
Marko Mikulicic 0:c0ecb8bf28eb 23541 }
Marko Mikulicic 0:c0ecb8bf28eb 23542 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23543 }
Marko Mikulicic 0:c0ecb8bf28eb 23544
Marko Mikulicic 0:c0ecb8bf28eb 23545 /*
Marko Mikulicic 0:c0ecb8bf28eb 23546 * static enum v7_err parse_member(struct v7 *v7, struct ast *a, ast_off_t pos)
Marko Mikulicic 0:c0ecb8bf28eb 23547 */
Marko Mikulicic 0:c0ecb8bf28eb 23548 fid_parse_member :
Marko Mikulicic 0:c0ecb8bf28eb 23549 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23550 #define L CR_CUR_LOCALS_PT(fid_parse_member_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23551 {
Marko Mikulicic 0:c0ecb8bf28eb 23552 switch (v7->cur_tok) {
Marko Mikulicic 0:c0ecb8bf28eb 23553 case TOK_DOT:
Marko Mikulicic 0:c0ecb8bf28eb 23554 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23555 /* Allow reserved words as member identifiers */
Marko Mikulicic 0:c0ecb8bf28eb 23556 if (is_reserved_word_token(v7->cur_tok) ||
Marko Mikulicic 0:c0ecb8bf28eb 23557 v7->cur_tok == TOK_IDENTIFIER) {
Marko Mikulicic 0:c0ecb8bf28eb 23558 insert_inlined_node(v7, a, L->arg.pos, AST_MEMBER, v7->tok,
Marko Mikulicic 0:c0ecb8bf28eb 23559 v7->tok_len);
Marko Mikulicic 0:c0ecb8bf28eb 23560 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23561 } else {
Marko Mikulicic 0:c0ecb8bf28eb 23562 CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 23563 }
Marko Mikulicic 0:c0ecb8bf28eb 23564 break;
Marko Mikulicic 0:c0ecb8bf28eb 23565 case TOK_OPEN_BRACKET:
Marko Mikulicic 0:c0ecb8bf28eb 23566 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23567 CALL_PARSE_EXPRESSION(fid_p_member_1);
Marko Mikulicic 0:c0ecb8bf28eb 23568 EXPECT(TOK_CLOSE_BRACKET);
Marko Mikulicic 0:c0ecb8bf28eb 23569 insert_node(v7, a, L->arg.pos, AST_INDEX);
Marko Mikulicic 0:c0ecb8bf28eb 23570 break;
Marko Mikulicic 0:c0ecb8bf28eb 23571 default:
Marko Mikulicic 0:c0ecb8bf28eb 23572 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23573 }
Marko Mikulicic 0:c0ecb8bf28eb 23574 /* not necessary, but let it be anyway */
Marko Mikulicic 0:c0ecb8bf28eb 23575 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23576 }
Marko Mikulicic 0:c0ecb8bf28eb 23577
Marko Mikulicic 0:c0ecb8bf28eb 23578 /* static enum v7_err parse_memberexpr(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23579 fid_parse_memberexpr :
Marko Mikulicic 0:c0ecb8bf28eb 23580 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23581 #define L CR_CUR_LOCALS_PT(fid_parse_memberexpr_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23582 {
Marko Mikulicic 0:c0ecb8bf28eb 23583 L->pos = a->mbuf.len;
Marko Mikulicic 0:c0ecb8bf28eb 23584 CALL_PARSE_NEWEXPR(fid_p_memberexpr_1);
Marko Mikulicic 0:c0ecb8bf28eb 23585
Marko Mikulicic 0:c0ecb8bf28eb 23586 for (;;) {
Marko Mikulicic 0:c0ecb8bf28eb 23587 switch (v7->cur_tok) {
Marko Mikulicic 0:c0ecb8bf28eb 23588 case TOK_DOT:
Marko Mikulicic 0:c0ecb8bf28eb 23589 case TOK_OPEN_BRACKET:
Marko Mikulicic 0:c0ecb8bf28eb 23590 CALL_PARSE_MEMBER(L->pos, fid_p_memberexpr_2);
Marko Mikulicic 0:c0ecb8bf28eb 23591 break;
Marko Mikulicic 0:c0ecb8bf28eb 23592 default:
Marko Mikulicic 0:c0ecb8bf28eb 23593 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23594 }
Marko Mikulicic 0:c0ecb8bf28eb 23595 }
Marko Mikulicic 0:c0ecb8bf28eb 23596 }
Marko Mikulicic 0:c0ecb8bf28eb 23597
Marko Mikulicic 0:c0ecb8bf28eb 23598 /* static enum v7_err parse_var(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23599 fid_parse_var :
Marko Mikulicic 0:c0ecb8bf28eb 23600 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23601 #define L CR_CUR_LOCALS_PT(fid_parse_var_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23602 {
Marko Mikulicic 0:c0ecb8bf28eb 23603 L->start = add_node(v7, a, AST_VAR);
Marko Mikulicic 0:c0ecb8bf28eb 23604 ast_modify_skip(a, v7->last_var_node, L->start, AST_FUNC_FIRST_VAR_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23605 /* zero out var node pointer */
Marko Mikulicic 0:c0ecb8bf28eb 23606 ast_modify_skip(a, L->start, L->start, AST_FUNC_FIRST_VAR_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23607 v7->last_var_node = L->start;
Marko Mikulicic 0:c0ecb8bf28eb 23608 do {
Marko Mikulicic 0:c0ecb8bf28eb 23609 add_inlined_node(v7, a, AST_VAR_DECL, v7->tok, v7->tok_len);
Marko Mikulicic 0:c0ecb8bf28eb 23610 EXPECT(TOK_IDENTIFIER);
Marko Mikulicic 0:c0ecb8bf28eb 23611 if (ACCEPT(TOK_ASSIGN)) {
Marko Mikulicic 0:c0ecb8bf28eb 23612 CALL_PARSE_ASSIGN(fid_p_var_1);
Marko Mikulicic 0:c0ecb8bf28eb 23613 } else {
Marko Mikulicic 0:c0ecb8bf28eb 23614 add_node(v7, a, AST_NOP);
Marko Mikulicic 0:c0ecb8bf28eb 23615 }
Marko Mikulicic 0:c0ecb8bf28eb 23616 } while (ACCEPT(TOK_COMMA));
Marko Mikulicic 0:c0ecb8bf28eb 23617 ast_set_skip(a, L->start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23618 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23619 }
Marko Mikulicic 0:c0ecb8bf28eb 23620
Marko Mikulicic 0:c0ecb8bf28eb 23621 /* static enum v7_err parse_prop(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23622 fid_parse_prop :
Marko Mikulicic 0:c0ecb8bf28eb 23623 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23624 #define L CR_CUR_LOCALS_PT(fid_parse_prop_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23625 {
Marko Mikulicic 0:c0ecb8bf28eb 23626 #ifdef V7_ENABLE_JS_GETTERS
Marko Mikulicic 0:c0ecb8bf28eb 23627 if (v7->cur_tok == TOK_IDENTIFIER && v7->tok_len == 3 &&
Marko Mikulicic 0:c0ecb8bf28eb 23628 strncmp(v7->tok, "get", v7->tok_len) == 0 && lookahead(v7) != TOK_COLON) {
Marko Mikulicic 0:c0ecb8bf28eb 23629 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23630 add_node(v7, a, AST_GETTER);
Marko Mikulicic 0:c0ecb8bf28eb 23631 CALL_PARSE_FUNCDECL(1, 1, fid_p_prop_1_getter);
Marko Mikulicic 0:c0ecb8bf28eb 23632 } else
Marko Mikulicic 0:c0ecb8bf28eb 23633 #endif
Marko Mikulicic 0:c0ecb8bf28eb 23634 if (v7->cur_tok == TOK_IDENTIFIER && lookahead(v7) == TOK_OPEN_PAREN) {
Marko Mikulicic 0:c0ecb8bf28eb 23635 /* ecmascript 6 feature */
Marko Mikulicic 0:c0ecb8bf28eb 23636 CALL_PARSE_FUNCDECL(1, 1, fid_p_prop_2);
Marko Mikulicic 0:c0ecb8bf28eb 23637 #ifdef V7_ENABLE_JS_SETTERS
Marko Mikulicic 0:c0ecb8bf28eb 23638 } else if (v7->cur_tok == TOK_IDENTIFIER && v7->tok_len == 3 &&
Marko Mikulicic 0:c0ecb8bf28eb 23639 strncmp(v7->tok, "set", v7->tok_len) == 0 &&
Marko Mikulicic 0:c0ecb8bf28eb 23640 lookahead(v7) != TOK_COLON) {
Marko Mikulicic 0:c0ecb8bf28eb 23641 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23642 add_node(v7, a, AST_SETTER);
Marko Mikulicic 0:c0ecb8bf28eb 23643 CALL_PARSE_FUNCDECL(1, 1, fid_p_prop_3_setter);
Marko Mikulicic 0:c0ecb8bf28eb 23644 #endif
Marko Mikulicic 0:c0ecb8bf28eb 23645 } else {
Marko Mikulicic 0:c0ecb8bf28eb 23646 /* Allow reserved words as property names. */
Marko Mikulicic 0:c0ecb8bf28eb 23647 if (is_reserved_word_token(v7->cur_tok) || v7->cur_tok == TOK_IDENTIFIER ||
Marko Mikulicic 0:c0ecb8bf28eb 23648 v7->cur_tok == TOK_NUMBER) {
Marko Mikulicic 0:c0ecb8bf28eb 23649 add_inlined_node(v7, a, AST_PROP, v7->tok, v7->tok_len);
Marko Mikulicic 0:c0ecb8bf28eb 23650 } else if (v7->cur_tok == TOK_STRING_LITERAL) {
Marko Mikulicic 0:c0ecb8bf28eb 23651 add_inlined_node(v7, a, AST_PROP, v7->tok + 1, v7->tok_len - 2);
Marko Mikulicic 0:c0ecb8bf28eb 23652 } else {
Marko Mikulicic 0:c0ecb8bf28eb 23653 CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 23654 }
Marko Mikulicic 0:c0ecb8bf28eb 23655 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23656 EXPECT(TOK_COLON);
Marko Mikulicic 0:c0ecb8bf28eb 23657 CALL_PARSE_ASSIGN(fid_p_prop_4);
Marko Mikulicic 0:c0ecb8bf28eb 23658 }
Marko Mikulicic 0:c0ecb8bf28eb 23659 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23660 }
Marko Mikulicic 0:c0ecb8bf28eb 23661
Marko Mikulicic 0:c0ecb8bf28eb 23662 /* static enum v7_err parse_dowhile(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23663 fid_parse_dowhile :
Marko Mikulicic 0:c0ecb8bf28eb 23664 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23665 #define L CR_CUR_LOCALS_PT(fid_parse_dowhile_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23666 {
Marko Mikulicic 0:c0ecb8bf28eb 23667 L->start = add_node(v7, a, AST_DOWHILE);
Marko Mikulicic 0:c0ecb8bf28eb 23668 L->saved_in_loop = v7->pstate.in_loop;
Marko Mikulicic 0:c0ecb8bf28eb 23669
Marko Mikulicic 0:c0ecb8bf28eb 23670 v7->pstate.in_loop = 1;
Marko Mikulicic 0:c0ecb8bf28eb 23671 CALL_PARSE_STATEMENT(fid_p_dowhile_1);
Marko Mikulicic 0:c0ecb8bf28eb 23672 v7->pstate.in_loop = L->saved_in_loop;
Marko Mikulicic 0:c0ecb8bf28eb 23673 ast_set_skip(a, L->start, AST_DO_WHILE_COND_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23674 EXPECT(TOK_WHILE);
Marko Mikulicic 0:c0ecb8bf28eb 23675 EXPECT(TOK_OPEN_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23676 CALL_PARSE_EXPRESSION(fid_p_dowhile_2);
Marko Mikulicic 0:c0ecb8bf28eb 23677 EXPECT(TOK_CLOSE_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23678 ast_set_skip(a, L->start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23679 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23680 }
Marko Mikulicic 0:c0ecb8bf28eb 23681
Marko Mikulicic 0:c0ecb8bf28eb 23682 /* static enum v7_err parse_for(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23683 fid_parse_for :
Marko Mikulicic 0:c0ecb8bf28eb 23684 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23685 #define L CR_CUR_LOCALS_PT(fid_parse_for_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23686 {
Marko Mikulicic 0:c0ecb8bf28eb 23687 /* TODO(mkm): for of, for each in */
Marko Mikulicic 0:c0ecb8bf28eb 23688 /*
Marko Mikulicic 0:c0ecb8bf28eb 23689 ast_off_t start;
Marko Mikulicic 0:c0ecb8bf28eb 23690 int saved_in_loop;
Marko Mikulicic 0:c0ecb8bf28eb 23691 */
Marko Mikulicic 0:c0ecb8bf28eb 23692
Marko Mikulicic 0:c0ecb8bf28eb 23693 L->start = add_node(v7, a, AST_FOR);
Marko Mikulicic 0:c0ecb8bf28eb 23694 L->saved_in_loop = v7->pstate.in_loop;
Marko Mikulicic 0:c0ecb8bf28eb 23695
Marko Mikulicic 0:c0ecb8bf28eb 23696 EXPECT(TOK_OPEN_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23697
Marko Mikulicic 0:c0ecb8bf28eb 23698 if (parse_optional(v7, a, TOK_SEMICOLON)) {
Marko Mikulicic 0:c0ecb8bf28eb 23699 /*
Marko Mikulicic 0:c0ecb8bf28eb 23700 * TODO(mkm): make this reentrant otherwise this pearl won't parse:
Marko Mikulicic 0:c0ecb8bf28eb 23701 * for((function(){return 1 in o.a ? o : x})().a in [1,2,3])
Marko Mikulicic 0:c0ecb8bf28eb 23702 */
Marko Mikulicic 0:c0ecb8bf28eb 23703 v7->pstate.inhibit_in = 1;
Marko Mikulicic 0:c0ecb8bf28eb 23704 if (ACCEPT(TOK_VAR)) {
Marko Mikulicic 0:c0ecb8bf28eb 23705 CALL_PARSE_VAR(fid_p_for_1);
Marko Mikulicic 0:c0ecb8bf28eb 23706 } else {
Marko Mikulicic 0:c0ecb8bf28eb 23707 CALL_PARSE_EXPRESSION(fid_p_for_2);
Marko Mikulicic 0:c0ecb8bf28eb 23708 }
Marko Mikulicic 0:c0ecb8bf28eb 23709 v7->pstate.inhibit_in = 0;
Marko Mikulicic 0:c0ecb8bf28eb 23710
Marko Mikulicic 0:c0ecb8bf28eb 23711 if (ACCEPT(TOK_IN)) {
Marko Mikulicic 0:c0ecb8bf28eb 23712 CALL_PARSE_EXPRESSION(fid_p_for_3);
Marko Mikulicic 0:c0ecb8bf28eb 23713 add_node(v7, a, AST_NOP);
Marko Mikulicic 0:c0ecb8bf28eb 23714 /*
Marko Mikulicic 0:c0ecb8bf28eb 23715 * Assumes that for and for in have the same AST format which is
Marko Mikulicic 0:c0ecb8bf28eb 23716 * suboptimal but avoids the need of fixing up the var offset chain.
Marko Mikulicic 0:c0ecb8bf28eb 23717 * TODO(mkm) improve this
Marko Mikulicic 0:c0ecb8bf28eb 23718 */
Marko Mikulicic 0:c0ecb8bf28eb 23719 ast_modify_tag(a, L->start - 1, AST_FOR_IN);
Marko Mikulicic 0:c0ecb8bf28eb 23720 goto for_loop_body;
Marko Mikulicic 0:c0ecb8bf28eb 23721 }
Marko Mikulicic 0:c0ecb8bf28eb 23722 }
Marko Mikulicic 0:c0ecb8bf28eb 23723
Marko Mikulicic 0:c0ecb8bf28eb 23724 EXPECT(TOK_SEMICOLON);
Marko Mikulicic 0:c0ecb8bf28eb 23725 if (parse_optional(v7, a, TOK_SEMICOLON)) {
Marko Mikulicic 0:c0ecb8bf28eb 23726 CALL_PARSE_EXPRESSION(fid_p_for_4);
Marko Mikulicic 0:c0ecb8bf28eb 23727 }
Marko Mikulicic 0:c0ecb8bf28eb 23728 EXPECT(TOK_SEMICOLON);
Marko Mikulicic 0:c0ecb8bf28eb 23729 if (parse_optional(v7, a, TOK_CLOSE_PAREN)) {
Marko Mikulicic 0:c0ecb8bf28eb 23730 CALL_PARSE_EXPRESSION(fid_p_for_5);
Marko Mikulicic 0:c0ecb8bf28eb 23731 }
Marko Mikulicic 0:c0ecb8bf28eb 23732
Marko Mikulicic 0:c0ecb8bf28eb 23733 for_loop_body:
Marko Mikulicic 0:c0ecb8bf28eb 23734 EXPECT(TOK_CLOSE_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23735 ast_set_skip(a, L->start, AST_FOR_BODY_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23736 v7->pstate.in_loop = 1;
Marko Mikulicic 0:c0ecb8bf28eb 23737 CALL_PARSE_STATEMENT(fid_p_for_6);
Marko Mikulicic 0:c0ecb8bf28eb 23738 v7->pstate.in_loop = L->saved_in_loop;
Marko Mikulicic 0:c0ecb8bf28eb 23739 ast_set_skip(a, L->start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23740 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23741 }
Marko Mikulicic 0:c0ecb8bf28eb 23742
Marko Mikulicic 0:c0ecb8bf28eb 23743 /* static enum v7_err parse_try(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23744 fid_parse_try :
Marko Mikulicic 0:c0ecb8bf28eb 23745 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23746 #define L CR_CUR_LOCALS_PT(fid_parse_try_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23747 {
Marko Mikulicic 0:c0ecb8bf28eb 23748 L->start = add_node(v7, a, AST_TRY);
Marko Mikulicic 0:c0ecb8bf28eb 23749 L->catch_or_finally = 0;
Marko Mikulicic 0:c0ecb8bf28eb 23750 CALL_PARSE_BLOCK(fid_p_try_1);
Marko Mikulicic 0:c0ecb8bf28eb 23751 ast_set_skip(a, L->start, AST_TRY_CATCH_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23752 if (ACCEPT(TOK_CATCH)) {
Marko Mikulicic 0:c0ecb8bf28eb 23753 L->catch_or_finally = 1;
Marko Mikulicic 0:c0ecb8bf28eb 23754 EXPECT(TOK_OPEN_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23755 CALL_PARSE_IDENT(fid_p_try_2);
Marko Mikulicic 0:c0ecb8bf28eb 23756 EXPECT(TOK_CLOSE_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23757 CALL_PARSE_BLOCK(fid_p_try_3);
Marko Mikulicic 0:c0ecb8bf28eb 23758 }
Marko Mikulicic 0:c0ecb8bf28eb 23759 ast_set_skip(a, L->start, AST_TRY_FINALLY_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23760 if (ACCEPT(TOK_FINALLY)) {
Marko Mikulicic 0:c0ecb8bf28eb 23761 L->catch_or_finally = 1;
Marko Mikulicic 0:c0ecb8bf28eb 23762 CALL_PARSE_BLOCK(fid_p_try_4);
Marko Mikulicic 0:c0ecb8bf28eb 23763 }
Marko Mikulicic 0:c0ecb8bf28eb 23764 ast_set_skip(a, L->start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23765
Marko Mikulicic 0:c0ecb8bf28eb 23766 /* make sure `catch` and `finally` aren't both missing */
Marko Mikulicic 0:c0ecb8bf28eb 23767 if (!L->catch_or_finally) {
Marko Mikulicic 0:c0ecb8bf28eb 23768 CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 23769 }
Marko Mikulicic 0:c0ecb8bf28eb 23770
Marko Mikulicic 0:c0ecb8bf28eb 23771 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23772 }
Marko Mikulicic 0:c0ecb8bf28eb 23773
Marko Mikulicic 0:c0ecb8bf28eb 23774 /* static enum v7_err parse_switch(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23775 fid_parse_switch :
Marko Mikulicic 0:c0ecb8bf28eb 23776 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23777 #define L CR_CUR_LOCALS_PT(fid_parse_switch_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23778 {
Marko Mikulicic 0:c0ecb8bf28eb 23779 L->start = add_node(v7, a, AST_SWITCH);
Marko Mikulicic 0:c0ecb8bf28eb 23780 L->saved_in_switch = v7->pstate.in_switch;
Marko Mikulicic 0:c0ecb8bf28eb 23781
Marko Mikulicic 0:c0ecb8bf28eb 23782 ast_set_skip(a, L->start, AST_SWITCH_DEFAULT_SKIP); /* clear out */
Marko Mikulicic 0:c0ecb8bf28eb 23783 EXPECT(TOK_OPEN_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23784 CALL_PARSE_EXPRESSION(fid_p_switch_1);
Marko Mikulicic 0:c0ecb8bf28eb 23785 EXPECT(TOK_CLOSE_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23786 EXPECT(TOK_OPEN_CURLY);
Marko Mikulicic 0:c0ecb8bf28eb 23787 v7->pstate.in_switch = 1;
Marko Mikulicic 0:c0ecb8bf28eb 23788 while (v7->cur_tok != TOK_CLOSE_CURLY) {
Marko Mikulicic 0:c0ecb8bf28eb 23789 switch (v7->cur_tok) {
Marko Mikulicic 0:c0ecb8bf28eb 23790 case TOK_CASE:
Marko Mikulicic 0:c0ecb8bf28eb 23791 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23792 L->case_start = add_node(v7, a, AST_CASE);
Marko Mikulicic 0:c0ecb8bf28eb 23793 CALL_PARSE_EXPRESSION(fid_p_switch_2);
Marko Mikulicic 0:c0ecb8bf28eb 23794 EXPECT(TOK_COLON);
Marko Mikulicic 0:c0ecb8bf28eb 23795 while (v7->cur_tok != TOK_CASE && v7->cur_tok != TOK_DEFAULT &&
Marko Mikulicic 0:c0ecb8bf28eb 23796 v7->cur_tok != TOK_CLOSE_CURLY) {
Marko Mikulicic 0:c0ecb8bf28eb 23797 CALL_PARSE_STATEMENT(fid_p_switch_3);
Marko Mikulicic 0:c0ecb8bf28eb 23798 }
Marko Mikulicic 0:c0ecb8bf28eb 23799 ast_set_skip(a, L->case_start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23800 break;
Marko Mikulicic 0:c0ecb8bf28eb 23801 case TOK_DEFAULT:
Marko Mikulicic 0:c0ecb8bf28eb 23802 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23803 EXPECT(TOK_COLON);
Marko Mikulicic 0:c0ecb8bf28eb 23804 ast_set_skip(a, L->start, AST_SWITCH_DEFAULT_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23805 L->case_start = add_node(v7, a, AST_DEFAULT);
Marko Mikulicic 0:c0ecb8bf28eb 23806 while (v7->cur_tok != TOK_CASE && v7->cur_tok != TOK_DEFAULT &&
Marko Mikulicic 0:c0ecb8bf28eb 23807 v7->cur_tok != TOK_CLOSE_CURLY) {
Marko Mikulicic 0:c0ecb8bf28eb 23808 CALL_PARSE_STATEMENT(fid_p_switch_4);
Marko Mikulicic 0:c0ecb8bf28eb 23809 }
Marko Mikulicic 0:c0ecb8bf28eb 23810 ast_set_skip(a, L->case_start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23811 break;
Marko Mikulicic 0:c0ecb8bf28eb 23812 default:
Marko Mikulicic 0:c0ecb8bf28eb 23813 CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 23814 }
Marko Mikulicic 0:c0ecb8bf28eb 23815 }
Marko Mikulicic 0:c0ecb8bf28eb 23816 EXPECT(TOK_CLOSE_CURLY);
Marko Mikulicic 0:c0ecb8bf28eb 23817 ast_set_skip(a, L->start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23818 v7->pstate.in_switch = L->saved_in_switch;
Marko Mikulicic 0:c0ecb8bf28eb 23819 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23820 }
Marko Mikulicic 0:c0ecb8bf28eb 23821
Marko Mikulicic 0:c0ecb8bf28eb 23822 /* static enum v7_err parse_with(struct v7 *v7, struct ast *a) */
Marko Mikulicic 0:c0ecb8bf28eb 23823 fid_parse_with :
Marko Mikulicic 0:c0ecb8bf28eb 23824 #undef L
Marko Mikulicic 0:c0ecb8bf28eb 23825 #define L CR_CUR_LOCALS_PT(fid_parse_with_locals_t)
Marko Mikulicic 0:c0ecb8bf28eb 23826 {
Marko Mikulicic 0:c0ecb8bf28eb 23827 L->start = add_node(v7, a, AST_WITH);
Marko Mikulicic 0:c0ecb8bf28eb 23828 if (v7->pstate.in_strict) {
Marko Mikulicic 0:c0ecb8bf28eb 23829 CR_THROW(PARSER_EXC_ID__SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 23830 }
Marko Mikulicic 0:c0ecb8bf28eb 23831 EXPECT(TOK_OPEN_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23832 CALL_PARSE_EXPRESSION(fid_p_with_1);
Marko Mikulicic 0:c0ecb8bf28eb 23833 EXPECT(TOK_CLOSE_PAREN);
Marko Mikulicic 0:c0ecb8bf28eb 23834 CALL_PARSE_STATEMENT(fid_p_with_2);
Marko Mikulicic 0:c0ecb8bf28eb 23835 ast_set_skip(a, L->start, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 23836 CR_RETURN_VOID();
Marko Mikulicic 0:c0ecb8bf28eb 23837 }
Marko Mikulicic 0:c0ecb8bf28eb 23838
Marko Mikulicic 0:c0ecb8bf28eb 23839 fid_none:
Marko Mikulicic 0:c0ecb8bf28eb 23840 /* stack is empty, so we're done; return */
Marko Mikulicic 0:c0ecb8bf28eb 23841 return rc;
Marko Mikulicic 0:c0ecb8bf28eb 23842 }
Marko Mikulicic 0:c0ecb8bf28eb 23843
Marko Mikulicic 0:c0ecb8bf28eb 23844 V7_PRIVATE enum v7_err parse(struct v7 *v7, struct ast *a, const char *src,
Marko Mikulicic 0:c0ecb8bf28eb 23845 size_t src_len, int is_json) {
Marko Mikulicic 0:c0ecb8bf28eb 23846 enum v7_err rcode;
Marko Mikulicic 0:c0ecb8bf28eb 23847 const char *error_msg = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 23848 const char *p;
Marko Mikulicic 0:c0ecb8bf28eb 23849 struct cr_ctx cr_ctx;
Marko Mikulicic 0:c0ecb8bf28eb 23850 union user_arg_ret arg_retval;
Marko Mikulicic 0:c0ecb8bf28eb 23851 enum cr_status rc;
Marko Mikulicic 0:c0ecb8bf28eb 23852 #if defined(V7_ENABLE_STACK_TRACKING)
Marko Mikulicic 0:c0ecb8bf28eb 23853 struct stack_track_ctx stack_track_ctx;
Marko Mikulicic 0:c0ecb8bf28eb 23854 #endif
Marko Mikulicic 0:c0ecb8bf28eb 23855 int saved_line_no = v7->line_no;
Marko Mikulicic 0:c0ecb8bf28eb 23856
Marko Mikulicic 0:c0ecb8bf28eb 23857 #if defined(V7_ENABLE_STACK_TRACKING)
Marko Mikulicic 0:c0ecb8bf28eb 23858 v7_stack_track_start(v7, &stack_track_ctx);
Marko Mikulicic 0:c0ecb8bf28eb 23859 #endif
Marko Mikulicic 0:c0ecb8bf28eb 23860
Marko Mikulicic 0:c0ecb8bf28eb 23861 v7->pstate.source_code = v7->pstate.pc = src;
Marko Mikulicic 0:c0ecb8bf28eb 23862 v7->pstate.src_end = src + src_len;
Marko Mikulicic 0:c0ecb8bf28eb 23863 v7->pstate.file_name = "<stdin>";
Marko Mikulicic 0:c0ecb8bf28eb 23864 v7->pstate.line_no = 1;
Marko Mikulicic 0:c0ecb8bf28eb 23865 v7->pstate.in_function = 0;
Marko Mikulicic 0:c0ecb8bf28eb 23866 v7->pstate.in_loop = 0;
Marko Mikulicic 0:c0ecb8bf28eb 23867 v7->pstate.in_switch = 0;
Marko Mikulicic 0:c0ecb8bf28eb 23868
Marko Mikulicic 0:c0ecb8bf28eb 23869 /*
Marko Mikulicic 0:c0ecb8bf28eb 23870 * TODO(dfrank): `v7->parser.line_no` vs `v7->line_no` is confusing. probaby
Marko Mikulicic 0:c0ecb8bf28eb 23871 * we need to refactor it.
Marko Mikulicic 0:c0ecb8bf28eb 23872 *
Marko Mikulicic 0:c0ecb8bf28eb 23873 * See comment for v7->line_no in core.h for some details.
Marko Mikulicic 0:c0ecb8bf28eb 23874 */
Marko Mikulicic 0:c0ecb8bf28eb 23875 v7->line_no = 1;
Marko Mikulicic 0:c0ecb8bf28eb 23876
Marko Mikulicic 0:c0ecb8bf28eb 23877 next_tok(v7);
Marko Mikulicic 0:c0ecb8bf28eb 23878 /*
Marko Mikulicic 0:c0ecb8bf28eb 23879 * setup initial state for "after newline" tracking.
Marko Mikulicic 0:c0ecb8bf28eb 23880 * next_tok will consume our token and position the current line
Marko Mikulicic 0:c0ecb8bf28eb 23881 * position at the beginning of the next token.
Marko Mikulicic 0:c0ecb8bf28eb 23882 * While processing the first token, both the leading and the
Marko Mikulicic 0:c0ecb8bf28eb 23883 * trailing newlines will be counted and thus it will create a spurious
Marko Mikulicic 0:c0ecb8bf28eb 23884 * "after newline" condition at the end of the first token
Marko Mikulicic 0:c0ecb8bf28eb 23885 * regardless if there is actually a newline after it.
Marko Mikulicic 0:c0ecb8bf28eb 23886 */
Marko Mikulicic 0:c0ecb8bf28eb 23887 for (p = src; isspace((int) *p); p++) {
Marko Mikulicic 0:c0ecb8bf28eb 23888 if (*p == '\n') {
Marko Mikulicic 0:c0ecb8bf28eb 23889 v7->pstate.prev_line_no++;
Marko Mikulicic 0:c0ecb8bf28eb 23890 }
Marko Mikulicic 0:c0ecb8bf28eb 23891 }
Marko Mikulicic 0:c0ecb8bf28eb 23892
Marko Mikulicic 0:c0ecb8bf28eb 23893 /* init cr context */
Marko Mikulicic 0:c0ecb8bf28eb 23894 cr_context_init(&cr_ctx, &arg_retval, sizeof(arg_retval), _fid_descrs);
Marko Mikulicic 0:c0ecb8bf28eb 23895
Marko Mikulicic 0:c0ecb8bf28eb 23896 /* prepare first function call: fid_mul_sum */
Marko Mikulicic 0:c0ecb8bf28eb 23897 if (is_json) {
Marko Mikulicic 0:c0ecb8bf28eb 23898 CR_FIRST_CALL_PREPARE_C(&cr_ctx, fid_parse_terminal);
Marko Mikulicic 0:c0ecb8bf28eb 23899 } else {
Marko Mikulicic 0:c0ecb8bf28eb 23900 CR_FIRST_CALL_PREPARE_C(&cr_ctx, fid_parse_script);
Marko Mikulicic 0:c0ecb8bf28eb 23901 }
Marko Mikulicic 0:c0ecb8bf28eb 23902
Marko Mikulicic 0:c0ecb8bf28eb 23903 /* proceed to coroutine execution */
Marko Mikulicic 0:c0ecb8bf28eb 23904 rc = parser_cr_exec(&cr_ctx, v7, a);
Marko Mikulicic 0:c0ecb8bf28eb 23905
Marko Mikulicic 0:c0ecb8bf28eb 23906 /* set `rcode` depending on coroutine state */
Marko Mikulicic 0:c0ecb8bf28eb 23907 switch (rc) {
Marko Mikulicic 0:c0ecb8bf28eb 23908 case CR_RES__OK:
Marko Mikulicic 0:c0ecb8bf28eb 23909 rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 23910 break;
Marko Mikulicic 0:c0ecb8bf28eb 23911 case CR_RES__ERR_UNCAUGHT_EXCEPTION:
Marko Mikulicic 0:c0ecb8bf28eb 23912 switch ((enum parser_exc_id) CR_THROWN_C(&cr_ctx)) {
Marko Mikulicic 0:c0ecb8bf28eb 23913 case PARSER_EXC_ID__SYNTAX_ERROR:
Marko Mikulicic 0:c0ecb8bf28eb 23914 rcode = V7_SYNTAX_ERROR;
Marko Mikulicic 0:c0ecb8bf28eb 23915 error_msg = "Syntax error";
Marko Mikulicic 0:c0ecb8bf28eb 23916 break;
Marko Mikulicic 0:c0ecb8bf28eb 23917
Marko Mikulicic 0:c0ecb8bf28eb 23918 default:
Marko Mikulicic 0:c0ecb8bf28eb 23919 rcode = V7_INTERNAL_ERROR;
Marko Mikulicic 0:c0ecb8bf28eb 23920 error_msg = "Internal error: no exception id set";
Marko Mikulicic 0:c0ecb8bf28eb 23921 break;
Marko Mikulicic 0:c0ecb8bf28eb 23922 }
Marko Mikulicic 0:c0ecb8bf28eb 23923 break;
Marko Mikulicic 0:c0ecb8bf28eb 23924 default:
Marko Mikulicic 0:c0ecb8bf28eb 23925 rcode = V7_INTERNAL_ERROR;
Marko Mikulicic 0:c0ecb8bf28eb 23926 error_msg = "Internal error: unexpected parser coroutine return code";
Marko Mikulicic 0:c0ecb8bf28eb 23927 break;
Marko Mikulicic 0:c0ecb8bf28eb 23928 }
Marko Mikulicic 0:c0ecb8bf28eb 23929
Marko Mikulicic 0:c0ecb8bf28eb 23930 #if defined(V7_TRACK_MAX_PARSER_STACK_SIZE)
Marko Mikulicic 0:c0ecb8bf28eb 23931 /* remember how much stack space was consumed */
Marko Mikulicic 0:c0ecb8bf28eb 23932
Marko Mikulicic 0:c0ecb8bf28eb 23933 if (v7->parser_stack_data_max_size < cr_ctx.stack_data.size) {
Marko Mikulicic 0:c0ecb8bf28eb 23934 v7->parser_stack_data_max_size = cr_ctx.stack_data.size;
Marko Mikulicic 0:c0ecb8bf28eb 23935 #ifndef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 23936 printf("parser_stack_data_max_size=%u\n",
Marko Mikulicic 0:c0ecb8bf28eb 23937 (unsigned int) v7->parser_stack_data_max_size);
Marko Mikulicic 0:c0ecb8bf28eb 23938 #endif
Marko Mikulicic 0:c0ecb8bf28eb 23939 }
Marko Mikulicic 0:c0ecb8bf28eb 23940
Marko Mikulicic 0:c0ecb8bf28eb 23941 if (v7->parser_stack_ret_max_size < cr_ctx.stack_ret.size) {
Marko Mikulicic 0:c0ecb8bf28eb 23942 v7->parser_stack_ret_max_size = cr_ctx.stack_ret.size;
Marko Mikulicic 0:c0ecb8bf28eb 23943 #ifndef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 23944 printf("parser_stack_ret_max_size=%u\n",
Marko Mikulicic 0:c0ecb8bf28eb 23945 (unsigned int) v7->parser_stack_ret_max_size);
Marko Mikulicic 0:c0ecb8bf28eb 23946 #endif
Marko Mikulicic 0:c0ecb8bf28eb 23947 }
Marko Mikulicic 0:c0ecb8bf28eb 23948
Marko Mikulicic 0:c0ecb8bf28eb 23949 #if defined(CR_TRACK_MAX_STACK_LEN)
Marko Mikulicic 0:c0ecb8bf28eb 23950 if (v7->parser_stack_data_max_len < cr_ctx.stack_data_max_len) {
Marko Mikulicic 0:c0ecb8bf28eb 23951 v7->parser_stack_data_max_len = cr_ctx.stack_data_max_len;
Marko Mikulicic 0:c0ecb8bf28eb 23952 #ifndef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 23953 printf("parser_stack_data_max_len=%u\n",
Marko Mikulicic 0:c0ecb8bf28eb 23954 (unsigned int) v7->parser_stack_data_max_len);
Marko Mikulicic 0:c0ecb8bf28eb 23955 #endif
Marko Mikulicic 0:c0ecb8bf28eb 23956 }
Marko Mikulicic 0:c0ecb8bf28eb 23957
Marko Mikulicic 0:c0ecb8bf28eb 23958 if (v7->parser_stack_ret_max_len < cr_ctx.stack_ret_max_len) {
Marko Mikulicic 0:c0ecb8bf28eb 23959 v7->parser_stack_ret_max_len = cr_ctx.stack_ret_max_len;
Marko Mikulicic 0:c0ecb8bf28eb 23960 #ifndef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 23961 printf("parser_stack_ret_max_len=%u\n",
Marko Mikulicic 0:c0ecb8bf28eb 23962 (unsigned int) v7->parser_stack_ret_max_len);
Marko Mikulicic 0:c0ecb8bf28eb 23963 #endif
Marko Mikulicic 0:c0ecb8bf28eb 23964 }
Marko Mikulicic 0:c0ecb8bf28eb 23965 #endif
Marko Mikulicic 0:c0ecb8bf28eb 23966
Marko Mikulicic 0:c0ecb8bf28eb 23967 #endif
Marko Mikulicic 0:c0ecb8bf28eb 23968
Marko Mikulicic 0:c0ecb8bf28eb 23969 /* free resources occupied by context (at least, "stack" arrays) */
Marko Mikulicic 0:c0ecb8bf28eb 23970 cr_context_free(&cr_ctx);
Marko Mikulicic 0:c0ecb8bf28eb 23971
Marko Mikulicic 0:c0ecb8bf28eb 23972 #if defined(V7_ENABLE_STACK_TRACKING)
Marko Mikulicic 0:c0ecb8bf28eb 23973 {
Marko Mikulicic 0:c0ecb8bf28eb 23974 int diff = v7_stack_track_end(v7, &stack_track_ctx);
Marko Mikulicic 0:c0ecb8bf28eb 23975 if (diff > v7->stack_stat[V7_STACK_STAT_PARSER]) {
Marko Mikulicic 0:c0ecb8bf28eb 23976 v7->stack_stat[V7_STACK_STAT_PARSER] = diff;
Marko Mikulicic 0:c0ecb8bf28eb 23977 }
Marko Mikulicic 0:c0ecb8bf28eb 23978 }
Marko Mikulicic 0:c0ecb8bf28eb 23979 #endif
Marko Mikulicic 0:c0ecb8bf28eb 23980
Marko Mikulicic 0:c0ecb8bf28eb 23981 /* Check if AST was overflown */
Marko Mikulicic 0:c0ecb8bf28eb 23982 if (a->has_overflow) {
Marko Mikulicic 0:c0ecb8bf28eb 23983 rcode = v7_throwf(v7, SYNTAX_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 23984 "Script too large (try V7_LARGE_AST build option)");
Marko Mikulicic 0:c0ecb8bf28eb 23985 V7_THROW(V7_AST_TOO_LARGE);
Marko Mikulicic 0:c0ecb8bf28eb 23986 }
Marko Mikulicic 0:c0ecb8bf28eb 23987
Marko Mikulicic 0:c0ecb8bf28eb 23988 if (rcode == V7_OK && v7->cur_tok != TOK_END_OF_INPUT) {
Marko Mikulicic 0:c0ecb8bf28eb 23989 rcode = V7_SYNTAX_ERROR;
Marko Mikulicic 0:c0ecb8bf28eb 23990 error_msg = "Syntax error";
Marko Mikulicic 0:c0ecb8bf28eb 23991 }
Marko Mikulicic 0:c0ecb8bf28eb 23992
Marko Mikulicic 0:c0ecb8bf28eb 23993 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 23994 unsigned long col = get_column(v7->pstate.source_code, v7->tok);
Marko Mikulicic 0:c0ecb8bf28eb 23995 int line_len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 23996
Marko Mikulicic 0:c0ecb8bf28eb 23997 assert(error_msg != NULL);
Marko Mikulicic 0:c0ecb8bf28eb 23998
Marko Mikulicic 0:c0ecb8bf28eb 23999 for (p = v7->tok - col; p < v7->pstate.src_end && *p != '\0' && *p != '\n';
Marko Mikulicic 0:c0ecb8bf28eb 24000 p++) {
Marko Mikulicic 0:c0ecb8bf28eb 24001 line_len++;
Marko Mikulicic 0:c0ecb8bf28eb 24002 }
Marko Mikulicic 0:c0ecb8bf28eb 24003
Marko Mikulicic 0:c0ecb8bf28eb 24004 /* fixup line number: line_no points to the beginning of the next token */
Marko Mikulicic 0:c0ecb8bf28eb 24005 for (; p < v7->pstate.pc; p++) {
Marko Mikulicic 0:c0ecb8bf28eb 24006 if (*p == '\n') {
Marko Mikulicic 0:c0ecb8bf28eb 24007 v7->pstate.line_no--;
Marko Mikulicic 0:c0ecb8bf28eb 24008 }
Marko Mikulicic 0:c0ecb8bf28eb 24009 }
Marko Mikulicic 0:c0ecb8bf28eb 24010
Marko Mikulicic 0:c0ecb8bf28eb 24011 /*
Marko Mikulicic 0:c0ecb8bf28eb 24012 * We already have a proper `rcode`, that's why we discard returned value
Marko Mikulicic 0:c0ecb8bf28eb 24013 * of `v7_throwf()`, which is always `V7_EXEC_EXCEPTION`.
Marko Mikulicic 0:c0ecb8bf28eb 24014 *
Marko Mikulicic 0:c0ecb8bf28eb 24015 * TODO(dfrank): probably get rid of distinct error types, and use just
Marko Mikulicic 0:c0ecb8bf28eb 24016 * `V7_JS_EXCEPTION`. However it would be good to have a way to get exact
Marko Mikulicic 0:c0ecb8bf28eb 24017 * error type, so probably error object should contain some property with
Marko Mikulicic 0:c0ecb8bf28eb 24018 * error code, but it would make exceptions even more expensive, etc, etc.
Marko Mikulicic 0:c0ecb8bf28eb 24019 */
Marko Mikulicic 0:c0ecb8bf28eb 24020 {
Marko Mikulicic 0:c0ecb8bf28eb 24021 enum v7_err _tmp;
Marko Mikulicic 0:c0ecb8bf28eb 24022 _tmp = v7_throwf(v7, SYNTAX_ERROR, "%s at line %d col %lu:\n%.*s\n%*s^",
Marko Mikulicic 0:c0ecb8bf28eb 24023 error_msg, v7->pstate.line_no, col, line_len,
Marko Mikulicic 0:c0ecb8bf28eb 24024 v7->tok - col, (int) col - 1, "");
Marko Mikulicic 0:c0ecb8bf28eb 24025 (void) _tmp;
Marko Mikulicic 0:c0ecb8bf28eb 24026 }
Marko Mikulicic 0:c0ecb8bf28eb 24027 V7_THROW(rcode);
Marko Mikulicic 0:c0ecb8bf28eb 24028 }
Marko Mikulicic 0:c0ecb8bf28eb 24029
Marko Mikulicic 0:c0ecb8bf28eb 24030 clean:
Marko Mikulicic 0:c0ecb8bf28eb 24031 v7->line_no = saved_line_no;
Marko Mikulicic 0:c0ecb8bf28eb 24032 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 24033 }
Marko Mikulicic 0:c0ecb8bf28eb 24034
Marko Mikulicic 0:c0ecb8bf28eb 24035 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 24036 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 24037 #line 1 "v7/src/compiler.c"
Marko Mikulicic 0:c0ecb8bf28eb 24038 #endif
Marko Mikulicic 0:c0ecb8bf28eb 24039 /*
Marko Mikulicic 0:c0ecb8bf28eb 24040 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 24041 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 24042 */
Marko Mikulicic 0:c0ecb8bf28eb 24043
Marko Mikulicic 0:c0ecb8bf28eb 24044 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 24045 /* Amalgamated: #include "v7/src/compiler.h" */
Marko Mikulicic 0:c0ecb8bf28eb 24046 /* Amalgamated: #include "v7/src/std_error.h" */
Marko Mikulicic 0:c0ecb8bf28eb 24047 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 24048 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 24049 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 24050 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 24051 /* Amalgamated: #include "v7/src/regexp.h" */
Marko Mikulicic 0:c0ecb8bf28eb 24052
Marko Mikulicic 0:c0ecb8bf28eb 24053 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 24054
Marko Mikulicic 0:c0ecb8bf28eb 24055 /*
Marko Mikulicic 0:c0ecb8bf28eb 24056 * The bytecode compiler takes an AST as input and produces one or more
Marko Mikulicic 0:c0ecb8bf28eb 24057 * bcode structure as output.
Marko Mikulicic 0:c0ecb8bf28eb 24058 *
Marko Mikulicic 0:c0ecb8bf28eb 24059 * Each script or function body is compiled into it's own bcode structure.
Marko Mikulicic 0:c0ecb8bf28eb 24060 *
Marko Mikulicic 0:c0ecb8bf28eb 24061 * Each bcode stream produces a new value on the stack, i.e. its overall
Marko Mikulicic 0:c0ecb8bf28eb 24062 * stack diagram is: `( -- a)`
Marko Mikulicic 0:c0ecb8bf28eb 24063 *
Marko Mikulicic 0:c0ecb8bf28eb 24064 * This value will be then popped by the function caller or by v7_exec in case
Marko Mikulicic 0:c0ecb8bf28eb 24065 * of scripts.
Marko Mikulicic 0:c0ecb8bf28eb 24066 *
Marko Mikulicic 0:c0ecb8bf28eb 24067 * In JS, the value of a script is the value of the last statement.
Marko Mikulicic 0:c0ecb8bf28eb 24068 * A script with no statement has an `undefined` value.
Marko Mikulicic 0:c0ecb8bf28eb 24069 * Functions instead require an explicit return value, so this matters only
Marko Mikulicic 0:c0ecb8bf28eb 24070 * for `v7_exec` and JS `eval`.
Marko Mikulicic 0:c0ecb8bf28eb 24071 *
Marko Mikulicic 0:c0ecb8bf28eb 24072 * Since an empty script has an undefined value, and each script has to
Marko Mikulicic 0:c0ecb8bf28eb 24073 * yield a value, the script/function prologue consists of a PUSH_UNDEFINED.
Marko Mikulicic 0:c0ecb8bf28eb 24074 *
Marko Mikulicic 0:c0ecb8bf28eb 24075 * Each statement will be compiled to push a value on the stack.
Marko Mikulicic 0:c0ecb8bf28eb 24076 * When a statement begins evaluating, the current TOS is thus either
Marko Mikulicic 0:c0ecb8bf28eb 24077 * the value of the previous statement or `undefined` in case of the first
Marko Mikulicic 0:c0ecb8bf28eb 24078 * statement.
Marko Mikulicic 0:c0ecb8bf28eb 24079 *
Marko Mikulicic 0:c0ecb8bf28eb 24080 * Every statement of a given script/function body always evaluates at the same
Marko Mikulicic 0:c0ecb8bf28eb 24081 * stack depth.
Marko Mikulicic 0:c0ecb8bf28eb 24082 *
Marko Mikulicic 0:c0ecb8bf28eb 24083 * In order to achieve that, after a statement is compiled out, a SWAP_DROP
Marko Mikulicic 0:c0ecb8bf28eb 24084 * opcode is emitted, that drops the value of the previous statement (or the
Marko Mikulicic 0:c0ecb8bf28eb 24085 * initial `undefined`). Dropping the value after the next statement is
Marko Mikulicic 0:c0ecb8bf28eb 24086 * evaluated and not before has allows us to correctly implement exception
Marko Mikulicic 0:c0ecb8bf28eb 24087 * behaviour and the break statement.
Marko Mikulicic 0:c0ecb8bf28eb 24088 *
Marko Mikulicic 0:c0ecb8bf28eb 24089 * Compound statements are constructs such as `if`/`while`/`for`/`try`. These
Marko Mikulicic 0:c0ecb8bf28eb 24090 * constructs contain a body consisting of a possibly empty statement list.
Marko Mikulicic 0:c0ecb8bf28eb 24091 *
Marko Mikulicic 0:c0ecb8bf28eb 24092 * Unlike normal statements, compound statements don't produce a value
Marko Mikulicic 0:c0ecb8bf28eb 24093 * themselves. Their value is either the value of their last executed statement
Marko Mikulicic 0:c0ecb8bf28eb 24094 * in their body, or the previous statement in case their body is empty or not
Marko Mikulicic 0:c0ecb8bf28eb 24095 * evaluated at all.
Marko Mikulicic 0:c0ecb8bf28eb 24096 *
Marko Mikulicic 0:c0ecb8bf28eb 24097 * An example is:
Marko Mikulicic 0:c0ecb8bf28eb 24098 *
Marko Mikulicic 0:c0ecb8bf28eb 24099 * [source,js]
Marko Mikulicic 0:c0ecb8bf28eb 24100 * ----
Marko Mikulicic 0:c0ecb8bf28eb 24101 * try {
Marko Mikulicic 0:c0ecb8bf28eb 24102 * 42;
Marko Mikulicic 0:c0ecb8bf28eb 24103 * someUnexistingVariable;
Marko Mikulicic 0:c0ecb8bf28eb 24104 * } catch(e) {
Marko Mikulicic 0:c0ecb8bf28eb 24105 * while(true) {}
Marko Mikulicic 0:c0ecb8bf28eb 24106 * if(true) {
Marko Mikulicic 0:c0ecb8bf28eb 24107 * }
Marko Mikulicic 0:c0ecb8bf28eb 24108 * if(false) {
Marko Mikulicic 0:c0ecb8bf28eb 24109 * 2;
Marko Mikulicic 0:c0ecb8bf28eb 24110 * }
Marko Mikulicic 0:c0ecb8bf28eb 24111 * break;
Marko Mikulicic 0:c0ecb8bf28eb 24112 * }
Marko Mikulicic 0:c0ecb8bf28eb 24113 * }
Marko Mikulicic 0:c0ecb8bf28eb 24114 * ----
Marko Mikulicic 0:c0ecb8bf28eb 24115 */
Marko Mikulicic 0:c0ecb8bf28eb 24116
Marko Mikulicic 0:c0ecb8bf28eb 24117 static const enum ast_tag assign_ast_map[] = {
Marko Mikulicic 0:c0ecb8bf28eb 24118 AST_REM, AST_MUL, AST_DIV, AST_XOR, AST_ADD, AST_SUB,
Marko Mikulicic 0:c0ecb8bf28eb 24119 AST_OR, AST_AND, AST_LSHIFT, AST_RSHIFT, AST_URSHIFT};
Marko Mikulicic 0:c0ecb8bf28eb 24120
Marko Mikulicic 0:c0ecb8bf28eb 24121 #ifdef V7_BCODE_DUMP
Marko Mikulicic 0:c0ecb8bf28eb 24122 extern void dump_bcode(struct v7 *v7, FILE *f, struct bcode *bcode);
Marko Mikulicic 0:c0ecb8bf28eb 24123 #endif
Marko Mikulicic 0:c0ecb8bf28eb 24124
Marko Mikulicic 0:c0ecb8bf28eb 24125 V7_PRIVATE enum v7_err compile_expr_builder(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 24126 struct ast *a, ast_off_t *ppos);
Marko Mikulicic 0:c0ecb8bf28eb 24127
Marko Mikulicic 0:c0ecb8bf28eb 24128 V7_PRIVATE enum v7_err compile_function(struct v7 *v7, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 24129 ast_off_t *ppos, struct bcode *bcode);
Marko Mikulicic 0:c0ecb8bf28eb 24130
Marko Mikulicic 0:c0ecb8bf28eb 24131 V7_PRIVATE enum v7_err binary_op(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 24132 enum ast_tag tag) {
Marko Mikulicic 0:c0ecb8bf28eb 24133 uint8_t op;
Marko Mikulicic 0:c0ecb8bf28eb 24134 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 24135 struct v7 *v7 = bbuilder->v7;
Marko Mikulicic 0:c0ecb8bf28eb 24136
Marko Mikulicic 0:c0ecb8bf28eb 24137 switch (tag) {
Marko Mikulicic 0:c0ecb8bf28eb 24138 case AST_ADD:
Marko Mikulicic 0:c0ecb8bf28eb 24139 op = OP_ADD;
Marko Mikulicic 0:c0ecb8bf28eb 24140 break;
Marko Mikulicic 0:c0ecb8bf28eb 24141 case AST_SUB:
Marko Mikulicic 0:c0ecb8bf28eb 24142 op = OP_SUB;
Marko Mikulicic 0:c0ecb8bf28eb 24143 break;
Marko Mikulicic 0:c0ecb8bf28eb 24144 case AST_REM:
Marko Mikulicic 0:c0ecb8bf28eb 24145 op = OP_REM;
Marko Mikulicic 0:c0ecb8bf28eb 24146 break;
Marko Mikulicic 0:c0ecb8bf28eb 24147 case AST_MUL:
Marko Mikulicic 0:c0ecb8bf28eb 24148 op = OP_MUL;
Marko Mikulicic 0:c0ecb8bf28eb 24149 break;
Marko Mikulicic 0:c0ecb8bf28eb 24150 case AST_DIV:
Marko Mikulicic 0:c0ecb8bf28eb 24151 op = OP_DIV;
Marko Mikulicic 0:c0ecb8bf28eb 24152 break;
Marko Mikulicic 0:c0ecb8bf28eb 24153 case AST_LSHIFT:
Marko Mikulicic 0:c0ecb8bf28eb 24154 op = OP_LSHIFT;
Marko Mikulicic 0:c0ecb8bf28eb 24155 break;
Marko Mikulicic 0:c0ecb8bf28eb 24156 case AST_RSHIFT:
Marko Mikulicic 0:c0ecb8bf28eb 24157 op = OP_RSHIFT;
Marko Mikulicic 0:c0ecb8bf28eb 24158 break;
Marko Mikulicic 0:c0ecb8bf28eb 24159 case AST_URSHIFT:
Marko Mikulicic 0:c0ecb8bf28eb 24160 op = OP_URSHIFT;
Marko Mikulicic 0:c0ecb8bf28eb 24161 break;
Marko Mikulicic 0:c0ecb8bf28eb 24162 case AST_OR:
Marko Mikulicic 0:c0ecb8bf28eb 24163 op = OP_OR;
Marko Mikulicic 0:c0ecb8bf28eb 24164 break;
Marko Mikulicic 0:c0ecb8bf28eb 24165 case AST_XOR:
Marko Mikulicic 0:c0ecb8bf28eb 24166 op = OP_XOR;
Marko Mikulicic 0:c0ecb8bf28eb 24167 break;
Marko Mikulicic 0:c0ecb8bf28eb 24168 case AST_AND:
Marko Mikulicic 0:c0ecb8bf28eb 24169 op = OP_AND;
Marko Mikulicic 0:c0ecb8bf28eb 24170 break;
Marko Mikulicic 0:c0ecb8bf28eb 24171 case AST_EQ_EQ:
Marko Mikulicic 0:c0ecb8bf28eb 24172 op = OP_EQ_EQ;
Marko Mikulicic 0:c0ecb8bf28eb 24173 break;
Marko Mikulicic 0:c0ecb8bf28eb 24174 case AST_EQ:
Marko Mikulicic 0:c0ecb8bf28eb 24175 op = OP_EQ;
Marko Mikulicic 0:c0ecb8bf28eb 24176 break;
Marko Mikulicic 0:c0ecb8bf28eb 24177 case AST_NE:
Marko Mikulicic 0:c0ecb8bf28eb 24178 op = OP_NE;
Marko Mikulicic 0:c0ecb8bf28eb 24179 break;
Marko Mikulicic 0:c0ecb8bf28eb 24180 case AST_NE_NE:
Marko Mikulicic 0:c0ecb8bf28eb 24181 op = OP_NE_NE;
Marko Mikulicic 0:c0ecb8bf28eb 24182 break;
Marko Mikulicic 0:c0ecb8bf28eb 24183 case AST_LT:
Marko Mikulicic 0:c0ecb8bf28eb 24184 op = OP_LT;
Marko Mikulicic 0:c0ecb8bf28eb 24185 break;
Marko Mikulicic 0:c0ecb8bf28eb 24186 case AST_LE:
Marko Mikulicic 0:c0ecb8bf28eb 24187 op = OP_LE;
Marko Mikulicic 0:c0ecb8bf28eb 24188 break;
Marko Mikulicic 0:c0ecb8bf28eb 24189 case AST_GT:
Marko Mikulicic 0:c0ecb8bf28eb 24190 op = OP_GT;
Marko Mikulicic 0:c0ecb8bf28eb 24191 break;
Marko Mikulicic 0:c0ecb8bf28eb 24192 case AST_GE:
Marko Mikulicic 0:c0ecb8bf28eb 24193 op = OP_GE;
Marko Mikulicic 0:c0ecb8bf28eb 24194 break;
Marko Mikulicic 0:c0ecb8bf28eb 24195 case AST_INSTANCEOF:
Marko Mikulicic 0:c0ecb8bf28eb 24196 op = OP_INSTANCEOF;
Marko Mikulicic 0:c0ecb8bf28eb 24197 break;
Marko Mikulicic 0:c0ecb8bf28eb 24198 default:
Marko Mikulicic 0:c0ecb8bf28eb 24199 rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "unknown binary ast node");
Marko Mikulicic 0:c0ecb8bf28eb 24200 V7_THROW(V7_SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 24201 }
Marko Mikulicic 0:c0ecb8bf28eb 24202 bcode_op(bbuilder, op);
Marko Mikulicic 0:c0ecb8bf28eb 24203 clean:
Marko Mikulicic 0:c0ecb8bf28eb 24204 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 24205 }
Marko Mikulicic 0:c0ecb8bf28eb 24206
Marko Mikulicic 0:c0ecb8bf28eb 24207 V7_PRIVATE enum v7_err compile_binary(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 24208 struct ast *a, ast_off_t *ppos,
Marko Mikulicic 0:c0ecb8bf28eb 24209 enum ast_tag tag) {
Marko Mikulicic 0:c0ecb8bf28eb 24210 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 24211 struct v7 *v7 = bbuilder->v7;
Marko Mikulicic 0:c0ecb8bf28eb 24212 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24213 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24214
Marko Mikulicic 0:c0ecb8bf28eb 24215 V7_TRY(binary_op(bbuilder, tag));
Marko Mikulicic 0:c0ecb8bf28eb 24216 clean:
Marko Mikulicic 0:c0ecb8bf28eb 24217 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 24218 }
Marko Mikulicic 0:c0ecb8bf28eb 24219
Marko Mikulicic 0:c0ecb8bf28eb 24220 /*
Marko Mikulicic 0:c0ecb8bf28eb 24221 * `pos` should be an offset of the byte right after a tag
Marko Mikulicic 0:c0ecb8bf28eb 24222 */
Marko Mikulicic 0:c0ecb8bf28eb 24223 static lit_t string_lit(struct bcode_builder *bbuilder, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 24224 ast_off_t pos) {
Marko Mikulicic 0:c0ecb8bf28eb 24225 size_t i = 0, name_len;
Marko Mikulicic 0:c0ecb8bf28eb 24226 val_t v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 24227 struct mbuf *m = &bbuilder->lit;
Marko Mikulicic 0:c0ecb8bf28eb 24228 char *name = ast_get_inlined_data(a, pos, &name_len);
Marko Mikulicic 0:c0ecb8bf28eb 24229
Marko Mikulicic 0:c0ecb8bf28eb 24230 /* temp disabled because of short lits */
Marko Mikulicic 0:c0ecb8bf28eb 24231 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 24232 for (i = 0; i < m->len / sizeof(val_t); i++) {
Marko Mikulicic 0:c0ecb8bf28eb 24233 v = ((val_t *) m->buf)[i];
Marko Mikulicic 0:c0ecb8bf28eb 24234 if (v7_is_string(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 24235 size_t l;
Marko Mikulicic 0:c0ecb8bf28eb 24236 const char *s = v7_get_string(bbuilder->v7, &v, &l);
Marko Mikulicic 0:c0ecb8bf28eb 24237 if (name_len == l && memcmp(name, s, name_len) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 24238 lit_t res;
Marko Mikulicic 0:c0ecb8bf28eb 24239 memset(&res, 0, sizeof(res));
Marko Mikulicic 0:c0ecb8bf28eb 24240 res.idx = i + bcode_max_inline_type_tag;
Marko Mikulicic 0:c0ecb8bf28eb 24241 return res;
Marko Mikulicic 0:c0ecb8bf28eb 24242 }
Marko Mikulicic 0:c0ecb8bf28eb 24243 }
Marko Mikulicic 0:c0ecb8bf28eb 24244 }
Marko Mikulicic 0:c0ecb8bf28eb 24245 #else
Marko Mikulicic 0:c0ecb8bf28eb 24246 (void) i;
Marko Mikulicic 0:c0ecb8bf28eb 24247 (void) v;
Marko Mikulicic 0:c0ecb8bf28eb 24248 (void) m;
Marko Mikulicic 0:c0ecb8bf28eb 24249 #endif
Marko Mikulicic 0:c0ecb8bf28eb 24250 return bcode_add_lit(bbuilder, v7_mk_string(bbuilder->v7, name, name_len, 1));
Marko Mikulicic 0:c0ecb8bf28eb 24251 }
Marko Mikulicic 0:c0ecb8bf28eb 24252
Marko Mikulicic 0:c0ecb8bf28eb 24253 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 24254 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 24255 static enum v7_err regexp_lit(struct bcode_builder *bbuilder, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 24256 ast_off_t pos, lit_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 24257 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 24258 size_t name_len;
Marko Mikulicic 0:c0ecb8bf28eb 24259 char *p;
Marko Mikulicic 0:c0ecb8bf28eb 24260 char *name = ast_get_inlined_data(a, pos, &name_len);
Marko Mikulicic 0:c0ecb8bf28eb 24261 val_t tmp = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 24262 struct v7 *v7 = bbuilder->v7;
Marko Mikulicic 0:c0ecb8bf28eb 24263
Marko Mikulicic 0:c0ecb8bf28eb 24264 for (p = name + name_len - 1; *p != '/';) p--;
Marko Mikulicic 0:c0ecb8bf28eb 24265
Marko Mikulicic 0:c0ecb8bf28eb 24266 V7_TRY(v7_mk_regexp(bbuilder->v7, name + 1, p - (name + 1), p + 1,
Marko Mikulicic 0:c0ecb8bf28eb 24267 (name + name_len) - p - 1, &tmp));
Marko Mikulicic 0:c0ecb8bf28eb 24268
Marko Mikulicic 0:c0ecb8bf28eb 24269 *res = bcode_add_lit(bbuilder, tmp);
Marko Mikulicic 0:c0ecb8bf28eb 24270
Marko Mikulicic 0:c0ecb8bf28eb 24271 clean:
Marko Mikulicic 0:c0ecb8bf28eb 24272 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 24273 }
Marko Mikulicic 0:c0ecb8bf28eb 24274 #endif
Marko Mikulicic 0:c0ecb8bf28eb 24275
Marko Mikulicic 0:c0ecb8bf28eb 24276 #ifndef V7_DISABLE_LINE_NUMBERS
Marko Mikulicic 0:c0ecb8bf28eb 24277 static void append_lineno_if_changed(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 24278 struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 24279 int line_no) {
Marko Mikulicic 0:c0ecb8bf28eb 24280 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 24281 if (line_no != 0 && line_no != v7->line_no) {
Marko Mikulicic 0:c0ecb8bf28eb 24282 v7->line_no = line_no;
Marko Mikulicic 0:c0ecb8bf28eb 24283 bcode_append_lineno(bbuilder, line_no);
Marko Mikulicic 0:c0ecb8bf28eb 24284 }
Marko Mikulicic 0:c0ecb8bf28eb 24285 }
Marko Mikulicic 0:c0ecb8bf28eb 24286 #else
Marko Mikulicic 0:c0ecb8bf28eb 24287 static void append_lineno_if_changed(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 24288 struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 24289 int line_no) {
Marko Mikulicic 0:c0ecb8bf28eb 24290 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 24291 (void) bbuilder;
Marko Mikulicic 0:c0ecb8bf28eb 24292 (void) line_no;
Marko Mikulicic 0:c0ecb8bf28eb 24293 }
Marko Mikulicic 0:c0ecb8bf28eb 24294 #endif
Marko Mikulicic 0:c0ecb8bf28eb 24295
Marko Mikulicic 0:c0ecb8bf28eb 24296 static enum ast_tag fetch_tag(struct v7 *v7, struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 24297 struct ast *a, ast_off_t *ppos,
Marko Mikulicic 0:c0ecb8bf28eb 24298 ast_off_t *ppos_after_tag) {
Marko Mikulicic 0:c0ecb8bf28eb 24299 enum ast_tag ret = ast_fetch_tag(a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 24300 int line_no = ast_get_line_no(a, *ppos);
Marko Mikulicic 0:c0ecb8bf28eb 24301 append_lineno_if_changed(v7, bbuilder, line_no);
Marko Mikulicic 0:c0ecb8bf28eb 24302 if (ppos_after_tag != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 24303 *ppos_after_tag = *ppos;
Marko Mikulicic 0:c0ecb8bf28eb 24304 }
Marko Mikulicic 0:c0ecb8bf28eb 24305 ast_move_to_children(a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 24306 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 24307 }
Marko Mikulicic 0:c0ecb8bf28eb 24308
Marko Mikulicic 0:c0ecb8bf28eb 24309 /*
Marko Mikulicic 0:c0ecb8bf28eb 24310 * a++ and a-- need to ignore the updated value.
Marko Mikulicic 0:c0ecb8bf28eb 24311 *
Marko Mikulicic 0:c0ecb8bf28eb 24312 * Call this before updating the lhs.
Marko Mikulicic 0:c0ecb8bf28eb 24313 */
Marko Mikulicic 0:c0ecb8bf28eb 24314 static void fixup_post_op(struct bcode_builder *bbuilder, enum ast_tag tag) {
Marko Mikulicic 0:c0ecb8bf28eb 24315 if (tag == AST_POSTINC || tag == AST_POSTDEC) {
Marko Mikulicic 0:c0ecb8bf28eb 24316 bcode_op(bbuilder, OP_UNSTASH);
Marko Mikulicic 0:c0ecb8bf28eb 24317 }
Marko Mikulicic 0:c0ecb8bf28eb 24318 }
Marko Mikulicic 0:c0ecb8bf28eb 24319
Marko Mikulicic 0:c0ecb8bf28eb 24320 /*
Marko Mikulicic 0:c0ecb8bf28eb 24321 * evaluate rhs expression.
Marko Mikulicic 0:c0ecb8bf28eb 24322 * ++a and a++ are equivalent to a+=1
Marko Mikulicic 0:c0ecb8bf28eb 24323 */
Marko Mikulicic 0:c0ecb8bf28eb 24324 static enum v7_err eval_assign_rhs(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 24325 struct ast *a, ast_off_t *ppos,
Marko Mikulicic 0:c0ecb8bf28eb 24326 enum ast_tag tag) {
Marko Mikulicic 0:c0ecb8bf28eb 24327 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 24328 struct v7 *v7 = bbuilder->v7;
Marko Mikulicic 0:c0ecb8bf28eb 24329
Marko Mikulicic 0:c0ecb8bf28eb 24330 /* a++ and a-- need to preserve initial value. */
Marko Mikulicic 0:c0ecb8bf28eb 24331 if (tag == AST_POSTINC || tag == AST_POSTDEC) {
Marko Mikulicic 0:c0ecb8bf28eb 24332 bcode_op(bbuilder, OP_STASH);
Marko Mikulicic 0:c0ecb8bf28eb 24333 }
Marko Mikulicic 0:c0ecb8bf28eb 24334 if (tag >= AST_PREINC && tag <= AST_POSTDEC) {
Marko Mikulicic 0:c0ecb8bf28eb 24335 bcode_op(bbuilder, OP_PUSH_ONE);
Marko Mikulicic 0:c0ecb8bf28eb 24336 } else {
Marko Mikulicic 0:c0ecb8bf28eb 24337 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24338 }
Marko Mikulicic 0:c0ecb8bf28eb 24339
Marko Mikulicic 0:c0ecb8bf28eb 24340 switch (tag) {
Marko Mikulicic 0:c0ecb8bf28eb 24341 case AST_PREINC:
Marko Mikulicic 0:c0ecb8bf28eb 24342 case AST_POSTINC:
Marko Mikulicic 0:c0ecb8bf28eb 24343 bcode_op(bbuilder, OP_ADD);
Marko Mikulicic 0:c0ecb8bf28eb 24344 break;
Marko Mikulicic 0:c0ecb8bf28eb 24345 case AST_PREDEC:
Marko Mikulicic 0:c0ecb8bf28eb 24346 case AST_POSTDEC:
Marko Mikulicic 0:c0ecb8bf28eb 24347 bcode_op(bbuilder, OP_SUB);
Marko Mikulicic 0:c0ecb8bf28eb 24348 break;
Marko Mikulicic 0:c0ecb8bf28eb 24349 case AST_ASSIGN:
Marko Mikulicic 0:c0ecb8bf28eb 24350 /* no operation */
Marko Mikulicic 0:c0ecb8bf28eb 24351 break;
Marko Mikulicic 0:c0ecb8bf28eb 24352 default:
Marko Mikulicic 0:c0ecb8bf28eb 24353 binary_op(bbuilder, assign_ast_map[tag - AST_ASSIGN - 1]);
Marko Mikulicic 0:c0ecb8bf28eb 24354 }
Marko Mikulicic 0:c0ecb8bf28eb 24355
Marko Mikulicic 0:c0ecb8bf28eb 24356 clean:
Marko Mikulicic 0:c0ecb8bf28eb 24357 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 24358 }
Marko Mikulicic 0:c0ecb8bf28eb 24359
Marko Mikulicic 0:c0ecb8bf28eb 24360 static enum v7_err compile_assign(struct bcode_builder *bbuilder, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 24361 ast_off_t *ppos, enum ast_tag tag) {
Marko Mikulicic 0:c0ecb8bf28eb 24362 lit_t lit;
Marko Mikulicic 0:c0ecb8bf28eb 24363 enum ast_tag ntag;
Marko Mikulicic 0:c0ecb8bf28eb 24364 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 24365 struct v7 *v7 = bbuilder->v7;
Marko Mikulicic 0:c0ecb8bf28eb 24366 ast_off_t pos_after_tag;
Marko Mikulicic 0:c0ecb8bf28eb 24367
Marko Mikulicic 0:c0ecb8bf28eb 24368 ntag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 24369
Marko Mikulicic 0:c0ecb8bf28eb 24370 switch (ntag) {
Marko Mikulicic 0:c0ecb8bf28eb 24371 case AST_IDENT:
Marko Mikulicic 0:c0ecb8bf28eb 24372 lit = string_lit(bbuilder, a, pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 24373 if (tag != AST_ASSIGN) {
Marko Mikulicic 0:c0ecb8bf28eb 24374 bcode_op_lit(bbuilder, OP_GET_VAR, lit);
Marko Mikulicic 0:c0ecb8bf28eb 24375 }
Marko Mikulicic 0:c0ecb8bf28eb 24376
Marko Mikulicic 0:c0ecb8bf28eb 24377 V7_TRY(eval_assign_rhs(bbuilder, a, ppos, tag));
Marko Mikulicic 0:c0ecb8bf28eb 24378 bcode_op_lit(bbuilder, OP_SET_VAR, lit);
Marko Mikulicic 0:c0ecb8bf28eb 24379
Marko Mikulicic 0:c0ecb8bf28eb 24380 fixup_post_op(bbuilder, tag);
Marko Mikulicic 0:c0ecb8bf28eb 24381 break;
Marko Mikulicic 0:c0ecb8bf28eb 24382 case AST_MEMBER:
Marko Mikulicic 0:c0ecb8bf28eb 24383 case AST_INDEX:
Marko Mikulicic 0:c0ecb8bf28eb 24384 switch (ntag) {
Marko Mikulicic 0:c0ecb8bf28eb 24385 case AST_MEMBER:
Marko Mikulicic 0:c0ecb8bf28eb 24386 lit = string_lit(bbuilder, a, pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 24387 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24388 bcode_push_lit(bbuilder, lit);
Marko Mikulicic 0:c0ecb8bf28eb 24389 break;
Marko Mikulicic 0:c0ecb8bf28eb 24390 case AST_INDEX:
Marko Mikulicic 0:c0ecb8bf28eb 24391 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24392 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24393 break;
Marko Mikulicic 0:c0ecb8bf28eb 24394 default:
Marko Mikulicic 0:c0ecb8bf28eb 24395 /* unreachable, compilers are dumb */
Marko Mikulicic 0:c0ecb8bf28eb 24396 V7_THROW(V7_SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 24397 }
Marko Mikulicic 0:c0ecb8bf28eb 24398 if (tag != AST_ASSIGN) {
Marko Mikulicic 0:c0ecb8bf28eb 24399 bcode_op(bbuilder, OP_2DUP);
Marko Mikulicic 0:c0ecb8bf28eb 24400 bcode_op(bbuilder, OP_GET);
Marko Mikulicic 0:c0ecb8bf28eb 24401 }
Marko Mikulicic 0:c0ecb8bf28eb 24402
Marko Mikulicic 0:c0ecb8bf28eb 24403 V7_TRY(eval_assign_rhs(bbuilder, a, ppos, tag));
Marko Mikulicic 0:c0ecb8bf28eb 24404 bcode_op(bbuilder, OP_SET);
Marko Mikulicic 0:c0ecb8bf28eb 24405
Marko Mikulicic 0:c0ecb8bf28eb 24406 fixup_post_op(bbuilder, tag);
Marko Mikulicic 0:c0ecb8bf28eb 24407 break;
Marko Mikulicic 0:c0ecb8bf28eb 24408 default:
Marko Mikulicic 0:c0ecb8bf28eb 24409 /* We end up here on expressions like `1 = 2;`, it's a ReferenceError */
Marko Mikulicic 0:c0ecb8bf28eb 24410 rcode = v7_throwf(bbuilder->v7, REFERENCE_ERROR, "unexpected ast node");
Marko Mikulicic 0:c0ecb8bf28eb 24411 V7_THROW(V7_SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 24412 }
Marko Mikulicic 0:c0ecb8bf28eb 24413 clean:
Marko Mikulicic 0:c0ecb8bf28eb 24414 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 24415 }
Marko Mikulicic 0:c0ecb8bf28eb 24416
Marko Mikulicic 0:c0ecb8bf28eb 24417 /*
Marko Mikulicic 0:c0ecb8bf28eb 24418 * Walks through all declarations (`var` and `function`) in the current scope,
Marko Mikulicic 0:c0ecb8bf28eb 24419 * and adds names of all of them to `bcode->ops`. Additionally, `function`
Marko Mikulicic 0:c0ecb8bf28eb 24420 * declarations are compiled right here, since they're hoisted in JS.
Marko Mikulicic 0:c0ecb8bf28eb 24421 */
Marko Mikulicic 0:c0ecb8bf28eb 24422 static enum v7_err compile_local_vars(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 24423 struct ast *a, ast_off_t start,
Marko Mikulicic 0:c0ecb8bf28eb 24424 ast_off_t fvar) {
Marko Mikulicic 0:c0ecb8bf28eb 24425 ast_off_t next, fvar_end;
Marko Mikulicic 0:c0ecb8bf28eb 24426 char *name;
Marko Mikulicic 0:c0ecb8bf28eb 24427 size_t name_len;
Marko Mikulicic 0:c0ecb8bf28eb 24428 lit_t lit;
Marko Mikulicic 0:c0ecb8bf28eb 24429 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 24430 struct v7 *v7 = bbuilder->v7;
Marko Mikulicic 0:c0ecb8bf28eb 24431 size_t names_end = 0;
Marko Mikulicic 0:c0ecb8bf28eb 24432 ast_off_t pos_after_tag;
Marko Mikulicic 0:c0ecb8bf28eb 24433
Marko Mikulicic 0:c0ecb8bf28eb 24434 /* calculate `names_end`: offset at which names in `bcode->ops` end */
Marko Mikulicic 0:c0ecb8bf28eb 24435 names_end =
Marko Mikulicic 0:c0ecb8bf28eb 24436 (size_t)(bcode_end_names(bbuilder->ops.buf, bbuilder->bcode->names_cnt) -
Marko Mikulicic 0:c0ecb8bf28eb 24437 bbuilder->ops.buf);
Marko Mikulicic 0:c0ecb8bf28eb 24438
Marko Mikulicic 0:c0ecb8bf28eb 24439 if (fvar != start) {
Marko Mikulicic 0:c0ecb8bf28eb 24440 /* iterate all `AST_VAR`s in the current scope */
Marko Mikulicic 0:c0ecb8bf28eb 24441 do {
Marko Mikulicic 0:c0ecb8bf28eb 24442 V7_CHECK_INTERNAL(fetch_tag(v7, bbuilder, a, &fvar, &pos_after_tag) ==
Marko Mikulicic 0:c0ecb8bf28eb 24443 AST_VAR);
Marko Mikulicic 0:c0ecb8bf28eb 24444
Marko Mikulicic 0:c0ecb8bf28eb 24445 next = ast_get_skip(a, pos_after_tag, AST_VAR_NEXT_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 24446 if (next == pos_after_tag) {
Marko Mikulicic 0:c0ecb8bf28eb 24447 next = 0;
Marko Mikulicic 0:c0ecb8bf28eb 24448 }
Marko Mikulicic 0:c0ecb8bf28eb 24449
Marko Mikulicic 0:c0ecb8bf28eb 24450 fvar_end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 24451
Marko Mikulicic 0:c0ecb8bf28eb 24452 /*
Marko Mikulicic 0:c0ecb8bf28eb 24453 * iterate all `AST_VAR_DECL`s and `AST_FUNC_DECL`s in the current
Marko Mikulicic 0:c0ecb8bf28eb 24454 * `AST_VAR`
Marko Mikulicic 0:c0ecb8bf28eb 24455 */
Marko Mikulicic 0:c0ecb8bf28eb 24456 while (fvar < fvar_end) {
Marko Mikulicic 0:c0ecb8bf28eb 24457 enum ast_tag tag = fetch_tag(v7, bbuilder, a, &fvar, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 24458 V7_CHECK_INTERNAL(tag == AST_VAR_DECL || tag == AST_FUNC_DECL);
Marko Mikulicic 0:c0ecb8bf28eb 24459 name = ast_get_inlined_data(a, pos_after_tag, &name_len);
Marko Mikulicic 0:c0ecb8bf28eb 24460 if (tag == AST_VAR_DECL) {
Marko Mikulicic 0:c0ecb8bf28eb 24461 /*
Marko Mikulicic 0:c0ecb8bf28eb 24462 * it's a `var` declaration, so, skip the value for now, it'll be set
Marko Mikulicic 0:c0ecb8bf28eb 24463 * to `undefined` initially
Marko Mikulicic 0:c0ecb8bf28eb 24464 */
Marko Mikulicic 0:c0ecb8bf28eb 24465 ast_skip_tree(a, &fvar);
Marko Mikulicic 0:c0ecb8bf28eb 24466 } else {
Marko Mikulicic 0:c0ecb8bf28eb 24467 /*
Marko Mikulicic 0:c0ecb8bf28eb 24468 * tag is an AST_FUNC_DECL: since functions in JS are hoisted,
Marko Mikulicic 0:c0ecb8bf28eb 24469 * we compile it and put `OP_SET_VAR` directly here
Marko Mikulicic 0:c0ecb8bf28eb 24470 */
Marko Mikulicic 0:c0ecb8bf28eb 24471 lit = string_lit(bbuilder, a, pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 24472 V7_TRY(compile_expr_builder(bbuilder, a, &fvar));
Marko Mikulicic 0:c0ecb8bf28eb 24473 bcode_op_lit(bbuilder, OP_SET_VAR, lit);
Marko Mikulicic 0:c0ecb8bf28eb 24474
Marko Mikulicic 0:c0ecb8bf28eb 24475 /* function declarations are stack-neutral */
Marko Mikulicic 0:c0ecb8bf28eb 24476 bcode_op(bbuilder, OP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 24477 /*
Marko Mikulicic 0:c0ecb8bf28eb 24478 * Note: the `is_stack_neutral` flag will be set by `compile_stmt`
Marko Mikulicic 0:c0ecb8bf28eb 24479 * later, when it encounters `AST_FUNC_DECL` again.
Marko Mikulicic 0:c0ecb8bf28eb 24480 */
Marko Mikulicic 0:c0ecb8bf28eb 24481 }
Marko Mikulicic 0:c0ecb8bf28eb 24482 V7_TRY(bcode_add_name(bbuilder, name, name_len, &names_end));
Marko Mikulicic 0:c0ecb8bf28eb 24483 }
Marko Mikulicic 0:c0ecb8bf28eb 24484
Marko Mikulicic 0:c0ecb8bf28eb 24485 if (next > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 24486 fvar = next - 1;
Marko Mikulicic 0:c0ecb8bf28eb 24487 }
Marko Mikulicic 0:c0ecb8bf28eb 24488
Marko Mikulicic 0:c0ecb8bf28eb 24489 } while (next != 0);
Marko Mikulicic 0:c0ecb8bf28eb 24490 }
Marko Mikulicic 0:c0ecb8bf28eb 24491
Marko Mikulicic 0:c0ecb8bf28eb 24492 clean:
Marko Mikulicic 0:c0ecb8bf28eb 24493 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 24494 }
Marko Mikulicic 0:c0ecb8bf28eb 24495
Marko Mikulicic 0:c0ecb8bf28eb 24496 /*
Marko Mikulicic 0:c0ecb8bf28eb 24497 * Just like `compile_expr_builder`, but it takes additional argument:
Marko Mikulicic 0:c0ecb8bf28eb 24498 *`for_call`.
Marko Mikulicic 0:c0ecb8bf28eb 24499 * If it's non-zero, the stack is additionally populated with `this` value
Marko Mikulicic 0:c0ecb8bf28eb 24500 * for call.
Marko Mikulicic 0:c0ecb8bf28eb 24501 *
Marko Mikulicic 0:c0ecb8bf28eb 24502 * If there is a refinement (a dot, or a subscript), then it'll be the
Marko Mikulicic 0:c0ecb8bf28eb 24503 * appropriate object. Otherwise, it's `undefined`.
Marko Mikulicic 0:c0ecb8bf28eb 24504 *
Marko Mikulicic 0:c0ecb8bf28eb 24505 * In non-strict mode, `undefined` will be changed to Global Object at runtime,
Marko Mikulicic 0:c0ecb8bf28eb 24506 * see `OP_CALL` handling in `eval_bcode()`.
Marko Mikulicic 0:c0ecb8bf28eb 24507 */
Marko Mikulicic 0:c0ecb8bf28eb 24508 V7_PRIVATE enum v7_err compile_expr_ext(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 24509 struct ast *a, ast_off_t *ppos,
Marko Mikulicic 0:c0ecb8bf28eb 24510 uint8_t for_call) {
Marko Mikulicic 0:c0ecb8bf28eb 24511 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 24512 struct v7 *v7 = bbuilder->v7;
Marko Mikulicic 0:c0ecb8bf28eb 24513 ast_off_t pos_after_tag;
Marko Mikulicic 0:c0ecb8bf28eb 24514 enum ast_tag tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 24515
Marko Mikulicic 0:c0ecb8bf28eb 24516 switch (tag) {
Marko Mikulicic 0:c0ecb8bf28eb 24517 case AST_MEMBER: {
Marko Mikulicic 0:c0ecb8bf28eb 24518 lit_t lit = string_lit(bbuilder, a, pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 24519 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24520 if (for_call) {
Marko Mikulicic 0:c0ecb8bf28eb 24521 /* current TOS will be used as `this` */
Marko Mikulicic 0:c0ecb8bf28eb 24522 bcode_op(bbuilder, OP_DUP);
Marko Mikulicic 0:c0ecb8bf28eb 24523 }
Marko Mikulicic 0:c0ecb8bf28eb 24524 bcode_push_lit(bbuilder, lit);
Marko Mikulicic 0:c0ecb8bf28eb 24525 bcode_op(bbuilder, OP_GET);
Marko Mikulicic 0:c0ecb8bf28eb 24526 break;
Marko Mikulicic 0:c0ecb8bf28eb 24527 }
Marko Mikulicic 0:c0ecb8bf28eb 24528
Marko Mikulicic 0:c0ecb8bf28eb 24529 case AST_INDEX:
Marko Mikulicic 0:c0ecb8bf28eb 24530 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24531 if (for_call) {
Marko Mikulicic 0:c0ecb8bf28eb 24532 /* current TOS will be used as `this` */
Marko Mikulicic 0:c0ecb8bf28eb 24533 bcode_op(bbuilder, OP_DUP);
Marko Mikulicic 0:c0ecb8bf28eb 24534 }
Marko Mikulicic 0:c0ecb8bf28eb 24535 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24536 bcode_op(bbuilder, OP_GET);
Marko Mikulicic 0:c0ecb8bf28eb 24537 break;
Marko Mikulicic 0:c0ecb8bf28eb 24538
Marko Mikulicic 0:c0ecb8bf28eb 24539 default:
Marko Mikulicic 0:c0ecb8bf28eb 24540 if (for_call) {
Marko Mikulicic 0:c0ecb8bf28eb 24541 /*
Marko Mikulicic 0:c0ecb8bf28eb 24542 * `this` will be an `undefined` (but it may change to Global Object
Marko Mikulicic 0:c0ecb8bf28eb 24543 * at runtime)
Marko Mikulicic 0:c0ecb8bf28eb 24544 */
Marko Mikulicic 0:c0ecb8bf28eb 24545 bcode_op(bbuilder, OP_PUSH_UNDEFINED);
Marko Mikulicic 0:c0ecb8bf28eb 24546 }
Marko Mikulicic 0:c0ecb8bf28eb 24547 *ppos = pos_after_tag - 1;
Marko Mikulicic 0:c0ecb8bf28eb 24548 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24549 break;
Marko Mikulicic 0:c0ecb8bf28eb 24550 }
Marko Mikulicic 0:c0ecb8bf28eb 24551
Marko Mikulicic 0:c0ecb8bf28eb 24552 clean:
Marko Mikulicic 0:c0ecb8bf28eb 24553 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 24554 }
Marko Mikulicic 0:c0ecb8bf28eb 24555
Marko Mikulicic 0:c0ecb8bf28eb 24556 V7_PRIVATE enum v7_err compile_delete(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 24557 struct ast *a, ast_off_t *ppos) {
Marko Mikulicic 0:c0ecb8bf28eb 24558 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 24559 struct v7 *v7 = bbuilder->v7;
Marko Mikulicic 0:c0ecb8bf28eb 24560 ast_off_t pos_after_tag;
Marko Mikulicic 0:c0ecb8bf28eb 24561 enum ast_tag tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 24562
Marko Mikulicic 0:c0ecb8bf28eb 24563 switch (tag) {
Marko Mikulicic 0:c0ecb8bf28eb 24564 case AST_MEMBER: {
Marko Mikulicic 0:c0ecb8bf28eb 24565 /* Delete a specified property of an object */
Marko Mikulicic 0:c0ecb8bf28eb 24566 lit_t lit = string_lit(bbuilder, a, pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 24567 /* put an object to delete property from */
Marko Mikulicic 0:c0ecb8bf28eb 24568 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24569 /* put a property name */
Marko Mikulicic 0:c0ecb8bf28eb 24570 bcode_push_lit(bbuilder, lit);
Marko Mikulicic 0:c0ecb8bf28eb 24571 bcode_op(bbuilder, OP_DELETE);
Marko Mikulicic 0:c0ecb8bf28eb 24572 break;
Marko Mikulicic 0:c0ecb8bf28eb 24573 }
Marko Mikulicic 0:c0ecb8bf28eb 24574
Marko Mikulicic 0:c0ecb8bf28eb 24575 case AST_INDEX:
Marko Mikulicic 0:c0ecb8bf28eb 24576 /* Delete a specified property of an object */
Marko Mikulicic 0:c0ecb8bf28eb 24577 /* put an object to delete property from */
Marko Mikulicic 0:c0ecb8bf28eb 24578 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24579 /* put a property name */
Marko Mikulicic 0:c0ecb8bf28eb 24580 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24581 bcode_op(bbuilder, OP_DELETE);
Marko Mikulicic 0:c0ecb8bf28eb 24582 break;
Marko Mikulicic 0:c0ecb8bf28eb 24583
Marko Mikulicic 0:c0ecb8bf28eb 24584 case AST_IDENT:
Marko Mikulicic 0:c0ecb8bf28eb 24585 /* Delete the scope variable (or throw an error if strict mode) */
Marko Mikulicic 0:c0ecb8bf28eb 24586 if (!bbuilder->bcode->strict_mode) {
Marko Mikulicic 0:c0ecb8bf28eb 24587 /* put a property name */
Marko Mikulicic 0:c0ecb8bf28eb 24588 bcode_push_lit(bbuilder, string_lit(bbuilder, a, pos_after_tag));
Marko Mikulicic 0:c0ecb8bf28eb 24589 bcode_op(bbuilder, OP_DELETE_VAR);
Marko Mikulicic 0:c0ecb8bf28eb 24590 } else {
Marko Mikulicic 0:c0ecb8bf28eb 24591 rcode =
Marko Mikulicic 0:c0ecb8bf28eb 24592 v7_throwf(bbuilder->v7, SYNTAX_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 24593 "Delete of an unqualified identifier in strict mode.");
Marko Mikulicic 0:c0ecb8bf28eb 24594 V7_THROW(V7_SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 24595 }
Marko Mikulicic 0:c0ecb8bf28eb 24596 break;
Marko Mikulicic 0:c0ecb8bf28eb 24597
Marko Mikulicic 0:c0ecb8bf28eb 24598 case AST_UNDEFINED:
Marko Mikulicic 0:c0ecb8bf28eb 24599 /*
Marko Mikulicic 0:c0ecb8bf28eb 24600 * `undefined` should actually be an undeletable property of the Global
Marko Mikulicic 0:c0ecb8bf28eb 24601 * Object, so, trying to delete it just yields `false`
Marko Mikulicic 0:c0ecb8bf28eb 24602 */
Marko Mikulicic 0:c0ecb8bf28eb 24603 bcode_op(bbuilder, OP_PUSH_FALSE);
Marko Mikulicic 0:c0ecb8bf28eb 24604 break;
Marko Mikulicic 0:c0ecb8bf28eb 24605
Marko Mikulicic 0:c0ecb8bf28eb 24606 default:
Marko Mikulicic 0:c0ecb8bf28eb 24607 /*
Marko Mikulicic 0:c0ecb8bf28eb 24608 * For all other cases, we evaluate the expression given to `delete`
Marko Mikulicic 0:c0ecb8bf28eb 24609 * for side effects, then drop the result, and yield `true`
Marko Mikulicic 0:c0ecb8bf28eb 24610 */
Marko Mikulicic 0:c0ecb8bf28eb 24611 *ppos = pos_after_tag - 1;
Marko Mikulicic 0:c0ecb8bf28eb 24612 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24613 bcode_op(bbuilder, OP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 24614 bcode_op(bbuilder, OP_PUSH_TRUE);
Marko Mikulicic 0:c0ecb8bf28eb 24615 break;
Marko Mikulicic 0:c0ecb8bf28eb 24616 }
Marko Mikulicic 0:c0ecb8bf28eb 24617
Marko Mikulicic 0:c0ecb8bf28eb 24618 clean:
Marko Mikulicic 0:c0ecb8bf28eb 24619 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 24620 }
Marko Mikulicic 0:c0ecb8bf28eb 24621
Marko Mikulicic 0:c0ecb8bf28eb 24622 V7_PRIVATE enum v7_err compile_expr_builder(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 24623 struct ast *a, ast_off_t *ppos) {
Marko Mikulicic 0:c0ecb8bf28eb 24624 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 24625 struct v7 *v7 = bbuilder->v7;
Marko Mikulicic 0:c0ecb8bf28eb 24626 ast_off_t pos_after_tag;
Marko Mikulicic 0:c0ecb8bf28eb 24627 enum ast_tag tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 24628
Marko Mikulicic 0:c0ecb8bf28eb 24629 switch (tag) {
Marko Mikulicic 0:c0ecb8bf28eb 24630 case AST_ADD:
Marko Mikulicic 0:c0ecb8bf28eb 24631 case AST_SUB:
Marko Mikulicic 0:c0ecb8bf28eb 24632 case AST_REM:
Marko Mikulicic 0:c0ecb8bf28eb 24633 case AST_MUL:
Marko Mikulicic 0:c0ecb8bf28eb 24634 case AST_DIV:
Marko Mikulicic 0:c0ecb8bf28eb 24635 case AST_LSHIFT:
Marko Mikulicic 0:c0ecb8bf28eb 24636 case AST_RSHIFT:
Marko Mikulicic 0:c0ecb8bf28eb 24637 case AST_URSHIFT:
Marko Mikulicic 0:c0ecb8bf28eb 24638 case AST_OR:
Marko Mikulicic 0:c0ecb8bf28eb 24639 case AST_XOR:
Marko Mikulicic 0:c0ecb8bf28eb 24640 case AST_AND:
Marko Mikulicic 0:c0ecb8bf28eb 24641 case AST_EQ_EQ:
Marko Mikulicic 0:c0ecb8bf28eb 24642 case AST_EQ:
Marko Mikulicic 0:c0ecb8bf28eb 24643 case AST_NE:
Marko Mikulicic 0:c0ecb8bf28eb 24644 case AST_NE_NE:
Marko Mikulicic 0:c0ecb8bf28eb 24645 case AST_LT:
Marko Mikulicic 0:c0ecb8bf28eb 24646 case AST_LE:
Marko Mikulicic 0:c0ecb8bf28eb 24647 case AST_GT:
Marko Mikulicic 0:c0ecb8bf28eb 24648 case AST_GE:
Marko Mikulicic 0:c0ecb8bf28eb 24649 case AST_INSTANCEOF:
Marko Mikulicic 0:c0ecb8bf28eb 24650 V7_TRY(compile_binary(bbuilder, a, ppos, tag));
Marko Mikulicic 0:c0ecb8bf28eb 24651 break;
Marko Mikulicic 0:c0ecb8bf28eb 24652 case AST_LOGICAL_NOT:
Marko Mikulicic 0:c0ecb8bf28eb 24653 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24654 bcode_op(bbuilder, OP_LOGICAL_NOT);
Marko Mikulicic 0:c0ecb8bf28eb 24655 break;
Marko Mikulicic 0:c0ecb8bf28eb 24656 case AST_NOT:
Marko Mikulicic 0:c0ecb8bf28eb 24657 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24658 bcode_op(bbuilder, OP_NOT);
Marko Mikulicic 0:c0ecb8bf28eb 24659 break;
Marko Mikulicic 0:c0ecb8bf28eb 24660 case AST_POSITIVE:
Marko Mikulicic 0:c0ecb8bf28eb 24661 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24662 bcode_op(bbuilder, OP_POS);
Marko Mikulicic 0:c0ecb8bf28eb 24663 break;
Marko Mikulicic 0:c0ecb8bf28eb 24664 case AST_NEGATIVE:
Marko Mikulicic 0:c0ecb8bf28eb 24665 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24666 bcode_op(bbuilder, OP_NEG);
Marko Mikulicic 0:c0ecb8bf28eb 24667 break;
Marko Mikulicic 0:c0ecb8bf28eb 24668 case AST_IDENT:
Marko Mikulicic 0:c0ecb8bf28eb 24669 bcode_op_lit(bbuilder, OP_GET_VAR,
Marko Mikulicic 0:c0ecb8bf28eb 24670 string_lit(bbuilder, a, pos_after_tag));
Marko Mikulicic 0:c0ecb8bf28eb 24671 break;
Marko Mikulicic 0:c0ecb8bf28eb 24672 case AST_MEMBER:
Marko Mikulicic 0:c0ecb8bf28eb 24673 case AST_INDEX:
Marko Mikulicic 0:c0ecb8bf28eb 24674 /*
Marko Mikulicic 0:c0ecb8bf28eb 24675 * These two are handled by the "extended" version of this function,
Marko Mikulicic 0:c0ecb8bf28eb 24676 * since we may need to put `this` value on stack, for "method pattern
Marko Mikulicic 0:c0ecb8bf28eb 24677 * invocation".
Marko Mikulicic 0:c0ecb8bf28eb 24678 *
Marko Mikulicic 0:c0ecb8bf28eb 24679 * First of all, restore starting AST position, and then call extended
Marko Mikulicic 0:c0ecb8bf28eb 24680 * function.
Marko Mikulicic 0:c0ecb8bf28eb 24681 */
Marko Mikulicic 0:c0ecb8bf28eb 24682 *ppos = pos_after_tag - 1;
Marko Mikulicic 0:c0ecb8bf28eb 24683 V7_TRY(compile_expr_ext(bbuilder, a, ppos, 0 /*not for call*/));
Marko Mikulicic 0:c0ecb8bf28eb 24684 break;
Marko Mikulicic 0:c0ecb8bf28eb 24685 case AST_IN:
Marko Mikulicic 0:c0ecb8bf28eb 24686 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24687 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24688 bcode_op(bbuilder, OP_IN);
Marko Mikulicic 0:c0ecb8bf28eb 24689 break;
Marko Mikulicic 0:c0ecb8bf28eb 24690 case AST_TYPEOF: {
Marko Mikulicic 0:c0ecb8bf28eb 24691 ast_off_t lookahead = *ppos;
Marko Mikulicic 0:c0ecb8bf28eb 24692 tag = fetch_tag(v7, bbuilder, a, &lookahead, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 24693 if (tag == AST_IDENT) {
Marko Mikulicic 0:c0ecb8bf28eb 24694 *ppos = lookahead;
Marko Mikulicic 0:c0ecb8bf28eb 24695 bcode_op_lit(bbuilder, OP_SAFE_GET_VAR,
Marko Mikulicic 0:c0ecb8bf28eb 24696 string_lit(bbuilder, a, pos_after_tag));
Marko Mikulicic 0:c0ecb8bf28eb 24697 } else {
Marko Mikulicic 0:c0ecb8bf28eb 24698 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24699 }
Marko Mikulicic 0:c0ecb8bf28eb 24700 bcode_op(bbuilder, OP_TYPEOF);
Marko Mikulicic 0:c0ecb8bf28eb 24701 break;
Marko Mikulicic 0:c0ecb8bf28eb 24702 }
Marko Mikulicic 0:c0ecb8bf28eb 24703 case AST_ASSIGN:
Marko Mikulicic 0:c0ecb8bf28eb 24704 case AST_PREINC:
Marko Mikulicic 0:c0ecb8bf28eb 24705 case AST_PREDEC:
Marko Mikulicic 0:c0ecb8bf28eb 24706 case AST_POSTINC:
Marko Mikulicic 0:c0ecb8bf28eb 24707 case AST_POSTDEC:
Marko Mikulicic 0:c0ecb8bf28eb 24708 case AST_REM_ASSIGN:
Marko Mikulicic 0:c0ecb8bf28eb 24709 case AST_MUL_ASSIGN:
Marko Mikulicic 0:c0ecb8bf28eb 24710 case AST_DIV_ASSIGN:
Marko Mikulicic 0:c0ecb8bf28eb 24711 case AST_XOR_ASSIGN:
Marko Mikulicic 0:c0ecb8bf28eb 24712 case AST_PLUS_ASSIGN:
Marko Mikulicic 0:c0ecb8bf28eb 24713 case AST_MINUS_ASSIGN:
Marko Mikulicic 0:c0ecb8bf28eb 24714 case AST_OR_ASSIGN:
Marko Mikulicic 0:c0ecb8bf28eb 24715 case AST_AND_ASSIGN:
Marko Mikulicic 0:c0ecb8bf28eb 24716 case AST_LSHIFT_ASSIGN:
Marko Mikulicic 0:c0ecb8bf28eb 24717 case AST_RSHIFT_ASSIGN:
Marko Mikulicic 0:c0ecb8bf28eb 24718 case AST_URSHIFT_ASSIGN:
Marko Mikulicic 0:c0ecb8bf28eb 24719 V7_TRY(compile_assign(bbuilder, a, ppos, tag));
Marko Mikulicic 0:c0ecb8bf28eb 24720 break;
Marko Mikulicic 0:c0ecb8bf28eb 24721 case AST_COND: {
Marko Mikulicic 0:c0ecb8bf28eb 24722 /*
Marko Mikulicic 0:c0ecb8bf28eb 24723 * A ? B : C
Marko Mikulicic 0:c0ecb8bf28eb 24724 *
Marko Mikulicic 0:c0ecb8bf28eb 24725 * ->
Marko Mikulicic 0:c0ecb8bf28eb 24726 *
Marko Mikulicic 0:c0ecb8bf28eb 24727 * <A>
Marko Mikulicic 0:c0ecb8bf28eb 24728 * JMP_FALSE false
Marko Mikulicic 0:c0ecb8bf28eb 24729 * <B>
Marko Mikulicic 0:c0ecb8bf28eb 24730 * JMP end
Marko Mikulicic 0:c0ecb8bf28eb 24731 * false:
Marko Mikulicic 0:c0ecb8bf28eb 24732 * <C>
Marko Mikulicic 0:c0ecb8bf28eb 24733 * end:
Marko Mikulicic 0:c0ecb8bf28eb 24734 *
Marko Mikulicic 0:c0ecb8bf28eb 24735 */
Marko Mikulicic 0:c0ecb8bf28eb 24736 bcode_off_t false_label, end_label;
Marko Mikulicic 0:c0ecb8bf28eb 24737 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24738 false_label = bcode_op_target(bbuilder, OP_JMP_FALSE);
Marko Mikulicic 0:c0ecb8bf28eb 24739 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24740 end_label = bcode_op_target(bbuilder, OP_JMP);
Marko Mikulicic 0:c0ecb8bf28eb 24741 bcode_patch_target(bbuilder, false_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 24742 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24743 bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 24744 break;
Marko Mikulicic 0:c0ecb8bf28eb 24745 }
Marko Mikulicic 0:c0ecb8bf28eb 24746 case AST_LOGICAL_OR:
Marko Mikulicic 0:c0ecb8bf28eb 24747 case AST_LOGICAL_AND: {
Marko Mikulicic 0:c0ecb8bf28eb 24748 /*
Marko Mikulicic 0:c0ecb8bf28eb 24749 * A && B
Marko Mikulicic 0:c0ecb8bf28eb 24750 *
Marko Mikulicic 0:c0ecb8bf28eb 24751 * ->
Marko Mikulicic 0:c0ecb8bf28eb 24752 *
Marko Mikulicic 0:c0ecb8bf28eb 24753 * <A>
Marko Mikulicic 0:c0ecb8bf28eb 24754 * JMP_FALSE end
Marko Mikulicic 0:c0ecb8bf28eb 24755 * POP
Marko Mikulicic 0:c0ecb8bf28eb 24756 * <B>
Marko Mikulicic 0:c0ecb8bf28eb 24757 * end:
Marko Mikulicic 0:c0ecb8bf28eb 24758 *
Marko Mikulicic 0:c0ecb8bf28eb 24759 */
Marko Mikulicic 0:c0ecb8bf28eb 24760 bcode_off_t end_label;
Marko Mikulicic 0:c0ecb8bf28eb 24761 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24762 bcode_op(bbuilder, OP_DUP);
Marko Mikulicic 0:c0ecb8bf28eb 24763 end_label = bcode_op_target(
Marko Mikulicic 0:c0ecb8bf28eb 24764 bbuilder, tag == AST_LOGICAL_AND ? OP_JMP_FALSE : OP_JMP_TRUE);
Marko Mikulicic 0:c0ecb8bf28eb 24765 bcode_op(bbuilder, OP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 24766 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24767 bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 24768 break;
Marko Mikulicic 0:c0ecb8bf28eb 24769 }
Marko Mikulicic 0:c0ecb8bf28eb 24770 /*
Marko Mikulicic 0:c0ecb8bf28eb 24771 * A, B, C
Marko Mikulicic 0:c0ecb8bf28eb 24772 *
Marko Mikulicic 0:c0ecb8bf28eb 24773 * ->
Marko Mikulicic 0:c0ecb8bf28eb 24774 *
Marko Mikulicic 0:c0ecb8bf28eb 24775 * <A>
Marko Mikulicic 0:c0ecb8bf28eb 24776 * DROP
Marko Mikulicic 0:c0ecb8bf28eb 24777 * <B>
Marko Mikulicic 0:c0ecb8bf28eb 24778 * DROP
Marko Mikulicic 0:c0ecb8bf28eb 24779 * <C>
Marko Mikulicic 0:c0ecb8bf28eb 24780 */
Marko Mikulicic 0:c0ecb8bf28eb 24781 case AST_SEQ: {
Marko Mikulicic 0:c0ecb8bf28eb 24782 ast_off_t end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 24783 while (*ppos < end) {
Marko Mikulicic 0:c0ecb8bf28eb 24784 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24785 if (*ppos < end) {
Marko Mikulicic 0:c0ecb8bf28eb 24786 bcode_op(bbuilder, OP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 24787 }
Marko Mikulicic 0:c0ecb8bf28eb 24788 }
Marko Mikulicic 0:c0ecb8bf28eb 24789 break;
Marko Mikulicic 0:c0ecb8bf28eb 24790 }
Marko Mikulicic 0:c0ecb8bf28eb 24791 case AST_CALL:
Marko Mikulicic 0:c0ecb8bf28eb 24792 case AST_NEW: {
Marko Mikulicic 0:c0ecb8bf28eb 24793 /*
Marko Mikulicic 0:c0ecb8bf28eb 24794 * f()
Marko Mikulicic 0:c0ecb8bf28eb 24795 *
Marko Mikulicic 0:c0ecb8bf28eb 24796 * ->
Marko Mikulicic 0:c0ecb8bf28eb 24797 *
Marko Mikulicic 0:c0ecb8bf28eb 24798 * PUSH_UNDEFINED (value for `this`)
Marko Mikulicic 0:c0ecb8bf28eb 24799 * GET_VAR "f"
Marko Mikulicic 0:c0ecb8bf28eb 24800 * CHECK_CALL
Marko Mikulicic 0:c0ecb8bf28eb 24801 * CALL 0 args
Marko Mikulicic 0:c0ecb8bf28eb 24802 *
Marko Mikulicic 0:c0ecb8bf28eb 24803 * ---------------
Marko Mikulicic 0:c0ecb8bf28eb 24804 *
Marko Mikulicic 0:c0ecb8bf28eb 24805 * f(a, b)
Marko Mikulicic 0:c0ecb8bf28eb 24806 *
Marko Mikulicic 0:c0ecb8bf28eb 24807 * ->
Marko Mikulicic 0:c0ecb8bf28eb 24808 *
Marko Mikulicic 0:c0ecb8bf28eb 24809 * PUSH_UNDEFINED (value for `this`)
Marko Mikulicic 0:c0ecb8bf28eb 24810 * GET_VAR "f"
Marko Mikulicic 0:c0ecb8bf28eb 24811 * CHECK_CALL
Marko Mikulicic 0:c0ecb8bf28eb 24812 * GET_VAR "a"
Marko Mikulicic 0:c0ecb8bf28eb 24813 * GET_VAR "b"
Marko Mikulicic 0:c0ecb8bf28eb 24814 * CALL 2 args
Marko Mikulicic 0:c0ecb8bf28eb 24815 *
Marko Mikulicic 0:c0ecb8bf28eb 24816 * ---------------
Marko Mikulicic 0:c0ecb8bf28eb 24817 *
Marko Mikulicic 0:c0ecb8bf28eb 24818 * o.f(a, b)
Marko Mikulicic 0:c0ecb8bf28eb 24819 *
Marko Mikulicic 0:c0ecb8bf28eb 24820 * ->
Marko Mikulicic 0:c0ecb8bf28eb 24821 *
Marko Mikulicic 0:c0ecb8bf28eb 24822 * GET_VAR "o" (so that `this` will be an `o`)
Marko Mikulicic 0:c0ecb8bf28eb 24823 * DUP (we'll also need `o` for GET below, so, duplicate it)
Marko Mikulicic 0:c0ecb8bf28eb 24824 * PUSH_LIT "f"
Marko Mikulicic 0:c0ecb8bf28eb 24825 * GET (get property "f" of the object "o")
Marko Mikulicic 0:c0ecb8bf28eb 24826 * CHECK_CALL
Marko Mikulicic 0:c0ecb8bf28eb 24827 * GET_VAR "a"
Marko Mikulicic 0:c0ecb8bf28eb 24828 * GET_VAR "b"
Marko Mikulicic 0:c0ecb8bf28eb 24829 * CALL 2 args
Marko Mikulicic 0:c0ecb8bf28eb 24830 *
Marko Mikulicic 0:c0ecb8bf28eb 24831 */
Marko Mikulicic 0:c0ecb8bf28eb 24832 int args;
Marko Mikulicic 0:c0ecb8bf28eb 24833 ast_off_t end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 24834
Marko Mikulicic 0:c0ecb8bf28eb 24835 V7_TRY(compile_expr_ext(bbuilder, a, ppos, 1 /*for call*/));
Marko Mikulicic 0:c0ecb8bf28eb 24836 bcode_op(bbuilder, OP_CHECK_CALL);
Marko Mikulicic 0:c0ecb8bf28eb 24837 for (args = 0; *ppos < end; args++) {
Marko Mikulicic 0:c0ecb8bf28eb 24838 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24839 }
Marko Mikulicic 0:c0ecb8bf28eb 24840 bcode_op(bbuilder, (tag == AST_CALL ? OP_CALL : OP_NEW));
Marko Mikulicic 0:c0ecb8bf28eb 24841 if (args > 0x7f) {
Marko Mikulicic 0:c0ecb8bf28eb 24842 rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "too many arguments");
Marko Mikulicic 0:c0ecb8bf28eb 24843 V7_THROW(V7_SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 24844 }
Marko Mikulicic 0:c0ecb8bf28eb 24845 bcode_op(bbuilder, (uint8_t) args);
Marko Mikulicic 0:c0ecb8bf28eb 24846 break;
Marko Mikulicic 0:c0ecb8bf28eb 24847 }
Marko Mikulicic 0:c0ecb8bf28eb 24848 case AST_DELETE: {
Marko Mikulicic 0:c0ecb8bf28eb 24849 V7_TRY(compile_delete(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24850 break;
Marko Mikulicic 0:c0ecb8bf28eb 24851 }
Marko Mikulicic 0:c0ecb8bf28eb 24852 case AST_OBJECT: {
Marko Mikulicic 0:c0ecb8bf28eb 24853 /*
Marko Mikulicic 0:c0ecb8bf28eb 24854 * {a:<B>, ...}
Marko Mikulicic 0:c0ecb8bf28eb 24855 *
Marko Mikulicic 0:c0ecb8bf28eb 24856 * ->
Marko Mikulicic 0:c0ecb8bf28eb 24857 *
Marko Mikulicic 0:c0ecb8bf28eb 24858 * CREATE_OBJ
Marko Mikulicic 0:c0ecb8bf28eb 24859 * DUP
Marko Mikulicic 0:c0ecb8bf28eb 24860 * PUSH_LIT "a"
Marko Mikulicic 0:c0ecb8bf28eb 24861 * <B>
Marko Mikulicic 0:c0ecb8bf28eb 24862 * SET
Marko Mikulicic 0:c0ecb8bf28eb 24863 * POP
Marko Mikulicic 0:c0ecb8bf28eb 24864 * ...
Marko Mikulicic 0:c0ecb8bf28eb 24865 */
Marko Mikulicic 0:c0ecb8bf28eb 24866
Marko Mikulicic 0:c0ecb8bf28eb 24867 /*
Marko Mikulicic 0:c0ecb8bf28eb 24868 * Literal indices of property names of current object literal.
Marko Mikulicic 0:c0ecb8bf28eb 24869 * Needed for strict mode: we need to keep track of the added
Marko Mikulicic 0:c0ecb8bf28eb 24870 * properties, since duplicates are not allowed
Marko Mikulicic 0:c0ecb8bf28eb 24871 */
Marko Mikulicic 0:c0ecb8bf28eb 24872 struct mbuf cur_literals;
Marko Mikulicic 0:c0ecb8bf28eb 24873 lit_t lit;
Marko Mikulicic 0:c0ecb8bf28eb 24874 ast_off_t end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 24875 mbuf_init(&cur_literals, 0);
Marko Mikulicic 0:c0ecb8bf28eb 24876
Marko Mikulicic 0:c0ecb8bf28eb 24877 bcode_op(bbuilder, OP_CREATE_OBJ);
Marko Mikulicic 0:c0ecb8bf28eb 24878 while (*ppos < end) {
Marko Mikulicic 0:c0ecb8bf28eb 24879 tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 24880 switch (tag) {
Marko Mikulicic 0:c0ecb8bf28eb 24881 case AST_PROP:
Marko Mikulicic 0:c0ecb8bf28eb 24882 bcode_op(bbuilder, OP_DUP);
Marko Mikulicic 0:c0ecb8bf28eb 24883 lit = string_lit(bbuilder, a, pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 24884
Marko Mikulicic 0:c0ecb8bf28eb 24885 /* disabled because we broke get_lit */
Marko Mikulicic 0:c0ecb8bf28eb 24886 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 24887 if (bbuilder->bcode->strict_mode) {
Marko Mikulicic 0:c0ecb8bf28eb 24888 /*
Marko Mikulicic 0:c0ecb8bf28eb 24889 * In strict mode, check for duplicate property names in
Marko Mikulicic 0:c0ecb8bf28eb 24890 * object literals
Marko Mikulicic 0:c0ecb8bf28eb 24891 */
Marko Mikulicic 0:c0ecb8bf28eb 24892 char *plit;
Marko Mikulicic 0:c0ecb8bf28eb 24893 for (plit = (char *) cur_literals.buf;
Marko Mikulicic 0:c0ecb8bf28eb 24894 (char *) plit < cur_literals.buf + cur_literals.len;
Marko Mikulicic 0:c0ecb8bf28eb 24895 plit++) {
Marko Mikulicic 0:c0ecb8bf28eb 24896 const char *str1, *str2;
Marko Mikulicic 0:c0ecb8bf28eb 24897 size_t size1, size2;
Marko Mikulicic 0:c0ecb8bf28eb 24898 v7_val_t val1, val2;
Marko Mikulicic 0:c0ecb8bf28eb 24899
Marko Mikulicic 0:c0ecb8bf28eb 24900 val1 = bcode_get_lit(bbuilder->bcode, lit);
Marko Mikulicic 0:c0ecb8bf28eb 24901 str1 = v7_get_string(bbuilder->v7, &val1, &size1);
Marko Mikulicic 0:c0ecb8bf28eb 24902
Marko Mikulicic 0:c0ecb8bf28eb 24903 val2 = bcode_get_lit(bbuilder->bcode, *plit);
Marko Mikulicic 0:c0ecb8bf28eb 24904 str2 = v7_get_string(bbuilder->v7, &val2, &size2);
Marko Mikulicic 0:c0ecb8bf28eb 24905
Marko Mikulicic 0:c0ecb8bf28eb 24906 if (size1 == size2 && memcmp(str1, str2, size1) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 24907 /* found already existing property of the same name */
Marko Mikulicic 0:c0ecb8bf28eb 24908 rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 24909 "duplicate data property in object literal "
Marko Mikulicic 0:c0ecb8bf28eb 24910 "is not allowed in strict mode");
Marko Mikulicic 0:c0ecb8bf28eb 24911 V7_THROW2(V7_SYNTAX_ERROR, ast_object_clean);
Marko Mikulicic 0:c0ecb8bf28eb 24912 }
Marko Mikulicic 0:c0ecb8bf28eb 24913 }
Marko Mikulicic 0:c0ecb8bf28eb 24914 mbuf_append(&cur_literals, &lit, sizeof(lit));
Marko Mikulicic 0:c0ecb8bf28eb 24915 }
Marko Mikulicic 0:c0ecb8bf28eb 24916 #endif
Marko Mikulicic 0:c0ecb8bf28eb 24917 bcode_push_lit(bbuilder, lit);
Marko Mikulicic 0:c0ecb8bf28eb 24918 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24919 bcode_op(bbuilder, OP_SET);
Marko Mikulicic 0:c0ecb8bf28eb 24920 bcode_op(bbuilder, OP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 24921 break;
Marko Mikulicic 0:c0ecb8bf28eb 24922 default:
Marko Mikulicic 0:c0ecb8bf28eb 24923 rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "not implemented");
Marko Mikulicic 0:c0ecb8bf28eb 24924 V7_THROW2(V7_SYNTAX_ERROR, ast_object_clean);
Marko Mikulicic 0:c0ecb8bf28eb 24925 }
Marko Mikulicic 0:c0ecb8bf28eb 24926 }
Marko Mikulicic 0:c0ecb8bf28eb 24927
Marko Mikulicic 0:c0ecb8bf28eb 24928 ast_object_clean:
Marko Mikulicic 0:c0ecb8bf28eb 24929 mbuf_free(&cur_literals);
Marko Mikulicic 0:c0ecb8bf28eb 24930 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 24931 V7_THROW(rcode);
Marko Mikulicic 0:c0ecb8bf28eb 24932 }
Marko Mikulicic 0:c0ecb8bf28eb 24933 break;
Marko Mikulicic 0:c0ecb8bf28eb 24934 }
Marko Mikulicic 0:c0ecb8bf28eb 24935 case AST_ARRAY: {
Marko Mikulicic 0:c0ecb8bf28eb 24936 /*
Marko Mikulicic 0:c0ecb8bf28eb 24937 * [<A>,,<B>,...]
Marko Mikulicic 0:c0ecb8bf28eb 24938 *
Marko Mikulicic 0:c0ecb8bf28eb 24939 * ->
Marko Mikulicic 0:c0ecb8bf28eb 24940 *
Marko Mikulicic 0:c0ecb8bf28eb 24941 * CREATE_ARR
Marko Mikulicic 0:c0ecb8bf28eb 24942 * PUSH_ZERO
Marko Mikulicic 0:c0ecb8bf28eb 24943 *
Marko Mikulicic 0:c0ecb8bf28eb 24944 * 2DUP
Marko Mikulicic 0:c0ecb8bf28eb 24945 * <A>
Marko Mikulicic 0:c0ecb8bf28eb 24946 * SET
Marko Mikulicic 0:c0ecb8bf28eb 24947 * POP
Marko Mikulicic 0:c0ecb8bf28eb 24948 * PUSH_ONE
Marko Mikulicic 0:c0ecb8bf28eb 24949 * ADD
Marko Mikulicic 0:c0ecb8bf28eb 24950 *
Marko Mikulicic 0:c0ecb8bf28eb 24951 * PUSH_ONE
Marko Mikulicic 0:c0ecb8bf28eb 24952 * ADD
Marko Mikulicic 0:c0ecb8bf28eb 24953 *
Marko Mikulicic 0:c0ecb8bf28eb 24954 * 2DUP
Marko Mikulicic 0:c0ecb8bf28eb 24955 * <B>
Marko Mikulicic 0:c0ecb8bf28eb 24956 * ...
Marko Mikulicic 0:c0ecb8bf28eb 24957 * POP // tmp index
Marko Mikulicic 0:c0ecb8bf28eb 24958 *
Marko Mikulicic 0:c0ecb8bf28eb 24959 * TODO(mkm): optimize this out. we can have more compact array push
Marko Mikulicic 0:c0ecb8bf28eb 24960 * that uses a special marker value for missing array elements
Marko Mikulicic 0:c0ecb8bf28eb 24961 * (which are not the same as undefined btw)
Marko Mikulicic 0:c0ecb8bf28eb 24962 */
Marko Mikulicic 0:c0ecb8bf28eb 24963 ast_off_t end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 24964 bcode_op(bbuilder, OP_CREATE_ARR);
Marko Mikulicic 0:c0ecb8bf28eb 24965 bcode_op(bbuilder, OP_PUSH_ZERO);
Marko Mikulicic 0:c0ecb8bf28eb 24966 while (*ppos < end) {
Marko Mikulicic 0:c0ecb8bf28eb 24967 ast_off_t lookahead = *ppos;
Marko Mikulicic 0:c0ecb8bf28eb 24968 tag = fetch_tag(v7, bbuilder, a, &lookahead, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 24969 if (tag != AST_NOP) {
Marko Mikulicic 0:c0ecb8bf28eb 24970 bcode_op(bbuilder, OP_2DUP);
Marko Mikulicic 0:c0ecb8bf28eb 24971 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 24972 bcode_op(bbuilder, OP_SET);
Marko Mikulicic 0:c0ecb8bf28eb 24973 bcode_op(bbuilder, OP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 24974 } else {
Marko Mikulicic 0:c0ecb8bf28eb 24975 *ppos = lookahead; /* skip nop */
Marko Mikulicic 0:c0ecb8bf28eb 24976 }
Marko Mikulicic 0:c0ecb8bf28eb 24977 bcode_op(bbuilder, OP_PUSH_ONE);
Marko Mikulicic 0:c0ecb8bf28eb 24978 bcode_op(bbuilder, OP_ADD);
Marko Mikulicic 0:c0ecb8bf28eb 24979 }
Marko Mikulicic 0:c0ecb8bf28eb 24980 bcode_op(bbuilder, OP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 24981 break;
Marko Mikulicic 0:c0ecb8bf28eb 24982 }
Marko Mikulicic 0:c0ecb8bf28eb 24983 case AST_FUNC: {
Marko Mikulicic 0:c0ecb8bf28eb 24984 lit_t flit;
Marko Mikulicic 0:c0ecb8bf28eb 24985
Marko Mikulicic 0:c0ecb8bf28eb 24986 /*
Marko Mikulicic 0:c0ecb8bf28eb 24987 * Create half-done function: without scope and prototype. The real
Marko Mikulicic 0:c0ecb8bf28eb 24988 * function will be created from this one during bcode evaluation: see
Marko Mikulicic 0:c0ecb8bf28eb 24989 * `bcode_instantiate_function()`.
Marko Mikulicic 0:c0ecb8bf28eb 24990 */
Marko Mikulicic 0:c0ecb8bf28eb 24991 val_t funv = mk_js_function(bbuilder->v7, NULL, V7_UNDEFINED);
Marko Mikulicic 0:c0ecb8bf28eb 24992
Marko Mikulicic 0:c0ecb8bf28eb 24993 /* Create bcode in this half-done function */
Marko Mikulicic 0:c0ecb8bf28eb 24994 struct v7_js_function *func = get_js_function_struct(funv);
Marko Mikulicic 0:c0ecb8bf28eb 24995 func->bcode = (struct bcode *) calloc(1, sizeof(*bbuilder->bcode));
Marko Mikulicic 0:c0ecb8bf28eb 24996 bcode_init(func->bcode, bbuilder->bcode->strict_mode,
Marko Mikulicic 0:c0ecb8bf28eb 24997 NULL /* will be set below */, 0);
Marko Mikulicic 0:c0ecb8bf28eb 24998 bcode_copy_filename_from(func->bcode, bbuilder->bcode);
Marko Mikulicic 0:c0ecb8bf28eb 24999 retain_bcode(bbuilder->v7, func->bcode);
Marko Mikulicic 0:c0ecb8bf28eb 25000 flit = bcode_add_lit(bbuilder, funv);
Marko Mikulicic 0:c0ecb8bf28eb 25001
Marko Mikulicic 0:c0ecb8bf28eb 25002 *ppos = pos_after_tag - 1;
Marko Mikulicic 0:c0ecb8bf28eb 25003 V7_TRY(compile_function(v7, a, ppos, func->bcode));
Marko Mikulicic 0:c0ecb8bf28eb 25004 bcode_push_lit(bbuilder, flit);
Marko Mikulicic 0:c0ecb8bf28eb 25005 bcode_op(bbuilder, OP_FUNC_LIT);
Marko Mikulicic 0:c0ecb8bf28eb 25006 break;
Marko Mikulicic 0:c0ecb8bf28eb 25007 }
Marko Mikulicic 0:c0ecb8bf28eb 25008 case AST_THIS:
Marko Mikulicic 0:c0ecb8bf28eb 25009 bcode_op(bbuilder, OP_PUSH_THIS);
Marko Mikulicic 0:c0ecb8bf28eb 25010 break;
Marko Mikulicic 0:c0ecb8bf28eb 25011 case AST_VOID:
Marko Mikulicic 0:c0ecb8bf28eb 25012 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 25013 bcode_op(bbuilder, OP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 25014 bcode_op(bbuilder, OP_PUSH_UNDEFINED);
Marko Mikulicic 0:c0ecb8bf28eb 25015 break;
Marko Mikulicic 0:c0ecb8bf28eb 25016 case AST_NULL:
Marko Mikulicic 0:c0ecb8bf28eb 25017 bcode_op(bbuilder, OP_PUSH_NULL);
Marko Mikulicic 0:c0ecb8bf28eb 25018 break;
Marko Mikulicic 0:c0ecb8bf28eb 25019 case AST_NOP:
Marko Mikulicic 0:c0ecb8bf28eb 25020 case AST_UNDEFINED:
Marko Mikulicic 0:c0ecb8bf28eb 25021 bcode_op(bbuilder, OP_PUSH_UNDEFINED);
Marko Mikulicic 0:c0ecb8bf28eb 25022 break;
Marko Mikulicic 0:c0ecb8bf28eb 25023 case AST_TRUE:
Marko Mikulicic 0:c0ecb8bf28eb 25024 bcode_op(bbuilder, OP_PUSH_TRUE);
Marko Mikulicic 0:c0ecb8bf28eb 25025 break;
Marko Mikulicic 0:c0ecb8bf28eb 25026 case AST_FALSE:
Marko Mikulicic 0:c0ecb8bf28eb 25027 bcode_op(bbuilder, OP_PUSH_FALSE);
Marko Mikulicic 0:c0ecb8bf28eb 25028 break;
Marko Mikulicic 0:c0ecb8bf28eb 25029 case AST_NUM: {
Marko Mikulicic 0:c0ecb8bf28eb 25030 double dv = ast_get_num(a, pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25031 if (dv == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 25032 bcode_op(bbuilder, OP_PUSH_ZERO);
Marko Mikulicic 0:c0ecb8bf28eb 25033 } else if (dv == 1) {
Marko Mikulicic 0:c0ecb8bf28eb 25034 bcode_op(bbuilder, OP_PUSH_ONE);
Marko Mikulicic 0:c0ecb8bf28eb 25035 } else {
Marko Mikulicic 0:c0ecb8bf28eb 25036 bcode_push_lit(bbuilder, bcode_add_lit(bbuilder, v7_mk_number(v7, dv)));
Marko Mikulicic 0:c0ecb8bf28eb 25037 }
Marko Mikulicic 0:c0ecb8bf28eb 25038 break;
Marko Mikulicic 0:c0ecb8bf28eb 25039 }
Marko Mikulicic 0:c0ecb8bf28eb 25040 case AST_STRING:
Marko Mikulicic 0:c0ecb8bf28eb 25041 bcode_push_lit(bbuilder, string_lit(bbuilder, a, pos_after_tag));
Marko Mikulicic 0:c0ecb8bf28eb 25042 break;
Marko Mikulicic 0:c0ecb8bf28eb 25043 case AST_REGEX:
Marko Mikulicic 0:c0ecb8bf28eb 25044 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 25045 {
Marko Mikulicic 0:c0ecb8bf28eb 25046 lit_t tmp;
Marko Mikulicic 0:c0ecb8bf28eb 25047 rcode = regexp_lit(bbuilder, a, pos_after_tag, &tmp);
Marko Mikulicic 0:c0ecb8bf28eb 25048 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 25049 rcode = V7_SYNTAX_ERROR;
Marko Mikulicic 0:c0ecb8bf28eb 25050 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 25051 }
Marko Mikulicic 0:c0ecb8bf28eb 25052
Marko Mikulicic 0:c0ecb8bf28eb 25053 bcode_push_lit(bbuilder, tmp);
Marko Mikulicic 0:c0ecb8bf28eb 25054 break;
Marko Mikulicic 0:c0ecb8bf28eb 25055 }
Marko Mikulicic 0:c0ecb8bf28eb 25056 #else
Marko Mikulicic 0:c0ecb8bf28eb 25057 rcode =
Marko Mikulicic 0:c0ecb8bf28eb 25058 v7_throwf(bbuilder->v7, SYNTAX_ERROR, "Regexp support is disabled");
Marko Mikulicic 0:c0ecb8bf28eb 25059 V7_THROW(V7_SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 25060 #endif
Marko Mikulicic 0:c0ecb8bf28eb 25061 case AST_LABEL:
Marko Mikulicic 0:c0ecb8bf28eb 25062 case AST_LABELED_BREAK:
Marko Mikulicic 0:c0ecb8bf28eb 25063 case AST_LABELED_CONTINUE:
Marko Mikulicic 0:c0ecb8bf28eb 25064 /* TODO(dfrank): implement */
Marko Mikulicic 0:c0ecb8bf28eb 25065 rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "not implemented");
Marko Mikulicic 0:c0ecb8bf28eb 25066 V7_THROW(V7_SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 25067 case AST_WITH:
Marko Mikulicic 0:c0ecb8bf28eb 25068 rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "not implemented");
Marko Mikulicic 0:c0ecb8bf28eb 25069 V7_THROW(V7_SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 25070 default:
Marko Mikulicic 0:c0ecb8bf28eb 25071 /*
Marko Mikulicic 0:c0ecb8bf28eb 25072 * We end up here if the AST is broken.
Marko Mikulicic 0:c0ecb8bf28eb 25073 *
Marko Mikulicic 0:c0ecb8bf28eb 25074 * It might be appropriate to return `V7_INTERNAL_ERROR` here, but since
Marko Mikulicic 0:c0ecb8bf28eb 25075 * we might receive AST from network or something, we just interpret
Marko Mikulicic 0:c0ecb8bf28eb 25076 * it as SyntaxError.
Marko Mikulicic 0:c0ecb8bf28eb 25077 */
Marko Mikulicic 0:c0ecb8bf28eb 25078 rcode = v7_throwf(bbuilder->v7, SYNTAX_ERROR, "unknown ast node %d",
Marko Mikulicic 0:c0ecb8bf28eb 25079 (int) tag);
Marko Mikulicic 0:c0ecb8bf28eb 25080 V7_THROW(V7_SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 25081 }
Marko Mikulicic 0:c0ecb8bf28eb 25082 clean:
Marko Mikulicic 0:c0ecb8bf28eb 25083 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 25084 }
Marko Mikulicic 0:c0ecb8bf28eb 25085
Marko Mikulicic 0:c0ecb8bf28eb 25086 V7_PRIVATE enum v7_err compile_stmt(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 25087 struct ast *a, ast_off_t *ppos);
Marko Mikulicic 0:c0ecb8bf28eb 25088
Marko Mikulicic 0:c0ecb8bf28eb 25089 V7_PRIVATE enum v7_err compile_stmts(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 25090 struct ast *a, ast_off_t *ppos,
Marko Mikulicic 0:c0ecb8bf28eb 25091 ast_off_t end) {
Marko Mikulicic 0:c0ecb8bf28eb 25092 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 25093 struct v7 *v7 = bbuilder->v7;
Marko Mikulicic 0:c0ecb8bf28eb 25094
Marko Mikulicic 0:c0ecb8bf28eb 25095 while (*ppos < end) {
Marko Mikulicic 0:c0ecb8bf28eb 25096 V7_TRY(compile_stmt(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 25097 if (!bbuilder->v7->is_stack_neutral) {
Marko Mikulicic 0:c0ecb8bf28eb 25098 bcode_op(bbuilder, OP_SWAP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 25099 } else {
Marko Mikulicic 0:c0ecb8bf28eb 25100 bbuilder->v7->is_stack_neutral = 0;
Marko Mikulicic 0:c0ecb8bf28eb 25101 }
Marko Mikulicic 0:c0ecb8bf28eb 25102 }
Marko Mikulicic 0:c0ecb8bf28eb 25103 clean:
Marko Mikulicic 0:c0ecb8bf28eb 25104 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 25105 }
Marko Mikulicic 0:c0ecb8bf28eb 25106
Marko Mikulicic 0:c0ecb8bf28eb 25107 V7_PRIVATE enum v7_err compile_stmt(struct bcode_builder *bbuilder,
Marko Mikulicic 0:c0ecb8bf28eb 25108 struct ast *a, ast_off_t *ppos) {
Marko Mikulicic 0:c0ecb8bf28eb 25109 ast_off_t end;
Marko Mikulicic 0:c0ecb8bf28eb 25110 enum ast_tag tag;
Marko Mikulicic 0:c0ecb8bf28eb 25111 ast_off_t cond, pos_after_tag;
Marko Mikulicic 0:c0ecb8bf28eb 25112 bcode_off_t body_target, body_label, cond_label;
Marko Mikulicic 0:c0ecb8bf28eb 25113 struct mbuf case_labels;
Marko Mikulicic 0:c0ecb8bf28eb 25114 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 25115 struct v7 *v7 = bbuilder->v7;
Marko Mikulicic 0:c0ecb8bf28eb 25116
Marko Mikulicic 0:c0ecb8bf28eb 25117 tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25118
Marko Mikulicic 0:c0ecb8bf28eb 25119 mbuf_init(&case_labels, 0);
Marko Mikulicic 0:c0ecb8bf28eb 25120
Marko Mikulicic 0:c0ecb8bf28eb 25121 switch (tag) {
Marko Mikulicic 0:c0ecb8bf28eb 25122 /*
Marko Mikulicic 0:c0ecb8bf28eb 25123 * if(E) {
Marko Mikulicic 0:c0ecb8bf28eb 25124 * BT...
Marko Mikulicic 0:c0ecb8bf28eb 25125 * } else {
Marko Mikulicic 0:c0ecb8bf28eb 25126 * BF...
Marko Mikulicic 0:c0ecb8bf28eb 25127 * }
Marko Mikulicic 0:c0ecb8bf28eb 25128 *
Marko Mikulicic 0:c0ecb8bf28eb 25129 * ->
Marko Mikulicic 0:c0ecb8bf28eb 25130 *
Marko Mikulicic 0:c0ecb8bf28eb 25131 * <E>
Marko Mikulicic 0:c0ecb8bf28eb 25132 * JMP_FALSE body
Marko Mikulicic 0:c0ecb8bf28eb 25133 * <BT>
Marko Mikulicic 0:c0ecb8bf28eb 25134 * JMP end
Marko Mikulicic 0:c0ecb8bf28eb 25135 * body:
Marko Mikulicic 0:c0ecb8bf28eb 25136 * <BF>
Marko Mikulicic 0:c0ecb8bf28eb 25137 * end:
Marko Mikulicic 0:c0ecb8bf28eb 25138 *
Marko Mikulicic 0:c0ecb8bf28eb 25139 * If else clause is omitted, it will emit output equivalent to:
Marko Mikulicic 0:c0ecb8bf28eb 25140 *
Marko Mikulicic 0:c0ecb8bf28eb 25141 * if(E) {BT} else undefined;
Marko Mikulicic 0:c0ecb8bf28eb 25142 */
Marko Mikulicic 0:c0ecb8bf28eb 25143 case AST_IF: {
Marko Mikulicic 0:c0ecb8bf28eb 25144 ast_off_t if_false;
Marko Mikulicic 0:c0ecb8bf28eb 25145 bcode_off_t end_label, if_false_label;
Marko Mikulicic 0:c0ecb8bf28eb 25146 end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25147 if_false = ast_get_skip(a, pos_after_tag, AST_END_IF_TRUE_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25148
Marko Mikulicic 0:c0ecb8bf28eb 25149 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 25150 if_false_label = bcode_op_target(bbuilder, OP_JMP_FALSE);
Marko Mikulicic 0:c0ecb8bf28eb 25151
Marko Mikulicic 0:c0ecb8bf28eb 25152 /* body if true */
Marko Mikulicic 0:c0ecb8bf28eb 25153 V7_TRY(compile_stmts(bbuilder, a, ppos, if_false));
Marko Mikulicic 0:c0ecb8bf28eb 25154
Marko Mikulicic 0:c0ecb8bf28eb 25155 if (if_false != end) {
Marko Mikulicic 0:c0ecb8bf28eb 25156 /* `else` branch is present */
Marko Mikulicic 0:c0ecb8bf28eb 25157 end_label = bcode_op_target(bbuilder, OP_JMP);
Marko Mikulicic 0:c0ecb8bf28eb 25158
Marko Mikulicic 0:c0ecb8bf28eb 25159 /* will jump here if `false` */
Marko Mikulicic 0:c0ecb8bf28eb 25160 bcode_patch_target(bbuilder, if_false_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25161
Marko Mikulicic 0:c0ecb8bf28eb 25162 /* body if false */
Marko Mikulicic 0:c0ecb8bf28eb 25163 V7_TRY(compile_stmts(bbuilder, a, ppos, end));
Marko Mikulicic 0:c0ecb8bf28eb 25164
Marko Mikulicic 0:c0ecb8bf28eb 25165 bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25166 } else {
Marko Mikulicic 0:c0ecb8bf28eb 25167 /*
Marko Mikulicic 0:c0ecb8bf28eb 25168 * `else` branch is not present: just remember where we should
Marko Mikulicic 0:c0ecb8bf28eb 25169 * jump in case of `false`
Marko Mikulicic 0:c0ecb8bf28eb 25170 */
Marko Mikulicic 0:c0ecb8bf28eb 25171 bcode_patch_target(bbuilder, if_false_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25172 }
Marko Mikulicic 0:c0ecb8bf28eb 25173
Marko Mikulicic 0:c0ecb8bf28eb 25174 bbuilder->v7->is_stack_neutral = 1;
Marko Mikulicic 0:c0ecb8bf28eb 25175 break;
Marko Mikulicic 0:c0ecb8bf28eb 25176 }
Marko Mikulicic 0:c0ecb8bf28eb 25177 /*
Marko Mikulicic 0:c0ecb8bf28eb 25178 * while(C) {
Marko Mikulicic 0:c0ecb8bf28eb 25179 * B...
Marko Mikulicic 0:c0ecb8bf28eb 25180 * }
Marko Mikulicic 0:c0ecb8bf28eb 25181 *
Marko Mikulicic 0:c0ecb8bf28eb 25182 * ->
Marko Mikulicic 0:c0ecb8bf28eb 25183 *
Marko Mikulicic 0:c0ecb8bf28eb 25184 * TRY_PUSH_LOOP end
Marko Mikulicic 0:c0ecb8bf28eb 25185 * JMP cond
Marko Mikulicic 0:c0ecb8bf28eb 25186 * body:
Marko Mikulicic 0:c0ecb8bf28eb 25187 * <B>
Marko Mikulicic 0:c0ecb8bf28eb 25188 * cond:
Marko Mikulicic 0:c0ecb8bf28eb 25189 * <C>
Marko Mikulicic 0:c0ecb8bf28eb 25190 * JMP_TRUE body
Marko Mikulicic 0:c0ecb8bf28eb 25191 * end:
Marko Mikulicic 0:c0ecb8bf28eb 25192 * JMP_IF_CONTINUE cond
Marko Mikulicic 0:c0ecb8bf28eb 25193 * TRY_POP
Marko Mikulicic 0:c0ecb8bf28eb 25194 *
Marko Mikulicic 0:c0ecb8bf28eb 25195 */
Marko Mikulicic 0:c0ecb8bf28eb 25196 case AST_WHILE: {
Marko Mikulicic 0:c0ecb8bf28eb 25197 bcode_off_t end_label, continue_label, continue_target;
Marko Mikulicic 0:c0ecb8bf28eb 25198
Marko Mikulicic 0:c0ecb8bf28eb 25199 end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25200 cond = *ppos;
Marko Mikulicic 0:c0ecb8bf28eb 25201 ast_skip_tree(a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 25202
Marko Mikulicic 0:c0ecb8bf28eb 25203 end_label = bcode_op_target(bbuilder, OP_TRY_PUSH_LOOP);
Marko Mikulicic 0:c0ecb8bf28eb 25204
Marko Mikulicic 0:c0ecb8bf28eb 25205 /*
Marko Mikulicic 0:c0ecb8bf28eb 25206 * Condition check is at the end of the loop, this layout
Marko Mikulicic 0:c0ecb8bf28eb 25207 * reduces the number of jumps in the steady state.
Marko Mikulicic 0:c0ecb8bf28eb 25208 */
Marko Mikulicic 0:c0ecb8bf28eb 25209 cond_label = bcode_op_target(bbuilder, OP_JMP);
Marko Mikulicic 0:c0ecb8bf28eb 25210 body_target = bcode_pos(bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 25211
Marko Mikulicic 0:c0ecb8bf28eb 25212 V7_TRY(compile_stmts(bbuilder, a, ppos, end));
Marko Mikulicic 0:c0ecb8bf28eb 25213
Marko Mikulicic 0:c0ecb8bf28eb 25214 continue_target = bcode_pos(bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 25215 bcode_patch_target(bbuilder, cond_label, continue_target);
Marko Mikulicic 0:c0ecb8bf28eb 25216
Marko Mikulicic 0:c0ecb8bf28eb 25217 V7_TRY(compile_expr_builder(bbuilder, a, &cond));
Marko Mikulicic 0:c0ecb8bf28eb 25218 body_label = bcode_op_target(bbuilder, OP_JMP_TRUE);
Marko Mikulicic 0:c0ecb8bf28eb 25219 bcode_patch_target(bbuilder, body_label, body_target);
Marko Mikulicic 0:c0ecb8bf28eb 25220
Marko Mikulicic 0:c0ecb8bf28eb 25221 bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25222 continue_label = bcode_op_target(bbuilder, OP_JMP_IF_CONTINUE);
Marko Mikulicic 0:c0ecb8bf28eb 25223 bcode_patch_target(bbuilder, continue_label, continue_target);
Marko Mikulicic 0:c0ecb8bf28eb 25224 bcode_op(bbuilder, OP_TRY_POP);
Marko Mikulicic 0:c0ecb8bf28eb 25225
Marko Mikulicic 0:c0ecb8bf28eb 25226 bbuilder->v7->is_stack_neutral = 1;
Marko Mikulicic 0:c0ecb8bf28eb 25227 break;
Marko Mikulicic 0:c0ecb8bf28eb 25228 }
Marko Mikulicic 0:c0ecb8bf28eb 25229 case AST_BREAK:
Marko Mikulicic 0:c0ecb8bf28eb 25230 bcode_op(bbuilder, OP_BREAK);
Marko Mikulicic 0:c0ecb8bf28eb 25231 break;
Marko Mikulicic 0:c0ecb8bf28eb 25232 case AST_CONTINUE:
Marko Mikulicic 0:c0ecb8bf28eb 25233 bcode_op(bbuilder, OP_CONTINUE);
Marko Mikulicic 0:c0ecb8bf28eb 25234 break;
Marko Mikulicic 0:c0ecb8bf28eb 25235 /*
Marko Mikulicic 0:c0ecb8bf28eb 25236 * Frame objects (`v7->vals.call_stack`) contain one more hidden property:
Marko Mikulicic 0:c0ecb8bf28eb 25237 * `____t`, which is an array of offsets in bcode. Each element of the array
Marko Mikulicic 0:c0ecb8bf28eb 25238 * is an offset of either `catch` or `finally` block (distinguished by the
Marko Mikulicic 0:c0ecb8bf28eb 25239 * tag: `OFFSET_TAG_CATCH` or `OFFSET_TAG_FINALLY`). Let's call this array
Marko Mikulicic 0:c0ecb8bf28eb 25240 * as a "try stack". When evaluator enters new `try` block, it adds
Marko Mikulicic 0:c0ecb8bf28eb 25241 * appropriate offset(s) at the top of "try stack", and when we unwind the
Marko Mikulicic 0:c0ecb8bf28eb 25242 * stack, we can "pop" offsets from "try stack" at each level.
Marko Mikulicic 0:c0ecb8bf28eb 25243 *
Marko Mikulicic 0:c0ecb8bf28eb 25244 * try {
Marko Mikulicic 0:c0ecb8bf28eb 25245 * TRY_B
Marko Mikulicic 0:c0ecb8bf28eb 25246 * } catch (e) {
Marko Mikulicic 0:c0ecb8bf28eb 25247 * CATCH_B
Marko Mikulicic 0:c0ecb8bf28eb 25248 * } finally {
Marko Mikulicic 0:c0ecb8bf28eb 25249 * FIN_B
Marko Mikulicic 0:c0ecb8bf28eb 25250 * }
Marko Mikulicic 0:c0ecb8bf28eb 25251 *
Marko Mikulicic 0:c0ecb8bf28eb 25252 * ->
Marko Mikulicic 0:c0ecb8bf28eb 25253 * OP_TRY_PUSH_FINALLY finally
Marko Mikulicic 0:c0ecb8bf28eb 25254 * OP_TRY_PUSH_CATCH catch
Marko Mikulicic 0:c0ecb8bf28eb 25255 * <TRY_B>
Marko Mikulicic 0:c0ecb8bf28eb 25256 * OP_TRY_POP
Marko Mikulicic 0:c0ecb8bf28eb 25257 * JMP finally
Marko Mikulicic 0:c0ecb8bf28eb 25258 * catch:
Marko Mikulicic 0:c0ecb8bf28eb 25259 * OP_TRY_POP
Marko Mikulicic 0:c0ecb8bf28eb 25260 * OP_ENTER_CATCH <e>
Marko Mikulicic 0:c0ecb8bf28eb 25261 * <CATCH_B>
Marko Mikulicic 0:c0ecb8bf28eb 25262 * OP_EXIT_CATCH
Marko Mikulicic 0:c0ecb8bf28eb 25263 * finally:
Marko Mikulicic 0:c0ecb8bf28eb 25264 * OP_TRY_POP
Marko Mikulicic 0:c0ecb8bf28eb 25265 * <FIN_B>
Marko Mikulicic 0:c0ecb8bf28eb 25266 * OP_AFTER_FINALLY
Marko Mikulicic 0:c0ecb8bf28eb 25267 *
Marko Mikulicic 0:c0ecb8bf28eb 25268 * ---------------
Marko Mikulicic 0:c0ecb8bf28eb 25269 *
Marko Mikulicic 0:c0ecb8bf28eb 25270 * try {
Marko Mikulicic 0:c0ecb8bf28eb 25271 * TRY_B
Marko Mikulicic 0:c0ecb8bf28eb 25272 * } catch (e) {
Marko Mikulicic 0:c0ecb8bf28eb 25273 * CATCH_B
Marko Mikulicic 0:c0ecb8bf28eb 25274 * }
Marko Mikulicic 0:c0ecb8bf28eb 25275 *
Marko Mikulicic 0:c0ecb8bf28eb 25276 * ->
Marko Mikulicic 0:c0ecb8bf28eb 25277 * OP_TRY_PUSH_CATCH catch
Marko Mikulicic 0:c0ecb8bf28eb 25278 * <TRY_B>
Marko Mikulicic 0:c0ecb8bf28eb 25279 * OP_TRY_POP
Marko Mikulicic 0:c0ecb8bf28eb 25280 * JMP end
Marko Mikulicic 0:c0ecb8bf28eb 25281 * catch:
Marko Mikulicic 0:c0ecb8bf28eb 25282 * OP_TRY_POP
Marko Mikulicic 0:c0ecb8bf28eb 25283 * OP_ENTER_CATCH <e>
Marko Mikulicic 0:c0ecb8bf28eb 25284 * <CATCH_B>
Marko Mikulicic 0:c0ecb8bf28eb 25285 * OP_EXIT_CATCH
Marko Mikulicic 0:c0ecb8bf28eb 25286 * end:
Marko Mikulicic 0:c0ecb8bf28eb 25287 *
Marko Mikulicic 0:c0ecb8bf28eb 25288 * ---------------
Marko Mikulicic 0:c0ecb8bf28eb 25289 *
Marko Mikulicic 0:c0ecb8bf28eb 25290 * try {
Marko Mikulicic 0:c0ecb8bf28eb 25291 * TRY_B
Marko Mikulicic 0:c0ecb8bf28eb 25292 * } finally {
Marko Mikulicic 0:c0ecb8bf28eb 25293 * FIN_B
Marko Mikulicic 0:c0ecb8bf28eb 25294 * }
Marko Mikulicic 0:c0ecb8bf28eb 25295 *
Marko Mikulicic 0:c0ecb8bf28eb 25296 * ->
Marko Mikulicic 0:c0ecb8bf28eb 25297 * OP_TRY_PUSH_FINALLY finally
Marko Mikulicic 0:c0ecb8bf28eb 25298 * <TRY_B>
Marko Mikulicic 0:c0ecb8bf28eb 25299 * finally:
Marko Mikulicic 0:c0ecb8bf28eb 25300 * OP_TRY_POP
Marko Mikulicic 0:c0ecb8bf28eb 25301 * <FIN_B>
Marko Mikulicic 0:c0ecb8bf28eb 25302 * OP_AFTER_FINALLY
Marko Mikulicic 0:c0ecb8bf28eb 25303 */
Marko Mikulicic 0:c0ecb8bf28eb 25304 case AST_TRY: {
Marko Mikulicic 0:c0ecb8bf28eb 25305 ast_off_t acatch, afinally;
Marko Mikulicic 0:c0ecb8bf28eb 25306 bcode_off_t finally_label, catch_label;
Marko Mikulicic 0:c0ecb8bf28eb 25307
Marko Mikulicic 0:c0ecb8bf28eb 25308 end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25309 acatch = ast_get_skip(a, pos_after_tag, AST_TRY_CATCH_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25310 afinally = ast_get_skip(a, pos_after_tag, AST_TRY_FINALLY_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25311
Marko Mikulicic 0:c0ecb8bf28eb 25312 if (afinally != end) {
Marko Mikulicic 0:c0ecb8bf28eb 25313 /* `finally` clause is present: push its offset */
Marko Mikulicic 0:c0ecb8bf28eb 25314 finally_label = bcode_op_target(bbuilder, OP_TRY_PUSH_FINALLY);
Marko Mikulicic 0:c0ecb8bf28eb 25315 }
Marko Mikulicic 0:c0ecb8bf28eb 25316
Marko Mikulicic 0:c0ecb8bf28eb 25317 if (acatch != afinally) {
Marko Mikulicic 0:c0ecb8bf28eb 25318 /* `catch` clause is present: push its offset */
Marko Mikulicic 0:c0ecb8bf28eb 25319 catch_label = bcode_op_target(bbuilder, OP_TRY_PUSH_CATCH);
Marko Mikulicic 0:c0ecb8bf28eb 25320 }
Marko Mikulicic 0:c0ecb8bf28eb 25321
Marko Mikulicic 0:c0ecb8bf28eb 25322 /* compile statements of `try` block */
Marko Mikulicic 0:c0ecb8bf28eb 25323 V7_TRY(compile_stmts(bbuilder, a, ppos, acatch));
Marko Mikulicic 0:c0ecb8bf28eb 25324
Marko Mikulicic 0:c0ecb8bf28eb 25325 if (acatch != afinally) {
Marko Mikulicic 0:c0ecb8bf28eb 25326 /* `catch` clause is present: compile it */
Marko Mikulicic 0:c0ecb8bf28eb 25327 bcode_off_t after_catch_label;
Marko Mikulicic 0:c0ecb8bf28eb 25328
Marko Mikulicic 0:c0ecb8bf28eb 25329 /*
Marko Mikulicic 0:c0ecb8bf28eb 25330 * pop offset pushed by OP_TRY_PUSH_CATCH, and jump over the `catch`
Marko Mikulicic 0:c0ecb8bf28eb 25331 * block
Marko Mikulicic 0:c0ecb8bf28eb 25332 */
Marko Mikulicic 0:c0ecb8bf28eb 25333 bcode_op(bbuilder, OP_TRY_POP);
Marko Mikulicic 0:c0ecb8bf28eb 25334 after_catch_label = bcode_op_target(bbuilder, OP_JMP);
Marko Mikulicic 0:c0ecb8bf28eb 25335
Marko Mikulicic 0:c0ecb8bf28eb 25336 /* --- catch --- */
Marko Mikulicic 0:c0ecb8bf28eb 25337
Marko Mikulicic 0:c0ecb8bf28eb 25338 /* in case of exception in the `try` block above, we'll get here */
Marko Mikulicic 0:c0ecb8bf28eb 25339 bcode_patch_target(bbuilder, catch_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25340
Marko Mikulicic 0:c0ecb8bf28eb 25341 /* pop offset pushed by OP_TRY_PUSH_CATCH */
Marko Mikulicic 0:c0ecb8bf28eb 25342 bcode_op(bbuilder, OP_TRY_POP);
Marko Mikulicic 0:c0ecb8bf28eb 25343
Marko Mikulicic 0:c0ecb8bf28eb 25344 /*
Marko Mikulicic 0:c0ecb8bf28eb 25345 * retrieve identifier where to store thrown error, and make sure
Marko Mikulicic 0:c0ecb8bf28eb 25346 * it is actually an indentifier (AST_IDENT)
Marko Mikulicic 0:c0ecb8bf28eb 25347 */
Marko Mikulicic 0:c0ecb8bf28eb 25348 tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25349 V7_CHECK(tag == AST_IDENT, V7_SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 25350
Marko Mikulicic 0:c0ecb8bf28eb 25351 /*
Marko Mikulicic 0:c0ecb8bf28eb 25352 * when we enter `catch` block, the TOS contains thrown value.
Marko Mikulicic 0:c0ecb8bf28eb 25353 * We should create private frame for the `catch` clause, and populate
Marko Mikulicic 0:c0ecb8bf28eb 25354 * a variable with the thrown value there.
Marko Mikulicic 0:c0ecb8bf28eb 25355 * The `OP_ENTER_CATCH` opcode does just that.
Marko Mikulicic 0:c0ecb8bf28eb 25356 */
Marko Mikulicic 0:c0ecb8bf28eb 25357 bcode_op_lit(bbuilder, OP_ENTER_CATCH,
Marko Mikulicic 0:c0ecb8bf28eb 25358 string_lit(bbuilder, a, pos_after_tag));
Marko Mikulicic 0:c0ecb8bf28eb 25359
Marko Mikulicic 0:c0ecb8bf28eb 25360 /*
Marko Mikulicic 0:c0ecb8bf28eb 25361 * compile statements until the end of `catch` clause
Marko Mikulicic 0:c0ecb8bf28eb 25362 * (`afinally` points to the end of the `catch` clause independently
Marko Mikulicic 0:c0ecb8bf28eb 25363 * of whether the `finally` clause is present)
Marko Mikulicic 0:c0ecb8bf28eb 25364 */
Marko Mikulicic 0:c0ecb8bf28eb 25365 V7_TRY(compile_stmts(bbuilder, a, ppos, afinally));
Marko Mikulicic 0:c0ecb8bf28eb 25366
Marko Mikulicic 0:c0ecb8bf28eb 25367 /* pop private frame */
Marko Mikulicic 0:c0ecb8bf28eb 25368 bcode_op(bbuilder, OP_EXIT_CATCH);
Marko Mikulicic 0:c0ecb8bf28eb 25369
Marko Mikulicic 0:c0ecb8bf28eb 25370 bcode_patch_target(bbuilder, after_catch_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25371 }
Marko Mikulicic 0:c0ecb8bf28eb 25372
Marko Mikulicic 0:c0ecb8bf28eb 25373 if (afinally != end) {
Marko Mikulicic 0:c0ecb8bf28eb 25374 /* `finally` clause is present: compile it */
Marko Mikulicic 0:c0ecb8bf28eb 25375
Marko Mikulicic 0:c0ecb8bf28eb 25376 /* --- finally --- */
Marko Mikulicic 0:c0ecb8bf28eb 25377
Marko Mikulicic 0:c0ecb8bf28eb 25378 /* after the `try` block above executes, we'll get here */
Marko Mikulicic 0:c0ecb8bf28eb 25379 bcode_patch_target(bbuilder, finally_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25380
Marko Mikulicic 0:c0ecb8bf28eb 25381 /* pop offset pushed by OP_TRY_PUSH_FINALLY */
Marko Mikulicic 0:c0ecb8bf28eb 25382 bcode_op(bbuilder, OP_TRY_POP);
Marko Mikulicic 0:c0ecb8bf28eb 25383
Marko Mikulicic 0:c0ecb8bf28eb 25384 /* compile statements until the end of `finally` clause */
Marko Mikulicic 0:c0ecb8bf28eb 25385 V7_TRY(compile_stmts(bbuilder, a, ppos, end));
Marko Mikulicic 0:c0ecb8bf28eb 25386
Marko Mikulicic 0:c0ecb8bf28eb 25387 bcode_op(bbuilder, OP_AFTER_FINALLY);
Marko Mikulicic 0:c0ecb8bf28eb 25388 }
Marko Mikulicic 0:c0ecb8bf28eb 25389
Marko Mikulicic 0:c0ecb8bf28eb 25390 bbuilder->v7->is_stack_neutral = 1;
Marko Mikulicic 0:c0ecb8bf28eb 25391 break;
Marko Mikulicic 0:c0ecb8bf28eb 25392 }
Marko Mikulicic 0:c0ecb8bf28eb 25393
Marko Mikulicic 0:c0ecb8bf28eb 25394 case AST_THROW: {
Marko Mikulicic 0:c0ecb8bf28eb 25395 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 25396 bcode_op(bbuilder, OP_THROW);
Marko Mikulicic 0:c0ecb8bf28eb 25397 break;
Marko Mikulicic 0:c0ecb8bf28eb 25398 }
Marko Mikulicic 0:c0ecb8bf28eb 25399
Marko Mikulicic 0:c0ecb8bf28eb 25400 /*
Marko Mikulicic 0:c0ecb8bf28eb 25401 * switch(E) {
Marko Mikulicic 0:c0ecb8bf28eb 25402 * default:
Marko Mikulicic 0:c0ecb8bf28eb 25403 * D...
Marko Mikulicic 0:c0ecb8bf28eb 25404 * case C1:
Marko Mikulicic 0:c0ecb8bf28eb 25405 * B1...
Marko Mikulicic 0:c0ecb8bf28eb 25406 * case C2:
Marko Mikulicic 0:c0ecb8bf28eb 25407 * B2...
Marko Mikulicic 0:c0ecb8bf28eb 25408 * }
Marko Mikulicic 0:c0ecb8bf28eb 25409 *
Marko Mikulicic 0:c0ecb8bf28eb 25410 * ->
Marko Mikulicic 0:c0ecb8bf28eb 25411 *
Marko Mikulicic 0:c0ecb8bf28eb 25412 * TRY_PUSH_SWITCH end
Marko Mikulicic 0:c0ecb8bf28eb 25413 * <E>
Marko Mikulicic 0:c0ecb8bf28eb 25414 * DUP
Marko Mikulicic 0:c0ecb8bf28eb 25415 * <C1>
Marko Mikulicic 0:c0ecb8bf28eb 25416 * EQ
Marko Mikulicic 0:c0ecb8bf28eb 25417 * JMP_TRUE_DROP l1
Marko Mikulicic 0:c0ecb8bf28eb 25418 * DUP
Marko Mikulicic 0:c0ecb8bf28eb 25419 * <C2>
Marko Mikulicic 0:c0ecb8bf28eb 25420 * EQ
Marko Mikulicic 0:c0ecb8bf28eb 25421 * JMP_TRUE_DROP l2
Marko Mikulicic 0:c0ecb8bf28eb 25422 * DROP
Marko Mikulicic 0:c0ecb8bf28eb 25423 * JMP dfl
Marko Mikulicic 0:c0ecb8bf28eb 25424 *
Marko Mikulicic 0:c0ecb8bf28eb 25425 * dfl:
Marko Mikulicic 0:c0ecb8bf28eb 25426 * <D>
Marko Mikulicic 0:c0ecb8bf28eb 25427 *
Marko Mikulicic 0:c0ecb8bf28eb 25428 * l1:
Marko Mikulicic 0:c0ecb8bf28eb 25429 * <B1>
Marko Mikulicic 0:c0ecb8bf28eb 25430 *
Marko Mikulicic 0:c0ecb8bf28eb 25431 * l2:
Marko Mikulicic 0:c0ecb8bf28eb 25432 * <B2>
Marko Mikulicic 0:c0ecb8bf28eb 25433 *
Marko Mikulicic 0:c0ecb8bf28eb 25434 * end:
Marko Mikulicic 0:c0ecb8bf28eb 25435 * TRY_POP
Marko Mikulicic 0:c0ecb8bf28eb 25436 *
Marko Mikulicic 0:c0ecb8bf28eb 25437 * If the default case is missing we treat it as if had an empty body and
Marko Mikulicic 0:c0ecb8bf28eb 25438 * placed in last position (i.e. `dfl` label is replaced with `end`).
Marko Mikulicic 0:c0ecb8bf28eb 25439 *
Marko Mikulicic 0:c0ecb8bf28eb 25440 * Before emitting a case/default block (except the first one) we have to
Marko Mikulicic 0:c0ecb8bf28eb 25441 * drop the TOS resulting from evaluating the last expression
Marko Mikulicic 0:c0ecb8bf28eb 25442 */
Marko Mikulicic 0:c0ecb8bf28eb 25443 case AST_SWITCH: {
Marko Mikulicic 0:c0ecb8bf28eb 25444 bcode_off_t dfl_label, end_label;
Marko Mikulicic 0:c0ecb8bf28eb 25445 ast_off_t case_end, case_start;
Marko Mikulicic 0:c0ecb8bf28eb 25446 enum ast_tag case_tag;
Marko Mikulicic 0:c0ecb8bf28eb 25447 int i, has_default = 0, cases = 0;
Marko Mikulicic 0:c0ecb8bf28eb 25448
Marko Mikulicic 0:c0ecb8bf28eb 25449 end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25450
Marko Mikulicic 0:c0ecb8bf28eb 25451 end_label = bcode_op_target(bbuilder, OP_TRY_PUSH_SWITCH);
Marko Mikulicic 0:c0ecb8bf28eb 25452
Marko Mikulicic 0:c0ecb8bf28eb 25453 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 25454
Marko Mikulicic 0:c0ecb8bf28eb 25455 case_start = *ppos;
Marko Mikulicic 0:c0ecb8bf28eb 25456 /* first pass: evaluate case expression and generate jump table */
Marko Mikulicic 0:c0ecb8bf28eb 25457 while (*ppos < end) {
Marko Mikulicic 0:c0ecb8bf28eb 25458 case_tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25459 assert(case_tag == AST_DEFAULT || case_tag == AST_CASE);
Marko Mikulicic 0:c0ecb8bf28eb 25460
Marko Mikulicic 0:c0ecb8bf28eb 25461 case_end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25462
Marko Mikulicic 0:c0ecb8bf28eb 25463 switch (case_tag) {
Marko Mikulicic 0:c0ecb8bf28eb 25464 case AST_DEFAULT:
Marko Mikulicic 0:c0ecb8bf28eb 25465 /* default jump table entry must be the last one */
Marko Mikulicic 0:c0ecb8bf28eb 25466 break;
Marko Mikulicic 0:c0ecb8bf28eb 25467 case AST_CASE: {
Marko Mikulicic 0:c0ecb8bf28eb 25468 bcode_off_t case_label;
Marko Mikulicic 0:c0ecb8bf28eb 25469 bcode_op(bbuilder, OP_DUP);
Marko Mikulicic 0:c0ecb8bf28eb 25470 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 25471 bcode_op(bbuilder, OP_EQ);
Marko Mikulicic 0:c0ecb8bf28eb 25472 case_label = bcode_op_target(bbuilder, OP_JMP_TRUE_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 25473 cases++;
Marko Mikulicic 0:c0ecb8bf28eb 25474 mbuf_append(&case_labels, &case_label, sizeof(case_label));
Marko Mikulicic 0:c0ecb8bf28eb 25475 break;
Marko Mikulicic 0:c0ecb8bf28eb 25476 }
Marko Mikulicic 0:c0ecb8bf28eb 25477 default:
Marko Mikulicic 0:c0ecb8bf28eb 25478 assert(case_tag == AST_DEFAULT || case_tag == AST_CASE);
Marko Mikulicic 0:c0ecb8bf28eb 25479 }
Marko Mikulicic 0:c0ecb8bf28eb 25480 *ppos = case_end;
Marko Mikulicic 0:c0ecb8bf28eb 25481 }
Marko Mikulicic 0:c0ecb8bf28eb 25482
Marko Mikulicic 0:c0ecb8bf28eb 25483 /* jmp table epilogue: unconditional jump to default case */
Marko Mikulicic 0:c0ecb8bf28eb 25484 bcode_op(bbuilder, OP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 25485 dfl_label = bcode_op_target(bbuilder, OP_JMP);
Marko Mikulicic 0:c0ecb8bf28eb 25486
Marko Mikulicic 0:c0ecb8bf28eb 25487 *ppos = case_start;
Marko Mikulicic 0:c0ecb8bf28eb 25488 /* second pass: emit case bodies and patch jump table */
Marko Mikulicic 0:c0ecb8bf28eb 25489
Marko Mikulicic 0:c0ecb8bf28eb 25490 for (i = 0; *ppos < end;) {
Marko Mikulicic 0:c0ecb8bf28eb 25491 case_tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25492 assert(case_tag == AST_DEFAULT || case_tag == AST_CASE);
Marko Mikulicic 0:c0ecb8bf28eb 25493 assert(i <= cases);
Marko Mikulicic 0:c0ecb8bf28eb 25494
Marko Mikulicic 0:c0ecb8bf28eb 25495 case_end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25496
Marko Mikulicic 0:c0ecb8bf28eb 25497 switch (case_tag) {
Marko Mikulicic 0:c0ecb8bf28eb 25498 case AST_DEFAULT:
Marko Mikulicic 0:c0ecb8bf28eb 25499 has_default = 1;
Marko Mikulicic 0:c0ecb8bf28eb 25500 bcode_patch_target(bbuilder, dfl_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25501 V7_TRY(compile_stmts(bbuilder, a, ppos, case_end));
Marko Mikulicic 0:c0ecb8bf28eb 25502 break;
Marko Mikulicic 0:c0ecb8bf28eb 25503 case AST_CASE: {
Marko Mikulicic 0:c0ecb8bf28eb 25504 bcode_off_t case_label = ((bcode_off_t *) case_labels.buf)[i++];
Marko Mikulicic 0:c0ecb8bf28eb 25505 bcode_patch_target(bbuilder, case_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25506 ast_skip_tree(a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 25507 V7_TRY(compile_stmts(bbuilder, a, ppos, case_end));
Marko Mikulicic 0:c0ecb8bf28eb 25508 break;
Marko Mikulicic 0:c0ecb8bf28eb 25509 }
Marko Mikulicic 0:c0ecb8bf28eb 25510 default:
Marko Mikulicic 0:c0ecb8bf28eb 25511 assert(case_tag == AST_DEFAULT || case_tag == AST_CASE);
Marko Mikulicic 0:c0ecb8bf28eb 25512 }
Marko Mikulicic 0:c0ecb8bf28eb 25513
Marko Mikulicic 0:c0ecb8bf28eb 25514 *ppos = case_end;
Marko Mikulicic 0:c0ecb8bf28eb 25515 }
Marko Mikulicic 0:c0ecb8bf28eb 25516 mbuf_free(&case_labels);
Marko Mikulicic 0:c0ecb8bf28eb 25517
Marko Mikulicic 0:c0ecb8bf28eb 25518 if (!has_default) {
Marko Mikulicic 0:c0ecb8bf28eb 25519 bcode_patch_target(bbuilder, dfl_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25520 }
Marko Mikulicic 0:c0ecb8bf28eb 25521
Marko Mikulicic 0:c0ecb8bf28eb 25522 bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25523 bcode_op(bbuilder, OP_TRY_POP);
Marko Mikulicic 0:c0ecb8bf28eb 25524
Marko Mikulicic 0:c0ecb8bf28eb 25525 bbuilder->v7->is_stack_neutral = 1;
Marko Mikulicic 0:c0ecb8bf28eb 25526 break;
Marko Mikulicic 0:c0ecb8bf28eb 25527 }
Marko Mikulicic 0:c0ecb8bf28eb 25528 /*
Marko Mikulicic 0:c0ecb8bf28eb 25529 * for(INIT,COND,IT) {
Marko Mikulicic 0:c0ecb8bf28eb 25530 * B...
Marko Mikulicic 0:c0ecb8bf28eb 25531 * }
Marko Mikulicic 0:c0ecb8bf28eb 25532 *
Marko Mikulicic 0:c0ecb8bf28eb 25533 * ->
Marko Mikulicic 0:c0ecb8bf28eb 25534 *
Marko Mikulicic 0:c0ecb8bf28eb 25535 * <INIT>
Marko Mikulicic 0:c0ecb8bf28eb 25536 * DROP
Marko Mikulicic 0:c0ecb8bf28eb 25537 * TRY_PUSH_LOOP end
Marko Mikulicic 0:c0ecb8bf28eb 25538 * JMP cond
Marko Mikulicic 0:c0ecb8bf28eb 25539 * body:
Marko Mikulicic 0:c0ecb8bf28eb 25540 * <B>
Marko Mikulicic 0:c0ecb8bf28eb 25541 * next:
Marko Mikulicic 0:c0ecb8bf28eb 25542 * <IT>
Marko Mikulicic 0:c0ecb8bf28eb 25543 * DROP
Marko Mikulicic 0:c0ecb8bf28eb 25544 * cond:
Marko Mikulicic 0:c0ecb8bf28eb 25545 * <COND>
Marko Mikulicic 0:c0ecb8bf28eb 25546 * JMP_TRUE body
Marko Mikulicic 0:c0ecb8bf28eb 25547 * end:
Marko Mikulicic 0:c0ecb8bf28eb 25548 * JMP_IF_CONTINUE next
Marko Mikulicic 0:c0ecb8bf28eb 25549 * TRY_POP
Marko Mikulicic 0:c0ecb8bf28eb 25550 *
Marko Mikulicic 0:c0ecb8bf28eb 25551 */
Marko Mikulicic 0:c0ecb8bf28eb 25552 case AST_FOR: {
Marko Mikulicic 0:c0ecb8bf28eb 25553 ast_off_t iter, body, lookahead;
Marko Mikulicic 0:c0ecb8bf28eb 25554 bcode_off_t end_label, continue_label, continue_target;
Marko Mikulicic 0:c0ecb8bf28eb 25555 end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25556 body = ast_get_skip(a, pos_after_tag, AST_FOR_BODY_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25557
Marko Mikulicic 0:c0ecb8bf28eb 25558 lookahead = *ppos;
Marko Mikulicic 0:c0ecb8bf28eb 25559 tag = fetch_tag(v7, bbuilder, a, &lookahead, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25560 /*
Marko Mikulicic 0:c0ecb8bf28eb 25561 * Support for `var` declaration in INIT
Marko Mikulicic 0:c0ecb8bf28eb 25562 */
Marko Mikulicic 0:c0ecb8bf28eb 25563 if (tag == AST_VAR) {
Marko Mikulicic 0:c0ecb8bf28eb 25564 ast_off_t fvar_end;
Marko Mikulicic 0:c0ecb8bf28eb 25565 lit_t lit;
Marko Mikulicic 0:c0ecb8bf28eb 25566
Marko Mikulicic 0:c0ecb8bf28eb 25567 *ppos = lookahead;
Marko Mikulicic 0:c0ecb8bf28eb 25568 fvar_end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25569
Marko Mikulicic 0:c0ecb8bf28eb 25570 /*
Marko Mikulicic 0:c0ecb8bf28eb 25571 * Iterate through all vars in the given `var` declaration: they are
Marko Mikulicic 0:c0ecb8bf28eb 25572 * just like assigments here
Marko Mikulicic 0:c0ecb8bf28eb 25573 */
Marko Mikulicic 0:c0ecb8bf28eb 25574 while (*ppos < fvar_end) {
Marko Mikulicic 0:c0ecb8bf28eb 25575 tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25576 /* Only var declarations are allowed (not function declarations) */
Marko Mikulicic 0:c0ecb8bf28eb 25577 V7_CHECK_INTERNAL(tag == AST_VAR_DECL);
Marko Mikulicic 0:c0ecb8bf28eb 25578 lit = string_lit(bbuilder, a, pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25579 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 25580
Marko Mikulicic 0:c0ecb8bf28eb 25581 /* Just like an assigment */
Marko Mikulicic 0:c0ecb8bf28eb 25582 bcode_op_lit(bbuilder, OP_SET_VAR, lit);
Marko Mikulicic 0:c0ecb8bf28eb 25583
Marko Mikulicic 0:c0ecb8bf28eb 25584 /* INIT is stack-neutral */
Marko Mikulicic 0:c0ecb8bf28eb 25585 bcode_op(bbuilder, OP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 25586 }
Marko Mikulicic 0:c0ecb8bf28eb 25587 } else {
Marko Mikulicic 0:c0ecb8bf28eb 25588 /* normal expression in INIT (not `var` declaration) */
Marko Mikulicic 0:c0ecb8bf28eb 25589 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 25590 /* INIT is stack-neutral */
Marko Mikulicic 0:c0ecb8bf28eb 25591 bcode_op(bbuilder, OP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 25592 }
Marko Mikulicic 0:c0ecb8bf28eb 25593 cond = *ppos;
Marko Mikulicic 0:c0ecb8bf28eb 25594 ast_skip_tree(a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 25595 iter = *ppos;
Marko Mikulicic 0:c0ecb8bf28eb 25596 *ppos = body;
Marko Mikulicic 0:c0ecb8bf28eb 25597
Marko Mikulicic 0:c0ecb8bf28eb 25598 end_label = bcode_op_target(bbuilder, OP_TRY_PUSH_LOOP);
Marko Mikulicic 0:c0ecb8bf28eb 25599 cond_label = bcode_op_target(bbuilder, OP_JMP);
Marko Mikulicic 0:c0ecb8bf28eb 25600 body_target = bcode_pos(bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 25601 V7_TRY(compile_stmts(bbuilder, a, ppos, end));
Marko Mikulicic 0:c0ecb8bf28eb 25602
Marko Mikulicic 0:c0ecb8bf28eb 25603 continue_target = bcode_pos(bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 25604
Marko Mikulicic 0:c0ecb8bf28eb 25605 V7_TRY(compile_expr_builder(bbuilder, a, &iter));
Marko Mikulicic 0:c0ecb8bf28eb 25606 bcode_op(bbuilder, OP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 25607
Marko Mikulicic 0:c0ecb8bf28eb 25608 bcode_patch_target(bbuilder, cond_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25609
Marko Mikulicic 0:c0ecb8bf28eb 25610 /*
Marko Mikulicic 0:c0ecb8bf28eb 25611 * Handle for(INIT;;ITER)
Marko Mikulicic 0:c0ecb8bf28eb 25612 */
Marko Mikulicic 0:c0ecb8bf28eb 25613 lookahead = cond;
Marko Mikulicic 0:c0ecb8bf28eb 25614 tag = fetch_tag(v7, bbuilder, a, &lookahead, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25615 if (tag == AST_NOP) {
Marko Mikulicic 0:c0ecb8bf28eb 25616 bcode_op(bbuilder, OP_JMP);
Marko Mikulicic 0:c0ecb8bf28eb 25617 } else {
Marko Mikulicic 0:c0ecb8bf28eb 25618 V7_TRY(compile_expr_builder(bbuilder, a, &cond));
Marko Mikulicic 0:c0ecb8bf28eb 25619 bcode_op(bbuilder, OP_JMP_TRUE);
Marko Mikulicic 0:c0ecb8bf28eb 25620 }
Marko Mikulicic 0:c0ecb8bf28eb 25621 body_label = bcode_add_target(bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 25622 bcode_patch_target(bbuilder, body_label, body_target);
Marko Mikulicic 0:c0ecb8bf28eb 25623 bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25624
Marko Mikulicic 0:c0ecb8bf28eb 25625 continue_label = bcode_op_target(bbuilder, OP_JMP_IF_CONTINUE);
Marko Mikulicic 0:c0ecb8bf28eb 25626 bcode_patch_target(bbuilder, continue_label, continue_target);
Marko Mikulicic 0:c0ecb8bf28eb 25627
Marko Mikulicic 0:c0ecb8bf28eb 25628 bcode_op(bbuilder, OP_TRY_POP);
Marko Mikulicic 0:c0ecb8bf28eb 25629
Marko Mikulicic 0:c0ecb8bf28eb 25630 bbuilder->v7->is_stack_neutral = 1;
Marko Mikulicic 0:c0ecb8bf28eb 25631 break;
Marko Mikulicic 0:c0ecb8bf28eb 25632 }
Marko Mikulicic 0:c0ecb8bf28eb 25633 /*
Marko Mikulicic 0:c0ecb8bf28eb 25634 * for(I in O) {
Marko Mikulicic 0:c0ecb8bf28eb 25635 * B...
Marko Mikulicic 0:c0ecb8bf28eb 25636 * }
Marko Mikulicic 0:c0ecb8bf28eb 25637 *
Marko Mikulicic 0:c0ecb8bf28eb 25638 * ->
Marko Mikulicic 0:c0ecb8bf28eb 25639 *
Marko Mikulicic 0:c0ecb8bf28eb 25640 * DUP
Marko Mikulicic 0:c0ecb8bf28eb 25641 * <O>
Marko Mikulicic 0:c0ecb8bf28eb 25642 * SWAP
Marko Mikulicic 0:c0ecb8bf28eb 25643 * STASH
Marko Mikulicic 0:c0ecb8bf28eb 25644 * DROP
Marko Mikulicic 0:c0ecb8bf28eb 25645 * PUSH_PROP_ITER_CTX # push initial iteration context
Marko Mikulicic 0:c0ecb8bf28eb 25646 * TRY_PUSH_LOOP brend
Marko Mikulicic 0:c0ecb8bf28eb 25647 * loop:
Marko Mikulicic 0:c0ecb8bf28eb 25648 * NEXT_PROP
Marko Mikulicic 0:c0ecb8bf28eb 25649 * JMP_FALSE end
Marko Mikulicic 0:c0ecb8bf28eb 25650 * SET_VAR <I>
Marko Mikulicic 0:c0ecb8bf28eb 25651 * UNSTASH
Marko Mikulicic 0:c0ecb8bf28eb 25652 * <B>
Marko Mikulicic 0:c0ecb8bf28eb 25653 * next:
Marko Mikulicic 0:c0ecb8bf28eb 25654 * STASH
Marko Mikulicic 0:c0ecb8bf28eb 25655 * DROP
Marko Mikulicic 0:c0ecb8bf28eb 25656 * JMP loop
Marko Mikulicic 0:c0ecb8bf28eb 25657 * end:
Marko Mikulicic 0:c0ecb8bf28eb 25658 * UNSTASH
Marko Mikulicic 0:c0ecb8bf28eb 25659 * JMP try_pop:
Marko Mikulicic 0:c0ecb8bf28eb 25660 * brend:
Marko Mikulicic 0:c0ecb8bf28eb 25661 * # got here after a `break` or `continue` from a loop body:
Marko Mikulicic 0:c0ecb8bf28eb 25662 * JMP_IF_CONTINUE next
Marko Mikulicic 0:c0ecb8bf28eb 25663 *
Marko Mikulicic 0:c0ecb8bf28eb 25664 * # we're not going to `continue`, so, need to remove an
Marko Mikulicic 0:c0ecb8bf28eb 25665 * # extra stuff that was needed for the NEXT_PROP
Marko Mikulicic 0:c0ecb8bf28eb 25666 *
Marko Mikulicic 0:c0ecb8bf28eb 25667 * SWAP_DROP # drop iteration context
Marko Mikulicic 0:c0ecb8bf28eb 25668 * SWAP_DROP # drop <O>
Marko Mikulicic 0:c0ecb8bf28eb 25669 * SWAP_DROP # drop the value preceding the loop
Marko Mikulicic 0:c0ecb8bf28eb 25670 * try_pop:
Marko Mikulicic 0:c0ecb8bf28eb 25671 * TRY_POP
Marko Mikulicic 0:c0ecb8bf28eb 25672 *
Marko Mikulicic 0:c0ecb8bf28eb 25673 */
Marko Mikulicic 0:c0ecb8bf28eb 25674 case AST_FOR_IN: {
Marko Mikulicic 0:c0ecb8bf28eb 25675 lit_t lit;
Marko Mikulicic 0:c0ecb8bf28eb 25676 bcode_off_t loop_label, loop_target, end_label, brend_label,
Marko Mikulicic 0:c0ecb8bf28eb 25677 continue_label, pop_label, continue_target;
Marko Mikulicic 0:c0ecb8bf28eb 25678 ast_off_t end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25679
Marko Mikulicic 0:c0ecb8bf28eb 25680 tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25681 /* TODO(mkm) accept any l-value */
Marko Mikulicic 0:c0ecb8bf28eb 25682 if (tag == AST_VAR) {
Marko Mikulicic 0:c0ecb8bf28eb 25683 tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25684 V7_CHECK_INTERNAL(tag == AST_VAR_DECL);
Marko Mikulicic 0:c0ecb8bf28eb 25685 lit = string_lit(bbuilder, a, pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25686 ast_skip_tree(a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 25687 } else {
Marko Mikulicic 0:c0ecb8bf28eb 25688 V7_CHECK_INTERNAL(tag == AST_IDENT);
Marko Mikulicic 0:c0ecb8bf28eb 25689 lit = string_lit(bbuilder, a, pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25690 }
Marko Mikulicic 0:c0ecb8bf28eb 25691
Marko Mikulicic 0:c0ecb8bf28eb 25692 /*
Marko Mikulicic 0:c0ecb8bf28eb 25693 * preserve previous statement value.
Marko Mikulicic 0:c0ecb8bf28eb 25694 * We need to feed the previous value into the stash
Marko Mikulicic 0:c0ecb8bf28eb 25695 * because it's required for the loop steady state.
Marko Mikulicic 0:c0ecb8bf28eb 25696 *
Marko Mikulicic 0:c0ecb8bf28eb 25697 * The stash register is required to simplify the steady state stack
Marko Mikulicic 0:c0ecb8bf28eb 25698 * management, in particular the removal of value in 3rd position in case
Marko Mikulicic 0:c0ecb8bf28eb 25699 * a of not taken exit.
Marko Mikulicic 0:c0ecb8bf28eb 25700 *
Marko Mikulicic 0:c0ecb8bf28eb 25701 * TODO(mkm): consider having a stash OP that moves a value to the stash
Marko Mikulicic 0:c0ecb8bf28eb 25702 * register instead of copying it. The current behaviour has been
Marko Mikulicic 0:c0ecb8bf28eb 25703 * optimized for the `assign` use case which seems more common.
Marko Mikulicic 0:c0ecb8bf28eb 25704 */
Marko Mikulicic 0:c0ecb8bf28eb 25705 bcode_op(bbuilder, OP_DUP);
Marko Mikulicic 0:c0ecb8bf28eb 25706 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 25707 bcode_op(bbuilder, OP_SWAP);
Marko Mikulicic 0:c0ecb8bf28eb 25708 bcode_op(bbuilder, OP_STASH);
Marko Mikulicic 0:c0ecb8bf28eb 25709 bcode_op(bbuilder, OP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 25710
Marko Mikulicic 0:c0ecb8bf28eb 25711 /*
Marko Mikulicic 0:c0ecb8bf28eb 25712 * OP_NEXT_PROP needs the iteration context, let's push the initial one.
Marko Mikulicic 0:c0ecb8bf28eb 25713 */
Marko Mikulicic 0:c0ecb8bf28eb 25714 bcode_op(bbuilder, OP_PUSH_PROP_ITER_CTX);
Marko Mikulicic 0:c0ecb8bf28eb 25715
Marko Mikulicic 0:c0ecb8bf28eb 25716 brend_label = bcode_op_target(bbuilder, OP_TRY_PUSH_LOOP);
Marko Mikulicic 0:c0ecb8bf28eb 25717
Marko Mikulicic 0:c0ecb8bf28eb 25718 /* loop: */
Marko Mikulicic 0:c0ecb8bf28eb 25719 loop_target = bcode_pos(bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 25720
Marko Mikulicic 0:c0ecb8bf28eb 25721 /*
Marko Mikulicic 0:c0ecb8bf28eb 25722 * The loop stead state begins with the following stack layout:
Marko Mikulicic 0:c0ecb8bf28eb 25723 * `( S:v o h )`
Marko Mikulicic 0:c0ecb8bf28eb 25724 */
Marko Mikulicic 0:c0ecb8bf28eb 25725
Marko Mikulicic 0:c0ecb8bf28eb 25726 bcode_op(bbuilder, OP_NEXT_PROP);
Marko Mikulicic 0:c0ecb8bf28eb 25727 end_label = bcode_op_target(bbuilder, OP_JMP_FALSE);
Marko Mikulicic 0:c0ecb8bf28eb 25728 bcode_op_lit(bbuilder, OP_SET_VAR, lit);
Marko Mikulicic 0:c0ecb8bf28eb 25729
Marko Mikulicic 0:c0ecb8bf28eb 25730 /*
Marko Mikulicic 0:c0ecb8bf28eb 25731 * The stash register contains the value of the previous statement,
Marko Mikulicic 0:c0ecb8bf28eb 25732 * being it the statement before the for..in statement or
Marko Mikulicic 0:c0ecb8bf28eb 25733 * the previous iteration. We move it to the data stack. It will
Marko Mikulicic 0:c0ecb8bf28eb 25734 * be replaced by the values of the body statements as usual.
Marko Mikulicic 0:c0ecb8bf28eb 25735 */
Marko Mikulicic 0:c0ecb8bf28eb 25736 bcode_op(bbuilder, OP_UNSTASH);
Marko Mikulicic 0:c0ecb8bf28eb 25737
Marko Mikulicic 0:c0ecb8bf28eb 25738 /*
Marko Mikulicic 0:c0ecb8bf28eb 25739 * This node is always a NOP, for compatibility
Marko Mikulicic 0:c0ecb8bf28eb 25740 * with the layout of the AST_FOR node.
Marko Mikulicic 0:c0ecb8bf28eb 25741 */
Marko Mikulicic 0:c0ecb8bf28eb 25742 ast_skip_tree(a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 25743
Marko Mikulicic 0:c0ecb8bf28eb 25744 V7_TRY(compile_stmts(bbuilder, a, ppos, end));
Marko Mikulicic 0:c0ecb8bf28eb 25745
Marko Mikulicic 0:c0ecb8bf28eb 25746 continue_target = bcode_pos(bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 25747
Marko Mikulicic 0:c0ecb8bf28eb 25748 /*
Marko Mikulicic 0:c0ecb8bf28eb 25749 * Save the last body statement. If next evaluation of NEXT_PROP returns
Marko Mikulicic 0:c0ecb8bf28eb 25750 * false, we'll unstash it.
Marko Mikulicic 0:c0ecb8bf28eb 25751 */
Marko Mikulicic 0:c0ecb8bf28eb 25752 bcode_op(bbuilder, OP_STASH);
Marko Mikulicic 0:c0ecb8bf28eb 25753 bcode_op(bbuilder, OP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 25754
Marko Mikulicic 0:c0ecb8bf28eb 25755 loop_label = bcode_op_target(bbuilder, OP_JMP);
Marko Mikulicic 0:c0ecb8bf28eb 25756 bcode_patch_target(bbuilder, loop_label, loop_target);
Marko Mikulicic 0:c0ecb8bf28eb 25757
Marko Mikulicic 0:c0ecb8bf28eb 25758 /* end: */
Marko Mikulicic 0:c0ecb8bf28eb 25759 bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25760 bcode_op(bbuilder, OP_UNSTASH);
Marko Mikulicic 0:c0ecb8bf28eb 25761
Marko Mikulicic 0:c0ecb8bf28eb 25762 pop_label = bcode_op_target(bbuilder, OP_JMP);
Marko Mikulicic 0:c0ecb8bf28eb 25763
Marko Mikulicic 0:c0ecb8bf28eb 25764 /* brend: */
Marko Mikulicic 0:c0ecb8bf28eb 25765 bcode_patch_target(bbuilder, brend_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25766
Marko Mikulicic 0:c0ecb8bf28eb 25767 continue_label = bcode_op_target(bbuilder, OP_JMP_IF_CONTINUE);
Marko Mikulicic 0:c0ecb8bf28eb 25768 bcode_patch_target(bbuilder, continue_label, continue_target);
Marko Mikulicic 0:c0ecb8bf28eb 25769
Marko Mikulicic 0:c0ecb8bf28eb 25770 bcode_op(bbuilder, OP_SWAP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 25771 bcode_op(bbuilder, OP_SWAP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 25772 bcode_op(bbuilder, OP_SWAP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 25773
Marko Mikulicic 0:c0ecb8bf28eb 25774 /* try_pop: */
Marko Mikulicic 0:c0ecb8bf28eb 25775 bcode_patch_target(bbuilder, pop_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25776
Marko Mikulicic 0:c0ecb8bf28eb 25777 bcode_op(bbuilder, OP_TRY_POP);
Marko Mikulicic 0:c0ecb8bf28eb 25778
Marko Mikulicic 0:c0ecb8bf28eb 25779 bbuilder->v7->is_stack_neutral = 1;
Marko Mikulicic 0:c0ecb8bf28eb 25780 break;
Marko Mikulicic 0:c0ecb8bf28eb 25781 }
Marko Mikulicic 0:c0ecb8bf28eb 25782 /*
Marko Mikulicic 0:c0ecb8bf28eb 25783 * do {
Marko Mikulicic 0:c0ecb8bf28eb 25784 * B...
Marko Mikulicic 0:c0ecb8bf28eb 25785 * } while(COND);
Marko Mikulicic 0:c0ecb8bf28eb 25786 *
Marko Mikulicic 0:c0ecb8bf28eb 25787 * ->
Marko Mikulicic 0:c0ecb8bf28eb 25788 *
Marko Mikulicic 0:c0ecb8bf28eb 25789 * TRY_PUSH_LOOP end
Marko Mikulicic 0:c0ecb8bf28eb 25790 * body:
Marko Mikulicic 0:c0ecb8bf28eb 25791 * <B>
Marko Mikulicic 0:c0ecb8bf28eb 25792 * cond:
Marko Mikulicic 0:c0ecb8bf28eb 25793 * <COND>
Marko Mikulicic 0:c0ecb8bf28eb 25794 * JMP_TRUE body
Marko Mikulicic 0:c0ecb8bf28eb 25795 * end:
Marko Mikulicic 0:c0ecb8bf28eb 25796 * JMP_IF_CONTINUE cond
Marko Mikulicic 0:c0ecb8bf28eb 25797 * TRY_POP
Marko Mikulicic 0:c0ecb8bf28eb 25798 *
Marko Mikulicic 0:c0ecb8bf28eb 25799 */
Marko Mikulicic 0:c0ecb8bf28eb 25800 case AST_DOWHILE: {
Marko Mikulicic 0:c0ecb8bf28eb 25801 bcode_off_t end_label, continue_label, continue_target;
Marko Mikulicic 0:c0ecb8bf28eb 25802 end = ast_get_skip(a, pos_after_tag, AST_DO_WHILE_COND_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25803 end_label = bcode_op_target(bbuilder, OP_TRY_PUSH_LOOP);
Marko Mikulicic 0:c0ecb8bf28eb 25804 body_target = bcode_pos(bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 25805 V7_TRY(compile_stmts(bbuilder, a, ppos, end));
Marko Mikulicic 0:c0ecb8bf28eb 25806
Marko Mikulicic 0:c0ecb8bf28eb 25807 continue_target = bcode_pos(bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 25808 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 25809 body_label = bcode_op_target(bbuilder, OP_JMP_TRUE);
Marko Mikulicic 0:c0ecb8bf28eb 25810 bcode_patch_target(bbuilder, body_label, body_target);
Marko Mikulicic 0:c0ecb8bf28eb 25811
Marko Mikulicic 0:c0ecb8bf28eb 25812 bcode_patch_target(bbuilder, end_label, bcode_pos(bbuilder));
Marko Mikulicic 0:c0ecb8bf28eb 25813 continue_label = bcode_op_target(bbuilder, OP_JMP_IF_CONTINUE);
Marko Mikulicic 0:c0ecb8bf28eb 25814 bcode_patch_target(bbuilder, continue_label, continue_target);
Marko Mikulicic 0:c0ecb8bf28eb 25815 bcode_op(bbuilder, OP_TRY_POP);
Marko Mikulicic 0:c0ecb8bf28eb 25816
Marko Mikulicic 0:c0ecb8bf28eb 25817 bbuilder->v7->is_stack_neutral = 1;
Marko Mikulicic 0:c0ecb8bf28eb 25818 break;
Marko Mikulicic 0:c0ecb8bf28eb 25819 }
Marko Mikulicic 0:c0ecb8bf28eb 25820 case AST_VAR: {
Marko Mikulicic 0:c0ecb8bf28eb 25821 /*
Marko Mikulicic 0:c0ecb8bf28eb 25822 * Var decls are hoisted when the function frame is created. Vars
Marko Mikulicic 0:c0ecb8bf28eb 25823 * declared inside a `with` or `catch` block belong to the function
Marko Mikulicic 0:c0ecb8bf28eb 25824 * lexical scope, and although those clauses create an inner frame
Marko Mikulicic 0:c0ecb8bf28eb 25825 * no new variables should be created in it. A var decl thus
Marko Mikulicic 0:c0ecb8bf28eb 25826 * behaves as a normal assignment at runtime.
Marko Mikulicic 0:c0ecb8bf28eb 25827 */
Marko Mikulicic 0:c0ecb8bf28eb 25828 lit_t lit;
Marko Mikulicic 0:c0ecb8bf28eb 25829 end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25830 while (*ppos < end) {
Marko Mikulicic 0:c0ecb8bf28eb 25831 tag = fetch_tag(v7, bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25832 if (tag == AST_FUNC_DECL) {
Marko Mikulicic 0:c0ecb8bf28eb 25833 /*
Marko Mikulicic 0:c0ecb8bf28eb 25834 * function declarations are already set during hoisting (see
Marko Mikulicic 0:c0ecb8bf28eb 25835 * `compile_local_vars()`), so, skip it.
Marko Mikulicic 0:c0ecb8bf28eb 25836 *
Marko Mikulicic 0:c0ecb8bf28eb 25837 * Plus, they are stack-neutral, so don't forget to set
Marko Mikulicic 0:c0ecb8bf28eb 25838 * `is_stack_neutral`.
Marko Mikulicic 0:c0ecb8bf28eb 25839 */
Marko Mikulicic 0:c0ecb8bf28eb 25840 ast_skip_tree(a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 25841 bbuilder->v7->is_stack_neutral = 1;
Marko Mikulicic 0:c0ecb8bf28eb 25842 } else {
Marko Mikulicic 0:c0ecb8bf28eb 25843 /*
Marko Mikulicic 0:c0ecb8bf28eb 25844 * compile `var` declaration: basically it looks similar to an
Marko Mikulicic 0:c0ecb8bf28eb 25845 * assignment, but it differs from an assignment is that it's
Marko Mikulicic 0:c0ecb8bf28eb 25846 * stack-neutral: `1; var a = 5;` yields `1`, not `5`.
Marko Mikulicic 0:c0ecb8bf28eb 25847 */
Marko Mikulicic 0:c0ecb8bf28eb 25848 V7_CHECK_INTERNAL(tag == AST_VAR_DECL);
Marko Mikulicic 0:c0ecb8bf28eb 25849 lit = string_lit(bbuilder, a, pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25850 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 25851 bcode_op_lit(bbuilder, OP_SET_VAR, lit);
Marko Mikulicic 0:c0ecb8bf28eb 25852
Marko Mikulicic 0:c0ecb8bf28eb 25853 /* `var` declaration is stack-neutral */
Marko Mikulicic 0:c0ecb8bf28eb 25854 bcode_op(bbuilder, OP_DROP);
Marko Mikulicic 0:c0ecb8bf28eb 25855 bbuilder->v7->is_stack_neutral = 1;
Marko Mikulicic 0:c0ecb8bf28eb 25856 }
Marko Mikulicic 0:c0ecb8bf28eb 25857 }
Marko Mikulicic 0:c0ecb8bf28eb 25858 break;
Marko Mikulicic 0:c0ecb8bf28eb 25859 }
Marko Mikulicic 0:c0ecb8bf28eb 25860 case AST_RETURN:
Marko Mikulicic 0:c0ecb8bf28eb 25861 bcode_op(bbuilder, OP_PUSH_UNDEFINED);
Marko Mikulicic 0:c0ecb8bf28eb 25862 bcode_op(bbuilder, OP_RET);
Marko Mikulicic 0:c0ecb8bf28eb 25863 break;
Marko Mikulicic 0:c0ecb8bf28eb 25864 case AST_VALUE_RETURN:
Marko Mikulicic 0:c0ecb8bf28eb 25865 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 25866 bcode_op(bbuilder, OP_RET);
Marko Mikulicic 0:c0ecb8bf28eb 25867 break;
Marko Mikulicic 0:c0ecb8bf28eb 25868 default:
Marko Mikulicic 0:c0ecb8bf28eb 25869 *ppos = pos_after_tag - 1;
Marko Mikulicic 0:c0ecb8bf28eb 25870 V7_TRY(compile_expr_builder(bbuilder, a, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 25871 }
Marko Mikulicic 0:c0ecb8bf28eb 25872
Marko Mikulicic 0:c0ecb8bf28eb 25873 clean:
Marko Mikulicic 0:c0ecb8bf28eb 25874 mbuf_free(&case_labels);
Marko Mikulicic 0:c0ecb8bf28eb 25875 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 25876 }
Marko Mikulicic 0:c0ecb8bf28eb 25877
Marko Mikulicic 0:c0ecb8bf28eb 25878 static enum v7_err compile_body(struct bcode_builder *bbuilder, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 25879 ast_off_t start, ast_off_t end, ast_off_t body,
Marko Mikulicic 0:c0ecb8bf28eb 25880 ast_off_t fvar, ast_off_t *ppos) {
Marko Mikulicic 0:c0ecb8bf28eb 25881 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 25882 struct v7 *v7 = bbuilder->v7;
Marko Mikulicic 0:c0ecb8bf28eb 25883
Marko Mikulicic 0:c0ecb8bf28eb 25884 #ifndef V7_FORCE_STRICT_MODE
Marko Mikulicic 0:c0ecb8bf28eb 25885 /* check 'use strict' */
Marko Mikulicic 0:c0ecb8bf28eb 25886 if (*ppos < end) {
Marko Mikulicic 0:c0ecb8bf28eb 25887 ast_off_t tmp_pos = body;
Marko Mikulicic 0:c0ecb8bf28eb 25888 if (fetch_tag(v7, bbuilder, a, &tmp_pos, NULL) == AST_USE_STRICT) {
Marko Mikulicic 0:c0ecb8bf28eb 25889 bbuilder->bcode->strict_mode = 1;
Marko Mikulicic 0:c0ecb8bf28eb 25890 /* move `body` offset, effectively removing `AST_USE_STRICT` from it */
Marko Mikulicic 0:c0ecb8bf28eb 25891 body = tmp_pos;
Marko Mikulicic 0:c0ecb8bf28eb 25892 }
Marko Mikulicic 0:c0ecb8bf28eb 25893 }
Marko Mikulicic 0:c0ecb8bf28eb 25894 #endif
Marko Mikulicic 0:c0ecb8bf28eb 25895
Marko Mikulicic 0:c0ecb8bf28eb 25896 /* put initial value for the function body execution */
Marko Mikulicic 0:c0ecb8bf28eb 25897 bcode_op(bbuilder, OP_PUSH_UNDEFINED);
Marko Mikulicic 0:c0ecb8bf28eb 25898
Marko Mikulicic 0:c0ecb8bf28eb 25899 /*
Marko Mikulicic 0:c0ecb8bf28eb 25900 * populate `bcode->ops` with function's local variable names. Note that we
Marko Mikulicic 0:c0ecb8bf28eb 25901 * should do this *after* `OP_PUSH_UNDEFINED`, since `compile_local_vars`
Marko Mikulicic 0:c0ecb8bf28eb 25902 * emits code that assigns the hoisted functions to local variables, and
Marko Mikulicic 0:c0ecb8bf28eb 25903 * those statements assume that the stack contains `undefined`.
Marko Mikulicic 0:c0ecb8bf28eb 25904 */
Marko Mikulicic 0:c0ecb8bf28eb 25905 V7_TRY(compile_local_vars(bbuilder, a, start, fvar));
Marko Mikulicic 0:c0ecb8bf28eb 25906
Marko Mikulicic 0:c0ecb8bf28eb 25907 /* compile body */
Marko Mikulicic 0:c0ecb8bf28eb 25908 *ppos = body;
Marko Mikulicic 0:c0ecb8bf28eb 25909 V7_TRY(compile_stmts(bbuilder, a, ppos, end));
Marko Mikulicic 0:c0ecb8bf28eb 25910
Marko Mikulicic 0:c0ecb8bf28eb 25911 clean:
Marko Mikulicic 0:c0ecb8bf28eb 25912 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 25913 }
Marko Mikulicic 0:c0ecb8bf28eb 25914
Marko Mikulicic 0:c0ecb8bf28eb 25915 /*
Marko Mikulicic 0:c0ecb8bf28eb 25916 * Compiles a given script and populates a bcode structure.
Marko Mikulicic 0:c0ecb8bf28eb 25917 * The AST must start with an AST_SCRIPT node.
Marko Mikulicic 0:c0ecb8bf28eb 25918 */
Marko Mikulicic 0:c0ecb8bf28eb 25919 V7_PRIVATE enum v7_err compile_script(struct v7 *v7, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 25920 struct bcode *bcode) {
Marko Mikulicic 0:c0ecb8bf28eb 25921 ast_off_t pos_after_tag, end, fvar, pos = 0;
Marko Mikulicic 0:c0ecb8bf28eb 25922 int saved_line_no = v7->line_no;
Marko Mikulicic 0:c0ecb8bf28eb 25923 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 25924 struct bcode_builder bbuilder;
Marko Mikulicic 0:c0ecb8bf28eb 25925 enum ast_tag tag;
Marko Mikulicic 0:c0ecb8bf28eb 25926
Marko Mikulicic 0:c0ecb8bf28eb 25927 bcode_builder_init(v7, &bbuilder, bcode);
Marko Mikulicic 0:c0ecb8bf28eb 25928 v7->line_no = 1;
Marko Mikulicic 0:c0ecb8bf28eb 25929
Marko Mikulicic 0:c0ecb8bf28eb 25930 tag = fetch_tag(v7, &bbuilder, a, &pos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25931
Marko Mikulicic 0:c0ecb8bf28eb 25932 /* first tag should always be AST_SCRIPT */
Marko Mikulicic 0:c0ecb8bf28eb 25933 assert(tag == AST_SCRIPT);
Marko Mikulicic 0:c0ecb8bf28eb 25934 (void) tag;
Marko Mikulicic 0:c0ecb8bf28eb 25935
Marko Mikulicic 0:c0ecb8bf28eb 25936 end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25937 fvar = ast_get_skip(a, pos_after_tag, AST_FUNC_FIRST_VAR_SKIP) - 1;
Marko Mikulicic 0:c0ecb8bf28eb 25938
Marko Mikulicic 0:c0ecb8bf28eb 25939 V7_TRY(compile_body(&bbuilder, a, pos_after_tag - 1, end, pos /* body */,
Marko Mikulicic 0:c0ecb8bf28eb 25940 fvar, &pos));
Marko Mikulicic 0:c0ecb8bf28eb 25941
Marko Mikulicic 0:c0ecb8bf28eb 25942 clean:
Marko Mikulicic 0:c0ecb8bf28eb 25943
Marko Mikulicic 0:c0ecb8bf28eb 25944 bcode_builder_finalize(&bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 25945
Marko Mikulicic 0:c0ecb8bf28eb 25946 #ifdef V7_BCODE_DUMP
Marko Mikulicic 0:c0ecb8bf28eb 25947 if (rcode == V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 25948 fprintf(stderr, "--- script ---\n");
Marko Mikulicic 0:c0ecb8bf28eb 25949 dump_bcode(v7, stderr, bcode);
Marko Mikulicic 0:c0ecb8bf28eb 25950 }
Marko Mikulicic 0:c0ecb8bf28eb 25951 #endif
Marko Mikulicic 0:c0ecb8bf28eb 25952
Marko Mikulicic 0:c0ecb8bf28eb 25953 v7->line_no = saved_line_no;
Marko Mikulicic 0:c0ecb8bf28eb 25954
Marko Mikulicic 0:c0ecb8bf28eb 25955 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 25956 }
Marko Mikulicic 0:c0ecb8bf28eb 25957
Marko Mikulicic 0:c0ecb8bf28eb 25958 /*
Marko Mikulicic 0:c0ecb8bf28eb 25959 * Compiles a given function and populates a bcode structure.
Marko Mikulicic 0:c0ecb8bf28eb 25960 * The AST must contain an AST_FUNC node at offset ast_off.
Marko Mikulicic 0:c0ecb8bf28eb 25961 */
Marko Mikulicic 0:c0ecb8bf28eb 25962 V7_PRIVATE enum v7_err compile_function(struct v7 *v7, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 25963 ast_off_t *ppos, struct bcode *bcode) {
Marko Mikulicic 0:c0ecb8bf28eb 25964 ast_off_t pos_after_tag, start, end, body, fvar;
Marko Mikulicic 0:c0ecb8bf28eb 25965 const char *name;
Marko Mikulicic 0:c0ecb8bf28eb 25966 size_t name_len;
Marko Mikulicic 0:c0ecb8bf28eb 25967 size_t args_cnt;
Marko Mikulicic 0:c0ecb8bf28eb 25968 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 25969 struct bcode_builder bbuilder;
Marko Mikulicic 0:c0ecb8bf28eb 25970 enum ast_tag tag;
Marko Mikulicic 0:c0ecb8bf28eb 25971 size_t names_end = 0;
Marko Mikulicic 0:c0ecb8bf28eb 25972 bcode_builder_init(v7, &bbuilder, bcode);
Marko Mikulicic 0:c0ecb8bf28eb 25973 tag = fetch_tag(v7, &bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25974 start = pos_after_tag - 1;
Marko Mikulicic 0:c0ecb8bf28eb 25975
Marko Mikulicic 0:c0ecb8bf28eb 25976 (void) tag;
Marko Mikulicic 0:c0ecb8bf28eb 25977 assert(tag == AST_FUNC);
Marko Mikulicic 0:c0ecb8bf28eb 25978 end = ast_get_skip(a, pos_after_tag, AST_END_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25979 body = ast_get_skip(a, pos_after_tag, AST_FUNC_BODY_SKIP);
Marko Mikulicic 0:c0ecb8bf28eb 25980 fvar = ast_get_skip(a, pos_after_tag, AST_FUNC_FIRST_VAR_SKIP) - 1;
Marko Mikulicic 0:c0ecb8bf28eb 25981
Marko Mikulicic 0:c0ecb8bf28eb 25982 /* retrieve function name */
Marko Mikulicic 0:c0ecb8bf28eb 25983 tag = fetch_tag(v7, &bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 25984 if (tag == AST_IDENT) {
Marko Mikulicic 0:c0ecb8bf28eb 25985 /* function name is provided */
Marko Mikulicic 0:c0ecb8bf28eb 25986 name = ast_get_inlined_data(a, pos_after_tag, &name_len);
Marko Mikulicic 0:c0ecb8bf28eb 25987 V7_TRY(bcode_add_name(&bbuilder, name, name_len, &names_end));
Marko Mikulicic 0:c0ecb8bf28eb 25988 } else {
Marko Mikulicic 0:c0ecb8bf28eb 25989 /* no name: anonymous function */
Marko Mikulicic 0:c0ecb8bf28eb 25990 V7_TRY(bcode_add_name(&bbuilder, "", 0, &names_end));
Marko Mikulicic 0:c0ecb8bf28eb 25991 }
Marko Mikulicic 0:c0ecb8bf28eb 25992
Marko Mikulicic 0:c0ecb8bf28eb 25993 /* retrieve function's argument names */
Marko Mikulicic 0:c0ecb8bf28eb 25994 for (args_cnt = 0; *ppos < body; args_cnt++) {
Marko Mikulicic 0:c0ecb8bf28eb 25995 if (args_cnt > V7_ARGS_CNT_MAX) {
Marko Mikulicic 0:c0ecb8bf28eb 25996 /* too many arguments */
Marko Mikulicic 0:c0ecb8bf28eb 25997 rcode = v7_throwf(v7, SYNTAX_ERROR, "Too many arguments");
Marko Mikulicic 0:c0ecb8bf28eb 25998 V7_THROW(V7_SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 25999 }
Marko Mikulicic 0:c0ecb8bf28eb 26000
Marko Mikulicic 0:c0ecb8bf28eb 26001 tag = fetch_tag(v7, &bbuilder, a, ppos, &pos_after_tag);
Marko Mikulicic 0:c0ecb8bf28eb 26002 /*
Marko Mikulicic 0:c0ecb8bf28eb 26003 * TODO(dfrank): it's not actually an internal error, we get here if
Marko Mikulicic 0:c0ecb8bf28eb 26004 * we compile e.g. the following: (function(1){})
Marko Mikulicic 0:c0ecb8bf28eb 26005 */
Marko Mikulicic 0:c0ecb8bf28eb 26006 V7_CHECK_INTERNAL(tag == AST_IDENT);
Marko Mikulicic 0:c0ecb8bf28eb 26007 name = ast_get_inlined_data(a, pos_after_tag, &name_len);
Marko Mikulicic 0:c0ecb8bf28eb 26008 V7_TRY(bcode_add_name(&bbuilder, name, name_len, &names_end));
Marko Mikulicic 0:c0ecb8bf28eb 26009 }
Marko Mikulicic 0:c0ecb8bf28eb 26010
Marko Mikulicic 0:c0ecb8bf28eb 26011 bcode->args_cnt = args_cnt;
Marko Mikulicic 0:c0ecb8bf28eb 26012 bcode->func_name_present = 1;
Marko Mikulicic 0:c0ecb8bf28eb 26013
Marko Mikulicic 0:c0ecb8bf28eb 26014 V7_TRY(compile_body(&bbuilder, a, start, end, body, fvar, ppos));
Marko Mikulicic 0:c0ecb8bf28eb 26015
Marko Mikulicic 0:c0ecb8bf28eb 26016 clean:
Marko Mikulicic 0:c0ecb8bf28eb 26017 bcode_builder_finalize(&bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 26018
Marko Mikulicic 0:c0ecb8bf28eb 26019 #ifdef V7_BCODE_DUMP
Marko Mikulicic 0:c0ecb8bf28eb 26020 if (rcode == V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 26021 fprintf(stderr, "--- function ---\n");
Marko Mikulicic 0:c0ecb8bf28eb 26022 dump_bcode(v7, stderr, bcode);
Marko Mikulicic 0:c0ecb8bf28eb 26023 }
Marko Mikulicic 0:c0ecb8bf28eb 26024 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26025
Marko Mikulicic 0:c0ecb8bf28eb 26026 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 26027 }
Marko Mikulicic 0:c0ecb8bf28eb 26028
Marko Mikulicic 0:c0ecb8bf28eb 26029 V7_PRIVATE enum v7_err compile_expr(struct v7 *v7, struct ast *a,
Marko Mikulicic 0:c0ecb8bf28eb 26030 ast_off_t *ppos, struct bcode *bcode) {
Marko Mikulicic 0:c0ecb8bf28eb 26031 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 26032 struct bcode_builder bbuilder;
Marko Mikulicic 0:c0ecb8bf28eb 26033 int saved_line_no = v7->line_no;
Marko Mikulicic 0:c0ecb8bf28eb 26034
Marko Mikulicic 0:c0ecb8bf28eb 26035 bcode_builder_init(v7, &bbuilder, bcode);
Marko Mikulicic 0:c0ecb8bf28eb 26036 v7->line_no = 1;
Marko Mikulicic 0:c0ecb8bf28eb 26037
Marko Mikulicic 0:c0ecb8bf28eb 26038 rcode = compile_expr_builder(&bbuilder, a, ppos);
Marko Mikulicic 0:c0ecb8bf28eb 26039
Marko Mikulicic 0:c0ecb8bf28eb 26040 bcode_builder_finalize(&bbuilder);
Marko Mikulicic 0:c0ecb8bf28eb 26041 v7->line_no = saved_line_no;
Marko Mikulicic 0:c0ecb8bf28eb 26042 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 26043 }
Marko Mikulicic 0:c0ecb8bf28eb 26044
Marko Mikulicic 0:c0ecb8bf28eb 26045 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 26046 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 26047 #line 1 "v7/src/stdlib.c"
Marko Mikulicic 0:c0ecb8bf28eb 26048 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26049 /*
Marko Mikulicic 0:c0ecb8bf28eb 26050 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 26051 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 26052 */
Marko Mikulicic 0:c0ecb8bf28eb 26053
Marko Mikulicic 0:c0ecb8bf28eb 26054 /* Amalgamated: #include "common/cs_strtod.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26055
Marko Mikulicic 0:c0ecb8bf28eb 26056 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26057 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26058 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26059 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26060 /* Amalgamated: #include "v7/src/stdlib.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26061 /* Amalgamated: #include "v7/src/std_array.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26062 /* Amalgamated: #include "v7/src/std_boolean.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26063 /* Amalgamated: #include "v7/src/std_date.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26064 /* Amalgamated: #include "v7/src/std_error.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26065 /* Amalgamated: #include "v7/src/std_function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26066 /* Amalgamated: #include "v7/src/std_json.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26067 /* Amalgamated: #include "v7/src/std_math.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26068 /* Amalgamated: #include "v7/src/std_number.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26069 /* Amalgamated: #include "v7/src/std_object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26070 /* Amalgamated: #include "v7/src/std_regex.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26071 /* Amalgamated: #include "v7/src/std_string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26072 /* Amalgamated: #include "v7/src/std_proxy.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26073 /* Amalgamated: #include "v7/src/js_stdlib.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26074 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26075 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26076 /* Amalgamated: #include "v7/src/util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26077 /* Amalgamated: #include "v7/src/exec.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26078
Marko Mikulicic 0:c0ecb8bf28eb 26079 #ifdef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 26080 void print_str(const char *str);
Marko Mikulicic 0:c0ecb8bf28eb 26081 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26082
Marko Mikulicic 0:c0ecb8bf28eb 26083 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 26084 V7_PRIVATE enum v7_err Std_print(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 26085 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 26086 int i, num_args = v7_argc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26087 val_t v;
Marko Mikulicic 0:c0ecb8bf28eb 26088
Marko Mikulicic 0:c0ecb8bf28eb 26089 (void) res;
Marko Mikulicic 0:c0ecb8bf28eb 26090
Marko Mikulicic 0:c0ecb8bf28eb 26091 for (i = 0; i < num_args; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 26092 v = v7_arg(v7, i);
Marko Mikulicic 0:c0ecb8bf28eb 26093 if (v7_is_string(v)) {
Marko Mikulicic 0:c0ecb8bf28eb 26094 size_t n;
Marko Mikulicic 0:c0ecb8bf28eb 26095 const char *s = v7_get_string(v7, &v, &n);
Marko Mikulicic 0:c0ecb8bf28eb 26096 printf("%.*s", (int) n, s);
Marko Mikulicic 0:c0ecb8bf28eb 26097 } else {
Marko Mikulicic 0:c0ecb8bf28eb 26098 v7_print(v7, v);
Marko Mikulicic 0:c0ecb8bf28eb 26099 }
Marko Mikulicic 0:c0ecb8bf28eb 26100 printf(" ");
Marko Mikulicic 0:c0ecb8bf28eb 26101 }
Marko Mikulicic 0:c0ecb8bf28eb 26102 printf(ENDL);
Marko Mikulicic 0:c0ecb8bf28eb 26103
Marko Mikulicic 0:c0ecb8bf28eb 26104 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 26105 }
Marko Mikulicic 0:c0ecb8bf28eb 26106
Marko Mikulicic 0:c0ecb8bf28eb 26107 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 26108 V7_PRIVATE enum v7_err std_eval(struct v7 *v7, v7_val_t arg, val_t this_obj,
Marko Mikulicic 0:c0ecb8bf28eb 26109 int is_json, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 26110 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 26111 char buf[100], *p = buf;
Marko Mikulicic 0:c0ecb8bf28eb 26112 struct v7_exec_opts opts;
Marko Mikulicic 0:c0ecb8bf28eb 26113 memset(&opts, 0x00, sizeof(opts));
Marko Mikulicic 0:c0ecb8bf28eb 26114 opts.filename = "Eval'd code";
Marko Mikulicic 0:c0ecb8bf28eb 26115
Marko Mikulicic 0:c0ecb8bf28eb 26116 if (arg != V7_UNDEFINED) {
Marko Mikulicic 0:c0ecb8bf28eb 26117 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 26118 rcode = to_string(v7, arg, NULL, buf, sizeof(buf), &len);
Marko Mikulicic 0:c0ecb8bf28eb 26119 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 26120 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 26121 }
Marko Mikulicic 0:c0ecb8bf28eb 26122
Marko Mikulicic 0:c0ecb8bf28eb 26123 /* Fit null terminating byte and quotes */
Marko Mikulicic 0:c0ecb8bf28eb 26124 if (len >= sizeof(buf) - 2) {
Marko Mikulicic 0:c0ecb8bf28eb 26125 /* Buffer is not large enough. Allocate a bigger one */
Marko Mikulicic 0:c0ecb8bf28eb 26126 p = (char *) malloc(len + 3);
Marko Mikulicic 0:c0ecb8bf28eb 26127 rcode = to_string(v7, arg, NULL, p, len + 2, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 26128 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 26129 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 26130 }
Marko Mikulicic 0:c0ecb8bf28eb 26131 }
Marko Mikulicic 0:c0ecb8bf28eb 26132
Marko Mikulicic 0:c0ecb8bf28eb 26133 v7_set_gc_enabled(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 26134 if (is_json) {
Marko Mikulicic 0:c0ecb8bf28eb 26135 opts.is_json = 1;
Marko Mikulicic 0:c0ecb8bf28eb 26136 } else {
Marko Mikulicic 0:c0ecb8bf28eb 26137 opts.this_obj = this_obj;
Marko Mikulicic 0:c0ecb8bf28eb 26138 }
Marko Mikulicic 0:c0ecb8bf28eb 26139 rcode = v7_exec_opt(v7, p, &opts, res);
Marko Mikulicic 0:c0ecb8bf28eb 26140 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 26141 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 26142 }
Marko Mikulicic 0:c0ecb8bf28eb 26143 }
Marko Mikulicic 0:c0ecb8bf28eb 26144
Marko Mikulicic 0:c0ecb8bf28eb 26145 clean:
Marko Mikulicic 0:c0ecb8bf28eb 26146 if (p != buf) {
Marko Mikulicic 0:c0ecb8bf28eb 26147 free(p);
Marko Mikulicic 0:c0ecb8bf28eb 26148 }
Marko Mikulicic 0:c0ecb8bf28eb 26149
Marko Mikulicic 0:c0ecb8bf28eb 26150 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 26151 }
Marko Mikulicic 0:c0ecb8bf28eb 26152
Marko Mikulicic 0:c0ecb8bf28eb 26153 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 26154 V7_PRIVATE enum v7_err Std_eval(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 26155 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26156 v7_val_t arg = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 26157 return std_eval(v7, arg, this_obj, 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 26158 }
Marko Mikulicic 0:c0ecb8bf28eb 26159
Marko Mikulicic 0:c0ecb8bf28eb 26160 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 26161 V7_PRIVATE enum v7_err Std_parseInt(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 26162 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 26163 v7_val_t arg0 = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 26164 v7_val_t arg1 = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 26165 long sign = 1, base, n;
Marko Mikulicic 0:c0ecb8bf28eb 26166 char buf[20], *p = buf, *end;
Marko Mikulicic 0:c0ecb8bf28eb 26167
Marko Mikulicic 0:c0ecb8bf28eb 26168 *res = V7_TAG_NAN;
Marko Mikulicic 0:c0ecb8bf28eb 26169
Marko Mikulicic 0:c0ecb8bf28eb 26170 arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 26171 arg1 = v7_arg(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 26172
Marko Mikulicic 0:c0ecb8bf28eb 26173 rcode = to_string(v7, arg0, &arg0, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 26174 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 26175 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 26176 }
Marko Mikulicic 0:c0ecb8bf28eb 26177
Marko Mikulicic 0:c0ecb8bf28eb 26178 rcode = to_number_v(v7, arg1, &arg1);
Marko Mikulicic 0:c0ecb8bf28eb 26179 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 26180 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 26181 }
Marko Mikulicic 0:c0ecb8bf28eb 26182
Marko Mikulicic 0:c0ecb8bf28eb 26183 if (is_finite(v7, arg1)) {
Marko Mikulicic 0:c0ecb8bf28eb 26184 base = v7_get_double(v7, arg1);
Marko Mikulicic 0:c0ecb8bf28eb 26185 } else {
Marko Mikulicic 0:c0ecb8bf28eb 26186 base = 0;
Marko Mikulicic 0:c0ecb8bf28eb 26187 }
Marko Mikulicic 0:c0ecb8bf28eb 26188
Marko Mikulicic 0:c0ecb8bf28eb 26189 if (base == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 26190 base = 10;
Marko Mikulicic 0:c0ecb8bf28eb 26191 }
Marko Mikulicic 0:c0ecb8bf28eb 26192
Marko Mikulicic 0:c0ecb8bf28eb 26193 if (base < 2 || base > 36) {
Marko Mikulicic 0:c0ecb8bf28eb 26194 *res = V7_TAG_NAN;
Marko Mikulicic 0:c0ecb8bf28eb 26195 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 26196 }
Marko Mikulicic 0:c0ecb8bf28eb 26197
Marko Mikulicic 0:c0ecb8bf28eb 26198 {
Marko Mikulicic 0:c0ecb8bf28eb 26199 size_t str_len;
Marko Mikulicic 0:c0ecb8bf28eb 26200 p = (char *) v7_get_string(v7, &arg0, &str_len);
Marko Mikulicic 0:c0ecb8bf28eb 26201 }
Marko Mikulicic 0:c0ecb8bf28eb 26202
Marko Mikulicic 0:c0ecb8bf28eb 26203 /* Strip leading whitespaces */
Marko Mikulicic 0:c0ecb8bf28eb 26204 while (*p != '\0' && isspace(*(unsigned char *) p)) {
Marko Mikulicic 0:c0ecb8bf28eb 26205 p++;
Marko Mikulicic 0:c0ecb8bf28eb 26206 }
Marko Mikulicic 0:c0ecb8bf28eb 26207
Marko Mikulicic 0:c0ecb8bf28eb 26208 if (*p == '+') {
Marko Mikulicic 0:c0ecb8bf28eb 26209 sign = 1;
Marko Mikulicic 0:c0ecb8bf28eb 26210 p++;
Marko Mikulicic 0:c0ecb8bf28eb 26211 } else if (*p == '-') {
Marko Mikulicic 0:c0ecb8bf28eb 26212 sign = -1;
Marko Mikulicic 0:c0ecb8bf28eb 26213 p++;
Marko Mikulicic 0:c0ecb8bf28eb 26214 }
Marko Mikulicic 0:c0ecb8bf28eb 26215
Marko Mikulicic 0:c0ecb8bf28eb 26216 if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
Marko Mikulicic 0:c0ecb8bf28eb 26217 base = 16;
Marko Mikulicic 0:c0ecb8bf28eb 26218 p += 2;
Marko Mikulicic 0:c0ecb8bf28eb 26219 }
Marko Mikulicic 0:c0ecb8bf28eb 26220
Marko Mikulicic 0:c0ecb8bf28eb 26221 n = strtol(p, &end, base);
Marko Mikulicic 0:c0ecb8bf28eb 26222
Marko Mikulicic 0:c0ecb8bf28eb 26223 *res = (p == end) ? V7_TAG_NAN : v7_mk_number(v7, n * sign);
Marko Mikulicic 0:c0ecb8bf28eb 26224
Marko Mikulicic 0:c0ecb8bf28eb 26225 clean:
Marko Mikulicic 0:c0ecb8bf28eb 26226 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 26227 }
Marko Mikulicic 0:c0ecb8bf28eb 26228
Marko Mikulicic 0:c0ecb8bf28eb 26229 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 26230 V7_PRIVATE enum v7_err Std_parseFloat(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 26231 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 26232 v7_val_t arg0 = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 26233 char buf[20], *p = buf, *end;
Marko Mikulicic 0:c0ecb8bf28eb 26234 double result;
Marko Mikulicic 0:c0ecb8bf28eb 26235
Marko Mikulicic 0:c0ecb8bf28eb 26236 rcode = to_primitive(v7, v7_arg(v7, 0), V7_TO_PRIMITIVE_HINT_NUMBER, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 26237 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 26238 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 26239 }
Marko Mikulicic 0:c0ecb8bf28eb 26240
Marko Mikulicic 0:c0ecb8bf28eb 26241 if (v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 26242 size_t str_len;
Marko Mikulicic 0:c0ecb8bf28eb 26243 p = (char *) v7_get_string(v7, &arg0, &str_len);
Marko Mikulicic 0:c0ecb8bf28eb 26244 } else {
Marko Mikulicic 0:c0ecb8bf28eb 26245 rcode = to_string(v7, arg0, NULL, buf, sizeof(buf), NULL);
Marko Mikulicic 0:c0ecb8bf28eb 26246 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 26247 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 26248 }
Marko Mikulicic 0:c0ecb8bf28eb 26249 buf[sizeof(buf) - 1] = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 26250 }
Marko Mikulicic 0:c0ecb8bf28eb 26251
Marko Mikulicic 0:c0ecb8bf28eb 26252 while (*p != '\0' && isspace(*(unsigned char *) p)) {
Marko Mikulicic 0:c0ecb8bf28eb 26253 p++;
Marko Mikulicic 0:c0ecb8bf28eb 26254 }
Marko Mikulicic 0:c0ecb8bf28eb 26255
Marko Mikulicic 0:c0ecb8bf28eb 26256 result = cs_strtod(p, &end);
Marko Mikulicic 0:c0ecb8bf28eb 26257
Marko Mikulicic 0:c0ecb8bf28eb 26258 *res = (p == end) ? V7_TAG_NAN : v7_mk_number(v7, result);
Marko Mikulicic 0:c0ecb8bf28eb 26259
Marko Mikulicic 0:c0ecb8bf28eb 26260 clean:
Marko Mikulicic 0:c0ecb8bf28eb 26261 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 26262 }
Marko Mikulicic 0:c0ecb8bf28eb 26263
Marko Mikulicic 0:c0ecb8bf28eb 26264 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 26265 V7_PRIVATE enum v7_err Std_isNaN(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 26266 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 26267 v7_val_t arg0 = V7_TAG_NAN;
Marko Mikulicic 0:c0ecb8bf28eb 26268 rcode = to_number_v(v7, v7_arg(v7, 0), &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 26269 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 26270 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 26271 }
Marko Mikulicic 0:c0ecb8bf28eb 26272
Marko Mikulicic 0:c0ecb8bf28eb 26273 *res = v7_mk_boolean(v7, isnan(v7_get_double(v7, arg0)));
Marko Mikulicic 0:c0ecb8bf28eb 26274
Marko Mikulicic 0:c0ecb8bf28eb 26275 clean:
Marko Mikulicic 0:c0ecb8bf28eb 26276 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 26277 }
Marko Mikulicic 0:c0ecb8bf28eb 26278
Marko Mikulicic 0:c0ecb8bf28eb 26279 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 26280 V7_PRIVATE enum v7_err Std_isFinite(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 26281 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 26282 v7_val_t arg0 = V7_TAG_NAN;
Marko Mikulicic 0:c0ecb8bf28eb 26283
Marko Mikulicic 0:c0ecb8bf28eb 26284 rcode = to_number_v(v7, v7_arg(v7, 0), &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 26285 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 26286 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 26287 }
Marko Mikulicic 0:c0ecb8bf28eb 26288
Marko Mikulicic 0:c0ecb8bf28eb 26289 *res = v7_mk_boolean(v7, is_finite(v7, arg0));
Marko Mikulicic 0:c0ecb8bf28eb 26290
Marko Mikulicic 0:c0ecb8bf28eb 26291 clean:
Marko Mikulicic 0:c0ecb8bf28eb 26292 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 26293 }
Marko Mikulicic 0:c0ecb8bf28eb 26294
Marko Mikulicic 0:c0ecb8bf28eb 26295 #ifndef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 26296 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 26297 V7_PRIVATE enum v7_err Std_exit(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 26298 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 26299 long exit_code;
Marko Mikulicic 0:c0ecb8bf28eb 26300
Marko Mikulicic 0:c0ecb8bf28eb 26301 (void) res;
Marko Mikulicic 0:c0ecb8bf28eb 26302
Marko Mikulicic 0:c0ecb8bf28eb 26303 rcode = to_long(v7, v7_arg(v7, 0), 0, &exit_code);
Marko Mikulicic 0:c0ecb8bf28eb 26304 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 26305 /* `to_long` has thrown, so, will return 1 */
Marko Mikulicic 0:c0ecb8bf28eb 26306 exit_code = 1;
Marko Mikulicic 0:c0ecb8bf28eb 26307 }
Marko Mikulicic 0:c0ecb8bf28eb 26308 exit(exit_code);
Marko Mikulicic 0:c0ecb8bf28eb 26309
Marko Mikulicic 0:c0ecb8bf28eb 26310 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 26311 }
Marko Mikulicic 0:c0ecb8bf28eb 26312 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26313
Marko Mikulicic 0:c0ecb8bf28eb 26314 /*
Marko Mikulicic 0:c0ecb8bf28eb 26315 * Initialize standard library.
Marko Mikulicic 0:c0ecb8bf28eb 26316 *
Marko Mikulicic 0:c0ecb8bf28eb 26317 * This function is used only internally, but used in a complicated mix of
Marko Mikulicic 0:c0ecb8bf28eb 26318 * configurations, hence the commented V7_PRIVATE
Marko Mikulicic 0:c0ecb8bf28eb 26319 */
Marko Mikulicic 0:c0ecb8bf28eb 26320 /*V7_PRIVATE*/ void init_stdlib(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 26321 v7_prop_attr_desc_t attr_internal =
Marko Mikulicic 0:c0ecb8bf28eb 26322 (V7_DESC_ENUMERABLE(0) | V7_DESC_WRITABLE(0) | V7_DESC_CONFIGURABLE(0));
Marko Mikulicic 0:c0ecb8bf28eb 26323
Marko Mikulicic 0:c0ecb8bf28eb 26324 /*
Marko Mikulicic 0:c0ecb8bf28eb 26325 * Ensure the first call to v7_mk_value will use a null proto:
Marko Mikulicic 0:c0ecb8bf28eb 26326 * {}.__proto__.__proto__ == null
Marko Mikulicic 0:c0ecb8bf28eb 26327 */
Marko Mikulicic 0:c0ecb8bf28eb 26328 v7->vals.object_prototype = mk_object(v7, V7_NULL);
Marko Mikulicic 0:c0ecb8bf28eb 26329 v7->vals.array_prototype = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26330 v7->vals.boolean_prototype = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26331 v7->vals.string_prototype = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26332 v7->vals.regexp_prototype = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26333 v7->vals.number_prototype = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26334 v7->vals.error_prototype = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26335 v7->vals.global_object = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26336 v7->vals.date_prototype = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26337 v7->vals.function_prototype = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26338 v7->vals.proxy_prototype = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26339
Marko Mikulicic 0:c0ecb8bf28eb 26340 set_method(v7, v7->vals.global_object, "eval", Std_eval, 1);
Marko Mikulicic 0:c0ecb8bf28eb 26341 set_method(v7, v7->vals.global_object, "print", Std_print, 1);
Marko Mikulicic 0:c0ecb8bf28eb 26342 #ifndef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 26343 set_method(v7, v7->vals.global_object, "exit", Std_exit, 1);
Marko Mikulicic 0:c0ecb8bf28eb 26344 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26345 set_method(v7, v7->vals.global_object, "parseInt", Std_parseInt, 2);
Marko Mikulicic 0:c0ecb8bf28eb 26346 set_method(v7, v7->vals.global_object, "parseFloat", Std_parseFloat, 1);
Marko Mikulicic 0:c0ecb8bf28eb 26347 set_method(v7, v7->vals.global_object, "isNaN", Std_isNaN, 1);
Marko Mikulicic 0:c0ecb8bf28eb 26348 set_method(v7, v7->vals.global_object, "isFinite", Std_isFinite, 1);
Marko Mikulicic 0:c0ecb8bf28eb 26349
Marko Mikulicic 0:c0ecb8bf28eb 26350 v7_def(v7, v7->vals.global_object, "Infinity", 8, attr_internal,
Marko Mikulicic 0:c0ecb8bf28eb 26351 v7_mk_number(v7, INFINITY));
Marko Mikulicic 0:c0ecb8bf28eb 26352 v7_set(v7, v7->vals.global_object, "global", 6, v7->vals.global_object);
Marko Mikulicic 0:c0ecb8bf28eb 26353
Marko Mikulicic 0:c0ecb8bf28eb 26354 init_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26355 init_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26356 init_error(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26357 init_boolean(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26358 #if V7_ENABLE__Math
Marko Mikulicic 0:c0ecb8bf28eb 26359 init_math(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26360 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26361 init_string(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26362 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 26363 init_regex(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26364 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26365 init_number(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26366 init_json(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26367 #if V7_ENABLE__Date
Marko Mikulicic 0:c0ecb8bf28eb 26368 init_date(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26369 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26370 init_function(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26371 init_js_stdlib(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26372
Marko Mikulicic 0:c0ecb8bf28eb 26373 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 26374 init_proxy(v7);
Marko Mikulicic 0:c0ecb8bf28eb 26375 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26376 }
Marko Mikulicic 0:c0ecb8bf28eb 26377 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 26378 #line 1 "v7/src/js_stdlib.c"
Marko Mikulicic 0:c0ecb8bf28eb 26379 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26380 /*
Marko Mikulicic 0:c0ecb8bf28eb 26381 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 26382 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 26383 */
Marko Mikulicic 0:c0ecb8bf28eb 26384
Marko Mikulicic 0:c0ecb8bf28eb 26385 /* clang-format off */
Marko Mikulicic 0:c0ecb8bf28eb 26386 /* because clang-format would break JS code, e.g. === converted to == = ... */
Marko Mikulicic 0:c0ecb8bf28eb 26387
Marko Mikulicic 0:c0ecb8bf28eb 26388 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26389 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26390 /* Amalgamated: #include "v7/src/exec.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26391 /* Amalgamated: #include "v7/src/util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26392
Marko Mikulicic 0:c0ecb8bf28eb 26393 #define STRINGIFY(x) #x
Marko Mikulicic 0:c0ecb8bf28eb 26394
Marko Mikulicic 0:c0ecb8bf28eb 26395 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 26396 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 26397 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 26398
Marko Mikulicic 0:c0ecb8bf28eb 26399 static const char js_array_indexOf[] = STRINGIFY(
Marko Mikulicic 0:c0ecb8bf28eb 26400 Object.defineProperty(Array.prototype, "indexOf", {
Marko Mikulicic 0:c0ecb8bf28eb 26401 writable:true,
Marko Mikulicic 0:c0ecb8bf28eb 26402 configurable: true,
Marko Mikulicic 0:c0ecb8bf28eb 26403 value: function(a, x) {
Marko Mikulicic 0:c0ecb8bf28eb 26404 var i; var r = -1; var b = +x;
Marko Mikulicic 0:c0ecb8bf28eb 26405 if (!b || b < 0) b = 0;
Marko Mikulicic 0:c0ecb8bf28eb 26406 for (i in this) if (i >= b && (r < 0 || i < r) && this[i] === a) r = +i;
Marko Mikulicic 0:c0ecb8bf28eb 26407 return r;
Marko Mikulicic 0:c0ecb8bf28eb 26408 }}););
Marko Mikulicic 0:c0ecb8bf28eb 26409
Marko Mikulicic 0:c0ecb8bf28eb 26410 static const char js_array_lastIndexOf[] = STRINGIFY(
Marko Mikulicic 0:c0ecb8bf28eb 26411 Object.defineProperty(Array.prototype, "lastIndexOf", {
Marko Mikulicic 0:c0ecb8bf28eb 26412 writable:true,
Marko Mikulicic 0:c0ecb8bf28eb 26413 configurable: true,
Marko Mikulicic 0:c0ecb8bf28eb 26414 value: function(a, x) {
Marko Mikulicic 0:c0ecb8bf28eb 26415 var i; var r = -1; var b = +x;
Marko Mikulicic 0:c0ecb8bf28eb 26416 if (isNaN(b) || b < 0 || b >= this.length) b = this.length - 1;
Marko Mikulicic 0:c0ecb8bf28eb 26417 for (i in this) if (i <= b && (r < 0 || i > r) && this[i] === a) r = +i;
Marko Mikulicic 0:c0ecb8bf28eb 26418 return r;
Marko Mikulicic 0:c0ecb8bf28eb 26419 }}););
Marko Mikulicic 0:c0ecb8bf28eb 26420
Marko Mikulicic 0:c0ecb8bf28eb 26421 #if V7_ENABLE__Array__reduce
Marko Mikulicic 0:c0ecb8bf28eb 26422 static const char js_array_reduce[] = STRINGIFY(
Marko Mikulicic 0:c0ecb8bf28eb 26423 Object.defineProperty(Array.prototype, "reduce", {
Marko Mikulicic 0:c0ecb8bf28eb 26424 writable:true,
Marko Mikulicic 0:c0ecb8bf28eb 26425 configurable: true,
Marko Mikulicic 0:c0ecb8bf28eb 26426 value: function(a, b) {
Marko Mikulicic 0:c0ecb8bf28eb 26427 var f = 0;
Marko Mikulicic 0:c0ecb8bf28eb 26428 if (typeof(a) != "function") {
Marko Mikulicic 0:c0ecb8bf28eb 26429 throw new TypeError(a + " is not a function");
Marko Mikulicic 0:c0ecb8bf28eb 26430 }
Marko Mikulicic 0:c0ecb8bf28eb 26431 for (var k in this) {
Marko Mikulicic 0:c0ecb8bf28eb 26432 if (k > this.length) break;
Marko Mikulicic 0:c0ecb8bf28eb 26433 if (f == 0 && b === undefined) {
Marko Mikulicic 0:c0ecb8bf28eb 26434 b = this[k];
Marko Mikulicic 0:c0ecb8bf28eb 26435 f = 1;
Marko Mikulicic 0:c0ecb8bf28eb 26436 } else {
Marko Mikulicic 0:c0ecb8bf28eb 26437 b = a(b, this[k], k, this);
Marko Mikulicic 0:c0ecb8bf28eb 26438 }
Marko Mikulicic 0:c0ecb8bf28eb 26439 }
Marko Mikulicic 0:c0ecb8bf28eb 26440 return b;
Marko Mikulicic 0:c0ecb8bf28eb 26441 }}););
Marko Mikulicic 0:c0ecb8bf28eb 26442 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26443
Marko Mikulicic 0:c0ecb8bf28eb 26444 static const char js_array_pop[] = STRINGIFY(
Marko Mikulicic 0:c0ecb8bf28eb 26445 Object.defineProperty(Array.prototype, "pop", {
Marko Mikulicic 0:c0ecb8bf28eb 26446 writable:true,
Marko Mikulicic 0:c0ecb8bf28eb 26447 configurable: true,
Marko Mikulicic 0:c0ecb8bf28eb 26448 value: function() {
Marko Mikulicic 0:c0ecb8bf28eb 26449 var i = this.length - 1;
Marko Mikulicic 0:c0ecb8bf28eb 26450 return this.splice(i, 1)[0];
Marko Mikulicic 0:c0ecb8bf28eb 26451 }}););
Marko Mikulicic 0:c0ecb8bf28eb 26452
Marko Mikulicic 0:c0ecb8bf28eb 26453 static const char js_array_shift[] = STRINGIFY(
Marko Mikulicic 0:c0ecb8bf28eb 26454 Object.defineProperty(Array.prototype, "shift", {
Marko Mikulicic 0:c0ecb8bf28eb 26455 writable:true,
Marko Mikulicic 0:c0ecb8bf28eb 26456 configurable: true,
Marko Mikulicic 0:c0ecb8bf28eb 26457 value: function() {
Marko Mikulicic 0:c0ecb8bf28eb 26458 return this.splice(0, 1)[0];
Marko Mikulicic 0:c0ecb8bf28eb 26459 }}););
Marko Mikulicic 0:c0ecb8bf28eb 26460
Marko Mikulicic 0:c0ecb8bf28eb 26461 #if V7_ENABLE__Function__call
Marko Mikulicic 0:c0ecb8bf28eb 26462 static const char js_function_call[] = STRINGIFY(
Marko Mikulicic 0:c0ecb8bf28eb 26463 Object.defineProperty(Function.prototype, "call", {
Marko Mikulicic 0:c0ecb8bf28eb 26464 writable:true,
Marko Mikulicic 0:c0ecb8bf28eb 26465 configurable: true,
Marko Mikulicic 0:c0ecb8bf28eb 26466 value: function() {
Marko Mikulicic 0:c0ecb8bf28eb 26467 var t = arguments.splice(0, 1)[0];
Marko Mikulicic 0:c0ecb8bf28eb 26468 return this.apply(t, arguments);
Marko Mikulicic 0:c0ecb8bf28eb 26469 }}););
Marko Mikulicic 0:c0ecb8bf28eb 26470 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26471
Marko Mikulicic 0:c0ecb8bf28eb 26472 #if V7_ENABLE__Function__bind
Marko Mikulicic 0:c0ecb8bf28eb 26473 static const char js_function_bind[] = STRINGIFY(
Marko Mikulicic 0:c0ecb8bf28eb 26474 Object.defineProperty(Function.prototype, "bind", {
Marko Mikulicic 0:c0ecb8bf28eb 26475 writable:true,
Marko Mikulicic 0:c0ecb8bf28eb 26476 configurable: true,
Marko Mikulicic 0:c0ecb8bf28eb 26477 value: function(t) {
Marko Mikulicic 0:c0ecb8bf28eb 26478 var f = this;
Marko Mikulicic 0:c0ecb8bf28eb 26479 return function() {
Marko Mikulicic 0:c0ecb8bf28eb 26480 return f.apply(t, arguments);
Marko Mikulicic 0:c0ecb8bf28eb 26481 };
Marko Mikulicic 0:c0ecb8bf28eb 26482 }}););
Marko Mikulicic 0:c0ecb8bf28eb 26483 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26484
Marko Mikulicic 0:c0ecb8bf28eb 26485 #if V7_ENABLE__Blob
Marko Mikulicic 0:c0ecb8bf28eb 26486 static const char js_Blob[] = STRINGIFY(
Marko Mikulicic 0:c0ecb8bf28eb 26487 function Blob(a) {
Marko Mikulicic 0:c0ecb8bf28eb 26488 this.a = a;
Marko Mikulicic 0:c0ecb8bf28eb 26489 });
Marko Mikulicic 0:c0ecb8bf28eb 26490 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26491
Marko Mikulicic 0:c0ecb8bf28eb 26492 static const char * const js_functions[] = {
Marko Mikulicic 0:c0ecb8bf28eb 26493 #if V7_ENABLE__Blob
Marko Mikulicic 0:c0ecb8bf28eb 26494 js_Blob,
Marko Mikulicic 0:c0ecb8bf28eb 26495 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26496 #if V7_ENABLE__Function__call
Marko Mikulicic 0:c0ecb8bf28eb 26497 js_function_call,
Marko Mikulicic 0:c0ecb8bf28eb 26498 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26499 #if V7_ENABLE__Function__bind
Marko Mikulicic 0:c0ecb8bf28eb 26500 js_function_bind,
Marko Mikulicic 0:c0ecb8bf28eb 26501 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26502 #if V7_ENABLE__Array__reduce
Marko Mikulicic 0:c0ecb8bf28eb 26503 js_array_reduce,
Marko Mikulicic 0:c0ecb8bf28eb 26504 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26505 js_array_indexOf,
Marko Mikulicic 0:c0ecb8bf28eb 26506 js_array_lastIndexOf,
Marko Mikulicic 0:c0ecb8bf28eb 26507 js_array_pop,
Marko Mikulicic 0:c0ecb8bf28eb 26508 js_array_shift
Marko Mikulicic 0:c0ecb8bf28eb 26509 };
Marko Mikulicic 0:c0ecb8bf28eb 26510
Marko Mikulicic 0:c0ecb8bf28eb 26511 V7_PRIVATE void init_js_stdlib(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 26512 val_t res;
Marko Mikulicic 0:c0ecb8bf28eb 26513 int i;
Marko Mikulicic 0:c0ecb8bf28eb 26514
Marko Mikulicic 0:c0ecb8bf28eb 26515 for(i = 0; i < (int) ARRAY_SIZE(js_functions); i++) {
Marko Mikulicic 0:c0ecb8bf28eb 26516 if (v7_exec(v7, js_functions[i], &res) != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 26517 fprintf(stderr, "ex: %s:\n", js_functions[i]);
Marko Mikulicic 0:c0ecb8bf28eb 26518 v7_fprintln(stderr, v7, res);
Marko Mikulicic 0:c0ecb8bf28eb 26519 }
Marko Mikulicic 0:c0ecb8bf28eb 26520 }
Marko Mikulicic 0:c0ecb8bf28eb 26521
Marko Mikulicic 0:c0ecb8bf28eb 26522 /* TODO(lsm): re-enable in a separate PR */
Marko Mikulicic 0:c0ecb8bf28eb 26523 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 26524 v7_exec(v7, &res, STRINGIFY(
Marko Mikulicic 0:c0ecb8bf28eb 26525 Array.prototype.unshift = function() {
Marko Mikulicic 0:c0ecb8bf28eb 26526 var a = new Array(0, 0);
Marko Mikulicic 0:c0ecb8bf28eb 26527 Array.prototype.push.apply(a, arguments);
Marko Mikulicic 0:c0ecb8bf28eb 26528 Array.prototype.splice.apply(this, a);
Marko Mikulicic 0:c0ecb8bf28eb 26529 return this.length;
Marko Mikulicic 0:c0ecb8bf28eb 26530 };));
Marko Mikulicic 0:c0ecb8bf28eb 26531 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26532 }
Marko Mikulicic 0:c0ecb8bf28eb 26533
Marko Mikulicic 0:c0ecb8bf28eb 26534 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 26535 }
Marko Mikulicic 0:c0ecb8bf28eb 26536 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 26537 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 26538 #line 1 "v7/src/slre.c"
Marko Mikulicic 0:c0ecb8bf28eb 26539 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26540 /*
Marko Mikulicic 0:c0ecb8bf28eb 26541 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 26542 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 26543 *
Marko Mikulicic 0:c0ecb8bf28eb 26544 * This software is dual-licensed: you can redistribute it and/or modify
Marko Mikulicic 0:c0ecb8bf28eb 26545 * it under the terms of the GNU General Public License version 2 as
Marko Mikulicic 0:c0ecb8bf28eb 26546 * published by the Free Software Foundation. For the terms of this
Marko Mikulicic 0:c0ecb8bf28eb 26547 * license, see <http://www.gnu.org/licenses/>.
Marko Mikulicic 0:c0ecb8bf28eb 26548 *
Marko Mikulicic 0:c0ecb8bf28eb 26549 * You are free to use this software under the terms of the GNU General
Marko Mikulicic 0:c0ecb8bf28eb 26550 * Public License, but WITHOUT ANY WARRANTY; without even the implied
Marko Mikulicic 0:c0ecb8bf28eb 26551 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Marko Mikulicic 0:c0ecb8bf28eb 26552 * See the GNU General Public License for more details.
Marko Mikulicic 0:c0ecb8bf28eb 26553 *
Marko Mikulicic 0:c0ecb8bf28eb 26554 * Alternatively, you can license this software under a commercial
Marko Mikulicic 0:c0ecb8bf28eb 26555 * license, as set out in <https://www.cesanta.com/license>.
Marko Mikulicic 0:c0ecb8bf28eb 26556 */
Marko Mikulicic 0:c0ecb8bf28eb 26557
Marko Mikulicic 0:c0ecb8bf28eb 26558 /* Amalgamated: #include "v7/src/v7_features.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26559
Marko Mikulicic 0:c0ecb8bf28eb 26560 #include <setjmp.h>
Marko Mikulicic 0:c0ecb8bf28eb 26561 #include <stdlib.h>
Marko Mikulicic 0:c0ecb8bf28eb 26562 #include <stdio.h>
Marko Mikulicic 0:c0ecb8bf28eb 26563 #include <string.h>
Marko Mikulicic 0:c0ecb8bf28eb 26564
Marko Mikulicic 0:c0ecb8bf28eb 26565 #ifndef NO_LIBC
Marko Mikulicic 0:c0ecb8bf28eb 26566 #include <ctype.h>
Marko Mikulicic 0:c0ecb8bf28eb 26567 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26568
Marko Mikulicic 0:c0ecb8bf28eb 26569 /* Amalgamated: #include "common/utf.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26570 /* Amalgamated: #include "v7/src/slre.h" */
Marko Mikulicic 0:c0ecb8bf28eb 26571
Marko Mikulicic 0:c0ecb8bf28eb 26572 /* Limitations */
Marko Mikulicic 0:c0ecb8bf28eb 26573 #define SLRE_MAX_RANGES 32
Marko Mikulicic 0:c0ecb8bf28eb 26574 #define SLRE_MAX_SETS 16
Marko Mikulicic 0:c0ecb8bf28eb 26575 #define SLRE_MAX_REP 0xFFFF
Marko Mikulicic 0:c0ecb8bf28eb 26576
Marko Mikulicic 0:c0ecb8bf28eb 26577 #define SLRE_MALLOC malloc
Marko Mikulicic 0:c0ecb8bf28eb 26578 #define SLRE_FREE free
Marko Mikulicic 0:c0ecb8bf28eb 26579 #define SLRE_THROW(e, err_code) longjmp((e)->jmp_buf, (err_code))
Marko Mikulicic 0:c0ecb8bf28eb 26580
Marko Mikulicic 0:c0ecb8bf28eb 26581 static int hex(int c) {
Marko Mikulicic 0:c0ecb8bf28eb 26582 if (c >= '0' && c <= '9') return c - '0';
Marko Mikulicic 0:c0ecb8bf28eb 26583 if (c >= 'a' && c <= 'f') return c - 'a' + 10;
Marko Mikulicic 0:c0ecb8bf28eb 26584 if (c >= 'A' && c <= 'F') return c - 'A' + 10;
Marko Mikulicic 0:c0ecb8bf28eb 26585 return -SLRE_INVALID_HEX_DIGIT;
Marko Mikulicic 0:c0ecb8bf28eb 26586 }
Marko Mikulicic 0:c0ecb8bf28eb 26587
Marko Mikulicic 0:c0ecb8bf28eb 26588 int nextesc(const char **p) {
Marko Mikulicic 0:c0ecb8bf28eb 26589 const unsigned char *s = (unsigned char *) (*p)++;
Marko Mikulicic 0:c0ecb8bf28eb 26590 switch (*s) {
Marko Mikulicic 0:c0ecb8bf28eb 26591 case 0:
Marko Mikulicic 0:c0ecb8bf28eb 26592 return -SLRE_UNTERM_ESC_SEQ;
Marko Mikulicic 0:c0ecb8bf28eb 26593 case 'c':
Marko Mikulicic 0:c0ecb8bf28eb 26594 ++*p;
Marko Mikulicic 0:c0ecb8bf28eb 26595 return *s & 31;
Marko Mikulicic 0:c0ecb8bf28eb 26596 case 'b':
Marko Mikulicic 0:c0ecb8bf28eb 26597 return '\b';
Marko Mikulicic 0:c0ecb8bf28eb 26598 case 't':
Marko Mikulicic 0:c0ecb8bf28eb 26599 return '\t';
Marko Mikulicic 0:c0ecb8bf28eb 26600 case 'n':
Marko Mikulicic 0:c0ecb8bf28eb 26601 return '\n';
Marko Mikulicic 0:c0ecb8bf28eb 26602 case 'v':
Marko Mikulicic 0:c0ecb8bf28eb 26603 return '\v';
Marko Mikulicic 0:c0ecb8bf28eb 26604 case 'f':
Marko Mikulicic 0:c0ecb8bf28eb 26605 return '\f';
Marko Mikulicic 0:c0ecb8bf28eb 26606 case 'r':
Marko Mikulicic 0:c0ecb8bf28eb 26607 return '\r';
Marko Mikulicic 0:c0ecb8bf28eb 26608 case '\\':
Marko Mikulicic 0:c0ecb8bf28eb 26609 return '\\';
Marko Mikulicic 0:c0ecb8bf28eb 26610 case 'u':
Marko Mikulicic 0:c0ecb8bf28eb 26611 if (isxdigit(s[1]) && isxdigit(s[2]) && isxdigit(s[3]) &&
Marko Mikulicic 0:c0ecb8bf28eb 26612 isxdigit(s[4])) {
Marko Mikulicic 0:c0ecb8bf28eb 26613 (*p) += 4;
Marko Mikulicic 0:c0ecb8bf28eb 26614 return hex(s[1]) << 12 | hex(s[2]) << 8 | hex(s[3]) << 4 | hex(s[4]);
Marko Mikulicic 0:c0ecb8bf28eb 26615 }
Marko Mikulicic 0:c0ecb8bf28eb 26616 return -SLRE_INVALID_HEX_DIGIT;
Marko Mikulicic 0:c0ecb8bf28eb 26617 case 'x':
Marko Mikulicic 0:c0ecb8bf28eb 26618 if (isxdigit(s[1]) && isxdigit(s[2])) {
Marko Mikulicic 0:c0ecb8bf28eb 26619 (*p) += 2;
Marko Mikulicic 0:c0ecb8bf28eb 26620 return (hex(s[1]) << 4) | hex(s[2]);
Marko Mikulicic 0:c0ecb8bf28eb 26621 }
Marko Mikulicic 0:c0ecb8bf28eb 26622 return -SLRE_INVALID_HEX_DIGIT;
Marko Mikulicic 0:c0ecb8bf28eb 26623 default:
Marko Mikulicic 0:c0ecb8bf28eb 26624 return -SLRE_INVALID_ESC_CHAR;
Marko Mikulicic 0:c0ecb8bf28eb 26625 }
Marko Mikulicic 0:c0ecb8bf28eb 26626 }
Marko Mikulicic 0:c0ecb8bf28eb 26627
Marko Mikulicic 0:c0ecb8bf28eb 26628 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 26629
Marko Mikulicic 0:c0ecb8bf28eb 26630 /* Parser Information */
Marko Mikulicic 0:c0ecb8bf28eb 26631 struct slre_node {
Marko Mikulicic 0:c0ecb8bf28eb 26632 unsigned char type;
Marko Mikulicic 0:c0ecb8bf28eb 26633 union {
Marko Mikulicic 0:c0ecb8bf28eb 26634 Rune c; /* character */
Marko Mikulicic 0:c0ecb8bf28eb 26635 struct slre_class *cp; /* class pointer */
Marko Mikulicic 0:c0ecb8bf28eb 26636 struct {
Marko Mikulicic 0:c0ecb8bf28eb 26637 struct slre_node *x;
Marko Mikulicic 0:c0ecb8bf28eb 26638 union {
Marko Mikulicic 0:c0ecb8bf28eb 26639 struct slre_node *y;
Marko Mikulicic 0:c0ecb8bf28eb 26640 unsigned char n;
Marko Mikulicic 0:c0ecb8bf28eb 26641 struct {
Marko Mikulicic 0:c0ecb8bf28eb 26642 unsigned char ng; /* not greedy flag */
Marko Mikulicic 0:c0ecb8bf28eb 26643 unsigned short min;
Marko Mikulicic 0:c0ecb8bf28eb 26644 unsigned short max;
Marko Mikulicic 0:c0ecb8bf28eb 26645 } rp;
Marko Mikulicic 0:c0ecb8bf28eb 26646 } y;
Marko Mikulicic 0:c0ecb8bf28eb 26647 } xy;
Marko Mikulicic 0:c0ecb8bf28eb 26648 } par;
Marko Mikulicic 0:c0ecb8bf28eb 26649 };
Marko Mikulicic 0:c0ecb8bf28eb 26650
Marko Mikulicic 0:c0ecb8bf28eb 26651 struct slre_range {
Marko Mikulicic 0:c0ecb8bf28eb 26652 unsigned short s, e;
Marko Mikulicic 0:c0ecb8bf28eb 26653 };
Marko Mikulicic 0:c0ecb8bf28eb 26654
Marko Mikulicic 0:c0ecb8bf28eb 26655 /* character class, each pair of rune's defines a range */
Marko Mikulicic 0:c0ecb8bf28eb 26656 struct slre_class {
Marko Mikulicic 0:c0ecb8bf28eb 26657 struct slre_range *end;
Marko Mikulicic 0:c0ecb8bf28eb 26658 struct slre_range spans[SLRE_MAX_RANGES];
Marko Mikulicic 0:c0ecb8bf28eb 26659 };
Marko Mikulicic 0:c0ecb8bf28eb 26660
Marko Mikulicic 0:c0ecb8bf28eb 26661 struct slre_instruction {
Marko Mikulicic 0:c0ecb8bf28eb 26662 unsigned char opcode;
Marko Mikulicic 0:c0ecb8bf28eb 26663 union {
Marko Mikulicic 0:c0ecb8bf28eb 26664 unsigned char n;
Marko Mikulicic 0:c0ecb8bf28eb 26665 Rune c; /* character */
Marko Mikulicic 0:c0ecb8bf28eb 26666 struct slre_class *cp; /* class pointer */
Marko Mikulicic 0:c0ecb8bf28eb 26667 struct {
Marko Mikulicic 0:c0ecb8bf28eb 26668 struct slre_instruction *x;
Marko Mikulicic 0:c0ecb8bf28eb 26669 union {
Marko Mikulicic 0:c0ecb8bf28eb 26670 struct {
Marko Mikulicic 0:c0ecb8bf28eb 26671 unsigned short min;
Marko Mikulicic 0:c0ecb8bf28eb 26672 unsigned short max;
Marko Mikulicic 0:c0ecb8bf28eb 26673 } rp;
Marko Mikulicic 0:c0ecb8bf28eb 26674 struct slre_instruction *y;
Marko Mikulicic 0:c0ecb8bf28eb 26675 } y;
Marko Mikulicic 0:c0ecb8bf28eb 26676 } xy;
Marko Mikulicic 0:c0ecb8bf28eb 26677 } par;
Marko Mikulicic 0:c0ecb8bf28eb 26678 };
Marko Mikulicic 0:c0ecb8bf28eb 26679
Marko Mikulicic 0:c0ecb8bf28eb 26680 struct slre_prog {
Marko Mikulicic 0:c0ecb8bf28eb 26681 struct slre_instruction *start, *end;
Marko Mikulicic 0:c0ecb8bf28eb 26682 unsigned int num_captures;
Marko Mikulicic 0:c0ecb8bf28eb 26683 int flags;
Marko Mikulicic 0:c0ecb8bf28eb 26684 struct slre_class charset[SLRE_MAX_SETS];
Marko Mikulicic 0:c0ecb8bf28eb 26685 };
Marko Mikulicic 0:c0ecb8bf28eb 26686
Marko Mikulicic 0:c0ecb8bf28eb 26687 struct slre_env {
Marko Mikulicic 0:c0ecb8bf28eb 26688 int is_regex;
Marko Mikulicic 0:c0ecb8bf28eb 26689 const char *src;
Marko Mikulicic 0:c0ecb8bf28eb 26690 const char *src_end;
Marko Mikulicic 0:c0ecb8bf28eb 26691 Rune curr_rune;
Marko Mikulicic 0:c0ecb8bf28eb 26692
Marko Mikulicic 0:c0ecb8bf28eb 26693 struct slre_prog *prog;
Marko Mikulicic 0:c0ecb8bf28eb 26694 struct slre_node *pstart, *pend;
Marko Mikulicic 0:c0ecb8bf28eb 26695
Marko Mikulicic 0:c0ecb8bf28eb 26696 struct slre_node *caps[SLRE_MAX_CAPS];
Marko Mikulicic 0:c0ecb8bf28eb 26697 unsigned int num_captures;
Marko Mikulicic 0:c0ecb8bf28eb 26698 unsigned int sets_num;
Marko Mikulicic 0:c0ecb8bf28eb 26699
Marko Mikulicic 0:c0ecb8bf28eb 26700 int lookahead;
Marko Mikulicic 0:c0ecb8bf28eb 26701 struct slre_class *curr_set;
Marko Mikulicic 0:c0ecb8bf28eb 26702 int min_rep, max_rep;
Marko Mikulicic 0:c0ecb8bf28eb 26703
Marko Mikulicic 0:c0ecb8bf28eb 26704 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 26705 ::jmp_buf jmp_buf;
Marko Mikulicic 0:c0ecb8bf28eb 26706 #else
Marko Mikulicic 0:c0ecb8bf28eb 26707 jmp_buf jmp_buf;
Marko Mikulicic 0:c0ecb8bf28eb 26708 #endif
Marko Mikulicic 0:c0ecb8bf28eb 26709 };
Marko Mikulicic 0:c0ecb8bf28eb 26710
Marko Mikulicic 0:c0ecb8bf28eb 26711 struct slre_thread {
Marko Mikulicic 0:c0ecb8bf28eb 26712 struct slre_thread *prev;
Marko Mikulicic 0:c0ecb8bf28eb 26713 struct slre_instruction *pc;
Marko Mikulicic 0:c0ecb8bf28eb 26714 const char *start;
Marko Mikulicic 0:c0ecb8bf28eb 26715 struct slre_loot loot;
Marko Mikulicic 0:c0ecb8bf28eb 26716 };
Marko Mikulicic 0:c0ecb8bf28eb 26717
Marko Mikulicic 0:c0ecb8bf28eb 26718 enum slre_opcode {
Marko Mikulicic 0:c0ecb8bf28eb 26719 I_END = 10, /* Terminate: match found */
Marko Mikulicic 0:c0ecb8bf28eb 26720 I_ANY,
Marko Mikulicic 0:c0ecb8bf28eb 26721 P_ANY = I_ANY, /* Any character except newline, . */
Marko Mikulicic 0:c0ecb8bf28eb 26722 I_ANYNL, /* Any character including newline, . */
Marko Mikulicic 0:c0ecb8bf28eb 26723 I_BOL,
Marko Mikulicic 0:c0ecb8bf28eb 26724 P_BOL = I_BOL, /* Beginning of line, ^ */
Marko Mikulicic 0:c0ecb8bf28eb 26725 I_CH,
Marko Mikulicic 0:c0ecb8bf28eb 26726 P_CH = I_CH,
Marko Mikulicic 0:c0ecb8bf28eb 26727 I_EOL,
Marko Mikulicic 0:c0ecb8bf28eb 26728 P_EOL = I_EOL, /* End of line, $ */
Marko Mikulicic 0:c0ecb8bf28eb 26729 I_EOS,
Marko Mikulicic 0:c0ecb8bf28eb 26730 P_EOS = I_EOS, /* End of string, \0 */
Marko Mikulicic 0:c0ecb8bf28eb 26731 I_JUMP,
Marko Mikulicic 0:c0ecb8bf28eb 26732 I_LA,
Marko Mikulicic 0:c0ecb8bf28eb 26733 P_LA = I_LA,
Marko Mikulicic 0:c0ecb8bf28eb 26734 I_LA_N,
Marko Mikulicic 0:c0ecb8bf28eb 26735 P_LA_N = I_LA_N,
Marko Mikulicic 0:c0ecb8bf28eb 26736 I_LBRA,
Marko Mikulicic 0:c0ecb8bf28eb 26737 P_BRA = I_LBRA, /* Left bracket, ( */
Marko Mikulicic 0:c0ecb8bf28eb 26738 I_REF,
Marko Mikulicic 0:c0ecb8bf28eb 26739 P_REF = I_REF,
Marko Mikulicic 0:c0ecb8bf28eb 26740 I_REP,
Marko Mikulicic 0:c0ecb8bf28eb 26741 P_REP = I_REP,
Marko Mikulicic 0:c0ecb8bf28eb 26742 I_REP_INI,
Marko Mikulicic 0:c0ecb8bf28eb 26743 I_RBRA, /* Right bracket, ) */
Marko Mikulicic 0:c0ecb8bf28eb 26744 I_SET,
Marko Mikulicic 0:c0ecb8bf28eb 26745 P_SET = I_SET, /* Character set, [] */
Marko Mikulicic 0:c0ecb8bf28eb 26746 I_SET_N,
Marko Mikulicic 0:c0ecb8bf28eb 26747 P_SET_N = I_SET_N, /* Negated character set, [] */
Marko Mikulicic 0:c0ecb8bf28eb 26748 I_SPLIT,
Marko Mikulicic 0:c0ecb8bf28eb 26749 I_WORD,
Marko Mikulicic 0:c0ecb8bf28eb 26750 P_WORD = I_WORD,
Marko Mikulicic 0:c0ecb8bf28eb 26751 I_WORD_N,
Marko Mikulicic 0:c0ecb8bf28eb 26752 P_WORD_N = I_WORD_N,
Marko Mikulicic 0:c0ecb8bf28eb 26753 P_ALT, /* Alternation, | */
Marko Mikulicic 0:c0ecb8bf28eb 26754 P_CAT, /* Concatentation, implicit operator */
Marko Mikulicic 0:c0ecb8bf28eb 26755 L_CH = 256,
Marko Mikulicic 0:c0ecb8bf28eb 26756 L_COUNT, /* {M,N} */
Marko Mikulicic 0:c0ecb8bf28eb 26757 L_EOS, /* End of string, \0 */
Marko Mikulicic 0:c0ecb8bf28eb 26758 L_LA, /* "(?=" lookahead */
Marko Mikulicic 0:c0ecb8bf28eb 26759 L_LA_CAP, /* "(?:" lookahead, capture */
Marko Mikulicic 0:c0ecb8bf28eb 26760 L_LA_N, /* "(?!" negative lookahead */
Marko Mikulicic 0:c0ecb8bf28eb 26761 L_REF, /* "\1" back-reference */
Marko Mikulicic 0:c0ecb8bf28eb 26762 L_CHSET, /* character set */
Marko Mikulicic 0:c0ecb8bf28eb 26763 L_SET_N, /* negative character set */
Marko Mikulicic 0:c0ecb8bf28eb 26764 L_WORD, /* "\b" word boundary */
Marko Mikulicic 0:c0ecb8bf28eb 26765 L_WORD_N /* "\B" non-word boundary */
Marko Mikulicic 0:c0ecb8bf28eb 26766 };
Marko Mikulicic 0:c0ecb8bf28eb 26767
Marko Mikulicic 0:c0ecb8bf28eb 26768 static signed char dec(int c) {
Marko Mikulicic 0:c0ecb8bf28eb 26769 if (isdigitrune(c)) return c - '0';
Marko Mikulicic 0:c0ecb8bf28eb 26770 return SLRE_INVALID_DEC_DIGIT;
Marko Mikulicic 0:c0ecb8bf28eb 26771 }
Marko Mikulicic 0:c0ecb8bf28eb 26772
Marko Mikulicic 0:c0ecb8bf28eb 26773 static unsigned char re_dec_digit(struct slre_env *e, int c) {
Marko Mikulicic 0:c0ecb8bf28eb 26774 signed char ret = dec(c);
Marko Mikulicic 0:c0ecb8bf28eb 26775 if (ret < 0) {
Marko Mikulicic 0:c0ecb8bf28eb 26776 SLRE_THROW(e, SLRE_INVALID_DEC_DIGIT);
Marko Mikulicic 0:c0ecb8bf28eb 26777 }
Marko Mikulicic 0:c0ecb8bf28eb 26778 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 26779 }
Marko Mikulicic 0:c0ecb8bf28eb 26780
Marko Mikulicic 0:c0ecb8bf28eb 26781 static int re_nextc(Rune *r, const char **src, const char *src_end) {
Marko Mikulicic 0:c0ecb8bf28eb 26782 *r = 0;
Marko Mikulicic 0:c0ecb8bf28eb 26783 if (*src >= src_end) return 0;
Marko Mikulicic 0:c0ecb8bf28eb 26784 *src += chartorune(r, *src);
Marko Mikulicic 0:c0ecb8bf28eb 26785 if (*r == '\\') {
Marko Mikulicic 0:c0ecb8bf28eb 26786 const char *tmp_s = *src;
Marko Mikulicic 0:c0ecb8bf28eb 26787 int i = nextesc(src);
Marko Mikulicic 0:c0ecb8bf28eb 26788 switch (i) {
Marko Mikulicic 0:c0ecb8bf28eb 26789 case -SLRE_INVALID_ESC_CHAR:
Marko Mikulicic 0:c0ecb8bf28eb 26790 *r = '\\';
Marko Mikulicic 0:c0ecb8bf28eb 26791 *src = tmp_s;
Marko Mikulicic 0:c0ecb8bf28eb 26792 *src += chartorune(r, *src);
Marko Mikulicic 0:c0ecb8bf28eb 26793 break;
Marko Mikulicic 0:c0ecb8bf28eb 26794 case -SLRE_INVALID_HEX_DIGIT:
Marko Mikulicic 0:c0ecb8bf28eb 26795 default:
Marko Mikulicic 0:c0ecb8bf28eb 26796 *r = i;
Marko Mikulicic 0:c0ecb8bf28eb 26797 }
Marko Mikulicic 0:c0ecb8bf28eb 26798 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 26799 }
Marko Mikulicic 0:c0ecb8bf28eb 26800 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 26801 }
Marko Mikulicic 0:c0ecb8bf28eb 26802
Marko Mikulicic 0:c0ecb8bf28eb 26803 static int re_nextc_raw(Rune *r, const char **src, const char *src_end) {
Marko Mikulicic 0:c0ecb8bf28eb 26804 *r = 0;
Marko Mikulicic 0:c0ecb8bf28eb 26805 if (*src >= src_end) return 0;
Marko Mikulicic 0:c0ecb8bf28eb 26806 *src += chartorune(r, *src);
Marko Mikulicic 0:c0ecb8bf28eb 26807 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 26808 }
Marko Mikulicic 0:c0ecb8bf28eb 26809
Marko Mikulicic 0:c0ecb8bf28eb 26810 static int re_nextc_env(struct slre_env *e) {
Marko Mikulicic 0:c0ecb8bf28eb 26811 return re_nextc(&e->curr_rune, &e->src, e->src_end);
Marko Mikulicic 0:c0ecb8bf28eb 26812 }
Marko Mikulicic 0:c0ecb8bf28eb 26813
Marko Mikulicic 0:c0ecb8bf28eb 26814 static void re_nchset(struct slre_env *e) {
Marko Mikulicic 0:c0ecb8bf28eb 26815 if (e->sets_num >= nelem(e->prog->charset)) {
Marko Mikulicic 0:c0ecb8bf28eb 26816 SLRE_THROW(e, SLRE_TOO_MANY_CHARSETS);
Marko Mikulicic 0:c0ecb8bf28eb 26817 }
Marko Mikulicic 0:c0ecb8bf28eb 26818 e->curr_set = e->prog->charset + e->sets_num++;
Marko Mikulicic 0:c0ecb8bf28eb 26819 e->curr_set->end = e->curr_set->spans;
Marko Mikulicic 0:c0ecb8bf28eb 26820 }
Marko Mikulicic 0:c0ecb8bf28eb 26821
Marko Mikulicic 0:c0ecb8bf28eb 26822 static void re_rng2set(struct slre_env *e, Rune start, Rune end) {
Marko Mikulicic 0:c0ecb8bf28eb 26823 if (start > end) {
Marko Mikulicic 0:c0ecb8bf28eb 26824 SLRE_THROW(e, SLRE_INV_CHARSET_RANGE);
Marko Mikulicic 0:c0ecb8bf28eb 26825 }
Marko Mikulicic 0:c0ecb8bf28eb 26826 if (e->curr_set->end + 2 == e->curr_set->spans + nelem(e->curr_set->spans)) {
Marko Mikulicic 0:c0ecb8bf28eb 26827 SLRE_THROW(e, SLRE_CHARSET_TOO_LARGE);
Marko Mikulicic 0:c0ecb8bf28eb 26828 }
Marko Mikulicic 0:c0ecb8bf28eb 26829 e->curr_set->end->s = start;
Marko Mikulicic 0:c0ecb8bf28eb 26830 e->curr_set->end->e = end;
Marko Mikulicic 0:c0ecb8bf28eb 26831 e->curr_set->end++;
Marko Mikulicic 0:c0ecb8bf28eb 26832 }
Marko Mikulicic 0:c0ecb8bf28eb 26833
Marko Mikulicic 0:c0ecb8bf28eb 26834 #define re_char2set(e, c) re_rng2set(e, c, c)
Marko Mikulicic 0:c0ecb8bf28eb 26835
Marko Mikulicic 0:c0ecb8bf28eb 26836 #define re_d_2set(e) re_rng2set(e, '0', '9')
Marko Mikulicic 0:c0ecb8bf28eb 26837
Marko Mikulicic 0:c0ecb8bf28eb 26838 static void re_D_2set(struct slre_env *e) {
Marko Mikulicic 0:c0ecb8bf28eb 26839 re_rng2set(e, 0, '0' - 1);
Marko Mikulicic 0:c0ecb8bf28eb 26840 re_rng2set(e, '9' + 1, 0xFFFF);
Marko Mikulicic 0:c0ecb8bf28eb 26841 }
Marko Mikulicic 0:c0ecb8bf28eb 26842
Marko Mikulicic 0:c0ecb8bf28eb 26843 static void re_s_2set(struct slre_env *e) {
Marko Mikulicic 0:c0ecb8bf28eb 26844 re_char2set(e, 0x9);
Marko Mikulicic 0:c0ecb8bf28eb 26845 re_rng2set(e, 0xA, 0xD);
Marko Mikulicic 0:c0ecb8bf28eb 26846 re_char2set(e, 0x20);
Marko Mikulicic 0:c0ecb8bf28eb 26847 re_char2set(e, 0xA0);
Marko Mikulicic 0:c0ecb8bf28eb 26848 re_rng2set(e, 0x2028, 0x2029);
Marko Mikulicic 0:c0ecb8bf28eb 26849 re_char2set(e, 0xFEFF);
Marko Mikulicic 0:c0ecb8bf28eb 26850 }
Marko Mikulicic 0:c0ecb8bf28eb 26851
Marko Mikulicic 0:c0ecb8bf28eb 26852 static void re_S_2set(struct slre_env *e) {
Marko Mikulicic 0:c0ecb8bf28eb 26853 re_rng2set(e, 0, 0x9 - 1);
Marko Mikulicic 0:c0ecb8bf28eb 26854 re_rng2set(e, 0xD + 1, 0x20 - 1);
Marko Mikulicic 0:c0ecb8bf28eb 26855 re_rng2set(e, 0x20 + 1, 0xA0 - 1);
Marko Mikulicic 0:c0ecb8bf28eb 26856 re_rng2set(e, 0xA0 + 1, 0x2028 - 1);
Marko Mikulicic 0:c0ecb8bf28eb 26857 re_rng2set(e, 0x2029 + 1, 0xFEFF - 1);
Marko Mikulicic 0:c0ecb8bf28eb 26858 re_rng2set(e, 0xFEFF + 1, 0xFFFF);
Marko Mikulicic 0:c0ecb8bf28eb 26859 }
Marko Mikulicic 0:c0ecb8bf28eb 26860
Marko Mikulicic 0:c0ecb8bf28eb 26861 static void re_w_2set(struct slre_env *e) {
Marko Mikulicic 0:c0ecb8bf28eb 26862 re_d_2set(e);
Marko Mikulicic 0:c0ecb8bf28eb 26863 re_rng2set(e, 'A', 'Z');
Marko Mikulicic 0:c0ecb8bf28eb 26864 re_char2set(e, '_');
Marko Mikulicic 0:c0ecb8bf28eb 26865 re_rng2set(e, 'a', 'z');
Marko Mikulicic 0:c0ecb8bf28eb 26866 }
Marko Mikulicic 0:c0ecb8bf28eb 26867
Marko Mikulicic 0:c0ecb8bf28eb 26868 static void re_W_2set(struct slre_env *e) {
Marko Mikulicic 0:c0ecb8bf28eb 26869 re_rng2set(e, 0, '0' - 1);
Marko Mikulicic 0:c0ecb8bf28eb 26870 re_rng2set(e, '9' + 1, 'A' - 1);
Marko Mikulicic 0:c0ecb8bf28eb 26871 re_rng2set(e, 'Z' + 1, '_' - 1);
Marko Mikulicic 0:c0ecb8bf28eb 26872 re_rng2set(e, '_' + 1, 'a' - 1);
Marko Mikulicic 0:c0ecb8bf28eb 26873 re_rng2set(e, 'z' + 1, 0xFFFF);
Marko Mikulicic 0:c0ecb8bf28eb 26874 }
Marko Mikulicic 0:c0ecb8bf28eb 26875
Marko Mikulicic 0:c0ecb8bf28eb 26876 static unsigned char re_endofcount(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 26877 switch (c) {
Marko Mikulicic 0:c0ecb8bf28eb 26878 case ',':
Marko Mikulicic 0:c0ecb8bf28eb 26879 case '}':
Marko Mikulicic 0:c0ecb8bf28eb 26880 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 26881 }
Marko Mikulicic 0:c0ecb8bf28eb 26882 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 26883 }
Marko Mikulicic 0:c0ecb8bf28eb 26884
Marko Mikulicic 0:c0ecb8bf28eb 26885 static void re_ex_num_overfl(struct slre_env *e) {
Marko Mikulicic 0:c0ecb8bf28eb 26886 SLRE_THROW(e, SLRE_NUM_OVERFLOW);
Marko Mikulicic 0:c0ecb8bf28eb 26887 }
Marko Mikulicic 0:c0ecb8bf28eb 26888
Marko Mikulicic 0:c0ecb8bf28eb 26889 static enum slre_opcode re_countrep(struct slre_env *e) {
Marko Mikulicic 0:c0ecb8bf28eb 26890 e->min_rep = 0;
Marko Mikulicic 0:c0ecb8bf28eb 26891 while (e->src < e->src_end && !re_endofcount(e->curr_rune = *e->src++)) {
Marko Mikulicic 0:c0ecb8bf28eb 26892 e->min_rep = e->min_rep * 10 + re_dec_digit(e, e->curr_rune);
Marko Mikulicic 0:c0ecb8bf28eb 26893 if (e->min_rep >= SLRE_MAX_REP) re_ex_num_overfl(e);
Marko Mikulicic 0:c0ecb8bf28eb 26894 }
Marko Mikulicic 0:c0ecb8bf28eb 26895
Marko Mikulicic 0:c0ecb8bf28eb 26896 if (e->curr_rune != ',') {
Marko Mikulicic 0:c0ecb8bf28eb 26897 e->max_rep = e->min_rep;
Marko Mikulicic 0:c0ecb8bf28eb 26898 return L_COUNT;
Marko Mikulicic 0:c0ecb8bf28eb 26899 }
Marko Mikulicic 0:c0ecb8bf28eb 26900 e->max_rep = 0;
Marko Mikulicic 0:c0ecb8bf28eb 26901 while (e->src < e->src_end && (e->curr_rune = *e->src++) != '}') {
Marko Mikulicic 0:c0ecb8bf28eb 26902 e->max_rep = e->max_rep * 10 + re_dec_digit(e, e->curr_rune);
Marko Mikulicic 0:c0ecb8bf28eb 26903 if (e->max_rep >= SLRE_MAX_REP) re_ex_num_overfl(e);
Marko Mikulicic 0:c0ecb8bf28eb 26904 }
Marko Mikulicic 0:c0ecb8bf28eb 26905 if (!e->max_rep) {
Marko Mikulicic 0:c0ecb8bf28eb 26906 e->max_rep = SLRE_MAX_REP;
Marko Mikulicic 0:c0ecb8bf28eb 26907 return L_COUNT;
Marko Mikulicic 0:c0ecb8bf28eb 26908 }
Marko Mikulicic 0:c0ecb8bf28eb 26909
Marko Mikulicic 0:c0ecb8bf28eb 26910 return L_COUNT;
Marko Mikulicic 0:c0ecb8bf28eb 26911 }
Marko Mikulicic 0:c0ecb8bf28eb 26912
Marko Mikulicic 0:c0ecb8bf28eb 26913 static enum slre_opcode re_lexset(struct slre_env *e) {
Marko Mikulicic 0:c0ecb8bf28eb 26914 Rune ch = 0;
Marko Mikulicic 0:c0ecb8bf28eb 26915 unsigned char esc, ch_fl = 0, dash_fl = 0;
Marko Mikulicic 0:c0ecb8bf28eb 26916 enum slre_opcode type = L_CHSET;
Marko Mikulicic 0:c0ecb8bf28eb 26917
Marko Mikulicic 0:c0ecb8bf28eb 26918 re_nchset(e);
Marko Mikulicic 0:c0ecb8bf28eb 26919
Marko Mikulicic 0:c0ecb8bf28eb 26920 esc = re_nextc_env(e);
Marko Mikulicic 0:c0ecb8bf28eb 26921 if (!esc && e->curr_rune == '^') {
Marko Mikulicic 0:c0ecb8bf28eb 26922 type = L_SET_N;
Marko Mikulicic 0:c0ecb8bf28eb 26923 esc = re_nextc_env(e);
Marko Mikulicic 0:c0ecb8bf28eb 26924 }
Marko Mikulicic 0:c0ecb8bf28eb 26925
Marko Mikulicic 0:c0ecb8bf28eb 26926 for (; esc || e->curr_rune != ']'; esc = re_nextc_env(e)) {
Marko Mikulicic 0:c0ecb8bf28eb 26927 if (!e->curr_rune) {
Marko Mikulicic 0:c0ecb8bf28eb 26928 SLRE_THROW(e, SLRE_MALFORMED_CHARSET);
Marko Mikulicic 0:c0ecb8bf28eb 26929 }
Marko Mikulicic 0:c0ecb8bf28eb 26930 if (esc) {
Marko Mikulicic 0:c0ecb8bf28eb 26931 if (strchr("DdSsWw", e->curr_rune)) {
Marko Mikulicic 0:c0ecb8bf28eb 26932 if (ch_fl) {
Marko Mikulicic 0:c0ecb8bf28eb 26933 re_char2set(e, ch);
Marko Mikulicic 0:c0ecb8bf28eb 26934 if (dash_fl) re_char2set(e, '-');
Marko Mikulicic 0:c0ecb8bf28eb 26935 }
Marko Mikulicic 0:c0ecb8bf28eb 26936 switch (e->curr_rune) {
Marko Mikulicic 0:c0ecb8bf28eb 26937 case 'D':
Marko Mikulicic 0:c0ecb8bf28eb 26938 re_D_2set(e);
Marko Mikulicic 0:c0ecb8bf28eb 26939 break;
Marko Mikulicic 0:c0ecb8bf28eb 26940 case 'd':
Marko Mikulicic 0:c0ecb8bf28eb 26941 re_d_2set(e);
Marko Mikulicic 0:c0ecb8bf28eb 26942 break;
Marko Mikulicic 0:c0ecb8bf28eb 26943 case 'S':
Marko Mikulicic 0:c0ecb8bf28eb 26944 re_S_2set(e);
Marko Mikulicic 0:c0ecb8bf28eb 26945 break;
Marko Mikulicic 0:c0ecb8bf28eb 26946 case 's':
Marko Mikulicic 0:c0ecb8bf28eb 26947 re_s_2set(e);
Marko Mikulicic 0:c0ecb8bf28eb 26948 break;
Marko Mikulicic 0:c0ecb8bf28eb 26949 case 'W':
Marko Mikulicic 0:c0ecb8bf28eb 26950 re_W_2set(e);
Marko Mikulicic 0:c0ecb8bf28eb 26951 break;
Marko Mikulicic 0:c0ecb8bf28eb 26952 case 'w':
Marko Mikulicic 0:c0ecb8bf28eb 26953 re_w_2set(e);
Marko Mikulicic 0:c0ecb8bf28eb 26954 break;
Marko Mikulicic 0:c0ecb8bf28eb 26955 }
Marko Mikulicic 0:c0ecb8bf28eb 26956 ch_fl = dash_fl = 0;
Marko Mikulicic 0:c0ecb8bf28eb 26957 continue;
Marko Mikulicic 0:c0ecb8bf28eb 26958 }
Marko Mikulicic 0:c0ecb8bf28eb 26959 switch (e->curr_rune) {
Marko Mikulicic 0:c0ecb8bf28eb 26960 default:
Marko Mikulicic 0:c0ecb8bf28eb 26961 /* case '-':
Marko Mikulicic 0:c0ecb8bf28eb 26962 case '\\':
Marko Mikulicic 0:c0ecb8bf28eb 26963 case '.':
Marko Mikulicic 0:c0ecb8bf28eb 26964 case '/':
Marko Mikulicic 0:c0ecb8bf28eb 26965 case ']':
Marko Mikulicic 0:c0ecb8bf28eb 26966 case '|': */
Marko Mikulicic 0:c0ecb8bf28eb 26967 break;
Marko Mikulicic 0:c0ecb8bf28eb 26968 case '0':
Marko Mikulicic 0:c0ecb8bf28eb 26969 e->curr_rune = 0;
Marko Mikulicic 0:c0ecb8bf28eb 26970 break;
Marko Mikulicic 0:c0ecb8bf28eb 26971 case 'b':
Marko Mikulicic 0:c0ecb8bf28eb 26972 e->curr_rune = '\b';
Marko Mikulicic 0:c0ecb8bf28eb 26973 break;
Marko Mikulicic 0:c0ecb8bf28eb 26974 /* default:
Marko Mikulicic 0:c0ecb8bf28eb 26975 SLRE_THROW(e->catch_point, e->err_msg,
Marko Mikulicic 0:c0ecb8bf28eb 26976 SLRE_INVALID_ESC_CHAR); */
Marko Mikulicic 0:c0ecb8bf28eb 26977 }
Marko Mikulicic 0:c0ecb8bf28eb 26978 } else {
Marko Mikulicic 0:c0ecb8bf28eb 26979 if (e->curr_rune == '-') {
Marko Mikulicic 0:c0ecb8bf28eb 26980 if (ch_fl) {
Marko Mikulicic 0:c0ecb8bf28eb 26981 if (dash_fl) {
Marko Mikulicic 0:c0ecb8bf28eb 26982 re_rng2set(e, ch, '-');
Marko Mikulicic 0:c0ecb8bf28eb 26983 ch_fl = dash_fl = 0;
Marko Mikulicic 0:c0ecb8bf28eb 26984 } else
Marko Mikulicic 0:c0ecb8bf28eb 26985 dash_fl = 1;
Marko Mikulicic 0:c0ecb8bf28eb 26986 } else {
Marko Mikulicic 0:c0ecb8bf28eb 26987 ch = '-';
Marko Mikulicic 0:c0ecb8bf28eb 26988 ch_fl = 1;
Marko Mikulicic 0:c0ecb8bf28eb 26989 }
Marko Mikulicic 0:c0ecb8bf28eb 26990 continue;
Marko Mikulicic 0:c0ecb8bf28eb 26991 }
Marko Mikulicic 0:c0ecb8bf28eb 26992 }
Marko Mikulicic 0:c0ecb8bf28eb 26993 if (ch_fl) {
Marko Mikulicic 0:c0ecb8bf28eb 26994 if (dash_fl) {
Marko Mikulicic 0:c0ecb8bf28eb 26995 re_rng2set(e, ch, e->curr_rune);
Marko Mikulicic 0:c0ecb8bf28eb 26996 ch_fl = dash_fl = 0;
Marko Mikulicic 0:c0ecb8bf28eb 26997 } else {
Marko Mikulicic 0:c0ecb8bf28eb 26998 re_char2set(e, ch);
Marko Mikulicic 0:c0ecb8bf28eb 26999 ch = e->curr_rune;
Marko Mikulicic 0:c0ecb8bf28eb 27000 }
Marko Mikulicic 0:c0ecb8bf28eb 27001 } else {
Marko Mikulicic 0:c0ecb8bf28eb 27002 ch = e->curr_rune;
Marko Mikulicic 0:c0ecb8bf28eb 27003 ch_fl = 1;
Marko Mikulicic 0:c0ecb8bf28eb 27004 }
Marko Mikulicic 0:c0ecb8bf28eb 27005 }
Marko Mikulicic 0:c0ecb8bf28eb 27006 if (ch_fl) {
Marko Mikulicic 0:c0ecb8bf28eb 27007 re_char2set(e, ch);
Marko Mikulicic 0:c0ecb8bf28eb 27008 if (dash_fl) re_char2set(e, '-');
Marko Mikulicic 0:c0ecb8bf28eb 27009 }
Marko Mikulicic 0:c0ecb8bf28eb 27010 return type;
Marko Mikulicic 0:c0ecb8bf28eb 27011 }
Marko Mikulicic 0:c0ecb8bf28eb 27012
Marko Mikulicic 0:c0ecb8bf28eb 27013 static int re_lexer(struct slre_env *e) {
Marko Mikulicic 0:c0ecb8bf28eb 27014 if (re_nextc_env(e)) {
Marko Mikulicic 0:c0ecb8bf28eb 27015 switch (e->curr_rune) {
Marko Mikulicic 0:c0ecb8bf28eb 27016 case '0':
Marko Mikulicic 0:c0ecb8bf28eb 27017 e->curr_rune = 0;
Marko Mikulicic 0:c0ecb8bf28eb 27018 return L_EOS;
Marko Mikulicic 0:c0ecb8bf28eb 27019 case 'b':
Marko Mikulicic 0:c0ecb8bf28eb 27020 return L_WORD;
Marko Mikulicic 0:c0ecb8bf28eb 27021 case 'B':
Marko Mikulicic 0:c0ecb8bf28eb 27022 return L_WORD_N;
Marko Mikulicic 0:c0ecb8bf28eb 27023 case 'd':
Marko Mikulicic 0:c0ecb8bf28eb 27024 re_nchset(e);
Marko Mikulicic 0:c0ecb8bf28eb 27025 re_d_2set(e);
Marko Mikulicic 0:c0ecb8bf28eb 27026 return L_CHSET;
Marko Mikulicic 0:c0ecb8bf28eb 27027 case 'D':
Marko Mikulicic 0:c0ecb8bf28eb 27028 re_nchset(e);
Marko Mikulicic 0:c0ecb8bf28eb 27029 re_d_2set(e);
Marko Mikulicic 0:c0ecb8bf28eb 27030 return L_SET_N;
Marko Mikulicic 0:c0ecb8bf28eb 27031 case 's':
Marko Mikulicic 0:c0ecb8bf28eb 27032 re_nchset(e);
Marko Mikulicic 0:c0ecb8bf28eb 27033 re_s_2set(e);
Marko Mikulicic 0:c0ecb8bf28eb 27034 return L_CHSET;
Marko Mikulicic 0:c0ecb8bf28eb 27035 case 'S':
Marko Mikulicic 0:c0ecb8bf28eb 27036 re_nchset(e);
Marko Mikulicic 0:c0ecb8bf28eb 27037 re_s_2set(e);
Marko Mikulicic 0:c0ecb8bf28eb 27038 return L_SET_N;
Marko Mikulicic 0:c0ecb8bf28eb 27039 case 'w':
Marko Mikulicic 0:c0ecb8bf28eb 27040 re_nchset(e);
Marko Mikulicic 0:c0ecb8bf28eb 27041 re_w_2set(e);
Marko Mikulicic 0:c0ecb8bf28eb 27042 return L_CHSET;
Marko Mikulicic 0:c0ecb8bf28eb 27043 case 'W':
Marko Mikulicic 0:c0ecb8bf28eb 27044 re_nchset(e);
Marko Mikulicic 0:c0ecb8bf28eb 27045 re_w_2set(e);
Marko Mikulicic 0:c0ecb8bf28eb 27046 return L_SET_N;
Marko Mikulicic 0:c0ecb8bf28eb 27047 }
Marko Mikulicic 0:c0ecb8bf28eb 27048 if (isdigitrune(e->curr_rune)) {
Marko Mikulicic 0:c0ecb8bf28eb 27049 e->curr_rune -= '0';
Marko Mikulicic 0:c0ecb8bf28eb 27050 if (isdigitrune(*e->src))
Marko Mikulicic 0:c0ecb8bf28eb 27051 e->curr_rune = e->curr_rune * 10 + *e->src++ - '0';
Marko Mikulicic 0:c0ecb8bf28eb 27052 return L_REF;
Marko Mikulicic 0:c0ecb8bf28eb 27053 }
Marko Mikulicic 0:c0ecb8bf28eb 27054 return L_CH;
Marko Mikulicic 0:c0ecb8bf28eb 27055 }
Marko Mikulicic 0:c0ecb8bf28eb 27056
Marko Mikulicic 0:c0ecb8bf28eb 27057 if (e->is_regex) {
Marko Mikulicic 0:c0ecb8bf28eb 27058 switch (e->curr_rune) {
Marko Mikulicic 0:c0ecb8bf28eb 27059 case 0:
Marko Mikulicic 0:c0ecb8bf28eb 27060 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 27061 case '$':
Marko Mikulicic 0:c0ecb8bf28eb 27062 case ')':
Marko Mikulicic 0:c0ecb8bf28eb 27063 case '*':
Marko Mikulicic 0:c0ecb8bf28eb 27064 case '+':
Marko Mikulicic 0:c0ecb8bf28eb 27065 case '.':
Marko Mikulicic 0:c0ecb8bf28eb 27066 case '?':
Marko Mikulicic 0:c0ecb8bf28eb 27067 case '^':
Marko Mikulicic 0:c0ecb8bf28eb 27068 case '|':
Marko Mikulicic 0:c0ecb8bf28eb 27069 return e->curr_rune;
Marko Mikulicic 0:c0ecb8bf28eb 27070 case '{':
Marko Mikulicic 0:c0ecb8bf28eb 27071 return re_countrep(e);
Marko Mikulicic 0:c0ecb8bf28eb 27072 case '[':
Marko Mikulicic 0:c0ecb8bf28eb 27073 return re_lexset(e);
Marko Mikulicic 0:c0ecb8bf28eb 27074 case '(':
Marko Mikulicic 0:c0ecb8bf28eb 27075 if (e->src[0] == '?') switch (e->src[1]) {
Marko Mikulicic 0:c0ecb8bf28eb 27076 case '=':
Marko Mikulicic 0:c0ecb8bf28eb 27077 e->src += 2;
Marko Mikulicic 0:c0ecb8bf28eb 27078 return L_LA;
Marko Mikulicic 0:c0ecb8bf28eb 27079 case ':':
Marko Mikulicic 0:c0ecb8bf28eb 27080 e->src += 2;
Marko Mikulicic 0:c0ecb8bf28eb 27081 return L_LA_CAP;
Marko Mikulicic 0:c0ecb8bf28eb 27082 case '!':
Marko Mikulicic 0:c0ecb8bf28eb 27083 e->src += 2;
Marko Mikulicic 0:c0ecb8bf28eb 27084 return L_LA_N;
Marko Mikulicic 0:c0ecb8bf28eb 27085 }
Marko Mikulicic 0:c0ecb8bf28eb 27086 return '(';
Marko Mikulicic 0:c0ecb8bf28eb 27087 }
Marko Mikulicic 0:c0ecb8bf28eb 27088 } else if (e->curr_rune == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 27089 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 27090 }
Marko Mikulicic 0:c0ecb8bf28eb 27091
Marko Mikulicic 0:c0ecb8bf28eb 27092 return L_CH;
Marko Mikulicic 0:c0ecb8bf28eb 27093 }
Marko Mikulicic 0:c0ecb8bf28eb 27094
Marko Mikulicic 0:c0ecb8bf28eb 27095 #define RE_NEXT(env) (env)->lookahead = re_lexer(env)
Marko Mikulicic 0:c0ecb8bf28eb 27096 #define RE_ACCEPT(env, t) ((env)->lookahead == (t) ? RE_NEXT(env), 1 : 0)
Marko Mikulicic 0:c0ecb8bf28eb 27097
Marko Mikulicic 0:c0ecb8bf28eb 27098 static struct slre_node *re_nnode(struct slre_env *e, int type) {
Marko Mikulicic 0:c0ecb8bf28eb 27099 memset(e->pend, 0, sizeof(struct slre_node));
Marko Mikulicic 0:c0ecb8bf28eb 27100 e->pend->type = type;
Marko Mikulicic 0:c0ecb8bf28eb 27101 return e->pend++;
Marko Mikulicic 0:c0ecb8bf28eb 27102 }
Marko Mikulicic 0:c0ecb8bf28eb 27103
Marko Mikulicic 0:c0ecb8bf28eb 27104 static unsigned char re_isemptynd(struct slre_node *nd) {
Marko Mikulicic 0:c0ecb8bf28eb 27105 if (!nd) return 1;
Marko Mikulicic 0:c0ecb8bf28eb 27106 switch (nd->type) {
Marko Mikulicic 0:c0ecb8bf28eb 27107 default:
Marko Mikulicic 0:c0ecb8bf28eb 27108 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 27109 case P_ANY:
Marko Mikulicic 0:c0ecb8bf28eb 27110 case P_CH:
Marko Mikulicic 0:c0ecb8bf28eb 27111 case P_SET:
Marko Mikulicic 0:c0ecb8bf28eb 27112 case P_SET_N:
Marko Mikulicic 0:c0ecb8bf28eb 27113 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 27114 case P_BRA:
Marko Mikulicic 0:c0ecb8bf28eb 27115 case P_REF:
Marko Mikulicic 0:c0ecb8bf28eb 27116 return re_isemptynd(nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27117 case P_CAT:
Marko Mikulicic 0:c0ecb8bf28eb 27118 return re_isemptynd(nd->par.xy.x) && re_isemptynd(nd->par.xy.y.y);
Marko Mikulicic 0:c0ecb8bf28eb 27119 case P_ALT:
Marko Mikulicic 0:c0ecb8bf28eb 27120 return re_isemptynd(nd->par.xy.x) || re_isemptynd(nd->par.xy.y.y);
Marko Mikulicic 0:c0ecb8bf28eb 27121 case P_REP:
Marko Mikulicic 0:c0ecb8bf28eb 27122 return re_isemptynd(nd->par.xy.x) || !nd->par.xy.y.rp.min;
Marko Mikulicic 0:c0ecb8bf28eb 27123 }
Marko Mikulicic 0:c0ecb8bf28eb 27124 }
Marko Mikulicic 0:c0ecb8bf28eb 27125
Marko Mikulicic 0:c0ecb8bf28eb 27126 static struct slre_node *re_nrep(struct slre_env *e, struct slre_node *nd,
Marko Mikulicic 0:c0ecb8bf28eb 27127 int ng, unsigned short min,
Marko Mikulicic 0:c0ecb8bf28eb 27128 unsigned short max) {
Marko Mikulicic 0:c0ecb8bf28eb 27129 struct slre_node *rep = re_nnode(e, P_REP);
Marko Mikulicic 0:c0ecb8bf28eb 27130 if (max == SLRE_MAX_REP && re_isemptynd(nd)) {
Marko Mikulicic 0:c0ecb8bf28eb 27131 SLRE_THROW(e, SLRE_INF_LOOP_M_EMP_STR);
Marko Mikulicic 0:c0ecb8bf28eb 27132 }
Marko Mikulicic 0:c0ecb8bf28eb 27133 rep->par.xy.y.rp.ng = ng;
Marko Mikulicic 0:c0ecb8bf28eb 27134 rep->par.xy.y.rp.min = min;
Marko Mikulicic 0:c0ecb8bf28eb 27135 rep->par.xy.y.rp.max = max;
Marko Mikulicic 0:c0ecb8bf28eb 27136 rep->par.xy.x = nd;
Marko Mikulicic 0:c0ecb8bf28eb 27137 return rep;
Marko Mikulicic 0:c0ecb8bf28eb 27138 }
Marko Mikulicic 0:c0ecb8bf28eb 27139
Marko Mikulicic 0:c0ecb8bf28eb 27140 static struct slre_node *re_parser(struct slre_env *e);
Marko Mikulicic 0:c0ecb8bf28eb 27141
Marko Mikulicic 0:c0ecb8bf28eb 27142 static struct slre_node *re_parse_la(struct slre_env *e) {
Marko Mikulicic 0:c0ecb8bf28eb 27143 struct slre_node *nd;
Marko Mikulicic 0:c0ecb8bf28eb 27144 int min, max;
Marko Mikulicic 0:c0ecb8bf28eb 27145 switch (e->lookahead) {
Marko Mikulicic 0:c0ecb8bf28eb 27146 case '^':
Marko Mikulicic 0:c0ecb8bf28eb 27147 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27148 return re_nnode(e, P_BOL);
Marko Mikulicic 0:c0ecb8bf28eb 27149 case '$':
Marko Mikulicic 0:c0ecb8bf28eb 27150 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27151 return re_nnode(e, P_EOL);
Marko Mikulicic 0:c0ecb8bf28eb 27152 case L_EOS:
Marko Mikulicic 0:c0ecb8bf28eb 27153 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27154 return re_nnode(e, P_EOS);
Marko Mikulicic 0:c0ecb8bf28eb 27155 case L_WORD:
Marko Mikulicic 0:c0ecb8bf28eb 27156 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27157 return re_nnode(e, P_WORD);
Marko Mikulicic 0:c0ecb8bf28eb 27158 case L_WORD_N:
Marko Mikulicic 0:c0ecb8bf28eb 27159 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27160 return re_nnode(e, P_WORD_N);
Marko Mikulicic 0:c0ecb8bf28eb 27161 }
Marko Mikulicic 0:c0ecb8bf28eb 27162
Marko Mikulicic 0:c0ecb8bf28eb 27163 switch (e->lookahead) {
Marko Mikulicic 0:c0ecb8bf28eb 27164 case L_CH:
Marko Mikulicic 0:c0ecb8bf28eb 27165 nd = re_nnode(e, P_CH);
Marko Mikulicic 0:c0ecb8bf28eb 27166 nd->par.c = e->curr_rune;
Marko Mikulicic 0:c0ecb8bf28eb 27167 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27168 break;
Marko Mikulicic 0:c0ecb8bf28eb 27169 case L_CHSET:
Marko Mikulicic 0:c0ecb8bf28eb 27170 nd = re_nnode(e, P_SET);
Marko Mikulicic 0:c0ecb8bf28eb 27171 nd->par.cp = e->curr_set;
Marko Mikulicic 0:c0ecb8bf28eb 27172 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27173 break;
Marko Mikulicic 0:c0ecb8bf28eb 27174 case L_SET_N:
Marko Mikulicic 0:c0ecb8bf28eb 27175 nd = re_nnode(e, P_SET_N);
Marko Mikulicic 0:c0ecb8bf28eb 27176 nd->par.cp = e->curr_set;
Marko Mikulicic 0:c0ecb8bf28eb 27177 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27178 break;
Marko Mikulicic 0:c0ecb8bf28eb 27179 case L_REF:
Marko Mikulicic 0:c0ecb8bf28eb 27180 nd = re_nnode(e, P_REF);
Marko Mikulicic 0:c0ecb8bf28eb 27181 if (!e->curr_rune || e->curr_rune > e->num_captures ||
Marko Mikulicic 0:c0ecb8bf28eb 27182 !e->caps[e->curr_rune]) {
Marko Mikulicic 0:c0ecb8bf28eb 27183 SLRE_THROW(e, SLRE_INVALID_BACK_REFERENCE);
Marko Mikulicic 0:c0ecb8bf28eb 27184 }
Marko Mikulicic 0:c0ecb8bf28eb 27185 nd->par.xy.y.n = e->curr_rune;
Marko Mikulicic 0:c0ecb8bf28eb 27186 nd->par.xy.x = e->caps[e->curr_rune];
Marko Mikulicic 0:c0ecb8bf28eb 27187 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27188 break;
Marko Mikulicic 0:c0ecb8bf28eb 27189 case '.':
Marko Mikulicic 0:c0ecb8bf28eb 27190 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27191 nd = re_nnode(e, P_ANY);
Marko Mikulicic 0:c0ecb8bf28eb 27192 break;
Marko Mikulicic 0:c0ecb8bf28eb 27193 case '(':
Marko Mikulicic 0:c0ecb8bf28eb 27194 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27195 nd = re_nnode(e, P_BRA);
Marko Mikulicic 0:c0ecb8bf28eb 27196 if (e->num_captures == SLRE_MAX_CAPS) {
Marko Mikulicic 0:c0ecb8bf28eb 27197 SLRE_THROW(e, SLRE_TOO_MANY_CAPTURES);
Marko Mikulicic 0:c0ecb8bf28eb 27198 }
Marko Mikulicic 0:c0ecb8bf28eb 27199 nd->par.xy.y.n = e->num_captures++;
Marko Mikulicic 0:c0ecb8bf28eb 27200 nd->par.xy.x = re_parser(e);
Marko Mikulicic 0:c0ecb8bf28eb 27201 e->caps[nd->par.xy.y.n] = nd;
Marko Mikulicic 0:c0ecb8bf28eb 27202 if (!RE_ACCEPT(e, ')')) {
Marko Mikulicic 0:c0ecb8bf28eb 27203 SLRE_THROW(e, SLRE_UNMATCH_LBR);
Marko Mikulicic 0:c0ecb8bf28eb 27204 }
Marko Mikulicic 0:c0ecb8bf28eb 27205 break;
Marko Mikulicic 0:c0ecb8bf28eb 27206 case L_LA:
Marko Mikulicic 0:c0ecb8bf28eb 27207 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27208 nd = re_nnode(e, P_LA);
Marko Mikulicic 0:c0ecb8bf28eb 27209 nd->par.xy.x = re_parser(e);
Marko Mikulicic 0:c0ecb8bf28eb 27210 if (!RE_ACCEPT(e, ')')) {
Marko Mikulicic 0:c0ecb8bf28eb 27211 SLRE_THROW(e, SLRE_UNMATCH_LBR);
Marko Mikulicic 0:c0ecb8bf28eb 27212 }
Marko Mikulicic 0:c0ecb8bf28eb 27213 break;
Marko Mikulicic 0:c0ecb8bf28eb 27214 case L_LA_CAP:
Marko Mikulicic 0:c0ecb8bf28eb 27215 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27216 nd = re_parser(e);
Marko Mikulicic 0:c0ecb8bf28eb 27217 if (!RE_ACCEPT(e, ')')) {
Marko Mikulicic 0:c0ecb8bf28eb 27218 SLRE_THROW(e, SLRE_UNMATCH_LBR);
Marko Mikulicic 0:c0ecb8bf28eb 27219 }
Marko Mikulicic 0:c0ecb8bf28eb 27220 break;
Marko Mikulicic 0:c0ecb8bf28eb 27221 case L_LA_N:
Marko Mikulicic 0:c0ecb8bf28eb 27222 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27223 nd = re_nnode(e, P_LA_N);
Marko Mikulicic 0:c0ecb8bf28eb 27224 nd->par.xy.x = re_parser(e);
Marko Mikulicic 0:c0ecb8bf28eb 27225 if (!RE_ACCEPT(e, ')')) {
Marko Mikulicic 0:c0ecb8bf28eb 27226 SLRE_THROW(e, SLRE_UNMATCH_LBR);
Marko Mikulicic 0:c0ecb8bf28eb 27227 }
Marko Mikulicic 0:c0ecb8bf28eb 27228 break;
Marko Mikulicic 0:c0ecb8bf28eb 27229 default:
Marko Mikulicic 0:c0ecb8bf28eb 27230 SLRE_THROW(e, SLRE_SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 27231 }
Marko Mikulicic 0:c0ecb8bf28eb 27232
Marko Mikulicic 0:c0ecb8bf28eb 27233 switch (e->lookahead) {
Marko Mikulicic 0:c0ecb8bf28eb 27234 case '*':
Marko Mikulicic 0:c0ecb8bf28eb 27235 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27236 return re_nrep(e, nd, RE_ACCEPT(e, '?'), 0, SLRE_MAX_REP);
Marko Mikulicic 0:c0ecb8bf28eb 27237 case '+':
Marko Mikulicic 0:c0ecb8bf28eb 27238 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27239 return re_nrep(e, nd, RE_ACCEPT(e, '?'), 1, SLRE_MAX_REP);
Marko Mikulicic 0:c0ecb8bf28eb 27240 case '?':
Marko Mikulicic 0:c0ecb8bf28eb 27241 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27242 return re_nrep(e, nd, RE_ACCEPT(e, '?'), 0, 1);
Marko Mikulicic 0:c0ecb8bf28eb 27243 case L_COUNT:
Marko Mikulicic 0:c0ecb8bf28eb 27244 min = e->min_rep, max = e->max_rep;
Marko Mikulicic 0:c0ecb8bf28eb 27245 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27246 if (max < min) {
Marko Mikulicic 0:c0ecb8bf28eb 27247 SLRE_THROW(e, SLRE_INVALID_QUANTIFIER);
Marko Mikulicic 0:c0ecb8bf28eb 27248 }
Marko Mikulicic 0:c0ecb8bf28eb 27249 return re_nrep(e, nd, RE_ACCEPT(e, '?'), min, max);
Marko Mikulicic 0:c0ecb8bf28eb 27250 }
Marko Mikulicic 0:c0ecb8bf28eb 27251 return nd;
Marko Mikulicic 0:c0ecb8bf28eb 27252 }
Marko Mikulicic 0:c0ecb8bf28eb 27253
Marko Mikulicic 0:c0ecb8bf28eb 27254 static unsigned char re_endofcat(Rune c, int is_regex) {
Marko Mikulicic 0:c0ecb8bf28eb 27255 switch (c) {
Marko Mikulicic 0:c0ecb8bf28eb 27256 case 0:
Marko Mikulicic 0:c0ecb8bf28eb 27257 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 27258 case '|':
Marko Mikulicic 0:c0ecb8bf28eb 27259 case ')':
Marko Mikulicic 0:c0ecb8bf28eb 27260 if (is_regex) return 1;
Marko Mikulicic 0:c0ecb8bf28eb 27261 }
Marko Mikulicic 0:c0ecb8bf28eb 27262 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 27263 }
Marko Mikulicic 0:c0ecb8bf28eb 27264
Marko Mikulicic 0:c0ecb8bf28eb 27265 static struct slre_node *re_parser(struct slre_env *e) {
Marko Mikulicic 0:c0ecb8bf28eb 27266 struct slre_node *alt = NULL, *cat, *nd;
Marko Mikulicic 0:c0ecb8bf28eb 27267 if (!re_endofcat(e->lookahead, e->is_regex)) {
Marko Mikulicic 0:c0ecb8bf28eb 27268 cat = re_parse_la(e);
Marko Mikulicic 0:c0ecb8bf28eb 27269 while (!re_endofcat(e->lookahead, e->is_regex)) {
Marko Mikulicic 0:c0ecb8bf28eb 27270 nd = cat;
Marko Mikulicic 0:c0ecb8bf28eb 27271 cat = re_nnode(e, P_CAT);
Marko Mikulicic 0:c0ecb8bf28eb 27272 cat->par.xy.x = nd;
Marko Mikulicic 0:c0ecb8bf28eb 27273 cat->par.xy.y.y = re_parse_la(e);
Marko Mikulicic 0:c0ecb8bf28eb 27274 }
Marko Mikulicic 0:c0ecb8bf28eb 27275 alt = cat;
Marko Mikulicic 0:c0ecb8bf28eb 27276 }
Marko Mikulicic 0:c0ecb8bf28eb 27277 if (e->lookahead == '|') {
Marko Mikulicic 0:c0ecb8bf28eb 27278 RE_NEXT(e);
Marko Mikulicic 0:c0ecb8bf28eb 27279 nd = alt;
Marko Mikulicic 0:c0ecb8bf28eb 27280 alt = re_nnode(e, P_ALT);
Marko Mikulicic 0:c0ecb8bf28eb 27281 alt->par.xy.x = nd;
Marko Mikulicic 0:c0ecb8bf28eb 27282 alt->par.xy.y.y = re_parser(e);
Marko Mikulicic 0:c0ecb8bf28eb 27283 }
Marko Mikulicic 0:c0ecb8bf28eb 27284 return alt;
Marko Mikulicic 0:c0ecb8bf28eb 27285 }
Marko Mikulicic 0:c0ecb8bf28eb 27286
Marko Mikulicic 0:c0ecb8bf28eb 27287 static unsigned int re_nodelen(struct slre_node *nd) {
Marko Mikulicic 0:c0ecb8bf28eb 27288 unsigned int n = 0;
Marko Mikulicic 0:c0ecb8bf28eb 27289 if (!nd) return 0;
Marko Mikulicic 0:c0ecb8bf28eb 27290 switch (nd->type) {
Marko Mikulicic 0:c0ecb8bf28eb 27291 case P_ALT:
Marko Mikulicic 0:c0ecb8bf28eb 27292 n = 2;
Marko Mikulicic 0:c0ecb8bf28eb 27293 case P_CAT:
Marko Mikulicic 0:c0ecb8bf28eb 27294 return re_nodelen(nd->par.xy.x) + re_nodelen(nd->par.xy.y.y) + n;
Marko Mikulicic 0:c0ecb8bf28eb 27295 case P_BRA:
Marko Mikulicic 0:c0ecb8bf28eb 27296 case P_LA:
Marko Mikulicic 0:c0ecb8bf28eb 27297 case P_LA_N:
Marko Mikulicic 0:c0ecb8bf28eb 27298 return re_nodelen(nd->par.xy.x) + 2;
Marko Mikulicic 0:c0ecb8bf28eb 27299 case P_REP:
Marko Mikulicic 0:c0ecb8bf28eb 27300 n = nd->par.xy.y.rp.max - nd->par.xy.y.rp.min;
Marko Mikulicic 0:c0ecb8bf28eb 27301 switch (nd->par.xy.y.rp.min) {
Marko Mikulicic 0:c0ecb8bf28eb 27302 case 0:
Marko Mikulicic 0:c0ecb8bf28eb 27303 if (!n) return 0;
Marko Mikulicic 0:c0ecb8bf28eb 27304 if (nd->par.xy.y.rp.max >= SLRE_MAX_REP)
Marko Mikulicic 0:c0ecb8bf28eb 27305 return re_nodelen(nd->par.xy.x) + 2;
Marko Mikulicic 0:c0ecb8bf28eb 27306 case 1:
Marko Mikulicic 0:c0ecb8bf28eb 27307 if (!n) return re_nodelen(nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27308 if (nd->par.xy.y.rp.max >= SLRE_MAX_REP)
Marko Mikulicic 0:c0ecb8bf28eb 27309 return re_nodelen(nd->par.xy.x) + 1;
Marko Mikulicic 0:c0ecb8bf28eb 27310 default:
Marko Mikulicic 0:c0ecb8bf28eb 27311 n = 4;
Marko Mikulicic 0:c0ecb8bf28eb 27312 if (nd->par.xy.y.rp.max >= SLRE_MAX_REP) n++;
Marko Mikulicic 0:c0ecb8bf28eb 27313 return re_nodelen(nd->par.xy.x) + n;
Marko Mikulicic 0:c0ecb8bf28eb 27314 }
Marko Mikulicic 0:c0ecb8bf28eb 27315 default:
Marko Mikulicic 0:c0ecb8bf28eb 27316 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 27317 }
Marko Mikulicic 0:c0ecb8bf28eb 27318 }
Marko Mikulicic 0:c0ecb8bf28eb 27319
Marko Mikulicic 0:c0ecb8bf28eb 27320 static struct slre_instruction *re_newinst(struct slre_prog *prog, int opcode) {
Marko Mikulicic 0:c0ecb8bf28eb 27321 memset(prog->end, 0, sizeof(struct slre_instruction));
Marko Mikulicic 0:c0ecb8bf28eb 27322 prog->end->opcode = opcode;
Marko Mikulicic 0:c0ecb8bf28eb 27323 return prog->end++;
Marko Mikulicic 0:c0ecb8bf28eb 27324 }
Marko Mikulicic 0:c0ecb8bf28eb 27325
Marko Mikulicic 0:c0ecb8bf28eb 27326 static void re_compile(struct slre_env *e, struct slre_node *nd) {
Marko Mikulicic 0:c0ecb8bf28eb 27327 struct slre_instruction *inst, *split, *jump, *rep;
Marko Mikulicic 0:c0ecb8bf28eb 27328 unsigned int n;
Marko Mikulicic 0:c0ecb8bf28eb 27329
Marko Mikulicic 0:c0ecb8bf28eb 27330 if (!nd) return;
Marko Mikulicic 0:c0ecb8bf28eb 27331
Marko Mikulicic 0:c0ecb8bf28eb 27332 switch (nd->type) {
Marko Mikulicic 0:c0ecb8bf28eb 27333 case P_ALT:
Marko Mikulicic 0:c0ecb8bf28eb 27334 split = re_newinst(e->prog, I_SPLIT);
Marko Mikulicic 0:c0ecb8bf28eb 27335 re_compile(e, nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27336 jump = re_newinst(e->prog, I_JUMP);
Marko Mikulicic 0:c0ecb8bf28eb 27337 re_compile(e, nd->par.xy.y.y);
Marko Mikulicic 0:c0ecb8bf28eb 27338 split->par.xy.x = split + 1;
Marko Mikulicic 0:c0ecb8bf28eb 27339 split->par.xy.y.y = jump + 1;
Marko Mikulicic 0:c0ecb8bf28eb 27340 jump->par.xy.x = e->prog->end;
Marko Mikulicic 0:c0ecb8bf28eb 27341 break;
Marko Mikulicic 0:c0ecb8bf28eb 27342
Marko Mikulicic 0:c0ecb8bf28eb 27343 case P_ANY:
Marko Mikulicic 0:c0ecb8bf28eb 27344 re_newinst(e->prog, I_ANY);
Marko Mikulicic 0:c0ecb8bf28eb 27345 break;
Marko Mikulicic 0:c0ecb8bf28eb 27346
Marko Mikulicic 0:c0ecb8bf28eb 27347 case P_BOL:
Marko Mikulicic 0:c0ecb8bf28eb 27348 re_newinst(e->prog, I_BOL);
Marko Mikulicic 0:c0ecb8bf28eb 27349 break;
Marko Mikulicic 0:c0ecb8bf28eb 27350
Marko Mikulicic 0:c0ecb8bf28eb 27351 case P_BRA:
Marko Mikulicic 0:c0ecb8bf28eb 27352 inst = re_newinst(e->prog, I_LBRA);
Marko Mikulicic 0:c0ecb8bf28eb 27353 inst->par.n = nd->par.xy.y.n;
Marko Mikulicic 0:c0ecb8bf28eb 27354 re_compile(e, nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27355 inst = re_newinst(e->prog, I_RBRA);
Marko Mikulicic 0:c0ecb8bf28eb 27356 inst->par.n = nd->par.xy.y.n;
Marko Mikulicic 0:c0ecb8bf28eb 27357 break;
Marko Mikulicic 0:c0ecb8bf28eb 27358
Marko Mikulicic 0:c0ecb8bf28eb 27359 case P_CAT:
Marko Mikulicic 0:c0ecb8bf28eb 27360 re_compile(e, nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27361 re_compile(e, nd->par.xy.y.y);
Marko Mikulicic 0:c0ecb8bf28eb 27362 break;
Marko Mikulicic 0:c0ecb8bf28eb 27363
Marko Mikulicic 0:c0ecb8bf28eb 27364 case P_CH:
Marko Mikulicic 0:c0ecb8bf28eb 27365 inst = re_newinst(e->prog, I_CH);
Marko Mikulicic 0:c0ecb8bf28eb 27366 inst->par.c = nd->par.c;
Marko Mikulicic 0:c0ecb8bf28eb 27367 break;
Marko Mikulicic 0:c0ecb8bf28eb 27368
Marko Mikulicic 0:c0ecb8bf28eb 27369 case P_EOL:
Marko Mikulicic 0:c0ecb8bf28eb 27370 re_newinst(e->prog, I_EOL);
Marko Mikulicic 0:c0ecb8bf28eb 27371 break;
Marko Mikulicic 0:c0ecb8bf28eb 27372
Marko Mikulicic 0:c0ecb8bf28eb 27373 case P_EOS:
Marko Mikulicic 0:c0ecb8bf28eb 27374 re_newinst(e->prog, I_EOS);
Marko Mikulicic 0:c0ecb8bf28eb 27375 break;
Marko Mikulicic 0:c0ecb8bf28eb 27376
Marko Mikulicic 0:c0ecb8bf28eb 27377 case P_LA:
Marko Mikulicic 0:c0ecb8bf28eb 27378 split = re_newinst(e->prog, I_LA);
Marko Mikulicic 0:c0ecb8bf28eb 27379 re_compile(e, nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27380 re_newinst(e->prog, I_END);
Marko Mikulicic 0:c0ecb8bf28eb 27381 split->par.xy.x = split + 1;
Marko Mikulicic 0:c0ecb8bf28eb 27382 split->par.xy.y.y = e->prog->end;
Marko Mikulicic 0:c0ecb8bf28eb 27383 break;
Marko Mikulicic 0:c0ecb8bf28eb 27384 case P_LA_N:
Marko Mikulicic 0:c0ecb8bf28eb 27385 split = re_newinst(e->prog, I_LA_N);
Marko Mikulicic 0:c0ecb8bf28eb 27386 re_compile(e, nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27387 re_newinst(e->prog, I_END);
Marko Mikulicic 0:c0ecb8bf28eb 27388 split->par.xy.x = split + 1;
Marko Mikulicic 0:c0ecb8bf28eb 27389 split->par.xy.y.y = e->prog->end;
Marko Mikulicic 0:c0ecb8bf28eb 27390 break;
Marko Mikulicic 0:c0ecb8bf28eb 27391
Marko Mikulicic 0:c0ecb8bf28eb 27392 case P_REF:
Marko Mikulicic 0:c0ecb8bf28eb 27393 inst = re_newinst(e->prog, I_REF);
Marko Mikulicic 0:c0ecb8bf28eb 27394 inst->par.n = nd->par.xy.y.n;
Marko Mikulicic 0:c0ecb8bf28eb 27395 break;
Marko Mikulicic 0:c0ecb8bf28eb 27396
Marko Mikulicic 0:c0ecb8bf28eb 27397 case P_REP:
Marko Mikulicic 0:c0ecb8bf28eb 27398 n = nd->par.xy.y.rp.max - nd->par.xy.y.rp.min;
Marko Mikulicic 0:c0ecb8bf28eb 27399 switch (nd->par.xy.y.rp.min) {
Marko Mikulicic 0:c0ecb8bf28eb 27400 case 0:
Marko Mikulicic 0:c0ecb8bf28eb 27401 if (!n) break;
Marko Mikulicic 0:c0ecb8bf28eb 27402 if (nd->par.xy.y.rp.max >= SLRE_MAX_REP) {
Marko Mikulicic 0:c0ecb8bf28eb 27403 split = re_newinst(e->prog, I_SPLIT);
Marko Mikulicic 0:c0ecb8bf28eb 27404 re_compile(e, nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27405 jump = re_newinst(e->prog, I_JUMP);
Marko Mikulicic 0:c0ecb8bf28eb 27406 jump->par.xy.x = split;
Marko Mikulicic 0:c0ecb8bf28eb 27407 split->par.xy.x = split + 1;
Marko Mikulicic 0:c0ecb8bf28eb 27408 split->par.xy.y.y = e->prog->end;
Marko Mikulicic 0:c0ecb8bf28eb 27409 if (nd->par.xy.y.rp.ng) {
Marko Mikulicic 0:c0ecb8bf28eb 27410 split->par.xy.y.y = split + 1;
Marko Mikulicic 0:c0ecb8bf28eb 27411 split->par.xy.x = e->prog->end;
Marko Mikulicic 0:c0ecb8bf28eb 27412 }
Marko Mikulicic 0:c0ecb8bf28eb 27413 break;
Marko Mikulicic 0:c0ecb8bf28eb 27414 }
Marko Mikulicic 0:c0ecb8bf28eb 27415 case 1:
Marko Mikulicic 0:c0ecb8bf28eb 27416 if (!n) {
Marko Mikulicic 0:c0ecb8bf28eb 27417 re_compile(e, nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27418 break;
Marko Mikulicic 0:c0ecb8bf28eb 27419 }
Marko Mikulicic 0:c0ecb8bf28eb 27420 if (nd->par.xy.y.rp.max >= SLRE_MAX_REP) {
Marko Mikulicic 0:c0ecb8bf28eb 27421 inst = e->prog->end;
Marko Mikulicic 0:c0ecb8bf28eb 27422 re_compile(e, nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27423 split = re_newinst(e->prog, I_SPLIT);
Marko Mikulicic 0:c0ecb8bf28eb 27424 split->par.xy.x = inst;
Marko Mikulicic 0:c0ecb8bf28eb 27425 split->par.xy.y.y = e->prog->end;
Marko Mikulicic 0:c0ecb8bf28eb 27426 if (nd->par.xy.y.rp.ng) {
Marko Mikulicic 0:c0ecb8bf28eb 27427 split->par.xy.y.y = inst;
Marko Mikulicic 0:c0ecb8bf28eb 27428 split->par.xy.x = e->prog->end;
Marko Mikulicic 0:c0ecb8bf28eb 27429 }
Marko Mikulicic 0:c0ecb8bf28eb 27430 break;
Marko Mikulicic 0:c0ecb8bf28eb 27431 }
Marko Mikulicic 0:c0ecb8bf28eb 27432 default:
Marko Mikulicic 0:c0ecb8bf28eb 27433 inst = re_newinst(e->prog, I_REP_INI);
Marko Mikulicic 0:c0ecb8bf28eb 27434 inst->par.xy.y.rp.min = nd->par.xy.y.rp.min;
Marko Mikulicic 0:c0ecb8bf28eb 27435 inst->par.xy.y.rp.max = n;
Marko Mikulicic 0:c0ecb8bf28eb 27436 rep = re_newinst(e->prog, I_REP);
Marko Mikulicic 0:c0ecb8bf28eb 27437 split = re_newinst(e->prog, I_SPLIT);
Marko Mikulicic 0:c0ecb8bf28eb 27438 re_compile(e, nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27439 jump = re_newinst(e->prog, I_JUMP);
Marko Mikulicic 0:c0ecb8bf28eb 27440 jump->par.xy.x = rep;
Marko Mikulicic 0:c0ecb8bf28eb 27441 rep->par.xy.x = e->prog->end;
Marko Mikulicic 0:c0ecb8bf28eb 27442 split->par.xy.x = split + 1;
Marko Mikulicic 0:c0ecb8bf28eb 27443 split->par.xy.y.y = e->prog->end;
Marko Mikulicic 0:c0ecb8bf28eb 27444 if (nd->par.xy.y.rp.ng) {
Marko Mikulicic 0:c0ecb8bf28eb 27445 split->par.xy.y.y = split + 1;
Marko Mikulicic 0:c0ecb8bf28eb 27446 split->par.xy.x = e->prog->end;
Marko Mikulicic 0:c0ecb8bf28eb 27447 }
Marko Mikulicic 0:c0ecb8bf28eb 27448 if (nd->par.xy.y.rp.max >= SLRE_MAX_REP) {
Marko Mikulicic 0:c0ecb8bf28eb 27449 inst = split + 1;
Marko Mikulicic 0:c0ecb8bf28eb 27450 split = re_newinst(e->prog, I_SPLIT);
Marko Mikulicic 0:c0ecb8bf28eb 27451 split->par.xy.x = inst;
Marko Mikulicic 0:c0ecb8bf28eb 27452 split->par.xy.y.y = e->prog->end;
Marko Mikulicic 0:c0ecb8bf28eb 27453 if (nd->par.xy.y.rp.ng) {
Marko Mikulicic 0:c0ecb8bf28eb 27454 split->par.xy.y.y = inst;
Marko Mikulicic 0:c0ecb8bf28eb 27455 split->par.xy.x = e->prog->end;
Marko Mikulicic 0:c0ecb8bf28eb 27456 }
Marko Mikulicic 0:c0ecb8bf28eb 27457 break;
Marko Mikulicic 0:c0ecb8bf28eb 27458 }
Marko Mikulicic 0:c0ecb8bf28eb 27459 break;
Marko Mikulicic 0:c0ecb8bf28eb 27460 }
Marko Mikulicic 0:c0ecb8bf28eb 27461 break;
Marko Mikulicic 0:c0ecb8bf28eb 27462
Marko Mikulicic 0:c0ecb8bf28eb 27463 case P_SET:
Marko Mikulicic 0:c0ecb8bf28eb 27464 inst = re_newinst(e->prog, I_SET);
Marko Mikulicic 0:c0ecb8bf28eb 27465 inst->par.cp = nd->par.cp;
Marko Mikulicic 0:c0ecb8bf28eb 27466 break;
Marko Mikulicic 0:c0ecb8bf28eb 27467 case P_SET_N:
Marko Mikulicic 0:c0ecb8bf28eb 27468 inst = re_newinst(e->prog, I_SET_N);
Marko Mikulicic 0:c0ecb8bf28eb 27469 inst->par.cp = nd->par.cp;
Marko Mikulicic 0:c0ecb8bf28eb 27470 break;
Marko Mikulicic 0:c0ecb8bf28eb 27471
Marko Mikulicic 0:c0ecb8bf28eb 27472 case P_WORD:
Marko Mikulicic 0:c0ecb8bf28eb 27473 re_newinst(e->prog, I_WORD);
Marko Mikulicic 0:c0ecb8bf28eb 27474 break;
Marko Mikulicic 0:c0ecb8bf28eb 27475 case P_WORD_N:
Marko Mikulicic 0:c0ecb8bf28eb 27476 re_newinst(e->prog, I_WORD_N);
Marko Mikulicic 0:c0ecb8bf28eb 27477 break;
Marko Mikulicic 0:c0ecb8bf28eb 27478 }
Marko Mikulicic 0:c0ecb8bf28eb 27479 }
Marko Mikulicic 0:c0ecb8bf28eb 27480
Marko Mikulicic 0:c0ecb8bf28eb 27481 #ifdef RE_TEST
Marko Mikulicic 0:c0ecb8bf28eb 27482 static void print_set(struct slre_class *cp) {
Marko Mikulicic 0:c0ecb8bf28eb 27483 struct slre_range *p;
Marko Mikulicic 0:c0ecb8bf28eb 27484 for (p = cp->spans; p < cp->end; p++) {
Marko Mikulicic 0:c0ecb8bf28eb 27485 printf("%s", p == cp->spans ? "'" : ",'");
Marko Mikulicic 0:c0ecb8bf28eb 27486 printf(
Marko Mikulicic 0:c0ecb8bf28eb 27487 p->s >= 32 && p->s < 127 ? "%c" : (p->s < 256 ? "\\x%02X" : "\\u%04X"),
Marko Mikulicic 0:c0ecb8bf28eb 27488 p->s);
Marko Mikulicic 0:c0ecb8bf28eb 27489 if (p->s != p->e) {
Marko Mikulicic 0:c0ecb8bf28eb 27490 printf(p->e >= 32 && p->e < 127 ? "-%c"
Marko Mikulicic 0:c0ecb8bf28eb 27491 : (p->e < 256 ? "-\\x%02X" : "-\\u%04X"),
Marko Mikulicic 0:c0ecb8bf28eb 27492 p->e);
Marko Mikulicic 0:c0ecb8bf28eb 27493 }
Marko Mikulicic 0:c0ecb8bf28eb 27494 printf("'");
Marko Mikulicic 0:c0ecb8bf28eb 27495 }
Marko Mikulicic 0:c0ecb8bf28eb 27496 printf("]");
Marko Mikulicic 0:c0ecb8bf28eb 27497 }
Marko Mikulicic 0:c0ecb8bf28eb 27498
Marko Mikulicic 0:c0ecb8bf28eb 27499 static void node_print(struct slre_node *nd) {
Marko Mikulicic 0:c0ecb8bf28eb 27500 if (!nd) {
Marko Mikulicic 0:c0ecb8bf28eb 27501 printf("Empty");
Marko Mikulicic 0:c0ecb8bf28eb 27502 return;
Marko Mikulicic 0:c0ecb8bf28eb 27503 }
Marko Mikulicic 0:c0ecb8bf28eb 27504 switch (nd->type) {
Marko Mikulicic 0:c0ecb8bf28eb 27505 case P_ALT:
Marko Mikulicic 0:c0ecb8bf28eb 27506 printf("{");
Marko Mikulicic 0:c0ecb8bf28eb 27507 node_print(nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27508 printf(" | ");
Marko Mikulicic 0:c0ecb8bf28eb 27509 node_print(nd->par.xy.y.y);
Marko Mikulicic 0:c0ecb8bf28eb 27510 printf("}");
Marko Mikulicic 0:c0ecb8bf28eb 27511 break;
Marko Mikulicic 0:c0ecb8bf28eb 27512 case P_ANY:
Marko Mikulicic 0:c0ecb8bf28eb 27513 printf(".");
Marko Mikulicic 0:c0ecb8bf28eb 27514 break;
Marko Mikulicic 0:c0ecb8bf28eb 27515 case P_BOL:
Marko Mikulicic 0:c0ecb8bf28eb 27516 printf("^");
Marko Mikulicic 0:c0ecb8bf28eb 27517 break;
Marko Mikulicic 0:c0ecb8bf28eb 27518 case P_BRA:
Marko Mikulicic 0:c0ecb8bf28eb 27519 node_print(nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27520 printf(")");
Marko Mikulicic 0:c0ecb8bf28eb 27521 break;
Marko Mikulicic 0:c0ecb8bf28eb 27522 case P_CAT:
Marko Mikulicic 0:c0ecb8bf28eb 27523 printf("{");
Marko Mikulicic 0:c0ecb8bf28eb 27524 node_print(nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27525 printf(" & ");
Marko Mikulicic 0:c0ecb8bf28eb 27526 node_print(nd->par.xy.y.y);
Marko Mikulicic 0:c0ecb8bf28eb 27527 printf("}");
Marko Mikulicic 0:c0ecb8bf28eb 27528 break;
Marko Mikulicic 0:c0ecb8bf28eb 27529 case P_CH:
Marko Mikulicic 0:c0ecb8bf28eb 27530 printf(nd->par.c >= 32 && nd->par.c < 127 ? "'%c'" : "'\\u%04X'",
Marko Mikulicic 0:c0ecb8bf28eb 27531 nd->par.c);
Marko Mikulicic 0:c0ecb8bf28eb 27532 break;
Marko Mikulicic 0:c0ecb8bf28eb 27533 case P_EOL:
Marko Mikulicic 0:c0ecb8bf28eb 27534 printf("$");
Marko Mikulicic 0:c0ecb8bf28eb 27535 break;
Marko Mikulicic 0:c0ecb8bf28eb 27536 case P_EOS:
Marko Mikulicic 0:c0ecb8bf28eb 27537 printf("\\0");
Marko Mikulicic 0:c0ecb8bf28eb 27538 break;
Marko Mikulicic 0:c0ecb8bf28eb 27539 case P_LA:
Marko Mikulicic 0:c0ecb8bf28eb 27540 printf("LA(");
Marko Mikulicic 0:c0ecb8bf28eb 27541 node_print(nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27542 printf(")");
Marko Mikulicic 0:c0ecb8bf28eb 27543 break;
Marko Mikulicic 0:c0ecb8bf28eb 27544 case P_LA_N:
Marko Mikulicic 0:c0ecb8bf28eb 27545 printf("LA_N(");
Marko Mikulicic 0:c0ecb8bf28eb 27546 node_print(nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27547 printf(")");
Marko Mikulicic 0:c0ecb8bf28eb 27548 break;
Marko Mikulicic 0:c0ecb8bf28eb 27549 case P_REF:
Marko Mikulicic 0:c0ecb8bf28eb 27550 printf("\\%d", nd->par.xy.y.n);
Marko Mikulicic 0:c0ecb8bf28eb 27551 break;
Marko Mikulicic 0:c0ecb8bf28eb 27552 case P_REP:
Marko Mikulicic 0:c0ecb8bf28eb 27553 node_print(nd->par.xy.x);
Marko Mikulicic 0:c0ecb8bf28eb 27554 printf(nd->par.xy.y.rp.ng ? "{%d,%d}?" : "{%d,%d}", nd->par.xy.y.rp.min,
Marko Mikulicic 0:c0ecb8bf28eb 27555 nd->par.xy.y.rp.max);
Marko Mikulicic 0:c0ecb8bf28eb 27556 break;
Marko Mikulicic 0:c0ecb8bf28eb 27557 case P_SET:
Marko Mikulicic 0:c0ecb8bf28eb 27558 printf("[");
Marko Mikulicic 0:c0ecb8bf28eb 27559 print_set(nd->par.cp);
Marko Mikulicic 0:c0ecb8bf28eb 27560 break;
Marko Mikulicic 0:c0ecb8bf28eb 27561 case P_SET_N:
Marko Mikulicic 0:c0ecb8bf28eb 27562 printf("[^");
Marko Mikulicic 0:c0ecb8bf28eb 27563 print_set(nd->par.cp);
Marko Mikulicic 0:c0ecb8bf28eb 27564 break;
Marko Mikulicic 0:c0ecb8bf28eb 27565 case P_WORD:
Marko Mikulicic 0:c0ecb8bf28eb 27566 printf("\\b");
Marko Mikulicic 0:c0ecb8bf28eb 27567 break;
Marko Mikulicic 0:c0ecb8bf28eb 27568 case P_WORD_N:
Marko Mikulicic 0:c0ecb8bf28eb 27569 printf("\\B");
Marko Mikulicic 0:c0ecb8bf28eb 27570 break;
Marko Mikulicic 0:c0ecb8bf28eb 27571 }
Marko Mikulicic 0:c0ecb8bf28eb 27572 }
Marko Mikulicic 0:c0ecb8bf28eb 27573
Marko Mikulicic 0:c0ecb8bf28eb 27574 static void program_print(struct slre_prog *prog) {
Marko Mikulicic 0:c0ecb8bf28eb 27575 struct slre_instruction *inst;
Marko Mikulicic 0:c0ecb8bf28eb 27576 for (inst = prog->start; inst < prog->end; ++inst) {
Marko Mikulicic 0:c0ecb8bf28eb 27577 printf("%3d: ", inst - prog->start);
Marko Mikulicic 0:c0ecb8bf28eb 27578 switch (inst->opcode) {
Marko Mikulicic 0:c0ecb8bf28eb 27579 case I_END:
Marko Mikulicic 0:c0ecb8bf28eb 27580 puts("end");
Marko Mikulicic 0:c0ecb8bf28eb 27581 break;
Marko Mikulicic 0:c0ecb8bf28eb 27582 case I_ANY:
Marko Mikulicic 0:c0ecb8bf28eb 27583 puts(".");
Marko Mikulicic 0:c0ecb8bf28eb 27584 break;
Marko Mikulicic 0:c0ecb8bf28eb 27585 case I_ANYNL:
Marko Mikulicic 0:c0ecb8bf28eb 27586 puts(". | '\\r' | '\\n'");
Marko Mikulicic 0:c0ecb8bf28eb 27587 break;
Marko Mikulicic 0:c0ecb8bf28eb 27588 case I_BOL:
Marko Mikulicic 0:c0ecb8bf28eb 27589 puts("^");
Marko Mikulicic 0:c0ecb8bf28eb 27590 break;
Marko Mikulicic 0:c0ecb8bf28eb 27591 case I_CH:
Marko Mikulicic 0:c0ecb8bf28eb 27592 printf(
Marko Mikulicic 0:c0ecb8bf28eb 27593 inst->par.c >= 32 && inst->par.c < 127 ? "'%c'\n" : "'\\u%04X'\n",
Marko Mikulicic 0:c0ecb8bf28eb 27594 inst->par.c);
Marko Mikulicic 0:c0ecb8bf28eb 27595 break;
Marko Mikulicic 0:c0ecb8bf28eb 27596 case I_EOL:
Marko Mikulicic 0:c0ecb8bf28eb 27597 puts("$");
Marko Mikulicic 0:c0ecb8bf28eb 27598 break;
Marko Mikulicic 0:c0ecb8bf28eb 27599 case I_EOS:
Marko Mikulicic 0:c0ecb8bf28eb 27600 puts("\\0");
Marko Mikulicic 0:c0ecb8bf28eb 27601 break;
Marko Mikulicic 0:c0ecb8bf28eb 27602 case I_JUMP:
Marko Mikulicic 0:c0ecb8bf28eb 27603 printf("-->%d\n", inst->par.xy.x - prog->start);
Marko Mikulicic 0:c0ecb8bf28eb 27604 break;
Marko Mikulicic 0:c0ecb8bf28eb 27605 case I_LA:
Marko Mikulicic 0:c0ecb8bf28eb 27606 printf("la %d %d\n", inst->par.xy.x - prog->start,
Marko Mikulicic 0:c0ecb8bf28eb 27607 inst->par.xy.y.y - prog->start);
Marko Mikulicic 0:c0ecb8bf28eb 27608 break;
Marko Mikulicic 0:c0ecb8bf28eb 27609 case I_LA_N:
Marko Mikulicic 0:c0ecb8bf28eb 27610 printf("la_n %d %d\n", inst->par.xy.x - prog->start,
Marko Mikulicic 0:c0ecb8bf28eb 27611 inst->par.xy.y.y - prog->start);
Marko Mikulicic 0:c0ecb8bf28eb 27612 break;
Marko Mikulicic 0:c0ecb8bf28eb 27613 case I_LBRA:
Marko Mikulicic 0:c0ecb8bf28eb 27614 printf("( %d\n", inst->par.n);
Marko Mikulicic 0:c0ecb8bf28eb 27615 break;
Marko Mikulicic 0:c0ecb8bf28eb 27616 case I_RBRA:
Marko Mikulicic 0:c0ecb8bf28eb 27617 printf(") %d\n", inst->par.n);
Marko Mikulicic 0:c0ecb8bf28eb 27618 break;
Marko Mikulicic 0:c0ecb8bf28eb 27619 case I_SPLIT:
Marko Mikulicic 0:c0ecb8bf28eb 27620 printf("-->%d | -->%d\n", inst->par.xy.x - prog->start,
Marko Mikulicic 0:c0ecb8bf28eb 27621 inst->par.xy.y.y - prog->start);
Marko Mikulicic 0:c0ecb8bf28eb 27622 break;
Marko Mikulicic 0:c0ecb8bf28eb 27623 case I_REF:
Marko Mikulicic 0:c0ecb8bf28eb 27624 printf("\\%d\n", inst->par.n);
Marko Mikulicic 0:c0ecb8bf28eb 27625 break;
Marko Mikulicic 0:c0ecb8bf28eb 27626 case I_REP:
Marko Mikulicic 0:c0ecb8bf28eb 27627 printf("repeat -->%d\n", inst->par.xy.x - prog->start);
Marko Mikulicic 0:c0ecb8bf28eb 27628 break;
Marko Mikulicic 0:c0ecb8bf28eb 27629 case I_REP_INI:
Marko Mikulicic 0:c0ecb8bf28eb 27630 printf("init_rep %d %d\n", inst->par.xy.y.rp.min,
Marko Mikulicic 0:c0ecb8bf28eb 27631 inst->par.xy.y.rp.min + inst->par.xy.y.rp.max);
Marko Mikulicic 0:c0ecb8bf28eb 27632 break;
Marko Mikulicic 0:c0ecb8bf28eb 27633 case I_SET:
Marko Mikulicic 0:c0ecb8bf28eb 27634 printf("[");
Marko Mikulicic 0:c0ecb8bf28eb 27635 print_set(inst->par.cp);
Marko Mikulicic 0:c0ecb8bf28eb 27636 puts("");
Marko Mikulicic 0:c0ecb8bf28eb 27637 break;
Marko Mikulicic 0:c0ecb8bf28eb 27638 case I_SET_N:
Marko Mikulicic 0:c0ecb8bf28eb 27639 printf("[^");
Marko Mikulicic 0:c0ecb8bf28eb 27640 print_set(inst->par.cp);
Marko Mikulicic 0:c0ecb8bf28eb 27641 puts("");
Marko Mikulicic 0:c0ecb8bf28eb 27642 break;
Marko Mikulicic 0:c0ecb8bf28eb 27643 case I_WORD:
Marko Mikulicic 0:c0ecb8bf28eb 27644 puts("\\w");
Marko Mikulicic 0:c0ecb8bf28eb 27645 break;
Marko Mikulicic 0:c0ecb8bf28eb 27646 case I_WORD_N:
Marko Mikulicic 0:c0ecb8bf28eb 27647 puts("\\W");
Marko Mikulicic 0:c0ecb8bf28eb 27648 break;
Marko Mikulicic 0:c0ecb8bf28eb 27649 }
Marko Mikulicic 0:c0ecb8bf28eb 27650 }
Marko Mikulicic 0:c0ecb8bf28eb 27651 }
Marko Mikulicic 0:c0ecb8bf28eb 27652 #endif
Marko Mikulicic 0:c0ecb8bf28eb 27653
Marko Mikulicic 0:c0ecb8bf28eb 27654 int slre_compile(const char *pat, size_t pat_len, const char *flags,
Marko Mikulicic 0:c0ecb8bf28eb 27655 volatile size_t fl_len, struct slre_prog **pr, int is_regex) {
Marko Mikulicic 0:c0ecb8bf28eb 27656 struct slre_env e;
Marko Mikulicic 0:c0ecb8bf28eb 27657 struct slre_node *nd;
Marko Mikulicic 0:c0ecb8bf28eb 27658 struct slre_instruction *split, *jump;
Marko Mikulicic 0:c0ecb8bf28eb 27659 int err_code;
Marko Mikulicic 0:c0ecb8bf28eb 27660
Marko Mikulicic 0:c0ecb8bf28eb 27661 e.is_regex = is_regex;
Marko Mikulicic 0:c0ecb8bf28eb 27662 e.prog = (struct slre_prog *) SLRE_MALLOC(sizeof(struct slre_prog));
Marko Mikulicic 0:c0ecb8bf28eb 27663 e.pstart = e.pend =
Marko Mikulicic 0:c0ecb8bf28eb 27664 (struct slre_node *) SLRE_MALLOC(sizeof(struct slre_node) * pat_len * 2);
Marko Mikulicic 0:c0ecb8bf28eb 27665 e.prog->flags = is_regex ? SLRE_FLAG_RE : 0;
Marko Mikulicic 0:c0ecb8bf28eb 27666
Marko Mikulicic 0:c0ecb8bf28eb 27667 if ((err_code = setjmp(e.jmp_buf)) != SLRE_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 27668 SLRE_FREE(e.pstart);
Marko Mikulicic 0:c0ecb8bf28eb 27669 SLRE_FREE(e.prog);
Marko Mikulicic 0:c0ecb8bf28eb 27670 return err_code;
Marko Mikulicic 0:c0ecb8bf28eb 27671 }
Marko Mikulicic 0:c0ecb8bf28eb 27672
Marko Mikulicic 0:c0ecb8bf28eb 27673 while (fl_len--) {
Marko Mikulicic 0:c0ecb8bf28eb 27674 switch (flags[fl_len]) {
Marko Mikulicic 0:c0ecb8bf28eb 27675 case 'g':
Marko Mikulicic 0:c0ecb8bf28eb 27676 e.prog->flags |= SLRE_FLAG_G;
Marko Mikulicic 0:c0ecb8bf28eb 27677 break;
Marko Mikulicic 0:c0ecb8bf28eb 27678 case 'i':
Marko Mikulicic 0:c0ecb8bf28eb 27679 e.prog->flags |= SLRE_FLAG_I;
Marko Mikulicic 0:c0ecb8bf28eb 27680 break;
Marko Mikulicic 0:c0ecb8bf28eb 27681 case 'm':
Marko Mikulicic 0:c0ecb8bf28eb 27682 e.prog->flags |= SLRE_FLAG_M;
Marko Mikulicic 0:c0ecb8bf28eb 27683 break;
Marko Mikulicic 0:c0ecb8bf28eb 27684 }
Marko Mikulicic 0:c0ecb8bf28eb 27685 }
Marko Mikulicic 0:c0ecb8bf28eb 27686
Marko Mikulicic 0:c0ecb8bf28eb 27687 e.src = pat;
Marko Mikulicic 0:c0ecb8bf28eb 27688 e.src_end = pat + pat_len;
Marko Mikulicic 0:c0ecb8bf28eb 27689 e.sets_num = 0;
Marko Mikulicic 0:c0ecb8bf28eb 27690 e.num_captures = 1;
Marko Mikulicic 0:c0ecb8bf28eb 27691 /*e.flags = flags;*/
Marko Mikulicic 0:c0ecb8bf28eb 27692 memset(e.caps, 0, sizeof(e.caps));
Marko Mikulicic 0:c0ecb8bf28eb 27693
Marko Mikulicic 0:c0ecb8bf28eb 27694 RE_NEXT(&e);
Marko Mikulicic 0:c0ecb8bf28eb 27695 nd = re_parser(&e);
Marko Mikulicic 0:c0ecb8bf28eb 27696 if (e.lookahead == ')') {
Marko Mikulicic 0:c0ecb8bf28eb 27697 SLRE_THROW(&e, SLRE_UNMATCH_RBR);
Marko Mikulicic 0:c0ecb8bf28eb 27698 }
Marko Mikulicic 0:c0ecb8bf28eb 27699 if (e.lookahead != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 27700 SLRE_THROW(&e, SLRE_SYNTAX_ERROR);
Marko Mikulicic 0:c0ecb8bf28eb 27701 }
Marko Mikulicic 0:c0ecb8bf28eb 27702
Marko Mikulicic 0:c0ecb8bf28eb 27703 e.prog->num_captures = e.num_captures;
Marko Mikulicic 0:c0ecb8bf28eb 27704 e.prog->start = e.prog->end = (struct slre_instruction *) SLRE_MALLOC(
Marko Mikulicic 0:c0ecb8bf28eb 27705 (re_nodelen(nd) + 6) * sizeof(struct slre_instruction));
Marko Mikulicic 0:c0ecb8bf28eb 27706
Marko Mikulicic 0:c0ecb8bf28eb 27707 split = re_newinst(e.prog, I_SPLIT);
Marko Mikulicic 0:c0ecb8bf28eb 27708 split->par.xy.x = split + 3;
Marko Mikulicic 0:c0ecb8bf28eb 27709 split->par.xy.y.y = split + 1;
Marko Mikulicic 0:c0ecb8bf28eb 27710 re_newinst(e.prog, I_ANYNL);
Marko Mikulicic 0:c0ecb8bf28eb 27711 jump = re_newinst(e.prog, I_JUMP);
Marko Mikulicic 0:c0ecb8bf28eb 27712 jump->par.xy.x = split;
Marko Mikulicic 0:c0ecb8bf28eb 27713 re_newinst(e.prog, I_LBRA);
Marko Mikulicic 0:c0ecb8bf28eb 27714 re_compile(&e, nd);
Marko Mikulicic 0:c0ecb8bf28eb 27715 re_newinst(e.prog, I_RBRA);
Marko Mikulicic 0:c0ecb8bf28eb 27716 re_newinst(e.prog, I_END);
Marko Mikulicic 0:c0ecb8bf28eb 27717
Marko Mikulicic 0:c0ecb8bf28eb 27718 #ifdef RE_TEST
Marko Mikulicic 0:c0ecb8bf28eb 27719 node_print(nd);
Marko Mikulicic 0:c0ecb8bf28eb 27720 putchar('\n');
Marko Mikulicic 0:c0ecb8bf28eb 27721 program_print(e.prog);
Marko Mikulicic 0:c0ecb8bf28eb 27722 #endif
Marko Mikulicic 0:c0ecb8bf28eb 27723
Marko Mikulicic 0:c0ecb8bf28eb 27724 SLRE_FREE(e.pstart);
Marko Mikulicic 0:c0ecb8bf28eb 27725
Marko Mikulicic 0:c0ecb8bf28eb 27726 if (pr != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 27727 *pr = e.prog;
Marko Mikulicic 0:c0ecb8bf28eb 27728 } else {
Marko Mikulicic 0:c0ecb8bf28eb 27729 slre_free(e.prog);
Marko Mikulicic 0:c0ecb8bf28eb 27730 }
Marko Mikulicic 0:c0ecb8bf28eb 27731
Marko Mikulicic 0:c0ecb8bf28eb 27732 return err_code;
Marko Mikulicic 0:c0ecb8bf28eb 27733 }
Marko Mikulicic 0:c0ecb8bf28eb 27734
Marko Mikulicic 0:c0ecb8bf28eb 27735 void slre_free(struct slre_prog *prog) {
Marko Mikulicic 0:c0ecb8bf28eb 27736 if (prog) {
Marko Mikulicic 0:c0ecb8bf28eb 27737 SLRE_FREE(prog->start);
Marko Mikulicic 0:c0ecb8bf28eb 27738 SLRE_FREE(prog);
Marko Mikulicic 0:c0ecb8bf28eb 27739 }
Marko Mikulicic 0:c0ecb8bf28eb 27740 }
Marko Mikulicic 0:c0ecb8bf28eb 27741
Marko Mikulicic 0:c0ecb8bf28eb 27742 static struct slre_thread *re_newthread(struct slre_thread *t,
Marko Mikulicic 0:c0ecb8bf28eb 27743 struct slre_instruction *pc,
Marko Mikulicic 0:c0ecb8bf28eb 27744 const char *start,
Marko Mikulicic 0:c0ecb8bf28eb 27745 struct slre_loot *loot) {
Marko Mikulicic 0:c0ecb8bf28eb 27746 struct slre_thread *new_thread =
Marko Mikulicic 0:c0ecb8bf28eb 27747 (struct slre_thread *) SLRE_MALLOC(sizeof(struct slre_thread));
Marko Mikulicic 0:c0ecb8bf28eb 27748 if (new_thread != NULL) new_thread->prev = t;
Marko Mikulicic 0:c0ecb8bf28eb 27749 t->pc = pc;
Marko Mikulicic 0:c0ecb8bf28eb 27750 t->start = start;
Marko Mikulicic 0:c0ecb8bf28eb 27751 t->loot = *loot;
Marko Mikulicic 0:c0ecb8bf28eb 27752 return new_thread;
Marko Mikulicic 0:c0ecb8bf28eb 27753 }
Marko Mikulicic 0:c0ecb8bf28eb 27754
Marko Mikulicic 0:c0ecb8bf28eb 27755 static struct slre_thread *get_prev_thread(struct slre_thread *t) {
Marko Mikulicic 0:c0ecb8bf28eb 27756 struct slre_thread *tmp_thr = t->prev;
Marko Mikulicic 0:c0ecb8bf28eb 27757 SLRE_FREE(t);
Marko Mikulicic 0:c0ecb8bf28eb 27758 return tmp_thr;
Marko Mikulicic 0:c0ecb8bf28eb 27759 }
Marko Mikulicic 0:c0ecb8bf28eb 27760
Marko Mikulicic 0:c0ecb8bf28eb 27761 static void free_threads(struct slre_thread *t) {
Marko Mikulicic 0:c0ecb8bf28eb 27762 while (t->prev != NULL) t = get_prev_thread(t);
Marko Mikulicic 0:c0ecb8bf28eb 27763 }
Marko Mikulicic 0:c0ecb8bf28eb 27764
Marko Mikulicic 0:c0ecb8bf28eb 27765 static unsigned char re_match(struct slre_instruction *pc, const char *current,
Marko Mikulicic 0:c0ecb8bf28eb 27766 const char *end, const char *bol,
Marko Mikulicic 0:c0ecb8bf28eb 27767 unsigned int flags, struct slre_loot *loot) {
Marko Mikulicic 0:c0ecb8bf28eb 27768 struct slre_loot sub, tmpsub;
Marko Mikulicic 0:c0ecb8bf28eb 27769 Rune c, r;
Marko Mikulicic 0:c0ecb8bf28eb 27770 struct slre_range *p;
Marko Mikulicic 0:c0ecb8bf28eb 27771 size_t i;
Marko Mikulicic 0:c0ecb8bf28eb 27772 struct slre_thread thread, *curr_thread, *tmp_thr;
Marko Mikulicic 0:c0ecb8bf28eb 27773
Marko Mikulicic 0:c0ecb8bf28eb 27774 /* queue initial thread */
Marko Mikulicic 0:c0ecb8bf28eb 27775 thread.prev = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 27776 curr_thread = re_newthread(&thread, pc, current, loot);
Marko Mikulicic 0:c0ecb8bf28eb 27777
Marko Mikulicic 0:c0ecb8bf28eb 27778 /* run threads in stack order */
Marko Mikulicic 0:c0ecb8bf28eb 27779 do {
Marko Mikulicic 0:c0ecb8bf28eb 27780 curr_thread = get_prev_thread(curr_thread);
Marko Mikulicic 0:c0ecb8bf28eb 27781 pc = curr_thread->pc;
Marko Mikulicic 0:c0ecb8bf28eb 27782 current = curr_thread->start;
Marko Mikulicic 0:c0ecb8bf28eb 27783 sub = curr_thread->loot;
Marko Mikulicic 0:c0ecb8bf28eb 27784 for (;;) {
Marko Mikulicic 0:c0ecb8bf28eb 27785 switch (pc->opcode) {
Marko Mikulicic 0:c0ecb8bf28eb 27786 case I_END:
Marko Mikulicic 0:c0ecb8bf28eb 27787 memcpy(loot->caps, sub.caps, sizeof loot->caps);
Marko Mikulicic 0:c0ecb8bf28eb 27788 free_threads(curr_thread);
Marko Mikulicic 0:c0ecb8bf28eb 27789 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 27790 case I_ANY:
Marko Mikulicic 0:c0ecb8bf28eb 27791 case I_ANYNL:
Marko Mikulicic 0:c0ecb8bf28eb 27792 if (current < end) {
Marko Mikulicic 0:c0ecb8bf28eb 27793 current += chartorune(&c, current);
Marko Mikulicic 0:c0ecb8bf28eb 27794 if (c && !(pc->opcode == I_ANY && isnewline(c))) break;
Marko Mikulicic 0:c0ecb8bf28eb 27795 }
Marko Mikulicic 0:c0ecb8bf28eb 27796 goto no_match;
Marko Mikulicic 0:c0ecb8bf28eb 27797
Marko Mikulicic 0:c0ecb8bf28eb 27798 case I_BOL:
Marko Mikulicic 0:c0ecb8bf28eb 27799 if (current == bol) break;
Marko Mikulicic 0:c0ecb8bf28eb 27800 if ((flags & SLRE_FLAG_M) && isnewline(current[-1])) break;
Marko Mikulicic 0:c0ecb8bf28eb 27801 goto no_match;
Marko Mikulicic 0:c0ecb8bf28eb 27802 case I_CH:
Marko Mikulicic 0:c0ecb8bf28eb 27803 if (current < end) {
Marko Mikulicic 0:c0ecb8bf28eb 27804 current += chartorune(&c, current);
Marko Mikulicic 0:c0ecb8bf28eb 27805 if (c &&
Marko Mikulicic 0:c0ecb8bf28eb 27806 (c == pc->par.c || ((flags & SLRE_FLAG_I) &&
Marko Mikulicic 0:c0ecb8bf28eb 27807 tolowerrune(c) == tolowerrune(pc->par.c))))
Marko Mikulicic 0:c0ecb8bf28eb 27808 break;
Marko Mikulicic 0:c0ecb8bf28eb 27809 }
Marko Mikulicic 0:c0ecb8bf28eb 27810 goto no_match;
Marko Mikulicic 0:c0ecb8bf28eb 27811 case I_EOL:
Marko Mikulicic 0:c0ecb8bf28eb 27812 if (current >= end) break;
Marko Mikulicic 0:c0ecb8bf28eb 27813 if ((flags & SLRE_FLAG_M) && isnewline(*current)) break;
Marko Mikulicic 0:c0ecb8bf28eb 27814 goto no_match;
Marko Mikulicic 0:c0ecb8bf28eb 27815 case I_EOS:
Marko Mikulicic 0:c0ecb8bf28eb 27816 if (current >= end) break;
Marko Mikulicic 0:c0ecb8bf28eb 27817 goto no_match;
Marko Mikulicic 0:c0ecb8bf28eb 27818
Marko Mikulicic 0:c0ecb8bf28eb 27819 case I_JUMP:
Marko Mikulicic 0:c0ecb8bf28eb 27820 pc = pc->par.xy.x;
Marko Mikulicic 0:c0ecb8bf28eb 27821 continue;
Marko Mikulicic 0:c0ecb8bf28eb 27822
Marko Mikulicic 0:c0ecb8bf28eb 27823 case I_LA:
Marko Mikulicic 0:c0ecb8bf28eb 27824 if (re_match(pc->par.xy.x, current, end, bol, flags, &sub)) {
Marko Mikulicic 0:c0ecb8bf28eb 27825 pc = pc->par.xy.y.y;
Marko Mikulicic 0:c0ecb8bf28eb 27826 continue;
Marko Mikulicic 0:c0ecb8bf28eb 27827 }
Marko Mikulicic 0:c0ecb8bf28eb 27828 goto no_match;
Marko Mikulicic 0:c0ecb8bf28eb 27829 case I_LA_N:
Marko Mikulicic 0:c0ecb8bf28eb 27830 tmpsub = sub;
Marko Mikulicic 0:c0ecb8bf28eb 27831 if (!re_match(pc->par.xy.x, current, end, bol, flags, &tmpsub)) {
Marko Mikulicic 0:c0ecb8bf28eb 27832 pc = pc->par.xy.y.y;
Marko Mikulicic 0:c0ecb8bf28eb 27833 continue;
Marko Mikulicic 0:c0ecb8bf28eb 27834 }
Marko Mikulicic 0:c0ecb8bf28eb 27835 goto no_match;
Marko Mikulicic 0:c0ecb8bf28eb 27836
Marko Mikulicic 0:c0ecb8bf28eb 27837 case I_LBRA:
Marko Mikulicic 0:c0ecb8bf28eb 27838 sub.caps[pc->par.n].start = current;
Marko Mikulicic 0:c0ecb8bf28eb 27839 break;
Marko Mikulicic 0:c0ecb8bf28eb 27840
Marko Mikulicic 0:c0ecb8bf28eb 27841 case I_REF:
Marko Mikulicic 0:c0ecb8bf28eb 27842 i = sub.caps[pc->par.n].end - sub.caps[pc->par.n].start;
Marko Mikulicic 0:c0ecb8bf28eb 27843 if (flags & SLRE_FLAG_I) {
Marko Mikulicic 0:c0ecb8bf28eb 27844 int num = i;
Marko Mikulicic 0:c0ecb8bf28eb 27845 const char *s = current, *p = sub.caps[pc->par.n].start;
Marko Mikulicic 0:c0ecb8bf28eb 27846 Rune rr;
Marko Mikulicic 0:c0ecb8bf28eb 27847 for (; num && *s && *p; num--) {
Marko Mikulicic 0:c0ecb8bf28eb 27848 s += chartorune(&r, s);
Marko Mikulicic 0:c0ecb8bf28eb 27849 p += chartorune(&rr, p);
Marko Mikulicic 0:c0ecb8bf28eb 27850 if (tolowerrune(r) != tolowerrune(rr)) break;
Marko Mikulicic 0:c0ecb8bf28eb 27851 }
Marko Mikulicic 0:c0ecb8bf28eb 27852 if (num) goto no_match;
Marko Mikulicic 0:c0ecb8bf28eb 27853 } else if (strncmp(current, sub.caps[pc->par.n].start, i)) {
Marko Mikulicic 0:c0ecb8bf28eb 27854 goto no_match;
Marko Mikulicic 0:c0ecb8bf28eb 27855 }
Marko Mikulicic 0:c0ecb8bf28eb 27856 if (i > 0) current += i;
Marko Mikulicic 0:c0ecb8bf28eb 27857 break;
Marko Mikulicic 0:c0ecb8bf28eb 27858
Marko Mikulicic 0:c0ecb8bf28eb 27859 case I_REP:
Marko Mikulicic 0:c0ecb8bf28eb 27860 if (pc->par.xy.y.rp.min) {
Marko Mikulicic 0:c0ecb8bf28eb 27861 pc->par.xy.y.rp.min--;
Marko Mikulicic 0:c0ecb8bf28eb 27862 pc++;
Marko Mikulicic 0:c0ecb8bf28eb 27863 } else if (!pc->par.xy.y.rp.max--) {
Marko Mikulicic 0:c0ecb8bf28eb 27864 pc = pc->par.xy.x;
Marko Mikulicic 0:c0ecb8bf28eb 27865 continue;
Marko Mikulicic 0:c0ecb8bf28eb 27866 }
Marko Mikulicic 0:c0ecb8bf28eb 27867 break;
Marko Mikulicic 0:c0ecb8bf28eb 27868
Marko Mikulicic 0:c0ecb8bf28eb 27869 case I_REP_INI:
Marko Mikulicic 0:c0ecb8bf28eb 27870 (pc + 1)->par.xy.y.rp.min = pc->par.xy.y.rp.min;
Marko Mikulicic 0:c0ecb8bf28eb 27871 (pc + 1)->par.xy.y.rp.max = pc->par.xy.y.rp.max;
Marko Mikulicic 0:c0ecb8bf28eb 27872 break;
Marko Mikulicic 0:c0ecb8bf28eb 27873
Marko Mikulicic 0:c0ecb8bf28eb 27874 case I_RBRA:
Marko Mikulicic 0:c0ecb8bf28eb 27875 sub.caps[pc->par.n].end = current;
Marko Mikulicic 0:c0ecb8bf28eb 27876 break;
Marko Mikulicic 0:c0ecb8bf28eb 27877
Marko Mikulicic 0:c0ecb8bf28eb 27878 case I_SET:
Marko Mikulicic 0:c0ecb8bf28eb 27879 case I_SET_N:
Marko Mikulicic 0:c0ecb8bf28eb 27880 if (current >= end) goto no_match;
Marko Mikulicic 0:c0ecb8bf28eb 27881 current += chartorune(&c, current);
Marko Mikulicic 0:c0ecb8bf28eb 27882 if (!c) goto no_match;
Marko Mikulicic 0:c0ecb8bf28eb 27883
Marko Mikulicic 0:c0ecb8bf28eb 27884 i = 1;
Marko Mikulicic 0:c0ecb8bf28eb 27885 for (p = pc->par.cp->spans; i && p < pc->par.cp->end; p++)
Marko Mikulicic 0:c0ecb8bf28eb 27886 if (flags & SLRE_FLAG_I) {
Marko Mikulicic 0:c0ecb8bf28eb 27887 for (r = p->s; r <= p->e; ++r)
Marko Mikulicic 0:c0ecb8bf28eb 27888 if (tolowerrune(c) == tolowerrune(r)) {
Marko Mikulicic 0:c0ecb8bf28eb 27889 i = 0;
Marko Mikulicic 0:c0ecb8bf28eb 27890 break;
Marko Mikulicic 0:c0ecb8bf28eb 27891 }
Marko Mikulicic 0:c0ecb8bf28eb 27892 } else if (p->s <= c && c <= p->e)
Marko Mikulicic 0:c0ecb8bf28eb 27893 i = 0;
Marko Mikulicic 0:c0ecb8bf28eb 27894
Marko Mikulicic 0:c0ecb8bf28eb 27895 if (pc->opcode == I_SET) i = !i;
Marko Mikulicic 0:c0ecb8bf28eb 27896 if (i) break;
Marko Mikulicic 0:c0ecb8bf28eb 27897 goto no_match;
Marko Mikulicic 0:c0ecb8bf28eb 27898
Marko Mikulicic 0:c0ecb8bf28eb 27899 case I_SPLIT:
Marko Mikulicic 0:c0ecb8bf28eb 27900 tmp_thr = curr_thread;
Marko Mikulicic 0:c0ecb8bf28eb 27901 curr_thread =
Marko Mikulicic 0:c0ecb8bf28eb 27902 re_newthread(curr_thread, pc->par.xy.y.y, current, &sub);
Marko Mikulicic 0:c0ecb8bf28eb 27903 if (curr_thread == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 27904 fprintf(stderr, "re_match: no memory for thread!\n");
Marko Mikulicic 0:c0ecb8bf28eb 27905 free_threads(tmp_thr);
Marko Mikulicic 0:c0ecb8bf28eb 27906 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 27907 }
Marko Mikulicic 0:c0ecb8bf28eb 27908 pc = pc->par.xy.x;
Marko Mikulicic 0:c0ecb8bf28eb 27909 continue;
Marko Mikulicic 0:c0ecb8bf28eb 27910
Marko Mikulicic 0:c0ecb8bf28eb 27911 case I_WORD:
Marko Mikulicic 0:c0ecb8bf28eb 27912 case I_WORD_N:
Marko Mikulicic 0:c0ecb8bf28eb 27913 i = (current > bol && iswordchar(current[-1]));
Marko Mikulicic 0:c0ecb8bf28eb 27914 if (iswordchar(current[0])) i = !i;
Marko Mikulicic 0:c0ecb8bf28eb 27915 if (pc->opcode == I_WORD_N) i = !i;
Marko Mikulicic 0:c0ecb8bf28eb 27916 if (i) break;
Marko Mikulicic 0:c0ecb8bf28eb 27917 /* goto no_match; */
Marko Mikulicic 0:c0ecb8bf28eb 27918
Marko Mikulicic 0:c0ecb8bf28eb 27919 default:
Marko Mikulicic 0:c0ecb8bf28eb 27920 goto no_match;
Marko Mikulicic 0:c0ecb8bf28eb 27921 }
Marko Mikulicic 0:c0ecb8bf28eb 27922 pc++;
Marko Mikulicic 0:c0ecb8bf28eb 27923 }
Marko Mikulicic 0:c0ecb8bf28eb 27924 no_match:
Marko Mikulicic 0:c0ecb8bf28eb 27925 ;
Marko Mikulicic 0:c0ecb8bf28eb 27926 } while (curr_thread->prev != NULL);
Marko Mikulicic 0:c0ecb8bf28eb 27927 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 27928 }
Marko Mikulicic 0:c0ecb8bf28eb 27929
Marko Mikulicic 0:c0ecb8bf28eb 27930 int slre_exec(struct slre_prog *prog, int flag_g, const char *start,
Marko Mikulicic 0:c0ecb8bf28eb 27931 const char *end, struct slre_loot *loot) {
Marko Mikulicic 0:c0ecb8bf28eb 27932 struct slre_loot tmpsub;
Marko Mikulicic 0:c0ecb8bf28eb 27933 const char *st = start;
Marko Mikulicic 0:c0ecb8bf28eb 27934
Marko Mikulicic 0:c0ecb8bf28eb 27935 if (!loot) loot = &tmpsub;
Marko Mikulicic 0:c0ecb8bf28eb 27936 memset(loot, 0, sizeof(*loot));
Marko Mikulicic 0:c0ecb8bf28eb 27937
Marko Mikulicic 0:c0ecb8bf28eb 27938 if (!flag_g) {
Marko Mikulicic 0:c0ecb8bf28eb 27939 loot->num_captures = prog->num_captures;
Marko Mikulicic 0:c0ecb8bf28eb 27940 return !re_match(prog->start, start, end, start, prog->flags, loot);
Marko Mikulicic 0:c0ecb8bf28eb 27941 }
Marko Mikulicic 0:c0ecb8bf28eb 27942
Marko Mikulicic 0:c0ecb8bf28eb 27943 while (re_match(prog->start, st, end, start, prog->flags, &tmpsub)) {
Marko Mikulicic 0:c0ecb8bf28eb 27944 unsigned int i;
Marko Mikulicic 0:c0ecb8bf28eb 27945 st = tmpsub.caps[0].end;
Marko Mikulicic 0:c0ecb8bf28eb 27946 for (i = 0; i < prog->num_captures; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 27947 struct slre_cap *l = &loot->caps[loot->num_captures + i];
Marko Mikulicic 0:c0ecb8bf28eb 27948 struct slre_cap *s = &tmpsub.caps[i];
Marko Mikulicic 0:c0ecb8bf28eb 27949 l->start = s->start;
Marko Mikulicic 0:c0ecb8bf28eb 27950 l->end = s->end;
Marko Mikulicic 0:c0ecb8bf28eb 27951 }
Marko Mikulicic 0:c0ecb8bf28eb 27952 loot->num_captures += prog->num_captures;
Marko Mikulicic 0:c0ecb8bf28eb 27953 }
Marko Mikulicic 0:c0ecb8bf28eb 27954 return !loot->num_captures;
Marko Mikulicic 0:c0ecb8bf28eb 27955 }
Marko Mikulicic 0:c0ecb8bf28eb 27956
Marko Mikulicic 0:c0ecb8bf28eb 27957 int slre_replace(struct slre_loot *loot, const char *src, size_t src_len,
Marko Mikulicic 0:c0ecb8bf28eb 27958 const char *rstr, size_t rstr_len, struct slre_loot *dstsub) {
Marko Mikulicic 0:c0ecb8bf28eb 27959 int size = 0, n;
Marko Mikulicic 0:c0ecb8bf28eb 27960 Rune curr_rune;
Marko Mikulicic 0:c0ecb8bf28eb 27961 const char *const rstr_end = rstr + rstr_len;
Marko Mikulicic 0:c0ecb8bf28eb 27962
Marko Mikulicic 0:c0ecb8bf28eb 27963 memset(dstsub, 0, sizeof(*dstsub));
Marko Mikulicic 0:c0ecb8bf28eb 27964 while (rstr < rstr_end && !(n = re_nextc_raw(&curr_rune, &rstr, rstr_end)) &&
Marko Mikulicic 0:c0ecb8bf28eb 27965 curr_rune) {
Marko Mikulicic 0:c0ecb8bf28eb 27966 int sz;
Marko Mikulicic 0:c0ecb8bf28eb 27967 if (n < 0) return n;
Marko Mikulicic 0:c0ecb8bf28eb 27968 if (curr_rune == '$') {
Marko Mikulicic 0:c0ecb8bf28eb 27969 n = re_nextc(&curr_rune, &rstr, rstr_end);
Marko Mikulicic 0:c0ecb8bf28eb 27970 if (n < 0) return n;
Marko Mikulicic 0:c0ecb8bf28eb 27971 switch (curr_rune) {
Marko Mikulicic 0:c0ecb8bf28eb 27972 case '&':
Marko Mikulicic 0:c0ecb8bf28eb 27973 sz = loot->caps[0].end - loot->caps[0].start;
Marko Mikulicic 0:c0ecb8bf28eb 27974 size += sz;
Marko Mikulicic 0:c0ecb8bf28eb 27975 dstsub->caps[dstsub->num_captures++] = loot->caps[0];
Marko Mikulicic 0:c0ecb8bf28eb 27976 break;
Marko Mikulicic 0:c0ecb8bf28eb 27977 case '0':
Marko Mikulicic 0:c0ecb8bf28eb 27978 case '1':
Marko Mikulicic 0:c0ecb8bf28eb 27979 case '2':
Marko Mikulicic 0:c0ecb8bf28eb 27980 case '3':
Marko Mikulicic 0:c0ecb8bf28eb 27981 case '4':
Marko Mikulicic 0:c0ecb8bf28eb 27982 case '5':
Marko Mikulicic 0:c0ecb8bf28eb 27983 case '6':
Marko Mikulicic 0:c0ecb8bf28eb 27984 case '7':
Marko Mikulicic 0:c0ecb8bf28eb 27985 case '8':
Marko Mikulicic 0:c0ecb8bf28eb 27986 case '9': {
Marko Mikulicic 0:c0ecb8bf28eb 27987 int sbn = dec(curr_rune);
Marko Mikulicic 0:c0ecb8bf28eb 27988 if (0 == sbn && rstr[0] && isdigitrune(rstr[0])) {
Marko Mikulicic 0:c0ecb8bf28eb 27989 n = re_nextc(&curr_rune, &rstr, rstr_end);
Marko Mikulicic 0:c0ecb8bf28eb 27990 if (n < 0) return n;
Marko Mikulicic 0:c0ecb8bf28eb 27991 sz = dec(curr_rune);
Marko Mikulicic 0:c0ecb8bf28eb 27992 sbn = sbn * 10 + sz;
Marko Mikulicic 0:c0ecb8bf28eb 27993 }
Marko Mikulicic 0:c0ecb8bf28eb 27994 if (sbn >= loot->num_captures) break;
Marko Mikulicic 0:c0ecb8bf28eb 27995 sz = loot->caps[sbn].end - loot->caps[sbn].start;
Marko Mikulicic 0:c0ecb8bf28eb 27996 size += sz;
Marko Mikulicic 0:c0ecb8bf28eb 27997 dstsub->caps[dstsub->num_captures++] = loot->caps[sbn];
Marko Mikulicic 0:c0ecb8bf28eb 27998 break;
Marko Mikulicic 0:c0ecb8bf28eb 27999 }
Marko Mikulicic 0:c0ecb8bf28eb 28000 case '`':
Marko Mikulicic 0:c0ecb8bf28eb 28001 sz = loot->caps[0].start - src;
Marko Mikulicic 0:c0ecb8bf28eb 28002 size += sz;
Marko Mikulicic 0:c0ecb8bf28eb 28003 dstsub->caps[dstsub->num_captures].start = src;
Marko Mikulicic 0:c0ecb8bf28eb 28004 dstsub->caps[dstsub->num_captures++].end = loot->caps[0].start;
Marko Mikulicic 0:c0ecb8bf28eb 28005 break;
Marko Mikulicic 0:c0ecb8bf28eb 28006 case '\'':
Marko Mikulicic 0:c0ecb8bf28eb 28007 sz = src + src_len - loot->caps[0].end;
Marko Mikulicic 0:c0ecb8bf28eb 28008 size += sz;
Marko Mikulicic 0:c0ecb8bf28eb 28009 dstsub->caps[dstsub->num_captures].start = loot->caps[0].end;
Marko Mikulicic 0:c0ecb8bf28eb 28010 dstsub->caps[dstsub->num_captures++].end = loot->caps[0].end + sz;
Marko Mikulicic 0:c0ecb8bf28eb 28011 break;
Marko Mikulicic 0:c0ecb8bf28eb 28012 case '$':
Marko Mikulicic 0:c0ecb8bf28eb 28013 size++;
Marko Mikulicic 0:c0ecb8bf28eb 28014 dstsub->caps[dstsub->num_captures].start = rstr - 1;
Marko Mikulicic 0:c0ecb8bf28eb 28015 dstsub->caps[dstsub->num_captures++].end = rstr;
Marko Mikulicic 0:c0ecb8bf28eb 28016 break;
Marko Mikulicic 0:c0ecb8bf28eb 28017 default:
Marko Mikulicic 0:c0ecb8bf28eb 28018 return SLRE_BAD_CHAR_AFTER_USD;
Marko Mikulicic 0:c0ecb8bf28eb 28019 }
Marko Mikulicic 0:c0ecb8bf28eb 28020 } else {
Marko Mikulicic 0:c0ecb8bf28eb 28021 char tmps[300], *d = tmps;
Marko Mikulicic 0:c0ecb8bf28eb 28022 size += (sz = runetochar(d, &curr_rune));
Marko Mikulicic 0:c0ecb8bf28eb 28023 if (!dstsub->num_captures ||
Marko Mikulicic 0:c0ecb8bf28eb 28024 dstsub->caps[dstsub->num_captures - 1].end != rstr - sz) {
Marko Mikulicic 0:c0ecb8bf28eb 28025 dstsub->caps[dstsub->num_captures].start = rstr - sz;
Marko Mikulicic 0:c0ecb8bf28eb 28026 dstsub->caps[dstsub->num_captures++].end = rstr;
Marko Mikulicic 0:c0ecb8bf28eb 28027 } else
Marko Mikulicic 0:c0ecb8bf28eb 28028 dstsub->caps[dstsub->num_captures - 1].end = rstr;
Marko Mikulicic 0:c0ecb8bf28eb 28029 }
Marko Mikulicic 0:c0ecb8bf28eb 28030 }
Marko Mikulicic 0:c0ecb8bf28eb 28031 return size;
Marko Mikulicic 0:c0ecb8bf28eb 28032 }
Marko Mikulicic 0:c0ecb8bf28eb 28033
Marko Mikulicic 0:c0ecb8bf28eb 28034 int slre_match(const char *re, size_t re_len, const char *flags, size_t fl_len,
Marko Mikulicic 0:c0ecb8bf28eb 28035 const char *str, size_t str_len, struct slre_loot *loot) {
Marko Mikulicic 0:c0ecb8bf28eb 28036 struct slre_prog *prog = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 28037 int res;
Marko Mikulicic 0:c0ecb8bf28eb 28038
Marko Mikulicic 0:c0ecb8bf28eb 28039 if ((res = slre_compile(re, re_len, flags, fl_len, &prog, 1)) == SLRE_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28040 res = slre_exec(prog, prog->flags & SLRE_FLAG_G, str, str + str_len, loot);
Marko Mikulicic 0:c0ecb8bf28eb 28041 slre_free(prog);
Marko Mikulicic 0:c0ecb8bf28eb 28042 }
Marko Mikulicic 0:c0ecb8bf28eb 28043
Marko Mikulicic 0:c0ecb8bf28eb 28044 return res;
Marko Mikulicic 0:c0ecb8bf28eb 28045 }
Marko Mikulicic 0:c0ecb8bf28eb 28046
Marko Mikulicic 0:c0ecb8bf28eb 28047 int slre_get_flags(struct slre_prog *crp) {
Marko Mikulicic 0:c0ecb8bf28eb 28048 return crp->flags;
Marko Mikulicic 0:c0ecb8bf28eb 28049 }
Marko Mikulicic 0:c0ecb8bf28eb 28050
Marko Mikulicic 0:c0ecb8bf28eb 28051 #ifdef SLRE_TEST
Marko Mikulicic 0:c0ecb8bf28eb 28052
Marko Mikulicic 0:c0ecb8bf28eb 28053 #include <errno.h>
Marko Mikulicic 0:c0ecb8bf28eb 28054
Marko Mikulicic 0:c0ecb8bf28eb 28055 static const char *err_code_to_str(int err_code) {
Marko Mikulicic 0:c0ecb8bf28eb 28056 static const char *ar[] = {
Marko Mikulicic 0:c0ecb8bf28eb 28057 "no error", "invalid decimal digit", "invalid hex digit",
Marko Mikulicic 0:c0ecb8bf28eb 28058 "invalid escape character", "invalid unterminated escape sequence",
Marko Mikulicic 0:c0ecb8bf28eb 28059 "syntax error", "unmatched left parenthesis",
Marko Mikulicic 0:c0ecb8bf28eb 28060 "unmatched right parenthesis", "numeric overflow",
Marko Mikulicic 0:c0ecb8bf28eb 28061 "infinite loop empty string", "too many charsets",
Marko Mikulicic 0:c0ecb8bf28eb 28062 "invalid charset range", "charset is too large", "malformed charset",
Marko Mikulicic 0:c0ecb8bf28eb 28063 "invalid back reference", "too many captures", "invalid quantifier",
Marko Mikulicic 0:c0ecb8bf28eb 28064 "bad character after $"};
Marko Mikulicic 0:c0ecb8bf28eb 28065
Marko Mikulicic 0:c0ecb8bf28eb 28066 typedef char static_assertion_err_codes_out_of_sync
Marko Mikulicic 0:c0ecb8bf28eb 28067 [2 * !!(((sizeof(ar) / sizeof(ar[0])) == SLRE_BAD_CHAR_AFTER_USD + 1)) -
Marko Mikulicic 0:c0ecb8bf28eb 28068 1];
Marko Mikulicic 0:c0ecb8bf28eb 28069
Marko Mikulicic 0:c0ecb8bf28eb 28070 return err_code >= 0 && err_code < (int) (sizeof(ar) / sizeof(ar[0]))
Marko Mikulicic 0:c0ecb8bf28eb 28071 ? ar[err_code]
Marko Mikulicic 0:c0ecb8bf28eb 28072 : "invalid error code";
Marko Mikulicic 0:c0ecb8bf28eb 28073 }
Marko Mikulicic 0:c0ecb8bf28eb 28074
Marko Mikulicic 0:c0ecb8bf28eb 28075 #define RE_TEST_STR_SIZE 2000
Marko Mikulicic 0:c0ecb8bf28eb 28076
Marko Mikulicic 0:c0ecb8bf28eb 28077 static unsigned get_flags(const char *ch) {
Marko Mikulicic 0:c0ecb8bf28eb 28078 unsigned int flags = 0;
Marko Mikulicic 0:c0ecb8bf28eb 28079
Marko Mikulicic 0:c0ecb8bf28eb 28080 while (*ch != '\0') {
Marko Mikulicic 0:c0ecb8bf28eb 28081 switch (*ch) {
Marko Mikulicic 0:c0ecb8bf28eb 28082 case 'g':
Marko Mikulicic 0:c0ecb8bf28eb 28083 flags |= SLRE_FLAG_G;
Marko Mikulicic 0:c0ecb8bf28eb 28084 break;
Marko Mikulicic 0:c0ecb8bf28eb 28085 case 'i':
Marko Mikulicic 0:c0ecb8bf28eb 28086 flags |= SLRE_FLAG_I;
Marko Mikulicic 0:c0ecb8bf28eb 28087 break;
Marko Mikulicic 0:c0ecb8bf28eb 28088 case 'm':
Marko Mikulicic 0:c0ecb8bf28eb 28089 flags |= SLRE_FLAG_M;
Marko Mikulicic 0:c0ecb8bf28eb 28090 break;
Marko Mikulicic 0:c0ecb8bf28eb 28091 case 'r':
Marko Mikulicic 0:c0ecb8bf28eb 28092 flags |= SLRE_FLAG_RE;
Marko Mikulicic 0:c0ecb8bf28eb 28093 break;
Marko Mikulicic 0:c0ecb8bf28eb 28094 default:
Marko Mikulicic 0:c0ecb8bf28eb 28095 return flags;
Marko Mikulicic 0:c0ecb8bf28eb 28096 }
Marko Mikulicic 0:c0ecb8bf28eb 28097 ch++;
Marko Mikulicic 0:c0ecb8bf28eb 28098 }
Marko Mikulicic 0:c0ecb8bf28eb 28099 return flags;
Marko Mikulicic 0:c0ecb8bf28eb 28100 }
Marko Mikulicic 0:c0ecb8bf28eb 28101
Marko Mikulicic 0:c0ecb8bf28eb 28102 static void show_usage_and_exit(char *argv[]) {
Marko Mikulicic 0:c0ecb8bf28eb 28103 fprintf(stderr, "Usage: %s [OPTIONS]\n", argv[0]);
Marko Mikulicic 0:c0ecb8bf28eb 28104 fprintf(stderr, "%s\n", "OPTIONS:");
Marko Mikulicic 0:c0ecb8bf28eb 28105 fprintf(stderr, "%s\n", " -p <regex_pattern> Regex pattern");
Marko Mikulicic 0:c0ecb8bf28eb 28106 fprintf(stderr, "%s\n", " -o <regex_flags> Combination of g,i,m");
Marko Mikulicic 0:c0ecb8bf28eb 28107 fprintf(stderr, "%s\n", " -s <string> String to match");
Marko Mikulicic 0:c0ecb8bf28eb 28108 fprintf(stderr, "%s\n", " -f <file_name> Match lines from file");
Marko Mikulicic 0:c0ecb8bf28eb 28109 fprintf(stderr, "%s\n", " -n <cap_no> Show given capture");
Marko Mikulicic 0:c0ecb8bf28eb 28110 fprintf(stderr, "%s\n", " -r <replace_str> Replace given capture");
Marko Mikulicic 0:c0ecb8bf28eb 28111 fprintf(stderr, "%s\n", " -v Show verbose stats");
Marko Mikulicic 0:c0ecb8bf28eb 28112 exit(1);
Marko Mikulicic 0:c0ecb8bf28eb 28113 }
Marko Mikulicic 0:c0ecb8bf28eb 28114
Marko Mikulicic 0:c0ecb8bf28eb 28115 static int process_line(struct slre_prog *pr, const char *flags,
Marko Mikulicic 0:c0ecb8bf28eb 28116 const char *line, const char *cap_no,
Marko Mikulicic 0:c0ecb8bf28eb 28117 const char *replace, const char *verbose) {
Marko Mikulicic 0:c0ecb8bf28eb 28118 struct slre_loot loot;
Marko Mikulicic 0:c0ecb8bf28eb 28119 unsigned int fl = flags == NULL ? 0 : get_flags(flags);
Marko Mikulicic 0:c0ecb8bf28eb 28120 int i, n = cap_no == NULL ? -1 : atoi(cap_no), err_code = 0;
Marko Mikulicic 0:c0ecb8bf28eb 28121 struct slre_cap *cap = &loot.caps[n];
Marko Mikulicic 0:c0ecb8bf28eb 28122
Marko Mikulicic 0:c0ecb8bf28eb 28123 err_code =
Marko Mikulicic 0:c0ecb8bf28eb 28124 slre_exec(pr, pr->flags & SLRE_FLAG_G, line, line + strlen(line), &loot);
Marko Mikulicic 0:c0ecb8bf28eb 28125 if (err_code == SLRE_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28126 if (n >= 0 && n < loot.num_captures && replace != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 28127 struct slre_cap *cap = &loot.caps[n];
Marko Mikulicic 0:c0ecb8bf28eb 28128 printf("%.*s", (int) (cap->start - line), line);
Marko Mikulicic 0:c0ecb8bf28eb 28129 printf("%s", replace);
Marko Mikulicic 0:c0ecb8bf28eb 28130 printf("%.*s", (int) ((line + strlen(line)) - cap->end), cap->end);
Marko Mikulicic 0:c0ecb8bf28eb 28131 } else if (n >= 0 && n < loot.num_captures) {
Marko Mikulicic 0:c0ecb8bf28eb 28132 printf("%.*s\n", (int) (cap->end - cap->start), cap->start);
Marko Mikulicic 0:c0ecb8bf28eb 28133 }
Marko Mikulicic 0:c0ecb8bf28eb 28134
Marko Mikulicic 0:c0ecb8bf28eb 28135 if (verbose != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 28136 fprintf(stderr, "%s\n", "Captures:");
Marko Mikulicic 0:c0ecb8bf28eb 28137 for (i = 0; i < loot.num_captures; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 28138 fprintf(stderr, "%d [%.*s]\n", i,
Marko Mikulicic 0:c0ecb8bf28eb 28139 (int) (loot.caps[i].end - loot.caps[i].start),
Marko Mikulicic 0:c0ecb8bf28eb 28140 loot.caps[i].start);
Marko Mikulicic 0:c0ecb8bf28eb 28141 }
Marko Mikulicic 0:c0ecb8bf28eb 28142 }
Marko Mikulicic 0:c0ecb8bf28eb 28143 }
Marko Mikulicic 0:c0ecb8bf28eb 28144
Marko Mikulicic 0:c0ecb8bf28eb 28145 return err_code;
Marko Mikulicic 0:c0ecb8bf28eb 28146 }
Marko Mikulicic 0:c0ecb8bf28eb 28147
Marko Mikulicic 0:c0ecb8bf28eb 28148 int main(int argc, char **argv) {
Marko Mikulicic 0:c0ecb8bf28eb 28149 const char *str = NULL, *pattern = NULL, *replace = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 28150 const char *flags = "", *file_name = NULL, *cap_no = NULL, *verbose = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 28151 struct slre_prog *pr = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 28152 int i, err_code = 0;
Marko Mikulicic 0:c0ecb8bf28eb 28153
Marko Mikulicic 0:c0ecb8bf28eb 28154 /* Execute inline code */
Marko Mikulicic 0:c0ecb8bf28eb 28155 for (i = 1; i < argc; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 28156 if (strcmp(argv[i], "-p") == 0 && i + 1 < argc) {
Marko Mikulicic 0:c0ecb8bf28eb 28157 pattern = argv[++i];
Marko Mikulicic 0:c0ecb8bf28eb 28158 } else if (strcmp(argv[i], "-o") == 0 && i + 1 < argc) {
Marko Mikulicic 0:c0ecb8bf28eb 28159 flags = argv[++i];
Marko Mikulicic 0:c0ecb8bf28eb 28160 } else if (strcmp(argv[i], "-s") == 0 && i + 1 < argc) {
Marko Mikulicic 0:c0ecb8bf28eb 28161 str = argv[++i];
Marko Mikulicic 0:c0ecb8bf28eb 28162 } else if (strcmp(argv[i], "-f") == 0 && i + 1 < argc) {
Marko Mikulicic 0:c0ecb8bf28eb 28163 file_name = argv[++i];
Marko Mikulicic 0:c0ecb8bf28eb 28164 } else if (strcmp(argv[i], "-n") == 0 && i + 1 < argc) {
Marko Mikulicic 0:c0ecb8bf28eb 28165 cap_no = argv[++i];
Marko Mikulicic 0:c0ecb8bf28eb 28166 } else if (strcmp(argv[i], "-r") == 0 && i + 1 < argc) {
Marko Mikulicic 0:c0ecb8bf28eb 28167 replace = argv[++i];
Marko Mikulicic 0:c0ecb8bf28eb 28168 } else if (strcmp(argv[i], "-v") == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 28169 verbose = "";
Marko Mikulicic 0:c0ecb8bf28eb 28170 } else if (strcmp(argv[i], "-h") == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 28171 show_usage_and_exit(argv);
Marko Mikulicic 0:c0ecb8bf28eb 28172 } else {
Marko Mikulicic 0:c0ecb8bf28eb 28173 show_usage_and_exit(argv);
Marko Mikulicic 0:c0ecb8bf28eb 28174 }
Marko Mikulicic 0:c0ecb8bf28eb 28175 }
Marko Mikulicic 0:c0ecb8bf28eb 28176
Marko Mikulicic 0:c0ecb8bf28eb 28177 if (pattern == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 28178 fprintf(stderr, "%s\n", "-p option is mandatory");
Marko Mikulicic 0:c0ecb8bf28eb 28179 exit(1);
Marko Mikulicic 0:c0ecb8bf28eb 28180 } else if ((err_code = slre_compile(pattern, strlen(pattern), flags,
Marko Mikulicic 0:c0ecb8bf28eb 28181 strlen(flags), &pr, 1)) != SLRE_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28182 fprintf(stderr, "slre_compile(%s): %s\n", argv[0],
Marko Mikulicic 0:c0ecb8bf28eb 28183 err_code_to_str(err_code));
Marko Mikulicic 0:c0ecb8bf28eb 28184 exit(1);
Marko Mikulicic 0:c0ecb8bf28eb 28185 } else if (str != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 28186 err_code = process_line(pr, flags, str, cap_no, replace, verbose);
Marko Mikulicic 0:c0ecb8bf28eb 28187 } else if (file_name != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 28188 FILE *fp = strcmp(file_name, "-") == 0 ? stdin : fopen(file_name, "rb");
Marko Mikulicic 0:c0ecb8bf28eb 28189 char line[20 * 1024];
Marko Mikulicic 0:c0ecb8bf28eb 28190 if (fp == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 28191 fprintf(stderr, "Cannot open %s: %s\n", file_name, strerror(errno));
Marko Mikulicic 0:c0ecb8bf28eb 28192 exit(1);
Marko Mikulicic 0:c0ecb8bf28eb 28193 } else {
Marko Mikulicic 0:c0ecb8bf28eb 28194 /* Return success if at least one line matches */
Marko Mikulicic 0:c0ecb8bf28eb 28195 err_code = 1;
Marko Mikulicic 0:c0ecb8bf28eb 28196 while (fgets(line, sizeof(line), fp) != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 28197 if (process_line(pr, flags, line, cap_no, replace, verbose) ==
Marko Mikulicic 0:c0ecb8bf28eb 28198 SLRE_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28199 err_code = 0;
Marko Mikulicic 0:c0ecb8bf28eb 28200 }
Marko Mikulicic 0:c0ecb8bf28eb 28201 }
Marko Mikulicic 0:c0ecb8bf28eb 28202 fclose(fp); /* If fp == stdin, it is safe to close, too */
Marko Mikulicic 0:c0ecb8bf28eb 28203 }
Marko Mikulicic 0:c0ecb8bf28eb 28204 } else {
Marko Mikulicic 0:c0ecb8bf28eb 28205 fprintf(stderr, "%s\n", "Please specify one of -s or -f options");
Marko Mikulicic 0:c0ecb8bf28eb 28206 exit(1);
Marko Mikulicic 0:c0ecb8bf28eb 28207 }
Marko Mikulicic 0:c0ecb8bf28eb 28208 slre_free(pr);
Marko Mikulicic 0:c0ecb8bf28eb 28209
Marko Mikulicic 0:c0ecb8bf28eb 28210 return err_code;
Marko Mikulicic 0:c0ecb8bf28eb 28211 }
Marko Mikulicic 0:c0ecb8bf28eb 28212 #endif /* SLRE_TEST */
Marko Mikulicic 0:c0ecb8bf28eb 28213
Marko Mikulicic 0:c0ecb8bf28eb 28214 #endif /* V7_ENABLE__RegExp */
Marko Mikulicic 0:c0ecb8bf28eb 28215 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 28216 #line 1 "v7/src/heapusage.c"
Marko Mikulicic 0:c0ecb8bf28eb 28217 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28218 /*
Marko Mikulicic 0:c0ecb8bf28eb 28219 * Copyright (c) 2014-2016 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 28220 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 28221 */
Marko Mikulicic 0:c0ecb8bf28eb 28222
Marko Mikulicic 0:c0ecb8bf28eb 28223 #include <stdlib.h>
Marko Mikulicic 0:c0ecb8bf28eb 28224 #include <stdio.h>
Marko Mikulicic 0:c0ecb8bf28eb 28225 #include <assert.h>
Marko Mikulicic 0:c0ecb8bf28eb 28226
Marko Mikulicic 0:c0ecb8bf28eb 28227 #if defined(V7_HEAPUSAGE_ENABLE)
Marko Mikulicic 0:c0ecb8bf28eb 28228
Marko Mikulicic 0:c0ecb8bf28eb 28229 /*
Marko Mikulicic 0:c0ecb8bf28eb 28230 * A flag that is set by GC before allocating its buffers, so we can
Marko Mikulicic 0:c0ecb8bf28eb 28231 * distinguish these buffers from other allocations
Marko Mikulicic 0:c0ecb8bf28eb 28232 */
Marko Mikulicic 0:c0ecb8bf28eb 28233 volatile int heap_dont_count = 0;
Marko Mikulicic 0:c0ecb8bf28eb 28234
Marko Mikulicic 0:c0ecb8bf28eb 28235 extern void *__real_malloc(size_t size);
Marko Mikulicic 0:c0ecb8bf28eb 28236 extern void *__real_calloc(size_t num, size_t size);
Marko Mikulicic 0:c0ecb8bf28eb 28237 extern void *__real_realloc(void *p, size_t size);
Marko Mikulicic 0:c0ecb8bf28eb 28238 extern void __real_free(void *p);
Marko Mikulicic 0:c0ecb8bf28eb 28239
Marko Mikulicic 0:c0ecb8bf28eb 28240 /* TODO(dfrank): make it dynamically allocated from heap */
Marko Mikulicic 0:c0ecb8bf28eb 28241 #define CELLS_CNT (1024 * 32)
Marko Mikulicic 0:c0ecb8bf28eb 28242
Marko Mikulicic 0:c0ecb8bf28eb 28243 typedef struct cell {
Marko Mikulicic 0:c0ecb8bf28eb 28244 void *p;
Marko Mikulicic 0:c0ecb8bf28eb 28245 unsigned dont_count : 1;
Marko Mikulicic 0:c0ecb8bf28eb 28246 unsigned size : 31;
Marko Mikulicic 0:c0ecb8bf28eb 28247 } cell_t;
Marko Mikulicic 0:c0ecb8bf28eb 28248
Marko Mikulicic 0:c0ecb8bf28eb 28249 typedef struct alloc_registry {
Marko Mikulicic 0:c0ecb8bf28eb 28250 size_t used_cells_cnt;
Marko Mikulicic 0:c0ecb8bf28eb 28251 size_t allocated_size;
Marko Mikulicic 0:c0ecb8bf28eb 28252 size_t real_used_cells_cnt;
Marko Mikulicic 0:c0ecb8bf28eb 28253 size_t real_allocated_size;
Marko Mikulicic 0:c0ecb8bf28eb 28254 cell_t cells[CELLS_CNT];
Marko Mikulicic 0:c0ecb8bf28eb 28255 } alloc_registry_t;
Marko Mikulicic 0:c0ecb8bf28eb 28256
Marko Mikulicic 0:c0ecb8bf28eb 28257 static alloc_registry_t registry = {0};
Marko Mikulicic 0:c0ecb8bf28eb 28258
Marko Mikulicic 0:c0ecb8bf28eb 28259 /*
Marko Mikulicic 0:c0ecb8bf28eb 28260 * Make a record about an allocated buffer `p` of size `size`
Marko Mikulicic 0:c0ecb8bf28eb 28261 */
Marko Mikulicic 0:c0ecb8bf28eb 28262 static void cell_allocated(void *p, size_t size) {
Marko Mikulicic 0:c0ecb8bf28eb 28263 int i;
Marko Mikulicic 0:c0ecb8bf28eb 28264 int cell_num = -1;
Marko Mikulicic 0:c0ecb8bf28eb 28265
Marko Mikulicic 0:c0ecb8bf28eb 28266 if (p != NULL && size != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 28267 /* TODO(dfrank): make it dynamically allocated from heap */
Marko Mikulicic 0:c0ecb8bf28eb 28268 assert(registry.real_used_cells_cnt < CELLS_CNT);
Marko Mikulicic 0:c0ecb8bf28eb 28269
Marko Mikulicic 0:c0ecb8bf28eb 28270 for (i = 0; i < CELLS_CNT; ++i) {
Marko Mikulicic 0:c0ecb8bf28eb 28271 if (registry.cells[i].p == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 28272 cell_num = i;
Marko Mikulicic 0:c0ecb8bf28eb 28273 break;
Marko Mikulicic 0:c0ecb8bf28eb 28274 }
Marko Mikulicic 0:c0ecb8bf28eb 28275 }
Marko Mikulicic 0:c0ecb8bf28eb 28276
Marko Mikulicic 0:c0ecb8bf28eb 28277 assert(cell_num != -1);
Marko Mikulicic 0:c0ecb8bf28eb 28278
Marko Mikulicic 0:c0ecb8bf28eb 28279 registry.cells[cell_num].p = p;
Marko Mikulicic 0:c0ecb8bf28eb 28280 registry.cells[cell_num].size = size;
Marko Mikulicic 0:c0ecb8bf28eb 28281 registry.cells[cell_num].dont_count = !!heap_dont_count;
Marko Mikulicic 0:c0ecb8bf28eb 28282
Marko Mikulicic 0:c0ecb8bf28eb 28283 registry.real_allocated_size += size;
Marko Mikulicic 0:c0ecb8bf28eb 28284 registry.real_used_cells_cnt += 1;
Marko Mikulicic 0:c0ecb8bf28eb 28285
Marko Mikulicic 0:c0ecb8bf28eb 28286 if (!heap_dont_count) {
Marko Mikulicic 0:c0ecb8bf28eb 28287 registry.allocated_size += size;
Marko Mikulicic 0:c0ecb8bf28eb 28288 registry.used_cells_cnt += 1;
Marko Mikulicic 0:c0ecb8bf28eb 28289 }
Marko Mikulicic 0:c0ecb8bf28eb 28290
Marko Mikulicic 0:c0ecb8bf28eb 28291 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 28292 printf("alloc=0x%lx, size=%lu, total=%lu\n", (unsigned long)p, size,
Marko Mikulicic 0:c0ecb8bf28eb 28293 registry.allocated_size);
Marko Mikulicic 0:c0ecb8bf28eb 28294 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28295 }
Marko Mikulicic 0:c0ecb8bf28eb 28296 }
Marko Mikulicic 0:c0ecb8bf28eb 28297
Marko Mikulicic 0:c0ecb8bf28eb 28298 /*
Marko Mikulicic 0:c0ecb8bf28eb 28299 * Delete a record about an allocated buffer `p`. If our registry does not
Marko Mikulicic 0:c0ecb8bf28eb 28300 * contain anything about the given pointer, the call is ignored. We can't
Marko Mikulicic 0:c0ecb8bf28eb 28301 * generate an error because shared libraries still use unwrapped heap
Marko Mikulicic 0:c0ecb8bf28eb 28302 * functions, so we can face "unknown" pointers.
Marko Mikulicic 0:c0ecb8bf28eb 28303 */
Marko Mikulicic 0:c0ecb8bf28eb 28304 static void cell_freed(void *p) {
Marko Mikulicic 0:c0ecb8bf28eb 28305 int i;
Marko Mikulicic 0:c0ecb8bf28eb 28306 int cell_num = -1;
Marko Mikulicic 0:c0ecb8bf28eb 28307
Marko Mikulicic 0:c0ecb8bf28eb 28308 if (p != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 28309 assert(registry.real_used_cells_cnt > 0);
Marko Mikulicic 0:c0ecb8bf28eb 28310
Marko Mikulicic 0:c0ecb8bf28eb 28311 for (i = 0; i < CELLS_CNT; ++i) {
Marko Mikulicic 0:c0ecb8bf28eb 28312 if (registry.cells[i].p == p) {
Marko Mikulicic 0:c0ecb8bf28eb 28313 cell_num = i;
Marko Mikulicic 0:c0ecb8bf28eb 28314 break;
Marko Mikulicic 0:c0ecb8bf28eb 28315 }
Marko Mikulicic 0:c0ecb8bf28eb 28316 }
Marko Mikulicic 0:c0ecb8bf28eb 28317
Marko Mikulicic 0:c0ecb8bf28eb 28318 /*
Marko Mikulicic 0:c0ecb8bf28eb 28319 * NOTE: it would be nice to have `assert(cell_num != -1);`, but
Marko Mikulicic 0:c0ecb8bf28eb 28320 * unfortunately not all allocations are wrapped: shared libraries will
Marko Mikulicic 0:c0ecb8bf28eb 28321 * still use unwrapped mallocs, so we might get unknown pointers here.
Marko Mikulicic 0:c0ecb8bf28eb 28322 */
Marko Mikulicic 0:c0ecb8bf28eb 28323
Marko Mikulicic 0:c0ecb8bf28eb 28324 if (cell_num != -1) {
Marko Mikulicic 0:c0ecb8bf28eb 28325 registry.real_allocated_size -= registry.cells[cell_num].size;
Marko Mikulicic 0:c0ecb8bf28eb 28326 registry.real_used_cells_cnt -= 1;
Marko Mikulicic 0:c0ecb8bf28eb 28327
Marko Mikulicic 0:c0ecb8bf28eb 28328 if (!registry.cells[cell_num].dont_count) {
Marko Mikulicic 0:c0ecb8bf28eb 28329 registry.allocated_size -= registry.cells[cell_num].size;
Marko Mikulicic 0:c0ecb8bf28eb 28330 registry.used_cells_cnt -= 1;
Marko Mikulicic 0:c0ecb8bf28eb 28331 }
Marko Mikulicic 0:c0ecb8bf28eb 28332
Marko Mikulicic 0:c0ecb8bf28eb 28333 registry.cells[cell_num].p = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 28334 registry.cells[cell_num].size = 0;
Marko Mikulicic 0:c0ecb8bf28eb 28335 registry.cells[cell_num].dont_count = 0;
Marko Mikulicic 0:c0ecb8bf28eb 28336
Marko Mikulicic 0:c0ecb8bf28eb 28337 #if 0
Marko Mikulicic 0:c0ecb8bf28eb 28338 printf("free=0x%lx, total=%lu\n", (unsigned long)p, registry.allocated_size);
Marko Mikulicic 0:c0ecb8bf28eb 28339 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28340 }
Marko Mikulicic 0:c0ecb8bf28eb 28341 }
Marko Mikulicic 0:c0ecb8bf28eb 28342 }
Marko Mikulicic 0:c0ecb8bf28eb 28343
Marko Mikulicic 0:c0ecb8bf28eb 28344 /*
Marko Mikulicic 0:c0ecb8bf28eb 28345 * Wrappers of the standard heap functions
Marko Mikulicic 0:c0ecb8bf28eb 28346 */
Marko Mikulicic 0:c0ecb8bf28eb 28347
Marko Mikulicic 0:c0ecb8bf28eb 28348 void *__wrap_malloc(size_t size) {
Marko Mikulicic 0:c0ecb8bf28eb 28349 void *ret = __real_malloc(size);
Marko Mikulicic 0:c0ecb8bf28eb 28350 cell_allocated(ret, size);
Marko Mikulicic 0:c0ecb8bf28eb 28351 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 28352 }
Marko Mikulicic 0:c0ecb8bf28eb 28353
Marko Mikulicic 0:c0ecb8bf28eb 28354 void *__wrap_calloc(size_t num, size_t size) {
Marko Mikulicic 0:c0ecb8bf28eb 28355 void *ret = __real_calloc(num, size);
Marko Mikulicic 0:c0ecb8bf28eb 28356 cell_allocated(ret, num * size);
Marko Mikulicic 0:c0ecb8bf28eb 28357 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 28358 }
Marko Mikulicic 0:c0ecb8bf28eb 28359
Marko Mikulicic 0:c0ecb8bf28eb 28360 void *__wrap_realloc(void *p, size_t size) {
Marko Mikulicic 0:c0ecb8bf28eb 28361 void *ret;
Marko Mikulicic 0:c0ecb8bf28eb 28362 cell_freed(p);
Marko Mikulicic 0:c0ecb8bf28eb 28363 ret = __real_realloc(p, size);
Marko Mikulicic 0:c0ecb8bf28eb 28364 cell_allocated(ret, size);
Marko Mikulicic 0:c0ecb8bf28eb 28365 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 28366 }
Marko Mikulicic 0:c0ecb8bf28eb 28367
Marko Mikulicic 0:c0ecb8bf28eb 28368 void __wrap_free(void *p) {
Marko Mikulicic 0:c0ecb8bf28eb 28369 __real_free(p);
Marko Mikulicic 0:c0ecb8bf28eb 28370 cell_freed(p);
Marko Mikulicic 0:c0ecb8bf28eb 28371 }
Marko Mikulicic 0:c0ecb8bf28eb 28372
Marko Mikulicic 0:c0ecb8bf28eb 28373 /*
Marko Mikulicic 0:c0ecb8bf28eb 28374 * Small API to get some stats, see header file for details
Marko Mikulicic 0:c0ecb8bf28eb 28375 */
Marko Mikulicic 0:c0ecb8bf28eb 28376
Marko Mikulicic 0:c0ecb8bf28eb 28377 size_t heapusage_alloc_size(void) {
Marko Mikulicic 0:c0ecb8bf28eb 28378 return registry.allocated_size;
Marko Mikulicic 0:c0ecb8bf28eb 28379 }
Marko Mikulicic 0:c0ecb8bf28eb 28380
Marko Mikulicic 0:c0ecb8bf28eb 28381 size_t heapusage_allocs_cnt(void) {
Marko Mikulicic 0:c0ecb8bf28eb 28382 return registry.used_cells_cnt;
Marko Mikulicic 0:c0ecb8bf28eb 28383 }
Marko Mikulicic 0:c0ecb8bf28eb 28384
Marko Mikulicic 0:c0ecb8bf28eb 28385 #endif /* V7_HEAPUSAGE_ENABLE */
Marko Mikulicic 0:c0ecb8bf28eb 28386 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 28387 #line 1 "v7/src/cyg_profile.c"
Marko Mikulicic 0:c0ecb8bf28eb 28388 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28389 /*
Marko Mikulicic 0:c0ecb8bf28eb 28390 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 28391 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 28392 */
Marko Mikulicic 0:c0ecb8bf28eb 28393
Marko Mikulicic 0:c0ecb8bf28eb 28394 /*
Marko Mikulicic 0:c0ecb8bf28eb 28395 * This file contains GCC/clang instrumentation callbacks. The actual
Marko Mikulicic 0:c0ecb8bf28eb 28396 * code in these callbacks depends on enabled features.
Marko Mikulicic 0:c0ecb8bf28eb 28397 *
Marko Mikulicic 0:c0ecb8bf28eb 28398 * Currently, the code from different subsystems is embedded right into
Marko Mikulicic 0:c0ecb8bf28eb 28399 * callbacks for performance reasons. It would be probably more elegant
Marko Mikulicic 0:c0ecb8bf28eb 28400 * to have subsystem-specific functions that will be called from these
Marko Mikulicic 0:c0ecb8bf28eb 28401 * callbacks, but since the callbacks are called really a lot (on each v7
Marko Mikulicic 0:c0ecb8bf28eb 28402 * function call), I decided it's better to inline the code right here.
Marko Mikulicic 0:c0ecb8bf28eb 28403 */
Marko Mikulicic 0:c0ecb8bf28eb 28404
Marko Mikulicic 0:c0ecb8bf28eb 28405 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28406 /* Amalgamated: #include "v7/src/cyg_profile.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28407 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28408
Marko Mikulicic 0:c0ecb8bf28eb 28409 #if defined(V7_CYG_PROFILE_ON)
Marko Mikulicic 0:c0ecb8bf28eb 28410
Marko Mikulicic 0:c0ecb8bf28eb 28411 #if defined(V7_ENABLE_CALL_TRACE)
Marko Mikulicic 0:c0ecb8bf28eb 28412
Marko Mikulicic 0:c0ecb8bf28eb 28413 #define CALL_TRACE_SIZE 32
Marko Mikulicic 0:c0ecb8bf28eb 28414
Marko Mikulicic 0:c0ecb8bf28eb 28415 typedef struct {
Marko Mikulicic 0:c0ecb8bf28eb 28416 uint16_t size;
Marko Mikulicic 0:c0ecb8bf28eb 28417 uint16_t missed_cnt;
Marko Mikulicic 0:c0ecb8bf28eb 28418 void *addresses[CALL_TRACE_SIZE];
Marko Mikulicic 0:c0ecb8bf28eb 28419 } call_trace_t;
Marko Mikulicic 0:c0ecb8bf28eb 28420
Marko Mikulicic 0:c0ecb8bf28eb 28421 static call_trace_t call_trace = {0};
Marko Mikulicic 0:c0ecb8bf28eb 28422
Marko Mikulicic 0:c0ecb8bf28eb 28423 NOINSTR
Marko Mikulicic 0:c0ecb8bf28eb 28424 void call_trace_print(const char *prefix, const char *suffix, size_t skip_cnt,
Marko Mikulicic 0:c0ecb8bf28eb 28425 size_t max_cnt) {
Marko Mikulicic 0:c0ecb8bf28eb 28426 int i;
Marko Mikulicic 0:c0ecb8bf28eb 28427 if (call_trace.missed_cnt > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 28428 fprintf(stderr, "missed calls! (%d) ", (int) call_trace.missed_cnt);
Marko Mikulicic 0:c0ecb8bf28eb 28429 }
Marko Mikulicic 0:c0ecb8bf28eb 28430 if (prefix != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 28431 fprintf(stderr, "%s", prefix);
Marko Mikulicic 0:c0ecb8bf28eb 28432 }
Marko Mikulicic 0:c0ecb8bf28eb 28433 for (i = (int) call_trace.size - 1 - skip_cnt; i >= 0; i--) {
Marko Mikulicic 0:c0ecb8bf28eb 28434 fprintf(stderr, " %lx", (unsigned long) call_trace.addresses[i]);
Marko Mikulicic 0:c0ecb8bf28eb 28435 if (max_cnt > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 28436 if (--max_cnt == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 28437 break;
Marko Mikulicic 0:c0ecb8bf28eb 28438 }
Marko Mikulicic 0:c0ecb8bf28eb 28439 }
Marko Mikulicic 0:c0ecb8bf28eb 28440 }
Marko Mikulicic 0:c0ecb8bf28eb 28441 if (suffix != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 28442 fprintf(stderr, "%s", suffix);
Marko Mikulicic 0:c0ecb8bf28eb 28443 }
Marko Mikulicic 0:c0ecb8bf28eb 28444 fprintf(stderr, "\n");
Marko Mikulicic 0:c0ecb8bf28eb 28445 }
Marko Mikulicic 0:c0ecb8bf28eb 28446
Marko Mikulicic 0:c0ecb8bf28eb 28447 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28448
Marko Mikulicic 0:c0ecb8bf28eb 28449 #ifndef IRAM
Marko Mikulicic 0:c0ecb8bf28eb 28450 #define IRAM
Marko Mikulicic 0:c0ecb8bf28eb 28451 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28452
Marko Mikulicic 0:c0ecb8bf28eb 28453 #ifndef NOINSTR
Marko Mikulicic 0:c0ecb8bf28eb 28454 #define NOINSTR __attribute__((no_instrument_function))
Marko Mikulicic 0:c0ecb8bf28eb 28455 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28456
Marko Mikulicic 0:c0ecb8bf28eb 28457 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 28458 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 28459 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 28460 IRAM NOINSTR void __cyg_profile_func_enter(void *this_fn, void *call_site);
Marko Mikulicic 0:c0ecb8bf28eb 28461
Marko Mikulicic 0:c0ecb8bf28eb 28462 IRAM NOINSTR void __cyg_profile_func_exit(void *this_fn, void *call_site);
Marko Mikulicic 0:c0ecb8bf28eb 28463
Marko Mikulicic 0:c0ecb8bf28eb 28464 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 28465 }
Marko Mikulicic 0:c0ecb8bf28eb 28466 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 28467
Marko Mikulicic 0:c0ecb8bf28eb 28468 IRAM void __cyg_profile_func_enter(void *this_fn, void *call_site) {
Marko Mikulicic 0:c0ecb8bf28eb 28469 #if defined(V7_STACK_GUARD_MIN_SIZE)
Marko Mikulicic 0:c0ecb8bf28eb 28470 {
Marko Mikulicic 0:c0ecb8bf28eb 28471 static int profile_enter = 0;
Marko Mikulicic 0:c0ecb8bf28eb 28472 void *fp = __builtin_frame_address(0);
Marko Mikulicic 0:c0ecb8bf28eb 28473
Marko Mikulicic 0:c0ecb8bf28eb 28474 (void) call_site;
Marko Mikulicic 0:c0ecb8bf28eb 28475
Marko Mikulicic 0:c0ecb8bf28eb 28476 if (profile_enter || v7_sp_limit == NULL) return;
Marko Mikulicic 0:c0ecb8bf28eb 28477
Marko Mikulicic 0:c0ecb8bf28eb 28478 profile_enter++;
Marko Mikulicic 0:c0ecb8bf28eb 28479 if (v7_head != NULL && fp < v7_head->sp_lwm) v7_head->sp_lwm = fp;
Marko Mikulicic 0:c0ecb8bf28eb 28480
Marko Mikulicic 0:c0ecb8bf28eb 28481 if (((int) fp - (int) v7_sp_limit) < V7_STACK_GUARD_MIN_SIZE) {
Marko Mikulicic 0:c0ecb8bf28eb 28482 printf("fun %p sp %p limit %p left %d\n", this_fn, fp, v7_sp_limit,
Marko Mikulicic 0:c0ecb8bf28eb 28483 (int) fp - (int) v7_sp_limit);
Marko Mikulicic 0:c0ecb8bf28eb 28484 abort();
Marko Mikulicic 0:c0ecb8bf28eb 28485 }
Marko Mikulicic 0:c0ecb8bf28eb 28486 profile_enter--;
Marko Mikulicic 0:c0ecb8bf28eb 28487 }
Marko Mikulicic 0:c0ecb8bf28eb 28488 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28489
Marko Mikulicic 0:c0ecb8bf28eb 28490 #if defined(V7_ENABLE_GC_CHECK)
Marko Mikulicic 0:c0ecb8bf28eb 28491 {
Marko Mikulicic 0:c0ecb8bf28eb 28492 (void) this_fn;
Marko Mikulicic 0:c0ecb8bf28eb 28493 (void) call_site;
Marko Mikulicic 0:c0ecb8bf28eb 28494 }
Marko Mikulicic 0:c0ecb8bf28eb 28495 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28496
Marko Mikulicic 0:c0ecb8bf28eb 28497 #if defined(V7_ENABLE_STACK_TRACKING)
Marko Mikulicic 0:c0ecb8bf28eb 28498 {
Marko Mikulicic 0:c0ecb8bf28eb 28499 struct v7 *v7;
Marko Mikulicic 0:c0ecb8bf28eb 28500 struct stack_track_ctx *ctx;
Marko Mikulicic 0:c0ecb8bf28eb 28501 void *fp = __builtin_frame_address(1);
Marko Mikulicic 0:c0ecb8bf28eb 28502
Marko Mikulicic 0:c0ecb8bf28eb 28503 (void) this_fn;
Marko Mikulicic 0:c0ecb8bf28eb 28504 (void) call_site;
Marko Mikulicic 0:c0ecb8bf28eb 28505
Marko Mikulicic 0:c0ecb8bf28eb 28506 /*
Marko Mikulicic 0:c0ecb8bf28eb 28507 * TODO(dfrank): it actually won't work for multiple instances of v7 running
Marko Mikulicic 0:c0ecb8bf28eb 28508 * in parallel threads. We need to know the exact v7 instance for which
Marko Mikulicic 0:c0ecb8bf28eb 28509 * current function is called, but so far I failed to find a way to do this.
Marko Mikulicic 0:c0ecb8bf28eb 28510 */
Marko Mikulicic 0:c0ecb8bf28eb 28511 for (v7 = v7_head; v7 != NULL; v7 = v7->next_v7) {
Marko Mikulicic 0:c0ecb8bf28eb 28512 for (ctx = v7->stack_track_ctx; ctx != NULL; ctx = ctx->next) {
Marko Mikulicic 0:c0ecb8bf28eb 28513 /* commented because it fails on legal code compiled with -O3 */
Marko Mikulicic 0:c0ecb8bf28eb 28514 /*assert(fp <= ctx->start);*/
Marko Mikulicic 0:c0ecb8bf28eb 28515
Marko Mikulicic 0:c0ecb8bf28eb 28516 if (fp < ctx->max) {
Marko Mikulicic 0:c0ecb8bf28eb 28517 ctx->max = fp;
Marko Mikulicic 0:c0ecb8bf28eb 28518 }
Marko Mikulicic 0:c0ecb8bf28eb 28519 }
Marko Mikulicic 0:c0ecb8bf28eb 28520 }
Marko Mikulicic 0:c0ecb8bf28eb 28521 }
Marko Mikulicic 0:c0ecb8bf28eb 28522 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28523
Marko Mikulicic 0:c0ecb8bf28eb 28524 #if defined(V7_ENABLE_CALL_TRACE)
Marko Mikulicic 0:c0ecb8bf28eb 28525 if (call_trace.size < CALL_TRACE_SIZE) {
Marko Mikulicic 0:c0ecb8bf28eb 28526 call_trace.addresses[call_trace.size] = this_fn;
Marko Mikulicic 0:c0ecb8bf28eb 28527 call_trace.size++;
Marko Mikulicic 0:c0ecb8bf28eb 28528 } else {
Marko Mikulicic 0:c0ecb8bf28eb 28529 call_trace.missed_cnt++;
Marko Mikulicic 0:c0ecb8bf28eb 28530 }
Marko Mikulicic 0:c0ecb8bf28eb 28531 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28532 }
Marko Mikulicic 0:c0ecb8bf28eb 28533
Marko Mikulicic 0:c0ecb8bf28eb 28534 IRAM void __cyg_profile_func_exit(void *this_fn, void *call_site) {
Marko Mikulicic 0:c0ecb8bf28eb 28535 #if defined(V7_STACK_GUARD_MIN_SIZE)
Marko Mikulicic 0:c0ecb8bf28eb 28536 {
Marko Mikulicic 0:c0ecb8bf28eb 28537 (void) this_fn;
Marko Mikulicic 0:c0ecb8bf28eb 28538 (void) call_site;
Marko Mikulicic 0:c0ecb8bf28eb 28539 }
Marko Mikulicic 0:c0ecb8bf28eb 28540 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28541
Marko Mikulicic 0:c0ecb8bf28eb 28542 #if defined(V7_ENABLE_GC_CHECK)
Marko Mikulicic 0:c0ecb8bf28eb 28543 {
Marko Mikulicic 0:c0ecb8bf28eb 28544 struct v7 *v7;
Marko Mikulicic 0:c0ecb8bf28eb 28545 void *fp = __builtin_frame_address(1);
Marko Mikulicic 0:c0ecb8bf28eb 28546
Marko Mikulicic 0:c0ecb8bf28eb 28547 (void) this_fn;
Marko Mikulicic 0:c0ecb8bf28eb 28548 (void) call_site;
Marko Mikulicic 0:c0ecb8bf28eb 28549
Marko Mikulicic 0:c0ecb8bf28eb 28550 for (v7 = v7_head; v7 != NULL; v7 = v7->next_v7) {
Marko Mikulicic 0:c0ecb8bf28eb 28551 v7_val_t **vp;
Marko Mikulicic 0:c0ecb8bf28eb 28552 if (v7->owned_values.buf == NULL) continue;
Marko Mikulicic 0:c0ecb8bf28eb 28553 vp = (v7_val_t **) (v7->owned_values.buf + v7->owned_values.len -
Marko Mikulicic 0:c0ecb8bf28eb 28554 sizeof(v7_val_t *));
Marko Mikulicic 0:c0ecb8bf28eb 28555
Marko Mikulicic 0:c0ecb8bf28eb 28556 for (; (char *) vp >= v7->owned_values.buf; vp--) {
Marko Mikulicic 0:c0ecb8bf28eb 28557 /*
Marko Mikulicic 0:c0ecb8bf28eb 28558 * Check if a variable belongs to a dead stack frame.
Marko Mikulicic 0:c0ecb8bf28eb 28559 * Addresses lower than the parent frame belong to the
Marko Mikulicic 0:c0ecb8bf28eb 28560 * stack frame of the function about to return.
Marko Mikulicic 0:c0ecb8bf28eb 28561 * But the heap also usually below the stack and
Marko Mikulicic 0:c0ecb8bf28eb 28562 * we don't know the end of the stack. But this hook
Marko Mikulicic 0:c0ecb8bf28eb 28563 * is called at each function return, so we have
Marko Mikulicic 0:c0ecb8bf28eb 28564 * to check only up to the maximum stack frame size,
Marko Mikulicic 0:c0ecb8bf28eb 28565 * let's arbitrarily but reasonably set that at 8k.
Marko Mikulicic 0:c0ecb8bf28eb 28566 */
Marko Mikulicic 0:c0ecb8bf28eb 28567 if ((void *) *vp <= fp && (void *) *vp > (fp + 8196)) {
Marko Mikulicic 0:c0ecb8bf28eb 28568 fprintf(stderr, "Found owned variable after return\n");
Marko Mikulicic 0:c0ecb8bf28eb 28569 abort();
Marko Mikulicic 0:c0ecb8bf28eb 28570 }
Marko Mikulicic 0:c0ecb8bf28eb 28571 }
Marko Mikulicic 0:c0ecb8bf28eb 28572 }
Marko Mikulicic 0:c0ecb8bf28eb 28573 }
Marko Mikulicic 0:c0ecb8bf28eb 28574 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28575
Marko Mikulicic 0:c0ecb8bf28eb 28576 #if defined(V7_ENABLE_STACK_TRACKING)
Marko Mikulicic 0:c0ecb8bf28eb 28577 {
Marko Mikulicic 0:c0ecb8bf28eb 28578 (void) this_fn;
Marko Mikulicic 0:c0ecb8bf28eb 28579 (void) call_site;
Marko Mikulicic 0:c0ecb8bf28eb 28580 }
Marko Mikulicic 0:c0ecb8bf28eb 28581 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28582
Marko Mikulicic 0:c0ecb8bf28eb 28583 #if defined(V7_ENABLE_CALL_TRACE)
Marko Mikulicic 0:c0ecb8bf28eb 28584 if (call_trace.missed_cnt > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 28585 call_trace.missed_cnt--;
Marko Mikulicic 0:c0ecb8bf28eb 28586 } else if (call_trace.size > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 28587 if (call_trace.addresses[call_trace.size - 1] != this_fn) {
Marko Mikulicic 0:c0ecb8bf28eb 28588 abort();
Marko Mikulicic 0:c0ecb8bf28eb 28589 }
Marko Mikulicic 0:c0ecb8bf28eb 28590 call_trace.size--;
Marko Mikulicic 0:c0ecb8bf28eb 28591 } else {
Marko Mikulicic 0:c0ecb8bf28eb 28592 /*
Marko Mikulicic 0:c0ecb8bf28eb 28593 * We may get here if calls to `__cyg_profile_func_exit()` and
Marko Mikulicic 0:c0ecb8bf28eb 28594 * `__cyg_profile_func_enter()` are unbalanced.
Marko Mikulicic 0:c0ecb8bf28eb 28595 *
Marko Mikulicic 0:c0ecb8bf28eb 28596 * TODO(dfrank) understand, why in the beginning of the program execution
Marko Mikulicic 0:c0ecb8bf28eb 28597 * we get here. I was sure this should be impossible.
Marko Mikulicic 0:c0ecb8bf28eb 28598 */
Marko Mikulicic 0:c0ecb8bf28eb 28599 /* abort(); */
Marko Mikulicic 0:c0ecb8bf28eb 28600 }
Marko Mikulicic 0:c0ecb8bf28eb 28601 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28602 }
Marko Mikulicic 0:c0ecb8bf28eb 28603
Marko Mikulicic 0:c0ecb8bf28eb 28604 #if defined(V7_ENABLE_STACK_TRACKING)
Marko Mikulicic 0:c0ecb8bf28eb 28605
Marko Mikulicic 0:c0ecb8bf28eb 28606 void v7_stack_track_start(struct v7 *v7, struct stack_track_ctx *ctx) {
Marko Mikulicic 0:c0ecb8bf28eb 28607 /* insert new context at the head of the list */
Marko Mikulicic 0:c0ecb8bf28eb 28608 ctx->next = v7->stack_track_ctx;
Marko Mikulicic 0:c0ecb8bf28eb 28609 v7->stack_track_ctx = ctx;
Marko Mikulicic 0:c0ecb8bf28eb 28610
Marko Mikulicic 0:c0ecb8bf28eb 28611 /* init both `max` and `start` to the current frame pointer */
Marko Mikulicic 0:c0ecb8bf28eb 28612 ctx->max = ctx->start = __builtin_frame_address(0);
Marko Mikulicic 0:c0ecb8bf28eb 28613 }
Marko Mikulicic 0:c0ecb8bf28eb 28614
Marko Mikulicic 0:c0ecb8bf28eb 28615 int v7_stack_track_end(struct v7 *v7, struct stack_track_ctx *ctx) {
Marko Mikulicic 0:c0ecb8bf28eb 28616 int diff;
Marko Mikulicic 0:c0ecb8bf28eb 28617
Marko Mikulicic 0:c0ecb8bf28eb 28618 /* this function can be called only for the head context */
Marko Mikulicic 0:c0ecb8bf28eb 28619 assert(v7->stack_track_ctx == ctx);
Marko Mikulicic 0:c0ecb8bf28eb 28620
Marko Mikulicic 0:c0ecb8bf28eb 28621 diff = (int) ((char *) ctx->start - (char *) ctx->max);
Marko Mikulicic 0:c0ecb8bf28eb 28622
Marko Mikulicic 0:c0ecb8bf28eb 28623 /* remove context from the linked list */
Marko Mikulicic 0:c0ecb8bf28eb 28624 v7->stack_track_ctx = ctx->next;
Marko Mikulicic 0:c0ecb8bf28eb 28625
Marko Mikulicic 0:c0ecb8bf28eb 28626 return (int) diff;
Marko Mikulicic 0:c0ecb8bf28eb 28627 }
Marko Mikulicic 0:c0ecb8bf28eb 28628
Marko Mikulicic 0:c0ecb8bf28eb 28629 #endif /* V7_ENABLE_STACK_TRACKING */
Marko Mikulicic 0:c0ecb8bf28eb 28630 #endif /* V7_CYG_PROFILE_ON */
Marko Mikulicic 0:c0ecb8bf28eb 28631 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 28632 #line 1 "v7/src/std_object.c"
Marko Mikulicic 0:c0ecb8bf28eb 28633 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28634 /*
Marko Mikulicic 0:c0ecb8bf28eb 28635 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 28636 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 28637 */
Marko Mikulicic 0:c0ecb8bf28eb 28638
Marko Mikulicic 0:c0ecb8bf28eb 28639 /* Amalgamated: #include "common/str_util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28640 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28641 /* Amalgamated: #include "v7/src/std_object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28642 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28643 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28644 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28645 /* Amalgamated: #include "v7/src/array.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28646 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28647 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28648 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28649 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28650 /* Amalgamated: #include "v7/src/regexp.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28651 /* Amalgamated: #include "v7/src/exec.h" */
Marko Mikulicic 0:c0ecb8bf28eb 28652
Marko Mikulicic 0:c0ecb8bf28eb 28653 #if V7_ENABLE__Object__getPrototypeOf
Marko Mikulicic 0:c0ecb8bf28eb 28654 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 28655 V7_PRIVATE enum v7_err Obj_getPrototypeOf(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 28656 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 28657 val_t arg = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 28658
Marko Mikulicic 0:c0ecb8bf28eb 28659 if (!v7_is_object(arg)) {
Marko Mikulicic 0:c0ecb8bf28eb 28660 rcode =
Marko Mikulicic 0:c0ecb8bf28eb 28661 v7_throwf(v7, TYPE_ERROR, "Object.getPrototypeOf called on non-object");
Marko Mikulicic 0:c0ecb8bf28eb 28662 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28663 }
Marko Mikulicic 0:c0ecb8bf28eb 28664 *res = v7_get_proto(v7, arg);
Marko Mikulicic 0:c0ecb8bf28eb 28665
Marko Mikulicic 0:c0ecb8bf28eb 28666 clean:
Marko Mikulicic 0:c0ecb8bf28eb 28667 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 28668 }
Marko Mikulicic 0:c0ecb8bf28eb 28669 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28670
Marko Mikulicic 0:c0ecb8bf28eb 28671 #if V7_ENABLE__Object__isPrototypeOf
Marko Mikulicic 0:c0ecb8bf28eb 28672 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 28673 V7_PRIVATE enum v7_err Obj_isPrototypeOf(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 28674 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 28675 val_t obj = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 28676 val_t proto = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 28677
Marko Mikulicic 0:c0ecb8bf28eb 28678 *res = v7_mk_boolean(v7, is_prototype_of(v7, obj, proto));
Marko Mikulicic 0:c0ecb8bf28eb 28679
Marko Mikulicic 0:c0ecb8bf28eb 28680 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 28681 }
Marko Mikulicic 0:c0ecb8bf28eb 28682 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28683
Marko Mikulicic 0:c0ecb8bf28eb 28684 #if V7_ENABLE__Object__getOwnPropertyNames || V7_ENABLE__Object__keys
Marko Mikulicic 0:c0ecb8bf28eb 28685 /*
Marko Mikulicic 0:c0ecb8bf28eb 28686 * Hack to ensure that the iteration order of the keys array is consistent
Marko Mikulicic 0:c0ecb8bf28eb 28687 * with the iteration order if properties in `for in`
Marko Mikulicic 0:c0ecb8bf28eb 28688 * This will be obsoleted when arrays will have a special object type.
Marko Mikulicic 0:c0ecb8bf28eb 28689 */
Marko Mikulicic 0:c0ecb8bf28eb 28690 static void _Obj_append_reverse(struct v7 *v7, struct v7_property *p, val_t res,
Marko Mikulicic 0:c0ecb8bf28eb 28691 int i, v7_prop_attr_t ignore_flags) {
Marko Mikulicic 0:c0ecb8bf28eb 28692 while (p && p->attributes & ignore_flags) p = p->next;
Marko Mikulicic 0:c0ecb8bf28eb 28693 if (p == NULL) return;
Marko Mikulicic 0:c0ecb8bf28eb 28694 if (p->next) _Obj_append_reverse(v7, p->next, res, i + 1, ignore_flags);
Marko Mikulicic 0:c0ecb8bf28eb 28695
Marko Mikulicic 0:c0ecb8bf28eb 28696 v7_array_set(v7, res, i, p->name);
Marko Mikulicic 0:c0ecb8bf28eb 28697 }
Marko Mikulicic 0:c0ecb8bf28eb 28698
Marko Mikulicic 0:c0ecb8bf28eb 28699 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 28700 static enum v7_err _Obj_ownKeys(struct v7 *v7, unsigned int ignore_flags,
Marko Mikulicic 0:c0ecb8bf28eb 28701 val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 28702 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 28703 val_t obj = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 28704
Marko Mikulicic 0:c0ecb8bf28eb 28705 *res = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 28706
Marko Mikulicic 0:c0ecb8bf28eb 28707 if (!v7_is_object(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 28708 rcode = v7_throwf(v7, TYPE_ERROR, "Object.keys called on non-object");
Marko Mikulicic 0:c0ecb8bf28eb 28709 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28710 }
Marko Mikulicic 0:c0ecb8bf28eb 28711
Marko Mikulicic 0:c0ecb8bf28eb 28712 _Obj_append_reverse(v7, get_object_struct(obj)->properties, *res, 0,
Marko Mikulicic 0:c0ecb8bf28eb 28713 ignore_flags);
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__hasOwnProperty || \
Marko Mikulicic 0:c0ecb8bf28eb 28721 V7_ENABLE__Object__propertyIsEnumerable || \
Marko Mikulicic 0:c0ecb8bf28eb 28722 V7_ENABLE__Object__getOwnPropertyDescriptor
Marko Mikulicic 0:c0ecb8bf28eb 28723 static enum v7_err _Obj_getOwnProperty(struct v7 *v7, val_t obj, val_t name,
Marko Mikulicic 0:c0ecb8bf28eb 28724 struct v7_property **res) {
Marko Mikulicic 0:c0ecb8bf28eb 28725 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 28726 char name_buf[512];
Marko Mikulicic 0:c0ecb8bf28eb 28727 size_t name_len;
Marko Mikulicic 0:c0ecb8bf28eb 28728
Marko Mikulicic 0:c0ecb8bf28eb 28729 rcode = to_string(v7, name, NULL, name_buf, sizeof(name_buf), &name_len);
Marko Mikulicic 0:c0ecb8bf28eb 28730 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28731 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28732 }
Marko Mikulicic 0:c0ecb8bf28eb 28733
Marko Mikulicic 0:c0ecb8bf28eb 28734 *res = v7_get_own_property(v7, obj, name_buf, name_len);
Marko Mikulicic 0:c0ecb8bf28eb 28735
Marko Mikulicic 0:c0ecb8bf28eb 28736 clean:
Marko Mikulicic 0:c0ecb8bf28eb 28737 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 28738 }
Marko Mikulicic 0:c0ecb8bf28eb 28739 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28740
Marko Mikulicic 0:c0ecb8bf28eb 28741 #if V7_ENABLE__Object__keys
Marko Mikulicic 0:c0ecb8bf28eb 28742 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 28743 V7_PRIVATE enum v7_err Obj_keys(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 28744 return _Obj_ownKeys(v7, _V7_PROPERTY_HIDDEN | V7_PROPERTY_NON_ENUMERABLE,
Marko Mikulicic 0:c0ecb8bf28eb 28745 res);
Marko Mikulicic 0:c0ecb8bf28eb 28746 }
Marko Mikulicic 0:c0ecb8bf28eb 28747 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28748
Marko Mikulicic 0:c0ecb8bf28eb 28749 #if V7_ENABLE__Object__getOwnPropertyNames
Marko Mikulicic 0:c0ecb8bf28eb 28750 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 28751 V7_PRIVATE enum v7_err Obj_getOwnPropertyNames(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 28752 return _Obj_ownKeys(v7, _V7_PROPERTY_HIDDEN, res);
Marko Mikulicic 0:c0ecb8bf28eb 28753 }
Marko Mikulicic 0:c0ecb8bf28eb 28754 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28755
Marko Mikulicic 0:c0ecb8bf28eb 28756 #if V7_ENABLE__Object__getOwnPropertyDescriptor
Marko Mikulicic 0:c0ecb8bf28eb 28757 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 28758 V7_PRIVATE enum v7_err Obj_getOwnPropertyDescriptor(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 28759 v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 28760 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 28761 struct v7_property *prop;
Marko Mikulicic 0:c0ecb8bf28eb 28762 val_t obj = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 28763 val_t name = v7_arg(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 28764 val_t desc;
Marko Mikulicic 0:c0ecb8bf28eb 28765
Marko Mikulicic 0:c0ecb8bf28eb 28766 rcode = _Obj_getOwnProperty(v7, obj, name, &prop);
Marko Mikulicic 0:c0ecb8bf28eb 28767 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28768 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28769 }
Marko Mikulicic 0:c0ecb8bf28eb 28770
Marko Mikulicic 0:c0ecb8bf28eb 28771 if (prop == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 28772 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28773 }
Marko Mikulicic 0:c0ecb8bf28eb 28774
Marko Mikulicic 0:c0ecb8bf28eb 28775 desc = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 28776 v7_set(v7, desc, "value", 5, prop->value);
Marko Mikulicic 0:c0ecb8bf28eb 28777 v7_set(v7, desc, "writable", 8,
Marko Mikulicic 0:c0ecb8bf28eb 28778 v7_mk_boolean(v7, !(prop->attributes & V7_PROPERTY_NON_WRITABLE)));
Marko Mikulicic 0:c0ecb8bf28eb 28779 v7_set(v7, desc, "enumerable", 10,
Marko Mikulicic 0:c0ecb8bf28eb 28780 v7_mk_boolean(v7, !(prop->attributes & (_V7_PROPERTY_HIDDEN |
Marko Mikulicic 0:c0ecb8bf28eb 28781 V7_PROPERTY_NON_ENUMERABLE))));
Marko Mikulicic 0:c0ecb8bf28eb 28782 v7_set(v7, desc, "configurable", 12,
Marko Mikulicic 0:c0ecb8bf28eb 28783 v7_mk_boolean(v7, !(prop->attributes & V7_PROPERTY_NON_CONFIGURABLE)));
Marko Mikulicic 0:c0ecb8bf28eb 28784
Marko Mikulicic 0:c0ecb8bf28eb 28785 *res = desc;
Marko Mikulicic 0:c0ecb8bf28eb 28786
Marko Mikulicic 0:c0ecb8bf28eb 28787 clean:
Marko Mikulicic 0:c0ecb8bf28eb 28788 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 28789 }
Marko Mikulicic 0:c0ecb8bf28eb 28790 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28791
Marko Mikulicic 0:c0ecb8bf28eb 28792 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 28793 static enum v7_err o_set_attr(struct v7 *v7, val_t desc, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 28794 size_t n, v7_prop_attr_desc_t *pattrs_delta,
Marko Mikulicic 0:c0ecb8bf28eb 28795 v7_prop_attr_desc_t flag_true,
Marko Mikulicic 0:c0ecb8bf28eb 28796 v7_prop_attr_desc_t flag_false) {
Marko Mikulicic 0:c0ecb8bf28eb 28797 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 28798
Marko Mikulicic 0:c0ecb8bf28eb 28799 val_t v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 28800 rcode = v7_get_throwing(v7, desc, name, n, &v);
Marko Mikulicic 0:c0ecb8bf28eb 28801 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28802 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28803 }
Marko Mikulicic 0:c0ecb8bf28eb 28804
Marko Mikulicic 0:c0ecb8bf28eb 28805 if (v7_is_truthy(v7, v)) {
Marko Mikulicic 0:c0ecb8bf28eb 28806 *pattrs_delta |= flag_true;
Marko Mikulicic 0:c0ecb8bf28eb 28807 } else {
Marko Mikulicic 0:c0ecb8bf28eb 28808 *pattrs_delta |= flag_false;
Marko Mikulicic 0:c0ecb8bf28eb 28809 }
Marko Mikulicic 0:c0ecb8bf28eb 28810
Marko Mikulicic 0:c0ecb8bf28eb 28811 clean:
Marko Mikulicic 0:c0ecb8bf28eb 28812 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 28813 }
Marko Mikulicic 0:c0ecb8bf28eb 28814
Marko Mikulicic 0:c0ecb8bf28eb 28815 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 28816 static enum v7_err _Obj_defineProperty(struct v7 *v7, val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 28817 const char *name, int name_len,
Marko Mikulicic 0:c0ecb8bf28eb 28818 val_t desc, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 28819 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 28820 val_t val = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 28821 v7_prop_attr_desc_t attrs_desc = 0;
Marko Mikulicic 0:c0ecb8bf28eb 28822
Marko Mikulicic 0:c0ecb8bf28eb 28823 /*
Marko Mikulicic 0:c0ecb8bf28eb 28824 * get provided value, or set `V7_DESC_PRESERVE_VALUE` flag if no value is
Marko Mikulicic 0:c0ecb8bf28eb 28825 * provided at all
Marko Mikulicic 0:c0ecb8bf28eb 28826 */
Marko Mikulicic 0:c0ecb8bf28eb 28827 {
Marko Mikulicic 0:c0ecb8bf28eb 28828 struct v7_property *prop = v7_get_property(v7, desc, "value", 5);
Marko Mikulicic 0:c0ecb8bf28eb 28829 if (prop == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 28830 /* no value is provided */
Marko Mikulicic 0:c0ecb8bf28eb 28831 attrs_desc |= V7_DESC_PRESERVE_VALUE;
Marko Mikulicic 0:c0ecb8bf28eb 28832 } else {
Marko Mikulicic 0:c0ecb8bf28eb 28833 /* value is provided: use it */
Marko Mikulicic 0:c0ecb8bf28eb 28834 rcode = v7_property_value(v7, desc, prop, &val);
Marko Mikulicic 0:c0ecb8bf28eb 28835 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28836 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28837 }
Marko Mikulicic 0:c0ecb8bf28eb 28838 }
Marko Mikulicic 0:c0ecb8bf28eb 28839 }
Marko Mikulicic 0:c0ecb8bf28eb 28840
Marko Mikulicic 0:c0ecb8bf28eb 28841 /* Examine given properties, and set appropriate flags for `def_property` */
Marko Mikulicic 0:c0ecb8bf28eb 28842
Marko Mikulicic 0:c0ecb8bf28eb 28843 rcode = o_set_attr(v7, desc, "enumerable", 10, &attrs_desc,
Marko Mikulicic 0:c0ecb8bf28eb 28844 V7_DESC_ENUMERABLE(1), V7_DESC_ENUMERABLE(0));
Marko Mikulicic 0:c0ecb8bf28eb 28845 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28846 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28847 }
Marko Mikulicic 0:c0ecb8bf28eb 28848
Marko Mikulicic 0:c0ecb8bf28eb 28849 rcode = o_set_attr(v7, desc, "writable", 8, &attrs_desc, V7_DESC_WRITABLE(1),
Marko Mikulicic 0:c0ecb8bf28eb 28850 V7_DESC_WRITABLE(0));
Marko Mikulicic 0:c0ecb8bf28eb 28851 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28852 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28853 }
Marko Mikulicic 0:c0ecb8bf28eb 28854
Marko Mikulicic 0:c0ecb8bf28eb 28855 rcode = o_set_attr(v7, desc, "configurable", 12, &attrs_desc,
Marko Mikulicic 0:c0ecb8bf28eb 28856 V7_DESC_CONFIGURABLE(1), V7_DESC_CONFIGURABLE(0));
Marko Mikulicic 0:c0ecb8bf28eb 28857 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28858 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28859 }
Marko Mikulicic 0:c0ecb8bf28eb 28860
Marko Mikulicic 0:c0ecb8bf28eb 28861 /* TODO(dfrank) : add getter/setter support */
Marko Mikulicic 0:c0ecb8bf28eb 28862
Marko Mikulicic 0:c0ecb8bf28eb 28863 /* Finally, do the job on defining the property */
Marko Mikulicic 0:c0ecb8bf28eb 28864 rcode = def_property(v7, obj, name, name_len, attrs_desc, val,
Marko Mikulicic 0:c0ecb8bf28eb 28865 0 /*not assign*/, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 28866 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28867 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28868 }
Marko Mikulicic 0:c0ecb8bf28eb 28869
Marko Mikulicic 0:c0ecb8bf28eb 28870 *res = obj;
Marko Mikulicic 0:c0ecb8bf28eb 28871 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28872
Marko Mikulicic 0:c0ecb8bf28eb 28873 clean:
Marko Mikulicic 0:c0ecb8bf28eb 28874 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 28875 }
Marko Mikulicic 0:c0ecb8bf28eb 28876
Marko Mikulicic 0:c0ecb8bf28eb 28877 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 28878 V7_PRIVATE enum v7_err Obj_defineProperty(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 28879 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 28880 val_t obj = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 28881 val_t name = v7_arg(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 28882 val_t desc = v7_arg(v7, 2);
Marko Mikulicic 0:c0ecb8bf28eb 28883 char name_buf[512];
Marko Mikulicic 0:c0ecb8bf28eb 28884 size_t name_len;
Marko Mikulicic 0:c0ecb8bf28eb 28885
Marko Mikulicic 0:c0ecb8bf28eb 28886 if (!v7_is_object(obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 28887 rcode = v7_throwf(v7, TYPE_ERROR, "object expected");
Marko Mikulicic 0:c0ecb8bf28eb 28888 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28889 }
Marko Mikulicic 0:c0ecb8bf28eb 28890
Marko Mikulicic 0:c0ecb8bf28eb 28891 rcode = to_string(v7, name, NULL, name_buf, sizeof(name_buf), &name_len);
Marko Mikulicic 0:c0ecb8bf28eb 28892 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28893 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28894 }
Marko Mikulicic 0:c0ecb8bf28eb 28895
Marko Mikulicic 0:c0ecb8bf28eb 28896 rcode = _Obj_defineProperty(v7, obj, name_buf, name_len, desc, res);
Marko Mikulicic 0:c0ecb8bf28eb 28897 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28898
Marko Mikulicic 0:c0ecb8bf28eb 28899 clean:
Marko Mikulicic 0:c0ecb8bf28eb 28900 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 28901 }
Marko Mikulicic 0:c0ecb8bf28eb 28902
Marko Mikulicic 0:c0ecb8bf28eb 28903 #if V7_ENABLE__Object__create || V7_ENABLE__Object__defineProperties
Marko Mikulicic 0:c0ecb8bf28eb 28904 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 28905 static enum v7_err o_define_props(struct v7 *v7, val_t obj, val_t descs,
Marko Mikulicic 0:c0ecb8bf28eb 28906 val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 28907 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 28908 struct v7_property *p;
Marko Mikulicic 0:c0ecb8bf28eb 28909
Marko Mikulicic 0:c0ecb8bf28eb 28910 if (!v7_is_object(descs)) {
Marko Mikulicic 0:c0ecb8bf28eb 28911 rcode = v7_throwf(v7, TYPE_ERROR, "object expected");
Marko Mikulicic 0:c0ecb8bf28eb 28912 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28913 }
Marko Mikulicic 0:c0ecb8bf28eb 28914
Marko Mikulicic 0:c0ecb8bf28eb 28915 for (p = get_object_struct(descs)->properties; p; p = p->next) {
Marko Mikulicic 0:c0ecb8bf28eb 28916 size_t n;
Marko Mikulicic 0:c0ecb8bf28eb 28917 const char *s = v7_get_string(v7, &p->name, &n);
Marko Mikulicic 0:c0ecb8bf28eb 28918 if (p->attributes & (_V7_PROPERTY_HIDDEN | V7_PROPERTY_NON_ENUMERABLE)) {
Marko Mikulicic 0:c0ecb8bf28eb 28919 continue;
Marko Mikulicic 0:c0ecb8bf28eb 28920 }
Marko Mikulicic 0:c0ecb8bf28eb 28921 rcode = _Obj_defineProperty(v7, obj, s, n, p->value, res);
Marko Mikulicic 0:c0ecb8bf28eb 28922 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28923 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28924 }
Marko Mikulicic 0:c0ecb8bf28eb 28925 }
Marko Mikulicic 0:c0ecb8bf28eb 28926
Marko Mikulicic 0:c0ecb8bf28eb 28927 clean:
Marko Mikulicic 0:c0ecb8bf28eb 28928 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 28929 }
Marko Mikulicic 0:c0ecb8bf28eb 28930 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28931
Marko Mikulicic 0:c0ecb8bf28eb 28932 #if V7_ENABLE__Object__defineProperties
Marko Mikulicic 0:c0ecb8bf28eb 28933 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 28934 V7_PRIVATE enum v7_err Obj_defineProperties(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 28935 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 28936 val_t descs = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 28937
Marko Mikulicic 0:c0ecb8bf28eb 28938 *res = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 28939 descs = v7_arg(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 28940 rcode = o_define_props(v7, *res, descs, res);
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 clean:
Marko Mikulicic 0:c0ecb8bf28eb 28946 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 28947 }
Marko Mikulicic 0:c0ecb8bf28eb 28948 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28949
Marko Mikulicic 0:c0ecb8bf28eb 28950 #if V7_ENABLE__Object__create
Marko Mikulicic 0:c0ecb8bf28eb 28951 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 28952 V7_PRIVATE enum v7_err Obj_create(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 28953 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 28954 val_t proto = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 28955 val_t descs = v7_arg(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 28956 if (!v7_is_null(proto) && !v7_is_object(proto)) {
Marko Mikulicic 0:c0ecb8bf28eb 28957 rcode = v7_throwf(v7, TYPE_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 28958 "Object prototype may only be an Object or null");
Marko Mikulicic 0:c0ecb8bf28eb 28959 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28960 }
Marko Mikulicic 0:c0ecb8bf28eb 28961 *res = mk_object(v7, proto);
Marko Mikulicic 0:c0ecb8bf28eb 28962 if (v7_is_object(descs)) {
Marko Mikulicic 0:c0ecb8bf28eb 28963 rcode = o_define_props(v7, *res, descs, res);
Marko Mikulicic 0:c0ecb8bf28eb 28964 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28965 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28966 }
Marko Mikulicic 0:c0ecb8bf28eb 28967 }
Marko Mikulicic 0:c0ecb8bf28eb 28968
Marko Mikulicic 0:c0ecb8bf28eb 28969 clean:
Marko Mikulicic 0:c0ecb8bf28eb 28970 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 28971 }
Marko Mikulicic 0:c0ecb8bf28eb 28972 #endif
Marko Mikulicic 0:c0ecb8bf28eb 28973
Marko Mikulicic 0:c0ecb8bf28eb 28974 #if V7_ENABLE__Object__propertyIsEnumerable
Marko Mikulicic 0:c0ecb8bf28eb 28975 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 28976 V7_PRIVATE enum v7_err Obj_propertyIsEnumerable(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 28977 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 28978 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 28979 struct v7_property *prop;
Marko Mikulicic 0:c0ecb8bf28eb 28980 val_t name = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 28981
Marko Mikulicic 0:c0ecb8bf28eb 28982 rcode = _Obj_getOwnProperty(v7, this_obj, name, &prop);
Marko Mikulicic 0:c0ecb8bf28eb 28983 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 28984 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28985 }
Marko Mikulicic 0:c0ecb8bf28eb 28986
Marko Mikulicic 0:c0ecb8bf28eb 28987 if (prop == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 28988 *res = v7_mk_boolean(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 28989 } else {
Marko Mikulicic 0:c0ecb8bf28eb 28990 *res =
Marko Mikulicic 0:c0ecb8bf28eb 28991 v7_mk_boolean(v7, !(prop->attributes & (_V7_PROPERTY_HIDDEN |
Marko Mikulicic 0:c0ecb8bf28eb 28992 V7_PROPERTY_NON_ENUMERABLE)));
Marko Mikulicic 0:c0ecb8bf28eb 28993 }
Marko Mikulicic 0:c0ecb8bf28eb 28994
Marko Mikulicic 0:c0ecb8bf28eb 28995 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 28996
Marko Mikulicic 0:c0ecb8bf28eb 28997 clean:
Marko Mikulicic 0:c0ecb8bf28eb 28998 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 28999 }
Marko Mikulicic 0:c0ecb8bf28eb 29000 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29001
Marko Mikulicic 0:c0ecb8bf28eb 29002 #if V7_ENABLE__Object__hasOwnProperty
Marko Mikulicic 0:c0ecb8bf28eb 29003 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29004 V7_PRIVATE enum v7_err Obj_hasOwnProperty(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29005 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29006 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29007 val_t name = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29008 struct v7_property *ptmp = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 29009
Marko Mikulicic 0:c0ecb8bf28eb 29010 rcode = _Obj_getOwnProperty(v7, this_obj, name, &ptmp);
Marko Mikulicic 0:c0ecb8bf28eb 29011 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29012 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29013 }
Marko Mikulicic 0:c0ecb8bf28eb 29014
Marko Mikulicic 0:c0ecb8bf28eb 29015 *res = v7_mk_boolean(v7, ptmp != NULL);
Marko Mikulicic 0:c0ecb8bf28eb 29016 goto clean;
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 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29024 V7_PRIVATE enum v7_err Obj_valueOf(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29025 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29026 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29027 struct v7_property *p;
Marko Mikulicic 0:c0ecb8bf28eb 29028
Marko Mikulicic 0:c0ecb8bf28eb 29029 *res = this_obj;
Marko Mikulicic 0:c0ecb8bf28eb 29030
Marko Mikulicic 0:c0ecb8bf28eb 29031 if (v7_is_regexp(v7, this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 29032 /* res is `this_obj` */
Marko Mikulicic 0:c0ecb8bf28eb 29033 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29034 }
Marko Mikulicic 0:c0ecb8bf28eb 29035
Marko Mikulicic 0:c0ecb8bf28eb 29036 p = v7_get_own_property2(v7, this_obj, "", 0, _V7_PROPERTY_HIDDEN);
Marko Mikulicic 0:c0ecb8bf28eb 29037 if (p != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 29038 *res = p->value;
Marko Mikulicic 0:c0ecb8bf28eb 29039 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29040 }
Marko Mikulicic 0:c0ecb8bf28eb 29041
Marko Mikulicic 0:c0ecb8bf28eb 29042 clean:
Marko Mikulicic 0:c0ecb8bf28eb 29043 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29044 }
Marko Mikulicic 0:c0ecb8bf28eb 29045
Marko Mikulicic 0:c0ecb8bf28eb 29046 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29047 V7_PRIVATE enum v7_err Obj_toString(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29048 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29049 val_t ctor, name, this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29050 char buf[20];
Marko Mikulicic 0:c0ecb8bf28eb 29051 const char *str = "Object";
Marko Mikulicic 0:c0ecb8bf28eb 29052 size_t name_len = ~0;
Marko Mikulicic 0:c0ecb8bf28eb 29053
Marko Mikulicic 0:c0ecb8bf28eb 29054 if (v7_is_undefined(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 29055 str = "Undefined";
Marko Mikulicic 0:c0ecb8bf28eb 29056 } else if (v7_is_null(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 29057 str = "Null";
Marko Mikulicic 0:c0ecb8bf28eb 29058 } else if (v7_is_number(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 29059 str = "Number";
Marko Mikulicic 0:c0ecb8bf28eb 29060 } else if (v7_is_boolean(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 29061 str = "Boolean";
Marko Mikulicic 0:c0ecb8bf28eb 29062 } else if (v7_is_string(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 29063 str = "String";
Marko Mikulicic 0:c0ecb8bf28eb 29064 } else if (v7_is_callable(v7, this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 29065 str = "Function";
Marko Mikulicic 0:c0ecb8bf28eb 29066 } else {
Marko Mikulicic 0:c0ecb8bf28eb 29067 rcode = v7_get_throwing(v7, this_obj, "constructor", ~0, &ctor);
Marko Mikulicic 0:c0ecb8bf28eb 29068 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29069 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29070 }
Marko Mikulicic 0:c0ecb8bf28eb 29071
Marko Mikulicic 0:c0ecb8bf28eb 29072 if (!v7_is_undefined(ctor)) {
Marko Mikulicic 0:c0ecb8bf28eb 29073 rcode = v7_get_throwing(v7, ctor, "name", ~0, &name);
Marko Mikulicic 0:c0ecb8bf28eb 29074 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29075 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29076 }
Marko Mikulicic 0:c0ecb8bf28eb 29077
Marko Mikulicic 0:c0ecb8bf28eb 29078 if (!v7_is_undefined(name)) {
Marko Mikulicic 0:c0ecb8bf28eb 29079 size_t tmp_len;
Marko Mikulicic 0:c0ecb8bf28eb 29080 const char *tmp_str;
Marko Mikulicic 0:c0ecb8bf28eb 29081 tmp_str = v7_get_string(v7, &name, &tmp_len);
Marko Mikulicic 0:c0ecb8bf28eb 29082 /*
Marko Mikulicic 0:c0ecb8bf28eb 29083 * objects constructed with an anonymous constructor are represented as
Marko Mikulicic 0:c0ecb8bf28eb 29084 * Object, ch11/11.1/11.1.1/S11.1.1_A4.2.js
Marko Mikulicic 0:c0ecb8bf28eb 29085 */
Marko Mikulicic 0:c0ecb8bf28eb 29086 if (tmp_len > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 29087 str = tmp_str;
Marko Mikulicic 0:c0ecb8bf28eb 29088 name_len = tmp_len;
Marko Mikulicic 0:c0ecb8bf28eb 29089 }
Marko Mikulicic 0:c0ecb8bf28eb 29090 }
Marko Mikulicic 0:c0ecb8bf28eb 29091 }
Marko Mikulicic 0:c0ecb8bf28eb 29092 }
Marko Mikulicic 0:c0ecb8bf28eb 29093
Marko Mikulicic 0:c0ecb8bf28eb 29094 if (name_len == (size_t) ~0) {
Marko Mikulicic 0:c0ecb8bf28eb 29095 name_len = strlen(str);
Marko Mikulicic 0:c0ecb8bf28eb 29096 }
Marko Mikulicic 0:c0ecb8bf28eb 29097
Marko Mikulicic 0:c0ecb8bf28eb 29098 c_snprintf(buf, sizeof(buf), "[object %.*s]", (int) name_len, str);
Marko Mikulicic 0:c0ecb8bf28eb 29099 *res = v7_mk_string(v7, buf, strlen(buf), 1);
Marko Mikulicic 0:c0ecb8bf28eb 29100
Marko Mikulicic 0:c0ecb8bf28eb 29101 clean:
Marko Mikulicic 0:c0ecb8bf28eb 29102 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29103 }
Marko Mikulicic 0:c0ecb8bf28eb 29104
Marko Mikulicic 0:c0ecb8bf28eb 29105 #if V7_ENABLE__Object__preventExtensions
Marko Mikulicic 0:c0ecb8bf28eb 29106 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29107 V7_PRIVATE enum v7_err Obj_preventExtensions(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29108 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29109 val_t arg = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29110 if (!v7_is_object(arg)) {
Marko Mikulicic 0:c0ecb8bf28eb 29111 rcode = v7_throwf(v7, TYPE_ERROR, "Object expected");
Marko Mikulicic 0:c0ecb8bf28eb 29112 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29113 }
Marko Mikulicic 0:c0ecb8bf28eb 29114 get_object_struct(arg)->attributes |= V7_OBJ_NOT_EXTENSIBLE;
Marko Mikulicic 0:c0ecb8bf28eb 29115 *res = arg;
Marko Mikulicic 0:c0ecb8bf28eb 29116
Marko Mikulicic 0:c0ecb8bf28eb 29117 clean:
Marko Mikulicic 0:c0ecb8bf28eb 29118 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29119 }
Marko Mikulicic 0:c0ecb8bf28eb 29120 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29121
Marko Mikulicic 0:c0ecb8bf28eb 29122 #if V7_ENABLE__Object__isExtensible
Marko Mikulicic 0:c0ecb8bf28eb 29123 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29124 V7_PRIVATE enum v7_err Obj_isExtensible(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29125 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29126 val_t arg = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29127
Marko Mikulicic 0:c0ecb8bf28eb 29128 if (!v7_is_object(arg)) {
Marko Mikulicic 0:c0ecb8bf28eb 29129 rcode = v7_throwf(v7, TYPE_ERROR, "Object expected");
Marko Mikulicic 0:c0ecb8bf28eb 29130 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29131 }
Marko Mikulicic 0:c0ecb8bf28eb 29132
Marko Mikulicic 0:c0ecb8bf28eb 29133 *res = v7_mk_boolean(
Marko Mikulicic 0:c0ecb8bf28eb 29134 v7, !(get_object_struct(arg)->attributes & V7_OBJ_NOT_EXTENSIBLE));
Marko Mikulicic 0:c0ecb8bf28eb 29135
Marko Mikulicic 0:c0ecb8bf28eb 29136 clean:
Marko Mikulicic 0:c0ecb8bf28eb 29137 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29138 }
Marko Mikulicic 0:c0ecb8bf28eb 29139 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29140
Marko Mikulicic 0:c0ecb8bf28eb 29141 #if V7_ENABLE__Object__isFrozen || V7_ENABLE__Object__isSealed
Marko Mikulicic 0:c0ecb8bf28eb 29142 static enum v7_err is_rigid(struct v7 *v7, v7_val_t *res, int is_frozen) {
Marko Mikulicic 0:c0ecb8bf28eb 29143 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29144 int ok = 0;
Marko Mikulicic 0:c0ecb8bf28eb 29145 val_t arg = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29146
Marko Mikulicic 0:c0ecb8bf28eb 29147 if (!v7_is_object(arg)) {
Marko Mikulicic 0:c0ecb8bf28eb 29148 rcode = v7_throwf(v7, TYPE_ERROR, "Object expected");
Marko Mikulicic 0:c0ecb8bf28eb 29149 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29150 }
Marko Mikulicic 0:c0ecb8bf28eb 29151
Marko Mikulicic 0:c0ecb8bf28eb 29152 *res = v7_mk_boolean(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29153
Marko Mikulicic 0:c0ecb8bf28eb 29154 if (get_object_struct(arg)->attributes & V7_OBJ_NOT_EXTENSIBLE) {
Marko Mikulicic 0:c0ecb8bf28eb 29155 v7_prop_attr_t attrs = 0;
Marko Mikulicic 0:c0ecb8bf28eb 29156 struct prop_iter_ctx ctx;
Marko Mikulicic 0:c0ecb8bf28eb 29157 memset(&ctx, 0, sizeof(ctx));
Marko Mikulicic 0:c0ecb8bf28eb 29158 V7_TRY2(init_prop_iter_ctx(v7, arg, 1, &ctx), clean_iter);
Marko Mikulicic 0:c0ecb8bf28eb 29159 while (1) {
Marko Mikulicic 0:c0ecb8bf28eb 29160 V7_TRY2(next_prop(v7, &ctx, NULL, NULL, &attrs, &ok), clean_iter);
Marko Mikulicic 0:c0ecb8bf28eb 29161 if (!ok) {
Marko Mikulicic 0:c0ecb8bf28eb 29162 break;
Marko Mikulicic 0:c0ecb8bf28eb 29163 }
Marko Mikulicic 0:c0ecb8bf28eb 29164 if (!(attrs & V7_PROPERTY_NON_CONFIGURABLE)) {
Marko Mikulicic 0:c0ecb8bf28eb 29165 goto clean_iter;
Marko Mikulicic 0:c0ecb8bf28eb 29166 }
Marko Mikulicic 0:c0ecb8bf28eb 29167 if (is_frozen) {
Marko Mikulicic 0:c0ecb8bf28eb 29168 if (!(attrs & V7_PROPERTY_SETTER) &&
Marko Mikulicic 0:c0ecb8bf28eb 29169 !(attrs & V7_PROPERTY_NON_WRITABLE)) {
Marko Mikulicic 0:c0ecb8bf28eb 29170 goto clean_iter;
Marko Mikulicic 0:c0ecb8bf28eb 29171 }
Marko Mikulicic 0:c0ecb8bf28eb 29172 }
Marko Mikulicic 0:c0ecb8bf28eb 29173 }
Marko Mikulicic 0:c0ecb8bf28eb 29174
Marko Mikulicic 0:c0ecb8bf28eb 29175 *res = v7_mk_boolean(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 29176
Marko Mikulicic 0:c0ecb8bf28eb 29177 clean_iter:
Marko Mikulicic 0:c0ecb8bf28eb 29178 v7_destruct_prop_iter_ctx(v7, &ctx);
Marko Mikulicic 0:c0ecb8bf28eb 29179 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29180 }
Marko Mikulicic 0:c0ecb8bf28eb 29181
Marko Mikulicic 0:c0ecb8bf28eb 29182 clean:
Marko Mikulicic 0:c0ecb8bf28eb 29183 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29184 }
Marko Mikulicic 0:c0ecb8bf28eb 29185 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29186
Marko Mikulicic 0:c0ecb8bf28eb 29187 #if V7_ENABLE__Object__isSealed
Marko Mikulicic 0:c0ecb8bf28eb 29188 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29189 V7_PRIVATE enum v7_err Obj_isSealed(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29190 return is_rigid(v7, res, 0 /* is_frozen */);
Marko Mikulicic 0:c0ecb8bf28eb 29191 }
Marko Mikulicic 0:c0ecb8bf28eb 29192 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29193
Marko Mikulicic 0:c0ecb8bf28eb 29194 #if V7_ENABLE__Object__isFrozen
Marko Mikulicic 0:c0ecb8bf28eb 29195 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29196 V7_PRIVATE enum v7_err Obj_isFrozen(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29197 return is_rigid(v7, res, 1 /* is_frozen */);
Marko Mikulicic 0:c0ecb8bf28eb 29198 }
Marko Mikulicic 0:c0ecb8bf28eb 29199 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29200
Marko Mikulicic 0:c0ecb8bf28eb 29201 static const char js_function_Object[] =
Marko Mikulicic 0:c0ecb8bf28eb 29202 "function Object(v) {"
Marko Mikulicic 0:c0ecb8bf28eb 29203 "if (typeof v === 'boolean') return new Boolean(v);"
Marko Mikulicic 0:c0ecb8bf28eb 29204 "if (typeof v === 'number') return new Number(v);"
Marko Mikulicic 0:c0ecb8bf28eb 29205 "if (typeof v === 'string') return new String(v);"
Marko Mikulicic 0:c0ecb8bf28eb 29206 "if (typeof v === 'date') return new Date(v);"
Marko Mikulicic 0:c0ecb8bf28eb 29207 "}";
Marko Mikulicic 0:c0ecb8bf28eb 29208
Marko Mikulicic 0:c0ecb8bf28eb 29209 V7_PRIVATE void init_object(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 29210 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29211 val_t object, v;
Marko Mikulicic 0:c0ecb8bf28eb 29212 /* TODO(mkm): initialize global object without requiring a parser */
Marko Mikulicic 0:c0ecb8bf28eb 29213 rcode = v7_exec(v7, js_function_Object, &v);
Marko Mikulicic 0:c0ecb8bf28eb 29214 assert(rcode == V7_OK);
Marko Mikulicic 0:c0ecb8bf28eb 29215 #if defined(NDEBUG)
Marko Mikulicic 0:c0ecb8bf28eb 29216 (void) rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29217 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29218
Marko Mikulicic 0:c0ecb8bf28eb 29219 object = v7_get(v7, v7->vals.global_object, "Object", 6);
Marko Mikulicic 0:c0ecb8bf28eb 29220 v7_set(v7, object, "prototype", 9, v7->vals.object_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 29221 v7_def(v7, v7->vals.object_prototype, "constructor", 11,
Marko Mikulicic 0:c0ecb8bf28eb 29222 V7_DESC_ENUMERABLE(0), object);
Marko Mikulicic 0:c0ecb8bf28eb 29223
Marko Mikulicic 0:c0ecb8bf28eb 29224 set_method(v7, v7->vals.object_prototype, "toString", Obj_toString, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29225 #if V7_ENABLE__Object__getPrototypeOf
Marko Mikulicic 0:c0ecb8bf28eb 29226 set_cfunc_prop(v7, object, "getPrototypeOf", Obj_getPrototypeOf);
Marko Mikulicic 0:c0ecb8bf28eb 29227 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29228 #if V7_ENABLE__Object__getOwnPropertyDescriptor
Marko Mikulicic 0:c0ecb8bf28eb 29229 set_cfunc_prop(v7, object, "getOwnPropertyDescriptor",
Marko Mikulicic 0:c0ecb8bf28eb 29230 Obj_getOwnPropertyDescriptor);
Marko Mikulicic 0:c0ecb8bf28eb 29231 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29232
Marko Mikulicic 0:c0ecb8bf28eb 29233 /* defineProperty is currently required to perform stdlib initialization */
Marko Mikulicic 0:c0ecb8bf28eb 29234 set_method(v7, object, "defineProperty", Obj_defineProperty, 3);
Marko Mikulicic 0:c0ecb8bf28eb 29235
Marko Mikulicic 0:c0ecb8bf28eb 29236 #if V7_ENABLE__Object__defineProperties
Marko Mikulicic 0:c0ecb8bf28eb 29237 set_cfunc_prop(v7, object, "defineProperties", Obj_defineProperties);
Marko Mikulicic 0:c0ecb8bf28eb 29238 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29239 #if V7_ENABLE__Object__create
Marko Mikulicic 0:c0ecb8bf28eb 29240 set_cfunc_prop(v7, object, "create", Obj_create);
Marko Mikulicic 0:c0ecb8bf28eb 29241 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29242 #if V7_ENABLE__Object__keys
Marko Mikulicic 0:c0ecb8bf28eb 29243 set_cfunc_prop(v7, object, "keys", Obj_keys);
Marko Mikulicic 0:c0ecb8bf28eb 29244 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29245 #if V7_ENABLE__Object__getOwnPropertyNames
Marko Mikulicic 0:c0ecb8bf28eb 29246 set_cfunc_prop(v7, object, "getOwnPropertyNames", Obj_getOwnPropertyNames);
Marko Mikulicic 0:c0ecb8bf28eb 29247 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29248 #if V7_ENABLE__Object__preventExtensions
Marko Mikulicic 0:c0ecb8bf28eb 29249 set_method(v7, object, "preventExtensions", Obj_preventExtensions, 1);
Marko Mikulicic 0:c0ecb8bf28eb 29250 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29251 #if V7_ENABLE__Object__isExtensible
Marko Mikulicic 0:c0ecb8bf28eb 29252 set_method(v7, object, "isExtensible", Obj_isExtensible, 1);
Marko Mikulicic 0:c0ecb8bf28eb 29253 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29254 #if V7_ENABLE__Object__isSealed
Marko Mikulicic 0:c0ecb8bf28eb 29255 set_method(v7, object, "isSealed", Obj_isSealed, 1);
Marko Mikulicic 0:c0ecb8bf28eb 29256 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29257 #if V7_ENABLE__Object__isFrozen
Marko Mikulicic 0:c0ecb8bf28eb 29258 set_method(v7, object, "isFrozen", Obj_isFrozen, 1);
Marko Mikulicic 0:c0ecb8bf28eb 29259 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29260
Marko Mikulicic 0:c0ecb8bf28eb 29261 #if V7_ENABLE__Object__propertyIsEnumerable
Marko Mikulicic 0:c0ecb8bf28eb 29262 set_cfunc_prop(v7, v7->vals.object_prototype, "propertyIsEnumerable",
Marko Mikulicic 0:c0ecb8bf28eb 29263 Obj_propertyIsEnumerable);
Marko Mikulicic 0:c0ecb8bf28eb 29264 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29265 #if V7_ENABLE__Object__hasOwnProperty
Marko Mikulicic 0:c0ecb8bf28eb 29266 set_cfunc_prop(v7, v7->vals.object_prototype, "hasOwnProperty",
Marko Mikulicic 0:c0ecb8bf28eb 29267 Obj_hasOwnProperty);
Marko Mikulicic 0:c0ecb8bf28eb 29268 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29269 #if V7_ENABLE__Object__isPrototypeOf
Marko Mikulicic 0:c0ecb8bf28eb 29270 set_cfunc_prop(v7, v7->vals.object_prototype, "isPrototypeOf",
Marko Mikulicic 0:c0ecb8bf28eb 29271 Obj_isPrototypeOf);
Marko Mikulicic 0:c0ecb8bf28eb 29272 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29273 set_cfunc_prop(v7, v7->vals.object_prototype, "valueOf", Obj_valueOf);
Marko Mikulicic 0:c0ecb8bf28eb 29274 }
Marko Mikulicic 0:c0ecb8bf28eb 29275 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 29276 #line 1 "v7/src/std_error.c"
Marko Mikulicic 0:c0ecb8bf28eb 29277 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29278 /*
Marko Mikulicic 0:c0ecb8bf28eb 29279 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 29280 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 29281 */
Marko Mikulicic 0:c0ecb8bf28eb 29282
Marko Mikulicic 0:c0ecb8bf28eb 29283 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29284 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29285 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29286 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29287 /* Amalgamated: #include "v7/src/std_error.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29288 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29289 /* Amalgamated: #include "v7/src/bcode.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29290 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29291 /* Amalgamated: #include "v7/src/util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29292
Marko Mikulicic 0:c0ecb8bf28eb 29293 /*
Marko Mikulicic 0:c0ecb8bf28eb 29294 * TODO(dfrank): make the top of v7->call_frame to represent the current
Marko Mikulicic 0:c0ecb8bf28eb 29295 * frame, and thus get rid of the `CUR_LINENO()`
Marko Mikulicic 0:c0ecb8bf28eb 29296 */
Marko Mikulicic 0:c0ecb8bf28eb 29297 #ifndef V7_DISABLE_LINE_NUMBERS
Marko Mikulicic 0:c0ecb8bf28eb 29298 #define CALLFRAME_LINENO(call_frame) ((call_frame)->line_no)
Marko Mikulicic 0:c0ecb8bf28eb 29299 #define CUR_LINENO() (v7->line_no)
Marko Mikulicic 0:c0ecb8bf28eb 29300 #else
Marko Mikulicic 0:c0ecb8bf28eb 29301 #define CALLFRAME_LINENO(call_frame) 0
Marko Mikulicic 0:c0ecb8bf28eb 29302 #define CUR_LINENO() 0
Marko Mikulicic 0:c0ecb8bf28eb 29303 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29304
Marko Mikulicic 0:c0ecb8bf28eb 29305 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29306 V7_PRIVATE enum v7_err Error_ctor(struct v7 *v7, v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 29307
Marko Mikulicic 0:c0ecb8bf28eb 29308 #if !defined(V7_DISABLE_FILENAMES) && !defined(V7_DISABLE_LINE_NUMBERS)
Marko Mikulicic 0:c0ecb8bf28eb 29309 static int printf_stack_line(char *p, size_t len, struct bcode *bcode,
Marko Mikulicic 0:c0ecb8bf28eb 29310 int line_no, const char *leading) {
Marko Mikulicic 0:c0ecb8bf28eb 29311 int ret;
Marko Mikulicic 0:c0ecb8bf28eb 29312 const char *fn = bcode_get_filename(bcode);
Marko Mikulicic 0:c0ecb8bf28eb 29313 if (fn == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 29314 fn = "<no filename>";
Marko Mikulicic 0:c0ecb8bf28eb 29315 }
Marko Mikulicic 0:c0ecb8bf28eb 29316
Marko Mikulicic 0:c0ecb8bf28eb 29317 if (bcode->func_name_present) {
Marko Mikulicic 0:c0ecb8bf28eb 29318 /* this is a function's bcode: let's show the function's name as well */
Marko Mikulicic 0:c0ecb8bf28eb 29319 char *funcname;
Marko Mikulicic 0:c0ecb8bf28eb 29320
Marko Mikulicic 0:c0ecb8bf28eb 29321 /*
Marko Mikulicic 0:c0ecb8bf28eb 29322 * read first name from the bcode ops, which is the function name,
Marko Mikulicic 0:c0ecb8bf28eb 29323 * since `func_name_present` is set
Marko Mikulicic 0:c0ecb8bf28eb 29324 */
Marko Mikulicic 0:c0ecb8bf28eb 29325 bcode_next_name(bcode->ops.p, &funcname, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 29326
Marko Mikulicic 0:c0ecb8bf28eb 29327 /* Check if it's an anonymous function */
Marko Mikulicic 0:c0ecb8bf28eb 29328 if (funcname[0] == '\0') {
Marko Mikulicic 0:c0ecb8bf28eb 29329 funcname = (char *) "<anonymous>";
Marko Mikulicic 0:c0ecb8bf28eb 29330 }
Marko Mikulicic 0:c0ecb8bf28eb 29331 ret =
Marko Mikulicic 0:c0ecb8bf28eb 29332 snprintf(p, len, "%s at %s (%s:%d)", leading, funcname, fn, line_no);
Marko Mikulicic 0:c0ecb8bf28eb 29333 } else {
Marko Mikulicic 0:c0ecb8bf28eb 29334 /* it's a file's bcode: show only filename and line number */
Marko Mikulicic 0:c0ecb8bf28eb 29335 ret = snprintf(p, len, "%s at %s:%d", leading, fn, line_no);
Marko Mikulicic 0:c0ecb8bf28eb 29336 }
Marko Mikulicic 0:c0ecb8bf28eb 29337 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 29338 }
Marko Mikulicic 0:c0ecb8bf28eb 29339
Marko Mikulicic 0:c0ecb8bf28eb 29340 static int printf_stack_line_cfunc(char *p, size_t len, v7_cfunction_t *cfunc,
Marko Mikulicic 0:c0ecb8bf28eb 29341 const char *leading) {
Marko Mikulicic 0:c0ecb8bf28eb 29342 int ret = 0;
Marko Mikulicic 0:c0ecb8bf28eb 29343
Marko Mikulicic 0:c0ecb8bf28eb 29344 #if !defined(V7_FILENAMES_SUPPRESS_CFUNC_ADDR)
Marko Mikulicic 0:c0ecb8bf28eb 29345 int name_len =
Marko Mikulicic 0:c0ecb8bf28eb 29346 snprintf(NULL, 0, "cfunc_%p", (void *) cfunc) + 1 /*null-term*/;
Marko Mikulicic 0:c0ecb8bf28eb 29347 char *buf = (char *) malloc(name_len);
Marko Mikulicic 0:c0ecb8bf28eb 29348
Marko Mikulicic 0:c0ecb8bf28eb 29349 snprintf(buf, name_len, "cfunc_%p", (void *) cfunc);
Marko Mikulicic 0:c0ecb8bf28eb 29350 #else
Marko Mikulicic 0:c0ecb8bf28eb 29351 /*
Marko Mikulicic 0:c0ecb8bf28eb 29352 * We need this mode only for ecma test reporting, so that the
Marko Mikulicic 0:c0ecb8bf28eb 29353 * report is not different from one run to another
Marko Mikulicic 0:c0ecb8bf28eb 29354 */
Marko Mikulicic 0:c0ecb8bf28eb 29355 char *buf = (char *) "cfunc";
Marko Mikulicic 0:c0ecb8bf28eb 29356 (void) cfunc;
Marko Mikulicic 0:c0ecb8bf28eb 29357 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29358
Marko Mikulicic 0:c0ecb8bf28eb 29359 ret = snprintf(p, len, "%s at %s", leading, buf);
Marko Mikulicic 0:c0ecb8bf28eb 29360
Marko Mikulicic 0:c0ecb8bf28eb 29361 #if !defined(V7_FILENAMES_SUPPRESS_CFUNC_ADDR)
Marko Mikulicic 0:c0ecb8bf28eb 29362 free(buf);
Marko Mikulicic 0:c0ecb8bf28eb 29363 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29364
Marko Mikulicic 0:c0ecb8bf28eb 29365 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 29366 }
Marko Mikulicic 0:c0ecb8bf28eb 29367
Marko Mikulicic 0:c0ecb8bf28eb 29368 static int print_stack_trace(char *p, size_t len,
Marko Mikulicic 0:c0ecb8bf28eb 29369 struct v7_call_frame_base *call_frame) {
Marko Mikulicic 0:c0ecb8bf28eb 29370 char *p_cur = p;
Marko Mikulicic 0:c0ecb8bf28eb 29371 int total_len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 29372
Marko Mikulicic 0:c0ecb8bf28eb 29373 assert(call_frame->type_mask == V7_CALL_FRAME_MASK_CFUNC &&
Marko Mikulicic 0:c0ecb8bf28eb 29374 ((struct v7_call_frame_cfunc *) call_frame)->cfunc == Error_ctor);
Marko Mikulicic 0:c0ecb8bf28eb 29375 call_frame = call_frame->prev;
Marko Mikulicic 0:c0ecb8bf28eb 29376
Marko Mikulicic 0:c0ecb8bf28eb 29377 while (call_frame != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 29378 int cur_len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 29379 const char *leading = (total_len ? "\n" : "");
Marko Mikulicic 0:c0ecb8bf28eb 29380 size_t line_len = len - (p_cur - p);
Marko Mikulicic 0:c0ecb8bf28eb 29381
Marko Mikulicic 0:c0ecb8bf28eb 29382 if (call_frame->type_mask & V7_CALL_FRAME_MASK_BCODE) {
Marko Mikulicic 0:c0ecb8bf28eb 29383 struct bcode *bcode = ((struct v7_call_frame_bcode *) call_frame)->bcode;
Marko Mikulicic 0:c0ecb8bf28eb 29384 if (bcode != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 29385 cur_len = printf_stack_line(p_cur, line_len, bcode,
Marko Mikulicic 0:c0ecb8bf28eb 29386 CALLFRAME_LINENO(call_frame), leading);
Marko Mikulicic 0:c0ecb8bf28eb 29387 }
Marko Mikulicic 0:c0ecb8bf28eb 29388 } else if (call_frame->type_mask & V7_CALL_FRAME_MASK_CFUNC) {
Marko Mikulicic 0:c0ecb8bf28eb 29389 cur_len = printf_stack_line_cfunc(
Marko Mikulicic 0:c0ecb8bf28eb 29390 p_cur, line_len, ((struct v7_call_frame_cfunc *) call_frame)->cfunc,
Marko Mikulicic 0:c0ecb8bf28eb 29391 leading);
Marko Mikulicic 0:c0ecb8bf28eb 29392 }
Marko Mikulicic 0:c0ecb8bf28eb 29393
Marko Mikulicic 0:c0ecb8bf28eb 29394 total_len += cur_len;
Marko Mikulicic 0:c0ecb8bf28eb 29395 if (p_cur != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 29396 p_cur += cur_len;
Marko Mikulicic 0:c0ecb8bf28eb 29397 }
Marko Mikulicic 0:c0ecb8bf28eb 29398
Marko Mikulicic 0:c0ecb8bf28eb 29399 call_frame = call_frame->prev;
Marko Mikulicic 0:c0ecb8bf28eb 29400
Marko Mikulicic 0:c0ecb8bf28eb 29401 #if !(V7_ENABLE__StackTrace)
Marko Mikulicic 0:c0ecb8bf28eb 29402 break;
Marko Mikulicic 0:c0ecb8bf28eb 29403 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29404 }
Marko Mikulicic 0:c0ecb8bf28eb 29405
Marko Mikulicic 0:c0ecb8bf28eb 29406 return total_len;
Marko Mikulicic 0:c0ecb8bf28eb 29407 }
Marko Mikulicic 0:c0ecb8bf28eb 29408 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29409
Marko Mikulicic 0:c0ecb8bf28eb 29410 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29411 V7_PRIVATE enum v7_err Error_ctor(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29412 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29413 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29414 val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29415
Marko Mikulicic 0:c0ecb8bf28eb 29416 if (v7_is_object(this_obj) && this_obj != v7->vals.global_object) {
Marko Mikulicic 0:c0ecb8bf28eb 29417 *res = this_obj;
Marko Mikulicic 0:c0ecb8bf28eb 29418 } else {
Marko Mikulicic 0:c0ecb8bf28eb 29419 *res = mk_object(v7, v7->vals.error_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 29420 }
Marko Mikulicic 0:c0ecb8bf28eb 29421 /* TODO(mkm): set non enumerable but provide toString method */
Marko Mikulicic 0:c0ecb8bf28eb 29422 v7_set(v7, *res, "message", 7, arg0);
Marko Mikulicic 0:c0ecb8bf28eb 29423
Marko Mikulicic 0:c0ecb8bf28eb 29424 #if !defined(V7_DISABLE_FILENAMES) && !defined(V7_DISABLE_LINE_NUMBERS)
Marko Mikulicic 0:c0ecb8bf28eb 29425 /* Save the stack trace */
Marko Mikulicic 0:c0ecb8bf28eb 29426 {
Marko Mikulicic 0:c0ecb8bf28eb 29427 size_t len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 29428 val_t st_v = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 29429
Marko Mikulicic 0:c0ecb8bf28eb 29430 v7_own(v7, &st_v);
Marko Mikulicic 0:c0ecb8bf28eb 29431
Marko Mikulicic 0:c0ecb8bf28eb 29432 len = print_stack_trace(NULL, 0, v7->call_stack);
Marko Mikulicic 0:c0ecb8bf28eb 29433
Marko Mikulicic 0:c0ecb8bf28eb 29434 if (len > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 29435 /* Now, create a placeholder for string */
Marko Mikulicic 0:c0ecb8bf28eb 29436 st_v = v7_mk_string(v7, NULL, len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 29437 len += 1 /*null-term*/;
Marko Mikulicic 0:c0ecb8bf28eb 29438
Marko Mikulicic 0:c0ecb8bf28eb 29439 /* And fill it with actual data */
Marko Mikulicic 0:c0ecb8bf28eb 29440 print_stack_trace((char *) v7_get_string(v7, &st_v, NULL), len,
Marko Mikulicic 0:c0ecb8bf28eb 29441 v7->call_stack);
Marko Mikulicic 0:c0ecb8bf28eb 29442
Marko Mikulicic 0:c0ecb8bf28eb 29443 v7_set(v7, *res, "stack", ~0, st_v);
Marko Mikulicic 0:c0ecb8bf28eb 29444 }
Marko Mikulicic 0:c0ecb8bf28eb 29445
Marko Mikulicic 0:c0ecb8bf28eb 29446 v7_disown(v7, &st_v);
Marko Mikulicic 0:c0ecb8bf28eb 29447 }
Marko Mikulicic 0:c0ecb8bf28eb 29448 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29449
Marko Mikulicic 0:c0ecb8bf28eb 29450 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29451 }
Marko Mikulicic 0:c0ecb8bf28eb 29452
Marko Mikulicic 0:c0ecb8bf28eb 29453 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29454 V7_PRIVATE enum v7_err Error_toString(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29455 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29456 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29457 val_t prefix, msg = v7_get(v7, this_obj, "message", ~0);
Marko Mikulicic 0:c0ecb8bf28eb 29458
Marko Mikulicic 0:c0ecb8bf28eb 29459 if (!v7_is_string(msg)) {
Marko Mikulicic 0:c0ecb8bf28eb 29460 *res = v7_mk_string(v7, "Error", ~0, 1);
Marko Mikulicic 0:c0ecb8bf28eb 29461 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29462 }
Marko Mikulicic 0:c0ecb8bf28eb 29463
Marko Mikulicic 0:c0ecb8bf28eb 29464 prefix = v7_mk_string(v7, "Error: ", ~0, 1);
Marko Mikulicic 0:c0ecb8bf28eb 29465 *res = s_concat(v7, prefix, msg);
Marko Mikulicic 0:c0ecb8bf28eb 29466 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29467
Marko Mikulicic 0:c0ecb8bf28eb 29468 clean:
Marko Mikulicic 0:c0ecb8bf28eb 29469 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29470 }
Marko Mikulicic 0:c0ecb8bf28eb 29471
Marko Mikulicic 0:c0ecb8bf28eb 29472 static const char *const error_names[] = {TYPE_ERROR, SYNTAX_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 29473 REFERENCE_ERROR, INTERNAL_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 29474 RANGE_ERROR, EVAL_ERROR};
Marko Mikulicic 0:c0ecb8bf28eb 29475
Marko Mikulicic 0:c0ecb8bf28eb 29476 V7_STATIC_ASSERT(ARRAY_SIZE(error_names) == ERROR_CTOR_MAX,
Marko Mikulicic 0:c0ecb8bf28eb 29477 error_name_count_mismatch);
Marko Mikulicic 0:c0ecb8bf28eb 29478
Marko Mikulicic 0:c0ecb8bf28eb 29479 V7_PRIVATE void init_error(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 29480 val_t error;
Marko Mikulicic 0:c0ecb8bf28eb 29481 size_t i;
Marko Mikulicic 0:c0ecb8bf28eb 29482
Marko Mikulicic 0:c0ecb8bf28eb 29483 error =
Marko Mikulicic 0:c0ecb8bf28eb 29484 mk_cfunction_obj_with_proto(v7, Error_ctor, 1, v7->vals.error_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 29485 v7_def(v7, v7->vals.global_object, "Error", 5, V7_DESC_ENUMERABLE(0), error);
Marko Mikulicic 0:c0ecb8bf28eb 29486 set_method(v7, v7->vals.error_prototype, "toString", Error_toString, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29487
Marko Mikulicic 0:c0ecb8bf28eb 29488 for (i = 0; i < ARRAY_SIZE(error_names); i++) {
Marko Mikulicic 0:c0ecb8bf28eb 29489 error = mk_cfunction_obj_with_proto(
Marko Mikulicic 0:c0ecb8bf28eb 29490 v7, Error_ctor, 1, mk_object(v7, v7->vals.error_prototype));
Marko Mikulicic 0:c0ecb8bf28eb 29491 v7_def(v7, v7->vals.global_object, error_names[i], strlen(error_names[i]),
Marko Mikulicic 0:c0ecb8bf28eb 29492 V7_DESC_ENUMERABLE(0), error);
Marko Mikulicic 0:c0ecb8bf28eb 29493 v7->vals.error_objects[i] = error;
Marko Mikulicic 0:c0ecb8bf28eb 29494 }
Marko Mikulicic 0:c0ecb8bf28eb 29495 }
Marko Mikulicic 0:c0ecb8bf28eb 29496 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 29497 #line 1 "v7/src/std_number.c"
Marko Mikulicic 0:c0ecb8bf28eb 29498 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29499 /*
Marko Mikulicic 0:c0ecb8bf28eb 29500 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 29501 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 29502 */
Marko Mikulicic 0:c0ecb8bf28eb 29503
Marko Mikulicic 0:c0ecb8bf28eb 29504 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29505 /* Amalgamated: #include "v7/src/std_object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29506 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29507 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29508 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29509 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29510 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29511 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29512 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29513
Marko Mikulicic 0:c0ecb8bf28eb 29514 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 29515 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 29516 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 29517
Marko Mikulicic 0:c0ecb8bf28eb 29518 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29519 V7_PRIVATE enum v7_err Number_ctor(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29520 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29521 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29522 val_t arg0 = v7_argc(v7) == 0 ? v7_mk_number(v7, 0.0) : v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29523
Marko Mikulicic 0:c0ecb8bf28eb 29524 if (v7_is_number(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 29525 *res = arg0;
Marko Mikulicic 0:c0ecb8bf28eb 29526 } else {
Marko Mikulicic 0:c0ecb8bf28eb 29527 rcode = to_number_v(v7, arg0, res);
Marko Mikulicic 0:c0ecb8bf28eb 29528 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29529 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29530 }
Marko Mikulicic 0:c0ecb8bf28eb 29531 }
Marko Mikulicic 0:c0ecb8bf28eb 29532
Marko Mikulicic 0:c0ecb8bf28eb 29533 if (v7_is_generic_object(this_obj) && this_obj != v7->vals.global_object) {
Marko Mikulicic 0:c0ecb8bf28eb 29534 obj_prototype_set(v7, get_object_struct(this_obj),
Marko Mikulicic 0:c0ecb8bf28eb 29535 get_object_struct(v7->vals.number_prototype));
Marko Mikulicic 0:c0ecb8bf28eb 29536 v7_def(v7, this_obj, "", 0, _V7_DESC_HIDDEN(1), *res);
Marko Mikulicic 0:c0ecb8bf28eb 29537
Marko Mikulicic 0:c0ecb8bf28eb 29538 /*
Marko Mikulicic 0:c0ecb8bf28eb 29539 * implicitly returning `this`: `call_cfunction()` in bcode.c will do
Marko Mikulicic 0:c0ecb8bf28eb 29540 * that for us
Marko Mikulicic 0:c0ecb8bf28eb 29541 */
Marko Mikulicic 0:c0ecb8bf28eb 29542 }
Marko Mikulicic 0:c0ecb8bf28eb 29543
Marko Mikulicic 0:c0ecb8bf28eb 29544 clean:
Marko Mikulicic 0:c0ecb8bf28eb 29545 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29546 }
Marko Mikulicic 0:c0ecb8bf28eb 29547
Marko Mikulicic 0:c0ecb8bf28eb 29548 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29549 V7_PRIVATE enum v7_err n_to_str(struct v7 *v7, const char *format, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29550 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29551 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29552 val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29553 int len, digits = 0;
Marko Mikulicic 0:c0ecb8bf28eb 29554 char fmt[10], buf[100];
Marko Mikulicic 0:c0ecb8bf28eb 29555
Marko Mikulicic 0:c0ecb8bf28eb 29556 rcode = to_number_v(v7, arg0, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 29557 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29558 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29559 }
Marko Mikulicic 0:c0ecb8bf28eb 29560
Marko Mikulicic 0:c0ecb8bf28eb 29561 if (v7_get_double(v7, arg0) > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 29562 digits = (int) v7_get_double(v7, arg0);
Marko Mikulicic 0:c0ecb8bf28eb 29563 }
Marko Mikulicic 0:c0ecb8bf28eb 29564
Marko Mikulicic 0:c0ecb8bf28eb 29565 /*
Marko Mikulicic 0:c0ecb8bf28eb 29566 * NOTE: we don't own `arg0` and `this_obj`, since this function is called
Marko Mikulicic 0:c0ecb8bf28eb 29567 * from cfunctions only, and GC is inhibited during these calls
Marko Mikulicic 0:c0ecb8bf28eb 29568 */
Marko Mikulicic 0:c0ecb8bf28eb 29569
Marko Mikulicic 0:c0ecb8bf28eb 29570 rcode = obj_value_of(v7, this_obj, &this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 29571 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29572 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29573 }
Marko Mikulicic 0:c0ecb8bf28eb 29574
Marko Mikulicic 0:c0ecb8bf28eb 29575 snprintf(fmt, sizeof(fmt), format, digits);
Marko Mikulicic 0:c0ecb8bf28eb 29576 len = snprintf(buf, sizeof(buf), fmt, v7_get_double(v7, this_obj));
Marko Mikulicic 0:c0ecb8bf28eb 29577
Marko Mikulicic 0:c0ecb8bf28eb 29578 *res = v7_mk_string(v7, buf, len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 29579
Marko Mikulicic 0:c0ecb8bf28eb 29580 clean:
Marko Mikulicic 0:c0ecb8bf28eb 29581 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29582 }
Marko Mikulicic 0:c0ecb8bf28eb 29583
Marko Mikulicic 0:c0ecb8bf28eb 29584 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29585 V7_PRIVATE enum v7_err Number_toFixed(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29586 return n_to_str(v7, "%%.%dlf", res);
Marko Mikulicic 0:c0ecb8bf28eb 29587 }
Marko Mikulicic 0:c0ecb8bf28eb 29588
Marko Mikulicic 0:c0ecb8bf28eb 29589 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29590 V7_PRIVATE enum v7_err Number_toExp(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29591 return n_to_str(v7, "%%.%de", res);
Marko Mikulicic 0:c0ecb8bf28eb 29592 }
Marko Mikulicic 0:c0ecb8bf28eb 29593
Marko Mikulicic 0:c0ecb8bf28eb 29594 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29595 V7_PRIVATE enum v7_err Number_toPrecision(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29596 return Number_toExp(v7, res);
Marko Mikulicic 0:c0ecb8bf28eb 29597 }
Marko Mikulicic 0:c0ecb8bf28eb 29598
Marko Mikulicic 0:c0ecb8bf28eb 29599 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29600 V7_PRIVATE enum v7_err Number_valueOf(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29601 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29602 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29603
Marko Mikulicic 0:c0ecb8bf28eb 29604 if (!v7_is_number(this_obj) &&
Marko Mikulicic 0:c0ecb8bf28eb 29605 (v7_is_object(this_obj) &&
Marko Mikulicic 0:c0ecb8bf28eb 29606 v7_get_proto(v7, this_obj) != v7->vals.number_prototype)) {
Marko Mikulicic 0:c0ecb8bf28eb 29607 rcode =
Marko Mikulicic 0:c0ecb8bf28eb 29608 v7_throwf(v7, TYPE_ERROR, "Number.valueOf called on non-number object");
Marko Mikulicic 0:c0ecb8bf28eb 29609 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29610 }
Marko Mikulicic 0:c0ecb8bf28eb 29611
Marko Mikulicic 0:c0ecb8bf28eb 29612 rcode = Obj_valueOf(v7, res);
Marko Mikulicic 0:c0ecb8bf28eb 29613 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29614 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29615 }
Marko Mikulicic 0:c0ecb8bf28eb 29616
Marko Mikulicic 0:c0ecb8bf28eb 29617 clean:
Marko Mikulicic 0:c0ecb8bf28eb 29618 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29619 }
Marko Mikulicic 0:c0ecb8bf28eb 29620
Marko Mikulicic 0:c0ecb8bf28eb 29621 /*
Marko Mikulicic 0:c0ecb8bf28eb 29622 * Converts a 64 bit signed integer into a string of a given base.
Marko Mikulicic 0:c0ecb8bf28eb 29623 * Requires space for 65 bytes (64 bit + null terminator) in the result buffer
Marko Mikulicic 0:c0ecb8bf28eb 29624 */
Marko Mikulicic 0:c0ecb8bf28eb 29625 static char *cs_itoa(int64_t value, char *result, int base) {
Marko Mikulicic 0:c0ecb8bf28eb 29626 char *ptr = result, *ptr1 = result, tmp_char;
Marko Mikulicic 0:c0ecb8bf28eb 29627 int64_t tmp_value;
Marko Mikulicic 0:c0ecb8bf28eb 29628 int64_t sign = value < 0 ? -1 : 1;
Marko Mikulicic 0:c0ecb8bf28eb 29629 const char *base36 = "0123456789abcdefghijklmnopqrstuvwxyz";
Marko Mikulicic 0:c0ecb8bf28eb 29630
Marko Mikulicic 0:c0ecb8bf28eb 29631 if (base < 2 || base > 36) {
Marko Mikulicic 0:c0ecb8bf28eb 29632 *result = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 29633 return result;
Marko Mikulicic 0:c0ecb8bf28eb 29634 }
Marko Mikulicic 0:c0ecb8bf28eb 29635
Marko Mikulicic 0:c0ecb8bf28eb 29636 /* let's think positive */
Marko Mikulicic 0:c0ecb8bf28eb 29637 value = value * sign;
Marko Mikulicic 0:c0ecb8bf28eb 29638 do {
Marko Mikulicic 0:c0ecb8bf28eb 29639 tmp_value = value;
Marko Mikulicic 0:c0ecb8bf28eb 29640 value /= base;
Marko Mikulicic 0:c0ecb8bf28eb 29641 *ptr++ = base36[tmp_value - value * base];
Marko Mikulicic 0:c0ecb8bf28eb 29642 } while (value);
Marko Mikulicic 0:c0ecb8bf28eb 29643
Marko Mikulicic 0:c0ecb8bf28eb 29644 /* sign */
Marko Mikulicic 0:c0ecb8bf28eb 29645 if (sign < 0) *ptr++ = '-';
Marko Mikulicic 0:c0ecb8bf28eb 29646 *ptr-- = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 29647 while (ptr1 < ptr) {
Marko Mikulicic 0:c0ecb8bf28eb 29648 tmp_char = *ptr;
Marko Mikulicic 0:c0ecb8bf28eb 29649 *ptr-- = *ptr1;
Marko Mikulicic 0:c0ecb8bf28eb 29650 *ptr1++ = tmp_char;
Marko Mikulicic 0:c0ecb8bf28eb 29651 }
Marko Mikulicic 0:c0ecb8bf28eb 29652 return result;
Marko Mikulicic 0:c0ecb8bf28eb 29653 }
Marko Mikulicic 0:c0ecb8bf28eb 29654
Marko Mikulicic 0:c0ecb8bf28eb 29655 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29656 V7_PRIVATE enum v7_err Number_toString(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29657 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29658 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29659 val_t radixv = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29660 char buf[65];
Marko Mikulicic 0:c0ecb8bf28eb 29661 double d, radix;
Marko Mikulicic 0:c0ecb8bf28eb 29662
Marko Mikulicic 0:c0ecb8bf28eb 29663 if (this_obj == v7->vals.number_prototype) {
Marko Mikulicic 0:c0ecb8bf28eb 29664 *res = v7_mk_string(v7, "0", 1, 1);
Marko Mikulicic 0:c0ecb8bf28eb 29665 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29666 }
Marko Mikulicic 0:c0ecb8bf28eb 29667
Marko Mikulicic 0:c0ecb8bf28eb 29668 /* Make sure this function was called on Number instance */
Marko Mikulicic 0:c0ecb8bf28eb 29669 if (!v7_is_number(this_obj) &&
Marko Mikulicic 0:c0ecb8bf28eb 29670 !(v7_is_generic_object(this_obj) &&
Marko Mikulicic 0:c0ecb8bf28eb 29671 is_prototype_of(v7, this_obj, v7->vals.number_prototype))) {
Marko Mikulicic 0:c0ecb8bf28eb 29672 rcode = v7_throwf(v7, TYPE_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 29673 "Number.toString called on non-number object");
Marko Mikulicic 0:c0ecb8bf28eb 29674 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29675 }
Marko Mikulicic 0:c0ecb8bf28eb 29676
Marko Mikulicic 0:c0ecb8bf28eb 29677 /* Get number primitive */
Marko Mikulicic 0:c0ecb8bf28eb 29678 rcode = to_number_v(v7, this_obj, &this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 29679 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29680 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29681 }
Marko Mikulicic 0:c0ecb8bf28eb 29682
Marko Mikulicic 0:c0ecb8bf28eb 29683 /* Get radix if provided, or 10 otherwise */
Marko Mikulicic 0:c0ecb8bf28eb 29684 if (!v7_is_undefined(radixv)) {
Marko Mikulicic 0:c0ecb8bf28eb 29685 rcode = to_number_v(v7, radixv, &radixv);
Marko Mikulicic 0:c0ecb8bf28eb 29686 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29687 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29688 }
Marko Mikulicic 0:c0ecb8bf28eb 29689 radix = v7_get_double(v7, radixv);
Marko Mikulicic 0:c0ecb8bf28eb 29690 } else {
Marko Mikulicic 0:c0ecb8bf28eb 29691 radix = 10.0;
Marko Mikulicic 0:c0ecb8bf28eb 29692 }
Marko Mikulicic 0:c0ecb8bf28eb 29693
Marko Mikulicic 0:c0ecb8bf28eb 29694 d = v7_get_double(v7, this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 29695 if (!isnan(d) && (int64_t) d == d && radix >= 2) {
Marko Mikulicic 0:c0ecb8bf28eb 29696 cs_itoa(d, buf, radix);
Marko Mikulicic 0:c0ecb8bf28eb 29697 *res = v7_mk_string(v7, buf, strlen(buf), 1);
Marko Mikulicic 0:c0ecb8bf28eb 29698 } else {
Marko Mikulicic 0:c0ecb8bf28eb 29699 rcode = to_string(v7, this_obj, res, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 29700 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29701 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29702 }
Marko Mikulicic 0:c0ecb8bf28eb 29703 }
Marko Mikulicic 0:c0ecb8bf28eb 29704
Marko Mikulicic 0:c0ecb8bf28eb 29705 clean:
Marko Mikulicic 0:c0ecb8bf28eb 29706 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29707 }
Marko Mikulicic 0:c0ecb8bf28eb 29708
Marko Mikulicic 0:c0ecb8bf28eb 29709 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29710 V7_PRIVATE enum v7_err n_isNaN(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29711 val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29712 *res = v7_mk_boolean(v7, !v7_is_number(arg0) || arg0 == V7_TAG_NAN);
Marko Mikulicic 0:c0ecb8bf28eb 29713 return V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29714 }
Marko Mikulicic 0:c0ecb8bf28eb 29715
Marko Mikulicic 0:c0ecb8bf28eb 29716 V7_PRIVATE void init_number(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 29717 v7_prop_attr_desc_t attrs_desc =
Marko Mikulicic 0:c0ecb8bf28eb 29718 (V7_DESC_WRITABLE(0) | V7_DESC_ENUMERABLE(0) | V7_DESC_CONFIGURABLE(0));
Marko Mikulicic 0:c0ecb8bf28eb 29719 val_t num = mk_cfunction_obj_with_proto(v7, Number_ctor, 1,
Marko Mikulicic 0:c0ecb8bf28eb 29720 v7->vals.number_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 29721
Marko Mikulicic 0:c0ecb8bf28eb 29722 v7_def(v7, v7->vals.global_object, "Number", 6, V7_DESC_ENUMERABLE(0), num);
Marko Mikulicic 0:c0ecb8bf28eb 29723
Marko Mikulicic 0:c0ecb8bf28eb 29724 set_cfunc_prop(v7, v7->vals.number_prototype, "toFixed", Number_toFixed);
Marko Mikulicic 0:c0ecb8bf28eb 29725 set_cfunc_prop(v7, v7->vals.number_prototype, "toPrecision",
Marko Mikulicic 0:c0ecb8bf28eb 29726 Number_toPrecision);
Marko Mikulicic 0:c0ecb8bf28eb 29727 set_cfunc_prop(v7, v7->vals.number_prototype, "toExponential", Number_toExp);
Marko Mikulicic 0:c0ecb8bf28eb 29728 set_cfunc_prop(v7, v7->vals.number_prototype, "valueOf", Number_valueOf);
Marko Mikulicic 0:c0ecb8bf28eb 29729 set_cfunc_prop(v7, v7->vals.number_prototype, "toString", Number_toString);
Marko Mikulicic 0:c0ecb8bf28eb 29730
Marko Mikulicic 0:c0ecb8bf28eb 29731 v7_def(v7, num, "MAX_VALUE", 9, attrs_desc,
Marko Mikulicic 0:c0ecb8bf28eb 29732 v7_mk_number(v7, 1.7976931348623157e+308));
Marko Mikulicic 0:c0ecb8bf28eb 29733 v7_def(v7, num, "MIN_VALUE", 9, attrs_desc, v7_mk_number(v7, 5e-324));
Marko Mikulicic 0:c0ecb8bf28eb 29734 #if V7_ENABLE__NUMBER__NEGATIVE_INFINITY
Marko Mikulicic 0:c0ecb8bf28eb 29735 v7_def(v7, num, "NEGATIVE_INFINITY", 17, attrs_desc,
Marko Mikulicic 0:c0ecb8bf28eb 29736 v7_mk_number(v7, -INFINITY));
Marko Mikulicic 0:c0ecb8bf28eb 29737 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29738 #if V7_ENABLE__NUMBER__POSITIVE_INFINITY
Marko Mikulicic 0:c0ecb8bf28eb 29739 v7_def(v7, num, "POSITIVE_INFINITY", 17, attrs_desc,
Marko Mikulicic 0:c0ecb8bf28eb 29740 v7_mk_number(v7, INFINITY));
Marko Mikulicic 0:c0ecb8bf28eb 29741 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29742 v7_def(v7, num, "NaN", 3, attrs_desc, V7_TAG_NAN);
Marko Mikulicic 0:c0ecb8bf28eb 29743
Marko Mikulicic 0:c0ecb8bf28eb 29744 v7_def(v7, v7->vals.global_object, "NaN", 3, attrs_desc, V7_TAG_NAN);
Marko Mikulicic 0:c0ecb8bf28eb 29745 v7_def(v7, v7->vals.global_object, "isNaN", 5, V7_DESC_ENUMERABLE(0),
Marko Mikulicic 0:c0ecb8bf28eb 29746 v7_mk_cfunction(n_isNaN));
Marko Mikulicic 0:c0ecb8bf28eb 29747 }
Marko Mikulicic 0:c0ecb8bf28eb 29748
Marko Mikulicic 0:c0ecb8bf28eb 29749 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 29750 }
Marko Mikulicic 0:c0ecb8bf28eb 29751 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 29752 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 29753 #line 1 "v7/src/std_json.c"
Marko Mikulicic 0:c0ecb8bf28eb 29754 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29755 /*
Marko Mikulicic 0:c0ecb8bf28eb 29756 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 29757 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 29758 */
Marko Mikulicic 0:c0ecb8bf28eb 29759
Marko Mikulicic 0:c0ecb8bf28eb 29760 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29761 /* Amalgamated: #include "v7/src/stdlib.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29762 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29763 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29764 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29765 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29766 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29767
Marko Mikulicic 0:c0ecb8bf28eb 29768 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 29769 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 29770 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 29771
Marko Mikulicic 0:c0ecb8bf28eb 29772 #if defined(V7_ALT_JSON_PARSE)
Marko Mikulicic 0:c0ecb8bf28eb 29773 extern enum v7_err v7_alt_json_parse(struct v7 *v7, v7_val_t json_string,
Marko Mikulicic 0:c0ecb8bf28eb 29774 v7_val_t *res);
Marko Mikulicic 0:c0ecb8bf28eb 29775 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29776
Marko Mikulicic 0:c0ecb8bf28eb 29777 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29778 V7_PRIVATE enum v7_err Json_stringify(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29779 val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29780 char buf[100], *p = v7_to_json(v7, arg0, buf, sizeof(buf));
Marko Mikulicic 0:c0ecb8bf28eb 29781 *res = v7_mk_string(v7, p, strlen(p), 1);
Marko Mikulicic 0:c0ecb8bf28eb 29782
Marko Mikulicic 0:c0ecb8bf28eb 29783 if (p != buf) free(p);
Marko Mikulicic 0:c0ecb8bf28eb 29784 return V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29785 }
Marko Mikulicic 0:c0ecb8bf28eb 29786
Marko Mikulicic 0:c0ecb8bf28eb 29787 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29788 V7_PRIVATE enum v7_err Json_parse(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29789 v7_val_t arg = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29790 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29791 #if defined(V7_ALT_JSON_PARSE)
Marko Mikulicic 0:c0ecb8bf28eb 29792 rcode = v7_alt_json_parse(v7, arg, res);
Marko Mikulicic 0:c0ecb8bf28eb 29793 #else
Marko Mikulicic 0:c0ecb8bf28eb 29794 rcode = std_eval(v7, arg, V7_UNDEFINED, 1, res);
Marko Mikulicic 0:c0ecb8bf28eb 29795 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29796 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29797 }
Marko Mikulicic 0:c0ecb8bf28eb 29798
Marko Mikulicic 0:c0ecb8bf28eb 29799 V7_PRIVATE void init_json(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 29800 val_t o = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29801 set_method(v7, o, "stringify", Json_stringify, 1);
Marko Mikulicic 0:c0ecb8bf28eb 29802 set_method(v7, o, "parse", Json_parse, 1);
Marko Mikulicic 0:c0ecb8bf28eb 29803 v7_def(v7, v7->vals.global_object, "JSON", 4, V7_DESC_ENUMERABLE(0), o);
Marko Mikulicic 0:c0ecb8bf28eb 29804 }
Marko Mikulicic 0:c0ecb8bf28eb 29805
Marko Mikulicic 0:c0ecb8bf28eb 29806 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 29807 }
Marko Mikulicic 0:c0ecb8bf28eb 29808 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 29809 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 29810 #line 1 "v7/src/std_array.c"
Marko Mikulicic 0:c0ecb8bf28eb 29811 #endif
Marko Mikulicic 0:c0ecb8bf28eb 29812 /*
Marko Mikulicic 0:c0ecb8bf28eb 29813 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 29814 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 29815 */
Marko Mikulicic 0:c0ecb8bf28eb 29816
Marko Mikulicic 0:c0ecb8bf28eb 29817 /* Amalgamated: #include "common/str_util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29818 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29819 /* Amalgamated: #include "v7/src/gc.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29820 /* Amalgamated: #include "v7/src/eval.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29821 /* Amalgamated: #include "v7/src/std_string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29822 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29823 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29824 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29825 /* Amalgamated: #include "v7/src/array.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29826 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29827 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 29828
Marko Mikulicic 0:c0ecb8bf28eb 29829 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 29830 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 29831 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 29832
Marko Mikulicic 0:c0ecb8bf28eb 29833 struct a_sort_data {
Marko Mikulicic 0:c0ecb8bf28eb 29834 val_t sort_func;
Marko Mikulicic 0:c0ecb8bf28eb 29835 };
Marko Mikulicic 0:c0ecb8bf28eb 29836
Marko Mikulicic 0:c0ecb8bf28eb 29837 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29838 V7_PRIVATE enum v7_err Array_ctor(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29839 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29840 unsigned long i, len;
Marko Mikulicic 0:c0ecb8bf28eb 29841
Marko Mikulicic 0:c0ecb8bf28eb 29842 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 29843 *res = v7_mk_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29844 /*
Marko Mikulicic 0:c0ecb8bf28eb 29845 * The interpreter passes dense array to C functions.
Marko Mikulicic 0:c0ecb8bf28eb 29846 * However dense array implementation is not yet complete
Marko Mikulicic 0:c0ecb8bf28eb 29847 * so we don't want to propagate them at each call to Array()
Marko Mikulicic 0:c0ecb8bf28eb 29848 */
Marko Mikulicic 0:c0ecb8bf28eb 29849 len = v7_argc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29850 for (i = 0; i < len; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 29851 rcode = v7_array_set_throwing(v7, *res, i, v7_arg(v7, i), NULL);
Marko Mikulicic 0:c0ecb8bf28eb 29852 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29853 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29854 }
Marko Mikulicic 0:c0ecb8bf28eb 29855 }
Marko Mikulicic 0:c0ecb8bf28eb 29856
Marko Mikulicic 0:c0ecb8bf28eb 29857 clean:
Marko Mikulicic 0:c0ecb8bf28eb 29858 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29859 }
Marko Mikulicic 0:c0ecb8bf28eb 29860
Marko Mikulicic 0:c0ecb8bf28eb 29861 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29862 V7_PRIVATE enum v7_err Array_push(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29863 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29864 int i, len = v7_argc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29865
Marko Mikulicic 0:c0ecb8bf28eb 29866 *res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 29867
Marko Mikulicic 0:c0ecb8bf28eb 29868 for (i = 0; i < len; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 29869 *res = v7_arg(v7, i);
Marko Mikulicic 0:c0ecb8bf28eb 29870 rcode = v7_array_push_throwing(v7, v7_get_this(v7), *res, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 29871 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29872 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29873 }
Marko Mikulicic 0:c0ecb8bf28eb 29874 }
Marko Mikulicic 0:c0ecb8bf28eb 29875
Marko Mikulicic 0:c0ecb8bf28eb 29876 /*
Marko Mikulicic 0:c0ecb8bf28eb 29877 * TODO(dfrank) : we need to implement `length` as a real property, and here
Marko Mikulicic 0:c0ecb8bf28eb 29878 * we need to set new length and return it (even if the object is not an
Marko Mikulicic 0:c0ecb8bf28eb 29879 * array)
Marko Mikulicic 0:c0ecb8bf28eb 29880 */
Marko Mikulicic 0:c0ecb8bf28eb 29881
Marko Mikulicic 0:c0ecb8bf28eb 29882 clean:
Marko Mikulicic 0:c0ecb8bf28eb 29883 return rcode;
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_get_length(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29888 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29889 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29890 long len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 29891
Marko Mikulicic 0:c0ecb8bf28eb 29892 if (is_prototype_of(v7, this_obj, v7->vals.array_prototype)) {
Marko Mikulicic 0:c0ecb8bf28eb 29893 len = v7_array_length(v7, this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 29894 }
Marko Mikulicic 0:c0ecb8bf28eb 29895 *res = v7_mk_number(v7, len);
Marko Mikulicic 0:c0ecb8bf28eb 29896
Marko Mikulicic 0:c0ecb8bf28eb 29897 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29898 }
Marko Mikulicic 0:c0ecb8bf28eb 29899
Marko Mikulicic 0:c0ecb8bf28eb 29900 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29901 V7_PRIVATE enum v7_err Array_set_length(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29902 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29903 val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 29904 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29905 long new_len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 29906
Marko Mikulicic 0:c0ecb8bf28eb 29907 rcode = to_long(v7, v7_arg(v7, 0), -1, &new_len);
Marko Mikulicic 0:c0ecb8bf28eb 29908 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29909 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29910 }
Marko Mikulicic 0:c0ecb8bf28eb 29911
Marko Mikulicic 0:c0ecb8bf28eb 29912 if (!v7_is_object(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 29913 rcode = v7_throwf(v7, TYPE_ERROR, "Array expected");
Marko Mikulicic 0:c0ecb8bf28eb 29914 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29915 } else if (new_len < 0 ||
Marko Mikulicic 0:c0ecb8bf28eb 29916 (v7_is_number(arg0) && (isnan(v7_get_double(v7, arg0)) ||
Marko Mikulicic 0:c0ecb8bf28eb 29917 isinf(v7_get_double(v7, arg0))))) {
Marko Mikulicic 0:c0ecb8bf28eb 29918 rcode = v7_throwf(v7, RANGE_ERROR, "Invalid array length");
Marko Mikulicic 0:c0ecb8bf28eb 29919 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29920 } else {
Marko Mikulicic 0:c0ecb8bf28eb 29921 struct v7_property **p, **next;
Marko Mikulicic 0:c0ecb8bf28eb 29922 long index, max_index = -1;
Marko Mikulicic 0:c0ecb8bf28eb 29923
Marko Mikulicic 0:c0ecb8bf28eb 29924 /* Remove all items with an index higher than new_len */
Marko Mikulicic 0:c0ecb8bf28eb 29925 for (p = &get_object_struct(this_obj)->properties; *p != NULL; p = next) {
Marko Mikulicic 0:c0ecb8bf28eb 29926 size_t n;
Marko Mikulicic 0:c0ecb8bf28eb 29927 const char *s = v7_get_string(v7, &p[0]->name, &n);
Marko Mikulicic 0:c0ecb8bf28eb 29928 next = &p[0]->next;
Marko Mikulicic 0:c0ecb8bf28eb 29929 index = strtol(s, NULL, 10);
Marko Mikulicic 0:c0ecb8bf28eb 29930 if (index >= new_len) {
Marko Mikulicic 0:c0ecb8bf28eb 29931 v7_destroy_property(p);
Marko Mikulicic 0:c0ecb8bf28eb 29932 *p = *next;
Marko Mikulicic 0:c0ecb8bf28eb 29933 next = p;
Marko Mikulicic 0:c0ecb8bf28eb 29934 } else if (index > max_index) {
Marko Mikulicic 0:c0ecb8bf28eb 29935 max_index = index;
Marko Mikulicic 0:c0ecb8bf28eb 29936 }
Marko Mikulicic 0:c0ecb8bf28eb 29937 }
Marko Mikulicic 0:c0ecb8bf28eb 29938
Marko Mikulicic 0:c0ecb8bf28eb 29939 /* If we have to expand, insert an item with appropriate index */
Marko Mikulicic 0:c0ecb8bf28eb 29940 if (new_len > 0 && max_index < new_len - 1) {
Marko Mikulicic 0:c0ecb8bf28eb 29941 char buf[40];
Marko Mikulicic 0:c0ecb8bf28eb 29942 c_snprintf(buf, sizeof(buf), "%ld", new_len - 1);
Marko Mikulicic 0:c0ecb8bf28eb 29943 v7_set(v7, this_obj, buf, strlen(buf), V7_UNDEFINED);
Marko Mikulicic 0:c0ecb8bf28eb 29944 }
Marko Mikulicic 0:c0ecb8bf28eb 29945 }
Marko Mikulicic 0:c0ecb8bf28eb 29946
Marko Mikulicic 0:c0ecb8bf28eb 29947 *res = v7_mk_number(v7, new_len);
Marko Mikulicic 0:c0ecb8bf28eb 29948
Marko Mikulicic 0:c0ecb8bf28eb 29949 clean:
Marko Mikulicic 0:c0ecb8bf28eb 29950 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29951 }
Marko Mikulicic 0:c0ecb8bf28eb 29952
Marko Mikulicic 0:c0ecb8bf28eb 29953 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29954 static enum v7_err a_cmp(struct v7 *v7, void *user_data, const void *pa,
Marko Mikulicic 0:c0ecb8bf28eb 29955 const void *pb, int *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29956 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29957 struct a_sort_data *sort_data = (struct a_sort_data *) user_data;
Marko Mikulicic 0:c0ecb8bf28eb 29958 val_t a = *(val_t *) pa, b = *(val_t *) pb, func = sort_data->sort_func;
Marko Mikulicic 0:c0ecb8bf28eb 29959
Marko Mikulicic 0:c0ecb8bf28eb 29960 if (v7_is_callable(v7, func)) {
Marko Mikulicic 0:c0ecb8bf28eb 29961 int saved_inhibit_gc = v7->inhibit_gc;
Marko Mikulicic 0:c0ecb8bf28eb 29962 val_t vres = V7_UNDEFINED, args = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 29963 v7_array_push(v7, args, a);
Marko Mikulicic 0:c0ecb8bf28eb 29964 v7_array_push(v7, args, b);
Marko Mikulicic 0:c0ecb8bf28eb 29965 v7->inhibit_gc = 0;
Marko Mikulicic 0:c0ecb8bf28eb 29966 rcode = b_apply(v7, func, V7_UNDEFINED, args, 0, &vres);
Marko Mikulicic 0:c0ecb8bf28eb 29967 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29968 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29969 }
Marko Mikulicic 0:c0ecb8bf28eb 29970 v7->inhibit_gc = saved_inhibit_gc;
Marko Mikulicic 0:c0ecb8bf28eb 29971 *res = (int) -v7_get_double(v7, vres);
Marko Mikulicic 0:c0ecb8bf28eb 29972 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29973 } else {
Marko Mikulicic 0:c0ecb8bf28eb 29974 char sa[100], sb[100];
Marko Mikulicic 0:c0ecb8bf28eb 29975
Marko Mikulicic 0:c0ecb8bf28eb 29976 rcode = to_string(v7, a, NULL, sa, sizeof(sa), NULL);
Marko Mikulicic 0:c0ecb8bf28eb 29977 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29978 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29979 }
Marko Mikulicic 0:c0ecb8bf28eb 29980
Marko Mikulicic 0:c0ecb8bf28eb 29981 rcode = to_string(v7, b, NULL, sb, sizeof(sb), NULL);
Marko Mikulicic 0:c0ecb8bf28eb 29982 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 29983 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29984 }
Marko Mikulicic 0:c0ecb8bf28eb 29985
Marko Mikulicic 0:c0ecb8bf28eb 29986 sa[sizeof(sa) - 1] = sb[sizeof(sb) - 1] = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 29987 *res = strcmp(sb, sa);
Marko Mikulicic 0:c0ecb8bf28eb 29988 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 29989 }
Marko Mikulicic 0:c0ecb8bf28eb 29990
Marko Mikulicic 0:c0ecb8bf28eb 29991 clean:
Marko Mikulicic 0:c0ecb8bf28eb 29992 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 29993 }
Marko Mikulicic 0:c0ecb8bf28eb 29994
Marko Mikulicic 0:c0ecb8bf28eb 29995 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 29996 static enum v7_err a_partition(struct v7 *v7, val_t *a, int l, int r,
Marko Mikulicic 0:c0ecb8bf28eb 29997 void *user_data, int *res) {
Marko Mikulicic 0:c0ecb8bf28eb 29998 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 29999 val_t t, pivot = a[l];
Marko Mikulicic 0:c0ecb8bf28eb 30000 int i = l, j = r + 1;
Marko Mikulicic 0:c0ecb8bf28eb 30001
Marko Mikulicic 0:c0ecb8bf28eb 30002 for (;;) {
Marko Mikulicic 0:c0ecb8bf28eb 30003 while (1) {
Marko Mikulicic 0:c0ecb8bf28eb 30004 ++i;
Marko Mikulicic 0:c0ecb8bf28eb 30005
Marko Mikulicic 0:c0ecb8bf28eb 30006 if (i <= r) {
Marko Mikulicic 0:c0ecb8bf28eb 30007 int tmp = 0;
Marko Mikulicic 0:c0ecb8bf28eb 30008 rcode = a_cmp(v7, user_data, &a[i], &pivot, &tmp);
Marko Mikulicic 0:c0ecb8bf28eb 30009 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30010 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30011 }
Marko Mikulicic 0:c0ecb8bf28eb 30012
Marko Mikulicic 0:c0ecb8bf28eb 30013 if (tmp > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 30014 break;
Marko Mikulicic 0:c0ecb8bf28eb 30015 }
Marko Mikulicic 0:c0ecb8bf28eb 30016 } else {
Marko Mikulicic 0:c0ecb8bf28eb 30017 break;
Marko Mikulicic 0:c0ecb8bf28eb 30018 }
Marko Mikulicic 0:c0ecb8bf28eb 30019 }
Marko Mikulicic 0:c0ecb8bf28eb 30020 while (1) {
Marko Mikulicic 0:c0ecb8bf28eb 30021 int tmp = 0;
Marko Mikulicic 0:c0ecb8bf28eb 30022 --j;
Marko Mikulicic 0:c0ecb8bf28eb 30023
Marko Mikulicic 0:c0ecb8bf28eb 30024 rcode = a_cmp(v7, user_data, &a[j], &pivot, &tmp);
Marko Mikulicic 0:c0ecb8bf28eb 30025 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30026 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30027 }
Marko Mikulicic 0:c0ecb8bf28eb 30028
Marko Mikulicic 0:c0ecb8bf28eb 30029 if (tmp <= 0) {
Marko Mikulicic 0:c0ecb8bf28eb 30030 break;
Marko Mikulicic 0:c0ecb8bf28eb 30031 }
Marko Mikulicic 0:c0ecb8bf28eb 30032 }
Marko Mikulicic 0:c0ecb8bf28eb 30033 if (i >= j) break;
Marko Mikulicic 0:c0ecb8bf28eb 30034 t = a[i];
Marko Mikulicic 0:c0ecb8bf28eb 30035 a[i] = a[j];
Marko Mikulicic 0:c0ecb8bf28eb 30036 a[j] = t;
Marko Mikulicic 0:c0ecb8bf28eb 30037 }
Marko Mikulicic 0:c0ecb8bf28eb 30038 t = a[l];
Marko Mikulicic 0:c0ecb8bf28eb 30039 a[l] = a[j];
Marko Mikulicic 0:c0ecb8bf28eb 30040 a[j] = t;
Marko Mikulicic 0:c0ecb8bf28eb 30041
Marko Mikulicic 0:c0ecb8bf28eb 30042 *res = j;
Marko Mikulicic 0:c0ecb8bf28eb 30043 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30044 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30045 }
Marko Mikulicic 0:c0ecb8bf28eb 30046
Marko Mikulicic 0:c0ecb8bf28eb 30047 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30048 static enum v7_err a_qsort(struct v7 *v7, val_t *a, int l, int r,
Marko Mikulicic 0:c0ecb8bf28eb 30049 void *user_data) {
Marko Mikulicic 0:c0ecb8bf28eb 30050 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30051 if (l < r) {
Marko Mikulicic 0:c0ecb8bf28eb 30052 int j = 0;
Marko Mikulicic 0:c0ecb8bf28eb 30053 rcode = a_partition(v7, a, l, r, user_data, &j);
Marko Mikulicic 0:c0ecb8bf28eb 30054 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30055 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30056 }
Marko Mikulicic 0:c0ecb8bf28eb 30057
Marko Mikulicic 0:c0ecb8bf28eb 30058 rcode = a_qsort(v7, a, l, j - 1, user_data);
Marko Mikulicic 0:c0ecb8bf28eb 30059 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30060 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30061 }
Marko Mikulicic 0:c0ecb8bf28eb 30062
Marko Mikulicic 0:c0ecb8bf28eb 30063 rcode = a_qsort(v7, a, j + 1, r, user_data);
Marko Mikulicic 0:c0ecb8bf28eb 30064 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30065 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30066 }
Marko Mikulicic 0:c0ecb8bf28eb 30067 }
Marko Mikulicic 0:c0ecb8bf28eb 30068 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30069 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30070 }
Marko Mikulicic 0:c0ecb8bf28eb 30071
Marko Mikulicic 0:c0ecb8bf28eb 30072 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30073 static enum v7_err a_sort(struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 30074 enum v7_err (*sorting_func)(struct v7 *v7, void *,
Marko Mikulicic 0:c0ecb8bf28eb 30075 const void *,
Marko Mikulicic 0:c0ecb8bf28eb 30076 const void *, int *res),
Marko Mikulicic 0:c0ecb8bf28eb 30077 v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30078 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30079 int i = 0, len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 30080 val_t *arr = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 30081 val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 30082
Marko Mikulicic 0:c0ecb8bf28eb 30083 *res = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30084 len = v7_array_length(v7, *res);
Marko Mikulicic 0:c0ecb8bf28eb 30085
Marko Mikulicic 0:c0ecb8bf28eb 30086 if (!v7_is_object(*res)) {
Marko Mikulicic 0:c0ecb8bf28eb 30087 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30088 }
Marko Mikulicic 0:c0ecb8bf28eb 30089
Marko Mikulicic 0:c0ecb8bf28eb 30090 arr = (val_t *) malloc(len * sizeof(arr[0]));
Marko Mikulicic 0:c0ecb8bf28eb 30091
Marko Mikulicic 0:c0ecb8bf28eb 30092 assert(*res != v7->vals.global_object);
Marko Mikulicic 0:c0ecb8bf28eb 30093
Marko Mikulicic 0:c0ecb8bf28eb 30094 for (i = 0; i < len; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 30095 arr[i] = v7_array_get(v7, *res, i);
Marko Mikulicic 0:c0ecb8bf28eb 30096 }
Marko Mikulicic 0:c0ecb8bf28eb 30097
Marko Mikulicic 0:c0ecb8bf28eb 30098 /* TODO(dfrank): sorting_func isn't actually used! something is wrong here */
Marko Mikulicic 0:c0ecb8bf28eb 30099 if (sorting_func != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 30100 struct a_sort_data sort_data;
Marko Mikulicic 0:c0ecb8bf28eb 30101 sort_data.sort_func = arg0;
Marko Mikulicic 0:c0ecb8bf28eb 30102 rcode = a_qsort(v7, arr, 0, len - 1, &sort_data);
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
Marko Mikulicic 0:c0ecb8bf28eb 30108 for (i = 0; i < len; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 30109 v7_array_set(v7, *res, i, arr[len - (i + 1)]);
Marko Mikulicic 0:c0ecb8bf28eb 30110 }
Marko Mikulicic 0:c0ecb8bf28eb 30111
Marko Mikulicic 0:c0ecb8bf28eb 30112 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30113 if (arr != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 30114 free(arr);
Marko Mikulicic 0:c0ecb8bf28eb 30115 }
Marko Mikulicic 0:c0ecb8bf28eb 30116 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30117 }
Marko Mikulicic 0:c0ecb8bf28eb 30118
Marko Mikulicic 0:c0ecb8bf28eb 30119 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30120 V7_PRIVATE enum v7_err Array_sort(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30121 return a_sort(v7, a_cmp, res);
Marko Mikulicic 0:c0ecb8bf28eb 30122 }
Marko Mikulicic 0:c0ecb8bf28eb 30123
Marko Mikulicic 0:c0ecb8bf28eb 30124 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30125 V7_PRIVATE enum v7_err Array_reverse(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30126 return a_sort(v7, NULL, res);
Marko Mikulicic 0:c0ecb8bf28eb 30127 }
Marko Mikulicic 0:c0ecb8bf28eb 30128
Marko Mikulicic 0:c0ecb8bf28eb 30129 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30130 V7_PRIVATE enum v7_err Array_join(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30131 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30132 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30133 val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 30134 size_t sep_size = 0;
Marko Mikulicic 0:c0ecb8bf28eb 30135 const char *sep = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 30136
Marko Mikulicic 0:c0ecb8bf28eb 30137 *res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 30138
Marko Mikulicic 0:c0ecb8bf28eb 30139 /* Get pointer to the separator string */
Marko Mikulicic 0:c0ecb8bf28eb 30140 if (!v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 30141 /* If no separator is provided, use comma */
Marko Mikulicic 0:c0ecb8bf28eb 30142 arg0 = v7_mk_string(v7, ",", 1, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30143 }
Marko Mikulicic 0:c0ecb8bf28eb 30144 sep = v7_get_string(v7, &arg0, &sep_size);
Marko Mikulicic 0:c0ecb8bf28eb 30145
Marko Mikulicic 0:c0ecb8bf28eb 30146 /* Do the actual join */
Marko Mikulicic 0:c0ecb8bf28eb 30147 if (is_prototype_of(v7, this_obj, v7->vals.array_prototype)) {
Marko Mikulicic 0:c0ecb8bf28eb 30148 struct mbuf m;
Marko Mikulicic 0:c0ecb8bf28eb 30149 char buf[100], *p;
Marko Mikulicic 0:c0ecb8bf28eb 30150 long i, n, num_elems = v7_array_length(v7, this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 30151
Marko Mikulicic 0:c0ecb8bf28eb 30152 mbuf_init(&m, 0);
Marko Mikulicic 0:c0ecb8bf28eb 30153
Marko Mikulicic 0:c0ecb8bf28eb 30154 for (i = 0; i < num_elems; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 30155 /* Append separator */
Marko Mikulicic 0:c0ecb8bf28eb 30156 if (i > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 30157 mbuf_append(&m, sep, sep_size);
Marko Mikulicic 0:c0ecb8bf28eb 30158 }
Marko Mikulicic 0:c0ecb8bf28eb 30159
Marko Mikulicic 0:c0ecb8bf28eb 30160 /* Append next item from an array */
Marko Mikulicic 0:c0ecb8bf28eb 30161 p = buf;
Marko Mikulicic 0:c0ecb8bf28eb 30162 {
Marko Mikulicic 0:c0ecb8bf28eb 30163 size_t tmp;
Marko Mikulicic 0:c0ecb8bf28eb 30164 rcode = to_string(v7, v7_array_get(v7, this_obj, i), NULL, buf,
Marko Mikulicic 0:c0ecb8bf28eb 30165 sizeof(buf), &tmp);
Marko Mikulicic 0:c0ecb8bf28eb 30166 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30167 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30168 }
Marko Mikulicic 0:c0ecb8bf28eb 30169 n = tmp;
Marko Mikulicic 0:c0ecb8bf28eb 30170 }
Marko Mikulicic 0:c0ecb8bf28eb 30171 if (n > (long) sizeof(buf)) {
Marko Mikulicic 0:c0ecb8bf28eb 30172 p = (char *) malloc(n + 1);
Marko Mikulicic 0:c0ecb8bf28eb 30173 rcode = to_string(v7, v7_array_get(v7, this_obj, i), NULL, p, n, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 30174 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30175 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30176 }
Marko Mikulicic 0:c0ecb8bf28eb 30177 }
Marko Mikulicic 0:c0ecb8bf28eb 30178 mbuf_append(&m, p, n);
Marko Mikulicic 0:c0ecb8bf28eb 30179 if (p != buf) {
Marko Mikulicic 0:c0ecb8bf28eb 30180 free(p);
Marko Mikulicic 0:c0ecb8bf28eb 30181 }
Marko Mikulicic 0:c0ecb8bf28eb 30182 }
Marko Mikulicic 0:c0ecb8bf28eb 30183
Marko Mikulicic 0:c0ecb8bf28eb 30184 /* mbuf contains concatenated string now. Copy it to the result. */
Marko Mikulicic 0:c0ecb8bf28eb 30185 *res = v7_mk_string(v7, m.buf, m.len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30186 mbuf_free(&m);
Marko Mikulicic 0:c0ecb8bf28eb 30187 }
Marko Mikulicic 0:c0ecb8bf28eb 30188
Marko Mikulicic 0:c0ecb8bf28eb 30189 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30190 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30191 }
Marko Mikulicic 0:c0ecb8bf28eb 30192
Marko Mikulicic 0:c0ecb8bf28eb 30193 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30194 V7_PRIVATE enum v7_err Array_toString(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30195 return Array_join(v7, res);
Marko Mikulicic 0:c0ecb8bf28eb 30196 }
Marko Mikulicic 0:c0ecb8bf28eb 30197
Marko Mikulicic 0:c0ecb8bf28eb 30198 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30199 static enum v7_err a_splice(struct v7 *v7, int mutate, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30200 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30201 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30202 long i, len = v7_array_length(v7, this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 30203 long num_args = v7_argc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30204 long elems_to_insert = num_args > 2 ? num_args - 2 : 0;
Marko Mikulicic 0:c0ecb8bf28eb 30205 long arg0, arg1;
Marko Mikulicic 0:c0ecb8bf28eb 30206
Marko Mikulicic 0:c0ecb8bf28eb 30207 if (!v7_is_object(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 30208 rcode = v7_throwf(v7, TYPE_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 30209 "Array.splice or Array.slice called on non-object value");
Marko Mikulicic 0:c0ecb8bf28eb 30210 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30211 }
Marko Mikulicic 0:c0ecb8bf28eb 30212
Marko Mikulicic 0:c0ecb8bf28eb 30213 *res = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30214
Marko Mikulicic 0:c0ecb8bf28eb 30215 rcode = to_long(v7, v7_arg(v7, 0), 0, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 30216 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30217 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30218 }
Marko Mikulicic 0:c0ecb8bf28eb 30219
Marko Mikulicic 0:c0ecb8bf28eb 30220 rcode = to_long(v7, v7_arg(v7, 1), len, &arg1);
Marko Mikulicic 0:c0ecb8bf28eb 30221 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30222 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30223 }
Marko Mikulicic 0:c0ecb8bf28eb 30224
Marko Mikulicic 0:c0ecb8bf28eb 30225 /* Bounds check */
Marko Mikulicic 0:c0ecb8bf28eb 30226 if (!mutate && len <= 0) {
Marko Mikulicic 0:c0ecb8bf28eb 30227 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30228 }
Marko Mikulicic 0:c0ecb8bf28eb 30229 if (arg0 < 0) arg0 = len + arg0;
Marko Mikulicic 0:c0ecb8bf28eb 30230 if (arg0 < 0) arg0 = 0;
Marko Mikulicic 0:c0ecb8bf28eb 30231 if (arg0 > len) arg0 = len;
Marko Mikulicic 0:c0ecb8bf28eb 30232 if (mutate) {
Marko Mikulicic 0:c0ecb8bf28eb 30233 if (arg1 < 0) arg1 = 0;
Marko Mikulicic 0:c0ecb8bf28eb 30234 arg1 += arg0;
Marko Mikulicic 0:c0ecb8bf28eb 30235 } else if (arg1 < 0) {
Marko Mikulicic 0:c0ecb8bf28eb 30236 arg1 = len + arg1;
Marko Mikulicic 0:c0ecb8bf28eb 30237 }
Marko Mikulicic 0:c0ecb8bf28eb 30238
Marko Mikulicic 0:c0ecb8bf28eb 30239 /* Create return value - slice */
Marko Mikulicic 0:c0ecb8bf28eb 30240 for (i = arg0; i < arg1 && i < len; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 30241 rcode =
Marko Mikulicic 0:c0ecb8bf28eb 30242 v7_array_push_throwing(v7, *res, v7_array_get(v7, this_obj, i), NULL);
Marko Mikulicic 0:c0ecb8bf28eb 30243 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30244 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30245 }
Marko Mikulicic 0:c0ecb8bf28eb 30246 }
Marko Mikulicic 0:c0ecb8bf28eb 30247
Marko Mikulicic 0:c0ecb8bf28eb 30248 if (mutate && get_object_struct(this_obj)->attributes & V7_OBJ_DENSE_ARRAY) {
Marko Mikulicic 0:c0ecb8bf28eb 30249 /*
Marko Mikulicic 0:c0ecb8bf28eb 30250 * dense arrays are spliced by memmoving leaving the trailing
Marko Mikulicic 0:c0ecb8bf28eb 30251 * space allocated for future appends.
Marko Mikulicic 0:c0ecb8bf28eb 30252 * TODO(mkm): figure out if trimming is better
Marko Mikulicic 0:c0ecb8bf28eb 30253 */
Marko Mikulicic 0:c0ecb8bf28eb 30254 struct v7_property *p =
Marko Mikulicic 0:c0ecb8bf28eb 30255 v7_get_own_property2(v7, this_obj, "", 0, _V7_PROPERTY_HIDDEN);
Marko Mikulicic 0:c0ecb8bf28eb 30256 struct mbuf *abuf;
Marko Mikulicic 0:c0ecb8bf28eb 30257 if (p == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 30258 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30259 }
Marko Mikulicic 0:c0ecb8bf28eb 30260 abuf = (struct mbuf *) v7_get_ptr(v7, p->value);
Marko Mikulicic 0:c0ecb8bf28eb 30261 if (abuf == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 30262 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30263 }
Marko Mikulicic 0:c0ecb8bf28eb 30264
Marko Mikulicic 0:c0ecb8bf28eb 30265 memmove(abuf->buf + arg0 * sizeof(val_t), abuf->buf + arg1 * sizeof(val_t),
Marko Mikulicic 0:c0ecb8bf28eb 30266 (len - arg1) * sizeof(val_t));
Marko Mikulicic 0:c0ecb8bf28eb 30267 abuf->len -= (arg1 - arg0) * sizeof(val_t);
Marko Mikulicic 0:c0ecb8bf28eb 30268 } else if (mutate) {
Marko Mikulicic 0:c0ecb8bf28eb 30269 /* If splicing, modify this_obj array: remove spliced sub-array */
Marko Mikulicic 0:c0ecb8bf28eb 30270 struct v7_property **p, **next;
Marko Mikulicic 0:c0ecb8bf28eb 30271 long i;
Marko Mikulicic 0:c0ecb8bf28eb 30272
Marko Mikulicic 0:c0ecb8bf28eb 30273 for (p = &get_object_struct(this_obj)->properties; *p != NULL; p = next) {
Marko Mikulicic 0:c0ecb8bf28eb 30274 size_t n;
Marko Mikulicic 0:c0ecb8bf28eb 30275 const char *s = v7_get_string(v7, &p[0]->name, &n);
Marko Mikulicic 0:c0ecb8bf28eb 30276 next = &p[0]->next;
Marko Mikulicic 0:c0ecb8bf28eb 30277 i = strtol(s, NULL, 10);
Marko Mikulicic 0:c0ecb8bf28eb 30278 if (i >= arg0 && i < arg1) {
Marko Mikulicic 0:c0ecb8bf28eb 30279 /* Remove items from spliced sub-array */
Marko Mikulicic 0:c0ecb8bf28eb 30280 v7_destroy_property(p);
Marko Mikulicic 0:c0ecb8bf28eb 30281 *p = *next;
Marko Mikulicic 0:c0ecb8bf28eb 30282 next = p;
Marko Mikulicic 0:c0ecb8bf28eb 30283 } else if (i >= arg1) {
Marko Mikulicic 0:c0ecb8bf28eb 30284 /* Modify indices of the elements past sub-array */
Marko Mikulicic 0:c0ecb8bf28eb 30285 char key[20];
Marko Mikulicic 0:c0ecb8bf28eb 30286 size_t n = c_snprintf(key, sizeof(key), "%ld",
Marko Mikulicic 0:c0ecb8bf28eb 30287 i - (arg1 - arg0) + elems_to_insert);
Marko Mikulicic 0:c0ecb8bf28eb 30288 p[0]->name = v7_mk_string(v7, key, n, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30289 }
Marko Mikulicic 0:c0ecb8bf28eb 30290 }
Marko Mikulicic 0:c0ecb8bf28eb 30291
Marko Mikulicic 0:c0ecb8bf28eb 30292 /* Insert optional extra elements */
Marko Mikulicic 0:c0ecb8bf28eb 30293 for (i = 2; i < num_args; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 30294 char key[20];
Marko Mikulicic 0:c0ecb8bf28eb 30295 size_t n = c_snprintf(key, sizeof(key), "%ld", arg0 + i - 2);
Marko Mikulicic 0:c0ecb8bf28eb 30296 rcode = set_property(v7, this_obj, key, n, v7_arg(v7, i), NULL);
Marko Mikulicic 0:c0ecb8bf28eb 30297 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30298 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30299 }
Marko Mikulicic 0:c0ecb8bf28eb 30300 }
Marko Mikulicic 0:c0ecb8bf28eb 30301 }
Marko Mikulicic 0:c0ecb8bf28eb 30302
Marko Mikulicic 0:c0ecb8bf28eb 30303 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30304 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30305 }
Marko Mikulicic 0:c0ecb8bf28eb 30306
Marko Mikulicic 0:c0ecb8bf28eb 30307 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30308 V7_PRIVATE enum v7_err Array_slice(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30309 return a_splice(v7, 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 30310 }
Marko Mikulicic 0:c0ecb8bf28eb 30311
Marko Mikulicic 0:c0ecb8bf28eb 30312 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30313 V7_PRIVATE enum v7_err Array_splice(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30314 return a_splice(v7, 1, res);
Marko Mikulicic 0:c0ecb8bf28eb 30315 }
Marko Mikulicic 0:c0ecb8bf28eb 30316
Marko Mikulicic 0:c0ecb8bf28eb 30317 static void a_prep1(struct v7 *v7, val_t t, val_t *a0, val_t *a1) {
Marko Mikulicic 0:c0ecb8bf28eb 30318 *a0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 30319 *a1 = v7_arg(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30320 if (v7_is_undefined(*a1)) {
Marko Mikulicic 0:c0ecb8bf28eb 30321 *a1 = t;
Marko Mikulicic 0:c0ecb8bf28eb 30322 }
Marko Mikulicic 0:c0ecb8bf28eb 30323 }
Marko Mikulicic 0:c0ecb8bf28eb 30324
Marko Mikulicic 0:c0ecb8bf28eb 30325 /*
Marko Mikulicic 0:c0ecb8bf28eb 30326 * Call callback function `cb`, passing `this_obj` as `this`, with the
Marko Mikulicic 0:c0ecb8bf28eb 30327 * following arguments:
Marko Mikulicic 0:c0ecb8bf28eb 30328 *
Marko Mikulicic 0:c0ecb8bf28eb 30329 * cb(v, n, this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 30330 *
Marko Mikulicic 0:c0ecb8bf28eb 30331 */
Marko Mikulicic 0:c0ecb8bf28eb 30332 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30333 static enum v7_err a_prep2(struct v7 *v7, val_t cb, val_t v, val_t n,
Marko Mikulicic 0:c0ecb8bf28eb 30334 val_t this_obj, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30335 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30336 int saved_inhibit_gc = v7->inhibit_gc;
Marko Mikulicic 0:c0ecb8bf28eb 30337 val_t args = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30338
Marko Mikulicic 0:c0ecb8bf28eb 30339 *res = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30340
Marko Mikulicic 0:c0ecb8bf28eb 30341 v7_own(v7, &args);
Marko Mikulicic 0:c0ecb8bf28eb 30342
Marko Mikulicic 0:c0ecb8bf28eb 30343 v7_array_push(v7, args, v);
Marko Mikulicic 0:c0ecb8bf28eb 30344 v7_array_push(v7, args, n);
Marko Mikulicic 0:c0ecb8bf28eb 30345 v7_array_push(v7, args, this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 30346
Marko Mikulicic 0:c0ecb8bf28eb 30347 v7->inhibit_gc = 0;
Marko Mikulicic 0:c0ecb8bf28eb 30348 rcode = b_apply(v7, cb, this_obj, args, 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 30349 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30350 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30351 }
Marko Mikulicic 0:c0ecb8bf28eb 30352
Marko Mikulicic 0:c0ecb8bf28eb 30353 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30354 v7->inhibit_gc = saved_inhibit_gc;
Marko Mikulicic 0:c0ecb8bf28eb 30355 v7_disown(v7, &args);
Marko Mikulicic 0:c0ecb8bf28eb 30356
Marko Mikulicic 0:c0ecb8bf28eb 30357 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30358 }
Marko Mikulicic 0:c0ecb8bf28eb 30359
Marko Mikulicic 0:c0ecb8bf28eb 30360 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30361 V7_PRIVATE enum v7_err Array_forEach(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30362 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30363 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30364 val_t v = V7_UNDEFINED, cb = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 30365 unsigned long len, i;
Marko Mikulicic 0:c0ecb8bf28eb 30366 int has;
Marko Mikulicic 0:c0ecb8bf28eb 30367 /* a_prep2 uninhibits GC when calling cb */
Marko Mikulicic 0:c0ecb8bf28eb 30368 struct gc_tmp_frame vf = new_tmp_frame(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30369
Marko Mikulicic 0:c0ecb8bf28eb 30370 if (!v7_is_object(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 30371 rcode = v7_throwf(v7, TYPE_ERROR, "Array expected");
Marko Mikulicic 0:c0ecb8bf28eb 30372 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30373 }
Marko Mikulicic 0:c0ecb8bf28eb 30374
Marko Mikulicic 0:c0ecb8bf28eb 30375 if (!v7_is_callable(v7, cb)) {
Marko Mikulicic 0:c0ecb8bf28eb 30376 rcode = v7_throwf(v7, TYPE_ERROR, "Function expected");
Marko Mikulicic 0:c0ecb8bf28eb 30377 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30378 }
Marko Mikulicic 0:c0ecb8bf28eb 30379
Marko Mikulicic 0:c0ecb8bf28eb 30380 tmp_stack_push(&vf, &v);
Marko Mikulicic 0:c0ecb8bf28eb 30381
Marko Mikulicic 0:c0ecb8bf28eb 30382 len = v7_array_length(v7, this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 30383 for (i = 0; i < len; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 30384 v = v7_array_get2(v7, this_obj, i, &has);
Marko Mikulicic 0:c0ecb8bf28eb 30385 if (!has) continue;
Marko Mikulicic 0:c0ecb8bf28eb 30386
Marko Mikulicic 0:c0ecb8bf28eb 30387 rcode = a_prep2(v7, cb, v, v7_mk_number(v7, i), this_obj, res);
Marko Mikulicic 0:c0ecb8bf28eb 30388 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30389 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30390 }
Marko Mikulicic 0:c0ecb8bf28eb 30391 }
Marko Mikulicic 0:c0ecb8bf28eb 30392
Marko Mikulicic 0:c0ecb8bf28eb 30393 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30394 tmp_frame_cleanup(&vf);
Marko Mikulicic 0:c0ecb8bf28eb 30395 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30396 }
Marko Mikulicic 0:c0ecb8bf28eb 30397
Marko Mikulicic 0:c0ecb8bf28eb 30398 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30399 V7_PRIVATE enum v7_err Array_map(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30400 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30401 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30402 val_t arg0, arg1, el, v;
Marko Mikulicic 0:c0ecb8bf28eb 30403 unsigned long len, i;
Marko Mikulicic 0:c0ecb8bf28eb 30404 int has;
Marko Mikulicic 0:c0ecb8bf28eb 30405 /* a_prep2 uninhibits GC when calling cb */
Marko Mikulicic 0:c0ecb8bf28eb 30406 struct gc_tmp_frame vf = new_tmp_frame(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30407
Marko Mikulicic 0:c0ecb8bf28eb 30408 if (!v7_is_object(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 30409 rcode = v7_throwf(v7, TYPE_ERROR, "Array expected");
Marko Mikulicic 0:c0ecb8bf28eb 30410 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30411 } else {
Marko Mikulicic 0:c0ecb8bf28eb 30412 a_prep1(v7, this_obj, &arg0, &arg1);
Marko Mikulicic 0:c0ecb8bf28eb 30413 *res = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30414 len = v7_array_length(v7, this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 30415
Marko Mikulicic 0:c0ecb8bf28eb 30416 tmp_stack_push(&vf, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 30417 tmp_stack_push(&vf, &arg1);
Marko Mikulicic 0:c0ecb8bf28eb 30418 tmp_stack_push(&vf, &v);
Marko Mikulicic 0:c0ecb8bf28eb 30419
Marko Mikulicic 0:c0ecb8bf28eb 30420 for (i = 0; i < len; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 30421 v = v7_array_get2(v7, this_obj, i, &has);
Marko Mikulicic 0:c0ecb8bf28eb 30422 if (!has) continue;
Marko Mikulicic 0:c0ecb8bf28eb 30423 rcode = a_prep2(v7, arg0, v, v7_mk_number(v7, i), arg1, &el);
Marko Mikulicic 0:c0ecb8bf28eb 30424 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30425 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30426 }
Marko Mikulicic 0:c0ecb8bf28eb 30427
Marko Mikulicic 0:c0ecb8bf28eb 30428 rcode = v7_array_set_throwing(v7, *res, i, el, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 30429 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30430 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30431 }
Marko Mikulicic 0:c0ecb8bf28eb 30432 }
Marko Mikulicic 0:c0ecb8bf28eb 30433 }
Marko Mikulicic 0:c0ecb8bf28eb 30434
Marko Mikulicic 0:c0ecb8bf28eb 30435 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30436 tmp_frame_cleanup(&vf);
Marko Mikulicic 0:c0ecb8bf28eb 30437 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30438 }
Marko Mikulicic 0:c0ecb8bf28eb 30439
Marko Mikulicic 0:c0ecb8bf28eb 30440 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30441 V7_PRIVATE enum v7_err Array_every(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30442 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30443 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30444 val_t arg0, arg1, el, v;
Marko Mikulicic 0:c0ecb8bf28eb 30445 unsigned long i, len;
Marko Mikulicic 0:c0ecb8bf28eb 30446 int has;
Marko Mikulicic 0:c0ecb8bf28eb 30447 /* a_prep2 uninhibits GC when calling cb */
Marko Mikulicic 0:c0ecb8bf28eb 30448 struct gc_tmp_frame vf = new_tmp_frame(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30449
Marko Mikulicic 0:c0ecb8bf28eb 30450 *res = v7_mk_boolean(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 30451
Marko Mikulicic 0:c0ecb8bf28eb 30452 if (!v7_is_object(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 30453 rcode = v7_throwf(v7, TYPE_ERROR, "Array expected");
Marko Mikulicic 0:c0ecb8bf28eb 30454 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30455 } else {
Marko Mikulicic 0:c0ecb8bf28eb 30456 a_prep1(v7, this_obj, &arg0, &arg1);
Marko Mikulicic 0:c0ecb8bf28eb 30457
Marko Mikulicic 0:c0ecb8bf28eb 30458 tmp_stack_push(&vf, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 30459 tmp_stack_push(&vf, &arg1);
Marko Mikulicic 0:c0ecb8bf28eb 30460 tmp_stack_push(&vf, &v);
Marko Mikulicic 0:c0ecb8bf28eb 30461
Marko Mikulicic 0:c0ecb8bf28eb 30462 len = v7_array_length(v7, this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 30463 for (i = 0; i < len; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 30464 v = v7_array_get2(v7, this_obj, i, &has);
Marko Mikulicic 0:c0ecb8bf28eb 30465 if (!has) continue;
Marko Mikulicic 0:c0ecb8bf28eb 30466 rcode = a_prep2(v7, arg0, v, v7_mk_number(v7, i), arg1, &el);
Marko Mikulicic 0:c0ecb8bf28eb 30467 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30468 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30469 }
Marko Mikulicic 0:c0ecb8bf28eb 30470 if (!v7_is_truthy(v7, el)) {
Marko Mikulicic 0:c0ecb8bf28eb 30471 *res = v7_mk_boolean(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 30472 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30473 }
Marko Mikulicic 0:c0ecb8bf28eb 30474 }
Marko Mikulicic 0:c0ecb8bf28eb 30475 }
Marko Mikulicic 0:c0ecb8bf28eb 30476
Marko Mikulicic 0:c0ecb8bf28eb 30477 *res = v7_mk_boolean(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30478
Marko Mikulicic 0:c0ecb8bf28eb 30479 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30480 tmp_frame_cleanup(&vf);
Marko Mikulicic 0:c0ecb8bf28eb 30481 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30482 }
Marko Mikulicic 0:c0ecb8bf28eb 30483
Marko Mikulicic 0:c0ecb8bf28eb 30484 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30485 V7_PRIVATE enum v7_err Array_some(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30486 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30487 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30488 val_t arg0, arg1, el, v;
Marko Mikulicic 0:c0ecb8bf28eb 30489 unsigned long i, len;
Marko Mikulicic 0:c0ecb8bf28eb 30490 int has;
Marko Mikulicic 0:c0ecb8bf28eb 30491 /* a_prep2 uninhibits GC when calling cb */
Marko Mikulicic 0:c0ecb8bf28eb 30492 struct gc_tmp_frame vf = new_tmp_frame(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30493
Marko Mikulicic 0:c0ecb8bf28eb 30494 *res = v7_mk_boolean(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30495
Marko Mikulicic 0:c0ecb8bf28eb 30496 if (!v7_is_object(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 30497 rcode = v7_throwf(v7, TYPE_ERROR, "Array expected");
Marko Mikulicic 0:c0ecb8bf28eb 30498 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30499 } else {
Marko Mikulicic 0:c0ecb8bf28eb 30500 a_prep1(v7, this_obj, &arg0, &arg1);
Marko Mikulicic 0:c0ecb8bf28eb 30501
Marko Mikulicic 0:c0ecb8bf28eb 30502 tmp_stack_push(&vf, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 30503 tmp_stack_push(&vf, &arg1);
Marko Mikulicic 0:c0ecb8bf28eb 30504 tmp_stack_push(&vf, &v);
Marko Mikulicic 0:c0ecb8bf28eb 30505
Marko Mikulicic 0:c0ecb8bf28eb 30506 len = v7_array_length(v7, this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 30507 for (i = 0; i < len; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 30508 v = v7_array_get2(v7, this_obj, i, &has);
Marko Mikulicic 0:c0ecb8bf28eb 30509 if (!has) continue;
Marko Mikulicic 0:c0ecb8bf28eb 30510 rcode = a_prep2(v7, arg0, v, v7_mk_number(v7, i), arg1, &el);
Marko Mikulicic 0:c0ecb8bf28eb 30511 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30512 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30513 }
Marko Mikulicic 0:c0ecb8bf28eb 30514 if (v7_is_truthy(v7, el)) {
Marko Mikulicic 0:c0ecb8bf28eb 30515 *res = v7_mk_boolean(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30516 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30517 }
Marko Mikulicic 0:c0ecb8bf28eb 30518 }
Marko Mikulicic 0:c0ecb8bf28eb 30519 }
Marko Mikulicic 0:c0ecb8bf28eb 30520
Marko Mikulicic 0:c0ecb8bf28eb 30521 *res = v7_mk_boolean(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 30522
Marko Mikulicic 0:c0ecb8bf28eb 30523 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30524 tmp_frame_cleanup(&vf);
Marko Mikulicic 0:c0ecb8bf28eb 30525 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30526 }
Marko Mikulicic 0:c0ecb8bf28eb 30527
Marko Mikulicic 0:c0ecb8bf28eb 30528 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30529 V7_PRIVATE enum v7_err Array_filter(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30530 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30531 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30532 val_t arg0, arg1, el, v;
Marko Mikulicic 0:c0ecb8bf28eb 30533 unsigned long len, i;
Marko Mikulicic 0:c0ecb8bf28eb 30534 int has;
Marko Mikulicic 0:c0ecb8bf28eb 30535 /* a_prep2 uninhibits GC when calling cb */
Marko Mikulicic 0:c0ecb8bf28eb 30536 struct gc_tmp_frame vf = new_tmp_frame(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30537
Marko Mikulicic 0:c0ecb8bf28eb 30538 if (!v7_is_object(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 30539 rcode = v7_throwf(v7, TYPE_ERROR, "Array expected");
Marko Mikulicic 0:c0ecb8bf28eb 30540 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30541 } else {
Marko Mikulicic 0:c0ecb8bf28eb 30542 a_prep1(v7, this_obj, &arg0, &arg1);
Marko Mikulicic 0:c0ecb8bf28eb 30543 *res = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30544 len = v7_array_length(v7, this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 30545
Marko Mikulicic 0:c0ecb8bf28eb 30546 tmp_stack_push(&vf, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 30547 tmp_stack_push(&vf, &arg1);
Marko Mikulicic 0:c0ecb8bf28eb 30548 tmp_stack_push(&vf, &v);
Marko Mikulicic 0:c0ecb8bf28eb 30549
Marko Mikulicic 0:c0ecb8bf28eb 30550 for (i = 0; i < len; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 30551 v = v7_array_get2(v7, this_obj, i, &has);
Marko Mikulicic 0:c0ecb8bf28eb 30552 if (!has) continue;
Marko Mikulicic 0:c0ecb8bf28eb 30553 rcode = a_prep2(v7, arg0, v, v7_mk_number(v7, i), arg1, &el);
Marko Mikulicic 0:c0ecb8bf28eb 30554 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30555 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30556 }
Marko Mikulicic 0:c0ecb8bf28eb 30557 if (v7_is_truthy(v7, el)) {
Marko Mikulicic 0:c0ecb8bf28eb 30558 rcode = v7_array_push_throwing(v7, *res, v, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 30559 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30560 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30561 }
Marko Mikulicic 0:c0ecb8bf28eb 30562 }
Marko Mikulicic 0:c0ecb8bf28eb 30563 }
Marko Mikulicic 0:c0ecb8bf28eb 30564 }
Marko Mikulicic 0:c0ecb8bf28eb 30565
Marko Mikulicic 0:c0ecb8bf28eb 30566 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30567 tmp_frame_cleanup(&vf);
Marko Mikulicic 0:c0ecb8bf28eb 30568 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30569 }
Marko Mikulicic 0:c0ecb8bf28eb 30570
Marko Mikulicic 0:c0ecb8bf28eb 30571 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30572 V7_PRIVATE enum v7_err Array_concat(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30573 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30574 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30575 size_t i, j, len;
Marko Mikulicic 0:c0ecb8bf28eb 30576 val_t saved_args;
Marko Mikulicic 0:c0ecb8bf28eb 30577
Marko Mikulicic 0:c0ecb8bf28eb 30578 if (!v7_is_array(v7, this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 30579 rcode = v7_throwf(v7, TYPE_ERROR, "Array expected");
Marko Mikulicic 0:c0ecb8bf28eb 30580 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30581 }
Marko Mikulicic 0:c0ecb8bf28eb 30582
Marko Mikulicic 0:c0ecb8bf28eb 30583 len = v7_argc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30584
Marko Mikulicic 0:c0ecb8bf28eb 30585 /*
Marko Mikulicic 0:c0ecb8bf28eb 30586 * reuse a_splice but override it's arguments. a_splice
Marko Mikulicic 0:c0ecb8bf28eb 30587 * internally uses a lot of helpers that fetch arguments
Marko Mikulicic 0:c0ecb8bf28eb 30588 * from the v7 context.
Marko Mikulicic 0:c0ecb8bf28eb 30589 * TODO(mkm): we need a better helper call another cfunction
Marko Mikulicic 0:c0ecb8bf28eb 30590 * from a cfunction.
Marko Mikulicic 0:c0ecb8bf28eb 30591 */
Marko Mikulicic 0:c0ecb8bf28eb 30592 saved_args = v7->vals.arguments;
Marko Mikulicic 0:c0ecb8bf28eb 30593 v7->vals.arguments = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 30594 rcode = a_splice(v7, 1, res);
Marko Mikulicic 0:c0ecb8bf28eb 30595 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30596 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30597 }
Marko Mikulicic 0:c0ecb8bf28eb 30598 v7->vals.arguments = saved_args;
Marko Mikulicic 0:c0ecb8bf28eb 30599
Marko Mikulicic 0:c0ecb8bf28eb 30600 for (i = 0; i < len; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 30601 val_t a = v7_arg(v7, i);
Marko Mikulicic 0:c0ecb8bf28eb 30602 if (!v7_is_array(v7, a)) {
Marko Mikulicic 0:c0ecb8bf28eb 30603 rcode = v7_array_push_throwing(v7, *res, a, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 30604 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30605 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30606 }
Marko Mikulicic 0:c0ecb8bf28eb 30607 } else {
Marko Mikulicic 0:c0ecb8bf28eb 30608 size_t alen = v7_array_length(v7, a);
Marko Mikulicic 0:c0ecb8bf28eb 30609 for (j = 0; j < alen; j++) {
Marko Mikulicic 0:c0ecb8bf28eb 30610 rcode = v7_array_push_throwing(v7, *res, v7_array_get(v7, a, j), NULL);
Marko Mikulicic 0:c0ecb8bf28eb 30611 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30612 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30613 }
Marko Mikulicic 0:c0ecb8bf28eb 30614 }
Marko Mikulicic 0:c0ecb8bf28eb 30615 }
Marko Mikulicic 0:c0ecb8bf28eb 30616 }
Marko Mikulicic 0:c0ecb8bf28eb 30617
Marko Mikulicic 0:c0ecb8bf28eb 30618 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30619 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30620 }
Marko Mikulicic 0:c0ecb8bf28eb 30621
Marko Mikulicic 0:c0ecb8bf28eb 30622 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30623 V7_PRIVATE enum v7_err Array_isArray(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30624 val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 30625 *res = v7_mk_boolean(v7, v7_is_array(v7, arg0));
Marko Mikulicic 0:c0ecb8bf28eb 30626 return V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30627 }
Marko Mikulicic 0:c0ecb8bf28eb 30628
Marko Mikulicic 0:c0ecb8bf28eb 30629 V7_PRIVATE void init_array(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 30630 val_t ctor = mk_cfunction_obj(v7, Array_ctor, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30631 val_t length = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30632
Marko Mikulicic 0:c0ecb8bf28eb 30633 v7_set(v7, ctor, "prototype", 9, v7->vals.array_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 30634 set_method(v7, ctor, "isArray", Array_isArray, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30635 v7_set(v7, v7->vals.global_object, "Array", 5, ctor);
Marko Mikulicic 0:c0ecb8bf28eb 30636 v7_def(v7, v7->vals.array_prototype, "constructor", ~0, _V7_DESC_HIDDEN(1),
Marko Mikulicic 0:c0ecb8bf28eb 30637 ctor);
Marko Mikulicic 0:c0ecb8bf28eb 30638 v7_set(v7, ctor, "name", 4, v7_mk_string(v7, "Array", ~0, 1));
Marko Mikulicic 0:c0ecb8bf28eb 30639
Marko Mikulicic 0:c0ecb8bf28eb 30640 set_method(v7, v7->vals.array_prototype, "concat", Array_concat, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30641 set_method(v7, v7->vals.array_prototype, "every", Array_every, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30642 set_method(v7, v7->vals.array_prototype, "filter", Array_filter, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30643 set_method(v7, v7->vals.array_prototype, "forEach", Array_forEach, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30644 set_method(v7, v7->vals.array_prototype, "join", Array_join, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30645 set_method(v7, v7->vals.array_prototype, "map", Array_map, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30646 set_method(v7, v7->vals.array_prototype, "push", Array_push, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30647 set_method(v7, v7->vals.array_prototype, "reverse", Array_reverse, 0);
Marko Mikulicic 0:c0ecb8bf28eb 30648 set_method(v7, v7->vals.array_prototype, "slice", Array_slice, 2);
Marko Mikulicic 0:c0ecb8bf28eb 30649 set_method(v7, v7->vals.array_prototype, "some", Array_some, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30650 set_method(v7, v7->vals.array_prototype, "sort", Array_sort, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30651 set_method(v7, v7->vals.array_prototype, "splice", Array_splice, 2);
Marko Mikulicic 0:c0ecb8bf28eb 30652 set_method(v7, v7->vals.array_prototype, "toString", Array_toString, 0);
Marko Mikulicic 0:c0ecb8bf28eb 30653
Marko Mikulicic 0:c0ecb8bf28eb 30654 v7_array_set(v7, length, 0, v7_mk_cfunction(Array_get_length));
Marko Mikulicic 0:c0ecb8bf28eb 30655 v7_array_set(v7, length, 1, v7_mk_cfunction(Array_set_length));
Marko Mikulicic 0:c0ecb8bf28eb 30656 v7_def(v7, v7->vals.array_prototype, "length", 6,
Marko Mikulicic 0:c0ecb8bf28eb 30657 V7_DESC_ENUMERABLE(0) | V7_DESC_GETTER(1) | V7_DESC_SETTER(1), length);
Marko Mikulicic 0:c0ecb8bf28eb 30658 }
Marko Mikulicic 0:c0ecb8bf28eb 30659
Marko Mikulicic 0:c0ecb8bf28eb 30660 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 30661 }
Marko Mikulicic 0:c0ecb8bf28eb 30662 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 30663 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 30664 #line 1 "v7/src/std_boolean.c"
Marko Mikulicic 0:c0ecb8bf28eb 30665 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30666 /*
Marko Mikulicic 0:c0ecb8bf28eb 30667 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 30668 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 30669 */
Marko Mikulicic 0:c0ecb8bf28eb 30670
Marko Mikulicic 0:c0ecb8bf28eb 30671 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 30672 /* Amalgamated: #include "v7/src/std_object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 30673 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 30674 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 30675 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 30676 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 30677 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 30678 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 30679 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 30680
Marko Mikulicic 0:c0ecb8bf28eb 30681 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 30682 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 30683 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 30684
Marko Mikulicic 0:c0ecb8bf28eb 30685 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30686 V7_PRIVATE enum v7_err Boolean_ctor(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30687 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30688 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30689
Marko Mikulicic 0:c0ecb8bf28eb 30690 *res = to_boolean_v(v7, v7_arg(v7, 0));
Marko Mikulicic 0:c0ecb8bf28eb 30691
Marko Mikulicic 0:c0ecb8bf28eb 30692 if (v7_is_generic_object(this_obj) && this_obj != v7->vals.global_object) {
Marko Mikulicic 0:c0ecb8bf28eb 30693 /* called as "new Boolean(...)" */
Marko Mikulicic 0:c0ecb8bf28eb 30694 obj_prototype_set(v7, get_object_struct(this_obj),
Marko Mikulicic 0:c0ecb8bf28eb 30695 get_object_struct(v7->vals.boolean_prototype));
Marko Mikulicic 0:c0ecb8bf28eb 30696 v7_def(v7, this_obj, "", 0, _V7_DESC_HIDDEN(1), *res);
Marko Mikulicic 0:c0ecb8bf28eb 30697
Marko Mikulicic 0:c0ecb8bf28eb 30698 /*
Marko Mikulicic 0:c0ecb8bf28eb 30699 * implicitly returning `this`: `call_cfunction()` in bcode.c will do
Marko Mikulicic 0:c0ecb8bf28eb 30700 * that for us
Marko Mikulicic 0:c0ecb8bf28eb 30701 */
Marko Mikulicic 0:c0ecb8bf28eb 30702 }
Marko Mikulicic 0:c0ecb8bf28eb 30703
Marko Mikulicic 0:c0ecb8bf28eb 30704 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30705 }
Marko Mikulicic 0:c0ecb8bf28eb 30706
Marko Mikulicic 0:c0ecb8bf28eb 30707 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30708 V7_PRIVATE enum v7_err Boolean_valueOf(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30709 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30710 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30711 if (!v7_is_boolean(this_obj) &&
Marko Mikulicic 0:c0ecb8bf28eb 30712 (v7_is_object(this_obj) &&
Marko Mikulicic 0:c0ecb8bf28eb 30713 v7_get_proto(v7, this_obj) != v7->vals.boolean_prototype)) {
Marko Mikulicic 0:c0ecb8bf28eb 30714 rcode = v7_throwf(v7, TYPE_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 30715 "Boolean.valueOf called on non-boolean object");
Marko Mikulicic 0:c0ecb8bf28eb 30716 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30717 }
Marko Mikulicic 0:c0ecb8bf28eb 30718
Marko Mikulicic 0:c0ecb8bf28eb 30719 rcode = Obj_valueOf(v7, res);
Marko Mikulicic 0:c0ecb8bf28eb 30720 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30721 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30722 }
Marko Mikulicic 0:c0ecb8bf28eb 30723
Marko Mikulicic 0:c0ecb8bf28eb 30724 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30725 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30726 }
Marko Mikulicic 0:c0ecb8bf28eb 30727
Marko Mikulicic 0:c0ecb8bf28eb 30728 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30729 V7_PRIVATE enum v7_err Boolean_toString(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30730 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30731 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30732
Marko Mikulicic 0:c0ecb8bf28eb 30733 *res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 30734
Marko Mikulicic 0:c0ecb8bf28eb 30735 if (this_obj == v7->vals.boolean_prototype) {
Marko Mikulicic 0:c0ecb8bf28eb 30736 *res = v7_mk_string(v7, "false", 5, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30737 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30738 }
Marko Mikulicic 0:c0ecb8bf28eb 30739
Marko Mikulicic 0:c0ecb8bf28eb 30740 if (!v7_is_boolean(this_obj) &&
Marko Mikulicic 0:c0ecb8bf28eb 30741 !(v7_is_generic_object(this_obj) &&
Marko Mikulicic 0:c0ecb8bf28eb 30742 is_prototype_of(v7, this_obj, v7->vals.boolean_prototype))) {
Marko Mikulicic 0:c0ecb8bf28eb 30743 rcode = v7_throwf(v7, TYPE_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 30744 "Boolean.toString called on non-boolean object");
Marko Mikulicic 0:c0ecb8bf28eb 30745 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30746 }
Marko Mikulicic 0:c0ecb8bf28eb 30747
Marko Mikulicic 0:c0ecb8bf28eb 30748 rcode = obj_value_of(v7, this_obj, res);
Marko Mikulicic 0:c0ecb8bf28eb 30749 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30750 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30751 }
Marko Mikulicic 0:c0ecb8bf28eb 30752
Marko Mikulicic 0:c0ecb8bf28eb 30753 rcode = primitive_to_str(v7, *res, res, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 30754 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 30755 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30756 }
Marko Mikulicic 0:c0ecb8bf28eb 30757
Marko Mikulicic 0:c0ecb8bf28eb 30758 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30759 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30760 }
Marko Mikulicic 0:c0ecb8bf28eb 30761
Marko Mikulicic 0:c0ecb8bf28eb 30762 V7_PRIVATE void init_boolean(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 30763 val_t ctor = mk_cfunction_obj_with_proto(v7, Boolean_ctor, 1,
Marko Mikulicic 0:c0ecb8bf28eb 30764 v7->vals.boolean_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 30765 v7_set(v7, v7->vals.global_object, "Boolean", 7, ctor);
Marko Mikulicic 0:c0ecb8bf28eb 30766
Marko Mikulicic 0:c0ecb8bf28eb 30767 set_cfunc_prop(v7, v7->vals.boolean_prototype, "valueOf", Boolean_valueOf);
Marko Mikulicic 0:c0ecb8bf28eb 30768 set_cfunc_prop(v7, v7->vals.boolean_prototype, "toString", Boolean_toString);
Marko Mikulicic 0:c0ecb8bf28eb 30769 }
Marko Mikulicic 0:c0ecb8bf28eb 30770
Marko Mikulicic 0:c0ecb8bf28eb 30771 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 30772 }
Marko Mikulicic 0:c0ecb8bf28eb 30773 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 30774 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 30775 #line 1 "v7/src/std_math.c"
Marko Mikulicic 0:c0ecb8bf28eb 30776 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30777 /*
Marko Mikulicic 0:c0ecb8bf28eb 30778 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 30779 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 30780 */
Marko Mikulicic 0:c0ecb8bf28eb 30781
Marko Mikulicic 0:c0ecb8bf28eb 30782 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 30783 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 30784 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 30785 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 30786
Marko Mikulicic 0:c0ecb8bf28eb 30787 #if V7_ENABLE__Math
Marko Mikulicic 0:c0ecb8bf28eb 30788
Marko Mikulicic 0:c0ecb8bf28eb 30789 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 30790 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 30791 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 30792
Marko Mikulicic 0:c0ecb8bf28eb 30793 #ifdef __WATCOM__
Marko Mikulicic 0:c0ecb8bf28eb 30794 int matherr(struct _exception *exc) {
Marko Mikulicic 0:c0ecb8bf28eb 30795 if (exc->type == DOMAIN) {
Marko Mikulicic 0:c0ecb8bf28eb 30796 exc->retval = NAN;
Marko Mikulicic 0:c0ecb8bf28eb 30797 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 30798 }
Marko Mikulicic 0:c0ecb8bf28eb 30799 }
Marko Mikulicic 0:c0ecb8bf28eb 30800 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30801
Marko Mikulicic 0:c0ecb8bf28eb 30802 #if V7_ENABLE__Math__abs || V7_ENABLE__Math__acos || V7_ENABLE__Math__asin || \
Marko Mikulicic 0:c0ecb8bf28eb 30803 V7_ENABLE__Math__atan || V7_ENABLE__Math__ceil || V7_ENABLE__Math__cos || \
Marko Mikulicic 0:c0ecb8bf28eb 30804 V7_ENABLE__Math__exp || V7_ENABLE__Math__floor || V7_ENABLE__Math__log || \
Marko Mikulicic 0:c0ecb8bf28eb 30805 V7_ENABLE__Math__round || V7_ENABLE__Math__sin || V7_ENABLE__Math__sqrt || \
Marko Mikulicic 0:c0ecb8bf28eb 30806 V7_ENABLE__Math__tan
Marko Mikulicic 0:c0ecb8bf28eb 30807 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30808 static enum v7_err m_one_arg(struct v7 *v7, double (*f)(double), val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30809 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30810 val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 30811 double d0 = v7_get_double(v7, arg0);
Marko Mikulicic 0:c0ecb8bf28eb 30812 #ifdef V7_BROKEN_NAN
Marko Mikulicic 0:c0ecb8bf28eb 30813 if (isnan(d0)) {
Marko Mikulicic 0:c0ecb8bf28eb 30814 *res = V7_TAG_NAN;
Marko Mikulicic 0:c0ecb8bf28eb 30815 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30816 }
Marko Mikulicic 0:c0ecb8bf28eb 30817 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30818 *res = v7_mk_number(v7, f(d0));
Marko Mikulicic 0:c0ecb8bf28eb 30819 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30820
Marko Mikulicic 0:c0ecb8bf28eb 30821 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30822 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30823 }
Marko Mikulicic 0:c0ecb8bf28eb 30824 #endif /* V7_ENABLE__Math__* */
Marko Mikulicic 0:c0ecb8bf28eb 30825
Marko Mikulicic 0:c0ecb8bf28eb 30826 #if V7_ENABLE__Math__pow || V7_ENABLE__Math__atan2
Marko Mikulicic 0:c0ecb8bf28eb 30827 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30828 static enum v7_err m_two_arg(struct v7 *v7, double (*f)(double, double),
Marko Mikulicic 0:c0ecb8bf28eb 30829 val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30830 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30831 val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 30832 val_t arg1 = v7_arg(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 30833 double d0 = v7_get_double(v7, arg0);
Marko Mikulicic 0:c0ecb8bf28eb 30834 double d1 = v7_get_double(v7, arg1);
Marko Mikulicic 0:c0ecb8bf28eb 30835 #ifdef V7_BROKEN_NAN
Marko Mikulicic 0:c0ecb8bf28eb 30836 /* pow(NaN,0) == 1, doesn't fix atan2, but who cares */
Marko Mikulicic 0:c0ecb8bf28eb 30837 if (isnan(d1)) {
Marko Mikulicic 0:c0ecb8bf28eb 30838 *res = V7_TAG_NAN;
Marko Mikulicic 0:c0ecb8bf28eb 30839 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30840 }
Marko Mikulicic 0:c0ecb8bf28eb 30841 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30842 *res = v7_mk_number(v7, f(d0, d1));
Marko Mikulicic 0:c0ecb8bf28eb 30843 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 30844
Marko Mikulicic 0:c0ecb8bf28eb 30845 clean:
Marko Mikulicic 0:c0ecb8bf28eb 30846 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30847 }
Marko Mikulicic 0:c0ecb8bf28eb 30848 #endif /* V7_ENABLE__Math__pow || V7_ENABLE__Math__atan2 */
Marko Mikulicic 0:c0ecb8bf28eb 30849
Marko Mikulicic 0:c0ecb8bf28eb 30850 #define DEFINE_WRAPPER(name, func) \
Marko Mikulicic 0:c0ecb8bf28eb 30851 WARN_UNUSED_RESULT \
Marko Mikulicic 0:c0ecb8bf28eb 30852 V7_PRIVATE enum v7_err Math_##name(struct v7 *v7, v7_val_t *res) { \
Marko Mikulicic 0:c0ecb8bf28eb 30853 return func(v7, name, res); \
Marko Mikulicic 0:c0ecb8bf28eb 30854 }
Marko Mikulicic 0:c0ecb8bf28eb 30855
Marko Mikulicic 0:c0ecb8bf28eb 30856 /* Visual studio 2012+ has round() */
Marko Mikulicic 0:c0ecb8bf28eb 30857 #if V7_ENABLE__Math__round && \
Marko Mikulicic 0:c0ecb8bf28eb 30858 ((defined(V7_WINDOWS) && _MSC_VER < 1700) || defined(__WATCOM__))
Marko Mikulicic 0:c0ecb8bf28eb 30859 static double round(double n) {
Marko Mikulicic 0:c0ecb8bf28eb 30860 return n;
Marko Mikulicic 0:c0ecb8bf28eb 30861 }
Marko Mikulicic 0:c0ecb8bf28eb 30862 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30863
Marko Mikulicic 0:c0ecb8bf28eb 30864 #if V7_ENABLE__Math__abs
Marko Mikulicic 0:c0ecb8bf28eb 30865 DEFINE_WRAPPER(fabs, m_one_arg)
Marko Mikulicic 0:c0ecb8bf28eb 30866 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30867 #if V7_ENABLE__Math__acos
Marko Mikulicic 0:c0ecb8bf28eb 30868 DEFINE_WRAPPER(acos, m_one_arg)
Marko Mikulicic 0:c0ecb8bf28eb 30869 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30870 #if V7_ENABLE__Math__asin
Marko Mikulicic 0:c0ecb8bf28eb 30871 DEFINE_WRAPPER(asin, m_one_arg)
Marko Mikulicic 0:c0ecb8bf28eb 30872 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30873 #if V7_ENABLE__Math__atan
Marko Mikulicic 0:c0ecb8bf28eb 30874 DEFINE_WRAPPER(atan, m_one_arg)
Marko Mikulicic 0:c0ecb8bf28eb 30875 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30876 #if V7_ENABLE__Math__atan2
Marko Mikulicic 0:c0ecb8bf28eb 30877 DEFINE_WRAPPER(atan2, m_two_arg)
Marko Mikulicic 0:c0ecb8bf28eb 30878 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30879 #if V7_ENABLE__Math__ceil
Marko Mikulicic 0:c0ecb8bf28eb 30880 DEFINE_WRAPPER(ceil, m_one_arg)
Marko Mikulicic 0:c0ecb8bf28eb 30881 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30882 #if V7_ENABLE__Math__cos
Marko Mikulicic 0:c0ecb8bf28eb 30883 DEFINE_WRAPPER(cos, m_one_arg)
Marko Mikulicic 0:c0ecb8bf28eb 30884 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30885 #if V7_ENABLE__Math__exp
Marko Mikulicic 0:c0ecb8bf28eb 30886 DEFINE_WRAPPER(exp, m_one_arg)
Marko Mikulicic 0:c0ecb8bf28eb 30887 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30888 #if V7_ENABLE__Math__floor
Marko Mikulicic 0:c0ecb8bf28eb 30889 DEFINE_WRAPPER(floor, m_one_arg)
Marko Mikulicic 0:c0ecb8bf28eb 30890 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30891 #if V7_ENABLE__Math__log
Marko Mikulicic 0:c0ecb8bf28eb 30892 DEFINE_WRAPPER(log, m_one_arg)
Marko Mikulicic 0:c0ecb8bf28eb 30893 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30894 #if V7_ENABLE__Math__pow
Marko Mikulicic 0:c0ecb8bf28eb 30895 DEFINE_WRAPPER(pow, m_two_arg)
Marko Mikulicic 0:c0ecb8bf28eb 30896 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30897 #if V7_ENABLE__Math__round
Marko Mikulicic 0:c0ecb8bf28eb 30898 DEFINE_WRAPPER(round, m_one_arg)
Marko Mikulicic 0:c0ecb8bf28eb 30899 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30900 #if V7_ENABLE__Math__sin
Marko Mikulicic 0:c0ecb8bf28eb 30901 DEFINE_WRAPPER(sin, m_one_arg)
Marko Mikulicic 0:c0ecb8bf28eb 30902 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30903 #if V7_ENABLE__Math__sqrt
Marko Mikulicic 0:c0ecb8bf28eb 30904 DEFINE_WRAPPER(sqrt, m_one_arg)
Marko Mikulicic 0:c0ecb8bf28eb 30905 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30906 #if V7_ENABLE__Math__tan
Marko Mikulicic 0:c0ecb8bf28eb 30907 DEFINE_WRAPPER(tan, m_one_arg)
Marko Mikulicic 0:c0ecb8bf28eb 30908 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30909
Marko Mikulicic 0:c0ecb8bf28eb 30910 #if V7_ENABLE__Math__random
Marko Mikulicic 0:c0ecb8bf28eb 30911 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30912 V7_PRIVATE enum v7_err Math_random(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30913 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 30914 *res = v7_mk_number(v7, (double) rand() / RAND_MAX);
Marko Mikulicic 0:c0ecb8bf28eb 30915 return V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30916 }
Marko Mikulicic 0:c0ecb8bf28eb 30917 #endif /* V7_ENABLE__Math__random */
Marko Mikulicic 0:c0ecb8bf28eb 30918
Marko Mikulicic 0:c0ecb8bf28eb 30919 #if V7_ENABLE__Math__min || V7_ENABLE__Math__max
Marko Mikulicic 0:c0ecb8bf28eb 30920 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30921 static enum v7_err min_max(struct v7 *v7, int is_min, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30922 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 30923 double dres = NAN;
Marko Mikulicic 0:c0ecb8bf28eb 30924 int i, len = v7_argc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30925
Marko Mikulicic 0:c0ecb8bf28eb 30926 for (i = 0; i < len; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 30927 double v = v7_get_double(v7, v7_arg(v7, i));
Marko Mikulicic 0:c0ecb8bf28eb 30928 if (isnan(dres) || (is_min && v < dres) || (!is_min && v > dres)) {
Marko Mikulicic 0:c0ecb8bf28eb 30929 dres = v;
Marko Mikulicic 0:c0ecb8bf28eb 30930 }
Marko Mikulicic 0:c0ecb8bf28eb 30931 }
Marko Mikulicic 0:c0ecb8bf28eb 30932
Marko Mikulicic 0:c0ecb8bf28eb 30933 *res = v7_mk_number(v7, dres);
Marko Mikulicic 0:c0ecb8bf28eb 30934
Marko Mikulicic 0:c0ecb8bf28eb 30935 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 30936 }
Marko Mikulicic 0:c0ecb8bf28eb 30937 #endif /* V7_ENABLE__Math__min || V7_ENABLE__Math__max */
Marko Mikulicic 0:c0ecb8bf28eb 30938
Marko Mikulicic 0:c0ecb8bf28eb 30939 #if V7_ENABLE__Math__min
Marko Mikulicic 0:c0ecb8bf28eb 30940 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30941 V7_PRIVATE enum v7_err Math_min(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30942 return min_max(v7, 1, res);
Marko Mikulicic 0:c0ecb8bf28eb 30943 }
Marko Mikulicic 0:c0ecb8bf28eb 30944 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30945
Marko Mikulicic 0:c0ecb8bf28eb 30946 #if V7_ENABLE__Math__max
Marko Mikulicic 0:c0ecb8bf28eb 30947 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 30948 V7_PRIVATE enum v7_err Math_max(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 30949 return min_max(v7, 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 30950 }
Marko Mikulicic 0:c0ecb8bf28eb 30951 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30952
Marko Mikulicic 0:c0ecb8bf28eb 30953 V7_PRIVATE void init_math(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 30954 val_t math = v7_mk_object(v7);
Marko Mikulicic 0:c0ecb8bf28eb 30955
Marko Mikulicic 0:c0ecb8bf28eb 30956 #if V7_ENABLE__Math__abs
Marko Mikulicic 0:c0ecb8bf28eb 30957 set_cfunc_prop(v7, math, "abs", Math_fabs);
Marko Mikulicic 0:c0ecb8bf28eb 30958 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30959 #if V7_ENABLE__Math__acos
Marko Mikulicic 0:c0ecb8bf28eb 30960 set_cfunc_prop(v7, math, "acos", Math_acos);
Marko Mikulicic 0:c0ecb8bf28eb 30961 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30962 #if V7_ENABLE__Math__asin
Marko Mikulicic 0:c0ecb8bf28eb 30963 set_cfunc_prop(v7, math, "asin", Math_asin);
Marko Mikulicic 0:c0ecb8bf28eb 30964 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30965 #if V7_ENABLE__Math__atan
Marko Mikulicic 0:c0ecb8bf28eb 30966 set_cfunc_prop(v7, math, "atan", Math_atan);
Marko Mikulicic 0:c0ecb8bf28eb 30967 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30968 #if V7_ENABLE__Math__atan2
Marko Mikulicic 0:c0ecb8bf28eb 30969 set_cfunc_prop(v7, math, "atan2", Math_atan2);
Marko Mikulicic 0:c0ecb8bf28eb 30970 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30971 #if V7_ENABLE__Math__ceil
Marko Mikulicic 0:c0ecb8bf28eb 30972 set_cfunc_prop(v7, math, "ceil", Math_ceil);
Marko Mikulicic 0:c0ecb8bf28eb 30973 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30974 #if V7_ENABLE__Math__cos
Marko Mikulicic 0:c0ecb8bf28eb 30975 set_cfunc_prop(v7, math, "cos", Math_cos);
Marko Mikulicic 0:c0ecb8bf28eb 30976 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30977 #if V7_ENABLE__Math__exp
Marko Mikulicic 0:c0ecb8bf28eb 30978 set_cfunc_prop(v7, math, "exp", Math_exp);
Marko Mikulicic 0:c0ecb8bf28eb 30979 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30980 #if V7_ENABLE__Math__floor
Marko Mikulicic 0:c0ecb8bf28eb 30981 set_cfunc_prop(v7, math, "floor", Math_floor);
Marko Mikulicic 0:c0ecb8bf28eb 30982 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30983 #if V7_ENABLE__Math__log
Marko Mikulicic 0:c0ecb8bf28eb 30984 set_cfunc_prop(v7, math, "log", Math_log);
Marko Mikulicic 0:c0ecb8bf28eb 30985 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30986 #if V7_ENABLE__Math__max
Marko Mikulicic 0:c0ecb8bf28eb 30987 set_cfunc_prop(v7, math, "max", Math_max);
Marko Mikulicic 0:c0ecb8bf28eb 30988 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30989 #if V7_ENABLE__Math__min
Marko Mikulicic 0:c0ecb8bf28eb 30990 set_cfunc_prop(v7, math, "min", Math_min);
Marko Mikulicic 0:c0ecb8bf28eb 30991 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30992 #if V7_ENABLE__Math__pow
Marko Mikulicic 0:c0ecb8bf28eb 30993 set_cfunc_prop(v7, math, "pow", Math_pow);
Marko Mikulicic 0:c0ecb8bf28eb 30994 #endif
Marko Mikulicic 0:c0ecb8bf28eb 30995 #if V7_ENABLE__Math__random
Marko Mikulicic 0:c0ecb8bf28eb 30996 /* Incorporate our pointer into the RNG.
Marko Mikulicic 0:c0ecb8bf28eb 30997 * If srand() has not been called before, this will provide some randomness.
Marko Mikulicic 0:c0ecb8bf28eb 30998 * If it has, it will hopefully not make things worse.
Marko Mikulicic 0:c0ecb8bf28eb 30999 */
Marko Mikulicic 0:c0ecb8bf28eb 31000 srand(rand() ^ ((uintptr_t) v7));
Marko Mikulicic 0:c0ecb8bf28eb 31001 set_cfunc_prop(v7, math, "random", Math_random);
Marko Mikulicic 0:c0ecb8bf28eb 31002 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31003 #if V7_ENABLE__Math__round
Marko Mikulicic 0:c0ecb8bf28eb 31004 set_cfunc_prop(v7, math, "round", Math_round);
Marko Mikulicic 0:c0ecb8bf28eb 31005 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31006 #if V7_ENABLE__Math__sin
Marko Mikulicic 0:c0ecb8bf28eb 31007 set_cfunc_prop(v7, math, "sin", Math_sin);
Marko Mikulicic 0:c0ecb8bf28eb 31008 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31009 #if V7_ENABLE__Math__sqrt
Marko Mikulicic 0:c0ecb8bf28eb 31010 set_cfunc_prop(v7, math, "sqrt", Math_sqrt);
Marko Mikulicic 0:c0ecb8bf28eb 31011 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31012 #if V7_ENABLE__Math__tan
Marko Mikulicic 0:c0ecb8bf28eb 31013 set_cfunc_prop(v7, math, "tan", Math_tan);
Marko Mikulicic 0:c0ecb8bf28eb 31014 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31015
Marko Mikulicic 0:c0ecb8bf28eb 31016 #if V7_ENABLE__Math__constants
Marko Mikulicic 0:c0ecb8bf28eb 31017 v7_set(v7, math, "E", 1, v7_mk_number(v7, M_E));
Marko Mikulicic 0:c0ecb8bf28eb 31018 v7_set(v7, math, "PI", 2, v7_mk_number(v7, M_PI));
Marko Mikulicic 0:c0ecb8bf28eb 31019 v7_set(v7, math, "LN2", 3, v7_mk_number(v7, M_LN2));
Marko Mikulicic 0:c0ecb8bf28eb 31020 v7_set(v7, math, "LN10", 4, v7_mk_number(v7, M_LN10));
Marko Mikulicic 0:c0ecb8bf28eb 31021 v7_set(v7, math, "LOG2E", 5, v7_mk_number(v7, M_LOG2E));
Marko Mikulicic 0:c0ecb8bf28eb 31022 v7_set(v7, math, "LOG10E", 6, v7_mk_number(v7, M_LOG10E));
Marko Mikulicic 0:c0ecb8bf28eb 31023 v7_set(v7, math, "SQRT1_2", 7, v7_mk_number(v7, M_SQRT1_2));
Marko Mikulicic 0:c0ecb8bf28eb 31024 v7_set(v7, math, "SQRT2", 5, v7_mk_number(v7, M_SQRT2));
Marko Mikulicic 0:c0ecb8bf28eb 31025 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31026
Marko Mikulicic 0:c0ecb8bf28eb 31027 v7_set(v7, v7->vals.global_object, "Math", 4, math);
Marko Mikulicic 0:c0ecb8bf28eb 31028 }
Marko Mikulicic 0:c0ecb8bf28eb 31029
Marko Mikulicic 0:c0ecb8bf28eb 31030 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 31031 }
Marko Mikulicic 0:c0ecb8bf28eb 31032 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 31033
Marko Mikulicic 0:c0ecb8bf28eb 31034 #endif /* V7_ENABLE__Math */
Marko Mikulicic 0:c0ecb8bf28eb 31035 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 31036 #line 1 "v7/src/std_string.c"
Marko Mikulicic 0:c0ecb8bf28eb 31037 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31038 /*
Marko Mikulicic 0:c0ecb8bf28eb 31039 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 31040 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 31041 */
Marko Mikulicic 0:c0ecb8bf28eb 31042
Marko Mikulicic 0:c0ecb8bf28eb 31043 /* Amalgamated: #include "common/utf.h" */
Marko Mikulicic 0:c0ecb8bf28eb 31044 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 31045 /* Amalgamated: #include "v7/src/std_string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 31046 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 31047 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 31048 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 31049 /* Amalgamated: #include "v7/src/slre.h" */
Marko Mikulicic 0:c0ecb8bf28eb 31050 /* Amalgamated: #include "v7/src/std_regex.h" */
Marko Mikulicic 0:c0ecb8bf28eb 31051 /* Amalgamated: #include "v7/src/std_object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 31052 /* Amalgamated: #include "v7/src/eval.h" */
Marko Mikulicic 0:c0ecb8bf28eb 31053 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 31054 /* Amalgamated: #include "v7/src/array.h" */
Marko Mikulicic 0:c0ecb8bf28eb 31055 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 31056 /* Amalgamated: #include "v7/src/regexp.h" */
Marko Mikulicic 0:c0ecb8bf28eb 31057 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 31058
Marko Mikulicic 0:c0ecb8bf28eb 31059 /* Substring implementations: RegExp-based and String-based {{{ */
Marko Mikulicic 0:c0ecb8bf28eb 31060
Marko Mikulicic 0:c0ecb8bf28eb 31061 /*
Marko Mikulicic 0:c0ecb8bf28eb 31062 * Substring context: currently, used in Str_split() only, but will probably
Marko Mikulicic 0:c0ecb8bf28eb 31063 * be used in Str_replace() and other functions as well.
Marko Mikulicic 0:c0ecb8bf28eb 31064 *
Marko Mikulicic 0:c0ecb8bf28eb 31065 * Needed to provide different implementation for RegExp or String arguments,
Marko Mikulicic 0:c0ecb8bf28eb 31066 * keeping common parts reusable.
Marko Mikulicic 0:c0ecb8bf28eb 31067 */
Marko Mikulicic 0:c0ecb8bf28eb 31068 struct _str_split_ctx {
Marko Mikulicic 0:c0ecb8bf28eb 31069 /* implementation-specific data */
Marko Mikulicic 0:c0ecb8bf28eb 31070 union {
Marko Mikulicic 0:c0ecb8bf28eb 31071 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 31072 struct {
Marko Mikulicic 0:c0ecb8bf28eb 31073 struct slre_prog *prog;
Marko Mikulicic 0:c0ecb8bf28eb 31074 struct slre_loot loot;
Marko Mikulicic 0:c0ecb8bf28eb 31075 } regexp;
Marko Mikulicic 0:c0ecb8bf28eb 31076 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31077
Marko Mikulicic 0:c0ecb8bf28eb 31078 struct {
Marko Mikulicic 0:c0ecb8bf28eb 31079 val_t sep;
Marko Mikulicic 0:c0ecb8bf28eb 31080 } string;
Marko Mikulicic 0:c0ecb8bf28eb 31081 } impl;
Marko Mikulicic 0:c0ecb8bf28eb 31082
Marko Mikulicic 0:c0ecb8bf28eb 31083 struct v7 *v7;
Marko Mikulicic 0:c0ecb8bf28eb 31084
Marko Mikulicic 0:c0ecb8bf28eb 31085 /* start and end of previous match (set by `p_exec()`) */
Marko Mikulicic 0:c0ecb8bf28eb 31086 const char *match_start;
Marko Mikulicic 0:c0ecb8bf28eb 31087 const char *match_end;
Marko Mikulicic 0:c0ecb8bf28eb 31088
Marko Mikulicic 0:c0ecb8bf28eb 31089 /* pointers to implementation functions */
Marko Mikulicic 0:c0ecb8bf28eb 31090
Marko Mikulicic 0:c0ecb8bf28eb 31091 /*
Marko Mikulicic 0:c0ecb8bf28eb 31092 * Initialize context
Marko Mikulicic 0:c0ecb8bf28eb 31093 */
Marko Mikulicic 0:c0ecb8bf28eb 31094 void (*p_init)(struct _str_split_ctx *ctx, struct v7 *v7, val_t sep);
Marko Mikulicic 0:c0ecb8bf28eb 31095
Marko Mikulicic 0:c0ecb8bf28eb 31096 /*
Marko Mikulicic 0:c0ecb8bf28eb 31097 * Look for the next match, set `match_start` and `match_end` to appropriate
Marko Mikulicic 0:c0ecb8bf28eb 31098 * values.
Marko Mikulicic 0:c0ecb8bf28eb 31099 *
Marko Mikulicic 0:c0ecb8bf28eb 31100 * Returns 0 if match found, 1 otherwise (in accordance with `slre_exec()`)
Marko Mikulicic 0:c0ecb8bf28eb 31101 */
Marko Mikulicic 0:c0ecb8bf28eb 31102 int (*p_exec)(struct _str_split_ctx *ctx, const char *start, const char *end);
Marko Mikulicic 0:c0ecb8bf28eb 31103
Marko Mikulicic 0:c0ecb8bf28eb 31104 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 31105 /*
Marko Mikulicic 0:c0ecb8bf28eb 31106 * Add captured data to resulting array (for RegExp-based implementation only)
Marko Mikulicic 0:c0ecb8bf28eb 31107 *
Marko Mikulicic 0:c0ecb8bf28eb 31108 * Returns updated `elem` value
Marko Mikulicic 0:c0ecb8bf28eb 31109 */
Marko Mikulicic 0:c0ecb8bf28eb 31110 long (*p_add_caps)(struct _str_split_ctx *ctx, val_t res, long elem,
Marko Mikulicic 0:c0ecb8bf28eb 31111 long limit);
Marko Mikulicic 0:c0ecb8bf28eb 31112 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31113 };
Marko Mikulicic 0:c0ecb8bf28eb 31114
Marko Mikulicic 0:c0ecb8bf28eb 31115 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 31116 /* RegExp-based implementation of `p_init` in `struct _str_split_ctx` */
Marko Mikulicic 0:c0ecb8bf28eb 31117 static void subs_regexp_init(struct _str_split_ctx *ctx, struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 31118 val_t sep) {
Marko Mikulicic 0:c0ecb8bf28eb 31119 ctx->v7 = v7;
Marko Mikulicic 0:c0ecb8bf28eb 31120 ctx->impl.regexp.prog = v7_get_regexp_struct(v7, sep)->compiled_regexp;
Marko Mikulicic 0:c0ecb8bf28eb 31121 }
Marko Mikulicic 0:c0ecb8bf28eb 31122
Marko Mikulicic 0:c0ecb8bf28eb 31123 /* RegExp-based implementation of `p_exec` in `struct _str_split_ctx` */
Marko Mikulicic 0:c0ecb8bf28eb 31124 static int subs_regexp_exec(struct _str_split_ctx *ctx, const char *start,
Marko Mikulicic 0:c0ecb8bf28eb 31125 const char *end) {
Marko Mikulicic 0:c0ecb8bf28eb 31126 int ret =
Marko Mikulicic 0:c0ecb8bf28eb 31127 slre_exec(ctx->impl.regexp.prog, 0, start, end, &ctx->impl.regexp.loot);
Marko Mikulicic 0:c0ecb8bf28eb 31128
Marko Mikulicic 0:c0ecb8bf28eb 31129 ctx->match_start = ctx->impl.regexp.loot.caps[0].start;
Marko Mikulicic 0:c0ecb8bf28eb 31130 ctx->match_end = ctx->impl.regexp.loot.caps[0].end;
Marko Mikulicic 0:c0ecb8bf28eb 31131
Marko Mikulicic 0:c0ecb8bf28eb 31132 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 31133 }
Marko Mikulicic 0:c0ecb8bf28eb 31134
Marko Mikulicic 0:c0ecb8bf28eb 31135 /* RegExp-based implementation of `p_add_caps` in `struct _str_split_ctx` */
Marko Mikulicic 0:c0ecb8bf28eb 31136 static long subs_regexp_split_add_caps(struct _str_split_ctx *ctx, val_t res,
Marko Mikulicic 0:c0ecb8bf28eb 31137 long elem, long limit) {
Marko Mikulicic 0:c0ecb8bf28eb 31138 int i;
Marko Mikulicic 0:c0ecb8bf28eb 31139 for (i = 1; i < ctx->impl.regexp.loot.num_captures && elem < limit; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 31140 size_t cap_len =
Marko Mikulicic 0:c0ecb8bf28eb 31141 ctx->impl.regexp.loot.caps[i].end - ctx->impl.regexp.loot.caps[i].start;
Marko Mikulicic 0:c0ecb8bf28eb 31142 v7_array_push(
Marko Mikulicic 0:c0ecb8bf28eb 31143 ctx->v7, res,
Marko Mikulicic 0:c0ecb8bf28eb 31144 (ctx->impl.regexp.loot.caps[i].start != NULL)
Marko Mikulicic 0:c0ecb8bf28eb 31145 ? v7_mk_string(ctx->v7, ctx->impl.regexp.loot.caps[i].start,
Marko Mikulicic 0:c0ecb8bf28eb 31146 cap_len, 1)
Marko Mikulicic 0:c0ecb8bf28eb 31147 : V7_UNDEFINED);
Marko Mikulicic 0:c0ecb8bf28eb 31148 elem++;
Marko Mikulicic 0:c0ecb8bf28eb 31149 }
Marko Mikulicic 0:c0ecb8bf28eb 31150 return elem;
Marko Mikulicic 0:c0ecb8bf28eb 31151 }
Marko Mikulicic 0:c0ecb8bf28eb 31152 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31153
Marko Mikulicic 0:c0ecb8bf28eb 31154 /* String-based implementation of `p_init` in `struct _str_split_ctx` */
Marko Mikulicic 0:c0ecb8bf28eb 31155 static void subs_string_init(struct _str_split_ctx *ctx, struct v7 *v7,
Marko Mikulicic 0:c0ecb8bf28eb 31156 val_t sep) {
Marko Mikulicic 0:c0ecb8bf28eb 31157 ctx->v7 = v7;
Marko Mikulicic 0:c0ecb8bf28eb 31158 ctx->impl.string.sep = sep;
Marko Mikulicic 0:c0ecb8bf28eb 31159 }
Marko Mikulicic 0:c0ecb8bf28eb 31160
Marko Mikulicic 0:c0ecb8bf28eb 31161 /* String-based implementation of `p_exec` in `struct _str_split_ctx` */
Marko Mikulicic 0:c0ecb8bf28eb 31162 static int subs_string_exec(struct _str_split_ctx *ctx, const char *start,
Marko Mikulicic 0:c0ecb8bf28eb 31163 const char *end) {
Marko Mikulicic 0:c0ecb8bf28eb 31164 int ret = 1;
Marko Mikulicic 0:c0ecb8bf28eb 31165 size_t sep_len;
Marko Mikulicic 0:c0ecb8bf28eb 31166 const char *psep = v7_get_string(ctx->v7, &ctx->impl.string.sep, &sep_len);
Marko Mikulicic 0:c0ecb8bf28eb 31167
Marko Mikulicic 0:c0ecb8bf28eb 31168 if (sep_len == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 31169 /* separator is an empty string: match empty string */
Marko Mikulicic 0:c0ecb8bf28eb 31170 ctx->match_start = start;
Marko Mikulicic 0:c0ecb8bf28eb 31171 ctx->match_end = start;
Marko Mikulicic 0:c0ecb8bf28eb 31172 ret = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31173 } else {
Marko Mikulicic 0:c0ecb8bf28eb 31174 size_t i;
Marko Mikulicic 0:c0ecb8bf28eb 31175 for (i = 0; start <= (end - sep_len); ++i, start = utfnshift(start, 1)) {
Marko Mikulicic 0:c0ecb8bf28eb 31176 if (memcmp(start, psep, sep_len) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 31177 ret = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31178 ctx->match_start = start;
Marko Mikulicic 0:c0ecb8bf28eb 31179 ctx->match_end = start + sep_len;
Marko Mikulicic 0:c0ecb8bf28eb 31180 break;
Marko Mikulicic 0:c0ecb8bf28eb 31181 }
Marko Mikulicic 0:c0ecb8bf28eb 31182 }
Marko Mikulicic 0:c0ecb8bf28eb 31183 }
Marko Mikulicic 0:c0ecb8bf28eb 31184
Marko Mikulicic 0:c0ecb8bf28eb 31185 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 31186 }
Marko Mikulicic 0:c0ecb8bf28eb 31187
Marko Mikulicic 0:c0ecb8bf28eb 31188 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 31189 /* String-based implementation of `p_add_caps` in `struct _str_split_ctx` */
Marko Mikulicic 0:c0ecb8bf28eb 31190 static long subs_string_split_add_caps(struct _str_split_ctx *ctx, val_t res,
Marko Mikulicic 0:c0ecb8bf28eb 31191 long elem, long limit) {
Marko Mikulicic 0:c0ecb8bf28eb 31192 /* this is a stub function */
Marko Mikulicic 0:c0ecb8bf28eb 31193 (void) ctx;
Marko Mikulicic 0:c0ecb8bf28eb 31194 (void) res;
Marko Mikulicic 0:c0ecb8bf28eb 31195 (void) limit;
Marko Mikulicic 0:c0ecb8bf28eb 31196 return elem;
Marko Mikulicic 0:c0ecb8bf28eb 31197 }
Marko Mikulicic 0:c0ecb8bf28eb 31198 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31199
Marko Mikulicic 0:c0ecb8bf28eb 31200 /* }}} */
Marko Mikulicic 0:c0ecb8bf28eb 31201
Marko Mikulicic 0:c0ecb8bf28eb 31202 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31203 V7_PRIVATE enum v7_err String_ctor(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31204 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31205 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31206 val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 31207
Marko Mikulicic 0:c0ecb8bf28eb 31208 *res = arg0;
Marko Mikulicic 0:c0ecb8bf28eb 31209
Marko Mikulicic 0:c0ecb8bf28eb 31210 if (v7_argc(v7) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 31211 *res = v7_mk_string(v7, NULL, 0, 1);
Marko Mikulicic 0:c0ecb8bf28eb 31212 } else if (!v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 31213 rcode = to_string(v7, arg0, res, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31214 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31215 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31216 }
Marko Mikulicic 0:c0ecb8bf28eb 31217 }
Marko Mikulicic 0:c0ecb8bf28eb 31218
Marko Mikulicic 0:c0ecb8bf28eb 31219 if (v7_is_generic_object(this_obj) && this_obj != v7->vals.global_object) {
Marko Mikulicic 0:c0ecb8bf28eb 31220 obj_prototype_set(v7, get_object_struct(this_obj),
Marko Mikulicic 0:c0ecb8bf28eb 31221 get_object_struct(v7->vals.string_prototype));
Marko Mikulicic 0:c0ecb8bf28eb 31222 v7_def(v7, this_obj, "", 0, _V7_DESC_HIDDEN(1), *res);
Marko Mikulicic 0:c0ecb8bf28eb 31223 /*
Marko Mikulicic 0:c0ecb8bf28eb 31224 * implicitly returning `this`: `call_cfunction()` in bcode.c will do
Marko Mikulicic 0:c0ecb8bf28eb 31225 * that for us
Marko Mikulicic 0:c0ecb8bf28eb 31226 */
Marko Mikulicic 0:c0ecb8bf28eb 31227 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31228 }
Marko Mikulicic 0:c0ecb8bf28eb 31229
Marko Mikulicic 0:c0ecb8bf28eb 31230 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31231 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31232 }
Marko Mikulicic 0:c0ecb8bf28eb 31233
Marko Mikulicic 0:c0ecb8bf28eb 31234 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31235 V7_PRIVATE enum v7_err Str_fromCharCode(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31236 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31237 int i, num_args = v7_argc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31238
Marko Mikulicic 0:c0ecb8bf28eb 31239 *res = v7_mk_string(v7, "", 0, 1); /* Empty string */
Marko Mikulicic 0:c0ecb8bf28eb 31240
Marko Mikulicic 0:c0ecb8bf28eb 31241 for (i = 0; i < num_args; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 31242 char buf[10];
Marko Mikulicic 0:c0ecb8bf28eb 31243 val_t arg = v7_arg(v7, i);
Marko Mikulicic 0:c0ecb8bf28eb 31244 double d = v7_get_double(v7, arg);
Marko Mikulicic 0:c0ecb8bf28eb 31245 Rune r = (Rune)((int32_t)(isnan(d) || isinf(d) ? 0 : d) & 0xffff);
Marko Mikulicic 0:c0ecb8bf28eb 31246 int n = runetochar(buf, &r);
Marko Mikulicic 0:c0ecb8bf28eb 31247 val_t s = v7_mk_string(v7, buf, n, 1);
Marko Mikulicic 0:c0ecb8bf28eb 31248 *res = s_concat(v7, *res, s);
Marko Mikulicic 0:c0ecb8bf28eb 31249 }
Marko Mikulicic 0:c0ecb8bf28eb 31250
Marko Mikulicic 0:c0ecb8bf28eb 31251 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31252 }
Marko Mikulicic 0:c0ecb8bf28eb 31253
Marko Mikulicic 0:c0ecb8bf28eb 31254 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31255 static enum v7_err s_charCodeAt(struct v7 *v7, double *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31256 return v7_char_code_at(v7, v7_get_this(v7), v7_arg(v7, 0), res);
Marko Mikulicic 0:c0ecb8bf28eb 31257 }
Marko Mikulicic 0:c0ecb8bf28eb 31258
Marko Mikulicic 0:c0ecb8bf28eb 31259 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31260 V7_PRIVATE enum v7_err Str_charCodeAt(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31261 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31262 double dnum = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31263
Marko Mikulicic 0:c0ecb8bf28eb 31264 rcode = s_charCodeAt(v7, &dnum);
Marko Mikulicic 0:c0ecb8bf28eb 31265 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31266 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31267 }
Marko Mikulicic 0:c0ecb8bf28eb 31268
Marko Mikulicic 0:c0ecb8bf28eb 31269 *res = v7_mk_number(v7, dnum);
Marko Mikulicic 0:c0ecb8bf28eb 31270
Marko Mikulicic 0:c0ecb8bf28eb 31271 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31272 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31273 }
Marko Mikulicic 0:c0ecb8bf28eb 31274
Marko Mikulicic 0:c0ecb8bf28eb 31275 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31276 V7_PRIVATE enum v7_err Str_charAt(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31277 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31278 double code = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31279 char buf[10] = {0};
Marko Mikulicic 0:c0ecb8bf28eb 31280 int len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31281
Marko Mikulicic 0:c0ecb8bf28eb 31282 rcode = s_charCodeAt(v7, &code);
Marko Mikulicic 0:c0ecb8bf28eb 31283 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31284 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31285 }
Marko Mikulicic 0:c0ecb8bf28eb 31286
Marko Mikulicic 0:c0ecb8bf28eb 31287 if (!isnan(code)) {
Marko Mikulicic 0:c0ecb8bf28eb 31288 Rune r = (Rune) code;
Marko Mikulicic 0:c0ecb8bf28eb 31289 len = runetochar(buf, &r);
Marko Mikulicic 0:c0ecb8bf28eb 31290 }
Marko Mikulicic 0:c0ecb8bf28eb 31291 *res = v7_mk_string(v7, buf, len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 31292
Marko Mikulicic 0:c0ecb8bf28eb 31293 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31294 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31295 }
Marko Mikulicic 0:c0ecb8bf28eb 31296
Marko Mikulicic 0:c0ecb8bf28eb 31297 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31298 V7_PRIVATE enum v7_err Str_concat(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31299 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31300 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31301 int i, num_args = v7_argc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31302
Marko Mikulicic 0:c0ecb8bf28eb 31303 rcode = to_string(v7, this_obj, res, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31304 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31305 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31306 }
Marko Mikulicic 0:c0ecb8bf28eb 31307
Marko Mikulicic 0:c0ecb8bf28eb 31308 for (i = 0; i < num_args; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 31309 val_t str = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 31310
Marko Mikulicic 0:c0ecb8bf28eb 31311 rcode = to_string(v7, v7_arg(v7, i), &str, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31312 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31313 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31314 }
Marko Mikulicic 0:c0ecb8bf28eb 31315
Marko Mikulicic 0:c0ecb8bf28eb 31316 *res = s_concat(v7, *res, str);
Marko Mikulicic 0:c0ecb8bf28eb 31317 }
Marko Mikulicic 0:c0ecb8bf28eb 31318
Marko Mikulicic 0:c0ecb8bf28eb 31319 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31320 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31321 }
Marko Mikulicic 0:c0ecb8bf28eb 31322
Marko Mikulicic 0:c0ecb8bf28eb 31323 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31324 static enum v7_err s_index_of(struct v7 *v7, int last, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31325 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31326 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31327 val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 31328 size_t fromIndex = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31329 double dres = -1;
Marko Mikulicic 0:c0ecb8bf28eb 31330
Marko Mikulicic 0:c0ecb8bf28eb 31331 if (!v7_is_undefined(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 31332 const char *p1, *p2, *end;
Marko Mikulicic 0:c0ecb8bf28eb 31333 size_t i, len1, len2, bytecnt1, bytecnt2;
Marko Mikulicic 0:c0ecb8bf28eb 31334 val_t sub = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 31335
Marko Mikulicic 0:c0ecb8bf28eb 31336 rcode = to_string(v7, arg0, &sub, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31337 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31338 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31339 }
Marko Mikulicic 0:c0ecb8bf28eb 31340
Marko Mikulicic 0:c0ecb8bf28eb 31341 rcode = to_string(v7, this_obj, &this_obj, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31342 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31343 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31344 }
Marko Mikulicic 0:c0ecb8bf28eb 31345
Marko Mikulicic 0:c0ecb8bf28eb 31346 p1 = v7_get_string(v7, &this_obj, &bytecnt1);
Marko Mikulicic 0:c0ecb8bf28eb 31347 p2 = v7_get_string(v7, &sub, &bytecnt2);
Marko Mikulicic 0:c0ecb8bf28eb 31348
Marko Mikulicic 0:c0ecb8bf28eb 31349 if (bytecnt2 <= bytecnt1) {
Marko Mikulicic 0:c0ecb8bf28eb 31350 end = p1 + bytecnt1;
Marko Mikulicic 0:c0ecb8bf28eb 31351 len1 = utfnlen(p1, bytecnt1);
Marko Mikulicic 0:c0ecb8bf28eb 31352 len2 = utfnlen(p2, bytecnt2);
Marko Mikulicic 0:c0ecb8bf28eb 31353
Marko Mikulicic 0:c0ecb8bf28eb 31354 if (v7_argc(v7) > 1) {
Marko Mikulicic 0:c0ecb8bf28eb 31355 /* `fromIndex` was provided. Normalize it */
Marko Mikulicic 0:c0ecb8bf28eb 31356 double d = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31357 {
Marko Mikulicic 0:c0ecb8bf28eb 31358 val_t arg = v7_arg(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 31359 rcode = to_number_v(v7, arg, &arg);
Marko Mikulicic 0:c0ecb8bf28eb 31360 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31361 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31362 }
Marko Mikulicic 0:c0ecb8bf28eb 31363 d = v7_get_double(v7, arg);
Marko Mikulicic 0:c0ecb8bf28eb 31364 }
Marko Mikulicic 0:c0ecb8bf28eb 31365 if (isnan(d) || d < 0) {
Marko Mikulicic 0:c0ecb8bf28eb 31366 d = 0.0;
Marko Mikulicic 0:c0ecb8bf28eb 31367 } else if (isinf(d) || d > len1) {
Marko Mikulicic 0:c0ecb8bf28eb 31368 d = len1;
Marko Mikulicic 0:c0ecb8bf28eb 31369 }
Marko Mikulicic 0:c0ecb8bf28eb 31370 fromIndex = d;
Marko Mikulicic 0:c0ecb8bf28eb 31371
Marko Mikulicic 0:c0ecb8bf28eb 31372 /* adjust pointers accordingly to `fromIndex` */
Marko Mikulicic 0:c0ecb8bf28eb 31373 if (last) {
Marko Mikulicic 0:c0ecb8bf28eb 31374 const char *end_tmp = utfnshift(p1, fromIndex + len2);
Marko Mikulicic 0:c0ecb8bf28eb 31375 end = (end_tmp < end) ? end_tmp : end;
Marko Mikulicic 0:c0ecb8bf28eb 31376 } else {
Marko Mikulicic 0:c0ecb8bf28eb 31377 p1 = utfnshift(p1, fromIndex);
Marko Mikulicic 0:c0ecb8bf28eb 31378 }
Marko Mikulicic 0:c0ecb8bf28eb 31379 }
Marko Mikulicic 0:c0ecb8bf28eb 31380
Marko Mikulicic 0:c0ecb8bf28eb 31381 /*
Marko Mikulicic 0:c0ecb8bf28eb 31382 * TODO(dfrank): when `last` is set, start from the end and look
Marko Mikulicic 0:c0ecb8bf28eb 31383 * backward. We'll need to improve `utfnshift()` for that, so that it can
Marko Mikulicic 0:c0ecb8bf28eb 31384 * handle negative offsets.
Marko Mikulicic 0:c0ecb8bf28eb 31385 */
Marko Mikulicic 0:c0ecb8bf28eb 31386 for (i = 0; p1 <= (end - bytecnt2); i++, p1 = utfnshift(p1, 1)) {
Marko Mikulicic 0:c0ecb8bf28eb 31387 if (memcmp(p1, p2, bytecnt2) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 31388 dres = i;
Marko Mikulicic 0:c0ecb8bf28eb 31389 if (!last) break;
Marko Mikulicic 0:c0ecb8bf28eb 31390 }
Marko Mikulicic 0:c0ecb8bf28eb 31391 }
Marko Mikulicic 0:c0ecb8bf28eb 31392 }
Marko Mikulicic 0:c0ecb8bf28eb 31393 }
Marko Mikulicic 0:c0ecb8bf28eb 31394 if (!last && dres >= 0) dres += fromIndex;
Marko Mikulicic 0:c0ecb8bf28eb 31395 *res = v7_mk_number(v7, dres);
Marko Mikulicic 0:c0ecb8bf28eb 31396
Marko Mikulicic 0:c0ecb8bf28eb 31397 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31398 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31399 }
Marko Mikulicic 0:c0ecb8bf28eb 31400
Marko Mikulicic 0:c0ecb8bf28eb 31401 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31402 V7_PRIVATE enum v7_err Str_valueOf(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31403 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31404 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31405
Marko Mikulicic 0:c0ecb8bf28eb 31406 if (!v7_is_string(this_obj) &&
Marko Mikulicic 0:c0ecb8bf28eb 31407 (v7_is_object(this_obj) &&
Marko Mikulicic 0:c0ecb8bf28eb 31408 v7_get_proto(v7, this_obj) != v7->vals.string_prototype)) {
Marko Mikulicic 0:c0ecb8bf28eb 31409 rcode =
Marko Mikulicic 0:c0ecb8bf28eb 31410 v7_throwf(v7, TYPE_ERROR, "String.valueOf called on non-string object");
Marko Mikulicic 0:c0ecb8bf28eb 31411 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31412 }
Marko Mikulicic 0:c0ecb8bf28eb 31413
Marko Mikulicic 0:c0ecb8bf28eb 31414 rcode = Obj_valueOf(v7, res);
Marko Mikulicic 0:c0ecb8bf28eb 31415 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31416
Marko Mikulicic 0:c0ecb8bf28eb 31417 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31418 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31419 }
Marko Mikulicic 0:c0ecb8bf28eb 31420
Marko Mikulicic 0:c0ecb8bf28eb 31421 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31422 V7_PRIVATE enum v7_err Str_indexOf(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31423 return s_index_of(v7, 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 31424 }
Marko Mikulicic 0:c0ecb8bf28eb 31425
Marko Mikulicic 0:c0ecb8bf28eb 31426 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31427 V7_PRIVATE enum v7_err Str_lastIndexOf(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31428 return s_index_of(v7, 1, res);
Marko Mikulicic 0:c0ecb8bf28eb 31429 }
Marko Mikulicic 0:c0ecb8bf28eb 31430
Marko Mikulicic 0:c0ecb8bf28eb 31431 #if V7_ENABLE__String__localeCompare
Marko Mikulicic 0:c0ecb8bf28eb 31432 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31433 V7_PRIVATE enum v7_err Str_localeCompare(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31434 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31435 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31436 val_t arg0 = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 31437 val_t s = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 31438
Marko Mikulicic 0:c0ecb8bf28eb 31439 rcode = to_string(v7, v7_arg(v7, 0), &arg0, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31440 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31441 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31442 }
Marko Mikulicic 0:c0ecb8bf28eb 31443
Marko Mikulicic 0:c0ecb8bf28eb 31444 rcode = to_string(v7, this_obj, &s, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31445 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31446 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31447 }
Marko Mikulicic 0:c0ecb8bf28eb 31448
Marko Mikulicic 0:c0ecb8bf28eb 31449 *res = v7_mk_number(v7, s_cmp(v7, s, arg0));
Marko Mikulicic 0:c0ecb8bf28eb 31450
Marko Mikulicic 0:c0ecb8bf28eb 31451 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31452 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31453 }
Marko Mikulicic 0:c0ecb8bf28eb 31454 #endif
Marko Mikulicic 0:c0ecb8bf28eb 31455
Marko Mikulicic 0:c0ecb8bf28eb 31456 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31457 V7_PRIVATE enum v7_err Str_toString(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31458 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31459 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31460
Marko Mikulicic 0:c0ecb8bf28eb 31461 if (this_obj == v7->vals.string_prototype) {
Marko Mikulicic 0:c0ecb8bf28eb 31462 *res = v7_mk_string(v7, "false", 5, 1);
Marko Mikulicic 0:c0ecb8bf28eb 31463 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31464 }
Marko Mikulicic 0:c0ecb8bf28eb 31465
Marko Mikulicic 0:c0ecb8bf28eb 31466 if (!v7_is_string(this_obj) &&
Marko Mikulicic 0:c0ecb8bf28eb 31467 !(v7_is_generic_object(this_obj) &&
Marko Mikulicic 0:c0ecb8bf28eb 31468 is_prototype_of(v7, this_obj, v7->vals.string_prototype))) {
Marko Mikulicic 0:c0ecb8bf28eb 31469 rcode = v7_throwf(v7, TYPE_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 31470 "String.toString called on non-string object");
Marko Mikulicic 0:c0ecb8bf28eb 31471 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31472 }
Marko Mikulicic 0:c0ecb8bf28eb 31473
Marko Mikulicic 0:c0ecb8bf28eb 31474 rcode = obj_value_of(v7, this_obj, &this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 31475 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31476 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31477 }
Marko Mikulicic 0:c0ecb8bf28eb 31478
Marko Mikulicic 0:c0ecb8bf28eb 31479 rcode = to_string(v7, this_obj, res, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31480 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31481 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31482 }
Marko Mikulicic 0:c0ecb8bf28eb 31483
Marko Mikulicic 0:c0ecb8bf28eb 31484 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31485 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31486 }
Marko Mikulicic 0:c0ecb8bf28eb 31487
Marko Mikulicic 0:c0ecb8bf28eb 31488 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 31489 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31490 enum v7_err call_regex_ctor(struct v7 *v7, val_t arg, val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31491 /* TODO(mkm): make general helper out of this */
Marko Mikulicic 0:c0ecb8bf28eb 31492 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31493 val_t saved_args = v7->vals.arguments, args = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31494 v7_array_push(v7, args, arg);
Marko Mikulicic 0:c0ecb8bf28eb 31495 v7->vals.arguments = args;
Marko Mikulicic 0:c0ecb8bf28eb 31496
Marko Mikulicic 0:c0ecb8bf28eb 31497 rcode = Regex_ctor(v7, res);
Marko Mikulicic 0:c0ecb8bf28eb 31498 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31499 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31500 }
Marko Mikulicic 0:c0ecb8bf28eb 31501 v7->vals.arguments = saved_args;
Marko Mikulicic 0:c0ecb8bf28eb 31502
Marko Mikulicic 0:c0ecb8bf28eb 31503 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31504 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31505 }
Marko Mikulicic 0:c0ecb8bf28eb 31506
Marko Mikulicic 0:c0ecb8bf28eb 31507 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31508 V7_PRIVATE enum v7_err Str_match(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31509 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31510 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31511 val_t so = V7_UNDEFINED, ro = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 31512 long previousLastIndex = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31513 int lastMatch = 1, n = 0, flag_g;
Marko Mikulicic 0:c0ecb8bf28eb 31514 struct v7_regexp *rxp;
Marko Mikulicic 0:c0ecb8bf28eb 31515
Marko Mikulicic 0:c0ecb8bf28eb 31516 *res = V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 31517
Marko Mikulicic 0:c0ecb8bf28eb 31518 rcode = to_string(v7, this_obj, &so, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31519 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31520 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31521 }
Marko Mikulicic 0:c0ecb8bf28eb 31522
Marko Mikulicic 0:c0ecb8bf28eb 31523 if (v7_argc(v7) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 31524 rcode = v7_mk_regexp(v7, "", 0, "", 0, &ro);
Marko Mikulicic 0:c0ecb8bf28eb 31525 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31526 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31527 }
Marko Mikulicic 0:c0ecb8bf28eb 31528 } else {
Marko Mikulicic 0:c0ecb8bf28eb 31529 rcode = obj_value_of(v7, v7_arg(v7, 0), &ro);
Marko Mikulicic 0:c0ecb8bf28eb 31530 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31531 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31532 }
Marko Mikulicic 0:c0ecb8bf28eb 31533 }
Marko Mikulicic 0:c0ecb8bf28eb 31534
Marko Mikulicic 0:c0ecb8bf28eb 31535 if (!v7_is_regexp(v7, ro)) {
Marko Mikulicic 0:c0ecb8bf28eb 31536 rcode = call_regex_ctor(v7, ro, &ro);
Marko Mikulicic 0:c0ecb8bf28eb 31537 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31538 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31539 }
Marko Mikulicic 0:c0ecb8bf28eb 31540 }
Marko Mikulicic 0:c0ecb8bf28eb 31541
Marko Mikulicic 0:c0ecb8bf28eb 31542 rxp = v7_get_regexp_struct(v7, ro);
Marko Mikulicic 0:c0ecb8bf28eb 31543 flag_g = slre_get_flags(rxp->compiled_regexp) & SLRE_FLAG_G;
Marko Mikulicic 0:c0ecb8bf28eb 31544 if (!flag_g) {
Marko Mikulicic 0:c0ecb8bf28eb 31545 rcode = rx_exec(v7, ro, so, 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 31546 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31547 }
Marko Mikulicic 0:c0ecb8bf28eb 31548
Marko Mikulicic 0:c0ecb8bf28eb 31549 rxp->lastIndex = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31550 *res = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31551 while (lastMatch) {
Marko Mikulicic 0:c0ecb8bf28eb 31552 val_t result;
Marko Mikulicic 0:c0ecb8bf28eb 31553
Marko Mikulicic 0:c0ecb8bf28eb 31554 rcode = rx_exec(v7, ro, so, 1, &result);
Marko Mikulicic 0:c0ecb8bf28eb 31555 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31556 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31557 }
Marko Mikulicic 0:c0ecb8bf28eb 31558
Marko Mikulicic 0:c0ecb8bf28eb 31559 if (v7_is_null(result)) {
Marko Mikulicic 0:c0ecb8bf28eb 31560 lastMatch = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31561 } else {
Marko Mikulicic 0:c0ecb8bf28eb 31562 long thisIndex = rxp->lastIndex;
Marko Mikulicic 0:c0ecb8bf28eb 31563 if (thisIndex == previousLastIndex) {
Marko Mikulicic 0:c0ecb8bf28eb 31564 previousLastIndex = thisIndex + 1;
Marko Mikulicic 0:c0ecb8bf28eb 31565 rxp->lastIndex = previousLastIndex;
Marko Mikulicic 0:c0ecb8bf28eb 31566 } else {
Marko Mikulicic 0:c0ecb8bf28eb 31567 previousLastIndex = thisIndex;
Marko Mikulicic 0:c0ecb8bf28eb 31568 }
Marko Mikulicic 0:c0ecb8bf28eb 31569 rcode =
Marko Mikulicic 0:c0ecb8bf28eb 31570 v7_array_push_throwing(v7, *res, v7_array_get(v7, result, 0), NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31571 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31572 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31573 }
Marko Mikulicic 0:c0ecb8bf28eb 31574 n++;
Marko Mikulicic 0:c0ecb8bf28eb 31575 }
Marko Mikulicic 0:c0ecb8bf28eb 31576 }
Marko Mikulicic 0:c0ecb8bf28eb 31577
Marko Mikulicic 0:c0ecb8bf28eb 31578 if (n == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 31579 *res = V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 31580 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31581 }
Marko Mikulicic 0:c0ecb8bf28eb 31582
Marko Mikulicic 0:c0ecb8bf28eb 31583 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31584 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31585 }
Marko Mikulicic 0:c0ecb8bf28eb 31586
Marko Mikulicic 0:c0ecb8bf28eb 31587 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31588 V7_PRIVATE enum v7_err Str_replace(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31589 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31590 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31591 const char *s;
Marko Mikulicic 0:c0ecb8bf28eb 31592 size_t s_len;
Marko Mikulicic 0:c0ecb8bf28eb 31593 /*
Marko Mikulicic 0:c0ecb8bf28eb 31594 * Buffer of temporary strings returned by the replacement funciton. Will be
Marko Mikulicic 0:c0ecb8bf28eb 31595 * allocated below if only the replacement is a function. We need to store
Marko Mikulicic 0:c0ecb8bf28eb 31596 * each string in a separate `val_t`, because string data of length <= 5 is
Marko Mikulicic 0:c0ecb8bf28eb 31597 * stored right in `val_t`, so if there's more than one replacement,
Marko Mikulicic 0:c0ecb8bf28eb 31598 * each subsequent replacement will overwrite the previous one.
Marko Mikulicic 0:c0ecb8bf28eb 31599 */
Marko Mikulicic 0:c0ecb8bf28eb 31600 val_t *tmp_str_buf = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 31601 val_t out_str_o;
Marko Mikulicic 0:c0ecb8bf28eb 31602 char *old_owned_mbuf_base = v7->owned_strings.buf;
Marko Mikulicic 0:c0ecb8bf28eb 31603 char *old_owned_mbuf_end = v7->owned_strings.buf + v7->owned_strings.len;
Marko Mikulicic 0:c0ecb8bf28eb 31604
Marko Mikulicic 0:c0ecb8bf28eb 31605 rcode = to_string(v7, this_obj, &this_obj, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31606 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31607 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31608 }
Marko Mikulicic 0:c0ecb8bf28eb 31609
Marko Mikulicic 0:c0ecb8bf28eb 31610 s = v7_get_string(v7, &this_obj, &s_len);
Marko Mikulicic 0:c0ecb8bf28eb 31611
Marko Mikulicic 0:c0ecb8bf28eb 31612 if (s_len != 0 && v7_argc(v7) > 1) {
Marko Mikulicic 0:c0ecb8bf28eb 31613 const char *const str_end = s + s_len;
Marko Mikulicic 0:c0ecb8bf28eb 31614 char *p = (char *) s;
Marko Mikulicic 0:c0ecb8bf28eb 31615 uint32_t out_sub_num = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31616 val_t ro = V7_UNDEFINED, str_func = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 31617 struct slre_prog *prog;
Marko Mikulicic 0:c0ecb8bf28eb 31618 struct slre_cap out_sub[V7_RE_MAX_REPL_SUB], *ptok = out_sub;
Marko Mikulicic 0:c0ecb8bf28eb 31619 struct slre_loot loot;
Marko Mikulicic 0:c0ecb8bf28eb 31620 int flag_g;
Marko Mikulicic 0:c0ecb8bf28eb 31621
Marko Mikulicic 0:c0ecb8bf28eb 31622 rcode = obj_value_of(v7, v7_arg(v7, 0), &ro);
Marko Mikulicic 0:c0ecb8bf28eb 31623 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31624 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31625 }
Marko Mikulicic 0:c0ecb8bf28eb 31626 rcode = obj_value_of(v7, v7_arg(v7, 1), &str_func);
Marko Mikulicic 0:c0ecb8bf28eb 31627 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31628 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31629 }
Marko Mikulicic 0:c0ecb8bf28eb 31630
Marko Mikulicic 0:c0ecb8bf28eb 31631 if (!v7_is_regexp(v7, ro)) {
Marko Mikulicic 0:c0ecb8bf28eb 31632 rcode = call_regex_ctor(v7, ro, &ro);
Marko Mikulicic 0:c0ecb8bf28eb 31633 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31634 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31635 }
Marko Mikulicic 0:c0ecb8bf28eb 31636 }
Marko Mikulicic 0:c0ecb8bf28eb 31637 prog = v7_get_regexp_struct(v7, ro)->compiled_regexp;
Marko Mikulicic 0:c0ecb8bf28eb 31638 flag_g = slre_get_flags(prog) & SLRE_FLAG_G;
Marko Mikulicic 0:c0ecb8bf28eb 31639
Marko Mikulicic 0:c0ecb8bf28eb 31640 if (!v7_is_callable(v7, str_func)) {
Marko Mikulicic 0:c0ecb8bf28eb 31641 rcode = to_string(v7, str_func, &str_func, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31642 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31643 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31644 }
Marko Mikulicic 0:c0ecb8bf28eb 31645 }
Marko Mikulicic 0:c0ecb8bf28eb 31646
Marko Mikulicic 0:c0ecb8bf28eb 31647 do {
Marko Mikulicic 0:c0ecb8bf28eb 31648 int i;
Marko Mikulicic 0:c0ecb8bf28eb 31649 if (slre_exec(prog, 0, p, str_end, &loot)) break;
Marko Mikulicic 0:c0ecb8bf28eb 31650 if (p != loot.caps->start) {
Marko Mikulicic 0:c0ecb8bf28eb 31651 ptok->start = p;
Marko Mikulicic 0:c0ecb8bf28eb 31652 ptok->end = loot.caps->start;
Marko Mikulicic 0:c0ecb8bf28eb 31653 ptok++;
Marko Mikulicic 0:c0ecb8bf28eb 31654 out_sub_num++;
Marko Mikulicic 0:c0ecb8bf28eb 31655 }
Marko Mikulicic 0:c0ecb8bf28eb 31656
Marko Mikulicic 0:c0ecb8bf28eb 31657 if (v7_is_callable(v7, str_func)) { /* replace function */
Marko Mikulicic 0:c0ecb8bf28eb 31658 const char *rez_str;
Marko Mikulicic 0:c0ecb8bf28eb 31659 size_t rez_len;
Marko Mikulicic 0:c0ecb8bf28eb 31660 val_t arr = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31661
Marko Mikulicic 0:c0ecb8bf28eb 31662 for (i = 0; i < loot.num_captures; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 31663 rcode = v7_array_push_throwing(
Marko Mikulicic 0:c0ecb8bf28eb 31664 v7, arr, v7_mk_string(v7, loot.caps[i].start,
Marko Mikulicic 0:c0ecb8bf28eb 31665 loot.caps[i].end - loot.caps[i].start, 1),
Marko Mikulicic 0:c0ecb8bf28eb 31666 NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31667 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31668 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31669 }
Marko Mikulicic 0:c0ecb8bf28eb 31670 }
Marko Mikulicic 0:c0ecb8bf28eb 31671 rcode = v7_array_push_throwing(
Marko Mikulicic 0:c0ecb8bf28eb 31672 v7, arr, v7_mk_number(v7, utfnlen(s, loot.caps[0].start - s)),
Marko Mikulicic 0:c0ecb8bf28eb 31673 NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31674 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31675 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31676 }
Marko Mikulicic 0:c0ecb8bf28eb 31677
Marko Mikulicic 0:c0ecb8bf28eb 31678 rcode = v7_array_push_throwing(v7, arr, this_obj, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31679 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31680 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31681 }
Marko Mikulicic 0:c0ecb8bf28eb 31682
Marko Mikulicic 0:c0ecb8bf28eb 31683 {
Marko Mikulicic 0:c0ecb8bf28eb 31684 val_t val = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 31685
Marko Mikulicic 0:c0ecb8bf28eb 31686 rcode = b_apply(v7, str_func, this_obj, arr, 0, &val);
Marko Mikulicic 0:c0ecb8bf28eb 31687 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31688 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31689 }
Marko Mikulicic 0:c0ecb8bf28eb 31690
Marko Mikulicic 0:c0ecb8bf28eb 31691 if (tmp_str_buf == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 31692 tmp_str_buf = (val_t *) calloc(sizeof(val_t), V7_RE_MAX_REPL_SUB);
Marko Mikulicic 0:c0ecb8bf28eb 31693 }
Marko Mikulicic 0:c0ecb8bf28eb 31694
Marko Mikulicic 0:c0ecb8bf28eb 31695 rcode = to_string(v7, val, &tmp_str_buf[out_sub_num], NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31696 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31697 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31698 }
Marko Mikulicic 0:c0ecb8bf28eb 31699 }
Marko Mikulicic 0:c0ecb8bf28eb 31700 rez_str = v7_get_string(v7, &tmp_str_buf[out_sub_num], &rez_len);
Marko Mikulicic 0:c0ecb8bf28eb 31701 if (rez_len) {
Marko Mikulicic 0:c0ecb8bf28eb 31702 ptok->start = rez_str;
Marko Mikulicic 0:c0ecb8bf28eb 31703 ptok->end = rez_str + rez_len;
Marko Mikulicic 0:c0ecb8bf28eb 31704 ptok++;
Marko Mikulicic 0:c0ecb8bf28eb 31705 out_sub_num++;
Marko Mikulicic 0:c0ecb8bf28eb 31706 }
Marko Mikulicic 0:c0ecb8bf28eb 31707 } else { /* replace string */
Marko Mikulicic 0:c0ecb8bf28eb 31708 struct slre_loot newsub;
Marko Mikulicic 0:c0ecb8bf28eb 31709 size_t f_len;
Marko Mikulicic 0:c0ecb8bf28eb 31710 const char *f_str = v7_get_string(v7, &str_func, &f_len);
Marko Mikulicic 0:c0ecb8bf28eb 31711 slre_replace(&loot, s, s_len, f_str, f_len, &newsub);
Marko Mikulicic 0:c0ecb8bf28eb 31712 for (i = 0; i < newsub.num_captures; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 31713 ptok->start = newsub.caps[i].start;
Marko Mikulicic 0:c0ecb8bf28eb 31714 ptok->end = newsub.caps[i].end;
Marko Mikulicic 0:c0ecb8bf28eb 31715 ptok++;
Marko Mikulicic 0:c0ecb8bf28eb 31716 out_sub_num++;
Marko Mikulicic 0:c0ecb8bf28eb 31717 }
Marko Mikulicic 0:c0ecb8bf28eb 31718 }
Marko Mikulicic 0:c0ecb8bf28eb 31719 p = (char *) loot.caps[0].end;
Marko Mikulicic 0:c0ecb8bf28eb 31720 } while (flag_g && p < str_end);
Marko Mikulicic 0:c0ecb8bf28eb 31721 if (p <= str_end) {
Marko Mikulicic 0:c0ecb8bf28eb 31722 ptok->start = p;
Marko Mikulicic 0:c0ecb8bf28eb 31723 ptok->end = str_end;
Marko Mikulicic 0:c0ecb8bf28eb 31724 ptok++;
Marko Mikulicic 0:c0ecb8bf28eb 31725 out_sub_num++;
Marko Mikulicic 0:c0ecb8bf28eb 31726 }
Marko Mikulicic 0:c0ecb8bf28eb 31727 out_str_o = v7_mk_string(v7, NULL, 0, 1);
Marko Mikulicic 0:c0ecb8bf28eb 31728 ptok = out_sub;
Marko Mikulicic 0:c0ecb8bf28eb 31729 do {
Marko Mikulicic 0:c0ecb8bf28eb 31730 size_t ln = ptok->end - ptok->start;
Marko Mikulicic 0:c0ecb8bf28eb 31731 const char *ps = ptok->start;
Marko Mikulicic 0:c0ecb8bf28eb 31732 if (ptok->start >= old_owned_mbuf_base &&
Marko Mikulicic 0:c0ecb8bf28eb 31733 ptok->start < old_owned_mbuf_end) {
Marko Mikulicic 0:c0ecb8bf28eb 31734 ps += v7->owned_strings.buf - old_owned_mbuf_base;
Marko Mikulicic 0:c0ecb8bf28eb 31735 }
Marko Mikulicic 0:c0ecb8bf28eb 31736 out_str_o = s_concat(v7, out_str_o, v7_mk_string(v7, ps, ln, 1));
Marko Mikulicic 0:c0ecb8bf28eb 31737 p += ln;
Marko Mikulicic 0:c0ecb8bf28eb 31738 ptok++;
Marko Mikulicic 0:c0ecb8bf28eb 31739 } while (--out_sub_num);
Marko Mikulicic 0:c0ecb8bf28eb 31740
Marko Mikulicic 0:c0ecb8bf28eb 31741 *res = out_str_o;
Marko Mikulicic 0:c0ecb8bf28eb 31742 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31743 }
Marko Mikulicic 0:c0ecb8bf28eb 31744
Marko Mikulicic 0:c0ecb8bf28eb 31745 *res = this_obj;
Marko Mikulicic 0:c0ecb8bf28eb 31746
Marko Mikulicic 0:c0ecb8bf28eb 31747 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31748 if (tmp_str_buf != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 31749 free(tmp_str_buf);
Marko Mikulicic 0:c0ecb8bf28eb 31750 tmp_str_buf = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 31751 }
Marko Mikulicic 0:c0ecb8bf28eb 31752 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31753 }
Marko Mikulicic 0:c0ecb8bf28eb 31754
Marko Mikulicic 0:c0ecb8bf28eb 31755 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31756 V7_PRIVATE enum v7_err Str_search(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31757 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31758 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31759 long utf_shift = -1;
Marko Mikulicic 0:c0ecb8bf28eb 31760
Marko Mikulicic 0:c0ecb8bf28eb 31761 if (v7_argc(v7) > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 31762 size_t s_len;
Marko Mikulicic 0:c0ecb8bf28eb 31763 struct slre_loot sub;
Marko Mikulicic 0:c0ecb8bf28eb 31764 val_t so = V7_UNDEFINED, ro = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 31765 const char *s;
Marko Mikulicic 0:c0ecb8bf28eb 31766
Marko Mikulicic 0:c0ecb8bf28eb 31767 rcode = obj_value_of(v7, v7_arg(v7, 0), &ro);
Marko Mikulicic 0:c0ecb8bf28eb 31768 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31769 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31770 }
Marko Mikulicic 0:c0ecb8bf28eb 31771
Marko Mikulicic 0:c0ecb8bf28eb 31772 if (!v7_is_regexp(v7, ro)) {
Marko Mikulicic 0:c0ecb8bf28eb 31773 rcode = call_regex_ctor(v7, ro, &ro);
Marko Mikulicic 0:c0ecb8bf28eb 31774 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31775 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31776 }
Marko Mikulicic 0:c0ecb8bf28eb 31777 }
Marko Mikulicic 0:c0ecb8bf28eb 31778
Marko Mikulicic 0:c0ecb8bf28eb 31779 rcode = to_string(v7, this_obj, &so, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31780 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31781 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31782 }
Marko Mikulicic 0:c0ecb8bf28eb 31783
Marko Mikulicic 0:c0ecb8bf28eb 31784 s = v7_get_string(v7, &so, &s_len);
Marko Mikulicic 0:c0ecb8bf28eb 31785
Marko Mikulicic 0:c0ecb8bf28eb 31786 if (!slre_exec(v7_get_regexp_struct(v7, ro)->compiled_regexp, 0, s,
Marko Mikulicic 0:c0ecb8bf28eb 31787 s + s_len, &sub))
Marko Mikulicic 0:c0ecb8bf28eb 31788 utf_shift = utfnlen(s, sub.caps[0].start - s); /* calc shift for UTF-8 */
Marko Mikulicic 0:c0ecb8bf28eb 31789 } else {
Marko Mikulicic 0:c0ecb8bf28eb 31790 utf_shift = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31791 }
Marko Mikulicic 0:c0ecb8bf28eb 31792
Marko Mikulicic 0:c0ecb8bf28eb 31793 *res = v7_mk_number(v7, utf_shift);
Marko Mikulicic 0:c0ecb8bf28eb 31794
Marko Mikulicic 0:c0ecb8bf28eb 31795 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31796 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31797 }
Marko Mikulicic 0:c0ecb8bf28eb 31798
Marko Mikulicic 0:c0ecb8bf28eb 31799 #endif /* V7_ENABLE__RegExp */
Marko Mikulicic 0:c0ecb8bf28eb 31800
Marko Mikulicic 0:c0ecb8bf28eb 31801 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31802 V7_PRIVATE enum v7_err Str_slice(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31803 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31804 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31805 long from = 0, to = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31806 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 31807 val_t so = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 31808 const char *begin, *end;
Marko Mikulicic 0:c0ecb8bf28eb 31809 int num_args = v7_argc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31810
Marko Mikulicic 0:c0ecb8bf28eb 31811 rcode = to_string(v7, this_obj, &so, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31812 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31813 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31814 }
Marko Mikulicic 0:c0ecb8bf28eb 31815
Marko Mikulicic 0:c0ecb8bf28eb 31816 begin = v7_get_string(v7, &so, &len);
Marko Mikulicic 0:c0ecb8bf28eb 31817
Marko Mikulicic 0:c0ecb8bf28eb 31818 to = len = utfnlen(begin, len);
Marko Mikulicic 0:c0ecb8bf28eb 31819 if (num_args > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 31820 rcode = to_long(v7, v7_arg(v7, 0), 0, &from);
Marko Mikulicic 0:c0ecb8bf28eb 31821 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31822 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31823 }
Marko Mikulicic 0:c0ecb8bf28eb 31824
Marko Mikulicic 0:c0ecb8bf28eb 31825 if (from < 0) {
Marko Mikulicic 0:c0ecb8bf28eb 31826 from += len;
Marko Mikulicic 0:c0ecb8bf28eb 31827 if (from < 0) from = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31828 } else if ((size_t) from > len)
Marko Mikulicic 0:c0ecb8bf28eb 31829 from = len;
Marko Mikulicic 0:c0ecb8bf28eb 31830 if (num_args > 1) {
Marko Mikulicic 0:c0ecb8bf28eb 31831 rcode = to_long(v7, v7_arg(v7, 1), 0, &to);
Marko Mikulicic 0:c0ecb8bf28eb 31832 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31833 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31834 }
Marko Mikulicic 0:c0ecb8bf28eb 31835
Marko Mikulicic 0:c0ecb8bf28eb 31836 if (to < 0) {
Marko Mikulicic 0:c0ecb8bf28eb 31837 to += len;
Marko Mikulicic 0:c0ecb8bf28eb 31838 if (to < 0) to = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31839 } else if ((size_t) to > len)
Marko Mikulicic 0:c0ecb8bf28eb 31840 to = len;
Marko Mikulicic 0:c0ecb8bf28eb 31841 }
Marko Mikulicic 0:c0ecb8bf28eb 31842 }
Marko Mikulicic 0:c0ecb8bf28eb 31843
Marko Mikulicic 0:c0ecb8bf28eb 31844 if (from > to) to = from;
Marko Mikulicic 0:c0ecb8bf28eb 31845 end = utfnshift(begin, to);
Marko Mikulicic 0:c0ecb8bf28eb 31846 begin = utfnshift(begin, from);
Marko Mikulicic 0:c0ecb8bf28eb 31847
Marko Mikulicic 0:c0ecb8bf28eb 31848 *res = v7_mk_string(v7, begin, end - begin, 1);
Marko Mikulicic 0:c0ecb8bf28eb 31849
Marko Mikulicic 0:c0ecb8bf28eb 31850 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31851 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31852 }
Marko Mikulicic 0:c0ecb8bf28eb 31853
Marko Mikulicic 0:c0ecb8bf28eb 31854 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31855 static enum v7_err s_transform(struct v7 *v7, val_t obj, Rune (*func)(Rune),
Marko Mikulicic 0:c0ecb8bf28eb 31856 val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31857 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31858 val_t s = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 31859 size_t i, n, len;
Marko Mikulicic 0:c0ecb8bf28eb 31860 const char *p2, *p;
Marko Mikulicic 0:c0ecb8bf28eb 31861
Marko Mikulicic 0:c0ecb8bf28eb 31862 rcode = to_string(v7, obj, &s, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 31863 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31864 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31865 }
Marko Mikulicic 0:c0ecb8bf28eb 31866
Marko Mikulicic 0:c0ecb8bf28eb 31867 p = v7_get_string(v7, &s, &len);
Marko Mikulicic 0:c0ecb8bf28eb 31868
Marko Mikulicic 0:c0ecb8bf28eb 31869 /* Pass NULL to make sure we're not creating dictionary value */
Marko Mikulicic 0:c0ecb8bf28eb 31870 *res = v7_mk_string(v7, NULL, len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 31871
Marko Mikulicic 0:c0ecb8bf28eb 31872 {
Marko Mikulicic 0:c0ecb8bf28eb 31873 Rune r;
Marko Mikulicic 0:c0ecb8bf28eb 31874 p2 = v7_get_string(v7, res, &len);
Marko Mikulicic 0:c0ecb8bf28eb 31875 for (i = 0; i < len; i += n) {
Marko Mikulicic 0:c0ecb8bf28eb 31876 n = chartorune(&r, p + i);
Marko Mikulicic 0:c0ecb8bf28eb 31877 r = func(r);
Marko Mikulicic 0:c0ecb8bf28eb 31878 runetochar((char *) p2 + i, &r);
Marko Mikulicic 0:c0ecb8bf28eb 31879 }
Marko Mikulicic 0:c0ecb8bf28eb 31880 }
Marko Mikulicic 0:c0ecb8bf28eb 31881
Marko Mikulicic 0:c0ecb8bf28eb 31882 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31883 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31884 }
Marko Mikulicic 0:c0ecb8bf28eb 31885
Marko Mikulicic 0:c0ecb8bf28eb 31886 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31887 V7_PRIVATE enum v7_err Str_toLowerCase(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31888 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31889 return s_transform(v7, this_obj, tolowerrune, res);
Marko Mikulicic 0:c0ecb8bf28eb 31890 }
Marko Mikulicic 0:c0ecb8bf28eb 31891
Marko Mikulicic 0:c0ecb8bf28eb 31892 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31893 V7_PRIVATE enum v7_err Str_toUpperCase(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31894 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31895 return s_transform(v7, this_obj, toupperrune, res);
Marko Mikulicic 0:c0ecb8bf28eb 31896 }
Marko Mikulicic 0:c0ecb8bf28eb 31897
Marko Mikulicic 0:c0ecb8bf28eb 31898 static int s_isspace(Rune c) {
Marko Mikulicic 0:c0ecb8bf28eb 31899 return isspacerune(c) || isnewline(c);
Marko Mikulicic 0:c0ecb8bf28eb 31900 }
Marko Mikulicic 0:c0ecb8bf28eb 31901
Marko Mikulicic 0:c0ecb8bf28eb 31902 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31903 V7_PRIVATE enum v7_err Str_trim(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31904 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31905 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31906 val_t s = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 31907 size_t i, n, len, start = 0, end, state = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31908 const char *p;
Marko Mikulicic 0:c0ecb8bf28eb 31909 Rune r;
Marko Mikulicic 0:c0ecb8bf28eb 31910
Marko Mikulicic 0:c0ecb8bf28eb 31911 rcode = to_string(v7, this_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 p = v7_get_string(v7, &s, &len);
Marko Mikulicic 0:c0ecb8bf28eb 31916
Marko Mikulicic 0:c0ecb8bf28eb 31917 end = len;
Marko Mikulicic 0:c0ecb8bf28eb 31918 for (i = 0; i < len; i += n) {
Marko Mikulicic 0:c0ecb8bf28eb 31919 n = chartorune(&r, p + i);
Marko Mikulicic 0:c0ecb8bf28eb 31920 if (!s_isspace(r)) {
Marko Mikulicic 0:c0ecb8bf28eb 31921 if (state++ == 0) start = i;
Marko Mikulicic 0:c0ecb8bf28eb 31922 end = i + n;
Marko Mikulicic 0:c0ecb8bf28eb 31923 }
Marko Mikulicic 0:c0ecb8bf28eb 31924 }
Marko Mikulicic 0:c0ecb8bf28eb 31925
Marko Mikulicic 0:c0ecb8bf28eb 31926 *res = v7_mk_string(v7, p + start, end - start, 1);
Marko Mikulicic 0:c0ecb8bf28eb 31927
Marko Mikulicic 0:c0ecb8bf28eb 31928 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31929 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31930 }
Marko Mikulicic 0:c0ecb8bf28eb 31931
Marko Mikulicic 0:c0ecb8bf28eb 31932 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31933 V7_PRIVATE enum v7_err Str_length(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31934 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31935 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31936 size_t len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31937 val_t s = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 31938
Marko Mikulicic 0:c0ecb8bf28eb 31939 rcode = obj_value_of(v7, this_obj, &s);
Marko Mikulicic 0:c0ecb8bf28eb 31940 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31941 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31942 }
Marko Mikulicic 0:c0ecb8bf28eb 31943
Marko Mikulicic 0:c0ecb8bf28eb 31944 if (v7_is_string(s)) {
Marko Mikulicic 0:c0ecb8bf28eb 31945 const char *p = v7_get_string(v7, &s, &len);
Marko Mikulicic 0:c0ecb8bf28eb 31946 len = utfnlen(p, len);
Marko Mikulicic 0:c0ecb8bf28eb 31947 }
Marko Mikulicic 0:c0ecb8bf28eb 31948
Marko Mikulicic 0:c0ecb8bf28eb 31949 *res = v7_mk_number(v7, len);
Marko Mikulicic 0:c0ecb8bf28eb 31950 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31951 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31952 }
Marko Mikulicic 0:c0ecb8bf28eb 31953
Marko Mikulicic 0:c0ecb8bf28eb 31954 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31955 V7_PRIVATE enum v7_err Str_at(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31956 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31957 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31958 long arg0;
Marko Mikulicic 0:c0ecb8bf28eb 31959 val_t s = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 31960
Marko Mikulicic 0:c0ecb8bf28eb 31961 rcode = to_long(v7, v7_arg(v7, 0), -1, &arg0);
Marko Mikulicic 0:c0ecb8bf28eb 31962 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31963 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31964 }
Marko Mikulicic 0:c0ecb8bf28eb 31965
Marko Mikulicic 0:c0ecb8bf28eb 31966 rcode = obj_value_of(v7, this_obj, &s);
Marko Mikulicic 0:c0ecb8bf28eb 31967 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31968 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31969 }
Marko Mikulicic 0:c0ecb8bf28eb 31970
Marko Mikulicic 0:c0ecb8bf28eb 31971 if (v7_is_string(s)) {
Marko Mikulicic 0:c0ecb8bf28eb 31972 size_t n;
Marko Mikulicic 0:c0ecb8bf28eb 31973 const unsigned char *p = (unsigned char *) v7_get_string(v7, &s, &n);
Marko Mikulicic 0:c0ecb8bf28eb 31974 if (arg0 >= 0 && (size_t) arg0 < n) {
Marko Mikulicic 0:c0ecb8bf28eb 31975 *res = v7_mk_number(v7, p[arg0]);
Marko Mikulicic 0:c0ecb8bf28eb 31976 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31977 }
Marko Mikulicic 0:c0ecb8bf28eb 31978 }
Marko Mikulicic 0:c0ecb8bf28eb 31979
Marko Mikulicic 0:c0ecb8bf28eb 31980 *res = v7_mk_number(v7, NAN);
Marko Mikulicic 0:c0ecb8bf28eb 31981
Marko Mikulicic 0:c0ecb8bf28eb 31982 clean:
Marko Mikulicic 0:c0ecb8bf28eb 31983 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 31984 }
Marko Mikulicic 0:c0ecb8bf28eb 31985
Marko Mikulicic 0:c0ecb8bf28eb 31986 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 31987 V7_PRIVATE enum v7_err Str_blen(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 31988 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 31989 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 31990 size_t len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 31991 val_t s = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 31992
Marko Mikulicic 0:c0ecb8bf28eb 31993 rcode = obj_value_of(v7, this_obj, &s);
Marko Mikulicic 0:c0ecb8bf28eb 31994 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 31995 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 31996 }
Marko Mikulicic 0:c0ecb8bf28eb 31997
Marko Mikulicic 0:c0ecb8bf28eb 31998 if (v7_is_string(s)) {
Marko Mikulicic 0:c0ecb8bf28eb 31999 v7_get_string(v7, &s, &len);
Marko Mikulicic 0:c0ecb8bf28eb 32000 }
Marko Mikulicic 0:c0ecb8bf28eb 32001
Marko Mikulicic 0:c0ecb8bf28eb 32002 *res = v7_mk_number(v7, len);
Marko Mikulicic 0:c0ecb8bf28eb 32003
Marko Mikulicic 0:c0ecb8bf28eb 32004 clean:
Marko Mikulicic 0:c0ecb8bf28eb 32005 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 32006 }
Marko Mikulicic 0:c0ecb8bf28eb 32007
Marko Mikulicic 0:c0ecb8bf28eb 32008 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 32009 static enum v7_err s_substr(struct v7 *v7, val_t s, long start, long len,
Marko Mikulicic 0:c0ecb8bf28eb 32010 val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 32011 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 32012 size_t n;
Marko Mikulicic 0:c0ecb8bf28eb 32013 const char *p;
Marko Mikulicic 0:c0ecb8bf28eb 32014
Marko Mikulicic 0:c0ecb8bf28eb 32015 rcode = to_string(v7, s, &s, NULL, 0, NULL);
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 p = v7_get_string(v7, &s, &n);
Marko Mikulicic 0:c0ecb8bf28eb 32021 n = utfnlen(p, n);
Marko Mikulicic 0:c0ecb8bf28eb 32022
Marko Mikulicic 0:c0ecb8bf28eb 32023 if (start < (long) n && len > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32024 if (start < 0) start = (long) n + start;
Marko Mikulicic 0:c0ecb8bf28eb 32025 if (start < 0) start = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32026
Marko Mikulicic 0:c0ecb8bf28eb 32027 if (start > (long) n) start = n;
Marko Mikulicic 0:c0ecb8bf28eb 32028 if (len < 0) len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32029 if (len > (long) n - start) len = n - start;
Marko Mikulicic 0:c0ecb8bf28eb 32030 p = utfnshift(p, start);
Marko Mikulicic 0:c0ecb8bf28eb 32031 } else {
Marko Mikulicic 0:c0ecb8bf28eb 32032 len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32033 }
Marko Mikulicic 0:c0ecb8bf28eb 32034
Marko Mikulicic 0:c0ecb8bf28eb 32035 *res = v7_mk_string(v7, p, len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 32036
Marko Mikulicic 0:c0ecb8bf28eb 32037 clean:
Marko Mikulicic 0:c0ecb8bf28eb 32038 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 32039 }
Marko Mikulicic 0:c0ecb8bf28eb 32040
Marko Mikulicic 0:c0ecb8bf28eb 32041 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 32042 V7_PRIVATE enum v7_err Str_substr(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 32043 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 32044 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 32045 long start, len;
Marko Mikulicic 0:c0ecb8bf28eb 32046
Marko Mikulicic 0:c0ecb8bf28eb 32047 rcode = to_long(v7, v7_arg(v7, 0), 0, &start);
Marko Mikulicic 0:c0ecb8bf28eb 32048 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32049 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32050 }
Marko Mikulicic 0:c0ecb8bf28eb 32051
Marko Mikulicic 0:c0ecb8bf28eb 32052 rcode = to_long(v7, v7_arg(v7, 1), LONG_MAX, &len);
Marko Mikulicic 0:c0ecb8bf28eb 32053 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32054 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32055 }
Marko Mikulicic 0:c0ecb8bf28eb 32056
Marko Mikulicic 0:c0ecb8bf28eb 32057 rcode = s_substr(v7, this_obj, start, len, res);
Marko Mikulicic 0:c0ecb8bf28eb 32058 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32059 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32060 }
Marko Mikulicic 0:c0ecb8bf28eb 32061
Marko Mikulicic 0:c0ecb8bf28eb 32062 clean:
Marko Mikulicic 0:c0ecb8bf28eb 32063 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 32064 }
Marko Mikulicic 0:c0ecb8bf28eb 32065
Marko Mikulicic 0:c0ecb8bf28eb 32066 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 32067 V7_PRIVATE enum v7_err Str_substring(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 32068 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 32069 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 32070 long start, end;
Marko Mikulicic 0:c0ecb8bf28eb 32071
Marko Mikulicic 0:c0ecb8bf28eb 32072 rcode = to_long(v7, v7_arg(v7, 0), 0, &start);
Marko Mikulicic 0:c0ecb8bf28eb 32073 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32074 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32075 }
Marko Mikulicic 0:c0ecb8bf28eb 32076
Marko Mikulicic 0:c0ecb8bf28eb 32077 rcode = to_long(v7, v7_arg(v7, 1), LONG_MAX, &end);
Marko Mikulicic 0:c0ecb8bf28eb 32078 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32079 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32080 }
Marko Mikulicic 0:c0ecb8bf28eb 32081
Marko Mikulicic 0:c0ecb8bf28eb 32082 if (start < 0) start = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32083 if (end < 0) end = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32084 if (start > end) {
Marko Mikulicic 0:c0ecb8bf28eb 32085 long tmp = start;
Marko Mikulicic 0:c0ecb8bf28eb 32086 start = end;
Marko Mikulicic 0:c0ecb8bf28eb 32087 end = tmp;
Marko Mikulicic 0:c0ecb8bf28eb 32088 }
Marko Mikulicic 0:c0ecb8bf28eb 32089
Marko Mikulicic 0:c0ecb8bf28eb 32090 rcode = s_substr(v7, this_obj, start, end - start, res);
Marko Mikulicic 0:c0ecb8bf28eb 32091 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32092
Marko Mikulicic 0:c0ecb8bf28eb 32093 clean:
Marko Mikulicic 0:c0ecb8bf28eb 32094 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 32095 }
Marko Mikulicic 0:c0ecb8bf28eb 32096
Marko Mikulicic 0:c0ecb8bf28eb 32097 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 32098 V7_PRIVATE enum v7_err Str_split(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 32099 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 32100 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 32101 const char *s, *s_end;
Marko Mikulicic 0:c0ecb8bf28eb 32102 size_t s_len;
Marko Mikulicic 0:c0ecb8bf28eb 32103 long num_args = v7_argc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 32104 rcode = to_string(v7, this_obj, &this_obj, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 32105 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32106 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32107 }
Marko Mikulicic 0:c0ecb8bf28eb 32108 s = v7_get_string(v7, &this_obj, &s_len);
Marko Mikulicic 0:c0ecb8bf28eb 32109 s_end = s + s_len;
Marko Mikulicic 0:c0ecb8bf28eb 32110
Marko Mikulicic 0:c0ecb8bf28eb 32111 *res = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 32112
Marko Mikulicic 0:c0ecb8bf28eb 32113 if (num_args == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32114 /*
Marko Mikulicic 0:c0ecb8bf28eb 32115 * No arguments were given: resulting array will contain just a single
Marko Mikulicic 0:c0ecb8bf28eb 32116 * element: the source string
Marko Mikulicic 0:c0ecb8bf28eb 32117 */
Marko Mikulicic 0:c0ecb8bf28eb 32118 rcode = v7_array_push_throwing(v7, *res, this_obj, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 32119 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32120 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32121 }
Marko Mikulicic 0:c0ecb8bf28eb 32122 } else {
Marko Mikulicic 0:c0ecb8bf28eb 32123 val_t ro = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 32124 long elem, limit;
Marko Mikulicic 0:c0ecb8bf28eb 32125 size_t lookup_idx = 0, substr_idx = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32126 struct _str_split_ctx ctx;
Marko Mikulicic 0:c0ecb8bf28eb 32127
Marko Mikulicic 0:c0ecb8bf28eb 32128 rcode = to_long(v7, v7_arg(v7, 1), LONG_MAX, &limit);
Marko Mikulicic 0:c0ecb8bf28eb 32129 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32130 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32131 }
Marko Mikulicic 0:c0ecb8bf28eb 32132
Marko Mikulicic 0:c0ecb8bf28eb 32133 rcode = obj_value_of(v7, v7_arg(v7, 0), &ro);
Marko Mikulicic 0:c0ecb8bf28eb 32134 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32135 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32136 }
Marko Mikulicic 0:c0ecb8bf28eb 32137
Marko Mikulicic 0:c0ecb8bf28eb 32138 /* Initialize substring context depending on the argument type */
Marko Mikulicic 0:c0ecb8bf28eb 32139 if (v7_is_regexp(v7, ro)) {
Marko Mikulicic 0:c0ecb8bf28eb 32140 /* use RegExp implementation */
Marko Mikulicic 0:c0ecb8bf28eb 32141 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 32142 ctx.p_init = subs_regexp_init;
Marko Mikulicic 0:c0ecb8bf28eb 32143 ctx.p_exec = subs_regexp_exec;
Marko Mikulicic 0:c0ecb8bf28eb 32144 ctx.p_add_caps = subs_regexp_split_add_caps;
Marko Mikulicic 0:c0ecb8bf28eb 32145 #else
Marko Mikulicic 0:c0ecb8bf28eb 32146 assert(0);
Marko Mikulicic 0:c0ecb8bf28eb 32147 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32148 } else {
Marko Mikulicic 0:c0ecb8bf28eb 32149 /*
Marko Mikulicic 0:c0ecb8bf28eb 32150 * use String implementation: first of all, convert to String (if it's
Marko Mikulicic 0:c0ecb8bf28eb 32151 * not already a String)
Marko Mikulicic 0:c0ecb8bf28eb 32152 */
Marko Mikulicic 0:c0ecb8bf28eb 32153 rcode = to_string(v7, ro, &ro, 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
Marko Mikulicic 0:c0ecb8bf28eb 32158 ctx.p_init = subs_string_init;
Marko Mikulicic 0:c0ecb8bf28eb 32159 ctx.p_exec = subs_string_exec;
Marko Mikulicic 0:c0ecb8bf28eb 32160 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 32161 ctx.p_add_caps = subs_string_split_add_caps;
Marko Mikulicic 0:c0ecb8bf28eb 32162 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32163 }
Marko Mikulicic 0:c0ecb8bf28eb 32164 /* initialize context */
Marko Mikulicic 0:c0ecb8bf28eb 32165 ctx.p_init(&ctx, v7, ro);
Marko Mikulicic 0:c0ecb8bf28eb 32166
Marko Mikulicic 0:c0ecb8bf28eb 32167 if (s_len == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32168 /*
Marko Mikulicic 0:c0ecb8bf28eb 32169 * if `this` is (or converts to) an empty string, resulting array should
Marko Mikulicic 0:c0ecb8bf28eb 32170 * contain empty string if only separator does not match an empty string.
Marko Mikulicic 0:c0ecb8bf28eb 32171 * Otherwise, the array is left empty
Marko Mikulicic 0:c0ecb8bf28eb 32172 */
Marko Mikulicic 0:c0ecb8bf28eb 32173 int matches_empty = !ctx.p_exec(&ctx, s, s);
Marko Mikulicic 0:c0ecb8bf28eb 32174 if (!matches_empty) {
Marko Mikulicic 0:c0ecb8bf28eb 32175 rcode = v7_array_push_throwing(v7, *res, this_obj, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 32176 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32177 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32178 }
Marko Mikulicic 0:c0ecb8bf28eb 32179 }
Marko Mikulicic 0:c0ecb8bf28eb 32180 } else {
Marko Mikulicic 0:c0ecb8bf28eb 32181 size_t last_match_len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32182
Marko Mikulicic 0:c0ecb8bf28eb 32183 for (elem = 0; elem < limit && lookup_idx < s_len;) {
Marko Mikulicic 0:c0ecb8bf28eb 32184 size_t substr_len;
Marko Mikulicic 0:c0ecb8bf28eb 32185 /* find next match, and break if there's no match */
Marko Mikulicic 0:c0ecb8bf28eb 32186 if (ctx.p_exec(&ctx, s + lookup_idx, s_end)) break;
Marko Mikulicic 0:c0ecb8bf28eb 32187
Marko Mikulicic 0:c0ecb8bf28eb 32188 last_match_len = ctx.match_end - ctx.match_start;
Marko Mikulicic 0:c0ecb8bf28eb 32189 substr_len = ctx.match_start - s - substr_idx;
Marko Mikulicic 0:c0ecb8bf28eb 32190
Marko Mikulicic 0:c0ecb8bf28eb 32191 /* add next substring to the resulting array, if needed */
Marko Mikulicic 0:c0ecb8bf28eb 32192 if (substr_len > 0 || last_match_len > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32193 rcode = v7_array_push_throwing(
Marko Mikulicic 0:c0ecb8bf28eb 32194 v7, *res, v7_mk_string(v7, s + substr_idx, substr_len, 1), NULL);
Marko Mikulicic 0:c0ecb8bf28eb 32195 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32196 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32197 }
Marko Mikulicic 0:c0ecb8bf28eb 32198 elem++;
Marko Mikulicic 0:c0ecb8bf28eb 32199
Marko Mikulicic 0:c0ecb8bf28eb 32200 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 32201 /* Add captures (for RegExp only) */
Marko Mikulicic 0:c0ecb8bf28eb 32202 elem = ctx.p_add_caps(&ctx, *res, elem, limit);
Marko Mikulicic 0:c0ecb8bf28eb 32203 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32204 }
Marko Mikulicic 0:c0ecb8bf28eb 32205
Marko Mikulicic 0:c0ecb8bf28eb 32206 /* advance lookup_idx appropriately */
Marko Mikulicic 0:c0ecb8bf28eb 32207 if (last_match_len == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32208 /* empty match: advance to the next char */
Marko Mikulicic 0:c0ecb8bf28eb 32209 const char *next = utfnshift((s + lookup_idx), 1);
Marko Mikulicic 0:c0ecb8bf28eb 32210 lookup_idx += (next - (s + lookup_idx));
Marko Mikulicic 0:c0ecb8bf28eb 32211 } else {
Marko Mikulicic 0:c0ecb8bf28eb 32212 /* non-empty match: advance to the end of match */
Marko Mikulicic 0:c0ecb8bf28eb 32213 lookup_idx = ctx.match_end - s;
Marko Mikulicic 0:c0ecb8bf28eb 32214 }
Marko Mikulicic 0:c0ecb8bf28eb 32215
Marko Mikulicic 0:c0ecb8bf28eb 32216 /*
Marko Mikulicic 0:c0ecb8bf28eb 32217 * always remember the end of the match, so that next time we will take
Marko Mikulicic 0:c0ecb8bf28eb 32218 * substring from that position
Marko Mikulicic 0:c0ecb8bf28eb 32219 */
Marko Mikulicic 0:c0ecb8bf28eb 32220 substr_idx = ctx.match_end - s;
Marko Mikulicic 0:c0ecb8bf28eb 32221 }
Marko Mikulicic 0:c0ecb8bf28eb 32222
Marko Mikulicic 0:c0ecb8bf28eb 32223 /* add the last substring to the resulting array, if needed */
Marko Mikulicic 0:c0ecb8bf28eb 32224 if (elem < limit) {
Marko Mikulicic 0:c0ecb8bf28eb 32225 size_t substr_len = s_len - substr_idx;
Marko Mikulicic 0:c0ecb8bf28eb 32226 if (substr_len > 0 || last_match_len > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32227 rcode = v7_array_push_throwing(
Marko Mikulicic 0:c0ecb8bf28eb 32228 v7, *res, v7_mk_string(v7, s + substr_idx, substr_len, 1), NULL);
Marko Mikulicic 0:c0ecb8bf28eb 32229 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32230 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32231 }
Marko Mikulicic 0:c0ecb8bf28eb 32232 }
Marko Mikulicic 0:c0ecb8bf28eb 32233 }
Marko Mikulicic 0:c0ecb8bf28eb 32234 }
Marko Mikulicic 0:c0ecb8bf28eb 32235 }
Marko Mikulicic 0:c0ecb8bf28eb 32236
Marko Mikulicic 0:c0ecb8bf28eb 32237 clean:
Marko Mikulicic 0:c0ecb8bf28eb 32238 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 32239 }
Marko Mikulicic 0:c0ecb8bf28eb 32240
Marko Mikulicic 0:c0ecb8bf28eb 32241 V7_PRIVATE void init_string(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 32242 val_t str = mk_cfunction_obj_with_proto(v7, String_ctor, 1,
Marko Mikulicic 0:c0ecb8bf28eb 32243 v7->vals.string_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 32244 v7_def(v7, v7->vals.global_object, "String", 6, V7_DESC_ENUMERABLE(0), str);
Marko Mikulicic 0:c0ecb8bf28eb 32245
Marko Mikulicic 0:c0ecb8bf28eb 32246 set_cfunc_prop(v7, str, "fromCharCode", Str_fromCharCode);
Marko Mikulicic 0:c0ecb8bf28eb 32247 set_cfunc_prop(v7, v7->vals.string_prototype, "charCodeAt", Str_charCodeAt);
Marko Mikulicic 0:c0ecb8bf28eb 32248 set_cfunc_prop(v7, v7->vals.string_prototype, "charAt", Str_charAt);
Marko Mikulicic 0:c0ecb8bf28eb 32249 set_cfunc_prop(v7, v7->vals.string_prototype, "concat", Str_concat);
Marko Mikulicic 0:c0ecb8bf28eb 32250 set_cfunc_prop(v7, v7->vals.string_prototype, "indexOf", Str_indexOf);
Marko Mikulicic 0:c0ecb8bf28eb 32251 set_cfunc_prop(v7, v7->vals.string_prototype, "substr", Str_substr);
Marko Mikulicic 0:c0ecb8bf28eb 32252 set_cfunc_prop(v7, v7->vals.string_prototype, "substring", Str_substring);
Marko Mikulicic 0:c0ecb8bf28eb 32253 set_cfunc_prop(v7, v7->vals.string_prototype, "valueOf", Str_valueOf);
Marko Mikulicic 0:c0ecb8bf28eb 32254 set_cfunc_prop(v7, v7->vals.string_prototype, "lastIndexOf", Str_lastIndexOf);
Marko Mikulicic 0:c0ecb8bf28eb 32255 #if V7_ENABLE__String__localeCompare
Marko Mikulicic 0:c0ecb8bf28eb 32256 set_cfunc_prop(v7, v7->vals.string_prototype, "localeCompare",
Marko Mikulicic 0:c0ecb8bf28eb 32257 Str_localeCompare);
Marko Mikulicic 0:c0ecb8bf28eb 32258 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32259 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 32260 set_cfunc_prop(v7, v7->vals.string_prototype, "match", Str_match);
Marko Mikulicic 0:c0ecb8bf28eb 32261 set_cfunc_prop(v7, v7->vals.string_prototype, "replace", Str_replace);
Marko Mikulicic 0:c0ecb8bf28eb 32262 set_cfunc_prop(v7, v7->vals.string_prototype, "search", Str_search);
Marko Mikulicic 0:c0ecb8bf28eb 32263 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32264 set_cfunc_prop(v7, v7->vals.string_prototype, "split", Str_split);
Marko Mikulicic 0:c0ecb8bf28eb 32265 set_cfunc_prop(v7, v7->vals.string_prototype, "slice", Str_slice);
Marko Mikulicic 0:c0ecb8bf28eb 32266 set_cfunc_prop(v7, v7->vals.string_prototype, "trim", Str_trim);
Marko Mikulicic 0:c0ecb8bf28eb 32267 set_cfunc_prop(v7, v7->vals.string_prototype, "toLowerCase", Str_toLowerCase);
Marko Mikulicic 0:c0ecb8bf28eb 32268 #if V7_ENABLE__String__localeLowerCase
Marko Mikulicic 0:c0ecb8bf28eb 32269 set_cfunc_prop(v7, v7->vals.string_prototype, "toLocaleLowerCase",
Marko Mikulicic 0:c0ecb8bf28eb 32270 Str_toLowerCase);
Marko Mikulicic 0:c0ecb8bf28eb 32271 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32272 set_cfunc_prop(v7, v7->vals.string_prototype, "toUpperCase", Str_toUpperCase);
Marko Mikulicic 0:c0ecb8bf28eb 32273 #if V7_ENABLE__String__localeUpperCase
Marko Mikulicic 0:c0ecb8bf28eb 32274 set_cfunc_prop(v7, v7->vals.string_prototype, "toLocaleUpperCase",
Marko Mikulicic 0:c0ecb8bf28eb 32275 Str_toUpperCase);
Marko Mikulicic 0:c0ecb8bf28eb 32276 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32277 set_cfunc_prop(v7, v7->vals.string_prototype, "toString", Str_toString);
Marko Mikulicic 0:c0ecb8bf28eb 32278
Marko Mikulicic 0:c0ecb8bf28eb 32279 v7_def(v7, v7->vals.string_prototype, "length", 6, V7_DESC_GETTER(1),
Marko Mikulicic 0:c0ecb8bf28eb 32280 v7_mk_cfunction(Str_length));
Marko Mikulicic 0:c0ecb8bf28eb 32281
Marko Mikulicic 0:c0ecb8bf28eb 32282 /* Non-standard Cesanta extension */
Marko Mikulicic 0:c0ecb8bf28eb 32283 set_cfunc_prop(v7, v7->vals.string_prototype, "at", Str_at);
Marko Mikulicic 0:c0ecb8bf28eb 32284 v7_def(v7, v7->vals.string_prototype, "blen", 4, V7_DESC_GETTER(1),
Marko Mikulicic 0:c0ecb8bf28eb 32285 v7_mk_cfunction(Str_blen));
Marko Mikulicic 0:c0ecb8bf28eb 32286 }
Marko Mikulicic 0:c0ecb8bf28eb 32287 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 32288 #line 1 "v7/src/std_date.c"
Marko Mikulicic 0:c0ecb8bf28eb 32289 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32290 /*
Marko Mikulicic 0:c0ecb8bf28eb 32291 * Copyright (c) 2015 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 32292 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 32293 */
Marko Mikulicic 0:c0ecb8bf28eb 32294
Marko Mikulicic 0:c0ecb8bf28eb 32295 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 32296 /* Amalgamated: #include "common/str_util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 32297 /* Amalgamated: #include "v7/src/std_object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 32298 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 32299 /* Amalgamated: #include "v7/src/util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 32300 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 32301 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 32302 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 32303 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 32304 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 32305 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 32306
Marko Mikulicic 0:c0ecb8bf28eb 32307 #if V7_ENABLE__Date
Marko Mikulicic 0:c0ecb8bf28eb 32308
Marko Mikulicic 0:c0ecb8bf28eb 32309 #include <locale.h>
Marko Mikulicic 0:c0ecb8bf28eb 32310 #include <time.h>
Marko Mikulicic 0:c0ecb8bf28eb 32311
Marko Mikulicic 0:c0ecb8bf28eb 32312 #ifndef _WIN32
Marko Mikulicic 0:c0ecb8bf28eb 32313 extern long timezone;
Marko Mikulicic 0:c0ecb8bf28eb 32314 #include <sys/time.h>
Marko Mikulicic 0:c0ecb8bf28eb 32315 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32316
Marko Mikulicic 0:c0ecb8bf28eb 32317 #if defined(_MSC_VER)
Marko Mikulicic 0:c0ecb8bf28eb 32318 #define timezone _timezone
Marko Mikulicic 0:c0ecb8bf28eb 32319 #define tzname _tzname
Marko Mikulicic 0:c0ecb8bf28eb 32320 #if _MSC_VER >= 1800
Marko Mikulicic 0:c0ecb8bf28eb 32321 #define tzset _tzset
Marko Mikulicic 0:c0ecb8bf28eb 32322 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32323 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32324
Marko Mikulicic 0:c0ecb8bf28eb 32325 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 32326 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 32327 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 32328
Marko Mikulicic 0:c0ecb8bf28eb 32329 typedef double etime_t; /* double is suitable type for ECMA time */
Marko Mikulicic 0:c0ecb8bf28eb 32330 /* inernally we have to use 64-bit integer for some operations */
Marko Mikulicic 0:c0ecb8bf28eb 32331 typedef int64_t etimeint_t;
Marko Mikulicic 0:c0ecb8bf28eb 32332 #define INVALID_TIME NAN
Marko Mikulicic 0:c0ecb8bf28eb 32333
Marko Mikulicic 0:c0ecb8bf28eb 32334 #define msPerDay 86400000
Marko Mikulicic 0:c0ecb8bf28eb 32335 #define HoursPerDay 24
Marko Mikulicic 0:c0ecb8bf28eb 32336 #define MinutesPerHour 60
Marko Mikulicic 0:c0ecb8bf28eb 32337 #define SecondsPerMinute 60
Marko Mikulicic 0:c0ecb8bf28eb 32338 #define SecondsPerHour 3600
Marko Mikulicic 0:c0ecb8bf28eb 32339 #define msPerSecond 1000
Marko Mikulicic 0:c0ecb8bf28eb 32340 #define msPerMinute 60000
Marko Mikulicic 0:c0ecb8bf28eb 32341 #define msPerHour 3600000
Marko Mikulicic 0:c0ecb8bf28eb 32342 #define MonthsInYear 12
Marko Mikulicic 0:c0ecb8bf28eb 32343
Marko Mikulicic 0:c0ecb8bf28eb 32344 /* ECMA alternative to struct tm */
Marko Mikulicic 0:c0ecb8bf28eb 32345 struct timeparts {
Marko Mikulicic 0:c0ecb8bf28eb 32346 int year; /* can be negative, up to +-282000 */
Marko Mikulicic 0:c0ecb8bf28eb 32347 int month; /* 0-11 */
Marko Mikulicic 0:c0ecb8bf28eb 32348 int day; /* 1-31 */
Marko Mikulicic 0:c0ecb8bf28eb 32349 int hour; /* 0-23 */
Marko Mikulicic 0:c0ecb8bf28eb 32350 int min; /* 0-59 */
Marko Mikulicic 0:c0ecb8bf28eb 32351 int sec; /* 0-59 */
Marko Mikulicic 0:c0ecb8bf28eb 32352 int msec;
Marko Mikulicic 0:c0ecb8bf28eb 32353 int dayofweek; /* 0-6 */
Marko Mikulicic 0:c0ecb8bf28eb 32354 };
Marko Mikulicic 0:c0ecb8bf28eb 32355
Marko Mikulicic 0:c0ecb8bf28eb 32356 static etimeint_t g_gmtoffms; /* timezone offset, ms, no DST */
Marko Mikulicic 0:c0ecb8bf28eb 32357 static const char *g_tzname; /* current timezone name */
Marko Mikulicic 0:c0ecb8bf28eb 32358
Marko Mikulicic 0:c0ecb8bf28eb 32359 /* Leap year formula copied from ECMA 5.1 standart as is */
Marko Mikulicic 0:c0ecb8bf28eb 32360 static int ecma_DaysInYear(int y) {
Marko Mikulicic 0:c0ecb8bf28eb 32361 if (y % 4 != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32362 return 365;
Marko Mikulicic 0:c0ecb8bf28eb 32363 } else if (y % 4 == 0 && y % 100 != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32364 return 366;
Marko Mikulicic 0:c0ecb8bf28eb 32365 } else if (y % 100 == 0 && y % 400 != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32366 return 365;
Marko Mikulicic 0:c0ecb8bf28eb 32367 } else if (y % 400 == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32368 return 366;
Marko Mikulicic 0:c0ecb8bf28eb 32369 } else {
Marko Mikulicic 0:c0ecb8bf28eb 32370 return 365;
Marko Mikulicic 0:c0ecb8bf28eb 32371 }
Marko Mikulicic 0:c0ecb8bf28eb 32372 }
Marko Mikulicic 0:c0ecb8bf28eb 32373
Marko Mikulicic 0:c0ecb8bf28eb 32374 static etimeint_t ecma_DayFromYear(etimeint_t y) {
Marko Mikulicic 0:c0ecb8bf28eb 32375 return 365 * (y - 1970) + floor((y - 1969) / 4) - floor((y - 1901) / 100) +
Marko Mikulicic 0:c0ecb8bf28eb 32376 floor((y - 1601) / 400);
Marko Mikulicic 0:c0ecb8bf28eb 32377 }
Marko Mikulicic 0:c0ecb8bf28eb 32378
Marko Mikulicic 0:c0ecb8bf28eb 32379 static etimeint_t ecma_TimeFromYear(etimeint_t y) {
Marko Mikulicic 0:c0ecb8bf28eb 32380 return msPerDay * ecma_DayFromYear(y);
Marko Mikulicic 0:c0ecb8bf28eb 32381 }
Marko Mikulicic 0:c0ecb8bf28eb 32382
Marko Mikulicic 0:c0ecb8bf28eb 32383 static int ecma_IsLeapYear(int year) {
Marko Mikulicic 0:c0ecb8bf28eb 32384 return ecma_DaysInYear(year) == 366;
Marko Mikulicic 0:c0ecb8bf28eb 32385 }
Marko Mikulicic 0:c0ecb8bf28eb 32386
Marko Mikulicic 0:c0ecb8bf28eb 32387 static int *ecma_getfirstdays(int isleap) {
Marko Mikulicic 0:c0ecb8bf28eb 32388 static int sdays[2][MonthsInYear + 1] = {
Marko Mikulicic 0:c0ecb8bf28eb 32389 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
Marko Mikulicic 0:c0ecb8bf28eb 32390 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}};
Marko Mikulicic 0:c0ecb8bf28eb 32391
Marko Mikulicic 0:c0ecb8bf28eb 32392 return sdays[isleap];
Marko Mikulicic 0:c0ecb8bf28eb 32393 }
Marko Mikulicic 0:c0ecb8bf28eb 32394
Marko Mikulicic 0:c0ecb8bf28eb 32395 static int ecma_DaylightSavingTA(etime_t t) {
Marko Mikulicic 0:c0ecb8bf28eb 32396 time_t time = t / 1000;
Marko Mikulicic 0:c0ecb8bf28eb 32397 /*
Marko Mikulicic 0:c0ecb8bf28eb 32398 * Win32 doesn't have locatime_r
Marko Mikulicic 0:c0ecb8bf28eb 32399 * nixes don't have localtime_s
Marko Mikulicic 0:c0ecb8bf28eb 32400 * as result using localtime
Marko Mikulicic 0:c0ecb8bf28eb 32401 */
Marko Mikulicic 0:c0ecb8bf28eb 32402 struct tm *tm = localtime(&time);
Marko Mikulicic 0:c0ecb8bf28eb 32403 if (tm == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 32404 /* doesn't work on windows for times before epoch */
Marko Mikulicic 0:c0ecb8bf28eb 32405 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 32406 }
Marko Mikulicic 0:c0ecb8bf28eb 32407 if (tm->tm_isdst > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32408 return msPerHour;
Marko Mikulicic 0:c0ecb8bf28eb 32409 } else {
Marko Mikulicic 0:c0ecb8bf28eb 32410 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 32411 }
Marko Mikulicic 0:c0ecb8bf28eb 32412 }
Marko Mikulicic 0:c0ecb8bf28eb 32413
Marko Mikulicic 0:c0ecb8bf28eb 32414 static int ecma_LocalTZA(void) {
Marko Mikulicic 0:c0ecb8bf28eb 32415 return (int) -g_gmtoffms;
Marko Mikulicic 0:c0ecb8bf28eb 32416 }
Marko Mikulicic 0:c0ecb8bf28eb 32417
Marko Mikulicic 0:c0ecb8bf28eb 32418 static etimeint_t ecma_UTC(etime_t t) {
Marko Mikulicic 0:c0ecb8bf28eb 32419 return t - ecma_LocalTZA() - ecma_DaylightSavingTA(t - ecma_LocalTZA());
Marko Mikulicic 0:c0ecb8bf28eb 32420 }
Marko Mikulicic 0:c0ecb8bf28eb 32421
Marko Mikulicic 0:c0ecb8bf28eb 32422 #if V7_ENABLE__Date__toString || V7_ENABLE__Date__toLocaleString || \
Marko Mikulicic 0:c0ecb8bf28eb 32423 V7_ENABLE__Date__toJSON || V7_ENABLE__Date__getters || \
Marko Mikulicic 0:c0ecb8bf28eb 32424 V7_ENABLE__Date__setters
Marko Mikulicic 0:c0ecb8bf28eb 32425 static int ecma_YearFromTime_s(etime_t t) {
Marko Mikulicic 0:c0ecb8bf28eb 32426 int first = floor((t / msPerDay) / 366) + 1970,
Marko Mikulicic 0:c0ecb8bf28eb 32427 last = floor((t / msPerDay) / 365) + 1970, middle = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32428
Marko Mikulicic 0:c0ecb8bf28eb 32429 if (last < first) {
Marko Mikulicic 0:c0ecb8bf28eb 32430 int temp = first;
Marko Mikulicic 0:c0ecb8bf28eb 32431 first = last;
Marko Mikulicic 0:c0ecb8bf28eb 32432 last = temp;
Marko Mikulicic 0:c0ecb8bf28eb 32433 }
Marko Mikulicic 0:c0ecb8bf28eb 32434
Marko Mikulicic 0:c0ecb8bf28eb 32435 while (last > first) {
Marko Mikulicic 0:c0ecb8bf28eb 32436 middle = (last + first) / 2;
Marko Mikulicic 0:c0ecb8bf28eb 32437 if (ecma_TimeFromYear(middle) > t) {
Marko Mikulicic 0:c0ecb8bf28eb 32438 last = middle - 1;
Marko Mikulicic 0:c0ecb8bf28eb 32439 } else {
Marko Mikulicic 0:c0ecb8bf28eb 32440 if (ecma_TimeFromYear(middle) <= t) {
Marko Mikulicic 0:c0ecb8bf28eb 32441 if (ecma_TimeFromYear(middle + 1) > t) {
Marko Mikulicic 0:c0ecb8bf28eb 32442 first = middle;
Marko Mikulicic 0:c0ecb8bf28eb 32443 break;
Marko Mikulicic 0:c0ecb8bf28eb 32444 }
Marko Mikulicic 0:c0ecb8bf28eb 32445 first = middle + 1;
Marko Mikulicic 0:c0ecb8bf28eb 32446 }
Marko Mikulicic 0:c0ecb8bf28eb 32447 }
Marko Mikulicic 0:c0ecb8bf28eb 32448 }
Marko Mikulicic 0:c0ecb8bf28eb 32449
Marko Mikulicic 0:c0ecb8bf28eb 32450 return first;
Marko Mikulicic 0:c0ecb8bf28eb 32451 }
Marko Mikulicic 0:c0ecb8bf28eb 32452
Marko Mikulicic 0:c0ecb8bf28eb 32453 static etimeint_t ecma_Day(etime_t t) {
Marko Mikulicic 0:c0ecb8bf28eb 32454 return floor(t / msPerDay);
Marko Mikulicic 0:c0ecb8bf28eb 32455 }
Marko Mikulicic 0:c0ecb8bf28eb 32456
Marko Mikulicic 0:c0ecb8bf28eb 32457 static int ecma_DayWithinYear(etime_t t, int year) {
Marko Mikulicic 0:c0ecb8bf28eb 32458 return (int) (ecma_Day(t) - ecma_DayFromYear(year));
Marko Mikulicic 0:c0ecb8bf28eb 32459 }
Marko Mikulicic 0:c0ecb8bf28eb 32460
Marko Mikulicic 0:c0ecb8bf28eb 32461 static int ecma_MonthFromTime(etime_t t, int year) {
Marko Mikulicic 0:c0ecb8bf28eb 32462 int *days, i;
Marko Mikulicic 0:c0ecb8bf28eb 32463 etimeint_t dwy = ecma_DayWithinYear(t, year);
Marko Mikulicic 0:c0ecb8bf28eb 32464
Marko Mikulicic 0:c0ecb8bf28eb 32465 days = ecma_getfirstdays(ecma_IsLeapYear(year));
Marko Mikulicic 0:c0ecb8bf28eb 32466
Marko Mikulicic 0:c0ecb8bf28eb 32467 for (i = 0; i < MonthsInYear; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 32468 if (dwy >= days[i] && dwy < days[i + 1]) {
Marko Mikulicic 0:c0ecb8bf28eb 32469 return i;
Marko Mikulicic 0:c0ecb8bf28eb 32470 }
Marko Mikulicic 0:c0ecb8bf28eb 32471 }
Marko Mikulicic 0:c0ecb8bf28eb 32472
Marko Mikulicic 0:c0ecb8bf28eb 32473 return -1;
Marko Mikulicic 0:c0ecb8bf28eb 32474 }
Marko Mikulicic 0:c0ecb8bf28eb 32475
Marko Mikulicic 0:c0ecb8bf28eb 32476 static int ecma_DateFromTime(etime_t t, int year) {
Marko Mikulicic 0:c0ecb8bf28eb 32477 int *days, mft = ecma_MonthFromTime(t, year),
Marko Mikulicic 0:c0ecb8bf28eb 32478 dwy = ecma_DayWithinYear(t, year);
Marko Mikulicic 0:c0ecb8bf28eb 32479
Marko Mikulicic 0:c0ecb8bf28eb 32480 if (mft > 11) {
Marko Mikulicic 0:c0ecb8bf28eb 32481 return -1;
Marko Mikulicic 0:c0ecb8bf28eb 32482 }
Marko Mikulicic 0:c0ecb8bf28eb 32483
Marko Mikulicic 0:c0ecb8bf28eb 32484 days = ecma_getfirstdays(ecma_IsLeapYear(year));
Marko Mikulicic 0:c0ecb8bf28eb 32485
Marko Mikulicic 0:c0ecb8bf28eb 32486 return dwy - days[mft] + 1;
Marko Mikulicic 0:c0ecb8bf28eb 32487 }
Marko Mikulicic 0:c0ecb8bf28eb 32488
Marko Mikulicic 0:c0ecb8bf28eb 32489 #define DEF_EXTRACT_TIMEPART(funcname, c1, c2) \
Marko Mikulicic 0:c0ecb8bf28eb 32490 static int ecma_##funcname(etime_t t) { \
Marko Mikulicic 0:c0ecb8bf28eb 32491 int ret = (etimeint_t) floor(t / c1) % c2; \
Marko Mikulicic 0:c0ecb8bf28eb 32492 if (ret < 0) { \
Marko Mikulicic 0:c0ecb8bf28eb 32493 ret += c2; \
Marko Mikulicic 0:c0ecb8bf28eb 32494 } \
Marko Mikulicic 0:c0ecb8bf28eb 32495 return ret; \
Marko Mikulicic 0:c0ecb8bf28eb 32496 }
Marko Mikulicic 0:c0ecb8bf28eb 32497
Marko Mikulicic 0:c0ecb8bf28eb 32498 DEF_EXTRACT_TIMEPART(HourFromTime, msPerHour, HoursPerDay)
Marko Mikulicic 0:c0ecb8bf28eb 32499 DEF_EXTRACT_TIMEPART(MinFromTime, msPerMinute, MinutesPerHour)
Marko Mikulicic 0:c0ecb8bf28eb 32500 DEF_EXTRACT_TIMEPART(SecFromTime, msPerSecond, SecondsPerMinute)
Marko Mikulicic 0:c0ecb8bf28eb 32501 DEF_EXTRACT_TIMEPART(msFromTime, 1, msPerSecond)
Marko Mikulicic 0:c0ecb8bf28eb 32502
Marko Mikulicic 0:c0ecb8bf28eb 32503 static int ecma_WeekDay(etime_t t) {
Marko Mikulicic 0:c0ecb8bf28eb 32504 int ret = (ecma_Day(t) + 4) % 7;
Marko Mikulicic 0:c0ecb8bf28eb 32505 if (ret < 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32506 ret += 7;
Marko Mikulicic 0:c0ecb8bf28eb 32507 }
Marko Mikulicic 0:c0ecb8bf28eb 32508
Marko Mikulicic 0:c0ecb8bf28eb 32509 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 32510 }
Marko Mikulicic 0:c0ecb8bf28eb 32511
Marko Mikulicic 0:c0ecb8bf28eb 32512 static void d_gmtime(const etime_t *t, struct timeparts *tp) {
Marko Mikulicic 0:c0ecb8bf28eb 32513 tp->year = ecma_YearFromTime_s(*t);
Marko Mikulicic 0:c0ecb8bf28eb 32514 tp->month = ecma_MonthFromTime(*t, tp->year);
Marko Mikulicic 0:c0ecb8bf28eb 32515 tp->day = ecma_DateFromTime(*t, tp->year);
Marko Mikulicic 0:c0ecb8bf28eb 32516 tp->hour = ecma_HourFromTime(*t);
Marko Mikulicic 0:c0ecb8bf28eb 32517 tp->min = ecma_MinFromTime(*t);
Marko Mikulicic 0:c0ecb8bf28eb 32518 tp->sec = ecma_SecFromTime(*t);
Marko Mikulicic 0:c0ecb8bf28eb 32519 tp->msec = ecma_msFromTime(*t);
Marko Mikulicic 0:c0ecb8bf28eb 32520 tp->dayofweek = ecma_WeekDay(*t);
Marko Mikulicic 0:c0ecb8bf28eb 32521 }
Marko Mikulicic 0:c0ecb8bf28eb 32522 #endif /* V7_ENABLE__Date__toString || V7_ENABLE__Date__toLocaleString || \
Marko Mikulicic 0:c0ecb8bf28eb 32523 V7_ENABLE__Date__getters || V7_ENABLE__Date__setters */
Marko Mikulicic 0:c0ecb8bf28eb 32524
Marko Mikulicic 0:c0ecb8bf28eb 32525 #if V7_ENABLE__Date__toString || V7_ENABLE__Date__toLocaleString || \
Marko Mikulicic 0:c0ecb8bf28eb 32526 V7_ENABLE__Date__getters || V7_ENABLE__Date__setters
Marko Mikulicic 0:c0ecb8bf28eb 32527 static etimeint_t ecma_LocalTime(etime_t t) {
Marko Mikulicic 0:c0ecb8bf28eb 32528 return t + ecma_LocalTZA() + ecma_DaylightSavingTA(t);
Marko Mikulicic 0:c0ecb8bf28eb 32529 }
Marko Mikulicic 0:c0ecb8bf28eb 32530
Marko Mikulicic 0:c0ecb8bf28eb 32531 static void d_localtime(const etime_t *time, struct timeparts *tp) {
Marko Mikulicic 0:c0ecb8bf28eb 32532 etime_t local_time = ecma_LocalTime(*time);
Marko Mikulicic 0:c0ecb8bf28eb 32533 d_gmtime(&local_time, tp);
Marko Mikulicic 0:c0ecb8bf28eb 32534 }
Marko Mikulicic 0:c0ecb8bf28eb 32535 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32536
Marko Mikulicic 0:c0ecb8bf28eb 32537 static etimeint_t ecma_MakeTime(etimeint_t hour, etimeint_t min, etimeint_t sec,
Marko Mikulicic 0:c0ecb8bf28eb 32538 etimeint_t ms) {
Marko Mikulicic 0:c0ecb8bf28eb 32539 return ((hour * MinutesPerHour + min) * SecondsPerMinute + sec) *
Marko Mikulicic 0:c0ecb8bf28eb 32540 msPerSecond +
Marko Mikulicic 0:c0ecb8bf28eb 32541 ms;
Marko Mikulicic 0:c0ecb8bf28eb 32542 }
Marko Mikulicic 0:c0ecb8bf28eb 32543
Marko Mikulicic 0:c0ecb8bf28eb 32544 static etimeint_t ecma_MakeDay(int year, int month, int date) {
Marko Mikulicic 0:c0ecb8bf28eb 32545 int *days;
Marko Mikulicic 0:c0ecb8bf28eb 32546 etimeint_t yday, mday;
Marko Mikulicic 0:c0ecb8bf28eb 32547
Marko Mikulicic 0:c0ecb8bf28eb 32548 year += floor(month / 12);
Marko Mikulicic 0:c0ecb8bf28eb 32549 month = month % 12;
Marko Mikulicic 0:c0ecb8bf28eb 32550 yday = floor(ecma_TimeFromYear(year) / msPerDay);
Marko Mikulicic 0:c0ecb8bf28eb 32551 days = ecma_getfirstdays(ecma_IsLeapYear(year));
Marko Mikulicic 0:c0ecb8bf28eb 32552 mday = days[month];
Marko Mikulicic 0:c0ecb8bf28eb 32553
Marko Mikulicic 0:c0ecb8bf28eb 32554 return yday + mday + date - 1;
Marko Mikulicic 0:c0ecb8bf28eb 32555 }
Marko Mikulicic 0:c0ecb8bf28eb 32556
Marko Mikulicic 0:c0ecb8bf28eb 32557 static etimeint_t ecma_MakeDate(etimeint_t day, etimeint_t time) {
Marko Mikulicic 0:c0ecb8bf28eb 32558 return (day * msPerDay + time);
Marko Mikulicic 0:c0ecb8bf28eb 32559 }
Marko Mikulicic 0:c0ecb8bf28eb 32560
Marko Mikulicic 0:c0ecb8bf28eb 32561 static void d_gettime(etime_t *t) {
Marko Mikulicic 0:c0ecb8bf28eb 32562 #ifndef _WIN32
Marko Mikulicic 0:c0ecb8bf28eb 32563 struct timeval tv;
Marko Mikulicic 0:c0ecb8bf28eb 32564 gettimeofday(&tv, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 32565 *t = (etime_t) tv.tv_sec * 1000 + (etime_t) tv.tv_usec / 1000;
Marko Mikulicic 0:c0ecb8bf28eb 32566 #else
Marko Mikulicic 0:c0ecb8bf28eb 32567 /* TODO(mkm): use native windows API in order to get ms granularity */
Marko Mikulicic 0:c0ecb8bf28eb 32568 *t = time(NULL) * 1000.0;
Marko Mikulicic 0:c0ecb8bf28eb 32569 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32570 }
Marko Mikulicic 0:c0ecb8bf28eb 32571
Marko Mikulicic 0:c0ecb8bf28eb 32572 static etime_t d_mktime_impl(const struct timeparts *tp) {
Marko Mikulicic 0:c0ecb8bf28eb 32573 return ecma_MakeDate(ecma_MakeDay(tp->year, tp->month, tp->day),
Marko Mikulicic 0:c0ecb8bf28eb 32574 ecma_MakeTime(tp->hour, tp->min, tp->sec, tp->msec));
Marko Mikulicic 0:c0ecb8bf28eb 32575 }
Marko Mikulicic 0:c0ecb8bf28eb 32576
Marko Mikulicic 0:c0ecb8bf28eb 32577 #if V7_ENABLE__Date__setters
Marko Mikulicic 0:c0ecb8bf28eb 32578 static etime_t d_lmktime(const struct timeparts *tp) {
Marko Mikulicic 0:c0ecb8bf28eb 32579 return ecma_UTC(d_mktime_impl(tp));
Marko Mikulicic 0:c0ecb8bf28eb 32580 }
Marko Mikulicic 0:c0ecb8bf28eb 32581 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32582
Marko Mikulicic 0:c0ecb8bf28eb 32583 static etime_t d_gmktime(const struct timeparts *tp) {
Marko Mikulicic 0:c0ecb8bf28eb 32584 return d_mktime_impl(tp);
Marko Mikulicic 0:c0ecb8bf28eb 32585 }
Marko Mikulicic 0:c0ecb8bf28eb 32586
Marko Mikulicic 0:c0ecb8bf28eb 32587 typedef etime_t (*fmaketime_t)(const struct timeparts *);
Marko Mikulicic 0:c0ecb8bf28eb 32588 typedef void (*fbreaktime_t)(const etime_t *, struct timeparts *);
Marko Mikulicic 0:c0ecb8bf28eb 32589
Marko Mikulicic 0:c0ecb8bf28eb 32590 #if V7_ENABLE__Date__toString || V7_ENABLE__Date__toLocaleString || \
Marko Mikulicic 0:c0ecb8bf28eb 32591 V7_ENABLE__Date__toJSON
Marko Mikulicic 0:c0ecb8bf28eb 32592 static val_t d_trytogetobjforstring(struct v7 *v7, val_t obj) {
Marko Mikulicic 0:c0ecb8bf28eb 32593 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 32594 val_t ret = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 32595
Marko Mikulicic 0:c0ecb8bf28eb 32596 rcode = obj_value_of(v7, obj, &ret);
Marko Mikulicic 0:c0ecb8bf28eb 32597 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32598 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32599 }
Marko Mikulicic 0:c0ecb8bf28eb 32600
Marko Mikulicic 0:c0ecb8bf28eb 32601 if (ret == V7_TAG_NAN) {
Marko Mikulicic 0:c0ecb8bf28eb 32602 rcode = v7_throwf(v7, TYPE_ERROR, "Date is invalid (for string)");
Marko Mikulicic 0:c0ecb8bf28eb 32603 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32604 }
Marko Mikulicic 0:c0ecb8bf28eb 32605
Marko Mikulicic 0:c0ecb8bf28eb 32606 clean:
Marko Mikulicic 0:c0ecb8bf28eb 32607 (void) rcode;
Marko Mikulicic 0:c0ecb8bf28eb 32608 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 32609 }
Marko Mikulicic 0:c0ecb8bf28eb 32610 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32611
Marko Mikulicic 0:c0ecb8bf28eb 32612 #if V7_ENABLE__Date__parse || V7_ENABLE__Date__UTC
Marko Mikulicic 0:c0ecb8bf28eb 32613 static int d_iscalledasfunction(struct v7 *v7, val_t this_obj) {
Marko Mikulicic 0:c0ecb8bf28eb 32614 /* TODO(alashkin): verify this statement */
Marko Mikulicic 0:c0ecb8bf28eb 32615 return is_prototype_of(v7, this_obj, v7->vals.date_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 32616 }
Marko Mikulicic 0:c0ecb8bf28eb 32617 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32618
Marko Mikulicic 0:c0ecb8bf28eb 32619 static const char *mon_name[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
Marko Mikulicic 0:c0ecb8bf28eb 32620 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
Marko Mikulicic 0:c0ecb8bf28eb 32621
Marko Mikulicic 0:c0ecb8bf28eb 32622 int d_getnumbyname(const char **arr, int arr_size, const char *str) {
Marko Mikulicic 0:c0ecb8bf28eb 32623 int i;
Marko Mikulicic 0:c0ecb8bf28eb 32624 for (i = 0; i < arr_size; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 32625 if (strncmp(arr[i], str, 3) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32626 return i + 1;
Marko Mikulicic 0:c0ecb8bf28eb 32627 }
Marko Mikulicic 0:c0ecb8bf28eb 32628 }
Marko Mikulicic 0:c0ecb8bf28eb 32629
Marko Mikulicic 0:c0ecb8bf28eb 32630 return -1;
Marko Mikulicic 0:c0ecb8bf28eb 32631 }
Marko Mikulicic 0:c0ecb8bf28eb 32632
Marko Mikulicic 0:c0ecb8bf28eb 32633 int date_parse(const char *str, int *a1, int *a2, int *a3, char sep,
Marko Mikulicic 0:c0ecb8bf28eb 32634 char *rest) {
Marko Mikulicic 0:c0ecb8bf28eb 32635 char frmDate[] = " %d/%d/%d%[^\0]";
Marko Mikulicic 0:c0ecb8bf28eb 32636 frmDate[3] = frmDate[6] = sep;
Marko Mikulicic 0:c0ecb8bf28eb 32637 return sscanf(str, frmDate, a1, a2, a3, rest);
Marko Mikulicic 0:c0ecb8bf28eb 32638 }
Marko Mikulicic 0:c0ecb8bf28eb 32639
Marko Mikulicic 0:c0ecb8bf28eb 32640 #define NO_TZ 0x7FFFFFFF
Marko Mikulicic 0:c0ecb8bf28eb 32641
Marko Mikulicic 0:c0ecb8bf28eb 32642 /*
Marko Mikulicic 0:c0ecb8bf28eb 32643 * not very smart but simple, and working according
Marko Mikulicic 0:c0ecb8bf28eb 32644 * to ECMA5.1 StringToDate function
Marko Mikulicic 0:c0ecb8bf28eb 32645 */
Marko Mikulicic 0:c0ecb8bf28eb 32646 static int d_parsedatestr(const char *jstr, size_t len, struct timeparts *tp,
Marko Mikulicic 0:c0ecb8bf28eb 32647 int *tz) {
Marko Mikulicic 0:c0ecb8bf28eb 32648 char gmt[4];
Marko Mikulicic 0:c0ecb8bf28eb 32649 char buf1[100] = {0}, buf2[100] = {0};
Marko Mikulicic 0:c0ecb8bf28eb 32650 int res = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32651 char str[101];
Marko Mikulicic 0:c0ecb8bf28eb 32652 memcpy(str, jstr, len);
Marko Mikulicic 0:c0ecb8bf28eb 32653 str[len] = '\0';
Marko Mikulicic 0:c0ecb8bf28eb 32654 memset(tp, 0, sizeof(*tp));
Marko Mikulicic 0:c0ecb8bf28eb 32655 *tz = NO_TZ;
Marko Mikulicic 0:c0ecb8bf28eb 32656
Marko Mikulicic 0:c0ecb8bf28eb 32657 /* trying toISOSrting() format */
Marko Mikulicic 0:c0ecb8bf28eb 32658 {
Marko Mikulicic 0:c0ecb8bf28eb 32659 const char *frmISOString = " %d-%02d-%02dT%02d:%02d:%02d.%03dZ";
Marko Mikulicic 0:c0ecb8bf28eb 32660 res = sscanf(str, frmISOString, &tp->year, &tp->month, &tp->day, &tp->hour,
Marko Mikulicic 0:c0ecb8bf28eb 32661 &tp->min, &tp->sec, &tp->msec);
Marko Mikulicic 0:c0ecb8bf28eb 32662 if (res == 7) {
Marko Mikulicic 0:c0ecb8bf28eb 32663 *tz = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32664 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 32665 }
Marko Mikulicic 0:c0ecb8bf28eb 32666 }
Marko Mikulicic 0:c0ecb8bf28eb 32667
Marko Mikulicic 0:c0ecb8bf28eb 32668 /* trying toString()/toUTCString()/toDateFormat() formats */
Marko Mikulicic 0:c0ecb8bf28eb 32669 {
Marko Mikulicic 0:c0ecb8bf28eb 32670 char month[4];
Marko Mikulicic 0:c0ecb8bf28eb 32671 int dowlen;
Marko Mikulicic 0:c0ecb8bf28eb 32672 const char *frmString = " %*s%n %03s %02d %d %02d:%02d:%02d %03s%d";
Marko Mikulicic 0:c0ecb8bf28eb 32673 res = sscanf(str, frmString, &dowlen, month, &tp->day, &tp->year, &tp->hour,
Marko Mikulicic 0:c0ecb8bf28eb 32674 &tp->min, &tp->sec, gmt, tz);
Marko Mikulicic 0:c0ecb8bf28eb 32675 if ((res == 3 || (res >= 6 && res <= 8)) && dowlen == 3) {
Marko Mikulicic 0:c0ecb8bf28eb 32676 if ((tp->month = d_getnumbyname(mon_name, ARRAY_SIZE(mon_name), month)) !=
Marko Mikulicic 0:c0ecb8bf28eb 32677 -1) {
Marko Mikulicic 0:c0ecb8bf28eb 32678 if (res == 7 && strncmp(gmt, "GMT", 3) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32679 *tz = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32680 }
Marko Mikulicic 0:c0ecb8bf28eb 32681 return 1;
Marko Mikulicic 0:c0ecb8bf28eb 32682 }
Marko Mikulicic 0:c0ecb8bf28eb 32683 }
Marko Mikulicic 0:c0ecb8bf28eb 32684 }
Marko Mikulicic 0:c0ecb8bf28eb 32685
Marko Mikulicic 0:c0ecb8bf28eb 32686 /* trying the rest */
Marko Mikulicic 0:c0ecb8bf28eb 32687
Marko Mikulicic 0:c0ecb8bf28eb 32688 /* trying date */
Marko Mikulicic 0:c0ecb8bf28eb 32689
Marko Mikulicic 0:c0ecb8bf28eb 32690 if (!(date_parse(str, &tp->month, &tp->day, &tp->year, '/', buf1) >= 3 ||
Marko Mikulicic 0:c0ecb8bf28eb 32691 date_parse(str, &tp->day, &tp->month, &tp->year, '.', buf1) >= 3 ||
Marko Mikulicic 0:c0ecb8bf28eb 32692 date_parse(str, &tp->year, &tp->month, &tp->day, '-', buf1) >= 3)) {
Marko Mikulicic 0:c0ecb8bf28eb 32693 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 32694 }
Marko Mikulicic 0:c0ecb8bf28eb 32695
Marko Mikulicic 0:c0ecb8bf28eb 32696 /* there is date, trying time; from here return 0 only on errors */
Marko Mikulicic 0:c0ecb8bf28eb 32697
Marko Mikulicic 0:c0ecb8bf28eb 32698 /* trying HH:mm */
Marko Mikulicic 0:c0ecb8bf28eb 32699 {
Marko Mikulicic 0:c0ecb8bf28eb 32700 const char *frmMMhh = " %d:%d%[^\0]";
Marko Mikulicic 0:c0ecb8bf28eb 32701 res = sscanf(buf1, frmMMhh, &tp->hour, &tp->min, buf2);
Marko Mikulicic 0:c0ecb8bf28eb 32702 /* can't get time, but have some symbols, assuming error */
Marko Mikulicic 0:c0ecb8bf28eb 32703 if (res < 2) {
Marko Mikulicic 0:c0ecb8bf28eb 32704 return (strlen(buf2) == 0);
Marko Mikulicic 0:c0ecb8bf28eb 32705 }
Marko Mikulicic 0:c0ecb8bf28eb 32706 }
Marko Mikulicic 0:c0ecb8bf28eb 32707
Marko Mikulicic 0:c0ecb8bf28eb 32708 /* trying seconds */
Marko Mikulicic 0:c0ecb8bf28eb 32709 {
Marko Mikulicic 0:c0ecb8bf28eb 32710 const char *frmss = ":%d%[^\0]";
Marko Mikulicic 0:c0ecb8bf28eb 32711 memset(buf1, 0, sizeof(buf1));
Marko Mikulicic 0:c0ecb8bf28eb 32712 res = sscanf(buf2, frmss, &tp->sec, buf1);
Marko Mikulicic 0:c0ecb8bf28eb 32713 }
Marko Mikulicic 0:c0ecb8bf28eb 32714
Marko Mikulicic 0:c0ecb8bf28eb 32715 /* even if we don't get seconds we gonna try to get tz */
Marko Mikulicic 0:c0ecb8bf28eb 32716 {
Marko Mikulicic 0:c0ecb8bf28eb 32717 char *rest = res ? buf1 : buf2;
Marko Mikulicic 0:c0ecb8bf28eb 32718 char *buf = res ? buf2 : buf1;
Marko Mikulicic 0:c0ecb8bf28eb 32719 const char *frmtz = " %03s%d%[^\0]";
Marko Mikulicic 0:c0ecb8bf28eb 32720
Marko Mikulicic 0:c0ecb8bf28eb 32721 res = sscanf(rest, frmtz, gmt, tz, buf);
Marko Mikulicic 0:c0ecb8bf28eb 32722 if (res == 1 && strncmp(gmt, "GMT", 3) == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32723 *tz = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32724 }
Marko Mikulicic 0:c0ecb8bf28eb 32725 }
Marko Mikulicic 0:c0ecb8bf28eb 32726
Marko Mikulicic 0:c0ecb8bf28eb 32727 /* return OK if we are at the end of string */
Marko Mikulicic 0:c0ecb8bf28eb 32728 return res <= 2;
Marko Mikulicic 0:c0ecb8bf28eb 32729 }
Marko Mikulicic 0:c0ecb8bf28eb 32730
Marko Mikulicic 0:c0ecb8bf28eb 32731 static int d_timeFromString(etime_t *time, const char *str, size_t str_len) {
Marko Mikulicic 0:c0ecb8bf28eb 32732 struct timeparts tp;
Marko Mikulicic 0:c0ecb8bf28eb 32733 int tz;
Marko Mikulicic 0:c0ecb8bf28eb 32734
Marko Mikulicic 0:c0ecb8bf28eb 32735 *time = INVALID_TIME;
Marko Mikulicic 0:c0ecb8bf28eb 32736
Marko Mikulicic 0:c0ecb8bf28eb 32737 if (str_len > 100) {
Marko Mikulicic 0:c0ecb8bf28eb 32738 /* too long for valid date string */
Marko Mikulicic 0:c0ecb8bf28eb 32739 return 0;
Marko Mikulicic 0:c0ecb8bf28eb 32740 }
Marko Mikulicic 0:c0ecb8bf28eb 32741
Marko Mikulicic 0:c0ecb8bf28eb 32742 if (d_parsedatestr(str, str_len, &tp, &tz)) {
Marko Mikulicic 0:c0ecb8bf28eb 32743 /* check results */
Marko Mikulicic 0:c0ecb8bf28eb 32744 int valid = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32745
Marko Mikulicic 0:c0ecb8bf28eb 32746 tp.month--;
Marko Mikulicic 0:c0ecb8bf28eb 32747 valid = tp.day >= 1 && tp.day <= 31;
Marko Mikulicic 0:c0ecb8bf28eb 32748 valid &= tp.month >= 0 && tp.month <= 11;
Marko Mikulicic 0:c0ecb8bf28eb 32749 valid &= tp.hour >= 0 && tp.hour <= 23;
Marko Mikulicic 0:c0ecb8bf28eb 32750 valid &= tp.min >= 0 && tp.min <= 59;
Marko Mikulicic 0:c0ecb8bf28eb 32751 valid &= tp.sec >= 0 && tp.sec <= 59;
Marko Mikulicic 0:c0ecb8bf28eb 32752
Marko Mikulicic 0:c0ecb8bf28eb 32753 if (tz != NO_TZ && tz > 12) {
Marko Mikulicic 0:c0ecb8bf28eb 32754 tz /= 100;
Marko Mikulicic 0:c0ecb8bf28eb 32755 }
Marko Mikulicic 0:c0ecb8bf28eb 32756
Marko Mikulicic 0:c0ecb8bf28eb 32757 valid &= (abs(tz) <= 12 || tz == NO_TZ);
Marko Mikulicic 0:c0ecb8bf28eb 32758
Marko Mikulicic 0:c0ecb8bf28eb 32759 if (valid) {
Marko Mikulicic 0:c0ecb8bf28eb 32760 *time = d_gmktime(&tp);
Marko Mikulicic 0:c0ecb8bf28eb 32761
Marko Mikulicic 0:c0ecb8bf28eb 32762 if (tz != NO_TZ) {
Marko Mikulicic 0:c0ecb8bf28eb 32763 /* timezone specified, use it */
Marko Mikulicic 0:c0ecb8bf28eb 32764 *time -= (tz * msPerHour);
Marko Mikulicic 0:c0ecb8bf28eb 32765 } else if (tz != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32766 /* assuming local timezone and moving back to UTC */
Marko Mikulicic 0:c0ecb8bf28eb 32767 *time = ecma_UTC(*time);
Marko Mikulicic 0:c0ecb8bf28eb 32768 }
Marko Mikulicic 0:c0ecb8bf28eb 32769 }
Marko Mikulicic 0:c0ecb8bf28eb 32770 }
Marko Mikulicic 0:c0ecb8bf28eb 32771
Marko Mikulicic 0:c0ecb8bf28eb 32772 return !isnan(*time);
Marko Mikulicic 0:c0ecb8bf28eb 32773 }
Marko Mikulicic 0:c0ecb8bf28eb 32774
Marko Mikulicic 0:c0ecb8bf28eb 32775 /* notice: holding month in calendar format (1-12, not 0-11) */
Marko Mikulicic 0:c0ecb8bf28eb 32776 struct dtimepartsarr {
Marko Mikulicic 0:c0ecb8bf28eb 32777 etime_t args[7];
Marko Mikulicic 0:c0ecb8bf28eb 32778 };
Marko Mikulicic 0:c0ecb8bf28eb 32779
Marko Mikulicic 0:c0ecb8bf28eb 32780 enum detimepartsarr {
Marko Mikulicic 0:c0ecb8bf28eb 32781 tpyear = 0,
Marko Mikulicic 0:c0ecb8bf28eb 32782 tpmonth,
Marko Mikulicic 0:c0ecb8bf28eb 32783 tpdate,
Marko Mikulicic 0:c0ecb8bf28eb 32784 tphours,
Marko Mikulicic 0:c0ecb8bf28eb 32785 tpminutes,
Marko Mikulicic 0:c0ecb8bf28eb 32786 tpseconds,
Marko Mikulicic 0:c0ecb8bf28eb 32787 tpmsec,
Marko Mikulicic 0:c0ecb8bf28eb 32788 tpmax
Marko Mikulicic 0:c0ecb8bf28eb 32789 };
Marko Mikulicic 0:c0ecb8bf28eb 32790
Marko Mikulicic 0:c0ecb8bf28eb 32791 static etime_t d_changepartoftime(const etime_t *current,
Marko Mikulicic 0:c0ecb8bf28eb 32792 struct dtimepartsarr *a,
Marko Mikulicic 0:c0ecb8bf28eb 32793 fbreaktime_t breaktimefunc,
Marko Mikulicic 0:c0ecb8bf28eb 32794 fmaketime_t maketimefunc) {
Marko Mikulicic 0:c0ecb8bf28eb 32795 /*
Marko Mikulicic 0:c0ecb8bf28eb 32796 * 0 = year, 1 = month , 2 = date , 3 = hours,
Marko Mikulicic 0:c0ecb8bf28eb 32797 * 4 = minutes, 5 = seconds, 6 = ms
Marko Mikulicic 0:c0ecb8bf28eb 32798 */
Marko Mikulicic 0:c0ecb8bf28eb 32799 struct timeparts tp;
Marko Mikulicic 0:c0ecb8bf28eb 32800 unsigned long i;
Marko Mikulicic 0:c0ecb8bf28eb 32801 int *tp_arr[7];
Marko Mikulicic 0:c0ecb8bf28eb 32802 /*
Marko Mikulicic 0:c0ecb8bf28eb 32803 * C89 doesn't allow initialization
Marko Mikulicic 0:c0ecb8bf28eb 32804 * like x = {&tp.year, &tp.month, .... }
Marko Mikulicic 0:c0ecb8bf28eb 32805 */
Marko Mikulicic 0:c0ecb8bf28eb 32806 tp_arr[0] = &tp.year;
Marko Mikulicic 0:c0ecb8bf28eb 32807 tp_arr[1] = &tp.month;
Marko Mikulicic 0:c0ecb8bf28eb 32808 tp_arr[2] = &tp.day;
Marko Mikulicic 0:c0ecb8bf28eb 32809 tp_arr[3] = &tp.hour;
Marko Mikulicic 0:c0ecb8bf28eb 32810 tp_arr[4] = &tp.min;
Marko Mikulicic 0:c0ecb8bf28eb 32811 tp_arr[5] = &tp.sec;
Marko Mikulicic 0:c0ecb8bf28eb 32812 tp_arr[6] = &tp.msec;
Marko Mikulicic 0:c0ecb8bf28eb 32813
Marko Mikulicic 0:c0ecb8bf28eb 32814 memset(&tp, 0, sizeof(tp));
Marko Mikulicic 0:c0ecb8bf28eb 32815
Marko Mikulicic 0:c0ecb8bf28eb 32816 if (breaktimefunc != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 32817 breaktimefunc(current, &tp);
Marko Mikulicic 0:c0ecb8bf28eb 32818 }
Marko Mikulicic 0:c0ecb8bf28eb 32819
Marko Mikulicic 0:c0ecb8bf28eb 32820 for (i = 0; i < ARRAY_SIZE(tp_arr); i++) {
Marko Mikulicic 0:c0ecb8bf28eb 32821 if (!isnan(a->args[i]) && !isinf(a->args[i])) {
Marko Mikulicic 0:c0ecb8bf28eb 32822 *tp_arr[i] = (int) a->args[i];
Marko Mikulicic 0:c0ecb8bf28eb 32823 }
Marko Mikulicic 0:c0ecb8bf28eb 32824 }
Marko Mikulicic 0:c0ecb8bf28eb 32825
Marko Mikulicic 0:c0ecb8bf28eb 32826 return maketimefunc(&tp);
Marko Mikulicic 0:c0ecb8bf28eb 32827 }
Marko Mikulicic 0:c0ecb8bf28eb 32828
Marko Mikulicic 0:c0ecb8bf28eb 32829 #if V7_ENABLE__Date__setters || V7_ENABLE__Date__UTC
Marko Mikulicic 0:c0ecb8bf28eb 32830 static etime_t d_time_number_from_arr(struct v7 *v7, int start_pos,
Marko Mikulicic 0:c0ecb8bf28eb 32831 fbreaktime_t breaktimefunc,
Marko Mikulicic 0:c0ecb8bf28eb 32832 fmaketime_t maketimefunc) {
Marko Mikulicic 0:c0ecb8bf28eb 32833 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 32834 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 32835 etime_t ret_time = INVALID_TIME;
Marko Mikulicic 0:c0ecb8bf28eb 32836 long cargs;
Marko Mikulicic 0:c0ecb8bf28eb 32837
Marko Mikulicic 0:c0ecb8bf28eb 32838 val_t objtime = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 32839 rcode = obj_value_of(v7, this_obj, &objtime);
Marko Mikulicic 0:c0ecb8bf28eb 32840 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32841 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32842 }
Marko Mikulicic 0:c0ecb8bf28eb 32843
Marko Mikulicic 0:c0ecb8bf28eb 32844 if ((cargs = v7_argc(v7)) >= 1 && objtime != V7_TAG_NAN) {
Marko Mikulicic 0:c0ecb8bf28eb 32845 int i;
Marko Mikulicic 0:c0ecb8bf28eb 32846 etime_t new_part = INVALID_TIME;
Marko Mikulicic 0:c0ecb8bf28eb 32847 struct dtimepartsarr a;
Marko Mikulicic 0:c0ecb8bf28eb 32848 for (i = 0; i < 7; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 32849 a.args[i] = INVALID_TIME;
Marko Mikulicic 0:c0ecb8bf28eb 32850 }
Marko Mikulicic 0:c0ecb8bf28eb 32851
Marko Mikulicic 0:c0ecb8bf28eb 32852 for (i = 0; i < cargs && (i + start_pos < tpmax); i++) {
Marko Mikulicic 0:c0ecb8bf28eb 32853 {
Marko Mikulicic 0:c0ecb8bf28eb 32854 val_t arg = v7_arg(v7, i);
Marko Mikulicic 0:c0ecb8bf28eb 32855 rcode = to_number_v(v7, arg, &arg);
Marko Mikulicic 0:c0ecb8bf28eb 32856 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32857 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32858 }
Marko Mikulicic 0:c0ecb8bf28eb 32859 new_part = v7_get_double(v7, arg);
Marko Mikulicic 0:c0ecb8bf28eb 32860 }
Marko Mikulicic 0:c0ecb8bf28eb 32861
Marko Mikulicic 0:c0ecb8bf28eb 32862 if (isnan(new_part)) {
Marko Mikulicic 0:c0ecb8bf28eb 32863 break;
Marko Mikulicic 0:c0ecb8bf28eb 32864 }
Marko Mikulicic 0:c0ecb8bf28eb 32865
Marko Mikulicic 0:c0ecb8bf28eb 32866 a.args[i + start_pos] = new_part;
Marko Mikulicic 0:c0ecb8bf28eb 32867 }
Marko Mikulicic 0:c0ecb8bf28eb 32868
Marko Mikulicic 0:c0ecb8bf28eb 32869 if (!isnan(new_part)) {
Marko Mikulicic 0:c0ecb8bf28eb 32870 etime_t current_time = v7_get_double(v7, objtime);
Marko Mikulicic 0:c0ecb8bf28eb 32871 ret_time =
Marko Mikulicic 0:c0ecb8bf28eb 32872 d_changepartoftime(&current_time, &a, breaktimefunc, maketimefunc);
Marko Mikulicic 0:c0ecb8bf28eb 32873 }
Marko Mikulicic 0:c0ecb8bf28eb 32874 }
Marko Mikulicic 0:c0ecb8bf28eb 32875
Marko Mikulicic 0:c0ecb8bf28eb 32876 clean:
Marko Mikulicic 0:c0ecb8bf28eb 32877 (void) rcode;
Marko Mikulicic 0:c0ecb8bf28eb 32878 return ret_time;
Marko Mikulicic 0:c0ecb8bf28eb 32879 }
Marko Mikulicic 0:c0ecb8bf28eb 32880 #endif /* V7_ENABLE__Date__setters */
Marko Mikulicic 0:c0ecb8bf28eb 32881
Marko Mikulicic 0:c0ecb8bf28eb 32882 #if V7_ENABLE__Date__toString
Marko Mikulicic 0:c0ecb8bf28eb 32883 static int d_tptostr(const struct timeparts *tp, char *buf, int addtz);
Marko Mikulicic 0:c0ecb8bf28eb 32884 #endif
Marko Mikulicic 0:c0ecb8bf28eb 32885
Marko Mikulicic 0:c0ecb8bf28eb 32886 /* constructor */
Marko Mikulicic 0:c0ecb8bf28eb 32887 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 32888 V7_PRIVATE enum v7_err Date_ctor(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 32889 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 32890 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 32891 etime_t ret_time = INVALID_TIME;
Marko Mikulicic 0:c0ecb8bf28eb 32892 if (v7_is_generic_object(this_obj) && this_obj != v7->vals.global_object) {
Marko Mikulicic 0:c0ecb8bf28eb 32893 long cargs = v7_argc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 32894 if (cargs <= 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32895 /* no parameters - return current date & time */
Marko Mikulicic 0:c0ecb8bf28eb 32896 d_gettime(&ret_time);
Marko Mikulicic 0:c0ecb8bf28eb 32897 } else if (cargs == 1) {
Marko Mikulicic 0:c0ecb8bf28eb 32898 /* one parameter */
Marko Mikulicic 0:c0ecb8bf28eb 32899 val_t arg = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 32900 if (v7_is_string(arg)) { /* it could be string */
Marko Mikulicic 0:c0ecb8bf28eb 32901 size_t str_size;
Marko Mikulicic 0:c0ecb8bf28eb 32902 const char *str = v7_get_string(v7, &arg, &str_size);
Marko Mikulicic 0:c0ecb8bf28eb 32903 d_timeFromString(&ret_time, str, str_size);
Marko Mikulicic 0:c0ecb8bf28eb 32904 }
Marko Mikulicic 0:c0ecb8bf28eb 32905 if (isnan(ret_time)) {
Marko Mikulicic 0:c0ecb8bf28eb 32906 /*
Marko Mikulicic 0:c0ecb8bf28eb 32907 * if cannot be parsed or
Marko Mikulicic 0:c0ecb8bf28eb 32908 * not string at all - trying to convert to number
Marko Mikulicic 0:c0ecb8bf28eb 32909 */
Marko Mikulicic 0:c0ecb8bf28eb 32910 ret_time = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32911 rcode = to_number_v(v7, arg, &arg);
Marko Mikulicic 0:c0ecb8bf28eb 32912 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32913 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32914 }
Marko Mikulicic 0:c0ecb8bf28eb 32915 ret_time = v7_get_double(v7, arg);
Marko Mikulicic 0:c0ecb8bf28eb 32916 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32917 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32918 }
Marko Mikulicic 0:c0ecb8bf28eb 32919 }
Marko Mikulicic 0:c0ecb8bf28eb 32920 } else {
Marko Mikulicic 0:c0ecb8bf28eb 32921 /* 2+ paramaters - should be parts of a date */
Marko Mikulicic 0:c0ecb8bf28eb 32922 struct dtimepartsarr a;
Marko Mikulicic 0:c0ecb8bf28eb 32923 int i;
Marko Mikulicic 0:c0ecb8bf28eb 32924
Marko Mikulicic 0:c0ecb8bf28eb 32925 memset(&a, 0, sizeof(a));
Marko Mikulicic 0:c0ecb8bf28eb 32926
Marko Mikulicic 0:c0ecb8bf28eb 32927 for (i = 0; i < cargs; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 32928 val_t arg = v7_arg(v7, i);
Marko Mikulicic 0:c0ecb8bf28eb 32929 rcode = to_number_v(v7, arg, &arg);
Marko Mikulicic 0:c0ecb8bf28eb 32930 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 32931 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32932 }
Marko Mikulicic 0:c0ecb8bf28eb 32933 a.args[i] = v7_get_double(v7, arg);
Marko Mikulicic 0:c0ecb8bf28eb 32934 if (isnan(a.args[i])) {
Marko Mikulicic 0:c0ecb8bf28eb 32935 break;
Marko Mikulicic 0:c0ecb8bf28eb 32936 }
Marko Mikulicic 0:c0ecb8bf28eb 32937 }
Marko Mikulicic 0:c0ecb8bf28eb 32938
Marko Mikulicic 0:c0ecb8bf28eb 32939 if (i >= cargs) {
Marko Mikulicic 0:c0ecb8bf28eb 32940 /*
Marko Mikulicic 0:c0ecb8bf28eb 32941 * If date is supplied then let
Marko Mikulicic 0:c0ecb8bf28eb 32942 * dt be ToNumber(date); else let dt be 1.
Marko Mikulicic 0:c0ecb8bf28eb 32943 */
Marko Mikulicic 0:c0ecb8bf28eb 32944 if (a.args[tpdate] == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 32945 a.args[tpdate] = 1;
Marko Mikulicic 0:c0ecb8bf28eb 32946 }
Marko Mikulicic 0:c0ecb8bf28eb 32947
Marko Mikulicic 0:c0ecb8bf28eb 32948 if (a.args[tpyear] >= 0 && a.args[tpyear] <= 99) {
Marko Mikulicic 0:c0ecb8bf28eb 32949 /*
Marko Mikulicic 0:c0ecb8bf28eb 32950 * If y is not NaN and 0 <= ToInteger(y) <= 99,
Marko Mikulicic 0:c0ecb8bf28eb 32951 * then let yr be 1900+ToInteger(y); otherwise, let yr be y.
Marko Mikulicic 0:c0ecb8bf28eb 32952 */
Marko Mikulicic 0:c0ecb8bf28eb 32953 a.args[tpyear] += 1900;
Marko Mikulicic 0:c0ecb8bf28eb 32954 }
Marko Mikulicic 0:c0ecb8bf28eb 32955
Marko Mikulicic 0:c0ecb8bf28eb 32956 ret_time = ecma_UTC(d_changepartoftime(0, &a, 0, d_gmktime));
Marko Mikulicic 0:c0ecb8bf28eb 32957 }
Marko Mikulicic 0:c0ecb8bf28eb 32958 }
Marko Mikulicic 0:c0ecb8bf28eb 32959
Marko Mikulicic 0:c0ecb8bf28eb 32960 obj_prototype_set(v7, get_object_struct(this_obj),
Marko Mikulicic 0:c0ecb8bf28eb 32961 get_object_struct(v7->vals.date_prototype));
Marko Mikulicic 0:c0ecb8bf28eb 32962
Marko Mikulicic 0:c0ecb8bf28eb 32963 v7_def(v7, this_obj, "", 0, _V7_DESC_HIDDEN(1), v7_mk_number(v7, ret_time));
Marko Mikulicic 0:c0ecb8bf28eb 32964 /*
Marko Mikulicic 0:c0ecb8bf28eb 32965 * implicitly returning `this`: `call_cfunction()` in bcode.c will do
Marko Mikulicic 0:c0ecb8bf28eb 32966 * that for us
Marko Mikulicic 0:c0ecb8bf28eb 32967 */
Marko Mikulicic 0:c0ecb8bf28eb 32968 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32969 } else {
Marko Mikulicic 0:c0ecb8bf28eb 32970 /*
Marko Mikulicic 0:c0ecb8bf28eb 32971 * according to 15.9.2.1 we should ignore all
Marko Mikulicic 0:c0ecb8bf28eb 32972 * parameters in case of function-call
Marko Mikulicic 0:c0ecb8bf28eb 32973 */
Marko Mikulicic 0:c0ecb8bf28eb 32974 char buf[50];
Marko Mikulicic 0:c0ecb8bf28eb 32975 int len;
Marko Mikulicic 0:c0ecb8bf28eb 32976
Marko Mikulicic 0:c0ecb8bf28eb 32977 #if V7_ENABLE__Date__toString
Marko Mikulicic 0:c0ecb8bf28eb 32978 struct timeparts tp;
Marko Mikulicic 0:c0ecb8bf28eb 32979 d_gettime(&ret_time);
Marko Mikulicic 0:c0ecb8bf28eb 32980 d_localtime(&ret_time, &tp);
Marko Mikulicic 0:c0ecb8bf28eb 32981 len = d_tptostr(&tp, buf, 1);
Marko Mikulicic 0:c0ecb8bf28eb 32982 #else
Marko Mikulicic 0:c0ecb8bf28eb 32983 len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32984 #endif /* V7_ENABLE__Date__toString */
Marko Mikulicic 0:c0ecb8bf28eb 32985
Marko Mikulicic 0:c0ecb8bf28eb 32986 *res = v7_mk_string(v7, buf, len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 32987 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 32988 }
Marko Mikulicic 0:c0ecb8bf28eb 32989
Marko Mikulicic 0:c0ecb8bf28eb 32990 clean:
Marko Mikulicic 0:c0ecb8bf28eb 32991 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 32992 }
Marko Mikulicic 0:c0ecb8bf28eb 32993
Marko Mikulicic 0:c0ecb8bf28eb 32994 #if V7_ENABLE__Date__toString || V7_ENABLE__Date__toJSON
Marko Mikulicic 0:c0ecb8bf28eb 32995 static int d_timetoISOstr(const etime_t *time, char *buf, size_t buf_size) {
Marko Mikulicic 0:c0ecb8bf28eb 32996 /* ISO format: "+XXYYYY-MM-DDTHH:mm:ss.sssZ"; */
Marko Mikulicic 0:c0ecb8bf28eb 32997 struct timeparts tp;
Marko Mikulicic 0:c0ecb8bf28eb 32998 char use_ext = 0;
Marko Mikulicic 0:c0ecb8bf28eb 32999 const char *ey_frm = "%06d-%02d-%02dT%02d:%02d:%02d.%03dZ";
Marko Mikulicic 0:c0ecb8bf28eb 33000 const char *simpl_frm = "%d-%02d-%02dT%02d:%02d:%02d.%03dZ";
Marko Mikulicic 0:c0ecb8bf28eb 33001
Marko Mikulicic 0:c0ecb8bf28eb 33002 d_gmtime(time, &tp);
Marko Mikulicic 0:c0ecb8bf28eb 33003
Marko Mikulicic 0:c0ecb8bf28eb 33004 if (abs(tp.year) > 9999 || tp.year < 0) {
Marko Mikulicic 0:c0ecb8bf28eb 33005 *buf = (tp.year > 0) ? '+' : '-';
Marko Mikulicic 0:c0ecb8bf28eb 33006 use_ext = 1;
Marko Mikulicic 0:c0ecb8bf28eb 33007 }
Marko Mikulicic 0:c0ecb8bf28eb 33008
Marko Mikulicic 0:c0ecb8bf28eb 33009 return c_snprintf(buf + use_ext, buf_size - use_ext,
Marko Mikulicic 0:c0ecb8bf28eb 33010 use_ext ? ey_frm : simpl_frm, abs(tp.year), tp.month + 1,
Marko Mikulicic 0:c0ecb8bf28eb 33011 tp.day, tp.hour, tp.min, tp.sec, tp.msec) +
Marko Mikulicic 0:c0ecb8bf28eb 33012 use_ext;
Marko Mikulicic 0:c0ecb8bf28eb 33013 }
Marko Mikulicic 0:c0ecb8bf28eb 33014
Marko Mikulicic 0:c0ecb8bf28eb 33015 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33016 V7_PRIVATE enum v7_err Date_toISOString(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33017 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33018 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33019 char buf[30];
Marko Mikulicic 0:c0ecb8bf28eb 33020 etime_t time;
Marko Mikulicic 0:c0ecb8bf28eb 33021 int len;
Marko Mikulicic 0:c0ecb8bf28eb 33022
Marko Mikulicic 0:c0ecb8bf28eb 33023 if (val_type(v7, this_obj) != V7_TYPE_DATE_OBJECT) {
Marko Mikulicic 0:c0ecb8bf28eb 33024 rcode = v7_throwf(v7, TYPE_ERROR, "This is not a Date object");
Marko Mikulicic 0:c0ecb8bf28eb 33025 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33026 }
Marko Mikulicic 0:c0ecb8bf28eb 33027
Marko Mikulicic 0:c0ecb8bf28eb 33028 time = v7_get_double(v7, d_trytogetobjforstring(v7, this_obj));
Marko Mikulicic 0:c0ecb8bf28eb 33029 len = d_timetoISOstr(&time, buf, sizeof(buf));
Marko Mikulicic 0:c0ecb8bf28eb 33030 if (len > (int) (sizeof(buf) - 1 /*null-term*/)) {
Marko Mikulicic 0:c0ecb8bf28eb 33031 len = (int) (sizeof(buf) - 1 /*null-term*/);
Marko Mikulicic 0:c0ecb8bf28eb 33032 }
Marko Mikulicic 0:c0ecb8bf28eb 33033
Marko Mikulicic 0:c0ecb8bf28eb 33034 *res = v7_mk_string(v7, buf, len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 33035
Marko Mikulicic 0:c0ecb8bf28eb 33036 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33037 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33038 }
Marko Mikulicic 0:c0ecb8bf28eb 33039 #endif /* V7_ENABLE__Date__toString || V7_ENABLE__Date__toJSON */
Marko Mikulicic 0:c0ecb8bf28eb 33040
Marko Mikulicic 0:c0ecb8bf28eb 33041 #if V7_ENABLE__Date__toString
Marko Mikulicic 0:c0ecb8bf28eb 33042 typedef int (*ftostring_t)(const struct timeparts *, char *, int);
Marko Mikulicic 0:c0ecb8bf28eb 33043
Marko Mikulicic 0:c0ecb8bf28eb 33044 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33045 static enum v7_err d_tostring(struct v7 *v7, val_t obj,
Marko Mikulicic 0:c0ecb8bf28eb 33046 fbreaktime_t breaktimefunc,
Marko Mikulicic 0:c0ecb8bf28eb 33047 ftostring_t tostringfunc, int addtz,
Marko Mikulicic 0:c0ecb8bf28eb 33048 v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33049 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33050 struct timeparts tp;
Marko Mikulicic 0:c0ecb8bf28eb 33051 int len;
Marko Mikulicic 0:c0ecb8bf28eb 33052 char buf[100];
Marko Mikulicic 0:c0ecb8bf28eb 33053 etime_t time;
Marko Mikulicic 0:c0ecb8bf28eb 33054
Marko Mikulicic 0:c0ecb8bf28eb 33055 time = v7_get_double(v7, d_trytogetobjforstring(v7, obj));
Marko Mikulicic 0:c0ecb8bf28eb 33056
Marko Mikulicic 0:c0ecb8bf28eb 33057 breaktimefunc(&time, &tp);
Marko Mikulicic 0:c0ecb8bf28eb 33058 len = tostringfunc(&tp, buf, addtz);
Marko Mikulicic 0:c0ecb8bf28eb 33059
Marko Mikulicic 0:c0ecb8bf28eb 33060 *res = v7_mk_string(v7, buf, len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 33061 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33062 }
Marko Mikulicic 0:c0ecb8bf28eb 33063
Marko Mikulicic 0:c0ecb8bf28eb 33064 /* using macros to avoid copy-paste technic */
Marko Mikulicic 0:c0ecb8bf28eb 33065 #define DEF_TOSTR(funcname, breaktimefunc, tostrfunc, addtz) \
Marko Mikulicic 0:c0ecb8bf28eb 33066 WARN_UNUSED_RESULT \
Marko Mikulicic 0:c0ecb8bf28eb 33067 V7_PRIVATE enum v7_err Date_to##funcname(struct v7 *v7, v7_val_t *res) { \
Marko Mikulicic 0:c0ecb8bf28eb 33068 val_t this_obj = v7_get_this(v7); \
Marko Mikulicic 0:c0ecb8bf28eb 33069 return d_tostring(v7, this_obj, breaktimefunc, tostrfunc, addtz, res); \
Marko Mikulicic 0:c0ecb8bf28eb 33070 }
Marko Mikulicic 0:c0ecb8bf28eb 33071
Marko Mikulicic 0:c0ecb8bf28eb 33072 /* non-locale function should always return in english and 24h-format */
Marko Mikulicic 0:c0ecb8bf28eb 33073 static const char *wday_name[] = {"Sun", "Mon", "Tue", "Wed",
Marko Mikulicic 0:c0ecb8bf28eb 33074 "Thu", "Fri", "Sat"};
Marko Mikulicic 0:c0ecb8bf28eb 33075
Marko Mikulicic 0:c0ecb8bf28eb 33076 static int d_tptodatestr(const struct timeparts *tp, char *buf, int addtz) {
Marko Mikulicic 0:c0ecb8bf28eb 33077 (void) addtz;
Marko Mikulicic 0:c0ecb8bf28eb 33078
Marko Mikulicic 0:c0ecb8bf28eb 33079 return sprintf(buf, "%s %s %02d %d", wday_name[tp->dayofweek],
Marko Mikulicic 0:c0ecb8bf28eb 33080 mon_name[tp->month], tp->day, tp->year);
Marko Mikulicic 0:c0ecb8bf28eb 33081 }
Marko Mikulicic 0:c0ecb8bf28eb 33082
Marko Mikulicic 0:c0ecb8bf28eb 33083 DEF_TOSTR(DateString, d_localtime, d_tptodatestr, 1)
Marko Mikulicic 0:c0ecb8bf28eb 33084
Marko Mikulicic 0:c0ecb8bf28eb 33085 static const char *d_gettzname(void) {
Marko Mikulicic 0:c0ecb8bf28eb 33086 return g_tzname;
Marko Mikulicic 0:c0ecb8bf28eb 33087 }
Marko Mikulicic 0:c0ecb8bf28eb 33088
Marko Mikulicic 0:c0ecb8bf28eb 33089 static int d_tptotimestr(const struct timeparts *tp, char *buf, int addtz) {
Marko Mikulicic 0:c0ecb8bf28eb 33090 int len;
Marko Mikulicic 0:c0ecb8bf28eb 33091
Marko Mikulicic 0:c0ecb8bf28eb 33092 len = sprintf(buf, "%02d:%02d:%02d GMT", tp->hour, tp->min, tp->sec);
Marko Mikulicic 0:c0ecb8bf28eb 33093
Marko Mikulicic 0:c0ecb8bf28eb 33094 if (addtz && g_gmtoffms != 0) {
Marko Mikulicic 0:c0ecb8bf28eb 33095 len = sprintf(buf + len, "%c%02d00 (%s)", g_gmtoffms > 0 ? '-' : '+',
Marko Mikulicic 0:c0ecb8bf28eb 33096 abs((int) g_gmtoffms / msPerHour), d_gettzname());
Marko Mikulicic 0:c0ecb8bf28eb 33097 }
Marko Mikulicic 0:c0ecb8bf28eb 33098
Marko Mikulicic 0:c0ecb8bf28eb 33099 return (int) strlen(buf);
Marko Mikulicic 0:c0ecb8bf28eb 33100 }
Marko Mikulicic 0:c0ecb8bf28eb 33101
Marko Mikulicic 0:c0ecb8bf28eb 33102 DEF_TOSTR(TimeString, d_localtime, d_tptotimestr, 1)
Marko Mikulicic 0:c0ecb8bf28eb 33103
Marko Mikulicic 0:c0ecb8bf28eb 33104 static int d_tptostr(const struct timeparts *tp, char *buf, int addtz) {
Marko Mikulicic 0:c0ecb8bf28eb 33105 int len = d_tptodatestr(tp, buf, addtz);
Marko Mikulicic 0:c0ecb8bf28eb 33106 *(buf + len) = ' ';
Marko Mikulicic 0:c0ecb8bf28eb 33107 return d_tptotimestr(tp, buf + len + 1, addtz) + len + 1;
Marko Mikulicic 0:c0ecb8bf28eb 33108 }
Marko Mikulicic 0:c0ecb8bf28eb 33109
Marko Mikulicic 0:c0ecb8bf28eb 33110 DEF_TOSTR(String, d_localtime, d_tptostr, 1)
Marko Mikulicic 0:c0ecb8bf28eb 33111 DEF_TOSTR(UTCString, d_gmtime, d_tptostr, 0)
Marko Mikulicic 0:c0ecb8bf28eb 33112 #endif /* V7_ENABLE__Date__toString */
Marko Mikulicic 0:c0ecb8bf28eb 33113
Marko Mikulicic 0:c0ecb8bf28eb 33114 #if V7_ENABLE__Date__toLocaleString
Marko Mikulicic 0:c0ecb8bf28eb 33115 struct d_locale {
Marko Mikulicic 0:c0ecb8bf28eb 33116 char locale[50];
Marko Mikulicic 0:c0ecb8bf28eb 33117 };
Marko Mikulicic 0:c0ecb8bf28eb 33118
Marko Mikulicic 0:c0ecb8bf28eb 33119 static void d_getcurrentlocale(struct d_locale *loc) {
Marko Mikulicic 0:c0ecb8bf28eb 33120 strcpy(loc->locale, setlocale(LC_TIME, 0));
Marko Mikulicic 0:c0ecb8bf28eb 33121 }
Marko Mikulicic 0:c0ecb8bf28eb 33122
Marko Mikulicic 0:c0ecb8bf28eb 33123 static void d_setlocale(const struct d_locale *loc) {
Marko Mikulicic 0:c0ecb8bf28eb 33124 setlocale(LC_TIME, loc ? loc->locale : "");
Marko Mikulicic 0:c0ecb8bf28eb 33125 }
Marko Mikulicic 0:c0ecb8bf28eb 33126
Marko Mikulicic 0:c0ecb8bf28eb 33127 /* TODO(alashkin): check portability */
Marko Mikulicic 0:c0ecb8bf28eb 33128 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33129 static enum v7_err d_tolocalestr(struct v7 *v7, val_t obj, const char *frm,
Marko Mikulicic 0:c0ecb8bf28eb 33130 v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33131 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33132 char buf[250];
Marko Mikulicic 0:c0ecb8bf28eb 33133 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 33134 struct tm t;
Marko Mikulicic 0:c0ecb8bf28eb 33135 etime_t time;
Marko Mikulicic 0:c0ecb8bf28eb 33136 struct d_locale prev_locale;
Marko Mikulicic 0:c0ecb8bf28eb 33137 struct timeparts tp;
Marko Mikulicic 0:c0ecb8bf28eb 33138
Marko Mikulicic 0:c0ecb8bf28eb 33139 time = v7_get_double(v7, d_trytogetobjforstring(v7, obj));
Marko Mikulicic 0:c0ecb8bf28eb 33140
Marko Mikulicic 0:c0ecb8bf28eb 33141 d_getcurrentlocale(&prev_locale);
Marko Mikulicic 0:c0ecb8bf28eb 33142 d_setlocale(0);
Marko Mikulicic 0:c0ecb8bf28eb 33143 d_localtime(&time, &tp);
Marko Mikulicic 0:c0ecb8bf28eb 33144
Marko Mikulicic 0:c0ecb8bf28eb 33145 memset(&t, 0, sizeof(t));
Marko Mikulicic 0:c0ecb8bf28eb 33146 t.tm_year = tp.year - 1900;
Marko Mikulicic 0:c0ecb8bf28eb 33147 t.tm_mon = tp.month;
Marko Mikulicic 0:c0ecb8bf28eb 33148 t.tm_mday = tp.day;
Marko Mikulicic 0:c0ecb8bf28eb 33149 t.tm_hour = tp.hour;
Marko Mikulicic 0:c0ecb8bf28eb 33150 t.tm_min = tp.min;
Marko Mikulicic 0:c0ecb8bf28eb 33151 t.tm_sec = tp.sec;
Marko Mikulicic 0:c0ecb8bf28eb 33152 t.tm_wday = tp.dayofweek;
Marko Mikulicic 0:c0ecb8bf28eb 33153
Marko Mikulicic 0:c0ecb8bf28eb 33154 len = strftime(buf, sizeof(buf), frm, &t);
Marko Mikulicic 0:c0ecb8bf28eb 33155
Marko Mikulicic 0:c0ecb8bf28eb 33156 d_setlocale(&prev_locale);
Marko Mikulicic 0:c0ecb8bf28eb 33157
Marko Mikulicic 0:c0ecb8bf28eb 33158 *res = v7_mk_string(v7, buf, len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 33159 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33160 }
Marko Mikulicic 0:c0ecb8bf28eb 33161
Marko Mikulicic 0:c0ecb8bf28eb 33162 #define DEF_TOLOCALESTR(funcname, frm) \
Marko Mikulicic 0:c0ecb8bf28eb 33163 WARN_UNUSED_RESULT \
Marko Mikulicic 0:c0ecb8bf28eb 33164 V7_PRIVATE enum v7_err Date_to##funcname(struct v7 *v7, v7_val_t *res) { \
Marko Mikulicic 0:c0ecb8bf28eb 33165 val_t this_obj = v7_get_this(v7); \
Marko Mikulicic 0:c0ecb8bf28eb 33166 return d_tolocalestr(v7, this_obj, frm, res); \
Marko Mikulicic 0:c0ecb8bf28eb 33167 }
Marko Mikulicic 0:c0ecb8bf28eb 33168
Marko Mikulicic 0:c0ecb8bf28eb 33169 DEF_TOLOCALESTR(LocaleString, "%c")
Marko Mikulicic 0:c0ecb8bf28eb 33170 DEF_TOLOCALESTR(LocaleDateString, "%x")
Marko Mikulicic 0:c0ecb8bf28eb 33171 DEF_TOLOCALESTR(LocaleTimeString, "%X")
Marko Mikulicic 0:c0ecb8bf28eb 33172 #endif /* V7_ENABLE__Date__toLocaleString */
Marko Mikulicic 0:c0ecb8bf28eb 33173
Marko Mikulicic 0:c0ecb8bf28eb 33174 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33175 V7_PRIVATE enum v7_err Date_valueOf(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33176 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33177 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33178 if (!v7_is_generic_object(this_obj) ||
Marko Mikulicic 0:c0ecb8bf28eb 33179 (v7_is_generic_object(this_obj) &&
Marko Mikulicic 0:c0ecb8bf28eb 33180 v7_get_proto(v7, this_obj) != v7->vals.date_prototype)) {
Marko Mikulicic 0:c0ecb8bf28eb 33181 rcode = v7_throwf(v7, TYPE_ERROR, "Date.valueOf called on non-Date object");
Marko Mikulicic 0:c0ecb8bf28eb 33182 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33183 }
Marko Mikulicic 0:c0ecb8bf28eb 33184
Marko Mikulicic 0:c0ecb8bf28eb 33185 rcode = Obj_valueOf(v7, res);
Marko Mikulicic 0:c0ecb8bf28eb 33186 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33187 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33188 }
Marko Mikulicic 0:c0ecb8bf28eb 33189
Marko Mikulicic 0:c0ecb8bf28eb 33190 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33191 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33192 }
Marko Mikulicic 0:c0ecb8bf28eb 33193
Marko Mikulicic 0:c0ecb8bf28eb 33194 #if V7_ENABLE__Date__getters
Marko Mikulicic 0:c0ecb8bf28eb 33195 static struct timeparts *d_getTimePart(struct v7 *v7, val_t val,
Marko Mikulicic 0:c0ecb8bf28eb 33196 struct timeparts *tp,
Marko Mikulicic 0:c0ecb8bf28eb 33197 fbreaktime_t breaktimefunc) {
Marko Mikulicic 0:c0ecb8bf28eb 33198 etime_t time;
Marko Mikulicic 0:c0ecb8bf28eb 33199 time = v7_get_double(v7, val);
Marko Mikulicic 0:c0ecb8bf28eb 33200 breaktimefunc(&time, tp);
Marko Mikulicic 0:c0ecb8bf28eb 33201 return tp;
Marko Mikulicic 0:c0ecb8bf28eb 33202 }
Marko Mikulicic 0:c0ecb8bf28eb 33203
Marko Mikulicic 0:c0ecb8bf28eb 33204 #define DEF_GET_TP_FUNC(funcName, tpmember, breaktimefunc) \
Marko Mikulicic 0:c0ecb8bf28eb 33205 WARN_UNUSED_RESULT \
Marko Mikulicic 0:c0ecb8bf28eb 33206 V7_PRIVATE enum v7_err Date_get##funcName(struct v7 *v7, v7_val_t *res) { \
Marko Mikulicic 0:c0ecb8bf28eb 33207 enum v7_err rcode = V7_OK; \
Marko Mikulicic 0:c0ecb8bf28eb 33208 val_t v = V7_UNDEFINED; \
Marko Mikulicic 0:c0ecb8bf28eb 33209 struct timeparts tp; \
Marko Mikulicic 0:c0ecb8bf28eb 33210 val_t this_obj = v7_get_this(v7); \
Marko Mikulicic 0:c0ecb8bf28eb 33211 \
Marko Mikulicic 0:c0ecb8bf28eb 33212 rcode = obj_value_of(v7, this_obj, &v); \
Marko Mikulicic 0:c0ecb8bf28eb 33213 if (rcode != V7_OK) { \
Marko Mikulicic 0:c0ecb8bf28eb 33214 goto clean; \
Marko Mikulicic 0:c0ecb8bf28eb 33215 } \
Marko Mikulicic 0:c0ecb8bf28eb 33216 *res = v7_mk_number( \
Marko Mikulicic 0:c0ecb8bf28eb 33217 v7, v == V7_TAG_NAN ? NAN : d_getTimePart(v7, v, &tp, breaktimefunc) \
Marko Mikulicic 0:c0ecb8bf28eb 33218 ->tpmember); \
Marko Mikulicic 0:c0ecb8bf28eb 33219 clean: \
Marko Mikulicic 0:c0ecb8bf28eb 33220 return rcode; \
Marko Mikulicic 0:c0ecb8bf28eb 33221 }
Marko Mikulicic 0:c0ecb8bf28eb 33222
Marko Mikulicic 0:c0ecb8bf28eb 33223 #define DEF_GET_TP(funcName, tpmember) \
Marko Mikulicic 0:c0ecb8bf28eb 33224 DEF_GET_TP_FUNC(UTC##funcName, tpmember, d_gmtime) \
Marko Mikulicic 0:c0ecb8bf28eb 33225 DEF_GET_TP_FUNC(funcName, tpmember, d_localtime)
Marko Mikulicic 0:c0ecb8bf28eb 33226
Marko Mikulicic 0:c0ecb8bf28eb 33227 DEF_GET_TP(Date, day)
Marko Mikulicic 0:c0ecb8bf28eb 33228 DEF_GET_TP(FullYear, year)
Marko Mikulicic 0:c0ecb8bf28eb 33229 DEF_GET_TP(Month, month)
Marko Mikulicic 0:c0ecb8bf28eb 33230 DEF_GET_TP(Hours, hour)
Marko Mikulicic 0:c0ecb8bf28eb 33231 DEF_GET_TP(Minutes, min)
Marko Mikulicic 0:c0ecb8bf28eb 33232 DEF_GET_TP(Seconds, sec)
Marko Mikulicic 0:c0ecb8bf28eb 33233 DEF_GET_TP(Milliseconds, msec)
Marko Mikulicic 0:c0ecb8bf28eb 33234 DEF_GET_TP(Day, dayofweek)
Marko Mikulicic 0:c0ecb8bf28eb 33235
Marko Mikulicic 0:c0ecb8bf28eb 33236 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33237 V7_PRIVATE enum v7_err Date_getTime(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33238 return Date_valueOf(v7, res);
Marko Mikulicic 0:c0ecb8bf28eb 33239 }
Marko Mikulicic 0:c0ecb8bf28eb 33240
Marko Mikulicic 0:c0ecb8bf28eb 33241 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33242 V7_PRIVATE enum v7_err Date_getTimezoneOffset(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33243 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 33244 *res = v7_mk_number(v7, g_gmtoffms / msPerMinute);
Marko Mikulicic 0:c0ecb8bf28eb 33245 return V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33246 }
Marko Mikulicic 0:c0ecb8bf28eb 33247 #endif /* V7_ENABLE__Date__getters */
Marko Mikulicic 0:c0ecb8bf28eb 33248
Marko Mikulicic 0:c0ecb8bf28eb 33249 #if V7_ENABLE__Date__setters
Marko Mikulicic 0:c0ecb8bf28eb 33250 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33251 static enum v7_err d_setTimePart(struct v7 *v7, int start_pos,
Marko Mikulicic 0:c0ecb8bf28eb 33252 fbreaktime_t breaktimefunc,
Marko Mikulicic 0:c0ecb8bf28eb 33253 fmaketime_t maketimefunc, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33254 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33255 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33256 etime_t ret_time =
Marko Mikulicic 0:c0ecb8bf28eb 33257 d_time_number_from_arr(v7, start_pos, breaktimefunc, maketimefunc);
Marko Mikulicic 0:c0ecb8bf28eb 33258
Marko Mikulicic 0:c0ecb8bf28eb 33259 *res = v7_mk_number(v7, ret_time);
Marko Mikulicic 0:c0ecb8bf28eb 33260 v7_def(v7, this_obj, "", 0, _V7_DESC_HIDDEN(1), *res);
Marko Mikulicic 0:c0ecb8bf28eb 33261
Marko Mikulicic 0:c0ecb8bf28eb 33262 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33263 }
Marko Mikulicic 0:c0ecb8bf28eb 33264
Marko Mikulicic 0:c0ecb8bf28eb 33265 #define DEF_SET_TP(name, start_pos) \
Marko Mikulicic 0:c0ecb8bf28eb 33266 WARN_UNUSED_RESULT \
Marko Mikulicic 0:c0ecb8bf28eb 33267 V7_PRIVATE enum v7_err Date_setUTC##name(struct v7 *v7, v7_val_t *res) { \
Marko Mikulicic 0:c0ecb8bf28eb 33268 return d_setTimePart(v7, start_pos, d_gmtime, d_gmktime, res); \
Marko Mikulicic 0:c0ecb8bf28eb 33269 } \
Marko Mikulicic 0:c0ecb8bf28eb 33270 WARN_UNUSED_RESULT \
Marko Mikulicic 0:c0ecb8bf28eb 33271 V7_PRIVATE enum v7_err Date_set##name(struct v7 *v7, v7_val_t *res) { \
Marko Mikulicic 0:c0ecb8bf28eb 33272 return d_setTimePart(v7, start_pos, d_localtime, d_lmktime, res); \
Marko Mikulicic 0:c0ecb8bf28eb 33273 }
Marko Mikulicic 0:c0ecb8bf28eb 33274
Marko Mikulicic 0:c0ecb8bf28eb 33275 DEF_SET_TP(Milliseconds, tpmsec)
Marko Mikulicic 0:c0ecb8bf28eb 33276 DEF_SET_TP(Seconds, tpseconds)
Marko Mikulicic 0:c0ecb8bf28eb 33277 DEF_SET_TP(Minutes, tpminutes)
Marko Mikulicic 0:c0ecb8bf28eb 33278 DEF_SET_TP(Hours, tphours)
Marko Mikulicic 0:c0ecb8bf28eb 33279 DEF_SET_TP(Date, tpdate)
Marko Mikulicic 0:c0ecb8bf28eb 33280 DEF_SET_TP(Month, tpmonth)
Marko Mikulicic 0:c0ecb8bf28eb 33281 DEF_SET_TP(FullYear, tpyear)
Marko Mikulicic 0:c0ecb8bf28eb 33282
Marko Mikulicic 0:c0ecb8bf28eb 33283 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33284 V7_PRIVATE enum v7_err Date_setTime(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33285 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33286 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33287
Marko Mikulicic 0:c0ecb8bf28eb 33288 if (v7_argc(v7) >= 1) {
Marko Mikulicic 0:c0ecb8bf28eb 33289 rcode = to_number_v(v7, v7_arg(v7, 0), res);
Marko Mikulicic 0:c0ecb8bf28eb 33290 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33291 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33292 }
Marko Mikulicic 0:c0ecb8bf28eb 33293 }
Marko Mikulicic 0:c0ecb8bf28eb 33294
Marko Mikulicic 0:c0ecb8bf28eb 33295 v7_def(v7, this_obj, "", 0, _V7_DESC_HIDDEN(1), *res);
Marko Mikulicic 0:c0ecb8bf28eb 33296
Marko Mikulicic 0:c0ecb8bf28eb 33297 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33298 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33299 }
Marko Mikulicic 0:c0ecb8bf28eb 33300 #endif /* V7_ENABLE__Date__setters */
Marko Mikulicic 0:c0ecb8bf28eb 33301
Marko Mikulicic 0:c0ecb8bf28eb 33302 #if V7_ENABLE__Date__toJSON
Marko Mikulicic 0:c0ecb8bf28eb 33303 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33304 V7_PRIVATE enum v7_err Date_toJSON(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33305 return Date_toISOString(v7, res);
Marko Mikulicic 0:c0ecb8bf28eb 33306 }
Marko Mikulicic 0:c0ecb8bf28eb 33307 #endif /* V7_ENABLE__Date__toJSON */
Marko Mikulicic 0:c0ecb8bf28eb 33308
Marko Mikulicic 0:c0ecb8bf28eb 33309 #if V7_ENABLE__Date__now
Marko Mikulicic 0:c0ecb8bf28eb 33310 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33311 V7_PRIVATE enum v7_err Date_now(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33312 etime_t ret_time;
Marko Mikulicic 0:c0ecb8bf28eb 33313 (void) v7;
Marko Mikulicic 0:c0ecb8bf28eb 33314
Marko Mikulicic 0:c0ecb8bf28eb 33315 d_gettime(&ret_time);
Marko Mikulicic 0:c0ecb8bf28eb 33316
Marko Mikulicic 0:c0ecb8bf28eb 33317 *res = v7_mk_number(v7, ret_time);
Marko Mikulicic 0:c0ecb8bf28eb 33318 return V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33319 }
Marko Mikulicic 0:c0ecb8bf28eb 33320 #endif /* V7_ENABLE__Date__now */
Marko Mikulicic 0:c0ecb8bf28eb 33321
Marko Mikulicic 0:c0ecb8bf28eb 33322 #if V7_ENABLE__Date__parse
Marko Mikulicic 0:c0ecb8bf28eb 33323 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33324 V7_PRIVATE enum v7_err Date_parse(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33325 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33326 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33327 etime_t ret_time = INVALID_TIME;
Marko Mikulicic 0:c0ecb8bf28eb 33328
Marko Mikulicic 0:c0ecb8bf28eb 33329 if (!d_iscalledasfunction(v7, this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 33330 rcode = v7_throwf(v7, TYPE_ERROR, "Date.parse() called on object");
Marko Mikulicic 0:c0ecb8bf28eb 33331 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33332 }
Marko Mikulicic 0:c0ecb8bf28eb 33333
Marko Mikulicic 0:c0ecb8bf28eb 33334 if (v7_argc(v7) >= 1) {
Marko Mikulicic 0:c0ecb8bf28eb 33335 val_t arg0 = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 33336 if (v7_is_string(arg0)) {
Marko Mikulicic 0:c0ecb8bf28eb 33337 size_t size;
Marko Mikulicic 0:c0ecb8bf28eb 33338 const char *time_str = v7_get_string(v7, &arg0, &size);
Marko Mikulicic 0:c0ecb8bf28eb 33339
Marko Mikulicic 0:c0ecb8bf28eb 33340 d_timeFromString(&ret_time, time_str, size);
Marko Mikulicic 0:c0ecb8bf28eb 33341 }
Marko Mikulicic 0:c0ecb8bf28eb 33342 }
Marko Mikulicic 0:c0ecb8bf28eb 33343
Marko Mikulicic 0:c0ecb8bf28eb 33344 *res = v7_mk_number(v7, ret_time);
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__parse */
Marko Mikulicic 0:c0ecb8bf28eb 33350
Marko Mikulicic 0:c0ecb8bf28eb 33351 #if V7_ENABLE__Date__UTC
Marko Mikulicic 0:c0ecb8bf28eb 33352 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33353 V7_PRIVATE enum v7_err Date_UTC(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33354 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33355 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33356 etime_t ret_time;
Marko Mikulicic 0:c0ecb8bf28eb 33357
Marko Mikulicic 0:c0ecb8bf28eb 33358 if (!d_iscalledasfunction(v7, this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 33359 rcode = v7_throwf(v7, TYPE_ERROR, "Date.now() called on object");
Marko Mikulicic 0:c0ecb8bf28eb 33360 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33361 }
Marko Mikulicic 0:c0ecb8bf28eb 33362
Marko Mikulicic 0:c0ecb8bf28eb 33363 ret_time = d_time_number_from_arr(v7, tpyear, 0, d_gmktime);
Marko Mikulicic 0:c0ecb8bf28eb 33364 *res = v7_mk_number(v7, ret_time);
Marko Mikulicic 0:c0ecb8bf28eb 33365
Marko Mikulicic 0:c0ecb8bf28eb 33366 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33367 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33368 }
Marko Mikulicic 0:c0ecb8bf28eb 33369 #endif /* V7_ENABLE__Date__UTC */
Marko Mikulicic 0:c0ecb8bf28eb 33370
Marko Mikulicic 0:c0ecb8bf28eb 33371 /****** Initialization *******/
Marko Mikulicic 0:c0ecb8bf28eb 33372
Marko Mikulicic 0:c0ecb8bf28eb 33373 /*
Marko Mikulicic 0:c0ecb8bf28eb 33374 * We should clear V7_PROPERTY_ENUMERABLE for all Date props
Marko Mikulicic 0:c0ecb8bf28eb 33375 * TODO(mkm): check other objects
Marko Mikulicic 0:c0ecb8bf28eb 33376 */
Marko Mikulicic 0:c0ecb8bf28eb 33377 static int d_set_cfunc_prop(struct v7 *v7, val_t o, const char *name,
Marko Mikulicic 0:c0ecb8bf28eb 33378 v7_cfunction_t *f) {
Marko Mikulicic 0:c0ecb8bf28eb 33379 return v7_def(v7, o, name, strlen(name), V7_DESC_ENUMERABLE(0),
Marko Mikulicic 0:c0ecb8bf28eb 33380 v7_mk_cfunction(f));
Marko Mikulicic 0:c0ecb8bf28eb 33381 }
Marko Mikulicic 0:c0ecb8bf28eb 33382
Marko Mikulicic 0:c0ecb8bf28eb 33383 #define DECLARE_GET(func) \
Marko Mikulicic 0:c0ecb8bf28eb 33384 d_set_cfunc_prop(v7, v7->vals.date_prototype, "getUTC" #func, \
Marko Mikulicic 0:c0ecb8bf28eb 33385 Date_getUTC##func); \
Marko Mikulicic 0:c0ecb8bf28eb 33386 d_set_cfunc_prop(v7, v7->vals.date_prototype, "get" #func, Date_get##func);
Marko Mikulicic 0:c0ecb8bf28eb 33387
Marko Mikulicic 0:c0ecb8bf28eb 33388 #define DECLARE_SET(func) \
Marko Mikulicic 0:c0ecb8bf28eb 33389 d_set_cfunc_prop(v7, v7->vals.date_prototype, "setUTC" #func, \
Marko Mikulicic 0:c0ecb8bf28eb 33390 Date_setUTC##func); \
Marko Mikulicic 0:c0ecb8bf28eb 33391 d_set_cfunc_prop(v7, v7->vals.date_prototype, "set" #func, Date_set##func);
Marko Mikulicic 0:c0ecb8bf28eb 33392
Marko Mikulicic 0:c0ecb8bf28eb 33393 V7_PRIVATE void init_date(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 33394 val_t date =
Marko Mikulicic 0:c0ecb8bf28eb 33395 mk_cfunction_obj_with_proto(v7, Date_ctor, 7, v7->vals.date_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 33396 v7_def(v7, v7->vals.global_object, "Date", 4, V7_DESC_ENUMERABLE(0), date);
Marko Mikulicic 0:c0ecb8bf28eb 33397 d_set_cfunc_prop(v7, v7->vals.date_prototype, "valueOf", Date_valueOf);
Marko Mikulicic 0:c0ecb8bf28eb 33398
Marko Mikulicic 0:c0ecb8bf28eb 33399 #if V7_ENABLE__Date__getters
Marko Mikulicic 0:c0ecb8bf28eb 33400 DECLARE_GET(Date);
Marko Mikulicic 0:c0ecb8bf28eb 33401 DECLARE_GET(FullYear);
Marko Mikulicic 0:c0ecb8bf28eb 33402 DECLARE_GET(Month);
Marko Mikulicic 0:c0ecb8bf28eb 33403 DECLARE_GET(Hours);
Marko Mikulicic 0:c0ecb8bf28eb 33404 DECLARE_GET(Minutes);
Marko Mikulicic 0:c0ecb8bf28eb 33405 DECLARE_GET(Seconds);
Marko Mikulicic 0:c0ecb8bf28eb 33406 DECLARE_GET(Milliseconds);
Marko Mikulicic 0:c0ecb8bf28eb 33407 DECLARE_GET(Day);
Marko Mikulicic 0:c0ecb8bf28eb 33408 d_set_cfunc_prop(v7, v7->vals.date_prototype, "getTime", Date_getTime);
Marko Mikulicic 0:c0ecb8bf28eb 33409 #endif
Marko Mikulicic 0:c0ecb8bf28eb 33410
Marko Mikulicic 0:c0ecb8bf28eb 33411 #if V7_ENABLE__Date__setters
Marko Mikulicic 0:c0ecb8bf28eb 33412 DECLARE_SET(Date);
Marko Mikulicic 0:c0ecb8bf28eb 33413 DECLARE_SET(FullYear);
Marko Mikulicic 0:c0ecb8bf28eb 33414 DECLARE_SET(Month);
Marko Mikulicic 0:c0ecb8bf28eb 33415 DECLARE_SET(Hours);
Marko Mikulicic 0:c0ecb8bf28eb 33416 DECLARE_SET(Minutes);
Marko Mikulicic 0:c0ecb8bf28eb 33417 DECLARE_SET(Seconds);
Marko Mikulicic 0:c0ecb8bf28eb 33418 DECLARE_SET(Milliseconds);
Marko Mikulicic 0:c0ecb8bf28eb 33419 d_set_cfunc_prop(v7, v7->vals.date_prototype, "setTime", Date_setTime);
Marko Mikulicic 0:c0ecb8bf28eb 33420 d_set_cfunc_prop(v7, v7->vals.date_prototype, "getTimezoneOffset",
Marko Mikulicic 0:c0ecb8bf28eb 33421 Date_getTimezoneOffset);
Marko Mikulicic 0:c0ecb8bf28eb 33422 #endif
Marko Mikulicic 0:c0ecb8bf28eb 33423
Marko Mikulicic 0:c0ecb8bf28eb 33424 #if V7_ENABLE__Date__now
Marko Mikulicic 0:c0ecb8bf28eb 33425 d_set_cfunc_prop(v7, date, "now", Date_now);
Marko Mikulicic 0:c0ecb8bf28eb 33426 #endif
Marko Mikulicic 0:c0ecb8bf28eb 33427 #if V7_ENABLE__Date__parse
Marko Mikulicic 0:c0ecb8bf28eb 33428 d_set_cfunc_prop(v7, date, "parse", Date_parse);
Marko Mikulicic 0:c0ecb8bf28eb 33429 #endif
Marko Mikulicic 0:c0ecb8bf28eb 33430 #if V7_ENABLE__Date__UTC
Marko Mikulicic 0:c0ecb8bf28eb 33431 d_set_cfunc_prop(v7, date, "UTC", Date_UTC);
Marko Mikulicic 0:c0ecb8bf28eb 33432 #endif
Marko Mikulicic 0:c0ecb8bf28eb 33433
Marko Mikulicic 0:c0ecb8bf28eb 33434 #if V7_ENABLE__Date__toString
Marko Mikulicic 0:c0ecb8bf28eb 33435 d_set_cfunc_prop(v7, v7->vals.date_prototype, "toString", Date_toString);
Marko Mikulicic 0:c0ecb8bf28eb 33436 d_set_cfunc_prop(v7, v7->vals.date_prototype, "toISOString",
Marko Mikulicic 0:c0ecb8bf28eb 33437 Date_toISOString);
Marko Mikulicic 0:c0ecb8bf28eb 33438 d_set_cfunc_prop(v7, v7->vals.date_prototype, "toUTCString",
Marko Mikulicic 0:c0ecb8bf28eb 33439 Date_toUTCString);
Marko Mikulicic 0:c0ecb8bf28eb 33440 d_set_cfunc_prop(v7, v7->vals.date_prototype, "toDateString",
Marko Mikulicic 0:c0ecb8bf28eb 33441 Date_toDateString);
Marko Mikulicic 0:c0ecb8bf28eb 33442 d_set_cfunc_prop(v7, v7->vals.date_prototype, "toTimeString",
Marko Mikulicic 0:c0ecb8bf28eb 33443 Date_toTimeString);
Marko Mikulicic 0:c0ecb8bf28eb 33444 #endif
Marko Mikulicic 0:c0ecb8bf28eb 33445 #if V7_ENABLE__Date__toLocaleString
Marko Mikulicic 0:c0ecb8bf28eb 33446 d_set_cfunc_prop(v7, v7->vals.date_prototype, "toLocaleString",
Marko Mikulicic 0:c0ecb8bf28eb 33447 Date_toLocaleString);
Marko Mikulicic 0:c0ecb8bf28eb 33448 d_set_cfunc_prop(v7, v7->vals.date_prototype, "toLocaleDateString",
Marko Mikulicic 0:c0ecb8bf28eb 33449 Date_toLocaleDateString);
Marko Mikulicic 0:c0ecb8bf28eb 33450 d_set_cfunc_prop(v7, v7->vals.date_prototype, "toLocaleTimeString",
Marko Mikulicic 0:c0ecb8bf28eb 33451 Date_toLocaleTimeString);
Marko Mikulicic 0:c0ecb8bf28eb 33452 #endif
Marko Mikulicic 0:c0ecb8bf28eb 33453 #if V7_ENABLE__Date__toJSON
Marko Mikulicic 0:c0ecb8bf28eb 33454 d_set_cfunc_prop(v7, v7->vals.date_prototype, "toJSON", Date_toJSON);
Marko Mikulicic 0:c0ecb8bf28eb 33455 #endif
Marko Mikulicic 0:c0ecb8bf28eb 33456
Marko Mikulicic 0:c0ecb8bf28eb 33457 /*
Marko Mikulicic 0:c0ecb8bf28eb 33458 * GTM offset without DST
Marko Mikulicic 0:c0ecb8bf28eb 33459 * TODO(alashkin): check this
Marko Mikulicic 0:c0ecb8bf28eb 33460 * Could be changed to tm::tm_gmtoff,
Marko Mikulicic 0:c0ecb8bf28eb 33461 * but tm_gmtoff includes DST, so
Marko Mikulicic 0:c0ecb8bf28eb 33462 * side effects are possible
Marko Mikulicic 0:c0ecb8bf28eb 33463 */
Marko Mikulicic 0:c0ecb8bf28eb 33464 tzset();
Marko Mikulicic 0:c0ecb8bf28eb 33465 g_gmtoffms = timezone * msPerSecond;
Marko Mikulicic 0:c0ecb8bf28eb 33466 /*
Marko Mikulicic 0:c0ecb8bf28eb 33467 * tzname could be changed by localtime_r call,
Marko Mikulicic 0:c0ecb8bf28eb 33468 * so we have to store pointer
Marko Mikulicic 0:c0ecb8bf28eb 33469 * TODO(alashkin): need restart on tz change???
Marko Mikulicic 0:c0ecb8bf28eb 33470 */
Marko Mikulicic 0:c0ecb8bf28eb 33471 g_tzname = tzname[0];
Marko Mikulicic 0:c0ecb8bf28eb 33472 }
Marko Mikulicic 0:c0ecb8bf28eb 33473
Marko Mikulicic 0:c0ecb8bf28eb 33474 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 33475 }
Marko Mikulicic 0:c0ecb8bf28eb 33476 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 33477
Marko Mikulicic 0:c0ecb8bf28eb 33478 #endif /* V7_ENABLE__Date */
Marko Mikulicic 0:c0ecb8bf28eb 33479 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 33480 #line 1 "v7/src/std_function.c"
Marko Mikulicic 0:c0ecb8bf28eb 33481 #endif
Marko Mikulicic 0:c0ecb8bf28eb 33482 /*
Marko Mikulicic 0:c0ecb8bf28eb 33483 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 33484 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 33485 */
Marko Mikulicic 0:c0ecb8bf28eb 33486
Marko Mikulicic 0:c0ecb8bf28eb 33487 /* Amalgamated: #include "common/str_util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33488 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33489 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33490 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33491 /* Amalgamated: #include "v7/src/bcode.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33492 /* Amalgamated: #include "v7/src/eval.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33493 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33494 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33495 /* Amalgamated: #include "v7/src/exec.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33496 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33497
Marko Mikulicic 0:c0ecb8bf28eb 33498 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 33499 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 33500 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 33501
Marko Mikulicic 0:c0ecb8bf28eb 33502 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33503 V7_PRIVATE enum v7_err Function_ctor(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33504 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33505 long i, num_args = v7_argc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33506 size_t size;
Marko Mikulicic 0:c0ecb8bf28eb 33507 const char *s;
Marko Mikulicic 0:c0ecb8bf28eb 33508 struct mbuf m;
Marko Mikulicic 0:c0ecb8bf28eb 33509
Marko Mikulicic 0:c0ecb8bf28eb 33510 mbuf_init(&m, 0);
Marko Mikulicic 0:c0ecb8bf28eb 33511
Marko Mikulicic 0:c0ecb8bf28eb 33512 if (num_args <= 0) {
Marko Mikulicic 0:c0ecb8bf28eb 33513 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33514 }
Marko Mikulicic 0:c0ecb8bf28eb 33515
Marko Mikulicic 0:c0ecb8bf28eb 33516 mbuf_append(&m, "(function(", 10);
Marko Mikulicic 0:c0ecb8bf28eb 33517
Marko Mikulicic 0:c0ecb8bf28eb 33518 for (i = 0; i < num_args - 1; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 33519 rcode = obj_value_of(v7, v7_arg(v7, i), res);
Marko Mikulicic 0:c0ecb8bf28eb 33520 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33521 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33522 }
Marko Mikulicic 0:c0ecb8bf28eb 33523 if (v7_is_string(*res)) {
Marko Mikulicic 0:c0ecb8bf28eb 33524 if (i > 0) mbuf_append(&m, ",", 1);
Marko Mikulicic 0:c0ecb8bf28eb 33525 s = v7_get_string(v7, res, &size);
Marko Mikulicic 0:c0ecb8bf28eb 33526 mbuf_append(&m, s, size);
Marko Mikulicic 0:c0ecb8bf28eb 33527 }
Marko Mikulicic 0:c0ecb8bf28eb 33528 }
Marko Mikulicic 0:c0ecb8bf28eb 33529 mbuf_append(&m, "){", 2);
Marko Mikulicic 0:c0ecb8bf28eb 33530 rcode = obj_value_of(v7, v7_arg(v7, num_args - 1), res);
Marko Mikulicic 0:c0ecb8bf28eb 33531 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33532 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33533 }
Marko Mikulicic 0:c0ecb8bf28eb 33534 if (v7_is_string(*res)) {
Marko Mikulicic 0:c0ecb8bf28eb 33535 s = v7_get_string(v7, res, &size);
Marko Mikulicic 0:c0ecb8bf28eb 33536 mbuf_append(&m, s, size);
Marko Mikulicic 0:c0ecb8bf28eb 33537 }
Marko Mikulicic 0:c0ecb8bf28eb 33538 mbuf_append(&m, "})\0", 3);
Marko Mikulicic 0:c0ecb8bf28eb 33539
Marko Mikulicic 0:c0ecb8bf28eb 33540 rcode = v7_exec(v7, m.buf, res);
Marko Mikulicic 0:c0ecb8bf28eb 33541 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33542 rcode = v7_throwf(v7, SYNTAX_ERROR, "Invalid function body");
Marko Mikulicic 0:c0ecb8bf28eb 33543 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33544 }
Marko Mikulicic 0:c0ecb8bf28eb 33545
Marko Mikulicic 0:c0ecb8bf28eb 33546 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33547 mbuf_free(&m);
Marko Mikulicic 0:c0ecb8bf28eb 33548 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33549 }
Marko Mikulicic 0:c0ecb8bf28eb 33550
Marko Mikulicic 0:c0ecb8bf28eb 33551 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33552 V7_PRIVATE enum v7_err Function_length(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33553 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33554 v7_val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33555 struct v7_js_function *func;
Marko Mikulicic 0:c0ecb8bf28eb 33556
Marko Mikulicic 0:c0ecb8bf28eb 33557 rcode = obj_value_of(v7, this_obj, &this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 33558 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33559 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33560 }
Marko Mikulicic 0:c0ecb8bf28eb 33561 if (!is_js_function(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 33562 *res = v7_mk_number(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 33563 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33564 }
Marko Mikulicic 0:c0ecb8bf28eb 33565
Marko Mikulicic 0:c0ecb8bf28eb 33566 func = get_js_function_struct(this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 33567
Marko Mikulicic 0:c0ecb8bf28eb 33568 *res = v7_mk_number(v7, func->bcode->args_cnt);
Marko Mikulicic 0:c0ecb8bf28eb 33569
Marko Mikulicic 0:c0ecb8bf28eb 33570 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33571 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33572 }
Marko Mikulicic 0:c0ecb8bf28eb 33573
Marko Mikulicic 0:c0ecb8bf28eb 33574 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33575 V7_PRIVATE enum v7_err Function_name(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33576 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33577 v7_val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33578 struct v7_js_function *func;
Marko Mikulicic 0:c0ecb8bf28eb 33579
Marko Mikulicic 0:c0ecb8bf28eb 33580 rcode = obj_value_of(v7, this_obj, &this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 33581 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33582 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33583 }
Marko Mikulicic 0:c0ecb8bf28eb 33584 if (!is_js_function(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 33585 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33586 }
Marko Mikulicic 0:c0ecb8bf28eb 33587
Marko Mikulicic 0:c0ecb8bf28eb 33588 func = get_js_function_struct(this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 33589
Marko Mikulicic 0:c0ecb8bf28eb 33590 assert(func->bcode != NULL);
Marko Mikulicic 0:c0ecb8bf28eb 33591
Marko Mikulicic 0:c0ecb8bf28eb 33592 assert(func->bcode->names_cnt >= 1);
Marko Mikulicic 0:c0ecb8bf28eb 33593 bcode_next_name_v(v7, func->bcode, func->bcode->ops.p, res);
Marko Mikulicic 0:c0ecb8bf28eb 33594
Marko Mikulicic 0:c0ecb8bf28eb 33595 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33596 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33597 }
Marko Mikulicic 0:c0ecb8bf28eb 33598
Marko Mikulicic 0:c0ecb8bf28eb 33599 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33600 V7_PRIVATE enum v7_err Function_apply(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33601 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33602 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33603 val_t this_arg = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 33604 val_t func_args = v7_arg(v7, 1);
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
Marko Mikulicic 0:c0ecb8bf28eb 33611 if (is_js_function(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 33612 /*
Marko Mikulicic 0:c0ecb8bf28eb 33613 * `Function_apply` is a cfunction, so, GC is inhibited before calling it.
Marko Mikulicic 0:c0ecb8bf28eb 33614 * But the given function to call is a JS function, so we should enable GC;
Marko Mikulicic 0:c0ecb8bf28eb 33615 * otherwise, it will be inhibited during the whole execution of the given
Marko Mikulicic 0:c0ecb8bf28eb 33616 * JS function
Marko Mikulicic 0:c0ecb8bf28eb 33617 */
Marko Mikulicic 0:c0ecb8bf28eb 33618 v7_set_gc_enabled(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 33619 }
Marko Mikulicic 0:c0ecb8bf28eb 33620
Marko Mikulicic 0:c0ecb8bf28eb 33621 rcode = b_apply(v7, this_obj, this_arg, func_args, 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 33622 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33623 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33624 }
Marko Mikulicic 0:c0ecb8bf28eb 33625
Marko Mikulicic 0:c0ecb8bf28eb 33626 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33627 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33628 }
Marko Mikulicic 0:c0ecb8bf28eb 33629
Marko Mikulicic 0:c0ecb8bf28eb 33630 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33631 V7_PRIVATE enum v7_err Function_toString(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33632 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33633 char *ops;
Marko Mikulicic 0:c0ecb8bf28eb 33634 char *name;
Marko Mikulicic 0:c0ecb8bf28eb 33635 size_t name_len;
Marko Mikulicic 0:c0ecb8bf28eb 33636 char buf[50];
Marko Mikulicic 0:c0ecb8bf28eb 33637 char *b = buf;
Marko Mikulicic 0:c0ecb8bf28eb 33638 struct v7_js_function *func = get_js_function_struct(v7_get_this(v7));
Marko Mikulicic 0:c0ecb8bf28eb 33639 int i;
Marko Mikulicic 0:c0ecb8bf28eb 33640
Marko Mikulicic 0:c0ecb8bf28eb 33641 b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "[function");
Marko Mikulicic 0:c0ecb8bf28eb 33642
Marko Mikulicic 0:c0ecb8bf28eb 33643 assert(func->bcode != NULL);
Marko Mikulicic 0:c0ecb8bf28eb 33644 ops = func->bcode->ops.p;
Marko Mikulicic 0:c0ecb8bf28eb 33645
Marko Mikulicic 0:c0ecb8bf28eb 33646 /* first entry in name list */
Marko Mikulicic 0:c0ecb8bf28eb 33647 ops = bcode_next_name(ops, &name, &name_len);
Marko Mikulicic 0:c0ecb8bf28eb 33648
Marko Mikulicic 0:c0ecb8bf28eb 33649 if (name_len > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 33650 b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), " %.*s", (int) name_len,
Marko Mikulicic 0:c0ecb8bf28eb 33651 name);
Marko Mikulicic 0:c0ecb8bf28eb 33652 }
Marko Mikulicic 0:c0ecb8bf28eb 33653 b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "(");
Marko Mikulicic 0:c0ecb8bf28eb 33654 for (i = 0; i < func->bcode->args_cnt; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 33655 ops = bcode_next_name(ops, &name, &name_len);
Marko Mikulicic 0:c0ecb8bf28eb 33656
Marko Mikulicic 0:c0ecb8bf28eb 33657 b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "%.*s", (int) name_len,
Marko Mikulicic 0:c0ecb8bf28eb 33658 name);
Marko Mikulicic 0:c0ecb8bf28eb 33659 if (i < func->bcode->args_cnt - 1) {
Marko Mikulicic 0:c0ecb8bf28eb 33660 b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), ",");
Marko Mikulicic 0:c0ecb8bf28eb 33661 }
Marko Mikulicic 0:c0ecb8bf28eb 33662 }
Marko Mikulicic 0:c0ecb8bf28eb 33663 b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), ")");
Marko Mikulicic 0:c0ecb8bf28eb 33664
Marko Mikulicic 0:c0ecb8bf28eb 33665 {
Marko Mikulicic 0:c0ecb8bf28eb 33666 uint8_t loc_cnt =
Marko Mikulicic 0:c0ecb8bf28eb 33667 func->bcode->names_cnt - func->bcode->args_cnt - 1 /*func name*/;
Marko Mikulicic 0:c0ecb8bf28eb 33668
Marko Mikulicic 0:c0ecb8bf28eb 33669 if (loc_cnt > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 33670 b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "{var ");
Marko Mikulicic 0:c0ecb8bf28eb 33671 for (i = 0; i < loc_cnt; ++i) {
Marko Mikulicic 0:c0ecb8bf28eb 33672 ops = bcode_next_name(ops, &name, &name_len);
Marko Mikulicic 0:c0ecb8bf28eb 33673
Marko Mikulicic 0:c0ecb8bf28eb 33674 b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "%.*s",
Marko Mikulicic 0:c0ecb8bf28eb 33675 (int) name_len, name);
Marko Mikulicic 0:c0ecb8bf28eb 33676 if (i < (loc_cnt - 1)) {
Marko Mikulicic 0:c0ecb8bf28eb 33677 b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), ",");
Marko Mikulicic 0:c0ecb8bf28eb 33678 }
Marko Mikulicic 0:c0ecb8bf28eb 33679 }
Marko Mikulicic 0:c0ecb8bf28eb 33680
Marko Mikulicic 0:c0ecb8bf28eb 33681 b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "}");
Marko Mikulicic 0:c0ecb8bf28eb 33682 }
Marko Mikulicic 0:c0ecb8bf28eb 33683 }
Marko Mikulicic 0:c0ecb8bf28eb 33684
Marko Mikulicic 0:c0ecb8bf28eb 33685 b += c_snprintf(b, BUF_LEFT(sizeof(buf), b - buf), "]");
Marko Mikulicic 0:c0ecb8bf28eb 33686
Marko Mikulicic 0:c0ecb8bf28eb 33687 *res = v7_mk_string(v7, buf, strlen(buf), 1);
Marko Mikulicic 0:c0ecb8bf28eb 33688
Marko Mikulicic 0:c0ecb8bf28eb 33689 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33690 }
Marko Mikulicic 0:c0ecb8bf28eb 33691
Marko Mikulicic 0:c0ecb8bf28eb 33692 V7_PRIVATE void init_function(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 33693 val_t ctor = mk_cfunction_obj(v7, Function_ctor, 1);
Marko Mikulicic 0:c0ecb8bf28eb 33694
Marko Mikulicic 0:c0ecb8bf28eb 33695 v7_set(v7, ctor, "prototype", 9, v7->vals.function_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 33696 v7_set(v7, v7->vals.global_object, "Function", 8, ctor);
Marko Mikulicic 0:c0ecb8bf28eb 33697 set_method(v7, v7->vals.function_prototype, "apply", Function_apply, 1);
Marko Mikulicic 0:c0ecb8bf28eb 33698 set_method(v7, v7->vals.function_prototype, "toString", Function_toString, 0);
Marko Mikulicic 0:c0ecb8bf28eb 33699 v7_def(v7, v7->vals.function_prototype, "length", 6,
Marko Mikulicic 0:c0ecb8bf28eb 33700 (V7_DESC_ENUMERABLE(0) | V7_DESC_GETTER(1)),
Marko Mikulicic 0:c0ecb8bf28eb 33701 v7_mk_cfunction(Function_length));
Marko Mikulicic 0:c0ecb8bf28eb 33702 v7_def(v7, v7->vals.function_prototype, "name", 4,
Marko Mikulicic 0:c0ecb8bf28eb 33703 (V7_DESC_ENUMERABLE(0) | V7_DESC_GETTER(1)),
Marko Mikulicic 0:c0ecb8bf28eb 33704 v7_mk_cfunction(Function_name));
Marko Mikulicic 0:c0ecb8bf28eb 33705 }
Marko Mikulicic 0:c0ecb8bf28eb 33706
Marko Mikulicic 0:c0ecb8bf28eb 33707 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 33708 }
Marko Mikulicic 0:c0ecb8bf28eb 33709 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 33710 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 33711 #line 1 "v7/src/std_regex.c"
Marko Mikulicic 0:c0ecb8bf28eb 33712 #endif
Marko Mikulicic 0:c0ecb8bf28eb 33713 /*
Marko Mikulicic 0:c0ecb8bf28eb 33714 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 33715 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 33716 */
Marko Mikulicic 0:c0ecb8bf28eb 33717
Marko Mikulicic 0:c0ecb8bf28eb 33718 /* Amalgamated: #include "common/utf.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33719 /* Amalgamated: #include "common/str_util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33720 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33721 /* Amalgamated: #include "v7/src/std_regex.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33722 /* Amalgamated: #include "v7/src/std_string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33723 /* Amalgamated: #include "v7/src/slre.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33724 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33725 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33726 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33727 /* Amalgamated: #include "v7/src/array.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33728 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33729 /* Amalgamated: #include "v7/src/regexp.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33730 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33731 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33732 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 33733
Marko Mikulicic 0:c0ecb8bf28eb 33734 #if V7_ENABLE__RegExp
Marko Mikulicic 0:c0ecb8bf28eb 33735
Marko Mikulicic 0:c0ecb8bf28eb 33736 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33737 V7_PRIVATE enum v7_err Regex_ctor(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33738 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33739 long argnum = v7_argc(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33740
Marko Mikulicic 0:c0ecb8bf28eb 33741 if (argnum > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 33742 val_t arg = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 33743 val_t ro, fl;
Marko Mikulicic 0:c0ecb8bf28eb 33744 size_t re_len, flags_len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 33745 const char *re, *flags = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 33746
Marko Mikulicic 0:c0ecb8bf28eb 33747 if (v7_is_regexp(v7, arg)) {
Marko Mikulicic 0:c0ecb8bf28eb 33748 if (argnum > 1) {
Marko Mikulicic 0:c0ecb8bf28eb 33749 /* ch15/15.10/15.10.3/S15.10.3.1_A2_T1.js */
Marko Mikulicic 0:c0ecb8bf28eb 33750 rcode = v7_throwf(v7, TYPE_ERROR, "invalid flags");
Marko Mikulicic 0:c0ecb8bf28eb 33751 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33752 }
Marko Mikulicic 0:c0ecb8bf28eb 33753 *res = arg;
Marko Mikulicic 0:c0ecb8bf28eb 33754 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33755 }
Marko Mikulicic 0:c0ecb8bf28eb 33756 rcode = to_string(v7, arg, &ro, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 33757 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33758 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33759 }
Marko Mikulicic 0:c0ecb8bf28eb 33760
Marko Mikulicic 0:c0ecb8bf28eb 33761 if (argnum > 1) {
Marko Mikulicic 0:c0ecb8bf28eb 33762 rcode = to_string(v7, v7_arg(v7, 1), &fl, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 33763 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33764 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33765 }
Marko Mikulicic 0:c0ecb8bf28eb 33766
Marko Mikulicic 0:c0ecb8bf28eb 33767 flags = v7_get_string(v7, &fl, &flags_len);
Marko Mikulicic 0:c0ecb8bf28eb 33768 }
Marko Mikulicic 0:c0ecb8bf28eb 33769 re = v7_get_string(v7, &ro, &re_len);
Marko Mikulicic 0:c0ecb8bf28eb 33770 rcode = v7_mk_regexp(v7, re, re_len, flags, flags_len, res);
Marko Mikulicic 0:c0ecb8bf28eb 33771 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33772 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33773 }
Marko Mikulicic 0:c0ecb8bf28eb 33774
Marko Mikulicic 0:c0ecb8bf28eb 33775 } else {
Marko Mikulicic 0:c0ecb8bf28eb 33776 rcode = v7_mk_regexp(v7, "(?:)", 4, NULL, 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 33777 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33778 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33779 }
Marko Mikulicic 0:c0ecb8bf28eb 33780 }
Marko Mikulicic 0:c0ecb8bf28eb 33781
Marko Mikulicic 0:c0ecb8bf28eb 33782 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33783 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33784 }
Marko Mikulicic 0:c0ecb8bf28eb 33785
Marko Mikulicic 0:c0ecb8bf28eb 33786 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33787 V7_PRIVATE enum v7_err Regex_global(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33788 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33789 int flags = 0;
Marko Mikulicic 0:c0ecb8bf28eb 33790 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33791 val_t r = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 33792 rcode = obj_value_of(v7, this_obj, &r);
Marko Mikulicic 0:c0ecb8bf28eb 33793 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33794 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33795 }
Marko Mikulicic 0:c0ecb8bf28eb 33796
Marko Mikulicic 0:c0ecb8bf28eb 33797 if (v7_is_regexp(v7, r)) {
Marko Mikulicic 0:c0ecb8bf28eb 33798 flags = slre_get_flags(v7_get_regexp_struct(v7, r)->compiled_regexp);
Marko Mikulicic 0:c0ecb8bf28eb 33799 }
Marko Mikulicic 0:c0ecb8bf28eb 33800
Marko Mikulicic 0:c0ecb8bf28eb 33801 *res = v7_mk_boolean(v7, flags & SLRE_FLAG_G);
Marko Mikulicic 0:c0ecb8bf28eb 33802
Marko Mikulicic 0:c0ecb8bf28eb 33803 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33804 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33805 }
Marko Mikulicic 0:c0ecb8bf28eb 33806
Marko Mikulicic 0:c0ecb8bf28eb 33807 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33808 V7_PRIVATE enum v7_err Regex_ignoreCase(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33809 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33810 int flags = 0;
Marko Mikulicic 0:c0ecb8bf28eb 33811 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33812 val_t r = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 33813 rcode = obj_value_of(v7, this_obj, &r);
Marko Mikulicic 0:c0ecb8bf28eb 33814 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33815 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33816 }
Marko Mikulicic 0:c0ecb8bf28eb 33817
Marko Mikulicic 0:c0ecb8bf28eb 33818 if (v7_is_regexp(v7, r)) {
Marko Mikulicic 0:c0ecb8bf28eb 33819 flags = slre_get_flags(v7_get_regexp_struct(v7, r)->compiled_regexp);
Marko Mikulicic 0:c0ecb8bf28eb 33820 }
Marko Mikulicic 0:c0ecb8bf28eb 33821
Marko Mikulicic 0:c0ecb8bf28eb 33822 *res = v7_mk_boolean(v7, flags & SLRE_FLAG_I);
Marko Mikulicic 0:c0ecb8bf28eb 33823
Marko Mikulicic 0:c0ecb8bf28eb 33824 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33825 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33826 }
Marko Mikulicic 0:c0ecb8bf28eb 33827
Marko Mikulicic 0:c0ecb8bf28eb 33828 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33829 V7_PRIVATE enum v7_err Regex_multiline(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33830 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33831 int flags = 0;
Marko Mikulicic 0:c0ecb8bf28eb 33832 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33833 val_t r = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 33834 rcode = obj_value_of(v7, this_obj, &r);
Marko Mikulicic 0:c0ecb8bf28eb 33835 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33836 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33837 }
Marko Mikulicic 0:c0ecb8bf28eb 33838
Marko Mikulicic 0:c0ecb8bf28eb 33839 if (v7_is_regexp(v7, r)) {
Marko Mikulicic 0:c0ecb8bf28eb 33840 flags = slre_get_flags(v7_get_regexp_struct(v7, r)->compiled_regexp);
Marko Mikulicic 0:c0ecb8bf28eb 33841 }
Marko Mikulicic 0:c0ecb8bf28eb 33842
Marko Mikulicic 0:c0ecb8bf28eb 33843 *res = v7_mk_boolean(v7, flags & SLRE_FLAG_M);
Marko Mikulicic 0:c0ecb8bf28eb 33844
Marko Mikulicic 0:c0ecb8bf28eb 33845 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33846 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33847 }
Marko Mikulicic 0:c0ecb8bf28eb 33848
Marko Mikulicic 0:c0ecb8bf28eb 33849 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33850 V7_PRIVATE enum v7_err Regex_source(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33851 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33852 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33853 val_t r = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 33854 const char *buf = 0;
Marko Mikulicic 0:c0ecb8bf28eb 33855 size_t len = 0;
Marko Mikulicic 0:c0ecb8bf28eb 33856
Marko Mikulicic 0:c0ecb8bf28eb 33857 rcode = obj_value_of(v7, this_obj, &r);
Marko Mikulicic 0:c0ecb8bf28eb 33858 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33859 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33860 }
Marko Mikulicic 0:c0ecb8bf28eb 33861
Marko Mikulicic 0:c0ecb8bf28eb 33862 if (v7_is_regexp(v7, r)) {
Marko Mikulicic 0:c0ecb8bf28eb 33863 buf = v7_get_string(v7, &v7_get_regexp_struct(v7, r)->regexp_string, &len);
Marko Mikulicic 0:c0ecb8bf28eb 33864 }
Marko Mikulicic 0:c0ecb8bf28eb 33865
Marko Mikulicic 0:c0ecb8bf28eb 33866 *res = v7_mk_string(v7, buf, len, 1);
Marko Mikulicic 0:c0ecb8bf28eb 33867
Marko Mikulicic 0:c0ecb8bf28eb 33868 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33869 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33870 }
Marko Mikulicic 0:c0ecb8bf28eb 33871
Marko Mikulicic 0:c0ecb8bf28eb 33872 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33873 V7_PRIVATE enum v7_err Regex_get_lastIndex(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33874 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33875 long lastIndex = 0;
Marko Mikulicic 0:c0ecb8bf28eb 33876 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33877
Marko Mikulicic 0:c0ecb8bf28eb 33878 if (v7_is_regexp(v7, this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 33879 lastIndex = v7_get_regexp_struct(v7, this_obj)->lastIndex;
Marko Mikulicic 0:c0ecb8bf28eb 33880 }
Marko Mikulicic 0:c0ecb8bf28eb 33881
Marko Mikulicic 0:c0ecb8bf28eb 33882 *res = v7_mk_number(v7, lastIndex);
Marko Mikulicic 0:c0ecb8bf28eb 33883
Marko Mikulicic 0:c0ecb8bf28eb 33884 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33885 }
Marko Mikulicic 0:c0ecb8bf28eb 33886
Marko Mikulicic 0:c0ecb8bf28eb 33887 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33888 V7_PRIVATE enum v7_err Regex_set_lastIndex(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33889 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33890 long lastIndex = 0;
Marko Mikulicic 0:c0ecb8bf28eb 33891 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33892
Marko Mikulicic 0:c0ecb8bf28eb 33893 if (v7_is_regexp(v7, this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 33894 rcode = to_long(v7, v7_arg(v7, 0), 0, &lastIndex);
Marko Mikulicic 0:c0ecb8bf28eb 33895 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33896 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33897 }
Marko Mikulicic 0:c0ecb8bf28eb 33898 v7_get_regexp_struct(v7, this_obj)->lastIndex = lastIndex;
Marko Mikulicic 0:c0ecb8bf28eb 33899 }
Marko Mikulicic 0:c0ecb8bf28eb 33900
Marko Mikulicic 0:c0ecb8bf28eb 33901 *res = v7_mk_number(v7, lastIndex);
Marko Mikulicic 0:c0ecb8bf28eb 33902
Marko Mikulicic 0:c0ecb8bf28eb 33903 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33904 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33905 }
Marko Mikulicic 0:c0ecb8bf28eb 33906
Marko Mikulicic 0:c0ecb8bf28eb 33907 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33908 V7_PRIVATE enum v7_err rx_exec(struct v7 *v7, val_t rx, val_t vstr, int lind,
Marko Mikulicic 0:c0ecb8bf28eb 33909 val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33910 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33911 if (v7_is_regexp(v7, rx)) {
Marko Mikulicic 0:c0ecb8bf28eb 33912 val_t s = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 33913 size_t len;
Marko Mikulicic 0:c0ecb8bf28eb 33914 struct slre_loot sub;
Marko Mikulicic 0:c0ecb8bf28eb 33915 struct slre_cap *ptok = sub.caps;
Marko Mikulicic 0:c0ecb8bf28eb 33916 const char *str = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 33917 const char *end = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 33918 const char *begin = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 33919 struct v7_regexp *rp = v7_get_regexp_struct(v7, rx);
Marko Mikulicic 0:c0ecb8bf28eb 33920 int flag_g = slre_get_flags(rp->compiled_regexp) & SLRE_FLAG_G;
Marko Mikulicic 0:c0ecb8bf28eb 33921
Marko Mikulicic 0:c0ecb8bf28eb 33922 rcode = to_string(v7, vstr, &s, NULL, 0, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 33923 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33924 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33925 }
Marko Mikulicic 0:c0ecb8bf28eb 33926 str = v7_get_string(v7, &s, &len);
Marko Mikulicic 0:c0ecb8bf28eb 33927 end = str + len;
Marko Mikulicic 0:c0ecb8bf28eb 33928 begin = str;
Marko Mikulicic 0:c0ecb8bf28eb 33929
Marko Mikulicic 0:c0ecb8bf28eb 33930 if (rp->lastIndex < 0) rp->lastIndex = 0;
Marko Mikulicic 0:c0ecb8bf28eb 33931 if (flag_g || lind) begin = utfnshift(str, rp->lastIndex);
Marko Mikulicic 0:c0ecb8bf28eb 33932
Marko Mikulicic 0:c0ecb8bf28eb 33933 if (!slre_exec(rp->compiled_regexp, 0, begin, end, &sub)) {
Marko Mikulicic 0:c0ecb8bf28eb 33934 int i;
Marko Mikulicic 0:c0ecb8bf28eb 33935 val_t arr = v7_mk_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33936 char *old_mbuf_base = v7->owned_strings.buf;
Marko Mikulicic 0:c0ecb8bf28eb 33937 ptrdiff_t rel = 0; /* creating strings might relocate the mbuf */
Marko Mikulicic 0:c0ecb8bf28eb 33938
Marko Mikulicic 0:c0ecb8bf28eb 33939 for (i = 0; i < sub.num_captures; i++, ptok++) {
Marko Mikulicic 0:c0ecb8bf28eb 33940 rel = v7->owned_strings.buf - old_mbuf_base;
Marko Mikulicic 0:c0ecb8bf28eb 33941 v7_array_push(v7, arr, v7_mk_string(v7, ptok->start + rel,
Marko Mikulicic 0:c0ecb8bf28eb 33942 ptok->end - ptok->start, 1));
Marko Mikulicic 0:c0ecb8bf28eb 33943 }
Marko Mikulicic 0:c0ecb8bf28eb 33944 if (flag_g) rp->lastIndex = utfnlen(str, sub.caps->end + rel - str);
Marko Mikulicic 0:c0ecb8bf28eb 33945 v7_def(v7, arr, "index", 5, V7_DESC_WRITABLE(0),
Marko Mikulicic 0:c0ecb8bf28eb 33946 v7_mk_number(v7, utfnlen(str + rel, sub.caps->start - str)));
Marko Mikulicic 0:c0ecb8bf28eb 33947 *res = arr;
Marko Mikulicic 0:c0ecb8bf28eb 33948 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33949 } else {
Marko Mikulicic 0:c0ecb8bf28eb 33950 rp->lastIndex = 0;
Marko Mikulicic 0:c0ecb8bf28eb 33951 }
Marko Mikulicic 0:c0ecb8bf28eb 33952 }
Marko Mikulicic 0:c0ecb8bf28eb 33953
Marko Mikulicic 0:c0ecb8bf28eb 33954 *res = V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 33955
Marko Mikulicic 0:c0ecb8bf28eb 33956 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33957 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33958 }
Marko Mikulicic 0:c0ecb8bf28eb 33959
Marko Mikulicic 0:c0ecb8bf28eb 33960 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33961 V7_PRIVATE enum v7_err Regex_exec(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33962 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33963 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33964
Marko Mikulicic 0:c0ecb8bf28eb 33965 if (v7_argc(v7) > 0) {
Marko Mikulicic 0:c0ecb8bf28eb 33966 rcode = rx_exec(v7, this_obj, v7_arg(v7, 0), 0, res);
Marko Mikulicic 0:c0ecb8bf28eb 33967 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33968 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33969 }
Marko Mikulicic 0:c0ecb8bf28eb 33970 } else {
Marko Mikulicic 0:c0ecb8bf28eb 33971 *res = V7_NULL;
Marko Mikulicic 0:c0ecb8bf28eb 33972 }
Marko Mikulicic 0:c0ecb8bf28eb 33973
Marko Mikulicic 0:c0ecb8bf28eb 33974 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33975 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33976 }
Marko Mikulicic 0:c0ecb8bf28eb 33977
Marko Mikulicic 0:c0ecb8bf28eb 33978 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33979 V7_PRIVATE enum v7_err Regex_test(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33980 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33981 val_t tmp = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 33982
Marko Mikulicic 0:c0ecb8bf28eb 33983 rcode = Regex_exec(v7, &tmp);
Marko Mikulicic 0:c0ecb8bf28eb 33984 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 33985 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 33986 }
Marko Mikulicic 0:c0ecb8bf28eb 33987
Marko Mikulicic 0:c0ecb8bf28eb 33988 *res = v7_mk_boolean(v7, !v7_is_null(tmp));
Marko Mikulicic 0:c0ecb8bf28eb 33989
Marko Mikulicic 0:c0ecb8bf28eb 33990 clean:
Marko Mikulicic 0:c0ecb8bf28eb 33991 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 33992 }
Marko Mikulicic 0:c0ecb8bf28eb 33993
Marko Mikulicic 0:c0ecb8bf28eb 33994 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 33995 V7_PRIVATE enum v7_err Regex_flags(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 33996 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 33997 char buf[3] = {0};
Marko Mikulicic 0:c0ecb8bf28eb 33998 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 33999 struct v7_regexp *rp = v7_get_regexp_struct(v7, this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 34000 size_t n = get_regexp_flags_str(v7, rp, buf);
Marko Mikulicic 0:c0ecb8bf28eb 34001 *res = v7_mk_string(v7, buf, n, 1);
Marko Mikulicic 0:c0ecb8bf28eb 34002
Marko Mikulicic 0:c0ecb8bf28eb 34003 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 34004 }
Marko Mikulicic 0:c0ecb8bf28eb 34005
Marko Mikulicic 0:c0ecb8bf28eb 34006 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 34007 V7_PRIVATE enum v7_err Regex_toString(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 34008 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 34009 size_t n1, n2 = 0;
Marko Mikulicic 0:c0ecb8bf28eb 34010 char s2[3] = {0};
Marko Mikulicic 0:c0ecb8bf28eb 34011 char buf[50];
Marko Mikulicic 0:c0ecb8bf28eb 34012 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 34013 struct v7_regexp *rp;
Marko Mikulicic 0:c0ecb8bf28eb 34014 const char *s1;
Marko Mikulicic 0:c0ecb8bf28eb 34015
Marko Mikulicic 0:c0ecb8bf28eb 34016 rcode = obj_value_of(v7, this_obj, &this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 34017 if (rcode != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 34018 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 34019 }
Marko Mikulicic 0:c0ecb8bf28eb 34020
Marko Mikulicic 0:c0ecb8bf28eb 34021 if (!v7_is_regexp(v7, this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 34022 rcode = v7_throwf(v7, TYPE_ERROR, "Not a regexp");
Marko Mikulicic 0:c0ecb8bf28eb 34023 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 34024 }
Marko Mikulicic 0:c0ecb8bf28eb 34025
Marko Mikulicic 0:c0ecb8bf28eb 34026 rp = v7_get_regexp_struct(v7, this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 34027 s1 = v7_get_string(v7, &rp->regexp_string, &n1);
Marko Mikulicic 0:c0ecb8bf28eb 34028 n2 = get_regexp_flags_str(v7, rp, s2);
Marko Mikulicic 0:c0ecb8bf28eb 34029
Marko Mikulicic 0:c0ecb8bf28eb 34030 c_snprintf(buf, sizeof(buf), "/%.*s/%.*s", (int) n1, s1, (int) n2, s2);
Marko Mikulicic 0:c0ecb8bf28eb 34031
Marko Mikulicic 0:c0ecb8bf28eb 34032 *res = v7_mk_string(v7, buf, strlen(buf), 1);
Marko Mikulicic 0:c0ecb8bf28eb 34033
Marko Mikulicic 0:c0ecb8bf28eb 34034 clean:
Marko Mikulicic 0:c0ecb8bf28eb 34035 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 34036 }
Marko Mikulicic 0:c0ecb8bf28eb 34037
Marko Mikulicic 0:c0ecb8bf28eb 34038 V7_PRIVATE void init_regex(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 34039 val_t ctor =
Marko Mikulicic 0:c0ecb8bf28eb 34040 mk_cfunction_obj_with_proto(v7, Regex_ctor, 1, v7->vals.regexp_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 34041 val_t lastIndex = v7_mk_dense_array(v7);
Marko Mikulicic 0:c0ecb8bf28eb 34042
Marko Mikulicic 0:c0ecb8bf28eb 34043 v7_def(v7, v7->vals.global_object, "RegExp", 6, V7_DESC_ENUMERABLE(0), ctor);
Marko Mikulicic 0:c0ecb8bf28eb 34044
Marko Mikulicic 0:c0ecb8bf28eb 34045 set_cfunc_prop(v7, v7->vals.regexp_prototype, "exec", Regex_exec);
Marko Mikulicic 0:c0ecb8bf28eb 34046 set_cfunc_prop(v7, v7->vals.regexp_prototype, "test", Regex_test);
Marko Mikulicic 0:c0ecb8bf28eb 34047 set_method(v7, v7->vals.regexp_prototype, "toString", Regex_toString, 0);
Marko Mikulicic 0:c0ecb8bf28eb 34048
Marko Mikulicic 0:c0ecb8bf28eb 34049 v7_def(v7, v7->vals.regexp_prototype, "global", 6, V7_DESC_GETTER(1),
Marko Mikulicic 0:c0ecb8bf28eb 34050 v7_mk_cfunction(Regex_global));
Marko Mikulicic 0:c0ecb8bf28eb 34051 v7_def(v7, v7->vals.regexp_prototype, "ignoreCase", 10, V7_DESC_GETTER(1),
Marko Mikulicic 0:c0ecb8bf28eb 34052 v7_mk_cfunction(Regex_ignoreCase));
Marko Mikulicic 0:c0ecb8bf28eb 34053 v7_def(v7, v7->vals.regexp_prototype, "multiline", 9, V7_DESC_GETTER(1),
Marko Mikulicic 0:c0ecb8bf28eb 34054 v7_mk_cfunction(Regex_multiline));
Marko Mikulicic 0:c0ecb8bf28eb 34055 v7_def(v7, v7->vals.regexp_prototype, "source", 6, V7_DESC_GETTER(1),
Marko Mikulicic 0:c0ecb8bf28eb 34056 v7_mk_cfunction(Regex_source));
Marko Mikulicic 0:c0ecb8bf28eb 34057 v7_def(v7, v7->vals.regexp_prototype, "flags", 5, V7_DESC_GETTER(1),
Marko Mikulicic 0:c0ecb8bf28eb 34058 v7_mk_cfunction(Regex_flags));
Marko Mikulicic 0:c0ecb8bf28eb 34059
Marko Mikulicic 0:c0ecb8bf28eb 34060 v7_array_set(v7, lastIndex, 0, v7_mk_cfunction(Regex_get_lastIndex));
Marko Mikulicic 0:c0ecb8bf28eb 34061 v7_array_set(v7, lastIndex, 1, v7_mk_cfunction(Regex_set_lastIndex));
Marko Mikulicic 0:c0ecb8bf28eb 34062 v7_def(v7, v7->vals.regexp_prototype, "lastIndex", 9,
Marko Mikulicic 0:c0ecb8bf28eb 34063 (V7_DESC_GETTER(1) | V7_DESC_SETTER(1)), lastIndex);
Marko Mikulicic 0:c0ecb8bf28eb 34064 }
Marko Mikulicic 0:c0ecb8bf28eb 34065
Marko Mikulicic 0:c0ecb8bf28eb 34066 #endif /* V7_ENABLE__RegExp */
Marko Mikulicic 0:c0ecb8bf28eb 34067 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 34068 #line 1 "v7/src/std_proxy.c"
Marko Mikulicic 0:c0ecb8bf28eb 34069 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34070 /*
Marko Mikulicic 0:c0ecb8bf28eb 34071 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 34072 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 34073 */
Marko Mikulicic 0:c0ecb8bf28eb 34074
Marko Mikulicic 0:c0ecb8bf28eb 34075 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34076 /* Amalgamated: #include "v7/src/std_object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34077 /* Amalgamated: #include "v7/src/std_proxy.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34078 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34079 /* Amalgamated: #include "v7/src/core.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34080 /* Amalgamated: #include "v7/src/function.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34081 /* Amalgamated: #include "v7/src/object.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34082 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34083 /* Amalgamated: #include "v7/src/string.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34084 /* Amalgamated: #include "v7/src/exceptions.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34085
Marko Mikulicic 0:c0ecb8bf28eb 34086 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 34087 extern "C" {
Marko Mikulicic 0:c0ecb8bf28eb 34088 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 34089
Marko Mikulicic 0:c0ecb8bf28eb 34090 #if V7_ENABLE__Proxy
Marko Mikulicic 0:c0ecb8bf28eb 34091
Marko Mikulicic 0:c0ecb8bf28eb 34092 WARN_UNUSED_RESULT
Marko Mikulicic 0:c0ecb8bf28eb 34093 V7_PRIVATE enum v7_err Proxy_ctor(struct v7 *v7, v7_val_t *res) {
Marko Mikulicic 0:c0ecb8bf28eb 34094 enum v7_err rcode = V7_OK;
Marko Mikulicic 0:c0ecb8bf28eb 34095 val_t this_obj = v7_get_this(v7);
Marko Mikulicic 0:c0ecb8bf28eb 34096 val_t target_v = v7_arg(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 34097 val_t handler_v = v7_arg(v7, 1);
Marko Mikulicic 0:c0ecb8bf28eb 34098 struct v7_object *t = NULL;
Marko Mikulicic 0:c0ecb8bf28eb 34099 v7_prop_attr_desc_t attrs_desc =
Marko Mikulicic 0:c0ecb8bf28eb 34100 (V7_DESC_WRITABLE(0) | V7_DESC_ENUMERABLE(0) | V7_DESC_CONFIGURABLE(0));
Marko Mikulicic 0:c0ecb8bf28eb 34101
Marko Mikulicic 0:c0ecb8bf28eb 34102 if (this_obj == v7_get_global(v7) || !v7_is_object(this_obj)) {
Marko Mikulicic 0:c0ecb8bf28eb 34103 rcode = v7_throwf(v7, TYPE_ERROR, "Wrong 'this' object for Proxy ctor");
Marko Mikulicic 0:c0ecb8bf28eb 34104 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 34105 }
Marko Mikulicic 0:c0ecb8bf28eb 34106
Marko Mikulicic 0:c0ecb8bf28eb 34107 if (!v7_is_object(target_v) || !v7_is_object(handler_v)) {
Marko Mikulicic 0:c0ecb8bf28eb 34108 rcode =
Marko Mikulicic 0:c0ecb8bf28eb 34109 v7_throwf(v7, TYPE_ERROR,
Marko Mikulicic 0:c0ecb8bf28eb 34110 "Cannot create proxy with a non-object as target or handler");
Marko Mikulicic 0:c0ecb8bf28eb 34111 goto clean;
Marko Mikulicic 0:c0ecb8bf28eb 34112 }
Marko Mikulicic 0:c0ecb8bf28eb 34113
Marko Mikulicic 0:c0ecb8bf28eb 34114 t = get_object_struct(this_obj);
Marko Mikulicic 0:c0ecb8bf28eb 34115 t->attributes |= V7_OBJ_PROXY;
Marko Mikulicic 0:c0ecb8bf28eb 34116
Marko Mikulicic 0:c0ecb8bf28eb 34117 v7_def(v7, this_obj, _V7_PROXY_TARGET_NAME, ~0, attrs_desc, target_v);
Marko Mikulicic 0:c0ecb8bf28eb 34118 v7_def(v7, this_obj, _V7_PROXY_HANDLER_NAME, ~0, attrs_desc, handler_v);
Marko Mikulicic 0:c0ecb8bf28eb 34119
Marko Mikulicic 0:c0ecb8bf28eb 34120 (void) res;
Marko Mikulicic 0:c0ecb8bf28eb 34121
Marko Mikulicic 0:c0ecb8bf28eb 34122 clean:
Marko Mikulicic 0:c0ecb8bf28eb 34123 return rcode;
Marko Mikulicic 0:c0ecb8bf28eb 34124 }
Marko Mikulicic 0:c0ecb8bf28eb 34125
Marko Mikulicic 0:c0ecb8bf28eb 34126 V7_PRIVATE void init_proxy(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 34127 /*v7_prop_attr_desc_t attrs_desc =*/
Marko Mikulicic 0:c0ecb8bf28eb 34128 /*(V7_DESC_WRITABLE(0) | V7_DESC_ENUMERABLE(0) | V7_DESC_CONFIGURABLE(0));*/
Marko Mikulicic 0:c0ecb8bf28eb 34129 val_t proxy =
Marko Mikulicic 0:c0ecb8bf28eb 34130 mk_cfunction_obj_with_proto(v7, Proxy_ctor, 1, v7->vals.proxy_prototype);
Marko Mikulicic 0:c0ecb8bf28eb 34131
Marko Mikulicic 0:c0ecb8bf28eb 34132 v7_def(v7, v7->vals.global_object, "Proxy", ~0, V7_DESC_ENUMERABLE(0), proxy);
Marko Mikulicic 0:c0ecb8bf28eb 34133 }
Marko Mikulicic 0:c0ecb8bf28eb 34134
Marko Mikulicic 0:c0ecb8bf28eb 34135 V7_PRIVATE int is_special_proxy_name(const char *name, size_t name_len) {
Marko Mikulicic 0:c0ecb8bf28eb 34136 int ret = 0;
Marko Mikulicic 0:c0ecb8bf28eb 34137 if (name_len == (size_t) ~0) {
Marko Mikulicic 0:c0ecb8bf28eb 34138 name_len = strlen(name);
Marko Mikulicic 0:c0ecb8bf28eb 34139 }
Marko Mikulicic 0:c0ecb8bf28eb 34140 if (name_len == 5 && (memcmp(name, _V7_PROXY_TARGET_NAME, name_len) == 0 ||
Marko Mikulicic 0:c0ecb8bf28eb 34141 memcmp(name, _V7_PROXY_HANDLER_NAME, name_len) == 0)) {
Marko Mikulicic 0:c0ecb8bf28eb 34142 ret = 1;
Marko Mikulicic 0:c0ecb8bf28eb 34143 }
Marko Mikulicic 0:c0ecb8bf28eb 34144 return ret;
Marko Mikulicic 0:c0ecb8bf28eb 34145 }
Marko Mikulicic 0:c0ecb8bf28eb 34146
Marko Mikulicic 0:c0ecb8bf28eb 34147 #endif /* V7_ENABLE__Proxy */
Marko Mikulicic 0:c0ecb8bf28eb 34148
Marko Mikulicic 0:c0ecb8bf28eb 34149 #if defined(__cplusplus)
Marko Mikulicic 0:c0ecb8bf28eb 34150 }
Marko Mikulicic 0:c0ecb8bf28eb 34151 #endif /* __cplusplus */
Marko Mikulicic 0:c0ecb8bf28eb 34152 #ifdef V7_MODULE_LINES
Marko Mikulicic 0:c0ecb8bf28eb 34153 #line 1 "v7/src/main.c"
Marko Mikulicic 0:c0ecb8bf28eb 34154 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34155 /*
Marko Mikulicic 0:c0ecb8bf28eb 34156 * Copyright (c) 2014 Cesanta Software Limited
Marko Mikulicic 0:c0ecb8bf28eb 34157 * All rights reserved
Marko Mikulicic 0:c0ecb8bf28eb 34158 */
Marko Mikulicic 0:c0ecb8bf28eb 34159
Marko Mikulicic 0:c0ecb8bf28eb 34160 /* Amalgamated: #include "v7/src/internal.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34161 /* Amalgamated: #include "v7/src/gc.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34162 /* Amalgamated: #include "v7/src/freeze.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34163 /* Amalgamated: #include "v7/src/main.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34164 /* Amalgamated: #include "v7/src/primitive.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34165 /* Amalgamated: #include "v7/src/exec.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34166 /* Amalgamated: #include "v7/src/util.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34167 /* Amalgamated: #include "v7/src/conversion.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34168 /* Amalgamated: #include "common/platform.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34169 /* Amalgamated: #include "common/cs_file.h" */
Marko Mikulicic 0:c0ecb8bf28eb 34170
Marko Mikulicic 0:c0ecb8bf28eb 34171 #if defined(_MSC_VER) && _MSC_VER >= 1800
Marko Mikulicic 0:c0ecb8bf28eb 34172 #define fileno _fileno
Marko Mikulicic 0:c0ecb8bf28eb 34173 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34174
Marko Mikulicic 0:c0ecb8bf28eb 34175 #ifdef V7_EXE
Marko Mikulicic 0:c0ecb8bf28eb 34176 #define V7_MAIN
Marko Mikulicic 0:c0ecb8bf28eb 34177 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34178
Marko Mikulicic 0:c0ecb8bf28eb 34179 #ifdef V7_MAIN
Marko Mikulicic 0:c0ecb8bf28eb 34180
Marko Mikulicic 0:c0ecb8bf28eb 34181 #include <sys/stat.h>
Marko Mikulicic 0:c0ecb8bf28eb 34182
Marko Mikulicic 0:c0ecb8bf28eb 34183 static void show_usage(char *argv[]) {
Marko Mikulicic 0:c0ecb8bf28eb 34184 fprintf(stderr, "V7 version %s (c) Cesanta Software, built on %s\n",
Marko Mikulicic 0:c0ecb8bf28eb 34185 V7_VERSION, __DATE__);
Marko Mikulicic 0:c0ecb8bf28eb 34186 fprintf(stderr, "Usage: %s [OPTIONS] js_file ...\n", argv[0]);
Marko Mikulicic 0:c0ecb8bf28eb 34187 fprintf(stderr, "%s\n", "OPTIONS:");
Marko Mikulicic 0:c0ecb8bf28eb 34188 fprintf(stderr, "%s\n", " -e <expr> execute expression");
Marko Mikulicic 0:c0ecb8bf28eb 34189 fprintf(stderr, "%s\n", " -t dump generated text AST");
Marko Mikulicic 0:c0ecb8bf28eb 34190 fprintf(stderr, "%s\n", " -b dump generated binary AST");
Marko Mikulicic 0:c0ecb8bf28eb 34191 fprintf(stderr, "%s\n", " -c dump compiled binary bcode");
Marko Mikulicic 0:c0ecb8bf28eb 34192 fprintf(stderr, "%s\n", " -mm dump memory stats");
Marko Mikulicic 0:c0ecb8bf28eb 34193 fprintf(stderr, "%s\n", " -vo <n> object arena size");
Marko Mikulicic 0:c0ecb8bf28eb 34194 fprintf(stderr, "%s\n", " -vf <n> function arena size");
Marko Mikulicic 0:c0ecb8bf28eb 34195 fprintf(stderr, "%s\n", " -vp <n> property arena size");
Marko Mikulicic 0:c0ecb8bf28eb 34196 #ifdef V7_FREEZE
Marko Mikulicic 0:c0ecb8bf28eb 34197 fprintf(stderr, "%s\n", " -freeze filename dump JS heap into a file");
Marko Mikulicic 0:c0ecb8bf28eb 34198 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34199 exit(EXIT_FAILURE);
Marko Mikulicic 0:c0ecb8bf28eb 34200 }
Marko Mikulicic 0:c0ecb8bf28eb 34201
Marko Mikulicic 0:c0ecb8bf28eb 34202 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 34203 static void dump_mm_arena_stats(const char *msg, struct gc_arena *a) {
Marko Mikulicic 0:c0ecb8bf28eb 34204 printf("%s: total allocations %lu, total garbage %lu, max %" SIZE_T_FMT
Marko Mikulicic 0:c0ecb8bf28eb 34205 ", alive %lu\n",
Marko Mikulicic 0:c0ecb8bf28eb 34206 msg, a->allocations, a->garbage, gc_arena_size(a), a->alive);
Marko Mikulicic 0:c0ecb8bf28eb 34207 printf(
Marko Mikulicic 0:c0ecb8bf28eb 34208 "%s: (bytes: total allocations %lu, total garbage %lu, max %" SIZE_T_FMT
Marko Mikulicic 0:c0ecb8bf28eb 34209 ", alive %lu)\n",
Marko Mikulicic 0:c0ecb8bf28eb 34210 msg, a->allocations * a->cell_size, a->garbage * a->cell_size,
Marko Mikulicic 0:c0ecb8bf28eb 34211 gc_arena_size(a) * a->cell_size, a->alive * a->cell_size);
Marko Mikulicic 0:c0ecb8bf28eb 34212 }
Marko Mikulicic 0:c0ecb8bf28eb 34213
Marko Mikulicic 0:c0ecb8bf28eb 34214 static void dump_mm_stats(struct v7 *v7) {
Marko Mikulicic 0:c0ecb8bf28eb 34215 dump_mm_arena_stats("object: ", &v7->generic_object_arena);
Marko Mikulicic 0:c0ecb8bf28eb 34216 dump_mm_arena_stats("function: ", &v7->function_arena);
Marko Mikulicic 0:c0ecb8bf28eb 34217 dump_mm_arena_stats("property: ", &v7->property_arena);
Marko Mikulicic 0:c0ecb8bf28eb 34218 printf("string arena len: %" SIZE_T_FMT "\n", v7->owned_strings.len);
Marko Mikulicic 0:c0ecb8bf28eb 34219 printf("Total heap size: %" SIZE_T_FMT "\n",
Marko Mikulicic 0:c0ecb8bf28eb 34220 v7->owned_strings.len +
Marko Mikulicic 0:c0ecb8bf28eb 34221 gc_arena_size(&v7->generic_object_arena) *
Marko Mikulicic 0:c0ecb8bf28eb 34222 v7->generic_object_arena.cell_size +
Marko Mikulicic 0:c0ecb8bf28eb 34223 gc_arena_size(&v7->function_arena) * v7->function_arena.cell_size +
Marko Mikulicic 0:c0ecb8bf28eb 34224 gc_arena_size(&v7->property_arena) * v7->property_arena.cell_size);
Marko Mikulicic 0:c0ecb8bf28eb 34225 }
Marko Mikulicic 0:c0ecb8bf28eb 34226 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34227
Marko Mikulicic 0:c0ecb8bf28eb 34228 int v7_main(int argc, char *argv[], void (*pre_freeze_init)(struct v7 *),
Marko Mikulicic 0:c0ecb8bf28eb 34229 void (*pre_init)(struct v7 *), void (*post_init)(struct v7 *)) {
Marko Mikulicic 0:c0ecb8bf28eb 34230 int exit_rcode = EXIT_SUCCESS;
Marko Mikulicic 0:c0ecb8bf28eb 34231 struct v7 *v7;
Marko Mikulicic 0:c0ecb8bf28eb 34232 struct v7_create_opts opts;
Marko Mikulicic 0:c0ecb8bf28eb 34233 int as_json = 0;
Marko Mikulicic 0:c0ecb8bf28eb 34234 int i, j, show_ast = 0, binary_ast = 0, dump_bcode = 0, dump_stats = 0;
Marko Mikulicic 0:c0ecb8bf28eb 34235 val_t res;
Marko Mikulicic 0:c0ecb8bf28eb 34236 int nexprs = 0;
Marko Mikulicic 0:c0ecb8bf28eb 34237 const char *exprs[16];
Marko Mikulicic 0:c0ecb8bf28eb 34238
Marko Mikulicic 0:c0ecb8bf28eb 34239 memset(&opts, 0, sizeof(opts));
Marko Mikulicic 0:c0ecb8bf28eb 34240
Marko Mikulicic 0:c0ecb8bf28eb 34241 (void) show_ast;
Marko Mikulicic 0:c0ecb8bf28eb 34242 (void) binary_ast;
Marko Mikulicic 0:c0ecb8bf28eb 34243 (void) dump_bcode;
Marko Mikulicic 0:c0ecb8bf28eb 34244
Marko Mikulicic 0:c0ecb8bf28eb 34245 /* Execute inline code */
Marko Mikulicic 0:c0ecb8bf28eb 34246 for (i = 1; i < argc && argv[i][0] == '-'; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 34247 if (strcmp(argv[i], "-e") == 0 && i + 1 < argc) {
Marko Mikulicic 0:c0ecb8bf28eb 34248 exprs[nexprs++] = argv[i + 1];
Marko Mikulicic 0:c0ecb8bf28eb 34249 i++;
Marko Mikulicic 0:c0ecb8bf28eb 34250 } else if (strcmp(argv[i], "-t") == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 34251 show_ast = 1;
Marko Mikulicic 0:c0ecb8bf28eb 34252 } else if (strcmp(argv[i], "-b") == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 34253 show_ast = 1;
Marko Mikulicic 0:c0ecb8bf28eb 34254 binary_ast = 1;
Marko Mikulicic 0:c0ecb8bf28eb 34255 } else if (strcmp(argv[i], "-c") == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 34256 binary_ast = 1;
Marko Mikulicic 0:c0ecb8bf28eb 34257 dump_bcode = 1;
Marko Mikulicic 0:c0ecb8bf28eb 34258 } else if (strcmp(argv[i], "-h") == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 34259 show_usage(argv);
Marko Mikulicic 0:c0ecb8bf28eb 34260 } else if (strcmp(argv[i], "-j") == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 34261 as_json = 1;
Marko Mikulicic 0:c0ecb8bf28eb 34262 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 34263 } else if (strcmp(argv[i], "-mm") == 0) {
Marko Mikulicic 0:c0ecb8bf28eb 34264 dump_stats = 1;
Marko Mikulicic 0:c0ecb8bf28eb 34265 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34266 } else if (strcmp(argv[i], "-vo") == 0 && i + 1 < argc) {
Marko Mikulicic 0:c0ecb8bf28eb 34267 opts.object_arena_size = atoi(argv[i + 1]);
Marko Mikulicic 0:c0ecb8bf28eb 34268 i++;
Marko Mikulicic 0:c0ecb8bf28eb 34269 } else if (strcmp(argv[i], "-vf") == 0 && i + 1 < argc) {
Marko Mikulicic 0:c0ecb8bf28eb 34270 opts.function_arena_size = atoi(argv[i + 1]);
Marko Mikulicic 0:c0ecb8bf28eb 34271 i++;
Marko Mikulicic 0:c0ecb8bf28eb 34272 } else if (strcmp(argv[i], "-vp") == 0 && i + 1 < argc) {
Marko Mikulicic 0:c0ecb8bf28eb 34273 opts.property_arena_size = atoi(argv[i + 1]);
Marko Mikulicic 0:c0ecb8bf28eb 34274 i++;
Marko Mikulicic 0:c0ecb8bf28eb 34275 }
Marko Mikulicic 0:c0ecb8bf28eb 34276 #ifdef V7_FREEZE
Marko Mikulicic 0:c0ecb8bf28eb 34277 else if (strcmp(argv[i], "-freeze") == 0 && i + 1 < argc) {
Marko Mikulicic 0:c0ecb8bf28eb 34278 opts.freeze_file = argv[i + 1];
Marko Mikulicic 0:c0ecb8bf28eb 34279 i++;
Marko Mikulicic 0:c0ecb8bf28eb 34280 }
Marko Mikulicic 0:c0ecb8bf28eb 34281 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34282 }
Marko Mikulicic 0:c0ecb8bf28eb 34283
Marko Mikulicic 0:c0ecb8bf28eb 34284 #ifndef V7_ALLOW_ARGLESS_MAIN
Marko Mikulicic 0:c0ecb8bf28eb 34285 if (argc == 1) {
Marko Mikulicic 0:c0ecb8bf28eb 34286 show_usage(argv);
Marko Mikulicic 0:c0ecb8bf28eb 34287 }
Marko Mikulicic 0:c0ecb8bf28eb 34288 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34289
Marko Mikulicic 0:c0ecb8bf28eb 34290 v7 = v7_create_opt(opts);
Marko Mikulicic 0:c0ecb8bf28eb 34291 res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 34292
Marko Mikulicic 0:c0ecb8bf28eb 34293 if (pre_freeze_init != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 34294 pre_freeze_init(v7);
Marko Mikulicic 0:c0ecb8bf28eb 34295 }
Marko Mikulicic 0:c0ecb8bf28eb 34296
Marko Mikulicic 0:c0ecb8bf28eb 34297 #ifdef V7_FREEZE
Marko Mikulicic 0:c0ecb8bf28eb 34298 /*
Marko Mikulicic 0:c0ecb8bf28eb 34299 * Skip pre_init if freezing, but still execute cmdline expressions.
Marko Mikulicic 0:c0ecb8bf28eb 34300 * This makes it easier to add custom code when freezing from cmdline.
Marko Mikulicic 0:c0ecb8bf28eb 34301 */
Marko Mikulicic 0:c0ecb8bf28eb 34302 if (opts.freeze_file == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 34303 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34304
Marko Mikulicic 0:c0ecb8bf28eb 34305 if (pre_init != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 34306 pre_init(v7);
Marko Mikulicic 0:c0ecb8bf28eb 34307 }
Marko Mikulicic 0:c0ecb8bf28eb 34308
Marko Mikulicic 0:c0ecb8bf28eb 34309 #ifdef V7_FREEZE
Marko Mikulicic 0:c0ecb8bf28eb 34310 }
Marko Mikulicic 0:c0ecb8bf28eb 34311 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34312
Marko Mikulicic 0:c0ecb8bf28eb 34313 #if V7_ENABLE__Memory__stats > 0 && !defined(V7_DISABLE_GC)
Marko Mikulicic 0:c0ecb8bf28eb 34314 if (dump_stats) {
Marko Mikulicic 0:c0ecb8bf28eb 34315 printf("Memory stats during init:\n");
Marko Mikulicic 0:c0ecb8bf28eb 34316 dump_mm_stats(v7);
Marko Mikulicic 0:c0ecb8bf28eb 34317 v7_gc(v7, 0);
Marko Mikulicic 0:c0ecb8bf28eb 34318 printf("Memory stats before run:\n");
Marko Mikulicic 0:c0ecb8bf28eb 34319 dump_mm_stats(v7);
Marko Mikulicic 0:c0ecb8bf28eb 34320 }
Marko Mikulicic 0:c0ecb8bf28eb 34321 #else
Marko Mikulicic 0:c0ecb8bf28eb 34322 (void) dump_stats;
Marko Mikulicic 0:c0ecb8bf28eb 34323 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34324
Marko Mikulicic 0:c0ecb8bf28eb 34325 /* Execute inline expressions */
Marko Mikulicic 0:c0ecb8bf28eb 34326 for (j = 0; j < nexprs; j++) {
Marko Mikulicic 0:c0ecb8bf28eb 34327 enum v7_err (*exec)(struct v7 *, const char *, v7_val_t *);
Marko Mikulicic 0:c0ecb8bf28eb 34328 exec = v7_exec;
Marko Mikulicic 0:c0ecb8bf28eb 34329
Marko Mikulicic 0:c0ecb8bf28eb 34330 if (show_ast || dump_bcode) {
Marko Mikulicic 0:c0ecb8bf28eb 34331 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 34332 if (v7_compile(exprs[j], binary_ast, dump_bcode, stdout) != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 34333 exit_rcode = EXIT_FAILURE;
Marko Mikulicic 0:c0ecb8bf28eb 34334 fprintf(stderr, "%s\n", "parse error");
Marko Mikulicic 0:c0ecb8bf28eb 34335 }
Marko Mikulicic 0:c0ecb8bf28eb 34336 #else /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 34337 exit_rcode = EXIT_FAILURE;
Marko Mikulicic 0:c0ecb8bf28eb 34338 fprintf(stderr, "%s\n", "Parsing is disabled by V7_NO_COMPILER");
Marko Mikulicic 0:c0ecb8bf28eb 34339 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 34340 } else if (exec(v7, exprs[j], &res) != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 34341 v7_print_error(stderr, v7, exprs[j], res);
Marko Mikulicic 0:c0ecb8bf28eb 34342 exit_rcode = EXIT_FAILURE;
Marko Mikulicic 0:c0ecb8bf28eb 34343 res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 34344 }
Marko Mikulicic 0:c0ecb8bf28eb 34345 }
Marko Mikulicic 0:c0ecb8bf28eb 34346
Marko Mikulicic 0:c0ecb8bf28eb 34347 /* Execute files */
Marko Mikulicic 0:c0ecb8bf28eb 34348 for (; i < argc; i++) {
Marko Mikulicic 0:c0ecb8bf28eb 34349 if (show_ast || dump_bcode) {
Marko Mikulicic 0:c0ecb8bf28eb 34350 #if !defined(V7_NO_COMPILER)
Marko Mikulicic 0:c0ecb8bf28eb 34351 size_t size;
Marko Mikulicic 0:c0ecb8bf28eb 34352 char *source_code;
Marko Mikulicic 0:c0ecb8bf28eb 34353 if ((source_code = cs_read_file(argv[i], &size)) == NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 34354 exit_rcode = EXIT_FAILURE;
Marko Mikulicic 0:c0ecb8bf28eb 34355 fprintf(stderr, "Cannot read [%s]\n", argv[i]);
Marko Mikulicic 0:c0ecb8bf28eb 34356 } else {
Marko Mikulicic 0:c0ecb8bf28eb 34357 if (_v7_compile(source_code, size, binary_ast, dump_bcode, stdout) !=
Marko Mikulicic 0:c0ecb8bf28eb 34358 V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 34359 fprintf(stderr, "error: %s\n", v7->error_msg);
Marko Mikulicic 0:c0ecb8bf28eb 34360 exit_rcode = EXIT_FAILURE;
Marko Mikulicic 0:c0ecb8bf28eb 34361 exit(exit_rcode);
Marko Mikulicic 0:c0ecb8bf28eb 34362 }
Marko Mikulicic 0:c0ecb8bf28eb 34363 free(source_code);
Marko Mikulicic 0:c0ecb8bf28eb 34364 }
Marko Mikulicic 0:c0ecb8bf28eb 34365 #else /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 34366 exit_rcode = EXIT_FAILURE;
Marko Mikulicic 0:c0ecb8bf28eb 34367 fprintf(stderr, "%s\n", "Parsing is disabled by V7_NO_COMPILER");
Marko Mikulicic 0:c0ecb8bf28eb 34368 #endif /* V7_NO_COMPILER */
Marko Mikulicic 0:c0ecb8bf28eb 34369 } else if (v7_exec_file(v7, argv[i], &res) != V7_OK) {
Marko Mikulicic 0:c0ecb8bf28eb 34370 v7_print_error(stderr, v7, argv[i], res);
Marko Mikulicic 0:c0ecb8bf28eb 34371 res = V7_UNDEFINED;
Marko Mikulicic 0:c0ecb8bf28eb 34372 }
Marko Mikulicic 0:c0ecb8bf28eb 34373 }
Marko Mikulicic 0:c0ecb8bf28eb 34374
Marko Mikulicic 0:c0ecb8bf28eb 34375 #ifdef V7_FREEZE
Marko Mikulicic 0:c0ecb8bf28eb 34376 if (opts.freeze_file != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 34377 freeze(v7, opts.freeze_file);
Marko Mikulicic 0:c0ecb8bf28eb 34378 exit(0);
Marko Mikulicic 0:c0ecb8bf28eb 34379 }
Marko Mikulicic 0:c0ecb8bf28eb 34380 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34381
Marko Mikulicic 0:c0ecb8bf28eb 34382 if (!(show_ast || dump_bcode)) {
Marko Mikulicic 0:c0ecb8bf28eb 34383 char buf[2000];
Marko Mikulicic 0:c0ecb8bf28eb 34384 char *s = v7_stringify(v7, res, buf, sizeof(buf),
Marko Mikulicic 0:c0ecb8bf28eb 34385 as_json ? V7_STRINGIFY_JSON : V7_STRINGIFY_DEBUG);
Marko Mikulicic 0:c0ecb8bf28eb 34386 printf("%s\n", s);
Marko Mikulicic 0:c0ecb8bf28eb 34387 if (s != buf) {
Marko Mikulicic 0:c0ecb8bf28eb 34388 free(s);
Marko Mikulicic 0:c0ecb8bf28eb 34389 }
Marko Mikulicic 0:c0ecb8bf28eb 34390 }
Marko Mikulicic 0:c0ecb8bf28eb 34391
Marko Mikulicic 0:c0ecb8bf28eb 34392 if (post_init != NULL) {
Marko Mikulicic 0:c0ecb8bf28eb 34393 post_init(v7);
Marko Mikulicic 0:c0ecb8bf28eb 34394 }
Marko Mikulicic 0:c0ecb8bf28eb 34395
Marko Mikulicic 0:c0ecb8bf28eb 34396 #if V7_ENABLE__Memory__stats
Marko Mikulicic 0:c0ecb8bf28eb 34397 if (dump_stats) {
Marko Mikulicic 0:c0ecb8bf28eb 34398 printf("Memory stats after run:\n");
Marko Mikulicic 0:c0ecb8bf28eb 34399 dump_mm_stats(v7);
Marko Mikulicic 0:c0ecb8bf28eb 34400 }
Marko Mikulicic 0:c0ecb8bf28eb 34401 #else
Marko Mikulicic 0:c0ecb8bf28eb 34402 (void) dump_stats;
Marko Mikulicic 0:c0ecb8bf28eb 34403 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34404
Marko Mikulicic 0:c0ecb8bf28eb 34405 v7_destroy(v7);
Marko Mikulicic 0:c0ecb8bf28eb 34406 return exit_rcode;
Marko Mikulicic 0:c0ecb8bf28eb 34407 }
Marko Mikulicic 0:c0ecb8bf28eb 34408 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34409
Marko Mikulicic 0:c0ecb8bf28eb 34410 #ifdef V7_EXE
Marko Mikulicic 0:c0ecb8bf28eb 34411 int main(int argc, char *argv[]) {
Marko Mikulicic 0:c0ecb8bf28eb 34412 return v7_main(argc, argv, NULL, NULL, NULL);
Marko Mikulicic 0:c0ecb8bf28eb 34413 }
Marko Mikulicic 0:c0ecb8bf28eb 34414 #endif
Marko Mikulicic 0:c0ecb8bf28eb 34415 #endif /* V7_EXPORT_INTERNAL_HEADERS */