1 /*
2 * Copyright © 2016 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23 #include <string.h>
24 #include <ctype.h>
25 #include "parser_utils.h"
26
27 bool
parse_whitespace(const char * s,const char ** rest)28 parse_whitespace(const char *s, const char **rest)
29 {
30 const char *end = s;
31 for (; *end && *end != '\n' && isspace(*end); end++);
32
33 if (rest)
34 *rest = end;
35
36 return end != s;
37 }
38
39 bool
parse_str(const char * s,const char * lit,const char ** rest)40 parse_str(const char *s, const char *lit, const char **rest)
41 {
42 const char *t;
43 parse_whitespace(s, &t);
44 const bool ret = strncmp(t, lit, strlen(lit)) == 0;
45
46 if (rest)
47 *rest = (ret ? t + strlen(lit) : s);
48
49 return ret;
50 }
51
52 unsigned
parse_ints(const char * s,int * i,unsigned n,const char ** rest)53 parse_ints(const char *s, int *i, unsigned n, const char **rest)
54 {
55 const char *end = s;
56 unsigned j;
57
58 for (j = 0; j < n; j++) {
59 int v = strtoll(s = end, (char **)&end, 0);
60 if (s == end)
61 break;
62 i[j] = v;
63 }
64
65 if (rest)
66 *rest = end;
67
68 return j;
69 }
70
71 unsigned
parse_uints(const char * s,unsigned * u,unsigned n,const char ** rest)72 parse_uints(const char *s, unsigned *u, unsigned n, const char **rest)
73 {
74 const char *end = s;
75 unsigned j;
76
77 for (j = 0; j < n; j++) {
78 unsigned v = strtoul(s = end, (char **)&end, 0);
79 if (s == end)
80 break;
81 u[j] = v;
82 }
83
84 if (rest)
85 *rest = end;
86
87 return j;
88 }
89
90 unsigned
parse_int64s(const char * s,int64_t * i,unsigned n,const char ** rest)91 parse_int64s(const char *s, int64_t *i, unsigned n, const char **rest)
92 {
93 const char *end = s;
94 unsigned j;
95
96 for (j = 0; j < n; j++) {
97 int64_t v;
98
99 s = end;
100 while (isspace(s[0]))
101 s++;
102
103 /* If the user specified a raw hex value, just parse the raw
104 * bit pattern. Hex values that represent negative numbers
105 * would be clamped to INT64_MAX by strtoll (and errno would
106 * be set to ERANGE).
107 */
108 errno = 0;
109 if (strncmp("0x", s, 2) == 0)
110 v = (int64_t) strtoull(s, (char **)&end, 0);
111 else
112 v = strtoll(s, (char **)&end, 0);
113
114 assert(errno == 0);
115
116 if (s == end)
117 break;
118 i[j] = v;
119 }
120
121 if (rest)
122 *rest = end;
123
124 return j;
125 }
126
127 unsigned
parse_uint64s(const char * s,uint64_t * u,unsigned n,const char ** rest)128 parse_uint64s(const char *s, uint64_t *u, unsigned n, const char **rest)
129 {
130 const char *end = s;
131 unsigned j;
132
133 for (j = 0; j < n; j++) {
134 uint64_t v = strtoull(s = end, (char **)&end, 0);
135 if (s == end)
136 break;
137 u[j] = v;
138 }
139
140 if (rest)
141 *rest = end;
142
143 return j;
144 }
145
146 unsigned
parse_floats(const char * s,float * f,unsigned n,const char ** rest)147 parse_floats(const char *s, float *f, unsigned n, const char **rest)
148 {
149 const char *end = s;
150 unsigned j;
151
152 for (j = 0; j < n; j++) {
153 float v = strtof_hex(s = end, (char **)&end);
154 if (s == end)
155 break;
156 f[j] = v;
157 }
158
159 if (rest)
160 *rest = end;
161
162 return j;
163 }
164
165 unsigned
parse_doubles(const char * s,double * d,unsigned n,const char ** rest)166 parse_doubles(const char *s, double *d, unsigned n, const char **rest)
167 {
168 const char *end = s;
169 unsigned j;
170
171 for (j = 0; j < n; j++) {
172 double v = strtod_hex(s = end, (char **)&end);
173 if (s == end)
174 break;
175 d[j] = v;
176 }
177
178 if (rest)
179 *rest = end;
180
181 return j;
182 }
183
184 bool
parse_word(const char * s,const char ** t,const char ** rest)185 parse_word(const char *s, const char **t, const char **rest)
186 {
187 parse_whitespace(s, t);
188
189 const char *end = *t;
190 for (; *end && !isspace(*end); end++);
191
192 if (rest)
193 *rest = (*t != end ? end : s);
194
195 return *t != end;
196 }
197
198 bool
parse_word_copy(const char * s,char * t,unsigned n,const char ** rest)199 parse_word_copy(const char *s, char *t, unsigned n, const char **rest)
200 {
201 const char *start, *end;
202 const bool ret = parse_word(s, &start, &end) && end - start < n;
203
204 if (ret) {
205 memcpy(t, start, end - start);
206 t[end - start] = 0;
207 }
208 if (rest)
209 *rest = (ret ? end : s);
210
211 return ret;
212 }
213
214 bool
parse_enum_gl(const char * s,GLenum * e,const char ** rest)215 parse_enum_gl(const char *s, GLenum *e, const char **rest)
216 {
217 char name[512];
218 const bool ret = parse_word_copy(s, name, sizeof(name), rest);
219 *e = (ret ? piglit_get_gl_enum_from_name(name) : GL_NONE);
220 return ret;
221 }
222
223 bool
parse_enum_tab(const struct string_to_enum * tab,const char * s,unsigned * e,const char ** rest)224 parse_enum_tab(const struct string_to_enum *tab,
225 const char *s, unsigned *e, const char **rest)
226 {
227 const char *end = s;
228 bool ret = parse_word(s, &s, &end);
229 unsigned i = 0;
230
231 if (ret) {
232 for (i = 0; tab[i].name; i++) {
233 if (!strncmp(tab[i].name, s, end - s) &&
234 !tab[i].name[end - s])
235 break;
236 }
237
238 *e = tab[i].value;
239 ret = tab[i].name;
240 }
241
242 if (rest)
243 *rest = (ret ? end : s);
244
245 return ret;
246 }
247
248 bool
parse_tex_target(const char * s,unsigned * t,const char ** rest)249 parse_tex_target(const char *s, unsigned *t, const char **rest)
250 {
251 static const struct string_to_enum tab[] = {
252 { "1D", GL_TEXTURE_1D },
253 { "2D", GL_TEXTURE_2D },
254 { "3D", GL_TEXTURE_3D },
255 { "Rect", GL_TEXTURE_RECTANGLE },
256 { "Cube", GL_TEXTURE_CUBE_MAP },
257 { "1DArray", GL_TEXTURE_1D_ARRAY },
258 { "2DArray", GL_TEXTURE_2D_ARRAY },
259 { "CubeArray", GL_TEXTURE_CUBE_MAP_ARRAY },
260 { NULL, 0 }
261 };
262 return parse_enum_tab(tab, s, t, rest);
263 }
264
265 bool
parse_comparison_op(const char * s,enum comparison * t,const char ** rest)266 parse_comparison_op(const char *s, enum comparison *t, const char **rest)
267 {
268 if (parse_str(s, "==", rest)) {
269 *t = equal;
270 return true;
271 } else if (parse_str(s, "!=", rest)) {
272 *t = greater;
273 return true;
274 } else if (parse_str(s, "<=", rest)) {
275 *t = less_equal;
276 return true;
277 } else if (parse_str(s, "<", rest)) {
278 *t = less;
279 return true;
280 } else if (parse_str(s, ">=", rest)) {
281 *t = greater_equal;
282 return true;
283 } else if (parse_str(s, ">", rest)) {
284 *t = greater;
285 return true;
286 } else {
287 return false;
288 }
289 }
290