Coverage Report

Created: 2023-09-20 06:34

/src/augeas/src/put.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * put.c:
3
 *
4
 * Copyright (C) 2007-2016 David Lutterkort
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
19
 *
20
 * Author: David Lutterkort <dlutter@redhat.com>
21
 */
22
23
#include <config.h>
24
25
#include <stdarg.h>
26
#include "regexp.h"
27
#include "memory.h"
28
#include "lens.h"
29
#include "errcode.h"
30
31
/* Data structure to keep track of where we are in the tree. The split
32
 * describes a sublist of the list of siblings in the current tree. The
33
 * put_* functions don't operate on the tree directly, instead they operate
34
 * on a split.
35
 *
36
 * The TREE field points to the first tree node for the current invocation
37
 * of put_*, FOLLOW points to the first sibling following TREE that is not
38
 * part of the split anymore (NULL if we are talking about all the siblings
39
 * of TREE)
40
 *
41
 * ENC is a string containing the encoding of the current position in the
42
 * tree.  The encoding is
43
 *   <label>=<value>/<label>=<value>/.../<label>=<value>/
44
 * where the label/value pairs come from TREE and its
45
 * siblings. The encoding uses ENC_EQ instead of the '=' above to avoid
46
 * clashes with legitimate values, and encodes NULL values as ENC_NULL.
47
 */
48
struct split {
49
    struct split *next;
50
    struct tree  *tree;
51
    struct tree  *follow;
52
    char         *enc;
53
    size_t        start;
54
    size_t        end;
55
};
56
57
struct state {
58
    FILE             *out;
59
    struct split     *split;
60
    const struct tree *tree;
61
    const char       *override;
62
    struct dict      *dict;
63
    struct skel      *skel;
64
    char             *path;   /* Position in the tree, for errors */
65
    size_t            pos;
66
    bool              with_span;
67
    struct info      *info;
68
    struct lns_error *error;
69
};
70
71
static void create_lens(struct lens *lens, struct state *state);
72
static void put_lens(struct lens *lens, struct state *state);
73
74
static void put_error(struct state *state, struct lens *lens,
75
                      const char *format, ...)
76
0
{
77
0
    va_list ap;
78
0
    int r;
79
80
0
    if (state->error != NULL)
81
0
        return;
82
83
0
    if (ALLOC(state->error) < 0)
84
0
        return;
85
0
    state->error->lens = ref(lens);
86
0
    state->error->pos  = -1;
87
0
    if (strlen(state->path) == 0) {
88
0
        state->error->path = strdup("");
89
0
    } else {
90
0
        state->error->path = strdup(state->path);
91
0
    }
92
93
0
    va_start(ap, format);
94
0
    r = vasprintf(&state->error->message, format, ap);
95
0
    va_end(ap);
96
0
    if (r == -1)
97
0
        state->error->message = NULL;
98
0
}
99
100
ATTRIBUTE_PURE
101
0
static int enclen(const char *key, const char *value) {
102
0
    return ENCLEN(key) + strlen(ENC_EQ) + ENCLEN(value)
103
0
        + strlen(ENC_SLASH);
104
0
}
105
106
0
static char *encpcpy(char *e, const char *key, const char *value) {
107
0
    e = stpcpy(e, ENCSTR(key));
108
0
    e = stpcpy(e, ENC_EQ);
109
0
    e = stpcpy(e, ENCSTR(value));
110
0
    e = stpcpy(e, ENC_SLASH);
111
0
    return e;
112
0
}
113
114
static void regexp_match_error(struct state *state, struct lens *lens,
115
0
                               int count, struct split *split) {
116
0
    char *text = NULL;
117
0
    char *pat = NULL;
118
119
0
    lns_format_atype(lens, &pat);
120
0
    text = enc_format_indent(split->enc + split->start,
121
0
                             split->end - split->start,
122
0
                             4);
123
124
0
    if (count == -1) {
125
0
        put_error(state, lens,
126
0
                  "Failed to match tree under %s\n\n%s\n  with pattern\n   %s\n",
127
0
                  state->path, text, pat);
128
0
    } else if (count == -2) {
129
0
        put_error(state, lens,
130
0
                  "Internal error matching\n    %s\n  with tree\n   %s\n",
131
0
                  pat, text);
132
0
    } else if (count == -3) {
133
        /* Should have been caught by the typechecker */
134
0
        put_error(state, lens, "Syntax error in tree schema\n    %s\n", pat);
135
0
    }
136
0
    free(pat);
137
0
    free(text);
138
0
}
139
140
0
static void free_split(struct split *split) {
141
0
    if (split == NULL)
142
0
        return;
143
144
0
    free(split->enc);
145
0
    free(split);
146
0
}
147
148
/* Encode the list of TREE's children as a string.
149
 */
150
0
static struct split *make_split(struct tree *tree) {
151
0
    struct split *split;
152
153
0
    if (ALLOC(split) < 0)
154
0
        return NULL;
155
156
0
    split->tree = tree;
157
0
    list_for_each(t, tree) {
158
0
        split->end += enclen(t->label, t->value);
159
0
    }
160
161
0
    if (ALLOC_N(split->enc, split->end + 1) < 0)
162
0
        goto error;
163
164
0
    char *enc = split->enc;
165
0
    list_for_each(t, tree) {
166
0
        enc = encpcpy(enc, t->label, t->value);
167
0
    }
168
0
    return split;
169
0
 error:
170
0
    free_split(split);
171
0
    return NULL;
172
0
}
173
174
static struct split *split_append(struct split **split, struct split *tail,
175
                                  struct tree *tree, struct tree *follow,
176
0
                                  char *enc, size_t start, size_t end) {
177
0
    struct split *sp;
178
0
    if (ALLOC(sp) < 0)
179
0
        return NULL;
180
0
    sp->tree = tree;
181
0
    sp->follow = follow;
182
0
    sp->enc = enc;
183
0
    sp->start = start;
184
0
    sp->end = end;
185
0
    list_tail_cons(*split, tail, sp);
186
0
    return tail;
187
0
}
188
189
0
static struct split *next_split(struct state *state) {
190
0
    if (state->split != NULL) {
191
0
        state->split = state->split->next;
192
0
        if (state->split != NULL)
193
0
            state->pos = state->split->end;
194
0
    }
195
0
    return state->split;
196
0
}
197
198
0
static struct split *set_split(struct state *state, struct split *split) {
199
0
    state->split = split;
200
0
    if (split != NULL)
201
0
        state->pos = split->end;
202
0
    return split;
203
0
}
204
205
/* Refine a tree split OUTER according to the L_CONCAT lens LENS */
206
0
static struct split *split_concat(struct state *state, struct lens *lens) {
207
0
    assert(lens->tag == L_CONCAT);
208
209
0
    int count = 0;
210
0
    struct split *outer = state->split;
211
0
    struct re_registers regs;
212
0
    struct split *split = NULL, *tail = NULL;
213
0
    struct regexp *atype = lens->atype;
214
215
0
    MEMZERO(&regs, 1);
216
217
    /* Fast path for leaf nodes, which will always lead to an empty split */
218
    // FIXME: This doesn't match the empty encoding
219
0
    if (outer->tree == NULL && strlen(outer->enc) == 0
220
0
        && regexp_is_empty_pattern(atype)) {
221
0
        for (int i=0; i < lens->nchildren; i++) {
222
0
            tail = split_append(&split, tail, NULL, NULL,
223
0
                                outer->enc, 0, 0);
224
0
            if (tail == NULL)
225
0
                goto error;
226
0
        }
227
0
        return split;
228
0
    }
229
230
0
    count = regexp_match(atype, outer->enc, outer->end,
231
0
                         outer->start, &regs);
232
0
    if (count >= 0 && count != outer->end - outer->start)
233
0
        count = -1;
234
0
    if (count < 0) {
235
0
        regexp_match_error(state, lens, count, outer);
236
0
        goto error;
237
0
    }
238
239
0
    struct tree *cur = outer->tree;
240
0
    int reg = 1;
241
0
    for (int i=0; i < lens->nchildren; i++) {
242
0
        assert(reg < regs.num_regs);
243
0
        assert(regs.start[reg] != -1);
244
0
        struct tree *follow = cur;
245
0
        for (int j = regs.start[reg]; j < regs.end[reg]; j++) {
246
0
            if (outer->enc[j] == ENC_SLASH_CH)
247
0
                follow = follow->next;
248
0
        }
249
0
        tail = split_append(&split, tail, cur, follow,
250
0
                            outer->enc, regs.start[reg], regs.end[reg]);
251
0
        cur = follow;
252
0
        reg += 1 + regexp_nsub(lens->children[i]->atype);
253
0
    }
254
0
    assert(reg < regs.num_regs);
255
0
 done:
256
0
    free(regs.start);
257
0
    free(regs.end);
258
0
    return split;
259
0
 error:
260
0
    free_split(split);
261
0
    split = NULL;
262
0
    goto done;
263
0
}
264
265
0
static struct split *split_iter(struct state *state, struct lens *lens) {
266
0
    assert(lens->tag == L_STAR);
267
268
0
    int count = 0;
269
0
    struct split *outer = state->split;
270
0
    struct split *split = NULL;
271
0
    struct regexp *atype = lens->child->atype;
272
273
0
    struct tree *cur = outer->tree;
274
0
    int pos = outer->start;
275
0
    struct split *tail = NULL;
276
0
    while (pos < outer->end) {
277
0
        count = regexp_match(atype, outer->enc, outer->end, pos, NULL);
278
0
        if (count == -1) {
279
0
            break;
280
0
        } else if (count < -1) {
281
0
            regexp_match_error(state, lens->child, count, outer);
282
0
            goto error;
283
0
        }
284
285
0
        struct tree *follow = cur;
286
0
        for (int j = pos; j < pos + count; j++) {
287
0
            if (outer->enc[j] == ENC_SLASH_CH)
288
0
                follow = follow->next;
289
0
        }
290
0
        tail = split_append(&split, tail, cur, follow,
291
0
                            outer->enc, pos, pos + count);
292
0
        cur = follow;
293
0
        pos += count;
294
0
    }
295
0
    return split;
296
0
 error:
297
0
    free_split(split);
298
0
    return NULL;
299
0
}
300
301
/* Check if LENS applies to the current split in STATE */
302
0
static int applies(struct lens *lens, struct state *state) {
303
0
    int count;
304
0
    struct split *split = state->split;
305
306
0
    count = regexp_match(lens->atype, split->enc, split->end,
307
0
                         split->start, NULL);
308
0
    if (count < -1) {
309
0
        regexp_match_error(state, lens, count, split);
310
0
        return 0;
311
0
    }
312
313
0
    if (count != split->end - split->start)
314
0
        return 0;
315
0
    if (count == 0 && lens->value)
316
0
        return state->tree->value != NULL;
317
0
    return 1;
318
0
}
319
320
/*
321
 * Check whether SKEL has the skeleton type required by LENS
322
 */
323
324
0
static int skel_instance_of(struct lens *lens, struct skel *skel) {
325
0
    if (skel == NULL)
326
0
        return 0;
327
328
0
    switch (lens->tag) {
329
0
    case L_DEL: {
330
0
        int count;
331
0
        if (skel->tag != L_DEL)
332
0
            return 0;
333
0
        count = regexp_match(lens->regexp, skel->text, strlen(skel->text),
334
0
                           0, NULL);
335
0
        return count == strlen(skel->text);
336
0
    }
337
0
    case L_STORE:
338
0
        return skel->tag == L_STORE;
339
0
    case L_KEY:
340
0
        return skel->tag == L_KEY;
341
0
    case L_LABEL:
342
0
        return skel->tag == L_LABEL;
343
0
    case L_VALUE:
344
0
        return skel->tag == L_VALUE;
345
0
    case L_SEQ:
346
0
        return skel->tag == L_SEQ;
347
0
    case L_COUNTER:
348
0
        return skel->tag == L_COUNTER;
349
0
    case L_CONCAT:
350
0
        {
351
0
            if (skel->tag != L_CONCAT)
352
0
                return 0;
353
0
            struct skel *s = skel->skels;
354
0
            for (int i=0; i < lens->nchildren; i++) {
355
0
                if (! skel_instance_of(lens->children[i], s))
356
0
                    return 0;
357
0
                s = s->next;
358
0
            }
359
0
            return 1;
360
0
        }
361
0
        break;
362
0
    case L_UNION:
363
0
        {
364
0
            for (int i=0; i < lens->nchildren; i++) {
365
0
                if (skel_instance_of(lens->children[i], skel))
366
0
                    return 1;
367
0
            }
368
0
            return 0;
369
0
        }
370
0
        break;
371
0
    case L_SUBTREE:
372
0
        return skel->tag == L_SUBTREE;
373
0
    case L_MAYBE:
374
0
        return skel->tag == L_MAYBE || skel_instance_of(lens->child, skel);
375
0
    case L_STAR:
376
0
        if (skel->tag != L_STAR)
377
0
            return 0;
378
0
        list_for_each(s, skel->skels) {
379
0
            if (! skel_instance_of(lens->child, s))
380
0
                return 0;
381
0
        }
382
0
        return 1;
383
0
    case L_REC:
384
0
        return skel_instance_of(lens->body, skel);
385
0
    case L_SQUARE:
386
0
        return skel->tag == L_SQUARE
387
0
            && skel_instance_of(lens->child, skel->skels);
388
0
    default:
389
0
        BUG_ON(true, lens->info, "illegal lens tag %d", lens->tag);
390
0
        break;
391
0
    }
392
0
 error:
393
0
    return 0;
394
0
}
395
396
enum span_kind { S_NONE, S_LABEL, S_VALUE };
397
398
0
static void emit(struct state *state, const char *text, enum span_kind kind) {
399
0
    struct span* span = state->tree->span;
400
401
0
    if (span != NULL) {
402
0
        long start = ftell(state->out);
403
0
        if (kind == S_LABEL) {
404
0
            span->label_start = start;
405
0
        } else if (kind == S_VALUE) {
406
0
            span->value_start = start;
407
0
        }
408
0
    }
409
0
    fprintf(state->out, "%s", text);
410
0
    if (span != NULL) {
411
0
        long end = ftell(state->out);
412
0
        if (kind == S_LABEL) {
413
0
            span->label_end = end;
414
0
        } else if (kind == S_VALUE) {
415
0
            span->value_end = end;
416
0
        }
417
0
    }
418
0
}
419
420
/*
421
 * put
422
 */
423
0
static void put_subtree(struct lens *lens, struct state *state) {
424
0
    assert(lens->tag == L_SUBTREE);
425
0
    struct state oldstate = *state;
426
0
    struct split oldsplit = *state->split;
427
0
    char *       oldpath = state->path;
428
429
0
    struct tree *tree = state->split->tree;
430
0
    struct split *split = NULL;
431
432
0
    state->tree = tree;
433
0
    state->path = path_of_tree(tree);
434
435
0
    split = make_split(tree->children);
436
0
    set_split(state, split);
437
438
0
    dict_lookup(tree->label, state->dict, &state->skel, &state->dict);
439
0
    if (state->with_span) {
440
0
        if (tree->span == NULL) {
441
0
            tree->span = make_span(state->info);
442
0
        }
443
0
        tree->span->span_start = ftell(state->out);
444
0
    }
445
0
    if (state->skel == NULL || ! skel_instance_of(lens->child, state->skel)) {
446
0
        create_lens(lens->child, state);
447
0
    } else {
448
0
        put_lens(lens->child, state);
449
0
    }
450
0
    assert(state->error != NULL || state->split->next == NULL);
451
0
    if (tree->span != NULL) {
452
0
        tree->span->span_end = ftell(state->out);
453
0
    }
454
455
0
    oldstate.error = state->error;
456
0
    oldstate.path = state->path;
457
0
    *state = oldstate;
458
0
    *state->split= oldsplit;
459
0
    free_split(split);
460
0
    free(state->path);
461
0
    state->path = oldpath;
462
0
}
463
464
0
static void put_del(ATTRIBUTE_UNUSED struct lens *lens, struct state *state) {
465
0
    assert(lens->tag == L_DEL);
466
0
    assert(state->skel != NULL);
467
0
    assert(state->skel->tag == L_DEL);
468
0
    if (state->override != NULL) {
469
0
        emit(state, state->override, S_NONE);
470
0
    } else {
471
0
        emit(state, state->skel->text, S_NONE);
472
0
    }
473
0
}
474
475
0
static void put_union(struct lens *lens, struct state *state) {
476
0
    assert(lens->tag == L_UNION);
477
478
0
    for (int i=0; i < lens->nchildren; i++) {
479
0
        struct lens *l = lens->children[i];
480
0
        if (applies(l, state)) {
481
0
            if (skel_instance_of(l, state->skel))
482
0
                put_lens(l, state);
483
0
            else
484
0
                create_lens(l, state);
485
0
            return;
486
0
        }
487
0
    }
488
0
    put_error(state, lens, "None of the alternatives in the union match");
489
0
}
490
491
0
static void put_concat(struct lens *lens, struct state *state) {
492
0
    assert(lens->tag == L_CONCAT);
493
0
    struct split *oldsplit = state->split;
494
0
    struct skel *oldskel = state->skel;
495
496
0
    struct split *split = split_concat(state, lens);
497
498
0
    state->skel = state->skel->skels;
499
0
    set_split(state, split);
500
0
    for (int i=0; i < lens->nchildren; i++) {
501
0
        if (state->split == NULL) {
502
0
            put_error(state, lens,
503
0
                      "Not enough components in concat");
504
0
            list_free(split);
505
0
            return;
506
0
        }
507
0
        put_lens(lens->children[i], state);
508
0
        state->skel = state->skel->next;
509
0
        next_split(state);
510
0
    }
511
0
    list_free(split);
512
0
    set_split(state, oldsplit);
513
0
    state->skel = oldskel;
514
0
}
515
516
static void error_quant_star(struct split *last_split, struct lens *lens,
517
0
                             struct state *state, const char *enc) {
518
0
    struct tree *child = NULL;
519
0
    if (last_split != NULL) {
520
0
        if (last_split->follow != NULL) {
521
0
            child = last_split->follow;
522
0
        } else {
523
0
            for (child = last_split->tree;
524
0
                 child != NULL && child->next != NULL;
525
0
                 child = child->next);
526
0
        }
527
0
    }
528
0
    char *text = NULL;
529
0
    char *pat = NULL;
530
531
0
    lns_format_atype(lens, &pat);
532
0
    text = enc_format_indent(enc, strlen(enc), 4);
533
534
0
    if (child == NULL) {
535
0
        put_error(state, lens,
536
0
             "Missing a node: can not match tree\n\n%s\n with pattern\n   %s\n",
537
0
                  text, pat);
538
0
    } else {
539
0
        char *s = path_of_tree(child);
540
0
        put_error(state, lens,
541
0
          "Unexpected node '%s': can not match tree\n\n%s\n with pattern\n   %s\n",
542
0
                  s, text, pat);
543
0
        free(s);
544
0
    }
545
0
    free(pat);
546
0
    free(text);
547
0
}
548
549
0
static void put_quant_star(struct lens *lens, struct state *state) {
550
0
    assert(lens->tag == L_STAR);
551
0
    struct split *oldsplit = state->split;
552
0
    struct skel *oldskel = state->skel;
553
0
    struct split *last_split = NULL;
554
555
0
    struct split *split = split_iter(state, lens);
556
557
0
    state->skel = state->skel->skels;
558
0
    set_split(state, split);
559
0
    last_split = state->split;
560
0
    while (state->split != NULL && state->skel != NULL) {
561
0
        put_lens(lens->child, state);
562
0
        state->skel = state->skel->next;
563
0
        last_split = state->split;
564
0
        next_split(state);
565
0
    }
566
0
    while (state->split != NULL) {
567
0
        create_lens(lens->child, state);
568
0
        last_split = state->split;
569
0
        next_split(state);
570
0
    }
571
0
    if (state->pos != oldsplit->end)
572
0
        error_quant_star(last_split, lens, state, oldsplit->enc + state->pos);
573
0
    list_free(split);
574
0
    set_split(state, oldsplit);
575
0
    state->skel = oldskel;
576
0
}
577
578
0
static void put_quant_maybe(struct lens *lens, struct state *state) {
579
0
    assert(lens->tag == L_MAYBE);
580
0
    struct lens *child = lens->child;
581
582
0
    if (applies(child, state)) {
583
0
        if (skel_instance_of(child, state->skel))
584
0
            put_lens(child, state);
585
0
        else
586
0
            create_lens(child, state);
587
0
    }
588
0
}
589
590
0
static void put_store(struct lens *lens, struct state *state) {
591
0
    const char *value = state->tree->value;
592
593
0
    if (value == NULL) {
594
0
        put_error(state, lens,
595
0
                  "Can not store a nonexistent (NULL) value");
596
0
    } else if (regexp_match(lens->regexp, value, strlen(value),
597
0
                            0, NULL) != strlen(value)) {
598
0
        char *pat = regexp_escape(lens->regexp);
599
0
        put_error(state, lens,
600
0
                  "Value '%s' does not match regexp /%s/ in store lens",
601
0
                  value, pat);
602
0
        free(pat);
603
0
    } else {
604
0
        emit(state, value, S_VALUE);
605
0
    }
606
0
}
607
608
0
static void put_rec(struct lens *lens, struct state *state) {
609
0
    put_lens(lens->body, state);
610
0
}
611
612
0
static void put_square(struct lens *lens, struct state *state) {
613
0
    assert(lens->tag == L_SQUARE);
614
0
    struct skel *oldskel = state->skel;
615
0
    struct split *oldsplit = state->split;
616
0
    struct lens *concat = lens->child;
617
0
    struct lens *left = concat->children[0];
618
0
    struct split *split = split_concat(state, concat);
619
620
    /* skels of concat is one depth more */
621
0
    state->skel = state->skel->skels->skels;
622
0
    set_split(state, split);
623
0
    for (int i=0; i < concat->nchildren; i++) {
624
0
        if (state->split == NULL) {
625
0
            put_error(state, concat, "Not enough components in square");
626
0
            list_free(split);
627
0
            return;
628
0
        }
629
0
        struct lens *curr = concat->children[i];
630
0
        if (i == (concat->nchildren - 1) && left->tag == L_KEY)
631
0
            state->override = state->tree->label;
632
0
        put_lens(curr, state);
633
0
        state->override = NULL;
634
0
        state->skel = state->skel->next;
635
0
        next_split(state);
636
0
    }
637
0
    list_free(split);
638
0
    set_split(state, oldsplit);
639
0
    state->skel = oldskel;
640
0
}
641
642
0
static void put_lens(struct lens *lens, struct state *state) {
643
0
    if (state->error != NULL)
644
0
        return;
645
646
0
    switch(lens->tag) {
647
0
    case L_DEL:
648
0
        put_del(lens, state);
649
0
        break;
650
0
    case L_STORE:
651
0
        put_store(lens, state);
652
0
        break;
653
0
    case L_KEY:
654
0
        emit(state, state->tree->label, S_LABEL);
655
0
        break;
656
0
    case L_LABEL:
657
0
    case L_VALUE:
658
        /* Nothing to do */
659
0
        break;
660
0
    case L_SEQ:
661
        /* Nothing to do */
662
0
        break;
663
0
    case L_COUNTER:
664
        /* Nothing to do */
665
0
        break;
666
0
    case L_CONCAT:
667
0
        put_concat(lens, state);
668
0
        break;
669
0
    case L_UNION:
670
0
        put_union(lens, state);
671
0
        break;
672
0
    case L_SUBTREE:
673
0
        put_subtree(lens, state);
674
0
        break;
675
0
    case L_STAR:
676
0
        put_quant_star(lens, state);
677
0
        break;
678
0
    case L_MAYBE:
679
0
        put_quant_maybe(lens, state);
680
0
        break;
681
0
    case L_REC:
682
0
        put_rec(lens, state);
683
0
        break;
684
0
    case L_SQUARE:
685
0
        put_square(lens, state);
686
0
        break;
687
0
    default:
688
0
        assert(0);
689
0
        break;
690
0
    }
691
0
}
692
693
0
static void create_subtree(struct lens *lens, struct state *state) {
694
0
    put_subtree(lens, state);
695
0
}
696
697
0
static void create_del(struct lens *lens, struct state *state) {
698
0
    assert(lens->tag == L_DEL);
699
0
    if (state->override != NULL) {
700
0
        emit(state, state->override, S_NONE);
701
0
    } else {
702
0
        emit(state, lens->string->str, S_NONE);
703
0
    }
704
0
}
705
706
0
static void create_union(struct lens *lens, struct state *state) {
707
0
    assert(lens->tag == L_UNION);
708
709
0
    for (int i=0; i < lens->nchildren; i++) {
710
0
        if (applies(lens->children[i], state)) {
711
0
            create_lens(lens->children[i], state);
712
0
            return;
713
0
        }
714
0
    }
715
0
    put_error(state, lens, "None of the alternatives in the union match");
716
0
}
717
718
0
static void create_concat(struct lens *lens, struct state *state) {
719
0
    assert(lens->tag == L_CONCAT);
720
0
    struct split *oldsplit = state->split;
721
722
0
    struct split *split = split_concat(state, lens);
723
724
0
    set_split(state, split);
725
0
    for (int i=0; i < lens->nchildren; i++) {
726
0
        if (state->split == NULL) {
727
0
            put_error(state, lens,
728
0
                      "Not enough components in concat");
729
0
            list_free(split);
730
0
            return;
731
0
        }
732
0
        create_lens(lens->children[i], state);
733
0
        next_split(state);
734
0
    }
735
0
    list_free(split);
736
0
    set_split(state, oldsplit);
737
0
}
738
739
0
static void create_square(struct lens *lens, struct state *state) {
740
0
    assert(lens->tag == L_SQUARE);
741
0
    struct lens *concat = lens->child;
742
743
0
    struct split *oldsplit = state->split;
744
0
    struct split *split = split_concat(state, concat);
745
0
    struct lens *left = concat->children[0];
746
747
0
    set_split(state, split);
748
0
    for (int i=0; i < concat->nchildren; i++) {
749
0
        if (state->split == NULL) {
750
0
            put_error(state, concat, "Not enough components in square");
751
0
            list_free(split);
752
0
            return;
753
0
        }
754
0
        struct lens *curr = concat->children[i];
755
0
        if (i == (concat->nchildren - 1) && left->tag == L_KEY)
756
0
            state->override = state->tree->label;
757
0
        create_lens(curr, state);
758
0
        state->override = NULL;
759
0
        next_split(state);
760
0
    }
761
0
    list_free(split);
762
0
    set_split(state, oldsplit);
763
0
}
764
765
0
static void create_quant_star(struct lens *lens, struct state *state) {
766
0
    assert(lens->tag == L_STAR);
767
0
    struct split *oldsplit = state->split;
768
0
    struct split *last_split = NULL;
769
770
0
    struct split *split = split_iter(state, lens);
771
772
0
    set_split(state, split);
773
0
    last_split = state->split;
774
0
    while (state->split != NULL) {
775
0
        create_lens(lens->child, state);
776
0
        last_split = state->split;
777
0
        next_split(state);
778
0
    }
779
0
    if (state->pos != oldsplit->end)
780
0
        error_quant_star(last_split, lens, state, oldsplit->enc + state->pos);
781
0
    list_free(split);
782
0
    set_split(state, oldsplit);
783
0
}
784
785
0
static void create_quant_maybe(struct lens *lens, struct state *state) {
786
0
    assert(lens->tag == L_MAYBE);
787
788
0
    if (applies(lens->child, state)) {
789
0
        create_lens(lens->child, state);
790
0
    }
791
0
}
792
793
0
static void create_rec(struct lens *lens, struct state *state) {
794
0
    create_lens(lens->body, state);
795
0
}
796
797
0
static void create_lens(struct lens *lens, struct state *state) {
798
0
    if (state->error != NULL)
799
0
        return;
800
0
    switch(lens->tag) {
801
0
    case L_DEL:
802
0
        create_del(lens, state);
803
0
        break;
804
0
    case L_STORE:
805
0
        put_store(lens, state);
806
0
        break;
807
0
    case L_KEY:
808
0
        emit(state, state->tree->label, S_LABEL);
809
0
        break;
810
0
    case L_LABEL:
811
0
    case L_VALUE:
812
        /* Nothing to do */
813
0
        break;
814
0
    case L_SEQ:
815
        /* Nothing to do */
816
0
        break;
817
0
    case L_COUNTER:
818
        /* Nothing to do */
819
0
        break;
820
0
    case L_CONCAT:
821
0
        create_concat(lens, state);
822
0
        break;
823
0
    case L_UNION:
824
0
        create_union(lens, state);
825
0
        break;
826
0
    case L_SUBTREE:
827
0
        create_subtree(lens, state);
828
0
        break;
829
0
    case L_STAR:
830
0
        create_quant_star(lens, state);
831
0
        break;
832
0
    case L_MAYBE:
833
0
        create_quant_maybe(lens, state);
834
0
        break;
835
0
    case L_REC:
836
0
        create_rec(lens, state);
837
0
        break;
838
0
    case L_SQUARE:
839
0
        create_square(lens, state);
840
0
        break;
841
0
    default:
842
0
        assert(0);
843
0
        break;
844
0
    }
845
0
}
846
847
void lns_put(struct info *info, FILE *out, struct lens *lens, struct tree *tree,
848
0
             const char *text, int enable_span, struct lns_error **err) {
849
0
    struct state state;
850
0
    struct lns_error *err1;
851
852
0
    if (err != NULL)
853
0
        *err = NULL;
854
0
    if (tree == NULL)
855
0
        return;
856
857
0
    MEMZERO(&state, 1);
858
0
    state.path = strdup("/");
859
0
    state.skel = lns_parse(lens, text, &state.dict, &err1);
860
861
0
    if (err1 != NULL) {
862
0
        if (err != NULL)
863
0
            *err = err1;
864
0
        else
865
0
            free_lns_error(err1);
866
0
        goto error;
867
0
    }
868
0
    state.out = out;
869
0
    state.split = make_split(tree);
870
0
    state.with_span = enable_span;
871
0
    state.tree = tree;
872
0
    state.info = info;
873
0
    if (state.with_span) {
874
0
        if (tree->span == NULL) {
875
0
            tree->span = make_span(info);
876
0
        }
877
0
        tree->span->span_start = ftell(out);
878
0
    }
879
0
    put_lens(lens, &state);
880
0
    if (state.with_span) {
881
0
        tree->span->span_end = ftell(out);
882
0
    }
883
0
    if (err != NULL) {
884
0
        *err = state.error;
885
0
    } else {
886
0
        free_lns_error(state.error);
887
0
    }
888
889
0
 error:
890
0
    free(state.path);
891
0
    free_split(state.split);
892
0
    free_skel(state.skel);
893
0
    free_dict(state.dict);
894
0
}
895
896
/*
897
 * Local variables:
898
 *  indent-tabs-mode: nil
899
 *  c-indent-level: 4
900
 *  c-basic-offset: 4
901
 *  tab-width: 4
902
 * End:
903
 */