]>
git.saurik.com Git - cycript.git/blob - Library.cpp
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/>.
24 #include "cycript.hpp"
26 #include "Pooling.hpp"
31 #include <ext/stdio_filebuf.h>
39 #include "Cycript.tab.hh"
43 #include "Execute.hpp"
44 #include "JavaScript.hpp"
46 #include "ConvertUTF.h"
49 CYUTF8String
CYPoolUTF8String(CYPool
&pool
, CYUTF16String utf16
) {
51 size_t size(utf16
.size
* 5);
52 char *temp(new(pool
) char[size
]);
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
);
59 return CYUTF8String(temp
, reinterpret_cast<char *>(rhs
) - temp
);
62 CYUTF16String
CYPoolUTF16String(CYPool
&pool
, CYUTF8String utf8
) {
64 size_t size(utf8
.size
* 5);
65 uint16_t *temp(new (pool
) uint16_t[size
]);
67 const uint8_t *lhs(reinterpret_cast<const uint8_t *>(utf8
.data
));
69 _assert(ConvertUTF8toUTF16(&lhs
, lhs
+ utf8
.size
, &rhs
, rhs
+ size
, lenientConversion
) == conversionOK
);
72 return CYUTF16String(temp
, rhs
- temp
);
75 /* Index Offsets {{{ */
76 size_t CYGetIndex(const CYUTF8String
&value
) {
77 if (value
.data
[0] != '0') {
79 for (size_t i(0); i
!= value
.size
; ++i
) {
80 if (!DigitRange_
[value
.data
[i
]])
83 index
+= value
.data
[i
] - '0';
86 } else if (value
.size
== 1)
92 // XXX: this isn't actually right
93 bool CYGetOffset(const char *value
, ssize_t
&index
) {
94 if (value
[0] != '0') {
96 index
= strtol(value
, &end
, 10);
97 if (value
+ strlen(value
) == end
)
99 } else if (value
[1] == '\0') {
107 /* JavaScript *ify {{{ */
108 void 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
)
113 else if (*value
== '\'')
116 bool single(quot
> apos
);
118 str
<< (single
? '\'' : '"');
120 for (const char *value(data
), *end(data
+ size
); value
!= end
; ++value
)
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;
143 // this test is designed to be "awesome", generating neither warnings nor incorrect results
144 if (*value
< 0x20 || *value
>= 0x7f)
145 str
<< "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << unsigned(uint8_t(*value
));
150 str
<< (single
? '\'' : '"');
153 void CYNumerify(std::ostringstream
&str
, double value
) {
155 // XXX: I want this to print 1e3 rather than 1000
156 sprintf(string
, "%.17g", value
);
160 bool CYIsKey(CYUTF8String value
) {
161 const char *data(value
.data
);
162 size_t size(value
.size
);
167 if (DigitRange_
[data
[0]]) {
168 size_t index(CYGetIndex(value
));
169 if (index
== _not(size_t))
172 if (!WordStartRange_
[data
[0]])
174 for (size_t i(1); i
!= size
; ++i
)
175 if (!WordEndRange_
[data
[i
]])
183 double CYCastDouble(const char *value
, size_t size
) {
185 double number(strtod(value
, &end
));
186 if (end
!= value
+ size
)
191 double CYCastDouble(const char *value
) {
192 return CYCastDouble(value
, strlen(value
));
195 size_t CYArrayLength(JSContextRef context
, JSObjectRef array
) {
196 return CYCastDouble(context
, CYGetProperty(context
, array
, length_s
));
199 JSValueRef
CYArrayGet(JSContextRef context
, JSObjectRef array
, size_t index
) {
200 JSValueRef
exception(NULL
);
201 JSValueRef
value(JSObjectGetPropertyAtIndex(context
, array
, index
, &exception
));
202 CYThrow(context
, exception
);
206 void CYArrayPush(JSContextRef context
, JSObjectRef array
, JSValueRef value
) {
207 JSValueRef
exception(NULL
);
208 JSValueRef arguments
[1];
209 arguments
[0] = value
;
210 JSObjectRef
Array(CYGetCachedObject(context
, CYJSString("Array_prototype")));
211 JSObjectCallAsFunction(context
, CYCastJSObject(context
, CYGetProperty(context
, Array
, push_s
)), array
, 1, arguments
, &exception
);
212 CYThrow(context
, exception
);
215 extern "C" void CydgetMemoryParse(const uint16_t **data
, size_t *size
) {
218 CYUTF8String
utf8(CYPoolUTF8String(local
, CYUTF16String(*data
, *size
)));
219 CYStream
stream(utf8
.data
, utf8
.data
+ utf8
.size
);
220 CYDriver
driver(stream
);
222 cy::parser
parser(driver
);
223 if (parser
.parse() != 0 || !driver
.errors_
.empty())
227 CYContext
context(options
);
228 driver
.program_
->Replace(context
);
229 std::ostringstream str
;
230 CYOutput
out(str
, options
);
231 out
<< *driver
.program_
;
232 std::string
code(str
.str());
235 CYUTF16String
utf16(CYPoolUTF16String(pool
, CYUTF8String(code
.c_str(), code
.size())));
237 size_t bytes(utf16
.size
* sizeof(uint16_t));
238 uint16_t *copy(reinterpret_cast<uint16_t *>(malloc(bytes
)));
239 memcpy(copy
, utf16
.data
, bytes
);
245 CYPool
&CYGetGlobalPool() {
250 void CYThrow(const char *format
, ...) {
252 va_start(args
, format
);
253 throw CYPoolError(format
, args
);
254 // XXX: does this matter? :(
258 const char *CYPoolError::PoolCString(CYPool
&pool
) const {
259 return pool
.strdup(message_
);
262 CYPoolError::CYPoolError(const CYPoolError
&rhs
) :
263 message_(pool_
.strdup(rhs
.message_
))
267 CYPoolError::CYPoolError(const char *format
, ...) {
269 va_start(args
, format
);
270 // XXX: there might be a beter way to think about this
271 message_
= pool_
.vsprintf(64, format
, args
);
275 CYPoolError::CYPoolError(const char *format
, va_list args
) {
276 // XXX: there might be a beter way to think about this
277 message_
= pool_
.vsprintf(64, format
, args
);