Annotation of src/usr.bin/mandoc/mandoc.c, Revision 1.11
1.11 ! schwarze 1: /* $Id: mandoc.c,v 1.10 2010/05/15 09:20:01 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 ('q'):
47: /* FALLTHROUGH */
48: case ('-'):
49: /* FALLTHROUGH */
50: case ('~'):
51: /* FALLTHROUGH */
52: case ('^'):
53: /* FALLTHROUGH */
54: case ('%'):
55: /* FALLTHROUGH */
56: case ('0'):
57: /* FALLTHROUGH */
58: case (' '):
59: /* FALLTHROUGH */
60: case ('|'):
61: /* FALLTHROUGH */
62: case ('&'):
63: /* FALLTHROUGH */
64: case ('.'):
65: /* FALLTHROUGH */
66: case (':'):
67: /* FALLTHROUGH */
1.3 schwarze 68: case ('c'):
69: return(2);
1.1 schwarze 70: case ('e'):
71: return(2);
1.6 schwarze 72: case ('s'):
73: if ('\0' == *++p)
74: return(2);
75:
76: c = 2;
77: terminator = 0;
78: lim = 1;
79:
80: if (*p == '\'') {
81: lim = 0;
82: terminator = 1;
83: ++p;
84: ++c;
85: } else if (*p == '[') {
86: lim = 0;
87: terminator = 2;
88: ++p;
89: ++c;
90: } else if (*p == '(') {
91: lim = 2;
92: terminator = 3;
93: ++p;
94: ++c;
95: }
96:
97: if (*p == '+' || *p == '-') {
98: ++p;
99: ++c;
100: }
101:
102: if (*p == '\'') {
103: if (terminator)
104: return(0);
105: lim = 0;
106: terminator = 1;
107: ++p;
108: ++c;
109: } else if (*p == '[') {
110: if (terminator)
111: return(0);
112: lim = 0;
113: terminator = 2;
114: ++p;
115: ++c;
116: } else if (*p == '(') {
117: if (terminator)
118: return(0);
119: lim = 2;
120: terminator = 3;
121: ++p;
122: ++c;
123: }
124:
125: /* TODO: needs to handle floating point. */
126:
127: if ( ! isdigit((u_char)*p))
128: return(0);
129:
130: for (i = 0; isdigit((u_char)*p); i++) {
131: if (lim && i >= lim)
132: break;
133: ++p;
134: ++c;
135: }
136:
137: if (terminator && terminator < 3) {
138: if (1 == terminator && *p != '\'')
139: return(0);
140: if (2 == terminator && *p != ']')
141: return(0);
142: ++p;
143: ++c;
144: }
145:
146: return(c);
1.8 schwarze 147: case ('f'):
148: /* FALLTHROUGH */
149: case ('F'):
150: /* FALLTHROUGH */
1.1 schwarze 151: case ('*'):
152: if (0 == *++p || ! isgraph((u_char)*p))
153: return(0);
154: switch (*p) {
155: case ('('):
156: if (0 == *++p || ! isgraph((u_char)*p))
157: return(0);
158: return(4);
159: case ('['):
160: for (c = 3, p++; *p && ']' != *p; p++, c++)
161: if ( ! isgraph((u_char)*p))
162: break;
163: return(*p == ']' ? c : 0);
164: default:
165: break;
166: }
167: return(3);
168: case ('('):
169: if (0 == *++p || ! isgraph((u_char)*p))
170: return(0);
171: if (0 == *++p || ! isgraph((u_char)*p))
172: return(0);
173: return(4);
174: case ('['):
175: break;
176: default:
177: return(0);
178: }
179:
180: for (c = 3, p++; *p && ']' != *p; p++, c++)
181: if ( ! isgraph((u_char)*p))
182: break;
183:
184: return(*p == ']' ? c : 0);
185: }
186:
1.4 schwarze 187:
188: void *
189: mandoc_calloc(size_t num, size_t size)
190: {
191: void *ptr;
192:
193: ptr = calloc(num, size);
194: if (NULL == ptr) {
195: perror(NULL);
196: exit(EXIT_FAILURE);
197: }
198:
199: return(ptr);
200: }
201:
202:
203: void *
204: mandoc_malloc(size_t size)
205: {
206: void *ptr;
207:
208: ptr = malloc(size);
209: if (NULL == ptr) {
210: perror(NULL);
211: exit(EXIT_FAILURE);
212: }
213:
214: return(ptr);
215: }
216:
217:
218: void *
219: mandoc_realloc(void *ptr, size_t size)
220: {
221:
222: ptr = realloc(ptr, size);
223: if (NULL == ptr) {
224: perror(NULL);
225: exit(EXIT_FAILURE);
226: }
227:
228: return(ptr);
229: }
230:
231:
232: char *
233: mandoc_strdup(const char *ptr)
234: {
235: char *p;
236:
237: p = strdup(ptr);
238: if (NULL == p) {
239: perror(NULL);
240: exit(EXIT_FAILURE);
241: }
242:
243: return(p);
244: }
1.5 schwarze 245:
246:
247: static int
248: a2time(time_t *t, const char *fmt, const char *p)
249: {
250: struct tm tm;
251: char *pp;
252:
253: memset(&tm, 0, sizeof(struct tm));
254:
255: pp = strptime(p, fmt, &tm);
256: if (NULL != pp && '\0' == *pp) {
257: *t = mktime(&tm);
258: return(1);
259: }
260:
261: return(0);
262: }
263:
264:
265: /*
266: * Convert from a manual date string (see mdoc(7) and man(7)) into a
267: * date according to the stipulated date type.
268: */
269: time_t
270: mandoc_a2time(int flags, const char *p)
271: {
272: time_t t;
273:
274: if (MTIME_MDOCDATE & flags) {
275: if (0 == strcmp(p, "$" "Mdocdate$"))
276: return(time(NULL));
277: if (a2time(&t, "$" "Mdocdate: %b %d %Y $", p))
278: return(t);
279: }
280:
281: if (MTIME_CANONICAL & flags || MTIME_REDUCED & flags)
282: if (a2time(&t, "%b %d, %Y", p))
283: return(t);
284:
285: if (MTIME_ISO_8601 & flags)
286: if (a2time(&t, "%Y-%m-%d", p))
287: return(t);
288:
289: if (MTIME_REDUCED & flags) {
290: if (a2time(&t, "%d, %Y", p))
291: return(t);
292: if (a2time(&t, "%Y", p))
293: return(t);
294: }
295:
296: return(0);
297: }
298:
1.9 schwarze 299:
300: int
301: mandoc_eos(const char *p, size_t sz)
302: {
303:
1.10 schwarze 304: if (0 == sz)
305: return(0);
1.9 schwarze 306:
1.11 ! schwarze 307: /*
! 308: * End-of-sentence recognition must include situations where
! 309: * some symbols, such as `)', allow prior EOS punctuation to
! 310: * propogate outward.
! 311: */
! 312:
! 313: for ( ; sz; sz--) {
! 314: switch (p[(int)sz - 1]) {
! 315: case ('\"'):
! 316: /* FALLTHROUGH */
! 317: case ('\''):
! 318: /* FALLTHROUGH */
! 319: case (']'):
! 320: /* FALLTHROUGH */
! 321: case (')'):
! 322: break;
! 323: case ('.'):
! 324: /* Escaped periods. */
! 325: if (sz > 1 && '\\' == p[(int)sz - 2])
! 326: return(0);
! 327: /* FALLTHROUGH */
! 328: case ('!'):
! 329: /* FALLTHROUGH */
! 330: case ('?'):
! 331: return(1);
! 332: default:
1.9 schwarze 333: return(0);
1.11 ! schwarze 334: }
1.9 schwarze 335: }
336:
1.11 ! schwarze 337: return(0);
1.9 schwarze 338: }