Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
magicant committed Dec 9, 2024
1 parent 6bb4452 commit ffdcae4
Showing 1 changed file with 36 additions and 26 deletions.
62 changes: 36 additions & 26 deletions expand.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,8 @@ static void add_empty_field(plist_T *dest, const wchar_t *p)
static inline void add_sq(
const wchar_t *restrict *ss, xwcsbuf_T *restrict buf, bool escape)
__attribute__((nonnull));
static void add_dsq(const wchar_t *restrict *ss, xwcsbuf_T *restrict buf)
__attribute__((nonnull));
static wchar_t *interpret_dsq(const wchar_t *restrict *ss)
__attribute__((nonnull,malloc,warn_unused_result));
static inline bool should_escape(charcategory_T cc, escaping_T escaping)
__attribute__((const));
static wchar_t *quote_removal_free(
Expand Down Expand Up @@ -487,7 +487,7 @@ struct expand_four_T expand_four(const wordunit_T *restrict w,
sb_ccat(&ccbuf, defaultcc | CC_QUOTATION);
sb_ccat(&ccbuf, defaultcc | CC_QUOTATION);

add_dsq(&ss, &valuebuf);
wb_catfree(&valuebuf, interpret_dsq(&ss));
assert(*ss == L'\'');
fill_ccbuf(&valuebuf, &ccbuf, defaultcc | CC_QUOTED);

Expand Down Expand Up @@ -1721,16 +1721,26 @@ void add_sq(const wchar_t *restrict *ss, xwcsbuf_T *restrict buf, bool escape)
}
}

/* Expands the content of a dollar-single-quoted string to a buffer.
/* Expands the content of a dollar-single-quoted string to a newly-malloced
* string.
* `ss' is a pointer to a pointer to the string to be expanded. Initially,
* `(*ss)[0]' and `(*ss)[1]' must be '$' and '\'', respectively, which are
* skipped in this function. The following characters in the string are appended
* to `buf', interpreting any backslash escapes encountered, until a closing
* '\'' is found (or the end of the string is reached). When this function
* returns, `*ss' is updated so that `**ss' is the closing quote or terminating
* null character. */
void add_dsq(const wchar_t *restrict *ss, xwcsbuf_T *restrict buf)
* skipped in this function. The following characters in the string are
* accumulated in the string to be returned, interpreting any backslash escapes
* encountered, until a closing '\'' is found (or the end of the string is
* reached). When this function returns, `*ss' is updated so that `**ss' is the
* closing quote or terminating null character. */
/* If an escape contained in `*ss' produces a null character, the rest of the
* string is ignored by the caller. This is one of the behaviors allowed by
* POSIX. This function could have been designed to take an `xwcsbuf_T *'
* argument and append the result directly to it, but that would not be
* compliant because the null character would also hide the characters after the
* closing quote. */
wchar_t *interpret_dsq(const wchar_t *restrict *ss)
{
xwcsbuf_T buf;
wb_init(&buf);

const wchar_t *s = *ss;
assert(s[0] == '$');
assert(s[1] == '\'');
Expand All @@ -1741,24 +1751,24 @@ void add_dsq(const wchar_t *restrict *ss, xwcsbuf_T *restrict buf)
case L'\0':
case L'\'':
*ss = s;
return;
return wb_towcs(&buf);
case L'\\':
s++;
switch (*s) {
case L'"':
case L'\'':
case L'\\':
wb_wccat(buf, *s);
wb_wccat(&buf, *s);
s++;
break;
case L'a': wb_wccat(buf, L'\a'); s++; break;
case L'b': wb_wccat(buf, L'\b'); s++; break;
case L'e': wb_wccat(buf, L'\033'); s++; break;
case L'f': wb_wccat(buf, L'\f'); s++; break;
case L'n': wb_wccat(buf, L'\n'); s++; break;
case L'r': wb_wccat(buf, L'\r'); s++; break;
case L't': wb_wccat(buf, L'\t'); s++; break;
case L'v': wb_wccat(buf, L'\v'); s++; break;
case L'a': wb_wccat(&buf, L'\a'); s++; break;
case L'b': wb_wccat(&buf, L'\b'); s++; break;
case L'e': wb_wccat(&buf, L'\033'); s++; break;
case L'f': wb_wccat(&buf, L'\f'); s++; break;
case L'n': wb_wccat(&buf, L'\n'); s++; break;
case L'r': wb_wccat(&buf, L'\r'); s++; break;
case L't': wb_wccat(&buf, L'\t'); s++; break;
case L'v': wb_wccat(&buf, L'\v'); s++; break;
case L'c':
s++;
wchar_t c;
Expand All @@ -1775,7 +1785,7 @@ void add_dsq(const wchar_t *restrict *ss, xwcsbuf_T *restrict buf)
} else { // Oops, unknown escape!
c = L'?';
}
wb_wccat(buf, c);
wb_wccat(&buf, c);
s++;
break;
case L'x':
Expand All @@ -1788,7 +1798,7 @@ void add_dsq(const wchar_t *restrict *ss, xwcsbuf_T *restrict buf)
} else if (L'a' <= *s && *s <= L'f') {
value = *s - L'a' + 0xA;
} else { // Oops, missing digit
wb_wccat(buf, L'?');
wb_wccat(&buf, L'?');
break;
}
s++;
Expand All @@ -1802,22 +1812,22 @@ void add_dsq(const wchar_t *restrict *ss, xwcsbuf_T *restrict buf)
goto only_one_xdigit;
s++;
only_one_xdigit:
wb_wccat(buf, (wchar_t) value);
wb_wccat(&buf, (wchar_t) value);
break;
default:;
int count = 0;
value = 0;
while (count < 3 && L'0' <= *s && *s <= L'7')
value = (value << 3) | (*s - L'0'), s++, count++;
if (count > 0 && (value & ~0xFF) == 0)
wb_wccat(buf, (wchar_t) value);
wb_wccat(&buf, (wchar_t) value);
else
wb_wccat(buf, L'?');
wb_wccat(&buf, L'?');
break;
}
break;
default:
wb_wccat(buf, *s);
wb_wccat(&buf, *s);
s++;
break;
}
Expand Down

0 comments on commit ffdcae4

Please sign in to comment.