]> git.saurik.com Git - cycript.git/blob - Library.cpp
With -p on all platforms, we can't use asprintf().
[cycript.git] / Library.cpp
1 /* Cycript - The Truly Universal Scripting Language
2 * Copyright (C) 2009-2016 Jay Freeman (saurik)
3 */
4
5 /* GNU Affero General Public License, Version 3 {{{ */
6 /*
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.
11
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.
16
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/>.
19 **/
20 /* }}} */
21
22 #include "cycript.hpp"
23
24 #include <iostream>
25 #include <set>
26 #include <map>
27 #include <sstream>
28
29 #include <dlfcn.h>
30
31 #include <sys/mman.h>
32
33 #include "Code.hpp"
34 #include "ConvertUTF.h"
35 #include "Driver.hpp"
36 #include "Error.hpp"
37 #include "Execute.hpp"
38 #include "Pooling.hpp"
39 #include "String.hpp"
40 #include "Syntax.hpp"
41
42 /* C Strings {{{ */
43 CYUTF8String CYPoolUTF8String(CYPool &pool, CYUTF16String utf16) {
44 // XXX: this is wrong
45 size_t size(utf16.size * 5);
46 char *temp(new(pool) char[size + 1]);
47
48 const uint16_t *lhs(utf16.data);
49 uint8_t *rhs(reinterpret_cast<uint8_t *>(temp));
50 _assert(ConvertUTF16toUTF8(&lhs, lhs + utf16.size, &rhs, rhs + size, lenientConversion) == conversionOK);
51
52 *rhs = 0;
53 return CYUTF8String(temp, reinterpret_cast<char *>(rhs) - temp);
54 }
55
56 CYUTF16String CYPoolUTF16String(CYPool &pool, CYUTF8String utf8) {
57 // XXX: this is wrong
58 size_t size(utf8.size * 5);
59 uint16_t *temp(new (pool) uint16_t[size + 1]);
60
61 const uint8_t *lhs(reinterpret_cast<const uint8_t *>(utf8.data));
62 uint16_t *rhs(temp);
63 _assert(ConvertUTF8toUTF16(&lhs, lhs + utf8.size, &rhs, rhs + size, lenientConversion) == conversionOK);
64
65 *rhs = 0;
66 return CYUTF16String(temp, rhs - temp);
67 }
68 /* }}} */
69 /* Index Offsets {{{ */
70 size_t CYGetIndex(const CYUTF8String &value) {
71 if (value.data[0] != '0') {
72 size_t index(0);
73 for (size_t i(0); i != value.size; ++i) {
74 if (!DigitRange_[value.data[i]])
75 return _not(size_t);
76 index *= 10;
77 index += value.data[i] - '0';
78 }
79 return index;
80 } else if (value.size == 1)
81 return 0;
82 else
83 return _not(size_t);
84 }
85
86 // XXX: this isn't actually right
87 bool CYGetOffset(const char *value, ssize_t &index) {
88 if (value[0] != '0') {
89 char *end;
90 index = strtol(value, &end, 10);
91 if (value + strlen(value) == end)
92 return true;
93 } else if (value[1] == '\0') {
94 index = 0;
95 return true;
96 }
97
98 return false;
99 }
100 /* }}} */
101
102 bool CYIsKey(CYUTF8String value) {
103 const char *data(value.data);
104 size_t size(value.size);
105
106 if (size == 0)
107 return false;
108
109 if (DigitRange_[data[0]]) {
110 size_t index(CYGetIndex(value));
111 if (index == _not(size_t))
112 return false;
113 } else {
114 if (!WordStartRange_[data[0]])
115 return false;
116 for (size_t i(1); i != size; ++i)
117 if (!WordEndRange_[data[i]])
118 return false;
119 }
120
121 return true;
122 }
123
124 _visible bool CYStartsWith(const CYUTF8String &haystack, const CYUTF8String &needle) {
125 return haystack.size >= needle.size && strncmp(haystack.data, needle.data, needle.size) == 0;
126 }
127
128 CYUTF8String CYPoolCode(CYPool &pool, std::streambuf &stream) {
129 CYLocalPool local;
130 CYDriver driver(local, stream);
131
132 if (driver.Parse()) {
133 if (!driver.errors_.empty())
134 CYThrow("%s", driver.errors_.front().message_.c_str());
135 CYThrow("syntax error");
136 }
137
138 CYOptions options;
139 CYContext context(options);
140 driver.script_->Replace(context);
141
142 std::stringbuf str;
143 CYOutput out(str, options);
144 out << *driver.script_;
145 return pool.strdup(str.str().c_str());
146 }
147
148 CYUTF8String CYPoolCode(CYPool &pool, CYUTF8String code) {
149 CYStream stream(code.data, code.data + code.size);
150 return CYPoolCode(pool, stream);
151 }
152
153 CYPool &CYGetGlobalPool() {
154 static CYPool pool;
155 return pool;
156 }