+
+/*
+ * A general text domain macro. When invoked, this opens a scope that
+ * accepts words until either end-of-line, only-punctuation, or a
+ * callable macro. If the word is punctuation (not only-punctuation),
+ * then the scope is closed out, the punctuation appended, then the
+ * scope opened again. If any terminating conditions are met, the scope
+ * is closed out. If this is the first macro in the line and
+ * only-punctuation remains, this punctuation is flushed.
+ */
+int
+macro_text(MACRO_PROT_ARGS)
+{
+ int la, lastpunct, c, sz, fl, argc;
+ struct mdoc_arg argv[MDOC_LINEARG_MAX];
+ char *p;
+
+ la = ppos;
+ lastpunct = 0;
+
+ for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
+ la = *pos;
+
+ c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
+ if (ARGV_EOLN == c)
+ break;
+ if (ARGV_WORD == c) {
+ *pos = la;
+ break;
+ } else if (ARGV_ARG == c)
+ continue;
+
+ mdoc_argv_free(argc, argv);
+ return(0);
+ }
+
+ if (MDOC_LINEARG_MAX == argc) {
+ mdoc_argv_free(argc, argv);
+ return(mdoc_perr(mdoc, line, ppos, "too many arguments"));
+ }
+
+ c = mdoc_elem_alloc(mdoc, line, ppos, tok, argc, argv);
+
+ if (0 == c) {
+ mdoc_argv_free(argc, argv);
+ return(0);
+ }
+
+ mdoc->next = MDOC_NEXT_CHILD;
+
+ fl = ARGS_DELIM;
+ if (MDOC_QUOTABLE & mdoc_macros[tok].flags)
+ fl |= ARGS_QUOTED;
+
+ for (lastpunct = sz = 0; sz + argc < MDOC_LINEARG_MAX; sz++) {
+ la = *pos;
+
+ c = mdoc_args(mdoc, line, pos, buf, fl, &p);
+ if (ARGS_ERROR == c) {
+ mdoc_argv_free(argc, argv);
+ return(0);
+ }
+
+ if (ARGS_EOLN == c)
+ break;
+ if (ARGS_PUNCT == c)
+ break;
+
+ if (-1 == (c = lookup(mdoc, line, la, tok, p)))
+ return(0);
+ else if (MDOC_MAX != c) {
+ if (0 == lastpunct && ! rewind_elem(mdoc, tok)) {
+ mdoc_argv_free(argc, argv);
+ return(0);
+ }
+ mdoc_argv_free(argc, argv);
+
+ c = mdoc_macro(mdoc, c, line, la, pos, buf);
+ if (0 == c)
+ return(0);
+ if (ppos > 1)
+ return(1);
+ return(append_delims(mdoc, tok, line, pos, buf));
+ }
+
+ if (mdoc_isdelim(p)) {
+ if (0 == lastpunct && ! rewind_elem(mdoc, tok)) {
+ mdoc_argv_free(argc, argv);
+ return(0);
+ }
+ lastpunct = 1;
+ } else if (lastpunct) {
+ c = mdoc_elem_alloc(mdoc, line,
+ ppos, tok, argc, argv);
+ if (0 == c) {
+ mdoc_argv_free(argc, argv);
+ return(0);
+ }
+ mdoc->next = MDOC_NEXT_CHILD;
+ lastpunct = 0;
+ }
+
+ if ( ! mdoc_word_alloc(mdoc, line, la, p))
+ return(0);
+ mdoc->next = MDOC_NEXT_SIBLING;
+ }
+
+ mdoc_argv_free(argc, argv);
+
+ if (sz == MDOC_LINEARG_MAX)
+ return(mdoc_perr(mdoc, line, ppos, "too many arguments"));
+
+ if (0 == lastpunct && ! rewind_elem(mdoc, tok))
+ return(0);
+ if (ppos > 1)