233a19f7ca36b55414faffaa9bf14251ce418866
[platform/upstream/glib.git] / glib / gvariant-parser.c
1 /*
2  * Copyright © 2009, 2010 Codethink Limited
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.1 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  * Author: Ryan Lortie <desrt@desrt.ca>
18  */
19
20 #include "config.h"
21
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25
26 #include "gerror.h"
27 #include "gquark.h"
28 #include "gstring.h"
29 #include "gstrfuncs.h"
30 #include "gtestutils.h"
31 #include "gvariant.h"
32 #include "gvarianttype.h"
33 #include "gslice.h"
34 #include "gthread.h"
35
36 /*
37  * two-pass algorithm
38  * designed by ryan lortie and william hua
39  * designed in itb-229 and at ghazi's, 2009.
40  */
41
42 /**
43  * G_VARIANT_PARSE_ERROR:
44  *
45  * Error domain for GVariant text format parsing.  Specific error codes
46  * are not currently defined for this domain.  See #GError for
47  * information on error domains.
48  **/
49 /**
50  * GVariantParseError:
51  * @G_VARIANT_PARSE_ERROR_FAILED: generic error (unused)
52  * @G_VARIANT_PARSE_ERROR_BASIC_TYPE_EXPECTED: a non-basic #GVariantType was given where a basic type was expected
53  * @G_VARIANT_PARSE_ERROR_CANNOT_INFER_TYPE: cannot infer the #GVariantType
54  * @G_VARIANT_PARSE_ERROR_DEFINITE_TYPE_EXPECTED: an indefinite #GVariantType was given where a definite type was expected
55  * @G_VARIANT_PARSE_ERROR_INPUT_NOT_AT_END: extra data after parsing finished
56  * @G_VARIANT_PARSE_ERROR_INVALID_CHARACTER: invalid character in number or unicode escape
57  * @G_VARIANT_PARSE_ERROR_INVALID_FORMAT_STRING: not a valid #GVariant format string
58  * @G_VARIANT_PARSE_ERROR_INVALID_OBJECT_PATH: not a valid object path
59  * @G_VARIANT_PARSE_ERROR_INVALID_SIGNATURE: not a valid type signature
60  * @G_VARIANT_PARSE_ERROR_INVALID_TYPE_STRING: not a valid #GVariant type string
61  * @G_VARIANT_PARSE_ERROR_NO_COMMON_TYPE: could not find a common type for array entries
62  * @G_VARIANT_PARSE_ERROR_NUMBER_OUT_OF_RANGE: the numerical value is out of range of the given type
63  * @G_VARIANT_PARSE_ERROR_NUMBER_TOO_BIG: the numerical value is out of range for any type
64  * @G_VARIANT_PARSE_ERROR_TYPE_ERROR: cannot parse as variant of the specified type
65  * @G_VARIANT_PARSE_ERROR_UNEXPECTED_TOKEN: an unexpected token was encountered
66  * @G_VARIANT_PARSE_ERROR_UNKNOWN_KEYWORD: an unknown keyword was encountered
67  * @G_VARIANT_PARSE_ERROR_UNTERMINATED_STRING_CONSTANT: unterminated string constant
68  * @G_VARIANT_PARSE_ERROR_VALUE_EXPECTED: no value given
69  *
70  * Error codes returned by parsing text-format GVariants.
71  **/
72 G_DEFINE_QUARK (g-variant-parse-error-quark, g_variant_parse_error)
73
74 /**
75  * g_variant_parser_get_error_quark:
76  *
77  * Same as g_variant_error_quark().
78  *
79  * Deprecated: Use g_variant_parse_error_quark() instead.
80  */
81 GQuark
82 g_variant_parser_get_error_quark (void)
83 {
84   return g_variant_parse_error_quark ();
85 }
86
87 typedef struct
88 {
89   gint start, end;
90 } SourceRef;
91
92 G_GNUC_PRINTF(5, 0)
93 static void
94 parser_set_error_va (GError      **error,
95                      SourceRef    *location,
96                      SourceRef    *other,
97                      gint          code,
98                      const gchar  *format,
99                      va_list       ap)
100 {
101   GString *msg = g_string_new (NULL);
102
103   if (location->start == location->end)
104     g_string_append_printf (msg, "%d", location->start);
105   else
106     g_string_append_printf (msg, "%d-%d", location->start, location->end);
107
108   if (other != NULL)
109     {
110       g_assert (other->start != other->end);
111       g_string_append_printf (msg, ",%d-%d", other->start, other->end);
112     }
113   g_string_append_c (msg, ':');
114
115   g_string_append_vprintf (msg, format, ap);
116   g_set_error_literal (error, G_VARIANT_PARSE_ERROR, code, msg->str);
117   g_string_free (msg, TRUE);
118 }
119
120 G_GNUC_PRINTF(5, 6)
121 static void
122 parser_set_error (GError      **error,
123                   SourceRef    *location,
124                   SourceRef    *other,
125                   gint          code,
126                   const gchar  *format,
127                   ...)
128 {
129   va_list ap;
130
131   va_start (ap, format);
132   parser_set_error_va (error, location, other, code, format, ap);
133   va_end (ap);
134 }
135
136 typedef struct
137 {
138   const gchar *start;
139   const gchar *stream;
140   const gchar *end;
141
142   const gchar *this;
143 } TokenStream;
144
145
146 G_GNUC_PRINTF(5, 6)
147 static void
148 token_stream_set_error (TokenStream  *stream,
149                         GError      **error,
150                         gboolean      this_token,
151                         gint          code,
152                         const gchar  *format,
153                         ...)
154 {
155   SourceRef ref;
156   va_list ap;
157
158   ref.start = stream->this - stream->start;
159
160   if (this_token)
161     ref.end = stream->stream - stream->start;
162   else
163     ref.end = ref.start;
164
165   va_start (ap, format);
166   parser_set_error_va (error, &ref, NULL, code, format, ap);
167   va_end (ap);
168 }
169
170 static gboolean
171 token_stream_prepare (TokenStream *stream)
172 {
173   gint brackets = 0;
174   const gchar *end;
175
176   if (stream->this != NULL)
177     return TRUE;
178
179   while (stream->stream != stream->end && g_ascii_isspace (*stream->stream))
180     stream->stream++;
181
182   if (stream->stream == stream->end || *stream->stream == '\0')
183     {
184       stream->this = stream->stream;
185       return FALSE;
186     }
187
188   switch (stream->stream[0])
189     {
190     case '-': case '+': case '.': case '0': case '1': case '2':
191     case '3': case '4': case '5': case '6': case '7': case '8':
192     case '9':
193       for (end = stream->stream; end != stream->end; end++)
194         if (!g_ascii_isalnum (*end) &&
195             *end != '-' && *end != '+' && *end != '.')
196           break;
197       break;
198
199     case 'b':
200       if (stream->stream[1] == '\'' || stream->stream[1] == '"')
201         {
202           for (end = stream->stream + 2; end != stream->end; end++)
203             if (*end == stream->stream[1] || *end == '\0' ||
204                 (*end == '\\' && (++end == stream->end || *end == '\0')))
205               break;
206
207           if (end != stream->end && *end)
208             end++;
209           break;
210         }
211
212       else
213         {
214           /* ↓↓↓ */
215         }
216
217     case 'a': /* 'b' */ case 'c': case 'd': case 'e': case 'f':
218     case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
219     case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
220     case 's': case 't': case 'u': case 'v': case 'w': case 'x':
221     case 'y': case 'z':
222       for (end = stream->stream; end != stream->end; end++)
223         if (!g_ascii_isalnum (*end))
224           break;
225       break;
226
227     case '\'': case '"':
228       for (end = stream->stream + 1; end != stream->end; end++)
229         if (*end == stream->stream[0] || *end == '\0' ||
230             (*end == '\\' && (++end == stream->end || *end == '\0')))
231           break;
232
233       if (end != stream->end && *end)
234         end++;
235       break;
236
237     case '@': case '%':
238       /* stop at the first space, comma, colon or unmatched bracket.
239        * deals nicely with cases like (%i, %i) or {%i: %i}.
240        * Also: ] and > are never in format strings.
241        */
242       for (end = stream->stream + 1;
243            end != stream->end && *end != '\0' && *end != ',' &&
244            *end != ':' && *end != '>' && *end != ']' && !g_ascii_isspace (*end);
245            end++)
246
247         if (*end == '(' || *end == '{')
248           brackets++;
249
250         else if ((*end == ')' || *end == '}') && !brackets--)
251           break;
252
253       break;
254
255     default:
256       end = stream->stream + 1;
257       break;
258     }
259
260   stream->this = stream->stream;
261   stream->stream = end;
262
263   /* We must have at least one byte in a token. */
264   g_assert (stream->stream - stream->this >= 1);
265
266   return TRUE;
267 }
268
269 static void
270 token_stream_next (TokenStream *stream)
271 {
272   stream->this = NULL;
273 }
274
275 static gboolean
276 token_stream_peek (TokenStream *stream,
277                    gchar        first_char)
278 {
279   if (!token_stream_prepare (stream))
280     return FALSE;
281
282   return stream->stream - stream->this >= 1 &&
283          stream->this[0] == first_char;
284 }
285
286 static gboolean
287 token_stream_peek2 (TokenStream *stream,
288                     gchar        first_char,
289                     gchar        second_char)
290 {
291   if (!token_stream_prepare (stream))
292     return FALSE;
293
294   return stream->stream - stream->this >= 2 &&
295          stream->this[0] == first_char &&
296          stream->this[1] == second_char;
297 }
298
299 static gboolean
300 token_stream_is_keyword (TokenStream *stream)
301 {
302   if (!token_stream_prepare (stream))
303     return FALSE;
304
305   return stream->stream - stream->this >= 2 &&
306          g_ascii_isalpha (stream->this[0]) &&
307          g_ascii_isalpha (stream->this[1]);
308 }
309
310 static gboolean
311 token_stream_is_numeric (TokenStream *stream)
312 {
313   if (!token_stream_prepare (stream))
314     return FALSE;
315
316   return (stream->stream - stream->this >= 1 &&
317           (g_ascii_isdigit (stream->this[0]) ||
318            stream->this[0] == '-' ||
319            stream->this[0] == '+' ||
320            stream->this[0] == '.'));
321 }
322
323 static gboolean
324 token_stream_peek_string (TokenStream *stream,
325                           const gchar *token)
326 {
327   gint length = strlen (token);
328
329   return token_stream_prepare (stream) &&
330          stream->stream - stream->this == length &&
331          memcmp (stream->this, token, length) == 0;
332 }
333
334 static gboolean
335 token_stream_consume (TokenStream *stream,
336                       const gchar *token)
337 {
338   if (!token_stream_peek_string (stream, token))
339     return FALSE;
340
341   token_stream_next (stream);
342   return TRUE;
343 }
344
345 static gboolean
346 token_stream_require (TokenStream  *stream,
347                       const gchar  *token,
348                       const gchar  *purpose,
349                       GError      **error)
350 {
351
352   if (!token_stream_consume (stream, token))
353     {
354       token_stream_set_error (stream, error, FALSE,
355                               G_VARIANT_PARSE_ERROR_UNEXPECTED_TOKEN,
356                               "expected '%s'%s", token, purpose);
357       return FALSE;
358     }
359
360   return TRUE;
361 }
362
363 static void
364 token_stream_assert (TokenStream *stream,
365                      const gchar *token)
366 {
367   gboolean correct_token;
368
369   correct_token = token_stream_consume (stream, token);
370   g_assert (correct_token);
371 }
372
373 static gchar *
374 token_stream_get (TokenStream *stream)
375 {
376   gchar *result;
377
378   if (!token_stream_prepare (stream))
379     return NULL;
380
381   result = g_strndup (stream->this, stream->stream - stream->this);
382
383   return result;
384 }
385
386 static void
387 token_stream_start_ref (TokenStream *stream,
388                         SourceRef   *ref)
389 {
390   token_stream_prepare (stream);
391   ref->start = stream->this - stream->start;
392 }
393
394 static void
395 token_stream_end_ref (TokenStream *stream,
396                       SourceRef   *ref)
397 {
398   ref->end = stream->stream - stream->start;
399 }
400
401 static void
402 pattern_copy (gchar       **out,
403               const gchar **in)
404 {
405   gint brackets = 0;
406
407   while (**in == 'a' || **in == 'm' || **in == 'M')
408     *(*out)++ = *(*in)++;
409
410   do
411     {
412       if (**in == '(' || **in == '{')
413         brackets++;
414
415       else if (**in == ')' || **in == '}')
416         brackets--;
417
418       *(*out)++ = *(*in)++;
419     }
420   while (brackets);
421 }
422
423 static gchar *
424 pattern_coalesce (const gchar *left,
425                   const gchar *right)
426 {
427   gchar *result;
428   gchar *out;
429
430   /* the length of the output is loosely bound by the sum of the input
431    * lengths, not simply the greater of the two lengths.
432    *
433    *   (*(iii)) + ((iii)*) ((iii)(iii))
434    *
435    *      8     +    8    =  12
436    */
437   out = result = g_malloc (strlen (left) + strlen (right));
438
439   while (*left && *right)
440     {
441       if (*left == *right)
442         {
443           *out++ = *left++;
444           right++;
445         }
446
447       else
448         {
449           const gchar **one = &left, **the_other = &right;
450
451          again:
452           if (**one == '*' && **the_other != ')')
453             {
454               pattern_copy (&out, the_other);
455               (*one)++;
456             }
457
458           else if (**one == 'M' && **the_other == 'm')
459             {
460               *out++ = *(*the_other)++;
461             }
462
463           else if (**one == 'M' && **the_other != 'm')
464             {
465               (*one)++;
466             }
467
468           else if (**one == 'N' && strchr ("ynqiuxthd", **the_other))
469             {
470               *out++ = *(*the_other)++;
471               (*one)++;
472             }
473
474           else if (**one == 'S' && strchr ("sog", **the_other))
475             {
476               *out++ = *(*the_other)++;
477               (*one)++;
478             }
479
480           else if (one == &left)
481             {
482               one = &right, the_other = &left;
483               goto again;
484             }
485
486           else
487             break;
488         }
489     }
490
491   if (*left || *right)
492     {
493       g_free (result);
494       result = NULL;
495     }
496   else
497     *out++ = '\0';
498
499   return result;
500 }
501
502 typedef struct _AST AST;
503 typedef gchar *    (*get_pattern_func)    (AST                 *ast,
504                                            GError             **error);
505 typedef GVariant * (*get_value_func)      (AST                 *ast,
506                                            const GVariantType  *type,
507                                            GError             **error);
508 typedef GVariant * (*get_base_value_func) (AST                 *ast,
509                                            const GVariantType  *type,
510                                            GError             **error);
511 typedef void       (*free_func)           (AST                 *ast);
512
513 typedef struct
514 {
515   gchar *    (* get_pattern)    (AST                 *ast,
516                                  GError             **error);
517   GVariant * (* get_value)      (AST                 *ast,
518                                  const GVariantType  *type,
519                                  GError             **error);
520   GVariant * (* get_base_value) (AST                 *ast,
521                                  const GVariantType  *type,
522                                  GError             **error);
523   void       (* free)           (AST                 *ast);
524 } ASTClass;
525
526 struct _AST
527 {
528   const ASTClass *class;
529   SourceRef source_ref;
530 };
531
532 static gchar *
533 ast_get_pattern (AST     *ast,
534                  GError **error)
535 {
536   return ast->class->get_pattern (ast, error);
537 }
538
539 static GVariant *
540 ast_get_value (AST                 *ast,
541                const GVariantType  *type,
542                GError             **error)
543 {
544   return ast->class->get_value (ast, type, error);
545 }
546
547 static void
548 ast_free (AST *ast)
549 {
550   ast->class->free (ast);
551 }
552
553 G_GNUC_PRINTF(5, 6)
554 static void
555 ast_set_error (AST          *ast,
556                GError      **error,
557                AST          *other_ast,
558                gint          code,
559                const gchar  *format,
560                ...)
561 {
562   va_list ap;
563
564   va_start (ap, format);
565   parser_set_error_va (error, &ast->source_ref,
566                        other_ast ? & other_ast->source_ref : NULL,
567                        code,
568                        format, ap);
569   va_end (ap);
570 }
571
572 static GVariant *
573 ast_type_error (AST                 *ast,
574                 const GVariantType  *type,
575                 GError             **error)
576 {
577   gchar *typestr;
578
579   typestr = g_variant_type_dup_string (type);
580   ast_set_error (ast, error, NULL,
581                  G_VARIANT_PARSE_ERROR_TYPE_ERROR,
582                  "can not parse as value of type '%s'",
583                  typestr);
584   g_free (typestr);
585
586   return NULL;
587 }
588
589 static GVariant *
590 ast_resolve (AST     *ast,
591              GError **error)
592 {
593   GVariant *value;
594   gchar *pattern;
595   gint i, j = 0;
596
597   pattern = ast_get_pattern (ast, error);
598
599   if (pattern == NULL)
600     return NULL;
601
602   /* choose reasonable defaults
603    *
604    *   1) favour non-maybe values where possible
605    *   2) default type for strings is 's'
606    *   3) default type for integers is 'i'
607    */
608   for (i = 0; pattern[i]; i++)
609     switch (pattern[i])
610       {
611       case '*':
612         ast_set_error (ast, error, NULL,
613                        G_VARIANT_PARSE_ERROR_CANNOT_INFER_TYPE,
614                        "unable to infer type");
615         g_free (pattern);
616         return NULL;
617
618       case 'M':
619         break;
620
621       case 'S':
622         pattern[j++] = 's';
623         break;
624
625       case 'N':
626         pattern[j++] = 'i';
627         break;
628
629       default:
630         pattern[j++] = pattern[i];
631         break;
632       }
633   pattern[j++] = '\0';
634
635   value = ast_get_value (ast, G_VARIANT_TYPE (pattern), error);
636   g_free (pattern);
637
638   return value;
639 }
640
641
642 static AST *parse (TokenStream  *stream,
643                    va_list      *app,
644                    GError      **error);
645
646 static void
647 ast_array_append (AST  ***array,
648                   gint   *n_items,
649                   AST    *ast)
650 {
651   if ((*n_items & (*n_items - 1)) == 0)
652     *array = g_renew (AST *, *array, *n_items ? 2 ** n_items : 1);
653
654   (*array)[(*n_items)++] = ast;
655 }
656
657 static void
658 ast_array_free (AST  **array,
659                 gint   n_items)
660 {
661   gint i;
662
663   for (i = 0; i < n_items; i++)
664     ast_free (array[i]);
665   g_free (array);
666 }
667
668 static gchar *
669 ast_array_get_pattern (AST    **array,
670                        gint     n_items,
671                        GError **error)
672 {
673   gchar *pattern;
674   gint i;
675
676   pattern = ast_get_pattern (array[0], error);
677
678   if (pattern == NULL)
679     return NULL;
680
681   for (i = 1; i < n_items; i++)
682     {
683       gchar *tmp, *merged;
684
685       tmp = ast_get_pattern (array[i], error);
686
687       if (tmp == NULL)
688         {
689           g_free (pattern);
690           return NULL;
691         }
692
693       merged = pattern_coalesce (pattern, tmp);
694       g_free (pattern);
695       pattern = merged;
696
697       if (merged == NULL)
698         /* set coalescence implies pairwise coalescence (i think).
699          * we should therefore be able to trace the failure to a single
700          * pair of values.
701          */
702         {
703           int j = 0;
704
705           while (TRUE)
706             {
707               gchar *tmp2;
708               gchar *m;
709
710               /* if 'j' reaches 'i' then we failed to find the pair */
711               g_assert (j < i);
712
713               tmp2 = ast_get_pattern (array[j], NULL);
714               g_assert (tmp2 != NULL);
715
716               m = pattern_coalesce (tmp, tmp2);
717               g_free (tmp2);
718               g_free (m);
719
720               if (m == NULL)
721                 {
722                   /* we found a conflict between 'i' and 'j'.
723                    *
724                    * report the error.  note: 'j' is first.
725                    */
726                   ast_set_error (array[j], error, array[i],
727                                  G_VARIANT_PARSE_ERROR_NO_COMMON_TYPE,
728                                  "unable to find a common type");
729                   g_free (tmp);
730                   return NULL;
731                 }
732
733               j++;
734             }
735
736         }
737
738       g_free (tmp);
739     }
740
741   return pattern;
742 }
743
744 typedef struct
745 {
746   AST ast;
747
748   AST *child;
749 } Maybe;
750
751 static gchar *
752 maybe_get_pattern (AST     *ast,
753                    GError **error)
754 {
755   Maybe *maybe = (Maybe *) ast;
756
757   if (maybe->child != NULL)
758     {
759       gchar *child_pattern;
760       gchar *pattern;
761
762       child_pattern = ast_get_pattern (maybe->child, error);
763
764       if (child_pattern == NULL)
765         return NULL;
766
767       pattern = g_strdup_printf ("m%s", child_pattern);
768       g_free (child_pattern);
769
770       return pattern;
771     }
772
773   return g_strdup ("m*");
774 }
775
776 static GVariant *
777 maybe_get_value (AST                 *ast,
778                  const GVariantType  *type,
779                  GError             **error)
780 {
781   Maybe *maybe = (Maybe *) ast;
782   GVariant *value;
783
784   if (!g_variant_type_is_maybe (type))
785     return ast_type_error (ast, type, error);
786
787   type = g_variant_type_element (type);
788
789   if (maybe->child)
790     {
791       value = ast_get_value (maybe->child, type, error);
792
793       if (value == NULL)
794         return NULL;
795     }
796   else
797     value = NULL;
798
799   return g_variant_new_maybe (type, value);
800 }
801
802 static void
803 maybe_free (AST *ast)
804 {
805   Maybe *maybe = (Maybe *) ast;
806
807   if (maybe->child != NULL)
808     ast_free (maybe->child);
809
810   g_slice_free (Maybe, maybe);
811 }
812
813 static AST *
814 maybe_parse (TokenStream  *stream,
815              va_list      *app,
816              GError      **error)
817 {
818   static const ASTClass maybe_class = {
819     maybe_get_pattern,
820     maybe_get_value, NULL,
821     maybe_free
822   };
823   AST *child = NULL;
824   Maybe *maybe;
825
826   if (token_stream_consume (stream, "just"))
827     {
828       child = parse (stream, app, error);
829       if (child == NULL)
830         return NULL;
831     }
832
833   else if (!token_stream_consume (stream, "nothing"))
834     {
835       token_stream_set_error (stream, error, TRUE,
836                               G_VARIANT_PARSE_ERROR_UNKNOWN_KEYWORD,
837                               "unknown keyword");
838       return NULL;
839     }
840
841   maybe = g_slice_new (Maybe);
842   maybe->ast.class = &maybe_class;
843   maybe->child = child;
844
845   return (AST *) maybe;
846 }
847
848 static GVariant *
849 maybe_wrapper (AST                 *ast,
850                const GVariantType  *type,
851                GError             **error)
852 {
853   const GVariantType *t;
854   GVariant *value;
855   int depth;
856
857   for (depth = 0, t = type;
858        g_variant_type_is_maybe (t);
859        depth++, t = g_variant_type_element (t));
860
861   value = ast->class->get_base_value (ast, t, error);
862
863   if (value == NULL)
864     return NULL;
865
866   while (depth--)
867     value = g_variant_new_maybe (NULL, value);
868
869   return value;
870 }
871
872 typedef struct
873 {
874   AST ast;
875
876   AST **children;
877   gint n_children;
878 } Array;
879
880 static gchar *
881 array_get_pattern (AST     *ast,
882                    GError **error)
883 {
884   Array *array = (Array *) ast;
885   gchar *pattern;
886   gchar *result;
887
888   if (array->n_children == 0)
889     return g_strdup ("Ma*");
890
891   pattern = ast_array_get_pattern (array->children, array->n_children, error);
892
893   if (pattern == NULL)
894     return NULL;
895
896   result = g_strdup_printf ("Ma%s", pattern);
897   g_free (pattern);
898
899   return result;
900 }
901
902 static GVariant *
903 array_get_value (AST                 *ast,
904                  const GVariantType  *type,
905                  GError             **error)
906 {
907   Array *array = (Array *) ast;
908   const GVariantType *childtype;
909   GVariantBuilder builder;
910   gint i;
911
912   if (!g_variant_type_is_array (type))
913     return ast_type_error (ast, type, error);
914
915   g_variant_builder_init (&builder, type);
916   childtype = g_variant_type_element (type);
917
918   for (i = 0; i < array->n_children; i++)
919     {
920       GVariant *child;
921
922       if (!(child = ast_get_value (array->children[i], childtype, error)))
923         {
924           g_variant_builder_clear (&builder);
925           return NULL;
926         }
927
928       g_variant_builder_add_value (&builder, child);
929     }
930
931   return g_variant_builder_end (&builder);
932 }
933
934 static void
935 array_free (AST *ast)
936 {
937   Array *array = (Array *) ast;
938
939   ast_array_free (array->children, array->n_children);
940   g_slice_free (Array, array);
941 }
942
943 static AST *
944 array_parse (TokenStream  *stream,
945              va_list      *app,
946              GError      **error)
947 {
948   static const ASTClass array_class = {
949     array_get_pattern,
950     maybe_wrapper, array_get_value,
951     array_free
952   };
953   gboolean need_comma = FALSE;
954   Array *array;
955
956   array = g_slice_new (Array);
957   array->ast.class = &array_class;
958   array->children = NULL;
959   array->n_children = 0;
960
961   token_stream_assert (stream, "[");
962   while (!token_stream_consume (stream, "]"))
963     {
964       AST *child;
965
966       if (need_comma &&
967           !token_stream_require (stream, ",",
968                                  " or ']' to follow array element",
969                                  error))
970         goto error;
971
972       child = parse (stream, app, error);
973
974       if (!child)
975         goto error;
976
977       ast_array_append (&array->children, &array->n_children, child);
978       need_comma = TRUE;
979     }
980
981   return (AST *) array;
982
983  error:
984   ast_array_free (array->children, array->n_children);
985   g_slice_free (Array, array);
986
987   return NULL;
988 }
989
990 typedef struct
991 {
992   AST ast;
993
994   AST **children;
995   gint n_children;
996 } Tuple;
997
998 static gchar *
999 tuple_get_pattern (AST     *ast,
1000                    GError **error)
1001 {
1002   Tuple *tuple = (Tuple *) ast;
1003   gchar *result = NULL;
1004   gchar **parts;
1005   gint i;
1006
1007   parts = g_new (gchar *, tuple->n_children + 4);
1008   parts[tuple->n_children + 1] = (gchar *) ")";
1009   parts[tuple->n_children + 2] = NULL;
1010   parts[0] = (gchar *) "M(";
1011
1012   for (i = 0; i < tuple->n_children; i++)
1013     if (!(parts[i + 1] = ast_get_pattern (tuple->children[i], error)))
1014       break;
1015
1016   if (i == tuple->n_children)
1017     result = g_strjoinv ("", parts);
1018
1019   /* parts[0] should not be freed */
1020   while (i)
1021     g_free (parts[i--]);
1022   g_free (parts);
1023
1024   return result;
1025 }
1026
1027 static GVariant *
1028 tuple_get_value (AST                 *ast,
1029                  const GVariantType  *type,
1030                  GError             **error)
1031 {
1032   Tuple *tuple = (Tuple *) ast;
1033   const GVariantType *childtype;
1034   GVariantBuilder builder;
1035   gint i;
1036
1037   if (!g_variant_type_is_tuple (type))
1038     return ast_type_error (ast, type, error);
1039
1040   g_variant_builder_init (&builder, type);
1041   childtype = g_variant_type_first (type);
1042
1043   for (i = 0; i < tuple->n_children; i++)
1044     {
1045       GVariant *child;
1046
1047       if (childtype == NULL)
1048         {
1049           g_variant_builder_clear (&builder);
1050           return ast_type_error (ast, type, error);
1051         }
1052
1053       if (!(child = ast_get_value (tuple->children[i], childtype, error)))
1054         {
1055           g_variant_builder_clear (&builder);
1056           return FALSE;
1057         }
1058
1059       g_variant_builder_add_value (&builder, child);
1060       childtype = g_variant_type_next (childtype);
1061     }
1062
1063   if (childtype != NULL)
1064     {
1065       g_variant_builder_clear (&builder);
1066       return ast_type_error (ast, type, error);
1067     }
1068
1069   return g_variant_builder_end (&builder);
1070 }
1071
1072 static void
1073 tuple_free (AST *ast)
1074 {
1075   Tuple *tuple = (Tuple *) ast;
1076
1077   ast_array_free (tuple->children, tuple->n_children);
1078   g_slice_free (Tuple, tuple);
1079 }
1080
1081 static AST *
1082 tuple_parse (TokenStream  *stream,
1083              va_list      *app,
1084              GError      **error)
1085 {
1086   static const ASTClass tuple_class = {
1087     tuple_get_pattern,
1088     maybe_wrapper, tuple_get_value,
1089     tuple_free
1090   };
1091   gboolean need_comma = FALSE;
1092   gboolean first = TRUE;
1093   Tuple *tuple;
1094
1095   tuple = g_slice_new (Tuple);
1096   tuple->ast.class = &tuple_class;
1097   tuple->children = NULL;
1098   tuple->n_children = 0;
1099
1100   token_stream_assert (stream, "(");
1101   while (!token_stream_consume (stream, ")"))
1102     {
1103       AST *child;
1104
1105       if (need_comma &&
1106           !token_stream_require (stream, ",",
1107                                  " or ')' to follow tuple element",
1108                                  error))
1109         goto error;
1110
1111       child = parse (stream, app, error);
1112
1113       if (!child)
1114         goto error;
1115
1116       ast_array_append (&tuple->children, &tuple->n_children, child);
1117
1118       /* the first time, we absolutely require a comma, so grab it here
1119        * and leave need_comma = FALSE so that the code above doesn't
1120        * require a second comma.
1121        *
1122        * the second and remaining times, we set need_comma = TRUE.
1123        */
1124       if (first)
1125         {
1126           if (!token_stream_require (stream, ",",
1127                                      " after first tuple element", error))
1128             goto error;
1129
1130           first = FALSE;
1131         }
1132       else
1133         need_comma = TRUE;
1134     }
1135
1136   return (AST *) tuple;
1137
1138  error:
1139   ast_array_free (tuple->children, tuple->n_children);
1140   g_slice_free (Tuple, tuple);
1141
1142   return NULL;
1143 }
1144
1145 typedef struct
1146 {
1147   AST ast;
1148
1149   AST *value;
1150 } Variant;
1151
1152 static gchar *
1153 variant_get_pattern (AST     *ast,
1154                      GError **error)
1155 {
1156   return g_strdup ("Mv");
1157 }
1158
1159 static GVariant *
1160 variant_get_value (AST                 *ast,
1161                    const GVariantType  *type,
1162                    GError             **error)
1163 {
1164   Variant *variant = (Variant *) ast;
1165   GVariant *child;
1166
1167   if (!g_variant_type_equal (type, G_VARIANT_TYPE_VARIANT))
1168     return ast_type_error (ast, type, error);
1169
1170   child = ast_resolve (variant->value, error);
1171
1172   if (child == NULL)
1173     return NULL;
1174
1175   return g_variant_new_variant (child);
1176 }
1177
1178 static void
1179 variant_free (AST *ast)
1180 {
1181   Variant *variant = (Variant *) ast;
1182
1183   ast_free (variant->value);
1184   g_slice_free (Variant, variant);
1185 }
1186
1187 static AST *
1188 variant_parse (TokenStream  *stream,
1189                va_list      *app,
1190                GError      **error)
1191 {
1192   static const ASTClass variant_class = {
1193     variant_get_pattern,
1194     maybe_wrapper, variant_get_value,
1195     variant_free
1196   };
1197   Variant *variant;
1198   AST *value;
1199
1200   token_stream_assert (stream, "<");
1201   value = parse (stream, app, error);
1202
1203   if (!value)
1204     return NULL;
1205
1206   if (!token_stream_require (stream, ">", " to follow variant value", error))
1207     {
1208       ast_free (value);
1209       return NULL;
1210     }
1211
1212   variant = g_slice_new (Variant);
1213   variant->ast.class = &variant_class;
1214   variant->value = value;
1215
1216   return (AST *) variant;
1217 }
1218
1219 typedef struct
1220 {
1221   AST ast;
1222
1223   AST **keys;
1224   AST **values;
1225   gint n_children;
1226 } Dictionary;
1227
1228 static gchar *
1229 dictionary_get_pattern (AST     *ast,
1230                         GError **error)
1231 {
1232   Dictionary *dict = (Dictionary *) ast;
1233   gchar *value_pattern;
1234   gchar *key_pattern;
1235   gchar key_char;
1236   gchar *result;
1237
1238   if (dict->n_children == 0)
1239     return g_strdup ("Ma{**}");
1240
1241   key_pattern = ast_array_get_pattern (dict->keys,
1242                                        abs (dict->n_children),
1243                                        error);
1244
1245   if (key_pattern == NULL)
1246     return NULL;
1247
1248   /* we can not have maybe keys */
1249   if (key_pattern[0] == 'M')
1250     key_char = key_pattern[1];
1251   else
1252     key_char = key_pattern[0];
1253
1254   g_free (key_pattern);
1255
1256   /* the basic types,
1257    * plus undetermined number type and undetermined string type.
1258    */
1259   if (!strchr ("bynqiuxthdsogNS", key_char))
1260     {
1261       ast_set_error (ast, error, NULL,
1262                      G_VARIANT_PARSE_ERROR_BASIC_TYPE_EXPECTED,
1263                      "dictionary keys must have basic types");
1264       return NULL;
1265     }
1266
1267   value_pattern = ast_get_pattern (dict->values[0], error);
1268
1269   if (value_pattern == NULL)
1270     return NULL;
1271
1272   result = g_strdup_printf ("M%s{%c%s}",
1273                             dict->n_children > 0 ? "a" : "",
1274                             key_char, value_pattern);
1275   g_free (value_pattern);
1276
1277   return result;
1278 }
1279
1280 static GVariant *
1281 dictionary_get_value (AST                 *ast,
1282                       const GVariantType  *type,
1283                       GError             **error)
1284 {
1285   Dictionary *dict = (Dictionary *) ast;
1286
1287   if (dict->n_children == -1)
1288     {
1289       const GVariantType *subtype;
1290       GVariantBuilder builder;
1291       GVariant *subvalue;
1292
1293       if (!g_variant_type_is_dict_entry (type))
1294         return ast_type_error (ast, type, error);
1295
1296       g_variant_builder_init (&builder, type);
1297
1298       subtype = g_variant_type_key (type);
1299       if (!(subvalue = ast_get_value (dict->keys[0], subtype, error)))
1300         {
1301           g_variant_builder_clear (&builder);
1302           return NULL;
1303         }
1304       g_variant_builder_add_value (&builder, subvalue);
1305
1306       subtype = g_variant_type_value (type);
1307       if (!(subvalue = ast_get_value (dict->values[0], subtype, error)))
1308         {
1309           g_variant_builder_clear (&builder);
1310           return NULL;
1311         }
1312       g_variant_builder_add_value (&builder, subvalue);
1313
1314       return g_variant_builder_end (&builder);
1315     }
1316   else
1317     {
1318       const GVariantType *entry, *key, *val;
1319       GVariantBuilder builder;
1320       gint i;
1321
1322       if (!g_variant_type_is_subtype_of (type, G_VARIANT_TYPE_DICTIONARY))
1323         return ast_type_error (ast, type, error);
1324
1325       entry = g_variant_type_element (type);
1326       key = g_variant_type_key (entry);
1327       val = g_variant_type_value (entry);
1328
1329       g_variant_builder_init (&builder, type);
1330
1331       for (i = 0; i < dict->n_children; i++)
1332         {
1333           GVariant *subvalue;
1334
1335           g_variant_builder_open (&builder, entry);
1336
1337           if (!(subvalue = ast_get_value (dict->keys[i], key, error)))
1338             {
1339               g_variant_builder_clear (&builder);
1340               return NULL;
1341             }
1342           g_variant_builder_add_value (&builder, subvalue);
1343
1344           if (!(subvalue = ast_get_value (dict->values[i], val, error)))
1345             {
1346               g_variant_builder_clear (&builder);
1347               return NULL;
1348             }
1349           g_variant_builder_add_value (&builder, subvalue);
1350           g_variant_builder_close (&builder);
1351         }
1352
1353       return g_variant_builder_end (&builder);
1354     }
1355 }
1356
1357 static void
1358 dictionary_free (AST *ast)
1359 {
1360   Dictionary *dict = (Dictionary *) ast;
1361   gint n_children;
1362
1363   if (dict->n_children > -1)
1364     n_children = dict->n_children;
1365   else
1366     n_children = 1;
1367
1368   ast_array_free (dict->keys, n_children);
1369   ast_array_free (dict->values, n_children);
1370   g_slice_free (Dictionary, dict);
1371 }
1372
1373 static AST *
1374 dictionary_parse (TokenStream  *stream,
1375                   va_list      *app,
1376                   GError      **error)
1377 {
1378   static const ASTClass dictionary_class = {
1379     dictionary_get_pattern,
1380     maybe_wrapper, dictionary_get_value,
1381     dictionary_free
1382   };
1383   gint n_keys, n_values;
1384   gboolean only_one;
1385   Dictionary *dict;
1386   AST *first;
1387
1388   dict = g_slice_new (Dictionary);
1389   dict->ast.class = &dictionary_class;
1390   dict->keys = NULL;
1391   dict->values = NULL;
1392   n_keys = n_values = 0;
1393
1394   token_stream_assert (stream, "{");
1395
1396   if (token_stream_consume (stream, "}"))
1397     {
1398       dict->n_children = 0;
1399       return (AST *) dict;
1400     }
1401
1402   if ((first = parse (stream, app, error)) == NULL)
1403     goto error;
1404
1405   ast_array_append (&dict->keys, &n_keys, first);
1406
1407   only_one = token_stream_consume (stream, ",");
1408   if (!only_one &&
1409       !token_stream_require (stream, ":",
1410                              " or ',' to follow dictionary entry key",
1411                              error))
1412     goto error;
1413
1414   if ((first = parse (stream, app, error)) == NULL)
1415     goto error;
1416
1417   ast_array_append (&dict->values, &n_values, first);
1418
1419   if (only_one)
1420     {
1421       if (!token_stream_require (stream, "}", " at end of dictionary entry",
1422                                  error))
1423         goto error;
1424
1425       g_assert (n_keys == 1 && n_values == 1);
1426       dict->n_children = -1;
1427
1428       return (AST *) dict;
1429     }
1430
1431   while (!token_stream_consume (stream, "}"))
1432     {
1433       AST *child;
1434
1435       if (!token_stream_require (stream, ",",
1436                                  " or '}' to follow dictionary entry", error))
1437         goto error;
1438
1439       child = parse (stream, app, error);
1440
1441       if (!child)
1442         goto error;
1443
1444       ast_array_append (&dict->keys, &n_keys, child);
1445
1446       if (!token_stream_require (stream, ":",
1447                                  " to follow dictionary entry key", error))
1448         goto error;
1449
1450       child = parse (stream, app, error);
1451
1452       if (!child)
1453         goto error;
1454
1455       ast_array_append (&dict->values, &n_values, child);
1456     }
1457
1458   g_assert (n_keys == n_values);
1459   dict->n_children = n_keys;
1460
1461   return (AST *) dict;
1462
1463  error:
1464   ast_array_free (dict->keys, n_keys);
1465   ast_array_free (dict->values, n_values);
1466   g_slice_free (Dictionary, dict);
1467
1468   return NULL;
1469 }
1470
1471 typedef struct
1472 {
1473   AST ast;
1474   gchar *string;
1475 } String;
1476
1477 static gchar *
1478 string_get_pattern (AST     *ast,
1479                     GError **error)
1480 {
1481   return g_strdup ("MS");
1482 }
1483
1484 static GVariant *
1485 string_get_value (AST                 *ast,
1486                   const GVariantType  *type,
1487                   GError             **error)
1488 {
1489   String *string = (String *) ast;
1490
1491   if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
1492     return g_variant_new_string (string->string);
1493
1494   else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
1495     {
1496       if (!g_variant_is_object_path (string->string))
1497         {
1498           ast_set_error (ast, error, NULL,
1499                          G_VARIANT_PARSE_ERROR_INVALID_OBJECT_PATH,
1500                          "not a valid object path");
1501           return NULL;
1502         }
1503
1504       return g_variant_new_object_path (string->string);
1505     }
1506
1507   else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
1508     {
1509       if (!g_variant_is_signature (string->string))
1510         {
1511           ast_set_error (ast, error, NULL,
1512                          G_VARIANT_PARSE_ERROR_INVALID_SIGNATURE,
1513                          "not a valid signature");
1514           return NULL;
1515         }
1516
1517       return g_variant_new_signature (string->string);
1518     }
1519
1520   else
1521     return ast_type_error (ast, type, error);
1522 }
1523
1524 static void
1525 string_free (AST *ast)
1526 {
1527   String *string = (String *) ast;
1528
1529   g_free (string->string);
1530   g_slice_free (String, string);
1531 }
1532
1533 static gboolean
1534 unicode_unescape (const gchar  *src,
1535                   gint         *src_ofs,
1536                   gchar        *dest,
1537                   gint         *dest_ofs,
1538                   gint          length,
1539                   SourceRef    *ref,
1540                   GError      **error)
1541 {
1542   gchar buffer[9];
1543   guint64 value;
1544   gchar *end;
1545
1546   (*src_ofs)++;
1547
1548   g_assert (length < sizeof (buffer));
1549   strncpy (buffer, src + *src_ofs, length);
1550   buffer[length] = '\0';
1551
1552   value = g_ascii_strtoull (buffer, &end, 0x10);
1553
1554   if (value == 0 || end != buffer + length)
1555     {
1556       parser_set_error (error, ref, NULL,
1557                         G_VARIANT_PARSE_ERROR_INVALID_CHARACTER,
1558                         "invalid %d-character unicode escape", length);
1559       return FALSE;
1560     }
1561
1562   g_assert (value <= G_MAXUINT32);
1563
1564   *dest_ofs += g_unichar_to_utf8 (value, dest + *dest_ofs);
1565   *src_ofs += length;
1566
1567   return TRUE;
1568 }
1569
1570 static AST *
1571 string_parse (TokenStream  *stream,
1572               va_list      *app,
1573               GError      **error)
1574 {
1575   static const ASTClass string_class = {
1576     string_get_pattern,
1577     maybe_wrapper, string_get_value,
1578     string_free
1579   };
1580   String *string;
1581   SourceRef ref;
1582   gchar *token;
1583   gsize length;
1584   gchar quote;
1585   gchar *str;
1586   gint i, j;
1587
1588   token_stream_start_ref (stream, &ref);
1589   token = token_stream_get (stream);
1590   token_stream_end_ref (stream, &ref);
1591   length = strlen (token);
1592   quote = token[0];
1593
1594   str = g_malloc (length);
1595   g_assert (quote == '"' || quote == '\'');
1596   j = 0;
1597   i = 1;
1598   while (token[i] != quote)
1599     switch (token[i])
1600       {
1601       case '\0':
1602         parser_set_error (error, &ref, NULL,
1603                           G_VARIANT_PARSE_ERROR_UNTERMINATED_STRING_CONSTANT,
1604                           "unterminated string constant");
1605         g_free (token);
1606         g_free (str);
1607         return NULL;
1608
1609       case '\\':
1610         switch (token[++i])
1611           {
1612           case '\0':
1613             parser_set_error (error, &ref, NULL,
1614                               G_VARIANT_PARSE_ERROR_UNTERMINATED_STRING_CONSTANT,
1615                               "unterminated string constant");
1616             g_free (token);
1617             g_free (str);
1618             return NULL;
1619
1620           case 'u':
1621             if (!unicode_unescape (token, &i, str, &j, 4, &ref, error))
1622               {
1623                 g_free (token);
1624                 g_free (str);
1625                 return NULL;
1626               }
1627             continue;
1628
1629           case 'U':
1630             if (!unicode_unescape (token, &i, str, &j, 8, &ref, error))
1631               {
1632                 g_free (token);
1633                 g_free (str);
1634                 return NULL;
1635               }
1636             continue;
1637
1638           case 'a': str[j++] = '\a'; i++; continue;
1639           case 'b': str[j++] = '\b'; i++; continue;
1640           case 'f': str[j++] = '\f'; i++; continue;
1641           case 'n': str[j++] = '\n'; i++; continue;
1642           case 'r': str[j++] = '\r'; i++; continue;
1643           case 't': str[j++] = '\t'; i++; continue;
1644           case 'v': str[j++] = '\v'; i++; continue;
1645           case '\n': i++; continue;
1646           }
1647
1648       default:
1649         str[j++] = token[i++];
1650       }
1651   str[j++] = '\0';
1652   g_free (token);
1653
1654   string = g_slice_new (String);
1655   string->ast.class = &string_class;
1656   string->string = str;
1657
1658   token_stream_next (stream);
1659
1660   return (AST *) string;
1661 }
1662
1663 typedef struct
1664 {
1665   AST ast;
1666   gchar *string;
1667 } ByteString;
1668
1669 static gchar *
1670 bytestring_get_pattern (AST     *ast,
1671                         GError **error)
1672 {
1673   return g_strdup ("May");
1674 }
1675
1676 static GVariant *
1677 bytestring_get_value (AST                 *ast,
1678                       const GVariantType  *type,
1679                       GError             **error)
1680 {
1681   ByteString *string = (ByteString *) ast;
1682
1683   if (!g_variant_type_equal (type, G_VARIANT_TYPE_BYTESTRING))
1684     return ast_type_error (ast, type, error);
1685
1686   return g_variant_new_bytestring (string->string);
1687 }
1688
1689 static void
1690 bytestring_free (AST *ast)
1691 {
1692   ByteString *string = (ByteString *) ast;
1693
1694   g_free (string->string);
1695   g_slice_free (ByteString, string);
1696 }
1697
1698 static AST *
1699 bytestring_parse (TokenStream  *stream,
1700                   va_list      *app,
1701                   GError      **error)
1702 {
1703   static const ASTClass bytestring_class = {
1704     bytestring_get_pattern,
1705     maybe_wrapper, bytestring_get_value,
1706     bytestring_free
1707   };
1708   ByteString *string;
1709   SourceRef ref;
1710   gchar *token;
1711   gsize length;
1712   gchar quote;
1713   gchar *str;
1714   gint i, j;
1715
1716   token_stream_start_ref (stream, &ref);
1717   token = token_stream_get (stream);
1718   token_stream_end_ref (stream, &ref);
1719   g_assert (token[0] == 'b');
1720   length = strlen (token);
1721   quote = token[1];
1722
1723   str = g_malloc (length);
1724   g_assert (quote == '"' || quote == '\'');
1725   j = 0;
1726   i = 2;
1727   while (token[i] != quote)
1728     switch (token[i])
1729       {
1730       case '\0':
1731         parser_set_error (error, &ref, NULL,
1732                           G_VARIANT_PARSE_ERROR_UNTERMINATED_STRING_CONSTANT,
1733                           "unterminated string constant");
1734         g_free (str);
1735         g_free (token);
1736         return NULL;
1737
1738       case '\\':
1739         switch (token[++i])
1740           {
1741           case '\0':
1742             parser_set_error (error, &ref, NULL,
1743                               G_VARIANT_PARSE_ERROR_UNTERMINATED_STRING_CONSTANT,
1744                               "unterminated string constant");
1745             g_free (str);
1746             g_free (token);
1747             return NULL;
1748
1749           case '0': case '1': case '2': case '3':
1750           case '4': case '5': case '6': case '7':
1751             {
1752               /* up to 3 characters */
1753               guchar val = token[i++] - '0';
1754
1755               if ('0' <= token[i] && token[i] < '8')
1756                 val = (val << 3) | (token[i++] - '0');
1757
1758               if ('0' <= token[i] && token[i] < '8')
1759                 val = (val << 3) | (token[i++] - '0');
1760
1761               str[j++] = val;
1762             }
1763             continue;
1764
1765           case 'a': str[j++] = '\a'; i++; continue;
1766           case 'b': str[j++] = '\b'; i++; continue;
1767           case 'f': str[j++] = '\f'; i++; continue;
1768           case 'n': str[j++] = '\n'; i++; continue;
1769           case 'r': str[j++] = '\r'; i++; continue;
1770           case 't': str[j++] = '\t'; i++; continue;
1771           case 'v': str[j++] = '\v'; i++; continue;
1772           case '\n': i++; continue;
1773           }
1774
1775       default:
1776         str[j++] = token[i++];
1777       }
1778   str[j++] = '\0';
1779   g_free (token);
1780
1781   string = g_slice_new (ByteString);
1782   string->ast.class = &bytestring_class;
1783   string->string = str;
1784
1785   token_stream_next (stream);
1786
1787   return (AST *) string;
1788 }
1789
1790 typedef struct
1791 {
1792   AST ast;
1793
1794   gchar *token;
1795 } Number;
1796
1797 static gchar *
1798 number_get_pattern (AST     *ast,
1799                     GError **error)
1800 {
1801   Number *number = (Number *) ast;
1802
1803   if (strchr (number->token, '.') ||
1804       (!g_str_has_prefix (number->token, "0x") && strchr (number->token, 'e')) ||
1805       strstr (number->token, "inf") ||
1806       strstr (number->token, "nan"))
1807     return g_strdup ("Md");
1808
1809   return g_strdup ("MN");
1810 }
1811
1812 static GVariant *
1813 number_overflow (AST                 *ast,
1814                  const GVariantType  *type,
1815                  GError             **error)
1816 {
1817   ast_set_error (ast, error, NULL,
1818                  G_VARIANT_PARSE_ERROR_NUMBER_OUT_OF_RANGE,
1819                  "number out of range for type '%c'",
1820                  g_variant_type_peek_string (type)[0]);
1821   return NULL;
1822 }
1823
1824 static GVariant *
1825 number_get_value (AST                 *ast,
1826                   const GVariantType  *type,
1827                   GError             **error)
1828 {
1829   Number *number = (Number *) ast;
1830   const gchar *token;
1831   gboolean negative;
1832   gboolean floating;
1833   guint64 abs_val;
1834   gdouble dbl_val;
1835   gchar *end;
1836
1837   token = number->token;
1838
1839   if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
1840     {
1841       floating = TRUE;
1842
1843       errno = 0;
1844       dbl_val = g_ascii_strtod (token, &end);
1845       if (dbl_val != 0.0 && errno == ERANGE)
1846         {
1847           ast_set_error (ast, error, NULL,
1848                          G_VARIANT_PARSE_ERROR_NUMBER_TOO_BIG,
1849                          "number too big for any type");
1850           return NULL;
1851         }
1852
1853       /* silence uninitialised warnings... */
1854       negative = FALSE;
1855       abs_val = 0;
1856     }
1857   else
1858     {
1859       floating = FALSE;
1860       negative = token[0] == '-';
1861       if (token[0] == '-')
1862         token++;
1863
1864       errno = 0;
1865       abs_val = g_ascii_strtoull (token, &end, 0);
1866       if (abs_val == G_MAXUINT64 && errno == ERANGE)
1867         {
1868           ast_set_error (ast, error, NULL,
1869                          G_VARIANT_PARSE_ERROR_NUMBER_TOO_BIG,
1870                          "integer too big for any type");
1871           return NULL;
1872         }
1873
1874       if (abs_val == 0)
1875         negative = FALSE;
1876
1877       /* silence uninitialised warning... */
1878       dbl_val = 0.0;
1879     }
1880
1881   if (*end != '\0')
1882     {
1883       SourceRef ref;
1884
1885       ref = ast->source_ref;
1886       ref.start += end - number->token;
1887       ref.end = ref.start + 1;
1888
1889       parser_set_error (error, &ref, NULL,
1890                         G_VARIANT_PARSE_ERROR_INVALID_CHARACTER,
1891                         "invalid character in number");
1892       return NULL;
1893      }
1894
1895   if (floating)
1896     return g_variant_new_double (dbl_val);
1897
1898   switch (*g_variant_type_peek_string (type))
1899     {
1900     case 'y':
1901       if (negative || abs_val > G_MAXUINT8)
1902         return number_overflow (ast, type, error);
1903       return g_variant_new_byte (abs_val);
1904
1905     case 'n':
1906       if (abs_val - negative > G_MAXINT16)
1907         return number_overflow (ast, type, error);
1908       return g_variant_new_int16 (negative ? -abs_val : abs_val);
1909
1910     case 'q':
1911       if (negative || abs_val > G_MAXUINT16)
1912         return number_overflow (ast, type, error);
1913       return g_variant_new_uint16 (abs_val);
1914
1915     case 'i':
1916       if (abs_val - negative > G_MAXINT32)
1917         return number_overflow (ast, type, error);
1918       return g_variant_new_int32 (negative ? -abs_val : abs_val);
1919
1920     case 'u':
1921       if (negative || abs_val > G_MAXUINT32)
1922         return number_overflow (ast, type, error);
1923       return g_variant_new_uint32 (abs_val);
1924
1925     case 'x':
1926       if (abs_val - negative > G_MAXINT64)
1927         return number_overflow (ast, type, error);
1928       return g_variant_new_int64 (negative ? -abs_val : abs_val);
1929
1930     case 't':
1931       if (negative)
1932         return number_overflow (ast, type, error);
1933       return g_variant_new_uint64 (abs_val);
1934
1935     case 'h':
1936       if (abs_val - negative > G_MAXINT32)
1937         return number_overflow (ast, type, error);
1938       return g_variant_new_handle (negative ? -abs_val : abs_val);
1939
1940     default:
1941       return ast_type_error (ast, type, error);
1942     }
1943 }
1944
1945 static void
1946 number_free (AST *ast)
1947 {
1948   Number *number = (Number *) ast;
1949
1950   g_free (number->token);
1951   g_slice_free (Number, number);
1952 }
1953
1954 static AST *
1955 number_parse (TokenStream  *stream,
1956               va_list      *app,
1957               GError      **error)
1958 {
1959   static const ASTClass number_class = {
1960     number_get_pattern,
1961     maybe_wrapper, number_get_value,
1962     number_free
1963   };
1964   Number *number;
1965
1966   number = g_slice_new (Number);
1967   number->ast.class = &number_class;
1968   number->token = token_stream_get (stream);
1969   token_stream_next (stream);
1970
1971   return (AST *) number;
1972 }
1973
1974 typedef struct
1975 {
1976   AST ast;
1977   gboolean value;
1978 } Boolean;
1979
1980 static gchar *
1981 boolean_get_pattern (AST     *ast,
1982                      GError **error)
1983 {
1984   return g_strdup ("Mb");
1985 }
1986
1987 static GVariant *
1988 boolean_get_value (AST                 *ast,
1989                    const GVariantType  *type,
1990                    GError             **error)
1991 {
1992   Boolean *boolean = (Boolean *) ast;
1993
1994   if (!g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
1995     return ast_type_error (ast, type, error);
1996
1997   return g_variant_new_boolean (boolean->value);
1998 }
1999
2000 static void
2001 boolean_free (AST *ast)
2002 {
2003   Boolean *boolean = (Boolean *) ast;
2004
2005   g_slice_free (Boolean, boolean);
2006 }
2007
2008 static AST *
2009 boolean_new (gboolean value)
2010 {
2011   static const ASTClass boolean_class = {
2012     boolean_get_pattern,
2013     maybe_wrapper, boolean_get_value,
2014     boolean_free
2015   };
2016   Boolean *boolean;
2017
2018   boolean = g_slice_new (Boolean);
2019   boolean->ast.class = &boolean_class;
2020   boolean->value = value;
2021
2022   return (AST *) boolean;
2023 }
2024
2025 typedef struct
2026 {
2027   AST ast;
2028
2029   GVariant *value;
2030 } Positional;
2031
2032 static gchar *
2033 positional_get_pattern (AST     *ast,
2034                         GError **error)
2035 {
2036   Positional *positional = (Positional *) ast;
2037
2038   return g_strdup (g_variant_get_type_string (positional->value));
2039 }
2040
2041 static GVariant *
2042 positional_get_value (AST                 *ast,
2043                       const GVariantType  *type,
2044                       GError             **error)
2045 {
2046   Positional *positional = (Positional *) ast;
2047   GVariant *value;
2048
2049   g_assert (positional->value != NULL);
2050
2051   if G_UNLIKELY (!g_variant_is_of_type (positional->value, type))
2052     return ast_type_error (ast, type, error);
2053
2054   /* NOTE: if _get is called more than once then
2055    * things get messed up with respect to floating refs.
2056    *
2057    * fortunately, this function should only ever get called once.
2058    */
2059   g_assert (positional->value != NULL);
2060   value = positional->value;
2061   positional->value = NULL;
2062
2063   return value;
2064 }
2065
2066 static void
2067 positional_free (AST *ast)
2068 {
2069   Positional *positional = (Positional *) ast;
2070
2071   /* if positional->value is set, just leave it.
2072    * memory management doesn't matter in case of programmer error.
2073    */
2074   g_slice_free (Positional, positional);
2075 }
2076
2077 static AST *
2078 positional_parse (TokenStream  *stream,
2079                   va_list      *app,
2080                   GError      **error)
2081 {
2082   static const ASTClass positional_class = {
2083     positional_get_pattern,
2084     positional_get_value, NULL,
2085     positional_free
2086   };
2087   Positional *positional;
2088   const gchar *endptr;
2089   gchar *token;
2090
2091   token = token_stream_get (stream);
2092   g_assert (token[0] == '%');
2093
2094   positional = g_slice_new (Positional);
2095   positional->ast.class = &positional_class;
2096   positional->value = g_variant_new_va (token + 1, &endptr, app);
2097
2098   if (*endptr || positional->value == NULL)
2099     {
2100       token_stream_set_error (stream, error, TRUE,
2101                               G_VARIANT_PARSE_ERROR_INVALID_FORMAT_STRING,
2102                               "invalid GVariant format string");
2103       /* memory management doesn't matter in case of programmer error. */
2104       return NULL;
2105     }
2106
2107   token_stream_next (stream);
2108   g_free (token);
2109
2110   return (AST *) positional;
2111 }
2112
2113 typedef struct
2114 {
2115   AST ast;
2116
2117   GVariantType *type;
2118   AST *child;
2119 } TypeDecl;
2120
2121 static gchar *
2122 typedecl_get_pattern (AST     *ast,
2123                       GError **error)
2124 {
2125   TypeDecl *decl = (TypeDecl *) ast;
2126
2127   return g_variant_type_dup_string (decl->type);
2128 }
2129
2130 static GVariant *
2131 typedecl_get_value (AST                 *ast,
2132                     const GVariantType  *type,
2133                     GError             **error)
2134 {
2135   TypeDecl *decl = (TypeDecl *) ast;
2136
2137   return ast_get_value (decl->child, type, error);
2138 }
2139
2140 static void
2141 typedecl_free (AST *ast)
2142 {
2143   TypeDecl *decl = (TypeDecl *) ast;
2144
2145   ast_free (decl->child);
2146   g_variant_type_free (decl->type);
2147   g_slice_free (TypeDecl, decl);
2148 }
2149
2150 static AST *
2151 typedecl_parse (TokenStream  *stream,
2152                 va_list      *app,
2153                 GError      **error)
2154 {
2155   static const ASTClass typedecl_class = {
2156     typedecl_get_pattern,
2157     typedecl_get_value, NULL,
2158     typedecl_free
2159   };
2160   GVariantType *type;
2161   TypeDecl *decl;
2162   AST *child;
2163
2164   if (token_stream_peek (stream, '@'))
2165     {
2166       gchar *token;
2167
2168       token = token_stream_get (stream);
2169
2170       if (!g_variant_type_string_is_valid (token + 1))
2171         {
2172           token_stream_set_error (stream, error, TRUE,
2173                                   G_VARIANT_PARSE_ERROR_INVALID_TYPE_STRING,
2174                                   "invalid type declaration");
2175           g_free (token);
2176
2177           return NULL;
2178         }
2179
2180       type = g_variant_type_new (token + 1);
2181
2182       if (!g_variant_type_is_definite (type))
2183         {
2184           token_stream_set_error (stream, error, TRUE,
2185                                   G_VARIANT_PARSE_ERROR_DEFINITE_TYPE_EXPECTED,
2186                                   "type declarations must be definite");
2187           g_variant_type_free (type);
2188           g_free (token);
2189
2190           return NULL;
2191         }
2192
2193       token_stream_next (stream);
2194       g_free (token);
2195     }
2196   else
2197     {
2198       if (token_stream_consume (stream, "boolean"))
2199         type = g_variant_type_copy (G_VARIANT_TYPE_BOOLEAN);
2200
2201       else if (token_stream_consume (stream, "byte"))
2202         type = g_variant_type_copy (G_VARIANT_TYPE_BYTE);
2203
2204       else if (token_stream_consume (stream, "int16"))
2205         type = g_variant_type_copy (G_VARIANT_TYPE_INT16);
2206
2207       else if (token_stream_consume (stream, "uint16"))
2208         type = g_variant_type_copy (G_VARIANT_TYPE_UINT16);
2209
2210       else if (token_stream_consume (stream, "int32"))
2211         type = g_variant_type_copy (G_VARIANT_TYPE_INT32);
2212
2213       else if (token_stream_consume (stream, "handle"))
2214         type = g_variant_type_copy (G_VARIANT_TYPE_HANDLE);
2215
2216       else if (token_stream_consume (stream, "uint32"))
2217         type = g_variant_type_copy (G_VARIANT_TYPE_UINT32);
2218
2219       else if (token_stream_consume (stream, "int64"))
2220         type = g_variant_type_copy (G_VARIANT_TYPE_INT64);
2221
2222       else if (token_stream_consume (stream, "uint64"))
2223         type = g_variant_type_copy (G_VARIANT_TYPE_UINT64);
2224
2225       else if (token_stream_consume (stream, "double"))
2226         type = g_variant_type_copy (G_VARIANT_TYPE_DOUBLE);
2227
2228       else if (token_stream_consume (stream, "string"))
2229         type = g_variant_type_copy (G_VARIANT_TYPE_STRING);
2230
2231       else if (token_stream_consume (stream, "objectpath"))
2232         type = g_variant_type_copy (G_VARIANT_TYPE_OBJECT_PATH);
2233
2234       else if (token_stream_consume (stream, "signature"))
2235         type = g_variant_type_copy (G_VARIANT_TYPE_SIGNATURE);
2236
2237       else
2238         {
2239           token_stream_set_error (stream, error, TRUE,
2240                                   G_VARIANT_PARSE_ERROR_UNKNOWN_KEYWORD,
2241                                   "unknown keyword");
2242           return NULL;
2243         }
2244     }
2245
2246   if ((child = parse (stream, app, error)) == NULL)
2247     {
2248       g_variant_type_free (type);
2249       return NULL;
2250     }
2251
2252   decl = g_slice_new (TypeDecl);
2253   decl->ast.class = &typedecl_class;
2254   decl->type = type;
2255   decl->child = child;
2256
2257   return (AST *) decl;
2258 }
2259
2260 static AST *
2261 parse (TokenStream  *stream,
2262        va_list      *app,
2263        GError      **error)
2264 {
2265   SourceRef source_ref;
2266   AST *result;
2267
2268   token_stream_prepare (stream);
2269   token_stream_start_ref (stream, &source_ref);
2270
2271   if (token_stream_peek (stream, '['))
2272     result = array_parse (stream, app, error);
2273
2274   else if (token_stream_peek (stream, '('))
2275     result = tuple_parse (stream, app, error);
2276
2277   else if (token_stream_peek (stream, '<'))
2278     result = variant_parse (stream, app, error);
2279
2280   else if (token_stream_peek (stream, '{'))
2281     result = dictionary_parse (stream, app, error);
2282
2283   else if (app && token_stream_peek (stream, '%'))
2284     result = positional_parse (stream, app, error);
2285
2286   else if (token_stream_consume (stream, "true"))
2287     result = boolean_new (TRUE);
2288
2289   else if (token_stream_consume (stream, "false"))
2290     result = boolean_new (FALSE);
2291
2292   else if (token_stream_is_numeric (stream) ||
2293            token_stream_peek_string (stream, "inf") ||
2294            token_stream_peek_string (stream, "nan"))
2295     result = number_parse (stream, app, error);
2296
2297   else if (token_stream_peek (stream, 'n') ||
2298            token_stream_peek (stream, 'j'))
2299     result = maybe_parse (stream, app, error);
2300
2301   else if (token_stream_peek (stream, '@') ||
2302            token_stream_is_keyword (stream))
2303     result = typedecl_parse (stream, app, error);
2304
2305   else if (token_stream_peek (stream, '\'') ||
2306            token_stream_peek (stream, '"'))
2307     result = string_parse (stream, app, error);
2308
2309   else if (token_stream_peek2 (stream, 'b', '\'') ||
2310            token_stream_peek2 (stream, 'b', '"'))
2311     result = bytestring_parse (stream, app, error);
2312
2313   else
2314     {
2315       token_stream_set_error (stream, error, FALSE,
2316                               G_VARIANT_PARSE_ERROR_VALUE_EXPECTED,
2317                               "expected value");
2318       return NULL;
2319     }
2320
2321   if (result != NULL)
2322     {
2323       token_stream_end_ref (stream, &source_ref);
2324       result->source_ref = source_ref;
2325     }
2326
2327   return result;
2328 }
2329
2330 /**
2331  * g_variant_parse:
2332  * @type: (nullable): a #GVariantType, or %NULL
2333  * @text: a string containing a GVariant in text form
2334  * @limit: (nullable): a pointer to the end of @text, or %NULL
2335  * @endptr: (nullable): a location to store the end pointer, or %NULL
2336  * @error: (nullable): a pointer to a %NULL #GError pointer, or %NULL
2337  *
2338  * Parses a #GVariant from a text representation.
2339  *
2340  * A single #GVariant is parsed from the content of @text.
2341  *
2342  * The format is described [here][gvariant-text].
2343  *
2344  * The memory at @limit will never be accessed and the parser behaves as
2345  * if the character at @limit is the nul terminator.  This has the
2346  * effect of bounding @text.
2347  *
2348  * If @endptr is non-%NULL then @text is permitted to contain data
2349  * following the value that this function parses and @endptr will be
2350  * updated to point to the first character past the end of the text
2351  * parsed by this function.  If @endptr is %NULL and there is extra data
2352  * then an error is returned.
2353  *
2354  * If @type is non-%NULL then the value will be parsed to have that
2355  * type.  This may result in additional parse errors (in the case that
2356  * the parsed value doesn't fit the type) but may also result in fewer
2357  * errors (in the case that the type would have been ambiguous, such as
2358  * with empty arrays).
2359  *
2360  * In the event that the parsing is successful, the resulting #GVariant
2361  * is returned. It is never floating, and must be freed with
2362  * g_variant_unref().
2363  *
2364  * In case of any error, %NULL will be returned.  If @error is non-%NULL
2365  * then it will be set to reflect the error that occurred.
2366  *
2367  * Officially, the language understood by the parser is "any string
2368  * produced by g_variant_print()".
2369  *
2370  * Returns: a non-floating reference to a #GVariant, or %NULL
2371  **/
2372 GVariant *
2373 g_variant_parse (const GVariantType  *type,
2374                  const gchar         *text,
2375                  const gchar         *limit,
2376                  const gchar        **endptr,
2377                  GError             **error)
2378 {
2379   TokenStream stream = { 0, };
2380   GVariant *result = NULL;
2381   AST *ast;
2382
2383   g_return_val_if_fail (text != NULL, NULL);
2384   g_return_val_if_fail (text == limit || text != NULL, NULL);
2385
2386   stream.start = text;
2387   stream.stream = text;
2388   stream.end = limit;
2389
2390   if ((ast = parse (&stream, NULL, error)))
2391     {
2392       if (type == NULL)
2393         result = ast_resolve (ast, error);
2394       else
2395         result = ast_get_value (ast, type, error);
2396
2397       if (result != NULL)
2398         {
2399           g_variant_ref_sink (result);
2400
2401           if (endptr == NULL)
2402             {
2403               while (stream.stream != limit &&
2404                      g_ascii_isspace (*stream.stream))
2405                 stream.stream++;
2406
2407               if (stream.stream != limit && *stream.stream != '\0')
2408                 {
2409                   SourceRef ref = { stream.stream - text,
2410                                     stream.stream - text };
2411
2412                   parser_set_error (error, &ref, NULL,
2413                                     G_VARIANT_PARSE_ERROR_INPUT_NOT_AT_END,
2414                                     "expected end of input");
2415                   g_variant_unref (result);
2416
2417                   result = NULL;
2418                 }
2419             }
2420           else
2421             *endptr = stream.stream;
2422         }
2423
2424       ast_free (ast);
2425     }
2426
2427   return result;
2428 }
2429
2430 /**
2431  * g_variant_new_parsed_va:
2432  * @format: a text format #GVariant
2433  * @app: a pointer to a #va_list
2434  *
2435  * Parses @format and returns the result.
2436  *
2437  * This is the version of g_variant_new_parsed() intended to be used
2438  * from libraries.
2439  *
2440  * The return value will be floating if it was a newly created GVariant
2441  * instance.  In the case that @format simply specified the collection
2442  * of a #GVariant pointer (eg: @format was "%*") then the collected
2443  * #GVariant pointer will be returned unmodified, without adding any
2444  * additional references.
2445  *
2446  * Note that the arguments in @app must be of the correct width for their types
2447  * specified in @format when collected into the #va_list. See
2448  * the [GVariant varargs documentation][gvariant-varargs].
2449  *
2450  * In order to behave correctly in all cases it is necessary for the
2451  * calling function to g_variant_ref_sink() the return result before
2452  * returning control to the user that originally provided the pointer.
2453  * At this point, the caller will have their own full reference to the
2454  * result.  This can also be done by adding the result to a container,
2455  * or by passing it to another g_variant_new() call.
2456  *
2457  * Returns: a new, usually floating, #GVariant
2458  **/
2459 GVariant *
2460 g_variant_new_parsed_va (const gchar *format,
2461                          va_list     *app)
2462 {
2463   TokenStream stream = { 0, };
2464   GVariant *result = NULL;
2465   GError *error = NULL;
2466   AST *ast;
2467
2468   g_return_val_if_fail (format != NULL, NULL);
2469   g_return_val_if_fail (app != NULL, NULL);
2470
2471   stream.start = format;
2472   stream.stream = format;
2473   stream.end = NULL;
2474
2475   if ((ast = parse (&stream, app, &error)))
2476     {
2477       result = ast_resolve (ast, &error);
2478       ast_free (ast);
2479     }
2480
2481   if (result == NULL)
2482     g_error ("g_variant_new_parsed: %s", error->message);
2483
2484   if (*stream.stream)
2485     g_error ("g_variant_new_parsed: trailing text after value");
2486
2487   return result;
2488 }
2489
2490 /**
2491  * g_variant_new_parsed:
2492  * @format: a text format #GVariant
2493  * @...: arguments as per @format
2494  *
2495  * Parses @format and returns the result.
2496  *
2497  * @format must be a text format #GVariant with one extension: at any
2498  * point that a value may appear in the text, a '%' character followed
2499  * by a GVariant format string (as per g_variant_new()) may appear.  In
2500  * that case, the same arguments are collected from the argument list as
2501  * g_variant_new() would have collected.
2502  *
2503  * Note that the arguments must be of the correct width for their types
2504  * specified in @format. This can be achieved by casting them. See
2505  * the [GVariant varargs documentation][gvariant-varargs].
2506  *
2507  * Consider this simple example:
2508  * |[<!-- language="C" --> 
2509  *  g_variant_new_parsed ("[('one', 1), ('two', %i), (%s, 3)]", 2, "three");
2510  * ]|
2511  *
2512  * In the example, the variable argument parameters are collected and
2513  * filled in as if they were part of the original string to produce the
2514  * result of
2515  * |[<!-- language="C" --> 
2516  * [('one', 1), ('two', 2), ('three', 3)]
2517  * ]|
2518  *
2519  * This function is intended only to be used with @format as a string
2520  * literal.  Any parse error is fatal to the calling process.  If you
2521  * want to parse data from untrusted sources, use g_variant_parse().
2522  *
2523  * You may not use this function to return, unmodified, a single
2524  * #GVariant pointer from the argument list.  ie: @format may not solely
2525  * be anything along the lines of "%*", "%?", "\%r", or anything starting
2526  * with "%@".
2527  *
2528  * Returns: a new floating #GVariant instance
2529  **/
2530 GVariant *
2531 g_variant_new_parsed (const gchar *format,
2532                       ...)
2533 {
2534   GVariant *result;
2535   va_list ap;
2536
2537   va_start (ap, format);
2538   result = g_variant_new_parsed_va (format, &ap);
2539   va_end (ap);
2540
2541   return result;
2542 }
2543
2544 /**
2545  * g_variant_builder_add_parsed:
2546  * @builder: a #GVariantBuilder
2547  * @format: a text format #GVariant
2548  * @...: arguments as per @format
2549  *
2550  * Adds to a #GVariantBuilder.
2551  *
2552  * This call is a convenience wrapper that is exactly equivalent to
2553  * calling g_variant_new_parsed() followed by
2554  * g_variant_builder_add_value().
2555  *
2556  * Note that the arguments must be of the correct width for their types
2557  * specified in @format_string. This can be achieved by casting them. See
2558  * the [GVariant varargs documentation][gvariant-varargs].
2559  *
2560  * This function might be used as follows:
2561  *
2562  * |[<!-- language="C" --> 
2563  * GVariant *
2564  * make_pointless_dictionary (void)
2565  * {
2566  *   GVariantBuilder builder;
2567  *   int i;
2568  *
2569  *   g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
2570  *   g_variant_builder_add_parsed (&builder, "{'width', <%i>}", 600);
2571  *   g_variant_builder_add_parsed (&builder, "{'title', <%s>}", "foo");
2572  *   g_variant_builder_add_parsed (&builder, "{'transparency', <0.5>}");
2573  *   return g_variant_builder_end (&builder);
2574  * }
2575  * ]|
2576  *
2577  * Since: 2.26
2578  */
2579 void
2580 g_variant_builder_add_parsed (GVariantBuilder *builder,
2581                               const gchar     *format,
2582                               ...)
2583 {
2584   va_list ap;
2585
2586   va_start (ap, format);
2587   g_variant_builder_add_value (builder, g_variant_new_parsed_va (format, &ap));
2588   va_end (ap);
2589 }
2590
2591 static gboolean
2592 parse_num (const gchar *num,
2593            const gchar *limit,
2594            gint        *result)
2595 {
2596   gchar *endptr;
2597   gint64 bignum;
2598
2599   bignum = g_ascii_strtoll (num, &endptr, 10);
2600
2601   if (endptr != limit)
2602     return FALSE;
2603
2604   if (bignum < 0 || bignum > G_MAXINT)
2605     return FALSE;
2606
2607   *result = bignum;
2608
2609   return TRUE;
2610 }
2611
2612 static void
2613 add_last_line (GString     *err,
2614                const gchar *str)
2615 {
2616   const gchar *last_nl;
2617   gchar *chomped;
2618   gint i;
2619
2620   /* This is an error at the end of input.  If we have a file
2621    * with newlines, that's probably the empty string after the
2622    * last newline, which is not the most useful thing to show.
2623    *
2624    * Instead, show the last line of non-whitespace that we have
2625    * and put the pointer at the end of it.
2626    */
2627   chomped = g_strchomp (g_strdup (str));
2628   last_nl = strrchr (chomped, '\n');
2629   if (last_nl == NULL)
2630     last_nl = chomped;
2631   else
2632     last_nl++;
2633
2634   /* Print the last line like so:
2635    *
2636    *   [1, 2, 3,
2637    *            ^
2638    */
2639   g_string_append (err, "  ");
2640   if (last_nl[0])
2641     g_string_append (err, last_nl);
2642   else
2643     g_string_append (err, "(empty input)");
2644   g_string_append (err, "\n  ");
2645   for (i = 0; last_nl[i]; i++)
2646     g_string_append_c (err, ' ');
2647   g_string_append (err, "^\n");
2648   g_free (chomped);
2649 }
2650
2651 static void
2652 add_lines_from_range (GString     *err,
2653                       const gchar *str,
2654                       const gchar *start1,
2655                       const gchar *end1,
2656                       const gchar *start2,
2657                       const gchar *end2)
2658 {
2659   while (str < end1 || str < end2)
2660     {
2661       const gchar *nl;
2662
2663       nl = str + strcspn (str, "\n");
2664
2665       if ((start1 < nl && str < end1) || (start2 < nl && str < end2))
2666         {
2667           const gchar *s;
2668
2669           /* We're going to print this line */
2670           g_string_append (err, "  ");
2671           g_string_append_len (err, str, nl - str);
2672           g_string_append (err, "\n  ");
2673
2674           /* And add underlines... */
2675           for (s = str; s < nl; s++)
2676             {
2677               if ((start1 <= s && s < end1) || (start2 <= s && s < end2))
2678                 g_string_append_c (err, '^');
2679               else
2680                 g_string_append_c (err, ' ');
2681             }
2682           g_string_append_c (err, '\n');
2683         }
2684
2685       if (!*nl)
2686         break;
2687
2688       str = nl + 1;
2689     }
2690 }
2691
2692 /**
2693  * g_variant_parse_error_print_context:
2694  * @error: a #GError from the #GVariantParseError domain
2695  * @source_str: the string that was given to the parser
2696  *
2697  * Pretty-prints a message showing the context of a #GVariant parse
2698  * error within the string for which parsing was attempted.
2699  *
2700  * The resulting string is suitable for output to the console or other
2701  * monospace media where newlines are treated in the usual way.
2702  *
2703  * The message will typically look something like one of the following:
2704  *
2705  * |[
2706  * unterminated string constant:
2707  *   (1, 2, 3, 'abc
2708  *             ^^^^
2709  * ]|
2710  *
2711  * or
2712  *
2713  * |[
2714  * unable to find a common type:
2715  *   [1, 2, 3, 'str']
2716  *    ^        ^^^^^
2717  * ]|
2718  *
2719  * The format of the message may change in a future version.
2720  *
2721  * @error must have come from a failed attempt to g_variant_parse() and
2722  * @source_str must be exactly the same string that caused the error.
2723  * If @source_str was not nul-terminated when you passed it to
2724  * g_variant_parse() then you must add nul termination before using this
2725  * function.
2726  *
2727  * Returns: (transfer full): the printed message
2728  *
2729  * Since: 2.40
2730  **/
2731 gchar *
2732 g_variant_parse_error_print_context (GError      *error,
2733                                      const gchar *source_str)
2734 {
2735   const gchar *colon, *dash, *comma;
2736   gboolean success = FALSE;
2737   GString *err;
2738
2739   g_return_val_if_fail (error->domain == G_VARIANT_PARSE_ERROR, FALSE);
2740
2741   /* We can only have a limited number of possible types of ranges
2742    * emitted from the parser:
2743    *
2744    *  - a:          -- usually errors from the tokeniser (eof, invalid char, etc.)
2745    *  - a-b:        -- usually errors from handling one single token
2746    *  - a-b,c-d:    -- errors involving two tokens (ie: type inferencing)
2747    *
2748    * We never see, for example "a,c".
2749    */
2750
2751   colon = strchr (error->message, ':');
2752   dash = strchr (error->message, '-');
2753   comma = strchr (error->message, ',');
2754
2755   if (!colon)
2756     return NULL;
2757
2758   err = g_string_new (colon + 1);
2759   g_string_append (err, ":\n");
2760
2761   if (dash == NULL || colon < dash)
2762     {
2763       gint point;
2764
2765       /* we have a single point */
2766       if (!parse_num (error->message, colon, &point))
2767         goto out;
2768
2769       if (point >= strlen (source_str))
2770         /* the error is at the end of the input */
2771         add_last_line (err, source_str);
2772       else
2773         /* otherwise just treat it as a error at a thin range */
2774         add_lines_from_range (err, source_str, source_str + point, source_str + point + 1, NULL, NULL);
2775     }
2776   else
2777     {
2778       /* We have one or two ranges... */
2779       if (comma && comma < colon)
2780         {
2781           gint start1, end1, start2, end2;
2782           const gchar *dash2;
2783
2784           /* Two ranges */
2785           dash2 = strchr (comma, '-');
2786
2787           if (!parse_num (error->message, dash, &start1) || !parse_num (dash + 1, comma, &end1) ||
2788               !parse_num (comma + 1, dash2, &start2) || !parse_num (dash2 + 1, colon, &end2))
2789             goto out;
2790
2791           add_lines_from_range (err, source_str,
2792                                 source_str + start1, source_str + end1,
2793                                 source_str + start2, source_str + end2);
2794         }
2795       else
2796         {
2797           gint start, end;
2798
2799           /* One range */
2800           if (!parse_num (error->message, dash, &start) || !parse_num (dash + 1, colon, &end))
2801             goto out;
2802
2803           add_lines_from_range (err, source_str, source_str + start, source_str + end, NULL, NULL);
2804         }
2805     }
2806
2807   success = TRUE;
2808
2809 out:
2810   return g_string_free (err, !success);
2811 }