Skip to content

Commit 4a8bafc

Browse files
committed
Fix an issue of capturing variable substitution
The issue was reported in #92.
1 parent f3ccc2b commit 4a8bafc

File tree

6 files changed

+104
-27
lines changed

6 files changed

+104
-27
lines changed

src/packcc.c

+42-26
Original file line numberDiff line numberDiff line change
@@ -1275,10 +1275,20 @@ static bool_t can_character_follow_identifier_(char ch) {
12751275

12761276
static bool_t stream__write_text(
12771277
stream_t *obj, const char *str, size_t len, bool_t lhead, size_t dedent, size_t indent,
1278-
code_block_kind_t kind, size_t ncapts, const string_array_t *mvars, const subst_map_t *subst
1278+
code_block_kind_t kind, const node_const_array_t *capts, const string_array_t *mvars, const subst_map_t *subst
12791279
) {
12801280
size_t i = 0;
1281+
size_t mc = 0;
12811282
if (len == VOID_VALUE) return lhead; /* for safety */
1283+
if (capts) {
1284+
size_t ic;
1285+
for (ic = 0; ic < capts->n; ic++) {
1286+
size_t kc;
1287+
assert(capts->p[ic]->type == NODE_CAPTURE);
1288+
kc = capts->p[ic]->data.capture.index + 1;
1289+
if (mc < kc) mc = kc;
1290+
}
1291+
}
12821292
while (i < len) {
12831293
if (str[i] == '\0') break;
12841294
if (match_eol(str, i, len, &i)) {
@@ -1324,15 +1334,21 @@ static bool_t stream__write_text(
13241334
c = str[j];
13251335
if (!(c >= '0' && c <= '9')) break;
13261336
k = (c - '0') + 10 * k;
1327-
if (k > ncapts) k = ncapts + 1; /* to avoid overflow */
1337+
if (k > mc) k = mc + 1; /* to avoid overflow */
13281338
j++;
13291339
}
13301340
if (j < len && (str[j] == 's' || str[j] == 'e')) j++;
1331-
if ((j >= len || can_character_follow_identifier_(str[j])) && k <= ncapts) {
1332-
stream__puts(obj, VARNAME_CAPTURE_PREFIX);
1333-
i++;
1334-
while (i < j) stream__putc(obj, str[i++]);
1335-
b = TRUE;
1341+
if (j >= len || can_character_follow_identifier_(str[j])) {
1342+
size_t ic;
1343+
for (ic = 0; ic < capts->n; ic++) {
1344+
if (k == capts->p[ic]->data.capture.index + 1) break;
1345+
}
1346+
if (ic < capts->n) {
1347+
stream__puts(obj, VARNAME_CAPTURE_PREFIX);
1348+
i++;
1349+
while (i < j) stream__putc(obj, str[i++]);
1350+
b = TRUE;
1351+
}
13361352
}
13371353
}
13381354
else if (c == '{') { /* ${...} */
@@ -1475,7 +1491,7 @@ static bool_t stream__write_text(
14751491

14761492
static bool_t stream__write_code(
14771493
stream_t *obj, const char *str, size_t len, bool_t lhead, size_t dedent, size_t indent,
1478-
code_block_kind_t kind, size_t ncapts, const string_array_t *mvars, const subst_map_t *subst, bool_t dircpp
1494+
code_block_kind_t kind, const node_const_array_t *capts, const string_array_t *mvars, const subst_map_t *subst, bool_t dircpp
14791495
) {
14801496
bool_t b = TRUE; /* TRUE if succeeding leading spaces in a line */
14811497
size_t h = 0;
@@ -1486,7 +1502,7 @@ static bool_t stream__write_code(
14861502
if (!dircpp && b && match_directive_c(str, i, len, &k)) {
14871503
{
14881504
const size_t j = find_back_preceding_spaces_in_line(str, i);
1489-
stream__write_text(obj, str + h, j - h, lhead, dedent, indent, kind, ncapts, mvars, subst);
1505+
stream__write_text(obj, str + h, j - h, lhead, dedent, indent, kind, capts, mvars, subst);
14901506
}
14911507
{
14921508
size_t md = VOID_VALUE; /* the minimum indent length of the successive lines */
@@ -1502,29 +1518,29 @@ static bool_t stream__write_code(
15021518
}
15031519
}
15041520
if (md == VOID_VALUE) md = 0;
1505-
lhead = stream__write_code(obj, str + i, k - i, FALSE, md, INDENT_UNIT, kind, ncapts, mvars, subst, TRUE);
1521+
lhead = stream__write_code(obj, str + i, k - i, FALSE, md, INDENT_UNIT, kind, capts, mvars, subst, TRUE);
15061522
}
15071523
h = i = k;
15081524
/* b == TRUE */
15091525
}
15101526
else if (match_comment_cxx(str, i, len, &k)) {
1511-
lhead = stream__write_text(obj, str + h, i - h, lhead, dedent, indent, kind, ncapts, mvars, subst);
1512-
lhead = stream__write_text(obj, str + i, k - i, lhead, dedent, indent, CODE_BLOCK_KIND__NONE, ncapts, mvars, subst);
1527+
lhead = stream__write_text(obj, str + h, i - h, lhead, dedent, indent, kind, capts, mvars, subst);
1528+
lhead = stream__write_text(obj, str + i, k - i, lhead, dedent, indent, CODE_BLOCK_KIND__NONE, capts, mvars, subst);
15131529
h = i = k;
15141530
b = TRUE;
15151531
}
15161532
else if (match_comment_c(str, i, len, &k)) {
1517-
lhead = stream__write_text(obj, str + h, i - h, lhead, dedent, indent, kind, ncapts, mvars, subst);
1518-
lhead = stream__write_text(obj, str + i, k - i, lhead, dedent, indent, CODE_BLOCK_KIND__NONE, ncapts, mvars, subst);
1533+
lhead = stream__write_text(obj, str + h, i - h, lhead, dedent, indent, kind, capts, mvars, subst);
1534+
lhead = stream__write_text(obj, str + i, k - i, lhead, dedent, indent, CODE_BLOCK_KIND__NONE, capts, mvars, subst);
15191535
h = i = k;
15201536
/* do not change `b` because a C-style comment is dealt as a white space */
15211537
}
15221538
else if (
15231539
match_quotation(str, i, len, '\'', &k) ||
15241540
match_quotation(str, i, len, '\"', &k)
15251541
) {
1526-
lhead = stream__write_text(obj, str + h, i - h, lhead, dedent, indent, kind, ncapts, mvars, subst);
1527-
lhead = stream__write_text(obj, str + i, k - i, lhead, dedent, indent, CODE_BLOCK_KIND__NONE, ncapts, mvars, subst);
1542+
lhead = stream__write_text(obj, str + h, i - h, lhead, dedent, indent, kind, capts, mvars, subst);
1543+
lhead = stream__write_text(obj, str + i, k - i, lhead, dedent, indent, CODE_BLOCK_KIND__NONE, capts, mvars, subst);
15281544
h = i = k;
15291545
b = FALSE;
15301546
}
@@ -1538,12 +1554,12 @@ static bool_t stream__write_code(
15381554
}
15391555
}
15401556
}
1541-
return stream__write_text(obj, str + h, i - h, lhead, dedent, indent, kind, ncapts, mvars, subst);
1557+
return stream__write_text(obj, str + h, i - h, lhead, dedent, indent, kind, capts, mvars, subst);
15421558
}
15431559

15441560
static void stream__write_code_block(
15451561
stream_t *obj, const char *str, size_t len, size_t indent, const char *path, size_t lineno,
1546-
code_block_kind_t kind, size_t ncapts, const string_array_t *mvars, const subst_map_t *subst
1562+
code_block_kind_t kind, const node_const_array_t *capts, const string_array_t *mvars, const subst_map_t *subst
15471563
) {
15481564
size_t m = VOID_VALUE; /* the minimum indent length except for the start line of the code block */
15491565
size_t b = TRUE; /* TRUE if the code starts at the first line */
@@ -1584,7 +1600,7 @@ static void stream__write_code_block(
15841600
assert(b || d >= m);
15851601
stream__write_characters(obj, ' ', indent + (b ? 0 : d - m));
15861602
}
1587-
stream__write_code(obj, str + h, len - h, FALSE, m, indent, kind, ncapts, mvars, subst, FALSE);
1603+
stream__write_code(obj, str + h, len - h, FALSE, m, indent, kind, capts, mvars, subst, FALSE);
15881604
stream__putc(obj, '\n');
15891605
if (obj->line != VOID_VALUE)
15901606
stream__write_line_directive(obj, obj->path, obj->line + 1);
@@ -1593,7 +1609,7 @@ static void stream__write_code_block(
15931609
static void stream__write_footer(
15941610
stream_t *obj, const char *str, size_t len, const char *path, size_t lineno, const subst_map_t *subst
15951611
) {
1596-
stream__write_code_block(obj, str, len, 0, path, lineno, CODE_BLOCK_KIND__NORMAL, 0, NULL, subst);
1612+
stream__write_code_block(obj, str, len, 0, path, lineno, CODE_BLOCK_KIND__NORMAL, NULL, NULL, subst);
15971613
}
15981614

15991615
static char *get_home_directory(void) {
@@ -4590,7 +4606,7 @@ static bool_t generate(context_t *ctx) {
45904606
for (i = 0; i < ctx->eheader.n; i++) {
45914607
stream__write_code_block(
45924608
&hstream, ctx->eheader.p[i].text, ctx->eheader.p[i].len, 0,
4593-
ctx->eheader.p[i].fpos.path, ctx->eheader.p[i].fpos.line, CODE_BLOCK_KIND__NORMAL, 0, NULL, &(ctx->subst)
4609+
ctx->eheader.p[i].fpos.path, ctx->eheader.p[i].fpos.line, CODE_BLOCK_KIND__NORMAL, NULL, NULL, &(ctx->subst)
45944610
);
45954611
stream__puts(&hstream, "\n");
45964612
}
@@ -4607,7 +4623,7 @@ static bool_t generate(context_t *ctx) {
46074623
for (i = 0; i < ctx->header.n; i++) {
46084624
stream__write_code_block(
46094625
&hstream, ctx->header.p[i].text, ctx->header.p[i].len, 0,
4610-
ctx->header.p[i].fpos.path, ctx->header.p[i].fpos.line, CODE_BLOCK_KIND__NORMAL, 0, NULL, &(ctx->subst)
4626+
ctx->header.p[i].fpos.path, ctx->header.p[i].fpos.line, CODE_BLOCK_KIND__NORMAL, NULL, NULL, &(ctx->subst)
46114627
);
46124628
stream__puts(&hstream, "\n");
46134629
}
@@ -4619,7 +4635,7 @@ static bool_t generate(context_t *ctx) {
46194635
for (i = 0; i < ctx->esource.n; i++) {
46204636
stream__write_code_block(
46214637
&sstream, ctx->esource.p[i].text, ctx->esource.p[i].len, 0,
4622-
ctx->esource.p[i].fpos.path, ctx->esource.p[i].fpos.line, CODE_BLOCK_KIND__NORMAL, 0, NULL, &(ctx->subst)
4638+
ctx->esource.p[i].fpos.path, ctx->esource.p[i].fpos.line, CODE_BLOCK_KIND__NORMAL, NULL, NULL, &(ctx->subst)
46234639
);
46244640
stream__puts(&sstream, "\n");
46254641
}
@@ -4667,7 +4683,7 @@ static bool_t generate(context_t *ctx) {
46674683
for (i = 0; i < ctx->source.n; i++) {
46684684
stream__write_code_block(
46694685
&sstream, ctx->source.p[i].text, ctx->source.p[i].len, 0,
4670-
ctx->source.p[i].fpos.path, ctx->source.p[i].fpos.line, CODE_BLOCK_KIND__NORMAL, 0, NULL, &(ctx->subst)
4686+
ctx->source.p[i].fpos.path, ctx->source.p[i].fpos.line, CODE_BLOCK_KIND__NORMAL, NULL, NULL, &(ctx->subst)
46714687
);
46724688
stream__puts(&sstream, "\n");
46734689
}
@@ -6423,7 +6439,7 @@ static bool_t generate(context_t *ctx) {
64236439
}
64246440
stream__write_code_block(
64256441
&sstream, b->text, b->len, INDENT_UNIT, b->fpos.path, b->fpos.line,
6426-
CODE_BLOCK_KIND__PROGPRED, c->n, &(ctx->mvars), &(ctx->subst)
6442+
CODE_BLOCK_KIND__PROGPRED, c, &(ctx->mvars), &(ctx->subst)
64276443
);
64286444
k = c->n;
64296445
while (k > 0) {
@@ -6537,7 +6553,7 @@ static bool_t generate(context_t *ctx) {
65376553
}
65386554
stream__write_code_block(
65396555
&sstream, b->text, b->len, INDENT_UNIT, b->fpos.path, b->fpos.line,
6540-
CODE_BLOCK_KIND__ACTION, c->n, &(ctx->mvars), &(ctx->subst)
6556+
CODE_BLOCK_KIND__ACTION, c, &(ctx->mvars), &(ctx->subst)
65416557
);
65426558
k = c->n;
65436559
while (k > 0) {

tests/captures.d/expected.txt

+4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
predicate $6 = 132,137:capt6
2+
predicate $8 = 138,143:capt8
13
0,11:capture all
24
12,19:capture
35
34,40:second
46
59,64:words
57
83,92:something
68
93,97:more 98,106:captures
79
116,121:again
10+
action $6 = 132,137:capt6
11+
action $8 = 138,143:capt8

tests/captures.d/input.peg

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
FILE <- (LINE '\n')*
2-
LINE <- ALL / FIRST / SECOND / MULTI1 / MULTI2 / MORE / CAPTURED / UNKNOWN
2+
LINE <- ALL / FIRST / SECOND / MULTI1 / MULTI2 / MORE / CAPTURED / ALTERNATE / UNKNOWN
33

44
ALL <- <'capture' _ 'all'> { printf("%d,%d:%s\n", (int)$1s, (int)$1e, $1); }
55
FIRST <- <'capture'> _ 'first' { printf("%d,%d:%s\n", (int)$1s, (int)$1e, $1); }
@@ -8,6 +8,16 @@ MULTI1 <- 'capture' _ 'multiple1' (_ <[a-z]+>)+ { printf("%d,%d:%s\n", (int)$1s,
88
MULTI2 <- 'capture' _ 'multiple2' (_ <[a-z]+> { printf("%d,%d:%s\n", (int)$1s, (int)$1e, $1); })+
99
MORE <- <'more'> _ <'captures'> { printf("%d,%d:%s %d,%d:%s\n", (int)$1s, (int)$1e, $1, (int)$2s, (int)$2e, $2); }
1010
CAPTURED <- "captured" _ <[a-z]+> _ 'and' _ $1 { printf("%d,%d:%s\n", (int)$1s, (int)$1e, $1); }
11+
ALTERNATE <- < 'capt1' > / ( < 'capt2' > _ ( < 'capt3' > / < 'capt4' > ) _ < 'capt5' > / < 'capt6' > _ ( < 'capt7' > / < 'capt8' >
12+
&{
13+
printf("predicate $6 = %d,%d:%s\n", (int)$6s, (int)$6e, $6 ? $6 : "(null)");
14+
printf("predicate $8 = %d,%d:%s\n", (int)$8s, (int)$8e, $8 ? $8 : "(null)");
15+
}
16+
{
17+
printf("action $6 = %d,%d:%s\n", (int)$6s, (int)$6e, $6 ? $6 : "(null)");
18+
printf("action $8 = %d,%d:%s\n", (int)$8s, (int)$8e, $8 ? $8 : "(null)");
19+
}
20+
) _ < 'capt9' > )
1121

1222
UNKNOWN <- [^\n]+ { printf("ERROR: %s\n", $0); }
1323
_ <- " "

tests/captures.d/input.txt

+1
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ capture multiple1 words
55
capture multiple2 something
66
more captures
77
captured again and again
8+
capt6 capt8 capt9

tests/substitution.d/expected.c.txt

+20
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,16 @@ TEST COMMON @var.restore() " @var.restore() " /* @var.restore()
197197
TEST PROGPRED5 $123 " $123 " /* $123 */
198198
TEST PROGPRED6 $123s " $123s " /* $123s */
199199
TEST PROGPRED7 $123e " $123e " /* $123e */
200+
TEST PROGPRED8 pcc_capture__0s:pcc_capture__0e=pcc_capture__0 " $0s:$0e=$0 " /* $0s:$0e=$0 */
201+
TEST PROGPRED8 $1s:$1e=$1 " $1s:$1e=$1 " /* $1s:$1e=$1 */
202+
TEST PROGPRED8 $2s:$2e=$2 " $2s:$2e=$2 " /* $2s:$2e=$2 */
203+
TEST PROGPRED8 $3s:$3e=$3 " $3s:$3e=$3 " /* $3s:$3e=$3 */
204+
TEST PROGPRED8 $4s:$4e=$4 " $4s:$4e=$4 " /* $4s:$4e=$4 */
205+
TEST PROGPRED8 $5s:$5e=$5 " $5s:$5e=$5 " /* $5s:$5e=$5 */
206+
TEST PROGPRED8 pcc_capture__6s:pcc_capture__6e=pcc_capture__6 " $6s:$6e=$6 " /* $6s:$6e=$6 */
207+
TEST PROGPRED8 $7s:$7e=$7 " $7s:$7e=$7 " /* $7s:$7e=$7 */
208+
TEST PROGPRED8 pcc_capture__8s:pcc_capture__8e=pcc_capture__8 " $8s:$8e=$8 " /* $8s:$8e=$8 */
209+
TEST PROGPRED8 $9s:$9e=$9 " $9s:$9e=$9 " /* $9s:$9e=$9 */
200210
TEST ACTION0 pcc_action_out. " $$. " /* $$. */ // $$.
201211
TEST ACTION0 $pcc_action_out " $$$ " /* $$$ */ // $$$
202212
TEST ACTION0 $pcc_capture__0 " $$0 " /* $$0 */ // $$0
@@ -272,6 +282,16 @@ TEST COMMON @var.restore() " @var.restore() " /* @var.restore()
272282
TEST ACTION5 $123 " $123 " /* $123 */
273283
TEST ACTION6 $123s " $123s " /* $123s */
274284
TEST ACTION7 $123e " $123e " /* $123e */
285+
TEST ACTION8 pcc_capture__0s:pcc_capture__0e=pcc_capture__0 " $0s:$0e=$0 " /* $0s:$0e=$0 */
286+
TEST ACTION8 $1s:$1e=$1 " $1s:$1e=$1 " /* $1s:$1e=$1 */
287+
TEST ACTION8 $2s:$2e=$2 " $2s:$2e=$2 " /* $2s:$2e=$2 */
288+
TEST ACTION8 $3s:$3e=$3 " $3s:$3e=$3 " /* $3s:$3e=$3 */
289+
TEST ACTION8 $4s:$4e=$4 " $4s:$4e=$4 " /* $4s:$4e=$4 */
290+
TEST ACTION8 $5s:$5e=$5 " $5s:$5e=$5 " /* $5s:$5e=$5 */
291+
TEST ACTION8 pcc_capture__6s:pcc_capture__6e=pcc_capture__6 " $6s:$6e=$6 " /* $6s:$6e=$6 */
292+
TEST ACTION8 $7s:$7e=$7 " $7s:$7e=$7 " /* $7s:$7e=$7 */
293+
TEST ACTION8 pcc_capture__8s:pcc_capture__8e=pcc_capture__8 " $8s:$8e=$8 " /* $8s:$8e=$8 */
294+
TEST ACTION8 $9s:$9e=$9 " $9s:$9e=$9 " /* $9s:$9e=$9 */
275295
TEST FOOTER $$ " $$ " /* $$ */ // $$
276296
TEST FOOTER $0 " $0 " /* $0 */ // $0
277297
TEST FOOTER $0s " $0s " /* $0s */ // $0s

tests/substitution.d/input.peg

+26
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,32 @@ FILE
360360
/ '123' &{ TEST PROGPRED5 $123 " $123 " /* $123 */ } { TEST ACTION5 $123 " $123 " /* $123 */ }
361361
/ '123s' &{ TEST PROGPRED6 $123s " $123s " /* $123s */ } { TEST ACTION6 $123s " $123s " /* $123s */ }
362362
/ '123e' &{ TEST PROGPRED7 $123e " $123e " /* $123e */ } { TEST ACTION7 $123e " $123e " /* $123e */ }
363+
/ ( < 'capt2' > ( < 'capt3' > / < 'capt4' > ) < 'capt5' > / < 'capt6' > ( < 'capt7' > / < 'capt8' >
364+
&{
365+
TEST PROGPRED8 $0s:$0e=$0 " $0s:$0e=$0 " /* $0s:$0e=$0 */
366+
TEST PROGPRED8 $1s:$1e=$1 " $1s:$1e=$1 " /* $1s:$1e=$1 */
367+
TEST PROGPRED8 $2s:$2e=$2 " $2s:$2e=$2 " /* $2s:$2e=$2 */
368+
TEST PROGPRED8 $3s:$3e=$3 " $3s:$3e=$3 " /* $3s:$3e=$3 */
369+
TEST PROGPRED8 $4s:$4e=$4 " $4s:$4e=$4 " /* $4s:$4e=$4 */
370+
TEST PROGPRED8 $5s:$5e=$5 " $5s:$5e=$5 " /* $5s:$5e=$5 */
371+
TEST PROGPRED8 $6s:$6e=$6 " $6s:$6e=$6 " /* $6s:$6e=$6 */
372+
TEST PROGPRED8 $7s:$7e=$7 " $7s:$7e=$7 " /* $7s:$7e=$7 */
373+
TEST PROGPRED8 $8s:$8e=$8 " $8s:$8e=$8 " /* $8s:$8e=$8 */
374+
TEST PROGPRED8 $9s:$9e=$9 " $9s:$9e=$9 " /* $9s:$9e=$9 */
375+
}
376+
{
377+
TEST ACTION8 $0s:$0e=$0 " $0s:$0e=$0 " /* $0s:$0e=$0 */
378+
TEST ACTION8 $1s:$1e=$1 " $1s:$1e=$1 " /* $1s:$1e=$1 */
379+
TEST ACTION8 $2s:$2e=$2 " $2s:$2e=$2 " /* $2s:$2e=$2 */
380+
TEST ACTION8 $3s:$3e=$3 " $3s:$3e=$3 " /* $3s:$3e=$3 */
381+
TEST ACTION8 $4s:$4e=$4 " $4s:$4e=$4 " /* $4s:$4e=$4 */
382+
TEST ACTION8 $5s:$5e=$5 " $5s:$5e=$5 " /* $5s:$5e=$5 */
383+
TEST ACTION8 $6s:$6e=$6 " $6s:$6e=$6 " /* $6s:$6e=$6 */
384+
TEST ACTION8 $7s:$7e=$7 " $7s:$7e=$7 " /* $7s:$7e=$7 */
385+
TEST ACTION8 $8s:$8e=$8 " $8s:$8e=$8 " /* $8s:$8e=$8 */
386+
TEST ACTION8 $9s:$9e=$9 " $9s:$9e=$9 " /* $9s:$9e=$9 */
387+
}
388+
) < 'capt9' > )
363389

364390
%%
365391

0 commit comments

Comments
 (0)