Annotation of mandoc/eqn.c, Revision 1.29
1.29 ! kristaps 1: /* $Id: eqn.c,v 1.28 2011/07/22 14:26:32 kristaps Exp $ */
1.1 kristaps 2: /*
3: * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
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 above
7: * copyright notice and this permission notice appear in all copies.
8: *
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.
16: */
17: #ifdef HAVE_CONFIG_H
18: #include "config.h"
19: #endif
20:
21: #include <assert.h>
1.19 kristaps 22: #include <limits.h>
1.1 kristaps 23: #include <stdio.h>
24: #include <stdlib.h>
25: #include <string.h>
26: #include <time.h>
27:
28: #include "mandoc.h"
29: #include "libmandoc.h"
30: #include "libroff.h"
31:
1.11 kristaps 32: #define EQN_NEST_MAX 128 /* maximum nesting of defines */
1.12 kristaps 33: #define EQN_MSG(t, x) mandoc_msg((t), (x)->parse, (x)->eqn.ln, (x)->eqn.pos, NULL)
1.8 kristaps 34:
1.20 kristaps 35: enum eqn_rest {
36: EQN_DESCOPE,
37: EQN_ERR,
38: EQN_OK,
39: EQN_EOF
40: };
41:
1.27 kristaps 42: enum eqn_symt {
43: EQNSYM_alpha,
44: EQNSYM_beta,
45: EQNSYM_chi,
46: EQNSYM_delta,
47: EQNSYM_epsilon,
48: EQNSYM_eta,
49: EQNSYM_gamma,
50: EQNSYM_iota,
51: EQNSYM_kappa,
52: EQNSYM_lambda,
53: EQNSYM_mu,
54: EQNSYM_nu,
55: EQNSYM_omega,
56: EQNSYM_omicron,
57: EQNSYM_phi,
58: EQNSYM_pi,
59: EQNSYM_ps,
60: EQNSYM_rho,
61: EQNSYM_sigma,
62: EQNSYM_tau,
63: EQNSYM_theta,
64: EQNSYM_upsilon,
65: EQNSYM_xi,
66: EQNSYM_zeta,
67: EQNSYM_DELTA,
68: EQNSYM_GAMMA,
69: EQNSYM_LAMBDA,
70: EQNSYM_OMEGA,
71: EQNSYM_PHI,
72: EQNSYM_PI,
73: EQNSYM_PSI,
74: EQNSYM_SIGMA,
75: EQNSYM_THETA,
76: EQNSYM_UPSILON,
77: EQNSYM_XI,
1.28 kristaps 78: EQNSYM_inter,
79: EQNSYM_union,
80: EQNSYM_prod,
81: EQNSYM_int,
82: EQNSYM_sum,
83: EQNSYM_grad,
84: EQNSYM_del,
85: EQNSYM_times,
86: EQNSYM_cdot,
87: EQNSYM_nothing,
88: EQNSYM_approx,
89: EQNSYM_prime,
90: EQNSYM_half,
91: EQNSYM_partial,
92: EQNSYM_inf,
93: EQNSYM_muchgreat,
94: EQNSYM_muchless,
95: EQNSYM_larrow,
96: EQNSYM_rarrow,
97: EQNSYM_pm,
98: EQNSYM_nequal,
99: EQNSYM_equiv,
100: EQNSYM_lessequal,
101: EQNSYM_moreequal,
1.27 kristaps 102: EQNSYM__MAX
103: };
104:
1.17 kristaps 105: struct eqnstr {
1.8 kristaps 106: const char *name;
107: size_t sz;
108: };
109:
1.24 kristaps 110: #define STRNEQ(p1, sz1, p2, sz2) \
1.25 kristaps 111: ((sz1) == (sz2) && 0 == strncmp((p1), (p2), (sz1)))
1.24 kristaps 112: #define EQNSTREQ(x, p, sz) \
113: STRNEQ((x)->name, (x)->sz, (p), (sz))
114:
1.17 kristaps 115: struct eqnpart {
116: struct eqnstr str;
117: int (*fp)(struct eqn_node *);
1.16 kristaps 118: };
119:
1.27 kristaps 120: struct eqnsym {
121: struct eqnstr str;
1.28 kristaps 122: const char *sym;
1.27 kristaps 123: };
124:
1.8 kristaps 125: enum eqnpartt {
126: EQN_DEFINE = 0,
127: EQN_SET,
128: EQN_UNDEF,
1.29 ! kristaps 129: EQN_GSIZE,
1.8 kristaps 130: EQN__MAX
131: };
132:
1.23 kristaps 133: static enum eqn_rest eqn_box(struct eqn_node *, struct eqn_box *);
1.29 ! kristaps 134: static struct eqn_box *eqn_box_alloc(struct eqn_node *,
! 135: struct eqn_box *);
1.13 kristaps 136: static void eqn_box_free(struct eqn_box *);
1.12 kristaps 137: static struct eqn_def *eqn_def_find(struct eqn_node *,
138: const char *, size_t);
1.29 ! kristaps 139: static int eqn_do_gsize(struct eqn_node *);
1.12 kristaps 140: static int eqn_do_define(struct eqn_node *);
1.14 kristaps 141: static int eqn_do_set(struct eqn_node *);
1.12 kristaps 142: static int eqn_do_undef(struct eqn_node *);
1.23 kristaps 143: static enum eqn_rest eqn_eqn(struct eqn_node *, struct eqn_box *);
144: static enum eqn_rest eqn_list(struct eqn_node *, struct eqn_box *);
1.12 kristaps 145: static const char *eqn_nexttok(struct eqn_node *, size_t *);
1.14 kristaps 146: static const char *eqn_nextrawtok(struct eqn_node *, size_t *);
147: static const char *eqn_next(struct eqn_node *,
148: char, size_t *, int);
1.20 kristaps 149: static void eqn_rewind(struct eqn_node *);
1.6 kristaps 150:
1.8 kristaps 151: static const struct eqnpart eqnparts[EQN__MAX] = {
1.17 kristaps 152: { { "define", 6 }, eqn_do_define }, /* EQN_DEFINE */
153: { { "set", 3 }, eqn_do_set }, /* EQN_SET */
154: { { "undef", 5 }, eqn_do_undef }, /* EQN_UNDEF */
1.29 ! kristaps 155: { { "gsize", 5 }, eqn_do_gsize }, /* EQN_UNDEF */
1.8 kristaps 156: };
157:
1.17 kristaps 158: static const struct eqnstr eqnmarks[EQNMARK__MAX] = {
1.16 kristaps 159: { "", 0 }, /* EQNMARK_NONE */
160: { "dot", 3 }, /* EQNMARK_DOT */
161: { "dotdot", 6 }, /* EQNMARK_DOTDOT */
162: { "hat", 3 }, /* EQNMARK_HAT */
163: { "tilde", 5 }, /* EQNMARK_TILDE */
164: { "vec", 3 }, /* EQNMARK_VEC */
165: { "dyad", 4 }, /* EQNMARK_DYAD */
166: { "bar", 3 }, /* EQNMARK_BAR */
167: { "under", 5 }, /* EQNMARK_UNDER */
168: };
169:
1.17 kristaps 170: static const struct eqnstr eqnfonts[EQNFONT__MAX] = {
1.20 kristaps 171: { "", 0 }, /* EQNFONT_NONE */
172: { "roman", 5 }, /* EQNFONT_ROMAN */
173: { "bold", 4 }, /* EQNFONT_BOLD */
174: { "italic", 6 }, /* EQNFONT_ITALIC */
1.17 kristaps 175: };
176:
1.18 kristaps 177: static const struct eqnstr eqnposs[EQNPOS__MAX] = {
1.20 kristaps 178: { "", 0 }, /* EQNPOS_NONE */
179: { "over", 4 }, /* EQNPOS_OVER */
180: { "sup", 3 }, /* EQNPOS_SUP */
181: { "sub", 3 }, /* EQNPOS_SUB */
182: { "to", 2 }, /* EQNPOS_TO */
183: { "from", 4 }, /* EQNPOS_FROM */
184: };
185:
186: static const struct eqnstr eqnpiles[EQNPILE__MAX] = {
187: { "", 0 }, /* EQNPILE_NONE */
188: { "cpile", 5 }, /* EQNPILE_CPILE */
189: { "rpile", 5 }, /* EQNPILE_RPILE */
190: { "lpile", 5 }, /* EQNPILE_LPILE */
1.18 kristaps 191: };
192:
1.27 kristaps 193: static const struct eqnsym eqnsyms[EQNSYM__MAX] = {
1.28 kristaps 194: { { "alpha", 5 }, "*a" }, /* EQNSYM_alpha */
195: { { "beta", 4 }, "*b" }, /* EQNSYM_beta */
196: { { "chi", 3 }, "*x" }, /* EQNSYM_chi */
197: { { "delta", 5 }, "*d" }, /* EQNSYM_delta */
198: { { "epsilon", 7 }, "*e" }, /* EQNSYM_epsilon */
199: { { "eta", 3 }, "*y" }, /* EQNSYM_eta */
200: { { "gamma", 5 }, "*g" }, /* EQNSYM_gamma */
201: { { "iota", 4 }, "*i" }, /* EQNSYM_iota */
202: { { "kappa", 5 }, "*k" }, /* EQNSYM_kappa */
203: { { "lambda", 6 }, "*l" }, /* EQNSYM_lambda */
204: { { "mu", 2 }, "*m" }, /* EQNSYM_mu */
205: { { "nu", 2 }, "*n" }, /* EQNSYM_nu */
206: { { "omega", 5 }, "*w" }, /* EQNSYM_omega */
207: { { "omicron", 7 }, "*o" }, /* EQNSYM_omicron */
208: { { "phi", 3 }, "*f" }, /* EQNSYM_phi */
209: { { "pi", 2 }, "*p" }, /* EQNSYM_pi */
210: { { "psi", 2 }, "*q" }, /* EQNSYM_psi */
211: { { "rho", 3 }, "*r" }, /* EQNSYM_rho */
212: { { "sigma", 5 }, "*s" }, /* EQNSYM_sigma */
213: { { "tau", 3 }, "*t" }, /* EQNSYM_tau */
214: { { "theta", 5 }, "*h" }, /* EQNSYM_theta */
215: { { "upsilon", 7 }, "*u" }, /* EQNSYM_upsilon */
216: { { "xi", 2 }, "*c" }, /* EQNSYM_xi */
217: { { "zeta", 4 }, "*z" }, /* EQNSYM_zeta */
218: { { "DELTA", 5 }, "*D" }, /* EQNSYM_DELTA */
219: { { "GAMMA", 5 }, "*G" }, /* EQNSYM_GAMMA */
220: { { "LAMBDA", 6 }, "*L" }, /* EQNSYM_LAMBDA */
221: { { "OMEGA", 5 }, "*W" }, /* EQNSYM_OMEGA */
222: { { "PHI", 3 }, "*F" }, /* EQNSYM_PHI */
223: { { "PI", 2 }, "*P" }, /* EQNSYM_PI */
224: { { "PSI", 3 }, "*Q" }, /* EQNSYM_PSI */
225: { { "SIGMA", 5 }, "*S" }, /* EQNSYM_SIGMA */
226: { { "THETA", 5 }, "*H" }, /* EQNSYM_THETA */
227: { { "UPSILON", 7 }, "*U" }, /* EQNSYM_UPSILON */
228: { { "XI", 2 }, "*C" }, /* EQNSYM_XI */
229: { { "inter", 5 }, "ca" }, /* EQNSYM_inter */
230: { { "union", 5 }, "cu" }, /* EQNSYM_union */
231: { { "prod", 4 }, "product" }, /* EQNSYM_prod */
232: { { "int", 3 }, "integral" }, /* EQNSYM_int */
233: { { "sum", 3 }, "sum" }, /* EQNSYM_sum */
234: { { "grad", 4 }, "gr" }, /* EQNSYM_grad */
235: { { "del", 3 }, "gr" }, /* EQNSYM_del */
236: { { "times", 5 }, "mu" }, /* EQNSYM_times */
237: { { "cdot", 4 }, "pc" }, /* EQNSYM_cdot */
238: { { "nothing", 7 }, "&" }, /* EQNSYM_nothing */
239: { { "approx", 6 }, "~~" }, /* EQNSYM_approx */
240: { { "prime", 5 }, "aq" }, /* EQNSYM_prime */
241: { { "half", 4 }, "12" }, /* EQNSYM_half */
242: { { "partial", 7 }, "pd" }, /* EQNSYM_partial */
243: { { "inf", 3 }, "if" }, /* EQNSYM_inf */
244: { { ">>", 2 }, ">>" }, /* EQNSYM_muchgreat */
245: { { "<<", 2 }, "<<" }, /* EQNSYM_muchless */
246: { { "<-", 2 }, "<-" }, /* EQNSYM_larrow */
247: { { "->", 2 }, "->" }, /* EQNSYM_rarrow */
248: { { "+-", 2 }, "+-" }, /* EQNSYM_pm */
249: { { "!=", 2 }, "!=" }, /* EQNSYM_nequal */
250: { { "==", 2 }, "==" }, /* EQNSYM_equiv */
251: { { "<=", 2 }, "<=" }, /* EQNSYM_lessequal */
252: { { ">=", 2 }, ">=" }, /* EQNSYM_moreequal */
1.27 kristaps 253: };
254:
1.1 kristaps 255: /* ARGSUSED */
256: enum rofferr
1.6 kristaps 257: eqn_read(struct eqn_node **epp, int ln,
258: const char *p, int pos, int *offs)
1.1 kristaps 259: {
1.8 kristaps 260: size_t sz;
261: struct eqn_node *ep;
1.12 kristaps 262: enum rofferr er;
263:
264: ep = *epp;
265:
266: /*
267: * If we're the terminating mark, unset our equation status and
268: * validate the full equation.
269: */
1.1 kristaps 270:
271: if (0 == strcmp(p, ".EN")) {
1.12 kristaps 272: er = eqn_end(ep);
1.1 kristaps 273: *epp = NULL;
1.12 kristaps 274: return(er);
1.1 kristaps 275: }
276:
1.12 kristaps 277: /*
278: * Build up the full string, replacing all newlines with regular
279: * whitespace.
280: */
1.6 kristaps 281:
1.12 kristaps 282: sz = strlen(p + pos) + 1;
283: ep->data = mandoc_realloc(ep->data, ep->sz + sz + 1);
1.6 kristaps 284:
1.12 kristaps 285: /* First invocation: nil terminate the string. */
1.8 kristaps 286:
1.12 kristaps 287: if (0 == ep->sz)
288: *ep->data = '\0';
1.8 kristaps 289:
1.12 kristaps 290: ep->sz += sz;
291: strlcat(ep->data, p + pos, ep->sz + 1);
292: strlcat(ep->data, " ", ep->sz + 1);
1.11 kristaps 293: return(ROFF_IGN);
294: }
295:
1.1 kristaps 296: struct eqn_node *
1.5 kristaps 297: eqn_alloc(int pos, int line, struct mparse *parse)
1.1 kristaps 298: {
299: struct eqn_node *p;
300:
301: p = mandoc_calloc(1, sizeof(struct eqn_node));
1.5 kristaps 302: p->parse = parse;
1.12 kristaps 303: p->eqn.ln = line;
1.2 kristaps 304: p->eqn.pos = pos;
1.29 ! kristaps 305: p->gsize = EQN_DEFSIZE;
1.1 kristaps 306:
307: return(p);
308: }
309:
1.12 kristaps 310: enum rofferr
311: eqn_end(struct eqn_node *ep)
312: {
1.20 kristaps 313: struct eqn_box *root;
314: enum eqn_rest c;
315:
316: ep->eqn.root = mandoc_calloc(1, sizeof(struct eqn_box));
1.13 kristaps 317:
1.20 kristaps 318: root = ep->eqn.root;
1.13 kristaps 319: root->type = EQN_ROOT;
320:
321: if (0 == ep->sz)
322: return(ROFF_IGN);
1.12 kristaps 323:
1.20 kristaps 324: if (EQN_DESCOPE == (c = eqn_eqn(ep, root))) {
325: EQN_MSG(MANDOCERR_EQNNSCOPE, ep);
326: c = EQN_ERR;
327: }
328:
329: return(EQN_EOF == c ? ROFF_EQN : ROFF_IGN);
330: }
331:
332: static enum eqn_rest
333: eqn_eqn(struct eqn_node *ep, struct eqn_box *last)
334: {
335: struct eqn_box *bp;
336: enum eqn_rest c;
337:
1.29 ! kristaps 338: bp = eqn_box_alloc(ep, last);
1.20 kristaps 339: bp->type = EQN_SUBEXPR;
1.12 kristaps 340:
1.20 kristaps 341: while (EQN_OK == (c = eqn_box(ep, bp)))
342: /* Spin! */ ;
1.15 kristaps 343:
1.20 kristaps 344: return(c);
1.12 kristaps 345: }
346:
1.20 kristaps 347: static enum eqn_rest
1.23 kristaps 348: eqn_list(struct eqn_node *ep, struct eqn_box *last)
349: {
350: struct eqn_box *bp;
351: const char *start;
352: size_t sz;
353: enum eqn_rest c;
354:
1.29 ! kristaps 355: bp = eqn_box_alloc(ep, last);
1.23 kristaps 356: bp->type = EQN_LIST;
357:
358: if (NULL == (start = eqn_nexttok(ep, &sz))) {
359: EQN_MSG(MANDOCERR_EQNEOF, ep);
360: return(EQN_ERR);
361: }
1.24 kristaps 362: if ( ! STRNEQ(start, sz, "{", 1)) {
1.23 kristaps 363: EQN_MSG(MANDOCERR_EQNSYNT, ep);
364: return(EQN_ERR);
365: }
366:
367: while (EQN_DESCOPE == (c = eqn_eqn(ep, bp))) {
368: eqn_rewind(ep);
369: start = eqn_nexttok(ep, &sz);
370: assert(start);
1.24 kristaps 371: if ( ! STRNEQ(start, sz, "above", 5))
1.23 kristaps 372: break;
373: bp->last->above = 1;
374: }
375:
376: if (EQN_DESCOPE != c) {
377: if (EQN_ERR != c)
378: EQN_MSG(MANDOCERR_EQNSCOPE, ep);
379: return(EQN_ERR);
380: }
381:
382: eqn_rewind(ep);
383: start = eqn_nexttok(ep, &sz);
384: assert(start);
1.24 kristaps 385: if (STRNEQ(start, sz, "}", 1))
1.23 kristaps 386: return(EQN_OK);
387:
388: EQN_MSG(MANDOCERR_EQNBADSCOPE, ep);
389: return(EQN_ERR);
390: }
391:
392: static enum eqn_rest
1.20 kristaps 393: eqn_box(struct eqn_node *ep, struct eqn_box *last)
1.1 kristaps 394: {
1.12 kristaps 395: size_t sz;
396: const char *start;
1.20 kristaps 397: char *left;
1.28 kristaps 398: char sym[64];
1.20 kristaps 399: enum eqn_rest c;
400: int i, size;
1.13 kristaps 401: struct eqn_box *bp;
1.12 kristaps 402:
1.20 kristaps 403: if (NULL == (start = eqn_nexttok(ep, &sz)))
404: return(EQN_EOF);
405:
1.24 kristaps 406: if (STRNEQ(start, sz, "}", 1))
1.20 kristaps 407: return(EQN_DESCOPE);
1.24 kristaps 408: else if (STRNEQ(start, sz, "right", 5))
1.20 kristaps 409: return(EQN_DESCOPE);
1.24 kristaps 410: else if (STRNEQ(start, sz, "above", 5))
1.20 kristaps 411: return(EQN_DESCOPE);
412:
413: for (i = 0; i < (int)EQN__MAX; i++) {
1.24 kristaps 414: if ( ! EQNSTREQ(&eqnparts[i].str, start, sz))
1.20 kristaps 415: continue;
416: return((*eqnparts[i].fp)(ep) ? EQN_OK : EQN_ERR);
417: }
1.15 kristaps 418:
1.24 kristaps 419: if (STRNEQ(start, sz, "{", 1)) {
1.20 kristaps 420: if (EQN_DESCOPE != (c = eqn_eqn(ep, last))) {
421: if (EQN_ERR != c)
422: EQN_MSG(MANDOCERR_EQNSCOPE, ep);
423: return(EQN_ERR);
424: }
425: eqn_rewind(ep);
426: start = eqn_nexttok(ep, &sz);
427: assert(start);
1.24 kristaps 428: if (STRNEQ(start, sz, "}", 1))
1.20 kristaps 429: return(EQN_OK);
430: EQN_MSG(MANDOCERR_EQNBADSCOPE, ep);
431: return(EQN_ERR);
432: }
1.12 kristaps 433:
1.20 kristaps 434: for (i = 0; i < (int)EQNPILE__MAX; i++) {
1.24 kristaps 435: if ( ! EQNSTREQ(&eqnpiles[i], start, sz))
1.17 kristaps 436: continue;
1.23 kristaps 437: if (EQN_OK == (c = eqn_list(ep, last)))
1.21 kristaps 438: last->last->pile = (enum eqn_pilet)i;
1.23 kristaps 439: return(c);
1.18 kristaps 440: }
441:
1.24 kristaps 442: if (STRNEQ(start, sz, "left", 4)) {
1.20 kristaps 443: if (NULL == (start = eqn_nexttok(ep, &sz))) {
444: EQN_MSG(MANDOCERR_EQNEOF, ep);
445: return(EQN_ERR);
446: }
447: left = mandoc_strndup(start, sz);
1.26 kristaps 448: c = eqn_eqn(ep, last);
449: if (last->last)
450: last->last->left = left;
451: else
452: free(left);
453: if (EQN_DESCOPE != c)
1.20 kristaps 454: return(c);
455: assert(last->last);
456: eqn_rewind(ep);
457: start = eqn_nexttok(ep, &sz);
458: assert(start);
1.26 kristaps 459: if ( ! STRNEQ(start, sz, "right", 5))
1.20 kristaps 460: return(EQN_DESCOPE);
461: if (NULL == (start = eqn_nexttok(ep, &sz))) {
462: EQN_MSG(MANDOCERR_EQNEOF, ep);
463: return(EQN_ERR);
464: }
465: last->last->right = mandoc_strndup(start, sz);
466: return(EQN_OK);
467: }
468:
469: for (i = 0; i < (int)EQNPOS__MAX; i++) {
1.24 kristaps 470: if ( ! EQNSTREQ(&eqnposs[i], start, sz))
1.18 kristaps 471: continue;
1.20 kristaps 472: if (NULL == last->last) {
473: EQN_MSG(MANDOCERR_EQNSYNT, ep);
474: return(EQN_ERR);
475: }
476: last->last->pos = (enum eqn_post)i;
477: if (EQN_EOF == (c = eqn_box(ep, last))) {
478: EQN_MSG(MANDOCERR_EQNEOF, ep);
479: return(EQN_ERR);
480: }
481: return(c);
1.17 kristaps 482: }
483:
1.16 kristaps 484: for (i = 0; i < (int)EQNMARK__MAX; i++) {
1.24 kristaps 485: if ( ! EQNSTREQ(&eqnmarks[i], start, sz))
1.16 kristaps 486: continue;
1.20 kristaps 487: if (NULL == last->last) {
488: EQN_MSG(MANDOCERR_EQNSYNT, ep);
489: return(EQN_ERR);
490: }
491: last->last->mark = (enum eqn_markt)i;
492: if (EQN_EOF == (c = eqn_box(ep, last))) {
493: EQN_MSG(MANDOCERR_EQNEOF, ep);
494: return(EQN_ERR);
495: }
496: return(c);
1.16 kristaps 497: }
1.12 kristaps 498:
1.20 kristaps 499: for (i = 0; i < (int)EQNFONT__MAX; i++) {
1.24 kristaps 500: if ( ! EQNSTREQ(&eqnfonts[i], start, sz))
1.20 kristaps 501: continue;
502: if (EQN_EOF == (c = eqn_box(ep, last))) {
503: EQN_MSG(MANDOCERR_EQNEOF, ep);
504: return(EQN_ERR);
505: } else if (EQN_OK == c)
506: last->last->font = (enum eqn_fontt)i;
507: return(c);
1.19 kristaps 508: }
1.15 kristaps 509:
1.24 kristaps 510: if (STRNEQ(start, sz, "size", 4)) {
1.20 kristaps 511: if (NULL == (start = eqn_nexttok(ep, &sz))) {
512: EQN_MSG(MANDOCERR_EQNEOF, ep);
513: return(EQN_ERR);
514: }
515: size = mandoc_strntoi(start, sz, 10);
516: if (EQN_EOF == (c = eqn_box(ep, last))) {
517: EQN_MSG(MANDOCERR_EQNEOF, ep);
518: return(EQN_ERR);
519: } else if (EQN_OK != c)
520: return(c);
521: last->last->size = size;
1.15 kristaps 522: }
523:
1.29 ! kristaps 524: bp = eqn_box_alloc(ep, last);
1.15 kristaps 525: bp->type = EQN_TEXT;
1.27 kristaps 526: for (i = 0; i < (int)EQNSYM__MAX; i++)
527: if (EQNSTREQ(&eqnsyms[i].str, start, sz)) {
1.28 kristaps 528: sym[63] = '\0';
529: snprintf(sym, 62, "\\[%s]", eqnsyms[i].sym);
1.27 kristaps 530: bp->text = mandoc_strdup(sym);
531: return(EQN_OK);
532: }
533:
1.20 kristaps 534: bp->text = mandoc_strndup(start, sz);
535: return(EQN_OK);
1.1 kristaps 536: }
537:
538: void
539: eqn_free(struct eqn_node *p)
540: {
1.6 kristaps 541: int i;
1.1 kristaps 542:
1.13 kristaps 543: eqn_box_free(p->eqn.root);
1.6 kristaps 544:
545: for (i = 0; i < (int)p->defsz; i++) {
546: free(p->defs[i].key);
547: free(p->defs[i].val);
548: }
549:
1.12 kristaps 550: free(p->data);
1.6 kristaps 551: free(p->defs);
1.1 kristaps 552: free(p);
1.6 kristaps 553: }
554:
1.20 kristaps 555: static struct eqn_box *
1.29 ! kristaps 556: eqn_box_alloc(struct eqn_node *ep, struct eqn_box *parent)
1.20 kristaps 557: {
558: struct eqn_box *bp;
559:
560: bp = mandoc_calloc(1, sizeof(struct eqn_box));
561: bp->parent = parent;
1.29 ! kristaps 562: bp->size = ep->gsize;
1.20 kristaps 563:
564: if (NULL == parent->first)
565: parent->first = bp;
566: else
567: parent->last->next = bp;
568:
569: parent->last = bp;
570: return(bp);
571: }
572:
1.13 kristaps 573: static void
574: eqn_box_free(struct eqn_box *bp)
575: {
576:
1.20 kristaps 577: if (bp->first)
578: eqn_box_free(bp->first);
1.13 kristaps 579: if (bp->next)
580: eqn_box_free(bp->next);
581:
582: free(bp->text);
1.20 kristaps 583: free(bp->left);
584: free(bp->right);
1.13 kristaps 585: free(bp);
586: }
587:
1.6 kristaps 588: static const char *
1.14 kristaps 589: eqn_nextrawtok(struct eqn_node *ep, size_t *sz)
590: {
591:
592: return(eqn_next(ep, '"', sz, 0));
593: }
594:
595: static const char *
1.12 kristaps 596: eqn_nexttok(struct eqn_node *ep, size_t *sz)
597: {
598:
1.14 kristaps 599: return(eqn_next(ep, '"', sz, 1));
1.12 kristaps 600: }
601:
1.20 kristaps 602: static void
603: eqn_rewind(struct eqn_node *ep)
604: {
605:
606: ep->cur = ep->rew;
607: }
608:
1.12 kristaps 609: static const char *
1.14 kristaps 610: eqn_next(struct eqn_node *ep, char quote, size_t *sz, int repl)
1.6 kristaps 611: {
1.12 kristaps 612: char *start, *next;
613: int q, diff, lim;
1.22 kristaps 614: size_t ssz, dummy;
1.12 kristaps 615: struct eqn_def *def;
616:
617: if (NULL == sz)
1.22 kristaps 618: sz = &dummy;
1.6 kristaps 619:
1.13 kristaps 620: lim = 0;
1.20 kristaps 621: ep->rew = ep->cur;
1.13 kristaps 622: again:
623: /* Prevent self-definitions. */
624:
625: if (lim >= EQN_NEST_MAX) {
626: EQN_MSG(MANDOCERR_EQNNEST, ep);
627: return(NULL);
628: }
629:
1.20 kristaps 630: ep->cur = ep->rew;
1.12 kristaps 631: start = &ep->data[(int)ep->cur];
1.6 kristaps 632: q = 0;
633:
634: if ('\0' == *start)
635: return(NULL);
636:
1.12 kristaps 637: if (quote == *start) {
638: ep->cur++;
1.6 kristaps 639: q = 1;
640: }
641:
1.12 kristaps 642: start = &ep->data[(int)ep->cur];
1.22 kristaps 643:
644: if ( ! q) {
645: if ('{' == *start || '}' == *start)
646: ssz = 1;
647: else
648: ssz = strcspn(start + 1, " ~\"{}\t") + 1;
649: next = start + (int)ssz;
650: if ('\0' == *next)
651: next = NULL;
652: } else
653: next = strchr(start, quote);
1.12 kristaps 654:
655: if (NULL != next) {
656: *sz = (size_t)(next - start);
657: ep->cur += *sz;
1.6 kristaps 658: if (q)
1.12 kristaps 659: ep->cur++;
1.22 kristaps 660: while (' ' == ep->data[(int)ep->cur] ||
661: '\t' == ep->data[(int)ep->cur] ||
662: '~' == ep->data[(int)ep->cur])
1.12 kristaps 663: ep->cur++;
1.6 kristaps 664: } else {
665: if (q)
1.12 kristaps 666: EQN_MSG(MANDOCERR_BADQUOTE, ep);
667: next = strchr(start, '\0');
668: *sz = (size_t)(next - start);
669: ep->cur += *sz;
670: }
671:
1.13 kristaps 672: /* Quotes aren't expanded for values. */
673:
1.14 kristaps 674: if (q || ! repl)
1.13 kristaps 675: return(start);
676:
1.12 kristaps 677: if (NULL != (def = eqn_def_find(ep, start, *sz))) {
678: diff = def->valsz - *sz;
679:
680: if (def->valsz > *sz) {
681: ep->sz += diff;
682: ep->data = mandoc_realloc(ep->data, ep->sz + 1);
683: ep->data[ep->sz] = '\0';
1.20 kristaps 684: start = &ep->data[(int)ep->rew];
1.12 kristaps 685: }
686:
687: diff = def->valsz - *sz;
688: memmove(start + *sz + diff, start + *sz,
689: (strlen(start) - *sz) + 1);
690: memcpy(start, def->val, def->valsz);
691: goto again;
1.6 kristaps 692: }
693:
694: return(start);
1.8 kristaps 695: }
696:
697: static int
1.14 kristaps 698: eqn_do_set(struct eqn_node *ep)
1.8 kristaps 699: {
700: const char *start;
701:
1.14 kristaps 702: if (NULL == (start = eqn_nextrawtok(ep, NULL)))
1.29 ! kristaps 703: EQN_MSG(MANDOCERR_EQNEOF, ep);
1.14 kristaps 704: else if (NULL == (start = eqn_nextrawtok(ep, NULL)))
1.29 ! kristaps 705: EQN_MSG(MANDOCERR_EQNEOF, ep);
1.12 kristaps 706: else
707: return(1);
1.8 kristaps 708:
1.12 kristaps 709: return(0);
1.8 kristaps 710: }
711:
712: static int
1.12 kristaps 713: eqn_do_define(struct eqn_node *ep)
1.8 kristaps 714: {
715: const char *start;
716: size_t sz;
1.12 kristaps 717: struct eqn_def *def;
1.8 kristaps 718: int i;
719:
1.14 kristaps 720: if (NULL == (start = eqn_nextrawtok(ep, &sz))) {
1.29 ! kristaps 721: EQN_MSG(MANDOCERR_EQNEOF, ep);
1.8 kristaps 722: return(0);
723: }
724:
725: /*
726: * Search for a key that already exists.
1.12 kristaps 727: * Create a new key if none is found.
1.8 kristaps 728: */
729:
1.12 kristaps 730: if (NULL == (def = eqn_def_find(ep, start, sz))) {
1.8 kristaps 731: /* Find holes in string array. */
732: for (i = 0; i < (int)ep->defsz; i++)
733: if (0 == ep->defs[i].keysz)
734: break;
735:
736: if (i == (int)ep->defsz) {
737: ep->defsz++;
738: ep->defs = mandoc_realloc
739: (ep->defs, ep->defsz *
740: sizeof(struct eqn_def));
1.9 kristaps 741: ep->defs[i].key = ep->defs[i].val = NULL;
1.8 kristaps 742: }
743:
744: ep->defs[i].keysz = sz;
745: ep->defs[i].key = mandoc_realloc
746: (ep->defs[i].key, sz + 1);
747:
748: memcpy(ep->defs[i].key, start, sz);
749: ep->defs[i].key[(int)sz] = '\0';
1.12 kristaps 750: def = &ep->defs[i];
1.8 kristaps 751: }
752:
1.14 kristaps 753: start = eqn_next(ep, ep->data[(int)ep->cur], &sz, 0);
1.8 kristaps 754:
1.12 kristaps 755: if (NULL == start) {
1.29 ! kristaps 756: EQN_MSG(MANDOCERR_EQNEOF, ep);
1.8 kristaps 757: return(0);
758: }
759:
1.12 kristaps 760: def->valsz = sz;
1.13 kristaps 761: def->val = mandoc_realloc(def->val, sz + 1);
1.12 kristaps 762: memcpy(def->val, start, sz);
763: def->val[(int)sz] = '\0';
764: return(1);
1.8 kristaps 765: }
766:
767: static int
1.29 ! kristaps 768: eqn_do_gsize(struct eqn_node *ep)
! 769: {
! 770: const char *start;
! 771: size_t sz;
! 772:
! 773: if (NULL == (start = eqn_nextrawtok(ep, &sz))) {
! 774: EQN_MSG(MANDOCERR_EQNEOF, ep);
! 775: return(0);
! 776: }
! 777:
! 778: ep->gsize = mandoc_strntoi(start, sz, 10);
! 779: return(1);
! 780: }
! 781:
! 782: static int
1.12 kristaps 783: eqn_do_undef(struct eqn_node *ep)
1.8 kristaps 784: {
785: const char *start;
1.12 kristaps 786: struct eqn_def *def;
1.8 kristaps 787: size_t sz;
788:
1.14 kristaps 789: if (NULL == (start = eqn_nextrawtok(ep, &sz))) {
1.29 ! kristaps 790: EQN_MSG(MANDOCERR_EQNEOF, ep);
1.12 kristaps 791: return(0);
792: } else if (NULL != (def = eqn_def_find(ep, start, sz)))
793: def->keysz = 0;
1.8 kristaps 794:
1.12 kristaps 795: return(1);
796: }
797:
798: static struct eqn_def *
799: eqn_def_find(struct eqn_node *ep, const char *key, size_t sz)
800: {
801: int i;
1.8 kristaps 802:
1.12 kristaps 803: for (i = 0; i < (int)ep->defsz; i++)
1.24 kristaps 804: if (ep->defs[i].keysz && STRNEQ(ep->defs[i].key,
805: ep->defs[i].keysz, key, sz))
1.12 kristaps 806: return(&ep->defs[i]);
1.8 kristaps 807:
1.12 kristaps 808: return(NULL);
1.1 kristaps 809: }
CVSweb