mandoc(1): Update to 1.9.11.
[dragonfly.git] / usr.bin / mandoc / man_action.c
1 /*      $Id: man_action.c,v 1.9 2009/10/27 21:40:07 schwarze 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 #include <sys/utsname.h>
18
19 #include <assert.h>
20 #include <errno.h>
21 #include <stdlib.h>
22 #include <string.h>
23
24 #include "libman.h"
25
26 struct  actions {
27         int     (*post)(struct man *);
28 };
29
30 static  int       post_TH(struct man *);
31 static  int       post_fi(struct man *);
32 static  int       post_nf(struct man *);
33
34 const   struct actions man_actions[MAN_MAX] = {
35         { NULL }, /* br */
36         { post_TH }, /* TH */
37         { NULL }, /* SH */
38         { NULL }, /* SS */
39         { NULL }, /* TP */
40         { NULL }, /* LP */
41         { NULL }, /* PP */
42         { NULL }, /* P */
43         { NULL }, /* IP */
44         { NULL }, /* HP */
45         { NULL }, /* SM */
46         { NULL }, /* SB */
47         { NULL }, /* BI */
48         { NULL }, /* IB */
49         { NULL }, /* BR */
50         { NULL }, /* RB */
51         { NULL }, /* R */
52         { NULL }, /* B */
53         { NULL }, /* I */
54         { NULL }, /* IR */
55         { NULL }, /* RI */
56         { NULL }, /* na */
57         { NULL }, /* i */
58         { NULL }, /* sp */
59         { post_nf }, /* nf */
60         { post_fi }, /* fi */
61         { NULL }, /* r */
62         { NULL }, /* RE */
63         { NULL }, /* RS */
64         { NULL }, /* DT */
65         { NULL }, /* UC */
66         { NULL }, /* PD */
67 };
68
69 static  time_t    man_atotime(const char *);
70
71
72 int
73 man_action_post(struct man *m)
74 {
75
76         if (MAN_ACTED & m->last->flags)
77                 return(1);
78         m->last->flags |= MAN_ACTED;
79
80         switch (m->last->type) {
81         case (MAN_TEXT):
82                 /* FALLTHROUGH */
83         case (MAN_ROOT):
84                 return(1);
85         default:
86                 break;
87         }
88
89         if (NULL == man_actions[m->last->tok].post)
90                 return(1);
91         return((*man_actions[m->last->tok].post)(m));
92 }
93
94
95 static int
96 post_fi(struct man *m)
97 {
98
99         if ( ! (MAN_LITERAL & m->flags))
100                 if ( ! man_nwarn(m, m->last, WNLITERAL))
101                         return(0);
102         m->flags &= ~MAN_LITERAL;
103         return(1);
104 }
105
106
107 static int
108 post_nf(struct man *m)
109 {
110
111         if (MAN_LITERAL & m->flags)
112                 if ( ! man_nwarn(m, m->last, WOLITERAL))
113                         return(0);
114         m->flags |= MAN_LITERAL;
115         return(1);
116 }
117
118
119 static int
120 post_TH(struct man *m)
121 {
122         struct man_node *n;
123         char            *ep;
124         long             lval;
125
126         if (m->meta.title)
127                 free(m->meta.title);
128         if (m->meta.vol)
129                 free(m->meta.vol);
130         if (m->meta.source)
131                 free(m->meta.source);
132
133         m->meta.title = m->meta.vol = m->meta.source = NULL;
134         m->meta.msec = 0;
135         m->meta.date = 0;
136
137         /* ->TITLE<- MSEC DATE SOURCE VOL */
138
139         n = m->last->child;
140         assert(n);
141
142         if (NULL == (m->meta.title = strdup(n->string)))
143                 return(man_nerr(m, n, WNMEM));
144
145         /* TITLE ->MSEC<- DATE SOURCE VOL */
146
147         n = n->next;
148         assert(n);
149
150         errno = 0;
151         lval = strtol(n->string, &ep, 10);
152         if (n->string[0] != '\0' && *ep == '\0')
153                 m->meta.msec = (int)lval;
154         else if ( ! man_nwarn(m, n, WMSEC))
155                 return(0);
156
157         /* TITLE MSEC ->DATE<- SOURCE VOL */
158
159         if (NULL == (n = n->next))
160                 m->meta.date = time(NULL);
161         else if (0 == (m->meta.date = man_atotime(n->string))) {
162                 if ( ! man_nwarn(m, n, WDATE))
163                         return(0);
164                 m->meta.date = time(NULL);
165         }
166
167         /* TITLE MSEC DATE ->SOURCE<- VOL */
168
169         if (n && (n = n->next))
170                 if (NULL == (m->meta.source = strdup(n->string)))
171                         return(man_nerr(m, n, WNMEM));
172
173         /* TITLE MSEC DATE SOURCE ->VOL<- */
174
175         if (n && (n = n->next))
176                 if (NULL == (m->meta.vol = strdup(n->string)))
177                         return(man_nerr(m, n, WNMEM));
178
179         /*
180          * The end document shouldn't have the prologue macros as part
181          * of the syntax tree (they encompass only meta-data).
182          */
183
184         if (m->last->parent->child == m->last) {
185                 m->last->parent->child = NULL;
186                 n = m->last;
187                 m->last = m->last->parent;
188                 m->next = MAN_NEXT_CHILD;
189         } else {
190                 assert(m->last->prev);
191                 m->last->prev->next = NULL;
192                 n = m->last;
193                 m->last = m->last->prev;
194                 m->next = MAN_NEXT_SIBLING;
195         }
196
197         man_node_freelist(n);
198         return(1);
199 }
200
201
202 static time_t
203 man_atotime(const char *p)
204 {
205         struct tm        tm;
206         char            *pp;
207
208         bzero(&tm, sizeof(struct tm));
209
210         if ((pp = strptime(p, "%b %d %Y", &tm)) && 0 == *pp)
211                 return(mktime(&tm));
212         if ((pp = strptime(p, "%d %b %Y", &tm)) && 0 == *pp)
213                 return(mktime(&tm));
214         if ((pp = strptime(p, "%b %d, %Y", &tm)) && 0 == *pp)
215                 return(mktime(&tm));
216         if ((pp = strptime(p, "%b %Y", &tm)) && 0 == *pp)
217                 return(mktime(&tm));
218
219         return(0);
220 }