]>
git.saurik.com Git - cycript.git/blob - Library.cpp
1 /* Cycript - Inlining/Optimizing JavaScript Compiler
2 * Copyright (C) 2009 Jay Freeman (saurik)
5 /* Modified BSD License {{{ */
7 * Redistribution and use in source and binary
8 * forms, with or without modification, are permitted
9 * provided that the following conditions are met:
11 * 1. Redistributions of source code must retain the
12 * above copyright notice, this list of conditions
13 * and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the
15 * above copyright notice, this list of conditions
16 * and the following disclaimer in the documentation
17 * and/or other materials provided with the
19 * 3. The name of the author may not be used to endorse
20 * or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
25 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
34 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
36 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 #include "cycript.hpp"
45 #include "Pooling.hpp"
46 #include "Context.hpp"
51 #include <ext/stdio_filebuf.h>
59 #include "Cycript.tab.hh"
65 template <typename Type_
>
66 _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
) {
67 return iconv(cd
, const_cast<Type_
>(inbuf
), inbytesleft
, outbuf
, outbytesleft
);
71 #define UCS_2_INTERNAL "UCS-2"
73 #define UCS_2_INTERNAL "UCS-2-INTERNAL"
76 CYUTF8String
CYPoolUTF8String(apr_pool_t
*pool
, CYUTF16String utf16
) {
77 _assert(pool
!= NULL
);
79 const char *in(reinterpret_cast<const char *>(utf16
.data
));
81 iconv_t
conversion(_syscall(iconv_open("UTF-8", UCS_2_INTERNAL
)));
84 size_t size(utf16
.size
* 5);
85 char *out(new(pool
) char[size
]);
86 CYUTF8String
utf8(out
, size
);
88 size
= utf16
.size
* 2;
89 _syscall(iconv_(&iconv
, conversion
, const_cast<char **>(&in
), &size
, &out
, &utf8
.size
));
92 utf8
.size
= out
- utf8
.data
;
94 _syscall(iconv_close(conversion
));
99 CYUTF16String
CYPoolUTF16String(apr_pool_t
*pool
, CYUTF8String utf8
) {
100 _assert(pool
!= NULL
);
102 const char *in(utf8
.data
);
104 iconv_t
conversion(_syscall(iconv_open(UCS_2_INTERNAL
, "UTF-8")));
106 // XXX: this is wrong
107 size_t size(utf8
.size
* 5);
108 uint16_t *temp(new (pool
) uint16_t[size
]);
109 CYUTF16String
utf16(temp
, size
* 2);
110 char *out(reinterpret_cast<char *>(temp
));
113 _syscall(iconv_(&iconv
, conversion
, const_cast<char **>(&in
), &size
, &out
, &utf16
.size
));
115 utf16
.size
= reinterpret_cast<uint16_t *>(out
) - utf16
.data
;
116 temp
[utf16
.size
] = 0;
118 _syscall(iconv_close(conversion
));
123 /* Index Offsets {{{ */
124 size_t CYGetIndex(const CYUTF8String
&value
) {
125 if (value
.data
[0] != '0') {
127 for (size_t i(0); i
!= value
.size
; ++i
) {
128 if (!DigitRange_
[value
.data
[i
]])
131 index
+= value
.data
[i
] - '0';
134 } else if (value
.size
== 1)
140 // XXX: this isn't actually right
141 bool CYGetOffset(const char *value
, ssize_t
&index
) {
142 if (value
[0] != '0') {
144 index
= strtol(value
, &end
, 10);
145 if (value
+ strlen(value
) == end
)
147 } else if (value
[1] == '\0') {
155 /* JavaScript *ify {{{ */
156 void CYStringify(std::ostringstream
&str
, const char *data
, size_t size
) {
157 unsigned quot(0), apos(0);
158 for (const char *value(data
), *end(data
+ size
); value
!= end
; ++value
)
161 else if (*value
== '\'')
164 bool single(quot
> apos
);
166 str
<< (single
? '\'' : '"');
168 for (const char *value(data
), *end(data
+ size
); value
!= end
; ++value
)
170 case '\\': str
<< "\\\\"; break;
171 case '\b': str
<< "\\b"; break;
172 case '\f': str
<< "\\f"; break;
173 case '\n': str
<< "\\n"; break;
174 case '\r': str
<< "\\r"; break;
175 case '\t': str
<< "\\t"; break;
176 case '\v': str
<< "\\v"; break;
191 // this test is designed to be "awesome", generating neither warnings nor incorrect results
192 if (*value
< 0x20 || *value
>= 0x7f)
193 str
<< "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << unsigned(uint8_t(*value
));
198 str
<< (single
? '\'' : '"');
201 void CYNumerify(std::ostringstream
&str
, double value
) {
203 // XXX: I want this to print 1e3 rather than 1000
204 sprintf(string
, "%.17g", value
);
208 bool CYIsKey(CYUTF8String value
) {
209 const char *data(value
.data
);
210 size_t size(value
.size
);
215 if (DigitRange_
[data
[0]]) {
216 size_t index(CYGetIndex(value
));
217 if (index
== _not(size_t))
220 if (!WordStartRange_
[data
[0]])
222 for (size_t i(1); i
!= size
; ++i
)
223 if (!WordEndRange_
[data
[i
]])
231 double CYCastDouble(const char *value
, size_t size
) {
233 double number(strtod(value
, &end
));
234 if (end
!= value
+ size
)
239 double CYCastDouble(const char *value
) {
240 return CYCastDouble(value
, strlen(value
));
243 extern "C" void CydgetPoolParse(apr_pool_t
*pool
, const uint16_t **data
, size_t *size
) {
245 cy::parser
parser(driver
);
247 CYUTF8String
utf8(CYPoolUTF8String(pool
, CYUTF16String(*data
, *size
)));
249 driver
.data_
= utf8
.data
;
250 driver
.size_
= utf8
.size
;
252 if (parser
.parse() != 0 || !driver
.errors_
.empty())
256 CYContext
context(driver
.pool_
, options
);
257 driver
.program_
->Replace(context
);
258 std::ostringstream str
;
259 CYOutput
out(str
, options
);
260 out
<< *driver
.program_
;
261 std::string
code(str
.str());
263 CYUTF16String
utf16(CYPoolUTF16String(pool
, CYUTF8String(code
.c_str(), code
.size())));
269 static apr_pool_t
*Pool_
;
271 static bool initialized_
;
273 void CYInitializeStatic() {
278 _aprcall(apr_initialize());
279 _aprcall(apr_pool_create(&Pool_
, NULL
));
282 apr_pool_t
*CYGetGlobalPool() {
283 CYInitializeStatic();
287 void CYThrow(const char *format
, ...) {
289 va_start(args
, format
);
290 throw CYPoolError(format
, args
);
291 // XXX: does this matter? :(
295 const char *CYPoolError::PoolCString(apr_pool_t
*pool
) const {
296 return apr_pstrdup(pool
, message_
);
299 CYPoolError::CYPoolError(const char *format
, ...) {
301 va_start(args
, format
);
302 message_
= apr_pvsprintf(pool_
, format
, args
);
306 CYPoolError::CYPoolError(const char *format
, va_list args
) {
307 message_
= apr_pvsprintf(pool_
, format
, args
);