let the popt replacement stuff survive a make proto
[samba.git] / source4 / lib / popt / poptparse.c
1 /* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
2    file accompanying popt source distributions, available from 
3    ftp://ftp.redhat.com/pub/code/popt */
4
5 #include "system.h"
6
7 #define POPT_ARGV_ARRAY_GROW_DELTA 5
8
9  int poptDupArgv(int argc, const char **argv,
10                 int * argcPtr, const char *** argvPtr)
11 {
12     size_t nb = (argc + 1) * sizeof(*argv);
13     const char ** argv2;
14     char * dst;
15     int i;
16
17     for (i = 0; i < argc; i++) {
18         if (argv[i] == NULL)
19             return POPT_ERROR_NOARG;
20         nb += strlen(argv[i]) + 1;
21     }
22         
23     dst = malloc(nb);
24     argv2 = (void *) dst;
25     dst += (argc + 1) * sizeof(*argv);
26
27     for (i = 0; i < argc; i++) {
28         argv2[i] = dst;
29         dst += strlen(strcpy(dst, argv[i])) + 1;
30     }
31     argv2[argc] = NULL;
32
33     *argvPtr = argv2;
34     *argcPtr = argc;
35     return 0;
36 }
37
38  int poptParseArgvString(const char * s, int * argcPtr, const char *** argvPtr)
39 {
40     const char * src;
41     char quote = '\0';
42     int argvAlloced = POPT_ARGV_ARRAY_GROW_DELTA;
43     const char ** argv = malloc(sizeof(*argv) * argvAlloced);
44     int argc = 0;
45     int buflen = strlen(s) + 1;
46     char *buf0 = calloc(buflen, 1);
47     char *buf = buf0;
48
49     argv[argc] = buf;
50
51     for (src = s; *src; src++) {
52         if (quote == *src) {
53             quote = '\0';
54         } else if (quote) {
55             if (*src == '\\') {
56                 src++;
57                 if (!*src) {
58                     free(argv);
59                     free(buf0);
60                     return POPT_ERROR_BADQUOTE;
61                 }
62                 if (*src != quote) *buf++ = '\\';
63             }
64             *buf++ = *src;
65         } else if (isspace(*src)) {
66             if (*argv[argc]) {
67                 buf++, argc++;
68                 if (argc == argvAlloced) {
69                     argvAlloced += POPT_ARGV_ARRAY_GROW_DELTA;
70                     argv = realloc(argv, sizeof(*argv) * argvAlloced);
71                 }
72                 argv[argc] = buf;
73             }
74         } else switch (*src) {
75           case '"':
76           case '\'':
77             quote = *src;
78             break;
79           case '\\':
80             src++;
81             if (!*src) {
82                 free(argv);
83                 free(buf0);
84                 return POPT_ERROR_BADQUOTE;
85             }
86             /*@fallthrough@*/
87           default:
88             *buf++ = *src;
89             break;
90         }
91     }
92
93     if (strlen(argv[argc])) {
94         argc++, buf++;
95     }
96
97     (void) poptDupArgv(argc, argv, argcPtr, argvPtr);
98
99     free(argv);
100     free(buf0);
101     return 0;
102 }