Annotation of src/usr.bin/mandoc/mandoc.c, Revision 1.6
1.6 ! schwarze 1: /* $Id: mandoc.c,v 1.5 2009/12/23 22:30:17 schwarze Exp $ */
1.1 schwarze 2: /*
3: * Copyright (c) 2008, 2009 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 above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
1.2 schwarze 17: #include <sys/types.h>
18:
1.1 schwarze 19: #include <assert.h>
20: #include <ctype.h>
21: #include <stdlib.h>
1.4 schwarze 22: #include <stdio.h>
23: #include <string.h>
1.5 schwarze 24: #include <time.h>
1.1 schwarze 25:
26: #include "libmandoc.h"
27:
1.5 schwarze 28: static int a2time(time_t *, const char *, const char *);
29:
30:
1.1 schwarze 31: int
32: mandoc_special(const char *p)
33: {
1.6 ! schwarze 34: int terminator; /* Terminator for \s. */
! 35: int lim; /* Limit for N in \s. */
! 36: int c, i;
1.1 schwarze 37:
38: if ('\\' != *p++)
39: return(0);
40:
41: switch (*p) {
42: case ('\\'):
43: /* FALLTHROUGH */
44: case ('\''):
45: /* FALLTHROUGH */
46: case ('`'):
47: /* FALLTHROUGH */
48: case ('q'):
49: /* FALLTHROUGH */
50: case ('-'):
51: /* FALLTHROUGH */
52: case ('~'):
53: /* FALLTHROUGH */
54: case ('^'):
55: /* FALLTHROUGH */
56: case ('%'):
57: /* FALLTHROUGH */
58: case ('0'):
59: /* FALLTHROUGH */
60: case (' '):
61: /* FALLTHROUGH */
62: case ('|'):
63: /* FALLTHROUGH */
64: case ('&'):
65: /* FALLTHROUGH */
66: case ('.'):
67: /* FALLTHROUGH */
68: case (':'):
69: /* FALLTHROUGH */
1.3 schwarze 70: case ('c'):
71: return(2);
1.1 schwarze 72: case ('e'):
73: return(2);
74: case ('f'):
1.6 ! schwarze 75: if ('\0' == *++p || ! isgraph((u_char)*p))
1.1 schwarze 76: return(0);
77: return(3);
1.6 ! schwarze 78: case ('s'):
! 79: if ('\0' == *++p)
! 80: return(2);
! 81:
! 82: c = 2;
! 83: terminator = 0;
! 84: lim = 1;
! 85:
! 86: if (*p == '\'') {
! 87: lim = 0;
! 88: terminator = 1;
! 89: ++p;
! 90: ++c;
! 91: } else if (*p == '[') {
! 92: lim = 0;
! 93: terminator = 2;
! 94: ++p;
! 95: ++c;
! 96: } else if (*p == '(') {
! 97: lim = 2;
! 98: terminator = 3;
! 99: ++p;
! 100: ++c;
! 101: }
! 102:
! 103: if (*p == '+' || *p == '-') {
! 104: ++p;
! 105: ++c;
! 106: }
! 107:
! 108: if (*p == '\'') {
! 109: if (terminator)
! 110: return(0);
! 111: lim = 0;
! 112: terminator = 1;
! 113: ++p;
! 114: ++c;
! 115: } else if (*p == '[') {
! 116: if (terminator)
! 117: return(0);
! 118: lim = 0;
! 119: terminator = 2;
! 120: ++p;
! 121: ++c;
! 122: } else if (*p == '(') {
! 123: if (terminator)
! 124: return(0);
! 125: lim = 2;
! 126: terminator = 3;
! 127: ++p;
! 128: ++c;
! 129: }
! 130:
! 131: /* TODO: needs to handle floating point. */
! 132:
! 133: if ( ! isdigit((u_char)*p))
! 134: return(0);
! 135:
! 136: for (i = 0; isdigit((u_char)*p); i++) {
! 137: if (lim && i >= lim)
! 138: break;
! 139: ++p;
! 140: ++c;
! 141: }
! 142:
! 143: if (terminator && terminator < 3) {
! 144: if (1 == terminator && *p != '\'')
! 145: return(0);
! 146: if (2 == terminator && *p != ']')
! 147: return(0);
! 148: ++p;
! 149: ++c;
! 150: }
! 151:
! 152: return(c);
1.1 schwarze 153: case ('*'):
154: if (0 == *++p || ! isgraph((u_char)*p))
155: return(0);
156: switch (*p) {
157: case ('('):
158: if (0 == *++p || ! isgraph((u_char)*p))
159: return(0);
160: return(4);
161: case ('['):
162: for (c = 3, p++; *p && ']' != *p; p++, c++)
163: if ( ! isgraph((u_char)*p))
164: break;
165: return(*p == ']' ? c : 0);
166: default:
167: break;
168: }
169: return(3);
170: case ('('):
171: if (0 == *++p || ! isgraph((u_char)*p))
172: return(0);
173: if (0 == *++p || ! isgraph((u_char)*p))
174: return(0);
175: return(4);
176: case ('['):
177: break;
178: default:
179: return(0);
180: }
181:
182: for (c = 3, p++; *p && ']' != *p; p++, c++)
183: if ( ! isgraph((u_char)*p))
184: break;
185:
186: return(*p == ']' ? c : 0);
187: }
188:
1.4 schwarze 189:
190: void *
191: mandoc_calloc(size_t num, size_t size)
192: {
193: void *ptr;
194:
195: ptr = calloc(num, size);
196: if (NULL == ptr) {
197: perror(NULL);
198: exit(EXIT_FAILURE);
199: }
200:
201: return(ptr);
202: }
203:
204:
205: void *
206: mandoc_malloc(size_t size)
207: {
208: void *ptr;
209:
210: ptr = malloc(size);
211: if (NULL == ptr) {
212: perror(NULL);
213: exit(EXIT_FAILURE);
214: }
215:
216: return(ptr);
217: }
218:
219:
220: void *
221: mandoc_realloc(void *ptr, size_t size)
222: {
223:
224: ptr = realloc(ptr, size);
225: if (NULL == ptr) {
226: perror(NULL);
227: exit(EXIT_FAILURE);
228: }
229:
230: return(ptr);
231: }
232:
233:
234: char *
235: mandoc_strdup(const char *ptr)
236: {
237: char *p;
238:
239: p = strdup(ptr);
240: if (NULL == p) {
241: perror(NULL);
242: exit(EXIT_FAILURE);
243: }
244:
245: return(p);
246: }
1.5 schwarze 247:
248:
249: static int
250: a2time(time_t *t, const char *fmt, const char *p)
251: {
252: struct tm tm;
253: char *pp;
254:
255: memset(&tm, 0, sizeof(struct tm));
256:
257: pp = strptime(p, fmt, &tm);
258: if (NULL != pp && '\0' == *pp) {
259: *t = mktime(&tm);
260: return(1);
261: }
262:
263: return(0);
264: }
265:
266:
267: /*
268: * Convert from a manual date string (see mdoc(7) and man(7)) into a
269: * date according to the stipulated date type.
270: */
271: time_t
272: mandoc_a2time(int flags, const char *p)
273: {
274: time_t t;
275:
276: if (MTIME_MDOCDATE & flags) {
277: if (0 == strcmp(p, "$" "Mdocdate$"))
278: return(time(NULL));
279: if (a2time(&t, "$" "Mdocdate: %b %d %Y $", p))
280: return(t);
281: }
282:
283: if (MTIME_CANONICAL & flags || MTIME_REDUCED & flags)
284: if (a2time(&t, "%b %d, %Y", p))
285: return(t);
286:
287: if (MTIME_ISO_8601 & flags)
288: if (a2time(&t, "%Y-%m-%d", p))
289: return(t);
290:
291: if (MTIME_REDUCED & flags) {
292: if (a2time(&t, "%d, %Y", p))
293: return(t);
294: if (a2time(&t, "%Y", p))
295: return(t);
296: }
297:
298: return(0);
299: }
300: