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