Skip to content

Commit

Permalink
Merge pull request #5303 from kc284/private/konstantin1/sdk
Browse files Browse the repository at this point in the history
[OIL] Moved some more generation code to templates.
  • Loading branch information
kc284 authored Mar 18, 2024
2 parents 0f6163e + ae7480c commit 2b35c8b
Show file tree
Hide file tree
Showing 11 changed files with 703 additions and 491 deletions.
218 changes: 39 additions & 179 deletions ocaml/sdk-gen/c/gen_c_binding.ml
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,7 @@ let rec main () =

all_headers := List.map (fun x -> x.name) filtered_classes ;

TypeSet.iter (gen_enum write_enum_decl decl_filename include_dir) !enums ;
TypeSet.iter (gen_enum write_enum_impl impl_filename src_dir) !enums ;
TypeSet.iter
(gen_enum write_enum_internal_decl internal_decl_filename include_dir)
!enums ;
TypeSet.iter render_enum !enums ;

maps := TypeSet.add (Map (String, Int)) !maps ;
maps := TypeSet.add (Map (Int, Int)) !maps ;
Expand Down Expand Up @@ -140,17 +136,6 @@ and gen_class f g clas targetdir =
let out_chan = open_out (Filename.concat targetdir (g clas.name)) in
Fun.protect (fun () -> f clas out_chan) ~finally:(fun () -> close_out out_chan)

and gen_enum f g targetdir = function
| Enum (name, _) as x ->
if not (List.mem name !all_headers) then
all_headers := name :: !all_headers ;
let out_chan = open_out (Filename.concat targetdir (g name)) in
Fun.protect
(fun () -> f x out_chan)
~finally:(fun () -> close_out out_chan)
| _ ->
assert false

and gen_map f g targetdir = function
| Map (l, r) ->
let name = mapname l r in
Expand Down Expand Up @@ -669,174 +654,49 @@ and hash_include n =
else
sprintf "#include <%s>" (decl_filename n)

and write_enum_decl x out_chan =
match x with
| Enum (name, contents) ->
let print format = fprintf out_chan format in
let protect = protector name in
let tn = typename name in

print_h_header out_chan protect ;
and replace_dashes x =
Astring.String.map (fun y -> match y with '-' -> '_' | _ -> y) x

print
"\n\
%s\n\n\n\
enum %s\n\
{\n\
%s\n\
};\n\n\n\
typedef struct %s_set\n\
{\n\
\ size_t size;\n\
\ enum %s contents[];\n\
} %s_set;\n\n\
%s\n\
extern %s_set *\n\
%s_set_alloc(size_t size);\n\n\
%s\n\n\n\
%s\n\
extern const char *\n\
%s_to_string(enum %s val);\n\n\n\
%s\n\
extern enum %s\n\
%s_from_string(xen_session *session, const char *str);\n\n"
(hash_include "common") tn
(joined ",\n\n" (enum_entry name)
(contents
@ [("undefined", "Unknown to this version of the bindings.")]
)
)
tn tn tn
(Helper.comment true (sprintf "Allocate a %s_set of the given size." tn))
tn tn
(decl_free (sprintf "%s_set" tn) "*set" false "set")
(Helper.comment true
"Return the name corresponding to the given code. This string must \
not be modified or freed."
)
tn tn
(Helper.comment true
"Return the correct code for the given string, or set the session \
object to failure and return an undefined value if the given \
string does not match a known code."
)
tn tn ;

print_h_footer out_chan
| _ ->
()

and enum_entry enum_name = function
| n, c ->
sprintf "%s\n XEN_%s_%s"
(Helper.comment true ~indent:4 c)
(String.uppercase_ascii enum_name)
(Astring.String.map
(fun x -> match x with '-' -> '_' | _ -> x)
(String.uppercase_ascii n)
)

and write_enum_impl x out_chan =
and render_enum x =
match x with
| Enum (name, contents) ->
let print format = fprintf out_chan format in
let tn = typename name in

print
"%s\n\n\
#include <string.h>\n\n\
%s\n\
%s\n\
%s\n\n\n\
/*\n\
\ * Maintain this in the same order as the enum declaration!\n\
\ */\n\
static const char *lookup_table[] =\n\
{\n\
%s\n\
};\n\n\n\
extern %s_set *\n\
%s_set_alloc(size_t size)\n\
{\n\
\ return calloc(1, sizeof(%s_set) +\n\
\ size * sizeof(enum %s));\n\
}\n\n\n\
extern void\n\
%s_set_free(%s_set *set)\n\
{\n\
\ free(set);\n\
}\n\n\n\
const char *\n\
%s_to_string(enum %s val)\n\
{\n\
\ return lookup_table[val];\n\
}\n\n\n\
extern enum %s\n\
%s_from_string(xen_session *session, const char *str)\n\
{\n\
\ (void)session;\n\
\ return ENUM_LOOKUP(str, lookup_table);\n\
}\n\n\n\
const abstract_type %s_abstract_type_ =\n\
\ {\n\
\ .XEN_API_TYPE = ENUM,\n\
\ .enum_marshaller =\n\
\ (const char *(*)(int))&%s_to_string,\n\
\ .enum_demarshaller =\n\
\ (int (*)(xen_session *, const char *))&%s_from_string\n\
\ };\n\n\n"
Licence.bsd_two_clause (hash_include "internal") (hash_include name)
(hash_include (name ^ "_internal"))
(enum_lookup_entries (contents @ [("undefined", "")]))
tn tn tn tn tn tn tn tn tn tn tn tn tn ;

if name <> "event_operation" then
print
"const abstract_type %s_set_abstract_type_ =\n\
\ {\n\
\ .XEN_API_TYPE = SET,\n\
\ .child = &%s_abstract_type_\n\
\ };\n\n\n"
tn tn
| _ ->
()

and enum_lookup_entries contents = joined ",\n" enum_lookup_entry contents

and enum_lookup_entry = function n, _ -> sprintf " \"%s\"" n

and write_enum_internal_decl x out_chan =
match x with
| Enum (name, _) ->
let print format = fprintf out_chan format in
let protect = protector (sprintf "%s_internal" name) in
let tn = typename name in

let set_abstract_type =
if name = "event_operations" then
""
else
sprintf "extern const abstract_type %s_set_abstract_type_;\n" tn
if not (List.mem name !all_headers) then
all_headers := name :: !all_headers ;
let json =
`O
[
("enum_name", `String name)
; ("enum_name_upper", `String (String.uppercase_ascii name))
; ("event_operations", `Bool (name = "event_operation"))
; ( "enum_values"
, `A
(List.map
(fun (n, c) ->
`O
[
("enum_value", `String n)
; ("enum_value_doc", `String c)
; ( "enum_value_upper"
, `String (replace_dashes (String.uppercase_ascii n))
)
]
)
contents
)
)
]
in

print
"%s\n\n\n\
%s\n\n\n\
#ifndef %s\n\
#define %s\n\n\n\
%s\n\n\n\
extern const abstract_type %s_abstract_type_;\n\
%s\n\n\
#endif\n"
Licence.bsd_two_clause
(Helper.comment false
(sprintf
"Declarations of the abstract types used during demarshalling of \
enum %s. Internal to this library -- do not use from outside."
tn
)
render_file
( "xen_enum_internal.h.mustache"
, sprintf "include/xen_%s_internal.h" name
)
protect protect (hash_include "internal") tn set_abstract_type
json templates_dir destdir ;
render_file
("xen_enum.h.mustache", sprintf "include/xen/api/xen_%s.h" name)
json templates_dir destdir ;
render_file
("xen_enum.c.mustache", sprintf "src/xen_%s.c" name)
json templates_dir destdir
| _ ->
()

Expand Down
98 changes: 98 additions & 0 deletions ocaml/sdk-gen/c/templates/xen_enum.c.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* Copyright (c) Cloud Software Group, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1) Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/


#include <string.h>

#include "xen_internal.h"
#include <xen/api/xen_{{{enum_name}}}.h>
#include "xen_{{{enum_name}}}_internal.h"


/*
* Maintain this in the same order as the enum declaration!
*/
static const char *lookup_table[] =
{
{{#enum_values}}
"{{{enum_value}}}",
{{/enum_values}}
"undefined"
};


extern xen_{{{enum_name}}}_set *
xen_{{{enum_name}}}_set_alloc(size_t size)
{
return calloc(1, sizeof(xen_{{{enum_name}}}_set) +
size * sizeof(enum xen_{{{enum_name}}}));
}


extern void
xen_{{{enum_name}}}_set_free(xen_{{{enum_name}}}_set *set)
{
free(set);
}


const char *
xen_{{{enum_name}}}_to_string(enum xen_{{{enum_name}}} val)
{
return lookup_table[val];
}


extern enum xen_{{{enum_name}}}
xen_{{{enum_name}}}_from_string(xen_session *session, const char *str)
{
(void)session;
return ENUM_LOOKUP(str, lookup_table);
}


const abstract_type xen_{{{enum_name}}}_abstract_type_ =
{
.XEN_API_TYPE = ENUM,
.enum_marshaller =
(const char *(*)(int))&xen_{{{enum_name}}}_to_string,
.enum_demarshaller =
(int (*)(xen_session *, const char *))&xen_{{{enum_name}}}_from_string
};


{{^event_operations}}
const abstract_type xen_{{{enum_name}}}_set_abstract_type_ =
{
.XEN_API_TYPE = SET,
.child = &xen_{{{enum_name}}}_abstract_type_
};


{{/event_operations}}
Loading

0 comments on commit 2b35c8b

Please sign in to comment.