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