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