From b00346cd08b55d25e427cfabafbaa66e09a8444b Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Tue, 23 Oct 2012 17:43:09 +0100 Subject: The name of teh tool is nsgenbind correct this everywhere --- src/nsgenbind-ast.c | 363 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 363 insertions(+) create mode 100644 src/nsgenbind-ast.c (limited to 'src/nsgenbind-ast.c') diff --git a/src/nsgenbind-ast.c b/src/nsgenbind-ast.c new file mode 100644 index 0000000..646548b --- /dev/null +++ b/src/nsgenbind-ast.c @@ -0,0 +1,363 @@ +/* binding generator AST implementation for parser + * + * This file is part of nsgenbind. + * Licensed under the MIT License, + * http://www.opensource.org/licenses/mit-license.php + * Copyright 2012 Vincent Sanders + */ + +/** @todo this currently stuffs everything in one global tree, not very nice + */ + +#include +#include +#include +#include +#include + +#include "nsgenbind-ast.h" +#include "options.h" + +/* parser and lexer interface */ +extern int nsgenbind_debug; +extern int nsgenbind__flex_debug; +extern void nsgenbind_restart(FILE*); +extern int nsgenbind_parse(struct genbind_node **genbind_ast); + +/* terminal nodes have a value only */ +struct genbind_node { + enum genbind_node_type type; + struct genbind_node *l; + union { + void *value; + struct genbind_node *node; + char *text; + } r; +}; + + +char *genbind_strapp(char *a, char *b) +{ + char *fullstr; + int fulllen; + fulllen = strlen(a) + strlen(b) + 1; + fullstr = malloc(fulllen); + snprintf(fullstr, fulllen, "%s%s", a, b); + free(a); + free(b); + return fullstr; +} + +struct genbind_node *genbind_node_link(struct genbind_node *tgt, struct genbind_node *src) +{ + tgt->l = src; + return tgt; +} + + +struct genbind_node * +genbind_new_node(enum genbind_node_type type, struct genbind_node *l, void *r) +{ + struct genbind_node *nn; + nn = calloc(1, sizeof(struct genbind_node)); + nn->type = type; + nn->l = l; + nn->r.value = r; + return nn; +} + +int +genbind_node_for_each_type(struct genbind_node *node, + enum genbind_node_type type, + genbind_callback_t *cb, + void *ctx) +{ + int ret; + + if (node == NULL) { + return -1; + } + if (node->l != NULL) { + ret = genbind_node_for_each_type(node->l, type, cb, ctx); + if (ret != 0) { + return ret; + } + } + if (node->type == type) { + return cb(node, ctx); + } + + return 0; +} + + +/* exported interface defined in nsgenbind-ast.h */ +struct genbind_node * +genbind_node_find(struct genbind_node *node, + struct genbind_node *prev, + genbind_callback_t *cb, + void *ctx) +{ + struct genbind_node *ret; + + if (node == NULL) { + return NULL; + } + + if (node->l != prev) { + ret = genbind_node_find(node->l, prev, cb, ctx); + if (ret != NULL) { + return ret; + } + } + + if (cb(node, ctx) != 0) { + return node; + } + + return NULL; +} + +/* exported interface defined in nsgenbind-ast.h */ +struct genbind_node * +genbind_node_find_type(struct genbind_node *node, + struct genbind_node *prev, + enum genbind_node_type type) +{ + return genbind_node_find(node, + prev, + genbind_cmp_node_type, + (void *)type); +} + +struct genbind_node * +genbind_node_find_type_ident(struct genbind_node *node, + struct genbind_node *prev, + enum genbind_node_type type, + const char *ident) +{ + struct genbind_node *found_node; + struct genbind_node *ident_node; + + found_node = genbind_node_find(node, + prev, + genbind_cmp_node_type, + (void *)type); + + while (found_node != NULL) { + + ident_node = genbind_node_find(genbind_node_getnode(found_node), + NULL, + genbind_cmp_node_type, + (void *)GENBIND_NODE_TYPE_IDENT); + if (ident_node != NULL) { + if (strcmp(ident_node->r.text, ident) == 0) + break; + } + + /* look for next matching node */ + found_node = genbind_node_find(node, + found_node, + genbind_cmp_node_type, + (void *)type); + + } + return found_node; +} + +int genbind_cmp_node_type(struct genbind_node *node, void *ctx) +{ + if (node->type == (enum genbind_node_type)ctx) + return 1; + return 0; +} + +char *genbind_node_gettext(struct genbind_node *node) +{ + switch(node->type) { + case GENBIND_NODE_TYPE_WEBIDLFILE: + case GENBIND_NODE_TYPE_STRING: + case GENBIND_NODE_TYPE_PREAMBLE: + case GENBIND_NODE_TYPE_IDENT: + case GENBIND_NODE_TYPE_BINDING_TYPE: + case GENBIND_NODE_TYPE_BINDING_INTERFACE: + case GENBIND_NODE_TYPE_CBLOCK: + return node->r.text; + + default: + return NULL; + } +} + +struct genbind_node *genbind_node_getnode(struct genbind_node *node) +{ + switch(node->type) { + case GENBIND_NODE_TYPE_HDRCOMMENT: + case GENBIND_NODE_TYPE_BINDING: + case GENBIND_NODE_TYPE_BINDING_PRIVATE: + case GENBIND_NODE_TYPE_OPERATION: + return node->r.node; + + default: + return NULL; + } +} + +static const char *genbind_node_type_to_str(enum genbind_node_type type) +{ + switch(type) { + case GENBIND_NODE_TYPE_IDENT: + return "Ident"; + + case GENBIND_NODE_TYPE_ROOT: + return "Root"; + + case GENBIND_NODE_TYPE_WEBIDLFILE: + return "webidlfile"; + + case GENBIND_NODE_TYPE_HDRCOMMENT: + return "HdrComment"; + + case GENBIND_NODE_TYPE_STRING: + return "String"; + + case GENBIND_NODE_TYPE_PREAMBLE: + return "Preamble"; + + case GENBIND_NODE_TYPE_BINDING: + return "Binding"; + + case GENBIND_NODE_TYPE_BINDING_TYPE: + return "Type"; + + case GENBIND_NODE_TYPE_BINDING_PRIVATE: + return "Private"; + + case GENBIND_NODE_TYPE_BINDING_INTERFACE: + return "Interface"; + + case GENBIND_NODE_TYPE_OPERATION: + return "Operation"; + + case GENBIND_NODE_TYPE_CBLOCK: + return "CBlock"; + + default: + return "Unknown"; + } +} + +int genbind_ast_dump(struct genbind_node *node, int indent) +{ + const char *SPACES=" "; + char *txt; + + while (node != NULL) { + printf("%.*s%s", indent, SPACES, genbind_node_type_to_str(node->type)); + + txt = genbind_node_gettext(node); + if (txt == NULL) { + printf("\n"); + genbind_ast_dump(genbind_node_getnode(node), indent + 2); + } else { + printf(": \"%.*s\"\n", 75 - indent, txt); + } + node = node->l; + } + return 0; +} + +FILE *genbindopen(const char *filename) +{ + FILE *genfile; + char *fullname; + int fulllen; + static char *prevfilepath = NULL; + + /* try filename raw */ + genfile = fopen(filename, "r"); + if (genfile != NULL) { + if (options->verbose) { + printf("Opened Genbind file %s\n", filename); + } + if (prevfilepath == NULL) { + fullname = strrchr(filename, '/'); + if (fullname == NULL) { + fulllen = strlen(filename); + } else { + fulllen = fullname - filename; + } + prevfilepath = strndup(filename,fulllen); + } + return genfile; + } + + /* try based on previous filename */ + if (prevfilepath != NULL) { + fulllen = strlen(prevfilepath) + strlen(filename) + 2; + fullname = malloc(fulllen); + snprintf(fullname, fulllen, "%s/%s", prevfilepath, filename); + if (options->debug) { + printf("Attempting to open Genbind file %s\n", fullname); + } + genfile = fopen(fullname, "r"); + if (genfile != NULL) { + if (options->verbose) { + printf("Opened Genbind file %s\n", fullname); + } + free(fullname); + return genfile; + } + free(fullname); + } + + /* try on idl path */ + if (options->idlpath != NULL) { + fulllen = strlen(options->idlpath) + strlen(filename) + 2; + fullname = malloc(fulllen); + snprintf(fullname, fulllen, "%s/%s", options->idlpath, filename); + genfile = fopen(fullname, "r"); + if ((genfile != NULL) && options->verbose) { + printf("Opend Genbind file %s\n", fullname); + } + + free(fullname); + } + + return genfile; +} + +int genbind_parsefile(char *infilename, struct genbind_node **ast) +{ + FILE *infile; + + /* open input file */ + if ((infilename[0] == '-') && + (infilename[1] == 0)) { + if (options->verbose) { + printf("Using stdin for input\n"); + } + infile = stdin; + } else { + infile = genbindopen(infilename); + } + + if (!infile) { + fprintf(stderr, "Error opening %s: %s\n", + infilename, + strerror(errno)); + return 3; + } + + if (options->debug) { + nsgenbind_debug = 1; + nsgenbind__flex_debug = 1; + } + + /* set flex to read from file */ + nsgenbind_restart(infile); + + /* process binding */ + return nsgenbind_parse(ast); + +} -- cgit v1.2.3