summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2016-01-26 00:33:03 -0800
committerOri Bernstein <ori@eigenstate.org>2016-01-26 00:33:03 -0800
commit26d24c9377f6b91a2278ca209d4619053806fa61 (patch)
tree47608e48b19ad565e74fb001414efa20c5d3275b
parent22a5bf9a39ed9c5fb2feb5153148416f24267158 (diff)
downloadmcbind-26d24c9377f6b91a2278ca209d4619053806fa61.tar.gz
Parse package definitions.
-rw-r--r--Makefile1
-rw-r--r--cparse.c9
-rw-r--r--main.c32
-rw-r--r--mcbind.h7
-rw-r--r--pkgdef.c167
5 files changed, 196 insertions, 20 deletions
diff --git a/Makefile b/Makefile
index 756bfee..e40b00e 100644
--- a/Makefile
+++ b/Makefile
@@ -6,6 +6,7 @@ OBJ = \
cgen.o \
myrgen.o \
optctx.o \
+ pkgdef.o \
types.o \
util.o \
diff --git a/cparse.c b/cparse.c
index abc9a41..8251232 100644
--- a/cparse.c
+++ b/cparse.c
@@ -51,10 +51,11 @@ Dcl *mkdcl(char *cname, Type *type, int isconst)
return dcl;
}
-void initargs(char ***args, size_t *nargs, char *f)
+void initargs(char ***args, size_t *nargs, Pkg *pkg)
{
*args = NULL;
*nargs = 0;
+ size_t i;
lappend(args, nargs, "/usr/lib/gcc/x86_64-linux-gnu/5/include");
lappend(args, nargs, "-I/usr/local/include");
@@ -63,7 +64,8 @@ void initargs(char ***args, size_t *nargs, char *f)
lappend(args, nargs, "-I/usr/lib/gcc/x86_64-linux-gnu");
lappend(args, nargs, "-I/usr/include");
lappend(args, nargs, "-I.");
- lappend(args, nargs, f);
+ for (i = 0; i < pkg->nhdr; i++)
+ lappend(args, nargs, pkg->hdr[i]);
}
char *striptype(const char *s)
@@ -400,8 +402,7 @@ void loadhdr(Pkg *pkg, char *f)
size_t nargs;
CXTranslationUnit tu;
- lappend(&pkg->hdr, &pkg->nhdr, f);
- initargs(&args, &nargs, f);
+ initargs(&args, &nargs, pkg);
CXIndex idx = clang_createIndex(0, 1);
tu = clang_parseTranslationUnit(
idx, 0,
diff --git a/main.c b/main.c
index 90363c5..fcbf082 100644
--- a/main.c
+++ b/main.c
@@ -21,36 +21,36 @@ static void usage(char *bin)
int main(int argc, char **argv)
{
+ size_t i, j, npkg;
+ Pkg **pkg;
+ Htab *tydefs;
Optctx ctx;
- char *out;
- size_t i;
- Pkg pkg;
optinit(&ctx, "hp:P:", argv, argc);
- pkg.tydefs = mkht(strhash, streq);
+ tydefs = mkht(strhash, streq);
while (!optdone(&ctx)) {
switch (optnext(&ctx)) {
- case 'h': usage(argv[0]); break;
- case 'p': pkg.pkg = ctx.optarg; break;
- case 'P': pkg.prefix = ctx.optarg; break;
+ case 'h':
+ usage(argv[0]);
+ break;
}
}
- if (!pkg.pkg) {
- fprintf(stderr, "package name is mandatory\n");
- exit(1);
- }
if (ctx.nargs == 0) {
- fprintf(stderr, "missing input headers\n");
+ fprintf(stderr, "missing input packages\n");
exit(1);
}
- out = pkg.pkg;
for (i = 0; i < ctx.nargs; i++) {
- loadhdr(&pkg, ctx.args[i]);
+ pkg = NULL;
+ npkg = 0;
+ parsepkg(&pkg, &npkg, tydefs, ctx.args[i]);
+ for (j = 0; j < npkg; j++)
+ loadhdr(pkg[j], ctx.args[i]);
+ myrgen(pkg[npkg - 1], pkg[npkg - 1]->pkg);
+ gluegen(pkg[npkg - 1], pkg[npkg - 1]->pkg);
+ free(pkg);
}
- myrgen(&pkg, out);
- gluegen(&pkg, out);
return 0;
}
diff --git a/mcbind.h b/mcbind.h
index c1adfa7..3a8bd20 100644
--- a/mcbind.h
+++ b/mcbind.h
@@ -69,6 +69,12 @@ struct Pkg {
char *prefix; /* the prefix to remove from C funcs */
char **hdr; /* the C headers the glue needs to include */
size_t nhdr; /* the count of headers to include */
+ char **dep; /* the C headers the glue needs to include */
+ size_t ndep; /* the count of headers to include */
+ char **cflags; /* the C headers the glue needs to include */
+ size_t ncflags; /* the count of headers to include */
+ char **ldflags; /* the C headers the glue needs to include */
+ size_t nldflags; /* the count of headers to include */
FILE *rejfile; /* the rejected functions that need manual binding */
Htab *tydefs; /* the type definitions */
Dcl **dcl; /* the C declarations */
@@ -77,6 +83,7 @@ struct Pkg {
};
void loadhdr(Pkg *pkg, char *f);
+void parsepkg(Pkg ***pkgs, size_t *npkgs, Htab *tydefs, char *path);
/* type */
Type *mktype(Ty ty);
diff --git a/pkgdef.c b/pkgdef.c
new file mode 100644
index 0000000..e6c42c1
--- /dev/null
+++ b/pkgdef.c
@@ -0,0 +1,167 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <clang-c/Index.h>
+
+#include "util.h"
+#include "mcbind.h"
+#include "optctx.h"
+
+static void failparse(int line, char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ exit(1);
+}
+
+static char *tok(int line, char **buf)
+{
+ char *s, *e;
+
+ s = *buf;
+ /* skip spaces and comments */
+ while(isspace(*s))
+ s++;
+ if (*s == '#')
+ *s = '\0';
+
+ e = s;
+ /* quoted strings */
+ if (s[0] == '"') {
+ s++;
+ e++;
+ while (*e && *e != '"') {
+ if (*e == '\\')
+ e++;
+ e++;
+ }
+ if (*e != '"')
+ failparse(line, "expected closing '\"'\n");
+ /* unquoted */
+ } else {
+ while (*e && !isspace(*e) && *e != '#')
+ e++;
+ }
+ if (*e != '\0') {
+ *e = '\0';
+ e++;
+ }
+ *buf = e;
+ if (s == e)
+ return NULL;
+ return s;
+}
+
+static void expectempty(int line, char *buf)
+{
+ char *p;
+
+ p = buf;
+ while (isspace(*p))
+ p++;
+ if (*p && *p != '#')
+ failparse(line, "trailing junk near '%s(%d)'\n", buf, buf[0]);
+}
+
+static void checksym(int line, char *nam)
+{
+ char *p;
+
+ if (!isalpha(*nam) && nam[0] != '_')
+ failparse(line, "invalid characters in package name '%s'\n", nam);
+ for (p = nam; *p; p++)
+ if (!isalnum(*p) && nam[0] != '_')
+ failparse(line, "invalid characters in package name '%s'\n", nam);
+}
+
+static void oncename(Pkg *pkg, int line, char **dst, char *type, char **buf)
+{
+ char *nam;
+
+ if (*dst)
+ failparse(line, "double specification of %s name %s\n", type, *dst);
+ nam = tok(line, buf);
+ if (!nam || strlen(nam) == 0)
+ failparse(line, "invalid or missing %s name %s\n", type, nam);
+ checksym(line, nam);
+ expectempty(line, *buf);
+ pkg->pkg = strdup(nam);
+}
+
+static void incpath(Pkg *pkg, int line, char ***dst, size_t *ndst, char **buf)
+{
+ char *w;
+
+ w = tok(line, buf);
+ if (!w || strlen(w) == 0)
+ failparse(line, "invalid or missing include\n");
+ lappend(dst, ndst, strdup(w));
+}
+
+static void flags(Pkg *pkg, int line, char ***flags, size_t *nflags, char **buf)
+{
+ char *w;
+
+ while ((w = tok(line, buf)) != NULL)
+ lappend(&flags, nflags, strdup(w));
+}
+
+void parsepkg(Pkg ***pkgs, size_t *npkgs, Htab *tydefs, char *path)
+{
+ char buf[2048];
+ Pkg *pkg;
+ FILE *f;
+ char *w, *p;
+ int line;
+ size_t i;
+
+ f = fopen(path, "r");
+ if (!f)
+ fprintf(stderr, "unable to open %s\n", path);
+ line = 0;
+ pkg = zalloc(sizeof(Pkg));
+ pkg->tydefs = tydefs;
+ while (fgets(buf, sizeof buf, f)) {
+ line++;
+ p = buf;
+ w = tok(line, &p);
+ if (!w || strlen(w) == 0) {
+ } else if (strcmp(w, "pkg") == 0) {
+ oncename(pkg, line, &pkg->pkg, "package", &p);
+ } else if (strcmp(w, "prefix") == 0) {
+ oncename(pkg, line, &pkg->prefix, "prefix", &p);
+ } else if (strcmp(w, "header") == 0) {
+ incpath(pkg, line, &pkg->hdr, &pkg->nhdr, &p);
+ } else if (strcmp(w, "use") == 0) {
+ incpath(pkg, line, &pkg->dep, &pkg->ndep, &p);
+ } else if (strcmp(w, "cflags") == 0) {
+ flags(pkg, line, &pkg->cflags, &pkg->ncflags, &p);
+ } else if (strcmp(w, "ldflags") == 0) {
+ flags(pkg, line, &pkg->ldflags, &pkg->nldflags, &p);
+ } else {
+ printf("unknown keyword %s\n", w);
+ exit(1);
+ }
+ }
+ if (!pkg->pkg) {
+ printf("missing package name for %s\n", path);
+ exit(1);
+ }
+ for (i = 0; i < pkg->ndep; i++)
+ parsepkg(pkgs, npkgs, tydefs, path);
+ lappend(pkgs, npkgs, pkg);
+}