]>
git.saurik.com Git - cycript.git/blob - Library.cpp
37e2b3c4cd6dd56786425788bb8c829b8e5bc375
   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(CYPool 
&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(CYPool 
&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()); 
 266     CYUTF16String 
utf16(CYPoolUTF16String(pool
, CYUTF8String(code
.c_str(), code
.size()))); 
 272 static bool initialized_
; 
 274 void CYInitializeStatic() { 
 279     _aprcall(apr_initialize()); 
 282 CYPool 
&CYGetGlobalPool() { 
 283     CYInitializeStatic(); 
 288 void CYThrow(const char *format
, ...) { 
 290     va_start(args
, format
); 
 291     throw CYPoolError(format
, args
); 
 292     // XXX: does this matter? :( 
 296 const char *CYPoolError::PoolCString(CYPool 
&pool
) const { 
 297     return pool
.strdup(message_
); 
 300 CYPoolError::CYPoolError(const char *format
, ...) { 
 302     va_start(args
, format
); 
 303     message_ 
= pool_
.vsprintf(format
, args
); 
 307 CYPoolError::CYPoolError(const char *format
, va_list args
) { 
 308     message_ 
= pool_
.vsprintf(format
, args
);