From 0fabc9bb0c15c25df5ba10958efd2d71fe64e0e8 Mon Sep 17 00:00:00 2001 From: Richard Bradfield Date: Fri, 13 Jul 2018 12:54:53 +0000 Subject: [PATCH] Support extra2 and extra3 in title section The groff .TH title/section macro additionally supports extra arguments: .TH title section [extra1 [extra2 [extra3]]] Extra2 and Extra3 allow changing the left footer and central header respectively. Here we allow the user to specify these fields through an optional extension to the preamble: test(8) "LeftFooter" test(8) "LeftFooter" "CenterHeader" test(8) "" "CenterHeader" --- scdoc.1.scd | 6 +++++- src/main.c | 45 ++++++++++++++++++++++++++++++++++++++++++++- test/preamble | 18 ++++++++++++++++++ diff --git a/scdoc.1.scd b/scdoc.1.scd index 9f485962e04fe96734855d3f0f18f63223526420..2ffe0211ad65d2649cb25bd0db61451ddf4225af 100644 --- a/scdoc.1.scd +++ b/scdoc.1.scd @@ -22,10 +22,14 @@ ## PREAMBLE Each scdoc file must begin with the following preamble: - *name*(_section_) + *name*(_section_) ["left\_footer" ["center\_header"]] The *name* is the name of the man page you are writing, and _section_ is the section you're writing for (see *man*(1) for information on manual sections). + +_left\_footer_ and _center\_header_ are optional arguments which set the text +positioned at those locations in the generated man page, and *must* be surrounded +with double quotes. ## SECTION HEADERS diff --git a/src/main.c b/src/main.c index 1e4bc078790e9b3d147c4143230157288639f5ca..68cced994d327941602a3404973a75577709dec9 100644 --- a/src/main.c +++ b/src/main.c @@ -37,8 +37,31 @@ parser_fatal(p, "Expected manual section"); return -1; } +static str_t *parse_extra(struct parser *p) { + str_t *extra = str_create(); + int ret = str_append_ch(extra, '"'); + assert(ret != -1); + uint32_t ch; + while ((ch = parser_getch(p)) != UTF8_INVALID) { + if (ch == '"') { + ret = str_append_ch(extra, ch); + assert(ret != -1); + return extra; + } else if (ch == '\n') { + parser_fatal(p, "Unclosed extra preamble field"); + break; + } else { + ret = str_append_ch(extra, ch); + assert(ret != -1); + } + } + return NULL; +} + static void parse_preamble(struct parser *p) { str_t *name = str_create(); + int ex = 0; + str_t *extras[2] = { NULL }; int section = -1; uint32_t ch; char date[256]; @@ -51,6 +74,11 @@ if ((ch < 0x80 && isalnum(ch)) || ch == '_' || ch == '-') { assert(str_append_ch(name, ch) != -1); } else if (ch == '(') { section = parse_section(p); + } else if (ch == '"') { + if (ex == 2) { + parser_fatal(p, "Too many extra preamble fields"); + } + extras[ex++] = parse_extra(p); } else if (ch == '\n') { if (name->len == 0) { parser_fatal(p, "Expected preamble"); @@ -59,11 +87,26 @@ if (section == -1) { parser_fatal(p, "Expected manual section"); } char sec[2] = { '0' + section, 0 }; - roff_macro(p, "TH", name->str, sec, date, NULL); + char *ex2 = extras[0] != NULL ? extras[0]->str : NULL; + char *ex3 = extras[1] != NULL ? extras[1]->str : NULL; + fprintf(p->output, ".TH \"%s\" \"%s\" \"%s\"", name->str, sec, date); + /* ex2 and ex3 are already double-quoted */ + if (ex2) { + fprintf(p->output, " %s", ex2); + } + if (ex3) { + fprintf(p->output, " %s", ex3); + } + fprintf(p->output, "\n"); break; } } str_free(name); + for (int i = 0; i < 2; ++i) { + if (extras[i] != NULL) { + str_free(extras[i]); + } + } } static void parse_format(struct parser *p, enum formatting fmt) { diff --git a/test/preamble b/test/preamble index 4d652c73934747ae54f6b29c89696201c81d94ef..03e2d0c528d3ff1b9a590aab6f822f25d0d55913 100755 --- a/test/preamble +++ b/test/preamble @@ -48,3 +48,21 @@ scdoc </dev/null test-manual(8) EOF end 0 + +begin "Handles extra footer field" +scdoc </dev/null +test-manual(8) "Footer" +EOF +end 0 + +begin "Handles both extra fields" +scdoc </dev/null +test-manual(8) "Footer" "Header" +EOF +end 0 + +begin "Emits empty footer correctly" +scdoc </dev/null +test-manual(8) "" "Header" +EOF +end 0 -- 2.48.1