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