/*
- * Copyright (C) 2016, 2017, 2018 "IoT.bzh"
+ * Copyright (C) 2016-2019 "IoT.bzh"
* Author José Bollo <jose.bollo@iot.bzh>
*
* Licensed under the Apache License, Version 2.0 (the "License");
#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)
/**
/**
* 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;
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)
{
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 });
return path.object;
}
+/* create c name by replacing non alpha numeric characters with underscores */
char *cify(const char *str)
{
char *r = strdup(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;
switch ((c = *b++)) {
case 0:
b--;
+ buf[0] = 0;
break;
case '/':
buf[0] = '/';
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;
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(fmtstr, json_object_get_string(json_object_array_get_idx(a_perms, i)));
}
}
+/*
+ * 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;
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);
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;
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)
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, cpp ? "afb::auth_permission(\"%s\")" : ".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, "not", &x)) {
x = decl_perm(x);
- asprintf(&a, cpp ? "afb::auth_not(%s)" : ".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);
}
{
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;
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)
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)
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)
",\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"
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", "?");
/* get the API name */
printf(
"\n"
- "static const char _afb_description_v2_%s[] =\n"
+ "static const char _afb_description_%s[] =\n"
"%s"
";\n"
"\n"
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(
" .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
);
/** process the list of files or stdin if none */
int main(int ac, char **av)
{
+ int r, w;
av++;
- if (*av && !(strcmp(*av, "-x") && strcmp(*av, "--cpp"))) {
- cpp = 1;
- 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 {
return 0;
}
-
-
-
-