Annotation of mandoc/mdoc_man.c, Revision 1.1
1.1 ! schwarze 1: /* $Id$ */
! 2: /*
! 3: * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
! 4: *
! 5: * Permission to use, copy, modify, and distribute this software for any
! 6: * purpose with or without fee is hereby granted, provided that the above
! 7: * copyright notice and this permission notice appear in all copies.
! 8: *
! 9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 16: */
! 17: #include <stdio.h>
! 18: #include <string.h>
! 19:
! 20: #include "mandoc.h"
! 21: #include "mdoc.h"
! 22: #include "main.h"
! 23:
! 24: static int need_space = 0;
! 25: static int need_nl = 0;
! 26:
! 27: #define DECL_ARGS const struct mdoc_meta *m, \
! 28: const struct mdoc_node *n
! 29:
! 30: struct manact {
! 31: int (*cond)(DECL_ARGS);
! 32: int (*pre)(DECL_ARGS);
! 33: void (*post)(DECL_ARGS);
! 34: char *prefix;
! 35: char *suffix;
! 36: };
! 37:
! 38: static void print_word(const char *);
! 39: static void print_node(DECL_ARGS);
! 40:
! 41: static int cond_head(DECL_ARGS);
! 42: static int cond_body(DECL_ARGS);
! 43: static int pre_enc(DECL_ARGS);
! 44: static void post_enc(DECL_ARGS);
! 45: static void post_percent(DECL_ARGS);
! 46:
! 47: static int pre_dl(DECL_ARGS);
! 48: static void post_dl(DECL_ARGS);
! 49: static int pre_it(DECL_ARGS);
! 50: static int pre_nm(DECL_ARGS);
! 51: static void post_nm(DECL_ARGS);
! 52: static int pre_ns(DECL_ARGS);
! 53: static int pre_pp(DECL_ARGS);
! 54: static int pre_sh(DECL_ARGS);
! 55: static void post_sh(DECL_ARGS);
! 56: static int pre_xr(DECL_ARGS);
! 57:
! 58:
! 59: static const struct manact manacts[MDOC_MAX] = {
! 60: { NULL, NULL, NULL, NULL, NULL }, /* _Ap */
! 61: { NULL, NULL, NULL, NULL, NULL }, /* _Dd */
! 62: { NULL, NULL, NULL, NULL, NULL }, /* _Dt */
! 63: { NULL, NULL, NULL, NULL, NULL }, /* _Os */
! 64: { NULL, pre_sh, post_sh, NULL, NULL }, /* Sh */
! 65: { NULL, NULL, NULL, NULL, NULL }, /* _Ss */
! 66: { NULL, pre_pp, NULL, NULL, NULL }, /* Pp */
! 67: { NULL, NULL, NULL, NULL, NULL }, /* _D1 */
! 68: { cond_body, pre_dl, post_dl, NULL, NULL }, /* Dl */
! 69: { NULL, NULL, NULL, NULL, NULL }, /* _Bd */
! 70: { NULL, NULL, NULL, NULL, NULL }, /* _Ed */
! 71: { NULL, NULL, NULL, NULL, NULL }, /* _Bl */
! 72: { NULL, NULL, NULL, NULL, NULL }, /* _El */
! 73: { NULL, pre_it, NULL, NULL, NULL }, /* _It */
! 74: { NULL, NULL, NULL, NULL, NULL }, /* _Ad */
! 75: { NULL, NULL, NULL, NULL, NULL }, /* _An */
! 76: { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Ar */
! 77: { NULL, NULL, NULL, NULL, NULL }, /* _Cd */
! 78: { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Cm */
! 79: { NULL, NULL, NULL, NULL, NULL }, /* _Dv */
! 80: { NULL, NULL, NULL, NULL, NULL }, /* _Er */
! 81: { NULL, NULL, NULL, NULL, NULL }, /* _Ev */
! 82: { NULL, pre_enc, post_enc, "The \\fB",
! 83: "\\fP\nutility exits 0 on success, and >0 if an error occurs."
! 84: }, /* Ex */
! 85: { NULL, NULL, NULL, NULL, NULL }, /* _Fa */
! 86: { NULL, NULL, NULL, NULL, NULL }, /* _Fd */
! 87: { NULL, pre_enc, post_enc, "\\fB-", "\\fP" }, /* Fl */
! 88: { NULL, NULL, NULL, NULL, NULL }, /* _Fn */
! 89: { NULL, NULL, NULL, NULL, NULL }, /* _Ft */
! 90: { NULL, NULL, NULL, NULL, NULL }, /* _Ic */
! 91: { NULL, NULL, NULL, NULL, NULL }, /* _In */
! 92: { NULL, NULL, NULL, NULL, NULL }, /* _Li */
! 93: { cond_head, pre_enc, NULL, "\\- ", NULL }, /* Nd */
! 94: { NULL, pre_nm, post_nm, NULL, NULL }, /* Nm */
! 95: { cond_body, pre_enc, post_enc, "[", "]" }, /* Op */
! 96: { NULL, NULL, NULL, NULL, NULL }, /* _Ot */
! 97: { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* _Pa */
! 98: { NULL, NULL, NULL, NULL, NULL }, /* _Rv */
! 99: { NULL, NULL, NULL, NULL, NULL }, /* _St */
! 100: { NULL, NULL, NULL, NULL, NULL }, /* _Va */
! 101: { NULL, NULL, NULL, NULL, NULL }, /* _Vt */
! 102: { NULL, pre_xr, NULL, NULL, NULL }, /* _Xr */
! 103: { NULL, NULL, post_percent, NULL, NULL }, /* _%A */
! 104: { NULL, NULL, NULL, NULL, NULL }, /* _%B */
! 105: { NULL, NULL, post_percent, NULL, NULL }, /* _%D */
! 106: { NULL, NULL, NULL, NULL, NULL }, /* _%I */
! 107: { NULL, pre_enc, post_percent, "\\fI", "\\fP" }, /* %J */
! 108: { NULL, NULL, NULL, NULL, NULL }, /* _%N */
! 109: { NULL, NULL, NULL, NULL, NULL }, /* _%O */
! 110: { NULL, NULL, NULL, NULL, NULL }, /* _%P */
! 111: { NULL, NULL, NULL, NULL, NULL }, /* _%R */
! 112: { NULL, pre_enc, post_percent, "\"", "\"" }, /* %T */
! 113: { NULL, NULL, NULL, NULL, NULL }, /* _%V */
! 114: { NULL, NULL, NULL, NULL, NULL }, /* _Ac */
! 115: { NULL, NULL, NULL, NULL, NULL }, /* _Ao */
! 116: { cond_body, pre_enc, post_enc, "<", ">" }, /* Aq */
! 117: { NULL, NULL, NULL, NULL, NULL }, /* _At */
! 118: { NULL, NULL, NULL, NULL, NULL }, /* _Bc */
! 119: { NULL, NULL, NULL, NULL, NULL }, /* _Bf */
! 120: { NULL, NULL, NULL, NULL, NULL }, /* _Bo */
! 121: { NULL, NULL, NULL, NULL, NULL }, /* _Bq */
! 122: { NULL, NULL, NULL, NULL, NULL }, /* _Bsx */
! 123: { NULL, NULL, NULL, NULL, NULL }, /* _Bx */
! 124: { NULL, NULL, NULL, NULL, NULL }, /* _Db */
! 125: { NULL, NULL, NULL, NULL, NULL }, /* _Dc */
! 126: { NULL, NULL, NULL, NULL, NULL }, /* _Do */
! 127: { cond_body, pre_enc, post_enc, "``", "''" }, /* Dq */
! 128: { NULL, NULL, NULL, NULL, NULL }, /* _Ec */
! 129: { NULL, NULL, NULL, NULL, NULL }, /* _Ef */
! 130: { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* _Em */
! 131: { NULL, NULL, NULL, NULL, NULL }, /* _Eo */
! 132: { NULL, NULL, NULL, NULL, NULL }, /* _Fx */
! 133: { NULL, NULL, NULL, NULL, NULL }, /* _Ms */
! 134: { NULL, NULL, NULL, NULL, NULL }, /* _No */
! 135: { NULL, pre_ns, NULL, NULL, NULL }, /* Ns */
! 136: { NULL, NULL, NULL, NULL, NULL }, /* _Nx */
! 137: { NULL, NULL, NULL, NULL, NULL }, /* _Ox */
! 138: { NULL, NULL, NULL, NULL, NULL }, /* _Pc */
! 139: { NULL, NULL, NULL, NULL, NULL }, /* _Pf */
! 140: { NULL, NULL, NULL, NULL, NULL }, /* _Po */
! 141: { cond_body, pre_enc, post_enc, "(", ")" }, /* _Pq */
! 142: { NULL, NULL, NULL, NULL, NULL }, /* _Qc */
! 143: { cond_body, pre_enc, post_enc, "`", "'" }, /* Ql */
! 144: { NULL, NULL, NULL, NULL, NULL }, /* _Qo */
! 145: { NULL, NULL, NULL, NULL, NULL }, /* _Qq */
! 146: { NULL, NULL, NULL, NULL, NULL }, /* _Re */
! 147: { cond_body, pre_pp, NULL, NULL, NULL }, /* Rs */
! 148: { NULL, NULL, NULL, NULL, NULL }, /* _Sc */
! 149: { NULL, NULL, NULL, NULL, NULL }, /* _So */
! 150: { cond_body, pre_enc, post_enc, "`", "'" }, /* Sq */
! 151: { NULL, NULL, NULL, NULL, NULL }, /* _Sm */
! 152: { NULL, NULL, NULL, NULL, NULL }, /* _Sx */
! 153: { NULL, NULL, NULL, NULL, NULL }, /* _Sy */
! 154: { NULL, NULL, NULL, NULL, NULL }, /* _Tn */
! 155: { NULL, NULL, NULL, NULL, NULL }, /* _Ux */
! 156: { NULL, NULL, NULL, NULL, NULL }, /* _Xc */
! 157: { NULL, NULL, NULL, NULL, NULL }, /* _Xo */
! 158: { NULL, NULL, NULL, NULL, NULL }, /* _Fo */
! 159: { NULL, NULL, NULL, NULL, NULL }, /* _Fc */
! 160: { NULL, NULL, NULL, NULL, NULL }, /* _Oo */
! 161: { NULL, NULL, NULL, NULL, NULL }, /* _Oc */
! 162: { NULL, NULL, NULL, NULL, NULL }, /* _Bk */
! 163: { NULL, NULL, NULL, NULL, NULL }, /* _Ek */
! 164: { NULL, NULL, NULL, NULL, NULL }, /* _Bt */
! 165: { NULL, NULL, NULL, NULL, NULL }, /* _Hf */
! 166: { NULL, NULL, NULL, NULL, NULL }, /* _Fr */
! 167: { NULL, NULL, NULL, NULL, NULL }, /* _Ud */
! 168: { NULL, NULL, NULL, NULL, NULL }, /* _Lb */
! 169: { NULL, NULL, NULL, NULL, NULL }, /* _Lp */
! 170: { NULL, NULL, NULL, NULL, NULL }, /* _Lk */
! 171: { NULL, NULL, NULL, NULL, NULL }, /* _Mt */
! 172: { NULL, NULL, NULL, NULL, NULL }, /* _Brq */
! 173: { NULL, NULL, NULL, NULL, NULL }, /* _Bro */
! 174: { NULL, NULL, NULL, NULL, NULL }, /* _Brc */
! 175: { NULL, NULL, NULL, NULL, NULL }, /* _%C */
! 176: { NULL, NULL, NULL, NULL, NULL }, /* _Es */
! 177: { NULL, NULL, NULL, NULL, NULL }, /* _En */
! 178: { NULL, NULL, NULL, NULL, NULL }, /* _Dx */
! 179: { NULL, NULL, NULL, NULL, NULL }, /* _%Q */
! 180: { NULL, NULL, NULL, NULL, NULL }, /* _br */
! 181: { NULL, NULL, NULL, NULL, NULL }, /* _sp */
! 182: { NULL, NULL, NULL, NULL, NULL }, /* _%U */
! 183: { NULL, NULL, NULL, NULL, NULL }, /* _Ta */
! 184: };
! 185:
! 186:
! 187: static void
! 188: print_word(const char *s)
! 189: {
! 190: if (need_nl) {
! 191: putchar('\n');
! 192: need_space = 0;
! 193: need_nl = 0;
! 194: } else if (need_space &&
! 195: (NULL == strchr(".,:;)]?!", s[0]) || '\0' != s[1]))
! 196: putchar(' ');
! 197: need_space = ('(' != s[0] && '[' != s[0]) || '\0' != s[1];
! 198: for ( ; *s; s++) {
! 199: switch (*s) {
! 200: case (ASCII_NBRSP):
! 201: printf("\\~");
! 202: break;
! 203: case (ASCII_HYPH):
! 204: putchar('-');
! 205: break;
! 206: default:
! 207: putchar(*s);
! 208: break;
! 209: }
! 210: }
! 211: }
! 212:
! 213: void
! 214: man_mdoc(void *arg, const struct mdoc *mdoc)
! 215: {
! 216: const struct mdoc_meta *m;
! 217: const struct mdoc_node *n;
! 218:
! 219: m = mdoc_meta(mdoc);
! 220: n = mdoc_node(mdoc);
! 221:
! 222: printf(".TH \"%s\" \"%s\" \"%s\"", m->title, m->msec, m->date);
! 223: need_nl = 1;
! 224: need_space = 0;
! 225:
! 226: print_node(m, n);
! 227: }
! 228:
! 229: static void
! 230: print_node(DECL_ARGS)
! 231: {
! 232: const struct mdoc_node *prev, *sub;
! 233: const struct manact *act = NULL;
! 234: int cond, do_sub;
! 235:
! 236: prev = n->prev ? n->prev : n->parent;
! 237: if (prev && prev->line < n->line)
! 238: need_nl = 1;
! 239:
! 240: cond = 0;
! 241: do_sub = 1;
! 242: if (MDOC_TEXT == n->type) {
! 243: print_word(n->string);
! 244: } else {
! 245: act = manacts + n->tok;
! 246: cond = NULL == act->cond || (*act->cond)(m, n);
! 247: if (cond && act->pre)
! 248: do_sub = (*act->pre)(m, n);
! 249: }
! 250:
! 251: if (do_sub)
! 252: for (sub = n->child; sub; sub = sub->next)
! 253: print_node(m, sub);
! 254:
! 255: if (cond && act->post)
! 256: (*act->post)(m, n);
! 257: }
! 258:
! 259: static int
! 260: cond_head(DECL_ARGS)
! 261: {
! 262: return(MDOC_HEAD == n->type);
! 263: }
! 264:
! 265: static int
! 266: cond_body(DECL_ARGS)
! 267: {
! 268: return(MDOC_BODY == n->type);
! 269: }
! 270:
! 271: static int
! 272: pre_enc(DECL_ARGS)
! 273: {
! 274: const char *prefix;
! 275:
! 276: prefix = manacts[n->tok].prefix;
! 277: if (NULL == prefix)
! 278: return(1);
! 279: print_word(prefix);
! 280: need_space = 0;
! 281: return(1);
! 282: }
! 283:
! 284: static void
! 285: post_enc(DECL_ARGS)
! 286: {
! 287: const char *suffix;
! 288:
! 289: suffix = manacts[n->tok].suffix;
! 290: if (NULL == suffix)
! 291: return;
! 292: need_space = 0;
! 293: print_word(suffix);
! 294: }
! 295:
! 296: static void
! 297: post_percent(DECL_ARGS)
! 298: {
! 299:
! 300: post_enc(m, n);
! 301: if (n->next)
! 302: print_word(",");
! 303: else {
! 304: print_word(".");
! 305: need_nl = 1;
! 306: }
! 307: }
! 308:
! 309: static int
! 310: pre_dl(DECL_ARGS)
! 311: {
! 312:
! 313: need_nl = 1;
! 314: print_word(".RS 6n");
! 315: need_nl = 1;
! 316: return(1);
! 317: }
! 318:
! 319: static void
! 320: post_dl(DECL_ARGS)
! 321: {
! 322:
! 323: need_nl = 1;
! 324: print_word(".RE");
! 325: need_nl = 1;
! 326: }
! 327:
! 328: static int
! 329: pre_it(DECL_ARGS)
! 330: {
! 331: const struct mdoc_node *bln;
! 332:
! 333: if (MDOC_HEAD == n->type) {
! 334: need_nl = 1;
! 335: print_word(".TP");
! 336: bln = n->parent->parent->prev;
! 337: print_word(bln->norm->Bl.width);
! 338: need_nl = 1;
! 339: }
! 340: return(1);
! 341: }
! 342:
! 343: static int
! 344: pre_nm(DECL_ARGS)
! 345: {
! 346:
! 347: if (MDOC_ELEM != n->type && MDOC_HEAD != n->type)
! 348: return(1);
! 349: print_word("\\fB");
! 350: need_space = 0;
! 351: if (NULL == n->child)
! 352: print_word(m->name);
! 353: return(1);
! 354: }
! 355:
! 356: static void
! 357: post_nm(DECL_ARGS)
! 358: {
! 359:
! 360: if (MDOC_ELEM != n->type && MDOC_HEAD != n->type)
! 361: return;
! 362: need_space = 0;
! 363: print_word("\\fP");
! 364: }
! 365:
! 366: static int
! 367: pre_ns(DECL_ARGS)
! 368: {
! 369:
! 370: need_space = 0;
! 371: return(0);
! 372: }
! 373:
! 374: static int
! 375: pre_pp(DECL_ARGS)
! 376: {
! 377:
! 378: need_nl = 1;
! 379: if (MDOC_It == n->parent->tok)
! 380: print_word(".sp");
! 381: else
! 382: print_word(".PP");
! 383: need_nl = 1;
! 384: return(1);
! 385: }
! 386:
! 387: static int
! 388: pre_sh(DECL_ARGS)
! 389: {
! 390:
! 391: if (MDOC_HEAD != n->type)
! 392: return(1);
! 393: need_nl = 1;
! 394: print_word(".SH \"");
! 395: need_space = 0;
! 396: return(1);
! 397: }
! 398:
! 399: static void
! 400: post_sh(DECL_ARGS)
! 401: {
! 402:
! 403: if (MDOC_HEAD != n->type)
! 404: return;
! 405: need_space = 0;
! 406: print_word("\"");
! 407: need_nl = 1;
! 408: }
! 409:
! 410: static int
! 411: pre_xr(DECL_ARGS)
! 412: {
! 413:
! 414: n = n->child;
! 415: if (NULL == n)
! 416: return(0);
! 417: print_node(m, n);
! 418: n = n->next;
! 419: if (NULL == n)
! 420: return(0);
! 421: need_space = 0;
! 422: print_word("(");
! 423: print_node(m, n);
! 424: print_word(")");
! 425: return(0);
! 426: }
CVSweb