mandoc(1): Update to 1.9.13.
[dragonfly.git] / usr.bin / mandoc / mandoc.c
1 /*      $Id: mandoc.c,v 1.7 2009/11/02 06:22:45 kristaps Exp $ */
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  */
17 #if defined(__linux__) || defined(__MINT__)
18 # define _GNU_SOURCE /* strptime() */
19 #endif
20
21 #include <sys/types.h>
22
23 #include <assert.h>
24 #include <ctype.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <time.h>
29
30 #include "libmandoc.h"
31
32 static int       a2time(time_t *, const char *, const char *);
33
34
35 int
36 mandoc_special(const char *p)
37 {
38         int              c;
39
40         if ('\\' != *p++)
41                 return(0);
42
43         switch (*p) {
44         case ('\\'):
45                 /* FALLTHROUGH */
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 */
72         case ('c'):
73                 return(2);
74         case ('e'):
75                 return(2);
76         case ('f'):
77                 if (0 == *++p || ! isgraph((u_char)*p))
78                         return(0);
79                 return(3);
80         case ('*'):
81                 if (0 == *++p || ! isgraph((u_char)*p))
82                         return(0);
83                 switch (*p) {
84                 case ('('):
85                         if (0 == *++p || ! isgraph((u_char)*p))
86                                 return(0);
87                         return(4);
88                 case ('['):
89                         for (c = 3, p++; *p && ']' != *p; p++, c++)
90                                 if ( ! isgraph((u_char)*p))
91                                         break;
92                         return(*p == ']' ? c : 0);
93                 default:
94                         break;
95                 }
96                 return(3);
97         case ('('):
98                 if (0 == *++p || ! isgraph((u_char)*p))
99                         return(0);
100                 if (0 == *++p || ! isgraph((u_char)*p))
101                         return(0);
102                 return(4);
103         case ('['):
104                 break;
105         default:
106                 return(0);
107         }
108
109         for (c = 3, p++; *p && ']' != *p; p++, c++)
110                 if ( ! isgraph((u_char)*p))
111                         break;
112
113         return(*p == ']' ? c : 0);
114 }
115
116
117 void *
118 mandoc_calloc(size_t num, size_t size)
119 {
120         void            *ptr;
121
122         ptr = calloc(num, size);
123         if (NULL == ptr) {
124                 perror(NULL);
125                 exit(EXIT_FAILURE);
126         }
127
128         return(ptr);
129 }
130
131
132 void *
133 mandoc_malloc(size_t size)
134 {
135         void            *ptr;
136
137         ptr = malloc(size);
138         if (NULL == ptr) {
139                 perror(NULL);
140                 exit(EXIT_FAILURE);
141         }
142
143         return(ptr);
144 }
145
146
147 void *
148 mandoc_realloc(void *ptr, size_t size)
149 {
150
151         ptr = realloc(ptr, size);
152         if (NULL == ptr) {
153                 perror(NULL);
154                 exit(EXIT_FAILURE);
155         }
156
157         return(ptr);
158 }
159
160
161 char *
162 mandoc_strdup(const char *ptr)
163 {
164         char            *p;
165
166         p = strdup(ptr);
167         if (NULL == p) {
168                 perror(NULL);
169                 exit(EXIT_FAILURE);
170         }
171
172         return(p);
173 }
174
175
176 static int
177 a2time(time_t *t, const char *fmt, const char *p)
178 {
179         struct tm        tm;
180         char            *pp;
181
182         memset(&tm, 0, sizeof(struct tm));
183
184         pp = strptime(p, fmt, &tm);
185         if (NULL != pp && '\0' == *pp) {
186                 *t = mktime(&tm);
187                 return(1);
188         }
189
190         return(0);
191 }
192
193
194 /*
195  * Convert from a manual date string (see mdoc(7) and man(7)) into a
196  * date according to the stipulated date type.
197  */
198 time_t
199 mandoc_a2time(int flags, const char *p)
200 {
201         time_t           t;
202
203         if (MTIME_MDOCDATE & flags) {
204                 if (0 == strcmp(p, "$" "Mdocdate$"))
205                         return(time(NULL));
206                 if (a2time(&t, "$" "Mdocdate: %b %d %Y $", p))
207                         return(t);
208         }
209
210         if (MTIME_CANONICAL & flags || MTIME_REDUCED & flags)
211                 if (a2time(&t, "%b %d, %Y", p))
212                         return(t);
213
214         if (MTIME_ISO_8601 & flags)
215                 if (a2time(&t, "%Y-%m-%d", p))
216                         return(t);
217
218         if (MTIME_REDUCED & flags) {
219                 if (a2time(&t, "%d, %Y", p))
220                         return(t);
221                 if (a2time(&t, "%Y", p))
222                         return(t);
223         }
224
225         return(0);
226 }