]>
Commit | Line | Data |
---|---|---|
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 | } |