e0e801a97912bc2ac3dde7a753c37ae3c1e124c9
[dragonfly.git] / usr.bin / mandoc / man_action.c
1 /*      $Id: man_action.c,v 1.25 2010/01/01 17:14:27 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 #include <sys/utsname.h>
18
19 #include <assert.h>
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include "libman.h"
24 #include "libmandoc.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
70 int
71 man_action_post(struct man *m)
72 {
73
74         if (MAN_ACTED & m->last->flags)
75                 return(1);
76         m->last->flags |= MAN_ACTED;
77
78         switch (m->last->type) {
79         case (MAN_TEXT):
80                 /* FALLTHROUGH */
81         case (MAN_ROOT):
82                 return(1);
83         default:
84                 break;
85         }
86
87         if (NULL == man_actions[m->last->tok].post)
88                 return(1);
89         return((*man_actions[m->last->tok].post)(m));
90 }
91
92
93 static int
94 post_fi(struct man *m)
95 {
96
97         if ( ! (MAN_LITERAL & m->flags))
98                 if ( ! man_nwarn(m, m->last, WNLITERAL))
99                         return(0);
100         m->flags &= ~MAN_LITERAL;
101         return(1);
102 }
103
104
105 static int
106 post_nf(struct man *m)
107 {
108
109         if (MAN_LITERAL & m->flags)
110                 if ( ! man_nwarn(m, m->last, WOLITERAL))
111                         return(0);
112         m->flags |= MAN_LITERAL;
113         return(1);
114 }
115
116
117 static int
118 post_TH(struct man *m)
119 {
120         struct man_node *n;
121         char            *ep;
122         long             lval;
123
124         if (m->meta.title)
125                 free(m->meta.title);
126         if (m->meta.vol)
127                 free(m->meta.vol);
128         if (m->meta.source)
129                 free(m->meta.source);
130
131         m->meta.title = m->meta.vol = m->meta.source = NULL;
132         m->meta.msec = 0;
133         m->meta.date = 0;
134
135         /* ->TITLE<- MSEC DATE SOURCE VOL */
136
137         n = m->last->child;
138         assert(n);
139         m->meta.title = mandoc_strdup(n->string);
140
141         /* TITLE ->MSEC<- DATE SOURCE VOL */
142
143         n = n->next;
144         assert(n);
145
146         lval = strtol(n->string, &ep, 10);
147         if (n->string[0] != '\0' && *ep == '\0')
148                 m->meta.msec = (int)lval;
149         else if ( ! man_nwarn(m, n, WMSEC))
150                 return(0);
151
152         /* TITLE MSEC ->DATE<- SOURCE VOL */
153
154         n = n->next;
155         if (n) {
156                 m->meta.date = mandoc_a2time
157                         (MTIME_ISO_8601, n->string);
158
159                 if (0 == m->meta.date) {
160                         if ( ! man_nwarn(m, n, WDATE))
161                                 return(0);
162                         m->meta.date = time(NULL);
163                 }
164         } else
165                 m->meta.date = time(NULL);
166
167         /* TITLE MSEC DATE ->SOURCE<- VOL */
168
169         if (n && (n = n->next))
170                 m->meta.source = mandoc_strdup(n->string);
171
172         /* TITLE MSEC DATE SOURCE ->VOL<- */
173
174         if (n && (n = n->next))
175                 m->meta.vol = mandoc_strdup(n->string);
176
177         /*
178          * The end document shouldn't have the prologue macros as part
179          * of the syntax tree (they encompass only meta-data).
180          */
181
182         if (m->last->parent->child == m->last) {
183                 m->last->parent->child = NULL;
184                 n = m->last;
185                 m->last = m->last->parent;
186                 m->next = MAN_NEXT_CHILD;
187         } else {
188                 assert(m->last->prev);
189                 m->last->prev->next = NULL;
190                 n = m->last;
191                 m->last = m->last->prev;
192                 m->next = MAN_NEXT_SIBLING;
193         }
194
195         man_node_freelist(n);
196         return(1);
197 }