Example #1
0
static void
start_element (GMarkupParseContext  *context,
	       const gchar          *element_name,
	       const gchar         **attribute_names,
	       const gchar         **attribute_values,
	       gpointer              user_data,
	       GError              **error)
{
  ParseState *state = user_data;
  const GSList *element_stack;
  const gchar *container;

  element_stack = g_markup_parse_context_get_element_stack (context);
  container = element_stack->next ? element_stack->next->data : NULL;

#define COLLECT(first, ...) \
  g_markup_collect_attributes (element_name,                                 \
			       attribute_names, attribute_values, error,     \
			       first, __VA_ARGS__, G_MARKUP_COLLECT_INVALID)
#define OPTIONAL   G_MARKUP_COLLECT_OPTIONAL
#define STRDUP     G_MARKUP_COLLECT_STRDUP
#define STRING     G_MARKUP_COLLECT_STRING
#define BOOL       G_MARKUP_COLLECT_BOOLEAN
#define NO_ATTRS()  COLLECT (G_MARKUP_COLLECT_INVALID, NULL)

  if (container == NULL)
    {
      if (strcmp (element_name, "gresources") == 0)
	return;
    }
  else if (strcmp (container, "gresources") == 0)
    {
      if (strcmp (element_name, "gresource") == 0)
	{
	  COLLECT (OPTIONAL | STRDUP,
		   "prefix", &state->prefix);
	  return;
	}
    }
  else if (strcmp (container, "gresource") == 0)
    {
      if (strcmp (element_name, "file") == 0)
	{
	  COLLECT (OPTIONAL | STRDUP, "alias", &state->alias,
		   OPTIONAL | BOOL, "compressed", &state->compressed,
                   OPTIONAL | STRDUP, "preprocess", &state->preproc_options);
	  state->string = g_string_new ("");
	  return;
	}
    }

  if (container)
    g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
		 _("Element <%s> not allowed inside <%s>"),
		 element_name, container);
  else
    g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
		 _("Element <%s> not allowed at toplevel"), element_name);

}
Example #2
0
TOK822 *tok822_scan_limit(const char *str, TOK822 **tailp, int tok_count_limit)
{
	TOK822 *head = 0;
	TOK822 *tail = 0;
	TOK822 *tp;
	int     ch;
	int     tok_count = 0;

	/*
	 * XXX 2822 new feature: Section 4.1 allows "." to appear in a phrase (to
	 * allow for forms such as: Johnny B. Goode <*****@*****.**>. I cannot
	 * handle that at the tokenizer level - it is not context sensitive. And
	 * to fix this at the parser level requires radical changes to preserve
	 * white space as part of the token stream. Thanks a lot, people.
	 */
	while ((ch = *(const unsigned char *) str++) != 0) {
		if (IS_SPACE_TAB_CR_LF(ch))
			continue;
		if (ch == '(') {
			tp = tok822_alloc(TOK822_COMMENT, (char *) 0);
			str = tok822_comment(tp, str);
		} else if (ch == '[') {
			tp = tok822_alloc(TOK822_DOMLIT, (char *) 0);
			COLLECT_SKIP_LAST(tp, str, ch, ch != ']');
		} else if (ch == '"') {
			tp = tok822_alloc(TOK822_QSTRING, (char *) 0);
			COLLECT_SKIP_LAST(tp, str, ch, ch != '"');
		} else if (ch != '\\' && strchr(tok822_opchar, ch)) {
			tp = tok822_alloc(ch, (char *) 0);
		} else {
			tp = tok822_alloc(TOK822_ATOM, (char *) 0);
			str -= 1;				/* \ may be first */
			COLLECT(tp, str, ch, !IS_SPACE_TAB_CR_LF(ch) && !strchr(tok822_opchar, ch));
			tok822_quote_atom(tp);
		}
		if (head == 0) {
			head = tail = tp;
			while (tail->next)
				tail = tail->next;
		} else {
			tail = tok822_append(tail, tp);
		}
		if (tok_count_limit > 0 && ++tok_count >= tok_count_limit)
			break;
	}
	if (tailp)
		*tailp = tail;
	return (head);
}
Example #3
0
static void
start_element (GMarkupParseContext  *context,
               const gchar          *element_name,
               const gchar         **attribute_names,
               const gchar         **attribute_values,
               gpointer              user_data,
               GError              **error)
{
  ParseState *state = user_data;
  const GSList *element_stack;
  const gchar *container;

  element_stack = g_markup_parse_context_get_element_stack (context);
  container = element_stack->next ? element_stack->next->data : NULL;

#define COLLECT(first, ...) \
  g_markup_collect_attributes (element_name,                                 \
                               attribute_names, attribute_values, error,     \
                               first, __VA_ARGS__, G_MARKUP_COLLECT_INVALID)
#define OPTIONAL   G_MARKUP_COLLECT_OPTIONAL
#define STRDUP     G_MARKUP_COLLECT_STRDUP
#define STRING     G_MARKUP_COLLECT_STRING
#define NO_ATTRS()  COLLECT (G_MARKUP_COLLECT_INVALID, NULL)

  if (container == NULL)
    {
      if (strcmp (element_name, "schemalist") == 0)
        {
          COLLECT (OPTIONAL | STRDUP,
                   "gettext-domain",
                   &state->schemalist_domain);
          return;
        }
    }
  else if (strcmp (container, "schemalist") == 0)
    {
      if (strcmp (element_name, "schema") == 0)
        {
          const gchar *id, *path;

          if (COLLECT (STRING, "id", &id,
                       OPTIONAL | STRING, "path", &path,
                       OPTIONAL | STRDUP, "gettext-domain",
                                          &state->schema_domain))
            {
              if (!g_hash_table_lookup (state->schemas, id))
                {
                  state->schema = gvdb_hash_table_new (state->schemas, id);
                  state->schema_root = gvdb_hash_table_insert (state->schema, "");

                  if (path != NULL)
                    gvdb_hash_table_insert_string (state->schema,
                                                   ".path", path);
                }
              else
                g_set_error (error, G_MARKUP_ERROR,
                             G_MARKUP_ERROR_INVALID_CONTENT,
                             "<schema id='%s'> already specified", id);
            }
          return;
        }
    }
  else if (strcmp (container, "schema") == 0)
    {
      if (strcmp (element_name, "key") == 0)
        {
          const gchar *name, *type;

          if (COLLECT (STRING, "name", &name, STRING, "type", &type))
            {
              if (!is_valid_keyname (name, error))
                return;

              if (!g_hash_table_lookup (state->schema, name))
                {
                  state->key = gvdb_hash_table_insert (state->schema, name);
                  gvdb_item_set_parent (state->key, state->schema_root);
                }
              else
                {
                  g_set_error (error, G_MARKUP_ERROR,
                               G_MARKUP_ERROR_INVALID_CONTENT,
                               "<key name='%s'> already specified", name);
                  return;
                }

              if (g_variant_type_string_is_valid (type))
                state->type = g_variant_type_new (type);
              else
                {
                  g_set_error (error, G_MARKUP_ERROR,
                               G_MARKUP_ERROR_INVALID_CONTENT,
                               "invalid GVariant type string '%s'", type);
                  return;
                }

              g_variant_builder_init (&state->key_options,
                                      G_VARIANT_TYPE ("a{sv}"));
            }

          return;
        }
      else if (strcmp (element_name, "child") == 0)
        {
          const gchar *name, *schema;

          if (COLLECT (STRING, "name", &name, STRING, "schema", &schema))
            {
              gchar *childname;

              if (!is_valid_keyname (name, error))
                return;

              childname = g_strconcat (name, "/", NULL);

              if (!g_hash_table_lookup (state->schema, childname))
                gvdb_hash_table_insert_string (state->schema, childname, schema);
              else
                g_set_error (error, G_MARKUP_ERROR,
                             G_MARKUP_ERROR_INVALID_CONTENT,
                             "<child name='%s'> already specified", name);

              g_free (childname);
              return;
            }
        }
    }
  else if (strcmp (container, "key") == 0)
    {
      if (strcmp (element_name, "default") == 0)
        {
          const gchar *l10n;

          if (COLLECT (STRING | OPTIONAL, "l10n", &l10n,
                       STRDUP | OPTIONAL, "context", &state->context))
            {
              if (l10n != NULL)
                {
                  if (!g_hash_table_lookup (state->schema, ".gettext-domain"))
                    {
                      const gchar *domain = state->schema_domain ?
                                            state->schema_domain :
                                            state->schemalist_domain;

                      if (domain == NULL)
                        {
                          g_set_error_literal (error, G_MARKUP_ERROR,
                                               G_MARKUP_ERROR_INVALID_CONTENT,
                                               "l10n requested, but no "
                                               "gettext domain given");
                          return;
                        }

                      gvdb_hash_table_insert_string (state->schema,
                                                     ".gettext-domain",
                                                     domain);

                      if (strcmp (l10n, "messages") == 0)
                        state->l10n = 'm';
                      else if (strcmp (l10n, "time") == 0)
                        state->l10n = 't';
                      else
                        {
                          g_set_error (error, G_MARKUP_ERROR,
                                       G_MARKUP_ERROR_INVALID_CONTENT,
                                       "unsupported l10n category: %s", l10n);
                          return;
                        }
                    }
                }
              else
                {
                  state->l10n = '\0';

                  if (state->context != NULL)
                    {
                      g_set_error_literal (error, G_MARKUP_ERROR,
                                           G_MARKUP_ERROR_INVALID_CONTENT,
                                           "translation context given for "
                                           " value without l10n enabled");
                      return;
                    }
                }

              state->string = g_string_new (NULL);
            }

          return;
        }
      else if (strcmp (element_name, "summary") == 0 ||
               strcmp (element_name, "description") == 0)
        {
          state->string = g_string_new (NULL);
          NO_ATTRS ();
          return;
        }
      else if (strcmp (element_name, "range") == 0)
        {
          const gchar *min_str, *max_str;

          if (!type_allows_range (state->type))
            {
              gchar *type = g_variant_type_dup_string (state->type);
              g_set_error (error, G_MARKUP_ERROR,
                          G_MARKUP_ERROR_INVALID_CONTENT,
                          "Element <%s> not allowed for keys of type \"%s\"\n",
                          element_name, type);
              g_free (type);
              return;
            }

          if (!COLLECT (STRING, "min", &min_str,
                        STRING, "max", &max_str))
            return;

          state->min = g_variant_parse (state->type, min_str, NULL, NULL, error);
          if (state->min == NULL)
            return;

          state->max = g_variant_parse (state->type, max_str, NULL, NULL, error);
          if (state->max == NULL)
            return;

          if (g_variant_compare (state->min, state->max) > 0)
            {
              g_set_error (error, G_MARKUP_ERROR,
                           G_MARKUP_ERROR_INVALID_CONTENT,
                           "Element <%s> specified minimum is greater than maxmimum",
                           element_name);
              return;
            }

          g_variant_builder_add (&state->key_options, "{sv}", "range",
                                 g_variant_new ("(@?@?)", state->min, state->max));
          return;
        }
      else if (strcmp (element_name, "choices") == 0)
        {
          if (!type_allows_choices (state->type))
            {
              gchar *type = g_variant_type_dup_string (state->type);
              g_set_error (error, G_MARKUP_ERROR,
                           G_MARKUP_ERROR_INVALID_CONTENT,
                           "Element <%s> not allowed for keys of type \"%s\"\n",
                           element_name, type);
              g_free (type);
              return;
            }

          state->choices = g_string_new ("\xff");

          NO_ATTRS ();
          return;
        }
    }
  else if (strcmp (container, "choices") == 0)
    {
      if (strcmp (element_name, "choice") == 0)
        {
          const gchar *value;

          if (COLLECT (STRING, "value", &value))
            g_string_append_printf (state->choices, "%s\xff", value);

          return;
        }
    }

  if (container)
    g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
                 "Element <%s> not allowed inside <%s>\n",
                 element_name, container);
  else
    g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
                 "Element <%s> not allowed at toplevel\n", element_name);
}