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