From 8070e692dfee4124143c9d77db227d40a652cbd6 Mon Sep 17 00:00:00 2001 From: David Lutterkort Date: Sat, 11 Apr 2015 00:29:42 -0700 Subject: [PATCH 1/4] RFC: Add a 'region' lens to make controlling spacing easier So far, how deleted text is handled when entries are added to or removed from the tree was tightly bound up with how the tree was structured, because the subtree combinator [ .. ] controlled both: construction of new tree nodes and glomming deleted stuff together. In addition, the [ .. ] does the glomming based on the key of the tree node it constructs, so that deleting a node from hte middle of a number of nodes with the same key had the weird effect that entries tended to 'shift up'. The region combinator tries to address this, in that all it does is demarcate how deleted stuff should be glommed, and it does that based on the position in the input file, not on the value of a key. Syntactically, this is written as < l >, though other syntax, like 'region l', or '<< l >>' might be better. It would be great if this could also be used to indent new things the same as surrounding stuff, i.e. if we have a lens < l >* and we add en entry in the middle of it, if that would automatically mean that the new entry gets the indentation of one of the surrounding lines - that's not implemented yet. I would really like to see and hear how this does or does not address some of the spacing/indentation problems that people have been having, ideally demonstrated by a simple test. --- src/ast.c | 25 ++++++++++++++ src/get.c | 63 ++++++++++++++++++++++++++++++++++ src/internal.h | 1 + src/jmt.c | 4 +++ src/lens.c | 33 ++++++++++++++++-- src/lens.h | 11 ++++-- src/lexer.l | 2 +- src/parser.y | 4 ++- src/put.c | 29 ++++++++++++++++ src/syntax.c | 29 ++++++++++++++++ src/syntax.h | 3 +- tests/modules/pass_region.aug | 64 +++++++++++++++++++++++++++++++++++ 12 files changed, 261 insertions(+), 7 deletions(-) create mode 100644 tests/modules/pass_region.aug diff --git a/src/ast.c b/src/ast.c index e90770d37..a8113b961 100644 --- a/src/ast.c +++ b/src/ast.c @@ -93,6 +93,21 @@ struct dict *make_dict(char *key, struct skel *skel, struct dict *subdict) { return NULL; } +static char *size_as_key(size_t key) { + char *s = NULL; + + xasprintf(&s, "%zx", key); + return s; +} + +struct dict *make_dictz(size_t key, struct skel *skel, struct dict *subdict) { + char *s = size_as_key(key); + + if (s == NULL) + return NULL; + return make_dict(s, skel, subdict); +} + void free_dict(struct dict *dict) { if (dict == NULL) return; @@ -213,7 +228,17 @@ void dict_lookup(const char *key, struct dict *dict, } } +void dict_lookupz(size_t key, struct dict *dict, + struct skel **skel, struct dict **subdict) { + char *s = size_as_key(key); + if (s == NULL) { + *skel = NULL; + *subdict = NULL; + return; + } + dict_lookup(s, dict, skel, subdict); +} /* * Local variables: diff --git a/src/get.c b/src/get.c index ce0864b21..d9940a2e4 100644 --- a/src/get.c +++ b/src/get.c @@ -344,6 +344,9 @@ static void print_skel(struct skel *skel) { case L_SUBTREE: print_skel_list(skel->skels, "[", " ", "]"); break; + case L_REGION: + print_skel_list(skel->skels, "<", " ", ">"); + break; default: printf("??"); break; @@ -779,6 +782,7 @@ static int try_match(struct lens *lens, struct state *state, return 0; break; case L_SUBTREE: + case L_REGION: case L_STAR: case L_MAYBE: case L_SQUARE: @@ -938,6 +942,41 @@ static struct skel *parse_subtree(struct lens *lens, struct state *state, return make_skel(lens); } +static struct tree *get_region(struct lens *lens, struct state *state) { + struct span *span = state->span; + + struct tree *tree; + + if (state->info->flags & AUG_ENABLE_SPAN) { + state->span = make_span(state->info); + ERR_NOMEM(state->span == NULL, state->info); + } + + tree = get_lens(lens->child, state); + + tree->span = state->span; + tree->pos = REG_START(state) + 1; + + if (state->span != NULL) { + update_span(span, state->span->span_start, state->span->span_end); + } + + state->span = span; + return tree; + error: + return NULL; +} + +static struct skel *parse_region(struct lens *lens, struct state *state, + struct dict **dict) { + struct skel *skel; + struct dict *di = NULL; + + skel = parse_lens(lens->child, state, &di); + *dict = make_dictz(REG_START(state) + 1, skel, di); + return make_skel(lens); +} + /* Check if left and right strings matches according to the square lens * definition. * @@ -1319,6 +1358,7 @@ static void visit_exit(struct lens *lens, tree = make_tree(top->key, top->value, NULL, top->tree); ERR_NOMEM(tree == NULL, lens->info); tree->span = state->span; + tree->pos = start; /* Restore the parse state from before entering this subtree */ top = pop_frame(rec_state); ERR_BAIL(state->info); @@ -1333,6 +1373,23 @@ static void visit_exit(struct lens *lens, } else { visit_exit_put_subtree(lens, rec_state, top); } + } else if (lens->tag == L_REGION) { + if (rec_state->mode == M_PARSE) { + struct frame *top = top_frame(rec_state); + struct skel *skel; + struct dict *dict; + skel = make_skel(lens); + ERR_NOMEM(skel == NULL, lens->info); + dict = make_dictz(start, top->skel, top->dict); + ERR_NOMEM(dict == NULL, lens->info); + top = pop_frame(rec_state); + ensure(lens == top->lens, state->info); + state->key = top->key; + pop_frame(rec_state); + top = push_frame(rec_state, lens); + top->skel = skel; + top->dict = dict; + } } else if (lens->tag == L_CONCAT) { ensure(rec_state->fused >= lens->nchildren, state->info); for (int i = 0; i < lens->nchildren; i++) { @@ -1554,6 +1611,9 @@ static struct tree *get_lens(struct lens *lens, struct state *state) { case L_SUBTREE: tree = get_subtree(lens, state); break; + case L_REGION: + tree = get_region(lens, state); + break; case L_STAR: tree = get_quant_star(lens, state); break; @@ -1695,6 +1755,9 @@ static struct skel *parse_lens(struct lens *lens, struct state *state, case L_SUBTREE: skel = parse_subtree(lens, state, dict); break; + case L_REGION: + skel = parse_region(lens, state,dict); + break; case L_STAR: skel = parse_quant_star(lens, state, dict); break; diff --git a/src/internal.h b/src/internal.h index 2633a983d..88828e7ec 100644 --- a/src/internal.h +++ b/src/internal.h @@ -422,6 +422,7 @@ struct tree { char *label; /* Last component of PATH */ struct tree *children; /* List of children through NEXT */ char *value; + size_t pos; struct span *span; /* Flags */ diff --git a/src/jmt.c b/src/jmt.c index 79953da15..7328a84b8 100644 --- a/src/jmt.c +++ b/src/jmt.c @@ -759,6 +759,7 @@ build_nullable(struct jmt_parse *parse, ind_t pos, lens->children[i], lvl+1); break; case L_SUBTREE: + case L_REGION: case L_SQUARE: build_nullable(parse, pos, visitor, lens->child, lvl+1); break; @@ -1217,6 +1218,7 @@ static void print_grammar(struct jmt *jmt, struct lens *lens) { print_grammar(jmt, lens->children[i]); break; case L_SUBTREE: + case L_REGION: print_lens_symbol(stdout, jmt, lens->child); printf("\n"); print_grammar(jmt, lens->child); @@ -1280,6 +1282,7 @@ static void index_lenses(struct jmt *jmt, struct lens *lens) { index_lenses(jmt, lens->children[i]); break; case L_SUBTREE: + case L_REGION: case L_STAR: case L_MAYBE: case L_SQUARE: @@ -1475,6 +1478,7 @@ static void conv_rhs(struct jmt *jmt, ind_t l) { conv_union(jmt, lens, &s, &e, &f); break; case L_SUBTREE: + case L_REGION: conv(jmt, lens->child, &s, &e, &f); break; case L_STAR: diff --git a/src/lens.c b/src/lens.c index f70d7b632..6e0dc04b4 100644 --- a/src/lens.c +++ b/src/lens.c @@ -347,6 +347,27 @@ struct value *lns_make_subtree(struct info *info, struct lens *l) { return make_lens_value(lens); } +/* + * A region lens l1 = < l > + * + * Types are simply copied + */ +struct value *lns_make_region(struct info *info, struct lens *l) { + struct lens *lens; + + lens = make_lens_unop(L_REGION, info, l); + for (int t = 0; t < ntypes; t++) { + ltype(lens, t) = ref(ltype(l, t)); + } + lens->value = l->value; + lens->key = l->key; + lens->recursive = l->recursive; + lens->rec_internal = l->rec_internal; + if (! l->recursive) + lens->ctype_nullable = l->ctype_nullable; + return make_lens_value(lens); +} + struct value *lns_make_star(struct info *info, struct lens *l, int check) { struct lens *lens; @@ -1016,6 +1037,7 @@ void free_lens(struct lens *lens) { unref(lens->string, string); break; case L_SUBTREE: + case L_REGION: case L_STAR: case L_MAYBE: case L_SQUARE: @@ -1057,8 +1079,9 @@ void lens_release(struct lens *lens) { if (lens->tag == L_KEY || lens->tag == L_STORE) regexp_release(lens->regexp); - if (lens->tag == L_SUBTREE || lens->tag == L_STAR - || lens->tag == L_MAYBE || lens->tag == L_SQUARE) { + if (lens->tag == L_SUBTREE || lens->tag == L_REGION + || lens->tag == L_STAR || lens->tag == L_MAYBE + || lens->tag == L_SQUARE) { lens_release(lens->child); } @@ -1362,6 +1385,7 @@ static int format_atype(struct lens *l, char **buf, uint indent) { return (*buf == NULL) ? -1 : 0; break; case L_SUBTREE: + case L_REGION: return format_subtree_atype(l, buf, indent); break; case L_STAR: @@ -1741,6 +1765,7 @@ static void rtn_rules(struct rtn *rtn, struct lens *l) { rtn_rules(rtn, l->body); RTN_BAIL(rtn); break; + case L_REGION: case L_SQUARE: add_trans(rtn, start, prod->end, l->child); RTN_BAIL(rtn); @@ -2078,6 +2103,7 @@ static void propagate_type(struct lens *l, enum lens_type lt) { case L_REC: /* Nothing to do */ break; + case L_REGION: case L_SQUARE: propagate_type(l->child, lt); ltype(l, lt) = ref(ltype(l->child, lt)); @@ -2158,6 +2184,7 @@ static struct value *typecheck(struct lens *l, int check) { exn = typecheck_n(l, lns_make_union, check); break; case L_SUBTREE: + case L_REGION: case L_SQUARE: exn = typecheck(l->child, check); break; @@ -2273,6 +2300,7 @@ static int ctype_nullable(struct lens *lens, struct value **exn) { } break; case L_SUBTREE: + case L_REGION: case L_SQUARE: ret = ctype_nullable(lens->child, exn); nullable = lens->child->ctype_nullable; @@ -2438,6 +2466,7 @@ void dump_lens(FILE *out, struct lens *lens){ } break; case L_SUBTREE: + case L_REGION: fprintf(out, "\"%p\" -> \"%p\"\n", lens, lens->child); dump_lens(out, lens->child); break; diff --git a/src/lens.h b/src/lens.h index d1a37cdad..3a480f717 100644 --- a/src/lens.h +++ b/src/lens.h @@ -39,6 +39,7 @@ enum lens_tag { L_CONCAT, L_UNION, L_SUBTREE, + L_REGION, L_STAR, L_MAYBE, L_REC, @@ -94,7 +95,8 @@ struct lens { struct string *string; /* L_VALUE, L_LABEL, L_SEQ, L_COUNTER */ }; /* Combinators */ - struct lens *child; /* L_SUBTREE, L_STAR, L_MAYBE, L_SQUARE */ + struct lens *child; /* L_SUBTREE, L_STAR, L_MAYBE, + L_SQUARE, L_REGION */ struct { /* L_UNION, L_CONCAT */ unsigned int nchildren; struct lens **children; @@ -134,6 +136,7 @@ struct value *lns_make_union(struct info *, struct lens *, struct lens *, struct value *lns_make_concat(struct info *, struct lens *, struct lens *, int check); struct value *lns_make_subtree(struct info *, struct lens *); +struct value *lns_make_region(struct info *, struct lens *); struct value *lns_make_star(struct info *, struct lens *, int check); struct value *lns_make_plus(struct info *, struct lens *, @@ -165,7 +168,7 @@ struct skel { char *text; /* L_DEL */ struct skel *skels; /* L_CONCAT, L_STAR, L_SQUARE */ }; - /* Also tag == L_SUBTREE, with no data in the union */ + /* Also tag == L_SUBTREE || tag == L_REGION, with no data in the union */ }; struct lns_error { @@ -178,8 +181,12 @@ struct lns_error { }; struct dict *make_dict(char *key, struct skel *skel, struct dict *subdict); +struct dict *make_dictz(size_t key, struct skel *skel, struct dict *subdict); + void dict_lookup(const char *key, struct dict *dict, struct skel **skel, struct dict **subdict); +void dict_lookupz(size_t key, struct dict *dict, + struct skel **skel, struct dict **subdict); int dict_append(struct dict **dict, struct dict *d2); void free_skel(struct skel *skel); void free_dict(struct dict *dict); diff --git a/src/lexer.l b/src/lexer.l index 78d4a89a0..80f93b9db 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -107,7 +107,7 @@ ARROW -> return REGEXP; } - [|*?+()=:;\.\[\]{}-] return yytext[0]; + [|*?+()=:;\.\[\]{}<>-] return yytext[0]; module return KW_MODULE; diff --git a/src/parser.y b/src/parser.y index edcd57b8e..32e60c112 100644 --- a/src/parser.y +++ b/src/parser.y @@ -264,6 +264,8 @@ aexp: qid { $$ = $2; } | '[' exp ']' { $$ = make_unop(A_BRACKET, $2, &@$); } + | '<' exp '>' + { $$ = make_unop(A_REGION, $2, &@$); } | '(' ')' { $$ = make_unit_term(&@$); } @@ -524,7 +526,7 @@ static struct term *make_binop(enum term_tag tag, static struct term *make_unop(enum term_tag tag, struct term *exp, struct info *locp) { - assert(tag == A_BRACKET); + assert(tag == A_BRACKET || tag == A_REGION); struct term *term = make_term_locp(tag, locp); term->brexp = exp; return term; diff --git a/src/put.c b/src/put.c index 5ada2ce15..dd26ce64d 100644 --- a/src/put.c +++ b/src/put.c @@ -365,6 +365,9 @@ static int skel_instance_of(struct lens *lens, struct skel *skel) { break; case L_SUBTREE: return skel->tag == L_SUBTREE; + case L_REGION: + return skel->tag == L_REGION + && skel_instance_of(lens->child, skel->skels); case L_MAYBE: return skel->tag == L_MAYBE || skel_instance_of(lens->child, skel); case L_STAR: @@ -456,6 +459,22 @@ static void put_subtree(struct lens *lens, struct state *state) { state->path = oldpath; } +static void put_region(struct lens *lens, struct state *state) { + assert(lens->tag == L_REGION); + struct skel *oldskel = state->skel; + struct dict *olddict = state->dict; + struct tree *tree = state->split->tree; + + dict_lookupz(tree->pos, state->dict, &state->skel, &state->dict); + if (state->skel == NULL || ! skel_instance_of(lens->child, state->skel)) { + create_lens(lens->child, state); + } else { + put_lens(lens->child, state); + } + state->skel = oldskel; + state->dict = olddict; +} + static void put_del(ATTRIBUTE_UNUSED struct lens *lens, struct state *state) { assert(lens->tag == L_DEL); assert(state->skel != NULL); @@ -667,6 +686,9 @@ static void put_lens(struct lens *lens, struct state *state) { case L_SUBTREE: put_subtree(lens, state); break; + case L_REGION: + put_region(lens, state); + break; case L_STAR: put_quant_star(lens, state); break; @@ -689,6 +711,10 @@ static void create_subtree(struct lens *lens, struct state *state) { put_subtree(lens, state); } +static void create_region(struct lens *lens, struct state *state) { + put_region(lens, state); +} + static void create_del(struct lens *lens, struct state *state) { assert(lens->tag == L_DEL); if (state->override != NULL) { @@ -821,6 +847,9 @@ static void create_lens(struct lens *lens, struct state *state) { case L_SUBTREE: create_subtree(lens, state); break; + case L_REGION: + create_region(lens, state); + break; case L_STAR: create_quant_star(lens, state); break; diff --git a/src/syntax.c b/src/syntax.c index 612544c75..8f51ad6d5 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -191,6 +191,7 @@ void free_term(struct term *term) { unref(term->ident, string); break; case A_BRACKET: + case A_REGION: unref(term->brexp, term); break; case A_FUNC: @@ -1280,6 +1281,19 @@ static int check_exp(struct term *term, struct ctx *ctx) { } } break; + case A_REGION: + result = check_exp(term->brexp, ctx); + if (result) { + term->type = ref(expect_types(term->info, term->brexp->type, + 1, t_lens)); + if (term->type == NULL) { + type_error1(term->info, + "<..> is only defined for lenses, not for %s", + term->brexp->type); + result = 0; + } + } + break; case A_FUNC: { bind_param(&ctx->local, term->param, NULL); @@ -1625,6 +1639,18 @@ static struct value *compile_bracket(struct term *exp, struct ctx *ctx) { return v; } +static struct value *compile_region(struct term *exp, struct ctx *ctx) { + struct value *arg = compile_exp(exp->info, exp->brexp, ctx); + if (EXN(arg)) + return arg; + assert(arg->tag == V_LENS); + + struct value *v = lns_make_region(ref(exp->info), ref(arg->lens)); + unref(arg, value); + + return v; +} + static struct value *compile_rep(struct term *rep, struct ctx *ctx) { struct value *arg = compile_exp(rep->info, rep->rexp, ctx); struct value *v = NULL; @@ -1699,6 +1725,9 @@ static struct value *compile_exp(struct info *info, case A_BRACKET: v = compile_bracket(exp, ctx); break; + case A_REGION: + v = compile_region(exp, ctx); + break; case A_FUNC: v = make_closure(exp, ctx->local); break; diff --git a/src/syntax.h b/src/syntax.h index 12c3bae40..441606911 100644 --- a/src/syntax.h +++ b/src/syntax.h @@ -49,6 +49,7 @@ enum term_tag { A_VALUE, A_IDENT, A_BRACKET, + A_REGION, A_FUNC, A_REP, A_TEST @@ -87,7 +88,7 @@ struct term { struct term *right; }; struct value *value; /* A_VALUE */ - struct term *brexp; /* A_BRACKET */ + struct term *brexp; /* A_BRACKET, A_REGION */ struct string *ident; /* A_IDENT */ struct { /* A_REP */ enum quant_tag quant; diff --git a/tests/modules/pass_region.aug b/tests/modules/pass_region.aug new file mode 100644 index 000000000..fafdbf4eb --- /dev/null +++ b/tests/modules/pass_region.aug @@ -0,0 +1,64 @@ +module Pass_Region = + +(* Some basic lenses that we will combine in a number of ways *) +let eol = del "\n" "\n" +let indent = del /[ _]*/ "_" (* Create spaces as '_' *) +let entry = key /a/ . del "=" "=" . store /[sx]*/ + +(* indent outside the subtree for entry *) +let outside = indent . [ entry ] . eol +(* indent inside the subtree for entry *) +let inside = [ indent . entry ] . eol + +(* The test text is set up so that the number of 's' indicate how many + spaces of indent we had *) +let text = "a=\n a=s\n a=ss\n" + +(* All these lenses produce the exact same tree, with or without < .. > *) +test (outside*) get text = + { "a" = "" } + { "a" = "s" } + { "a" = "ss" } + +test (inside*) get text = + { "a" = "" } + { "a" = "s" } + { "a" = "ss" } + +test (< outside >*) get text = + { "a" = "" } + { "a" = "s" } + { "a" = "ss" } + +test (< inside >*) get text = + { "a" = "" } + { "a" = "s" } + { "a" = "ss" } + +(* They behave slightly differently when we insert in the middle, + depending on whether we use < .. > or not *) +let text_new_middle = "a=\n_a=sx\n a=s\n a=ss\n" +let text_new_end = "a=\n a=sx\n a=s\n_a=ss\n" + +test (outside*) put text after insa "a" "/a[1]"; set "/a[2]" "sx" = + text_new_end + +test (inside*) put text after insa "a" "/a[1]"; set "/a[2]" "sx" = + text_new_end + +test (< outside >*) put text after insa "a" "/a[1]"; set "/a[2]" "sx" = + text_new_middle + +test (< inside >*) put text after insa "a" "/a[1]"; set "/a[2]" "sx" = + text_new_middle + +(* Delete an entry in the middle *) +let text_rm_shift = "a=\n a=ss\n" +let text_rm_noshift = "a=\n a=ss\n" +test (outside*) put text after rm "/a[2]" = text_rm_shift + +test (inside*) put text after rm "/a[2]" = text_rm_shift + +test (< outside >*) put text after rm "/a[2]" = text_rm_noshift + +test (< inside >*) put text after rm "/a[2]" = text_rm_noshift From 131fc067d6e3f4b44e3378511fdae2991ef97910 Mon Sep 17 00:00:00 2001 From: David Lutterkort Date: Thu, 8 Mar 2018 10:46:31 -0800 Subject: [PATCH 2/4] Allow toggling of idempotent/shift behavior via env var AUGEAS_NO_SHIFT --- src/get.c | 82 ++++++++++++------------------------------------------- src/put.c | 34 +++++------------------ 2 files changed, 25 insertions(+), 91 deletions(-) diff --git a/src/get.c b/src/get.c index d9940a2e4..5c04ab1b7 100644 --- a/src/get.c +++ b/src/get.c @@ -914,6 +914,7 @@ static struct tree *get_subtree(struct lens *lens, struct state *state) { tree = make_tree(state->key, state->value, NULL, children); ERR_NOMEM(tree == NULL, state->info); tree->span = move(state->span); + tree->pos = REG_START(state) + 1; if (tree->span != NULL) { update_span(span, tree->span->span_start, tree->span->span_end); @@ -937,43 +938,12 @@ static struct skel *parse_subtree(struct lens *lens, struct state *state, state->key = NULL; skel = parse_lens(lens->child, state, &di); - *dict = make_dict(state->key, skel, di); - state->key = key; - return make_skel(lens); -} - -static struct tree *get_region(struct lens *lens, struct state *state) { - struct span *span = state->span; - - struct tree *tree; - - if (state->info->flags & AUG_ENABLE_SPAN) { - state->span = make_span(state->info); - ERR_NOMEM(state->span == NULL, state->info); - } - - tree = get_lens(lens->child, state); - - tree->span = state->span; - tree->pos = REG_START(state) + 1; - - if (state->span != NULL) { - update_span(span, state->span->span_start, state->span->span_end); + if (getenv("AUGEAS_NO_SHIFT") == NULL) { + *dict = make_dict(state->key, skel, di); + } else { + *dict = make_dictz(REG_START(state) + 1, skel, di); } - - state->span = span; - return tree; - error: - return NULL; -} - -static struct skel *parse_region(struct lens *lens, struct state *state, - struct dict **dict) { - struct skel *skel; - struct dict *di = NULL; - - skel = parse_lens(lens->child, state, &di); - *dict = make_dictz(REG_START(state) + 1, skel, di); + state->key = key; return make_skel(lens); } @@ -1310,14 +1280,19 @@ static void parse_combine(struct rec_state *rec_state, static void visit_exit_put_subtree(struct lens *lens, struct rec_state *rec_state, - struct frame *top) { + struct frame *top, + size_t start) { struct state *state = rec_state->state; struct skel *skel = NULL; struct dict *dict = NULL; skel = make_skel(lens); ERR_NOMEM(skel == NULL, lens->info); - dict = make_dict(top->key, top->skel, top->dict); + if (getenv("AUGEAS_NO_SHIFT") == NULL) { + dict = make_dict(top->key, top->skel, top->dict); + } else { + dict = make_dictz(start, top->skel, top->dict); + } ERR_NOMEM(dict == NULL, lens->info); top = pop_frame(rec_state); @@ -1334,7 +1309,7 @@ static void visit_exit_put_subtree(struct lens *lens, } static void visit_exit(struct lens *lens, - ATTRIBUTE_UNUSED size_t start, + size_t start, ATTRIBUTE_UNUSED size_t end, void *data) { struct rec_state *rec_state = data; @@ -1350,7 +1325,7 @@ static void visit_exit(struct lens *lens, ERR_BAIL(lens->info); - if (lens->tag == L_SUBTREE) { + if (lens->tag == L_SUBTREE || lens->tag == L_REGION) { /* Get the result of parsing lens->child */ struct frame *top = pop_frame(rec_state); ERR_BAIL(state->info); @@ -1371,24 +1346,7 @@ static void visit_exit(struct lens *lens, ERR_BAIL(state->info); top->tree = move(tree); } else { - visit_exit_put_subtree(lens, rec_state, top); - } - } else if (lens->tag == L_REGION) { - if (rec_state->mode == M_PARSE) { - struct frame *top = top_frame(rec_state); - struct skel *skel; - struct dict *dict; - skel = make_skel(lens); - ERR_NOMEM(skel == NULL, lens->info); - dict = make_dictz(start, top->skel, top->dict); - ERR_NOMEM(dict == NULL, lens->info); - top = pop_frame(rec_state); - ensure(lens == top->lens, state->info); - state->key = top->key; - pop_frame(rec_state); - top = push_frame(rec_state, lens); - top->skel = skel; - top->dict = dict; + visit_exit_put_subtree(lens, rec_state, top, start); } } else if (lens->tag == L_CONCAT) { ensure(rec_state->fused >= lens->nchildren, state->info); @@ -1609,10 +1567,8 @@ static struct tree *get_lens(struct lens *lens, struct state *state) { tree = get_union(lens, state); break; case L_SUBTREE: - tree = get_subtree(lens, state); - break; case L_REGION: - tree = get_region(lens, state); + tree = get_subtree(lens, state); break; case L_STAR: tree = get_quant_star(lens, state); @@ -1753,10 +1709,8 @@ static struct skel *parse_lens(struct lens *lens, struct state *state, skel = parse_union(lens, state, dict); break; case L_SUBTREE: - skel = parse_subtree(lens, state, dict); - break; case L_REGION: - skel = parse_region(lens, state,dict); + skel = parse_subtree(lens, state, dict); break; case L_STAR: skel = parse_quant_star(lens, state, dict); diff --git a/src/put.c b/src/put.c index dd26ce64d..48b15ccc5 100644 --- a/src/put.c +++ b/src/put.c @@ -433,7 +433,11 @@ static void put_subtree(struct lens *lens, struct state *state) { split = make_split(tree->children); set_split(state, split); - dict_lookup(tree->label, state->dict, &state->skel, &state->dict); + if (getenv("AUGEAS_NO_SHIFT") == NULL) { + dict_lookup(tree->label, state->dict, &state->skel, &state->dict); + } else { + dict_lookupz(tree->pos, state->dict, &state->skel, &state->dict); + } if (state->with_span) { if (tree->span == NULL) { tree->span = make_span(state->info); @@ -459,22 +463,6 @@ static void put_subtree(struct lens *lens, struct state *state) { state->path = oldpath; } -static void put_region(struct lens *lens, struct state *state) { - assert(lens->tag == L_REGION); - struct skel *oldskel = state->skel; - struct dict *olddict = state->dict; - struct tree *tree = state->split->tree; - - dict_lookupz(tree->pos, state->dict, &state->skel, &state->dict); - if (state->skel == NULL || ! skel_instance_of(lens->child, state->skel)) { - create_lens(lens->child, state); - } else { - put_lens(lens->child, state); - } - state->skel = oldskel; - state->dict = olddict; -} - static void put_del(ATTRIBUTE_UNUSED struct lens *lens, struct state *state) { assert(lens->tag == L_DEL); assert(state->skel != NULL); @@ -684,10 +672,8 @@ static void put_lens(struct lens *lens, struct state *state) { put_union(lens, state); break; case L_SUBTREE: - put_subtree(lens, state); - break; case L_REGION: - put_region(lens, state); + put_subtree(lens, state); break; case L_STAR: put_quant_star(lens, state); @@ -711,10 +697,6 @@ static void create_subtree(struct lens *lens, struct state *state) { put_subtree(lens, state); } -static void create_region(struct lens *lens, struct state *state) { - put_region(lens, state); -} - static void create_del(struct lens *lens, struct state *state) { assert(lens->tag == L_DEL); if (state->override != NULL) { @@ -845,10 +827,8 @@ static void create_lens(struct lens *lens, struct state *state) { create_union(lens, state); break; case L_SUBTREE: - create_subtree(lens, state); - break; case L_REGION: - create_region(lens, state); + create_subtree(lens, state); break; case L_STAR: create_quant_star(lens, state); From a751acae6fd20a6338775f9229bbee281247987f Mon Sep 17 00:00:00 2001 From: David Lutterkort Date: Thu, 8 Mar 2018 10:47:08 -0800 Subject: [PATCH 3/4] Test from domcleal that only succeeds when AUGEAS_NO_SHIFT is set --- lenses/tests/test_inifile.aug | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lenses/tests/test_inifile.aug b/lenses/tests/test_inifile.aug index 873e1fdf7..e8a786d1a 100644 --- a/lenses/tests/test_inifile.aug +++ b/lenses/tests/test_inifile.aug @@ -390,7 +390,19 @@ ticket_243 = \"value1;value2#value3\" # end of line comment { "#comment" = "comment with colon" } { } } - + test IniFile.lns_loose_multiline get multiline_test = { "section" = ".anon" { "test_ace" = "val1\n val2\n val3" } } + +let simpler_lens = (IniFile.empty | IniFile.comment IniFile.comment_re IniFile.comment_default)* + +test simpler_lens put "## Default value: /etc/zypp +## +# configdir = /etc/zypp + +##\n" after rm "/#comment[2]" = + "## Default value: /etc/zypp +# configdir = /etc/zypp + +##\n" From 2b9c87f5927d4b04081f0baf8f130f2f7ca8ee90 Mon Sep 17 00:00:00 2001 From: David Lutterkort Date: Thu, 8 Mar 2018 11:01:02 -0800 Subject: [PATCH 4/4] Remove pass_region test which we do not need anymore --- tests/modules/pass_region.aug | 64 ----------------------------------- 1 file changed, 64 deletions(-) delete mode 100644 tests/modules/pass_region.aug diff --git a/tests/modules/pass_region.aug b/tests/modules/pass_region.aug deleted file mode 100644 index fafdbf4eb..000000000 --- a/tests/modules/pass_region.aug +++ /dev/null @@ -1,64 +0,0 @@ -module Pass_Region = - -(* Some basic lenses that we will combine in a number of ways *) -let eol = del "\n" "\n" -let indent = del /[ _]*/ "_" (* Create spaces as '_' *) -let entry = key /a/ . del "=" "=" . store /[sx]*/ - -(* indent outside the subtree for entry *) -let outside = indent . [ entry ] . eol -(* indent inside the subtree for entry *) -let inside = [ indent . entry ] . eol - -(* The test text is set up so that the number of 's' indicate how many - spaces of indent we had *) -let text = "a=\n a=s\n a=ss\n" - -(* All these lenses produce the exact same tree, with or without < .. > *) -test (outside*) get text = - { "a" = "" } - { "a" = "s" } - { "a" = "ss" } - -test (inside*) get text = - { "a" = "" } - { "a" = "s" } - { "a" = "ss" } - -test (< outside >*) get text = - { "a" = "" } - { "a" = "s" } - { "a" = "ss" } - -test (< inside >*) get text = - { "a" = "" } - { "a" = "s" } - { "a" = "ss" } - -(* They behave slightly differently when we insert in the middle, - depending on whether we use < .. > or not *) -let text_new_middle = "a=\n_a=sx\n a=s\n a=ss\n" -let text_new_end = "a=\n a=sx\n a=s\n_a=ss\n" - -test (outside*) put text after insa "a" "/a[1]"; set "/a[2]" "sx" = - text_new_end - -test (inside*) put text after insa "a" "/a[1]"; set "/a[2]" "sx" = - text_new_end - -test (< outside >*) put text after insa "a" "/a[1]"; set "/a[2]" "sx" = - text_new_middle - -test (< inside >*) put text after insa "a" "/a[1]"; set "/a[2]" "sx" = - text_new_middle - -(* Delete an entry in the middle *) -let text_rm_shift = "a=\n a=ss\n" -let text_rm_noshift = "a=\n a=ss\n" -test (outside*) put text after rm "/a[2]" = text_rm_shift - -test (inside*) put text after rm "/a[2]" = text_rm_shift - -test (< outside >*) put text after rm "/a[2]" = text_rm_noshift - -test (< inside >*) put text after rm "/a[2]" = text_rm_noshift