Unverified Commit 7e116b5e authored by Yukihiro "Matz" Matsumoto's avatar Yukihiro "Matz" Matsumoto Committed by GitHub

Merge pull request #5260 from SeekingMeaning/squiggly-fix-5

Fix line continuations with mixed indentation in squiggly heredocs
parents 5e752caf d52c82d6
...@@ -4626,9 +4626,9 @@ read_escape(parser_state *p) ...@@ -4626,9 +4626,9 @@ read_escape(parser_state *p)
} }
static void static void
heredoc_count_indent(parser_heredoc_info *hinf, const char *str, size_t len, size_t *indent, size_t *offset) heredoc_count_indent(parser_heredoc_info *hinf, const char *str, size_t len, size_t spaces, size_t *offset)
{ {
*indent = 0; size_t indent = 0;
*offset = 0; *offset = 0;
for (size_t i = 0; i < len; i++) { for (size_t i = 0; i < len; i++) {
size_t size; size_t size;
...@@ -4640,9 +4640,10 @@ heredoc_count_indent(parser_heredoc_info *hinf, const char *str, size_t len, siz ...@@ -4640,9 +4640,10 @@ heredoc_count_indent(parser_heredoc_info *hinf, const char *str, size_t len, siz
size = 1; size = 1;
else else
break; break;
if (*indent + size > hinf->indent) size_t nindent = indent + size;
if (nindent > spaces || nindent > hinf->indent)
break; break;
*indent += size; indent = nindent;
*offset += 1; *offset += 1;
} }
} }
...@@ -4650,61 +4651,42 @@ heredoc_count_indent(parser_heredoc_info *hinf, const char *str, size_t len, siz ...@@ -4650,61 +4651,42 @@ heredoc_count_indent(parser_heredoc_info *hinf, const char *str, size_t len, siz
static void static void
heredoc_remove_indent(parser_state *p, parser_heredoc_info *hinf) heredoc_remove_indent(parser_state *p, parser_heredoc_info *hinf)
{ {
if (!hinf->remove_indent) if (!hinf->remove_indent || hinf->indent == 0)
return; return;
node *indented, *n, *pair, *escaped; node *indented, *n, *pair, *escaped, *nspaces;
const char *str; const char *str;
size_t len, indent, offset, start, end; size_t len, spaces, offset, start, end;
indented = hinf->indented; indented = hinf->indented;
while (indented) { while (indented) {
n = indented->car; n = indented->car;
pair = n->car; pair = n->car;
str = (char*)pair->car; str = (char*)pair->car;
len = (size_t)pair->cdr; len = (size_t)pair->cdr;
escaped = n->cdr; escaped = n->cdr->car;
if (escaped) { nspaces = n->cdr->cdr;
start = 0;
while (start < len) {
end = escaped ? (size_t)escaped->car : len;
heredoc_count_indent(hinf, str + start, end - start, &indent, &offset);
if (indent < hinf->indent)
hinf->indent = indent;
start = end;
if (escaped)
escaped = escaped->cdr;
}
}
indented = indented->cdr;
}
if (hinf->indent == 0)
return;
indented = hinf->indented;
while (indented) {
n = indented->car;
pair = n->car;
str = (char*)pair->car;
len = (size_t)pair->cdr;
escaped = n->cdr;
if (escaped) { if (escaped) {
char *newstr = strndup(str, len); char *newstr = strndup(str, len);
size_t newlen = 0; size_t newlen = 0;
start = 0; start = 0;
while (start < len) { while (start < len) {
end = escaped ? (size_t)escaped->car : len; end = escaped ? (size_t)escaped->car : len;
spaces = (size_t)nspaces->car;
size_t esclen = end - start; size_t esclen = end - start;
heredoc_count_indent(hinf, str + start, esclen, &indent, &offset); heredoc_count_indent(hinf, str + start, esclen, spaces, &offset);
esclen -= offset; esclen -= offset;
memcpy(newstr + newlen, str + start + offset, esclen); memcpy(newstr + newlen, str + start + offset, esclen);
newlen += esclen; newlen += esclen;
start = end; start = end;
if (escaped) if (escaped)
escaped = escaped->cdr; escaped = escaped->cdr;
nspaces = nspaces->cdr;
} }
newstr[newlen] = '\0'; newstr[newlen] = '\0';
pair->car = (node*)newstr; pair->car = (node*)newstr;
pair->cdr = (node*)newlen; pair->cdr = (node*)newlen;
} else { } else {
heredoc_count_indent(hinf, str, len, &indent, &offset); spaces = (size_t)nspaces->car;
heredoc_count_indent(hinf, str, len, spaces, &offset);
pair->car = (node*)(str + offset); pair->car = (node*)(str + offset);
pair->cdr = (node*)(len - offset); pair->cdr = (node*)(len - offset);
} }
...@@ -4712,6 +4694,18 @@ heredoc_remove_indent(parser_state *p, parser_heredoc_info *hinf) ...@@ -4712,6 +4694,18 @@ heredoc_remove_indent(parser_state *p, parser_heredoc_info *hinf)
} }
} }
static void
heredoc_push_indented(parser_state *p, parser_heredoc_info *hinf, node *pair, node *escaped, node *nspaces, mrb_bool empty_line)
{
hinf->indented = push(hinf->indented, cons(pair, cons(escaped, nspaces)));
while (nspaces) {
size_t tspaces = (size_t)nspaces->car;
if ((hinf->indent == ~0U || tspaces < hinf->indent) && !empty_line)
hinf->indent = tspaces;
nspaces = nspaces->cdr;
}
}
static int static int
parse_string(parser_state *p) parse_string(parser_state *p)
{ {
...@@ -4728,6 +4722,7 @@ parse_string(parser_state *p) ...@@ -4728,6 +4722,7 @@ parse_string(parser_state *p)
size_t spaces = 0; size_t spaces = 0;
size_t pos = -1; size_t pos = -1;
node *escaped = NULL; node *escaped = NULL;
node *nspaces = NULL;
if (beg == 0) beg = -3; /* should never happen */ if (beg == 0) beg = -3; /* should never happen */
if (end == 0) end = -3; if (end == 0) end = -3;
...@@ -4775,13 +4770,12 @@ parse_string(parser_state *p) ...@@ -4775,13 +4770,12 @@ parse_string(parser_state *p)
node *nd = new_str(p, tok(p), toklen(p)); node *nd = new_str(p, tok(p), toklen(p));
pylval.nd = nd; pylval.nd = nd;
if (unindent && head) { if (unindent && head) {
hinf->indented = push(hinf->indented, cons(nd->cdr, escaped)); nspaces = push(nspaces, (node*)spaces);
if ((hinf->indent == ~0U || spaces < hinf->indent) && (!empty || !line_head)) heredoc_push_indented(p, hinf, nd->cdr, escaped, nspaces, empty && line_head);
hinf->indent = spaces;
} }
return tHD_STRING_MID; return tHD_STRING_MID;
} }
if (unindent && head && empty) { if (unindent && empty) {
if (c == '\t') if (c == '\t')
spaces += 8; spaces += 8;
else if (ISSPACE(c)) else if (ISSPACE(c))
...@@ -4811,8 +4805,11 @@ parse_string(parser_state *p) ...@@ -4811,8 +4805,11 @@ parse_string(parser_state *p)
p->lineno++; p->lineno++;
p->column = 0; p->column = 0;
if (unindent) { if (unindent) {
nspaces = push(nspaces, (node*)spaces);
escaped = push(escaped, (node*)pos); escaped = push(escaped, (node*)pos);
pos--; pos--;
empty = TRUE;
spaces = 0;
} }
if (type & STR_FUNC_ARRAY) { if (type & STR_FUNC_ARRAY) {
tokadd(p, '\n'); tokadd(p, '\n');
...@@ -4867,9 +4864,8 @@ parse_string(parser_state *p) ...@@ -4867,9 +4864,8 @@ parse_string(parser_state *p)
pylval.nd = nd; pylval.nd = nd;
if (hinf) { if (hinf) {
if (unindent && head) { if (unindent && head) {
hinf->indented = push(hinf->indented, cons(nd->cdr, escaped)); nspaces = push(nspaces, (node*)spaces);
if (hinf->indent == ~0U || spaces < hinf->indent) heredoc_push_indented(p, hinf, nd->cdr, escaped, nspaces, FALSE);
hinf->indent = spaces;
} }
hinf->line_head = FALSE; hinf->line_head = FALSE;
return tHD_STRING_PART; return tHD_STRING_PART;
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment