mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-21 22:53:37 +00:00
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:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -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
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
Reference in New Issue
Block a user