#include <pwd.h>
#include <apr_getopt.h>
+#include <apr_pools.h>
+#include <apr_strings.h>
#include <dlfcn.h>
else
passwd = getpwuid(getuid());
- const char *basedir(pool.sprintf("%s/.cycript", passwd->pw_dir));
- const char *histfile(pool.sprintf("%s/history", basedir));
+ const char *basedir(pool.strcat(passwd->pw_dir, "/.cycript", NULL));
+ const char *histfile(pool.strcat(basedir, "/history", NULL));
size_t histlines(0);
rl_initialize();
void InjectLibrary(pid_t pid);
int Main(int argc, char const * const argv[], char const * const envp[]) {
+ _aprcall(apr_initialize());
+
+ apr_pool_t *pool;
+ apr_pool_create(&pool, NULL);
+
bool tty(isatty(STDIN_FILENO));
bool compile(false);
CYOptions options;
pid_t pid(_not(pid_t));
#endif
- CYPool pool;
apr_getopt_t *state;
_aprcall(apr_getopt_init(&state, pool, argc, argv));
pid = strtoul(arg, &end, 0);
if (arg + size != end) {
// XXX: arg needs to be escaped in some horrendous way of doom
- const char *command(pool.sprintf("ps axc|sed -e '/^ *[0-9]/{s/^ *\\([0-9]*\\)\\( *[^ ]*\\)\\{3\\} *-*\\([^ ]*\\)/\\3 \\1/;/^%s /{s/^[^ ]* //;q;};};d'", arg));
+ const char *command(apr_pstrcat(pool, "ps axc|sed -e '/^ *[0-9]/{s/^ *\\([0-9]*\\)\\( *[^ ]*\\)\\{3\\} *-*\\([^ ]*\\)/\\3 \\1/;/^", arg, " /{s/^[^ ]* //;q;};};d'", NULL));
if (FILE *pids = popen(command, "r")) {
char value[32];
}
}
+ apr_pool_destroy(pool);
+
return 0;
}
} while (false)
#define A new($pool)
-#define Y apr_pstrmemdup($pool, yytext, yyleng)
+#define Y $pool.strmemdup(yytext, yyleng)
#define I(type, Type, value, highlight) do { \
yylval->type ## _ = A CY ## Type; \
CYPool pool_;
const char *message_;
+ CYPoolError(const CYPoolError &rhs);
+
CYPoolError(const char *format, ...);
CYPoolError(const char *format, va_list args);
#include <JavaScriptCore/JSBase.h>
#endif
+// XXX: does _assert really need this?
+#include <errno.h>
+
#include "Standard.hpp"
class CYPool;
internal->value_ = data;
else {
size_t size(typical->GetFFI()->size);
- void *copy((*internal->pool_)(size));
+ void *copy(internal->pool_->malloc<void>(size));
memcpy(copy, data, size);
internal->value_ = copy;
}
static JSValueRef $cyq(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
CYPool pool;
- const char *name(pool.sprintf("%s%"APR_SIZE_T_FMT"", CYPoolCString(pool, context, arguments[0]), Nonce_++));
+ const char *name(pool.strcat(CYPoolCString(pool, context, arguments[0]), pool.itoa(Nonce_++), NULL));
return CYCastJSValue(context, name);
}
const char *type(sig::Unparse(pool, internal->type_));
std::ostringstream str;
CYStringify(str, type, strlen(type));
- char *cyon(apr_pstrcat(pool, "new Type(", str.str().c_str(), ")", NULL));
+ char *cyon(pool.strcat("new Type(", str.str().c_str(), ")", NULL));
return CYCastJSValue(context, CYJSString(cyon));
} CYCatch(NULL) }
initialized_ = true;
else return;
- CYInitializeStatic();
-
JSObjectMakeArray$ = reinterpret_cast<JSObjectRef (*)(JSContextRef, size_t, const JSValueRef[], JSValueRef *)>(dlsym(RTLD_DEFAULT, "JSObjectMakeArray"));
JSClassDefinition definition;
va_list args;
va_start(args, format);
- const char *message(pool.vsprintf(format, args));
+ // XXX: there might be a beter way to think about this
+ const char *message(pool.vsprintf(64, format, args));
va_end(args);
value_ = CYCastJSError(context, message);
}
};
-static void * APR_THREAD_FUNC OnClient(void *data) {
+static void *OnClient(void *data) {
CYClient *client(reinterpret_cast<CYClient *>(data));
client->Handle();
delete client;
#endif
CYUTF8String CYPoolUTF8String(CYPool &pool, CYUTF16String utf16) {
- _assert(pool != NULL);
-
const char *in(reinterpret_cast<const char *>(utf16.data));
iconv_t conversion(_syscall(iconv_open("UTF-8", UCS_2_INTERNAL)));
}
CYUTF16String CYPoolUTF16String(CYPool &pool, CYUTF8String utf8) {
- _assert(pool != NULL);
-
const char *in(utf8.data);
iconv_t conversion(_syscall(iconv_open(UCS_2_INTERNAL, "UTF-8")));
*size = utf16.size;
}
-static bool initialized_;
-
-void CYInitializeStatic() {
- if (!initialized_)
- initialized_ = true;
- else return;
-
- _aprcall(apr_initialize());
-}
-
CYPool &CYGetGlobalPool() {
- CYInitializeStatic();
static CYPool pool;
return pool;
}
return pool.strdup(message_);
}
+CYPoolError::CYPoolError(const CYPoolError &rhs) :
+ message_(pool_.strdup(rhs.message_))
+{
+}
+
CYPoolError::CYPoolError(const char *format, ...) {
va_list args;
va_start(args, format);
- message_ = pool_.vsprintf(format, args);
+ // XXX: there might be a beter way to think about this
+ message_ = pool_.vsprintf(64, format, args);
va_end(args);
}
CYPoolError::CYPoolError(const char *format, va_list args) {
- message_ = pool_.vsprintf(format, args);
+ // XXX: there might be a beter way to think about this
+ message_ = pool_.vsprintf(64, format, args);
}
depth = (depth + sizeof(uintptr_t) + 1) / sizeof(uintptr_t) * sizeof(uintptr_t);
CYPool pool;
- uint8_t *local(reinterpret_cast<uint8_t *>(pool(depth)));
+ uint8_t *local(pool.malloc<uint8_t>(depth));
Baton *baton(reinterpret_cast<Baton *>(local));
baton->__pthread_set_self = &__pthread_set_self;
lib_LTLIBRARIES = libcycript.la
libcycript_la_SOURCES = Highlight.cpp Network.cpp Output.cpp Parser.cpp Replace.cpp
libcycript_la_LDFLAGS = -no-undefined -avoid-version -export-dynamic
-libcycript_la_LIBADD = $(LTLIBAPR) $(LTLIBFFI) $(LTLIBICONV) -ldl
+libcycript_la_LIBADD = $(LTLIBFFI) $(LTLIBICONV) -ldl
libcycript_la_SOURCES += Cycript.tab.cc
libcycript_la_SOURCES += lex.cy.cpp
LTLIBRARIES = $(lib_LTLIBRARIES)
am__DEPENDENCIES_1 =
libcycript_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+ $(am__DEPENDENCIES_1)
am__libcycript_la_SOURCES_DIST = Highlight.cpp Network.cpp Output.cpp \
Parser.cpp Replace.cpp Cycript.tab.cc lex.cy.cpp \
sig/ffi_type.cpp sig/parse.cpp sig/copy.cpp Bridge.cpp \
Parser.cpp Replace.cpp Cycript.tab.cc lex.cy.cpp \
$(am__append_1) $(am__append_6) $(am__append_7)
libcycript_la_LDFLAGS = -no-undefined -avoid-version -export-dynamic
-libcycript_la_LIBADD = $(LTLIBAPR) $(LTLIBFFI) $(LTLIBICONV) -ldl
+libcycript_la_LIBADD = $(LTLIBFFI) $(LTLIBICONV) -ldl
cycript_SOURCES = Console.cpp Display.cpp $(am__append_8)
cycript_LDADD = libcycript.la $(LTLIBAPR) $(LTLIBREADLINE) $(LTLIBTERMCAP) -ldl
ldid = true
/* }}} */
/* Objective-C Strings {{{ */
const char *CYPoolCString(CYPool &pool, JSContextRef context, NSString *value) {
- if (pool == NULL)
- return [value UTF8String];
- else {
- size_t size([value maximumLengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1);
- char *string(new(pool) char[size]);
- if (![value getCString:string maxLength:size encoding:NSUTF8StringEncoding])
- throw CYJSError(context, "[NSString getCString:maxLength:encoding:] == NO");
- return string;
- }
+ size_t size([value maximumLengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1);
+ char *string(new(pool) char[size]);
+ if (![value getCString:string maxLength:size encoding:NSUTF8StringEncoding])
+ throw CYJSError(context, "[NSString getCString:maxLength:encoding:] == NO");
+ return string;
}
JSStringRef CYCopyJSString(JSContextRef context, NSString *value) {
#define CYCRIPT_POOLING_HPP
#include <cstdarg>
+#include <cstdio>
#include <cstdlib>
+#include <cstring>
-#include <apr_pools.h>
-#include <apr_strings.h>
+#include <algorithm>
+
+#include <stdint.h>
#include "Exception.hpp"
#include "Local.hpp"
#include "Standard.hpp"
+class CYPool;
+_finline void *operator new(size_t size, CYPool &pool);
+_finline void *operator new [](size_t size, CYPool &pool);
+
class CYPool {
private:
- apr_pool_t *pool_;
+ uint8_t *data_;
+ size_t size_;
struct Cleaner {
Cleaner *next_;
}
} *cleaner_;
+ static _finline size_t align(size_t size) {
+ // XXX: alignment is more complex than this
+ return (size + 7) & ~0x3;
+ }
+
+ CYPool(const CYPool &);
+
public:
CYPool() :
+ data_(NULL),
+ size_(0),
cleaner_(NULL)
{
- _aprcall(apr_pool_create(&pool_, NULL));
}
~CYPool() {
- for (Cleaner *cleaner(cleaner_); cleaner_ != NULL; cleaner_ = cleaner_->next_)
+ for (Cleaner *cleaner(cleaner_); cleaner != NULL; ) {
+ Cleaner *next(cleaner->next_);
(*cleaner->code_)(cleaner->data_);
- apr_pool_destroy(pool_);
+ cleaner = next;
+ }
}
- void Clear() {
- apr_pool_clear(pool_);
- }
+ template <typename Type_>
+ Type_ *malloc(size_t size) {
+ size = align(size);
+
+ if (size > size_) {
+ // XXX: is this an optimal malloc size?
+ size_ = std::max<size_t>(size, size + align(sizeof(Cleaner)));
+ data_ = reinterpret_cast<uint8_t *>(::malloc(size_));
+ atexit(free, data_);
+ _assert(size <= size_);
+ }
- operator apr_pool_t *() const {
- return pool_;
+ void *data(data_);
+ data_ += size;
+ size_ -= size;
+ return reinterpret_cast<Type_ *>(data);
}
- void *operator()(size_t size) const {
- return apr_palloc(pool_, size);
+ char *strdup(const char *data) {
+ return reinterpret_cast<char *>(memdup(data, strlen(data) + 1));
}
- char *strdup(const char *data) const {
- return apr_pstrdup(pool_, data);
+ void *memdup(const void *data, size_t size) {
+ void *copy(malloc<void>(size));
+ memcpy(copy, data, size);
+ return copy;
}
char *strndup(const char *data, size_t size) const {
- return apr_pstrndup(pool_, data, size);
+ return strmemdup(data, strnlen(data, size));
}
char *strmemdup(const char *data, size_t size) const {
- return apr_pstrmemdup(pool_, data, size);
+ char *copy(new char[size + 1]);
+ memcpy(copy, data, size);
+ copy[size] = '\0';
+ return copy;
}
- char *sprintf(const char *format, ...) const {
+ // XXX: this could be made much more efficient
+ __attribute__((__sentinel__))
+ char *strcat(const char *data, ...) {
+ size_t size(strlen(data)); {
+ va_list args;
+ va_start(args, data);
+
+ while (const char *arg = va_arg(args, const char *))
+ size += strlen(arg);
+
+ va_end(args);
+ }
+
+ char *copy(malloc<char>(size + 1)); {
+ va_list args;
+ va_start(args, data);
+
+ size_t offset(strlen(data));
+ memcpy(copy, data, offset);
+
+ while (const char *arg = va_arg(args, const char *)) {
+ size_t size(strlen(arg));
+ memcpy(copy + offset, arg, size);
+ offset += size;
+ }
+
+ va_end(args);
+ }
+
+ copy[size] = '\0';
+ return copy;
+ }
+
+ // XXX: most people using this might should use sprintf
+ char *itoa(long value) {
+ return sprintf(16, "%ld", value);
+ }
+
+ __attribute__((__format__(__printf__, 3, 4)))
+ char *sprintf(size_t size, const char *format, ...) {
va_list args;
va_start(args, format);
- char *data(vsprintf(format, args));
+ char *copy(vsprintf(size, format, args));
va_end(args);
- return data;
+ return copy;
}
- char *vsprintf(const char *format, va_list args) const {
- return apr_pvsprintf(pool_, format, args);
+ char *vsprintf(size_t size, const char *format, va_list args) {
+ va_list copy;
+ va_copy(copy, args);
+ char buffer[size];
+ int writ(vsnprintf(buffer, size, format, copy));
+ va_end(copy);
+ _assert(writ >= 0);
+
+ if (size_t(writ) >= size)
+ return vsprintf(writ + 1, format, args);
+ return strmemdup(buffer, writ);
}
void atexit(void (*code)(void *), void *data = NULL);
};
_finline void *operator new(size_t size, CYPool &pool) {
- return pool(size);
+ return pool.malloc<void>(size);
}
_finline void *operator new [](size_t size, CYPool &pool) {
- return pool(size);
+ return pool.malloc<void>(size);
}
_finline void CYPool::atexit(void (*code)(void *), void *data) {
}
static void *operator new(size_t size, CYPool &pool) {
- void *data(pool(size));
+ void *data(pool.malloc<void>(size));
reinterpret_cast<CYData *>(data)->pool_ = &pool;
return data;
}
}
pointer allocate(size_type size, const void *hint = 0) {
- return reinterpret_cast<pointer>((*pool_)(size));
+ return pool_->malloc<value_type>(size);
}
void deallocate(pointer data, size_type size) {
}
CYIdentifier *CYContext::Unique() {
- return $ CYIdentifier($pool.sprintf("$cy%u", unique_++));
+ return $ CYIdentifier($pool.strcat("$cy", $pool.itoa(unique_++), NULL));
}
CYStatement *CYContinue::Replace(CYContext &context) {
CYString *CYNumber::String(CYContext &context) {
// XXX: there is a precise algorithm for this
- return $S($pool.sprintf("%.17g", Value()));
+ return $S($pool.sprintf(24, "%.17g", Value()));
}
CYExpression *CYObject::Replace(CYContext &context) {
const char *name;
if (context.options_.verbose_)
- name = $pool.sprintf("$%"APR_SIZE_T_FMT"", offset);
+ name = $pool.strcat("$", $pool.itoa(offset), NULL);
else {
char id[8];
id[7] = '\0';
#include "Pooling.hpp"
#include "String.hpp"
-void CYInitializeStatic();
-
bool CYRecvAll_(int socket, uint8_t *data, size_t size);
bool CYSendAll_(int socket, const uint8_t *data, size_t size);
case array_P: {
// XXX: this is really lame
- ffi_type *aggregate(reinterpret_cast<ffi_type *>(pool(sizeof(ffi_type))));
+ ffi_type *aggregate(new(pool) ffi_type());
aggregate->size = 0;
aggregate->alignment = 0;
aggregate->type = FFI_TYPE_STRUCT;
ffi_type *element(ObjectiveC(pool, type->data.data.type));
size_t size(type->data.data.size);
- aggregate->elements = reinterpret_cast<ffi_type **>(pool((size + 1) * sizeof(ffi_type *)));
+ aggregate->elements = new(pool) ffi_type *[size + 1];
for (size_t i(0); i != size; ++i)
aggregate->elements[i] = element;
aggregate->elements[size] = NULL;
case void_P: return &ffi_type_void;
case struct_P: {
- ffi_type *aggregate(reinterpret_cast<ffi_type *>(pool(sizeof(ffi_type))));
+ ffi_type *aggregate(new(pool) ffi_type());
aggregate->size = 0;
aggregate->alignment = 0;
aggregate->type = FFI_TYPE_STRUCT;
- aggregate->elements = reinterpret_cast<ffi_type **>(pool((type->data.signature.count + 1) * sizeof(ffi_type *)));
+ aggregate->elements = new(pool) ffi_type *[type->data.signature.count + 1];
sig_ffi_types(pool, &ObjectiveC, &type->data.signature, aggregate->elements);
aggregate->elements[type->data.signature.count] = NULL;
size_t offset
) {
if (types == NULL)
- types = reinterpret_cast<ffi_type **>(pool((signature->count - 1) * sizeof(ffi_type *)));
+ types = new(pool) ffi_type *[signature->count - 1];
ffi_type *type = (*sig_ffi_type)(pool, signature->elements[0].type);
sig_ffi_types(pool, sig_ffi_type, signature, types, 1 + skip, offset);
ffi_status status = ffi_prep_cif(cif, FFI_DEFAULT_ABI, signature->count - 1 - skip + offset, type, types);
/* XXX: I really screwed up this time */
void *prealloc_(CYPool &pool, void *odata, size_t osize, size_t nsize) {
- void *ndata(pool(nsize));
+ void *ndata(pool.malloc<void>(nsize));
memcpy(ndata, odata, osize);
return ndata;
}
for (offset = 0; offset != signature->count; ++offset) {
const char *type = Unparse(pool, signature->elements[offset].type);
- value = apr_pstrcat(pool, value, type, NULL);
+ value = pool.strcat(value, type, NULL);
}
return value;
const char *Unparse_(CYPool &pool, struct Type *type) {
switch (type->primitive) {
case typename_P: return "#";
- case union_P: return pool.sprintf("(%s)", Unparse(pool, &type->data.signature));
+ case union_P: return pool.strcat("(", Unparse(pool, &type->data.signature), ")", NULL);
case string_P: return "*";
case selector_P: return ":";
case block_P: return "@?";
- case object_P: return type->name == NULL ? "@" : pool.sprintf("@\"%s\"", type->name);
+ case object_P: return type->name == NULL ? "@" : pool.strcat("@\"", type->name, "\"", NULL);
case boolean_P: return "B";
case uchar_P: return "C";
case uint_P: return "I";
case array_P: {
const char *value = Unparse(pool, type->data.data.type);
- return pool.sprintf("[%"APR_SIZE_T_FMT"%s]", type->data.data.size, value);
+ return pool.strcat("[", pool.itoa(type->data.data.size), value, "]", NULL);
} break;
- case pointer_P: return pool.sprintf("^%s", type->data.data.type == NULL ? "v" : Unparse(pool, type->data.data.type));
- case bit_P: return pool.sprintf("b%"APR_SIZE_T_FMT"", type->data.data.size);
+ case pointer_P: return pool.strcat("^", type->data.data.type == NULL ? "v" : Unparse(pool, type->data.data.type), NULL);
+ case bit_P: return pool.strcat("b", pool.itoa(type->data.data.size), NULL);
case char_P: return "c";
case double_P: return "d";
case float_P: return "f";
case longlong_P: return "q";
case short_P: return "s";
case void_P: return "v";
- case struct_P: return pool.sprintf("{%s=%s}", type->name == NULL ? "?" : type->name, Unparse(pool, &type->data.signature));
+ case struct_P: return pool.strcat("{", type->name == NULL ? "?" : type->name, "=", Unparse(pool, &type->data.signature), "}", NULL);
}
_assert(false);
#define iovec_(base, size) \
(struct iovec) {const_cast<char *>(base), size}
- struct iovec parts[8];
- memset(parts, 0, sizeof(parts));
+ size_t size(strlen(base));
+ char buffer[7 + size];
+ size_t offset(0);
if ((type->flags & JOC_TYPE_INOUT) != 0)
- parts[0] = iovec_("N", 1);
+ buffer[offset++] = 'N';
if ((type->flags & JOC_TYPE_IN) != 0)
- parts[1] = iovec_("n", 1);
+ buffer[offset++] = 'n';
if ((type->flags & JOC_TYPE_BYCOPY) != 0)
- parts[2] = iovec_("O", 1);
+ buffer[offset++] = 'O';
if ((type->flags & JOC_TYPE_OUT) != 0)
- parts[3] = iovec_("o", 1);
+ buffer[offset++] = 'o';
if ((type->flags & JOC_TYPE_BYREF) != 0)
- parts[4] = iovec_("R", 1);
+ buffer[offset++] = 'R';
if ((type->flags & JOC_TYPE_CONST) != 0)
- parts[5] = iovec_("r", 1);
+ buffer[offset++] = 'r';
if ((type->flags & JOC_TYPE_ONEWAY) != 0)
- parts[6] = iovec_("V", 1);
+ buffer[offset++] = 'V';
- parts[7] = iovec_(base, strlen(base));
- return apr_pstrcatv(pool, parts, 8, NULL);
+ memcpy(buffer + offset, base, size);
+ return pool.strmemdup(buffer, offset + size);
}
}