1*260e9a87SYuri Pankov /* $Id: tbl_opts.c,v 1.20 2015/01/28 17:32:07 schwarze Exp $ */
295c635efSGarrett D'Amore /*
395c635efSGarrett D'Amore * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4*260e9a87SYuri Pankov * Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org>
595c635efSGarrett D'Amore *
695c635efSGarrett D'Amore * Permission to use, copy, modify, and distribute this software for any
795c635efSGarrett D'Amore * purpose with or without fee is hereby granted, provided that the above
895c635efSGarrett D'Amore * copyright notice and this permission notice appear in all copies.
995c635efSGarrett D'Amore *
1095c635efSGarrett D'Amore * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1195c635efSGarrett D'Amore * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1295c635efSGarrett D'Amore * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1395c635efSGarrett D'Amore * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1495c635efSGarrett D'Amore * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1595c635efSGarrett D'Amore * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1695c635efSGarrett D'Amore * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1795c635efSGarrett D'Amore */
1895c635efSGarrett D'Amore #include "config.h"
19*260e9a87SYuri Pankov
20*260e9a87SYuri Pankov #include <sys/types.h>
2195c635efSGarrett D'Amore
2295c635efSGarrett D'Amore #include <ctype.h>
2395c635efSGarrett D'Amore #include <stdio.h>
2495c635efSGarrett D'Amore #include <stdlib.h>
2595c635efSGarrett D'Amore #include <string.h>
2695c635efSGarrett D'Amore
2795c635efSGarrett D'Amore #include "mandoc.h"
2895c635efSGarrett D'Amore #include "libmandoc.h"
2995c635efSGarrett D'Amore #include "libroff.h"
3095c635efSGarrett D'Amore
31*260e9a87SYuri Pankov #define KEY_DPOINT 0
32*260e9a87SYuri Pankov #define KEY_DELIM 1
33*260e9a87SYuri Pankov #define KEY_LINESIZE 2
34*260e9a87SYuri Pankov #define KEY_TAB 3
3595c635efSGarrett D'Amore
3695c635efSGarrett D'Amore struct tbl_phrase {
3795c635efSGarrett D'Amore const char *name;
3895c635efSGarrett D'Amore int key;
3995c635efSGarrett D'Amore };
4095c635efSGarrett D'Amore
41*260e9a87SYuri Pankov static const struct tbl_phrase keys[] = {
42*260e9a87SYuri Pankov {"decimalpoint", 0},
43*260e9a87SYuri Pankov {"delim", 0},
44*260e9a87SYuri Pankov {"linesize", 0},
45*260e9a87SYuri Pankov {"tab", 0},
46*260e9a87SYuri Pankov {"allbox", TBL_OPT_ALLBOX | TBL_OPT_BOX},
47*260e9a87SYuri Pankov {"box", TBL_OPT_BOX},
48*260e9a87SYuri Pankov {"frame", TBL_OPT_BOX},
49*260e9a87SYuri Pankov {"center", TBL_OPT_CENTRE},
50*260e9a87SYuri Pankov {"centre", TBL_OPT_CENTRE},
51*260e9a87SYuri Pankov {"doublebox", TBL_OPT_DBOX},
52*260e9a87SYuri Pankov {"doubleframe", TBL_OPT_DBOX},
53*260e9a87SYuri Pankov {"expand", TBL_OPT_EXPAND},
54*260e9a87SYuri Pankov {"nokeep", TBL_OPT_NOKEEP},
55*260e9a87SYuri Pankov {"nospaces", TBL_OPT_NOSPACE},
56*260e9a87SYuri Pankov {"nowarn", TBL_OPT_NOWARN},
5795c635efSGarrett D'Amore };
5895c635efSGarrett D'Amore
59*260e9a87SYuri Pankov #define KEY_MAXKEYS ((int)(sizeof(keys)/sizeof(keys[0])))
6095c635efSGarrett D'Amore
61*260e9a87SYuri Pankov static void arg(struct tbl_node *, int, const char *, int *, int);
62*260e9a87SYuri Pankov
63*260e9a87SYuri Pankov
64*260e9a87SYuri Pankov static void
arg(struct tbl_node * tbl,int ln,const char * p,int * pos,int key)65*260e9a87SYuri Pankov arg(struct tbl_node *tbl, int ln, const char *p, int *pos, int key)
6695c635efSGarrett D'Amore {
67*260e9a87SYuri Pankov int len, want;
6895c635efSGarrett D'Amore
69*260e9a87SYuri Pankov while (p[*pos] == ' ' || p[*pos] == '\t')
7095c635efSGarrett D'Amore (*pos)++;
7195c635efSGarrett D'Amore
72*260e9a87SYuri Pankov /* Arguments are enclosed in parentheses. */
7395c635efSGarrett D'Amore
74*260e9a87SYuri Pankov len = 0;
75*260e9a87SYuri Pankov if (p[*pos] == '(') {
76*260e9a87SYuri Pankov (*pos)++;
77*260e9a87SYuri Pankov while (p[*pos + len] != ')')
78*260e9a87SYuri Pankov len++;
7995c635efSGarrett D'Amore }
8095c635efSGarrett D'Amore
8195c635efSGarrett D'Amore switch (key) {
82*260e9a87SYuri Pankov case KEY_DELIM:
83*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_TBLOPT_EQN, tbl->parse,
84*260e9a87SYuri Pankov ln, *pos, "%.*s", len, p + *pos);
85*260e9a87SYuri Pankov want = 2;
8695c635efSGarrett D'Amore break;
87*260e9a87SYuri Pankov case KEY_TAB:
88*260e9a87SYuri Pankov want = 1;
89*260e9a87SYuri Pankov if (len == want)
90*260e9a87SYuri Pankov tbl->opts.tab = p[*pos];
9195c635efSGarrett D'Amore break;
92*260e9a87SYuri Pankov case KEY_LINESIZE:
93*260e9a87SYuri Pankov want = 0;
9495c635efSGarrett D'Amore break;
95*260e9a87SYuri Pankov case KEY_DPOINT:
96*260e9a87SYuri Pankov want = 1;
97*260e9a87SYuri Pankov if (len == want)
98*260e9a87SYuri Pankov tbl->opts.decimal = p[*pos];
9995c635efSGarrett D'Amore break;
10095c635efSGarrett D'Amore default:
10195c635efSGarrett D'Amore abort();
10295c635efSGarrett D'Amore /* NOTREACHED */
10395c635efSGarrett D'Amore }
10495c635efSGarrett D'Amore
105*260e9a87SYuri Pankov if (len == 0)
106*260e9a87SYuri Pankov mandoc_msg(MANDOCERR_TBLOPT_NOARG,
107*260e9a87SYuri Pankov tbl->parse, ln, *pos, keys[key].name);
108*260e9a87SYuri Pankov else if (want && len != want)
109*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_TBLOPT_ARGSZ,
110*260e9a87SYuri Pankov tbl->parse, ln, *pos, "%s want %d have %d",
111*260e9a87SYuri Pankov keys[key].name, want, len);
11295c635efSGarrett D'Amore
113*260e9a87SYuri Pankov *pos += len;
114*260e9a87SYuri Pankov if (p[*pos] == ')')
115*260e9a87SYuri Pankov (*pos)++;
11695c635efSGarrett D'Amore }
11795c635efSGarrett D'Amore
118*260e9a87SYuri Pankov /*
119*260e9a87SYuri Pankov * Parse one line of options up to the semicolon.
120*260e9a87SYuri Pankov * Each option can be preceded by blanks and/or commas,
121*260e9a87SYuri Pankov * and some options are followed by arguments.
122*260e9a87SYuri Pankov */
123*260e9a87SYuri Pankov void
tbl_option(struct tbl_node * tbl,int ln,const char * p,int * offs)124*260e9a87SYuri Pankov tbl_option(struct tbl_node *tbl, int ln, const char *p, int *offs)
12595c635efSGarrett D'Amore {
126*260e9a87SYuri Pankov int i, pos, len;
12795c635efSGarrett D'Amore
128*260e9a87SYuri Pankov pos = *offs;
129*260e9a87SYuri Pankov for (;;) {
130*260e9a87SYuri Pankov while (p[pos] == ' ' || p[pos] == '\t' || p[pos] == ',')
131*260e9a87SYuri Pankov pos++;
13295c635efSGarrett D'Amore
133*260e9a87SYuri Pankov if (p[pos] == ';') {
134*260e9a87SYuri Pankov *offs = pos + 1;
13595c635efSGarrett D'Amore return;
13695c635efSGarrett D'Amore }
13795c635efSGarrett D'Amore
138*260e9a87SYuri Pankov /* Parse one option name. */
13995c635efSGarrett D'Amore
140*260e9a87SYuri Pankov len = 0;
141*260e9a87SYuri Pankov while (isalpha((unsigned char)p[pos + len]))
142*260e9a87SYuri Pankov len++;
14395c635efSGarrett D'Amore
144*260e9a87SYuri Pankov if (len == 0) {
145*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_TBLOPT_ALPHA,
146*260e9a87SYuri Pankov tbl->parse, ln, pos, "%c", p[pos]);
147*260e9a87SYuri Pankov pos++;
14895c635efSGarrett D'Amore continue;
149*260e9a87SYuri Pankov }
15095c635efSGarrett D'Amore
151*260e9a87SYuri Pankov /* Look up the option name. */
15295c635efSGarrett D'Amore
153*260e9a87SYuri Pankov i = 0;
154*260e9a87SYuri Pankov while (i < KEY_MAXKEYS &&
155*260e9a87SYuri Pankov (strncasecmp(p + pos, keys[i].name, len) ||
156*260e9a87SYuri Pankov keys[i].name[len] != '\0'))
157*260e9a87SYuri Pankov i++;
158*260e9a87SYuri Pankov
159*260e9a87SYuri Pankov if (i == KEY_MAXKEYS) {
160*260e9a87SYuri Pankov mandoc_vmsg(MANDOCERR_TBLOPT_BAD, tbl->parse,
161*260e9a87SYuri Pankov ln, pos, "%.*s", len, p + pos);
162*260e9a87SYuri Pankov pos += len;
163*260e9a87SYuri Pankov continue;
164*260e9a87SYuri Pankov }
165*260e9a87SYuri Pankov
166*260e9a87SYuri Pankov /* Handle the option. */
167*260e9a87SYuri Pankov
168*260e9a87SYuri Pankov pos += len;
16995c635efSGarrett D'Amore if (keys[i].key)
17095c635efSGarrett D'Amore tbl->opts.opts |= keys[i].key;
171*260e9a87SYuri Pankov else
172*260e9a87SYuri Pankov arg(tbl, ln, p, &pos, i);
17395c635efSGarrett D'Amore }
17495c635efSGarrett D'Amore }
175