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