]> git.saurik.com Git - cycript.git/blame - Library.cpp
Flex drove me crazy with "you just got jammed" :/.
[cycript.git] / Library.cpp
CommitLineData
b3378a02 1/* Cycript - Optimizing JavaScript Compiler/Runtime
c1d3e52e 2 * Copyright (C) 2009-2015 Jay Freeman (saurik)
37954781
JF
3*/
4
f95d2598 5/* GNU Affero General Public License, Version 3 {{{ */
37954781 6/*
f95d2598
JF
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
c15969fd 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
f95d2598
JF
15 * GNU Affero General Public License for more details.
16
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
b3378a02 19**/
37954781
JF
20/* }}} */
21
37954781 22#include <dlfcn.h>
37954781
JF
23
24#include "cycript.hpp"
25
37954781
JF
26#include "Pooling.hpp"
27
28#include <sys/mman.h>
29
30#include <iostream>
37954781
JF
31#include <set>
32#include <map>
33#include <iomanip>
34#include <sstream>
35#include <cmath>
36
8a392978 37#include "Driver.hpp"
37954781 38#include "Error.hpp"
2f51d6ab 39#include "Execute.hpp"
b12a9965
JF
40#include "Parser.hpp"
41#include "String.hpp"
42
142cb9e3 43#include "ConvertUTF.h"
59cd74c1 44
fa3c5be8
JF
45template <>
46::pthread_key_t CYLocal<CYPool>::key_ = Key_();
47
142cb9e3 48/* C Strings {{{ */
b799113b 49CYUTF8String CYPoolUTF8String(CYPool &pool, CYUTF16String utf16) {
59cd74c1
JF
50 // XXX: this is wrong
51 size_t size(utf16.size * 5);
142cb9e3 52 char *temp(new(pool) char[size]);
59cd74c1 53
142cb9e3
JF
54 const uint16_t *lhs(utf16.data);
55 uint8_t *rhs(reinterpret_cast<uint8_t *>(temp));
56 _assert(ConvertUTF16toUTF8(&lhs, lhs + utf16.size, &rhs, rhs + size, lenientConversion) == conversionOK);
59cd74c1 57
142cb9e3
JF
58 *rhs = 0;
59 return CYUTF8String(temp, reinterpret_cast<char *>(rhs) - temp);
59cd74c1
JF
60}
61
b799113b 62CYUTF16String CYPoolUTF16String(CYPool &pool, CYUTF8String utf8) {
59cd74c1
JF
63 // XXX: this is wrong
64 size_t size(utf8.size * 5);
65 uint16_t *temp(new (pool) uint16_t[size]);
59cd74c1 66
142cb9e3
JF
67 const uint8_t *lhs(reinterpret_cast<const uint8_t *>(utf8.data));
68 uint16_t *rhs(temp);
69 _assert(ConvertUTF8toUTF16(&lhs, lhs + utf8.size, &rhs, rhs + size, lenientConversion) == conversionOK);
59cd74c1 70
142cb9e3
JF
71 *rhs = 0;
72 return CYUTF16String(temp, rhs - temp);
59cd74c1
JF
73}
74/* }}} */
37954781
JF
75/* Index Offsets {{{ */
76size_t CYGetIndex(const CYUTF8String &value) {
77 if (value.data[0] != '0') {
ba4fa42f
JF
78 size_t index(0);
79 for (size_t i(0); i != value.size; ++i) {
80 if (!DigitRange_[value.data[i]])
81 return _not(size_t);
82 index *= 10;
83 index += value.data[i] - '0';
84 }
85 return index;
86 } else if (value.size == 1)
37954781 87 return 0;
ba4fa42f
JF
88 else
89 return _not(size_t);
37954781
JF
90}
91
ba4fa42f 92// XXX: this isn't actually right
37954781
JF
93bool CYGetOffset(const char *value, ssize_t &index) {
94 if (value[0] != '0') {
95 char *end;
96 index = strtol(value, &end, 10);
97 if (value + strlen(value) == end)
98 return true;
99 } else if (value[1] == '\0') {
100 index = 0;
101 return true;
102 }
103
104 return false;
105}
106/* }}} */
37954781
JF
107/* JavaScript *ify {{{ */
108void CYStringify(std::ostringstream &str, const char *data, size_t size) {
109 unsigned quot(0), apos(0);
110 for (const char *value(data), *end(data + size); value != end; ++value)
111 if (*value == '"')
112 ++quot;
113 else if (*value == '\'')
114 ++apos;
115
116 bool single(quot > apos);
117
118 str << (single ? '\'' : '"');
119
120 for (const char *value(data), *end(data + size); value != end; ++value)
ee6c04ef 121 switch (uint8_t next = *value) {
37954781
JF
122 case '\\': str << "\\\\"; break;
123 case '\b': str << "\\b"; break;
124 case '\f': str << "\\f"; break;
125 case '\n': str << "\\n"; break;
126 case '\r': str << "\\r"; break;
127 case '\t': str << "\\t"; break;
128 case '\v': str << "\\v"; break;
129
130 case '"':
131 if (!single)
132 str << "\\\"";
133 else goto simple;
134 break;
135
136 case '\'':
137 if (single)
138 str << "\\'";
139 else goto simple;
140 break;
141
ee6c04ef
JF
142 case '\0':
143 if (value[1] >= '0' && value[1] <= '9')
144 str << "\\x00";
145 else
146 str << "\\0";
147 break;
148
37954781 149 default:
ee6c04ef 150 if (next >= 0x20 && next < 0x7f) simple:
37954781 151 str << *value;
ee6c04ef
JF
152 else {
153 unsigned levels(1);
154 if ((next & 0x80) != 0)
155 while ((next & 0x80 >> ++levels) != 0);
156
157 unsigned point(next & 0xff >> levels);
158 while (--levels != 0)
159 point = point << 6 | uint8_t(*++value) & 0x3f;
160
161 if (point < 0x100)
162 str << "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << point;
163 else if (point < 0x10000)
164 str << "\\u" << std::setbase(16) << std::setw(4) << std::setfill('0') << point;
165 else {
166 point -= 0x10000;
167 str << "\\u" << std::setbase(16) << std::setw(4) << std::setfill('0') << (0xd800 | point >> 0x0a);
168 str << "\\u" << std::setbase(16) << std::setw(4) << std::setfill('0') << (0xdc00 | point & 0x3ff);
169 }
170 }
37954781
JF
171 }
172
173 str << (single ? '\'' : '"');
174}
175
176void CYNumerify(std::ostringstream &str, double value) {
177 char string[32];
178 // XXX: I want this to print 1e3 rather than 1000
179 sprintf(string, "%.17g", value);
180 str << string;
181}
182
183bool CYIsKey(CYUTF8String value) {
184 const char *data(value.data);
185 size_t size(value.size);
186
187 if (size == 0)
188 return false;
189
190 if (DigitRange_[data[0]]) {
191 size_t index(CYGetIndex(value));
192 if (index == _not(size_t))
193 return false;
194 } else {
195 if (!WordStartRange_[data[0]])
196 return false;
197 for (size_t i(1); i != size; ++i)
198 if (!WordEndRange_[data[i]])
199 return false;
200 }
201
202 return true;
203}
204/* }}} */
205
37954781
JF
206double CYCastDouble(const char *value, size_t size) {
207 char *end;
208 double number(strtod(value, &end));
209 if (end != value + size)
210 return NAN;
211 return number;
212}
213
214double CYCastDouble(const char *value) {
215 return CYCastDouble(value, strlen(value));
216}
217
5587a93f 218CYUTF8String CYPoolCode(CYPool &pool, std::istream &stream) {
2eb8215d 219 CYLocalPool local;
2c1d569a 220 CYDriver driver(local, stream);
8a392978 221 _assert(!driver.Parse());
57930129 222 _assert(driver.errors_.empty());
59cd74c1 223
029bc65b 224 CYOptions options;
2eb8215d 225 CYContext context(options);
a7d8b413 226 driver.script_->Replace(context);
57930129 227
efd689d8 228 std::stringbuf str;
029bc65b 229 CYOutput out(str, options);
a7d8b413 230 out << *driver.script_;
a2b8d7ad 231 return $pool.strdup(str.str().c_str());
57930129 232}
59cd74c1 233
b799113b 234CYPool &CYGetGlobalPool() {
b799113b
JF
235 static CYPool pool;
236 return pool;
37954781
JF
237}
238
d9c91152 239_visible void CYThrow(const char *format, ...) {
37954781 240 va_list args;
b64ab4da 241 va_start(args, format);
37954781
JF
242 throw CYPoolError(format, args);
243 // XXX: does this matter? :(
b64ab4da 244 va_end(args);
37954781
JF
245}
246
b799113b
JF
247const char *CYPoolError::PoolCString(CYPool &pool) const {
248 return pool.strdup(message_);
37954781
JF
249}
250
0cbeddf8
JF
251CYPoolError::CYPoolError(const CYPoolError &rhs) :
252 message_(pool_.strdup(rhs.message_))
253{
254}
255
37954781
JF
256CYPoolError::CYPoolError(const char *format, ...) {
257 va_list args;
b64ab4da 258 va_start(args, format);
0cbeddf8
JF
259 // XXX: there might be a beter way to think about this
260 message_ = pool_.vsprintf(64, format, args);
b64ab4da 261 va_end(args);
37954781
JF
262}
263
264CYPoolError::CYPoolError(const char *format, va_list args) {
0cbeddf8
JF
265 // XXX: there might be a beter way to think about this
266 message_ = pool_.vsprintf(64, format, args);
37954781 267}