Annotation of src/usr.bin/mandoc/tbl_opts.c, Revision 1.15
1.15 ! schwarze 1: /* $OpenBSD: tbl_opts.c,v 1.14 2018/12/12 21:54:30 schwarze Exp $ */
1.1 schwarze 2: /*
1.2 schwarze 3: * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
1.9 schwarze 4: * Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org>
1.1 schwarze 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.7 schwarze 18: #include <sys/types.h>
19:
1.1 schwarze 20: #include <ctype.h>
21: #include <stdio.h>
22: #include <stdlib.h>
23: #include <string.h>
24:
25: #include "mandoc.h"
1.14 schwarze 26: #include "tbl.h"
1.4 schwarze 27: #include "libmandoc.h"
1.15 ! schwarze 28: #include "tbl_int.h"
1.1 schwarze 29:
1.10 schwarze 30: #define KEY_DPOINT 0
31: #define KEY_DELIM 1
32: #define KEY_LINESIZE 2
33: #define KEY_TAB 3
1.1 schwarze 34:
35: struct tbl_phrase {
36: const char *name;
37: int key;
38: };
39:
1.10 schwarze 40: static const struct tbl_phrase keys[] = {
41: {"decimalpoint", 0},
42: {"delim", 0},
43: {"linesize", 0},
44: {"tab", 0},
45: {"allbox", TBL_OPT_ALLBOX | TBL_OPT_BOX},
46: {"box", TBL_OPT_BOX},
47: {"frame", TBL_OPT_BOX},
48: {"center", TBL_OPT_CENTRE},
49: {"centre", TBL_OPT_CENTRE},
50: {"doublebox", TBL_OPT_DBOX},
51: {"doubleframe", TBL_OPT_DBOX},
52: {"expand", TBL_OPT_EXPAND},
53: {"nokeep", TBL_OPT_NOKEEP},
54: {"nospaces", TBL_OPT_NOSPACE},
55: {"nowarn", TBL_OPT_NOWARN},
56: };
1.1 schwarze 57:
1.10 schwarze 58: #define KEY_MAXKEYS ((int)(sizeof(keys)/sizeof(keys[0])))
1.1 schwarze 59:
1.10 schwarze 60: static void arg(struct tbl_node *, int, const char *, int *, int);
1.1 schwarze 61:
1.5 schwarze 62:
1.9 schwarze 63: static void
1.10 schwarze 64: arg(struct tbl_node *tbl, int ln, const char *p, int *pos, int key)
1.1 schwarze 65: {
1.9 schwarze 66: int len, want;
1.1 schwarze 67:
1.10 schwarze 68: while (p[*pos] == ' ' || p[*pos] == '\t')
1.1 schwarze 69: (*pos)++;
70:
1.9 schwarze 71: /* Arguments are enclosed in parentheses. */
1.1 schwarze 72:
1.9 schwarze 73: len = 0;
74: if (p[*pos] == '(') {
75: (*pos)++;
76: while (p[*pos + len] != ')')
77: len++;
1.1 schwarze 78: }
79:
80: switch (key) {
1.5 schwarze 81: case KEY_DELIM:
1.12 schwarze 82: mandoc_vmsg(MANDOCERR_TBLOPT_EQN, tbl->parse,
83: ln, *pos, "%.*s", len, p + *pos);
1.9 schwarze 84: want = 2;
1.1 schwarze 85: break;
1.5 schwarze 86: case KEY_TAB:
1.9 schwarze 87: want = 1;
88: if (len == want)
89: tbl->opts.tab = p[*pos];
90: break;
1.5 schwarze 91: case KEY_LINESIZE:
1.9 schwarze 92: want = 0;
93: break;
1.5 schwarze 94: case KEY_DPOINT:
1.9 schwarze 95: want = 1;
96: if (len == want)
97: tbl->opts.decimal = p[*pos];
98: break;
1.1 schwarze 99: default:
100: abort();
101: }
102:
1.9 schwarze 103: if (len == 0)
104: mandoc_msg(MANDOCERR_TBLOPT_NOARG,
1.10 schwarze 105: tbl->parse, ln, *pos, keys[key].name);
1.9 schwarze 106: else if (want && len != want)
107: mandoc_vmsg(MANDOCERR_TBLOPT_ARGSZ,
1.10 schwarze 108: tbl->parse, ln, *pos, "%s want %d have %d",
109: keys[key].name, want, len);
1.1 schwarze 110:
1.9 schwarze 111: *pos += len;
112: if (p[*pos] == ')')
113: (*pos)++;
1.1 schwarze 114: }
115:
1.9 schwarze 116: /*
117: * Parse one line of options up to the semicolon.
118: * Each option can be preceded by blanks and/or commas,
119: * and some options are followed by arguments.
120: */
121: void
1.11 schwarze 122: tbl_option(struct tbl_node *tbl, int ln, const char *p, int *offs)
1.1 schwarze 123: {
1.9 schwarze 124: int i, pos, len;
1.1 schwarze 125:
1.11 schwarze 126: pos = *offs;
1.9 schwarze 127: for (;;) {
1.10 schwarze 128: while (p[pos] == ' ' || p[pos] == '\t' || p[pos] == ',')
1.9 schwarze 129: pos++;
1.1 schwarze 130:
1.11 schwarze 131: if (p[pos] == ';') {
132: *offs = pos + 1;
1.9 schwarze 133: return;
1.11 schwarze 134: }
1.1 schwarze 135:
1.9 schwarze 136: /* Parse one option name. */
1.1 schwarze 137:
1.9 schwarze 138: len = 0;
139: while (isalpha((unsigned char)p[pos + len]))
140: len++;
141:
142: if (len == 0) {
143: mandoc_vmsg(MANDOCERR_TBLOPT_ALPHA,
144: tbl->parse, ln, pos, "%c", p[pos]);
145: pos++;
146: continue;
147: }
1.1 schwarze 148:
1.9 schwarze 149: /* Look up the option name. */
1.1 schwarze 150:
1.9 schwarze 151: i = 0;
152: while (i < KEY_MAXKEYS &&
153: (strncasecmp(p + pos, keys[i].name, len) ||
154: keys[i].name[len] != '\0'))
155: i++;
156:
157: if (i == KEY_MAXKEYS) {
158: mandoc_vmsg(MANDOCERR_TBLOPT_BAD, tbl->parse,
159: ln, pos, "%.*s", len, p + pos);
160: pos += len;
1.1 schwarze 161: continue;
1.9 schwarze 162: }
1.1 schwarze 163:
1.9 schwarze 164: /* Handle the option. */
1.1 schwarze 165:
1.9 schwarze 166: pos += len;
1.5 schwarze 167: if (keys[i].key)
1.1 schwarze 168: tbl->opts.opts |= keys[i].key;
1.9 schwarze 169: else
1.10 schwarze 170: arg(tbl, ln, p, &pos, i);
1.1 schwarze 171: }
172: }