Check in built-in copy of libpopt in preparation for switching
[rsync/rsync.git] / popt-1.2 / poptparse.c
CommitLineData
62402cb1
MP
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
15int 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}