]> git.saurik.com Git - cycript.git/blame - Application.mm
Remove e: debugging NSLog.
[cycript.git] / Application.mm
CommitLineData
057f943f
JF
1#define _GNU_SOURCE
2
693d501b 3#include <substrate.h>
30ddc20c 4#include "cycript.hpp"
057f943f
JF
5
6#include <cstdio>
7#include <sstream>
8
9#include <setjmp.h>
10
11#include <readline/readline.h>
12#include <readline/history.h>
13
b09da87b
JF
14#include <sys/mman.h>
15
16#include <errno.h>
17#include <unistd.h>
18
19#include <sys/types.h>
20#include <sys/stat.h>
21#include <fcntl.h>
22
057f943f
JF
23#include "Cycript.tab.hh"
24
25static jmp_buf ctrlc_;
26
27void sigint(int) {
28 longjmp(ctrlc_, 1);
29}
30
4cf49641 31void Run(const char *code, FILE *fout) { _pooled
b09da87b
JF
32 JSStringRef script(JSStringCreateWithUTF8CString(code));
33
34 JSContextRef context(CYGetJSContext());
35
36 JSValueRef exception(NULL);
37 JSValueRef result(JSEvaluateScript(context, script, NULL, NULL, 0, &exception));
38 JSStringRelease(script);
39
4cf49641 40 if (exception != NULL) { error:
b09da87b 41 result = exception;
4cf49641
JF
42 exception = NULL;
43 }
b09da87b
JF
44
45 if (!JSValueIsUndefined(context, result)) {
478d4ed0
JF
46 CYPool pool;
47 const char *json;
b09da87b 48
4cf49641
JF
49 json = CYPoolJSONString(pool, context, result, &exception);
50 if (exception != NULL)
51 goto error;
b09da87b
JF
52
53 if (fout != NULL) {
478d4ed0 54 fputs(json, fout);
b09da87b
JF
55 fputs("\n", fout);
56 fflush(fout);
57 }
b09da87b
JF
58 }
59}
60
61void Console() {
1f8eae40
JF
62 bool bypass(false);
63 bool debug(false);
64
057f943f
JF
65 FILE *fout(stdout);
66
67 rl_bind_key('\t', rl_insert);
68
69 struct sigaction action;
70 sigemptyset(&action.sa_mask);
71 action.sa_handler = &sigint;
72 action.sa_flags = 0;
73 sigaction(SIGINT, &action, NULL);
74
75 restart: for (;;) {
76 std::string command;
77 std::vector<std::string> lines;
78
931b816a
JF
79 bool extra(false);
80 const char *prompt("cy# ");
81
057f943f
JF
82 if (setjmp(ctrlc_) != 0) {
83 fputs("\n", fout);
84 fflush(fout);
85 goto restart;
86 }
87
057f943f
JF
88 read:
89 char *line(readline(prompt));
90 if (line == NULL)
91 break;
931b816a
JF
92
93 if (!extra) {
94 extra = true;
95 if (line[0] == '\\') {
1f8eae40
JF
96 std::string data(line + 1);
97 if (data == "bypass") {
98 bypass = !bypass;
99 fprintf(fout, "bypass == %s\n", bypass ? "true" : "false");
100 fflush(fout);
101 } else if (data == "debug") {
102 debug = !debug;
103 fprintf(fout, "debug == %s\n", debug ? "true" : "false");
104 fflush(fout);
105 }
d35a3b07 106 add_history(line);
931b816a
JF
107 goto restart;
108 }
109 }
110
057f943f
JF
111 lines.push_back(line);
112 command += line;
113 free(line);
114
1f8eae40
JF
115 std::string code;
116
117 if (bypass)
118 code = command;
119 else {
120 CYDriver driver("");
121 cy::parser parser(driver);
122
123 driver.data_ = command.c_str();
124 driver.size_ = command.size();
125
126 if (parser.parse() != 0 || !driver.errors_.empty()) {
127 for (CYDriver::Errors::const_iterator i(driver.errors_.begin()); i != driver.errors_.end(); ++i) {
128 cy::position begin(i->location_.begin);
129 if (begin.line != lines.size() || begin.column - 1 != lines.back().size()) {
130 std::cerr << i->message_ << std::endl;
131 add_history(command.c_str());
132 goto restart;
133 }
134 }
057f943f 135
1f8eae40 136 driver.errors_.clear();
057f943f 137
1f8eae40
JF
138 command += '\n';
139 prompt = "cy> ";
140 goto read;
057f943f
JF
141 }
142
1f8eae40
JF
143 if (driver.source_ == NULL)
144 goto restart;
057f943f 145
1f8eae40
JF
146 std::ostringstream str;
147 driver.source_->Show(str);
148 code = str.str();
057f943f
JF
149 }
150
057f943f
JF
151 add_history(command.c_str());
152
1f8eae40
JF
153 if (debug)
154 std::cout << code << std::endl;
057f943f 155
b09da87b
JF
156 Run(code.c_str(), fout);
157 }
057f943f 158
b09da87b
JF
159 fputs("\n", fout);
160 fflush(fout);
161}
057f943f 162
b09da87b
JF
163void *Map(const char *path, size_t *psize) {
164 int fd;
165 _syscall(fd = open(path, O_RDONLY));
057f943f 166
b09da87b
JF
167 struct stat stat;
168 _syscall(fstat(fd, &stat));
169 size_t size(stat.st_size);
057f943f 170
b09da87b 171 *psize = size;
057f943f 172
b09da87b
JF
173 void *base;
174 _syscall(base = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0));
057f943f 175
b09da87b
JF
176 _syscall(close(fd));
177 return base;
178}
057f943f 179
b09da87b
JF
180int main(int argc, const char *argv[]) {
181 const char *script;
182
183 if (argc == 1)
184 script = NULL;
185 else {
186 CYSetArgs(argc - 1, argv + 1);
187 script = argv[1];
188 }
189
190 if (script == NULL || strcmp(script, "-") == 0)
191 Console();
192 else {
193 CYDriver driver(script);
194 cy::parser parser(driver);
195
196 size_t size;
197 char *start(reinterpret_cast<char *>(Map(script, &size)));
198 char *end(start + size);
199
200 if (size >= 2 && start[0] == '#' && start[1] == '!') {
201 start += 2;
202 while (start != end && *start++ != '\n');
057f943f
JF
203 }
204
b09da87b
JF
205 driver.data_ = start;
206 driver.size_ = end - start;
62ca2b82 207
b09da87b
JF
208 if (parser.parse() != 0 || !driver.errors_.empty()) {
209 for (CYDriver::Errors::const_iterator i(driver.errors_.begin()); i != driver.errors_.end(); ++i)
210 std::cerr << i->location_.begin << ": " << i->message_ << std::endl;
211 } else if (driver.source_ != NULL) {
212 std::ostringstream str;
213 driver.source_->Show(str);
214 std::string code(str.str());
215 std::cout << code << std::endl;
216 Run(code.c_str(), stdout);
217 }
057f943f 218 }
62ca2b82 219
057f943f 220 return 0;
62ca2b82 221}