On 03/07/2011 11:46 AM, Michal Privoznik wrote:
This is needed to detect situations when optional argument was
specified with non-integer value: '--int-opt foo'. To keep functions
uniform vshCommandOptString function was also changed, because it
returns tri-state value as well. Given result pointer is updated only
in case of success. If parsing fails, result is not updated at all.
diff --git a/tools/virsh.c b/tools/virsh.c
index f3754d7..c274a6b 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -252,13 +252,14 @@ static const vshCmdGrp *vshCmdGrpSearch(const char *grpname);
static int vshCmdGrpHelp(vshControl *ctl, const char *name);
static vshCmdOpt *vshCommandOpt(const vshCmd *cmd, const char *name);
-static int vshCommandOptInt(const vshCmd *cmd, const char *name, int *found);
-static unsigned long vshCommandOptUL(const vshCmd *cmd, const char *name,
- int *found);
-static char *vshCommandOptString(const vshCmd *cmd, const char *name,
- int *found);
Ouch - this was not const-correct pre-patch, but at least assigning
'char *' to 'const char *' is trivial...
-static long long vshCommandOptLongLong(const vshCmd *cmd, const char
*name,
- int *found);
+static int vshCommandOptInt(const vshCmd *cmd, const char *name, int *value)
+ ATTRIBUTE_NONNULL(3);
+static int vshCommandOptUL(const vshCmd *cmd, const char *name,
+ unsigned long *value) ATTRIBUTE_NONNULL(3);
+static int vshCommandOptString(const vshCmd *cmd, const char *name,
+ char **value) ATTRIBUTE_NONNULL(3);
whereas this rewrite exposes the const-correctness issue - you can't
pass 'const char* var; &var' to a 'char **' argument and still keep
the
compiler happy...
+static int vshCommandOptLongLong(const vshCmd *cmd, const char
*name,
+ unsigned long long *value) ATTRIBUTE_NONNULL(3);
static int vshCommandOptBool(const vshCmd *cmd, const char *name);
static char *vshCommandOptArgv(const vshCmd *cmd, int count);
@@ -589,9 +590,9 @@ static const vshCmdOptDef opts_help[] = {
static int
cmdHelp(vshControl *ctl, const vshCmd *cmd)
{
- const char *name;
+ char *name = NULL;
- name = vshCommandOptString(cmd, "command", NULL);
+ vshCommandOptString(cmd, "command", &name);
...leading to instances like this where you nukes const designators...
@@ -773,7 +773,7 @@ cmdConsole(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
int ret;
- const char *name;
+ const char *name = NULL;
if (!vshConnectionUsability(ctl, ctl->conn))
return FALSE;
@@ -781,7 +781,7 @@ cmdConsole(vshControl *ctl, const vshCmd *cmd)
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
return FALSE;
- name = vshCommandOptString(cmd, "devname", NULL);
+ vshCommandOptString(cmd, "devname", (char**) &name);
...or even worse, where you had to introduce a cast. Would you mind
splitting this into two patches?
The first patch should _just_ touch vshCommandOptString to change its
return type to const char *, and fix the fallout in the few functions
that need to be a bit more careful about type-safety. I already _know_
that cmdCd will be impacted: commit 5a814012 touched that function, and
exposed a place where we had been leaking memory when
vshCommandOptString returned NULL so we replaced things with a malloc'd
string, so there you will have to split things into using two variables,
one 'const char *' for vshCommandOptString, and the other 'char *' when
doing fallback. But hopefully most other functions will be okay with
using 'const char *' in the first place.
Then the second patch will swap argument order for all the vshCommandOpt
functions, including vshCommandOpt taking a const char ** third
argument, which should just work without any casts or removal of const
throughout the rest of the code.
That said,
@@ -1288,16 +1286,14 @@ static int
cmdDefine(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
- char *from;
- int found;
+ char *from = NULL;
int ret = TRUE;
char *buffer;
if (!vshConnectionUsability(ctl, ctl->conn))
return FALSE;
- from = vshCommandOptString(cmd, "file", &found);
- if (!found)
+ if (vshCommandOptString(cmd, "file", &from) <= 0)
return FALSE;
The rest of this patch (module the const issues) shows how nice the
change is! Your patch didn't include a diffstat, but it looks like you
have a net reduction in lines of code (always a good sign that the
cleanup was worth it).
@@ -2862,7 +2852,7 @@ cmdSetvcpus(vshControl *ctl, const vshCmd
*cmd)
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
return FALSE;
- count = vshCommandOptInt(cmd, "count", &count);
+ vshCommandOptInt(cmd, "count", &count);
Why the indentation change here?
@@ -2918,7 +2908,7 @@ cmdSetmem(vshControl *ctl, const vshCmd *cmd)
{
virDomainPtr dom;
virDomainInfo info;
- unsigned long kilobytes;
+ unsigned long kilobytes = 0;
int ret = TRUE;
if (!vshConnectionUsability(ctl, ctl->conn))
@@ -2927,7 +2917,7 @@ cmdSetmem(vshControl *ctl, const vshCmd *cmd)
if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
return FALSE;
- kilobytes = vshCommandOptUL(cmd, "kilobytes", NULL);
+ vshCommandOptUL(cmd, "kilobytes", &kilobytes);
if (kilobytes <= 0) {
virDomainFree(dom);
vshError(ctl, _("Invalid value of %lu for memory size"), kilobytes);
Hmm, I wonder if we should have been checking if vshCommandOptUL
returned a negative value. Then again, since you defaulted the value to
0, and the value is unchanged on error, and an explicit 0 is also
invalid, you still end up with the right error message.
If you change the helper functions to be ATTRIBUTE_RETURN_CHECK, then
the compiler would enforce that you check all vshCommandOpt* functions
for parse error.
/*
- * Returns option as INT
+ * @cmd command reference
+ * @name option name
+ * @value result
+ *
+ * Convert option to int
+ * Return value:
+ * >0 if option found and valid (@value updated)
+ * 0 in case option not found (@value untouched)
+ * <0 in all other cases (@value untouched)
*/
static int
-vshCommandOptInt(const vshCmd *cmd, const char *name, int *found)
+vshCommandOptInt(const vshCmd *cmd, const char *name, int *value)
{
vshCmdOpt *arg = vshCommandOpt(cmd, name);
- int res = 0, num_found = FALSE;
+ int ret = 0, num;
char *end_p = NULL;
if ((arg != NULL) && (arg->data != NULL)) {
- res = strtol(arg->data, &end_p, 10);
- if ((arg->data == end_p) || (*end_p!= 0))
- num_found = FALSE;
- else
- num_found = TRUE;
+ num = strtol(arg->data, &end_p, 10);
+ ret = -1;
+ if ((arg->data != end_p) && (*end_p == 0) && value) {
+ *value = num;
+ ret = 1;
+ }
}
- if (found)
- *found = num_found;
- return res;
+ return ret;
Nice! Exactly what I had in mind.
Looking forward to v3.
--
Eric Blake eblake(a)redhat.com +1-801-349-2682
Libvirt virtualization library
http://libvirt.org