/* AST generator for the WEB IDL parser * * This file is part of nsgenjsbind. * Licensed under the MIT License, * http://www.opensource.org/licenses/mit-license.php * Copyright 2012 Vincent Sanders */ #include #include #include #include #include #include "webidl-ast.h" #include "options.h" extern int webidl_debug; extern int webidl__flex_debug; extern void webidl_restart(FILE*); extern int webidl_parse(struct webidl_node **webidl_ast); struct webidl_node * webidl_node_link(struct webidl_node *tgt, struct webidl_node *src) { if (tgt != NULL) { tgt->l = src; return tgt; } return src; } struct webidl_node *webidl_node_new(enum webidl_node_type type, struct webidl_node *l, void *r) { struct webidl_node *nn; nn = calloc(1, sizeof(struct webidl_node)); nn->type = type; nn->l = l; nn->r.text = r; return nn; } int webidl_node_for_each_type(struct webidl_node *node, enum webidl_node_type type, webidl_callback_t *cb, void *ctx) { int ret; if (node == NULL) { return -1; } if (node->l != NULL) { ret = webidl_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 genjsbind-ast.h */ struct webidl_node * webidl_node_find(struct webidl_node *node, struct webidl_node *prev, webidl_callback_t *cb, void *ctx) { struct webidl_node *ret; if (node == NULL) { return NULL; } if (node->l != prev) { ret = webidl_node_find(node->l, prev, cb, ctx); if (ret != NULL) { return ret; } } if (cb(node, ctx) != 0) { return node; } return NULL; } int webidl_cmp_node_type(struct webidl_node *node, void *ctx) { if (node->type == (enum webidl_node_type)ctx) return 1; return 0; } struct webidl_node * webidl_node_find_type_ident(struct webidl_node *root_node, enum webidl_node_type type, const char *ident) { struct webidl_node *node; struct webidl_node *ident_node; node = webidl_node_find(root_node, NULL, webidl_cmp_node_type, (void *)type); while (node != NULL) { ident_node = webidl_node_find(webidl_node_getnode(node), NULL, webidl_cmp_node_type, (void *)WEBIDL_NODE_TYPE_IDENT); if (ident_node != NULL) { if (strcmp(ident_node->r.text, ident) == 0) break; } node = webidl_node_find(root_node, node, webidl_cmp_node_type, (void *)type); } return node; } char *webidl_node_gettext(struct webidl_node *node) { switch(node->type) { case WEBIDL_NODE_TYPE_IDENT: case WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE: return node->r.text; default: return NULL; } } struct webidl_node *webidl_node_getnode(struct webidl_node *node) { switch(node->type) { case WEBIDL_NODE_TYPE_ROOT: case WEBIDL_NODE_TYPE_INTERFACE: case WEBIDL_NODE_TYPE_INTERFACE_MEMBERS: case WEBIDL_NODE_TYPE_ATTRIBUTE: case WEBIDL_NODE_TYPE_OPERATION: return node->r.node; default: return NULL; } } static const char *webidl_node_type_to_str(enum webidl_node_type type) { switch(type) { case WEBIDL_NODE_TYPE_ROOT: return "root"; case WEBIDL_NODE_TYPE_IDENT: return "Ident"; case WEBIDL_NODE_TYPE_INTERFACE_INHERITANCE: return "Inherit"; case WEBIDL_NODE_TYPE_INTERFACE: return "Interface"; case WEBIDL_NODE_TYPE_INTERFACE_MEMBERS: return "Members"; case WEBIDL_NODE_TYPE_ATTRIBUTE: return "Attribute"; case WEBIDL_NODE_TYPE_OPERATION: return "Operation"; default: return "Unknown"; } } int webidl_ast_dump(struct webidl_node *node, int indent) { const char *SPACES=" "; char *txt; while (node != NULL) { printf("%.*s%s", indent, SPACES, webidl_node_type_to_str(node->type)); txt = webidl_node_gettext(node); if (txt == NULL) { printf("\n"); webidl_ast_dump(webidl_node_getnode(node), indent + 2); } else { printf(": \"%s\"\n", txt); } node = node->l; } return 0; } static FILE *idlopen(const char *filename) { FILE *idlfile; if (options->idlpath == NULL) { if (options->verbose) { printf("Opening IDL file %s\n", filename); } idlfile = fopen(filename, "r"); } else { char *fullname; int fulllen = strlen(options->idlpath) + strlen(filename) + 2; fullname = malloc(fulllen); snprintf(fullname, fulllen, "%s/%s", options->idlpath, filename); if (options->verbose) { printf("Opening IDL file %s\n", fullname); } idlfile = fopen(fullname, "r"); free(fullname); } return idlfile; } int webidl_parsefile(char *filename, struct webidl_node **webidl_ast) { FILE *idlfile; idlfile = idlopen(filename); if (!idlfile) { fprintf(stderr, "Error opening %s: %s\n", filename, strerror(errno)); return 2; } if (options->debug) { webidl_debug = 1; webidl__flex_debug = 1; } /* set flex to read from file */ webidl_restart(idlfile); /* parse the file */ return webidl_parse(webidl_ast); }