Lines Matching +full:a +full:- +full:hlm
3 * Copyright (c) 2010-2015, 2017-2025 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.
93 * A macro processing context.
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') */
131 * A macro definition, condition, or ignored block.
140 int endspan; /* scope to: 1=eol 2=next line -1=\} */
170 /* --- function prototypes ------------------------------------------------ */
257 /* --- constant data ------------------------------------------------------ */
287 "hidechar", "hla", "hlm", "hpf",
334 "Xr", "%A", "%B", "%D",
477 { roff_line_ignore, NULL, NULL, 0 }, /* hlm */
626 static char *roffit_macro; /* nil-terminated macro line */
629 /* --- request table ------------------------------------------------------ */
648 req->tok = tok; in roffhash_alloc()
649 memcpy(req->name, roff_name[tok], sz + 1); in roffhash_alloc()
650 slot = ohash_qlookup(htab, req->name); in roffhash_alloc()
682 return req == NULL ? TOKEN_NONE : req->tok; in roffhash_find()
685 /* --- stack of request blocks -------------------------------------------- */
689 * pending. Return 1 if it is a loop or 0 otherwise.
697 p = r->last; in roffnode_pop()
698 inloop = p->tok == ROFF_while; in roffnode_pop()
699 r->last = p->parent; in roffnode_pop()
700 free(p->name); in roffnode_pop()
701 free(p->end); in roffnode_pop()
707 * Push a roff node onto the instruction stack. This must later be
717 p->tok = tok; in roffnode_push()
719 p->name = mandoc_strdup(name); in roffnode_push()
720 p->parent = r->last; in roffnode_push()
721 p->line = line; in roffnode_push()
722 p->col = col; in roffnode_push()
723 p->rule = p->parent ? p->parent->rule : 0; in roffnode_push()
725 r->last = p; in roffnode_push()
728 /* --- roff parser state data management ---------------------------------- */
735 tbl_free(r->first_tbl); in roff_free1()
736 r->first_tbl = r->last_tbl = r->tbl = NULL; in roff_free1()
738 eqn_free(r->last_eqn); in roff_free1()
739 r->last_eqn = r->eqn = NULL; in roff_free1()
741 while (r->mstackpos >= 0) in roff_free1()
744 while (r->last) in roff_free1()
747 free (r->rstack); in roff_free1()
748 r->rstack = NULL; in roff_free1()
749 r->rstacksz = 0; in roff_free1()
750 r->rstackpos = -1; in roff_free1()
752 roff_freereg(r->regtab); in roff_free1()
753 r->regtab = NULL; in roff_free1()
755 roff_freestr(r->strtab); in roff_free1()
756 roff_freestr(r->rentab); in roff_free1()
757 roff_freestr(r->xmbtab); in roff_free1()
758 r->strtab = r->rentab = r->xmbtab = NULL; in roff_free1()
760 if (r->xtab) in roff_free1()
762 free(r->xtab[i].p); in roff_free1()
763 free(r->xtab); in roff_free1()
764 r->xtab = NULL; in roff_free1()
771 r->options |= MPARSE_COMMENT; in roff_reset()
772 r->format = r->options & (MPARSE_MDOC | MPARSE_MAN); in roff_reset()
773 r->control = '\0'; in roff_reset()
774 r->escape = '\\'; in roff_reset()
787 for (i = 0; i < r->mstacksz; i++) in roff_free()
788 free(r->mstack[i].argv); in roff_free()
789 free(r->mstack); in roff_free()
790 roffhash_free(r->reqtab); in roff_free()
800 r->reqtab = roffhash_alloc(0, ROFF_RENAMED); in roff_alloc()
801 r->options = options | MPARSE_COMMENT; in roff_alloc()
802 r->format = options & (MPARSE_MDOC | MPARSE_MAN); in roff_alloc()
803 r->mstackpos = -1; in roff_alloc()
804 r->rstackpos = -1; in roff_alloc()
805 r->escape = '\\'; in roff_alloc()
809 /* --- syntax tree state data management ---------------------------------- */
814 if (man->meta.first != NULL) in roff_man_free1()
815 roff_node_delete(man, man->meta.first); in roff_man_free1()
816 free(man->meta.msec); in roff_man_free1()
817 free(man->meta.vol); in roff_man_free1()
818 free(man->meta.os); in roff_man_free1()
819 free(man->meta.arch); in roff_man_free1()
820 free(man->meta.title); in roff_man_free1()
821 free(man->meta.name); in roff_man_free1()
822 free(man->meta.date); in roff_man_free1()
823 free(man->meta.sodest); in roff_man_free1()
829 man->last = man->meta.first; in roff_state_reset()
830 man->last_es = NULL; in roff_state_reset()
831 man->flags = 0; in roff_state_reset()
832 man->lastsec = man->lastnamed = SEC_NONE; in roff_state_reset()
833 man->next = ROFF_NEXT_CHILD; in roff_state_reset()
834 roff_setreg(man->roff, "nS", 0, '='); in roff_state_reset()
840 memset(&man->meta, 0, sizeof(man->meta)); in roff_man_alloc1()
841 man->meta.first = mandoc_calloc(1, sizeof(*man->meta.first)); in roff_man_alloc1()
842 man->meta.first->type = ROFFT_ROOT; in roff_man_alloc1()
843 man->meta.macroset = MACROSET_NONE; in roff_man_alloc1()
858 free(man->os_r); in roff_man_free()
868 man->roff = roff; in roff_man_alloc()
869 man->os_s = os_s; in roff_man_alloc()
870 man->quick = quick; in roff_man_alloc()
872 roff->man = man; in roff_man_alloc()
876 /* --- syntax tree handling ----------------------------------------------- */
885 n->line = line; in roff_node_alloc()
886 n->pos = pos; in roff_node_alloc()
887 n->tok = tok; in roff_node_alloc()
888 n->type = type; in roff_node_alloc()
889 n->sec = man->lastsec; in roff_node_alloc()
891 if (man->flags & MDOC_SYNOPSIS) in roff_node_alloc()
892 n->flags |= NODE_SYNPRETTY; in roff_node_alloc()
894 n->flags &= ~NODE_SYNPRETTY; in roff_node_alloc()
895 if ((man->flags & (ROFF_NOFILL | ROFF_NONOFILL)) == ROFF_NOFILL) in roff_node_alloc()
896 n->flags |= NODE_NOFILL; in roff_node_alloc()
898 n->flags &= ~NODE_NOFILL; in roff_node_alloc()
899 if (man->flags & MDOC_NEWLINE) in roff_node_alloc()
900 n->flags |= NODE_LINE; in roff_node_alloc()
901 man->flags &= ~MDOC_NEWLINE; in roff_node_alloc()
910 switch (man->next) { in roff_node_append()
912 if (man->last->next != NULL) { in roff_node_append()
913 n->next = man->last->next; in roff_node_append()
914 man->last->next->prev = n; in roff_node_append()
916 man->last->parent->last = n; in roff_node_append()
917 man->last->next = n; in roff_node_append()
918 n->prev = man->last; in roff_node_append()
919 n->parent = man->last->parent; in roff_node_append()
922 if (man->last->child != NULL) { in roff_node_append()
923 n->next = man->last->child; in roff_node_append()
924 man->last->child->prev = n; in roff_node_append()
926 man->last->last = n; in roff_node_append()
927 man->last->child = n; in roff_node_append()
928 n->parent = man->last; in roff_node_append()
933 man->last = n; in roff_node_append()
935 switch (n->type) { in roff_node_append()
937 n->parent->head = n; in roff_node_append()
940 if (n->end != ENDBODY_NOT) in roff_node_append()
942 n->parent->body = n; in roff_node_append()
945 n->parent->tail = n; in roff_node_append()
952 * Copy over the normalised-data pointer of our parent. Not in roff_node_append()
953 * everybody has one, but copying a null pointer is fine. in roff_node_append()
956 n->norm = n->parent->norm; in roff_node_append()
957 assert(n->parent->type == ROFFT_BLOCK); in roff_node_append()
966 n->string = roff_strdup(man->roff, word); in roff_word_alloc()
968 n->flags |= NODE_VALID | NODE_ENDED; in roff_word_alloc()
969 man->next = ROFF_NEXT_SIBLING; in roff_word_alloc()
978 n = man->last; in roff_word_append()
979 addstr = roff_strdup(man->roff, word); in roff_word_append()
980 mandoc_asprintf(&newstr, "%s %s", n->string, addstr); in roff_word_append()
982 free(n->string); in roff_word_append()
983 n->string = newstr; in roff_word_append()
984 man->next = ROFF_NEXT_SIBLING; in roff_word_append()
994 man->next = ROFF_NEXT_CHILD; in roff_elem_alloc()
1004 man->next = ROFF_NEXT_CHILD; in roff_block_alloc()
1015 man->next = ROFF_NEXT_CHILD; in roff_head_alloc()
1026 man->next = ROFF_NEXT_CHILD; in roff_body_alloc()
1036 if (man->meta.macroset == MACROSET_MAN) in roff_addtbl()
1040 n->span = span; in roff_addtbl()
1042 n->flags |= NODE_VALID | NODE_ENDED; in roff_addtbl()
1043 man->next = ROFF_NEXT_SIBLING; in roff_addtbl()
1053 if (n->prev) in roff_node_unlink()
1054 n->prev->next = n->next; in roff_node_unlink()
1055 if (n->next) in roff_node_unlink()
1056 n->next->prev = n->prev; in roff_node_unlink()
1060 if (n->parent != NULL) { in roff_node_unlink()
1061 if (n->parent->child == n) in roff_node_unlink()
1062 n->parent->child = n->next; in roff_node_unlink()
1063 if (n->parent->last == n) in roff_node_unlink()
1064 n->parent->last = n->prev; in roff_node_unlink()
1071 if (man->last == n) { in roff_node_unlink()
1072 if (n->prev == NULL) { in roff_node_unlink()
1073 man->last = n->parent; in roff_node_unlink()
1074 man->next = ROFF_NEXT_CHILD; in roff_node_unlink()
1076 man->last = n->prev; in roff_node_unlink()
1077 man->next = ROFF_NEXT_SIBLING; in roff_node_unlink()
1080 if (man->meta.first == n) in roff_node_unlink()
1081 man->meta.first = NULL; in roff_node_unlink()
1088 n->prev = n->next = NULL; in roff_node_relink()
1096 if (n->args != NULL) in roff_node_free()
1097 mdoc_argv_free(n->args); in roff_node_free()
1098 if (n->type == ROFFT_BLOCK || n->type == ROFFT_ELEM) in roff_node_free()
1099 free(n->norm); in roff_node_free()
1100 eqn_box_free(n->eqn); in roff_node_free()
1101 free(n->string); in roff_node_free()
1102 free(n->tag); in roff_node_free()
1110 while (n->child != NULL) in roff_node_delete()
1111 roff_node_delete(man, n->child); in roff_node_delete()
1121 if (n->type == ROFFT_COMMENT || n->flags & NODE_NOPRT) in roff_node_transparent()
1123 return roff_tok_transparent(n->tok); in roff_node_transparent()
1152 for (n = n->child; roff_node_transparent(n); n = n->next) in roff_node_child()
1161 n = n->prev; in roff_node_prev()
1170 n = n->next; in roff_node_next()
1181 if (n->string == NULL) { in deroff()
1182 for (n = n->child; n != NULL; n = n->next) in deroff()
1189 for (cp = n->string; *cp != '\0'; cp++) { in deroff()
1200 if (sz > 0 && cp[sz - 1] == '\\') in deroff()
1201 sz--; in deroff()
1205 for (; sz; sz--) in deroff()
1206 if ( ! isspace((unsigned char)cp[sz-1])) in deroff()
1224 /* --- main functions of the roff parser ---------------------------------- */
1243 for (start = stesc = buf->buf + pos;; stesc++) { in roff_parse_comment()
1264 * if the function mparse_buf_r() appended a newline in roff_parse_comment()
1282 /* Found a comment: process it. */ in roff_parse_comment()
1303 if (r->man->meta.rcsids & rcsid) in roff_parse_comment()
1305 (int)(stesc - buf->buf) + 2, "%s", stesc + 1); in roff_parse_comment()
1306 r->man->meta.rcsids |= rcsid; in roff_parse_comment()
1311 ep = strchr(stesc + 2, '\0') - 1; in roff_parse_comment()
1313 *ep-- = '\0'; in roff_parse_comment()
1316 ln, (int)(ep - buf->buf), NULL); in roff_parse_comment()
1320 if (r->options & MPARSE_COMMENT) { in roff_parse_comment()
1322 ep--; in roff_parse_comment()
1324 n = roff_node_alloc(r->man, ln, stesc + 1 - buf->buf, in roff_parse_comment()
1326 n->string = mandoc_strdup(stesc + 2); in roff_parse_comment()
1327 roff_node_append(r->man, n); in roff_parse_comment()
1328 n->flags |= NODE_VALID | NODE_ENDED; in roff_parse_comment()
1329 r->man->next = ROFF_NEXT_SIBLING; in roff_parse_comment()
1341 while (stesc > start && stesc[-1] == ' ' && in roff_parse_comment()
1342 (stesc == start + 1 || stesc[-2] != '\\')) in roff_parse_comment()
1343 stesc--; in roff_parse_comment()
1356 char ubuf[24]; /* buffer to print a number */ in roff_expand()
1377 while (buf->buf[pos] != '\0') { in roff_expand()
1381 * If we have a non-standard escape character, in roff_expand()
1386 if (buf->buf[pos] != ec) { in roff_expand()
1387 if (buf->buf[pos] == '\\') { in roff_expand()
1399 * If we have a non-standard escape character, translate in roff_expand()
1403 if (roff_escape(buf->buf, ln, pos, &iesc, &inam, in roff_expand()
1406 if (buf->buf[pos] == ec) { in roff_expand()
1407 buf->buf[pos] = '\\'; in roff_expand()
1410 } else if (buf->buf[pos] == '\\') { in roff_expand()
1423 if (buf->buf[inam] == '*' || buf->buf[inam] == 'n') { in roff_expand()
1427 buf->buf[isrc] == '\\' && in roff_expand()
1428 (buf->buf[isrc + 1] == '\\' || in roff_expand()
1429 buf->buf[isrc + 1] == '.')) in roff_expand()
1431 buf->buf[idst++] = buf->buf[isrc++]; in roff_expand()
1433 iendarg -= isrc - idst; in roff_expand()
1439 switch (buf->buf[inam]) { in roff_expand()
1444 if ((res = roff_getstrn(r, buf->buf + iarg, in roff_expand()
1445 iendarg - iarg, &deftype)) != NULL) in roff_expand()
1453 if (iendarg - iarg == 2 && in roff_expand()
1454 buf->buf[iarg] == '.' && in roff_expand()
1455 buf->buf[iarg + 1] == 'T') { in roff_expand()
1456 roff_setstrn(&r->strtab, ".T", 2, NULL, 0, 0); in roff_expand()
1462 "%.*s", iendarg - iarg, buf->buf + iarg); in roff_expand()
1466 if (r->mstackpos < 0) { in roff_expand()
1468 "%.*s", iend - iesc, buf->buf + iesc); in roff_expand()
1471 ctx = r->mstack + r->mstackpos; in roff_expand()
1472 argi = buf->buf[iarg] - '1'; in roff_expand()
1474 if (argi < ctx->argc) in roff_expand()
1475 res = ctx->argv[argi]; in roff_expand()
1478 if (buf->buf[iarg] == '*') in roff_expand()
1480 else if (buf->buf[iarg] == '@') in roff_expand()
1484 "%.*s", iend - iesc, buf->buf + iesc); in roff_expand()
1488 for (argi = 0; argi < ctx->argc; argi++) { in roff_expand()
1493 asz += strlen(ctx->argv[argi]); in roff_expand()
1495 if (asz != iend - iesc) { in roff_expand()
1496 rsz = buf->sz - iend; in roff_expand()
1497 if (asz < iend - iesc) in roff_expand()
1498 memmove(buf->buf + iesc + asz, in roff_expand()
1499 buf->buf + iend, rsz); in roff_expand()
1500 buf->sz = iesc + asz + rsz; in roff_expand()
1501 buf->buf = mandoc_realloc(buf->buf, buf->sz); in roff_expand()
1502 if (asz > iend - iesc) in roff_expand()
1503 memmove(buf->buf + iesc + asz, in roff_expand()
1504 buf->buf + iend, rsz); in roff_expand()
1506 dst = buf->buf + iesc; in roff_expand()
1507 for (argi = 0; argi < ctx->argc; argi++) { in roff_expand()
1512 src = ctx->argv[argi]; in roff_expand()
1519 case 'A': in roff_expand()
1527 roff_evalnum(ln, buf->buf + iarg, &npos, in roff_expand()
1529 npos == iendarg - iarg ? '1' : '0'; in roff_expand()
1535 "%.*s", iend - iesc, buf->buf + iesc); in roff_expand()
1544 roff_getregn(r, buf->buf + iarg, in roff_expand()
1545 iendarg - iarg, buf->buf[inam + 1])); in roff_expand()
1555 if (buf->buf[iarg] != '\\') { in roff_expand()
1560 switch ((subtype = roff_escape(buf->buf, 0, in roff_expand()
1587 buf->sz + strlen(res) > SHRT_MAX) { in roff_expand()
1605 buf->sz = mandoc_asprintf(&nbuf, "%.*s%s%s", start, buf->buf, in roff_expand_patch()
1606 repl, buf->buf + end) + 1; in roff_expand_patch()
1607 free(buf->buf); in roff_expand_patch()
1608 buf->buf = nbuf; in roff_expand_patch()
1612 * Parse a quoted or unquoted roff-style request or macro argument.
1613 * Return a pointer to the parsed argument, which is either the original
1615 * NUL-terminate the argument in place.
1627 /* Quoting can only start with a new word. */ in roff_getarg()
1643 cp[-pairs] = cp[0]; in roff_getarg()
1648 * backslashes and backslash-t to literal tabs. in roff_getarg()
1651 case 'a': in roff_getarg()
1653 cp[-pairs] = '\t'; in roff_getarg()
1658 cp[-pairs] = '\\'; in roff_getarg()
1690 /* Quoted argument without a closing quote. */ in roff_getarg()
1694 /* NUL-terminate this argument and move to the next one. */ in roff_getarg()
1696 cp[-pairs] = '\0'; in roff_getarg()
1702 *pos += (int)(cp - start) + (quoted ? 1 : 0); in roff_getarg()
1705 if ('\0' == *cp && (white || ' ' == cp[-1])) in roff_getarg()
1738 isz = mandoc_asprintf(&p, "%s\n.%s", buf->buf, roffit_macro); in roff_parsetext()
1739 free(buf->buf); in roff_parsetext()
1740 buf->buf = p; in roff_parsetext()
1741 buf->sz = isz + 1; in roff_parsetext()
1747 --roffit_lines; in roff_parsetext()
1749 if (roffce_node != NULL && buf->buf[pos] != '\0') { in roff_parsetext()
1751 r->man->last = roffce_node; in roff_parsetext()
1752 r->man->next = ROFF_NEXT_SIBLING; in roff_parsetext()
1756 roffce_lines--; in roff_parsetext()
1761 start = p = buf->buf + pos; in roff_parsetext()
1764 sz = strcspn(p, "-\\"); in roff_parsetext()
1776 while (*p == '-') in roff_parsetext()
1784 if (isalpha((unsigned char)p[-1]) && in roff_parsetext()
1799 int ppos; /* original offset in buf->buf */ in roff_parseln()
1804 if (len > 80 && r->tbl == NULL && r->eqn == NULL && in roff_parseln()
1805 (r->man->flags & ROFF_NOFILL) == 0 && in roff_parseln()
1806 strchr(" .\\", buf->buf[pos]) == NULL && in roff_parseln()
1807 buf->buf[pos] != r->control && in roff_parseln()
1808 strcspn(buf->buf, " ") < 80) in roff_parseln()
1809 mandoc_msg(MANDOCERR_TEXT_LONG, ln, (int)len - 1, in roff_parseln()
1810 "%.20s...", buf->buf + pos); in roff_parseln()
1812 /* Handle in-line equation delimiters. */ in roff_parseln()
1814 if (r->tbl == NULL && in roff_parseln()
1815 r->last_eqn != NULL && r->last_eqn->delim && in roff_parseln()
1816 (r->eqn == NULL || r->eqn_inline)) { in roff_parseln()
1825 e = roff_parse_comment(r, buf, ln, pos, r->escape); in roff_parseln()
1830 e = roff_expand(r, buf, ln, pos, r->escape); in roff_parseln()
1835 ctl = roff_getcontrol(r, buf->buf, &pos); in roff_parseln()
1838 * First, if a scope is open and we're not a macro, pass the in roff_parseln()
1845 if (r->last != NULL && ! ctl) { in roff_parseln()
1846 t = r->last->tok; in roff_parseln()
1853 if (r->eqn != NULL && strncmp(buf->buf + ppos, ".EN", 3)) { in roff_parseln()
1854 eqn_read(r->eqn, buf->buf + ppos); in roff_parseln()
1857 if (r->tbl != NULL && (ctl == 0 || buf->buf[pos] == '\0')) { in roff_parseln()
1858 tbl_read(r->tbl, ln, buf->buf, ppos); in roff_parseln()
1859 roff_addtbl(r->man, ln, r->tbl); in roff_parseln()
1863 r->options &= ~MPARSE_COMMENT; in roff_parseln()
1869 if (buf->buf[pos] == '"') { in roff_parseln()
1872 } else if (buf->buf[pos] == '\0') in roff_parseln()
1876 * If a scope is open, go to the child handler for that macro, in roff_parseln()
1880 if (r->last) { in roff_parseln()
1881 t = r->last->tok; in roff_parseln()
1885 r->options &= ~MPARSE_COMMENT; in roff_parseln()
1887 t = roff_parse(r, buf->buf, &pos, ln, ppos); in roff_parseln()
1892 * Handle a new request or macro.
1893 * May be called outside any scope or from inside a conditional scope.
1900 if (r->tbl != NULL && (tok == TOKEN_NONE || tok == ROFF_TS || in roff_req_or_macro()
1904 ln, ppos, "%s", buf->buf + ppos); in roff_req_or_macro()
1907 while (buf->buf[pos] != '\0' && buf->buf[pos] != ' ') in roff_req_or_macro()
1909 while (buf->buf[pos] == ' ') in roff_req_or_macro()
1911 tbl_read(r->tbl, ln, buf->buf, pos); in roff_req_or_macro()
1912 roff_addtbl(r->man, ln, r->tbl); in roff_req_or_macro()
1921 r->man->last = roffce_node; in roff_req_or_macro()
1922 r->man->next = ROFF_NEXT_SIBLING; in roff_req_or_macro()
1928 * This is neither a roff request nor a user-defined macro. in roff_req_or_macro()
1935 /* Execute a roff request or a user-defined macro. */ in roff_req_or_macro()
1943 * definitions usually do not end with a .return request.
1951 assert(r->mstackpos >= 0); in roff_userret()
1952 ctx = r->mstack + r->mstackpos; in roff_userret()
1953 for (i = 0; i < ctx->argc; i++) in roff_userret()
1954 free(ctx->argv[i]); in roff_userret()
1955 ctx->argc = 0; in roff_userret()
1956 r->mstackpos--; in roff_userret()
1962 if (r->last != NULL) in roff_endparse()
1963 mandoc_msg(MANDOCERR_BLK_NOEND, r->last->line, in roff_endparse()
1964 r->last->col, "%s", roff_name[r->last->tok]); in roff_endparse()
1966 if (r->eqn != NULL) { in roff_endparse()
1968 r->eqn->node->line, r->eqn->node->pos, "EQ"); in roff_endparse()
1969 eqn_parse(r->eqn); in roff_endparse()
1970 r->eqn = NULL; in roff_endparse()
1973 if (r->tbl != NULL) { in roff_endparse()
1974 tbl_end(r->tbl, 1); in roff_endparse()
1975 r->tbl = NULL; in roff_endparse()
1981 * Return ROFF_RENAMED, ROFF_USERDEF, or a ROFF_* token value.
1983 * As a side effect, set r->current_string to the definition or to NULL.
2003 r->current_string = roff_getstrn(r, mac, maclen, &deftype); in roff_parse()
2012 t = roffhash_find(r->reqtab, mac, maclen); in roff_parse()
2016 *pos = cp - buf; in roff_parse()
2019 roff_setstrn(&r->strtab, mac, maclen, "", 0, 0); in roff_parse()
2020 roff_setstrn(&r->rentab, mac, maclen, NULL, 0, 0); in roff_parse()
2025 /* --- handling of request blocks ----------------------------------------- */
2028 * Close a macro definition block or an "ignore" block.
2035 if (r->last == NULL) { in roff_cblock()
2040 switch (r->last->tok) { in roff_cblock()
2060 * If a conditional block with braces is still open, in roff_cblock()
2064 if (r->last != NULL && r->last->endspan < 0) { in roff_cblock()
2069 if (buf->buf[pos] != '\0') in roff_cblock()
2071 ".. %s", buf->buf + pos); in roff_cblock()
2086 while (r->last != NULL && r->last->endspan > 0) { in roffnode_cleanscope()
2087 if (--r->last->endspan != 0) in roffnode_cleanscope()
2095 * Handle the closing "\}" of a conditional block.
2102 if (NULL == r->last) { in roff_ccond()
2107 switch (r->last->tok) { in roff_ccond()
2118 if (r->last->endspan > -1) { in roff_ccond()
2147 cp = buf->buf + pos; in roff_block()
2164 ln, (int)(iname - buf->buf), in roff_block()
2181 * At the beginning of a `de' macro, clear the existing string in roff_block()
2187 roff_setstrn(&r->strtab, name, namesz, "", 0, 0); in roff_block()
2188 roff_setstrn(&r->rentab, name, namesz, NULL, 0, 0); in roff_block()
2193 case ROFFDEF_PRE: /* copy predefined to user-defined. */ in roff_block()
2194 roff_setstrn(&r->strtab, name, namesz, in roff_block()
2200 roff_setstrn(&r->strtab, name, namesz, call, csz, 0); in roff_block()
2201 roff_setstrn(&r->rentab, name, namesz, NULL, 0, 0); in roff_block()
2206 roff_setstrn(&r->rentab, rname, rsz, name, namesz, 0); in roff_block()
2209 roff_setstrn(&r->strtab, name, namesz, call, csz, 0); in roff_block()
2233 ln, (int)(iname - buf->buf), in roff_block()
2242 r->last->end = mandoc_strndup(name, namesz); in roff_block()
2258 * If a custom end marker is a user-defined or predefined macro in roff_block_sub()
2259 * or a request, interpret it. in roff_block_sub()
2262 if (r->last->end) { in roff_block_sub()
2263 for (i = pos, j = 0; r->last->end[j]; j++, i++) in roff_block_sub()
2264 if (buf->buf[i] != r->last->end[j]) in roff_block_sub()
2267 if (r->last->end[j] == '\0' && in roff_block_sub()
2268 (buf->buf[i] == '\0' || in roff_block_sub()
2269 buf->buf[i] == ' ' || in roff_block_sub()
2270 buf->buf[i] == '\t')) { in roff_block_sub()
2274 while (buf->buf[i] == ' ' || buf->buf[i] == '\t') in roff_block_sub()
2278 if (roff_parse(r, buf->buf, &pos, ln, ppos) != in roff_block_sub()
2287 t = roff_parse(r, buf->buf, &pos, ln, ppos); in roff_block_sub()
2294 roff_setstr(r, r->last->name, buf->buf + ppos, 2); in roff_block_sub()
2303 roff_setstr(r, r->last->name, buf->buf + pos, 2); in roff_block_text()
2309 * Check for a closing "\}" and handle it.
2324 rr = r->last->rule; in roff_cond_checkend()
2331 * If "\}" occurs on a macro line without a preceding macro or in roff_cond_checkend()
2332 * a text line contains nothing else, drop the line completely. in roff_cond_checkend()
2335 ep = buf->buf + pos; in roff_cond_checkend()
2353 if (roff_ccond(r, ln, ep - buf->buf)) in roff_cond_checkend()
2369 * Parse and process a request or macro line in conditional scope.
2381 t = roff_parse(r, buf->buf, &pos, ln, ppos); in roff_cond_sub()
2393 for (bl = r->last; bl != NULL; bl = bl->parent) { in roff_cond_sub()
2394 bl->rule = 0; in roff_cond_sub()
2395 if (bl->tok == ROFF_while) in roff_cond_sub()
2408 * Parse and process a text line in conditional scope.
2422 /* --- handling of numeric and conditional expressions -------------------- */
2425 * Parse a single signed decimal number. Stop at the first non-digit.
2437 n = v[p] == '-'; in roff_getnum()
2446 myres = myres * 10.0 + (v[p] - '0'); in roff_getnum()
2449 myres += frac * (v[p] - '0'); in roff_getnum()
2455 myres *= -1.0; in roff_getnum()
2504 * Evaluate a string comparison condition.
2542 *pos = s3 - v; in roff_evalstrcond()
2601 istrue = mchars_spec2cp(start, len) != -1; in roff_evalcond()
2607 istrue = mchars_num2char(start, len) != -1; in roff_evalcond()
2613 *pos = end - v; in roff_evalcond()
2621 sz = roff_getname(&cp, ln, cp - v); in roff_evalcond()
2631 *pos = (name + sz) - v; in roff_evalcond()
2684 r->last->rule = tok == ROFF_el ? in roff_cond()
2685 (r->rstackpos < 0 ? 0 : r->rstack[r->rstackpos--]) : in roff_cond()
2686 roff_evalcond(r, ln, buf->buf, &pos); in roff_cond()
2689 * An if-else will put the NEGATION of the current evaluated in roff_cond()
2694 if (r->rstackpos + 1 == r->rstacksz) { in roff_cond()
2695 r->rstacksz += 16; in roff_cond()
2696 r->rstack = mandoc_reallocarray(r->rstack, in roff_cond()
2697 r->rstacksz, sizeof(int)); in roff_cond()
2699 r->rstack[++r->rstackpos] = !r->last->rule; in roff_cond()
2704 if (r->last->parent && !r->last->parent->rule) in roff_cond()
2705 r->last->rule = 0; in roff_cond()
2710 * not even whitespace, use next-line scope. in roff_cond()
2711 * Except that .while does not support next-line scope. in roff_cond()
2714 if (buf->buf[pos] == '\0' && tok != ROFF_while) { in roff_cond()
2715 r->last->endspan = 2; in roff_cond()
2719 while (buf->buf[pos] == ' ') in roff_cond()
2724 if (buf->buf[pos] == '\\' && buf->buf[pos + 1] == '{') { in roff_cond()
2725 r->last->endspan = -1; in roff_cond()
2727 while (buf->buf[pos] == ' ') in roff_cond()
2734 * single-line scope. Warn if the scope contains in roff_cond()
2738 if (buf->buf[pos] == '\0') in roff_cond()
2742 r->last->endspan = 1; in roff_cond()
2772 name = string = buf->buf + pos; in roff_ds()
2781 string = buf->buf + pos + namesz; in roff_ds()
2787 /* Read past the initial double-quote, if any. */ in roff_ds()
2792 roff_setstrn(&r->strtab, name, namesz, string, strlen(string), in roff_ds()
2794 roff_setstrn(&r->rentab, name, namesz, NULL, 0, 0); in roff_ds()
2799 * Parse a single operator, one or two characters long.
2811 case '-': in roff_getop()
2843 *res = 'a'; in roff_getop()
2863 * Evaluate either a parenthesized numeric expression
2864 * or a single signed integer number.
2893 * Evaluate a complete numeric expression.
2941 case '-': in roff_evalnum()
2942 *res -= operand2; in roff_evalnum()
2993 case 'a': in roff_evalnum()
3004 /* --- register management ------------------------------------------------ */
3019 reg = r->regtab; in roff_setregn()
3021 while (reg != NULL && (reg->key.sz != len || in roff_setregn()
3022 strncmp(reg->key.p, name, len) != 0)) in roff_setregn()
3023 reg = reg->next; in roff_setregn()
3026 /* Create a new register. */ in roff_setregn()
3028 reg->key.p = mandoc_strndup(name, len); in roff_setregn()
3029 reg->key.sz = len; in roff_setregn()
3030 reg->val = 0; in roff_setregn()
3031 reg->step = 0; in roff_setregn()
3032 reg->next = r->regtab; in roff_setregn()
3033 r->regtab = reg; in roff_setregn()
3037 reg->val += val; in roff_setregn()
3038 else if ('-' == sign) in roff_setregn()
3039 reg->val -= val; in roff_setregn()
3041 reg->val = val; in roff_setregn()
3043 reg->step = step; in roff_setregn()
3047 * Handle some predefined read-only number registers.
3048 * For now, return -1 if the requested register is not predefined;
3049 * in case a predefined read-only register having the value -1
3058 return r->mstackpos < 0 ? 0 : r->mstack[r->mstackpos].argc; in roff_getregro()
3059 case 'A': /* ASCII approximation mode is always off. */ in roff_getregro()
3074 return -1; in roff_getregro()
3092 if (-1 != val) in roff_getregn()
3096 for (reg = r->regtab; reg; reg = reg->next) { in roff_getregn()
3097 if (len == reg->key.sz && in roff_getregn()
3098 0 == strncmp(name, reg->key.p, len)) { in roff_getregn()
3101 reg->val += reg->step; in roff_getregn()
3103 case '-': in roff_getregn()
3104 reg->val -= reg->step; in roff_getregn()
3109 return reg->val; in roff_getregn()
3125 if (-1 != val) in roff_hasregn()
3129 for (reg = r->regtab; reg; reg = reg->next) in roff_hasregn()
3130 if (len == reg->key.sz && in roff_hasregn()
3131 0 == strncmp(name, reg->key.p, len)) in roff_hasregn()
3143 free(reg->key.p); in roff_freereg()
3145 reg = reg->next; in roff_freereg()
3158 key = val = buf->buf + pos; in roff_nr()
3167 if (sign == '+' || sign == '-') in roff_nr()
3191 name = cp = buf->buf + pos; in roff_rr()
3197 prev = &r->regtab; in roff_rr()
3200 if (reg == NULL || !strcmp(name, reg->key.p)) in roff_rr()
3202 prev = ®->next; in roff_rr()
3205 *prev = reg->next; in roff_rr()
3206 free(reg->key.p); in roff_rr()
3212 /* --- handler functions for roff requests -------------------------------- */
3221 cp = buf->buf + pos; in roff_rm()
3224 namesz = roff_getname(&cp, ln, (int)(cp - buf->buf)); in roff_rm()
3225 roff_setstrn(&r->strtab, name, namesz, NULL, 0, 0); in roff_rm()
3226 roff_setstrn(&r->rentab, name, namesz, NULL, 0, 0); in roff_rm()
3240 if ( ! roff_evalnum(ln, buf->buf, &pos, &iv, '\0', 0)) { in roff_it()
3242 ln, ppos, "%s", buf->buf + 1); in roff_it()
3246 while (isspace((unsigned char)buf->buf[pos])) in roff_it()
3251 * Special-casing "an-trap" is an ugly workaround to cope in roff_it()
3257 strcmp(buf->buf + pos, "an-trap") ? in roff_it()
3258 buf->buf + pos : "br"); in roff_it()
3272 if (r->format == 0) in roff_Dd()
3273 r->format = MPARSE_MDOC; in roff_Dd()
3279 if (r->format == 0) in roff_Dd()
3280 r->format = MPARSE_MAN; in roff_Dd()
3286 if ((r->options & mask) == 0) in roff_Dd()
3295 r->man->flags &= ~ROFF_NONOFILL; in roff_TE()
3296 if (r->tbl == NULL) { in roff_TE()
3300 if (tbl_end(r->tbl, 0) == 0) { in roff_TE()
3301 r->tbl = NULL; in roff_TE()
3302 free(buf->buf); in roff_TE()
3303 buf->buf = mandoc_strdup(".sp"); in roff_TE()
3304 buf->sz = 4; in roff_TE()
3308 r->tbl = NULL; in roff_TE()
3316 if (NULL == r->tbl) in roff_T_()
3319 tbl_restart(ln, ppos, r->tbl); in roff_T_()
3325 * Handle in-line equation delimiters.
3336 * in-line, or this function wouldn't have been called; in roff_eqndelim()
3337 * so look for a closing delimiter. in roff_eqndelim()
3340 cp1 = buf->buf + pos; in roff_eqndelim()
3341 cp2 = strchr(cp1, r->eqn == NULL ? in roff_eqndelim()
3342 r->last_eqn->odelim : r->last_eqn->cdelim); in roff_eqndelim()
3351 if (*buf->buf != '\0') { in roff_eqndelim()
3352 if (r->eqn == NULL) in roff_eqndelim()
3362 if (r->eqn == NULL) { in roff_eqndelim()
3373 if (r->eqn != NULL) in roff_eqndelim()
3379 buf->sz = mandoc_asprintf(&cp1, "%s%s%s%s%s%s%s", buf->buf, in roff_eqndelim()
3381 free(buf->buf); in roff_eqndelim()
3382 buf->buf = cp1; in roff_eqndelim()
3384 /* Toggle the in-line state of the eqn subsystem. */ in roff_eqndelim()
3386 r->eqn_inline = r->eqn == NULL; in roff_eqndelim()
3395 if (r->man->meta.macroset == MACROSET_MAN) in roff_EQ()
3396 man_breakscope(r->man, ROFF_EQ); in roff_EQ()
3397 n = roff_node_alloc(r->man, ln, ppos, ROFFT_EQN, TOKEN_NONE); in roff_EQ()
3398 if (ln > r->man->last->line) in roff_EQ()
3399 n->flags |= NODE_LINE; in roff_EQ()
3400 n->eqn = eqn_box_new(); in roff_EQ()
3401 roff_node_append(r->man, n); in roff_EQ()
3402 r->man->next = ROFF_NEXT_SIBLING; in roff_EQ()
3404 assert(r->eqn == NULL); in roff_EQ()
3405 if (r->last_eqn == NULL) in roff_EQ()
3406 r->last_eqn = eqn_alloc(); in roff_EQ()
3408 eqn_reset(r->last_eqn); in roff_EQ()
3409 r->eqn = r->last_eqn; in roff_EQ()
3410 r->eqn->node = n; in roff_EQ()
3412 if (buf->buf[pos] != '\0') in roff_EQ()
3414 ".EQ %s", buf->buf + pos); in roff_EQ()
3422 if (r->eqn != NULL) { in roff_EN()
3423 eqn_parse(r->eqn); in roff_EN()
3424 r->eqn = NULL; in roff_EN()
3427 if (buf->buf[pos] != '\0') in roff_EN()
3429 "EN %s", buf->buf + pos); in roff_EN()
3436 if (r->tbl != NULL) { in roff_TS()
3438 tbl_end(r->tbl, 0); in roff_TS()
3440 r->man->flags |= ROFF_NONOFILL; in roff_TS()
3441 r->tbl = tbl_alloc(ppos, ln, r->last_tbl); in roff_TS()
3442 if (r->last_tbl == NULL) in roff_TS()
3443 r->first_tbl = r->tbl; in roff_TS()
3444 r->last_tbl = r->tbl; in roff_TS()
3451 if (r->man->flags & (MAN_BLINE | MAN_ELINE)) in roff_noarg()
3452 man_breakscope(r->man, tok); in roff_noarg()
3455 roff_elem_alloc(r->man, ln, ppos, tok); in roff_noarg()
3456 if (buf->buf[pos] != '\0') in roff_noarg()
3458 "%s %s", roff_name[tok], buf->buf + pos); in roff_noarg()
3460 r->man->flags |= ROFF_NOFILL; in roff_noarg()
3462 r->man->flags &= ~ROFF_NOFILL; in roff_noarg()
3463 r->man->last->flags |= NODE_LINE | NODE_VALID | NODE_ENDED; in roff_noarg()
3464 r->man->next = ROFF_NEXT_SIBLING; in roff_noarg()
3475 if (r->man->flags & (MAN_BLINE | MAN_ELINE) && in roff_onearg()
3478 man_breakscope(r->man, tok); in roff_onearg()
3481 r->man->last = roffce_node; in roff_onearg()
3482 r->man->next = ROFF_NEXT_SIBLING; in roff_onearg()
3485 roff_elem_alloc(r->man, ln, ppos, tok); in roff_onearg()
3486 n = r->man->last; in roff_onearg()
3488 cp = buf->buf + pos; in roff_onearg()
3496 ln, (int)(cp - buf->buf), in roff_onearg()
3498 roff_word_alloc(r->man, ln, pos, buf->buf + pos); in roff_onearg()
3502 if (r->man->last->type == ROFFT_ELEM) { in roff_onearg()
3503 roff_word_alloc(r->man, ln, pos, "1"); in roff_onearg()
3504 r->man->last->flags |= NODE_NOSRC; in roff_onearg()
3507 if (roff_evalnum(ln, r->man->last->string, &npos, in roff_onearg()
3510 ln, pos, "ce %s", buf->buf + pos); in roff_onearg()
3514 r->man->last = r->man->last->parent; in roff_onearg()
3518 roffce_node = r->man->last->parent; in roff_onearg()
3520 n->flags |= NODE_VALID | NODE_ENDED; in roff_onearg()
3521 r->man->last = n; in roff_onearg()
3523 n->flags |= NODE_LINE; in roff_onearg()
3524 r->man->next = ROFF_NEXT_SIBLING; in roff_onearg()
3534 roff_elem_alloc(r->man, ln, ppos, tok); in roff_manyarg()
3535 n = r->man->last; in roff_manyarg()
3537 for (sp = ep = buf->buf + pos; *sp != '\0'; sp = ep) { in roff_manyarg()
3542 roff_word_alloc(r->man, ln, sp - buf->buf, sp); in roff_manyarg()
3545 n->flags |= NODE_LINE | NODE_VALID | NODE_ENDED; in roff_manyarg()
3546 r->man->last = n; in roff_manyarg()
3547 r->man->next = ROFF_NEXT_SIBLING; in roff_manyarg()
3557 newn = oldn = buf->buf + pos; in roff_als()
3566 oldsz = roff_getname(&end, ln, oldn - buf->buf); in roff_als()
3572 roff_setstrn(&r->strtab, newn, newsz, value, valsz, 0); in roff_als()
3573 roff_setstrn(&r->rentab, newn, newsz, NULL, 0, 0); in roff_als()
3594 p = buf->buf + pos; in roff_cc()
3596 if (*p == '\0' || (r->control = *p++) == '.') in roff_cc()
3597 r->control = '\0'; in roff_cc()
3601 ln, p - buf->buf, "cc ... %s", p); in roff_cc()
3615 kp = buf->buf + pos; in roff_char()
3623 ksz = p - kp; in roff_char()
3628 * If the replacement string contains a font escape sequence, in roff_char()
3656 ln, (int)(vp - buf->buf), "%s", vp); in roff_char()
3664 if (r->xtab == NULL) in roff_char()
3665 r->xtab = mandoc_calloc(128, sizeof(*r->xtab)); in roff_char()
3667 free(r->xtab[(int)*kp].p); in roff_char()
3668 r->xtab[(int)*kp].sz = mandoc_asprintf(&r->xtab[(int)*kp].p, in roff_char()
3671 roff_setstrn(&r->xmbtab, kp, ksz, vp, vsz, 0); in roff_char()
3673 roff_setstrn(&r->xmbtab, kp, ksz, "\\fP", 3, 1); in roff_char()
3683 p = buf->buf + pos; in roff_ec()
3685 r->escape = '\\'; in roff_ec()
3687 r->escape = *p; in roff_ec()
3690 (int)(p - buf->buf), "ec ... %s", p); in roff_ec()
3698 r->escape = '\0'; in roff_eo()
3699 if (buf->buf[pos] != '\0') in roff_eo()
3701 ln, pos, "eo %s", buf->buf + pos); in roff_eo()
3713 cp = buf->buf + pos; in roff_mc()
3716 if (buf->buf[pos] == '\\') { in roff_mc()
3725 "mc %s", buf->buf + pos); in roff_mc()
3726 buf->buf[pos] = '\0'; in roff_mc()
3736 mandoc_msg(MANDOCERR_MC_DIST, ln, (int)(cp - buf->buf), in roff_mc()
3743 roff_elem_alloc(r->man, ln, ppos, tok); in roff_mc()
3744 n = r->man->last; in roff_mc()
3745 if (buf->buf[pos] != '\0') in roff_mc()
3746 roff_word_alloc(r->man, ln, pos, buf->buf + pos); in roff_mc()
3747 n->flags |= NODE_LINE | NODE_VALID | NODE_ENDED; in roff_mc()
3748 r->man->last = n; in roff_mc()
3749 r->man->next = ROFF_NEXT_SIBLING; in roff_mc()
3756 while (buf->buf[pos] == ' ') in roff_nop()
3768 p = buf->buf + pos; in roff_tr()
3782 fsz = (size_t)(p - first); in roff_tr()
3789 ssz = (size_t)(p - second); in roff_tr()
3792 (int)(first - buf->buf), "tr %s", first); in roff_tr()
3794 p--; in roff_tr()
3798 roff_setstrn(&r->xmbtab, first, fsz, in roff_tr()
3803 if (r->xtab == NULL) in roff_tr()
3804 r->xtab = mandoc_calloc(128, in roff_tr()
3807 free(r->xtab[(int)*first].p); in roff_tr()
3808 r->xtab[(int)*first].p = mandoc_strndup(second, ssz); in roff_tr()
3809 r->xtab[(int)*first].sz = ssz; in roff_tr()
3824 if (r->mstackpos >= 0) in roff_return()
3839 oldn = newn = buf->buf + pos; in roff_rn()
3848 newsz = roff_getname(&end, ln, newn - buf->buf); in roff_rn()
3856 roff_setstrn(&r->strtab, newn, newsz, value, strlen(value), 0); in roff_rn()
3857 roff_setstrn(&r->strtab, oldn, oldsz, NULL, 0, 0); in roff_rn()
3858 roff_setstrn(&r->rentab, newn, newsz, NULL, 0, 0); in roff_rn()
3861 roff_setstrn(&r->strtab, newn, newsz, value, strlen(value), 0); in roff_rn()
3862 roff_setstrn(&r->rentab, newn, newsz, NULL, 0, 0); in roff_rn()
3865 roff_setstrn(&r->rentab, newn, newsz, value, strlen(value), 0); in roff_rn()
3866 roff_setstrn(&r->rentab, oldn, oldsz, NULL, 0, 0); in roff_rn()
3867 roff_setstrn(&r->strtab, newn, newsz, NULL, 0, 0); in roff_rn()
3870 roff_setstrn(&r->rentab, newn, newsz, oldn, oldsz, 0); in roff_rn()
3871 roff_setstrn(&r->strtab, newn, newsz, NULL, 0, 0); in roff_rn()
3874 roff_setstrn(&r->strtab, newn, newsz, NULL, 0, 0); in roff_rn()
3875 roff_setstrn(&r->rentab, newn, newsz, NULL, 0, 0); in roff_rn()
3889 if (buf->buf[pos] != '\0' && in roff_shift()
3890 roff_evalnum(ln, buf->buf, &pos, &levels, '\0', 0) == 0) { in roff_shift()
3892 ln, pos, "shift %s", buf->buf + pos); in roff_shift()
3895 if (r->mstackpos < 0) { in roff_shift()
3899 ctx = r->mstack + r->mstackpos; in roff_shift()
3900 if (levels > ctx->argc) { in roff_shift()
3902 ln, argpos, "%d, but max is %d", levels, ctx->argc); in roff_shift()
3903 levels = ctx->argc; in roff_shift()
3912 free(ctx->argv[i]); in roff_shift()
3913 ctx->argc -= levels; in roff_shift()
3914 for (i = 0; i < ctx->argc; i++) in roff_shift()
3915 ctx->argv[i] = ctx->argv[i + levels]; in roff_shift()
3924 name = buf->buf + pos; in roff_so()
3930 * it. Thus, explicitly disallow traversing up the file-system in roff_so()
3936 buf->sz = mandoc_asprintf(&cp, in roff_so()
3938 free(buf->buf); in roff_so()
3939 buf->buf = cp; in roff_so()
3948 /* --- user defined strings and macros ------------------------------------ */
3959 if (*r->current_string == '\0') in roff_userdef()
3962 /* Initialize a new macro stack context. */ in roff_userdef()
3964 if (++r->mstackpos == r->mstacksz) { in roff_userdef()
3965 r->mstack = mandoc_recallocarray(r->mstack, in roff_userdef()
3966 r->mstacksz, r->mstacksz + 8, sizeof(*r->mstack)); in roff_userdef()
3967 r->mstacksz += 8; in roff_userdef()
3969 ctx = r->mstack + r->mstackpos; in roff_userdef()
3970 ctx->argc = 0; in roff_userdef()
3974 * NUL-terminating them and escaping quotes. in roff_userdef()
3977 src = buf->buf + pos; in roff_userdef()
3979 if (ctx->argc == ctx->argsz) { in roff_userdef()
3980 ctx->argsz += 8; in roff_userdef()
3981 ctx->argv = mandoc_reallocarray(ctx->argv, in roff_userdef()
3982 ctx->argsz, sizeof(*ctx->argv)); in roff_userdef()
3988 ctx->argv[ctx->argc++] = dst = mandoc_malloc(sz); in roff_userdef()
4002 free(buf->buf); in roff_userdef()
4003 buf->buf = mandoc_strdup(r->current_string); in roff_userdef()
4004 buf->sz = strlen(buf->buf) + 1; in roff_userdef()
4007 return buf->buf[buf->sz - 2] == '\n' ? in roff_userdef()
4012 * Calling a high-level macro that was renamed with .rn.
4013 * r->current_string has already been set up by roff_parse().
4020 buf->sz = mandoc_asprintf(&nbuf, ".%s%s%s", r->current_string, in roff_renamed()
4021 buf->buf[pos] == '\0' ? "" : " ", buf->buf + pos) + 1; in roff_renamed()
4022 free(buf->buf); in roff_renamed()
4023 buf->buf = nbuf; in roff_renamed()
4079 while (iend--) { in roff_getname()
4096 * Store *string into the user-defined string called *name.
4099 * append == 1: single-line append mode
4109 roff_setstrn(&r->strtab, name, namesz, string, in roff_setstr()
4111 roff_setstrn(&r->rentab, name, namesz, NULL, 0, 0); in roff_setstr()
4126 while (n && (namesz != n->key.sz || in roff_setstrn()
4127 strncmp(n->key.p, name, namesz))) in roff_setstrn()
4128 n = n->next; in roff_setstrn()
4131 /* Create a new string table entry. */ in roff_setstrn()
4133 n->key.p = mandoc_strndup(name, namesz); in roff_setstrn()
4134 n->key.sz = namesz; in roff_setstrn()
4135 n->val.p = NULL; in roff_setstrn()
4136 n->val.sz = 0; in roff_setstrn()
4137 n->next = *r; in roff_setstrn()
4140 free(n->val.p); in roff_setstrn()
4141 n->val.p = NULL; in roff_setstrn()
4142 n->val.sz = 0; in roff_setstrn()
4154 if (NULL == n->val.p) { in roff_setstrn()
4155 n->val.p = mandoc_malloc(newch); in roff_setstrn()
4156 *n->val.p = '\0'; in roff_setstrn()
4159 oldch = n->val.sz; in roff_setstrn()
4160 n->val.p = mandoc_realloc(n->val.p, oldch + newch); in roff_setstrn()
4164 c = n->val.p + (int)oldch; in roff_setstrn()
4183 n->val.sz = (int)(c - n->val.p); in roff_setstrn()
4195 for (n = r->strtab; n != NULL; n = n->next) { in roff_getstrn()
4196 if (strncmp(name, n->key.p, len) != 0 || in roff_getstrn()
4197 n->key.p[len] != '\0' || n->val.p == NULL) in roff_getstrn()
4201 return n->val.p; in roff_getstrn()
4207 for (n = r->rentab; n != NULL; n = n->next) { in roff_getstrn()
4208 if (strncmp(name, n->key.p, len) != 0 || in roff_getstrn()
4209 n->key.p[len] != '\0' || n->val.p == NULL) in roff_getstrn()
4213 return n->val.p; in roff_getstrn()
4231 if (r->man->meta.macroset != MACROSET_MAN) { in roff_getstrn()
4245 if (r->man->meta.macroset != MACROSET_MDOC) { in roff_getstrn()
4263 * This might still be a request, in roff_getstrn()
4272 roff_setstrn(&r->strtab, name, len, "", 0, 0); in roff_getstrn()
4273 roff_setstrn(&r->rentab, name, len, NULL, 0, 0); in roff_getstrn()
4286 free(n->key.p); in roff_freestr()
4287 free(n->val.p); in roff_freestr()
4288 nn = n->next; in roff_freestr()
4293 /* --- accessors and utility functions ------------------------------------ */
4298 * Returns a heap-allocated string with all the replacements made.
4309 if (NULL == r->xmbtab && NULL == r->xtab) in roff_strdup()
4316 * (remember that a `tr' can be invoked with an escape, which is in roff_strdup()
4317 * a glyph but the escape is multi-character). in roff_strdup()
4327 if ('\\' != *p && r->xtab && r->xtab[(unsigned int)*p].p) { in roff_strdup()
4328 sz = r->xtab[(int)*p].sz; in roff_strdup()
4330 memcpy(res + ssz, r->xtab[(int)*p].p, sz); in roff_strdup()
4341 for (cp = r->xmbtab; cp; cp = cp->next) in roff_strdup()
4342 if (0 == strncmp(p, cp->key.p, cp->key.sz)) in roff_strdup()
4347 * A match has been found. in roff_strdup()
4352 ssz + cp->val.sz + 1); in roff_strdup()
4353 memcpy(res + ssz, cp->val.p, cp->val.sz); in roff_strdup()
4354 ssz += cp->val.sz; in roff_strdup()
4355 p += (int)cp->key.sz; in roff_strdup()
4378 sz = (int)(p - pp); in roff_strdup()
4392 return r->format; in roff_getformat()
4396 * Find out whether a line is a macro line or not.
4401 * This is slightly contrary to groff, where using the non-breaking
4403 * non-breaking macro contents to be printed verbatim.
4412 if (r->control != '\0' && cp[pos] == r->control) in roff_getcontrol()
4414 else if (r->control != '\0') in roff_getcontrol()