Coverage Report

Created: 2025-10-10 07:05

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