Annotation of mandoc/tbl_opts.c, Revision 1.17
1.17 ! schwarze 1: /* $Id: tbl_opts.c,v 1.16 2015/01/14 22:44:55 schwarze Exp $ */
1.1 kristaps 2: /*
1.12 schwarze 3: * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
1.17 ! schwarze 4: * Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org>
1.1 kristaps 5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
1.11 kristaps 18: #include "config.h"
1.14 schwarze 19:
20: #include <sys/types.h>
1.11 kristaps 21:
1.3 kristaps 22: #include <ctype.h>
1.1 kristaps 23: #include <stdio.h>
24: #include <stdlib.h>
25: #include <string.h>
26:
1.3 kristaps 27: #include "mandoc.h"
1.10 kristaps 28: #include "libmandoc.h"
1.1 kristaps 29: #include "libroff.h"
30:
31: enum tbl_ident {
32: KEY_CENTRE = 0,
33: KEY_DELIM,
34: KEY_EXPAND,
35: KEY_BOX,
36: KEY_DBOX,
37: KEY_ALLBOX,
38: KEY_TAB,
39: KEY_LINESIZE,
40: KEY_NOKEEP,
41: KEY_DPOINT,
42: KEY_NOSPACE,
43: KEY_FRAME,
44: KEY_DFRAME,
45: KEY_MAX
46: };
47:
48: struct tbl_phrase {
49: const char *name;
50: int key;
51: enum tbl_ident ident;
52: };
53:
54: /* Handle Commonwealth/American spellings. */
55: #define KEY_MAXKEYS 14
56:
57: static const struct tbl_phrase keys[KEY_MAXKEYS] = {
58: { "center", TBL_OPT_CENTRE, KEY_CENTRE},
59: { "centre", TBL_OPT_CENTRE, KEY_CENTRE},
1.13 schwarze 60: { "delim", 0, KEY_DELIM},
1.1 kristaps 61: { "expand", TBL_OPT_EXPAND, KEY_EXPAND},
1.13 schwarze 62: { "box", TBL_OPT_BOX, KEY_BOX},
63: { "doublebox", TBL_OPT_DBOX, KEY_DBOX},
1.1 kristaps 64: { "allbox", TBL_OPT_ALLBOX, KEY_ALLBOX},
65: { "frame", TBL_OPT_BOX, KEY_FRAME},
66: { "doubleframe", TBL_OPT_DBOX, KEY_DFRAME},
67: { "tab", 0, KEY_TAB},
68: { "linesize", 0, KEY_LINESIZE},
69: { "nokeep", TBL_OPT_NOKEEP, KEY_NOKEEP},
70: { "decimalpoint", 0, KEY_DPOINT},
71: { "nospaces", TBL_OPT_NOSPACE, KEY_NOSPACE},
72: };
73:
1.17 ! schwarze 74: static void arg(struct tbl_node *, int,
1.7 kristaps 75: const char *, int *, enum tbl_ident);
1.1 kristaps 76:
1.13 schwarze 77:
1.17 ! schwarze 78: static void
1.7 kristaps 79: arg(struct tbl_node *tbl, int ln, const char *p, int *pos, enum tbl_ident key)
1.1 kristaps 80: {
1.17 ! schwarze 81: const char *optname;
! 82: int len, want;
1.1 kristaps 83:
1.3 kristaps 84: while (isspace((unsigned char)p[*pos]))
85: (*pos)++;
1.1 kristaps 86:
1.17 ! schwarze 87: /* Arguments are enclosed in parentheses. */
1.3 kristaps 88:
1.17 ! schwarze 89: len = 0;
! 90: if (p[*pos] == '(') {
! 91: (*pos)++;
! 92: while (p[*pos + len] != ')')
! 93: len++;
1.1 kristaps 94: }
95:
96: switch (key) {
1.13 schwarze 97: case KEY_DELIM:
1.17 ! schwarze 98: optname = "delim";
! 99: want = 2;
1.1 kristaps 100: break;
1.13 schwarze 101: case KEY_TAB:
1.17 ! schwarze 102: optname = "tab";
! 103: want = 1;
! 104: if (len == want)
! 105: tbl->opts.tab = p[*pos];
! 106: break;
1.13 schwarze 107: case KEY_LINESIZE:
1.17 ! schwarze 108: optname = "linesize";
! 109: want = 0;
! 110: break;
1.13 schwarze 111: case KEY_DPOINT:
1.17 ! schwarze 112: optname = "decimalpoint";
! 113: want = 1;
! 114: if (len == want)
! 115: tbl->opts.decimal = p[*pos];
! 116: break;
1.1 kristaps 117: default:
118: abort();
1.3 kristaps 119: /* NOTREACHED */
1.1 kristaps 120: }
121:
1.17 ! schwarze 122: if (len == 0)
! 123: mandoc_msg(MANDOCERR_TBLOPT_NOARG,
! 124: tbl->parse, ln, *pos, optname);
! 125: else if (want && len != want)
! 126: mandoc_vmsg(MANDOCERR_TBLOPT_ARGSZ,
! 127: tbl->parse, ln, *pos,
! 128: "%s want %d have %d", optname, want, len);
1.1 kristaps 129:
1.17 ! schwarze 130: *pos += len;
! 131: if (p[*pos] == ')')
! 132: (*pos)++;
1.1 kristaps 133: }
134:
1.17 ! schwarze 135: /*
! 136: * Parse one line of options up to the semicolon.
! 137: * Each option can be preceded by blanks and/or commas,
! 138: * and some options are followed by arguments.
! 139: */
! 140: void
! 141: tbl_option(struct tbl_node *tbl, int ln, const char *p)
1.1 kristaps 142: {
1.17 ! schwarze 143: int i, pos, len;
1.1 kristaps 144:
1.17 ! schwarze 145: pos = 0;
! 146: for (;;) {
! 147: while (isspace((unsigned char)p[pos]) || p[pos] == ',')
! 148: pos++;
1.1 kristaps 149:
1.17 ! schwarze 150: if (p[pos] == ';')
! 151: return;
1.3 kristaps 152:
1.17 ! schwarze 153: /* Parse one option name. */
1.3 kristaps 154:
1.17 ! schwarze 155: len = 0;
! 156: while (isalpha((unsigned char)p[pos + len]))
! 157: len++;
! 158:
! 159: if (len == 0) {
! 160: mandoc_vmsg(MANDOCERR_TBLOPT_ALPHA,
! 161: tbl->parse, ln, pos, "%c", p[pos]);
! 162: pos++;
! 163: continue;
! 164: }
1.3 kristaps 165:
1.17 ! schwarze 166: /* Look up the option name. */
1.3 kristaps 167:
1.17 ! schwarze 168: i = 0;
! 169: while (i < KEY_MAXKEYS &&
! 170: (strncasecmp(p + pos, keys[i].name, len) ||
! 171: keys[i].name[len] != '\0'))
! 172: i++;
! 173:
! 174: if (i == KEY_MAXKEYS) {
! 175: mandoc_vmsg(MANDOCERR_TBLOPT_BAD, tbl->parse,
! 176: ln, pos, "%.*s", len, p + pos);
! 177: pos += len;
1.1 kristaps 178: continue;
1.17 ! schwarze 179: }
1.3 kristaps 180:
1.17 ! schwarze 181: /* Handle the option. */
1.3 kristaps 182:
1.17 ! schwarze 183: pos += len;
1.13 schwarze 184: if (keys[i].key)
1.5 kristaps 185: tbl->opts.opts |= keys[i].key;
1.17 ! schwarze 186: else
! 187: arg(tbl, ln, p, &pos, keys[i].ident);
1.1 kristaps 188: }
189: }
CVSweb