]>
git.cameronkatri.com Git - mandoc.git/blob - html4_strict.c
1 /* $Id: html4_strict.c,v 1.1 2008/11/23 16:53:18 kristaps Exp $ */
3 * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
27 #include "libmdocml.h"
42 #define ROFFCALL_ARGS const struct md_args *arg, \
43 struct md_mbuf *out, \
44 const struct md_rbuf *in, \
45 const char *buf, size_t sz, \
46 size_t pos, enum roffd type, \
48 typedef int (*roffcall
)(ROFFCALL_ARGS
);
50 static int roff_Dd(ROFFCALL_ARGS
);
51 static int roff_Dt(ROFFCALL_ARGS
);
52 static int roff_Os(ROFFCALL_ARGS
);
53 static int roff_Sh(ROFFCALL_ARGS
);
67 #define ROFF_NESTED (1 << 0)
70 static const struct rofftok tokens
[ROFF_Max
] = {
71 { ROFF___
, "\\\"", NULL
, ROFF_NONE
, 0 },
72 { ROFF_Dd
, "Dd", roff_Dd
, ROFF_NONE
, 0 },
73 { ROFF_Dt
, "Dt", roff_Dt
, ROFF_NONE
, 0 },
74 { ROFF_Os
, "Os", roff_Os
, ROFF_LAYOUT
, 0 },
75 { ROFF_Sh
, "Sh", roff_Sh
, ROFF_LAYOUT
, 0 },
80 struct roffnode
*parent
;
81 /* TODO: line number at acquisition. */
85 struct roffnode
*last
;
93 #define ROFF_PRELUDE (1 << 0)
94 #define ROFF_PRELUDE_Os (1 << 1)
95 #define ROFF_PRELUDE_Dt (1 << 2)
96 #define ROFF_PRELUDE_Dd (1 << 3)
99 static int rofffind(const char *);
100 static int roffparse(const struct md_args
*,
102 const struct md_rbuf
*,
103 const char *, size_t,
105 static int textparse(struct md_mbuf
*,
106 const struct md_rbuf
*,
107 const char *, size_t,
108 const struct rofftree
*);
112 md_exit_html4_strict(const struct md_args
*args
, struct md_mbuf
*out
,
113 const struct md_rbuf
*in
, void *data
)
115 struct rofftree
*tree
;
120 tree
= (struct rofftree
*)data
;
124 if ( ! (*tokens
[tree
->last
->tok
].cb
)
125 (args
, error
? NULL
: out
, in
, NULL
,
126 0, 0, ROFF_EXIT
, tree
))
130 return(error
? 0 : 1);
135 md_init_html4_strict(const struct md_args
*args
, struct md_mbuf
*out
,
136 const struct md_rbuf
*in
, void **data
)
138 struct rofftree
*tree
;
145 /* TODO: write HTML-DTD header. */
147 if (NULL
== (tree
= calloc(1, sizeof(struct rofftree
)))) {
158 md_line_html4_strict(const struct md_args
*args
, struct md_mbuf
*out
,
159 const struct md_rbuf
*in
, const char *buf
,
160 size_t sz
, void *data
)
162 struct rofftree
*tree
;
168 tree
= (struct rofftree
*)data
;
171 warnx("%s: blank line (line %zu)", in
->name
, in
->line
);
173 } else if ('.' != *buf
)
174 return(textparse(out
, in
, buf
, sz
, tree
));
176 return(roffparse(args
, out
, in
, buf
, sz
, tree
));
181 textparse(struct md_mbuf
*out
, const struct md_rbuf
*in
,
182 const char *buf
, size_t sz
,
183 const struct rofftree
*tree
)
192 if (NULL
== tree
->last
) {
193 warnx("%s: unexpected text (line %zu)",
196 } else if (NULL
== tree
->last
->parent
) {
197 warnx("%s: disallowed text (line %zu)",
202 if ( ! md_buf_puts(out
, buf
, sz
))
204 return(md_buf_putstring(out
, " "));
209 roffparse(const struct md_args
*args
, struct md_mbuf
*out
,
210 const struct md_rbuf
*in
, const char *buf
,
211 size_t sz
, struct rofftree
*tree
)
215 struct roffnode
*node
;
225 * Extract the token identifier from the buffer. If there's no
226 * callback for the token (comment, etc.) then exit immediately.
227 * We don't do any error handling (yet), so if the token doesn't
232 warnx("%s: malformed input (line %zu, col 1)",
235 } else if (ROFF_Max
== (tokid
= rofffind(buf
+ 1))) {
236 warnx("%s: unknown token `%c%c' (line %zu, col 1)",
237 in
->name
, *(buf
+ 1),
238 *(buf
+ 2), in
->line
);
240 } else if (NULL
== tokens
[tokid
].cb
)
241 return(1); /* Skip token. */
246 * If this is a non-nestable layout token and we're below a
247 * token of the same type, then recurse upward to the token,
248 * closing out the interim scopes.
250 * If there's a nested token on the chain, then raise an error
251 * as nested tokens have corresponding "ending" tokens and we're
252 * breaking their scope.
257 if (ROFF_LAYOUT
== tokens
[tokid
].type
&&
258 ! (ROFF_NESTED
& tokens
[tokid
].flags
)) {
259 for (node
= tree
->last
; node
; node
= node
->parent
) {
260 if (node
->tok
== tokid
)
263 /* Don't break nested scope. */
265 if ( ! (ROFF_NESTED
& tokens
[node
->tok
].flags
))
267 warnx("%s: scope of %s broken by %s "
268 "(line %zu, col %zu)",
269 in
->name
, tokens
[tokid
].name
,
270 tokens
[node
->tok
].name
,
276 assert(ROFF_LAYOUT
== tokens
[tokid
].type
);
277 assert( ! (ROFF_NESTED
& tokens
[tokid
].flags
));
278 assert(node
->tok
== tokid
);
280 /* Clear up to last scoped token. */
284 if ( ! (*tokens
[tree
->last
->tok
].cb
)
285 (args
, out
, in
, NULL
,
286 0, 0, ROFF_EXIT
, tree
))
288 } while (t
!= tokid
);
291 /* Proceed with actual token processing. */
293 return((*tokens
[tokid
].cb
)(args
, out
, in
, buf
, sz
,
294 pos
, ROFF_ENTER
, tree
));
299 rofffind(const char *name
)
304 /* FIXME: use a table, this is slow but ok for now. */
305 for (i
= 0; i
< ROFF_Max
; i
++)
306 if (0 == strncmp(name
, tokens
[i
].name
, 2))
315 roff_Dd(ROFFCALL_ARGS
)
325 assert(type
== ROFF_ENTER
);
328 warnx("%s: superfluous prelude (line %zu, col %zu)",
329 in
->name
, in
->line
, pos
);
333 if (0 != tree
->state
) {
334 warnx("%s: bad manual prelude (line %zu, col %zu)",
335 in
->name
, in
->line
, pos
);
339 /* TODO: parse date from buffer. */
341 tree
->date
= time(NULL
);
342 tree
->state
|= ROFF_PRELUDE_Dd
;
348 roff_Dt(ROFFCALL_ARGS
)
358 assert(type
== ROFF_ENTER
);
361 warnx("%s: superfluous prelude (line %zu, col %zu)",
362 in
->name
, in
->line
, pos
);
366 if ( ! (ROFF_PRELUDE_Dd
& tree
->state
) ||
367 (ROFF_PRELUDE_Os
& tree
->state
) ||
368 (ROFF_PRELUDE_Dt
& tree
->state
)) {
369 warnx("%s: bad manual prelude (line %zu, col %zu)",
370 in
->name
, in
->line
, pos
);
374 /* TODO: parse titles from buffer. */
376 tree
->state
|= ROFF_PRELUDE_Dt
;
382 roff_Os(ROFFCALL_ARGS
)
384 struct roffnode
*node
;
390 if (ROFF_EXIT
== type
) {
392 assert(tree
->last
->tok
== ROFF_Os
);
394 /* TODO: flush out ML footer. */
397 tree
->last
= node
->parent
;
409 warnx("%s: superfluous prelude (line %zu, col %zu)",
410 in
->name
, in
->line
, pos
);
414 if ((ROFF_PRELUDE_Os
& tree
->state
) ||
415 ! (ROFF_PRELUDE_Dt
& tree
->state
) ||
416 ! (ROFF_PRELUDE_Dd
& tree
->state
)) {
417 warnx("%s: bad manual prelude (line %zu, col %zu)",
418 in
->name
, in
->line
, pos
);
422 node
= malloc(sizeof(struct roffnode
));
430 tree
->state
|= ROFF_PRELUDE_Os
;
438 roff_Sh(ROFFCALL_ARGS
)
442 /*assert(out);*/(void)out
;
444 /*assert(buf);*/(void)buf
;