Annotation of mandoc/man_macro.c, Revision 1.12
1.12 ! kristaps 1: /* $Id: man_macro.c,v 1.11 2009/03/31 13:50:19 kristaps Exp $ */
1.1 kristaps 2: /*
3: * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@openbsd.org>
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
7: * above copyright notice and this permission notice appear in all
8: * copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11: * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12: * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13: * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14: * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15: * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16: * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17: * PERFORMANCE OF THIS SOFTWARE.
18: */
19: #include <assert.h>
20: #include <ctype.h>
21: #include <stdlib.h>
22: #include <string.h>
23:
24: #include "libman.h"
25:
1.9 kristaps 26: #define FL_NLINE (1 << 0)
27: #define FL_TLINE (1 << 1)
28:
1.3 kristaps 29: static int man_args(struct man *, int,
30: int *, char *, char **);
1.1 kristaps 31:
1.9 kristaps 32: static int man_flags[MAN_MAX] = {
33: 0, /* __ */
34: 0, /* TH */
35: 0, /* SH */
36: 0, /* SS */
37: FL_TLINE, /* TP */
38: 0, /* LP */
39: 0, /* PP */
40: 0, /* P */
41: 0, /* IP */
42: 0, /* HP */
43: FL_NLINE, /* SM */
44: FL_NLINE, /* SB */
45: FL_NLINE, /* BI */
46: FL_NLINE, /* IB */
47: FL_NLINE, /* BR */
48: FL_NLINE, /* RB */
49: FL_NLINE, /* R */
50: FL_NLINE, /* B */
51: FL_NLINE, /* I */
52: FL_NLINE, /* IR */
53: FL_NLINE, /* RI */
1.10 kristaps 54: 0, /* br */
1.12 ! kristaps 55: 0, /* na */
1.9 kristaps 56: };
1.1 kristaps 57:
1.3 kristaps 58: int
59: man_macro(struct man *man, int tok, int line,
60: int ppos, int *pos, char *buf)
1.1 kristaps 61: {
1.3 kristaps 62: int w, la;
63: char *p;
64: struct man_node *n;
1.1 kristaps 65:
1.3 kristaps 66: if ( ! man_elem_alloc(man, line, ppos, tok))
1.1 kristaps 67: return(0);
1.3 kristaps 68: n = man->last;
69: man->next = MAN_NEXT_CHILD;
1.1 kristaps 70:
71: for (;;) {
72: la = *pos;
1.3 kristaps 73: w = man_args(man, line, pos, buf, &p);
1.1 kristaps 74:
1.3 kristaps 75: if (-1 == w)
1.1 kristaps 76: return(0);
1.3 kristaps 77: if (0 == w)
1.1 kristaps 78: break;
79:
1.3 kristaps 80: if ( ! man_word_alloc(man, line, la, p))
81: return(0);
82: man->next = MAN_NEXT_SIBLING;
83: }
1.1 kristaps 84:
1.9 kristaps 85: if (n == man->last && (FL_NLINE & man_flags[tok])) {
86: if (MAN_NLINE & man->flags)
87: return(man_verr(man, line, ppos,
88: "next-line scope already open"));
89: man->flags |= MAN_NLINE;
90: return(1);
91: }
92:
93: if (FL_TLINE & man_flags[tok]) {
94: if (MAN_NLINE & man->flags)
95: return(man_verr(man, line, ppos,
96: "next-line scope already open"));
97: man->flags |= MAN_NLINE;
98: return(1);
99: }
100:
1.7 kristaps 101: /*
102: * Note that when TH is pruned, we'll be back at the root, so
103: * make sure that we don't clobber as its sibling.
104: */
105:
106: for ( ; man->last; man->last = man->last->parent) {
107: if (man->last == n)
108: break;
109: if (man->last->type == MAN_ROOT)
110: break;
1.5 kristaps 111: if ( ! man_valid_post(man))
112: return(0);
1.6 kristaps 113: if ( ! man_action_post(man))
114: return(0);
115: }
1.1 kristaps 116:
1.5 kristaps 117: assert(man->last);
1.6 kristaps 118:
1.7 kristaps 119: /*
120: * Same here regarding whether we're back at the root.
121: */
122:
123: if (man->last->type != MAN_ROOT && ! man_valid_post(man))
1.5 kristaps 124: return(0);
1.7 kristaps 125: if (man->last->type != MAN_ROOT && ! man_action_post(man))
1.6 kristaps 126: return(0);
1.7 kristaps 127: if (man->last->type != MAN_ROOT)
128: man->next = MAN_NEXT_SIBLING;
1.1 kristaps 129:
130: return(1);
131: }
132:
1.3 kristaps 133:
1.4 kristaps 134: int
135: man_macroend(struct man *m)
136: {
137:
1.6 kristaps 138: for ( ; m->last && m->last != m->first;
139: m->last = m->last->parent) {
140: if ( ! man_valid_post(m))
141: return(0);
142: if ( ! man_action_post(m))
143: return(0);
144: }
1.7 kristaps 145: assert(m->last == m->first);
1.6 kristaps 146:
147: if ( ! man_valid_post(m))
148: return(0);
149: if ( ! man_action_post(m))
150: return(0);
151:
1.4 kristaps 152: return(1);
153: }
154:
155:
1.3 kristaps 156: /* ARGSUSED */
1.4 kristaps 157: static int
1.8 kristaps 158: man_args(struct man *m, int line,
1.3 kristaps 159: int *pos, char *buf, char **v)
160: {
161:
162: if (0 == buf[*pos])
163: return(0);
164:
165: /* First parse non-quoted strings. */
166:
167: if ('\"' != buf[*pos]) {
168: *v = &buf[*pos];
169:
170: while (buf[*pos]) {
171: if (' ' == buf[*pos])
172: if ('\\' != buf[*pos - 1])
173: break;
174: (*pos)++;
175: }
176:
177: if (0 == buf[*pos])
178: return(1);
179:
180: buf[(*pos)++] = 0;
181:
182: if (0 == buf[*pos])
183: return(1);
184:
185: while (buf[*pos] && ' ' == buf[*pos])
186: (*pos)++;
187:
188: if (buf[*pos])
189: return(1);
190:
1.8 kristaps 191: if ( ! man_vwarn(m, line, *pos, "trailing spaces"))
192: return(-1);
193:
194: return(1);
1.3 kristaps 195: }
196:
197: /*
198: * If we're a quoted string (and quoted strings are allowed),
199: * then parse ahead to the next quote. If none's found, it's an
200: * error. After, parse to the next word.
201: */
202:
203: *v = &buf[++(*pos)];
204:
205: while (buf[*pos] && '\"' != buf[*pos])
206: (*pos)++;
207:
208: if (0 == buf[*pos]) {
1.8 kristaps 209: if ( ! man_vwarn(m, line, *pos, "unterminated quote"))
210: return(-1);
211: return(1);
1.3 kristaps 212: }
213:
214: buf[(*pos)++] = 0;
215: if (0 == buf[*pos])
216: return(1);
217:
218: while (buf[*pos] && ' ' == buf[*pos])
219: (*pos)++;
220:
221: if (buf[*pos])
222: return(1);
223:
1.8 kristaps 224: if ( ! man_vwarn(m, line, *pos, "trailing spaces"))
225: return(-1);
226: return(1);
1.3 kristaps 227: }
CVSweb