Added SILC Thread Queue API
[crypto.git] / apps / irssi / src / 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 #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 static const int poptArgvArrayGrowDelta = 5;
16
17 int poptParseArgvString(const char * s, int * argcPtr, char *** argvPtr) {
18     char * buf, * bufStart, * dst;
19     const char * src;
20     char quote = '\0';
21     int argvAlloced = poptArgvArrayGrowDelta;
22     char ** argv = malloc(sizeof(*argv) * argvAlloced);
23     char ** argv2;
24     int argc = 0;
25     int i, buflen;
26
27     buflen = strlen(s) + 1;
28     bufStart = buf = malloc(buflen);
29     memset(buf, '\0', buflen);
30
31     src = s;
32     argv[argc] = buf;
33
34     while (*src) {
35         if (quote == *src) {
36             quote = '\0';
37         } else if (quote) {
38             if (*src == '\\') {
39                 src++;
40                 if (!*src) {
41                     free(argv);
42                     free(bufStart);
43                     return POPT_ERROR_BADQUOTE;
44                 }
45                 if (*src != quote) *buf++ = '\\';
46             }
47             *buf++ = *src;
48         } else if (isspace((int) (unsigned char) *src)) {
49             if (*argv[argc]) {
50                 buf++, argc++;
51                 if (argc == argvAlloced) {
52                     argvAlloced += poptArgvArrayGrowDelta;
53                     argv = realloc(argv, sizeof(*argv) * argvAlloced);
54                 }
55                 argv[argc] = buf;
56             }
57         } else switch (*src) {
58           case '"':
59           case '\'':
60             quote = *src;
61             break;
62           case '\\':
63             src++;
64             if (!*src) {
65                 free(argv);
66                 free(bufStart);
67                 return POPT_ERROR_BADQUOTE;
68             }
69             /* fallthrough */
70           default:
71             *buf++ = *src;
72         }
73
74         src++;
75     }
76
77     if (strlen(argv[argc])) {
78         argc++, buf++;
79     }
80
81     dst = malloc(argc * sizeof(*argv) + (buf - bufStart));
82     argv2 = (void *) dst;
83     dst += argc * sizeof(*argv);
84     memcpy(argv2, argv, argc * sizeof(*argv));
85     memcpy(dst, bufStart, buf - bufStart);
86
87     for (i = 0; i < argc; i++) {
88         argv2[i] = dst + (argv[i] - bufStart);
89     }
90
91     free(argv);
92
93     *argvPtr = argv2;
94     *argcPtr = argc;
95
96     free(bufStart);
97     return 0;
98 }