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