Lines Matching +full:- +full:pvs

3  * Copyright (c) 2010-2015, 2017-2023 Ingo Schwarze <schwarze@openbsd.org>
4 * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
47 #define ROFFDEF_USER (1 << 1) /* User-defined. */
55 /* --- data types --------------------------------------------------------- */
58 * An incredibly-simple string buffer.
61 char *p; /* nil-terminated buffer */
66 * A key-value roffstr pair as part of a singly-linked list.
75 * A single number register as part of a singly-linked list.
109 struct roffkv *strtab; /* user-defined strings & macros */
111 struct roffkv *xmbtab; /* multi-byte trans table (`tr') */
112 struct roffstr *xtab; /* single-byte trans table (`tr') */
140 int endspan; /* scope to: 1=eol 2=next line -1=\} */
170 /* --- function prototypes ------------------------------------------------ */
259 /* --- constant data ------------------------------------------------------ */
311 "pvs", "rchar", "rd", "recursionlimit",
554 { roff_line_ignore, NULL, NULL, 0 }, /* pvs */
631 static char *roffit_macro; /* nil-terminated macro line */
634 /* --- request table ------------------------------------------------------ */
653 req->tok = tok;
654 memcpy(req->name, roff_name[tok], sz + 1);
655 slot = ohash_qlookup(htab, req->name);
687 return req == NULL ? TOKEN_NONE : req->tok;
690 /* --- stack of request blocks -------------------------------------------- */
702 p = r->last;
703 inloop = p->tok == ROFF_while;
704 r->last = p->parent;
705 free(p->name);
706 free(p->end);
722 p->tok = tok;
724 p->name = mandoc_strdup(name);
725 p->parent = r->last;
726 p->line = line;
727 p->col = col;
728 p->rule = p->parent ? p->parent->rule : 0;
730 r->last = p;
733 /* --- roff parser state data management ---------------------------------- */
740 tbl_free(r->first_tbl);
741 r->first_tbl = r->last_tbl = r->tbl = NULL;
743 eqn_free(r->last_eqn);
744 r->last_eqn = r->eqn = NULL;
746 while (r->mstackpos >= 0)
749 while (r->last)
752 free (r->rstack);
753 r->rstack = NULL;
754 r->rstacksz = 0;
755 r->rstackpos = -1;
757 roff_freereg(r->regtab);
758 r->regtab = NULL;
760 roff_freestr(r->strtab);
761 roff_freestr(r->rentab);
762 roff_freestr(r->xmbtab);
763 r->strtab = r->rentab = r->xmbtab = NULL;
765 if (r->xtab)
767 free(r->xtab[i].p);
768 free(r->xtab);
769 r->xtab = NULL;
776 r->options |= MPARSE_COMMENT;
777 r->format = r->options & (MPARSE_MDOC | MPARSE_MAN);
778 r->control = '\0';
779 r->escape = '\\';
792 for (i = 0; i < r->mstacksz; i++)
793 free(r->mstack[i].argv);
794 free(r->mstack);
795 roffhash_free(r->reqtab);
805 r->reqtab = roffhash_alloc(0, ROFF_RENAMED);
806 r->options = options | MPARSE_COMMENT;
807 r->format = options & (MPARSE_MDOC | MPARSE_MAN);
808 r->mstackpos = -1;
809 r->rstackpos = -1;
810 r->escape = '\\';
814 /* --- syntax tree state data management ---------------------------------- */
819 if (man->meta.first != NULL)
820 roff_node_delete(man, man->meta.first);
821 free(man->meta.msec);
822 free(man->meta.vol);
823 free(man->meta.os);
824 free(man->meta.arch);
825 free(man->meta.title);
826 free(man->meta.name);
827 free(man->meta.date);
828 free(man->meta.sodest);
834 man->last = man->meta.first;
835 man->last_es = NULL;
836 man->flags = 0;
837 man->lastsec = man->lastnamed = SEC_NONE;
838 man->next = ROFF_NEXT_CHILD;
839 roff_setreg(man->roff, "nS", 0, '=');
845 memset(&man->meta, 0, sizeof(man->meta));
846 man->meta.first = mandoc_calloc(1, sizeof(*man->meta.first));
847 man->meta.first->type = ROFFT_ROOT;
848 man->meta.macroset = MACROSET_NONE;
863 free(man->os_r);
873 man->roff = roff;
874 man->os_s = os_s;
875 man->quick = quick;
877 roff->man = man;
881 /* --- syntax tree handling ----------------------------------------------- */
890 n->line = line;
891 n->pos = pos;
892 n->tok = tok;
893 n->type = type;
894 n->sec = man->lastsec;
896 if (man->flags & MDOC_SYNOPSIS)
897 n->flags |= NODE_SYNPRETTY;
899 n->flags &= ~NODE_SYNPRETTY;
900 if ((man->flags & (ROFF_NOFILL | ROFF_NONOFILL)) == ROFF_NOFILL)
901 n->flags |= NODE_NOFILL;
903 n->flags &= ~NODE_NOFILL;
904 if (man->flags & MDOC_NEWLINE)
905 n->flags |= NODE_LINE;
906 man->flags &= ~MDOC_NEWLINE;
915 switch (man->next) {
917 if (man->last->next != NULL) {
918 n->next = man->last->next;
919 man->last->next->prev = n;
921 man->last->parent->last = n;
922 man->last->next = n;
923 n->prev = man->last;
924 n->parent = man->last->parent;
927 if (man->last->child != NULL) {
928 n->next = man->last->child;
929 man->last->child->prev = n;
931 man->last->last = n;
932 man->last->child = n;
933 n->parent = man->last;
938 man->last = n;
940 switch (n->type) {
942 n->parent->head = n;
945 if (n->end != ENDBODY_NOT)
947 n->parent->body = n;
950 n->parent->tail = n;
957 * Copy over the normalised-data pointer of our parent. Not
961 n->norm = n->parent->norm;
962 assert(n->parent->type == ROFFT_BLOCK);
971 n->string = roff_strdup(man->roff, word);
973 n->flags |= NODE_VALID | NODE_ENDED;
974 man->next = ROFF_NEXT_SIBLING;
983 n = man->last;
984 addstr = roff_strdup(man->roff, word);
985 mandoc_asprintf(&newstr, "%s %s", n->string, addstr);
987 free(n->string);
988 n->string = newstr;
989 man->next = ROFF_NEXT_SIBLING;
999 man->next = ROFF_NEXT_CHILD;
1009 man->next = ROFF_NEXT_CHILD;
1020 man->next = ROFF_NEXT_CHILD;
1031 man->next = ROFF_NEXT_CHILD;
1041 if (man->meta.macroset == MACROSET_MAN)
1045 n->span = span;
1047 n->flags |= NODE_VALID | NODE_ENDED;
1048 man->next = ROFF_NEXT_SIBLING;
1058 if (n->prev)
1059 n->prev->next = n->next;
1060 if (n->next)
1061 n->next->prev = n->prev;
1065 if (n->parent != NULL) {
1066 if (n->parent->child == n)
1067 n->parent->child = n->next;
1068 if (n->parent->last == n)
1069 n->parent->last = n->prev;
1076 if (man->last == n) {
1077 if (n->prev == NULL) {
1078 man->last = n->parent;
1079 man->next = ROFF_NEXT_CHILD;
1081 man->last = n->prev;
1082 man->next = ROFF_NEXT_SIBLING;
1085 if (man->meta.first == n)
1086 man->meta.first = NULL;
1093 n->prev = n->next = NULL;
1101 if (n->args != NULL)
1102 mdoc_argv_free(n->args);
1103 if (n->type == ROFFT_BLOCK || n->type == ROFFT_ELEM)
1104 free(n->norm);
1105 eqn_box_free(n->eqn);
1106 free(n->string);
1107 free(n->tag);
1115 while (n->child != NULL)
1116 roff_node_delete(man, n->child);
1126 if (n->type == ROFFT_COMMENT || n->flags & NODE_NOPRT)
1128 return roff_tok_transparent(n->tok);
1157 for (n = n->child; roff_node_transparent(n); n = n->next)
1166 n = n->prev;
1175 n = n->next;
1186 if (n->string == NULL) {
1187 for (n = n->child; n != NULL; n = n->next)
1194 for (cp = n->string; *cp != '\0'; cp++) {
1205 if (sz > 0 && cp[sz - 1] == '\\')
1206 sz--;
1210 for (; sz; sz--)
1211 if ( ! isspace((unsigned char)cp[sz-1]))
1229 /* --- main functions of the roff parser ---------------------------------- */
1248 for (start = stesc = buf->buf + pos;; stesc++) {
1308 if (r->man->meta.rcsids & rcsid)
1310 (int)(stesc - buf->buf) + 2, "%s", stesc + 1);
1311 r->man->meta.rcsids |= rcsid;
1316 ep = strchr(stesc + 2, '\0') - 1;
1318 *ep-- = '\0';
1321 ln, (int)(ep - buf->buf), NULL);
1325 if (r->options & MPARSE_COMMENT) {
1327 ep--;
1329 n = roff_node_alloc(r->man, ln, stesc + 1 - buf->buf,
1331 n->string = mandoc_strdup(stesc + 2);
1332 roff_node_append(r->man, n);
1333 n->flags |= NODE_VALID | NODE_ENDED;
1334 r->man->next = ROFF_NEXT_SIBLING;
1346 while (stesc > start && stesc[-1] == ' ' &&
1347 (stesc == start + 1 || stesc[-2] != '\\'))
1348 stesc--;
1382 while (buf->buf[pos] != '\0') {
1386 * If we have a non-standard escape character,
1391 if (buf->buf[pos] != ec) {
1392 if (buf->buf[pos] == '\\') {
1404 * If we have a non-standard escape character, translate
1408 if (roff_escape(buf->buf, ln, pos, &iesc, &inam,
1411 if (buf->buf[pos] == ec) {
1412 buf->buf[pos] = '\\';
1415 } else if (buf->buf[pos] == '\\') {
1428 if (buf->buf[inam] == '*' || buf->buf[inam] == 'n') {
1432 buf->buf[isrc] == '\\' &&
1433 (buf->buf[isrc + 1] == '\\' ||
1434 buf->buf[isrc + 1] == '.'))
1436 buf->buf[idst++] = buf->buf[isrc++];
1438 iendarg -= isrc - idst;
1444 switch (buf->buf[inam]) {
1449 if ((res = roff_getstrn(r, buf->buf + iarg,
1450 iendarg - iarg, &deftype)) != NULL)
1458 if (iendarg - iarg == 2 &&
1459 buf->buf[iarg] == '.' &&
1460 buf->buf[iarg + 1] == 'T') {
1461 roff_setstrn(&r->strtab, ".T", 2, NULL, 0, 0);
1467 "%.*s", iendarg - iarg, buf->buf + iarg);
1471 if (r->mstackpos < 0) {
1473 "%.*s", iend - iesc, buf->buf + iesc);
1476 ctx = r->mstack + r->mstackpos;
1477 argi = buf->buf[iarg] - '1';
1479 if (argi < ctx->argc)
1480 res = ctx->argv[argi];
1483 if (buf->buf[iarg] == '*')
1485 else if (buf->buf[iarg] == '@')
1489 "%.*s", iend - iesc, buf->buf + iesc);
1493 for (argi = 0; argi < ctx->argc; argi++) {
1498 asz += strlen(ctx->argv[argi]);
1500 if (asz != iend - iesc) {
1501 rsz = buf->sz - iend;
1502 if (asz < iend - iesc)
1503 memmove(buf->buf + iesc + asz,
1504 buf->buf + iend, rsz);
1505 buf->sz = iesc + asz + rsz;
1506 buf->buf = mandoc_realloc(buf->buf, buf->sz);
1507 if (asz > iend - iesc)
1508 memmove(buf->buf + iesc + asz,
1509 buf->buf + iend, rsz);
1511 dst = buf->buf + iesc;
1512 for (argi = 0; argi < ctx->argc; argi++) {
1517 src = ctx->argv[argi];
1532 roff_evalnum(r, ln, buf->buf + iarg, &npos,
1534 npos == iendarg - iarg ? '1' : '0';
1540 "%.*s", iend - iesc, buf->buf + iesc);
1549 roff_getregn(r, buf->buf + iarg,
1550 iendarg - iarg, buf->buf[inam + 1]));
1560 if (buf->buf[iarg] != '\\') {
1565 switch ((subtype = roff_escape(buf->buf, 0,
1592 buf->sz + strlen(res) > SHRT_MAX) {
1610 buf->sz = mandoc_asprintf(&nbuf, "%.*s%s%s", start, buf->buf,
1611 repl, buf->buf + end) + 1;
1612 free(buf->buf);
1613 buf->buf = nbuf;
1617 * Parse a quoted or unquoted roff-style request or macro argument.
1620 * NUL-terminate the argument in place.
1648 cp[-pairs] = cp[0];
1653 * backslashes and backslash-t to literal tabs.
1658 cp[-pairs] = '\t';
1663 cp[-pairs] = '\\';
1699 /* NUL-terminate this argument and move to the next one. */
1701 cp[-pairs] = '\0';
1707 *pos += (int)(cp - start) + (quoted ? 1 : 0);
1710 if ('\0' == *cp && (white || ' ' == cp[-1]))
1743 isz = mandoc_asprintf(&p, "%s\n.%s", buf->buf, roffit_macro);
1744 free(buf->buf);
1745 buf->buf = p;
1746 buf->sz = isz + 1;
1752 --roffit_lines;
1754 if (roffce_node != NULL && buf->buf[pos] != '\0') {
1756 r->man->last = roffce_node;
1757 r->man->next = ROFF_NEXT_SIBLING;
1761 roffce_lines--;
1766 start = p = buf->buf + pos;
1769 sz = strcspn(p, "-\\");
1781 while (*p == '-')
1789 if (isalpha((unsigned char)p[-1]) &&
1804 int ppos; /* original offset in buf->buf */
1809 if (len > 80 && r->tbl == NULL && r->eqn == NULL &&
1810 (r->man->flags & ROFF_NOFILL) == 0 &&
1811 strchr(" .\\", buf->buf[pos]) == NULL &&
1812 buf->buf[pos] != r->control &&
1813 strcspn(buf->buf, " ") < 80)
1814 mandoc_msg(MANDOCERR_TEXT_LONG, ln, (int)len - 1,
1815 "%.20s...", buf->buf + pos);
1817 /* Handle in-line equation delimiters. */
1819 if (r->tbl == NULL &&
1820 r->last_eqn != NULL && r->last_eqn->delim &&
1821 (r->eqn == NULL || r->eqn_inline)) {
1830 e = roff_parse_comment(r, buf, ln, pos, r->escape);
1835 e = roff_expand(r, buf, ln, pos, r->escape);
1840 ctl = roff_getcontrol(r, buf->buf, &pos);
1850 if (r->last != NULL && ! ctl) {
1851 t = r->last->tok;
1858 if (r->eqn != NULL && strncmp(buf->buf + ppos, ".EN", 3)) {
1859 eqn_read(r->eqn, buf->buf + ppos);
1862 if (r->tbl != NULL && (ctl == 0 || buf->buf[pos] == '\0')) {
1863 tbl_read(r->tbl, ln, buf->buf, ppos);
1864 roff_addtbl(r->man, ln, r->tbl);
1868 r->options &= ~MPARSE_COMMENT;
1874 if (buf->buf[pos] == '"') {
1877 } else if (buf->buf[pos] == '\0')
1885 if (r->last) {
1886 t = r->last->tok;
1890 r->options &= ~MPARSE_COMMENT;
1892 t = roff_parse(r, buf->buf, &pos, ln, ppos);
1905 if (r->tbl != NULL && (tok == TOKEN_NONE || tok == ROFF_TS ||
1909 ln, ppos, "%s", buf->buf + ppos);
1912 while (buf->buf[pos] != '\0' && buf->buf[pos] != ' ')
1914 while (buf->buf[pos] == ' ')
1916 tbl_read(r->tbl, ln, buf->buf, pos);
1917 roff_addtbl(r->man, ln, r->tbl);
1926 r->man->last = roffce_node;
1927 r->man->next = ROFF_NEXT_SIBLING;
1933 * This is neither a roff request nor a user-defined macro.
1940 /* Execute a roff request or a user-defined macro. */
1956 assert(r->mstackpos >= 0);
1957 ctx = r->mstack + r->mstackpos;
1958 for (i = 0; i < ctx->argc; i++)
1959 free(ctx->argv[i]);
1960 ctx->argc = 0;
1961 r->mstackpos--;
1967 if (r->last != NULL)
1968 mandoc_msg(MANDOCERR_BLK_NOEND, r->last->line,
1969 r->last->col, "%s", roff_name[r->last->tok]);
1971 if (r->eqn != NULL) {
1973 r->eqn->node->line, r->eqn->node->pos, "EQ");
1974 eqn_parse(r->eqn);
1975 r->eqn = NULL;
1978 if (r->tbl != NULL) {
1979 tbl_end(r->tbl, 1);
1980 r->tbl = NULL;
1988 * As a side effect, set r->current_string to the definition or to NULL.
2008 r->current_string = roff_getstrn(r, mac, maclen, &deftype);
2017 t = roffhash_find(r->reqtab, mac, maclen);
2021 *pos = cp - buf;
2024 roff_setstrn(&r->strtab, mac, maclen, "", 0, 0);
2025 roff_setstrn(&r->rentab, mac, maclen, NULL, 0, 0);
2030 /* --- handling of request blocks ----------------------------------------- */
2040 if (r->last == NULL) {
2045 switch (r->last->tok) {
2069 if (r->last != NULL && r->last->endspan < 0) {
2074 if (buf->buf[pos] != '\0')
2076 ".. %s", buf->buf + pos);
2091 while (r->last != NULL && r->last->endspan > 0) {
2092 if (--r->last->endspan != 0)
2107 if (NULL == r->last) {
2112 switch (r->last->tok) {
2123 if (r->last->endspan > -1) {
2152 cp = buf->buf + pos;
2169 ln, (int)(iname - buf->buf),
2192 roff_setstrn(&r->strtab, name, namesz, "", 0, 0);
2193 roff_setstrn(&r->rentab, name, namesz, NULL, 0, 0);
2198 case ROFFDEF_PRE: /* copy predefined to user-defined. */
2199 roff_setstrn(&r->strtab, name, namesz,
2205 roff_setstrn(&r->strtab, name, namesz, call, csz, 0);
2206 roff_setstrn(&r->rentab, name, namesz, NULL, 0, 0);
2211 roff_setstrn(&r->rentab, rname, rsz, name, namesz, 0);
2214 roff_setstrn(&r->strtab, name, namesz, call, csz, 0);
2238 ln, (int)(iname - buf->buf),
2247 r->last->end = mandoc_strndup(name, namesz);
2263 * If a custom end marker is a user-defined or predefined macro
2267 if (r->last->end) {
2268 for (i = pos, j = 0; r->last->end[j]; j++, i++)
2269 if (buf->buf[i] != r->last->end[j])
2272 if (r->last->end[j] == '\0' &&
2273 (buf->buf[i] == '\0' ||
2274 buf->buf[i] == ' ' ||
2275 buf->buf[i] == '\t')) {
2279 while (buf->buf[i] == ' ' || buf->buf[i] == '\t')
2283 if (roff_parse(r, buf->buf, &pos, ln, ppos) !=
2292 t = roff_parse(r, buf->buf, &pos, ln, ppos);
2299 roff_setstr(r, r->last->name, buf->buf + ppos, 2);
2308 roff_setstr(r, r->last->name, buf->buf + pos, 2);
2329 rr = r->last->rule;
2340 ep = buf->buf + pos;
2358 if (roff_ccond(r, ln, ep - buf->buf))
2386 t = roff_parse(r, buf->buf, &pos, ln, ppos);
2398 for (bl = r->last; bl != NULL; bl = bl->parent) {
2399 bl->rule = 0;
2400 if (bl->tok == ROFF_while)
2427 /* --- handling of numeric and conditional expressions -------------------- */
2430 * Parse a single signed integer number. Stop at the first non-digit.
2444 n = v[p] == '-';
2453 *res = 10 * *res + v[p] - '0';
2458 *res = -*res;
2491 p--;
2540 *pos = s3 - v;
2599 istrue = mchars_spec2cp(start, len) != -1;
2605 istrue = mchars_num2char(start, len) != -1;
2611 *pos = end - v;
2619 sz = roff_getname(r, &cp, ln, cp - v);
2629 *pos = (name + sz) - v;
2682 r->last->rule = tok == ROFF_el ?
2683 (r->rstackpos < 0 ? 0 : r->rstack[r->rstackpos--]) :
2684 roff_evalcond(r, ln, buf->buf, &pos);
2687 * An if-else will put the NEGATION of the current evaluated
2692 if (r->rstackpos + 1 == r->rstacksz) {
2693 r->rstacksz += 16;
2694 r->rstack = mandoc_reallocarray(r->rstack,
2695 r->rstacksz, sizeof(int));
2697 r->rstack[++r->rstackpos] = !r->last->rule;
2702 if (r->last->parent && !r->last->parent->rule)
2703 r->last->rule = 0;
2708 * not even whitespace, use next-line scope.
2709 * Except that .while does not support next-line scope.
2712 if (buf->buf[pos] == '\0' && tok != ROFF_while) {
2713 r->last->endspan = 2;
2717 while (buf->buf[pos] == ' ')
2722 if (buf->buf[pos] == '\\' && buf->buf[pos + 1] == '{') {
2723 r->last->endspan = -1;
2725 while (buf->buf[pos] == ' ')
2732 * single-line scope. Warn if the scope contains
2736 if (buf->buf[pos] == '\0')
2740 r->last->endspan = 1;
2770 name = string = buf->buf + pos;
2779 string = buf->buf + pos + namesz;
2785 /* Read past the initial double-quote, if any. */
2790 roff_setstrn(&r->strtab, name, namesz, string, strlen(string),
2792 roff_setstrn(&r->rentab, name, namesz, NULL, 0, 0);
2809 case '-':
2939 case '-':
2940 *res -= operand2;
3002 /* --- register management ------------------------------------------------ */
3017 reg = r->regtab;
3019 while (reg != NULL && (reg->key.sz != len ||
3020 strncmp(reg->key.p, name, len) != 0))
3021 reg = reg->next;
3026 reg->key.p = mandoc_strndup(name, len);
3027 reg->key.sz = len;
3028 reg->val = 0;
3029 reg->step = 0;
3030 reg->next = r->regtab;
3031 r->regtab = reg;
3035 reg->val += val;
3036 else if ('-' == sign)
3037 reg->val -= val;
3039 reg->val = val;
3041 reg->step = step;
3045 * Handle some predefined read-only number registers.
3046 * For now, return -1 if the requested register is not predefined;
3047 * in case a predefined read-only register having the value -1
3056 return r->mstackpos < 0 ? 0 : r->mstack[r->mstackpos].argc;
3070 return -1;
3088 if (-1 != val)
3092 for (reg = r->regtab; reg; reg = reg->next) {
3093 if (len == reg->key.sz &&
3094 0 == strncmp(name, reg->key.p, len)) {
3097 reg->val += reg->step;
3099 case '-':
3100 reg->val -= reg->step;
3105 return reg->val;
3121 if (-1 != val)
3125 for (reg = r->regtab; reg; reg = reg->next)
3126 if (len == reg->key.sz &&
3127 0 == strncmp(name, reg->key.p, len))
3139 free(reg->key.p);
3141 reg = reg->next;
3154 key = val = buf->buf + pos;
3163 if (sign == '+' || sign == '-')
3187 name = cp = buf->buf + pos;
3193 prev = &r->regtab;
3196 if (reg == NULL || !strcmp(name, reg->key.p))
3198 prev = &reg->next;
3201 *prev = reg->next;
3202 free(reg->key.p);
3208 /* --- handler functions for roff requests -------------------------------- */
3217 cp = buf->buf + pos;
3220 namesz = roff_getname(r, &cp, ln, (int)(cp - buf->buf));
3221 roff_setstrn(&r->strtab, name, namesz, NULL, 0, 0);
3222 roff_setstrn(&r->rentab, name, namesz, NULL, 0, 0);
3236 if ( ! roff_evalnum(r, ln, buf->buf, &pos, &iv, 0)) {
3238 ln, ppos, "%s", buf->buf + 1);
3242 while (isspace((unsigned char)buf->buf[pos]))
3247 * Special-casing "an-trap" is an ugly workaround to cope
3253 strcmp(buf->buf + pos, "an-trap") ?
3254 buf->buf + pos : "br");
3268 if (r->format == 0)
3269 r->format = MPARSE_MDOC;
3275 if (r->format == 0)
3276 r->format = MPARSE_MAN;
3282 if ((r->options & mask) == 0)
3291 r->man->flags &= ~ROFF_NONOFILL;
3292 if (r->tbl == NULL) {
3296 if (tbl_end(r->tbl, 0) == 0) {
3297 r->tbl = NULL;
3298 free(buf->buf);
3299 buf->buf = mandoc_strdup(".sp");
3300 buf->sz = 4;
3304 r->tbl = NULL;
3312 if (NULL == r->tbl)
3315 tbl_restart(ln, ppos, r->tbl);
3321 * Handle in-line equation delimiters.
3332 * in-line, or this function wouldn't have been called;
3336 cp1 = buf->buf + pos;
3337 cp2 = strchr(cp1, r->eqn == NULL ?
3338 r->last_eqn->odelim : r->last_eqn->cdelim);
3347 if (*buf->buf != '\0') {
3348 if (r->eqn == NULL)
3358 if (r->eqn == NULL) {
3369 if (r->eqn != NULL)
3375 buf->sz = mandoc_asprintf(&cp1, "%s%s%s%s%s%s%s", buf->buf,
3377 free(buf->buf);
3378 buf->buf = cp1;
3380 /* Toggle the in-line state of the eqn subsystem. */
3382 r->eqn_inline = r->eqn == NULL;
3391 if (r->man->meta.macroset == MACROSET_MAN)
3392 man_breakscope(r->man, ROFF_EQ);
3393 n = roff_node_alloc(r->man, ln, ppos, ROFFT_EQN, TOKEN_NONE);
3394 if (ln > r->man->last->line)
3395 n->flags |= NODE_LINE;
3396 n->eqn = eqn_box_new();
3397 roff_node_append(r->man, n);
3398 r->man->next = ROFF_NEXT_SIBLING;
3400 assert(r->eqn == NULL);
3401 if (r->last_eqn == NULL)
3402 r->last_eqn = eqn_alloc();
3404 eqn_reset(r->last_eqn);
3405 r->eqn = r->last_eqn;
3406 r->eqn->node = n;
3408 if (buf->buf[pos] != '\0')
3410 ".EQ %s", buf->buf + pos);
3418 if (r->eqn != NULL) {
3419 eqn_parse(r->eqn);
3420 r->eqn = NULL;
3423 if (buf->buf[pos] != '\0')
3425 "EN %s", buf->buf + pos);
3432 if (r->tbl != NULL) {
3434 tbl_end(r->tbl, 0);
3436 r->man->flags |= ROFF_NONOFILL;
3437 r->tbl = tbl_alloc(ppos, ln, r->last_tbl);
3438 if (r->last_tbl == NULL)
3439 r->first_tbl = r->tbl;
3440 r->last_tbl = r->tbl;
3447 if (r->man->flags & (MAN_BLINE | MAN_ELINE))
3448 man_breakscope(r->man, tok);
3451 roff_elem_alloc(r->man, ln, ppos, tok);
3452 if (buf->buf[pos] != '\0')
3454 "%s %s", roff_name[tok], buf->buf + pos);
3456 r->man->flags |= ROFF_NOFILL;
3458 r->man->flags &= ~ROFF_NOFILL;
3459 r->man->last->flags |= NODE_LINE | NODE_VALID | NODE_ENDED;
3460 r->man->next = ROFF_NEXT_SIBLING;
3471 if (r->man->flags & (MAN_BLINE | MAN_ELINE) &&
3474 man_breakscope(r->man, tok);
3477 r->man->last = roffce_node;
3478 r->man->next = ROFF_NEXT_SIBLING;
3481 roff_elem_alloc(r->man, ln, ppos, tok);
3482 n = r->man->last;
3484 cp = buf->buf + pos;
3492 ln, (int)(cp - buf->buf),
3494 roff_word_alloc(r->man, ln, pos, buf->buf + pos);
3498 if (r->man->last->type == ROFFT_ELEM) {
3499 roff_word_alloc(r->man, ln, pos, "1");
3500 r->man->last->flags |= NODE_NOSRC;
3503 if (roff_evalnum(r, ln, r->man->last->string, &npos,
3506 ln, pos, "ce %s", buf->buf + pos);
3510 r->man->last = r->man->last->parent;
3514 roffce_node = r->man->last->parent;
3516 n->flags |= NODE_VALID | NODE_ENDED;
3517 r->man->last = n;
3519 n->flags |= NODE_LINE;
3520 r->man->next = ROFF_NEXT_SIBLING;
3530 roff_elem_alloc(r->man, ln, ppos, tok);
3531 n = r->man->last;
3533 for (sp = ep = buf->buf + pos; *sp != '\0'; sp = ep) {
3538 roff_word_alloc(r->man, ln, sp - buf->buf, sp);
3541 n->flags |= NODE_LINE | NODE_VALID | NODE_ENDED;
3542 r->man->last = n;
3543 r->man->next = ROFF_NEXT_SIBLING;
3553 newn = oldn = buf->buf + pos;
3562 oldsz = roff_getname(r, &end, ln, oldn - buf->buf);
3568 roff_setstrn(&r->strtab, newn, newsz, value, valsz, 0);
3569 roff_setstrn(&r->rentab, newn, newsz, NULL, 0, 0);
3590 p = buf->buf + pos;
3592 if (*p == '\0' || (r->control = *p++) == '.')
3593 r->control = '\0';
3597 ln, p - buf->buf, "cc ... %s", p);
3611 kp = buf->buf + pos;
3619 ksz = p - kp;
3652 ln, (int)(vp - buf->buf), "%s", vp);
3660 if (r->xtab == NULL)
3661 r->xtab = mandoc_calloc(128, sizeof(*r->xtab));
3663 free(r->xtab[(int)*kp].p);
3664 r->xtab[(int)*kp].sz = mandoc_asprintf(&r->xtab[(int)*kp].p,
3667 roff_setstrn(&r->xmbtab, kp, ksz, vp, vsz, 0);
3669 roff_setstrn(&r->xmbtab, kp, ksz, "\\fP", 3, 1);
3679 p = buf->buf + pos;
3681 r->escape = '\\';
3683 r->escape = *p;
3686 (int)(p - buf->buf), "ec ... %s", p);
3694 r->escape = '\0';
3695 if (buf->buf[pos] != '\0')
3697 ln, pos, "eo %s", buf->buf + pos);
3709 cp = buf->buf + pos;
3712 if (buf->buf[pos] == '\\') {
3721 "mc %s", buf->buf + pos);
3722 buf->buf[pos] = '\0';
3732 mandoc_msg(MANDOCERR_MC_DIST, ln, (int)(cp - buf->buf),
3739 roff_elem_alloc(r->man, ln, ppos, tok);
3740 n = r->man->last;
3741 if (buf->buf[pos] != '\0')
3742 roff_word_alloc(r->man, ln, pos, buf->buf + pos);
3743 n->flags |= NODE_LINE | NODE_VALID | NODE_ENDED;
3744 r->man->last = n;
3745 r->man->next = ROFF_NEXT_SIBLING;
3752 while (buf->buf[pos] == ' ')
3764 p = buf->buf + pos;
3778 fsz = (size_t)(p - first);
3785 ssz = (size_t)(p - second);
3788 (int)(first - buf->buf), "tr %s", first);
3790 p--;
3794 roff_setstrn(&r->xmbtab, first, fsz,
3799 if (r->xtab == NULL)
3800 r->xtab = mandoc_calloc(128,
3803 free(r->xtab[(int)*first].p);
3804 r->xtab[(int)*first].p = mandoc_strndup(second, ssz);
3805 r->xtab[(int)*first].sz = ssz;
3820 if (r->mstackpos >= 0)
3835 oldn = newn = buf->buf + pos;
3844 newsz = roff_getname(r, &end, ln, newn - buf->buf);
3852 roff_setstrn(&r->strtab, newn, newsz, value, strlen(value), 0);
3853 roff_setstrn(&r->strtab, oldn, oldsz, NULL, 0, 0);
3854 roff_setstrn(&r->rentab, newn, newsz, NULL, 0, 0);
3857 roff_setstrn(&r->strtab, newn, newsz, value, strlen(value), 0);
3858 roff_setstrn(&r->rentab, newn, newsz, NULL, 0, 0);
3861 roff_setstrn(&r->rentab, newn, newsz, value, strlen(value), 0);
3862 roff_setstrn(&r->rentab, oldn, oldsz, NULL, 0, 0);
3863 roff_setstrn(&r->strtab, newn, newsz, NULL, 0, 0);
3866 roff_setstrn(&r->rentab, newn, newsz, oldn, oldsz, 0);
3867 roff_setstrn(&r->strtab, newn, newsz, NULL, 0, 0);
3870 roff_setstrn(&r->strtab, newn, newsz, NULL, 0, 0);
3871 roff_setstrn(&r->rentab, newn, newsz, NULL, 0, 0);
3885 if (buf->buf[pos] != '\0' &&
3886 roff_evalnum(r, ln, buf->buf, &pos, &levels, 0) == 0) {
3888 ln, pos, "shift %s", buf->buf + pos);
3891 if (r->mstackpos < 0) {
3895 ctx = r->mstack + r->mstackpos;
3896 if (levels > ctx->argc) {
3898 ln, argpos, "%d, but max is %d", levels, ctx->argc);
3899 levels = ctx->argc;
3908 free(ctx->argv[i]);
3909 ctx->argc -= levels;
3910 for (i = 0; i < ctx->argc; i++)
3911 ctx->argv[i] = ctx->argv[i + levels];
3920 name = buf->buf + pos;
3926 * it. Thus, explicitly disallow traversing up the file-system
3932 buf->sz = mandoc_asprintf(&cp,
3934 free(buf->buf);
3935 buf->buf = cp;
3944 /* --- user defined strings and macros ------------------------------------ */
3955 if (*r->current_string == '\0')
3960 if (++r->mstackpos == r->mstacksz) {
3961 r->mstack = mandoc_recallocarray(r->mstack,
3962 r->mstacksz, r->mstacksz + 8, sizeof(*r->mstack));
3963 r->mstacksz += 8;
3965 ctx = r->mstack + r->mstackpos;
3966 ctx->argc = 0;
3970 * NUL-terminating them and escaping quotes.
3973 src = buf->buf + pos;
3975 if (ctx->argc == ctx->argsz) {
3976 ctx->argsz += 8;
3977 ctx->argv = mandoc_reallocarray(ctx->argv,
3978 ctx->argsz, sizeof(*ctx->argv));
3984 ctx->argv[ctx->argc++] = dst = mandoc_malloc(sz);
3998 free(buf->buf);
3999 buf->buf = mandoc_strdup(r->current_string);
4000 buf->sz = strlen(buf->buf) + 1;
4003 return buf->buf[buf->sz - 2] == '\n' ?
4008 * Calling a high-level macro that was renamed with .rn.
4009 * r->current_string has already been set up by roff_parse().
4016 buf->sz = mandoc_asprintf(&nbuf, ".%s%s%s", r->current_string,
4017 buf->buf[pos] == '\0' ? "" : " ", buf->buf + pos) + 1;
4018 free(buf->buf);
4019 buf->buf = nbuf;
4075 while (iend--) {
4092 * Store *string into the user-defined string called *name.
4095 * append == 1: single-line append mode
4105 roff_setstrn(&r->strtab, name, namesz, string,
4107 roff_setstrn(&r->rentab, name, namesz, NULL, 0, 0);
4122 while (n && (namesz != n->key.sz ||
4123 strncmp(n->key.p, name, namesz)))
4124 n = n->next;
4129 n->key.p = mandoc_strndup(name, namesz);
4130 n->key.sz = namesz;
4131 n->val.p = NULL;
4132 n->val.sz = 0;
4133 n->next = *r;
4136 free(n->val.p);
4137 n->val.p = NULL;
4138 n->val.sz = 0;
4150 if (NULL == n->val.p) {
4151 n->val.p = mandoc_malloc(newch);
4152 *n->val.p = '\0';
4155 oldch = n->val.sz;
4156 n->val.p = mandoc_realloc(n->val.p, oldch + newch);
4160 c = n->val.p + (int)oldch;
4179 n->val.sz = (int)(c - n->val.p);
4191 for (n = r->strtab; n != NULL; n = n->next) {
4192 if (strncmp(name, n->key.p, len) != 0 ||
4193 n->key.p[len] != '\0' || n->val.p == NULL)
4197 return n->val.p;
4203 for (n = r->rentab; n != NULL; n = n->next) {
4204 if (strncmp(name, n->key.p, len) != 0 ||
4205 n->key.p[len] != '\0' || n->val.p == NULL)
4209 return n->val.p;
4227 if (r->man->meta.macroset != MACROSET_MAN) {
4241 if (r->man->meta.macroset != MACROSET_MDOC) {
4268 roff_setstrn(&r->strtab, name, len, "", 0, 0);
4269 roff_setstrn(&r->rentab, name, len, NULL, 0, 0);
4282 free(n->key.p);
4283 free(n->val.p);
4284 nn = n->next;
4289 /* --- accessors and utility functions ------------------------------------ */
4294 * Returns a heap-allocated string with all the replacements made.
4305 if (NULL == r->xmbtab && NULL == r->xtab)
4313 * a glyph but the escape is multi-character).
4323 if ('\\' != *p && r->xtab && r->xtab[(unsigned int)*p].p) {
4324 sz = r->xtab[(int)*p].sz;
4326 memcpy(res + ssz, r->xtab[(int)*p].p, sz);
4337 for (cp = r->xmbtab; cp; cp = cp->next)
4338 if (0 == strncmp(p, cp->key.p, cp->key.sz))
4348 ssz + cp->val.sz + 1);
4349 memcpy(res + ssz, cp->val.p, cp->val.sz);
4350 ssz += cp->val.sz;
4351 p += (int)cp->key.sz;
4374 sz = (int)(p - pp);
4388 return r->format;
4397 * This is slightly contrary to groff, where using the non-breaking
4399 * non-breaking macro contents to be printed verbatim.
4408 if (r->control != '\0' && cp[pos] == r->control)
4410 else if (r->control != '\0')