Update copyright dates
[src/app-framework-binder.git] / src / devtools / genskel.c
index 62dfe3f..aab2e56 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016, 2017 "IoT.bzh"
+ * Copyright (C) 2015-2020 "IoT.bzh"
  * Author José Bollo <jose.bollo@iot.bzh>
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -48,6 +48,7 @@
 
 #include <json-c/json.h>
 
+#define T(x)   ((x) && *(x))
 #define oom(x) do{if(!(x)){fprintf(stderr,"out of memory\n");exit(1);}}while(0)
 
 /**
@@ -62,6 +63,7 @@ struct path
 /**
  * root of the JSON being parsed
  */
+int version = 3;
 struct json_object *root = NULL;
 struct json_object *d_perms = NULL;
 struct json_object *a_perms = NULL;
@@ -72,13 +74,17 @@ const char *api = NULL;
 const char *scope = NULL;
 const char *prefix = NULL;
 const char *postfix = NULL;
+const char *provideclass = NULL;
+const char *requireclass = NULL;
+const char *requireapi = NULL;
 char *capi = NULL;
 int priv = -1;
 int noconc = -1;
+int cpp = 0;
 
 /**
- * Search for a reference of type "#/a/b/c" int the
- * parsed JSON object
+ * Search for a reference of type "#/a/b/c" in the
+ * parsed JSON object (root)
  */
 struct json_object *search(const char *path)
 {
@@ -151,7 +157,7 @@ struct json_object *expand_$ref(struct path path)
        case json_type_array:
                /* expand the values of arrays */
                i = 0;
-               n = json_object_array_length(path.object);
+               n = (int)json_object_array_length(path.object);
                while (i != n) {
                        o = json_object_array_get_idx(path.object, i);
                        x = expand_$ref((struct path){ .object = o, .upper = &path });
@@ -169,6 +175,7 @@ struct json_object *expand_$ref(struct path path)
        return path.object;
 }
 
+/* create c name by replacing non alpha numeric characters with underscores */
 char *cify(const char *str)
 {
        char *r = strdup(str);
@@ -181,10 +188,11 @@ char *cify(const char *str)
        return r;
 }
 
+/* format the specification as a C string */
 char *make_info(const char *text, int split)
 {
        const char *a, *b;
-       char *desc, c, buf[3];
+       char *desc, c, buf[3] = {0};
        size_t len;
        int i, pos, e;
 
@@ -213,6 +221,7 @@ char *make_info(const char *text, int split)
                        switch ((c = *b++)) {
                        case 0:
                                b--;
+                               buf[0] = 0;
                                break;
                        case '/':
                                buf[0] = '/';
@@ -259,11 +268,13 @@ char *make_info(const char *text, int split)
        return desc;
 }
 
+/* make the description of the object */
 char *make_desc(struct json_object *o)
 {
-       return make_info(json_object_to_json_string_ext(root, 0), 1);
+       return make_info(json_object_to_json_string_ext(o, 0), 1);
 }
 
+/* get the permission odescription if set */
 struct json_object *permissions_of_verb(struct json_object *obj)
 {
        struct json_object *x, *y;
@@ -278,22 +289,28 @@ struct json_object *permissions_of_verb(struct json_object *obj)
        return NULL;
 }
 
+/* output the array of permissions */
 void print_perms()
 {
        int i, n;
+       const char *fmtstr = cpp ? "\t%s" : "\t{ %s }";
 
-       n = a_perms ? json_object_array_length(a_perms) : 0;
+       n = a_perms ? (int)json_object_array_length(a_perms) : 0;
        if (n) {
-               printf("static const struct afb_auth _afb_auths_v2_%s[] = {\n" , capi);
+               printf("static const struct afb_auth _afb_auths_%s[] = {\n" , capi);
                i = 0;
                while (i < n) {
-                       printf("\t{ %s }", json_object_get_string(json_object_array_get_idx(a_perms, i)));
+                       printf(fmtstr, json_object_get_string(json_object_array_get_idx(a_perms, i)));
                        printf(",\n"+(++i == n));
                }
                printf("};\n\n");
        }
 }
 
+/*
+ * search in the global object 'd_perm' the computed representation
+ * of the permission described either by 'obj' or 'desc'
+ */
 struct json_object *new_perm(struct json_object *obj, const char *desc)
 {
        const char *tag;
@@ -302,12 +319,15 @@ struct json_object *new_perm(struct json_object *obj, const char *desc)
 
        tag = obj ? json_object_to_json_string_ext(obj, 0) : desc;
        if (!json_object_object_get_ex(d_perms, tag, &y)) {
+
+               /* creates the d_perms dico and the a_perms array */
                if (!d_perms) {
                        d_perms = json_object_new_object();
                        a_perms = json_object_new_array();
                }
 
-               asprintf(&b, "&_afb_auths_v2_%s[%d]", capi, json_object_array_length(a_perms));
+               /* creates the reference in the structure */
+               asprintf(&b, "&_afb_auths_%s[%d]", capi, (int)json_object_array_length(a_perms));
                x = json_object_new_string(desc);
                y = json_object_new_string(b);
                json_object_array_add(a_perms, x);
@@ -319,14 +339,25 @@ struct json_object *new_perm(struct json_object *obj, const char *desc)
 
 struct json_object *decl_perm(struct json_object *obj);
 
-struct json_object *decl_perm_a(const char *op, struct json_object *obj)
+enum optype { And, Or };
+
+/* recursive declare and/or permissions */
+struct json_object *decl_perm_a(enum optype op, struct json_object *obj)
 {
        int i, n;
        char *a;
+       const char *opstr, *fmtstr;
        struct json_object *x, *y;
 
+       if (cpp) {
+               fmtstr = "afb::auth_%s(%s, %s)";
+               opstr = op==And ? "and" : "or";
+       } else {
+               fmtstr = ".type = afb_auth_%s, .first = %s, .next = %s";
+               opstr = op==And ? "And" : "Or";
+       }
        x = NULL;
-       i = n = obj ? json_object_array_length(obj) : 0;
+       i = n = obj ? (int)json_object_array_length(obj) : 0;
        while (i) {
                y = decl_perm(json_object_array_get_idx(obj, --i));
                if (!y)
@@ -334,8 +365,7 @@ struct json_object *decl_perm_a(const char *op, struct json_object *obj)
                else if (!x)
                        x = y;
                else if (x != y) {
-                       asprintf(&a, ".type = afb_auth_%s, .first = %s, .next = %s",
-                                op, json_object_get_string(y), json_object_get_string(x));
+                       asprintf(&a, fmtstr, opstr, json_object_get_string(y), json_object_get_string(x));
                        x = new_perm(NULL, a);
                        free(a);
                }
@@ -343,28 +373,38 @@ struct json_object *decl_perm_a(const char *op, struct json_object *obj)
        return x;
 }
 
+/* declare the permission for obj */
 struct json_object *decl_perm(struct json_object *obj)
 {
        char *a;
+       const char *fmt;
        struct json_object *x, *y;
 
        if (json_object_object_get_ex(d_perms, json_object_to_json_string_ext(obj, 0), &x))
                return x;
 
        if (json_object_object_get_ex(obj, "permission", &x)) {
-               asprintf(&a, ".type = afb_auth_Permission, .text = \"%s\"", json_object_get_string(x));
+               if (cpp)
+                       fmt = "afb::auth_permission(\"%s\")";
+               else
+                       fmt = ".type = afb_auth_Permission, .text = \"%s\"";
+               asprintf(&a, fmt, json_object_get_string(x));
                y = new_perm(obj, a);
                free(a);
        }
        else if (json_object_object_get_ex(obj, "anyOf", &x)) {
-               y = decl_perm_a("Or", x);
+               y = decl_perm_a(Or, x);
        }
        else if (json_object_object_get_ex(obj, "allOf", &x)) {
-               y = decl_perm_a("And", x);
+               y = decl_perm_a(And, x);
        }
        else if (json_object_object_get_ex(obj, "not", &x)) {
                x = decl_perm(x);
-               asprintf(&a, ".type = afb_auth_Not, .first = %s", json_object_get_string(x));
+               if (cpp)
+                       fmt = "afb::auth_not(%s)";
+               else
+                       fmt = ".type = afb_auth_Not, .first = %s";
+               asprintf(&a, fmt, json_object_get_string(x));
                y = new_perm(obj, a);
                free(a);
        }
@@ -403,7 +443,7 @@ int get_session_a(int and, struct json_object *obj)
 {
        int i, n, x, y;
 
-       n = obj ? json_object_array_length(obj) : 0;
+       n = obj ? (int)json_object_array_length(obj) : 0;
        if (n == 0)
                return 0;
 
@@ -466,7 +506,7 @@ void print_session(struct json_object *p)
        s = p ? get_session(p) : 0;
        c = 1;
        if (s & SESSION_CHECK) {
-               printf("%s", "|AFB_SESSION_CHECK_V2" + c);
+               printf("%s", "|AFB_SESSION_CHECK" + c);
                c = 0;
        }
        if (s & SESSION_LOA_3 & ~SESSION_LOA_2)
@@ -478,19 +518,19 @@ void print_session(struct json_object *p)
        else
                l = 0;
        if (l) {
-               printf("%s%d_V2", "|AFB_SESSION_LOA_" + c, l);
+               printf("%s%d", "|AFB_SESSION_LOA_" + c, l);
                c = 0;
        }
        if (s & SESSION_CLOSE) {
-               printf("%s", "|AFB_SESSION_CLOSE_V2" + c);
+               printf("%s", "|AFB_SESSION_CLOSE" + c);
                c = 0;
        }
        if (s & SESSION_RENEW) {
-               printf("%s", "|AFB_SESSION_REFRESH_V2" + c);
+               printf("%s", "|AFB_SESSION_REFRESH" + c);
                c = 0;
        }
        if (c)
-               printf("AFB_SESSION_NONE_V2");
+               printf("AFB_SESSION_NONE");
 }
 
 void print_verb(const char *name)
@@ -500,9 +540,11 @@ void print_verb(const char *name)
 
 void print_declare_verb(const char *name, struct json_object *obj)
 {
-       printf("%s void ", scope);
+       if (T(scope))
+               printf("%s ", scope);
+       printf("void ");
        print_verb(name);
-       printf("(struct afb_req req);\n");
+       printf("(afb_req_t req);\n");
 }
 
 void print_struct_verb(const char *name, struct json_object *obj)
@@ -526,11 +568,22 @@ void print_struct_verb(const char *name, struct json_object *obj)
                ",\n"
                "        .auth = %s,\n"
                "        .info = %s,\n"
-               "        .session = "
                , p && decl_perm(p) ? json_object_get_string(decl_perm(p)) : "NULL"
                , info ? make_info(info, 0) : "NULL"
        );
+       if (version == 3)
+               printf(
+                       "        .vcbdata = NULL,\n"
+               );
+       printf(
+               "        .session = "
+       );
        print_session(p);
+       if (version == 3)
+               printf(
+                       ",\n"
+                       "        .glob = 0"
+               );
        printf(
                "\n"
                "    },\n"
@@ -625,6 +678,9 @@ void process(char *filename)
        getvar(&scope, "#/info/x-binding-c-generator/scope", "static");
        getvar(&prefix, "#/info/x-binding-c-generator/prefix", "afb_verb_");
        getvar(&postfix, "#/info/x-binding-c-generator/postfix", "_cb");
+       getvar(&provideclass, "#/info/x-binding-c-generator/provide-class", NULL);
+       getvar(&requireclass, "#/info/x-binding-c-generator/require-class", NULL);
+       getvar(&requireapi, "#/info/x-binding-c-generator/require-api", NULL);
        getvarbool(&priv, "#/info/x-binding-c-generator/private", 0);
        getvarbool(&noconc, "#/info/x-binding-c-generator/noconcurrency", 0);
        getvar(&api, "#/info/title", "?");
@@ -635,7 +691,7 @@ void process(char *filename)
        /* get the API name */
        printf(
                "\n"
-               "static const char _afb_description_v2_%s[] =\n"
+               "static const char _afb_description_%s[] =\n"
                "%s"
                ";\n"
                "\n"
@@ -646,8 +702,8 @@ void process(char *filename)
        enum_verbs(print_declare_verb);
        printf(
                "\n"
-               "static const struct afb_verb_v2 _afb_verbs_v2_%s[] = {\n"
-                , capi
+               "static const struct afb_verb_v%d _afb_verbs_%s[] = {\n"
+                , version, capi
        );
        enum_verbs(print_struct_verb);
        printf(
@@ -656,33 +712,82 @@ void process(char *filename)
                "        .callback = NULL,\n"
                "        .auth = NULL,\n"
                "        .info = NULL,\n"
-               "        .session = 0\n"
+       );
+       if (version == 3)
+               printf(
+                       "        .vcbdata = NULL,\n"
+               );
+       printf(
+               "        .session = 0"
+       );
+       if (version == 3)
+               printf(
+                       ",\n"
+                       "        .glob = 0"
+               );
+       printf(
+               "\n"
                "       }\n"
                "};\n"
        );
+
+       if (T(preinit) || T(init) || T(onevent)) {
+               printf("\n");
+               if (T(preinit)) {
+                       if (T(scope)) printf("%s ", scope);
+                       printf("int %s(%s);\n", preinit, version==3 ? "afb_api_t api" : "");
+               }
+               if (T(init)) {
+                       if (T(scope)) printf("%s ", scope);
+                       printf("int %s(%s);\n", init, version==3 ? "afb_api_t api" : "");
+               }
+               if (T(onevent)) {
+                       if (T(scope)) printf("%s ", scope);
+                       printf("void %s(%sconst char *event, struct json_object *object);\n",
+                                       onevent, version==3 ? "afb_api_t api, " : "");
+               }
+       }
+
        printf(
                "\n"
-               "%sconst struct afb_binding_v2 %s%s = {\n"
+               "%sconst struct afb_binding_v%d %s%s = {\n"
                "    .api = \"%s\",\n"
-               "    .specification = _afb_description_v2_%s,\n"
+               "    .specification = _afb_description_%s,\n"
                "    .info = %s,\n"
-               "    .verbs = _afb_verbs_v2_%s,\n"
+               "    .verbs = _afb_verbs_%s,\n"
                "    .preinit = %s,\n"
                "    .init = %s,\n"
                "    .onevent = %s,\n"
-               "    .noconcurrency = %d\n"
-               "};\n"
-               "\n"
                , priv ? "static " : ""
-               , priv ? "_afb_binding_v2_" : "afbBindingV2"
+               , version
+               , priv ? "_afb_binding_" : version==3 ? "afbBindingV3" : "afbBindingV2"
                , priv ? capi : ""
                , api
                , capi
                , info ? make_info(info, 0) : "NULL"
                , capi
-               , preinit ?: "NULL"
-               , init ?: "NULL"
-               , onevent ?: "NULL"
+               , T(preinit) ? preinit : "NULL"
+               , T(init) ? init : "NULL"
+               , T(onevent) ? onevent : "NULL"
+       );
+
+
+       if (version == 3)
+               printf(
+                       "    .userdata = NULL,\n"
+                       "    .provide_class = %s%s%s,\n"
+                       "    .require_class = %s%s%s,\n"
+                       "    .require_api = %s%s%s,\n"
+                       , T(provideclass) ? "\"" : "", T(provideclass) ? provideclass : "NULL", T(provideclass) ? "\"" : ""
+                       , T(requireclass) ? "\"" : "", T(requireclass) ? requireclass : "NULL", T(requireclass) ? "\"" : ""
+                       , T(requireapi) ? "\"" : "", T(requireapi) ? requireapi : "NULL", T(requireapi) ? "\"" : ""
+               );
+
+
+       printf(
+               "    .noconcurrency = %d\n"
+               "};\n"
+               "\n"
                , !!noconc
        );
 
@@ -694,15 +799,30 @@ void process(char *filename)
 /** process the list of files or stdin if none */
 int main(int ac, char **av)
 {
-       if (!*++av)
+       int r, w;
+       av++;
+
+       r = w = 0;
+       while (av[r]) {
+               if (!(strcmp(av[r], "-x") && strcmp(av[r], "--cpp"))) {
+                       cpp = 1;
+                       r++;
+               } else if (!strcmp(av[r], "-2")) {
+                       version = 2;
+                       r++;
+               } else if (!strcmp(av[r], "-3")) {
+                       version = 3;
+                       r++;
+               } else {
+                       av[w++] = av[r++];
+               }
+       }
+       av[w] = NULL;
+       if (!*av)
                process("-");
        else {
-               do { process(*av); } while(*++av);
+               do { process(*av++); } while(*av);
        }
        return 0;
 }
 
-
-
-
-