version 1.23, 2014/04/07 11:46:03 |
version 1.30, 2014/07/15 19:00:48 |
Line 181 trylink(const char *buf, size_t *start, size_t end, si |
|
Line 181 trylink(const char *buf, size_t *start, size_t end, si |
|
{ |
{ |
size_t linkstart, realend, linkend, |
size_t linkstart, realend, linkend, |
i, j, textsz, stack; |
i, j, textsz, stack; |
const char *text; |
|
|
|
/* |
/* |
* Scan to the start of the terminus. |
* Scan to the start of the terminus. |
Line 218 trylink(const char *buf, size_t *start, size_t end, si |
|
Line 217 trylink(const char *buf, size_t *start, size_t end, si |
|
linkend = dsz > 1 ? realend - 1 : realend; |
linkend = dsz > 1 ? realend - 1 : realend; |
|
|
/* Re-scan to see if we have a title or section. */ |
/* Re-scan to see if we have a title or section. */ |
text = &buf[*start]; |
|
for (textsz = *start; textsz < linkend; textsz++) |
for (textsz = *start; textsz < linkend; textsz++) |
if ('|' == buf[textsz] || '/' == buf[textsz]) |
if ('|' == buf[textsz] || '/' == buf[textsz]) |
break; |
break; |
Line 399 formatcode(struct state *st, const char *buf, size_t * |
|
Line 397 formatcode(struct state *st, const char *buf, size_t * |
|
|
|
/* |
/* |
* First, look up the format code. |
* First, look up the format code. |
* If it's not valid, then exit immediately. |
* If it's not valid, treat it as a NOOP. |
*/ |
*/ |
for (fmt = 0; fmt < FMT__MAX; fmt++) |
for (fmt = 0; fmt < FMT__MAX; fmt++) |
if (buf[*start] == fmts[fmt]) |
if (buf[*start] == fmts[fmt]) |
break; |
break; |
|
|
if (FMT__MAX == fmt) { |
|
putchar(last = buf[(*start)++]); |
|
if ('\\' == last) |
|
putchar('e'); |
|
return(0); |
|
} |
|
|
|
/* |
/* |
* Determine whether we're overriding our delimiter. |
* Determine whether we're overriding our delimiter. |
* According to POD, if we have more than one '<' followed by a |
* According to POD, if we have more than one '<' followed by a |
Line 460 formatcode(struct state *st, const char *buf, size_t * |
|
Line 451 formatcode(struct state *st, const char *buf, size_t * |
|
(*start) += dsz; |
(*start) += dsz; |
break; |
break; |
} |
} |
|
if (*start < end) { |
|
assert('>' == buf[*start]); |
|
(*start)++; |
|
} |
|
if (isspace(last)) |
|
while (*start < end && isspace((int)buf[*start])) |
|
(*start)++; |
return(0); |
return(0); |
} |
} |
|
|
Line 467 formatcode(struct state *st, const char *buf, size_t * |
|
Line 465 formatcode(struct state *st, const char *buf, size_t * |
|
* Check whether we're supposed to print macro stuff (this is |
* Check whether we're supposed to print macro stuff (this is |
* suppressed in, e.g., "Nm" and "Sh" macros). |
* suppressed in, e.g., "Nm" and "Sh" macros). |
*/ |
*/ |
if ( ! nomacro) { |
if (FMT__MAX != fmt && !nomacro) { |
/* |
/* |
* Print out the macro describing this format code. |
* Print out the macro describing this format code. |
* If we're not "reentrant" (not yet on a macro line) |
* If we're not "reentrant" (not yet on a macro line) |
Line 504 formatcode(struct state *st, const char *buf, size_t * |
|
Line 502 formatcode(struct state *st, const char *buf, size_t * |
|
printf("Ar "); |
printf("Ar "); |
break; |
break; |
} |
} |
printf("Sy "); |
if (0 == strncmp(buf + *start, "NULL", 4) && |
|
('=' == buf[*start + 4] || |
|
'>' == buf[*start + 4])) |
|
printf("Dv "); |
|
else |
|
printf("Sy "); |
break; |
break; |
case (FMT_CODE): |
case (FMT_CODE): |
printf("Qo Li "); |
printf("Qo Li "); |
Line 589 formatcode(struct state *st, const char *buf, size_t * |
|
Line 592 formatcode(struct state *st, const char *buf, size_t * |
|
(*start)++; |
(*start)++; |
} |
} |
|
|
|
if (FMT__MAX == fmt) |
|
return(0); |
|
|
if ( ! nomacro && FMT_CODE == fmt) |
if ( ! nomacro && FMT_CODE == fmt) |
printf(" Qc "); |
printf(" Qc "); |
|
|
Line 1085 ordinary(struct state *st, const char *buf, size_t sta |
|
Line 1091 ordinary(struct state *st, const char *buf, size_t sta |
|
} |
} |
|
|
if (start < end - 1 && '<' == buf[start + 1]) { |
if (start < end - 1 && '<' == buf[start + 1]) { |
/* |
|
* We've encountered a format code. |
|
* This is going to trigger a macro no matter |
|
* what, so print a newline now. |
|
* Then print the (possibly nested) macros and |
|
* following that, a newline. |
|
* Consume all whitespace so we don't |
|
* accidentally start an implicit literal line. |
|
* If the macro ends with a flush comma or |
|
* period, let mdoc(7) handle it for us. |
|
*/ |
|
if (formatcode(st, buf, &start, end, 0, 0, seq)) { |
if (formatcode(st, buf, &start, end, 0, 0, seq)) { |
|
/* |
|
* Let mdoc(7) handle trailing punctuation. |
|
* XXX Some punctuation characters |
|
* are not handled yet. |
|
*/ |
if ((start == end - 1 || |
if ((start == end - 1 || |
(start < end - 1 && |
(start < end - 1 && |
(' ' == buf[start + 1] || |
(' ' == buf[start + 1] || |
Line 1106 ordinary(struct state *st, const char *buf, size_t sta |
|
Line 1106 ordinary(struct state *st, const char *buf, size_t sta |
|
putchar(' '); |
putchar(' '); |
putchar(buf[start++]); |
putchar(buf[start++]); |
} |
} |
|
/* End the macro line. */ |
putchar(last = '\n'); |
putchar(last = '\n'); |
|
/* |
|
* Consume all whitespace |
|
* so we don't accidentally start |
|
* an implicit literal line. |
|
*/ |
while (start < end && ' ' == buf[start]) |
while (start < end && ' ' == buf[start]) |
start++; |
start++; |
} |
} |
|
|
dofile(const struct args *args, const char *fname, |
dofile(const struct args *args, const char *fname, |
const struct tm *tm, const char *buf, size_t sz) |
const struct tm *tm, const char *buf, size_t sz) |
{ |
{ |
size_t sup, end, i, cur = 0; |
|
struct state st; |
|
const char *section, *date; |
|
char datebuf[64]; |
char datebuf[64]; |
|
struct state st; |
|
const char *fbase, *fext, *section, *date; |
char *title, *cp; |
char *title, *cp; |
|
size_t sup, end, i, cur = 0; |
|
|
if (0 == sz) |
if (0 == sz) |
return; |
return; |
|
|
/* Title is last path component of the filename. */ |
/* |
|
* Parsing the filename is almost always required, |
|
* except when both the title and the section |
|
* are provided on the command line. |
|
*/ |
|
|
if (NULL != args->title) |
if (NULL == args->title || NULL == args->section) { |
title = strdup(args->title); |
fbase = strrchr(fname, '/'); |
else if (NULL != (cp = strrchr(fname, '/'))) |
if (NULL == fbase) |
title = strdup(cp + 1); |
fbase = fname; |
else |
else |
title = strdup(fname); |
fbase++; |
|
fext = strrchr(fbase, '.'); |
|
} else |
|
fext = NULL; |
|
|
|
/* |
|
* The title will be converted to uppercase, |
|
* so it needs to be copied. |
|
*/ |
|
|
|
title = (NULL != args->title) ? strdup(args->title) : |
|
(NULL != fext) ? strndup(fbase, fext - fbase) : |
|
strdup(fbase); |
|
|
if (NULL == title) { |
if (NULL == title) { |
perror(NULL); |
perror(NULL); |
exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
Line 1193 dofile(const struct args *args, const char *fname, |
|
Line 1215 dofile(const struct args *args, const char *fname, |
|
|
|
/* Section is 1 unless suffix is "pm". */ |
/* Section is 1 unless suffix is "pm". */ |
|
|
if (NULL == (section = args->section)) { |
section = (NULL != args->section) ? args->section : |
section = "1"; |
(NULL == fext || strcmp(fext + 1, "pm")) ? "1" : |
if (NULL != (cp = strrchr(title, '.'))) { |
PERL_SECTION; |
*cp++ = '\0'; |
|
if (0 == strcmp(cp, "pm")) |
|
section = PERL_SECTION; |
|
} |
|
} |
|
|
|
/* Date. Or the given "tm" if not supplied. */ |
/* Date. Or the given "tm" if not supplied. */ |
|
|
Line 1263 readfile(const struct args *args, const char *fname) |
|
Line 1280 readfile(const struct args *args, const char *fname) |
|
time_t ttm; |
time_t ttm; |
struct stat st; |
struct stat st; |
|
|
assert(NULL != fname); |
|
|
|
fd = 0 != strcmp("-", fname) ? |
fd = 0 != strcmp("-", fname) ? |
open(fname, O_RDONLY, 0) : STDIN_FILENO; |
open(fname, O_RDONLY, 0) : STDIN_FILENO; |
|
|
Line 1370 main(int argc, char *argv[]) |
|
Line 1385 main(int argc, char *argv[]) |
|
|
|
/* Accept only a single input file. */ |
/* Accept only a single input file. */ |
|
|
if (argc > 2) |
if (argc > 1) |
return(EXIT_FAILURE); |
goto usage; |
else if (1 == argc) |
else if (1 == argc) |
fname = *argv; |
fname = *argv; |
|
|
Line 1380 main(int argc, char *argv[]) |
|
Line 1395 main(int argc, char *argv[]) |
|
|
|
usage: |
usage: |
fprintf(stderr, "usage: %s [-d date] " |
fprintf(stderr, "usage: %s [-d date] " |
"[-n title] [-s section]\n", name); |
"[-n title] [-s section] [file]\n", name); |
|
|
return(EXIT_FAILURE); |
return(EXIT_FAILURE); |
} |
} |