2 * Copyright © 2010 Codethink Limited
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 licence, or (at your option) any later version.
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.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
19 * Author: Ryan Lortie <desrt@desrt.ca>
34 #include "gvdb/gvdb-builder.h"
37 /* Handling of <enum> {{{1 */
38 typedef GString EnumState;
41 enum_state_free (gpointer data)
43 EnumState *state = data;
45 g_string_free (state, TRUE);
49 enum_state_add_value (EnumState *state,
51 const gchar *valuestr,
57 if (nick[0] == '\0' || nick[1] == '\0')
59 g_set_error (error, G_MARKUP_ERROR,
60 G_MARKUP_ERROR_INVALID_CONTENT,
61 "enum nick must be a minimum of 2 characters");
65 value = g_ascii_strtoll (valuestr, &end, 0);
66 if (*end || value > G_MAXINT32 || value < G_MININT32)
68 g_set_error (error, G_MARKUP_ERROR,
69 G_MARKUP_ERROR_INVALID_CONTENT,
70 "invalid numeric value");
74 if (strinfo_builder_contains (state, nick))
76 g_set_error (error, G_MARKUP_ERROR,
77 G_MARKUP_ERROR_INVALID_CONTENT,
78 "<value nick='%s'> already specified", nick);
82 strinfo_builder_append_item (state, nick, value);
86 enum_state_end (EnumState **state_ptr,
95 g_set_error_literal (error,
96 G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
97 "<enum> must contain at least one <value>");
100 /* Handling of <key> {{{1 */
103 /* for <child>, @child_schema will be set.
104 * for <key>, everything else will be set.
110 gboolean have_gettext_domain;
114 GString *unparsed_default_value;
115 GVariant *default_value;
123 gboolean has_choices;
124 gboolean has_aliases;
127 GVariant *serialised;
131 key_state_new (const gchar *type_string,
132 const gchar *gettext_domain,
133 EnumState *enum_data)
137 state = g_slice_new0 (KeyState);
138 state->type = g_variant_type_new (type_string);
139 state->have_gettext_domain = gettext_domain != NULL;
141 if ((state->is_enum = (enum_data != NULL)))
142 state->strinfo = g_string_new_len (enum_data->str, enum_data->len);
144 state->strinfo = g_string_new (NULL);
150 key_state_new_child (const gchar *child_schema)
154 state = g_slice_new0 (KeyState);
155 state->child_schema = g_strdup (child_schema);
161 is_valid_choices (GVariant *variant,
164 switch (g_variant_classify (variant))
166 case G_VARIANT_CLASS_MAYBE:
167 case G_VARIANT_CLASS_ARRAY:
169 gboolean valid = TRUE;
172 g_variant_iter_init (&iter, variant);
174 while (valid && (variant = g_variant_iter_next_value (&iter)))
176 valid = is_valid_choices (variant, strinfo);
177 g_variant_unref (variant);
183 case G_VARIANT_CLASS_STRING:
184 return strinfo_is_string_valid ((const guint32 *) strinfo->str,
186 g_variant_get_string (variant, NULL));
189 g_assert_not_reached ();
194 /* Gets called at </default> </choices> or <range/> to check for
195 * validity of the default value so that any inconsistency is
196 * reported as soon as it is encountered.
199 key_state_check_range (KeyState *state,
202 if (state->default_value)
206 if (g_variant_compare (state->default_value, state->minimum) < 0 ||
207 g_variant_compare (state->default_value, state->maximum) > 0)
209 g_set_error (error, G_MARKUP_ERROR,
210 G_MARKUP_ERROR_INVALID_CONTENT,
211 "<default> is not contained in "
212 "the specified range");
216 else if (state->strinfo->len)
218 if (!is_valid_choices (state->default_value, state->strinfo))
221 g_set_error_literal (error, G_MARKUP_ERROR,
222 G_MARKUP_ERROR_INVALID_CONTENT,
223 "<default> is not a valid member of "
224 "the specified enumerated type");
227 g_set_error_literal (error, G_MARKUP_ERROR,
228 G_MARKUP_ERROR_INVALID_CONTENT,
229 "<default> contains string not in "
237 key_state_set_range (KeyState *state,
238 const gchar *min_str,
239 const gchar *max_str,
244 g_set_error_literal (error, G_MARKUP_ERROR,
245 G_MARKUP_ERROR_INVALID_CONTENT,
246 "<range/> already specified for this key");
250 if (strchr ("ynqiuxtd", *(char *) state->type) == NULL)
252 gchar *type = g_variant_type_dup_string (state->type);
253 g_set_error (error, G_MARKUP_ERROR,
254 G_MARKUP_ERROR_INVALID_CONTENT,
255 "<range> not allowed for keys of type '%s'", type);
260 state->minimum = g_variant_parse (state->type, min_str, NULL, NULL, error);
261 if (state->minimum == NULL)
264 state->maximum = g_variant_parse (state->type, max_str, NULL, NULL, error);
265 if (state->maximum == NULL)
268 if (g_variant_compare (state->minimum, state->maximum) > 0)
270 g_set_error (error, G_MARKUP_ERROR,
271 G_MARKUP_ERROR_INVALID_CONTENT,
272 "<range> specified minimum is greater than maxmimum");
276 key_state_check_range (state, error);
280 key_state_start_default (KeyState *state,
282 const gchar *context,
287 if (strcmp (l10n, "messages") == 0)
290 else if (strcmp (l10n, "time") == 0)
295 g_set_error (error, G_MARKUP_ERROR,
296 G_MARKUP_ERROR_INVALID_CONTENT,
297 "unsupported l10n category: %s", l10n);
301 if (!state->have_gettext_domain)
303 g_set_error_literal (error, G_MARKUP_ERROR,
304 G_MARKUP_ERROR_INVALID_CONTENT,
305 "l10n requested, but no "
306 "gettext domain given");
310 state->l10n_context = g_strdup (context);
313 else if (context != NULL)
315 g_set_error_literal (error, G_MARKUP_ERROR,
316 G_MARKUP_ERROR_INVALID_CONTENT,
317 "translation context given for "
318 " value without l10n enabled");
322 return g_string_new (NULL);
326 key_state_end_default (KeyState *state,
330 state->unparsed_default_value = *string;
333 state->default_value = g_variant_parse (state->type,
334 state->unparsed_default_value->str,
336 key_state_check_range (state, error);
340 key_state_start_choices (KeyState *state,
343 const GVariantType *type = state->type;
347 g_set_error_literal (error, G_MARKUP_ERROR,
348 G_MARKUP_ERROR_INVALID_CONTENT,
349 "<choices> can not be specified for keys "
350 "tagged as having an enumerated type");
354 if (state->has_choices)
356 g_set_error_literal (error, G_MARKUP_ERROR,
357 G_MARKUP_ERROR_INVALID_CONTENT,
358 "<choices> already specified for this key");
362 while (g_variant_type_is_maybe (type) || g_variant_type_is_array (type))
363 type = g_variant_type_element (type);
365 if (!g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
367 gchar *type_string = g_variant_type_dup_string (state->type);
368 g_set_error (error, G_MARKUP_ERROR,
369 G_MARKUP_ERROR_INVALID_CONTENT,
370 "<choices> not allowed for keys of type '%s'",
372 g_free (type_string);
378 key_state_add_choice (KeyState *state,
382 if (strinfo_builder_contains (state->strinfo, choice))
384 g_set_error (error, G_MARKUP_ERROR,
385 G_MARKUP_ERROR_INVALID_CONTENT,
386 "<choice value='%s'/> already given", choice);
390 strinfo_builder_append_item (state->strinfo, choice, 0);
391 state->has_choices = TRUE;
395 key_state_end_choices (KeyState *state,
398 if (!state->has_choices)
400 g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
401 "<choices> must contain at least one <choice>");
405 key_state_check_range (state, error);
409 key_state_start_aliases (KeyState *state,
412 if (state->has_aliases)
413 g_set_error_literal (error, G_MARKUP_ERROR,
414 G_MARKUP_ERROR_INVALID_CONTENT,
415 "<aliases> already specified for this key");
417 if (!state->is_enum && !state->has_choices)
418 g_set_error_literal (error, G_MARKUP_ERROR,
419 G_MARKUP_ERROR_INVALID_CONTENT,
420 "<aliases> can only be specified for keys with "
421 "enumerated types or after <choices>");
425 key_state_add_alias (KeyState *state,
430 if (strinfo_builder_contains (state->strinfo, alias))
432 if (strinfo_is_string_valid ((guint32 *) state->strinfo->str,
433 state->strinfo->len / 4,
437 g_set_error (error, G_MARKUP_ERROR,
438 G_MARKUP_ERROR_INVALID_CONTENT,
439 "<alias value='%s'/> given when '%s' is already "
440 "a member of the enumerated type", alias, alias);
443 g_set_error (error, G_MARKUP_ERROR,
444 G_MARKUP_ERROR_INVALID_CONTENT,
445 "<alias value='%s'/> given when "
446 "<choice value='%s'/> was already given",
451 g_set_error (error, G_MARKUP_ERROR,
452 G_MARKUP_ERROR_INVALID_CONTENT,
453 "<alias value='%s'/> already specified", alias);
458 if (!strinfo_builder_append_alias (state->strinfo, alias, target))
460 g_set_error (error, G_MARKUP_ERROR,
461 G_MARKUP_ERROR_INVALID_CONTENT,
462 "alias target '%s' is not in %s", target,
463 state->is_enum ? "enumerated type" : "<choices>");
467 state->has_aliases = TRUE;
471 key_state_end_aliases (KeyState *state,
474 if (!state->has_aliases)
476 g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
477 "<aliases> must contain at least one <alias>");
483 key_state_check (KeyState *state,
489 return state->checked = TRUE;
493 key_state_serialise (KeyState *state)
495 if (state->serialised == NULL)
497 if (state->child_schema)
499 state->serialised = g_variant_new_string (state->child_schema);
504 GVariantBuilder builder;
506 g_assert (key_state_check (state, NULL));
508 g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
511 g_variant_builder_add_value (&builder, state->default_value);
516 if (state->l10n_context)
520 /* Contextified messages are supported by prepending
521 * the context, followed by '\004' to the start of the
522 * message string. We do that here to save GSettings
525 len = strlen (state->l10n_context);
526 state->l10n_context[len] = '\004';
527 g_string_prepend_len (state->unparsed_default_value,
528 state->l10n_context, len + 1);
529 g_free (state->l10n_context);
530 state->l10n_context = NULL;
533 g_variant_builder_add (&builder, "(y(y&s))", 'l', state->l10n,
534 state->unparsed_default_value);
535 g_string_free (state->unparsed_default_value, TRUE);
536 state->unparsed_default_value = NULL;
539 /* choice, aliases, enums */
540 if (state->strinfo->len)
546 data = state->strinfo->str;
547 size = state->strinfo->len;
549 array = g_variant_new_from_data (G_VARIANT_TYPE ("au"),
553 g_string_free (state->strinfo, FALSE);
554 state->strinfo = NULL;
556 g_variant_builder_add (&builder, "(y@au)",
557 state->is_enum ? 'e' : 'c',
562 if (state->minimum || state->maximum)
563 g_variant_builder_add (&builder, "(y(**))", 'r',
564 state->minimum, state->maximum);
566 state->serialised = g_variant_builder_end (&builder);
569 g_variant_ref_sink (state->serialised);
572 return g_variant_ref (state->serialised);
576 key_state_free (gpointer data)
578 KeyState *state = data;
581 g_variant_type_free (state->type);
583 g_free (state->l10n_context);
585 if (state->unparsed_default_value)
586 g_string_free (state->unparsed_default_value, TRUE);
588 if (state->default_value)
589 g_variant_unref (state->default_value);
592 g_string_free (state->strinfo, TRUE);
595 g_variant_unref (state->minimum);
598 g_variant_unref (state->maximum);
600 if (state->serialised)
601 g_variant_unref (state->serialised);
603 g_slice_free (KeyState, state);
606 /* Key name validity {{{1 */
607 static gboolean allow_any_name = FALSE;
610 is_valid_keyname (const gchar *key,
617 g_set_error_literal (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
618 "empty names are not permitted");
625 if (!g_ascii_islower (key[0]))
627 g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
628 "invalid name '%s': names must begin "
629 "with a lowercase letter", key);
633 for (i = 1; key[i]; i++)
636 !g_ascii_islower (key[i]) &&
637 !g_ascii_isdigit (key[i]))
639 g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
640 "invalid name '%s': invalid character '%c'; "
641 "only lowercase letters, numbers and dash ('-') "
642 "are permitted.", key, key[i]);
646 if (key[i] == '-' && key[i + 1] == '-')
648 g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
649 "invalid name '%s': two successive dashes ('--') are "
650 "not permitted.", key);
655 if (key[i - 1] == '-')
657 g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
658 "invalid name '%s': the last character may not be a "
665 g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
666 "invalid name '%s': maximum length is 32", key);
673 /* Handling of <schema> {{{1 */
677 gchar *gettext_domain;
683 schema_state_new (const gchar *path,
684 const gchar *gettext_domain)
688 state = g_slice_new (SchemaState);
689 state->path = g_strdup (path);
690 state->gettext_domain = g_strdup (gettext_domain);
691 state->keys = g_hash_table_new_full (g_str_hash, g_str_equal,
692 g_free, key_state_free);
698 schema_state_free (gpointer data)
700 SchemaState *state = data;
702 g_free (state->path);
703 g_free (state->gettext_domain);
704 g_hash_table_unref (state->keys);
708 schema_state_add_child (SchemaState *state,
715 if (!is_valid_keyname (name, error))
718 childname = g_strconcat (name, "/", NULL);
720 if (g_hash_table_lookup (state->keys, childname))
722 g_set_error (error, G_MARKUP_ERROR,
723 G_MARKUP_ERROR_INVALID_CONTENT,
724 "<child name='%s'> already specified", name);
728 g_hash_table_insert (state->keys, childname,
729 key_state_new_child (schema));
733 schema_state_add_key (SchemaState *state,
734 GHashTable *enum_table,
736 const gchar *type_string,
737 const gchar *enum_type,
743 if (!is_valid_keyname (name, error))
746 if (g_hash_table_lookup (state->keys, name))
748 g_set_error (error, G_MARKUP_ERROR,
749 G_MARKUP_ERROR_INVALID_CONTENT,
750 "<key name='%s'> already specified", name);
754 if ((type_string == NULL) == (enum_type == NULL))
756 g_set_error (error, G_MARKUP_ERROR,
757 G_MARKUP_ERROR_MISSING_ATTRIBUTE,
758 "exactly one of 'type' or 'enum' must "
759 "be specified as an attribute to <key>");
763 if (enum_type != NULL)
765 enum_data = g_hash_table_lookup (enum_table, enum_type);
767 if (enum_data == NULL)
769 g_set_error (error, G_MARKUP_ERROR,
770 G_MARKUP_ERROR_INVALID_CONTENT,
771 "<enum id='%s'> not (yet) defined.", enum_type);
775 g_assert (type_string == NULL);
780 if (!g_variant_type_string_is_valid (type_string))
782 g_set_error (error, G_MARKUP_ERROR,
783 G_MARKUP_ERROR_INVALID_CONTENT,
784 "invalid GVariant type string '%s'", type_string);
791 key = key_state_new (type_string, state->gettext_domain, enum_data);
792 g_hash_table_insert (state->keys, g_strdup (name), key);
797 /* Handling of toplevel state {{{1 */
800 GHashTable *schema_table; /* string -> SchemaState */
801 GHashTable *enum_table; /* string -> GString */
803 gchar *schemalist_domain; /* the <schemalist> gettext domain */
805 SchemaState *schema_state; /* non-NULL when inside <schema> */
806 KeyState *key_state; /* non-NULL when inside <key> */
807 GString *enum_state; /* non-NULL when inside <enum> */
809 GString *string; /* non-NULL when accepting text */
813 parse_state_start_schema (ParseState *state,
816 const gchar *gettext_domain,
819 if (g_hash_table_lookup (state->schema_table, id))
821 g_set_error (error, G_MARKUP_ERROR,
822 G_MARKUP_ERROR_INVALID_CONTENT,
823 "<schema id='%s'> already specified", id);
827 if (path && !(g_str_has_prefix (path, "/") && g_str_has_suffix (path, "/")))
829 g_set_error (error, G_MARKUP_ERROR,
830 G_MARKUP_ERROR_INVALID_CONTENT,
831 "a path, if given, must begin and "
836 state->schema_state = schema_state_new (path, gettext_domain);
837 g_hash_table_insert (state->schema_table, g_strdup (id),
838 state->schema_state);
842 parse_state_start_enum (ParseState *state,
846 if (g_hash_table_lookup (state->enum_table, id))
848 g_set_error (error, G_MARKUP_ERROR,
849 G_MARKUP_ERROR_INVALID_CONTENT,
850 "<enum id='%s'> already specified", id);
854 state->enum_state = g_string_new (NULL);
855 g_hash_table_insert (state->enum_table, g_strdup (id), state->enum_state);
858 /* GMarkup Parser Functions {{{1 */
860 /* Start element {{{2 */
862 start_element (GMarkupParseContext *context,
863 const gchar *element_name,
864 const gchar **attribute_names,
865 const gchar **attribute_values,
869 ParseState *state = user_data;
870 const GSList *element_stack;
871 const gchar *container;
873 element_stack = g_markup_parse_context_get_element_stack (context);
874 container = element_stack->next ? element_stack->next->data : NULL;
876 #define COLLECT(first, ...) \
877 g_markup_collect_attributes (element_name, \
878 attribute_names, attribute_values, error, \
879 first, __VA_ARGS__, G_MARKUP_COLLECT_INVALID)
880 #define OPTIONAL G_MARKUP_COLLECT_OPTIONAL
881 #define STRDUP G_MARKUP_COLLECT_STRDUP
882 #define STRING G_MARKUP_COLLECT_STRING
883 #define NO_ATTRS() COLLECT (G_MARKUP_COLLECT_INVALID, NULL)
885 /* Toplevel items {{{3 */
886 if (container == NULL)
888 if (strcmp (element_name, "schemalist") == 0)
890 COLLECT (OPTIONAL | STRDUP,
892 &state->schemalist_domain);
898 /* children of <schemalist> {{{3 */
899 else if (strcmp (container, "schemalist") == 0)
901 if (strcmp (element_name, "schema") == 0)
903 const gchar *id, *path, *gettext_domain;
904 if (COLLECT (STRING, "id", &id,
905 OPTIONAL | STRING, "path", &path,
906 OPTIONAL | STRDUP, "gettext-domain", &gettext_domain))
907 parse_state_start_schema (state, id, path, gettext_domain, error);
911 else if (strcmp (element_name, "enum") == 0)
914 if (COLLECT (STRING, "id", &id))
915 parse_state_start_enum (state, id, error);
921 /* children of <schema> {{{3 */
922 else if (strcmp (container, "schema") == 0)
924 if (strcmp (element_name, "key") == 0)
926 const gchar *name, *type_string, *enum_type;
928 if (COLLECT (STRING, "name", &name,
929 OPTIONAL | STRING, "type", &type_string,
930 OPTIONAL | STRING, "enum", &enum_type))
932 state->key_state = schema_state_add_key (state->schema_state,
938 else if (strcmp (element_name, "child") == 0)
940 const gchar *name, *schema;
942 if (COLLECT (STRING, "name", &name, STRING, "schema", &schema))
943 schema_state_add_child (state->schema_state,
944 name, schema, error);
950 /* children of <key> {{{3 */
951 else if (strcmp (container, "key") == 0)
953 if (strcmp (element_name, "default") == 0)
955 const gchar *l10n, *context;
956 if (COLLECT (STRING | OPTIONAL, "l10n", &l10n,
957 STRING | OPTIONAL, "context", &context))
958 state->string = key_state_start_default (state->key_state,
959 l10n, context, error);
963 else if (strcmp (element_name, "summary") == 0 ||
964 strcmp (element_name, "description") == 0)
967 state->string = g_string_new (NULL);
971 else if (strcmp (element_name, "range") == 0)
973 const gchar *min, *max;
974 if (COLLECT (STRING, "min", &min, STRING, "max", &max))
975 key_state_set_range (state->key_state, min, max, error);
979 else if (strcmp (element_name, "choices") == 0)
982 key_state_start_choices (state->key_state, error);
986 else if (strcmp (element_name, "aliases") == 0)
989 key_state_start_aliases (state->key_state, error);
995 /* children of <choices> {{{3 */
996 else if (strcmp (container, "choices") == 0)
998 if (strcmp (element_name, "choice") == 0)
1001 if (COLLECT (STRING, "value", &value))
1002 key_state_add_choice (state->key_state, value, error);
1008 /* children of <aliases> {{{3 */
1009 else if (strcmp (container, "aliases") == 0)
1011 if (strcmp (element_name, "alias") == 0)
1013 const gchar *value, *target;
1014 if (COLLECT (STRING, "value", &value, STRING, "target", &target))
1015 key_state_add_alias (state->key_state, value, target, error);
1021 /* children of <enum> {{{3 */
1022 else if (strcmp (container, "enum") == 0)
1024 if (strcmp (element_name, "value") == 0)
1026 const gchar *nick, *valuestr;
1027 if (COLLECT (STRING, "nick", &nick,
1028 STRING, "value", &valuestr))
1029 enum_state_add_value (state->enum_state, nick, valuestr, error);
1036 g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
1037 "Element <%s> not allowed inside <%s>",
1038 element_name, container);
1040 g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
1041 "Element <%s> not allowed at toplevel", element_name);
1044 /* End element {{{2 */
1047 key_state_end (KeyState **state_ptr,
1055 if (state->default_value == NULL)
1057 g_set_error_literal (error,
1058 G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
1059 "element <default> is required in <key>");
1065 schema_state_end (SchemaState **state_ptr,
1075 end_element (GMarkupParseContext *context,
1076 const gchar *element_name,
1080 ParseState *state = user_data;
1082 if (strcmp (element_name, "schemalist") == 0)
1084 g_free (state->schemalist_domain);
1085 state->schemalist_domain = NULL;
1088 else if (strcmp (element_name, "enum") == 0)
1089 enum_state_end (&state->enum_state, error);
1091 else if (strcmp (element_name, "schema") == 0)
1092 schema_state_end (&state->schema_state, error);
1094 else if (strcmp (element_name, "key") == 0)
1095 key_state_end (&state->key_state, error);
1097 else if (strcmp (element_name, "default") == 0)
1098 key_state_end_default (state->key_state, &state->string, error);
1100 else if (strcmp (element_name, "choices") == 0)
1101 key_state_end_choices (state->key_state, error);
1103 else if (strcmp (element_name, "aliases") == 0)
1104 key_state_end_aliases (state->key_state, error);
1108 g_string_free (state->string, TRUE);
1109 state->string = NULL;
1114 text (GMarkupParseContext *context,
1120 ParseState *state = user_data;
1123 for (i = 0; i < text_len; i++)
1124 if (!g_ascii_isspace (text[i]))
1127 g_string_append_len (state->string, text, text_len);
1130 g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
1131 "text may not appear inside <%s>",
1132 g_markup_parse_context_get_element (context));
1138 /* Write to GVDB {{{1 */
1146 gvdb_pair_init (GvdbPair *pair)
1148 pair->table = gvdb_hash_table_new (NULL, NULL);
1149 pair->root = gvdb_hash_table_insert (pair->table, "");
1159 output_key (gpointer key,
1163 OutputSchemaData *data;
1172 item = gvdb_hash_table_insert (data->pair.table, name);
1173 gvdb_item_set_parent (item, data->pair.root);
1174 gvdb_item_set_value (item, key_state_serialise (state));
1181 output_schema (gpointer key,
1185 OutputSchemaData data;
1186 GvdbPair *root_pair;
1193 root_pair = user_data;
1195 gvdb_pair_init (&data.pair);
1198 item = gvdb_hash_table_insert (root_pair->table, id);
1199 gvdb_item_set_parent (item, root_pair->root);
1200 gvdb_item_set_hash_table (item, data.pair.table);
1202 g_hash_table_foreach (state->keys, output_key, &data);
1205 gvdb_hash_table_insert_string (data.pair.table, ".path", state->path);
1208 gvdb_hash_table_insert_string (data.pair.table,
1210 state->gettext_domain);
1214 write_to_file (GHashTable *schema_table,
1215 const gchar *filename,
1221 gvdb_pair_init (&pair);
1223 g_hash_table_foreach (schema_table, output_schema, &pair);
1225 success = gvdb_table_write_contents (pair.table, filename,
1226 G_BYTE_ORDER != G_LITTLE_ENDIAN,
1228 g_hash_table_unref (pair.table);
1233 /* Parser driver {{{1 */
1235 parse_gschema_files (gchar **files,
1238 GMarkupParser parser = { start_element, end_element, text };
1239 GMarkupParseContext *context;
1240 ParseState state = { 0, };
1241 const gchar *filename;
1243 context = g_markup_parse_context_new (&parser,
1244 G_MARKUP_PREFIX_ERROR_POSITION,
1247 state.enum_table = g_hash_table_new_full (g_str_hash, g_str_equal,
1248 g_free, enum_state_free);
1250 state.schema_table = g_hash_table_new_full (g_str_hash, g_str_equal,
1251 g_free, schema_state_free);
1253 while ((filename = *files++) != NULL)
1258 if (!g_file_get_contents (filename, &contents, &size, error))
1261 if (!g_markup_parse_context_parse (context, contents, size, error))
1263 g_prefix_error (error, "%s: ", filename);
1267 if (!g_markup_parse_context_end_parse (context, error))
1269 g_prefix_error (error, "%s: ", filename);
1274 g_hash_table_unref (state.enum_table);
1276 return state.schema_table;
1280 compare_strings (gconstpointer a,
1283 gchar *one = *(gchar **) a;
1284 gchar *two = *(gchar **) b;
1286 return strcmp (one, two);
1290 main (int argc, char **argv)
1297 gchar *targetdir = NULL;
1299 gboolean uninstall = FALSE;
1300 gboolean dry_run = FALSE;
1301 gchar **schema_files = NULL;
1302 GOptionContext *context;
1303 GOptionEntry entries[] = {
1304 { "targetdir", 0, 0, G_OPTION_ARG_FILENAME, &targetdir, N_("where to store the gschemas.compiled file"), N_("DIRECTORY") },
1305 { "dry-run", 0, 0, G_OPTION_ARG_NONE, &dry_run, N_("Do not write the gschema.compiled file"), NULL },
1306 { "uninstall", 0, 0, G_OPTION_ARG_NONE, &uninstall, N_("Do not give error for empty directory"), NULL },
1307 { "allow-any-name", 0, 0, G_OPTION_ARG_NONE, &allow_any_name, N_("Do not enforce key name restrictions") },
1309 /* These options are only for use in the gschema-compile tests */
1310 { "schema-file", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_FILENAME_ARRAY, &schema_files, NULL, NULL },
1314 setlocale (LC_ALL, "");
1316 context = g_option_context_new (N_("DIRECTORY"));
1317 g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
1318 g_option_context_set_summary (context,
1319 N_("Compile all GSettings schema files into a schema cache.\n"
1320 "Schema files are required to have the extension .gschema.xml,\n"
1321 "and the cache file is called gschemas.compiled."));
1322 g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
1325 if (!g_option_context_parse (context, &argc, &argv, &error))
1327 fprintf (stderr, "%s", error->message);
1331 g_option_context_free (context);
1333 if (!schema_files && argc != 2)
1335 fprintf (stderr, _("You should give exactly one directory name\n"));
1341 if (targetdir == NULL)
1344 target = g_build_filename (targetdir, "gschemas.compiled", NULL);
1350 files = g_ptr_array_new ();
1352 dir = g_dir_open (srcdir, 0, &error);
1355 fprintf (stderr, "%s\n", error->message);
1359 while ((file = g_dir_read_name (dir)) != NULL)
1361 if (g_str_has_suffix (file, ".gschema.xml") ||
1362 g_str_has_suffix (file, ".enums.xml"))
1363 g_ptr_array_add (files, g_build_filename (srcdir, file, NULL));
1366 if (files->len == 0)
1375 fprintf (stderr, _("No schema files found\n"));
1379 g_ptr_array_sort (files, compare_strings);
1380 g_ptr_array_add (files, NULL);
1382 schema_files = (char **) g_ptr_array_free (files, FALSE);
1386 if (!(table = parse_gschema_files (schema_files, &error)) ||
1387 (!dry_run && !write_to_file (table, target, &error)))
1389 fprintf (stderr, "%s\n", error->message);
1400 /* vim:set foldmethod=marker: */