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