-/* $Id: roff.c,v 1.389 2022/05/30 23:03:47 schwarze Exp $ */
+/* $Id: roff.c,v 1.394 2022/06/07 09:41:59 schwarze Exp $ */
/*
* Copyright (c) 2010-2015, 2017-2022 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
int iarg; /* index beginning the argument */
int iendarg; /* index right after the argument */
int iend; /* index right after the sequence */
+ int isrc, idst; /* to reduce \\ and \. in names */
int deftype; /* type of definition to paste */
int argi; /* macro argument index */
int quote_args; /* true for \\$@, false for \\$* */
* it to backslashes and translate backslashes to \e.
*/
- if (roff_escape(buf->buf, ln, pos,
- &iesc, &iarg, &iendarg, &iend) != ESCAPE_EXPAND) {
+ if (roff_escape(buf->buf, ln, pos, &iesc, &inam,
+ &iarg, &iendarg, &iend) != ESCAPE_EXPAND) {
while (pos < iend) {
if (buf->buf[pos] == ec) {
buf->buf[pos] = '\\';
continue;
}
- /*
- * Treat "\E" just like "\";
- * it only makes a difference in copy mode.
- */
-
- inam = iesc + 1;
- while (buf->buf[inam] == 'E')
- inam++;
+ /* Reduce \\ and \. in names. */
+
+ if (buf->buf[inam] == '*' || buf->buf[inam] == 'n') {
+ isrc = idst = iarg;
+ while (isrc < iendarg) {
+ if (isrc + 1 < iendarg &&
+ buf->buf[isrc] == '\\' &&
+ (buf->buf[isrc + 1] == '\\' ||
+ buf->buf[isrc + 1] == '.'))
+ isrc++;
+ buf->buf[idst++] = buf->buf[isrc++];
+ }
+ iendarg -= isrc - idst;
+ }
/* Handle expansion. */
*dst++ = '"';
}
continue;
+ case 'A':
+ ubuf[0] = iendarg > iarg ? '1' : '0';
+ ubuf[1] = '\0';
+ res = ubuf;
+ break;
case 'B':
npos = 0;
ubuf[0] = iendarg > iarg && iend > iendarg &&
roff_expand_patch(buf, iendarg, "}", iend);
roff_expand_patch(buf, iesc, "${", iarg);
continue;
+ case 'g':
+ break;
case 'n':
if (iendarg > iarg)
(void)snprintf(ubuf, sizeof(ubuf), "%d",
{
const char *p, *first, *second;
size_t fsz, ssz;
- enum mandoc_esc esc;
p = buf->buf + pos;
first = p++;
if (*first == '\\') {
- esc = mandoc_escape(&p, NULL, NULL);
- if (esc == ESCAPE_ERROR) {
- mandoc_msg(MANDOCERR_ESC_BAD, ln,
- (int)(p - buf->buf), "%s", first);
+ if (mandoc_escape(&p, NULL, NULL) == ESCAPE_ERROR)
return ROFF_IGN;
- }
fsz = (size_t)(p - first);
}
second = p++;
if (*second == '\\') {
- esc = mandoc_escape(&p, NULL, NULL);
- if (esc == ESCAPE_ERROR) {
- mandoc_msg(MANDOCERR_ESC_BAD, ln,
- (int)(p - buf->buf), "%s", second);
+ if (mandoc_escape(&p, NULL, NULL) == ESCAPE_ERROR)
return ROFF_IGN;
- }
ssz = (size_t)(p - second);
} else if (*second == '\0') {
mandoc_msg(MANDOCERR_TR_ODD, ln,
roff_getname(struct roff *r, char **cpp, int ln, int pos)
{
char *name, *cp;
- size_t namesz;
+ int namesz, inam, iend;
name = *cpp;
if (*name == '\0')
/* Advance cp to the byte after the end of the name. */
- for (cp = name; 1; cp++) {
- namesz = cp - name;
+ cp = name;
+ namesz = 0;
+ for (;;) {
if (*cp == '\0')
break;
if (*cp == ' ' || *cp == '\t') {
cp++;
break;
}
- if (*cp != '\\')
+ if (*cp != '\\') {
+ if (name + namesz < cp) {
+ name[namesz] = *cp;
+ *cp = ' ';
+ }
+ namesz++;
+ cp++;
continue;
+ }
if (cp[1] == '{' || cp[1] == '}')
break;
- if (*++cp == '\\')
- continue;
- mandoc_msg(MANDOCERR_NAMESC, ln, pos,
- "%.*s", (int)(cp - name + 1), name);
- mandoc_escape((const char **)&cp, NULL, NULL);
- break;
+ if (roff_escape(cp, 0, 0, NULL, &inam,
+ NULL, NULL, &iend) != ESCAPE_UNDEF) {
+ mandoc_msg(MANDOCERR_NAMESC, ln, pos,
+ "%.*s%.*s", namesz, name, iend, cp);
+ cp += iend;
+ break;
+ }
+
+ /*
+ * In an identifier, \\, \., \G and so on
+ * are reduced to \, ., G and so on,
+ * vaguely similar to copy mode.
+ */
+
+ name[namesz++] = cp[inam];
+ while (iend--) {
+ if (cp >= name + namesz)
+ *cp = ' ';
+ cp++;
+ }
}
/* Read past spaces. */