File: argparse.c

package info (click to toggle)
inn2 2.5.2-2~squeeze1
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 11,072 kB
  • ctags: 8,521
  • sloc: ansic: 91,418; sh: 13,249; perl: 12,311; makefile: 2,928; yacc: 868; python: 342; lex: 266
file content (139 lines) | stat: -rw-r--r-- 3,240 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*  $Id: argparse.c 8750 2009-11-15 09:17:05Z iulius $
**
**  Routines for parsing arguments.
*/

#include "config.h"
#include "clibrary.h"
#include <ctype.h>
#include <time.h>

#include "inn/innconf.h"
#include "inn/libinn.h"


/*
**  Parse a string into a NULL-terminated array of words; return number
**  of words.  If argvp isn't NULL, it and what it points to will be freed.
*/
int
Argify(char *line, char ***argvp)
{
    return nArgify(line, argvp, -1);
}


/*
**  Parse a string into a NULL-terminated array of at most n words;
**  return number of words.  If there are more than n words, stop
**  processing at the beginning of the (n+1)th word, store everything
**  from the beginning of word (n+1) in argv[n] and return (n+1).
**  If n is negative, parses all words.  If argvp isn't NULL, it and
**  what it points to will be freed.
*/
int
nArgify(char *line, char ***argvp, int n)
{
    char        *p;

    if (*argvp != NULL) {
        free(*argvp[0]);
        free(*argvp);
    }

    /* Copy the line, which we will split up. */
    while (ISWHITE(*line))
        line++;
    p = xstrdup(line);

    /* Allocate worst-case amount of space. */
    *argvp = xmalloc((strlen(p) + 2) * sizeof(char *));

    return reArgify(p, *argvp, n, true);
}


/*
**  Destructively parse a string into a NULL-terminated array of at most
**  n words; return number of words.  Behaviour on negative n and strings
**  of more than n words matches that of nArgify (see above).  Caller
**  must supply an array of sufficient size (such as created by nArgify).
**
**  Note that the sequence
**     ac = nArgify(line, &argv, n1);
**     ac--;
**     ac += reArgify(argv[ac], &argv[ac], n2, true);
**  is equivalent to
**     ac = nArgify(line, &argv, n1 + n2);
**
**  It is sometimes useful not to strip spaces.  For instance
**  "AUTHINFO PASS  test" should be understood as giving the
**  password " test", beginning with a space.
*/
int
reArgify(char *p, char **argv, int n, bool stripspaces)
{
    char **save = argv;

    /* Should never happen unless caller modifies argv between calls
     * or stripspaces has previously been set to false. */
    if (stripspaces) {
        while (ISWHITE(*p))
            p++;
    }

    for ( ; *p; ) {
        if (n == 0) {
            *argv++ = p;
            break;
        }

        /* Decrement limit, mark start of this word, find its end. */
        for (n--, *argv++ = p; *p && !ISWHITE(*p); )
            p++;

        if (*p == '\0')
            break;

        /* Nip off word. */
        *p++ = '\0';
        
        /* Skip whitespace. */
        if (stripspaces) {
            while (ISWHITE(*p))
                p++;
        }
    }

    *argv = NULL;

    return argv - save;
}


/*
**  Take a vector which Argify made and glue it back together with
**  spaces between each element.  Returns a pointer to dynamic space.
*/
char *
Glom(char **av)
{
    char        **v;
    int i;
    char                *save;

    /* Get space. */
    for (i = 0, v = av; *v; v++)
        i += strlen(*v) + 1;
    i++;

    save = xmalloc(i);
    save[0] = '\0';
    for (v = av; *v; v++) {
        if (v > av)
            strlcat(save, " ", i);
        strlcat(save, *v, i);
    }

    return save;
}