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