mandoc 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +7 -0
- data/COPYING +674 -0
- data/README.md +117 -0
- data/ext/mandoc/extconf.rb +59 -0
- data/ext/mandoc/rb_mandoc.c +548 -0
- data/ext/mandoc/rb_mandoc.h +22 -0
- data/lib/mandoc/version.rb +19 -0
- data/lib/mandoc.rb +26 -0
- data/mandoc-1.14.6/LICENSE +55 -0
- data/mandoc-1.14.6/arch.c +54 -0
- data/mandoc-1.14.6/att.c +49 -0
- data/mandoc-1.14.6/catman.c +260 -0
- data/mandoc-1.14.6/cgi.c +1279 -0
- data/mandoc-1.14.6/chars.c +507 -0
- data/mandoc-1.14.6/compat_err.c +103 -0
- data/mandoc-1.14.6/compat_fts.c +696 -0
- data/mandoc-1.14.6/compat_fts.h +106 -0
- data/mandoc-1.14.6/compat_getline.c +59 -0
- data/mandoc-1.14.6/compat_getsubopt.c +87 -0
- data/mandoc-1.14.6/compat_isblank.c +23 -0
- data/mandoc-1.14.6/compat_mkdtemp.c +50 -0
- data/mandoc-1.14.6/compat_mkstemps.c +63 -0
- data/mandoc-1.14.6/compat_ohash.c +330 -0
- data/mandoc-1.14.6/compat_ohash.h +72 -0
- data/mandoc-1.14.6/compat_progname.c +31 -0
- data/mandoc-1.14.6/compat_reallocarray.c +40 -0
- data/mandoc-1.14.6/compat_recallocarray.c +99 -0
- data/mandoc-1.14.6/compat_strcasestr.c +64 -0
- data/mandoc-1.14.6/compat_stringlist.c +135 -0
- data/mandoc-1.14.6/compat_stringlist.h +48 -0
- data/mandoc-1.14.6/compat_strlcat.c +57 -0
- data/mandoc-1.14.6/compat_strlcpy.c +52 -0
- data/mandoc-1.14.6/compat_strndup.c +42 -0
- data/mandoc-1.14.6/compat_strsep.c +70 -0
- data/mandoc-1.14.6/compat_strtonum.c +67 -0
- data/mandoc-1.14.6/compat_vasprintf.c +47 -0
- data/mandoc-1.14.6/config.h +52 -0
- data/mandoc-1.14.6/dba.c +508 -0
- data/mandoc-1.14.6/dba.h +50 -0
- data/mandoc-1.14.6/dba_array.c +190 -0
- data/mandoc-1.14.6/dba_array.h +47 -0
- data/mandoc-1.14.6/dba_read.c +74 -0
- data/mandoc-1.14.6/dba_write.c +127 -0
- data/mandoc-1.14.6/dba_write.h +30 -0
- data/mandoc-1.14.6/dbm.c +480 -0
- data/mandoc-1.14.6/dbm.h +68 -0
- data/mandoc-1.14.6/dbm_map.c +194 -0
- data/mandoc-1.14.6/dbm_map.h +29 -0
- data/mandoc-1.14.6/demandoc.c +260 -0
- data/mandoc-1.14.6/eqn.c +1132 -0
- data/mandoc-1.14.6/eqn.h +72 -0
- data/mandoc-1.14.6/eqn_html.c +246 -0
- data/mandoc-1.14.6/eqn_parse.h +48 -0
- data/mandoc-1.14.6/eqn_term.c +174 -0
- data/mandoc-1.14.6/html.c +1102 -0
- data/mandoc-1.14.6/html.h +142 -0
- data/mandoc-1.14.6/lib.c +35 -0
- data/mandoc-1.14.6/libman.h +42 -0
- data/mandoc-1.14.6/libmandoc.h +85 -0
- data/mandoc-1.14.6/libmdoc.h +87 -0
- data/mandoc-1.14.6/main.c +1375 -0
- data/mandoc-1.14.6/main.h +53 -0
- data/mandoc-1.14.6/man.c +345 -0
- data/mandoc-1.14.6/man.h +21 -0
- data/mandoc-1.14.6/man_html.c +640 -0
- data/mandoc-1.14.6/man_macro.c +470 -0
- data/mandoc-1.14.6/man_term.c +1143 -0
- data/mandoc-1.14.6/man_validate.c +660 -0
- data/mandoc-1.14.6/manconf.h +58 -0
- data/mandoc-1.14.6/mandoc.c +669 -0
- data/mandoc-1.14.6/mandoc.h +329 -0
- data/mandoc-1.14.6/mandoc_aux.c +118 -0
- data/mandoc-1.14.6/mandoc_aux.h +27 -0
- data/mandoc-1.14.6/mandoc_msg.c +375 -0
- data/mandoc-1.14.6/mandoc_ohash.c +65 -0
- data/mandoc-1.14.6/mandoc_ohash.h +23 -0
- data/mandoc-1.14.6/mandoc_parse.h +44 -0
- data/mandoc-1.14.6/mandoc_xr.c +123 -0
- data/mandoc-1.14.6/mandoc_xr.h +31 -0
- data/mandoc-1.14.6/mandocd.c +282 -0
- data/mandoc-1.14.6/mandocdb.c +2448 -0
- data/mandoc-1.14.6/manpath.c +363 -0
- data/mandoc-1.14.6/mansearch.c +851 -0
- data/mandoc-1.14.6/mansearch.h +118 -0
- data/mandoc-1.14.6/mdoc.c +433 -0
- data/mandoc-1.14.6/mdoc.h +158 -0
- data/mandoc-1.14.6/mdoc_argv.c +682 -0
- data/mandoc-1.14.6/mdoc_html.c +1762 -0
- data/mandoc-1.14.6/mdoc_macro.c +1600 -0
- data/mandoc-1.14.6/mdoc_man.c +1850 -0
- data/mandoc-1.14.6/mdoc_markdown.c +1610 -0
- data/mandoc-1.14.6/mdoc_state.c +256 -0
- data/mandoc-1.14.6/mdoc_term.c +1964 -0
- data/mandoc-1.14.6/mdoc_validate.c +3062 -0
- data/mandoc-1.14.6/msec.c +37 -0
- data/mandoc-1.14.6/out.c +544 -0
- data/mandoc-1.14.6/out.h +70 -0
- data/mandoc-1.14.6/preconv.c +179 -0
- data/mandoc-1.14.6/read.c +732 -0
- data/mandoc-1.14.6/roff.c +4390 -0
- data/mandoc-1.14.6/roff.h +561 -0
- data/mandoc-1.14.6/roff_html.c +119 -0
- data/mandoc-1.14.6/roff_int.h +94 -0
- data/mandoc-1.14.6/roff_term.c +266 -0
- data/mandoc-1.14.6/roff_validate.c +151 -0
- data/mandoc-1.14.6/soelim.c +182 -0
- data/mandoc-1.14.6/st.c +82 -0
- data/mandoc-1.14.6/tag.c +327 -0
- data/mandoc-1.14.6/tag.h +35 -0
- data/mandoc-1.14.6/tbl.c +183 -0
- data/mandoc-1.14.6/tbl.h +121 -0
- data/mandoc-1.14.6/tbl_data.c +323 -0
- data/mandoc-1.14.6/tbl_html.c +293 -0
- data/mandoc-1.14.6/tbl_int.h +47 -0
- data/mandoc-1.14.6/tbl_layout.c +376 -0
- data/mandoc-1.14.6/tbl_opts.c +173 -0
- data/mandoc-1.14.6/tbl_parse.h +30 -0
- data/mandoc-1.14.6/tbl_term.c +948 -0
- data/mandoc-1.14.6/term.c +1113 -0
- data/mandoc-1.14.6/term.h +158 -0
- data/mandoc-1.14.6/term_ascii.c +424 -0
- data/mandoc-1.14.6/term_ps.c +1362 -0
- data/mandoc-1.14.6/term_tab.c +130 -0
- data/mandoc-1.14.6/term_tag.c +227 -0
- data/mandoc-1.14.6/term_tag.h +34 -0
- data/mandoc-1.14.6/tree.c +536 -0
- metadata +170 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
/* $Id: tbl_html.c,v 1.38 2021/09/09 16:52:52 schwarze Exp $ */
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
|
4
|
+
* Copyright (c) 2014,2015,2017,2018,2021 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 "config.h"
|
|
19
|
+
|
|
20
|
+
#include <sys/types.h>
|
|
21
|
+
|
|
22
|
+
#include <assert.h>
|
|
23
|
+
#include <stdio.h>
|
|
24
|
+
#include <stdlib.h>
|
|
25
|
+
#include <string.h>
|
|
26
|
+
|
|
27
|
+
#include "mandoc.h"
|
|
28
|
+
#include "roff.h"
|
|
29
|
+
#include "tbl.h"
|
|
30
|
+
#include "out.h"
|
|
31
|
+
#include "html.h"
|
|
32
|
+
|
|
33
|
+
static void html_tblopen(struct html *, const struct tbl_span *);
|
|
34
|
+
static size_t html_tbl_len(size_t, void *);
|
|
35
|
+
static size_t html_tbl_strlen(const char *, void *);
|
|
36
|
+
static size_t html_tbl_sulen(const struct roffsu *, void *);
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
static size_t
|
|
40
|
+
html_tbl_len(size_t sz, void *arg)
|
|
41
|
+
{
|
|
42
|
+
return sz;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
static size_t
|
|
46
|
+
html_tbl_strlen(const char *p, void *arg)
|
|
47
|
+
{
|
|
48
|
+
return strlen(p);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
static size_t
|
|
52
|
+
html_tbl_sulen(const struct roffsu *su, void *arg)
|
|
53
|
+
{
|
|
54
|
+
if (su->scale < 0.0)
|
|
55
|
+
return 0;
|
|
56
|
+
|
|
57
|
+
switch (su->unit) {
|
|
58
|
+
case SCALE_FS: /* 2^16 basic units */
|
|
59
|
+
return su->scale * 65536.0 / 24.0;
|
|
60
|
+
case SCALE_IN: /* 10 characters per inch */
|
|
61
|
+
return su->scale * 10.0;
|
|
62
|
+
case SCALE_CM: /* 2.54 cm per inch */
|
|
63
|
+
return su->scale * 10.0 / 2.54;
|
|
64
|
+
case SCALE_PC: /* 6 pica per inch */
|
|
65
|
+
case SCALE_VS:
|
|
66
|
+
return su->scale * 10.0 / 6.0;
|
|
67
|
+
case SCALE_EN:
|
|
68
|
+
case SCALE_EM:
|
|
69
|
+
return su->scale;
|
|
70
|
+
case SCALE_PT: /* 12 points per pica */
|
|
71
|
+
return su->scale * 10.0 / 6.0 / 12.0;
|
|
72
|
+
case SCALE_BU: /* 24 basic units per character */
|
|
73
|
+
return su->scale / 24.0;
|
|
74
|
+
case SCALE_MM: /* 1/1000 inch */
|
|
75
|
+
return su->scale / 100.0;
|
|
76
|
+
default:
|
|
77
|
+
abort();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
static void
|
|
82
|
+
html_tblopen(struct html *h, const struct tbl_span *sp)
|
|
83
|
+
{
|
|
84
|
+
html_close_paragraph(h);
|
|
85
|
+
if (h->tbl.cols == NULL) {
|
|
86
|
+
h->tbl.len = html_tbl_len;
|
|
87
|
+
h->tbl.slen = html_tbl_strlen;
|
|
88
|
+
h->tbl.sulen = html_tbl_sulen;
|
|
89
|
+
tblcalc(&h->tbl, sp, 0, 0);
|
|
90
|
+
}
|
|
91
|
+
assert(NULL == h->tblt);
|
|
92
|
+
h->tblt = print_otag(h, TAG_TABLE, "c?ss", "tbl",
|
|
93
|
+
"border",
|
|
94
|
+
sp->opts->opts & TBL_OPT_ALLBOX ? "1" : NULL,
|
|
95
|
+
"border-style",
|
|
96
|
+
sp->opts->opts & TBL_OPT_DBOX ? "double" :
|
|
97
|
+
sp->opts->opts & TBL_OPT_BOX ? "solid" : NULL,
|
|
98
|
+
"border-top-style",
|
|
99
|
+
sp->pos == TBL_SPAN_DHORIZ ? "double" :
|
|
100
|
+
sp->pos == TBL_SPAN_HORIZ ? "solid" : NULL);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
void
|
|
104
|
+
print_tblclose(struct html *h)
|
|
105
|
+
{
|
|
106
|
+
|
|
107
|
+
assert(h->tblt);
|
|
108
|
+
print_tagq(h, h->tblt);
|
|
109
|
+
h->tblt = NULL;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
void
|
|
113
|
+
print_tbl(struct html *h, const struct tbl_span *sp)
|
|
114
|
+
{
|
|
115
|
+
const struct tbl_dat *dp;
|
|
116
|
+
const struct tbl_cell *cp;
|
|
117
|
+
const struct tbl_span *psp;
|
|
118
|
+
const struct roffcol *col;
|
|
119
|
+
struct tag *tt;
|
|
120
|
+
const char *hspans, *vspans, *halign, *valign;
|
|
121
|
+
const char *bborder, *lborder, *rborder;
|
|
122
|
+
const char *ccp;
|
|
123
|
+
char hbuf[4], vbuf[4];
|
|
124
|
+
size_t sz;
|
|
125
|
+
enum mandoc_esc save_font;
|
|
126
|
+
int i;
|
|
127
|
+
|
|
128
|
+
if (h->tblt == NULL)
|
|
129
|
+
html_tblopen(h, sp);
|
|
130
|
+
|
|
131
|
+
/*
|
|
132
|
+
* Horizontal lines spanning the whole table
|
|
133
|
+
* are handled by previous or following table rows.
|
|
134
|
+
*/
|
|
135
|
+
|
|
136
|
+
if (sp->pos != TBL_SPAN_DATA)
|
|
137
|
+
return;
|
|
138
|
+
|
|
139
|
+
/* Inhibit printing of spaces: we do padding ourselves. */
|
|
140
|
+
|
|
141
|
+
h->flags |= HTML_NONOSPACE;
|
|
142
|
+
h->flags |= HTML_NOSPACE;
|
|
143
|
+
|
|
144
|
+
/* Draw a vertical line left of this row? */
|
|
145
|
+
|
|
146
|
+
switch (sp->layout->vert) {
|
|
147
|
+
case 2:
|
|
148
|
+
lborder = "double";
|
|
149
|
+
break;
|
|
150
|
+
case 1:
|
|
151
|
+
lborder = "solid";
|
|
152
|
+
break;
|
|
153
|
+
default:
|
|
154
|
+
lborder = NULL;
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/* Draw a horizontal line below this row? */
|
|
159
|
+
|
|
160
|
+
bborder = NULL;
|
|
161
|
+
if ((psp = sp->next) != NULL) {
|
|
162
|
+
switch (psp->pos) {
|
|
163
|
+
case TBL_SPAN_DHORIZ:
|
|
164
|
+
bborder = "double";
|
|
165
|
+
break;
|
|
166
|
+
case TBL_SPAN_HORIZ:
|
|
167
|
+
bborder = "solid";
|
|
168
|
+
break;
|
|
169
|
+
default:
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
tt = print_otag(h, TAG_TR, "ss",
|
|
175
|
+
"border-left-style", lborder,
|
|
176
|
+
"border-bottom-style", bborder);
|
|
177
|
+
|
|
178
|
+
for (dp = sp->first; dp != NULL; dp = dp->next) {
|
|
179
|
+
print_stagq(h, tt);
|
|
180
|
+
|
|
181
|
+
/*
|
|
182
|
+
* Do not generate <td> elements for continuations
|
|
183
|
+
* of spanned cells. Larger <td> elements covering
|
|
184
|
+
* this space were already generated earlier.
|
|
185
|
+
*/
|
|
186
|
+
|
|
187
|
+
cp = dp->layout;
|
|
188
|
+
if (cp->pos == TBL_CELL_SPAN || cp->pos == TBL_CELL_DOWN ||
|
|
189
|
+
(dp->string != NULL && strcmp(dp->string, "\\^") == 0))
|
|
190
|
+
continue;
|
|
191
|
+
|
|
192
|
+
/* Determine the attribute values. */
|
|
193
|
+
|
|
194
|
+
if (dp->hspans > 0) {
|
|
195
|
+
(void)snprintf(hbuf, sizeof(hbuf),
|
|
196
|
+
"%d", dp->hspans + 1);
|
|
197
|
+
hspans = hbuf;
|
|
198
|
+
} else
|
|
199
|
+
hspans = NULL;
|
|
200
|
+
if (dp->vspans > 0) {
|
|
201
|
+
(void)snprintf(vbuf, sizeof(vbuf),
|
|
202
|
+
"%d", dp->vspans + 1);
|
|
203
|
+
vspans = vbuf;
|
|
204
|
+
} else
|
|
205
|
+
vspans = NULL;
|
|
206
|
+
|
|
207
|
+
switch (cp->pos) {
|
|
208
|
+
case TBL_CELL_CENTRE:
|
|
209
|
+
halign = "center";
|
|
210
|
+
break;
|
|
211
|
+
case TBL_CELL_RIGHT:
|
|
212
|
+
case TBL_CELL_NUMBER:
|
|
213
|
+
halign = "right";
|
|
214
|
+
break;
|
|
215
|
+
default:
|
|
216
|
+
halign = NULL;
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
if (cp->flags & TBL_CELL_TALIGN)
|
|
220
|
+
valign = "top";
|
|
221
|
+
else if (cp->flags & TBL_CELL_BALIGN)
|
|
222
|
+
valign = "bottom";
|
|
223
|
+
else
|
|
224
|
+
valign = NULL;
|
|
225
|
+
|
|
226
|
+
for (i = dp->hspans; i > 0; i--)
|
|
227
|
+
cp = cp->next;
|
|
228
|
+
switch (cp->vert) {
|
|
229
|
+
case 2:
|
|
230
|
+
rborder = "double";
|
|
231
|
+
break;
|
|
232
|
+
case 1:
|
|
233
|
+
rborder = "solid";
|
|
234
|
+
break;
|
|
235
|
+
default:
|
|
236
|
+
rborder = NULL;
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/* Print the element and the attributes. */
|
|
241
|
+
|
|
242
|
+
print_otag(h, TAG_TD, "??sss",
|
|
243
|
+
"colspan", hspans, "rowspan", vspans,
|
|
244
|
+
"vertical-align", valign,
|
|
245
|
+
"text-align", halign,
|
|
246
|
+
"border-right-style", rborder);
|
|
247
|
+
if (dp->layout->pos == TBL_CELL_HORIZ ||
|
|
248
|
+
dp->layout->pos == TBL_CELL_DHORIZ ||
|
|
249
|
+
dp->pos == TBL_DATA_HORIZ ||
|
|
250
|
+
dp->pos == TBL_DATA_DHORIZ)
|
|
251
|
+
print_otag(h, TAG_HR, "");
|
|
252
|
+
else if (dp->string != NULL) {
|
|
253
|
+
save_font = h->metac;
|
|
254
|
+
html_setfont(h, dp->layout->font);
|
|
255
|
+
if (dp->layout->pos == TBL_CELL_LONG)
|
|
256
|
+
print_text(h, "\\[u2003]"); /* em space */
|
|
257
|
+
print_text(h, dp->string);
|
|
258
|
+
if (dp->layout->pos == TBL_CELL_NUMBER) {
|
|
259
|
+
col = h->tbl.cols + dp->layout->col;
|
|
260
|
+
if (col->decimal < col->nwidth) {
|
|
261
|
+
if ((ccp = strrchr(dp->string,
|
|
262
|
+
sp->opts->decimal)) == NULL) {
|
|
263
|
+
/* Punctuation space. */
|
|
264
|
+
print_text(h, "\\[u2008]");
|
|
265
|
+
ccp = strchr(dp->string, '\0');
|
|
266
|
+
} else
|
|
267
|
+
ccp++;
|
|
268
|
+
sz = col->nwidth - col->decimal;
|
|
269
|
+
while (--sz > 0) {
|
|
270
|
+
if (*ccp == '\0')
|
|
271
|
+
/* Figure space. */
|
|
272
|
+
print_text(h,
|
|
273
|
+
"\\[u2007]");
|
|
274
|
+
else
|
|
275
|
+
ccp++;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
html_setfont(h, save_font);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
print_tagq(h, tt);
|
|
284
|
+
|
|
285
|
+
h->flags &= ~HTML_NONOSPACE;
|
|
286
|
+
|
|
287
|
+
if (sp->next == NULL) {
|
|
288
|
+
assert(h->tbl.cols);
|
|
289
|
+
free(h->tbl.cols);
|
|
290
|
+
h->tbl.cols = NULL;
|
|
291
|
+
print_tblclose(h);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/* $Id: tbl_int.h,v 1.2 2018/12/14 06:33:14 schwarze Exp $ */
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
|
4
|
+
* Copyright (c) 2011,2013,2015,2017,2018 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 AUTHORS DISCLAIM ALL WARRANTIES
|
|
11
|
+
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
12
|
+
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS 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
|
+
* Internal interfaces of the tbl(7) parser.
|
|
19
|
+
* For use inside the tbl(7) parser only.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
enum tbl_part {
|
|
23
|
+
TBL_PART_OPTS, /* In the first line, ends with semicolon. */
|
|
24
|
+
TBL_PART_LAYOUT, /* In the layout section, ends with full stop. */
|
|
25
|
+
TBL_PART_DATA, /* In the data section, ends with TE. */
|
|
26
|
+
TBL_PART_CDATA /* In a T{ block, ends with T} */
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
struct tbl_node {
|
|
30
|
+
struct tbl_opts opts; /* Options for the whole table. */
|
|
31
|
+
struct tbl_node *next; /* Next table. */
|
|
32
|
+
struct tbl_row *first_row; /* First layout row. */
|
|
33
|
+
struct tbl_row *last_row; /* Last layout row. */
|
|
34
|
+
struct tbl_span *first_span; /* First data row. */
|
|
35
|
+
struct tbl_span *current_span; /* Data row being parsed. */
|
|
36
|
+
struct tbl_span *last_span; /* Last data row. */
|
|
37
|
+
int line; /* Line number in input file. */
|
|
38
|
+
int pos; /* Column number in input file. */
|
|
39
|
+
enum tbl_part part; /* Table section being parsed. */
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
void tbl_option(struct tbl_node *, int, const char *, int *);
|
|
44
|
+
void tbl_layout(struct tbl_node *, int, const char *, int);
|
|
45
|
+
void tbl_data(struct tbl_node *, int, const char *, int);
|
|
46
|
+
void tbl_cdata(struct tbl_node *, int, const char *, int);
|
|
47
|
+
void tbl_reset(struct tbl_node *);
|
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
/* $Id: tbl_layout.c,v 1.50 2021/08/10 12:55:04 schwarze Exp $ */
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
|
|
4
|
+
* Copyright (c) 2012, 2014, 2015, 2017, 2020, 2021
|
|
5
|
+
* Ingo Schwarze <schwarze@openbsd.org>
|
|
6
|
+
*
|
|
7
|
+
* Permission to use, copy, modify, and distribute this software for any
|
|
8
|
+
* purpose with or without fee is hereby granted, provided that the above
|
|
9
|
+
* copyright notice and this permission notice appear in all copies.
|
|
10
|
+
*
|
|
11
|
+
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
12
|
+
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
13
|
+
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
14
|
+
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
15
|
+
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
16
|
+
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
17
|
+
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
18
|
+
*/
|
|
19
|
+
#include "config.h"
|
|
20
|
+
|
|
21
|
+
#include <sys/types.h>
|
|
22
|
+
|
|
23
|
+
#include <ctype.h>
|
|
24
|
+
#include <stdint.h>
|
|
25
|
+
#include <stdio.h>
|
|
26
|
+
#include <stdlib.h>
|
|
27
|
+
#include <string.h>
|
|
28
|
+
#include <time.h>
|
|
29
|
+
|
|
30
|
+
#include "mandoc_aux.h"
|
|
31
|
+
#include "mandoc.h"
|
|
32
|
+
#include "tbl.h"
|
|
33
|
+
#include "libmandoc.h"
|
|
34
|
+
#include "tbl_int.h"
|
|
35
|
+
|
|
36
|
+
struct tbl_phrase {
|
|
37
|
+
char name;
|
|
38
|
+
enum tbl_cellt key;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
static const struct tbl_phrase keys[] = {
|
|
42
|
+
{ 'c', TBL_CELL_CENTRE },
|
|
43
|
+
{ 'r', TBL_CELL_RIGHT },
|
|
44
|
+
{ 'l', TBL_CELL_LEFT },
|
|
45
|
+
{ 'n', TBL_CELL_NUMBER },
|
|
46
|
+
{ 's', TBL_CELL_SPAN },
|
|
47
|
+
{ 'a', TBL_CELL_LONG },
|
|
48
|
+
{ '^', TBL_CELL_DOWN },
|
|
49
|
+
{ '-', TBL_CELL_HORIZ },
|
|
50
|
+
{ '_', TBL_CELL_HORIZ },
|
|
51
|
+
{ '=', TBL_CELL_DHORIZ }
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
#define KEYS_MAX ((int)(sizeof(keys)/sizeof(keys[0])))
|
|
55
|
+
|
|
56
|
+
static void mods(struct tbl_node *, struct tbl_cell *,
|
|
57
|
+
int, const char *, int *);
|
|
58
|
+
static void cell(struct tbl_node *, struct tbl_row *,
|
|
59
|
+
int, const char *, int *);
|
|
60
|
+
static struct tbl_cell *cell_alloc(struct tbl_node *, struct tbl_row *,
|
|
61
|
+
enum tbl_cellt);
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
static void
|
|
65
|
+
mods(struct tbl_node *tbl, struct tbl_cell *cp,
|
|
66
|
+
int ln, const char *p, int *pos)
|
|
67
|
+
{
|
|
68
|
+
char *endptr;
|
|
69
|
+
unsigned long spacing;
|
|
70
|
+
size_t sz;
|
|
71
|
+
int isz;
|
|
72
|
+
enum mandoc_esc fontesc;
|
|
73
|
+
|
|
74
|
+
mod:
|
|
75
|
+
while (p[*pos] == ' ' || p[*pos] == '\t')
|
|
76
|
+
(*pos)++;
|
|
77
|
+
|
|
78
|
+
/* Row delimiters and cell specifiers end modifier lists. */
|
|
79
|
+
|
|
80
|
+
if (strchr(".,-=^_ACLNRSaclnrs", p[*pos]) != NULL)
|
|
81
|
+
return;
|
|
82
|
+
|
|
83
|
+
/* Throw away parenthesised expression. */
|
|
84
|
+
|
|
85
|
+
if ('(' == p[*pos]) {
|
|
86
|
+
(*pos)++;
|
|
87
|
+
while (p[*pos] && ')' != p[*pos])
|
|
88
|
+
(*pos)++;
|
|
89
|
+
if (')' == p[*pos]) {
|
|
90
|
+
(*pos)++;
|
|
91
|
+
goto mod;
|
|
92
|
+
}
|
|
93
|
+
mandoc_msg(MANDOCERR_TBLLAYOUT_PAR, ln, *pos, NULL);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/* Parse numerical spacing from modifier string. */
|
|
98
|
+
|
|
99
|
+
if (isdigit((unsigned char)p[*pos])) {
|
|
100
|
+
if ((spacing = strtoul(p + *pos, &endptr, 10)) > 9)
|
|
101
|
+
mandoc_msg(MANDOCERR_TBLLAYOUT_SPC, ln, *pos,
|
|
102
|
+
"%lu", spacing);
|
|
103
|
+
else
|
|
104
|
+
cp->spacing = spacing;
|
|
105
|
+
*pos = endptr - p;
|
|
106
|
+
goto mod;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
switch (tolower((unsigned char)p[(*pos)++])) {
|
|
110
|
+
case 'b':
|
|
111
|
+
cp->font = ESCAPE_FONTBOLD;
|
|
112
|
+
goto mod;
|
|
113
|
+
case 'd':
|
|
114
|
+
cp->flags |= TBL_CELL_BALIGN;
|
|
115
|
+
goto mod;
|
|
116
|
+
case 'e':
|
|
117
|
+
cp->flags |= TBL_CELL_EQUAL;
|
|
118
|
+
goto mod;
|
|
119
|
+
case 'f':
|
|
120
|
+
break;
|
|
121
|
+
case 'i':
|
|
122
|
+
cp->font = ESCAPE_FONTITALIC;
|
|
123
|
+
goto mod;
|
|
124
|
+
case 'm':
|
|
125
|
+
mandoc_msg(MANDOCERR_TBLLAYOUT_MOD, ln, *pos, "m");
|
|
126
|
+
goto mod;
|
|
127
|
+
case 'p':
|
|
128
|
+
case 'v':
|
|
129
|
+
if (p[*pos] == '-' || p[*pos] == '+')
|
|
130
|
+
(*pos)++;
|
|
131
|
+
while (isdigit((unsigned char)p[*pos]))
|
|
132
|
+
(*pos)++;
|
|
133
|
+
goto mod;
|
|
134
|
+
case 't':
|
|
135
|
+
cp->flags |= TBL_CELL_TALIGN;
|
|
136
|
+
goto mod;
|
|
137
|
+
case 'u':
|
|
138
|
+
cp->flags |= TBL_CELL_UP;
|
|
139
|
+
goto mod;
|
|
140
|
+
case 'w':
|
|
141
|
+
sz = 0;
|
|
142
|
+
if (p[*pos] == '(') {
|
|
143
|
+
(*pos)++;
|
|
144
|
+
while (p[*pos + sz] != '\0' && p[*pos + sz] != ')')
|
|
145
|
+
sz++;
|
|
146
|
+
} else
|
|
147
|
+
while (isdigit((unsigned char)p[*pos + sz]))
|
|
148
|
+
sz++;
|
|
149
|
+
if (sz) {
|
|
150
|
+
free(cp->wstr);
|
|
151
|
+
cp->wstr = mandoc_strndup(p + *pos, sz);
|
|
152
|
+
*pos += sz;
|
|
153
|
+
if (p[*pos] == ')')
|
|
154
|
+
(*pos)++;
|
|
155
|
+
}
|
|
156
|
+
goto mod;
|
|
157
|
+
case 'x':
|
|
158
|
+
cp->flags |= TBL_CELL_WMAX;
|
|
159
|
+
goto mod;
|
|
160
|
+
case 'z':
|
|
161
|
+
cp->flags |= TBL_CELL_WIGN;
|
|
162
|
+
goto mod;
|
|
163
|
+
case '|':
|
|
164
|
+
if (cp->vert < 2)
|
|
165
|
+
cp->vert++;
|
|
166
|
+
else
|
|
167
|
+
mandoc_msg(MANDOCERR_TBLLAYOUT_VERT,
|
|
168
|
+
ln, *pos - 1, NULL);
|
|
169
|
+
goto mod;
|
|
170
|
+
default:
|
|
171
|
+
mandoc_msg(MANDOCERR_TBLLAYOUT_CHAR,
|
|
172
|
+
ln, *pos - 1, "%c", p[*pos - 1]);
|
|
173
|
+
goto mod;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
while (p[*pos] == ' ' || p[*pos] == '\t')
|
|
177
|
+
(*pos)++;
|
|
178
|
+
|
|
179
|
+
/* Ignore parenthised font names for now. */
|
|
180
|
+
|
|
181
|
+
if (p[*pos] == '(')
|
|
182
|
+
goto mod;
|
|
183
|
+
|
|
184
|
+
isz = 0;
|
|
185
|
+
if (p[*pos] != '\0')
|
|
186
|
+
isz++;
|
|
187
|
+
if (strchr(" \t.", p[*pos + isz]) == NULL)
|
|
188
|
+
isz++;
|
|
189
|
+
|
|
190
|
+
fontesc = mandoc_font(p + *pos, isz);
|
|
191
|
+
|
|
192
|
+
switch (fontesc) {
|
|
193
|
+
case ESCAPE_FONTPREV:
|
|
194
|
+
case ESCAPE_ERROR:
|
|
195
|
+
mandoc_msg(MANDOCERR_FT_BAD,
|
|
196
|
+
ln, *pos, "TS %s", p + *pos - 1);
|
|
197
|
+
break;
|
|
198
|
+
default:
|
|
199
|
+
cp->font = fontesc;
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
*pos += isz;
|
|
203
|
+
goto mod;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
static void
|
|
207
|
+
cell(struct tbl_node *tbl, struct tbl_row *rp,
|
|
208
|
+
int ln, const char *p, int *pos)
|
|
209
|
+
{
|
|
210
|
+
int i;
|
|
211
|
+
enum tbl_cellt c;
|
|
212
|
+
|
|
213
|
+
/* Handle leading vertical lines */
|
|
214
|
+
|
|
215
|
+
while (p[*pos] == ' ' || p[*pos] == '\t' || p[*pos] == '|') {
|
|
216
|
+
if (p[*pos] == '|') {
|
|
217
|
+
if (rp->vert < 2)
|
|
218
|
+
rp->vert++;
|
|
219
|
+
else
|
|
220
|
+
mandoc_msg(MANDOCERR_TBLLAYOUT_VERT,
|
|
221
|
+
ln, *pos, NULL);
|
|
222
|
+
}
|
|
223
|
+
(*pos)++;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
again:
|
|
227
|
+
while (p[*pos] == ' ' || p[*pos] == '\t')
|
|
228
|
+
(*pos)++;
|
|
229
|
+
|
|
230
|
+
if (p[*pos] == '.' || p[*pos] == '\0')
|
|
231
|
+
return;
|
|
232
|
+
|
|
233
|
+
/* Parse the column position (`c', `l', `r', ...). */
|
|
234
|
+
|
|
235
|
+
for (i = 0; i < KEYS_MAX; i++)
|
|
236
|
+
if (tolower((unsigned char)p[*pos]) == keys[i].name)
|
|
237
|
+
break;
|
|
238
|
+
|
|
239
|
+
if (i == KEYS_MAX) {
|
|
240
|
+
mandoc_msg(MANDOCERR_TBLLAYOUT_CHAR,
|
|
241
|
+
ln, *pos, "%c", p[*pos]);
|
|
242
|
+
(*pos)++;
|
|
243
|
+
goto again;
|
|
244
|
+
}
|
|
245
|
+
c = keys[i].key;
|
|
246
|
+
|
|
247
|
+
/* Special cases of spanners. */
|
|
248
|
+
|
|
249
|
+
if (c == TBL_CELL_SPAN) {
|
|
250
|
+
if (rp->last == NULL)
|
|
251
|
+
mandoc_msg(MANDOCERR_TBLLAYOUT_SPAN, ln, *pos, NULL);
|
|
252
|
+
else if (rp->last->pos == TBL_CELL_HORIZ ||
|
|
253
|
+
rp->last->pos == TBL_CELL_DHORIZ)
|
|
254
|
+
c = rp->last->pos;
|
|
255
|
+
} else if (c == TBL_CELL_DOWN && rp == tbl->first_row)
|
|
256
|
+
mandoc_msg(MANDOCERR_TBLLAYOUT_DOWN, ln, *pos, NULL);
|
|
257
|
+
|
|
258
|
+
(*pos)++;
|
|
259
|
+
|
|
260
|
+
/* Allocate cell then parse its modifiers. */
|
|
261
|
+
|
|
262
|
+
mods(tbl, cell_alloc(tbl, rp, c), ln, p, pos);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
void
|
|
266
|
+
tbl_layout(struct tbl_node *tbl, int ln, const char *p, int pos)
|
|
267
|
+
{
|
|
268
|
+
struct tbl_row *rp;
|
|
269
|
+
|
|
270
|
+
rp = NULL;
|
|
271
|
+
for (;;) {
|
|
272
|
+
/* Skip whitespace before and after each cell. */
|
|
273
|
+
|
|
274
|
+
while (p[pos] == ' ' || p[pos] == '\t')
|
|
275
|
+
pos++;
|
|
276
|
+
|
|
277
|
+
switch (p[pos]) {
|
|
278
|
+
case ',': /* Next row on this input line. */
|
|
279
|
+
pos++;
|
|
280
|
+
rp = NULL;
|
|
281
|
+
continue;
|
|
282
|
+
case '\0': /* Next row on next input line. */
|
|
283
|
+
return;
|
|
284
|
+
case '.': /* End of layout. */
|
|
285
|
+
pos++;
|
|
286
|
+
tbl->part = TBL_PART_DATA;
|
|
287
|
+
|
|
288
|
+
/*
|
|
289
|
+
* When the layout is completely empty,
|
|
290
|
+
* default to one left-justified column.
|
|
291
|
+
*/
|
|
292
|
+
|
|
293
|
+
if (tbl->first_row == NULL) {
|
|
294
|
+
tbl->first_row = tbl->last_row =
|
|
295
|
+
mandoc_calloc(1, sizeof(*rp));
|
|
296
|
+
}
|
|
297
|
+
if (tbl->first_row->first == NULL) {
|
|
298
|
+
mandoc_msg(MANDOCERR_TBLLAYOUT_NONE,
|
|
299
|
+
ln, pos, NULL);
|
|
300
|
+
cell_alloc(tbl, tbl->first_row,
|
|
301
|
+
TBL_CELL_LEFT);
|
|
302
|
+
if (tbl->opts.lvert < tbl->first_row->vert)
|
|
303
|
+
tbl->opts.lvert = tbl->first_row->vert;
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/*
|
|
308
|
+
* Search for the widest line
|
|
309
|
+
* along the left and right margins.
|
|
310
|
+
*/
|
|
311
|
+
|
|
312
|
+
for (rp = tbl->first_row; rp; rp = rp->next) {
|
|
313
|
+
if (tbl->opts.lvert < rp->vert)
|
|
314
|
+
tbl->opts.lvert = rp->vert;
|
|
315
|
+
if (rp->last != NULL &&
|
|
316
|
+
rp->last->col + 1 == tbl->opts.cols &&
|
|
317
|
+
tbl->opts.rvert < rp->last->vert)
|
|
318
|
+
tbl->opts.rvert = rp->last->vert;
|
|
319
|
+
|
|
320
|
+
/* If the last line is empty, drop it. */
|
|
321
|
+
|
|
322
|
+
if (rp->next != NULL &&
|
|
323
|
+
rp->next->first == NULL) {
|
|
324
|
+
free(rp->next);
|
|
325
|
+
rp->next = NULL;
|
|
326
|
+
tbl->last_row = rp;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
return;
|
|
330
|
+
default: /* Cell. */
|
|
331
|
+
break;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/*
|
|
335
|
+
* If the last line had at least one cell,
|
|
336
|
+
* start a new one; otherwise, continue it.
|
|
337
|
+
*/
|
|
338
|
+
|
|
339
|
+
if (rp == NULL) {
|
|
340
|
+
if (tbl->last_row == NULL ||
|
|
341
|
+
tbl->last_row->first != NULL) {
|
|
342
|
+
rp = mandoc_calloc(1, sizeof(*rp));
|
|
343
|
+
if (tbl->last_row)
|
|
344
|
+
tbl->last_row->next = rp;
|
|
345
|
+
else
|
|
346
|
+
tbl->first_row = rp;
|
|
347
|
+
tbl->last_row = rp;
|
|
348
|
+
} else
|
|
349
|
+
rp = tbl->last_row;
|
|
350
|
+
}
|
|
351
|
+
cell(tbl, rp, ln, p, &pos);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
static struct tbl_cell *
|
|
356
|
+
cell_alloc(struct tbl_node *tbl, struct tbl_row *rp, enum tbl_cellt pos)
|
|
357
|
+
{
|
|
358
|
+
struct tbl_cell *p, *pp;
|
|
359
|
+
|
|
360
|
+
p = mandoc_calloc(1, sizeof(*p));
|
|
361
|
+
p->spacing = SIZE_MAX;
|
|
362
|
+
p->font = ESCAPE_FONTROMAN;
|
|
363
|
+
p->pos = pos;
|
|
364
|
+
|
|
365
|
+
if ((pp = rp->last) != NULL) {
|
|
366
|
+
pp->next = p;
|
|
367
|
+
p->col = pp->col + 1;
|
|
368
|
+
} else
|
|
369
|
+
rp->first = p;
|
|
370
|
+
rp->last = p;
|
|
371
|
+
|
|
372
|
+
if (tbl->opts.cols <= p->col)
|
|
373
|
+
tbl->opts.cols = p->col + 1;
|
|
374
|
+
|
|
375
|
+
return p;
|
|
376
|
+
}
|