=================================================================== RCS file: /cvs/pod2mdoc/pod2mdoc.c,v retrieving revision 1.18 retrieving revision 1.19 diff -u -p -r1.18 -r1.19 --- pod2mdoc/pod2mdoc.c 2014/04/02 22:36:56 1.18 +++ pod2mdoc/pod2mdoc.c 2014/04/03 10:17:14 1.19 @@ -1,4 +1,4 @@ -/* $Id: pod2mdoc.c,v 1.18 2014/04/02 22:36:56 kristaps Exp $ */ +/* $Id: pod2mdoc.c,v 1.19 2014/04/03 10:17:14 kristaps Exp $ */ /* * Copyright (c) 2014 Kristaps Dzonsons * @@ -27,7 +27,9 @@ #include /* - * In what section can we find Perl manuals? + * In what section can we find Perl module manuals? + * Sometimes (Mac OS X) it's 3pm, sometimes (OpenBSD, etc.) 3p. + * XXX IF YOU CHANGE THIS, CHANGE POD2MDOC.1 AS WELL. */ #define PERL_SECTION "3p" @@ -170,85 +172,117 @@ formatescape(const char *buf, size_t *start, size_t en /* * Run some heuristics to intuit a link format. - * I recognise L as a Perl manpage, printing it in section 3p; - * or a general UNIX foo(5) manpage. - * If I recognise one, I set "start" to be the end of the sequence so + * I set "start" to be the end of the sequence (last right-carrot) so * that the caller can safely just continue processing. - * Otherwise, I don't touch "start". + * If this is just an empty tag, I'll return 0. */ static int trylink(const char *buf, size_t *start, size_t end, size_t dsz) { - size_t sv, nstart, nend, i, j, textsz; + size_t linkstart, realend, linkend, i, j, textsz; const char *text; - int hasdouble; /* * Scan to the start of the terminus. * This function is more or less replicated in the formatcode() * for null or index formatting codes. */ - for (sv = nstart = *start; nstart < end; nstart++) { - if ('>' != buf[nstart]) + for (linkstart = realend = *start; realend < end; realend++) { + if ('>' != buf[realend]) continue; else if (dsz == 1) break; - assert(nstart > 0); - if (' ' != buf[nstart - 1]) + assert(realend > 0); + if (' ' != buf[realend - 1]) continue; - for (i = nstart, j = 0; i < end && j < dsz; j++) + for (i = realend, j = 0; i < end && j < dsz; j++) if ('>' != buf[i++]) break; if (dsz == j) break; } - - /* We don't care about stubs. */ - if (nstart == end || nstart == *start) + + /* Ignore stubs. */ + if (realend == end || realend == *start) return(0); - /* Set nend to the end of content. */ - nend = nstart; - if (dsz > 1) - nend--; + /* Set linkend to the end of content. */ + linkend = dsz > 1 ? realend - 1 : realend; - /* Re-scan to see if we have a title. */ + /* Re-scan to see if we have a title or section. */ text = &buf[*start]; - for (textsz = *start; textsz < nend; textsz++) - if ('|' == buf[textsz]) + for (textsz = *start; textsz < linkend; textsz++) + if ('|' == buf[textsz] || '/' == buf[textsz]) break; - if (textsz < nend) { - sv = textsz + 1; + /* If we have a title, find the section. */ + if (textsz < linkend && '|' == buf[textsz]) { + linkstart = textsz + 1; textsz = textsz - *start; - } else + for (i = linkstart; i < linkend; i++) + if ('/' == buf[i]) + break; + if (i < linkend) + linkend = i; + } else { textsz = 0; + if (textsz < linkend && '/' == buf[textsz]) + linkend = textsz; + } - /* Now see if we're a Perl manual. */ - for (hasdouble = 0, i = sv + 1; i < end; i++) - if (':' == buf[i] && ':' == buf[i - 1]) { - hasdouble = 1; + *start = realend; + + j = linkend - linkstart; + + if (0 == j) + return(0); + + /* See if we qualify as being a link or not. */ + if ((j > 5 && 0 == memcmp("http:", &buf[linkstart], j)) || + (j > 6 && 0 == memcmp("https:", &buf[linkstart], j)) || + (j > 4 && 0 == memcmp("ftp:", &buf[linkstart], j)) || + (j > 5 && 0 == memcmp("sftp:", &buf[linkstart], j)) || + (j > 4 && 0 == memcmp("smb:", &buf[linkstart], j)) || + (j > 4 && 0 == memcmp("afs:", &buf[linkstart], j))) { + printf("Lk %.*s", (int)j, &buf[linkstart]); + return(1); + } + + /* See if we qualify as a mailto. */ + if (j > 7 && 0 == memcmp("mailto:", &buf[linkstart], j)) { + printf("Mt %.*s", (int)j, &buf[linkstart]); + return(1); + } + + /* See if we're a foo(5), foo(5x), or foo(5xx) manpage. */ + if ((j > 3 && ')' == buf[linkend - 1]) && + ('(' == buf[linkend - 3])) { + printf("Xr %.*s %c", (int)(j - 3), + &buf[linkstart], buf[linkend - 2]); + return(1); + } else if ((j > 4 && ')' == buf[linkend - 1]) && + ('(' == buf[linkend - 4])) { + printf("Xr %.*s %.*s", (int)(j - 4), + &buf[linkstart], 2, &buf[linkend - 3]); + return(1); + } else if ((j > 5 && ')' == buf[linkend - 1]) && + ('(' == buf[linkend - 5])) { + printf("Xr %.*s %.*s", (int)(j - 5), + &buf[linkstart], 3, &buf[linkend - 4]); + return(1); + } + + /* Last try: do we have a double-colon? */ + for (i = linkstart + 1; i < linkend; i++) + if (':' == buf[i] && ':' == buf[i - 1]) break; - } - /* - * Provide for some common invocations of the link primitive. - * First, allow us to link to other Perl manuals. - */ - if (hasdouble) + if (i < linkend) printf("Xr %.*s " PERL_SECTION, - (int)(nend - sv), &buf[sv]); - else if (nend - sv > 3 && isalnum(buf[sv]) && - ')' == buf[nend - 1] && - isdigit((int)buf[nend - 2]) && - '(' == buf[nend - 3]) - printf("Xr %.*s %c", - (int)(nend - 3 - sv), - &buf[sv], buf[nend - 2]); + (int)j, &buf[linkstart]); else - return(0); + printf("Xr %.*s 1", (int)j, &buf[linkstart]); - *start = nstart; return(1); } @@ -457,6 +491,7 @@ formatcode(struct state *st, const char *buf, size_t * printf("Qo Li "); break; case (FMT_LINK): + /* Try to link; use "No" if it's empty. */ if ( ! trylink(buf, start, end, dsz)) printf("No "); break;