LCOV - code coverage report
Current view: top level - libreoffice/hwpfilter/source - hwpeq.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 220 0.0 %
Date: 2012-12-27 Functions: 0 12 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <assert.h>
      21             : #include <stdio.h>
      22             : #include <string.h>
      23             : #include <ctype.h>
      24             : 
      25             : // DVO: always use standard headers:
      26             : #include <istream>
      27             : #include <sstream>
      28             : using namespace std;
      29             : 
      30             : #include "mzstring.h"
      31             : #include "hwpeq.h"
      32             : #include <sal/types.h>
      33             : #include <sal/macros.h>
      34             : 
      35             : /* @Man: hwp¼ö½ÄÀ» LaTeXÀ¸·Î ¹Ù²Ù±â */
      36             : #ifdef WIN32
      37             : # define ENDL  "\r\n"
      38             : #else /* !WIN32 */
      39             : # define ENDL  "\n"
      40             : #endif
      41             : 
      42             : #define WS  " \t\r\n\v\f"
      43             : 
      44             : #define EQ_CASE 0x01    // case sensitive cmd
      45             : #define EQ_ENV  0x02    // equiv to latex environment
      46             : #define EQ_ATOP 0x04    // must revert order
      47             : 
      48             : #define IS_WS(ch)   (strchr(WS, ch))
      49             : #define IS_BINARY(ch)   (strchr("+-<=>", ch))
      50             : 
      51             : #ifdef WIN32
      52             : #define STRICMP stricmp
      53             : #else
      54             : #define STRICMP strcasecmp
      55             : #endif
      56             : 
      57             : // sub and sup scipt script status
      58             : enum { SCRIPT_NONE, SCRIPT_SUB, SCRIPT_SUP, SCRIPT_ALL};
      59             : 
      60             : static int  eq_word(MzString& outs, istream *strm, int script = SCRIPT_NONE);
      61             : static bool eq_sentence(MzString& outs, istream *strm, const char *end = 0);
      62             : 
      63             : struct hwpeq {
      64             :   const char    *key;       // hwp math keyword
      65             :   const char    *latex;     // corresponding latex keywork
      66             :   int       nargs;      // # of argument
      67             :   unsigned char flag;       // case sensitive?
      68             : };
      69             : 
      70             : static hwpeq eq_tbl[] = {
      71             :   { "!=",       "\\equiv ", 0,  0   },
      72             :   { "#",        "\\\\",     0,  0   },
      73             :   { "+-",       "\\pm ",    0,  0   },
      74             :   { "-+",       "\\mp ",    0,  0   },
      75             :   { "<=",       "\\leq ",   0,  0   },
      76             :   { "==",       "\\equiv ", 0,  0   },
      77             :   { ">=",       "\\geq ",   0,  0   },
      78             :   { "Pr",       NULL,       0,  0   },
      79             :   { "^",        "^",        1,  0   },
      80             :   { "_",        "_",        1,  0   },
      81             :   { "`",        "\\;",      0,  0   },
      82             :   { "acute",        NULL,       1,  0   },
      83             :   { "aleph",        NULL,       0,  0   },
      84             :   { "alpha",        NULL,       0,  EQ_CASE },
      85             :   { "amalg",        NULL,       0,  0   },
      86             :   { "and",      NULL,       0,  0   },
      87             :   { "angle",        NULL,       0,  0   },
      88             :   { "angstrom",     NULL,       0,  0   },
      89             :   { "approx",       NULL,       0,  0   },
      90             :   { "arc",      NULL,       0,  0   },
      91             :   { "arccos",       NULL,       0,  0   },
      92             :   { "arch",     NULL,       0,  0   },
      93             :   { "arcsin",       NULL,       0,  0   },
      94             :   { "arctan",       NULL,       0,  0   },
      95             :   { "arg",      NULL,       0,  0   },
      96             :   { "assert",       "\\vdash",  0,  0   },
      97             :   { "ast",      NULL,       0,  0   },
      98             :   { "asymp",        NULL,       0,  0   },
      99             :   { "atop",     NULL,       1,  EQ_ATOP },
     100             :   { "backslash",    NULL,       0,  0   },
     101             :   { "bar",      NULL,       1,  0   },
     102             :   { "because",      NULL,       0,  0   },
     103             :   { "beta",     NULL,       0,  EQ_CASE },
     104             :   { "big",      NULL,       0,  EQ_CASE },
     105             :   { "bigcap",       NULL,       0,  0   },
     106             :   { "bigcirc",      NULL,       0,  0   },
     107             :   { "bigcup",       NULL,       0,  0   },
     108             :   { "bigg",     NULL,       0,  EQ_CASE },
     109             :   { "bigodiv",      NULL,       0,  0   },
     110             :   { "bigodot",      NULL,       0,  0   },
     111             :   { "bigominus",    NULL,       0,  0   },
     112             :   { "bigoplus",     NULL,       0,  0   },
     113             :   { "bigotimes",    NULL,       0,  0   },
     114             :   { "bigsqcap",     NULL,       0,  0   },
     115             :   { "bigsqcup",     NULL,       0,  0   },
     116             :   { "biguplus",     NULL,       0,  0   },
     117             :   { "bigvee",       NULL,       0,  0   },
     118             :   { "bigwedge",     NULL,       0,  0   },
     119             :   { "binom",        NULL,       2,  0   },
     120             :   { "bmatrix",      NULL,       0,  EQ_ENV  },
     121             :   { "bold",     NULL,       0,  0   },
     122             :   { "bot",      NULL,       0,  0   },
     123             :   { "breve",        NULL,       1,  0   },
     124             :   { "buildrel",     NULL,       0,  0   }, // LATER
     125             :   { "bullet",       NULL,       0,  0   },
     126             :   { "cap",      NULL,       0,  0   },
     127             :   { "cases",        NULL,       0,  EQ_ENV  },
     128             :   { "ccol",     NULL,       0,  0   }, /* ¼¼·Î·Î °¡¿îµ¥ */
     129             :   { "cdot",     NULL,       0,  0   },
     130             :   { "cdots",        NULL,       0,  0   },
     131             :   { "check",        NULL,       1,  0   },
     132             :   { "chi",      NULL,       0,  EQ_CASE },
     133             :   { "choose",       NULL,       0,  EQ_ATOP },
     134             :   { "circ",     NULL,       0,  0   },
     135             :   { "col",      NULL,       0,  0   }, // LATER
     136             :   { "cong",     NULL,       0,  0   },
     137             :   { "coprod",       NULL,       0,  0   },
     138             :   { "cos",      NULL,       0,  0   },
     139             :   { "cosec",        NULL,       0,  0   },
     140             :   { "cosh",     NULL,       0,  0   },
     141             :   { "cot",      NULL,       0,  0   },
     142             :   { "coth",     NULL,       0,  0   },
     143             :   { "cpile",        NULL,       0,  0   }, // LATER
     144             :   { "csc",      NULL,       0,  0   },
     145             :   { "cup",      NULL,       0,  0   },
     146             :   { "dagger",       NULL,       0,  0   },
     147             :   { "dashv",        NULL,       0,  0   },
     148             :   { "ddagger",      NULL,       0,  0   },
     149             :   { "ddot",     NULL,       1,  0   },
     150             :   { "ddots",        NULL,       0,  0   },
     151             :   { "def",      NULL,       0,  0   },
     152             :   { "deg",      NULL,       0,  0   },
     153             :   { "del",      NULL,       0,  0   },
     154             :   { "delta",        NULL,       0,  EQ_CASE },
     155             :   { "diamond",      NULL,       0,  0   },
     156             :   { "dim",      NULL,       0,  0   },
     157             :   { "div",      NULL,       0,  0   },
     158             :   { "divide",       NULL,       0,  0   },
     159             :   { "dline",        NULL,       0,  0   },
     160             :   { "dmatrix",      NULL,       0,  EQ_ENV  },
     161             :   { "dot",      NULL,       1,  0   },
     162             :   { "doteq",        NULL,       0,  0   },
     163             :   { "dotsaxis",     NULL,       0,  0   },
     164             :   { "dotsdiag",     NULL,       0,  0   },
     165             :   { "dotslow",      "\\ldots",  0,  0   },
     166             :   { "dotsvert",     "\\vdots",  0,  0   },
     167             :   { "downarrow",    NULL,       0,  EQ_CASE },
     168             :   { "dsum",     "+",        0,  0   },
     169             :   { "dyad",     NULL,       0,  0   }, // LATER
     170             :   { "ell",      NULL,       0,  0   },
     171             :   { "emptyset",     NULL,       0,  0   },
     172             :   { "epsilon",      NULL,       0,  EQ_CASE },
     173             :   { "eqalign",      NULL,       0,  EQ_ENV  },
     174             :   { "equiv",        NULL,       0,  0   },
     175             :   { "eta",      NULL,       0,  EQ_CASE },
     176             :   { "exarrow",      NULL,       0,  0   },
     177             :   { "exist",        "\\exists", 0,  0   },
     178             :   { "exists",       NULL,       0,  0   },
     179             :   { "exp",      NULL,       0,  EQ_CASE },
     180             :   { "for",      NULL,       0,  0   },
     181             :   { "forall",       NULL,       0,  0   },
     182             :   { "from",     "_",        1,  0   },
     183             :   { "gamma",        NULL,       0,  EQ_CASE },
     184             :   { "gcd",      NULL,       0,  0   },
     185             :   { "ge",       "\\geq",    0,  0   },
     186             :   { "geq",      NULL,       0,  0   },
     187             :   { "ggg",      NULL,       0,  0   },
     188             :   { "grad",     NULL,       0,  0   },
     189             :   { "grave",        NULL,       1,  0   },
     190             :   { "hat",      "\\widehat",    1,  0   },
     191             :   { "hbar",     NULL,       0,  0   },
     192             :   { "hom",      NULL,       0,  0   },
     193             :   { "hookleft",     NULL,       0,  0   },
     194             :   { "hookright",    NULL,       0,  0   },
     195             :   { "identical",    NULL,       0,  0   }, // LATER
     196             :   { "if",       NULL,       0,  0   },
     197             :   { "imag",     NULL,       0,  0   },
     198             :   { "image",        NULL,       0,  0   },
     199             :   { "imath",        NULL,       0,  0   },
     200             :   { "in",       NULL,       0,  0   },
     201             :   { "inf",      "\\infty",  0,  0   },
     202             :   { "infinity",     "\\infty",  0,  0   },
     203             :   { "infty",        NULL,       0,  0   },
     204             :   { "int",      NULL,       0,  0   },
     205             :   { "integral",     "\\int",    0,  0   },
     206             :   { "inter",        "\\bigcap", 0,  0   },
     207             :   { "iota",     NULL,       0,  EQ_CASE },
     208             :   { "iso",      NULL,       0,  0   }, // ams
     209             :   { "it",       NULL,       0,  0   },
     210             :   { "jmath",        NULL,       0,  0   },
     211             :   { "kappa",        NULL,       0,  EQ_CASE },
     212             :   { "ker",      NULL,       0,  0   },
     213             :   { "lambda",       NULL,       0,  EQ_CASE },
     214             :   { "land",     NULL,       0,  0   }, // LATER
     215             :   { "langle",       NULL,       0,  0   },
     216             :   { "larrow",       "\\leftarrow",  0,  EQ_CASE },
     217             :   { "lbrace",       NULL,       0,  0   },
     218             :   { "lbrack",       "[",        0,  0   },
     219             :   { "lceil",        NULL,       0,  0   },
     220             :   { "lcol",     NULL,       0,  0   }, // LATER
     221             :   { "ldots",        NULL,       0,  0   },
     222             :   { "le",       NULL,       0,  0   },
     223             :   { "left",     NULL,       0,  0   },
     224             :   { "leftarrow",    NULL,       0,  EQ_CASE },
     225             :   { "leq",      NULL,       0,  0   },
     226             :   { "lfloor",       NULL,       0,  0   },
     227             :   { "lg",       NULL,       0,  0   },
     228             :   { "lim",      NULL,       0,  EQ_CASE },
     229             :   { "line",     "\\vert",   0,  0   },
     230             :   { "liter",        "\\ell",    0,  0   },
     231             :   { "lll",      NULL,       0,  0   }, // ams
     232             :   { "ln",       NULL,       0,  0   },
     233             :   { "log",      NULL,       0,  0   },
     234             :   { "lor",      "\\vee",    0,  0   },
     235             :   { "lparen",       "(",        0,  0   },
     236             :   { "lpile",        NULL,       0,  0   }, // LATER
     237             :   { "lrarrow",    "\\leftrightarrow",   0,  EQ_CASE },
     238             :   { "lrharpoons", "\\leftrightharpoons",0,  0   },
     239             :   { "mapsto",       NULL,       0,  0   },
     240             :   { "massert",      "\\dashv",  0,  0   },
     241             :   { "matrix",       NULL,       0,  EQ_ENV  },
     242             :   { "max",      NULL,       0,  0   },
     243             :   { "mho",      NULL,       0,  0   }, // ams
     244             :   { "min",      NULL,       0,  0   },
     245             :   { "minusplus",    NULL,       0,  0   },
     246             :   { "mit",      "",     0,  0   }, // font
     247             :   { "mod",      "\\bmod",   0,  0   },
     248             :   { "models",       NULL,       0,  0   },
     249             :   { "msangle",      NULL,       0,  0   }, // LATER
     250             :   { "mu",       NULL,       0,  EQ_CASE },
     251             :   { "nabla",        NULL,       0,  0   },
     252             :   { "ne",       NULL,       0,  0   },
     253             :   { "nearrow",      NULL,       0,  0   },
     254             :   { "neg",      NULL,       0,  0   },
     255             :   { "neq",      NULL,       0,  0   },
     256             :   { "nequiv",       NULL,       0,  0   },
     257             :   { "ni",       NULL,       0,  0   },
     258             :   { "not",      NULL,       0,  0   },
     259             :   { "notin",        NULL,       0,  0   },
     260             :   { "nu",       NULL,       0,  EQ_CASE },
     261             :   { "nwarrow",      NULL,       0,  0   },
     262             :   { "odiv",     NULL,       0,  0   },
     263             :   { "odot",     NULL,       0,  0   },
     264             :   { "oint",     NULL,       0,  0   },
     265             :   { "omega",        NULL,       0,  EQ_CASE },
     266             :   { "omicron",      NULL,       0,  EQ_CASE },
     267             :   { "ominus",       NULL,       0,  0   },
     268             :   { "oplus",        NULL,       0,  0   },
     269             :   { "or ",      NULL,       0,  0   },
     270             :   { "oslash",       NULL,       0,  0   },
     271             :   { "otimes",       NULL,       0,  0   },
     272             :   { "over",     NULL,       1,  EQ_ATOP },
     273             :   { "overline",     NULL,       1,  0   },
     274             :   { "owns",     "\\ni",     0,  0   },
     275             :   { "parallel",     NULL,       0,  0   },
     276             :   { "partial",      NULL,       0,  0   },
     277             :   { "phantom",      NULL,       0,  0   },
     278             :   { "phi",      NULL,       0,  EQ_CASE },
     279             :   { "pi",       NULL,       0,  EQ_CASE },
     280             :   { "pile",     NULL,       0,  0   }, // LATER
     281             :   { "plusminus",    "\\pm",     0,  0   },
     282             :   { "pmatrix",      NULL,       0,  EQ_ENV  },
     283             :   { "prec",     NULL,       0,  0   },
     284             :   { "prep",     NULL,       0,  0   },
     285             :   { "prime",        NULL,       0,  0   },
     286             :   { "prod",     NULL,       0,  0   },
     287             :   { "propto",       NULL,       0,  0   },
     288             :   { "psi",      NULL,       0,  EQ_CASE },
     289             :   { "rangle",       NULL,       0,  0   },
     290             :   { "rarrow",       "\\rightarrow", 0,  EQ_CASE },
     291             :   { "rbrace",       "]",        0,  0   },
     292             :   { "rbrace",       NULL,       0,  0   },
     293             :   { "rceil",        NULL,       0,  0   },
     294             :   { "rcol",     NULL,       0,  0   }, // LATER
     295             :   { "real",     "\\Re",     0,  0   },
     296             :   { "reimage",      NULL,       0,  0   },
     297             :   { "rel",      NULL,       0,  0   },
     298             :   { "rfloor",       NULL,       0,  0   },
     299             :   { "rho",      NULL,       0,  EQ_CASE },
     300             :   { "right",        NULL,       0,  0   },
     301             :   { "rightarrow",   NULL,       0,  EQ_CASE },
     302             :   { "rlharpoons",   NULL,       0,  0   },
     303             :   { "rm",       NULL,       0,  0   },
     304             :   { "root",     "\\sqrt",   1,  0   },
     305             :   { "rparen",       ")",        0,  0   },
     306             :   { "rpile",        NULL,       0,  0   }, // LATER
     307             :   { "rtangle",      NULL,       0,  0   },
     308             :   { "sangle",       NULL,       0,  0   },
     309             :   { "scale",        NULL,       0,  0   },
     310             :   { "searrow",      NULL,       0,  0   },
     311             :   { "sec",      NULL,       0,  0   },
     312             :   { "sigma",        NULL,       0,  EQ_CASE },
     313             :   { "sim",      NULL,       0,  0   },
     314             :   { "simeq",        NULL,       0,  0   },
     315             :   { "sin",      NULL,       0,  0   },
     316             :   { "sinh",     NULL,       0,  0   },
     317             :   { "slash",        NULL,       0,  0   },
     318             :   { "smallint",     NULL,       0,  0   },
     319             :   { "smallinter",   NULL,       0,  0   },
     320             :   { "smalloint",    NULL,       0,  0   },
     321             :   { "smallprod",    NULL,       0,  0   },
     322             :   { "smallsum",     NULL,       0,  0   },
     323             :   { "smallunion",   NULL,       0,  0   },
     324             :   { "smcoprod",     NULL,       0,  0   },
     325             :   { "sqcap",        NULL,       0,  0   },
     326             :   { "sqcup",        NULL,       0,  0   },
     327             :   { "sqrt",     NULL,       1,  0   },
     328             :   { "sqsubset",     NULL,       0,  0   },
     329             :   { "sqsubseteq",   NULL,       0,  0   },
     330             :   { "sqsupset",     NULL,       0,  0   },
     331             :   { "sqsupseteq",   NULL,       0,  0   },
     332             :   { "star",     NULL,       0,  0   },
     333             :   { "sub",      "_",        0,  0   },
     334             :   { "subset",       NULL,       0,  0   },
     335             :   { "subseteq",     NULL,       0,  0   },
     336             :   { "succ",     NULL,       0,  0   },
     337             :   { "sum",      NULL,       0,  0   },
     338             :   { "sup",      "^",        0,  0   },
     339             :   { "superset",     NULL,       0,  0   },
     340             :   { "supset",       NULL,       0,  0   },
     341             :   { "supseteq",     NULL,       0,  0   },
     342             :   { "swarrow",      NULL,       0,  0   },
     343             :   { "tan",      NULL,       0,  0   },
     344             :   { "tanh",     NULL,       0,  0   },
     345             :   { "tau",      NULL,       0,  EQ_CASE },
     346             :   { "therefore",    NULL,       0,  0   },
     347             :   { "theta",        NULL,       0,  EQ_CASE },
     348             :   { "tilde",        "\\widetilde",  1,  0   },
     349             :   { "times",        NULL,       0,  0   },
     350             :   { "to",       "^",        1,  0   },
     351             :   { "top",      NULL,       0,  0   },
     352             :   { "triangle",     NULL,       0,  0   },
     353             :   { "triangled",    NULL,       0,  0   },
     354             :   { "trianglel",    NULL,       0,  0   },
     355             :   { "triangler",    NULL,       0,  0   },
     356             :   { "triangleu",    NULL,       0,  0   },
     357             :   { "udarrow",      "\\updownarrow",0,  EQ_CASE },
     358             :   { "under",        "\\underline",  1,  0   },
     359             :   { "underline",    "\\underline",  1,  0   },
     360             :   { "union",        "\\bigcup", 0,  0   },
     361             :   { "uparrow",      NULL,       0,  EQ_CASE },
     362             :   { "uplus",        NULL,       0,  0   },
     363             :   { "upsilon",      NULL,       0,  EQ_CASE },
     364             :   { "varepsilon",   NULL,       0,  0   },
     365             :   { "varphi",       NULL,       0,  0   },
     366             :   { "varpi",        NULL,       0,  0   },
     367             :   { "varrho",       NULL,       0,  0   },
     368             :   { "varsigma",     NULL,       0,  0   },
     369             :   { "vartheta",     NULL,       0,  0   },
     370             :   { "varupsilon",   NULL,       0,  0   },
     371             :   { "vdash",        NULL,       0,  0   },
     372             :   { "vdots",        NULL,       0,  0   },
     373             :   { "vec",      NULL,       1,  0   },
     374             :   { "vee",      NULL,       0,  0   },
     375             :   { "vert",     NULL,       0,  0   },
     376             :   { "wedge",        NULL,       0,  0   },
     377             :   { "wp",       NULL,       0,  0   },
     378             :   { "xi",       NULL,       0,  EQ_CASE },
     379             :   { "xor",      NULL,       0,  0   },
     380             :   { "zeta",     NULL,       0,  EQ_CASE }
     381             : };
     382             : 
     383           0 : static hwpeq *lookup_eqn(char *str)
     384             : {
     385             :   static int    eqCount = SAL_N_ELEMENTS(eq_tbl);
     386           0 :   int       m, k, l = 0, r = eqCount;
     387           0 :   hwpeq     *result = 0;
     388             : 
     389           0 :   while( l < r ) {
     390           0 :     m = (l + r) / 2;
     391           0 :     k = strcmp(eq_tbl[m].key, str);
     392           0 :     if( k == 0 ) {
     393           0 :       result = eq_tbl + m;;
     394           0 :       break;
     395             :     }
     396           0 :     else if( k < 0 )
     397           0 :       l = m + 1;
     398             :     else
     399           0 :       r = m;
     400             :   }
     401           0 :   return result;
     402             : }
     403             : 
     404             : /* ùÀÚ¸¸ ´ë¹®ÀÚÀ̰ųª ÀüºÎ ´ë¹®ÀÚ¸é ¼Ò¹®ÀÚ·Î ¹Ù²Û´Ù. */
     405             : 
     406           0 : static char *make_keyword( char *keyword, const char *token)
     407             : {
     408             :   assert(keyword);
     409             :   char  *ptr;
     410           0 :   int   result = true, len = strlen(token);
     411             : 
     412           0 :   if( 255 < len )
     413           0 :     strncpy(keyword, token, 255);
     414             :   else
     415           0 :     strcpy(keyword, token);
     416             : 
     417           0 :   if( (token[0] & 0x80) || islower(token[0]) ||
     418           0 :       strlen(token) < 2 )
     419           0 :     return keyword;
     420             : 
     421           0 :   int capital = isupper(keyword[1]);
     422           0 :   for( ptr = keyword + 2; *ptr && result; ptr++ )
     423           0 :     if( (*ptr & 0x80) ||
     424           0 :     (!capital && isupper(*ptr)) ||
     425           0 :     (capital && islower(*ptr)) )
     426           0 :       result = false;
     427             : 
     428           0 :   if( result ) {
     429           0 :     ptr = keyword;
     430           0 :     while( *ptr ) {
     431           0 :       if( isupper(*ptr) )
     432           0 :     *ptr = sal::static_int_cast<char>(tolower(*ptr));
     433           0 :       ptr++;
     434             :     }
     435             :   }
     436           0 :   return keyword;
     437             : }
     438             : 
     439             : // token reading funtion
     440           0 : struct eq_stack {
     441             :   MzString  white;
     442             :   MzString  token;
     443             :   istream   *strm;
     444             : 
     445           0 :   eq_stack() { strm = 0; };
     446           0 :   bool state(istream *s) {
     447           0 :     if( strm != s) { white = 0; token = 0; }
     448           0 :     return token.length() != 0;
     449             :   }
     450             : };
     451             : 
     452             : static eq_stack *stk = 0;
     453             : 
     454           0 : void push_token(MzString &white, MzString &token, istream *strm)
     455             : {
     456             :   // one time stack
     457             :   assert(stk->state(strm) == false);
     458             : 
     459           0 :   stk->white = white;
     460           0 :   stk->token = token;
     461           0 :   stk->strm = strm;
     462           0 : }
     463             : 
     464             : /*
 ÀÐÀº ÅäÅ«ÀÇ ±æÀ̸¦ ¹ÝȯÇÑ´Ù. */
     465             : /* control char, control sequence, binary sequence,
     466             :    alphabet string, sigle character */
     467             : static int next_token(MzString &white, MzString &token, istream *strm)
     468           0 : {
     469             :   register int  ch = 0;
     470           0 : 
     471             :   if( stk->state(strm) ) {
     472           0 :     white = stk->white;
     473           0 :     token = stk->token;
     474           0 :     stk->token = 0;
     475           0 :     stk->white = 0;
     476           0 :     return token.length();
     477           0 :   }
     478             : 
     479             :   token = 0;
     480           0 :   white = 0;
     481           0 :   if( !strm->good() || (ch = strm->get()) == EOF )
     482           0 :     return 0;
     483           0 : 
     484             :   // read preceeding ws
     485             :   if( IS_WS(ch) ) {
     486           0 :     do white << (char) ch;
     487           0 :     while( IS_WS(ch = strm->get()) );
     488           0 :   }
     489             : 
     490             :   if( ch == '\\' || ch & 0x80 || isalpha(ch) ) {
     491           0 :     if( ch == '\\' ) {
     492           0 :       token << (char) ch;
     493           0 :       ch = strm->get();
     494           0 :     }
     495             :     do {
     496           0 :       token << (char) ch;
     497           0 :       ch = strm->get();
     498           0 :     } while( ch != EOF && (ch & 0x80 || isalpha(ch)) ) ;
     499           0 :     strm->putback(sal::static_int_cast<char>(ch));
     500           0 :     /*  sub, sub, over, atop Ư¼ö ó¸®
     501             :         ±× ÀÌÀ¯´Â next_state()¿¡ ¿µÇâÀ» ¹ÌÄ¡±â ¶§¹®ÀÌ´Ù.
     502             :      */
     503             :     if( !STRICMP("sub", token) || !STRICMP("from", token) ||
     504           0 :     !STRICMP("sup", token) || !STRICMP("to", token) ||
     505           0 :     !STRICMP("over", token) || !STRICMP("atop", token) ||
     506           0 :     !STRICMP("left", token) || !STRICMP("right", token) )
     507           0 :     {
     508             :       char buf[256];
     509             :       make_keyword(buf, token);
     510           0 :       token = buf;
     511           0 :     }
     512             :     if( !token.compare("sub") || !token.compare("from") )
     513           0 :       token = "_";
     514           0 :     if( !token.compare("sup") || !token.compare("to") )
     515           0 :       token = "^";
     516           0 :   }
     517             :   else if( IS_BINARY(ch) ) {
     518           0 :     do token << (char) ch;
     519           0 :     while( IS_BINARY(ch = strm->get()) );
     520           0 :     strm->putback(sal::static_int_cast<char>(ch));
     521           0 :   }
     522             :   else if( isdigit(ch) ) {
     523           0 :     do token << (char) ch;
     524           0 :     while( isdigit(ch = strm->get()) );
     525           0 :     strm->putback(sal::static_int_cast<char>(ch));
     526           0 :   }
     527             :   else
     528             :     token << (char) ch;
     529           0 : 
     530             :   return token.length();
     531           0 : }
     532             : 
     533             : static int read_white_space(MzString& outs, istream *strm)
     534           0 : {
     535             :   int   result;
     536             : 
     537             :   if( stk->state(strm) ) {
     538           0 :     outs << stk->white;
     539           0 :     stk->white = 0;
     540           0 :     result = stk->token[0];
     541           0 :   }
     542             :   else {
     543             :     int ch;
     544             :     while( IS_WS(ch = strm->get()) )
     545           0 :       outs << (char )ch;
     546           0 :     strm->putback(sal::static_int_cast<char>(ch));
     547           0 :     result = ch;
     548           0 :   }
     549             :   return result;
     550           0 : }
     551             : 
     552             : /* Àμö°¡ ÇÊ¿äÇÏÁö ¾ÊÀº °æ¿ì °¢ Ç׸ñ°£ÀÇ ±¸ºÐÀº space¿Í brace
     553             :      sqrt {ab}c = sqrt{ab} c
     554             :    (, }´Â grouping
     555             :    ^, _ ´Â ¾ÕµÚ·Î °áÇÕÇÑ´Ù.
     556             : 
     557             :    sqrt µî°ú °°ÀÌ Àμö°¡ ÀÖ´Â Çü½Ä Á¤¸®
     558             :      sqrt a  -> sqrt{a}
     559             :      sqrt {a}    -> sqrt{a}
     560             :    1 ÀÌ»óÀÇ Àμö°¡ ÀÖ´Â °æ¿ì Àμöµé°£ÀÇ ¿ª¹éÀº ¾ø¾Ø´Ù.
     561             :      \frac a b   -> frac{a}{b}
     562             :    overÀÇ Çü½Ä Á¤¸®
     563             :      a over b    -> {a}over{b}
     564             :  */
     565             : 
     566             : static int eq_word(MzString& outs, istream *strm, int status)
     567           0 : {
     568             :   MzString  token, white, state;
     569           0 :   int       result;
     570             :   char      keyword[256];
     571             :   hwpeq     *eq;
     572             : 
     573             :   next_token(white, token, strm);
     574           0 :   if (token.length() <= 0)
     575           0 :       return 0;
     576           0 :   result = token[0];
     577           0 : 
     578             :   if( token.compare("{") == 0 ) {
     579           0 :     state << white << token;
     580           0 :     eq_sentence(state, strm, "}");
     581           0 :   }
     582             :   else if( token.compare("left") == 0 ) {
     583           0 :     state << white << token;
     584           0 :     next_token(white, token, strm);
     585           0 :     state << white << token;
     586           0 : 
     587             :     eq_sentence(state, strm, "right");
     588           0 : 
     589             :     next_token(white, token, strm);
     590           0 :     state << white << token;
     591           0 :   }
     592             :   else {
     593             :     /* Á¤»óÀûÀÎ token */
     594             :     int script_status = SCRIPT_NONE;
     595           0 :     while( 1 ) {
     596           0 :       state << white << token;
     597           0 :       make_keyword(keyword, token);
     598           0 :       if( token[0] == '^' )
     599           0 :     script_status |= SCRIPT_SUP;
     600           0 :       else if( token[0] == '_' )
     601           0 :     script_status |= SCRIPT_SUB;
     602           0 :       else
     603             :     script_status = SCRIPT_NONE;
     604           0 : 
     605             :       if( 0 != (eq = lookup_eqn(keyword)) ) {
     606           0 :     int nargs = eq->nargs;
     607           0 :     int ch;
     608             :     while( nargs-- ) {
     609           0 :       ch = read_white_space(state, strm);
     610           0 :       if( ch != '{' ) state << '{';
     611           0 :       eq_word(state, strm, script_status);
     612           0 :       if( ch != '{' ) state << '}';
     613           0 :     }
     614             :       }
     615             : 
     616             :       if( !next_token(white, token, strm) )
     617           0 :     break;
     618           0 :       // end loop and restart with this
     619             :       if( (token[0] == '^' && status && !(status & SCRIPT_SUP)) ||
     620           0 :           (token[0] == '_' && status && !(status & SCRIPT_SUB)) ||
     621           0 :       strcmp("over", token) == 0 || strcmp("atop", token) == 0 ||
     622           0 :       strchr("{}#&`", token[0]) ||
     623           0 :       (!strchr("^_", token[0]) && white.length()) ) {
     624           0 :     push_token(white, token, strm);
     625           0 :     break;
     626           0 :       }
     627             :     }
     628             :   }
     629             :   outs << state;
     630           0 : 
     631             :   return result;
     632           0 : }
     633             : 
     634             : static bool eq_sentence(MzString& outs, istream *strm, const char *end)
     635           0 : {
     636             :   MzString  state;
     637           0 :   MzString  white, token;
     638           0 :   bool      multiline = false;
     639           0 : 
     640             :   read_white_space(outs, strm);
     641           0 :   while( eq_word(state, strm) ) {
     642           0 :     if( !next_token(white, token, strm) ||
     643           0 :     (end && strcmp(token.c_str(), end) == 0) )
     644           0 :     {
     645             :       state << white << token;
     646           0 :       break;
     647           0 :     }
     648             :     push_token(white, token, strm);
     649           0 :     if( !token.compare("atop") || !token.compare("over") )
     650           0 :       outs << '{' << state << '}';
     651           0 :     else {
     652             :       if( !token.compare("#") )
     653           0 :     multiline = true;
     654           0 :       outs << state;
     655           0 :     }
     656             :     state =  0;
     657           0 :     read_white_space(outs, strm);
     658           0 :   }
     659             :   outs << state;
     660           0 :   return multiline;
     661           0 : }
     662             : 
     663             : static char eq2ltxconv(MzString& sstr, istream *strm, const char *sentinel)
     664           0 : {
     665             :   MzString  white, token;
     666           0 :   char      key[256];
     667             :   int       ch, result;
     668             :   hwpeq     *eq = 0;
     669           0 : 
     670             :   while( 0 != (result = next_token(white, token, strm)) ) {
     671           0 :     if( sentinel && (result == 1) && strchr(sentinel, token[0]) )
     672           0 :       break;
     673           0 :     make_keyword(key, token);
     674           0 :     if( (eq = lookup_eqn(key)) != 0 ) {
     675           0 :       if( eq->latex )
     676           0 :     strcpy(key, eq->latex);
     677           0 :       else {
     678             :     key[0] = '\\';
     679           0 :     strcpy(key + 1, eq->key);
     680           0 :       }
     681             :       if( (eq->flag & EQ_CASE) && isupper(token[0]) )
     682           0 :     key[1] = sal::static_int_cast<char>(toupper(key[1]));
     683           0 :       token = key;
     684           0 :     }
     685             : 
     686             :     if( token[0] == '{' ) { // grouping
     687           0 :       sstr << white << token;
     688           0 :       eq2ltxconv(sstr, strm, "}");
     689           0 :       sstr << '}';
     690           0 :     }
     691             :     else if( eq && (eq->flag & EQ_ENV) ) {
     692           0 :       next_token(white, token, strm);
     693           0 :       if( token[0] != '{' ) return 0;
     694           0 :       sstr << "\\begin" << "{" << eq->key << "}" << ENDL ;
     695           0 :       eq2ltxconv(sstr, strm, "}");
     696           0 :       if( sstr[sstr.length() - 1] != '\n' )
     697           0 :     sstr << ENDL ;
     698           0 :       sstr << "\\end" << "{" << eq->key << "}" << ENDL ;
     699           0 :     }
     700             :     else if( eq && (eq->flag & EQ_ATOP) ) {
     701           0 :       if( sstr.length() == 0 )
     702           0 :     sstr << '{';
     703           0 :       else {
     704             :     int pos  = sstr.rfind('}');
     705           0 :     if( 0 < pos)
     706           0 :       sstr.replace(pos, ' ');
     707           0 :       }
     708             :       sstr << token;
     709           0 :       while( (ch = strm->get()) != EOF && IS_WS(ch) )
     710           0 :     sstr << (char)ch;
     711           0 :       if( ch != '{' )
     712           0 :     sstr << "{}";
     713           0 :       else {
     714             :     eq2ltxconv(sstr, strm, "}");
     715           0 :     sstr << '}';
     716           0 :       }
     717           0 :     }
     718             :     else
     719             :       sstr << white << token;
     720           0 :   }
     721             :   return token[0];
     722           0 : }
     723             : 
     724             : void eq2latex(MzString& outs, char *s)
     725           0 : {
     726             :   assert(s);
     727             :   if( stk == 0 )
     728           0 :     stk = new eq_stack;
     729           0 : 
     730             :   MzString  tstr;
     731           0 : 
     732             :   istringstream tstrm(s);
     733           0 :   bool eqnarray = eq_sentence(tstr, &tstrm);
     734           0 :   istringstream strm(tstr.c_str());
     735           0 : 
     736             :   if( eqnarray )
     737           0 :     outs << "\\begin{array}{rllll}" << ENDL;
     738           0 :   eq2ltxconv(outs, &strm, 0);
     739           0 :   outs << ENDL;
     740           0 :   if( eqnarray )
     741           0 :     outs << "\\end{array}" << ENDL;
     742           0 :   delete stk;
     743           0 :   stk = 0;
     744           0 : }
     745           0 : 
     746             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10