]> git.saurik.com Git - cycript.git/blame - Library.cpp
Support SO variable even when not Mach.
[cycript.git] / Library.cpp
CommitLineData
b3378a02
JF
1/* Cycript - Optimizing JavaScript Compiler/Runtime
2 * Copyright (C) 2009-2010 Jay Freeman (saurik)
37954781
JF
3*/
4
b3378a02 5/* GNU Lesser General Public License, Version 3 {{{ */
37954781 6/*
b3378a02
JF
7 * Cycript is free software: you can redistribute it and/or modify it under
8 * the terms of the GNU Lesser General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
37954781 11 *
b3378a02
JF
12 * Cycript is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 * License for more details.
37954781 16 *
b3378a02
JF
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with Cycript. If not, see <http://www.gnu.org/licenses/>.
19**/
37954781
JF
20/* }}} */
21
37954781
JF
22#include <dlfcn.h>
23#include <iconv.h>
24
25#include "cycript.hpp"
26
37954781
JF
27#include "Pooling.hpp"
28
29#include <sys/mman.h>
30
31#include <iostream>
32#include <ext/stdio_filebuf.h>
33#include <set>
34#include <map>
35#include <iomanip>
36#include <sstream>
37#include <cmath>
38
39#include "Parser.hpp"
40#include "Cycript.tab.hh"
41
42#include "Error.hpp"
37954781 43#include "String.hpp"
2f51d6ab 44#include "Execute.hpp"
37954781 45
59cd74c1
JF
46/* C Strings {{{ */
47template <typename Type_>
48_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) {
49 return iconv(cd, const_cast<Type_>(inbuf), inbytesleft, outbuf, outbytesleft);
50}
51
52#ifdef __GLIBC__
53#define UCS_2_INTERNAL "UCS-2"
54#else
55#define UCS_2_INTERNAL "UCS-2-INTERNAL"
56#endif
57
58CYUTF8String CYPoolUTF8String(apr_pool_t *pool, CYUTF16String utf16) {
59 _assert(pool != NULL);
60
61 const char *in(reinterpret_cast<const char *>(utf16.data));
62
63 iconv_t conversion(_syscall(iconv_open("UTF-8", UCS_2_INTERNAL)));
64
65 // XXX: this is wrong
66 size_t size(utf16.size * 5);
67 char *out(new(pool) char[size]);
68 CYUTF8String utf8(out, size);
69
70 size = utf16.size * 2;
71 _syscall(iconv_(&iconv, conversion, const_cast<char **>(&in), &size, &out, &utf8.size));
72
73 *out = '\0';
74 utf8.size = out - utf8.data;
75
76 _syscall(iconv_close(conversion));
77
78 return utf8;
79}
80
81CYUTF16String CYPoolUTF16String(apr_pool_t *pool, CYUTF8String utf8) {
82 _assert(pool != NULL);
83
84 const char *in(utf8.data);
85
86 iconv_t conversion(_syscall(iconv_open(UCS_2_INTERNAL, "UTF-8")));
87
88 // XXX: this is wrong
89 size_t size(utf8.size * 5);
90 uint16_t *temp(new (pool) uint16_t[size]);
91 CYUTF16String utf16(temp, size * 2);
92 char *out(reinterpret_cast<char *>(temp));
93
94 size = utf8.size;
95 _syscall(iconv_(&iconv, conversion, const_cast<char **>(&in), &size, &out, &utf16.size));
96
97 utf16.size = reinterpret_cast<uint16_t *>(out) - utf16.data;
98 temp[utf16.size] = 0;
99
100 _syscall(iconv_close(conversion));
101
102 return utf16;
103}
104/* }}} */
37954781
JF
105/* Index Offsets {{{ */
106size_t CYGetIndex(const CYUTF8String &value) {
107 if (value.data[0] != '0') {
ba4fa42f
JF
108 size_t index(0);
109 for (size_t i(0); i != value.size; ++i) {
110 if (!DigitRange_[value.data[i]])
111 return _not(size_t);
112 index *= 10;
113 index += value.data[i] - '0';
114 }
115 return index;
116 } else if (value.size == 1)
37954781 117 return 0;
ba4fa42f
JF
118 else
119 return _not(size_t);
37954781
JF
120}
121
ba4fa42f 122// XXX: this isn't actually right
37954781
JF
123bool CYGetOffset(const char *value, ssize_t &index) {
124 if (value[0] != '0') {
125 char *end;
126 index = strtol(value, &end, 10);
127 if (value + strlen(value) == end)
128 return true;
129 } else if (value[1] == '\0') {
130 index = 0;
131 return true;
132 }
133
134 return false;
135}
136/* }}} */
37954781
JF
137/* JavaScript *ify {{{ */
138void CYStringify(std::ostringstream &str, const char *data, size_t size) {
139 unsigned quot(0), apos(0);
140 for (const char *value(data), *end(data + size); value != end; ++value)
141 if (*value == '"')
142 ++quot;
143 else if (*value == '\'')
144 ++apos;
145
146 bool single(quot > apos);
147
148 str << (single ? '\'' : '"');
149
150 for (const char *value(data), *end(data + size); value != end; ++value)
151 switch (*value) {
152 case '\\': str << "\\\\"; break;
153 case '\b': str << "\\b"; break;
154 case '\f': str << "\\f"; break;
155 case '\n': str << "\\n"; break;
156 case '\r': str << "\\r"; break;
157 case '\t': str << "\\t"; break;
158 case '\v': str << "\\v"; break;
159
160 case '"':
161 if (!single)
162 str << "\\\"";
163 else goto simple;
164 break;
165
166 case '\'':
167 if (single)
168 str << "\\'";
169 else goto simple;
170 break;
171
172 default:
b64ab4da 173 // this test is designed to be "awesome", generating neither warnings nor incorrect results
37954781 174 if (*value < 0x20 || *value >= 0x7f)
51a72a9d 175 str << "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << unsigned(uint8_t(*value));
37954781
JF
176 else simple:
177 str << *value;
178 }
179
180 str << (single ? '\'' : '"');
181}
182
183void CYNumerify(std::ostringstream &str, double value) {
184 char string[32];
185 // XXX: I want this to print 1e3 rather than 1000
186 sprintf(string, "%.17g", value);
187 str << string;
188}
189
190bool CYIsKey(CYUTF8String value) {
191 const char *data(value.data);
192 size_t size(value.size);
193
194 if (size == 0)
195 return false;
196
197 if (DigitRange_[data[0]]) {
198 size_t index(CYGetIndex(value));
199 if (index == _not(size_t))
200 return false;
201 } else {
202 if (!WordStartRange_[data[0]])
203 return false;
204 for (size_t i(1); i != size; ++i)
205 if (!WordEndRange_[data[i]])
206 return false;
207 }
208
209 return true;
210}
211/* }}} */
212
37954781
JF
213double CYCastDouble(const char *value, size_t size) {
214 char *end;
215 double number(strtod(value, &end));
216 if (end != value + size)
217 return NAN;
218 return number;
219}
220
221double CYCastDouble(const char *value) {
222 return CYCastDouble(value, strlen(value));
223}
224
2eb8215d
JF
225extern "C" void CydgetPoolParse(apr_pool_t *remote, const uint16_t **data, size_t *size) {
226 CYLocalPool local;
227
7e5391fd 228 CYDriver driver;
59cd74c1
JF
229 cy::parser parser(driver);
230
2eb8215d 231 CYUTF8String utf8(CYPoolUTF8String(local, CYUTF16String(*data, *size)));
59cd74c1
JF
232
233 driver.data_ = utf8.data;
234 driver.size_ = utf8.size;
235
236 if (parser.parse() != 0 || !driver.errors_.empty())
237 return;
238
029bc65b 239 CYOptions options;
2eb8215d 240 CYContext context(options);
59cd74c1
JF
241 driver.program_->Replace(context);
242 std::ostringstream str;
029bc65b 243 CYOutput out(str, options);
59cd74c1
JF
244 out << *driver.program_;
245 std::string code(str.str());
246
2eb8215d 247 CYUTF16String utf16(CYPoolUTF16String(remote, CYUTF8String(code.c_str(), code.size())));
59cd74c1
JF
248
249 *data = utf16.data;
250 *size = utf16.size;
251}
252
37954781
JF
253static apr_pool_t *Pool_;
254
255static bool initialized_;
256
9cad30fa 257void CYInitializeStatic() {
37954781
JF
258 if (!initialized_)
259 initialized_ = true;
260 else return;
261
262 _aprcall(apr_initialize());
263 _aprcall(apr_pool_create(&Pool_, NULL));
37954781
JF
264}
265
266apr_pool_t *CYGetGlobalPool() {
9cad30fa 267 CYInitializeStatic();
37954781
JF
268 return Pool_;
269}
270
37954781
JF
271void CYThrow(const char *format, ...) {
272 va_list args;
b64ab4da 273 va_start(args, format);
37954781
JF
274 throw CYPoolError(format, args);
275 // XXX: does this matter? :(
b64ab4da 276 va_end(args);
37954781
JF
277}
278
279const char *CYPoolError::PoolCString(apr_pool_t *pool) const {
280 return apr_pstrdup(pool, message_);
281}
282
283CYPoolError::CYPoolError(const char *format, ...) {
284 va_list args;
b64ab4da 285 va_start(args, format);
37954781 286 message_ = apr_pvsprintf(pool_, format, args);
b64ab4da 287 va_end(args);
37954781
JF
288}
289
290CYPoolError::CYPoolError(const char *format, va_list args) {
291 message_ = apr_pvsprintf(pool_, format, args);
292}