summaryrefslogtreecommitdiff
path: root/src/interface-map.c
diff options
context:
space:
mode:
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);
}
}