]> git.cameronkatri.com Git - mandoc.git/blob - mdocml.c
Considerable clean-ups.
[mandoc.git] / mdocml.c
1 /* $Id: mdocml.c,v 1.19 2008/12/09 17:09:12 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 <sys/param.h>
20 #include <sys/stat.h>
21
22 #include <assert.h>
23 #include <err.h>
24 #include <fcntl.h>
25 #include <getopt.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30
31 #include "libmdocml.h"
32
33 #define BUFFER_IN_DEF BUFSIZ /* See begin_bufs. */
34 #define BUFFER_OUT_DEF BUFSIZ /* See begin_bufs. */
35
36 #ifdef DEBUG
37 #define CSS "mdocml.css"
38 #else
39 #define CSS "/usr/local/share/mdocml/mdocml.css"
40 #endif
41
42 static void usage(void);
43
44 static int begin_io(const struct md_args *,
45 char *, char *);
46 static int leave_io(const struct md_buf *,
47 const struct md_buf *, int);
48 static int begin_bufs(const struct md_args *,
49 struct md_buf *, struct md_buf *);
50 static int leave_bufs(const struct md_buf *,
51 const struct md_buf *, int);
52
53 #ifdef __linux__
54 extern int getsubopt(char **, char *const *, char **);
55 #endif
56
57 int
58 main(int argc, char *argv[])
59 {
60 int c;
61 char *out, *in, *opts, *v;
62 struct md_args args;
63 #define ALL 0
64 #define ERROR 1
65 char *toks[] = { "all", "error", NULL };
66
67 extern char *optarg;
68 extern int optind;
69
70 out = in = NULL;
71
72 (void)memset(&args, 0, sizeof(struct md_args));
73
74 args.type = MD_XML;
75
76 while (-1 != (c = getopt(argc, argv, "c:ef:o:vW:")))
77 switch (c) {
78 case ('c'):
79 if (args.type != MD_HTML)
80 errx(1, "-c only valid for -fhtml");
81 args.params.html.css = optarg;
82 break;
83 case ('e'):
84 if (args.type != MD_HTML)
85 errx(1, "-e only valid for -fhtml");
86 args.params.html.flags |= HTML_CSS_EMBED;
87 break;
88 case ('f'):
89 if (0 == strcmp(optarg, "html"))
90 args.type = MD_HTML;
91 else if (0 == strcmp(optarg, "xml"))
92 args.type = MD_XML;
93 else
94 errx(1, "invalid filter type");
95 break;
96 case ('o'):
97 out = optarg;
98 break;
99 case ('v'):
100 args.verbosity++;
101 break;
102 case ('W'):
103 opts = optarg;
104 while (*opts)
105 switch (getsubopt(&opts, toks, &v)) {
106 case (ALL):
107 args.warnings |= MD_WARN_ALL;
108 break;
109 case (ERROR):
110 args.warnings |= MD_WARN_ERROR;
111 break;
112 default:
113 usage();
114 return(1);
115 }
116 break;
117 default:
118 usage();
119 return(1);
120 }
121
122 if (MD_HTML == args.type)
123 if (NULL == args.params.html.css)
124 args.params.html.css = CSS;
125
126 argv += optind;
127 argc -= optind;
128
129 if (1 == argc)
130 in = *argv++;
131
132 return(begin_io(&args, out ? out : "-", in ? in : "-"));
133 }
134
135
136 /*
137 * Close out file descriptors opened in begin_io. If the descriptor
138 * refers to stdin/stdout, then do nothing.
139 */
140 static int
141 leave_io(const struct md_buf *out,
142 const struct md_buf *in, int c)
143 {
144 assert(out);
145 assert(in);
146
147 if (-1 != in->fd && -1 == close(in->fd)) {
148 assert(in->name);
149 warn("%s", in->name);
150 c = 1;
151 }
152 if (-1 != out->fd && STDOUT_FILENO != out->fd &&
153 -1 == close(out->fd)) {
154 assert(out->name);
155 warn("%s", out->name);
156 c = 1;
157 }
158 if (1 == c && STDOUT_FILENO != out->fd)
159 if (-1 == unlink(out->name))
160 warn("%s", out->name);
161
162 return(c);
163 }
164
165
166 /*
167 * Open file descriptors or assign stdin/stdout, if dictated by the "-"
168 * token instead of a filename.
169 */
170 static int
171 begin_io(const struct md_args *args, char *out, char *in)
172 {
173 struct md_buf fi;
174 struct md_buf fo;
175
176 #define FI_FL O_RDONLY
177 #define FO_FL O_WRONLY|O_CREAT|O_TRUNC
178
179 assert(args);
180 assert(out);
181 assert(in);
182
183 bzero(&fi, sizeof(struct md_buf));
184 bzero(&fo, sizeof(struct md_buf));
185
186 fi.fd = STDIN_FILENO;
187 fo.fd = STDOUT_FILENO;
188
189 fi.name = in;
190 fo.name = out;
191
192 if (0 != strncmp(fi.name, "-", 1))
193 if (-1 == (fi.fd = open(fi.name, FI_FL, 0))) {
194 warn("%s", fi.name);
195 return(leave_io(&fo, &fi, 1));
196 }
197
198 if (0 != strncmp(fo.name, "-", 1))
199 if (-1 == (fo.fd = open(fo.name, FO_FL, 0644))) {
200 warn("%s", fo.name);
201 return(leave_io(&fo, &fi, 1));
202 }
203
204 return(leave_io(&fo, &fi, begin_bufs(args, &fo, &fi)));
205 }
206
207
208 /*
209 * Free buffers allocated in begin_bufs.
210 */
211 static int
212 leave_bufs(const struct md_buf *out,
213 const struct md_buf *in, int c)
214 {
215 assert(out);
216 assert(in);
217 if (out->buf)
218 free(out->buf);
219 if (in->buf)
220 free(in->buf);
221 return(c);
222 }
223
224
225 /*
226 * Allocate buffers to the maximum of either the input file's blocksize
227 * or BUFFER_IN_DEF/BUFFER_OUT_DEF, which should be around BUFSIZE.
228 */
229 static int
230 begin_bufs(const struct md_args *args,
231 struct md_buf *out, struct md_buf *in)
232 {
233 struct stat stin, stout;
234 int c;
235
236 assert(args);
237 assert(in);
238 assert(out);
239
240 if (-1 == fstat(in->fd, &stin)) {
241 warn("%s", in->name);
242 return(1);
243 } else if (STDIN_FILENO != in->fd && 0 == stin.st_size) {
244 warnx("%s: empty file", in->name);
245 return(1);
246 } else if (-1 == fstat(out->fd, &stout)) {
247 warn("%s", out->name);
248 return(1);
249 }
250
251 in->bufsz = MAX(stin.st_blksize, BUFFER_IN_DEF);
252 out->bufsz = MAX(stout.st_blksize, BUFFER_OUT_DEF);
253
254 if (NULL == (in->buf = malloc(in->bufsz))) {
255 warn("malloc");
256 return(leave_bufs(out, in, 1));
257 } else if (NULL == (out->buf = malloc(out->bufsz))) {
258 warn("malloc");
259 return(leave_bufs(out, in, 1));
260 }
261
262 c = md_run(args, out, in);
263 return(leave_bufs(out, in, -1 == c ? 1 : 0));
264 }
265
266
267 static void
268 usage(void)
269 {
270 extern char *__progname;
271
272 (void)fprintf(stderr, "usage: %s [-v] [-Wwarn...] "
273 "[-f filter] [-o outfile] [infile]\n",
274 __progname);
275 }
276