summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2015-04-24 20:40:38 -0700
committerOri Bernstein <ori@eigenstate.org>2015-04-24 20:40:38 -0700
commite755da348db4af9ee68510a6b8aea6e1db40ede3 (patch)
tree840520ad212b088909a7790edc056f2199071f67
downloadmcbind-e755da348db4af9ee68510a6b8aea6e1db40ede3.tar.gz
Stub in initial code.
-rw-r--r--asmgen.c0
-rwxr-xr-xconfigure72
-rw-r--r--cparse.c46
-rw-r--r--dclrepo.c0
-rw-r--r--main.c40
-rw-r--r--mcbind.h43
-rw-r--r--mk/c.mk122
-rw-r--r--myrgen.c0
-rw-r--r--optctx.c100
-rw-r--r--optctx.h21
-rw-r--r--util.c121
-rw-r--r--util.h22
12 files changed, 587 insertions, 0 deletions
diff --git a/asmgen.c b/asmgen.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asmgen.c
diff --git a/configure b/configure
new file mode 100755
index 0000000..03d334b
--- /dev/null
+++ b/configure
@@ -0,0 +1,72 @@
+#!/bin/bash
+
+prefix="/usr/local"
+
+for i in `seq 300`; do
+ echo "Lots of output to emulate automake... ok"
+ echo "Testing for things you'll never use... fail"
+ echo "Satisfying the fortran77 lobby... ok"
+ echo "Burning CPU time checking for the bloody obvious... ok"
+done
+echo "Automake emulated successfully"
+
+INST_ROOT='/usr/local'
+
+for arg in $*; do
+ shift 1
+ echo $*
+ case $arg in
+ "--redo" | "-r")
+ if [ -f ./configvar_cache ]; then
+ . ./configvar_cache
+ fi
+ ;;
+ --prefix=*)
+ prefix=`echo $arg | sed 's/^--prefix=//g'`
+ ;;
+ --clanglib=*)
+ clanglib=`echo $arg | sed 's/^--clanglib=//g'`
+ ;;
+ --clanginc=*)
+ clanginc=`echo $arg | sed 's/^--clanginc=//g'`
+ ;;
+ "--prefix" | "--clangpath"| "--help" | "-h")
+ echo "Usage:"
+ echo " --prefix=pfx : The prefix to install to"
+ echo " --clangdir=dir : The path to find clang in"
+ break;
+ ;;
+ *) echo "Unrecognized argument $arg";;
+ esac
+done
+
+OS=`uname`
+
+
+for version in "" -3.7 -3.6 -3.5 3.4; do
+ if [ ! -z "`which llvm-config$version`" ]; then
+ llc=llvm-config$version
+ break
+ fi
+done
+
+if [ -z "$clanglib" ]; then
+ clanglib=`$llc --libdir`
+fi
+if [ -z "$clanginc" ]; then
+ clanginc=`$llc --includedir`
+fi
+
+echo "export INST_ROOT=$prefix" > config.mk
+echo "export CFLAGS+=-I$clanginc" >> config.mk
+echo "export LDFLAGS+=-L$clanglib -lclang" >> config.mk
+
+echo "prefix=$prefix" > configvar_cache
+echo "clangdir=$clangdir" > configvar_cache
+cat << EOF
+ Building with:
+ prefix=$prefix
+ clanglib=$clanglib
+ clanglib=$clanginc
+EOF
+
diff --git a/cparse.c b/cparse.c
new file mode 100644
index 0000000..f04faf0
--- /dev/null
+++ b/cparse.c
@@ -0,0 +1,46 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <clang-c/Index.h>
+
+#include "util.h"
+#include "mcbind.h"
+
+void initargs(char ***args, size_t *nargs, char *f)
+{
+ *args = NULL;
+ *nargs = 0;
+
+ lappend(args, nargs, "-I/usr/include");
+ lappend(args, nargs, f);
+}
+
+enum CXChildVisitResult dumpdcls(CXCursor c, CXCursor pc, CXClientData d)
+{
+ switch (clang_getCursorKind(c)) {
+ case CXCursor_StructDecl:
+ printf("struct\n");
+ break;
+ default:
+ break;
+ }
+ return CXChildVisit_Continue;
+}
+
+void loadhdr(char *f)
+{
+ char **args;
+ size_t nargs;
+
+ initargs(&args, &nargs, f);
+ CXIndex idx = clang_createIndex(0, 1);
+ CXTranslationUnit tu = clang_parseTranslationUnit(
+ idx, 0,
+ (const char * const *) args, nargs,
+ 0, 0, CXTranslationUnit_None);
+ clang_visitChildren(clang_getTranslationUnitCursor(tu), dumpdcls, NULL);
+ clang_disposeTranslationUnit(tu);
+ clang_disposeIndex(idx);
+}
+
diff --git a/dclrepo.c b/dclrepo.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/dclrepo.c
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..750c67b
--- /dev/null
+++ b/main.c
@@ -0,0 +1,40 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <clang-c/Index.h>
+
+#include "mcbind.h"
+#include "optctx.h"
+
+char *opt_pkgname;
+char *opt_cprefix;
+
+static void usage(char *bin)
+{
+
+ printf("%s [-h] [-p pkg] [-P prefix]\n", bin);
+ printf("\t-h\tprint this help\n");
+ printf("\t-p pkg\tgenerate bindings in package 'pkg'\n");
+ printf("\t-P pfx\tstrip 'pfx' from C function names\n");
+ exit(0);
+}
+
+int main(int argc, char **argv)
+{
+ Optctx ctx;
+ size_t i;
+
+ optinit(&ctx, "hp:P:", argv, argc);
+ while (!optdone(&ctx)) {
+ switch (optnext(&ctx)) {
+ case 'h': usage(argv[0]); break;
+ case 'p': opt_pkgname = ctx.optarg; break;
+ case 'P': opt_cprefix = ctx.optarg; break;
+ }
+ }
+
+ for (i = 0; i < ctx.nargs; i++) {
+ loadhdr(ctx.args[i]);
+ }
+ return 0;
+}
+
diff --git a/mcbind.h b/mcbind.h
new file mode 100644
index 0000000..8deaf94
--- /dev/null
+++ b/mcbind.h
@@ -0,0 +1,43 @@
+typedef struct Type Type;
+typedef struct Dcl Dcl;
+extern char *opt_pkgname;
+extern char *opt_cprefix;
+
+/* C types */
+typedef enum {
+ Tyvoid,
+ Tybool,
+
+ Tychar,
+ Tyshort,
+ Tyint,
+ Tylong,
+ Tyvlong,
+ Tyuchar,
+ Tyushort,
+ Tyuint,
+ Tyulong,
+ Tyuvlong,
+ Tyfloat,
+ Tydouble,
+ Tystruct,
+ Tyunion,
+
+ Tyfunc,
+} Ty;
+
+struct Type {
+ Ty ty;
+ struct {
+ size_t nsub;
+ Type **sub;
+ char **subname;
+ };
+};
+
+struct Dcl {
+ char *name;
+ Type *type;
+};
+
+void loadhdr(char *f);
diff --git a/mk/c.mk b/mk/c.mk
new file mode 100644
index 0000000..696d0cb
--- /dev/null
+++ b/mk/c.mk
@@ -0,0 +1,122 @@
+.DEFAULT_GOAL=all
+_DEPSDIR = .deps
+_DEPS=$(addprefix $(_DEPSDIR)/, $(OBJ:.o=.d))
+
+_LIBSRCHPATHS=$(addprefix -L, $(dir $(DEPS)))
+_LIBINCPATHS=$(addprefix -I, $(dir $(DEPS)))
+_LIBPATHS=$(addprefix -l, $(patsubst lib%.a,%,$(notdir $(DEPS))))
+
+CFLAGS += -O0 -Wall -Werror -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -g
+CFLAGS += -MMD -MP -MF ${_DEPSDIR}/$(subst /,-,$*).d
+
+LIB ?= $(INSTLIB)
+BIN ?= $(INSTBIN)
+
+# disable implicit rules.
+.SUFFIXES:
+.PHONY: clean clean-gen clean-bin clean-obj clean-misc clean-backups
+.PHONY: all
+
+all: subdirs $(BIN) $(LIB) $(EXTRA)
+
+$(LIB): $(OBJ) $(EXTRADEP) $(DEPS)
+ $(AR) -rcs $@ $(OBJ)
+
+$(BIN): $(OBJ) $(EXTRADEP) $(DEPS)
+ $(CC) -o $@ $(OBJ) $(_LIBSRCHPATHS) $(_LIBPATHS) $(LDFLAGS)
+
+$(DEPS):
+ @cd $(dir $@) && $(MAKE)
+
+subdirs:
+ @for i in $(SUB); do (\
+ cd $$i && \
+ $(MAKE) || \
+ exit 1 \
+ ) || exit 1; done
+
+subdirs-clean:
+ @for i in $(SUB); do (\
+ cd $$i && \
+ $(MAKE) clean|| \
+ exit 1 \
+ ); done
+
+subdirs-install:
+ @for i in $(SUB); do (\
+ cd $$i && \
+ $(MAKE) install|| \
+ exit 1 \
+ ); done
+
+clean: subdirs-clean $(EXTRACLEAN)
+ rm -f ${BIN} ${OBJ} ${CLEAN} ${LIB}
+
+install: subdirs-install $(INSTBIN) $(INSTLIB) $(INSTHDR) $(INSTPKG) $(EXTRAINSTALL)
+ @for i in $(INSTBIN); do \
+ echo install $(abspath $$i $(DESTDIR)/$(INST_ROOT)/bin); \
+ mkdir -p $(abspath $(DESTDIR)/$(INST_ROOT)/bin); \
+ install $$i $(abspath $(DESTDIR)/$(INST_ROOT)/bin); \
+ done
+ @for i in $(INSTLIB); do \
+ echo install -m 644 $$i $(abspath $(DESTDIR)/$(INST_ROOT)/lib); \
+ mkdir -p $(abspath $(DESTDIR)/$(INST_ROOT)/lib); \
+ install -m 644 $$i $(abspath $(DESTDIR)/$(INST_ROOT)/lib); \
+ done
+ @for i in $(INSTHDR); do \
+ echo install $$i $(abspath $(DESTDIR)/$(INST_ROOT)/include); \
+ mkdir -p $(abspath $(DESTDIR)/$(INST_ROOT)/include); \
+ install $$i $(abspath $(DESTDIR)/$(INST_ROOT)/include); \
+ done
+ @for i in $(INSTPKG); do \
+ echo install $(abspath $$i $(DESTDIR)/$(INST_ROOT)/lib/pkgconfig); \
+ mkdir -p $(abspath $(DESTDIR)/$(INST_ROOT)/lib/pkgconfig); \
+ install $(abspath $$i $(DESTDIR)/$(INST_ROOT)/lib/pkgconfig); \
+ done
+ @for i in $(INSTMAN); do \
+ sect="$${i##*.}"; \
+ echo install -m 644 $$i $(abspath $(DESTDIR)/$(INST_ROOT)/share/man/man$${sect}); \
+ mkdir -p $(abspath $(DESTDIR)/$(INST_ROOT)/share/man/man$${sect}); \
+ install -m 644 $$i $(abspath $(DESTDIR)/$(INST_ROOT)/share/man/man$${sect}); \
+ done
+
+subdirs-uninstall:
+ @for i in $(SUB); do (\
+ cd $$i && \
+ $(MAKE) uninstall|| \
+ exit 1 \
+ ); done
+
+uninstall: subdirs-uninstall $(EXTRAUNINSTALL)
+ @for i in $(INSTBIN); do \
+ echo rm -f $(abspath $(DESTDIR)/$(INST_ROOT)/bin/$$i); \
+ rm -f $(abspath $(DESTDIR)/$(INST_ROOT)/bin/$$i); \
+ done
+ @for i in $(INSTLIB); do \
+ echo rm -f $(abspath $(DESTDIR)/$(INST_ROOT)/lib/$$i); \
+ rm -f $(abspath $(DESTDIR)/$(INST_ROOT)/lib/$$i); \
+ done
+ @for i in $(INSTHDR); do \
+ echo rm -f $(abspath $(DESTDIR)/$(INST_ROOT)/include/$$i); \
+ rm -f $(abspath $(DESTDIR)/$(INST_ROOT)/include/$$i); \
+ done
+ @for i in $(INSTPKG); do \
+ echo rm -f $(abspath $(DESTDIR)/$(INST_ROOT)/lib/pkgconfig/$$i); \
+ rm -f $(abspath $(DESTDIR)/$(INST_ROOT)/lib/pkgconfig/$$i); \
+ done
+ @for i in $(INSTMAN); do \
+ sect="$${i##*.}" \
+ echo rm -f $$i $(abspath $(DESTDIR)/$(INST_ROOT)/share/man/man$${sect}/$$i); \
+ rm -f $(abspath $(DESTDIR)/$(INST_ROOT)/share/man/man$${sect}/$$i); \
+ done
+
+%.o: %.c $(GENHDR) .deps
+ $(CC) -c $(CFLAGS) $(_LIBINCPATHS) $<
+
+.deps:
+ mkdir -p $(_DEPSDIR)
+
+config.mk: configure
+ ./configure --redo
+
+-include $(_DEPS)
diff --git a/myrgen.c b/myrgen.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/myrgen.c
diff --git a/optctx.c b/optctx.c
new file mode 100644
index 0000000..22c7201
--- /dev/null
+++ b/optctx.c
@@ -0,0 +1,100 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "optctx.h"
+#include "util.h"
+
+static int optinfo(Optctx *ctx, char arg, int *take, int *mand)
+{
+ char *s;
+
+ for (s = ctx->optstr; *s != '\0'; s++) {
+ if (*s == arg) {
+ s++;
+ if (*s == ':') {
+ *take = 1;
+ *mand = 1;
+ return 1;
+ } else if (*s == '?') {
+ *take = 1;
+ *mand = 0;
+ return 1;
+ } else {
+ *take = 0;
+ *mand = 0;
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+static int findnextopt(Optctx *ctx)
+{
+ size_t i;
+
+ for (i = ctx->argidx + 1; i < ctx->noptargs; i++) {
+ if (ctx->optargs[i][0] == '-')
+ goto foundopt;
+ else
+ lappend(&ctx->args, &ctx->nargs, ctx->optargs[i]);
+ }
+ ctx->finished = 1;
+ return 0;
+foundopt:
+ ctx->argidx = i;
+ ctx->curarg = ctx->optargs[i] + 1; /* skip initial '-' */
+ return 1;
+}
+
+void optinit(Optctx *ctx, char *optstr, char **optargs, size_t noptargs)
+{
+ ctx->args = NULL;
+ ctx->nargs = 0;
+
+ ctx->optstr = optstr;
+ ctx->optargs = optargs;
+ ctx->noptargs = noptargs;
+ ctx->optdone = 0;
+ ctx->finished = 0;
+ ctx->argidx = 0;
+ ctx->curarg = "";
+ findnextopt(ctx);
+}
+
+int optnext(Optctx *ctx)
+{
+ int take, mand;
+ int c;
+
+ c = *ctx->curarg;
+ ctx->curarg++;
+ if (!optinfo(ctx, c, &take, &mand)) {
+ printf("Unexpected argument %c\n", *ctx->curarg);
+ exit(1);
+ }
+
+ ctx->optarg = NULL;
+ if (take) {
+ if (*ctx->curarg) {
+ ctx->optarg = ctx->curarg;
+ ctx->curarg += strlen(ctx->optarg);
+ } else if (ctx->argidx < ctx->noptargs - 1) {
+ ctx->optarg = ctx->optargs[ctx->argidx + 1];
+ ctx->argidx++;
+ } else if (mand) {
+ fprintf(stderr, "expected argument for %c\n", *ctx->curarg);
+ }
+ findnextopt(ctx);
+ } else {
+ if (*ctx->curarg == '\0')
+ findnextopt(ctx);
+ }
+ return c;
+}
+
+int optdone(Optctx *ctx)
+{
+ return *ctx->curarg == '\0' && ctx->finished;
+}
diff --git a/optctx.h b/optctx.h
new file mode 100644
index 0000000..cf14b59
--- /dev/null
+++ b/optctx.h
@@ -0,0 +1,21 @@
+typedef struct Optctx Optctx;
+struct Optctx {
+ /* public exports */
+ char *optarg;
+ char **args;
+ size_t nargs;
+
+ /* internal state */
+ char *optstr;
+ char **optargs;
+ size_t noptargs;
+ size_t argidx;
+ int optdone; /* seen -- */
+ int finished;
+ char *curarg;
+};
+
+void optinit(Optctx *ctx, char *optstr, char **optargs, size_t noptargs);
+int optnext(Optctx *c);
+int optdone(Optctx *c);
+
diff --git a/util.c b/util.c
new file mode 100644
index 0000000..d7114f2
--- /dev/null
+++ b/util.c
@@ -0,0 +1,121 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <string.h>
+#include <assert.h>
+#include <stdarg.h>
+
+#include "util.h"
+
+/* errors */
+void die(char *msg, ...)
+{
+ va_list ap;
+
+ va_start(ap, msg);
+ vfprintf(stderr, msg, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+ abort();
+}
+
+void *zalloc(size_t sz)
+{
+ void *mem;
+
+ mem = calloc(1, sz);
+ if (!mem && sz)
+ die("Out of memory");
+ return mem;
+}
+
+
+void *xalloc(size_t sz)
+{
+ void *mem;
+
+ mem = malloc(sz);
+ if (!mem && sz)
+ die("Out of memory");
+ return mem;
+}
+
+void *zrealloc(void *mem, size_t oldsz, size_t sz)
+{
+ char *p;
+
+ p = xrealloc(mem, sz);
+ if (sz > oldsz)
+ memset(&p[oldsz], 0, sz - oldsz);
+ return p;
+}
+
+void *xrealloc(void *mem, size_t sz)
+{
+ mem = realloc(mem, sz);
+ if (!mem && sz)
+ die("Out of memory");
+ return mem;
+}
+
+/* lists */
+void lappend(void *l, size_t *len, void *n)
+{
+ void ***pl;
+
+ pl = l;
+ *pl = xrealloc(*pl, (*len + 1)*sizeof(void*));
+ (*pl)[*len] = n;
+ (*len)++;
+}
+
+void *lpop(void *l, size_t *len)
+{
+ void ***pl;
+ void *v;
+
+ pl = l;
+ (*len)--;
+ v = (*pl)[*len];
+ *pl = xrealloc(*pl, *len * sizeof(void*));
+ return v;
+}
+
+void linsert(void *p, size_t *len, size_t idx, void *v)
+{
+ void ***pl, **l;
+
+ pl = p;
+ *pl = xrealloc(*pl, (*len + 1)*sizeof(void*));
+ l = *pl;
+
+ memmove(&l[idx + 1], &l[idx], (*len - idx)*sizeof(void*));
+ l[idx] = v;
+ (*len)++;
+}
+
+void ldel(void *p, size_t *len, size_t idx)
+{
+ void ***pl, **l;
+
+ assert(p != NULL);
+ assert(idx < *len);
+ pl = p;
+ l = *pl;
+ memmove(&l[idx], &l[idx + 1], (*len - idx - 1)*sizeof(void*));
+ (*len)--;
+ *pl = xrealloc(l, *len * sizeof(void*));
+}
+
+
+void lfree(void *l, size_t *len)
+{
+ void ***pl;
+
+ assert(l != NULL);
+ pl = l;
+ free(*pl);
+ *pl = NULL;
+ *len = 0;
+}
+
diff --git a/util.h b/util.h
new file mode 100644
index 0000000..4d25181
--- /dev/null
+++ b/util.h
@@ -0,0 +1,22 @@
+#ifdef __GNUC__
+# define FATAL __attribute__((noreturn))
+#else
+# define FATAL
+#endif
+
+/* death */
+void die(char *msg, ...) FATAL;
+
+/* memory allocation */
+void *zalloc(size_t size);
+void *xalloc(size_t size);
+void *zrealloc(void *p, size_t oldsz, size_t size);
+void *xrealloc(void *p, size_t size);
+
+/* simple list management */
+void lappend(void *l, size_t *len, void *n); /* hack; nl is void* b/c void*** is incompatible with T*** */
+void linsert(void *l, size_t *len, size_t idx, void *n);
+void *lpop(void *l, size_t *len);
+void ldel(void *l, size_t *len, size_t idx);
+void lfree(void *l, size_t *len);
+