]> git.saurik.com Git - cycript.git/blame - Handler.mm
Support full compilation on Mac OS X with clang++.
[cycript.git] / Handler.mm
CommitLineData
b3378a02 1/* Cycript - Optimizing JavaScript Compiler/Runtime
c15969fd 2 * Copyright (C) 2009-2013 Jay Freeman (saurik)
b24eb750
JF
3*/
4
c15969fd 5/* GNU General Public License, Version 3 {{{ */
b24eb750 6/*
c15969fd
JF
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.
b24eb750 11 *
c15969fd
JF
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.
b24eb750 16 *
c15969fd 17 * You should have received a copy of the GNU General Public License
b3378a02
JF
18 * along with Cycript. If not, see <http://www.gnu.org/licenses/>.
19**/
b24eb750
JF
20/* }}} */
21
b24eb750 22#include "cycript.hpp"
09eee478 23#include "JavaScript.hpp"
b24eb750
JF
24
25#include "Pooling.hpp"
26#include "Parser.hpp"
27
28#include "Cycript.tab.hh"
29
30#include <Foundation/Foundation.h>
31#include <apr_thread_proc.h>
32#include <unistd.h>
33#include <sstream>
34
bb1c419c
JF
35#include <sys/types.h>
36#include <sys/socket.h>
37#include <netinet/in.h>
38#include <sys/un.h>
39
b24eb750
JF
40struct CYExecute_ {
41 apr_pool_t *pool_;
42 const char * volatile data_;
43};
44
45// XXX: this is "tre lame"
46@interface CYClient_ : NSObject {
47}
48
49- (void) execute:(NSValue *)value;
50
51@end
52
53@implementation CYClient_
54
55- (void) execute:(NSValue *)value {
56 CYExecute_ *execute(reinterpret_cast<CYExecute_ *>([value pointerValue]));
57 const char *data(execute->data_);
58 execute->data_ = NULL;
0ced2e47 59 execute->data_ = CYExecute(execute->pool_, CYUTF8String(data));
b24eb750
JF
60}
61
62@end
63
64struct CYClient :
65 CYData
66{
67 int socket_;
68 apr_thread_t *thread_;
69
70 CYClient(int socket) :
71 socket_(socket)
72 {
73 }
74
75 ~CYClient() {
76 _syscall(close(socket_));
77 }
78
37954781 79 void Handle() {
d3760804
JF
80 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
81
82 CYClient_ *client = [[[CYClient_ alloc] init] autorelease];
b24eb750 83
bb1c419c
JF
84 bool dispatch;
85 if (CFStringRef mode = CFRunLoopCopyCurrentMode(CFRunLoopGetMain())) {
86 dispatch = true;
87 CFRelease(mode);
88 } else
89 dispatch = false;
90
b24eb750
JF
91 for (;;) {
92 size_t size;
93 if (!CYRecvAll(socket_, &size, sizeof(size)))
94 return;
95
97f6a005 96 CYLocalPool pool;
b24eb750
JF
97 char *data(new(pool) char[size + 1]);
98 if (!CYRecvAll(socket_, data, size))
99 return;
100 data[size] = '\0';
101
d3b63265
JF
102 CYStream stream(data, data + size);
103 CYDriver driver(stream);
b24eb750 104
d3b63265 105 cy::parser parser(driver);
b24eb750
JF
106
107 const char *json;
108 if (parser.parse() != 0 || !driver.errors_.empty()) {
109 json = NULL;
110 size = _not(size_t);
111 } else {
bb1c419c
JF
112 NSAutoreleasePool *ar = [[NSAutoreleasePool alloc] init];
113
69688ca1 114 CYOptions options;
97f6a005 115 CYContext context(options);
b24eb750
JF
116 driver.program_->Replace(context);
117 std::ostringstream str;
69688ca1 118 CYOutput out(str, options);
b24eb750
JF
119 out << *driver.program_;
120 std::string code(str.str());
121 CYExecute_ execute = {pool, code.c_str()};
bb1c419c
JF
122 NSValue *value([NSValue valueWithPointer:&execute]);
123 if (dispatch)
124 [client performSelectorOnMainThread:@selector(execute:) withObject:value waitUntilDone:YES];
125 else
126 [client execute:value];
b24eb750
JF
127 json = execute.data_;
128 size = json == NULL ? _not(size_t) : strlen(json);
bb1c419c
JF
129
130 [ar release];
b24eb750
JF
131 }
132
133 if (!CYSendAll(socket_, &size, sizeof(size)))
134 return;
135 if (json != NULL)
136 if (!CYSendAll(socket_, json, size))
137 return;
138 }
37954781 139
d3760804 140 [pool release];
b24eb750
JF
141 }
142};
143
144static void * APR_THREAD_FUNC OnClient(apr_thread_t *thread, void *data) {
145 CYClient *client(reinterpret_cast<CYClient *>(data));
146 client->Handle();
147 delete client;
148 return NULL;
149}
150
151extern "C" void CYHandleClient(apr_pool_t *pool, int socket) {
152 CYClient *client(new(pool) CYClient(socket));
153 apr_threadattr_t *attr;
154 _aprcall(apr_threadattr_create(&attr, client->pool_));
155 _aprcall(apr_thread_create(&client->thread_, attr, &OnClient, client, client->pool_));
156}
994434e5
JF
157
158extern "C" void CYHandleServer(pid_t pid) {
09eee478 159 CYInitializeDynamic();
994434e5
JF
160
161 int socket(_syscall(::socket(PF_UNIX, SOCK_STREAM, 0))); try {
162 struct sockaddr_un address;
163 memset(&address, 0, sizeof(address));
164 address.sun_family = AF_UNIX;
165 sprintf(address.sun_path, "/tmp/.s.cy.%u", pid);
166
167 _syscall(connect(socket, reinterpret_cast<sockaddr *>(&address), SUN_LEN(&address)));
168
169 apr_pool_t *pool;
170 apr_pool_create(&pool, NULL);
171
172 CYHandleClient(pool, socket);
173 } catch (const CYException &error) {
174 CYPool pool;
175 fprintf(stderr, "%s\n", error.PoolCString(pool));
176 }
177}