Doc.
[rsync/rsync.git] / popt-1.2 / 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 #ifdef HAVE_CONFIG_H
6 #include "config.h"
7 #endif
8
9 #include <ctype.h>
10 #include <stdlib.h>
11 #include <string.h>
12
13 #include "popt.h"
14
15 int poptParseArgvString(char * s, int * argcPtr, char *** argvPtr) {
16     char * buf = strcpy(alloca(strlen(s) + 1), s);
17     char * bufStart = buf;
18     char * src, * dst;
19     char quote = '\0';
20     int argvAlloced = 5;
21     char ** argv = malloc(sizeof(*argv) * argvAlloced);
22     char ** argv2;
23     int argc = 0;
24     int i;
25
26     src = s;
27     dst = buf;
28     argv[argc] = buf;
29
30     memset(buf, '\0', strlen(s) + 1);
31
32     while (*src) {
33         if (quote == *src) {
34             quote = '\0';
35         } else if (quote) {
36             if (*src == '\\') {
37                 src++;
38                 if (!*src) {
39                     free(argv);
40                     return POPT_ERROR_BADQUOTE;
41                 }
42                 if (*src != quote) *buf++ = '\\';
43             }
44             *buf++ = *src;
45         } else if (isspace(*src)) {
46             if (*argv[argc]) {
47                 buf++, argc++;
48                 if (argc == argvAlloced) {
49                     argvAlloced += 5;
50                     argv = realloc(argv, sizeof(*argv) * argvAlloced);
51                 }
52                 argv[argc] = buf;
53             }
54         } else switch (*src) {
55           case '"':
56           case '\'':
57             quote = *src;
58             break;
59           case '\\':
60             src++;
61             if (!*src) {
62                 free(argv);
63                 return POPT_ERROR_BADQUOTE;
64             }
65             /* fallthrough */
66           default:
67             *buf++ = *src;
68         }
69
70         src++;
71     }
72
73     if (strlen(argv[argc])) {
74         argc++, buf++;
75     }
76
77     dst = malloc(argc * sizeof(*argv) + (buf - bufStart));
78     argv2 = (void *) dst;
79     dst += argc * sizeof(*argv);
80     memcpy(argv2, argv, argc * sizeof(*argv));
81     memcpy(dst, bufStart, buf - bufStart);
82
83     for (i = 0; i < argc; i++) {
84         argv2[i] = dst + (argv[i] - bufStart);
85     }
86
87     free(argv);
88
89     *argvPtr = argv2;
90     *argcPtr = argc;
91
92     return 0;
93 }