]> git.cameronkatri.com Git - mandoc.git/blob - mdocml.c
df834d90d0e0ea73c6ad7960bf1cda4ee33febd7
[mandoc.git] / mdocml.c
1 /* $Id: mdocml.c,v 1.8 2008/11/23 22:30:53 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
34 #define BUFFER_OUT_DEF BUFSIZ
35
36 static void usage(void);
37 static int begin_io(const struct md_args *,
38 char *, char *);
39 static int leave_io(const struct md_buf *,
40 const struct md_buf *, int);
41 static int begin_bufs(const struct md_args *,
42 struct md_buf *, struct md_buf *);
43 static int leave_bufs(const struct md_buf *,
44 const struct md_buf *, int);
45
46 int
47 main(int argc, char *argv[])
48 {
49 int c;
50 char *out, *in;
51 struct md_args args;
52
53 extern char *optarg;
54 extern int optind;
55
56 out = in = NULL;
57
58 while (-1 != (c = getopt(argc, argv, "o:")))
59 switch (c) {
60 case ('o'):
61 out = optarg;
62 break;
63 default:
64 usage();
65 return(1);
66 }
67
68 argv += optind;
69 argc -= optind;
70
71 if (1 == argc)
72 in = *argv++;
73
74 args.type = MD_HTML4_STRICT;
75 args.dbg = MD_DBG_TREE;
76
77 return(begin_io(&args, out ? out : "-", in ? in : "-"));
78 }
79
80
81 static int
82 leave_io(const struct md_buf *out,
83 const struct md_buf *in, int c)
84 {
85 assert(out);
86 assert(in);
87
88 if (-1 != in->fd && -1 == close(in->fd)) {
89 assert(in->name);
90 warn("%s", in->name);
91 c = 1;
92 }
93 if (-1 != out->fd && STDOUT_FILENO != out->fd &&
94 -1 == close(out->fd)) {
95 assert(out->name);
96 warn("%s", out->name);
97 c = 1;
98 }
99
100 return(c);
101 }
102
103
104 static int
105 begin_io(const struct md_args *args, char *out, char *in)
106 {
107 struct md_buf fi;
108 struct md_buf fo;
109
110 #define FI_FL O_RDONLY
111 #define FO_FL O_WRONLY|O_CREAT|O_TRUNC
112
113 assert(args);
114 assert(out);
115 assert(in);
116
117 bzero(&fi, sizeof(struct md_buf));
118 bzero(&fo, sizeof(struct md_buf));
119
120 fi.fd = STDIN_FILENO;
121 fo.fd = STDOUT_FILENO;
122
123 fi.name = in;
124 fo.name = out;
125
126 if (0 != strncmp(fi.name, "-", 1))
127 if (-1 == (fi.fd = open(fi.name, FI_FL, 0))) {
128 warn("%s", fi.name);
129 return(leave_io(&fo, &fi, 1));
130 }
131
132 if (0 != strncmp(fo.name, "-", 1))
133 if (-1 == (fo.fd = open(fo.name, FO_FL, 0644))) {
134 warn("%s", fo.name);
135 return(leave_io(&fo, &fi, 1));
136 }
137
138 return(leave_io(&fo, &fi, begin_bufs(args, &fo, &fi)));
139 }
140
141
142 static int
143 leave_bufs(const struct md_buf *out,
144 const struct md_buf *in, int c)
145 {
146 assert(out);
147 assert(in);
148 if (out->buf)
149 free(out->buf);
150 if (in->buf)
151 free(in->buf);
152 return(c);
153 }
154
155
156 static int
157 begin_bufs(const struct md_args *args,
158 struct md_buf *out, struct md_buf *in)
159 {
160 struct stat stin, stout;
161 int c;
162
163 assert(args);
164 assert(in);
165 assert(out);
166
167 if (-1 == fstat(in->fd, &stin)) {
168 warn("%s", in->name);
169 return(1);
170 } else if (0 == stin.st_size) {
171 warnx("%s: empty file", in->name);
172 return(1);
173 } else if (-1 == fstat(out->fd, &stout)) {
174 warn("%s", out->name);
175 return(1);
176 }
177
178 in->bufsz = MAX(stin.st_blksize, BUFFER_IN_DEF);
179 out->bufsz = MAX(stout.st_blksize, BUFFER_OUT_DEF);
180
181 if (NULL == (in->buf = malloc(in->bufsz))) {
182 warn("malloc");
183 return(leave_bufs(out, in, 1));
184 } else if (NULL == (out->buf = malloc(out->bufsz))) {
185 warn("malloc");
186 return(leave_bufs(out, in, 1));
187 }
188
189 c = md_run(args, out, in);
190 return(leave_bufs(out, in, -1 == c ? 1 : 0));
191 }
192
193
194 static void
195 usage(void)
196 {
197 extern char *__progname;
198
199 (void)printf("usage: %s [-o outfile] [infile]\n", __progname);
200 }