lib: Add CLEANUP_FREE_<struct>, CLEANUP_FREE_<struct>_LIST macros for API structs.

For example:

 {
   CLEANUP_FREE_STAT struct guestfs_stat *stat = guestfs_stat (g, "/foo");

   // stat is freed automatically when we leave the scope.
 }

The new header file "guestfs-internal-frontend-cleanups.h"
includes definitions for these.  It should not be included
directly.
This commit is contained in:
Richard W.M. Jones
2013-02-08 13:39:47 +00:00
parent 5e770c8f6a
commit 5f54da6fdf
5 changed files with 99 additions and 3 deletions

1
.gitignore vendored
View File

@@ -371,6 +371,7 @@ Makefile.in
/src/guestfs-availability.pod
/src/guestfs.h
/src/guestfs-internal-actions.h
/src/guestfs-internal-frontend-cleanups.h
/src/guestfs_protocol.c
/src/guestfs_protocol.h
/src/guestfs_protocol.x

View File

@@ -779,6 +779,60 @@ and generate_internal_actions_h () =
pr "\n";
pr "#endif /* GUESTFS_INTERNAL_ACTIONS_H_ */\n"
(* Generate guestfs-internal-frontend-cleanups.h file. *)
and generate_internal_frontend_cleanups_h () =
generate_header CStyle LGPLv2plus;
pr "\
/* These CLEANUP_* macros automatically free the struct or struct list
* pointed to by the local variable at the end of the current scope.
*
* Don't include this file directly! To use these cleanups in library
* bindings and tools, include \"guestfs-internal-frontend.h\" only.
*/
#ifndef GUESTFS_INTERNAL_FRONTEND_CLEANUPS_H_
#define GUESTFS_INTERNAL_FRONTEND_CLEANUPS_H_
#ifdef HAVE_ATTRIBUTE_CLEANUP
";
List.iter (
fun { s_name = name } ->
pr "#define CLEANUP_FREE_%s \\\n" (String.uppercase name);
pr " __attribute__((cleanup(guestfs___cleanup_free_%s)))\n" name;
pr "#define CLEANUP_FREE_%s_LIST \\\n" (String.uppercase name);
pr " __attribute__((cleanup(guestfs___cleanup_free_%s_list)))\n" name
) structs;
pr "#else /* !HAVE_ATTRIBUTE_CLEANUP */\n";
List.iter (
fun { s_name = name } ->
pr "#define CLEANUP_FREE_%s\n" (String.uppercase name);
pr "#define CLEANUP_FREE_%s_LIST\n" (String.uppercase name)
) structs;
pr "\
#endif /* !HAVE_ATTRIBUTE_CLEANUP */
/* These functions are used internally by the CLEANUP_* macros.
* Don't call them directly.
*/
";
List.iter (
fun { s_name = name } ->
pr "extern GUESTFS_DLL_PUBLIC void guestfs___cleanup_free_%s (void *ptr);\n"
name;
pr "extern GUESTFS_DLL_PUBLIC void guestfs___cleanup_free_%s_list (void *ptr);\n"
name
) structs;
pr "\n";
pr "#endif /* GUESTFS_INTERNAL_FRONTEND_CLEANUPS_H_ */\n"
(* Functions to free structures. *)
and generate_client_free_structs () =
generate_header CStyle LGPLv2plus;
@@ -824,6 +878,28 @@ and generate_client_free_structs () =
pr "}\n";
pr "\n";
) structs;
pr "/* Cleanup functions used by CLEANUP_* macros. */\n";
pr "\n";
List.iter (
fun { s_name = typ } ->
pr "GUESTFS_DLL_PUBLIC void\n";
pr "guestfs___cleanup_free_%s (void *ptr)\n" typ;
pr "{\n";
pr " guestfs_free_%s (* (struct guestfs_%s **) ptr);\n" typ typ;
pr "}\n";
pr "\n";
pr "GUESTFS_DLL_PUBLIC void\n";
pr "guestfs___cleanup_free_%s_list (void *ptr)\n" typ;
pr "{\n";
pr " guestfs_free_%s_list (* (struct guestfs_%s_list **) ptr);\n"
typ typ;
pr "}\n";
pr "\n";
) structs
(* Generate the client-side dispatch stubs. *)
@@ -1707,13 +1783,24 @@ and generate_linker_script () =
"guestfs_" ^ c_name ^ "_argv"]
) all_functions
) in
let structs =
let struct_frees =
List.concat (
List.map (fun { s_name = typ } ->
["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
["guestfs_free_" ^ typ;
"guestfs_free_" ^ typ ^ "_list"])
structs
) in
let globals = List.sort compare (globals @ functions @ structs) in
let struct_cleanups =
List.concat (
List.map (fun { s_name = typ } ->
["guestfs___cleanup_free_" ^ typ;
"guestfs___cleanup_free_" ^ typ ^ "_list"])
structs
) in
let globals = List.sort compare (globals @
functions @
struct_frees @
struct_cleanups) in
pr "{\n";
pr " global:\n";

View File

@@ -84,6 +84,8 @@ Run it from the top source directory using the command
output_to "src/guestfs_protocol.x" generate_xdr;
output_to "src/guestfs.h" generate_guestfs_h;
output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
output_to "src/guestfs-internal-frontend-cleanups.h"
generate_internal_frontend_cleanups_h;
output_to "src/bindtests.c" generate_bindtests;
output_to "src/guestfs-structs.pod" generate_structs_pod;
output_to "src/guestfs-actions.pod" generate_actions_pod;

View File

@@ -23,6 +23,7 @@ generator_built = \
guestfs_protocol.x \
guestfs.h \
guestfs-internal-actions.h \
guestfs-internal-frontend-cleanups.h \
actions-0.c \
actions-1.c \
actions-2.c \

View File

@@ -108,4 +108,9 @@ extern void guestfs___cleanup_xmlXPathFreeContext (void *ptr);
extern void guestfs___cleanup_xmlXPathFreeObject (void *ptr);
#endif
/* These are in a separate header so the header can be generated.
* Don't include the following file directly:
*/
#include "guestfs-internal-frontend-cleanups.h"
#endif /* GUESTFS_INTERNAL_FRONTEND_H_ */