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