/* $Id$ */ /* * Copyright (c) 2008 Kristaps Dzonsons * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all * copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include #include #include #include "mdoc.h" static int termprint_r(size_t, size_t, const struct mdoc_node *); static void termprint_head(size_t, const struct mdoc_meta *); static void termprint_tail(size_t, const struct mdoc_meta *); static char *arch2a(enum mdoc_arch); static char *vol2a(enum mdoc_vol); static char *msec2a(enum mdoc_msec); static size_t ttitle2a(char *, enum mdoc_vol, enum mdoc_msec, enum mdoc_arch, size_t); static char * arch2a(enum mdoc_arch arch) { switch (arch) { case (ARCH_alpha): return("Alpha"); case (ARCH_amd64): return("AMD64"); case (ARCH_amiga): return("Amiga"); case (ARCH_arc): return("ARC"); case (ARCH_arm): return("ARM"); case (ARCH_armish): return("ARMISH"); case (ARCH_aviion): return("AViion"); case (ARCH_hp300): return("HP300"); case (ARCH_hppa): return("HPPA"); case (ARCH_hppa64): return("HPPA64"); case (ARCH_i386): return("i386"); case (ARCH_landisk): return("LANDISK"); case (ARCH_luna88k): return("Luna88k"); case (ARCH_mac68k): return("Mac68k"); case (ARCH_macppc): return("MacPPC"); case (ARCH_mvme68k): return("MVME68k"); case (ARCH_mvme88k): return("MVME88k"); case (ARCH_mvmeppc): return("MVMEPPC"); case (ARCH_pmax): return("PMAX"); case (ARCH_sgi): return("SGI"); case (ARCH_socppc): return("SOCPPC"); case (ARCH_sparc): return("SPARC"); case (ARCH_sparc64): return("SPARC64"); case (ARCH_sun3): return("Sun3"); case (ARCH_vax): return("VAX"); case (ARCH_zaurus): return("Zaurus"); default: break; } return(NULL); } static char * vol2a(enum mdoc_vol vol) { switch (vol) { case (VOL_AMD): return("OpenBSD Ancestral Manual Documents"); case (VOL_IND): return("OpenBSD Manual Master Index"); case (VOL_KM): return("OpenBSD Kernel Manual"); case (VOL_LOCAL): return("OpenBSD Local Manual"); case (VOL_PRM): return("OpenBSD Programmer's Manual"); case (VOL_PS1): return("OpenBSD Programmer's Supplementary Documents"); case (VOL_SMM): return("OpenBSD System Manager's Manual"); case (VOL_URM): return("OpenBSD Reference Manual"); case (VOL_USD): return("OpenBSD User's Supplementary Documents"); default: break; } return(NULL); } static char * msec2a(enum mdoc_msec msec) { switch (msec) { case(MSEC_1): return("1"); case(MSEC_2): return("2"); case(MSEC_3): return("3"); case(MSEC_3f): return("3f"); case(MSEC_3p): return("3p"); case(MSEC_4): return("4"); case(MSEC_5): return("5"); case(MSEC_6): return("6"); case(MSEC_7): return("7"); case(MSEC_8): return("8"); case(MSEC_9): return("9"); case(MSEC_X11): return("X11"); case(MSEC_X11R6): return("X11R6"); case(MSEC_local): return("local"); case(MSEC_n): return("n"); case(MSEC_unass): /* FALLTHROUGH */ case(MSEC_draft): return("draft"); case(MSEC_paper): return("paper"); default: break; } return(NULL); } static size_t ttitle2a(char *dst, enum mdoc_vol vol, enum mdoc_msec msec, enum mdoc_arch arch, size_t sz) { char *p; size_t ssz; if (NULL == (p = vol2a(vol))) switch (msec) { case (MSEC_1): /* FALLTHROUGH */ case (MSEC_6): /* FALLTHROUGH */ case (MSEC_7): p = vol2a(VOL_URM); break; case (MSEC_8): p = vol2a(VOL_SMM); break; case (MSEC_2): /* FALLTHROUGH */ case (MSEC_3): /* FALLTHROUGH */ case (MSEC_4): /* FALLTHROUGH */ case (MSEC_5): p = vol2a(VOL_PRM); break; case (MSEC_9): p = vol2a(VOL_KM); break; default: /* FIXME: capitalise. */ if (NULL == (p = msec2a(msec))) p = msec2a(MSEC_local); break; } assert(p); if ((ssz = strlcpy(dst, p, sz)) >= sz) return(ssz); if ((p = arch2a(arch))) { if ((ssz = strlcat(dst, " (", sz)) >= sz) return(ssz); if ((ssz = strlcat(dst, p, sz)) >= sz) return(ssz); if ((ssz = strlcat(dst, ")", sz)) >= sz) return(ssz); } return(ssz); } static int termprint_r(size_t cols, size_t indent, const struct mdoc_node *node) { return(1); } static void termprint_tail(size_t cols, const struct mdoc_meta *meta) { struct tm *tm; char *buf, *os; size_t sz, osz, ssz, i; if (NULL == (buf = malloc(cols))) err(1, "malloc"); if (NULL == (os = malloc(cols))) err(1, "malloc"); tm = localtime(&meta->date); if (NULL == strftime(buf, cols, "%B %d, %Y", tm)) err(1, "strftime"); osz = strlcpy(os, meta->os, cols); sz = strlen(buf); ssz = sz + osz + 1; if (ssz > cols) { ssz -= cols; assert(ssz <= osz); os[osz - ssz] = 0; ssz = 1; } else ssz = cols - ssz + 1; printf("%s", os); for (i = 0; i < ssz; i++) printf(" "); printf("%s\n", buf); free(buf); free(os); } static void termprint_head(size_t cols, const struct mdoc_meta *meta) { char *msec, *buf, *title; size_t ssz, tsz, ttsz, i; if (NULL == (buf = malloc(cols))) err(1, "malloc"); if (NULL == (title = malloc(cols))) err(1, "malloc"); /* Format the manual page header. */ tsz = ttitle2a(buf, meta->vol, meta->msec, meta->arch, cols); ttsz = strlcpy(title, meta->title, cols); if (NULL == (msec = msec2a(meta->msec))) msec = ""; ssz = (2 * (ttsz + 2 + strlen(msec))) + tsz + 2; if (ssz > cols) { if ((ssz -= cols) % 2) ssz++; ssz /= 2; assert(ssz <= ttsz); title[ttsz - ssz] = 0; ssz = 1; } else ssz = ((cols - ssz) / 2) + 1; printf("%s(%s)", title, msec); for (i = 0; i < ssz; i++) printf(" "); printf("%s", buf); for (i = 0; i < ssz; i++) printf(" "); printf("%s(%s)\n\n", title, msec); free(title); free(buf); } int termprint(const struct mdoc_node *node, const struct mdoc_meta *meta) { size_t cols; if (ERR == setupterm(NULL, STDOUT_FILENO, NULL)) return(0); cols = columns < 60 ? 60 : (size_t)columns; termprint_head(cols, meta); if ( ! termprint_r(cols, 0, node)) return(0); termprint_tail(cols, meta); return(1); }