]>
git.saurik.com Git - cycript.git/blob - Library.cpp
258ef61d004eb09e5de99307060f00793222a5be
   1 /* Cycript - Optimizing JavaScript Compiler/Runtime 
   2  * Copyright (C) 2009-2015  Jay Freeman (saurik) 
   5 /* GNU Affero General Public License, Version 3 {{{ */ 
   7  * This program is free software: you can redistribute it and/or modify 
   8  * it under the terms of the GNU Affero General Public License as published by 
   9  * the Free Software Foundation, either version 3 of the License, or 
  10  * (at your option) any later version. 
  12  * This program is distributed in the hope that it will be useful, 
  13  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
  14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  15  * GNU Affero General Public License for more details. 
  17  * You should have received a copy of the GNU Affero General Public License 
  18  * along with this program.  If not, see <http://www.gnu.org/licenses/>. 
  24 #include "cycript.hpp" 
  26 #include "Pooling.hpp" 
  38 #include "Execute.hpp" 
  42 #include "Cycript.tab.hh" 
  45 #include "ConvertUTF.h" 
  48 ::pthread_key_t CYLocal
<CYPool
>::key_ 
= Key_(); 
  51 CYUTF8String 
CYPoolUTF8String(CYPool 
&pool
, CYUTF16String utf16
) { 
  53     size_t size(utf16
.size 
* 5); 
  54     char *temp(new(pool
) char[size
]); 
  56     const uint16_t *lhs(utf16
.data
); 
  57     uint8_t *rhs(reinterpret_cast<uint8_t *>(temp
)); 
  58     _assert(ConvertUTF16toUTF8(&lhs
, lhs 
+ utf16
.size
, &rhs
, rhs 
+ size
, lenientConversion
) == conversionOK
); 
  61     return CYUTF8String(temp
, reinterpret_cast<char *>(rhs
) - temp
); 
  64 CYUTF16String 
CYPoolUTF16String(CYPool 
&pool
, CYUTF8String utf8
) { 
  66     size_t size(utf8
.size 
* 5); 
  67     uint16_t *temp(new (pool
) uint16_t[size
]); 
  69     const uint8_t *lhs(reinterpret_cast<const uint8_t *>(utf8
.data
)); 
  71     _assert(ConvertUTF8toUTF16(&lhs
, lhs 
+ utf8
.size
, &rhs
, rhs 
+ size
, lenientConversion
) == conversionOK
); 
  74     return CYUTF16String(temp
, rhs 
- temp
); 
  77 /* Index Offsets {{{ */ 
  78 size_t CYGetIndex(const CYUTF8String 
&value
) { 
  79     if (value
.data
[0] != '0') { 
  81         for (size_t i(0); i 
!= value
.size
; ++i
) { 
  82             if (!DigitRange_
[value
.data
[i
]]) 
  85             index 
+= value
.data
[i
] - '0'; 
  88     } else if (value
.size 
== 1) 
  94 // XXX: this isn't actually right 
  95 bool CYGetOffset(const char *value
, ssize_t 
&index
) { 
  96     if (value
[0] != '0') { 
  98         index 
= strtol(value
, &end
, 10); 
  99         if (value 
+ strlen(value
) == end
) 
 101     } else if (value
[1] == '\0') { 
 109 /* JavaScript *ify {{{ */ 
 110 void CYStringify(std::ostringstream 
&str
, const char *data
, size_t size
) { 
 111     unsigned quot(0), apos(0); 
 112     for (const char *value(data
), *end(data 
+ size
); value 
!= end
; ++value
) 
 115         else if (*value 
== '\'') 
 118     bool single(quot 
> apos
); 
 120     str 
<< (single 
? '\'' : '"'); 
 122     for (const char *value(data
), *end(data 
+ size
); value 
!= end
; ++value
) 
 123         switch (uint8_t next 
= *value
) { 
 124             case '\\': str 
<< "\\\\"; break; 
 125             case '\b': str 
<< "\\b"; break; 
 126             case '\f': str 
<< "\\f"; break; 
 127             case '\n': str 
<< "\\n"; break; 
 128             case '\r': str 
<< "\\r"; break; 
 129             case '\t': str 
<< "\\t"; break; 
 130             case '\v': str 
<< "\\v"; break; 
 145                 if (value
[1] >= '0' && value
[1] <= '9') 
 152                 if (next 
>= 0x20 && next 
< 0x7f) simple
: 
 156                     if ((next 
& 0x80) != 0) 
 157                         while ((next 
& 0x80 >> ++levels
) != 0); 
 159                     unsigned point(next 
& 0xff >> levels
); 
 160                     while (--levels 
!= 0) 
 161                         point 
= point 
<< 6 | uint8_t(*++value
) & 0x3f; 
 164                         str 
<< "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << point
; 
 165                     else if (point 
< 0x10000) 
 166                         str 
<< "\\u" << std::setbase(16) << std::setw(4) << std::setfill('0') << point
; 
 169                         str 
<< "\\u" << std::setbase(16) << std::setw(4) << std::setfill('0') << (0xd800 | point 
>> 0x0a); 
 170                         str 
<< "\\u" << std::setbase(16) << std::setw(4) << std::setfill('0') << (0xdc00 | point 
& 0x3ff); 
 175     str 
<< (single 
? '\'' : '"'); 
 178 void CYNumerify(std::ostringstream 
&str
, double value
) { 
 180     // XXX: I want this to print 1e3 rather than 1000 
 181     sprintf(string
, "%.17g", value
); 
 185 bool CYIsKey(CYUTF8String value
) { 
 186     const char *data(value
.data
); 
 187     size_t size(value
.size
); 
 192     if (DigitRange_
[data
[0]]) { 
 193         size_t index(CYGetIndex(value
)); 
 194         if (index 
== _not(size_t)) 
 197         if (!WordStartRange_
[data
[0]]) 
 199         for (size_t i(1); i 
!= size
; ++i
) 
 200             if (!WordEndRange_
[data
[i
]]) 
 208 double CYCastDouble(const char *value
, size_t size
) { 
 210     double number(strtod(value
, &end
)); 
 211     if (end 
!= value 
+ size
) 
 216 double CYCastDouble(const char *value
) { 
 217     return CYCastDouble(value
, strlen(value
)); 
 220 CYUTF8String 
CYPoolCode(CYPool 
&pool
, std::istream 
&stream
) { 
 222     CYDriver 
driver(local
, stream
); 
 224     cy::parser 
parser(driver
); 
 225     _assert(parser
.parse() == 0); 
 226     _assert(driver
.errors_
.empty()); 
 229     CYContext 
context(options
); 
 230     driver
.program_
->Replace(context
); 
 233     CYOutput 
out(str
, options
); 
 234     out 
<< *driver
.program_
; 
 235     return $pool
.strdup(str
.str().c_str()); 
 238 CYPool 
&CYGetGlobalPool() { 
 243 _visible 
void CYThrow(const char *format
, ...) { 
 245     va_start(args
, format
); 
 246     throw CYPoolError(format
, args
); 
 247     // XXX: does this matter? :( 
 251 const char *CYPoolError::PoolCString(CYPool 
&pool
) const { 
 252     return pool
.strdup(message_
); 
 255 CYPoolError::CYPoolError(const CYPoolError 
&rhs
) : 
 256     message_(pool_
.strdup(rhs
.message_
)) 
 260 CYPoolError::CYPoolError(const char *format
, ...) { 
 262     va_start(args
, format
); 
 263     // XXX: there might be a beter way to think about this 
 264     message_ 
= pool_
.vsprintf(64, format
, args
); 
 268 CYPoolError::CYPoolError(const char *format
, va_list args
) { 
 269     // XXX: there might be a beter way to think about this 
 270     message_ 
= pool_
.vsprintf(64, format
, args
);