]> git.cameronkatri.com Git - mandoc.git/blobdiff - roff.c
spelling; patch from jsg@
[mandoc.git] / roff.c
diff --git a/roff.c b/roff.c
index 59e2644f94ae1e4c875f155af312cbe62b6443f3..ee0da3e6244e7ed2b19f3d85f03461463c9f9743 100644 (file)
--- a/roff.c
+++ b/roff.c
@@ -1,4 +1,4 @@
-/* $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>
@@ -1375,6 +1375,7 @@ roff_expand(struct roff *r, struct buf *buf, int ln, int pos, char ec)
        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 \\$* */
@@ -1410,8 +1411,8 @@ roff_expand(struct roff *r, struct buf *buf, int ln, int pos, char ec)
                 * 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] = '\\';
@@ -1428,14 +1429,20 @@ roff_expand(struct roff *r, struct buf *buf, int ln, int pos, char ec)
                        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. */
 
@@ -1520,6 +1527,11 @@ roff_expand(struct roff *r, struct buf *buf, int ln, int pos, char ec)
                                        *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 &&
@@ -1535,6 +1547,8 @@ roff_expand(struct roff *r, struct buf *buf, int ln, int pos, char ec)
                        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",
@@ -3726,7 +3740,6 @@ roff_tr(ROFF_ARGS)
 {
        const char      *p, *first, *second;
        size_t           fsz, ssz;
-       enum mandoc_esc  esc;
 
        p = buf->buf + pos;
 
@@ -3740,23 +3753,15 @@ roff_tr(ROFF_ARGS)
 
                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,
@@ -4004,7 +4009,7 @@ static size_t
 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')
@@ -4012,24 +4017,46 @@ roff_getname(struct roff *r, char **cpp, int ln, int pos)
 
        /* 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. */