Updated to version 1.6.4.
[rsync/rsync.git] / popt / poptparse.c
index 8f00769..2ffb7dd 100644 (file)
@@ -1,6 +1,10 @@
-/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
+/** \ingroup popt
+ * \file popt/poptparse.c
+ */
+
+/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
    file accompanying popt source distributions, available from 
-   ftp://ftp.redhat.com/pub/code/popt */
+   ftp://ftp.rpm.org/pub/rpm/dist. */
 
 #include "system.h"
 
@@ -14,6 +18,8 @@ int poptDupArgv(int argc, const char **argv,
     char * dst;
     int i;
 
+    if (argc <= 0 || argv == NULL)     /* XXX can't happen */
+       return POPT_ERROR_NOARG;
     for (i = 0; i < argc; i++) {
        if (argv[i] == NULL)
            return POPT_ERROR_NOARG;
@@ -21,17 +27,27 @@ int poptDupArgv(int argc, const char **argv,
     }
        
     dst = malloc(nb);
+    if (dst == NULL)                   /* XXX can't happen */
+       return POPT_ERROR_MALLOC;
     argv2 = (void *) dst;
     dst += (argc + 1) * sizeof(*argv);
 
+    /*@-branchstate@*/
     for (i = 0; i < argc; i++) {
        argv2[i] = dst;
        dst += strlen(strcpy(dst, argv[i])) + 1;
     }
+    /*@=branchstate@*/
     argv2[argc] = NULL;
 
-    *argvPtr = argv2;
-    *argcPtr = argc;
+    if (argvPtr) {
+       *argvPtr = argv2;
+    } else {
+       free(argv2);
+       argv2 = NULL;
+    }
+    if (argcPtr)
+       *argcPtr = argc;
     return 0;
 }
 
@@ -43,31 +59,32 @@ int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
     const char ** argv = malloc(sizeof(*argv) * argvAlloced);
     int argc = 0;
     int buflen = strlen(s) + 1;
-    char *buf0 = calloc(buflen, 1);
-    char *buf = buf0;
+    char * buf = memset(alloca(buflen), 0, buflen);
+    int rc = POPT_ERROR_MALLOC;
 
+    if (argv == NULL) return rc;
     argv[argc] = buf;
 
-    for (src = s; *src; src++) {
+    for (src = s; *src != '\0'; src++) {
        if (quote == *src) {
            quote = '\0';
-       } else if (quote) {
+       } else if (quote != '\0') {
            if (*src == '\\') {
                src++;
                if (!*src) {
-                   free(argv);
-                   free(buf0);
-                   return POPT_ERROR_BADQUOTE;
+                   rc = POPT_ERROR_BADQUOTE;
+                   goto exit;
                }
                if (*src != quote) *buf++ = '\\';
            }
            *buf++ = *src;
        } else if (isspace(*src)) {
-           if (*argv[argc]) {
+           if (*argv[argc] != '\0') {
                buf++, argc++;
                if (argc == argvAlloced) {
                    argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA;
                    argv = realloc(argv, sizeof(*argv) * argvAlloced);
+                   if (argv == NULL) goto exit;
                }
                argv[argc] = buf;
            }
@@ -75,18 +92,17 @@ int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
          case '"':
          case '\'':
            quote = *src;
-           break;
+           /*@switchbreak@*/ break;
          case '\\':
            src++;
            if (!*src) {
-               free(argv);
-               free(buf0);
-               return POPT_ERROR_BADQUOTE;
+               rc = POPT_ERROR_BADQUOTE;
+               goto exit;
            }
            /*@fallthrough@*/
          default:
            *buf++ = *src;
-           break;
+           /*@switchbreak@*/ break;
        }
     }
 
@@ -94,9 +110,9 @@ int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
        argc++, buf++;
     }
 
-    (void) poptDupArgv(argc, argv, argcPtr, argvPtr);
+    rc = poptDupArgv(argc, argv, argcPtr, argvPtr);
 
-    free(argv);
-    free(buf0);
-    return 0;
+exit:
+    if (argv) free(argv);
+    return rc;
 }