Annotation of mandoc/man_macro.c, Revision 1.17
1.17 ! kristaps 1: /* $Id: man_macro.c,v 1.16 2009/06/16 19:55:28 kristaps Exp $ */
1.1 kristaps 2: /*
1.15 kristaps 3: * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
1.1 kristaps 4: *
5: * Permission to use, copy, modify, and distribute this software for any
1.14 kristaps 6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
1.1 kristaps 8: *
1.14 kristaps 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.
1.1 kristaps 16: */
17: #include <assert.h>
18: #include <ctype.h>
19: #include <stdlib.h>
20: #include <string.h>
21:
22: #include "libman.h"
23:
1.9 kristaps 24: #define FL_NLINE (1 << 0)
25: #define FL_TLINE (1 << 1)
26:
1.3 kristaps 27: static int man_args(struct man *, int,
28: int *, char *, char **);
1.1 kristaps 29:
1.9 kristaps 30: static int man_flags[MAN_MAX] = {
1.16 kristaps 31: 0, /* br */
1.9 kristaps 32: 0, /* TH */
33: 0, /* SH */
34: 0, /* SS */
35: FL_TLINE, /* TP */
36: 0, /* LP */
37: 0, /* PP */
38: 0, /* P */
39: 0, /* IP */
40: 0, /* HP */
41: FL_NLINE, /* SM */
42: FL_NLINE, /* SB */
43: FL_NLINE, /* BI */
44: FL_NLINE, /* IB */
45: FL_NLINE, /* BR */
46: FL_NLINE, /* RB */
47: FL_NLINE, /* R */
48: FL_NLINE, /* B */
49: FL_NLINE, /* I */
50: FL_NLINE, /* IR */
51: FL_NLINE, /* RI */
1.12 kristaps 52: 0, /* na */
1.13 kristaps 53: FL_NLINE, /* i */
1.9 kristaps 54: };
1.1 kristaps 55:
1.3 kristaps 56: int
57: man_macro(struct man *man, int tok, int line,
58: int ppos, int *pos, char *buf)
1.1 kristaps 59: {
1.3 kristaps 60: int w, la;
61: char *p;
62: struct man_node *n;
1.1 kristaps 63:
1.3 kristaps 64: if ( ! man_elem_alloc(man, line, ppos, tok))
1.1 kristaps 65: return(0);
1.3 kristaps 66: n = man->last;
67: man->next = MAN_NEXT_CHILD;
1.1 kristaps 68:
69: for (;;) {
70: la = *pos;
1.3 kristaps 71: w = man_args(man, line, pos, buf, &p);
1.1 kristaps 72:
1.3 kristaps 73: if (-1 == w)
1.1 kristaps 74: return(0);
1.3 kristaps 75: if (0 == w)
1.1 kristaps 76: break;
77:
1.3 kristaps 78: if ( ! man_word_alloc(man, line, la, p))
79: return(0);
80: man->next = MAN_NEXT_SIBLING;
81: }
1.1 kristaps 82:
1.9 kristaps 83: if (n == man->last && (FL_NLINE & man_flags[tok])) {
84: if (MAN_NLINE & man->flags)
1.17 ! kristaps 85: return(man_perr(man, line, ppos, WLNSCOPE));
1.9 kristaps 86: man->flags |= MAN_NLINE;
87: return(1);
88: }
89:
90: if (FL_TLINE & man_flags[tok]) {
91: if (MAN_NLINE & man->flags)
1.17 ! kristaps 92: return(man_perr(man, line, ppos, WLNSCOPE));
1.9 kristaps 93: man->flags |= MAN_NLINE;
94: return(1);
95: }
96:
1.7 kristaps 97: /*
98: * Note that when TH is pruned, we'll be back at the root, so
99: * make sure that we don't clobber as its sibling.
100: */
101:
102: for ( ; man->last; man->last = man->last->parent) {
103: if (man->last == n)
104: break;
105: if (man->last->type == MAN_ROOT)
106: break;
1.5 kristaps 107: if ( ! man_valid_post(man))
108: return(0);
1.6 kristaps 109: if ( ! man_action_post(man))
110: return(0);
111: }
1.1 kristaps 112:
1.5 kristaps 113: assert(man->last);
1.6 kristaps 114:
1.7 kristaps 115: /*
116: * Same here regarding whether we're back at the root.
117: */
118:
119: if (man->last->type != MAN_ROOT && ! man_valid_post(man))
1.5 kristaps 120: return(0);
1.7 kristaps 121: if (man->last->type != MAN_ROOT && ! man_action_post(man))
1.6 kristaps 122: return(0);
1.7 kristaps 123: if (man->last->type != MAN_ROOT)
124: man->next = MAN_NEXT_SIBLING;
1.1 kristaps 125:
126: return(1);
127: }
128:
1.3 kristaps 129:
1.4 kristaps 130: int
131: man_macroend(struct man *m)
132: {
133:
1.6 kristaps 134: for ( ; m->last && m->last != m->first;
135: m->last = m->last->parent) {
136: if ( ! man_valid_post(m))
137: return(0);
138: if ( ! man_action_post(m))
139: return(0);
140: }
1.7 kristaps 141: assert(m->last == m->first);
1.6 kristaps 142:
143: if ( ! man_valid_post(m))
144: return(0);
145: if ( ! man_action_post(m))
146: return(0);
147:
1.4 kristaps 148: return(1);
149: }
150:
151:
1.3 kristaps 152: /* ARGSUSED */
1.4 kristaps 153: static int
1.8 kristaps 154: man_args(struct man *m, int line,
1.3 kristaps 155: int *pos, char *buf, char **v)
156: {
157:
158: if (0 == buf[*pos])
159: return(0);
160:
161: /* First parse non-quoted strings. */
162:
163: if ('\"' != buf[*pos]) {
164: *v = &buf[*pos];
165:
166: while (buf[*pos]) {
167: if (' ' == buf[*pos])
168: if ('\\' != buf[*pos - 1])
169: break;
170: (*pos)++;
171: }
172:
173: if (0 == buf[*pos])
174: return(1);
175:
176: buf[(*pos)++] = 0;
177:
178: if (0 == buf[*pos])
179: return(1);
180:
181: while (buf[*pos] && ' ' == buf[*pos])
182: (*pos)++;
183:
184: if (buf[*pos])
185: return(1);
186:
1.17 ! kristaps 187: if ( ! man_pwarn(m, line, *pos, WTSPACE))
1.8 kristaps 188: return(-1);
189:
190: return(1);
1.3 kristaps 191: }
192:
193: /*
194: * If we're a quoted string (and quoted strings are allowed),
195: * then parse ahead to the next quote. If none's found, it's an
196: * error. After, parse to the next word.
197: */
198:
199: *v = &buf[++(*pos)];
200:
201: while (buf[*pos] && '\"' != buf[*pos])
202: (*pos)++;
203:
204: if (0 == buf[*pos]) {
1.17 ! kristaps 205: if ( ! man_pwarn(m, line, *pos, WTQUOTE))
1.8 kristaps 206: return(-1);
207: return(1);
1.3 kristaps 208: }
209:
210: buf[(*pos)++] = 0;
211: if (0 == buf[*pos])
212: return(1);
213:
214: while (buf[*pos] && ' ' == buf[*pos])
215: (*pos)++;
216:
217: if (buf[*pos])
218: return(1);
219:
1.17 ! kristaps 220: if ( ! man_pwarn(m, line, *pos, WTSPACE))
1.8 kristaps 221: return(-1);
222: return(1);
1.3 kristaps 223: }
CVSweb