]> git.cameronkatri.com Git - mandoc.git/blob - libmdocml.c
Putting md_run and friends into libmdocml (needs work to be useful).
[mandoc.git] / libmdocml.c
1 /* $Id: libmdocml.c,v 1.2 2008/11/22 18:34:06 kristaps Exp $ */
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 */
19 #include <assert.h>
20 #include <fcntl.h>
21 #include <err.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26
27 #include "libmdocml.h"
28
29 #define BUFFER_LINE BUFSIZ
30
31 typedef int (*md_line) (struct md_mbuf *, const struct md_rbuf *,
32 const char *, size_t);
33
34 static int md_line_dummy(struct md_mbuf *,
35 const struct md_rbuf *,
36 const char *, size_t);
37 static ssize_t md_buf_fill(struct md_rbuf *);
38 static int md_buf_flush(struct md_mbuf *);
39 static int md_buf_putchar(struct md_mbuf *, char);
40 static int md_buf_puts(struct md_mbuf *,
41 const char *, size_t);
42
43
44 ssize_t
45 md_buf_fill(struct md_rbuf *in)
46 {
47 ssize_t ssz;
48
49 assert(in);
50 assert(in->buf);
51 assert(in->bufsz > 0);
52 assert(in->name);
53
54 if (-1 == (ssz = read(in->fd, in->buf, in->bufsz)))
55 warn("%s", in->name);
56
57 return(ssz);
58 }
59
60
61 int
62 md_buf_flush(struct md_mbuf *buf)
63 {
64 ssize_t sz;
65
66 assert(buf);
67 assert(buf->buf);
68 assert(buf->name);
69
70 if (0 == buf->pos)
71 return(1);
72
73 sz = write(buf->fd, buf->buf, buf->pos);
74
75 if (-1 == sz) {
76 warn("%s", buf->name);
77 return(0);
78 } else if ((size_t)sz != buf->pos) {
79 warnx("%s: short write", buf->name);
80 return(0);
81 }
82
83 buf->pos = 0;
84 return(1);
85 }
86
87
88 int
89 md_buf_putchar(struct md_mbuf *buf, char c)
90 {
91 return(md_buf_puts(buf, &c, 1));
92 }
93
94
95 int
96 md_buf_puts(struct md_mbuf *buf, const char *p, size_t sz)
97 {
98 size_t ssz;
99
100 assert(p);
101 assert(buf);
102 assert(buf->buf);
103
104 /* LINTED */
105 while (buf->pos + sz > buf->bufsz) {
106 ssz = buf->bufsz - buf->pos;
107 (void)memcpy(/* LINTED */
108 buf->buf + buf->pos, p, ssz);
109 p += (long)ssz;
110 sz -= ssz;
111 buf->pos += ssz;
112
113 if ( ! md_buf_flush(buf))
114 return(0);
115 }
116
117 (void)memcpy(/* LINTED */
118 buf->buf + buf->pos, p, sz);
119 buf->pos += sz;
120 return(1);
121 }
122
123
124 int
125 md_run(enum md_type type, struct md_mbuf *out, struct md_rbuf *in)
126 {
127 ssize_t sz, i;
128 char line[BUFFER_LINE];
129 size_t pos;
130 md_line func;
131
132 assert(in);
133 assert(out);
134
135 out->pos = 0;
136 in->line = 1;
137
138 assert(MD_DUMMY == type);
139 func = md_line_dummy;
140
141 /* LINTED */
142 for (pos = 0; ; ) {
143 if (-1 == (sz = md_buf_fill(in)))
144 return(1);
145 else if (0 == sz)
146 break;
147
148 for (i = 0; i < sz; i++) {
149 if ('\n' == in->buf[i]) {
150 if ((*func)(out, in, line, pos))
151 return(1);
152 in->line++;
153 pos = 0;
154 continue;
155 }
156
157 if (pos < BUFFER_LINE) {
158 /* LINTED */
159 line[pos++] = in->buf[i];
160 continue;
161 }
162
163 warnx("%s: line %zu too long",
164 in->name, in->line);
165 return(1);
166 }
167 }
168
169 if (0 != pos && (*func)(out, in, line, pos))
170 return(1);
171
172 return(md_buf_flush(out) ? 0 : 1);
173 }
174
175
176 static int
177 md_line_dummy(struct md_mbuf *out, const struct md_rbuf *in,
178 const char *buf, size_t sz)
179 {
180
181 assert(buf);
182 assert(out);
183 assert(in);
184
185 if ( ! md_buf_puts(out, buf, sz))
186 return(1);
187 if ( ! md_buf_putchar(out, '\n'))
188 return(1);
189
190 return(0);
191 }
192
193