]> git.cameronkatri.com Git - mandoc.git/blob - man_action.c
Add -Owidth=width option to mandoc -Tascii. Asked for by joerg@ about a
[mandoc.git] / man_action.c
1 /* $Id: man_action.c,v 1.39 2010/05/26 14:03:54 kristaps Exp $ */
2 /*
3 * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20
21 #include <assert.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include "mandoc.h"
26 #include "libman.h"
27 #include "libmandoc.h"
28
29 struct actions {
30 int (*post)(struct man *);
31 };
32
33 static int post_TH(struct man *);
34 static int post_fi(struct man *);
35 static int post_nf(struct man *);
36 static int post_AT(struct man *);
37 static int post_UC(struct man *);
38
39 const struct actions man_actions[MAN_MAX] = {
40 { NULL }, /* br */
41 { post_TH }, /* TH */
42 { NULL }, /* SH */
43 { NULL }, /* SS */
44 { NULL }, /* TP */
45 { NULL }, /* LP */
46 { NULL }, /* PP */
47 { NULL }, /* P */
48 { NULL }, /* IP */
49 { NULL }, /* HP */
50 { NULL }, /* SM */
51 { NULL }, /* SB */
52 { NULL }, /* BI */
53 { NULL }, /* IB */
54 { NULL }, /* BR */
55 { NULL }, /* RB */
56 { NULL }, /* R */
57 { NULL }, /* B */
58 { NULL }, /* I */
59 { NULL }, /* IR */
60 { NULL }, /* RI */
61 { NULL }, /* na */
62 { NULL }, /* i */
63 { NULL }, /* sp */
64 { post_nf }, /* nf */
65 { post_fi }, /* fi */
66 { NULL }, /* r */
67 { NULL }, /* RE */
68 { NULL }, /* RS */
69 { NULL }, /* DT */
70 { post_UC }, /* UC */
71 { NULL }, /* PD */
72 { NULL }, /* Sp */
73 { post_nf }, /* Vb */
74 { post_fi }, /* Ve */
75 { post_AT }, /* AT */
76 };
77
78
79 int
80 man_action_post(struct man *m)
81 {
82
83 if (MAN_ACTED & m->last->flags)
84 return(1);
85 m->last->flags |= MAN_ACTED;
86
87 switch (m->last->type) {
88 case (MAN_TEXT):
89 /* FALLTHROUGH */
90 case (MAN_ROOT):
91 return(1);
92 default:
93 break;
94 }
95
96 if (NULL == man_actions[m->last->tok].post)
97 return(1);
98 return((*man_actions[m->last->tok].post)(m));
99 }
100
101
102 static int
103 post_fi(struct man *m)
104 {
105
106 if ( ! (MAN_LITERAL & m->flags))
107 if ( ! man_nmsg(m, m->last, MANDOCERR_NOSCOPE))
108 return(0);
109 m->flags &= ~MAN_LITERAL;
110 return(1);
111 }
112
113
114 static int
115 post_nf(struct man *m)
116 {
117
118 if (MAN_LITERAL & m->flags)
119 if ( ! man_nmsg(m, m->last, MANDOCERR_SCOPEREP))
120 return(0);
121 m->flags |= MAN_LITERAL;
122 return(1);
123 }
124
125
126 static int
127 post_TH(struct man *m)
128 {
129 struct man_node *n;
130
131 if (m->meta.title)
132 free(m->meta.title);
133 if (m->meta.vol)
134 free(m->meta.vol);
135 if (m->meta.source)
136 free(m->meta.source);
137 if (m->meta.msec)
138 free(m->meta.msec);
139 if (m->meta.rawdate)
140 free(m->meta.rawdate);
141
142 m->meta.title = m->meta.vol = m->meta.rawdate =
143 m->meta.msec = m->meta.source = NULL;
144 m->meta.date = 0;
145
146 /* ->TITLE<- MSEC DATE SOURCE VOL */
147
148 n = m->last->child;
149 assert(n);
150 m->meta.title = mandoc_strdup(n->string);
151
152 /* TITLE ->MSEC<- DATE SOURCE VOL */
153
154 n = n->next;
155 assert(n);
156 m->meta.msec = mandoc_strdup(n->string);
157
158 /* TITLE MSEC ->DATE<- SOURCE VOL */
159
160 /*
161 * Try to parse the date. If this works, stash the epoch (this
162 * is optimal because we can reformat it in the canonical form).
163 * If it doesn't parse, isn't specified at all, or is an empty
164 * string, then use the current date.
165 */
166
167 n = n->next;
168 if (n && n->string && *n->string) {
169 m->meta.date = mandoc_a2time
170 (MTIME_ISO_8601, n->string);
171 if (0 == m->meta.date) {
172 if ( ! man_nmsg(m, n, MANDOCERR_BADDATE))
173 return(0);
174 m->meta.rawdate = mandoc_strdup(n->string);
175 }
176 } else
177 m->meta.date = time(NULL);
178
179 /* TITLE MSEC DATE ->SOURCE<- VOL */
180
181 if (n && (n = n->next))
182 m->meta.source = mandoc_strdup(n->string);
183
184 /* TITLE MSEC DATE SOURCE ->VOL<- */
185
186 if (n && (n = n->next))
187 m->meta.vol = mandoc_strdup(n->string);
188
189 /*
190 * Remove the `TH' node after we've processed it for our
191 * meta-data.
192 */
193 man_node_delete(m, m->last);
194 return(1);
195 }
196
197
198 static int
199 post_AT(struct man *m)
200 {
201 static const char * const unix_versions[] = {
202 "7th Edition",
203 "System III",
204 "System V",
205 "System V Release 2",
206 };
207
208 const char *p, *s;
209 struct man_node *n, *nn;
210
211 n = m->last->child;
212
213 if (NULL == n || MAN_TEXT != n->type)
214 p = unix_versions[0];
215 else {
216 s = n->string;
217 if (0 == strcmp(s, "3"))
218 p = unix_versions[0];
219 else if (0 == strcmp(s, "4"))
220 p = unix_versions[1];
221 else if (0 == strcmp(s, "5")) {
222 nn = n->next;
223 if (nn && MAN_TEXT == nn->type && nn->string[0])
224 p = unix_versions[3];
225 else
226 p = unix_versions[2];
227 } else
228 p = unix_versions[0];
229 }
230
231 if (m->meta.source)
232 free(m->meta.source);
233
234 m->meta.source = mandoc_strdup(p);
235
236 return(1);
237 }
238
239
240 static int
241 post_UC(struct man *m)
242 {
243 static const char * const bsd_versions[] = {
244 "3rd Berkeley Distribution",
245 "4th Berkeley Distribution",
246 "4.2 Berkeley Distribution",
247 "4.3 Berkeley Distribution",
248 "4.4 Berkeley Distribution",
249 };
250
251 const char *p, *s;
252 struct man_node *n;
253
254 n = m->last->child;
255
256 if (NULL == n || MAN_TEXT != n->type)
257 p = bsd_versions[0];
258 else {
259 s = n->string;
260 if (0 == strcmp(s, "3"))
261 p = bsd_versions[0];
262 else if (0 == strcmp(s, "4"))
263 p = bsd_versions[1];
264 else if (0 == strcmp(s, "5"))
265 p = bsd_versions[2];
266 else if (0 == strcmp(s, "6"))
267 p = bsd_versions[3];
268 else if (0 == strcmp(s, "7"))
269 p = bsd_versions[4];
270 else
271 p = bsd_versions[0];
272 }
273
274 if (m->meta.source)
275 free(m->meta.source);
276
277 m->meta.source = mandoc_strdup(p);
278
279 return(1);
280 }