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