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