1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
4 * GimpRc deserialization routines
5 * Copyright (C) 2001-2002 Sven Neumann <sven@gimp.org>
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21 #include "config.h"
22
23 #include <cairo.h>
24 #include <gegl.h>
25 #include <gdk-pixbuf/gdk-pixbuf.h>
26
27 #include "libgimpcolor/gimpcolor.h"
28 #include "libgimpmath/gimpmath.h"
29 #include "libgimpconfig/gimpconfig.h"
30
31 #include "config-types.h"
32
33 #include "gimprc-deserialize.h"
34 #include "gimprc-unknown.h"
35
36 #include "gimp-intl.h"
37
38
39 static GTokenType gimp_rc_deserialize_unknown (GimpConfig *config,
40 GScanner *scanner);
41
42
43 gboolean
gimp_rc_deserialize(GimpConfig * config,GScanner * scanner,gint nest_level,gpointer data)44 gimp_rc_deserialize (GimpConfig *config,
45 GScanner *scanner,
46 gint nest_level,
47 gpointer data)
48 {
49 GObjectClass *klass;
50 GParamSpec **property_specs;
51 guint n_property_specs;
52 guint i;
53 guint scope_id;
54 guint old_scope_id;
55 GTokenType token;
56 GTokenType next;
57
58 g_return_val_if_fail (GIMP_IS_CONFIG (config), FALSE);
59
60 klass = G_OBJECT_GET_CLASS (config);
61
62 property_specs = g_object_class_list_properties (klass, &n_property_specs);
63 if (! property_specs)
64 return TRUE;
65
66 scope_id = g_type_qname (G_TYPE_FROM_INSTANCE (config));
67 old_scope_id = g_scanner_set_scope (scanner, scope_id);
68
69 for (i = 0; i < n_property_specs; i++)
70 {
71 GParamSpec *prop_spec = property_specs[i];
72
73 if (prop_spec->flags & GIMP_CONFIG_PARAM_SERIALIZE)
74 {
75 g_scanner_scope_add_symbol (scanner, scope_id,
76 prop_spec->name, prop_spec);
77 }
78 }
79
80 g_free (property_specs);
81
82 g_object_freeze_notify (G_OBJECT (config));
83
84 token = G_TOKEN_LEFT_PAREN;
85
86 while (TRUE)
87 {
88 next = g_scanner_peek_next_token (scanner);
89
90 if (G_UNLIKELY (next != token && ! (token == G_TOKEN_SYMBOL &&
91 next == G_TOKEN_IDENTIFIER)))
92 {
93 break;
94 }
95
96 token = g_scanner_get_next_token (scanner);
97
98 switch (token)
99 {
100 case G_TOKEN_LEFT_PAREN:
101 token = G_TOKEN_SYMBOL;
102 break;
103
104 case G_TOKEN_IDENTIFIER:
105 token = gimp_rc_deserialize_unknown (config, scanner);
106 break;
107
108 case G_TOKEN_SYMBOL:
109 token = gimp_config_deserialize_property (config,
110 scanner, nest_level);
111 break;
112
113 case G_TOKEN_RIGHT_PAREN:
114 token = G_TOKEN_LEFT_PAREN;
115 break;
116
117 default: /* do nothing */
118 break;
119 }
120 }
121
122 g_scanner_set_scope (scanner, old_scope_id);
123
124 g_object_thaw_notify (G_OBJECT (config));
125
126 if (token == G_TOKEN_NONE)
127 return FALSE;
128
129 /* If the unknown token value couldn't be parsed the default error
130 message is rather confusing. We try to produce something more
131 meaningful here ...
132 */
133 if (token == G_TOKEN_STRING && next == G_TOKEN_IDENTIFIER)
134 {
135 g_scanner_unexp_token (scanner, G_TOKEN_SYMBOL, NULL, NULL, NULL,
136 _("fatal parse error"), TRUE);
137 return FALSE;
138 }
139
140 return gimp_config_deserialize_return (scanner, token, nest_level);
141 }
142
143 static GTokenType
gimp_rc_deserialize_unknown(GimpConfig * config,GScanner * scanner)144 gimp_rc_deserialize_unknown (GimpConfig *config,
145 GScanner *scanner)
146 {
147 gchar *key;
148 guint old_scope_id;
149
150 old_scope_id = g_scanner_set_scope (scanner, 0);
151
152 if (g_scanner_peek_next_token (scanner) != G_TOKEN_STRING)
153 return G_TOKEN_STRING;
154
155 key = g_strdup (scanner->value.v_identifier);
156
157 g_scanner_get_next_token (scanner);
158
159 g_scanner_set_scope (scanner, old_scope_id);
160
161 if (! g_utf8_validate (scanner->value.v_string, -1, NULL))
162 {
163 g_scanner_error (scanner,
164 _("value for token %s is not a valid UTF-8 string"),
165 key);
166 g_free (key);
167 return G_TOKEN_NONE;
168 }
169
170 gimp_rc_add_unknown_token (config, key, scanner->value.v_string);
171 g_free (key);
172
173 return G_TOKEN_RIGHT_PAREN;
174 }
175