Annotation of mandoc/man_macro.c, Revision 1.7
1.7 ! kristaps 1: /* $Id: man_macro.c,v 1.6 2009/03/25 15:36:05 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>
1.3 kristaps 21: #include <err.h> /* XXX */
1.1 kristaps 22: #include <stdlib.h>
23: #include <stdio.h>
24: #include <string.h>
25:
26: #include "libman.h"
27:
1.3 kristaps 28: static int man_args(struct man *, int,
29: int *, char *, char **);
1.1 kristaps 30:
31:
1.3 kristaps 32: int
33: man_macro(struct man *man, int tok, int line,
34: int ppos, int *pos, char *buf)
1.1 kristaps 35: {
1.3 kristaps 36: int w, la;
37: char *p;
38: struct man_node *n;
1.1 kristaps 39:
1.3 kristaps 40: if ( ! man_elem_alloc(man, line, ppos, tok))
1.1 kristaps 41: return(0);
1.3 kristaps 42: n = man->last;
43: man->next = MAN_NEXT_CHILD;
1.1 kristaps 44:
45: for (;;) {
46: la = *pos;
1.3 kristaps 47: w = man_args(man, line, pos, buf, &p);
1.1 kristaps 48:
1.3 kristaps 49: if (-1 == w)
1.1 kristaps 50: return(0);
1.3 kristaps 51: if (0 == w)
1.1 kristaps 52: break;
53:
1.3 kristaps 54: if ( ! man_word_alloc(man, line, la, p))
55: return(0);
56: man->next = MAN_NEXT_SIBLING;
57: }
1.1 kristaps 58:
1.7 ! kristaps 59: /*
! 60: * Note that when TH is pruned, we'll be back at the root, so
! 61: * make sure that we don't clobber as its sibling.
! 62: */
! 63:
! 64: for ( ; man->last; man->last = man->last->parent) {
! 65: if (man->last == n)
! 66: break;
! 67: if (man->last->type == MAN_ROOT)
! 68: break;
1.5 kristaps 69: if ( ! man_valid_post(man))
70: return(0);
1.6 kristaps 71: if ( ! man_action_post(man))
72: return(0);
73: }
1.1 kristaps 74:
1.5 kristaps 75: assert(man->last);
1.6 kristaps 76:
1.7 ! kristaps 77: /*
! 78: * Same here regarding whether we're back at the root.
! 79: */
! 80:
! 81: if (man->last->type != MAN_ROOT && ! man_valid_post(man))
1.5 kristaps 82: return(0);
1.7 ! kristaps 83: if (man->last->type != MAN_ROOT && ! man_action_post(man))
1.6 kristaps 84: return(0);
1.7 ! kristaps 85: if (man->last->type != MAN_ROOT)
! 86: man->next = MAN_NEXT_SIBLING;
1.1 kristaps 87:
88: return(1);
89: }
90:
1.3 kristaps 91:
1.4 kristaps 92: int
93: man_macroend(struct man *m)
94: {
95:
1.6 kristaps 96: for ( ; m->last && m->last != m->first;
97: m->last = m->last->parent) {
98: if ( ! man_valid_post(m))
99: return(0);
100: if ( ! man_action_post(m))
101: return(0);
102: }
1.7 ! kristaps 103: assert(m->last == m->first);
1.6 kristaps 104:
105: if ( ! man_valid_post(m))
106: return(0);
107: if ( ! man_action_post(m))
108: return(0);
109:
1.4 kristaps 110: return(1);
111: }
112:
113:
1.3 kristaps 114: /* ARGSUSED */
1.4 kristaps 115: static int
1.3 kristaps 116: man_args(struct man *man, int line,
117: int *pos, char *buf, char **v)
118: {
119:
120: if (0 == buf[*pos])
121: return(0);
122:
123: /* First parse non-quoted strings. */
124:
125: if ('\"' != buf[*pos]) {
126: *v = &buf[*pos];
127:
128: while (buf[*pos]) {
129: if (' ' == buf[*pos])
130: if ('\\' != buf[*pos - 1])
131: break;
132: (*pos)++;
133: }
134:
135: if (0 == buf[*pos])
136: return(1);
137:
138: buf[(*pos)++] = 0;
139:
140: if (0 == buf[*pos])
141: return(1);
142:
143: while (buf[*pos] && ' ' == buf[*pos])
144: (*pos)++;
145:
146: if (buf[*pos])
147: return(1);
148:
149: warnx("tail whitespace");
150: return(-1);
151: }
152:
153: /*
154: * If we're a quoted string (and quoted strings are allowed),
155: * then parse ahead to the next quote. If none's found, it's an
156: * error. After, parse to the next word.
157: */
158:
159: *v = &buf[++(*pos)];
160:
161: while (buf[*pos] && '\"' != buf[*pos])
162: (*pos)++;
163:
164: if (0 == buf[*pos]) {
165: warnx("unterminated quotation");
166: return(-1);
167: }
168:
169: buf[(*pos)++] = 0;
170: if (0 == buf[*pos])
171: return(1);
172:
173: while (buf[*pos] && ' ' == buf[*pos])
174: (*pos)++;
175:
176: if (buf[*pos])
177: return(1);
178:
179: warnx("tail whitespace");
180: return(-1);
181: }
CVSweb