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