Annotation of mandoc/man_macro.c, Revision 1.13
1.13 ! kristaps 1: /* $Id: man_macro.c,v 1.12 2009/04/02 06:51:44 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.13 ! kristaps 56: FL_NLINE, /* i */
1.9 kristaps 57: };
1.1 kristaps 58:
1.3 kristaps 59: int
60: man_macro(struct man *man, int tok, int line,
61: int ppos, int *pos, char *buf)
1.1 kristaps 62: {
1.3 kristaps 63: int w, la;
64: char *p;
65: struct man_node *n;
1.1 kristaps 66:
1.3 kristaps 67: if ( ! man_elem_alloc(man, line, ppos, tok))
1.1 kristaps 68: return(0);
1.3 kristaps 69: n = man->last;
70: man->next = MAN_NEXT_CHILD;
1.1 kristaps 71:
72: for (;;) {
73: la = *pos;
1.3 kristaps 74: w = man_args(man, line, pos, buf, &p);
1.1 kristaps 75:
1.3 kristaps 76: if (-1 == w)
1.1 kristaps 77: return(0);
1.3 kristaps 78: if (0 == w)
1.1 kristaps 79: break;
80:
1.3 kristaps 81: if ( ! man_word_alloc(man, line, la, p))
82: return(0);
83: man->next = MAN_NEXT_SIBLING;
84: }
1.1 kristaps 85:
1.9 kristaps 86: if (n == man->last && (FL_NLINE & man_flags[tok])) {
87: if (MAN_NLINE & man->flags)
88: return(man_verr(man, line, ppos,
89: "next-line scope already open"));
90: man->flags |= MAN_NLINE;
91: return(1);
92: }
93:
94: if (FL_TLINE & man_flags[tok]) {
95: if (MAN_NLINE & man->flags)
96: return(man_verr(man, line, ppos,
97: "next-line scope already open"));
98: man->flags |= MAN_NLINE;
99: return(1);
100: }
101:
1.7 kristaps 102: /*
103: * Note that when TH is pruned, we'll be back at the root, so
104: * make sure that we don't clobber as its sibling.
105: */
106:
107: for ( ; man->last; man->last = man->last->parent) {
108: if (man->last == n)
109: break;
110: if (man->last->type == MAN_ROOT)
111: break;
1.5 kristaps 112: if ( ! man_valid_post(man))
113: return(0);
1.6 kristaps 114: if ( ! man_action_post(man))
115: return(0);
116: }
1.1 kristaps 117:
1.5 kristaps 118: assert(man->last);
1.6 kristaps 119:
1.7 kristaps 120: /*
121: * Same here regarding whether we're back at the root.
122: */
123:
124: if (man->last->type != MAN_ROOT && ! man_valid_post(man))
1.5 kristaps 125: return(0);
1.7 kristaps 126: if (man->last->type != MAN_ROOT && ! man_action_post(man))
1.6 kristaps 127: return(0);
1.7 kristaps 128: if (man->last->type != MAN_ROOT)
129: man->next = MAN_NEXT_SIBLING;
1.1 kristaps 130:
131: return(1);
132: }
133:
1.3 kristaps 134:
1.4 kristaps 135: int
136: man_macroend(struct man *m)
137: {
138:
1.6 kristaps 139: for ( ; m->last && m->last != m->first;
140: m->last = m->last->parent) {
141: if ( ! man_valid_post(m))
142: return(0);
143: if ( ! man_action_post(m))
144: return(0);
145: }
1.7 kristaps 146: assert(m->last == m->first);
1.6 kristaps 147:
148: if ( ! man_valid_post(m))
149: return(0);
150: if ( ! man_action_post(m))
151: return(0);
152:
1.4 kristaps 153: return(1);
154: }
155:
156:
1.3 kristaps 157: /* ARGSUSED */
1.4 kristaps 158: static int
1.8 kristaps 159: man_args(struct man *m, int line,
1.3 kristaps 160: int *pos, char *buf, char **v)
161: {
162:
163: if (0 == buf[*pos])
164: return(0);
165:
166: /* First parse non-quoted strings. */
167:
168: if ('\"' != buf[*pos]) {
169: *v = &buf[*pos];
170:
171: while (buf[*pos]) {
172: if (' ' == buf[*pos])
173: if ('\\' != buf[*pos - 1])
174: break;
175: (*pos)++;
176: }
177:
178: if (0 == buf[*pos])
179: return(1);
180:
181: buf[(*pos)++] = 0;
182:
183: if (0 == buf[*pos])
184: return(1);
185:
186: while (buf[*pos] && ' ' == buf[*pos])
187: (*pos)++;
188:
189: if (buf[*pos])
190: return(1);
191:
1.8 kristaps 192: if ( ! man_vwarn(m, line, *pos, "trailing spaces"))
193: return(-1);
194:
195: return(1);
1.3 kristaps 196: }
197:
198: /*
199: * If we're a quoted string (and quoted strings are allowed),
200: * then parse ahead to the next quote. If none's found, it's an
201: * error. After, parse to the next word.
202: */
203:
204: *v = &buf[++(*pos)];
205:
206: while (buf[*pos] && '\"' != buf[*pos])
207: (*pos)++;
208:
209: if (0 == buf[*pos]) {
1.8 kristaps 210: if ( ! man_vwarn(m, line, *pos, "unterminated quote"))
211: return(-1);
212: return(1);
1.3 kristaps 213: }
214:
215: buf[(*pos)++] = 0;
216: if (0 == buf[*pos])
217: return(1);
218:
219: while (buf[*pos] && ' ' == buf[*pos])
220: (*pos)++;
221:
222: if (buf[*pos])
223: return(1);
224:
1.8 kristaps 225: if ( ! man_vwarn(m, line, *pos, "trailing spaces"))
226: return(-1);
227: return(1);
1.3 kristaps 228: }
CVSweb