[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] remote generator: Legacy support for hyper to long mappings



This can be considered as a v2 for hyper annotation patch [1]. Dan
argued that hyper-to-long mapping is considered as legacy and hyper
should be mapped to long long for all new APIs. Therefore, he voted
against the longlong annotation, because this should be the default
anyway.

I removed the longlong annotations from the original patch. This
results in version-A of the attached patch 0001. But this optional
annotation makes the parser more complex. One of the reasons for
annotating things in the .x is to have single place to define a new
procedure. But as the long/longlong annotation only affect exiting
procedures and will not be added to new ones it's much simpler to
store this information in the generator itself. This information it is
fixed and will not change anymore. This is implemented in version-B of
the attached patch 0001. I favor version-B, what's your opinion on
this?

Attached patch 0002 extends the apibuild script to allow the usage of
long for the same fixed set as in the remote generator only. It
reports an error when new functions or structs use long instead of
longlong.

[1] https://www.redhat.com/archives/libvir-list/2011-May/msg01434.html

Matthias
From de01fb5f4c8dc56595c9c191293438038ffe1017 Mon Sep 17 00:00:00 2001
From: Matthias Bolte <matthias bolte googlemail com>
Date: Sun, 29 May 2011 18:12:01 +0200
Subject: [PATCH] remote generator: Legacy support for hyper to long mappings

Remove some special case code that took care of mapping hyper to the
correct C types.

Annotate hyper members in the .x files that should be mapped to long
instead of long long.

Use macros for hyper to long assignments that perform overflow checks
when long is smaller than hyper. Map hyper to long long by default.

Suggested by Eric Blake.
---
 configure.ac                 |    1 +
 daemon/remote.c              |   18 +++
 daemon/remote_generator.pl   |  262 ++++++++++++++++++++++++++++--------------
 src/remote/remote_driver.c   |   18 +++
 src/remote/remote_protocol.x |   64 ++++++-----
 5 files changed, 247 insertions(+), 116 deletions(-)

diff --git a/configure.ac b/configure.ac
index 55ae791..2ae7e1d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -117,6 +117,7 @@ if test "x$have_cpuid" = xyes; then
 fi
 AC_MSG_RESULT([$have_cpuid])
 
+AC_CHECK_SIZEOF(long)
 
 dnl Availability of various common functions (non-fatal if missing),
 dnl and various less common threadsafe functions
diff --git a/daemon/remote.c b/daemon/remote.c
index 3f13247..5bcf202 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -68,6 +68,24 @@
     virReportErrorHelper(VIR_FROM_THIS, code, __FILE__,           \
                          __FUNCTION__, __LINE__, __VA_ARGS__)
 
+#define HYPER_TO_TYPE(_type, _to, _from)                                      \
+    do {                                                                      \
+        if ((_from) != (_type)(_from)) {                                      \
+            virNetError(VIR_ERR_INTERNAL_ERROR,                               \
+                        _("conversion from hyper to %s overflowed"), #_type); \
+            goto cleanup;                                                     \
+        }                                                                     \
+        (_to) = (_from);                                                      \
+    } while (0)
+
+#if SIZEOF_LONG < 8
+# define HYPER_TO_LONG(_to, _from) HYPER_TO_TYPE(long, _to, _from)
+# define HYPER_TO_ULONG(_to, _from) HYPER_TO_TYPE(unsigned long, _to, _from)
+#else
+# define HYPER_TO_LONG(_to, _from) (_to) = (_from)
+# define HYPER_TO_ULONG(_to, _from) (_to) = (_from)
+#endif
+
 static virDomainPtr get_nonnull_domain(virConnectPtr conn, remote_nonnull_domain domain);
 static virNetworkPtr get_nonnull_network(virConnectPtr conn, remote_nonnull_network network);
 static virInterfacePtr get_nonnull_interface(virConnectPtr conn, remote_nonnull_interface iface);
diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl
index ac808fb..e0125b2 100755
--- a/daemon/remote_generator.pl
+++ b/daemon/remote_generator.pl
@@ -174,6 +174,47 @@ while (<PROTOCOL>) {
 
 close(PROTOCOL);
 
+sub handle_multi_ret_member
+{
+    my $dst = shift;
+    my $src = shift;
+    my $ret_member = shift;
+    my $check_overflow = shift;
+
+    if ($ret_member =~ m/^(unsigned )?hyper (\S+)\[\S+\];\s*\/\*\s*(long|ulong)\s*\*\//) {
+        if ((!$1 and $3 ne "long") or ($1 and $3 ne "ulong")) {
+            die "sign mismatch in [unsigned] hyper annotation: $ret_member";
+        }
+
+        # FIXME: currently the XDR protocol doesn't use [u]long hyper arrays,
+        #        so the generator can lack an implementation for this at the
+        #        moment. it would require a for loop with overflow check for
+        #        each element instead of a simple memcpy
+        die "[u]long hyper arrays aren't implemented yet";
+    } elsif ($ret_member =~ m/^(unsigned )?(char|short|int|hyper) (\S+)\[\S+\];/) {
+        return "memcpy($dst->$3, $src.$3, sizeof $dst->$3);";
+    } elsif ($ret_member =~ m/<\S+>;/ or $ret_member =~ m/\[\S+\];/) {
+        # just make all other array types fail
+        die "unhandled type for multi-return-value: $ret_member";
+    } elsif ($ret_member =~ m/^(unsigned )?hyper (\S+);\s*\/\*\s*(long|ulong)\s*\*\//) {
+        if ((!$1 and $3 ne "long") or ($1 and $3 ne "ulong")) {
+            die "sign mismatch in [unsigned] hyper annotation: $ret_member";
+        }
+
+        if ($check_overflow) {
+            my $sign = ""; $sign = "U" if ($1);
+
+            return "HYPER_TO_${sign}LONG($dst->$2, $src.$2);";
+        } else {
+            return "$dst->$2 = $src.$2;";
+        }
+    } elsif ($ret_member =~ m/^(unsigned )?(char|short|int|hyper) (\S+);/) {
+        return "$dst->$3 = $src.$3;";
+    } else {
+        die "unhandled type for multi-return-value: $ret_member";
+    }
+}
+
 #----------------------------------------------------------------------
 # Output
 
@@ -378,12 +437,28 @@ elsif ($opt_b) {
                     }
 
                     push(@args_list, "args->$1");
-                } elsif ($args_member =~ m/^(unsigned )?(int|hyper) (\S+);/) {
+                } elsif ($args_member =~ m/^(unsigned )?hyper (\S+);\s*\/\*\s*(long|ulong)\s*\*\//) {
+                    if ((!$1 and $3 ne "long") or ($1 and $3 ne "ulong")) {
+                        die "sign mismatch in [unsigned] hyper annotation: $args_member";
+                    }
+
+                    if (! @args_list) {
+                        push(@args_list, "conn");
+                    }
+
+                    my $type_name = $1; $type_name .= "long";
+                    my $arg_name = $2;
+                    my $sign = ""; $sign = "U" if ($1);
+
+                    push(@vars_list, "$type_name $arg_name");
+                    push(@getters_list, "    HYPER_TO_${sign}LONG($arg_name, args->$arg_name);\n");
+                    push(@args_list, "$arg_name");
+                } elsif ($args_member =~ m/^(?:unsigned )?(?:int|hyper) (\S+);/) {
                     if (! @args_list) {
                         push(@args_list, "conn");
                     }
 
-                    push(@args_list, "args->$3");
+                    push(@args_list, "args->$1");
                 } elsif ($args_member =~ m/^(\/)?\*/) {
                     # ignore comments
                 } else {
@@ -410,13 +485,7 @@ elsif ($opt_b) {
         if ($call->{ret} ne "void") {
             foreach my $ret_member (@{$call->{ret_members}}) {
                 if ($multi_ret) {
-                    if ($ret_member =~ m/^(unsigned )?(char|short|int|hyper) (\S+)\[\S+\];/) {
-                        push(@ret_list, "memcpy(ret->$3, tmp.$3, sizeof ret->$3);");
-                    } elsif ($ret_member =~ m/^(unsigned )?(char|short|int|hyper) (\S+);/) {
-                        push(@ret_list, "ret->$3 = tmp.$3;");
-                    } else {
-                        die "unhandled type for multi-return-value: $ret_member";
-                    }
+                    push(@ret_list, handle_multi_ret_member("ret", "tmp", $ret_member, 0));
                 } elsif ($ret_member =~ m/^remote_nonnull_string (\S+)<(\S+)>;\s*\/\*\s*insert@(\d+)\s*\*\//) {
                     push(@vars_list, "int len");
                     splice(@args_list, int($3), 0, ("ret->$1.$1_val"));
@@ -482,9 +551,60 @@ elsif ($opt_b) {
                     $single_ret_list_name = $1;
                     $single_ret_list_max_var = "max$1";
                     $single_ret_list_max_define = $2;
-                } elsif ($ret_member =~ m/^int (\S+)<\S+>;/) {
+                } elsif ($ret_member =~ m/^(unsigned )?hyper (\S+)<(\S+)>;\s*\/\*\s*insert@(\d+)\s+(long|ulong)\s*\*\//) {
+                    if ($5 and (!$1 and $5 ne "long") or ($1 and $5 ne "ulong")) {
+                        die "sign mismatch in [unsigned] hyper annotation: $ret_member";
+                    }
+
+                    # FIXME: currently the XDR protocol doesn't use [u]long hyper
+                    #        arrays, so the generator can lack an implementation
+                    #        for this at the moment. it would require a temporaty
+                    #        [u]long array and afor loop with overflow check for
+                    #        each element
+                    die "[u]long hyper arrays aren't implemented yet";
+                } elsif ($ret_member =~ m/^(unsigned )?hyper (\S+)<(\S+)>;\s*\/\*\s*insert@(\d+)\s*\*\//) {
+                   #my $type_name = $1; $type_name .= "long long";
+
+                    push(@vars_list, "int len");
+                    push(@ret_list, "ret->$2.$2_len = len;");
+                    push(@free_list_on_error, "VIR_FREE(ret->$2.$2_val);");
+                    $single_ret_var = "len";
+                    $single_ret_by_ref = 0;
+                    $single_ret_as_list = 1;
+                    $single_ret_list_name = $2;
+                    $single_ret_list_max_var = "max$2";
+                    $single_ret_list_max_define = $3;
+
+                    if ($call->{ProcName} eq "NodeGetCellsFreeMemory") {
+                        $single_ret_check = " <= 0";
+                        splice(@args_list, int($4), 0, ("(unsigned long long *)ret->$2.$2_val"));
+                    } else {
+                        $single_ret_check = " < 0";
+                        splice(@args_list, int($4), 0, ("ret->$2.$2_val"));
+                    }
+                } elsif ($ret_member =~ m/^(unsigned )?(int|hyper) \S+<\S+>;/) {
                     # error out on unannotated arrays
-                    die "int array without insert@<offset> annotation: $ret_member";
+                    die "$2 array without insert@<offset> annotation: $ret_member";
+                } elsif ($ret_member =~ m/^(unsigned )?hyper (\S+);\s*\/\*\s*(long|ulong)\s*\*\//) {
+                    if ((!$1 and $3 ne "long") or ($1 and $3 ne "ulong")) {
+                        die "sign mismatch in [unsigned] hyper annotation: $ret_member";
+                    }
+
+                    my $type_name = $1 if ($1); $type_name .= "long";
+                    my $ret_name = $2;
+
+                    push(@vars_list, "$type_name $ret_name");
+                    push(@ret_list, "ret->$ret_name = $ret_name;");
+                    $single_ret_var = $ret_name;
+
+                    if ($call->{ProcName} eq "DomainGetMaxMemory") {
+                        # SPECIAL: virDomainGetMaxMemory returns the actual
+                        #          value directly and 0 indicates an error
+                        $single_ret_by_ref = 0;
+                        $single_ret_check = " == 0";
+                    } else {
+                        $single_ret_by_ref = 1;
+                    }
                 } elsif ($ret_member =~ m/^int (\S+);/) {
                     push(@vars_list, "int $1");
                     push(@ret_list, "ret->$1 = $1;");
@@ -501,43 +621,17 @@ elsif ($opt_b) {
                             $single_ret_check = " < 0";
                         }
                     }
-                } elsif ($ret_member =~ m/^(?:unsigned )?hyper (\S+)<(\S+)>;\s*\/\*\s*insert@(\d+)\s*\*\//) {
-                    push(@vars_list, "int len");
-                    push(@ret_list, "ret->$1.$1_len = len;");
-                    push(@free_list_on_error, "VIR_FREE(ret->$1.$1_val);");
-                    $single_ret_var = "len";
-                    $single_ret_by_ref = 0;
-                    $single_ret_as_list = 1;
-                    $single_ret_list_name = $1;
-                    $single_ret_list_max_var = "max$1";
-                    $single_ret_list_max_define = $2;
-
-                    if ($call->{ProcName} eq "NodeGetCellsFreeMemory") {
-                        $single_ret_check = " <= 0";
-                        splice(@args_list, int($3), 0, ("(unsigned long long *)ret->$1.$1_val"));
-                    } else {
-                        $single_ret_check = " < 0";
-                        splice(@args_list, int($3), 0, ("ret->$1.$1_val"));
-                    }
-                } elsif ($ret_member =~ m/^(?:unsigned )?hyper (\S+)<\S+>;/) {
-                    # error out on unannotated arrays
-                    die "hyper array without insert@<offset> annotation: $ret_member";
                 } elsif ($ret_member =~ m/^(unsigned )?hyper (\S+);/) {
-                    my $type_name;
+                    my $type_name = $1; $type_name .= "long long";
                     my $ret_name = $2;
 
-                    $type_name = $1 if ($1);
-                    $type_name .= "long";
-
                     push(@vars_list, "$type_name $ret_name");
                     push(@ret_list, "ret->$ret_name = $ret_name;");
                     $single_ret_var = $ret_name;
 
-                    if ($call->{ProcName} eq "DomainGetMaxMemory" or
-                        $call->{ProcName} eq "NodeGetFreeMemory") {
-                        # SPECIAL: virDomainGetMaxMemory and virNodeGetFreeMemory
-                        #          return the actual value directly and 0 indicates
-                        #          an error
+                    if ($call->{ProcName} eq "NodeGetFreeMemory") {
+                        # SPECIAL: virNodeGetFreeMemory returns the actual
+                        #          value directly and 0 indicates an error
                         $single_ret_by_ref = 0;
                         $single_ret_check = " == 0";
                     } else {
@@ -888,23 +982,21 @@ elsif ($opt_k) {
                     push(@setters_list, "args.$arg_name.${arg_name}_val = (char *)$arg_name;");
                     push(@setters_list, "args.$arg_name.${arg_name}_len = ${arg_name}len;");
                     push(@args_check_list, { name => "\"$arg_name\"", arg => "${arg_name}len", limit => $limit });
+                } elsif ($args_member =~ m/^(unsigned )?hyper (\S+);\s*\/\*\s*(long|ulong)\s*\*\//) {
+                    if ((!$1 and $3 ne "long") or ($1 and $3 ne "ulong")) {
+                        die "sign mismatch in [unsigned] hyper annotation: $args_member";
+                    }
+
+                    my $type_name = $1; $type_name .= "long";
+                    my $arg_name = $2;
+
+                    push(@args_list, "$type_name $arg_name");
+                    push(@setters_list, "args.$arg_name = $arg_name;");
                 } elsif ($args_member =~ m/^(unsigned )?(int|hyper) (\S+);/) {
-                    my $type_name;
+                    my $type_name = $1; $type_name .= $2;
                     my $arg_name = $3;
 
-                    $type_name = $1 if ($1);
-                    $type_name .= $2;
-                    $type_name =~ s/hyper/long/;
-
-                    # SPECIAL: some hyper parameters map to long longs
-                    if (($call->{ProcName} eq "DomainMigrateSetMaxDowntime" and
-                         $arg_name eq "downtime") or
-                        ($call->{ProcName} eq "StorageVolUpload" and
-                         ($arg_name eq "offset" or $arg_name eq "length")) or
-                        ($call->{ProcName} eq "StorageVolDownload" and
-                         ($arg_name eq "offset" or $arg_name eq "length"))) {
-                        $type_name .= " long";
-                    }
+                    $type_name =~ s/hyper/long long/;
 
                     push(@args_list, "$type_name $arg_name");
                     push(@setters_list, "args.$arg_name = $arg_name;");
@@ -960,18 +1052,7 @@ elsif ($opt_k) {
 
             foreach my $ret_member (@{$call->{ret_members}}) {
                 if ($multi_ret) {
-                    if ($ret_member =~ m/^(unsigned )?(char|short|int|hyper) (\S+)\[\S+\];/) {
-                        push(@ret_list, "memcpy(result->$3, ret.$3, sizeof result->$3);");
-                    } elsif ($ret_member =~ m/<\S+>;/ or $ret_member =~ m/\[\S+\];/) {
-                        # just make all other array types fail
-                        die "unhandled type for multi-return-value for " .
-                            "procedure $call->{name}: $ret_member";
-                    } elsif ($ret_member =~ m/^(unsigned )?(char|short|int|hyper) (\S+);/) {
-                        push(@ret_list, "result->$3 = ret.$3;");
-                    } else {
-                        die "unhandled type for multi-return-value for " .
-                            "procedure $call->{name}: $ret_member";
-                    }
+                    push(@ret_list, handle_multi_ret_member("result", "ret", $ret_member, 1));
                 } elsif ($ret_member =~ m/^remote_nonnull_string (\S+)<(\S+)>;\s*\/\*\s*insert@(\d+)\s*\*\//) {
                     splice(@args_list, int($3), 0, ("char **const $1"));
                     push(@ret_list, "rv = ret.$1.$1_len;");
@@ -1025,37 +1106,44 @@ elsif ($opt_k) {
                         $single_ret_var = "vir${type_name}Ptr rv = NULL";
                         $single_ret_type = "vir${type_name}Ptr";
                     }
-                } elsif ($ret_member =~ m/^int (\S+);/) {
-                    my $arg_name = $1;
+                } elsif ($ret_member =~ m/^(unsigned )?hyper (\S+);\s*\/\*\s*(long|ulong)\s*\*\//) {
+                    if ((!$1 and $3 ne "long") or ($1 and $3 ne "ulong")) {
+                        die "sign mismatch in [unsigned] hyper annotation: $ret_member";
+                    }
 
-                    if ($call->{ProcName} =~ m/GetAutostart$/) {
-                        push(@args_list, "int *$arg_name");
-                        push(@ret_list, "if ($arg_name) *$arg_name = ret.$arg_name;");
+                    my $type_name = $1; $type_name .= "long";
+                    my $arg_name = $2;
+                    my $default = "-1"; $default = "0" if ($1);
+                    my $sign = ""; $sign = "U" if ($1);
+
+                    if ($call->{ProcName} =~ m/Get(Lib)?Version/) {
+                        push(@args_list, "$type_name *$arg_name");
+                        push(@ret_list, "if ($arg_name) HYPER_TO_${sign}LONG(*$arg_name, ret.$arg_name);");
                         push(@ret_list, "rv = 0;");
+                        $single_ret_var = "int rv = -1";
+                        $single_ret_type = "int";
                     } else {
-                        push(@ret_list, "rv = ret.$arg_name;");
+                        push(@ret_list, "HYPER_TO_${sign}LONG(rv, ret.$arg_name);");
+                        $single_ret_var = "$type_name rv = $default";
+                        $single_ret_type = "$type_name";
                     }
+                } elsif ($ret_member =~ m/^(unsigned )?(int|hyper) (\S+);/) {
+                    my $type_name = $1; $type_name .= $2;
+                    my $arg_name = $3;
+                    my $default = "-1"; $default = "0" if ($1);
 
-                    $single_ret_var = "int rv = -1";
-                    $single_ret_type = "int";
-                } elsif ($ret_member =~ m/^unsigned hyper (\S+);/) {
-                    my $arg_name = $1;
+                    $type_name =~ s/hyper/long long/;
 
-                    if ($call->{ProcName} =~ m/Get(Lib)?Version/) {
-                        push(@args_list, "unsigned long *$arg_name");
+                    if ($call->{ProcName} =~ m/GetAutostart$/) {
+                        push(@args_list, "int *$arg_name");
                         push(@ret_list, "if ($arg_name) *$arg_name = ret.$arg_name;");
                         push(@ret_list, "rv = 0;");
-                        $single_ret_var = "int rv = -1";
-                        $single_ret_type = "int";
-                    } elsif ($call->{ProcName} eq "NodeGetFreeMemory") {
-                        push(@ret_list, "rv = ret.$arg_name;");
-                        $single_ret_var = "unsigned long long rv = 0";
-                        $single_ret_type = "unsigned long long";
                     } else {
                         push(@ret_list, "rv = ret.$arg_name;");
-                        $single_ret_var = "unsigned long rv = 0";
-                        $single_ret_type = "unsigned long";
                     }
+
+                    $single_ret_var = "$type_name rv = $default";
+                    $single_ret_type = "$type_name";
                 } elsif ($ret_member =~ m/^(\/)?\*/) {
                     # ignore comments
                 } else {
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index d6bf7c3..75c7db3 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -87,6 +87,24 @@
 
 #define VIR_FROM_THIS VIR_FROM_REMOTE
 
+#define HYPER_TO_TYPE(_type, _to, _from)                                      \
+    do {                                                                      \
+        if ((_from) != (_type)(_from)) {                                      \
+            remoteError(VIR_ERR_INTERNAL_ERROR,                               \
+                        _("conversion from hyper to %s overflowed"), #_type); \
+            goto done;                                                        \
+        }                                                                     \
+        (_to) = (_from);                                                      \
+    } while (0)
+
+#if SIZEOF_LONG < 8
+# define HYPER_TO_LONG(_to, _from) HYPER_TO_TYPE(long, _to, _from)
+# define HYPER_TO_ULONG(_to, _from) HYPER_TO_TYPE(unsigned long, _to, _from)
+#else
+# define HYPER_TO_LONG(_to, _from) (_to) = (_from)
+# define HYPER_TO_ULONG(_to, _from) (_to) = (_from)
+#endif
+
 static int inside_daemon = 0;
 
 struct remote_thread_call;
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index 0602c27..ff31d57 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -331,7 +331,13 @@ struct remote_typed_param {
  *
  * 'remote_CALL_ret' members that are filled via call-by-reference must be
  * annotated with a insert@<offset> comment to indicate the offset in the
- * parameter list of the function to be called. */
+ * parameter list of the function to be called.
+ *
+ * 'remote_CALL_args' and 'remote_CALL_ret' members of type hyper that map
+ * to long must be annotated wit long or ulong.  This is considered as
+ * legacy support.  All hyper members that already map to long long and
+ * future hyper additions to the protocol are not annotated.  long long is
+ * the default from now on. */
 
 struct remote_open_args {
     /* NB. "name" might be NULL although in practice you can't
@@ -354,11 +360,11 @@ struct remote_get_type_ret {
 };
 
 struct remote_get_version_ret {
-    unsigned hyper hv_ver;
+    unsigned hyper hv_ver; /* ulong */
 };
 
 struct remote_get_lib_version_ret {
-    unsigned hyper lib_ver;
+    unsigned hyper lib_ver; /* ulong */
 };
 
 struct remote_get_hostname_ret {
@@ -390,7 +396,7 @@ struct remote_get_max_vcpus_ret {
 
 struct remote_node_get_info_ret {
     char model[32];
-    unsigned hyper memory;
+    unsigned hyper memory; /* ulong */
     int cpus;
     int mhz;
     int nodes;
@@ -647,22 +653,22 @@ struct remote_domain_get_max_memory_args {
 };
 
 struct remote_domain_get_max_memory_ret {
-    unsigned hyper memory;
+    unsigned hyper memory; /* ulong */
 };
 
 struct remote_domain_set_max_memory_args {
     remote_nonnull_domain dom;
-    unsigned hyper memory;
+    unsigned hyper memory; /* ulong */
 };
 
 struct remote_domain_set_memory_args {
     remote_nonnull_domain dom;
-    unsigned hyper memory;
+    unsigned hyper memory; /* ulong */
 };
 
 struct remote_domain_set_memory_flags_args {
     remote_nonnull_domain dom;
-    unsigned hyper memory;
+    unsigned hyper memory; /* ulong */
     unsigned int flags;
 };
 
@@ -672,8 +678,8 @@ struct remote_domain_get_info_args {
 
 struct remote_domain_get_info_ret {
     unsigned char state;
-    unsigned hyper maxMem;
-    unsigned hyper memory;
+    unsigned hyper maxMem; /* ulong */
+    unsigned hyper memory; /* ulong */
     unsigned short nrVirtCpu;
     unsigned hyper cpuTime;
 };
@@ -728,16 +734,16 @@ struct remote_domain_migrate_perform_args {
     remote_nonnull_domain dom;
     opaque cookie<REMOTE_MIGRATE_COOKIE_MAX>;
     remote_nonnull_string uri;
-    unsigned hyper flags;
+    unsigned hyper flags; /* ulong */
     remote_string dname;
-    unsigned hyper resource;
+    unsigned hyper resource; /* ulong */
 };
 
 struct remote_domain_migrate_finish_args {
     remote_nonnull_string dname;
     opaque cookie<REMOTE_MIGRATE_COOKIE_MAX>;
     remote_nonnull_string uri;
-    unsigned hyper flags;
+    unsigned hyper flags; /* ulong */
 };
 
 struct remote_domain_migrate_finish_ret {
@@ -746,9 +752,9 @@ struct remote_domain_migrate_finish_ret {
 
 struct remote_domain_migrate_prepare2_args {
     remote_string uri_in;
-    unsigned hyper flags;
+    unsigned hyper flags; /* ulong */
     remote_string dname;
-    unsigned hyper resource;
+    unsigned hyper resource; /* ulong */
     remote_nonnull_string dom_xml;
 };
 
@@ -761,7 +767,7 @@ struct remote_domain_migrate_finish2_args {
     remote_nonnull_string dname;
     opaque cookie<REMOTE_MIGRATE_COOKIE_MAX>;
     remote_nonnull_string uri;
-    unsigned hyper flags;
+    unsigned hyper flags; /* ulong */
     int retcode;
 };
 
@@ -1631,9 +1637,9 @@ struct remote_secret_lookup_by_usage_ret {
 };
 
 struct remote_domain_migrate_prepare_tunnel_args {
-    unsigned hyper flags;
+    unsigned hyper flags; /* ulong */
     remote_string dname;
-    unsigned hyper resource;
+    unsigned hyper resource; /* ulong */
     remote_nonnull_string dom_xml;
 };
 
@@ -1768,7 +1774,7 @@ struct remote_domain_migrate_set_max_downtime_args {
 
 struct remote_domain_migrate_set_max_speed_args {
     remote_nonnull_domain dom;
-    unsigned hyper bandwidth;
+    unsigned hyper bandwidth; /* ulong */
     unsigned int flags;
 };
 
@@ -1959,9 +1965,9 @@ struct remote_domain_get_state_ret {
 struct remote_domain_migrate_begin3_args {
     remote_nonnull_domain dom;
     remote_string xmlin;
-    unsigned hyper flags;
+    unsigned hyper flags; /* ulong */
     remote_string dname;
-    unsigned hyper resource;
+    unsigned hyper resource; /* ulong */
 };
 
 struct remote_domain_migrate_begin3_ret {
@@ -1972,9 +1978,9 @@ struct remote_domain_migrate_begin3_ret {
 struct remote_domain_migrate_prepare3_args {
     opaque cookie_in<REMOTE_MIGRATE_COOKIE_MAX>;
     remote_string uri_in;
-    unsigned hyper flags;
+    unsigned hyper flags; /* ulong */
     remote_string dname;
-    unsigned hyper resource;
+    unsigned hyper resource; /* ulong */
     remote_nonnull_string dom_xml;
 };
 
@@ -1985,9 +1991,9 @@ struct remote_domain_migrate_prepare3_ret {
 
 struct remote_domain_migrate_prepare_tunnel3_args {
     opaque cookie_in<REMOTE_MIGRATE_COOKIE_MAX>;
-    unsigned hyper flags;
+    unsigned hyper flags; /* ulong */
     remote_string dname;
-    unsigned hyper resource;
+    unsigned hyper resource; /* ulong */
     remote_nonnull_string dom_xml;
 };
 
@@ -2001,9 +2007,9 @@ struct remote_domain_migrate_perform3_args {
     opaque cookie_in<REMOTE_MIGRATE_COOKIE_MAX>;
     remote_string dconnuri;
     remote_string uri;
-    unsigned hyper flags;
+    unsigned hyper flags; /* ulong */
     remote_string dname;
-    unsigned hyper resource;
+    unsigned hyper resource; /* ulong */
 };
 
 struct remote_domain_migrate_perform3_ret {
@@ -2015,7 +2021,7 @@ struct remote_domain_migrate_finish3_args {
     opaque cookie_in<REMOTE_MIGRATE_COOKIE_MAX>;
     remote_string dconnuri;
     remote_string uri;
-    unsigned hyper flags;
+    unsigned hyper flags; /* ulong */
     int cancelled;
 };
 
@@ -2027,7 +2033,7 @@ struct remote_domain_migrate_finish3_ret {
 struct remote_domain_migrate_confirm3_args {
     remote_nonnull_domain dom;
     opaque cookie_in<REMOTE_MIGRATE_COOKIE_MAX>;
-    unsigned hyper flags;
+    unsigned hyper flags; /* ulong */
     int cancelled;
 };
 
-- 
1.7.0.4

From 726dae7b4c21d4c17ac19808c06d7fc978b36778 Mon Sep 17 00:00:00 2001
From: Matthias Bolte <matthias bolte googlemail com>
Date: Mon, 30 May 2011 12:58:57 +0200
Subject: [PATCH] remote generator: Legacy support for hyper to long mappings

Remove some special case code that took care of mapping hyper to the
correct C types.

As the list of procedures that is allowed to map hyper to long is fixed
put it in the generator instead annotations in the .x files. This
results in simpler .x file parsing code.

Use macros for hyper to long assignments that perform overflow checks
when long is smaller than hyper. Map hyper to long long by default.

Suggested by Eric Blake.
---
 configure.ac               |    1 +
 daemon/remote.c            |   18 +++++
 daemon/remote_generator.pl |  157 +++++++++++++++++++++++++++++++++++---------
 src/remote/remote_driver.c |   18 +++++
 4 files changed, 162 insertions(+), 32 deletions(-)

diff --git a/configure.ac b/configure.ac
index 55ae791..2ae7e1d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -117,6 +117,7 @@ if test "x$have_cpuid" = xyes; then
 fi
 AC_MSG_RESULT([$have_cpuid])
 
+AC_CHECK_SIZEOF(long)
 
 dnl Availability of various common functions (non-fatal if missing),
 dnl and various less common threadsafe functions
diff --git a/daemon/remote.c b/daemon/remote.c
index 3f13247..5bcf202 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -68,6 +68,24 @@
     virReportErrorHelper(VIR_FROM_THIS, code, __FILE__,           \
                          __FUNCTION__, __LINE__, __VA_ARGS__)
 
+#define HYPER_TO_TYPE(_type, _to, _from)                                      \
+    do {                                                                      \
+        if ((_from) != (_type)(_from)) {                                      \
+            virNetError(VIR_ERR_INTERNAL_ERROR,                               \
+                        _("conversion from hyper to %s overflowed"), #_type); \
+            goto cleanup;                                                     \
+        }                                                                     \
+        (_to) = (_from);                                                      \
+    } while (0)
+
+#if SIZEOF_LONG < 8
+# define HYPER_TO_LONG(_to, _from) HYPER_TO_TYPE(long, _to, _from)
+# define HYPER_TO_ULONG(_to, _from) HYPER_TO_TYPE(unsigned long, _to, _from)
+#else
+# define HYPER_TO_LONG(_to, _from) (_to) = (_from)
+# define HYPER_TO_ULONG(_to, _from) (_to) = (_from)
+#endif
+
 static virDomainPtr get_nonnull_domain(virConnectPtr conn, remote_nonnull_domain domain);
 static virNetworkPtr get_nonnull_network(virConnectPtr conn, remote_nonnull_network network);
 static virInterfacePtr get_nonnull_interface(virConnectPtr conn, remote_nonnull_interface iface);
diff --git a/daemon/remote_generator.pl b/daemon/remote_generator.pl
index ac808fb..e901acd 100755
--- a/daemon/remote_generator.pl
+++ b/daemon/remote_generator.pl
@@ -174,6 +174,58 @@ while (<PROTOCOL>) {
 
 close(PROTOCOL);
 
+# this dict contains the procedures that are allowed to map [unsigend] hyper
+# to [unsigend] long for legacy reasons in their signature and return type.
+# this list is fixed. new procedures and public APIs have to map [unsigend]
+# hyper to [unsigend] long long
+my $long_legacy = {
+    DomainGetMaxMemory          => { ret => { memory => 1 } },
+    DomainGetInfo               => { ret => { maxMem => 1, memory => 1 } },
+    DomainMigrate               => { arg => { flags => 1, resource => 1 } },
+    DomainMigrate2              => { arg => { flags => 1, resource => 1 } },
+    DomainMigrateBegin3         => { arg => { flags => 1, resource => 1 } },
+    DomainMigrateConfirm3       => { arg => { flags => 1, resource => 1 } },
+    DomainMigrateDirect         => { arg => { flags => 1, resource => 1 } },
+    DomainMigrateFinish         => { arg => { flags => 1 } },
+    DomainMigrateFinish2        => { arg => { flags => 1 } },
+    DomainMigrateFinish3        => { arg => { flags => 1 } },
+    DomainMigratePeer2Peer      => { arg => { flags => 1, resource => 1 } },
+    DomainMigratePerform        => { arg => { flags => 1, resource => 1 } },
+    DomainMigratePerform3       => { arg => { flags => 1, resource => 1 } },
+    DomainMigratePrepare        => { arg => { flags => 1, resource => 1 } },
+    DomainMigratePrepare2       => { arg => { flags => 1, resource => 1 } },
+    DomainMigratePrepare3       => { arg => { flags => 1, resource => 1 } },
+    DomainMigratePrepareTunnel  => { arg => { flags => 1, resource => 1 } },
+    DomainMigratePrepareTunnel3 => { arg => { flags => 1, resource => 1 } },
+    DomainMigrateToURI          => { arg => { flags => 1, resource => 1 } },
+    DomainMigrateToURI2         => { arg => { flags => 1, resource => 1 } },
+    DomainMigrateVersion1       => { arg => { flags => 1, resource => 1 } },
+    DomainMigrateVersion2       => { arg => { flags => 1, resource => 1 } },
+    DomainMigrateVersion3       => { arg => { flags => 1, resource => 1 } },
+    DomainMigrateSetMaxSpeed    => { arg => { bandwidth => 1 } },
+    DomainSetMaxMemory          => { arg => { memory => 1 } },
+    DomainSetMemory             => { arg => { memory => 1 } },
+    DomainSetMemoryFlags        => { arg => { memory => 1 } },
+    GetLibVersion               => { ret => { lib_ver => 1 } },
+    GetVersion                  => { ret => { hv_ver => 1 } },
+    NodeGetInfo                 => { ret => { memory => 1 } },
+};
+
+sub hyper_to_long
+{
+    my $proc_name = shift;
+    my $ret_or_arg = shift;
+    my $member = shift;
+
+    if ($long_legacy->{$proc_name} and
+        $long_legacy->{$proc_name}->{$ret_or_arg} and
+        $long_legacy->{$proc_name}->{$ret_or_arg}->{$member}) {
+        return 1;
+    } else {
+        return 0
+    }
+}
+
 #----------------------------------------------------------------------
 # Output
 
@@ -378,12 +430,29 @@ elsif ($opt_b) {
                     }
 
                     push(@args_list, "args->$1");
-                } elsif ($args_member =~ m/^(unsigned )?(int|hyper) (\S+);/) {
+                } elsif ($args_member =~ m/^(unsigned )?int (\S+);/) {
                     if (! @args_list) {
                         push(@args_list, "conn");
                     }
 
-                    push(@args_list, "args->$3");
+                    push(@args_list, "args->$2");
+                } elsif ($args_member =~ m/^(unsigned )?hyper (\S+);/) {
+                    if (! @args_list) {
+                        push(@args_list, "conn");
+                    }
+
+                    my $arg_name = $2;
+
+                    if (hyper_to_long($call->{ProcName}, "arg", $arg_name)) {
+                        my $type_name = $1; $type_name .= "long";
+                        my $sign = ""; $sign = "U" if ($1);
+
+                        push(@vars_list, "$type_name $arg_name");
+                        push(@getters_list, "    HYPER_TO_${sign}LONG($arg_name, args->$arg_name);\n");
+                        push(@args_list, "$arg_name");
+                    } else {
+                        push(@args_list, "args->$arg_name");
+                    }
                 } elsif ($args_member =~ m/^(\/)?\*/) {
                     # ignore comments
                 } else {
@@ -411,6 +480,10 @@ elsif ($opt_b) {
             foreach my $ret_member (@{$call->{ret_members}}) {
                 if ($multi_ret) {
                     if ($ret_member =~ m/^(unsigned )?(char|short|int|hyper) (\S+)\[\S+\];/) {
+                        if ($2 eq "hyper" and hyper_to_long($call->{ProcName}, "ret", $3)) {
+                            die "legacy [u]long hyper arrays aren't supported";
+                        }
+
                         push(@ret_list, "memcpy(ret->$3, tmp.$3, sizeof ret->$3);");
                     } elsif ($ret_member =~ m/^(unsigned )?(char|short|int|hyper) (\S+);/) {
                         push(@ret_list, "ret->$3 = tmp.$3;");
@@ -502,6 +575,10 @@ elsif ($opt_b) {
                         }
                     }
                 } elsif ($ret_member =~ m/^(?:unsigned )?hyper (\S+)<(\S+)>;\s*\/\*\s*insert@(\d+)\s*\*\//) {
+                    if (hyper_to_long($call->{ProcName}, "ret", $1)) {
+                        die "legacy [u]long hyper arrays aren't supported";
+                    }
+
                     push(@vars_list, "int len");
                     push(@ret_list, "ret->$1.$1_len = len;");
                     push(@free_list_on_error, "VIR_FREE(ret->$1.$1_val);");
@@ -523,14 +600,22 @@ elsif ($opt_b) {
                     # error out on unannotated arrays
                     die "hyper array without insert@<offset> annotation: $ret_member";
                 } elsif ($ret_member =~ m/^(unsigned )?hyper (\S+);/) {
-                    my $type_name;
+                    my $type_name = $1;
                     my $ret_name = $2;
+                    my $ret_assign;
 
-                    $type_name = $1 if ($1);
-                    $type_name .= "long";
+                    if (hyper_to_long($call->{ProcName}, "ret", $ret_name)) {
+                        my $sign = ""; $sign = "U" if ($1);
+
+                        $type_name .= "long";
+                        $ret_assign = "HYPER_TO_${sign}LONG(ret->$ret_name, $ret_name);";
+                    } else {
+                        $type_name .= "long long";
+                        $ret_assign = "ret->$ret_name = $ret_name;";
+                    }
 
                     push(@vars_list, "$type_name $ret_name");
-                    push(@ret_list, "ret->$ret_name = $ret_name;");
+                    push(@ret_list, $ret_assign);
                     $single_ret_var = $ret_name;
 
                     if ($call->{ProcName} eq "DomainGetMaxMemory" or
@@ -888,22 +973,20 @@ elsif ($opt_k) {
                     push(@setters_list, "args.$arg_name.${arg_name}_val = (char *)$arg_name;");
                     push(@setters_list, "args.$arg_name.${arg_name}_len = ${arg_name}len;");
                     push(@args_check_list, { name => "\"$arg_name\"", arg => "${arg_name}len", limit => $limit });
-                } elsif ($args_member =~ m/^(unsigned )?(int|hyper) (\S+);/) {
-                    my $type_name;
-                    my $arg_name = $3;
-
-                    $type_name = $1 if ($1);
-                    $type_name .= $2;
-                    $type_name =~ s/hyper/long/;
-
-                    # SPECIAL: some hyper parameters map to long longs
-                    if (($call->{ProcName} eq "DomainMigrateSetMaxDowntime" and
-                         $arg_name eq "downtime") or
-                        ($call->{ProcName} eq "StorageVolUpload" and
-                         ($arg_name eq "offset" or $arg_name eq "length")) or
-                        ($call->{ProcName} eq "StorageVolDownload" and
-                         ($arg_name eq "offset" or $arg_name eq "length"))) {
-                        $type_name .= " long";
+                } elsif ($args_member =~ m/^(unsigned )?int (\S+);/) {
+                    my $type_name = $1; $type_name .= "int";
+                    my $arg_name = $2;
+
+                    push(@args_list, "$type_name $arg_name");
+                    push(@setters_list, "args.$arg_name = $arg_name;");
+                } elsif ($args_member =~ m/^(unsigned )?hyper (\S+);/) {
+                    my $type_name = $1;
+                    my $arg_name = $2;
+
+                    if (hyper_to_long($call->{ProcName}, "arg", $arg_name)) {
+                        $type_name .= "long";
+                    } else {
+                        $type_name .= "long long";
                     }
 
                     push(@args_list, "$type_name $arg_name");
@@ -961,13 +1044,23 @@ elsif ($opt_k) {
             foreach my $ret_member (@{$call->{ret_members}}) {
                 if ($multi_ret) {
                     if ($ret_member =~ m/^(unsigned )?(char|short|int|hyper) (\S+)\[\S+\];/) {
+                        if ($2 eq "hyper" and hyper_to_long($call->{ProcName}, "ret", $3)) {
+                            die "legacy [u]long hyper arrays aren't supported";
+                        }
+
                         push(@ret_list, "memcpy(result->$3, ret.$3, sizeof result->$3);");
                     } elsif ($ret_member =~ m/<\S+>;/ or $ret_member =~ m/\[\S+\];/) {
                         # just make all other array types fail
                         die "unhandled type for multi-return-value for " .
                             "procedure $call->{name}: $ret_member";
                     } elsif ($ret_member =~ m/^(unsigned )?(char|short|int|hyper) (\S+);/) {
-                        push(@ret_list, "result->$3 = ret.$3;");
+                        if ($2 eq "hyper" and hyper_to_long($call->{ProcName}, "ret", $3)) {
+                            my $sign = ""; $sign = "U" if ($1);
+
+                            push(@ret_list, "HYPER_TO_${sign}LONG(result->$3, ret.$3);");
+                        } else {
+                            push(@ret_list, "result->$3 = ret.$3;");
+                        }
                     } else {
                         die "unhandled type for multi-return-value for " .
                             "procedure $call->{name}: $ret_member";
@@ -1039,22 +1132,22 @@ elsif ($opt_k) {
                     $single_ret_var = "int rv = -1";
                     $single_ret_type = "int";
                 } elsif ($ret_member =~ m/^unsigned hyper (\S+);/) {
-                    my $arg_name = $1;
+                    my $ret_name = $1;
 
                     if ($call->{ProcName} =~ m/Get(Lib)?Version/) {
-                        push(@args_list, "unsigned long *$arg_name");
-                        push(@ret_list, "if ($arg_name) *$arg_name = ret.$arg_name;");
+                        push(@args_list, "unsigned long *$ret_name");
+                        push(@ret_list, "if ($ret_name) HYPER_TO_ULONG(*$ret_name, ret.$ret_name);");
                         push(@ret_list, "rv = 0;");
                         $single_ret_var = "int rv = -1";
                         $single_ret_type = "int";
-                    } elsif ($call->{ProcName} eq "NodeGetFreeMemory") {
-                        push(@ret_list, "rv = ret.$arg_name;");
-                        $single_ret_var = "unsigned long long rv = 0";
-                        $single_ret_type = "unsigned long long";
-                    } else {
-                        push(@ret_list, "rv = ret.$arg_name;");
+                    } elsif (hyper_to_long($call->{ProcName}, "ret", $ret_name)) {
+                        push(@ret_list, "HYPER_TO_ULONG(rv, ret.$ret_name);");
                         $single_ret_var = "unsigned long rv = 0";
                         $single_ret_type = "unsigned long";
+                    } else {
+                        push(@ret_list, "rv = ret.$ret_name;");
+                        $single_ret_var = "unsigned long long rv = 0";
+                        $single_ret_type = "unsigned long long";
                     }
                 } elsif ($ret_member =~ m/^(\/)?\*/) {
                     # ignore comments
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index d6bf7c3..75c7db3 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -87,6 +87,24 @@
 
 #define VIR_FROM_THIS VIR_FROM_REMOTE
 
+#define HYPER_TO_TYPE(_type, _to, _from)                                      \
+    do {                                                                      \
+        if ((_from) != (_type)(_from)) {                                      \
+            remoteError(VIR_ERR_INTERNAL_ERROR,                               \
+                        _("conversion from hyper to %s overflowed"), #_type); \
+            goto done;                                                        \
+        }                                                                     \
+        (_to) = (_from);                                                      \
+    } while (0)
+
+#if SIZEOF_LONG < 8
+# define HYPER_TO_LONG(_to, _from) HYPER_TO_TYPE(long, _to, _from)
+# define HYPER_TO_ULONG(_to, _from) HYPER_TO_TYPE(unsigned long, _to, _from)
+#else
+# define HYPER_TO_LONG(_to, _from) (_to) = (_from)
+# define HYPER_TO_ULONG(_to, _from) (_to) = (_from)
+#endif
+
 static int inside_daemon = 0;
 
 struct remote_thread_call;
-- 
1.7.0.4

From 3bb05f7543f86e3b47772f0fabecbda4f167b3bc Mon Sep 17 00:00:00 2001
From: Matthias Bolte <matthias bolte googlemail com>
Date: Mon, 30 May 2011 14:36:41 +0200
Subject: [PATCH] apibuild: Restrict long usage to existing functions and struct

New APIs have to use long long instead of long.

Also make apibuild errors fatal.
---
 docs/Makefile.am |    2 +-
 docs/apibuild.py |   74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 75 insertions(+), 1 deletions(-)

diff --git a/docs/Makefile.am b/docs/Makefile.am
index 59ae685..a98f08d 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -179,7 +179,7 @@ $(python_generated_files): $(srcdir)/apibuild.py \
 		$(srcdir)/../include/libvirt/*.h \
 		$(srcdir)/../src/libvirt.c \
 		$(srcdir)/../src/util/virterror.c
-	-srcdir=$(srcdir) $(srcdir)/apibuild.py
+	srcdir=$(srcdir) $(srcdir)/apibuild.py
 
 check-local: all
 
diff --git a/docs/apibuild.py b/docs/apibuild.py
index 2ab0599..2dc2e9d 100755
--- a/docs/apibuild.py
+++ b/docs/apibuild.py
@@ -1480,6 +1480,77 @@ class CParser:
         self.signature = signature
         return token
 
+    # this dict contains the functions that are allowed to use [unsigend]
+    # long for legacy reasons in their signature and return type. this list is
+    # fixed. new procedures and public APIs have to use [unsigend] long long
+    long_legacy_functions = \
+      { "virGetVersion"                  : (False, ("libVer", "typeVer")),
+        "virConnectGetLibVersion"        : (False, ("libVer")),
+        "virConnectGetVersion"           : (False, ("hvVer")),
+        "virDomainGetMaxMemory"          : (True,  ()),
+        "virDomainMigrate"               : (False, ("flags", "bandwidth")),
+        "virDomainMigrate2"              : (False, ("flags", "bandwidth")),
+        "virDomainMigrateBegin3"         : (False, ("flags", "bandwidth")),
+        "virDomainMigrateConfirm3"       : (False, ("flags", "bandwidth")),
+        "virDomainMigrateDirect"         : (False, ("flags", "bandwidth")),
+        "virDomainMigrateFinish"         : (False, ("flags")),
+        "virDomainMigrateFinish2"        : (False, ("flags")),
+        "virDomainMigrateFinish3"        : (False, ("flags")),
+        "virDomainMigratePeer2Peer"      : (False, ("flags", "bandwidth")),
+        "virDomainMigratePerform"        : (False, ("flags", "bandwidth")),
+        "virDomainMigratePerform3"       : (False, ("flags", "bandwidth")),
+        "virDomainMigratePrepare"        : (False, ("flags", "bandwidth")),
+        "virDomainMigratePrepare2"       : (False, ("flags", "bandwidth")),
+        "virDomainMigratePrepare3"       : (False, ("flags", "bandwidth")),
+        "virDomainMigratePrepareTunnel"  : (False, ("flags", "bandwidth")),
+        "virDomainMigratePrepareTunnel3" : (False, ("flags", "bandwidth")),
+        "virDomainMigrateToURI"          : (False, ("flags", "bandwidth")),
+        "virDomainMigrateToURI2"         : (False, ("flags", "bandwidth")),
+        "virDomainMigrateVersion1"       : (False, ("flags", "bandwidth")),
+        "virDomainMigrateVersion2"       : (False, ("flags", "bandwidth")),
+        "virDomainMigrateVersion3"       : (False, ("flags", "bandwidth")),
+        "virDomainMigrateSetMaxSpeed"    : (False, ("bandwidth")),
+        "virDomainSetMaxMemory"          : (False, ("memory")),
+        "virDomainSetMemory"             : (False, ("memory")),
+        "virDomainSetMemoryFlags"        : (False, ("memory")) }
+
+    def checkLongLegacyFunction(self, name, return_type, signature):
+        if "long" in return_type and "long long" not in return_type:
+            try:
+                if not CParser.long_legacy_functions[name][0]:
+                    raise Exception()
+            except:
+                self.error(("function '%s' is not allowed to return long, "
+                            "use long long instead") % (name))
+
+        for param in signature:
+            if "long" in param[0] and "long long" not in param[0]:
+                try:
+                    if param[1] not in CParser.long_legacy_functions[name][1]:
+                        raise Exception()
+                except:
+                    self.error(("function '%s' is not allowed to take long "
+                                "parameter '%s', use long long instead")
+                               % (name, param[1]))
+
+    # this dict contains the structs that are allowed to use [unsigend]
+    # long for legacy reasons. this list is fixed. new structs have to use
+    # [unsigend] long long
+    long_legacy_struct_fields = \
+      { "_virDomainInfo"                 : ("maxMem", "memory"),
+        "_virNodeInfo"                   : ("memory") }
+
+    def checkLongLegacyStruct(self, name, fields):
+        for field in fields:
+            if "long" in field[0] and "long long" not in field[0]:
+                try:
+                    if field[1] not in CParser.long_legacy_struct_fields[name]:
+                        raise Exception()
+                except:
+                    self.error(("struct '%s' is not allowed to contain long "
+                                "field '%s', use long long instead") \
+                               % (name, field[1]))
+
      #
      # Parse a global definition, be it a type, variable or function
      # the extern "C" blocks are a bit nasty and require it to recurse.
@@ -1562,6 +1633,7 @@ class CParser:
                     self.comment = None
                     token = self.token()
                     if type == "struct":
+                        self.checkLongLegacyStruct(self.name, self.struct_fields)
                         self.index_add(self.name, self.filename,
                              not self.is_header, "struct", self.struct_fields)
                     else:
@@ -1574,12 +1646,14 @@ class CParser:
                     if token == None:
                         return None
                     if token[0] == "sep" and token[1] == ";":
+                        self.checkLongLegacyFunction(self.name, type, self.signature)
                         d = self.mergeFunctionComment(self.name,
                                 ((type, None), self.signature), 1)
                         self.index_add(self.name, self.filename, static,
                                         "function", d)
                         token = self.token()
                     elif token[0] == "sep" and token[1] == "{":
+                        self.checkLongLegacyFunction(self.name, type, self.signature)
                         d = self.mergeFunctionComment(self.name,
                                 ((type, None), self.signature), static)
                         self.index_add(self.name, self.filename, static,
-- 
1.7.0.4


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]