Merge branch 'vendor/BINUTILS220' into bu220
[dragonfly.git] / usr.bin / mandoc / man_action.c
1 /*      $Id: man_action.c,v 1.8 2009/09/18 22:46:14 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 };
67
68 static  time_t    man_atotime(const char *);
69
70
71 int
72 man_action_post(struct man *m)
73 {
74
75         if (MAN_ACTED & m->last->flags)
76                 return(1);
77         m->last->flags |= MAN_ACTED;
78
79         switch (m->last->type) {
80         case (MAN_TEXT):
81                 /* FALLTHROUGH */
82         case (MAN_ROOT):
83                 return(1);
84         default:
85                 break;
86         }
87
88         if (NULL == man_actions[m->last->tok].post)
89                 return(1);
90         return((*man_actions[m->last->tok].post)(m));
91 }
92
93
94 static int
95 post_fi(struct man *m)
96 {
97
98         if ( ! (MAN_LITERAL & m->flags))
99                 if ( ! man_nwarn(m, m->last, WNLITERAL))
100                         return(0);
101         m->flags &= ~MAN_LITERAL;
102         return(1);
103 }
104
105
106 static int
107 post_nf(struct man *m)
108 {
109
110         if (MAN_LITERAL & m->flags)
111                 if ( ! man_nwarn(m, m->last, WOLITERAL))
112                         return(0);
113         m->flags |= MAN_LITERAL;
114         return(1);
115 }
116
117
118 static int
119 post_TH(struct man *m)
120 {
121         struct man_node *n;
122         char            *ep;
123         long             lval;
124
125         if (m->meta.title)
126                 free(m->meta.title);
127         if (m->meta.vol)
128                 free(m->meta.vol);
129         if (m->meta.source)
130                 free(m->meta.source);
131
132         m->meta.title = m->meta.vol = m->meta.source = NULL;
133         m->meta.msec = 0;
134         m->meta.date = 0;
135
136         /* ->TITLE<- MSEC DATE SOURCE VOL */
137
138         n = m->last->child;
139         assert(n);
140
141         if (NULL == (m->meta.title = strdup(n->string)))
142                 return(man_nerr(m, n, WNMEM));
143
144         /* TITLE ->MSEC<- DATE SOURCE VOL */
145
146         n = n->next;
147         assert(n);
148
149         errno = 0;
150         lval = strtol(n->string, &ep, 10);
151         if (n->string[0] != '\0' && *ep == '\0')
152                 m->meta.msec = (int)lval;
153         else if ( ! man_nwarn(m, n, WMSEC))
154                 return(0);
155
156         /* TITLE MSEC ->DATE<- SOURCE VOL */
157
158         if (NULL == (n = n->next))
159                 m->meta.date = time(NULL);
160         else if (0 == (m->meta.date = man_atotime(n->string))) {
161                 if ( ! man_nwarn(m, n, WDATE))
162                         return(0);
163                 m->meta.date = time(NULL);
164         }
165
166         /* TITLE MSEC DATE ->SOURCE<- VOL */
167
168         if (n && (n = n->next))
169                 if (NULL == (m->meta.source = strdup(n->string)))
170                         return(man_nerr(m, n, WNMEM));
171
172         /* TITLE MSEC DATE SOURCE ->VOL<- */
173
174         if (n && (n = n->next))
175                 if (NULL == (m->meta.vol = strdup(n->string)))
176                         return(man_nerr(m, n, WNMEM));
177
178         /*
179          * The end document shouldn't have the prologue macros as part
180          * of the syntax tree (they encompass only meta-data).
181          */
182
183         if (m->last->parent->child == m->last) {
184                 m->last->parent->child = NULL;
185                 n = m->last;
186                 m->last = m->last->parent;
187                 m->next = MAN_NEXT_CHILD;
188         } else {
189                 assert(m->last->prev);
190                 m->last->prev->next = NULL;
191                 n = m->last;
192                 m->last = m->last->prev;
193                 m->next = MAN_NEXT_SIBLING;
194         }
195
196         man_node_freelist(n);
197         return(1);
198 }
199
200
201 static time_t
202 man_atotime(const char *p)
203 {
204         struct tm        tm;
205         char            *pp;
206
207         bzero(&tm, sizeof(struct tm));
208
209         if ((pp = strptime(p, "%b %d %Y", &tm)) && 0 == *pp)
210                 return(mktime(&tm));
211         if ((pp = strptime(p, "%d %b %Y", &tm)) && 0 == *pp)
212                 return(mktime(&tm));
213         if ((pp = strptime(p, "%b %d, %Y", &tm)) && 0 == *pp)
214                 return(mktime(&tm));
215         if ((pp = strptime(p, "%b %Y", &tm)) && 0 == *pp)
216                 return(mktime(&tm));
217
218         return(0);
219 }