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