]>
git.cameronkatri.com Git - mandoc.git/blob - eqn.c
1 /* $Id: eqn.c,v 1.10 2011/07/17 14:15:11 kristaps Exp $ */
3 * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
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.
28 #include "libmandoc.h"
31 #define EQN_ARGS struct eqn_node *ep, \
49 static int eqn_do_define(EQN_ARGS
);
50 static int eqn_do_set(EQN_ARGS
);
51 static int eqn_do_undef(EQN_ARGS
);
52 static const char *eqn_nexttok(struct mparse
*, int, int,
53 const char **, size_t *);
55 static const struct eqnpart eqnparts
[EQN__MAX
] = {
56 { "define", 6, eqn_do_define
}, /* EQN_DEFINE */
57 { "set", 3, eqn_do_set
}, /* EQN_SET */
58 { "undef", 5, eqn_do_undef
}, /* EQN_UNDEF */
63 eqn_read(struct eqn_node
**epp
, int ln
,
64 const char *p
, int pos
, int *offs
)
69 const char *start
, *end
;
72 if (0 == strcmp(p
, ".EN")) {
81 if (NULL
== (start
= eqn_nexttok(mp
, ln
, pos
, &end
, &sz
)))
84 for (i
= 0; i
< (int)EQN__MAX
; i
++) {
85 if (eqnparts
[i
].sz
!= sz
)
87 if (strncmp(eqnparts
[i
].name
, start
, sz
))
90 if ((c
= (*eqnparts
[i
].fp
)(ep
, ln
, pos
, &end
)) < 0)
92 else if (0 == c
|| '\0' == *end
)
96 * Re-calculate offset and rerun, if trailing text.
97 * This allows multiple definitions (say) on each line.
100 *offs
= end
- (p
+ pos
);
105 while (NULL
!= (start
= eqn_nexttok(mp
, ln
, pos
, &end
, &sz
))) {
109 for (i
= 0; i
< (int)ep
->defsz
; i
++) {
110 if (0 == ep
->defs
[i
].keysz
)
112 if (ep
->defs
[i
].keysz
!= sz
)
114 if (strncmp(ep
->defs
[i
].key
, start
, sz
))
116 start
= ep
->defs
[i
].val
;
117 sz
= ep
->defs
[i
].valsz
;
121 ep
->eqn
.data
= mandoc_realloc
122 (ep
->eqn
.data
, ep
->eqn
.sz
+ sz
+ 1);
125 *ep
->eqn
.data
= '\0';
128 strlcat(ep
->eqn
.data
, start
, ep
->eqn
.sz
+ 1);
135 eqn_alloc(int pos
, int line
, struct mparse
*parse
)
139 p
= mandoc_calloc(1, sizeof(struct eqn_node
));
149 eqn_end(struct eqn_node
*e
)
156 eqn_free(struct eqn_node
*p
)
162 for (i
= 0; i
< (int)p
->defsz
; i
++) {
163 free(p
->defs
[i
].key
);
164 free(p
->defs
[i
].val
);
172 * Return the current equation token setting "next" on the next one,
173 * setting the token size in "sz".
174 * This does the Right Thing for quoted strings, too.
175 * Returns NULL if no more tokens exist.
178 eqn_nexttok(struct mparse
*mp
, int ln
, int pos
,
179 const char **next
, size_t *sz
)
195 *next
= q
? strchr(start
, '"') : strchr(start
, ' ');
198 *sz
= (size_t)(*next
- start
);
201 while (' ' == **next
)
205 * XXX: groff gets confused by this and doesn't always
206 * do the "right thing" (just terminate it and warn
210 mandoc_msg(MANDOCERR_BADQUOTE
,
212 *next
= strchr(start
, '\0');
213 *sz
= (size_t)(*next
- start
);
220 eqn_do_set(struct eqn_node
*ep
, int ln
, int pos
, const char **end
)
228 start
= eqn_nexttok(ep
->parse
, ln
, pos
, end
, &sz
);
229 if (NULL
== start
|| 0 == sz
) {
230 mandoc_msg(MANDOCERR_EQNARGS
, mp
, ln
, pos
, NULL
);
234 start
= eqn_nexttok(ep
->parse
, ln
, pos
, end
, &sz
);
235 if (NULL
== start
|| 0 == sz
) {
236 mandoc_msg(MANDOCERR_EQNARGS
, mp
, ln
, pos
, NULL
);
244 eqn_do_define(struct eqn_node
*ep
, int ln
, int pos
, const char **end
)
253 start
= eqn_nexttok(mp
, ln
, pos
, end
, &sz
);
254 if (NULL
== start
|| 0 == sz
) {
255 mandoc_msg(MANDOCERR_EQNARGS
, mp
, ln
, pos
, NULL
);
259 /* TODO: merge this code with roff_getstr(). */
262 * Search for a key that already exists.
263 * Note that the string array can have "holes" (null key).
266 for (i
= 0; i
< (int)ep
->defsz
; i
++) {
267 if (0 == ep
->defs
[i
].keysz
|| ep
->defs
[i
].keysz
!= sz
)
269 if (0 == strncmp(ep
->defs
[i
].key
, start
, sz
))
273 /* Create a new key. */
275 if (i
== (int)ep
->defsz
) {
276 /* Find holes in string array. */
277 for (i
= 0; i
< (int)ep
->defsz
; i
++)
278 if (0 == ep
->defs
[i
].keysz
)
281 if (i
== (int)ep
->defsz
) {
283 ep
->defs
= mandoc_realloc
284 (ep
->defs
, ep
->defsz
*
285 sizeof(struct eqn_def
));
286 ep
->defs
[i
].key
= ep
->defs
[i
].val
= NULL
;
289 ep
->defs
[i
].keysz
= sz
;
290 ep
->defs
[i
].key
= mandoc_realloc
291 (ep
->defs
[i
].key
, sz
+ 1);
293 memcpy(ep
->defs
[i
].key
, start
, sz
);
294 ep
->defs
[i
].key
[(int)sz
] = '\0';
297 start
= eqn_nexttok(mp
, ln
, pos
, end
, &sz
);
299 if (NULL
== start
|| 0 == sz
) {
300 ep
->defs
[i
].keysz
= 0;
301 mandoc_msg(MANDOCERR_EQNARGS
, mp
, ln
, pos
, NULL
);
305 ep
->defs
[i
].valsz
= sz
;
306 ep
->defs
[i
].val
= mandoc_realloc
307 (ep
->defs
[i
].val
, sz
+ 1);
308 memcpy(ep
->defs
[i
].val
, start
, sz
);
309 ep
->defs
[i
].val
[(int)sz
] = '\0';
315 eqn_do_undef(struct eqn_node
*ep
, int ln
, int pos
, const char **end
)
324 start
= eqn_nexttok(mp
, ln
, pos
, end
, &sz
);
325 if (NULL
== start
|| 0 == sz
) {
326 mandoc_msg(MANDOCERR_EQNARGS
, mp
, ln
, pos
, NULL
);
330 for (i
= 0; i
< (int)ep
->defsz
; i
++) {
331 if (0 == ep
->defs
[i
].keysz
|| ep
->defs
[i
].keysz
!= sz
)
333 if (strncmp(ep
->defs
[i
].key
, start
, sz
))
335 ep
->defs
[i
].keysz
= 0;