1 /* Cycript - Optimizing JavaScript Compiler/Runtime
2 * Copyright (C) 2009-2013 Jay Freeman (saurik)
5 /* GNU General Public License, Version 3 {{{ */
7 * Cycript is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation, either version 3 of the License,
10 * or (at your option) any later version.
12 * Cycript is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Cycript. If not, see <http://www.gnu.org/licenses/>.
25 #include "cycript.hpp"
27 #include "Pooling.hpp"
32 #include <ext/stdio_filebuf.h>
40 #include "Cycript.tab.hh"
44 #include "Execute.hpp"
45 #include "JavaScript.hpp"
48 template <typename Type_
>
49 _finline
size_t iconv_(size_t (*iconv
)(iconv_t
, Type_
, size_t *, char **, size_t *), iconv_t cd
, char **inbuf
, size_t *inbytesleft
, char **outbuf
, size_t *outbytesleft
) {
50 return iconv(cd
, const_cast<Type_
>(inbuf
), inbytesleft
, outbuf
, outbytesleft
);
54 #define UCS_2_INTERNAL "UCS-2"
56 #define UCS_2_INTERNAL "UCS-2-INTERNAL"
59 CYUTF8String
CYPoolUTF8String(apr_pool_t
*pool
, CYUTF16String utf16
) {
60 _assert(pool
!= NULL
);
62 const char *in(reinterpret_cast<const char *>(utf16
.data
));
64 iconv_t
conversion(_syscall(iconv_open("UTF-8", UCS_2_INTERNAL
)));
67 size_t size(utf16
.size
* 5);
68 char *out(new(pool
) char[size
]);
69 CYUTF8String
utf8(out
, size
);
71 size
= utf16
.size
* 2;
72 _syscall(iconv_(&iconv
, conversion
, const_cast<char **>(&in
), &size
, &out
, &utf8
.size
));
75 utf8
.size
= out
- utf8
.data
;
77 _syscall(iconv_close(conversion
));
82 CYUTF16String
CYPoolUTF16String(apr_pool_t
*pool
, CYUTF8String utf8
) {
83 _assert(pool
!= NULL
);
85 const char *in(utf8
.data
);
87 iconv_t
conversion(_syscall(iconv_open(UCS_2_INTERNAL
, "UTF-8")));
90 size_t size(utf8
.size
* 5);
91 uint16_t *temp(new (pool
) uint16_t[size
]);
92 CYUTF16String
utf16(temp
, size
* 2);
93 char *out(reinterpret_cast<char *>(temp
));
96 _syscall(iconv_(&iconv
, conversion
, const_cast<char **>(&in
), &size
, &out
, &utf16
.size
));
98 utf16
.size
= reinterpret_cast<uint16_t *>(out
) - utf16
.data
;
101 _syscall(iconv_close(conversion
));
106 /* Index Offsets {{{ */
107 size_t CYGetIndex(const CYUTF8String
&value
) {
108 if (value
.data
[0] != '0') {
110 for (size_t i(0); i
!= value
.size
; ++i
) {
111 if (!DigitRange_
[value
.data
[i
]])
114 index
+= value
.data
[i
] - '0';
117 } else if (value
.size
== 1)
123 // XXX: this isn't actually right
124 bool CYGetOffset(const char *value
, ssize_t
&index
) {
125 if (value
[0] != '0') {
127 index
= strtol(value
, &end
, 10);
128 if (value
+ strlen(value
) == end
)
130 } else if (value
[1] == '\0') {
138 /* JavaScript *ify {{{ */
139 void CYStringify(std::ostringstream
&str
, const char *data
, size_t size
) {
140 unsigned quot(0), apos(0);
141 for (const char *value(data
), *end(data
+ size
); value
!= end
; ++value
)
144 else if (*value
== '\'')
147 bool single(quot
> apos
);
149 str
<< (single
? '\'' : '"');
151 for (const char *value(data
), *end(data
+ size
); value
!= end
; ++value
)
153 case '\\': str
<< "\\\\"; break;
154 case '\b': str
<< "\\b"; break;
155 case '\f': str
<< "\\f"; break;
156 case '\n': str
<< "\\n"; break;
157 case '\r': str
<< "\\r"; break;
158 case '\t': str
<< "\\t"; break;
159 case '\v': str
<< "\\v"; break;
174 // this test is designed to be "awesome", generating neither warnings nor incorrect results
175 if (*value
< 0x20 || *value
>= 0x7f)
176 str
<< "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << unsigned(uint8_t(*value
));
181 str
<< (single
? '\'' : '"');
184 void CYNumerify(std::ostringstream
&str
, double value
) {
186 // XXX: I want this to print 1e3 rather than 1000
187 sprintf(string
, "%.17g", value
);
191 bool CYIsKey(CYUTF8String value
) {
192 const char *data(value
.data
);
193 size_t size(value
.size
);
198 if (DigitRange_
[data
[0]]) {
199 size_t index(CYGetIndex(value
));
200 if (index
== _not(size_t))
203 if (!WordStartRange_
[data
[0]])
205 for (size_t i(1); i
!= size
; ++i
)
206 if (!WordEndRange_
[data
[i
]])
214 double CYCastDouble(const char *value
, size_t size
) {
216 double number(strtod(value
, &end
));
217 if (end
!= value
+ size
)
222 double CYCastDouble(const char *value
) {
223 return CYCastDouble(value
, strlen(value
));
226 size_t CYArrayLength(JSContextRef context
, JSObjectRef array
) {
227 return CYCastDouble(context
, CYGetProperty(context
, array
, length_s
));
230 JSValueRef
CYArrayGet(JSContextRef context
, JSObjectRef array
, size_t index
) {
231 JSValueRef
exception(NULL
);
232 JSValueRef
value(JSObjectGetPropertyAtIndex(context
, array
, index
, &exception
));
233 CYThrow(context
, exception
);
237 void CYArrayPush(JSContextRef context
, JSObjectRef array
, JSValueRef value
) {
238 JSValueRef
exception(NULL
);
239 JSValueRef arguments
[1];
240 arguments
[0] = value
;
241 JSObjectRef
Array(CYGetCachedObject(context
, CYJSString("Array_prototype")));
242 JSObjectCallAsFunction(context
, CYCastJSObject(context
, CYGetProperty(context
, Array
, push_s
)), array
, 1, arguments
, &exception
);
243 CYThrow(context
, exception
);
246 extern "C" void CydgetPoolParse(apr_pool_t
*remote
, const uint16_t **data
, size_t *size
) {
249 CYUTF8String
utf8(CYPoolUTF8String(local
, CYUTF16String(*data
, *size
)));
250 CYStream
stream(utf8
.data
, utf8
.data
+ utf8
.size
);
251 CYDriver
driver(stream
);
253 cy::parser
parser(driver
);
254 if (parser
.parse() != 0 || !driver
.errors_
.empty())
258 CYContext
context(options
);
259 driver
.program_
->Replace(context
);
260 std::ostringstream str
;
261 CYOutput
out(str
, options
);
262 out
<< *driver
.program_
;
263 std::string
code(str
.str());
265 CYUTF16String
utf16(CYPoolUTF16String(remote
, CYUTF8String(code
.c_str(), code
.size())));
271 static apr_pool_t
*Pool_
;
273 static bool initialized_
;
275 void CYInitializeStatic() {
280 _aprcall(apr_initialize());
281 _aprcall(apr_pool_create(&Pool_
, NULL
));
284 apr_pool_t
*CYGetGlobalPool() {
285 CYInitializeStatic();
289 void CYThrow(const char *format
, ...) {
291 va_start(args
, format
);
292 throw CYPoolError(format
, args
);
293 // XXX: does this matter? :(
297 const char *CYPoolError::PoolCString(apr_pool_t
*pool
) const {
298 return apr_pstrdup(pool
, message_
);
301 CYPoolError::CYPoolError(const char *format
, ...) {
303 va_start(args
, format
);
304 message_
= apr_pvsprintf(pool_
, format
, args
);
308 CYPoolError::CYPoolError(const char *format
, va_list args
) {
309 message_
= apr_pvsprintf(pool_
, format
, args
);