]> git.cameronkatri.com Git - mandoc.git/blob - strings.c
Memory-corruption fix.
[mandoc.git] / strings.c
1 /* $Id: strings.c,v 1.26 2009/03/06 14:13:47 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 <ctype.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #ifndef __OpenBSD__
25 #include <time.h>
26 #endif
27
28 #include "private.h"
29
30 /*
31 * Various string-literal operations: converting scalars to and from
32 * strings, etc.
33 */
34
35 struct mdoc_secname {
36 const char *name;
37 int flag;
38 #define MSECNAME_META (1 << 0)
39 };
40
41 /* Section names corresponding to mdoc_sec. */
42
43 static const struct mdoc_secname secnames[] = {
44 { "PROLOGUE", MSECNAME_META },
45 { "BODY", MSECNAME_META },
46 { "NAME", 0 },
47 { "LIBRARY", 0 },
48 { "SYNOPSIS", 0 },
49 { "DESCRIPTION", 0 },
50 { "IMPLEMENTATION NOTES", 0 },
51 { "RETURN VALUES", 0 },
52 { "ENVIRONMENT", 0 },
53 { "FILES", 0 },
54 { "EXAMPLES", 0 },
55 { "DIAGNOSTICS", 0 },
56 { "COMPATIBILITY", 0 },
57 { "ERRORS", 0 },
58 { "SEE ALSO", 0 },
59 { "STANDARDS", 0 },
60 { "HISTORY", 0 },
61 { "AUTHORS", 0 },
62 { "CAVEATS", 0 },
63 { "BUGS", 0 },
64 { NULL, 0 }
65 };
66
67 #ifdef __linux__
68 extern char *strptime(const char *, const char *, struct tm *);
69 #endif
70
71
72 size_t
73 mdoc_isescape(const char *p)
74 {
75 size_t c;
76
77 if ('\\' != *p++)
78 return(0);
79
80 switch (*p) {
81 case ('\\'):
82 /* FALLTHROUGH */
83 case ('\''):
84 /* FALLTHROUGH */
85 case ('`'):
86 /* FALLTHROUGH */
87 case ('-'):
88 /* FALLTHROUGH */
89 case (' '):
90 /* FALLTHROUGH */
91 case ('&'):
92 /* FALLTHROUGH */
93 case ('.'):
94 /* FALLTHROUGH */
95 case ('e'):
96 return(2);
97 case ('*'):
98 if (0 == *++p || ! isgraph((u_char)*p))
99 return(0);
100 switch (*p) {
101 case ('('):
102 if (0 == *++p || ! isgraph((u_char)*p))
103 return(0);
104 return(4);
105 case ('['):
106 for (c = 3, p++; *p && ']' != *p; p++, c++)
107 if ( ! isgraph((u_char)*p))
108 break;
109 return(*p == ']' ? c : 0);
110 default:
111 break;
112 }
113 return(3);
114 case ('('):
115 if (0 == *++p || ! isgraph((u_char)*p))
116 return(0);
117 if (0 == *++p || ! isgraph((u_char)*p))
118 return(0);
119 return(4);
120 case ('['):
121 break;
122 default:
123 return(0);
124 }
125
126 for (c = 3, p++; *p && ']' != *p; p++, c++)
127 if ( ! isgraph((u_char)*p))
128 break;
129
130 return(*p == ']' ? c : 0);
131 }
132
133
134 int
135 mdoc_iscdelim(char p)
136 {
137
138 switch (p) {
139 case('.'):
140 /* FALLTHROUGH */
141 case(','):
142 /* FALLTHROUGH */
143 case(';'):
144 /* FALLTHROUGH */
145 case(':'):
146 /* FALLTHROUGH */
147 case('?'):
148 /* FALLTHROUGH */
149 case('!'):
150 /* FALLTHROUGH */
151 case('('):
152 /* FALLTHROUGH */
153 case(')'):
154 /* FALLTHROUGH */
155 case('['):
156 /* FALLTHROUGH */
157 case(']'):
158 /* FALLTHROUGH */
159 case('{'):
160 /* FALLTHROUGH */
161 case('}'):
162 return(1);
163 default:
164 break;
165 }
166
167 return(0);
168 }
169
170
171 int
172 mdoc_isdelim(const char *p)
173 {
174
175 if (0 == *p)
176 return(0);
177 if (0 != *(p + 1))
178 return(0);
179 return(mdoc_iscdelim(*p));
180 }
181
182
183 enum mdoc_sec
184 mdoc_atosec(const char *p)
185 {
186 const struct mdoc_secname *n;
187 int i;
188
189 for (i = 0, n = secnames; n->name; n++, i++)
190 if ( ! (n->flag & MSECNAME_META))
191 if (xstrcmp(p, n->name))
192 return((enum mdoc_sec)i);
193
194 return(SEC_CUSTOM);
195 }
196
197
198 time_t
199 mdoc_atotime(const char *p)
200 {
201 struct tm tm;
202 char *pp;
203
204 (void)memset(&tm, 0, sizeof(struct tm));
205
206 if (xstrcmp(p, "$Mdocdate: March 6 2009 $"))
207 return(time(NULL));
208 if ((pp = strptime(p, "$Mdocdate: March 6 2009 $", &tm)) && 0 == *pp)
209 return(mktime(&tm));
210 /* XXX - this matches "June 1999", which is wrong. */
211 if ((pp = strptime(p, "%b %d %Y", &tm)) && 0 == *pp)
212 return(mktime(&tm));
213 if ((pp = strptime(p, "%b %d, %Y", &tm)) && 0 == *pp)
214 return(mktime(&tm));
215
216 return(0);
217 }
218
219
220 size_t
221 mdoc_macro2len(int macro)
222 {
223
224 switch (macro) {
225 case(MDOC_Ad):
226 return(12);
227 case(MDOC_Ao):
228 return(12);
229 case(MDOC_An):
230 return(12);
231 case(MDOC_Aq):
232 return(12);
233 case(MDOC_Ar):
234 return(12);
235 case(MDOC_Bo):
236 return(12);
237 case(MDOC_Bq):
238 return(12);
239 case(MDOC_Cd):
240 return(12);
241 case(MDOC_Cm):
242 return(10);
243 case(MDOC_Do):
244 return(10);
245 case(MDOC_Dq):
246 return(12);
247 case(MDOC_Dv):
248 return(12);
249 case(MDOC_Eo):
250 return(12);
251 case(MDOC_Em):
252 return(10);
253 case(MDOC_Er):
254 return(12);
255 case(MDOC_Ev):
256 return(15);
257 case(MDOC_Fa):
258 return(12);
259 case(MDOC_Fl):
260 return(10);
261 case(MDOC_Fo):
262 return(16);
263 case(MDOC_Fn):
264 return(16);
265 case(MDOC_Ic):
266 return(10);
267 case(MDOC_Li):
268 return(16);
269 case(MDOC_Ms):
270 return(6);
271 case(MDOC_Nm):
272 return(10);
273 case(MDOC_No):
274 return(12);
275 case(MDOC_Oo):
276 return(10);
277 case(MDOC_Op):
278 return(14);
279 case(MDOC_Pa):
280 return(32);
281 case(MDOC_Pf):
282 return(12);
283 case(MDOC_Po):
284 return(12);
285 case(MDOC_Pq):
286 return(12);
287 case(MDOC_Ql):
288 return(16);
289 case(MDOC_Qo):
290 return(12);
291 case(MDOC_So):
292 return(12);
293 case(MDOC_Sq):
294 return(12);
295 case(MDOC_Sy):
296 return(6);
297 case(MDOC_Sx):
298 return(16);
299 case(MDOC_Tn):
300 return(10);
301 case(MDOC_Va):
302 return(12);
303 case(MDOC_Vt):
304 return(12);
305 case(MDOC_Xr):
306 return(10);
307 default:
308 break;
309 };
310 return(0);
311 }