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