xref: /illumos-gate/usr/src/cmd/mandoc/tbl_opts.c (revision cec8643b)
1*cec8643bSMichal Nowak /*	$Id: tbl_opts.c,v 1.24 2018/12/14 05:18:03 schwarze Exp $ */
295c635efSGarrett D'Amore /*
395c635efSGarrett D'Amore  * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4260e9a87SYuri 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"
19260e9a87SYuri Pankov 
20260e9a87SYuri 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"
28*cec8643bSMichal Nowak #include "tbl.h"
2995c635efSGarrett D'Amore #include "libmandoc.h"
30*cec8643bSMichal Nowak #include "tbl_int.h"
3195c635efSGarrett D'Amore 
32260e9a87SYuri Pankov #define	KEY_DPOINT	0
33260e9a87SYuri Pankov #define	KEY_DELIM	1
34260e9a87SYuri Pankov #define	KEY_LINESIZE	2
35260e9a87SYuri Pankov #define	KEY_TAB		3
3695c635efSGarrett D'Amore 
3795c635efSGarrett D'Amore struct	tbl_phrase {
3895c635efSGarrett D'Amore 	const char	*name;
3995c635efSGarrett D'Amore 	int		 key;
4095c635efSGarrett D'Amore };
4195c635efSGarrett D'Amore 
42260e9a87SYuri Pankov static	const struct tbl_phrase keys[] = {
43260e9a87SYuri Pankov 	{"decimalpoint", 0},
44260e9a87SYuri Pankov 	{"delim",	 0},
45260e9a87SYuri Pankov 	{"linesize",	 0},
46260e9a87SYuri Pankov 	{"tab",		 0},
47260e9a87SYuri Pankov 	{"allbox",	 TBL_OPT_ALLBOX | TBL_OPT_BOX},
48260e9a87SYuri Pankov 	{"box",		 TBL_OPT_BOX},
49260e9a87SYuri Pankov 	{"frame",	 TBL_OPT_BOX},
50260e9a87SYuri Pankov 	{"center",	 TBL_OPT_CENTRE},
51260e9a87SYuri Pankov 	{"centre",	 TBL_OPT_CENTRE},
52260e9a87SYuri Pankov 	{"doublebox",	 TBL_OPT_DBOX},
53260e9a87SYuri Pankov 	{"doubleframe",  TBL_OPT_DBOX},
54260e9a87SYuri Pankov 	{"expand",	 TBL_OPT_EXPAND},
55260e9a87SYuri Pankov 	{"nokeep",	 TBL_OPT_NOKEEP},
56260e9a87SYuri Pankov 	{"nospaces",	 TBL_OPT_NOSPACE},
57260e9a87SYuri Pankov 	{"nowarn",	 TBL_OPT_NOWARN},
58260e9a87SYuri Pankov };
5995c635efSGarrett D'Amore 
60260e9a87SYuri Pankov #define KEY_MAXKEYS ((int)(sizeof(keys)/sizeof(keys[0])))
6195c635efSGarrett D'Amore 
62260e9a87SYuri Pankov static	void	 arg(struct tbl_node *, int, const char *, int *, int);
6395c635efSGarrett D'Amore 
6495c635efSGarrett D'Amore 
65260e9a87SYuri Pankov static void
arg(struct tbl_node * tbl,int ln,const char * p,int * pos,int key)66260e9a87SYuri Pankov arg(struct tbl_node *tbl, int ln, const char *p, int *pos, int key)
6795c635efSGarrett D'Amore {
68260e9a87SYuri Pankov 	int		 len, want;
6995c635efSGarrett D'Amore 
70260e9a87SYuri Pankov 	while (p[*pos] == ' ' || p[*pos] == '\t')
7195c635efSGarrett D'Amore 		(*pos)++;
7295c635efSGarrett D'Amore 
73260e9a87SYuri Pankov 	/* Arguments are enclosed in parentheses. */
7495c635efSGarrett D'Amore 
75260e9a87SYuri Pankov 	len = 0;
76260e9a87SYuri Pankov 	if (p[*pos] == '(') {
77260e9a87SYuri Pankov 		(*pos)++;
78260e9a87SYuri Pankov 		while (p[*pos + len] != ')')
79260e9a87SYuri Pankov 			len++;
8095c635efSGarrett D'Amore 	}
8195c635efSGarrett D'Amore 
8295c635efSGarrett D'Amore 	switch (key) {
83260e9a87SYuri Pankov 	case KEY_DELIM:
84*cec8643bSMichal Nowak 		mandoc_msg(MANDOCERR_TBLOPT_EQN,
85260e9a87SYuri Pankov 		    ln, *pos, "%.*s", len, p + *pos);
86260e9a87SYuri Pankov 		want = 2;
87260e9a87SYuri Pankov 		break;
88260e9a87SYuri Pankov 	case KEY_TAB:
89260e9a87SYuri Pankov 		want = 1;
90260e9a87SYuri Pankov 		if (len == want)
91260e9a87SYuri Pankov 			tbl->opts.tab = p[*pos];
92260e9a87SYuri Pankov 		break;
93260e9a87SYuri Pankov 	case KEY_LINESIZE:
94260e9a87SYuri Pankov 		want = 0;
95260e9a87SYuri Pankov 		break;
96260e9a87SYuri Pankov 	case KEY_DPOINT:
97260e9a87SYuri Pankov 		want = 1;
98260e9a87SYuri Pankov 		if (len == want)
99260e9a87SYuri Pankov 			tbl->opts.decimal = p[*pos];
10095c635efSGarrett D'Amore 		break;
10195c635efSGarrett D'Amore 	default:
10295c635efSGarrett D'Amore 		abort();
10395c635efSGarrett D'Amore 	}
10495c635efSGarrett D'Amore 
105260e9a87SYuri Pankov 	if (len == 0)
106*cec8643bSMichal Nowak 		mandoc_msg(MANDOCERR_TBLOPT_NOARG, ln, *pos,
107*cec8643bSMichal Nowak 		    "%s", keys[key].name);
108260e9a87SYuri Pankov 	else if (want && len != want)
109*cec8643bSMichal Nowak 		mandoc_msg(MANDOCERR_TBLOPT_ARGSZ, ln, *pos,
110*cec8643bSMichal Nowak 		    "%s want %d have %d", keys[key].name, want, len);
11195c635efSGarrett D'Amore 
112260e9a87SYuri Pankov 	*pos += len;
113260e9a87SYuri Pankov 	if (p[*pos] == ')')
114260e9a87SYuri Pankov 		(*pos)++;
11595c635efSGarrett D'Amore }
11695c635efSGarrett D'Amore 
117260e9a87SYuri Pankov /*
118260e9a87SYuri Pankov  * Parse one line of options up to the semicolon.
119260e9a87SYuri Pankov  * Each option can be preceded by blanks and/or commas,
120260e9a87SYuri Pankov  * and some options are followed by arguments.
121260e9a87SYuri Pankov  */
122260e9a87SYuri Pankov void
tbl_option(struct tbl_node * tbl,int ln,const char * p,int * offs)123260e9a87SYuri Pankov tbl_option(struct tbl_node *tbl, int ln, const char *p, int *offs)
12495c635efSGarrett D'Amore {
125260e9a87SYuri Pankov 	int		 i, pos, len;
12695c635efSGarrett D'Amore 
127260e9a87SYuri Pankov 	pos = *offs;
128260e9a87SYuri Pankov 	for (;;) {
129260e9a87SYuri Pankov 		while (p[pos] == ' ' || p[pos] == '\t' || p[pos] == ',')
130260e9a87SYuri Pankov 			pos++;
13195c635efSGarrett D'Amore 
132260e9a87SYuri Pankov 		if (p[pos] == ';') {
133260e9a87SYuri Pankov 			*offs = pos + 1;
134260e9a87SYuri Pankov 			return;
135260e9a87SYuri Pankov 		}
13695c635efSGarrett D'Amore 
137260e9a87SYuri Pankov 		/* Parse one option name. */
13895c635efSGarrett D'Amore 
139260e9a87SYuri Pankov 		len = 0;
140260e9a87SYuri Pankov 		while (isalpha((unsigned char)p[pos + len]))
141260e9a87SYuri Pankov 			len++;
14295c635efSGarrett D'Amore 
143260e9a87SYuri Pankov 		if (len == 0) {
144*cec8643bSMichal Nowak 			mandoc_msg(MANDOCERR_TBLOPT_ALPHA,
145*cec8643bSMichal Nowak 			    ln, pos, "%c", p[pos]);
146260e9a87SYuri Pankov 			pos++;
147260e9a87SYuri Pankov 			continue;
148260e9a87SYuri Pankov 		}
14995c635efSGarrett D'Amore 
150260e9a87SYuri Pankov 		/* Look up the option name. */
15195c635efSGarrett D'Amore 
152260e9a87SYuri Pankov 		i = 0;
153260e9a87SYuri Pankov 		while (i < KEY_MAXKEYS &&
154260e9a87SYuri Pankov 		    (strncasecmp(p + pos, keys[i].name, len) ||
155260e9a87SYuri Pankov 		     keys[i].name[len] != '\0'))
156260e9a87SYuri Pankov 			i++;
15795c635efSGarrett D'Amore 
158260e9a87SYuri Pankov 		if (i == KEY_MAXKEYS) {
159*cec8643bSMichal Nowak 			mandoc_msg(MANDOCERR_TBLOPT_BAD,
160260e9a87SYuri Pankov 			    ln, pos, "%.*s", len, p + pos);
161260e9a87SYuri Pankov 			pos += len;
16295c635efSGarrett D'Amore 			continue;
163260e9a87SYuri Pankov 		}
16495c635efSGarrett D'Amore 
165260e9a87SYuri Pankov 		/* Handle the option. */
16695c635efSGarrett D'Amore 
167260e9a87SYuri Pankov 		pos += len;
168260e9a87SYuri Pankov 		if (keys[i].key)
16995c635efSGarrett D'Amore 			tbl->opts.opts |= keys[i].key;
170260e9a87SYuri Pankov 		else
171260e9a87SYuri Pankov 			arg(tbl, ln, p, &pos, i);
17295c635efSGarrett D'Amore 	}
17395c635efSGarrett D'Amore }
174