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