Bug Summary

File:ctk/ctkcssparser.c
Warning:line 259, column 22
Out of bound memory access (access exceeds upper limit of memory block)

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ctkcssparser.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/ctk -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I .. -D G_LOG_DOMAIN="Ctk" -D G_LOG_USE_STRUCTURED=1 -D CTK_VERSION="3.25.5" -D CTK_BINARY_VERSION="3.0.0" -D CTK_COMPILATION -D CTK_PRINT_BACKEND_ENABLE_UNSUPPORTED -D CTK_LIBDIR="/usr/lib" -D CTK_LOCALEDIR="/usr/share/locale" -D CTK_DATADIR="/usr/share" -D CTK_DATA_PREFIX="/usr" -D CTK_SYSCONFDIR="/usr/etc" -D CTK_HOST="x86_64-pc-linux-gnu" -D CTK_PRINT_BACKENDS="file,cups" -D X11_DATA_PREFIX="/usr" -D ISO_CODES_PREFIX="" -I .. -I ../ctk -I .. -I ../cdk -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -D G_ENABLE_DEBUG -D G_ENABLE_CONSISTENCY_CHECKS -D GLIB_MIN_REQUIRED_VERSION=GLIB_VERSION_2_66 -D GLIB_MAX_ALLOWED_VERSION=GLIB_VERSION_2_66 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/atk-1.0 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/gio-unix-2.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/pango-1.0 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -D PIC -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/ctk -ferror-limit 19 -fvisibility=hidden -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2024-09-19-171836-43636-1 -x c ctkcssparser.c
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
38struct _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
49CtkCssParser *
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
74void
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
85gboolean
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
93gboolean
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
102gboolean
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
111guint
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
119guint
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
127static GFile *
128ctk_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
146GFile *
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
162GFile *
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
170void
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
179void
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
197void
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}
214static gboolean
215ctk_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
239static gboolean
240ctk_css_parser_skip_comment (CtkCssParser *parser)
241{
242 if (parser->data[0] != '/' ||
18
Assuming the condition is false
20
Taking false branch
243 parser->data[1] != '*')
19
Assuming the condition is false
244 return FALSE(0);
245
246 parser->data += 2;
247
248 while (*parser->data)
21
Loop condition is true. Entering loop body
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))
22
Assuming the condition is false
23
Taking false branch
255 continue;
256
257 parser->data++;
258
259 if (len > 0 && parser->data[-2] == '*')
24
Assuming 'len' is > 0
25
Out of bound memory access (access exceeds upper limit of memory block)
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
270void
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
292gboolean
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
310static guint
311get_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
321static 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
362static 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
393char *
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
412char *
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
447gboolean
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
455char *
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
516gboolean
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
547gboolean
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
574gboolean
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
599gboolean
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
613CtkCssValue *
614ctk_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 */
735gboolean
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
750gboolean
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
798gboolean
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
834GFile *
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
895static void
896ctk_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))
5
Taking false branch
14
Taking false branch
908 continue;
909
910 if (_ctk_css_parser_is_string (parser))
6
Assuming the condition is false
7
Taking false branch
15
Assuming the condition is false
16
Taking false branch
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))
8
Taking false branch
17
Calling 'ctk_css_parser_skip_comment'
919 continue;
920
921 switch (*parser->data)
9
Control jumps to 'case 123:' at line 952
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), '}');
10
Calling '_ctk_css_parser_resync'
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
983char *
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)
;
1
Assuming 'parser' is not equal to null
2
Taking true branch
3
Loop condition is false. Exiting loop
990
991 start = parser->data;
992
993 /* This needs to be done better */
994 ctk_css_parser_resync_internal (parser, TRUE(!(0)), FALSE(0), '}');
4
Calling 'ctk_css_parser_resync_internal'
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
1013void
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)
;
11
Taking true branch
12
Loop condition is false. Exiting loop
1019
1020 ctk_css_parser_resync_internal (parser, sync_at_semicolon, TRUE(!(0)), terminator);
13
Calling 'ctk_css_parser_resync_internal'
1021}
1022
1023void
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
1064out:
1065 g_string_append_c (str, '"')g_string_append_c_inline (str, '"');
1066}
1067