~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to lib/parser.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * lib/parser.c - simple parser for mount, etc. options.
 
3
 *
 
4
 * This source code is licensed under the GNU General Public License,
 
5
 * Version 2.  See the file COPYING for more details.
 
6
 */
 
7
 
 
8
#include <linux/ctype.h>
 
9
#include <linux/module.h>
 
10
#include <linux/parser.h>
 
11
#include <linux/slab.h>
 
12
#include <linux/string.h>
 
13
 
 
14
/**
 
15
 * match_one: - Determines if a string matches a simple pattern
 
16
 * @s: the string to examine for presence of the pattern
 
17
 * @p: the string containing the pattern
 
18
 * @args: array of %MAX_OPT_ARGS &substring_t elements. Used to return match
 
19
 * locations.
 
20
 *
 
21
 * Description: Determines if the pattern @p is present in string @s. Can only
 
22
 * match extremely simple token=arg style patterns. If the pattern is found,
 
23
 * the location(s) of the arguments will be returned in the @args array.
 
24
 */
 
25
static int match_one(char *s, const char *p, substring_t args[])
 
26
{
 
27
        char *meta;
 
28
        int argc = 0;
 
29
 
 
30
        if (!p)
 
31
                return 1;
 
32
 
 
33
        while(1) {
 
34
                int len = -1;
 
35
                meta = strchr(p, '%');
 
36
                if (!meta)
 
37
                        return strcmp(p, s) == 0;
 
38
 
 
39
                if (strncmp(p, s, meta-p))
 
40
                        return 0;
 
41
 
 
42
                s += meta - p;
 
43
                p = meta + 1;
 
44
 
 
45
                if (isdigit(*p))
 
46
                        len = simple_strtoul(p, (char **) &p, 10);
 
47
                else if (*p == '%') {
 
48
                        if (*s++ != '%')
 
49
                                return 0;
 
50
                        p++;
 
51
                        continue;
 
52
                }
 
53
 
 
54
                if (argc >= MAX_OPT_ARGS)
 
55
                        return 0;
 
56
 
 
57
                args[argc].from = s;
 
58
                switch (*p++) {
 
59
                case 's': {
 
60
                        size_t str_len = strlen(s);
 
61
 
 
62
                        if (str_len == 0)
 
63
                                return 0;
 
64
                        if (len == -1 || len > str_len)
 
65
                                len = str_len;
 
66
                        args[argc].to = s + len;
 
67
                        break;
 
68
                }
 
69
                case 'd':
 
70
                        simple_strtol(s, &args[argc].to, 0);
 
71
                        goto num;
 
72
                case 'u':
 
73
                        simple_strtoul(s, &args[argc].to, 0);
 
74
                        goto num;
 
75
                case 'o':
 
76
                        simple_strtoul(s, &args[argc].to, 8);
 
77
                        goto num;
 
78
                case 'x':
 
79
                        simple_strtoul(s, &args[argc].to, 16);
 
80
                num:
 
81
                        if (args[argc].to == args[argc].from)
 
82
                                return 0;
 
83
                        break;
 
84
                default:
 
85
                        return 0;
 
86
                }
 
87
                s = args[argc].to;
 
88
                argc++;
 
89
        }
 
90
}
 
91
 
 
92
/**
 
93
 * match_token: - Find a token (and optional args) in a string
 
94
 * @s: the string to examine for token/argument pairs
 
95
 * @table: match_table_t describing the set of allowed option tokens and the
 
96
 * arguments that may be associated with them. Must be terminated with a
 
97
 * &struct match_token whose pattern is set to the NULL pointer.
 
98
 * @args: array of %MAX_OPT_ARGS &substring_t elements. Used to return match
 
99
 * locations.
 
100
 *
 
101
 * Description: Detects which if any of a set of token strings has been passed
 
102
 * to it. Tokens can include up to MAX_OPT_ARGS instances of basic c-style
 
103
 * format identifiers which will be taken into account when matching the
 
104
 * tokens, and whose locations will be returned in the @args array.
 
105
 */
 
106
int match_token(char *s, const match_table_t table, substring_t args[])
 
107
{
 
108
        const struct match_token *p;
 
109
 
 
110
        for (p = table; !match_one(s, p->pattern, args) ; p++)
 
111
                ;
 
112
 
 
113
        return p->token;
 
114
}
 
115
 
 
116
/**
 
117
 * match_number: scan a number in the given base from a substring_t
 
118
 * @s: substring to be scanned
 
119
 * @result: resulting integer on success
 
120
 * @base: base to use when converting string
 
121
 *
 
122
 * Description: Given a &substring_t and a base, attempts to parse the substring
 
123
 * as a number in that base. On success, sets @result to the integer represented
 
124
 * by the string and returns 0. Returns either -ENOMEM or -EINVAL on failure.
 
125
 */
 
126
static int match_number(substring_t *s, int *result, int base)
 
127
{
 
128
        char *endp;
 
129
        char *buf;
 
130
        int ret;
 
131
        size_t len = s->to - s->from;
 
132
 
 
133
        buf = kmalloc(len + 1, GFP_KERNEL);
 
134
        if (!buf)
 
135
                return -ENOMEM;
 
136
        memcpy(buf, s->from, len);
 
137
        buf[len] = '\0';
 
138
        *result = simple_strtol(buf, &endp, base);
 
139
        ret = 0;
 
140
        if (endp == buf)
 
141
                ret = -EINVAL;
 
142
        kfree(buf);
 
143
        return ret;
 
144
}
 
145
 
 
146
/**
 
147
 * match_int: - scan a decimal representation of an integer from a substring_t
 
148
 * @s: substring_t to be scanned
 
149
 * @result: resulting integer on success
 
150
 *
 
151
 * Description: Attempts to parse the &substring_t @s as a decimal integer. On
 
152
 * success, sets @result to the integer represented by the string and returns 0.
 
153
 * Returns either -ENOMEM or -EINVAL on failure.
 
154
 */
 
155
int match_int(substring_t *s, int *result)
 
156
{
 
157
        return match_number(s, result, 0);
 
158
}
 
159
 
 
160
/**
 
161
 * match_octal: - scan an octal representation of an integer from a substring_t
 
162
 * @s: substring_t to be scanned
 
163
 * @result: resulting integer on success
 
164
 *
 
165
 * Description: Attempts to parse the &substring_t @s as an octal integer. On
 
166
 * success, sets @result to the integer represented by the string and returns
 
167
 * 0. Returns either -ENOMEM or -EINVAL on failure.
 
168
 */
 
169
int match_octal(substring_t *s, int *result)
 
170
{
 
171
        return match_number(s, result, 8);
 
172
}
 
173
 
 
174
/**
 
175
 * match_hex: - scan a hex representation of an integer from a substring_t
 
176
 * @s: substring_t to be scanned
 
177
 * @result: resulting integer on success
 
178
 *
 
179
 * Description: Attempts to parse the &substring_t @s as a hexadecimal integer.
 
180
 * On success, sets @result to the integer represented by the string and
 
181
 * returns 0. Returns either -ENOMEM or -EINVAL on failure.
 
182
 */
 
183
int match_hex(substring_t *s, int *result)
 
184
{
 
185
        return match_number(s, result, 16);
 
186
}
 
187
 
 
188
/**
 
189
 * match_strlcpy: - Copy the characters from a substring_t to a sized buffer
 
190
 * @dest: where to copy to
 
191
 * @src: &substring_t to copy
 
192
 * @size: size of destination buffer
 
193
 *
 
194
 * Description: Copy the characters in &substring_t @src to the
 
195
 * c-style string @dest.  Copy no more than @size - 1 characters, plus
 
196
 * the terminating NUL.  Return length of @src.
 
197
 */
 
198
size_t match_strlcpy(char *dest, const substring_t *src, size_t size)
 
199
{
 
200
        size_t ret = src->to - src->from;
 
201
 
 
202
        if (size) {
 
203
                size_t len = ret >= size ? size - 1 : ret;
 
204
                memcpy(dest, src->from, len);
 
205
                dest[len] = '\0';
 
206
        }
 
207
        return ret;
 
208
}
 
209
 
 
210
/**
 
211
 * match_strdup: - allocate a new string with the contents of a substring_t
 
212
 * @s: &substring_t to copy
 
213
 *
 
214
 * Description: Allocates and returns a string filled with the contents of
 
215
 * the &substring_t @s. The caller is responsible for freeing the returned
 
216
 * string with kfree().
 
217
 */
 
218
char *match_strdup(const substring_t *s)
 
219
{
 
220
        size_t sz = s->to - s->from + 1;
 
221
        char *p = kmalloc(sz, GFP_KERNEL);
 
222
        if (p)
 
223
                match_strlcpy(p, s, sz);
 
224
        return p;
 
225
}
 
226
 
 
227
EXPORT_SYMBOL(match_token);
 
228
EXPORT_SYMBOL(match_int);
 
229
EXPORT_SYMBOL(match_octal);
 
230
EXPORT_SYMBOL(match_hex);
 
231
EXPORT_SYMBOL(match_strlcpy);
 
232
EXPORT_SYMBOL(match_strdup);