summaryrefslogtreecommitdiff
path: root/src/interface-map.c
diff options
context:
space:
mode:
authorVincent Sanders <vince@kyllikki.org>2015-08-09 11:07:11 +0100
committerVincent Sanders <vince@kyllikki.org>2015-08-09 11:07:11 +0100
commita9e5295d8735ff4ffe10e63f48728380edf6d7a0 (patch)
tree2ab8872a172bc11ac1a4c2b62b13170d9363bb58 /src/interface-map.c
parente78ea8b28064181d9081e7ff0143830c4ec37d7f (diff)
downloadnsgenbind-a9e5295d8735ff4ffe10e63f48728380edf6d7a0.tar.gz
nsgenbind-a9e5295d8735ff4ffe10e63f48728380edf6d7a0.tar.bz2
Update the interface map to contain all operation arguments
This extends the interface map (the intermediate representation) to have information on every operations arguments including overloading and optional arguments. This is important to allow automated checking of passed parameters numbers and types in future.
Diffstat (limited to 'src/interface-map.c')
-rw-r--r--src/interface-map.c269
1 files changed, 219 insertions, 50 deletions
diff --git a/src/interface-map.c b/src/interface-map.c
index 29e9ec0..a5a672a 100644
--- a/src/interface-map.c
+++ b/src/interface-map.c
@@ -132,31 +132,149 @@ interface_topoligical_sort(struct interface_map_entry *srcinf, int infc)
return dstinf;
}
-static int
-count_operation_name(struct interface_map_operation_entry *operationv,
+static struct interface_map_operation_entry *
+find_operation_name(struct interface_map_operation_entry *operationv,
int operationc,
const char *name)
{
struct interface_map_operation_entry *cure;
int opc;
- int res = 0;
for (opc = 0; opc < operationc; opc++) {
cure = operationv + opc;
if (cure->name == name) {
/* check pointers for equivalence */
- res++;
+ return cure;
} else {
if ((cure->name != NULL) &&
(name != NULL) &&
(strcmp(cure->name, name) == 0)) {
- res++;
+ return cure;
}
}
}
- return res;
+ return NULL;
+}
+
+static int
+argument_map_new(struct webidl_node *arg_list_node,
+ int *argumentc_out,
+ struct interface_map_operation_argument_entry **argumentv_out)
+{
+ int argumentc;
+ struct webidl_node *argument;
+ struct interface_map_operation_argument_entry *argumentv;
+ struct interface_map_operation_argument_entry *cure;
+
+ argumentc = webidl_node_enumerate_type(
+ webidl_node_getnode(arg_list_node),
+ WEBIDL_NODE_TYPE_ARGUMENT);
+ if (argumentc == 0) {
+ *argumentc_out = 0;
+ *argumentv_out = NULL;
+ return 0;
+ }
+
+ argumentv = calloc(argumentc, sizeof(*argumentv));
+ cure = argumentv;
+
+ /* iterate each argument node within the list */
+ argument = webidl_node_find_type(webidl_node_getnode(arg_list_node),
+ NULL,
+ WEBIDL_NODE_TYPE_ARGUMENT);
+
+ while (argument != NULL) {
+
+ cure->name = webidl_node_gettext(
+ webidl_node_find_type(
+ webidl_node_getnode(argument),
+ NULL,
+ WEBIDL_NODE_TYPE_IDENT));
+
+ cure->node = argument;
+
+
+ cure->optionalc = webidl_node_enumerate_type(
+ webidl_node_getnode(argument),
+ WEBIDL_NODE_TYPE_OPTIONAL);
+
+ cure->elipsisc = webidl_node_enumerate_type(
+ webidl_node_getnode(argument),
+ WEBIDL_NODE_TYPE_ELLIPSIS);
+
+ cure++;
+
+ argument = webidl_node_find_type(
+ webidl_node_getnode(arg_list_node),
+ argument,
+ WEBIDL_NODE_TYPE_ARGUMENT);
+ }
+
+ *argumentc_out = argumentc;
+ *argumentv_out = argumentv;
+
+ return 0;
+}
+
+/**
+ * create a new overloaded parameter set on an operation
+ *
+ * each operation can be overloaded with multiple function signatures. By
+ * adding them to the operation as overloads duplicate operation enrtries is
+ * avoided.
+ */
+static int
+overload_map_new(struct webidl_node *op_node,
+ int *overloadc_out,
+ struct interface_map_operation_overload_entry **overloadv_out)
+{
+ int overloadc = *overloadc_out;
+ struct interface_map_operation_overload_entry *overloadv;
+ struct interface_map_operation_overload_entry *cure;
+ struct webidl_node *arg_list_node;
+ int argc;
+
+ /* update allocation */
+ overloadc++;
+ overloadv = realloc(*overloadv_out, overloadc * sizeof(*overloadv));
+ if (overloadv == NULL) {
+ return -1;
+ }
+
+ /* get added entry */
+ cure = overloadv + (overloadc - 1);
+
+ /* clear entry */
+ cure = memset(cure, 0, sizeof(*cure));
+
+ /* return type */
+ cure->type = webidl_node_find_type(webidl_node_getnode(op_node),
+ NULL,
+ WEBIDL_NODE_TYPE_TYPE);
+
+ arg_list_node = webidl_node_find_type(webidl_node_getnode(op_node),
+ NULL,
+ WEBIDL_NODE_TYPE_LIST);
+ if (arg_list_node != NULL) {
+ argument_map_new(arg_list_node,
+ &cure->argumentc,
+ &cure->argumentv);
+ }
+
+ for (argc = 0; argc < cure->argumentc; argc++) {
+ struct interface_map_operation_argument_entry *arge;
+ arge = cure->argumentv + argc;
+ cure->optionalc += arge->optionalc;
+ cure->elipsisc += arge->elipsisc;
+ }
+
+ /* return entry list */
+ *overloadc_out = overloadc;
+ *overloadv_out = overloadv;
+
+ return 0;
}
static int
@@ -170,9 +288,8 @@ operation_map_new(struct webidl_node *interface,
struct interface_map_operation_entry *cure; /* current entry */
struct interface_map_operation_entry *operationv;
int operationc;
- int opc;
- /* enumerate operationss */
+ /* enumerate operationss including overloaded members */
operationc = enumerate_interface_type(interface,
WEBIDL_NODE_TYPE_OPERATION);
@@ -204,25 +321,49 @@ operation_map_new(struct webidl_node *interface,
WEBIDL_NODE_TYPE_OPERATION);
while (op_node != NULL) {
- cure->node = op_node;
+ const char *operation_name;
+ struct interface_map_operation_entry *finde;
- cure->name = webidl_node_gettext(
+ /* get operation name */
+ operation_name = webidl_node_gettext(
webidl_node_find_type(
webidl_node_getnode(op_node),
NULL,
WEBIDL_NODE_TYPE_IDENT));
+ /* if this operation is already an entry in the list
+ * augment that entry else create a new one
+ */
+ finde = find_operation_name(operationv,
+ operationc,
+ operation_name);
+ if (finde == NULL) {
+ /* operation does not already exist in list */
+
+ cure->name = operation_name;
+
+ cure->node = op_node;
- cure->method = genbind_node_find_method_ident(
+ cure->method = genbind_node_find_method_ident(
class,
NULL,
GENBIND_METHOD_TYPE_METHOD,
cure->name);
- cure->overloadc = count_operation_name(operationv,
- operationc,
- cure->name);
+ overload_map_new(op_node,
+ &cure->overloadc,
+ &cure->overloadv);
- cure++;
+ cure++; /* advance to next entry */
+ } else {
+ overload_map_new(op_node,
+ &finde->overloadc,
+ &finde->overloadv);
+ /* Overloaded entry does not advance the
+ * current entry but does reduce list
+ * length. Do not bother shortening allocation.
+ */
+ operationc--;
+ }
/* move to next operation */
op_node = webidl_node_find_type(
@@ -237,20 +378,6 @@ operation_map_new(struct webidl_node *interface,
WEBIDL_NODE_TYPE_LIST);
}
- /* finally take a pass over the table to correct the overload count */
- for (opc = 0; opc < operationc; opc++) {
- cure = operationv + opc;
- if ((cure->overloadc == 1) &&
- (count_operation_name(operationv,
- operationc,
- cure->name) == 1)) {
- /* if the "overloaded" member is itself it is not
- * overloaded.
- */
- cure->overloadc = 0;
- }
- }
-
*operationc_out = operationc;
*operationv_out = operationv; /* resulting operations map */
@@ -567,46 +694,88 @@ int interface_map_dump(struct interface_map *index)
for (eidx = 0; eidx < index->entryc; eidx++) {
fprintf(dumpf, "%d %s\n", eidx, ecur->name);
if (ecur->inherit_name != NULL) {
- fprintf(dumpf, " inherit:%s\n", ecur->inherit_name);
+ fprintf(dumpf, "\tinherit:%s\n", ecur->inherit_name);
}
if (ecur->class != NULL) {
- fprintf(dumpf, " class:%p\n", ecur->class);
+ fprintf(dumpf, "\tclass:%p\n", ecur->class);
}
+
if (ecur->operationc > 0) {
- int opc = ecur->operationc;
- struct interface_map_operation_entry *ope;
+ int opc;
- fprintf(dumpf, " %d operations\n",
+ fprintf(dumpf, "\t%d operations\n",
ecur->operationc);
- ope = ecur->operationv;
- while (ope != NULL) {
+ for (opc = 0; opc < ecur->operationc; opc++) {
+ int ovlc;
+ struct interface_map_operation_entry *ope;
+
+ ope = ecur->operationv + opc;
+
fprintf(dumpf,
- " %s\n",
+ "\t\t%s\n",
ope->name);
fprintf(dumpf,
- " method:%p\n",
+ "\t\t\tmethod:%p\n",
ope->method);
- fprintf(dumpf,
- " overload:%d\n",
- ope->overloadc);
- ope++;
- opc--;
- if (opc == 0) {
- break;
+ for(ovlc = 0; ovlc < ope->overloadc;ovlc++) {
+ int argc;
+ struct interface_map_operation_overload_entry *ovle;
+ ovle = ope->overloadv + ovlc;
+
+ fprintf(dumpf,
+ "\t\t\toverload:%d\n", ovlc);
+
+ fprintf(dumpf,
+ "\t\t\t\treturn type:%p\n",
+ ovle->type);
+
+ fprintf(dumpf,
+ "\t\t\t\targuments:%d\n",
+ ovle->argumentc);
+
+ fprintf(dumpf,
+ "\t\t\t\toptionals:%d\n",
+ ovle->optionalc);
+
+ fprintf(dumpf,
+ "\t\t\t\telipsis:%d\n",
+ ovle->elipsisc);
+
+ for (argc = 0; argc < ovle->argumentc; argc++) {
+ struct interface_map_operation_argument_entry *arge;
+ arge = ovle->argumentv + argc;
+
+ fprintf(dumpf,
+ "\t\t\t\t\t%s\n",
+ arge->name);
+
+ if (arge->optionalc != 0) {
+ fprintf(dumpf,
+ "\t\t\t\t\t\toptional:%d\n",
+ arge->optionalc);
+ }
+
+ if (arge->elipsisc != 0) {
+ fprintf(dumpf,
+ "\t\t\t\t\t\telipsis:%d\n",
+ arge->elipsisc);
+ }
+
+ }
}
}
-
}
+
if (ecur->attributec > 0) {
int attrc = ecur->attributec;
struct interface_map_attribute_entry *attre;
- fprintf(dumpf, " %d attributes\n", attrc);
+ fprintf(dumpf, "\t%d attributes\n", attrc);
attre = ecur->attributev;
while (attre != NULL) {
- fprintf(dumpf, " %s %p",
+ fprintf(dumpf, "\t\t%s %p",
attre->name,
attre->getter);
if (attre->modifier == WEBIDL_TYPE_MODIFIER_NONE) {
@@ -624,13 +793,13 @@ int interface_map_dump(struct interface_map *index)
if (ecur->constantc > 0) {
int idx;
- fprintf(dumpf, " %d constants\n",
+ fprintf(dumpf, "\t%d constants\n",
ecur->constantc);
for (idx = 0; idx < ecur->constantc; idx++) {
struct interface_map_constant_entry *cone;
cone = ecur->constantv + idx;
- fprintf(dumpf, " %s\n",
+ fprintf(dumpf, "\t\t%s\n",
cone->name);
}
}