Annotation of mandoc/libmdocml.c, Revision 1.6
1.6 ! kristaps 1: /* $Id: libmdocml.c,v 1.5 2008/11/23 16:53:18 kristaps Exp $ */
1.1 kristaps 2: /*
3: * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
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
7: * above copyright notice and this permission notice appear in all
8: * copies.
9: *
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.
18: */
1.2 kristaps 19: #include <assert.h>
20: #include <fcntl.h>
21: #include <err.h>
22: #include <stdio.h>
1.1 kristaps 23: #include <stdlib.h>
1.2 kristaps 24: #include <string.h>
25: #include <unistd.h>
1.1 kristaps 26:
27: #include "libmdocml.h"
1.5 kristaps 28: #include "private.h"
1.2 kristaps 29:
30: #define BUFFER_LINE BUFSIZ
31:
1.5 kristaps 32: static int md_run_enter(const struct md_args *,
33: struct md_mbuf *, struct md_rbuf *, void *);
34: static int md_run_leave(const struct md_args *, struct md_mbuf *,
35: struct md_rbuf *, int, void *);
36: static ssize_t md_buf_fill(struct md_rbuf *);
37: static int md_buf_flush(struct md_mbuf *);
1.2 kristaps 38:
39:
1.3 kristaps 40: static ssize_t
1.2 kristaps 41: md_buf_fill(struct md_rbuf *in)
42: {
43: ssize_t ssz;
44:
45: assert(in);
46: assert(in->buf);
47: assert(in->bufsz > 0);
48: assert(in->name);
49:
50: if (-1 == (ssz = read(in->fd, in->buf, in->bufsz)))
51: warn("%s", in->name);
52:
53: return(ssz);
54: }
55:
56:
1.3 kristaps 57: static int
1.2 kristaps 58: md_buf_flush(struct md_mbuf *buf)
59: {
60: ssize_t sz;
61:
62: assert(buf);
63: assert(buf->buf);
64: assert(buf->name);
65:
66: if (0 == buf->pos)
67: return(1);
68:
69: sz = write(buf->fd, buf->buf, buf->pos);
70:
71: if (-1 == sz) {
72: warn("%s", buf->name);
73: return(0);
74: } else if ((size_t)sz != buf->pos) {
75: warnx("%s: short write", buf->name);
76: return(0);
77: }
78:
79: buf->pos = 0;
80: return(1);
81: }
82:
83:
1.5 kristaps 84: int
1.2 kristaps 85: md_buf_putchar(struct md_mbuf *buf, char c)
86: {
87: return(md_buf_puts(buf, &c, 1));
88: }
89:
90:
1.5 kristaps 91: int
1.4 kristaps 92: md_buf_putstring(struct md_mbuf *buf, const char *p)
93: {
94: return(md_buf_puts(buf, p, strlen(p)));
95: }
96:
97:
1.5 kristaps 98: int
1.2 kristaps 99: md_buf_puts(struct md_mbuf *buf, const char *p, size_t sz)
100: {
101: size_t ssz;
102:
103: assert(p);
104: assert(buf);
105: assert(buf->buf);
106:
107: /* LINTED */
108: while (buf->pos + sz > buf->bufsz) {
109: ssz = buf->bufsz - buf->pos;
110: (void)memcpy(/* LINTED */
111: buf->buf + buf->pos, p, ssz);
112: p += (long)ssz;
113: sz -= ssz;
114: buf->pos += ssz;
115:
116: if ( ! md_buf_flush(buf))
117: return(0);
118: }
119:
120: (void)memcpy(/* LINTED */
121: buf->buf + buf->pos, p, sz);
122: buf->pos += sz;
123: return(1);
124: }
125:
126:
1.3 kristaps 127: static int
1.5 kristaps 128: md_run_leave(const struct md_args *args, struct md_mbuf *mbuf,
129: struct md_rbuf *rbuf, int c, void *data)
1.3 kristaps 130: {
131: assert(args);
132: assert(mbuf);
133: assert(rbuf);
134:
135: /* Run exiters. */
136: switch (args->type) {
137: case (MD_HTML4_STRICT):
1.6 ! kristaps 138: if ( ! md_exit_html4_strict(args, mbuf, rbuf, c, data))
1.3 kristaps 139: return(-1);
140: break;
141: case (MD_DUMMY):
142: break;
143: default:
144: abort();
145: }
146:
147: /* Make final flush of buffer. */
148: if ( ! md_buf_flush(mbuf))
149: return(-1);
150:
151: return(c);
152: }
153:
154:
155: static int
1.5 kristaps 156: md_run_enter(const struct md_args *args, struct md_mbuf *mbuf,
157: struct md_rbuf *rbuf, void *p)
1.2 kristaps 158: {
159: ssize_t sz, i;
160: char line[BUFFER_LINE];
161: size_t pos;
1.3 kristaps 162: md_line fp;
1.2 kristaps 163:
1.3 kristaps 164: assert(args);
165: assert(mbuf);
166: assert(rbuf);
167:
168: /* Function ptrs to line-parsers. */
169: switch (args->type) {
170: case (MD_HTML4_STRICT):
171: fp = md_line_html4_strict;
172: break;
173: case (MD_DUMMY):
174: fp = md_line_dummy;
175: break;
176: default:
177: abort();
178: }
1.2 kristaps 179:
180: /* LINTED */
181: for (pos = 0; ; ) {
1.3 kristaps 182: if (-1 == (sz = md_buf_fill(rbuf)))
1.5 kristaps 183: return(md_run_leave(args, mbuf, rbuf, -1, p));
1.2 kristaps 184: else if (0 == sz)
185: break;
186:
187: for (i = 0; i < sz; i++) {
1.3 kristaps 188: if ('\n' == rbuf->buf[i]) {
1.5 kristaps 189: if ( ! (*fp)(args, mbuf, rbuf, line, pos, p))
190: return(md_run_leave(args, mbuf, rbuf,
191: -1, p));
1.3 kristaps 192: rbuf->line++;
1.2 kristaps 193: pos = 0;
194: continue;
195: }
196:
197: if (pos < BUFFER_LINE) {
198: /* LINTED */
1.3 kristaps 199: line[pos++] = rbuf->buf[i];
1.2 kristaps 200: continue;
201: }
202:
203: warnx("%s: line %zu too long",
1.3 kristaps 204: rbuf->name, rbuf->line);
1.5 kristaps 205: return(md_run_leave(args, mbuf, rbuf, -1, p));
1.2 kristaps 206: }
207: }
208:
1.5 kristaps 209: if (0 != pos && ! (*fp)(args, mbuf, rbuf, line, pos, p))
210: return(md_run_leave(args, mbuf, rbuf, -1, p));
1.3 kristaps 211:
1.5 kristaps 212: return(md_run_leave(args, mbuf, rbuf, 0, p));
1.3 kristaps 213: }
214:
215:
216: int
217: md_run(const struct md_args *args,
218: const struct md_buf *out, const struct md_buf *in)
219: {
220: struct md_mbuf mbuf;
221: struct md_rbuf rbuf;
1.5 kristaps 222: void *data;
1.3 kristaps 223:
224: assert(args);
225: assert(in);
226: assert(out);
227:
228: (void)memcpy(&mbuf, out, sizeof(struct md_buf));
229: (void)memcpy(&rbuf, in, sizeof(struct md_buf));
230:
231: mbuf.pos = 0;
232: rbuf.line = 1;
1.5 kristaps 233: data = NULL;
1.3 kristaps 234:
235: /* Run initialisers. */
236: switch (args->type) {
237: case (MD_HTML4_STRICT):
1.6 ! kristaps 238: if ( ! md_init_html4_strict(args, &mbuf, &rbuf, &data))
1.3 kristaps 239: return(-1);
240: break;
241: case (MD_DUMMY):
242: break;
243: default:
244: abort();
245: }
1.2 kristaps 246:
1.3 kristaps 247: /* Go into mainline. */
1.5 kristaps 248: return(md_run_enter(args, &mbuf, &rbuf, data));
1.3 kristaps 249: }
CVSweb