Annotation of mandoc/libmdocml.c, Revision 1.3
1.3 ! kristaps 1: /* $Id: libmdocml.c,v 1.2 2008/11/22 18:34:06 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.2 kristaps 28:
29: #define BUFFER_LINE BUFSIZ
30:
1.3 ! kristaps 31: struct md_rbuf {
! 32: int fd;
! 33: char *name;
! 34: char *buf;
! 35: size_t bufsz;
! 36: size_t line;
! 37: };
! 38:
! 39: struct md_mbuf {
! 40: int fd;
! 41: char *name;
! 42: char *buf;
! 43: size_t bufsz;
! 44: size_t pos;
! 45: };
! 46:
! 47: typedef int (*md_line) (const struct md_args *, struct md_mbuf *,
! 48: const struct md_rbuf *,
! 49: const char *, size_t);
! 50: typedef int (*md_init) (const struct md_args *, struct md_mbuf *);
! 51: typedef int (*md_exit) (const struct md_args *, struct md_mbuf *);
! 52:
! 53: static int md_line_dummy(const struct md_args *,
! 54: struct md_mbuf *,
! 55: const struct md_rbuf *,
1.2 kristaps 56: const char *, size_t);
57:
1.3 ! kristaps 58: static int md_line_html4_strict(const struct md_args *,
! 59: struct md_mbuf *,
1.2 kristaps 60: const struct md_rbuf *,
61: const char *, size_t);
1.3 ! kristaps 62: static int md_init_html4_strict(const struct md_args *,
! 63: struct md_mbuf *);
! 64: static int md_exit_html4_strict(const struct md_args *,
! 65: struct md_mbuf *);
! 66:
! 67: static int md_run_enter(const struct md_args *,
! 68: struct md_mbuf *, struct md_rbuf *);
! 69: static int md_run_leave(const struct md_args *,
! 70: struct md_mbuf *,
! 71: struct md_rbuf *, int);
! 72:
1.2 kristaps 73: static ssize_t md_buf_fill(struct md_rbuf *);
74: static int md_buf_flush(struct md_mbuf *);
75: static int md_buf_putchar(struct md_mbuf *, char);
76: static int md_buf_puts(struct md_mbuf *,
77: const char *, size_t);
78:
79:
1.3 ! kristaps 80: static ssize_t
1.2 kristaps 81: md_buf_fill(struct md_rbuf *in)
82: {
83: ssize_t ssz;
84:
85: assert(in);
86: assert(in->buf);
87: assert(in->bufsz > 0);
88: assert(in->name);
89:
90: if (-1 == (ssz = read(in->fd, in->buf, in->bufsz)))
91: warn("%s", in->name);
92:
93: return(ssz);
94: }
95:
96:
1.3 ! kristaps 97: static int
1.2 kristaps 98: md_buf_flush(struct md_mbuf *buf)
99: {
100: ssize_t sz;
101:
102: assert(buf);
103: assert(buf->buf);
104: assert(buf->name);
105:
106: if (0 == buf->pos)
107: return(1);
108:
109: sz = write(buf->fd, buf->buf, buf->pos);
110:
111: if (-1 == sz) {
112: warn("%s", buf->name);
113: return(0);
114: } else if ((size_t)sz != buf->pos) {
115: warnx("%s: short write", buf->name);
116: return(0);
117: }
118:
119: buf->pos = 0;
120: return(1);
121: }
122:
123:
1.3 ! kristaps 124: static int
1.2 kristaps 125: md_buf_putchar(struct md_mbuf *buf, char c)
126: {
127: return(md_buf_puts(buf, &c, 1));
128: }
129:
130:
1.3 ! kristaps 131: static int
1.2 kristaps 132: md_buf_puts(struct md_mbuf *buf, const char *p, size_t sz)
133: {
134: size_t ssz;
135:
136: assert(p);
137: assert(buf);
138: assert(buf->buf);
139:
140: /* LINTED */
141: while (buf->pos + sz > buf->bufsz) {
142: ssz = buf->bufsz - buf->pos;
143: (void)memcpy(/* LINTED */
144: buf->buf + buf->pos, p, ssz);
145: p += (long)ssz;
146: sz -= ssz;
147: buf->pos += ssz;
148:
149: if ( ! md_buf_flush(buf))
150: return(0);
151: }
152:
153: (void)memcpy(/* LINTED */
154: buf->buf + buf->pos, p, sz);
155: buf->pos += sz;
156: return(1);
157: }
158:
159:
1.3 ! kristaps 160: static int
! 161: md_run_leave(const struct md_args *args,
! 162: struct md_mbuf *mbuf, struct md_rbuf *rbuf, int c)
! 163: {
! 164: assert(args);
! 165: assert(mbuf);
! 166: assert(rbuf);
! 167:
! 168: /* Run exiters. */
! 169: switch (args->type) {
! 170: case (MD_HTML4_STRICT):
! 171: if ( ! md_exit_html4_strict(args, mbuf))
! 172: return(-1);
! 173: break;
! 174: case (MD_DUMMY):
! 175: break;
! 176: default:
! 177: abort();
! 178: }
! 179:
! 180: /* Make final flush of buffer. */
! 181: if ( ! md_buf_flush(mbuf))
! 182: return(-1);
! 183:
! 184: return(c);
! 185: }
! 186:
! 187:
! 188: static int
! 189: md_run_enter(const struct md_args *args,
! 190: struct md_mbuf *mbuf, struct md_rbuf *rbuf)
1.2 kristaps 191: {
192: ssize_t sz, i;
193: char line[BUFFER_LINE];
194: size_t pos;
1.3 ! kristaps 195: md_line fp;
1.2 kristaps 196:
1.3 ! kristaps 197: assert(args);
! 198: assert(mbuf);
! 199: assert(rbuf);
! 200:
! 201: /* Function ptrs to line-parsers. */
! 202: switch (args->type) {
! 203: case (MD_HTML4_STRICT):
! 204: fp = md_line_html4_strict;
! 205: break;
! 206: case (MD_DUMMY):
! 207: fp = md_line_dummy;
! 208: break;
! 209: default:
! 210: abort();
! 211: }
1.2 kristaps 212:
213: /* LINTED */
214: for (pos = 0; ; ) {
1.3 ! kristaps 215: if (-1 == (sz = md_buf_fill(rbuf)))
! 216: return(-1);
1.2 kristaps 217: else if (0 == sz)
218: break;
219:
220: for (i = 0; i < sz; i++) {
1.3 ! kristaps 221: if ('\n' == rbuf->buf[i]) {
! 222: if ( ! (*fp)(args, mbuf, rbuf, line, pos))
! 223: return(-1);
! 224: rbuf->line++;
1.2 kristaps 225: pos = 0;
226: continue;
227: }
228:
229: if (pos < BUFFER_LINE) {
230: /* LINTED */
1.3 ! kristaps 231: line[pos++] = rbuf->buf[i];
1.2 kristaps 232: continue;
233: }
234:
235: warnx("%s: line %zu too long",
1.3 ! kristaps 236: rbuf->name, rbuf->line);
! 237: return(-1);
1.2 kristaps 238: }
239: }
240:
1.3 ! kristaps 241: if (0 != pos && ! (*fp)(args, mbuf, rbuf, line, pos))
! 242: return(-1);
! 243:
! 244: return(md_run_leave(args, mbuf, rbuf, 0));
! 245: }
! 246:
! 247:
! 248: int
! 249: md_run(const struct md_args *args,
! 250: const struct md_buf *out, const struct md_buf *in)
! 251: {
! 252: struct md_mbuf mbuf;
! 253: struct md_rbuf rbuf;
! 254:
! 255: assert(args);
! 256: assert(in);
! 257: assert(out);
! 258:
! 259: (void)memcpy(&mbuf, out, sizeof(struct md_buf));
! 260: (void)memcpy(&rbuf, in, sizeof(struct md_buf));
! 261:
! 262: mbuf.pos = 0;
! 263: rbuf.line = 1;
! 264:
! 265: /* Run initialisers. */
! 266: switch (args->type) {
! 267: case (MD_HTML4_STRICT):
! 268: if ( ! md_init_html4_strict(args, &mbuf))
! 269: return(-1);
! 270: break;
! 271: case (MD_DUMMY):
! 272: break;
! 273: default:
! 274: abort();
! 275: }
1.2 kristaps 276:
1.3 ! kristaps 277: /* Go into mainline. */
! 278: return(md_run_enter(args, &mbuf, &rbuf));
1.2 kristaps 279: }
280:
281:
282: static int
1.3 ! kristaps 283: md_line_dummy(const struct md_args *args, struct md_mbuf *out,
! 284: const struct md_rbuf *in, const char *buf, size_t sz)
1.2 kristaps 285: {
286:
287: assert(buf);
288: assert(out);
289: assert(in);
1.3 ! kristaps 290: assert(args);
1.2 kristaps 291:
292: if ( ! md_buf_puts(out, buf, sz))
1.3 ! kristaps 293: return(0);
1.2 kristaps 294: if ( ! md_buf_putchar(out, '\n'))
1.3 ! kristaps 295: return(0);
! 296:
! 297: return(1);
! 298: }
! 299:
! 300:
! 301: static int
! 302: md_exit_html4_strict(const struct md_args *args, struct md_mbuf *p)
! 303: {
! 304:
! 305: assert(p);
! 306: assert(args);
! 307: return(1);
! 308: }
! 309:
! 310:
! 311: static int
! 312: md_init_html4_strict(const struct md_args *args, struct md_mbuf *p)
! 313: {
1.2 kristaps 314:
1.3 ! kristaps 315: assert(p);
! 316: assert(args);
! 317: return(1);
1.2 kristaps 318: }
319:
320:
1.3 ! kristaps 321: static int
! 322: md_line_html4_strict(const struct md_args *args, struct md_mbuf *out,
! 323: const struct md_rbuf *in, const char *buf, size_t sz)
! 324: {
! 325:
! 326: assert(args);
! 327: assert(buf);
! 328: assert(out);
! 329: assert(in);
! 330: (void)sz;
! 331:
! 332: return(1);
! 333: }
CVSweb