mandoc(1): Update to 1.9.19.
[dragonfly.git] / usr.bin / mandoc / man_action.c
1 /*      $Id: man_action.c,v 1.30 2010/03/27 10:04:56 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
18 #include <assert.h>
19 #include <stdlib.h>
20 #include <string.h>
21
22 #include "libman.h"
23 #include "libmandoc.h"
24
25 struct  actions {
26         int     (*post)(struct man *);
27 };
28
29 static  int       post_TH(struct man *);
30 static  int       post_de(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         { NULL }, /* Sp */
68         { post_nf }, /* Vb */
69         { post_fi }, /* Ve */
70         { post_de }, /* de */
71         { post_de }, /* dei */
72         { post_de }, /* am */
73         { post_de }, /* ami */
74         { post_de }, /* ig */
75         { NULL }, /* . */
76 };
77
78
79 int
80 man_action_post(struct man *m)
81 {
82
83         if (MAN_ACTED & m->last->flags)
84                 return(1);
85         m->last->flags |= MAN_ACTED;
86
87         switch (m->last->type) {
88         case (MAN_TEXT):
89                 /* FALLTHROUGH */
90         case (MAN_ROOT):
91                 return(1);
92         default:
93                 break;
94         }
95
96         if (NULL == man_actions[m->last->tok].post)
97                 return(1);
98         return((*man_actions[m->last->tok].post)(m));
99 }
100
101
102 static int
103 post_fi(struct man *m)
104 {
105
106         if ( ! (MAN_LITERAL & m->flags))
107                 if ( ! man_nwarn(m, m->last, WNLITERAL))
108                         return(0);
109         m->flags &= ~MAN_LITERAL;
110         return(1);
111 }
112
113
114 static int
115 post_de(struct man *m)
116 {
117
118         /*
119          * XXX: for the time being, we indiscriminately remove roff
120          * instructions from the parse stream.
121          */
122         if (MAN_BLOCK == m->last->type)
123                 man_node_delete(m, m->last);
124         return(1);
125 }
126
127
128 static int
129 post_nf(struct man *m)
130 {
131
132         if (MAN_LITERAL & m->flags)
133                 if ( ! man_nwarn(m, m->last, WOLITERAL))
134                         return(0);
135         m->flags |= MAN_LITERAL;
136         return(1);
137 }
138
139
140 static int
141 post_TH(struct man *m)
142 {
143         struct man_node *n;
144         char            *ep;
145         long             lval;
146
147         if (m->meta.title)
148                 free(m->meta.title);
149         if (m->meta.vol)
150                 free(m->meta.vol);
151         if (m->meta.source)
152                 free(m->meta.source);
153
154         m->meta.title = m->meta.vol = m->meta.source = NULL;
155         m->meta.msec = 0;
156         m->meta.date = 0;
157
158         /* ->TITLE<- MSEC DATE SOURCE VOL */
159
160         n = m->last->child;
161         assert(n);
162         m->meta.title = mandoc_strdup(n->string);
163
164         /* TITLE ->MSEC<- DATE SOURCE VOL */
165
166         n = n->next;
167         assert(n);
168
169         lval = strtol(n->string, &ep, 10);
170         if (n->string[0] != '\0' && *ep == '\0')
171                 m->meta.msec = (int)lval;
172         else if ( ! man_nwarn(m, n, WMSEC))
173                 return(0);
174
175         /* TITLE MSEC ->DATE<- SOURCE VOL */
176
177         n = n->next;
178         if (n) {
179                 m->meta.date = mandoc_a2time
180                         (MTIME_ISO_8601, n->string);
181
182                 if (0 == m->meta.date) {
183                         if ( ! man_nwarn(m, n, WDATE))
184                                 return(0);
185                         m->meta.date = time(NULL);
186                 }
187         } else
188                 m->meta.date = time(NULL);
189
190         /* TITLE MSEC DATE ->SOURCE<- VOL */
191
192         if (n && (n = n->next))
193                 m->meta.source = mandoc_strdup(n->string);
194
195         /* TITLE MSEC DATE SOURCE ->VOL<- */
196
197         if (n && (n = n->next))
198                 m->meta.vol = mandoc_strdup(n->string);
199
200         /*
201          * Remove the `TH' node after we've processed it for our
202          * meta-data.
203          */
204         man_node_delete(m, m->last);
205         return(1);
206 }