Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
[linux-2.6] / lib / argv_split.c
1 /*
2  * Helper function for splitting a string into an argv-like array.
3  */
4
5 #include <linux/kernel.h>
6 #include <linux/ctype.h>
7 #include <linux/slab.h>
8 #include <linux/module.h>
9
10 static const char *skip_sep(const char *cp)
11 {
12         while (*cp && isspace(*cp))
13                 cp++;
14
15         return cp;
16 }
17
18 static const char *skip_arg(const char *cp)
19 {
20         while (*cp && !isspace(*cp))
21                 cp++;
22
23         return cp;
24 }
25
26 static int count_argc(const char *str)
27 {
28         int count = 0;
29
30         while (*str) {
31                 str = skip_sep(str);
32                 if (*str) {
33                         count++;
34                         str = skip_arg(str);
35                 }
36         }
37
38         return count;
39 }
40
41 /**
42  * argv_free - free an argv
43  * @argv - the argument vector to be freed
44  *
45  * Frees an argv and the strings it points to.
46  */
47 void argv_free(char **argv)
48 {
49         char **p;
50         for (p = argv; *p; p++)
51                 kfree(*p);
52
53         kfree(argv);
54 }
55 EXPORT_SYMBOL(argv_free);
56
57 /**
58  * argv_split - split a string at whitespace, returning an argv
59  * @gfp: the GFP mask used to allocate memory
60  * @str: the string to be split
61  * @argcp: returned argument count
62  *
63  * Returns an array of pointers to strings which are split out from
64  * @str.  This is performed by strictly splitting on white-space; no
65  * quote processing is performed.  Multiple whitespace characters are
66  * considered to be a single argument separator.  The returned array
67  * is always NULL-terminated.  Returns NULL on memory allocation
68  * failure.
69  */
70 char **argv_split(gfp_t gfp, const char *str, int *argcp)
71 {
72         int argc = count_argc(str);
73         char **argv = kzalloc(sizeof(*argv) * (argc+1), gfp);
74         char **argvp;
75
76         if (argv == NULL)
77                 goto out;
78
79         if (argcp)
80                 *argcp = argc;
81
82         argvp = argv;
83
84         while (*str) {
85                 str = skip_sep(str);
86
87                 if (*str) {
88                         const char *p = str;
89                         char *t;
90
91                         str = skip_arg(str);
92
93                         t = kstrndup(p, str-p, gfp);
94                         if (t == NULL)
95                                 goto fail;
96                         *argvp++ = t;
97                 }
98         }
99         *argvp = NULL;
100
101   out:
102         return argv;
103
104   fail:
105         argv_free(argv);
106         return NULL;
107 }
108 EXPORT_SYMBOL(argv_split);