File: | ctk/ctkcssparser.c |
Warning: | line 259, column 22 Out of bound memory access (access exceeds upper limit of memory block) |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* CTK - The GIMP Toolkit | |||
2 | * Copyright (C) 2011 Benjamin Otte <otte@gnome.org> | |||
3 | * | |||
4 | * This library is free software; you can redistribute it and/or | |||
5 | * modify it under the terms of the GNU Lesser General Public | |||
6 | * License as published by the Free Software Foundation; either | |||
7 | * version 2 of the License, or (at your option) any later version. | |||
8 | * | |||
9 | * This library is distributed in the hope that it will be useful, | |||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
12 | * Lesser General Public License for more details. | |||
13 | * | |||
14 | * You should have received a copy of the GNU Lesser General Public | |||
15 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. | |||
16 | */ | |||
17 | ||||
18 | #include "config.h" | |||
19 | ||||
20 | #include "ctkcssparserprivate.h" | |||
21 | ||||
22 | #include "ctkcssdimensionvalueprivate.h" | |||
23 | ||||
24 | #include <errno(*__errno_location ()).h> | |||
25 | #include <string.h> | |||
26 | ||||
27 | /* just for the errors, yay! */ | |||
28 | #include "ctkcssprovider.h" | |||
29 | ||||
30 | #define NEWLINE_CHARS"\r\n" "\r\n" | |||
31 | #define WHITESPACE_CHARS"\f \t" "\f \t" | |||
32 | #define NMSTART"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" | |||
33 | #define NMCHAR"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" "01234567890-_" NMSTART"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" "01234567890-_" | |||
34 | #define URLCHAR"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" "01234567890-_" "!#$%&*~" NMCHAR"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" "01234567890-_" "!#$%&*~" | |||
35 | ||||
36 | #define CTK_IS_CSS_PARSER(parser)((parser) != ((void*)0)) ((parser) != NULL((void*)0)) | |||
37 | ||||
38 | struct _CtkCssParser | |||
39 | { | |||
40 | const char *data; | |||
41 | GFile *file; | |||
42 | CtkCssParserErrorFunc error_func; | |||
43 | gpointer user_data; | |||
44 | ||||
45 | const char *line_start; | |||
46 | guint line; | |||
47 | }; | |||
48 | ||||
49 | CtkCssParser * | |||
50 | _ctk_css_parser_new (const char *data, | |||
51 | GFile *file, | |||
52 | CtkCssParserErrorFunc error_func, | |||
53 | gpointer user_data) | |||
54 | { | |||
55 | CtkCssParser *parser; | |||
56 | ||||
57 | g_return_val_if_fail (data != NULL, NULL)do { if ((data != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "data != NULL"); return ( ((void*)0)); } } while (0); | |||
58 | g_return_val_if_fail (file == NULL || G_IS_FILE (file), NULL)do { if ((file == ((void*)0) || (((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ((file)); GType __t = ((g_file_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst-> g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "file == NULL || G_IS_FILE (file)"); return (((void*)0)); } } while (0); | |||
59 | ||||
60 | parser = g_slice_new0 (CtkCssParser)((CtkCssParser*) g_slice_alloc0 (sizeof (CtkCssParser))); | |||
61 | ||||
62 | parser->data = data; | |||
63 | if (file) | |||
64 | parser->file = g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file)); | |||
65 | parser->error_func = error_func; | |||
66 | parser->user_data = user_data; | |||
67 | ||||
68 | parser->line_start = data; | |||
69 | parser->line = 0; | |||
70 | ||||
71 | return parser; | |||
72 | } | |||
73 | ||||
74 | void | |||
75 | _ctk_css_parser_free (CtkCssParser *parser) | |||
76 | { | |||
77 | g_return_if_fail (CTK_IS_CSS_PARSER (parser))do { if ((((parser) != ((void*)0)))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "CTK_IS_CSS_PARSER (parser)" ); return; } } while (0); | |||
78 | ||||
79 | if (parser->file) | |||
80 | g_object_unref (parser->file); | |||
81 | ||||
82 | g_slice_free (CtkCssParser, parser)do { if (1) g_slice_free1 (sizeof (CtkCssParser), (parser)); else (void) ((CtkCssParser*) 0 == (parser)); } while (0); | |||
83 | } | |||
84 | ||||
85 | gboolean | |||
86 | _ctk_css_parser_is_eof (CtkCssParser *parser) | |||
87 | { | |||
88 | g_return_val_if_fail (CTK_IS_CSS_PARSER (parser), TRUE)do { if ((((parser) != ((void*)0)))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "CTK_IS_CSS_PARSER (parser)" ); return ((!(0))); } } while (0); | |||
89 | ||||
90 | return *parser->data == 0; | |||
91 | } | |||
92 | ||||
93 | gboolean | |||
94 | _ctk_css_parser_begins_with (CtkCssParser *parser, | |||
95 | char c) | |||
96 | { | |||
97 | g_return_val_if_fail (CTK_IS_CSS_PARSER (parser), TRUE)do { if ((((parser) != ((void*)0)))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "CTK_IS_CSS_PARSER (parser)" ); return ((!(0))); } } while (0); | |||
98 | ||||
99 | return *parser->data == c; | |||
100 | } | |||
101 | ||||
102 | gboolean | |||
103 | _ctk_css_parser_has_prefix (CtkCssParser *parser, | |||
104 | const char *prefix) | |||
105 | { | |||
106 | g_return_val_if_fail (CTK_IS_CSS_PARSER (parser), FALSE)do { if ((((parser) != ((void*)0)))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "CTK_IS_CSS_PARSER (parser)" ); return ((0)); } } while (0); | |||
107 | ||||
108 | return g_ascii_strncasecmp (parser->data, prefix, strlen (prefix)) == 0; | |||
109 | } | |||
110 | ||||
111 | guint | |||
112 | _ctk_css_parser_get_line (CtkCssParser *parser) | |||
113 | { | |||
114 | g_return_val_if_fail (CTK_IS_CSS_PARSER (parser), 1)do { if ((((parser) != ((void*)0)))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "CTK_IS_CSS_PARSER (parser)" ); return (1); } } while (0); | |||
115 | ||||
116 | return parser->line; | |||
117 | } | |||
118 | ||||
119 | guint | |||
120 | _ctk_css_parser_get_position (CtkCssParser *parser) | |||
121 | { | |||
122 | g_return_val_if_fail (CTK_IS_CSS_PARSER (parser), 1)do { if ((((parser) != ((void*)0)))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "CTK_IS_CSS_PARSER (parser)" ); return (1); } } while (0); | |||
123 | ||||
124 | return parser->data - parser->line_start; | |||
125 | } | |||
126 | ||||
127 | static GFile * | |||
128 | ctk_css_parser_get_base_file (CtkCssParser *parser) | |||
129 | { | |||
130 | GFile *base; | |||
131 | ||||
132 | if (parser->file) | |||
133 | { | |||
134 | base = g_file_get_parent (parser->file); | |||
135 | } | |||
136 | else | |||
137 | { | |||
138 | char *dir = g_get_current_dir (); | |||
139 | base = g_file_new_for_path (dir); | |||
140 | g_free (dir); | |||
141 | } | |||
142 | ||||
143 | return base; | |||
144 | } | |||
145 | ||||
146 | GFile * | |||
147 | _ctk_css_parser_get_file_for_path (CtkCssParser *parser, | |||
148 | const char *path) | |||
149 | { | |||
150 | GFile *base, *file; | |||
151 | ||||
152 | g_return_val_if_fail (parser != NULL, NULL)do { if ((parser != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "parser != NULL"); return (((void*)0)); } } while (0); | |||
153 | g_return_val_if_fail (path != NULL, NULL)do { if ((path != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "path != NULL"); return ( ((void*)0)); } } while (0); | |||
154 | ||||
155 | base = ctk_css_parser_get_base_file (parser); | |||
156 | file = g_file_resolve_relative_path (base, path); | |||
157 | g_object_unref (base); | |||
158 | ||||
159 | return file; | |||
160 | } | |||
161 | ||||
162 | GFile * | |||
163 | _ctk_css_parser_get_file (CtkCssParser *parser) | |||
164 | { | |||
165 | g_return_val_if_fail (parser != NULL, NULL)do { if ((parser != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "parser != NULL"); return (((void*)0)); } } while (0); | |||
166 | ||||
167 | return parser->file; | |||
168 | } | |||
169 | ||||
170 | void | |||
171 | _ctk_css_parser_take_error (CtkCssParser *parser, | |||
172 | GError *error) | |||
173 | { | |||
174 | parser->error_func (parser, error, parser->user_data); | |||
175 | ||||
176 | g_error_free (error); | |||
177 | } | |||
178 | ||||
179 | void | |||
180 | _ctk_css_parser_error (CtkCssParser *parser, | |||
181 | const char *format, | |||
182 | ...) | |||
183 | { | |||
184 | GError *error; | |||
185 | ||||
186 | va_list args; | |||
187 | ||||
188 | va_start (args, format)__builtin_va_start(args, format); | |||
189 | error = g_error_new_valist (CTK_CSS_PROVIDER_ERROR(ctk_css_provider_error_quark ()), | |||
190 | CTK_CSS_PROVIDER_ERROR_SYNTAX, | |||
191 | format, args); | |||
192 | va_end (args)__builtin_va_end(args); | |||
193 | ||||
194 | _ctk_css_parser_take_error (parser, error); | |||
195 | } | |||
196 | ||||
197 | void | |||
198 | _ctk_css_parser_error_full (CtkCssParser *parser, | |||
199 | CtkCssProviderError code, | |||
200 | const char *format, | |||
201 | ...) | |||
202 | { | |||
203 | GError *error; | |||
204 | ||||
205 | va_list args; | |||
206 | ||||
207 | va_start (args, format)__builtin_va_start(args, format); | |||
208 | error = g_error_new_valist (CTK_CSS_PROVIDER_ERROR(ctk_css_provider_error_quark ()), | |||
209 | code, format, args); | |||
210 | va_end (args)__builtin_va_end(args); | |||
211 | ||||
212 | _ctk_css_parser_take_error (parser, error); | |||
213 | } | |||
214 | static gboolean | |||
215 | ctk_css_parser_new_line (CtkCssParser *parser) | |||
216 | { | |||
217 | gboolean result = FALSE(0); | |||
218 | ||||
219 | if (*parser->data == '\r') | |||
220 | { | |||
221 | result = TRUE(!(0)); | |||
222 | parser->data++; | |||
223 | } | |||
224 | if (*parser->data == '\n') | |||
225 | { | |||
226 | result = TRUE(!(0)); | |||
227 | parser->data++; | |||
228 | } | |||
229 | ||||
230 | if (result) | |||
231 | { | |||
232 | parser->line++; | |||
233 | parser->line_start = parser->data; | |||
234 | } | |||
235 | ||||
236 | return result; | |||
237 | } | |||
238 | ||||
239 | static gboolean | |||
240 | ctk_css_parser_skip_comment (CtkCssParser *parser) | |||
241 | { | |||
242 | if (parser->data[0] != '/' || | |||
243 | parser->data[1] != '*') | |||
244 | return FALSE(0); | |||
245 | ||||
246 | parser->data += 2; | |||
247 | ||||
248 | while (*parser->data) | |||
249 | { | |||
250 | gsize len = strcspn (parser->data, NEWLINE_CHARS"\r\n" "/"); | |||
251 | ||||
252 | parser->data += len; | |||
253 | ||||
254 | if (ctk_css_parser_new_line (parser)) | |||
255 | continue; | |||
256 | ||||
257 | parser->data++; | |||
258 | ||||
259 | if (len > 0 && parser->data[-2] == '*') | |||
| ||||
260 | return TRUE(!(0)); | |||
261 | if (parser->data[0] == '*') | |||
262 | _ctk_css_parser_error (parser, "'/*' in comment block"); | |||
263 | } | |||
264 | ||||
265 | /* FIXME: position */ | |||
266 | _ctk_css_parser_error (parser, "Unterminated comment"); | |||
267 | return TRUE(!(0)); | |||
268 | } | |||
269 | ||||
270 | void | |||
271 | _ctk_css_parser_skip_whitespace (CtkCssParser *parser) | |||
272 | { | |||
273 | size_t len; | |||
274 | ||||
275 | while (*parser->data) | |||
276 | { | |||
277 | if (ctk_css_parser_new_line (parser)) | |||
278 | continue; | |||
279 | ||||
280 | len = strspn (parser->data, WHITESPACE_CHARS"\f \t"); | |||
281 | if (len) | |||
282 | { | |||
283 | parser->data += len; | |||
284 | continue; | |||
285 | } | |||
286 | ||||
287 | if (!ctk_css_parser_skip_comment (parser)) | |||
288 | break; | |||
289 | } | |||
290 | } | |||
291 | ||||
292 | gboolean | |||
293 | _ctk_css_parser_try (CtkCssParser *parser, | |||
294 | const char *string, | |||
295 | gboolean skip_whitespace) | |||
296 | { | |||
297 | g_return_val_if_fail (CTK_IS_CSS_PARSER (parser), FALSE)do { if ((((parser) != ((void*)0)))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "CTK_IS_CSS_PARSER (parser)" ); return ((0)); } } while (0); | |||
298 | g_return_val_if_fail (string != NULL, FALSE)do { if ((string != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "string != NULL"); return ((0)); } } while (0); | |||
299 | ||||
300 | if (g_ascii_strncasecmp (parser->data, string, strlen (string)) != 0) | |||
301 | return FALSE(0); | |||
302 | ||||
303 | parser->data += strlen (string); | |||
304 | ||||
305 | if (skip_whitespace) | |||
306 | _ctk_css_parser_skip_whitespace (parser); | |||
307 | return TRUE(!(0)); | |||
308 | } | |||
309 | ||||
310 | static guint | |||
311 | get_xdigit (char c) | |||
312 | { | |||
313 | if (c >= 'a') | |||
314 | return c - 'a' + 10; | |||
315 | else if (c >= 'A') | |||
316 | return c - 'A' + 10; | |||
317 | else | |||
318 | return c - '0'; | |||
319 | } | |||
320 | ||||
321 | static void | |||
322 | _ctk_css_parser_unescape (CtkCssParser *parser, | |||
323 | GString *str) | |||
324 | { | |||
325 | guint i; | |||
326 | gunichar result = 0; | |||
327 | ||||
328 | g_assert (*parser->data == '\\')do { if (*parser->data == '\\') ; else g_assertion_message_expr ("Ctk", "ctkcssparser.c", 328, ((const char*) (__func__)), "*parser->data == '\\\\'" ); } while (0); | |||
329 | ||||
330 | parser->data++; | |||
331 | ||||
332 | for (i = 0; i < 6; i++) | |||
333 | { | |||
334 | if (!g_ascii_isxdigit (parser->data[i])((g_ascii_table[(guchar) (parser->data[i])] & G_ASCII_XDIGIT ) != 0)) | |||
335 | break; | |||
336 | ||||
337 | result = (result << 4) + get_xdigit (parser->data[i]); | |||
338 | } | |||
339 | ||||
340 | if (i != 0) | |||
341 | { | |||
342 | g_string_append_unichar (str, result); | |||
343 | parser->data += i; | |||
344 | ||||
345 | /* NB: ctk_css_parser_new_line() forward data pointer itself */ | |||
346 | if (!ctk_css_parser_new_line (parser) && | |||
347 | *parser->data && | |||
348 | strchr (WHITESPACE_CHARS"\f \t", *parser->data)) | |||
349 | parser->data++; | |||
350 | return; | |||
351 | } | |||
352 | ||||
353 | if (ctk_css_parser_new_line (parser)) | |||
354 | return; | |||
355 | ||||
356 | g_string_append_c (str, *parser->data)g_string_append_c_inline (str, *parser->data); | |||
357 | parser->data++; | |||
358 | ||||
359 | return; | |||
360 | } | |||
361 | ||||
362 | static gboolean | |||
363 | _ctk_css_parser_read_char (CtkCssParser *parser, | |||
364 | GString * str, | |||
365 | const char * allowed) | |||
366 | { | |||
367 | if (*parser->data == 0) | |||
368 | return FALSE(0); | |||
369 | ||||
370 | if (strchr (allowed, *parser->data)) | |||
371 | { | |||
372 | g_string_append_c (str, *parser->data)g_string_append_c_inline (str, *parser->data); | |||
373 | parser->data++; | |||
374 | return TRUE(!(0)); | |||
375 | } | |||
376 | if (*parser->data >= 127) | |||
377 | { | |||
378 | gsize len = g_utf8_skip[(guint) *(guchar *) parser->data]; | |||
379 | ||||
380 | g_string_append_len (str, parser->data, len)g_string_append_len_inline (str, parser->data, len); | |||
381 | parser->data += len; | |||
382 | return TRUE(!(0)); | |||
383 | } | |||
384 | if (*parser->data == '\\') | |||
385 | { | |||
386 | _ctk_css_parser_unescape (parser, str); | |||
387 | return TRUE(!(0)); | |||
388 | } | |||
389 | ||||
390 | return FALSE(0); | |||
391 | } | |||
392 | ||||
393 | char * | |||
394 | _ctk_css_parser_try_name (CtkCssParser *parser, | |||
395 | gboolean skip_whitespace) | |||
396 | { | |||
397 | GString *name; | |||
398 | ||||
399 | g_return_val_if_fail (CTK_IS_CSS_PARSER (parser), NULL)do { if ((((parser) != ((void*)0)))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "CTK_IS_CSS_PARSER (parser)" ); return (((void*)0)); } } while (0); | |||
400 | ||||
401 | name = g_string_new (NULL((void*)0)); | |||
402 | ||||
403 | while (_ctk_css_parser_read_char (parser, name, NMCHAR"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" "01234567890-_")) | |||
404 | ; | |||
405 | ||||
406 | if (skip_whitespace) | |||
407 | _ctk_css_parser_skip_whitespace (parser); | |||
408 | ||||
409 | return g_string_free (name, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((name ), ((0))) : g_string_free_and_steal (name)) : (g_string_free) ((name), ((0)))); | |||
410 | } | |||
411 | ||||
412 | char * | |||
413 | _ctk_css_parser_try_ident (CtkCssParser *parser, | |||
414 | gboolean skip_whitespace) | |||
415 | { | |||
416 | const char *start; | |||
417 | GString *ident; | |||
418 | ||||
419 | g_return_val_if_fail (CTK_IS_CSS_PARSER (parser), NULL)do { if ((((parser) != ((void*)0)))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "CTK_IS_CSS_PARSER (parser)" ); return (((void*)0)); } } while (0); | |||
420 | ||||
421 | start = parser->data; | |||
422 | ||||
423 | ident = g_string_new (NULL((void*)0)); | |||
424 | ||||
425 | if (*parser->data == '-') | |||
426 | { | |||
427 | g_string_append_c (ident, '-')g_string_append_c_inline (ident, '-'); | |||
428 | parser->data++; | |||
429 | } | |||
430 | ||||
431 | if (!_ctk_css_parser_read_char (parser, ident, NMSTART"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")) | |||
432 | { | |||
433 | parser->data = start; | |||
434 | g_string_free (ident, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) ( (ident), ((!(0)))) : g_string_free_and_steal (ident)) : (g_string_free ) ((ident), ((!(0))))); | |||
435 | return NULL((void*)0); | |||
436 | } | |||
437 | ||||
438 | while (_ctk_css_parser_read_char (parser, ident, NMCHAR"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" "01234567890-_")) | |||
439 | ; | |||
440 | ||||
441 | if (skip_whitespace) | |||
442 | _ctk_css_parser_skip_whitespace (parser); | |||
443 | ||||
444 | return g_string_free (ident, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((ident ), ((0))) : g_string_free_and_steal (ident)) : (g_string_free ) ((ident), ((0)))); | |||
445 | } | |||
446 | ||||
447 | gboolean | |||
448 | _ctk_css_parser_is_string (CtkCssParser *parser) | |||
449 | { | |||
450 | g_return_val_if_fail (CTK_IS_CSS_PARSER (parser), FALSE)do { if ((((parser) != ((void*)0)))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "CTK_IS_CSS_PARSER (parser)" ); return ((0)); } } while (0); | |||
451 | ||||
452 | return *parser->data == '"' || *parser->data == '\''; | |||
453 | } | |||
454 | ||||
455 | char * | |||
456 | _ctk_css_parser_read_string (CtkCssParser *parser) | |||
457 | { | |||
458 | GString *str; | |||
459 | char quote; | |||
460 | ||||
461 | g_return_val_if_fail (CTK_IS_CSS_PARSER (parser), NULL)do { if ((((parser) != ((void*)0)))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "CTK_IS_CSS_PARSER (parser)" ); return (((void*)0)); } } while (0); | |||
462 | ||||
463 | quote = *parser->data; | |||
464 | ||||
465 | if (quote != '"' && quote != '\'') | |||
466 | { | |||
467 | _ctk_css_parser_error (parser, "Expected a string."); | |||
468 | return NULL((void*)0); | |||
469 | } | |||
470 | ||||
471 | parser->data++; | |||
472 | str = g_string_new (NULL((void*)0)); | |||
473 | ||||
474 | while (TRUE(!(0))) | |||
475 | { | |||
476 | gsize len = strcspn (parser->data, "\\'\"\n\r\f"); | |||
477 | ||||
478 | g_string_append_len (str, parser->data, len)g_string_append_len_inline (str, parser->data, len); | |||
479 | ||||
480 | parser->data += len; | |||
481 | ||||
482 | switch (*parser->data) | |||
483 | { | |||
484 | case '\\': | |||
485 | _ctk_css_parser_unescape (parser, str); | |||
486 | break; | |||
487 | case '"': | |||
488 | case '\'': | |||
489 | if (*parser->data == quote) | |||
490 | { | |||
491 | parser->data++; | |||
492 | _ctk_css_parser_skip_whitespace (parser); | |||
493 | return g_string_free (str, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((str) , ((0))) : g_string_free_and_steal (str)) : (g_string_free) ( (str), ((0)))); | |||
494 | } | |||
495 | ||||
496 | g_string_append_c (str, *parser->data)g_string_append_c_inline (str, *parser->data); | |||
497 | parser->data++; | |||
498 | break; | |||
499 | case '\0': | |||
500 | /* FIXME: position */ | |||
501 | _ctk_css_parser_error (parser, "Missing end quote in string."); | |||
502 | g_string_free (str, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) ( (str), ((!(0)))) : g_string_free_and_steal (str)) : (g_string_free ) ((str), ((!(0))))); | |||
503 | return NULL((void*)0); | |||
504 | default: | |||
505 | _ctk_css_parser_error (parser, | |||
506 | "Invalid character in string. Must be escaped."); | |||
507 | g_string_free (str, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) ( (str), ((!(0)))) : g_string_free_and_steal (str)) : (g_string_free ) ((str), ((!(0))))); | |||
508 | return NULL((void*)0); | |||
509 | } | |||
510 | } | |||
511 | ||||
512 | g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctkcssparser.c", 512, ( (const char*) (__func__)), ((void*)0)); } while (0); | |||
513 | return NULL((void*)0); | |||
514 | } | |||
515 | ||||
516 | gboolean | |||
517 | _ctk_css_parser_try_int (CtkCssParser *parser, | |||
518 | int *value) | |||
519 | { | |||
520 | gint64 result; | |||
521 | char *end; | |||
522 | ||||
523 | g_return_val_if_fail (CTK_IS_CSS_PARSER (parser), FALSE)do { if ((((parser) != ((void*)0)))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "CTK_IS_CSS_PARSER (parser)" ); return ((0)); } } while (0); | |||
524 | g_return_val_if_fail (value != NULL, FALSE)do { if ((value != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "value != NULL"); return ((0)); } } while (0); | |||
525 | ||||
526 | /* strtoll parses a plus, but we are not allowed to */ | |||
527 | if (*parser->data == '+') | |||
528 | return FALSE(0); | |||
529 | ||||
530 | errno(*__errno_location ()) = 0; | |||
531 | result = g_ascii_strtoll (parser->data, &end, 10); | |||
532 | if (errno(*__errno_location ())) | |||
533 | return FALSE(0); | |||
534 | if (result > G_MAXINT2147483647 || result < G_MININT(-2147483647 -1)) | |||
535 | return FALSE(0); | |||
536 | if (parser->data == end) | |||
537 | return FALSE(0); | |||
538 | ||||
539 | parser->data = end; | |||
540 | *value = result; | |||
541 | ||||
542 | _ctk_css_parser_skip_whitespace (parser); | |||
543 | ||||
544 | return TRUE(!(0)); | |||
545 | } | |||
546 | ||||
547 | gboolean | |||
548 | _ctk_css_parser_try_uint (CtkCssParser *parser, | |||
549 | guint *value) | |||
550 | { | |||
551 | guint64 result; | |||
552 | char *end; | |||
553 | ||||
554 | g_return_val_if_fail (CTK_IS_CSS_PARSER (parser), FALSE)do { if ((((parser) != ((void*)0)))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "CTK_IS_CSS_PARSER (parser)" ); return ((0)); } } while (0); | |||
555 | g_return_val_if_fail (value != NULL, FALSE)do { if ((value != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "value != NULL"); return ((0)); } } while (0); | |||
556 | ||||
557 | errno(*__errno_location ()) = 0; | |||
558 | result = g_ascii_strtoull (parser->data, &end, 10); | |||
559 | if (errno(*__errno_location ())) | |||
560 | return FALSE(0); | |||
561 | if (result > G_MAXUINT(2147483647 *2U +1U)) | |||
562 | return FALSE(0); | |||
563 | if (parser->data == end) | |||
564 | return FALSE(0); | |||
565 | ||||
566 | parser->data = end; | |||
567 | *value = result; | |||
568 | ||||
569 | _ctk_css_parser_skip_whitespace (parser); | |||
570 | ||||
571 | return TRUE(!(0)); | |||
572 | } | |||
573 | ||||
574 | gboolean | |||
575 | _ctk_css_parser_try_double (CtkCssParser *parser, | |||
576 | gdouble *value) | |||
577 | { | |||
578 | gdouble result; | |||
579 | char *end; | |||
580 | ||||
581 | g_return_val_if_fail (CTK_IS_CSS_PARSER (parser), FALSE)do { if ((((parser) != ((void*)0)))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "CTK_IS_CSS_PARSER (parser)" ); return ((0)); } } while (0); | |||
582 | g_return_val_if_fail (value != NULL, FALSE)do { if ((value != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "value != NULL"); return ((0)); } } while (0); | |||
583 | ||||
584 | errno(*__errno_location ()) = 0; | |||
585 | result = g_ascii_strtod (parser->data, &end); | |||
586 | if (errno(*__errno_location ())) | |||
587 | return FALSE(0); | |||
588 | if (parser->data == end) | |||
589 | return FALSE(0); | |||
590 | ||||
591 | parser->data = end; | |||
592 | *value = result; | |||
593 | ||||
594 | _ctk_css_parser_skip_whitespace (parser); | |||
595 | ||||
596 | return TRUE(!(0)); | |||
597 | } | |||
598 | ||||
599 | gboolean | |||
600 | _ctk_css_parser_has_number (CtkCssParser *parser) | |||
601 | { | |||
602 | char c; | |||
603 | ||||
604 | if (parser->data[0] == '-' || parser->data[0] == '+') | |||
605 | c = parser->data[1]; | |||
606 | else | |||
607 | c = parser->data[0]; | |||
608 | ||||
609 | /* ahem */ | |||
610 | return g_ascii_isdigit (c)((g_ascii_table[(guchar) (c)] & G_ASCII_DIGIT) != 0) || c == '.'; | |||
611 | } | |||
612 | ||||
613 | CtkCssValue * | |||
614 | ctk_css_dimension_value_parse (CtkCssParser *parser, | |||
615 | CtkCssNumberParseFlags flags) | |||
616 | { | |||
617 | static const struct { | |||
618 | const char *name; | |||
619 | CtkCssUnit unit; | |||
620 | CtkCssNumberParseFlags required_flags; | |||
621 | } units[] = { | |||
622 | { "px", CTK_CSS_PX, CTK_CSS_PARSE_LENGTH }, | |||
623 | { "pt", CTK_CSS_PT, CTK_CSS_PARSE_LENGTH }, | |||
624 | { "em", CTK_CSS_EM, CTK_CSS_PARSE_LENGTH }, | |||
625 | { "ex", CTK_CSS_EX, CTK_CSS_PARSE_LENGTH }, | |||
626 | { "rem", CTK_CSS_REM, CTK_CSS_PARSE_LENGTH }, | |||
627 | { "pc", CTK_CSS_PC, CTK_CSS_PARSE_LENGTH }, | |||
628 | { "in", CTK_CSS_IN, CTK_CSS_PARSE_LENGTH }, | |||
629 | { "cm", CTK_CSS_CM, CTK_CSS_PARSE_LENGTH }, | |||
630 | { "mm", CTK_CSS_MM, CTK_CSS_PARSE_LENGTH }, | |||
631 | { "rad", CTK_CSS_RAD, CTK_CSS_PARSE_ANGLE }, | |||
632 | { "deg", CTK_CSS_DEG, CTK_CSS_PARSE_ANGLE }, | |||
633 | { "grad", CTK_CSS_GRAD, CTK_CSS_PARSE_ANGLE }, | |||
634 | { "turn", CTK_CSS_TURN, CTK_CSS_PARSE_ANGLE }, | |||
635 | { "s", CTK_CSS_S, CTK_CSS_PARSE_TIME }, | |||
636 | { "ms", CTK_CSS_MS, CTK_CSS_PARSE_TIME } | |||
637 | }; | |||
638 | char *end, *unit_name; | |||
639 | double value; | |||
640 | CtkCssUnit unit; | |||
641 | ||||
642 | g_return_val_if_fail (CTK_IS_CSS_PARSER (parser), NULL)do { if ((((parser) != ((void*)0)))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "CTK_IS_CSS_PARSER (parser)" ); return (((void*)0)); } } while (0); | |||
643 | ||||
644 | errno(*__errno_location ()) = 0; | |||
645 | value = g_ascii_strtod (parser->data, &end); | |||
646 | if (errno(*__errno_location ())) | |||
647 | { | |||
648 | _ctk_css_parser_error (parser, "not a number: %s", g_strerror (errno(*__errno_location ()))); | |||
649 | return NULL((void*)0); | |||
650 | } | |||
651 | if (parser->data == end) | |||
652 | { | |||
653 | _ctk_css_parser_error (parser, "not a number"); | |||
654 | return NULL((void*)0); | |||
655 | } | |||
656 | ||||
657 | parser->data = end; | |||
658 | ||||
659 | if (flags & CTK_CSS_POSITIVE_ONLY && | |||
660 | value < 0) | |||
661 | { | |||
662 | _ctk_css_parser_error (parser, "negative values are not allowed."); | |||
663 | return NULL((void*)0); | |||
664 | } | |||
665 | ||||
666 | unit_name = _ctk_css_parser_try_ident (parser, FALSE(0)); | |||
667 | ||||
668 | if (unit_name) | |||
669 | { | |||
670 | guint i; | |||
671 | ||||
672 | for (i = 0; i < G_N_ELEMENTS (units)(sizeof (units) / sizeof ((units)[0])); i++) | |||
673 | { | |||
674 | if (flags & units[i].required_flags && | |||
675 | g_ascii_strcasecmp (unit_name, units[i].name) == 0) | |||
676 | break; | |||
677 | } | |||
678 | ||||
679 | if (i >= G_N_ELEMENTS (units)(sizeof (units) / sizeof ((units)[0]))) | |||
680 | { | |||
681 | _ctk_css_parser_error (parser, "'%s' is not a valid unit.", unit_name); | |||
682 | g_free (unit_name); | |||
683 | return NULL((void*)0); | |||
684 | } | |||
685 | ||||
686 | unit = units[i].unit; | |||
687 | ||||
688 | g_free (unit_name); | |||
689 | } | |||
690 | else | |||
691 | { | |||
692 | if ((flags & CTK_CSS_PARSE_PERCENT) && | |||
693 | _ctk_css_parser_try (parser, "%", FALSE(0))) | |||
694 | { | |||
695 | unit = CTK_CSS_PERCENT; | |||
696 | } | |||
697 | else if (value == 0.0) | |||
698 | { | |||
699 | if (flags & CTK_CSS_PARSE_NUMBER) | |||
700 | unit = CTK_CSS_NUMBER; | |||
701 | else if (flags & CTK_CSS_PARSE_LENGTH) | |||
702 | unit = CTK_CSS_PX; | |||
703 | else if (flags & CTK_CSS_PARSE_ANGLE) | |||
704 | unit = CTK_CSS_DEG; | |||
705 | else if (flags & CTK_CSS_PARSE_TIME) | |||
706 | unit = CTK_CSS_S; | |||
707 | else | |||
708 | unit = CTK_CSS_PERCENT; | |||
709 | } | |||
710 | else if (flags & CTK_CSS_NUMBER_AS_PIXELS) | |||
711 | { | |||
712 | _ctk_css_parser_error_full (parser, | |||
713 | CTK_CSS_PROVIDER_ERROR_DEPRECATED, | |||
714 | "Not using units is deprecated. Assuming 'px'."); | |||
715 | unit = CTK_CSS_PX; | |||
716 | } | |||
717 | else if (flags & CTK_CSS_PARSE_NUMBER) | |||
718 | { | |||
719 | unit = CTK_CSS_NUMBER; | |||
720 | } | |||
721 | else | |||
722 | { | |||
723 | _ctk_css_parser_error (parser, "Unit is missing."); | |||
724 | return NULL((void*)0); | |||
725 | } | |||
726 | } | |||
727 | ||||
728 | _ctk_css_parser_skip_whitespace (parser); | |||
729 | ||||
730 | return ctk_css_dimension_value_new (value, unit); | |||
731 | } | |||
732 | ||||
733 | /* XXX: we should introduce CtkCssLenght that deals with | |||
734 | * different kind of units */ | |||
735 | gboolean | |||
736 | _ctk_css_parser_try_length (CtkCssParser *parser, | |||
737 | int *value) | |||
738 | { | |||
739 | if (!_ctk_css_parser_try_int (parser, value)) | |||
740 | return FALSE(0); | |||
741 | ||||
742 | /* FIXME: _try_uint skips spaces while the | |||
743 | * spec forbids them | |||
744 | */ | |||
745 | _ctk_css_parser_try (parser, "px", TRUE(!(0))); | |||
746 | ||||
747 | return TRUE(!(0)); | |||
748 | } | |||
749 | ||||
750 | gboolean | |||
751 | _ctk_css_parser_try_enum (CtkCssParser *parser, | |||
752 | GType enum_type, | |||
753 | int *value) | |||
754 | { | |||
755 | GEnumClass *enum_class; | |||
756 | gboolean result; | |||
757 | const char *start; | |||
758 | char *str; | |||
759 | ||||
760 | g_return_val_if_fail (CTK_IS_CSS_PARSER (parser), FALSE)do { if ((((parser) != ((void*)0)))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "CTK_IS_CSS_PARSER (parser)" ); return ((0)); } } while (0); | |||
761 | g_return_val_if_fail (value != NULL, FALSE)do { if ((value != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "value != NULL"); return ((0)); } } while (0); | |||
762 | ||||
763 | result = FALSE(0); | |||
764 | ||||
765 | enum_class = g_type_class_ref (enum_type); | |||
766 | ||||
767 | start = parser->data; | |||
768 | ||||
769 | str = _ctk_css_parser_try_ident (parser, TRUE(!(0))); | |||
770 | if (str == NULL((void*)0)) | |||
771 | return FALSE(0); | |||
772 | ||||
773 | if (enum_class->n_values) | |||
774 | { | |||
775 | GEnumValue *enum_value; | |||
776 | ||||
777 | for (enum_value = enum_class->values; enum_value->value_name; enum_value++) | |||
778 | { | |||
779 | if (enum_value->value_nick && | |||
780 | g_ascii_strcasecmp (str, enum_value->value_nick) == 0) | |||
781 | { | |||
782 | *value = enum_value->value; | |||
783 | result = TRUE(!(0)); | |||
784 | break; | |||
785 | } | |||
786 | } | |||
787 | } | |||
788 | ||||
789 | g_free (str); | |||
790 | g_type_class_unref (enum_class); | |||
791 | ||||
792 | if (!result) | |||
793 | parser->data = start; | |||
794 | ||||
795 | return result; | |||
796 | } | |||
797 | ||||
798 | gboolean | |||
799 | _ctk_css_parser_try_hash_color (CtkCssParser *parser, | |||
800 | CdkRGBA *rgba) | |||
801 | { | |||
802 | if (parser->data[0] == '#' && | |||
803 | g_ascii_isxdigit (parser->data[1])((g_ascii_table[(guchar) (parser->data[1])] & G_ASCII_XDIGIT ) != 0) && | |||
804 | g_ascii_isxdigit (parser->data[2])((g_ascii_table[(guchar) (parser->data[2])] & G_ASCII_XDIGIT ) != 0) && | |||
805 | g_ascii_isxdigit (parser->data[3])((g_ascii_table[(guchar) (parser->data[3])] & G_ASCII_XDIGIT ) != 0)) | |||
806 | { | |||
807 | if (g_ascii_isxdigit (parser->data[4])((g_ascii_table[(guchar) (parser->data[4])] & G_ASCII_XDIGIT ) != 0) && | |||
808 | g_ascii_isxdigit (parser->data[5])((g_ascii_table[(guchar) (parser->data[5])] & G_ASCII_XDIGIT ) != 0) && | |||
809 | g_ascii_isxdigit (parser->data[6])((g_ascii_table[(guchar) (parser->data[6])] & G_ASCII_XDIGIT ) != 0)) | |||
810 | { | |||
811 | rgba->red = ((get_xdigit (parser->data[1]) << 4) + get_xdigit (parser->data[2])) / 255.0; | |||
812 | rgba->green = ((get_xdigit (parser->data[3]) << 4) + get_xdigit (parser->data[4])) / 255.0; | |||
813 | rgba->blue = ((get_xdigit (parser->data[5]) << 4) + get_xdigit (parser->data[6])) / 255.0; | |||
814 | rgba->alpha = 1.0; | |||
815 | parser->data += 7; | |||
816 | } | |||
817 | else | |||
818 | { | |||
819 | rgba->red = get_xdigit (parser->data[1]) / 15.0; | |||
820 | rgba->green = get_xdigit (parser->data[2]) / 15.0; | |||
821 | rgba->blue = get_xdigit (parser->data[3]) / 15.0; | |||
822 | rgba->alpha = 1.0; | |||
823 | parser->data += 4; | |||
824 | } | |||
825 | ||||
826 | _ctk_css_parser_skip_whitespace (parser); | |||
827 | ||||
828 | return TRUE(!(0)); | |||
829 | } | |||
830 | ||||
831 | return FALSE(0); | |||
832 | } | |||
833 | ||||
834 | GFile * | |||
835 | _ctk_css_parser_read_url (CtkCssParser *parser) | |||
836 | { | |||
837 | gchar *path; | |||
838 | char *scheme; | |||
839 | GFile *file; | |||
840 | ||||
841 | if (_ctk_css_parser_try (parser, "url", FALSE(0))) | |||
842 | { | |||
843 | if (!_ctk_css_parser_try (parser, "(", TRUE(!(0)))) | |||
844 | { | |||
845 | _ctk_css_parser_skip_whitespace (parser); | |||
846 | if (_ctk_css_parser_try (parser, "(", TRUE(!(0)))) | |||
847 | { | |||
848 | _ctk_css_parser_error_full (parser, | |||
849 | CTK_CSS_PROVIDER_ERROR_DEPRECATED, | |||
850 | "Whitespace between 'url' and '(' is deprecated"); | |||
851 | } | |||
852 | else | |||
853 | { | |||
854 | _ctk_css_parser_error (parser, "Expected '(' after 'url'"); | |||
855 | return NULL((void*)0); | |||
856 | } | |||
857 | } | |||
858 | ||||
859 | path = _ctk_css_parser_read_string (parser); | |||
860 | if (path == NULL((void*)0)) | |||
861 | return NULL((void*)0); | |||
862 | ||||
863 | if (!_ctk_css_parser_try (parser, ")", TRUE(!(0)))) | |||
864 | { | |||
865 | _ctk_css_parser_error (parser, "No closing ')' found for 'url'"); | |||
866 | g_free (path); | |||
867 | return NULL((void*)0); | |||
868 | } | |||
869 | ||||
870 | scheme = g_uri_parse_scheme (path); | |||
871 | if (scheme != NULL((void*)0)) | |||
872 | { | |||
873 | file = g_file_new_for_uri (path); | |||
874 | g_free (path); | |||
875 | g_free (scheme); | |||
876 | return file; | |||
877 | } | |||
878 | } | |||
879 | else | |||
880 | { | |||
881 | path = _ctk_css_parser_try_name (parser, TRUE(!(0))); | |||
882 | if (path == NULL((void*)0)) | |||
883 | { | |||
884 | _ctk_css_parser_error (parser, "Not a valid url"); | |||
885 | return NULL((void*)0); | |||
886 | } | |||
887 | } | |||
888 | ||||
889 | file = _ctk_css_parser_get_file_for_path (parser, path); | |||
890 | g_free (path); | |||
891 | ||||
892 | return file; | |||
893 | } | |||
894 | ||||
895 | static void | |||
896 | ctk_css_parser_resync_internal (CtkCssParser *parser, | |||
897 | gboolean sync_at_semicolon, | |||
898 | gboolean read_sync_token, | |||
899 | char terminator) | |||
900 | { | |||
901 | gsize len; | |||
902 | ||||
903 | do { | |||
904 | len = strcspn (parser->data, "\\\"'/()[]{};" NEWLINE_CHARS"\r\n"); | |||
905 | parser->data += len; | |||
906 | ||||
907 | if (ctk_css_parser_new_line (parser)) | |||
908 | continue; | |||
909 | ||||
910 | if (_ctk_css_parser_is_string (parser)) | |||
911 | { | |||
912 | /* Hrm, this emits errors, and i suspect it shouldn't... */ | |||
913 | char *free_me = _ctk_css_parser_read_string (parser); | |||
914 | g_free (free_me); | |||
915 | continue; | |||
916 | } | |||
917 | ||||
918 | if (ctk_css_parser_skip_comment (parser)) | |||
919 | continue; | |||
920 | ||||
921 | switch (*parser->data) | |||
922 | { | |||
923 | case '\\': | |||
924 | { | |||
925 | GString *ignore = g_string_new (NULL((void*)0)); | |||
926 | _ctk_css_parser_unescape (parser, ignore); | |||
927 | g_string_free (ignore, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) ( (ignore), ((!(0)))) : g_string_free_and_steal (ignore)) : (g_string_free ) ((ignore), ((!(0))))); | |||
928 | } | |||
929 | break; | |||
930 | case ';': | |||
931 | if (sync_at_semicolon && !read_sync_token) | |||
932 | return; | |||
933 | parser->data++; | |||
934 | if (sync_at_semicolon) | |||
935 | { | |||
936 | _ctk_css_parser_skip_whitespace (parser); | |||
937 | return; | |||
938 | } | |||
939 | break; | |||
940 | case '(': | |||
941 | parser->data++; | |||
942 | _ctk_css_parser_resync (parser, FALSE(0), ')'); | |||
943 | if (*parser->data) | |||
944 | parser->data++; | |||
945 | break; | |||
946 | case '[': | |||
947 | parser->data++; | |||
948 | _ctk_css_parser_resync (parser, FALSE(0), ']'); | |||
949 | if (*parser->data) | |||
950 | parser->data++; | |||
951 | break; | |||
952 | case '{': | |||
953 | parser->data++; | |||
954 | _ctk_css_parser_resync (parser, FALSE(0), '}'); | |||
955 | if (*parser->data) | |||
956 | parser->data++; | |||
957 | if (sync_at_semicolon || !terminator) | |||
958 | { | |||
959 | _ctk_css_parser_skip_whitespace (parser); | |||
960 | return; | |||
961 | } | |||
962 | break; | |||
963 | case '}': | |||
964 | case ')': | |||
965 | case ']': | |||
966 | if (terminator == *parser->data) | |||
967 | { | |||
968 | _ctk_css_parser_skip_whitespace (parser); | |||
969 | return; | |||
970 | } | |||
971 | parser->data++; | |||
972 | continue; | |||
973 | case '\0': | |||
974 | break; | |||
975 | case '/': | |||
976 | default: | |||
977 | parser->data++; | |||
978 | break; | |||
979 | } | |||
980 | } while (*parser->data); | |||
981 | } | |||
982 | ||||
983 | char * | |||
984 | _ctk_css_parser_read_value (CtkCssParser *parser) | |||
985 | { | |||
986 | const char *start; | |||
987 | char *result; | |||
988 | ||||
989 | g_return_val_if_fail (CTK_IS_CSS_PARSER (parser), NULL)do { if ((((parser) != ((void*)0)))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "CTK_IS_CSS_PARSER (parser)" ); return (((void*)0)); } } while (0); | |||
| ||||
990 | ||||
991 | start = parser->data; | |||
992 | ||||
993 | /* This needs to be done better */ | |||
994 | ctk_css_parser_resync_internal (parser, TRUE(!(0)), FALSE(0), '}'); | |||
995 | ||||
996 | result = g_strndup (start, parser->data - start); | |||
997 | if (result) | |||
998 | { | |||
999 | g_strchomp (result); | |||
1000 | if (result[0] == 0) | |||
1001 | { | |||
1002 | g_free (result); | |||
1003 | result = NULL((void*)0); | |||
1004 | } | |||
1005 | } | |||
1006 | ||||
1007 | if (result == NULL((void*)0)) | |||
1008 | _ctk_css_parser_error (parser, "Expected a property value"); | |||
1009 | ||||
1010 | return result; | |||
1011 | } | |||
1012 | ||||
1013 | void | |||
1014 | _ctk_css_parser_resync (CtkCssParser *parser, | |||
1015 | gboolean sync_at_semicolon, | |||
1016 | char terminator) | |||
1017 | { | |||
1018 | g_return_if_fail (CTK_IS_CSS_PARSER (parser))do { if ((((parser) != ((void*)0)))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "CTK_IS_CSS_PARSER (parser)" ); return; } } while (0); | |||
1019 | ||||
1020 | ctk_css_parser_resync_internal (parser, sync_at_semicolon, TRUE(!(0)), terminator); | |||
1021 | } | |||
1022 | ||||
1023 | void | |||
1024 | _ctk_css_print_string (GString *str, | |||
1025 | const char *string) | |||
1026 | { | |||
1027 | gsize len; | |||
1028 | ||||
1029 | g_return_if_fail (str != NULL)do { if ((str != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "str != NULL"); return; } } while (0); | |||
1030 | g_return_if_fail (string != NULL)do { if ((string != ((void*)0))) { } else { g_return_if_fail_warning ("Ctk", ((const char*) (__func__)), "string != NULL"); return ; } } while (0); | |||
1031 | ||||
1032 | g_string_append_c (str, '"')g_string_append_c_inline (str, '"'); | |||
1033 | ||||
1034 | do { | |||
1035 | len = strcspn (string, "\\\"\n\r\f"); | |||
1036 | g_string_append_len (str, string, len)g_string_append_len_inline (str, string, len); | |||
1037 | string += len; | |||
1038 | switch (*string) | |||
1039 | { | |||
1040 | case '\0': | |||
1041 | goto out; | |||
1042 | case '\n': | |||
1043 | g_string_append (str, "\\A ")(__builtin_constant_p ("\\A ") ? __extension__ ({ const char * const __val = ("\\A "); g_string_append_len_inline (str, __val , (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val ))) : (gssize) -1); }) : g_string_append_len_inline (str, "\\A " , (gssize) -1)); | |||
1044 | break; | |||
1045 | case '\r': | |||
1046 | g_string_append (str, "\\D ")(__builtin_constant_p ("\\D ") ? __extension__ ({ const char * const __val = ("\\D "); g_string_append_len_inline (str, __val , (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val ))) : (gssize) -1); }) : g_string_append_len_inline (str, "\\D " , (gssize) -1)); | |||
1047 | break; | |||
1048 | case '\f': | |||
1049 | g_string_append (str, "\\C ")(__builtin_constant_p ("\\C ") ? __extension__ ({ const char * const __val = ("\\C "); g_string_append_len_inline (str, __val , (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val ))) : (gssize) -1); }) : g_string_append_len_inline (str, "\\C " , (gssize) -1)); | |||
1050 | break; | |||
1051 | case '\"': | |||
1052 | g_string_append (str, "\\\"")(__builtin_constant_p ("\\\"") ? __extension__ ({ const char * const __val = ("\\\""); g_string_append_len_inline (str, __val , (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val ))) : (gssize) -1); }) : g_string_append_len_inline (str, "\\\"" , (gssize) -1)); | |||
1053 | break; | |||
1054 | case '\\': | |||
1055 | g_string_append (str, "\\\\")(__builtin_constant_p ("\\\\") ? __extension__ ({ const char * const __val = ("\\\\"); g_string_append_len_inline (str, __val , (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val ))) : (gssize) -1); }) : g_string_append_len_inline (str, "\\\\" , (gssize) -1)); | |||
1056 | break; | |||
1057 | default: | |||
1058 | g_assert_not_reached ()do { g_assertion_message_expr ("Ctk", "ctkcssparser.c", 1058, ((const char*) (__func__)), ((void*)0)); } while (0); | |||
1059 | break; | |||
1060 | } | |||
1061 | string++; | |||
1062 | } while (*string); | |||
1063 | ||||
1064 | out: | |||
1065 | g_string_append_c (str, '"')g_string_append_c_inline (str, '"'); | |||
1066 | } | |||
1067 |