mathematical 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +14 -7
  3. data/Rakefile +4 -1
  4. data/ext/mathematical/cairo_callbacks.h +5 -0
  5. data/ext/mathematical/extconf.rb +34 -8
  6. data/ext/mathematical/lasem_overrides.c +32 -3
  7. data/ext/mathematical/lasem_overrides.h +11 -2
  8. data/ext/mathematical/mathematical.c +27 -26
  9. data/ext/mathematical/mathematical.h +5 -1
  10. data/ext/mathematical/mtex2MML/deps/strdup/strdup.c +24 -0
  11. data/ext/mathematical/mtex2MML/deps/strdup/strdup.h +24 -0
  12. data/ext/mathematical/mtex2MML/deps/uthash/utarray.h +1 -0
  13. data/ext/mathematical/mtex2MML/src/{color_definitions.c → colors.c} +2 -3
  14. data/ext/mathematical/mtex2MML/src/colors.h +23 -0
  15. data/ext/mathematical/mtex2MML/src/em.c +99 -0
  16. data/ext/mathematical/mtex2MML/src/em.h +31 -0
  17. data/ext/mathematical/mtex2MML/src/{parse_extras.c → environment.c} +73 -157
  18. data/ext/mathematical/mtex2MML/src/environment.h +85 -0
  19. data/ext/mathematical/mtex2MML/src/{mtex2MML.l → lexer.l} +26 -15
  20. data/ext/mathematical/mtex2MML/src/main.c +31 -10
  21. data/ext/mathematical/mtex2MML/src/mtex2MML.h +19 -7
  22. data/ext/mathematical/mtex2MML/src/{mtex2MML.y → parser.y} +451 -446
  23. data/ext/mathematical/mtex2MML/src/string_extras.c +4 -3
  24. data/ext/mathematical/mtex2MML/src/string_extras.h +7 -7
  25. data/ext/mathematical/mtex2MML/tests/array.c +11 -11
  26. data/ext/mathematical/mtex2MML/tests/basic.c +14 -13
  27. data/ext/mathematical/mtex2MML/tests/clar.c +2 -0
  28. data/ext/mathematical/mtex2MML/tests/clar/fs.h +3 -1
  29. data/ext/mathematical/mtex2MML/tests/clar/sandbox.h +3 -1
  30. data/ext/mathematical/mtex2MML/tests/cornercases.c +3 -2
  31. data/ext/mathematical/mtex2MML/tests/delimiters.c +126 -0
  32. data/ext/mathematical/mtex2MML/tests/deps/file2str/file2str.c +2 -4
  33. data/ext/mathematical/mtex2MML/tests/deps/mkdtemp/mkdtemp.c +151 -0
  34. data/ext/mathematical/mtex2MML/tests/deps/mkdtemp/mkdtemp.h +10 -0
  35. data/ext/mathematical/mtex2MML/tests/deps/trim/trim.c +4 -1
  36. data/ext/mathematical/mtex2MML/tests/env.c +35 -34
  37. data/ext/mathematical/mtex2MML/tests/functions.c +3 -2
  38. data/ext/mathematical/mtex2MML/tests/helpers.c +6 -4
  39. data/ext/mathematical/mtex2MML/tests/helpers.h +2 -2
  40. data/ext/mathematical/mtex2MML/tests/main.c +1 -1
  41. data/ext/mathematical/mtex2MML/tests/maliciousness.c +35 -9
  42. data/ext/mathematical/mtex2MML/tests/mathjax.c +202 -202
  43. data/ext/mathematical/mtex2MML/tests/numbered_equations.c +6 -6
  44. data/ext/mathematical/mtex2MML/tests/performance.c +39 -0
  45. data/lib/mathematical.rb +38 -5
  46. data/lib/mathematical/configuration.rb +19 -0
  47. data/lib/mathematical/validator.rb +17 -31
  48. data/lib/mathematical/version.rb +1 -1
  49. data/mathematical.gemspec +3 -1
  50. data/test/mathematical/basic_test.rb +60 -7
  51. data/test/mathematical/corrections_test.rb +1 -1
  52. data/test/mathematical/delimiters_test.rb +58 -0
  53. data/test/mathematical/fixtures_test.rb +3 -2
  54. data/test/mathematical/maliciousness_test.rb +19 -27
  55. data/test/mathematical/mathjax_test.rb +6 -5
  56. data/test/mathematical/mathml_test.rb +1 -1
  57. data/test/mathematical/multiples_test.rb +1 -1
  58. data/test/mathematical/performance_test.rb +3 -1
  59. data/test/mathematical/png_test.rb +3 -3
  60. data/test/test_helper.rb +4 -1
  61. metadata +35 -21
  62. data/ext/mathematical/lasem/src/lsmdomenumtypes.c +0 -99
  63. data/ext/mathematical/lasem/src/lsmdomenumtypes.h +0 -26
  64. data/ext/mathematical/lasem/src/lsmmathmlenumtypes.c +0 -737
  65. data/ext/mathematical/lasem/src/lsmmathmlenumtypes.h +0 -93
  66. data/ext/mathematical/lasem/src/lsmsvgenumtypes.c +0 -1083
  67. data/ext/mathematical/lasem/src/lsmsvgenumtypes.h +0 -111
  68. data/ext/mathematical/mtex2MML/Makefile +0 -100
  69. data/ext/mathematical/mtex2MML/build/libmtex2MML.a +0 -0
  70. data/ext/mathematical/mtex2MML/build/mtex2MML.h +0 -73
  71. data/ext/mathematical/mtex2MML/src/lex.yy.c +0 -8845
  72. data/ext/mathematical/mtex2MML/src/parse_extras.h +0 -111
  73. data/ext/mathematical/mtex2MML/src/y.tab.c +0 -10178
  74. data/ext/mathematical/mtex2MML/src/y.tab.h +0 -617
@@ -0,0 +1,85 @@
1
+ #ifndef ENVIRONMENT_H
2
+ #define ENVIRONMENT_H
3
+
4
+ #include "../deps/uthash/uthash.h"
5
+ #include "../deps/uthash/utarray.h"
6
+
7
+ #ifdef __cplusplus
8
+ extern "C" {
9
+ #endif
10
+
11
+ typedef enum {NONE = 0, TOPENCLOSE} encaseType;
12
+ typedef enum {OTHER = 0, ENV_ALIGN, ENV_ALIGNAT, ENV_ALIGNED, ENV_EQUATION, ENV_GATHER, ENV_GATHERED, ENV_EQNARRAY, ENV_MULTLINE, ENV_MULTLINESTAR, ENV_SMALLMATRIX} envType;
13
+
14
+ typedef struct {
15
+ char *rowspacing;
16
+ char *rowlines;
17
+ envType environment_type;
18
+ UT_array *eqn_numbers;
19
+ int line_count;
20
+ } envdata_t;
21
+
22
+ /* Move various symbols not easily supported inline within the `\begin` line
23
+ This is so that the Bison parser can properly act on these. For example,
24
+ `\hline`, `\hlinedash`, or `\\[2ex]` declerations.
25
+
26
+ In order to properly address these situations, we need to parse them, find their symbols,
27
+ and then modify the starting environment declaration to point out where those symbols are.
28
+
29
+ Suppose there is an array like:
30
+
31
+ \begin{array}{c:c}
32
+ \begin{array}{c|cclc}
33
+ \text{min} & 0 & 1 & 2 & 3\\
34
+ \hline
35
+ 0 & 0 & 0 & 0 & 0\\
36
+ 1 & 0 & 1 & 1 & 1\\
37
+ 2 & 0 & 1 & 2 & 2\\
38
+ 3 & 0 & 1 & 2 & 3
39
+ \end{array}
40
+ &
41
+ \begin{array}{c|cccl}
42
+ \text{max}&0&1&2&3\\
43
+ \hline
44
+ 0 & 0 & 1 & 2 & 3\\
45
+ 1 & 1 & 1 & 2 & 3\\
46
+ 2 & 2 & 2 & 2 & 3\\
47
+ 3 & 3 & 3 & 3 & 3
48
+ \end{array}
49
+ \end{array}
50
+
51
+ The env_replacements function will push every line onto a stack. When an \end
52
+ is detected, it starts popping off the stack until it reaches the corresponding
53
+ \begin. It then modifies that stack with attribute strings, an arrangement of
54
+ the symbols encountered while popping lines off. */
55
+ void mtex2MML_env_replacements(UT_array **environment_data_stack, encaseType **encase, const char *environment);
56
+
57
+ int mtex2MML_determine_environment(const char *environment);
58
+
59
+ int mtex2MML_identify_eqn_number(envType environment_type, char *line);
60
+
61
+ void mtex2MML_perform_replacement(UT_array **environment_data_stack, UT_array *rowlines_stack, envType environment_type, UT_array *has_eqn_number, UT_array *row_spacing_stack);
62
+
63
+ /* determines the column border arrangement from the array environment definition (c|cc|c...) */
64
+ char *mtex2MML_vertical_pipe_extract(char *string);
65
+
66
+ /* removes placeholder pipe characters from columnalign (for example, c|c:c becomes "center s center d center")--we need to remove the "s" and "d" characters */
67
+ char *mtex2MML_remove_excess_pipe_chars(char *string);
68
+
69
+ /* return the proper rowlines information */
70
+ char *mtex2MML_combine_row_data(UT_array **environment_data_stack);
71
+
72
+ /* return the has_eqn_number value of the last row */
73
+ int mtex2MML_fetch_eqn_number(UT_array **environment_data_stack);
74
+
75
+ /* get the environment type of the top-most item */
76
+ envType mtex2MML_current_env_type(UT_array **environment_data_stack);
77
+
78
+ /* get the line count of the top-most item */
79
+ int mtex2MML_current_env_line_count(UT_array **environment_data_stack);
80
+
81
+ #ifdef __cplusplus
82
+ }
83
+ #endif
84
+
85
+ #endif /* ! ENVIRONMENT_H */
@@ -7,14 +7,16 @@
7
7
 
8
8
  #define YYSTYPE char *
9
9
 
10
- #include "y.tab.h"
10
+ #include "parser.h"
11
11
  #include "mtex2MML.h"
12
- #include "parse_extras.h"
12
+ #include "environment.h"
13
13
  #include "string_extras.h"
14
14
 
15
15
  #define YY_NEVER_INTERACTIVE 1
16
16
  #define YY_INPUT(buffer,result,max_size) result = s_mtex2MML_read (buffer, max_size)
17
17
 
18
+ extern int fileno(FILE *); /* avoids gcc warning */
19
+
18
20
  static int s_mtex2MML_read (char * buffer, int max_size);
19
21
 
20
22
  #define yylval mtex2MML_yylval
@@ -37,9 +39,9 @@ char * mtex2MML_str;
37
39
 
38
40
  int mtex2MML_rowposn = 0;
39
41
 
40
- // TODO: I'm not sure what the next option does. My addition
41
- // of `display_style` is to fix issue776. Probably worth merging
42
- // these in the future?
42
+ /* TODO: I'm not sure what the next option does. My addition
43
+ of `display_style` is to fix issue776. Probably worth merging
44
+ these in the future? */
43
45
  int mtex2MML_displaymode = 0;
44
46
  int display_style = 0;
45
47
 
@@ -49,8 +51,17 @@ int display_style = 0;
49
51
  if (mtex2MML_rowposn==2) mtex2MML_rowposn=1;
50
52
  %}
51
53
 
52
- <INITIAL>"$"{1,2} BEGIN(MATH); mtex2MML_inoptarg[0] = 0; mtex2MML_rowposn=2; if (yyleng==2) { mtex2MML_displaymode=1; return STARTDMATH;}; mtex2MML_displaymode=0; return STARTMATH;
53
- <INITIAL>"\\[" BEGIN(MATH); mtex2MML_inoptarg[0] = 0; mtex2MML_rowposn=2; mtex2MML_displaymode=1; return STARTDMATH;
54
+ /* "Basic heuristic is: opening $ can't be followed by whitespace, closing $ can't be followed by
55
+ a digit or preceded by whitespace." -- @jgm, http://bit.ly/1HVtemx */
56
+
57
+ <INITIAL>"$$" if (mtex2MML_delimiter_type(MTEX2MML_DELIMITER_DOUBLE)) { BEGIN(MATH); mtex2MML_inoptarg[0] = 0; mtex2MML_rowposn=2; mtex2MML_displaymode=1; return STARTDMATH; }
58
+
59
+ <INITIAL>"$"[\t\r\n ]? if (mtex2MML_delimiter_type(MTEX2MML_DELIMITER_DOLLAR)) { mtex2MML_inoptarg[0] = 0; mtex2MML_rowposn=2; if (yyleng==2) { BEGIN(ENDMATH); return INITIAL;}; BEGIN(MATH); mtex2MML_displaymode=0; return STARTMATH; }
60
+
61
+ <INITIAL>"\\(" if (mtex2MML_delimiter_type(MTEX2MML_DELIMITER_PARENS)) {BEGIN(MATH); mtex2MML_inoptarg[0] = 0; mtex2MML_rowposn=2; mtex2MML_displaymode=0; return STARTMATH; }
62
+
63
+ <INITIAL>"\\[" if (mtex2MML_delimiter_type(MTEX2MML_DELIMITER_BRACKETS)) {BEGIN(MATH); mtex2MML_inoptarg[0] = 0; mtex2MML_rowposn=2; mtex2MML_displaymode=1; return STARTDMATH; }
64
+
54
65
  <INITIAL>EOF return 0;
55
66
  <INITIAL>"\n" {mtex2MML_lineno++; yylval=mtex2MML_copy_string(yytext); return CHAR;}
56
67
  <INITIAL>. {yylval=mtex2MML_copy_string(yytext); return CHAR;}
@@ -58,11 +69,11 @@ int display_style = 0;
58
69
 
59
70
  <MATH>{
60
71
 
72
+ "$"{1,2} if (mtex2MML_delimiter_type(MTEX2MML_DELIMITER_DOLLAR) || mtex2MML_delimiter_type(MTEX2MML_DELIMITER_DOUBLE)) { mtex2MML_eqn_src[mtex2MML_eqn_end-mtex2MML_eqn_src-yyleng]=0; mtex2MML_eqn_end=mtex2MML_eqn_src; yylval=mtex2MML_copy_escaped(mtex2MML_eqn_src); BEGIN(INITIAL); return ENDMATH;} else {yylval=mtex2MML_copy_string("$"); return MI;}
61
73
 
74
+ "\\)" if (mtex2MML_delimiter_type(MTEX2MML_DELIMITER_PARENS)) {mtex2MML_eqn_src[mtex2MML_eqn_end-mtex2MML_eqn_src-yyleng]=0; mtex2MML_eqn_end=mtex2MML_eqn_src; yylval=mtex2MML_copy_escaped(mtex2MML_eqn_src); BEGIN(INITIAL); return ENDMATH;}
62
75
 
63
- "$"{1,2} |
64
- "\\]" {mtex2MML_eqn_src[mtex2MML_eqn_end-mtex2MML_eqn_src-yyleng]=0; mtex2MML_eqn_end=mtex2MML_eqn_src; yylval=mtex2MML_copy_escaped(mtex2MML_eqn_src); BEGIN(INITIAL); return ENDMATH;}
65
-
76
+ "\\]" if (mtex2MML_delimiter_type(MTEX2MML_DELIMITER_BRACKETS)) {mtex2MML_eqn_src[mtex2MML_eqn_end-mtex2MML_eqn_src-yyleng]=0; mtex2MML_eqn_end=mtex2MML_eqn_src; yylval=mtex2MML_copy_escaped(mtex2MML_eqn_src); BEGIN(INITIAL); return ENDMATH;}
66
77
 
67
78
  "\\limits" return LIMITS;
68
79
  "\\nolimits" return NOLIMITS;
@@ -123,7 +134,7 @@ int display_style = 0;
123
134
  "\\cr"[\n\r\t ]* |
124
135
  "\\\\"[\n\r\t ]* { mtex2MML_rowposn=2; return ROWSEP; }
125
136
 
126
- [0-9\.,]+(em|ex|px|in|cm|mm|mu|pt|pc|%) {char * normalized_px = str_replace(yytext, ",", "."); yylval=mtex2MML_copy_string(normalized_px); mtex2MML_free_string(normalized_px); return PXSTRING; }
137
+ [0-9\.,]+(em|ex|px|in|cm|mm|mu|pt|pc|%) {char * normalized_px = mtex2MML_str_replace(yytext, ",", "."); yylval=mtex2MML_copy_string(normalized_px); mtex2MML_free_string(normalized_px); return PXSTRING; }
127
138
 
128
139
  [a-zA-Z] {yylval=mtex2MML_copy_string(yytext); return MI;}
129
140
 
@@ -1244,7 +1255,7 @@ int display_style = 0;
1244
1255
  <BRACKETLIST>{
1245
1256
  "\[" {return ST;}
1246
1257
  "\]" {BEGIN(MATH); return END;}
1247
- [0-9\.,]+(em|ex|px|in|cm|mm|mu|pt|pc|%) {char * normalized_px = str_replace(yytext, ",", "."); if (normalized_px[0] == '.') remove_first_char(normalized_px); yylval=mtex2MML_copy_string(normalized_px); mtex2MML_free_string(normalized_px); return PXSTRING; }
1258
+ [0-9\.,]+(em|ex|px|in|cm|mm|mu|pt|pc|%) {char * normalized_px = mtex2MML_str_replace(yytext, ",", "."); if (normalized_px[0] == '.') mtex2MML_remove_first_char(normalized_px); yylval=mtex2MML_copy_string(normalized_px); mtex2MML_free_string(normalized_px); return PXSTRING; }
1248
1259
  [0-9a-zA-Z ]+":"[0-9a-zA-Z ]+ {yylval=mtex2MML_copy_string(yytext); return STYLESTRING;}
1249
1260
  #?[0-9a-zA-Z]+ {yylval=mtex2MML_copy_string(yytext); return COLORSTRING;}
1250
1261
  [\t\n\r, ]+ ;
@@ -1470,21 +1481,21 @@ int display_style = 0;
1470
1481
 
1471
1482
  <SPACEWIDTH>{
1472
1483
  "\{" { return ST;}
1473
- [0-9\.,]+(em|ex|px|in|cm|mm|mu|pt|pc|%) {char * normalized_px = str_replace(yytext, ",", "."); yylval=mtex2MML_copy_string(normalized_px); mtex2MML_free_string(normalized_px); return PXSTRING; }
1484
+ [0-9\.,]+(em|ex|px|in|cm|mm|mu|pt|pc|%) {char * normalized_px = mtex2MML_str_replace(yytext, ",", "."); yylval=mtex2MML_copy_string(normalized_px); mtex2MML_free_string(normalized_px); return PXSTRING; }
1474
1485
  "\}" {BEGIN(SPACEHEIGHT); return ST;}
1475
1486
  [\t\n\r ]+ ;
1476
1487
  }
1477
1488
 
1478
1489
  <SPACEHEIGHT>{
1479
1490
  "\{" { return ST;}
1480
- [0-9\.,]+(em|ex|px|in|cm|mm|mu|pt|pc|%) {char * normalized_px = str_replace(yytext, ",", "."); yylval=mtex2MML_copy_string(normalized_px); mtex2MML_free_string(normalized_px); return PXSTRING; }
1491
+ [0-9\.,]+(em|ex|px|in|cm|mm|mu|pt|pc|%) {char * normalized_px = mtex2MML_str_replace(yytext, ",", "."); yylval=mtex2MML_copy_string(normalized_px); mtex2MML_free_string(normalized_px); return PXSTRING; }
1481
1492
  "\}" {BEGIN(SPACEDEPTH); return ST;}
1482
1493
  [\t\n\r ]+ ;
1483
1494
  }
1484
1495
 
1485
1496
  <SPACEDEPTH>{
1486
1497
  "\{" { return ST;}
1487
- [0-9\.,]+(em|ex|px|in|cm|mm|mu|pt|pc|%) {char * normalized_px = str_replace(yytext, ",", "."); yylval=mtex2MML_copy_string(normalized_px); mtex2MML_free_string(normalized_px); return PXSTRING; }
1498
+ [0-9\.,]+(em|ex|px|in|cm|mm|mu|pt|pc|%) {char * normalized_px = mtex2MML_str_replace(yytext, ",", "."); yylval=mtex2MML_copy_string(normalized_px); mtex2MML_free_string(normalized_px); return PXSTRING; }
1488
1499
  "\}" {BEGIN(MATH); return ST;}
1489
1500
  [\t\n\r ]+ ;
1490
1501
  }
@@ -9,6 +9,7 @@ int main (int argc, char ** argv)
9
9
  int bRawFilter = 0;
10
10
  int bInline = 0;
11
11
  int bDisplay = 0;
12
+ int bDelimiters = 0;
12
13
 
13
14
  int bStop = 0;
14
15
  int bForbidMarkup = 0;
@@ -40,13 +41,17 @@ int main (int argc, char ** argv)
40
41
  "\n"
41
42
  "mtex2MML Options:\n"
42
43
  "\n"
43
- " --raw-filter filter input stream, converting equations as found to MathML [stops on error]\n"
44
- " --inline converts a single TeX equation, without any $ symbols, to inline MathML\n"
45
- " --display converts a single TeX equation, without any $ symbols, to display-mode MathML\n"
46
- " --forbid-markup forbid markup (more precisely, the '<' and '>' characters) in TeX equations\n"
47
- " --print-mtex used in conjuction with --inline or --display: prints the TeX string\n"
44
+ " --raw-filter filter input stream, converting equations as found to MathML [stops on error]\n"
45
+ " --inline converts a single TeX equation, without any $ symbols, to inline MathML\n"
46
+ " --display converts a single TeX equation, without any $ symbols, to display-mode MathML\n"
47
+ " --forbid-markup forbid markup (more precisely, the '<' and '>' characters) in TeX equations\n"
48
+ " --print-mtex used in conjuction with --inline or --display: prints the TeX string\n"
49
+ " --use-dollar uses `$..$` for inline math\n"
50
+ " --use-double uses `$$..$$` for display math\n"
51
+ " --use-parens uses `\\(..\\)` for inline math\n"
52
+ " --use-brackets uses `\\[..\\]` for display math\n"
48
53
  "\n"
49
- "For further information, see https://github.com/gjtorikian/mtex2MML\n", stdout);
54
+ "For more information, see https://github.com/gjtorikian/mtex2MML\n", stdout);
50
55
 
51
56
  bStop = 1;
52
57
  break;
@@ -80,6 +85,22 @@ int main (int argc, char ** argv)
80
85
  bDisplay = 0;
81
86
  continue;
82
87
  }
88
+ if (strcmp(args, "--use-dollar") == 0) {
89
+ bDelimiters |= MTEX2MML_DELIMITER_DOLLAR;
90
+ continue;
91
+ }
92
+ if (strcmp(args, "--use-double") == 0) {
93
+ bDelimiters |= MTEX2MML_DELIMITER_DOUBLE;
94
+ continue;
95
+ }
96
+ if (strcmp(args, "--use-parens") == 0) {
97
+ bDelimiters |= MTEX2MML_DELIMITER_PARENS;
98
+ continue;
99
+ }
100
+ if (strcmp(args, "--use-brackets") == 0) {
101
+ bDelimiters |= MTEX2MML_DELIMITER_BRACKETS;
102
+ continue;
103
+ }
83
104
  }
84
105
  if (bStop) { return 0; }
85
106
 
@@ -109,11 +130,11 @@ int main (int argc, char ** argv)
109
130
  char *s = utstring_body(mtex);
110
131
  int len = utstring_len(mtex);
111
132
  if (bRawFilter) {
112
- mtex2MML_filter (s, len);
133
+ mtex2MML_filter (s, len, bDelimiters);
113
134
  } else if (bForbidMarkup) {
114
- mtex2MML_strict_html_filter (s, len);
135
+ mtex2MML_strict_filter (s, len, bDelimiters);
115
136
  } else {
116
- mtex2MML_html_filter (s, len);
137
+ mtex2MML_text_filter (s, len, bDelimiters);
117
138
  }
118
139
  utstring_free(mtex);
119
140
  return 0;
@@ -121,7 +142,7 @@ int main (int argc, char ** argv)
121
142
 
122
143
  char *s = utstring_body(mtex);
123
144
  int len = utstring_len(mtex);
124
- char * mathml = mtex2MML_parse (s, len);
145
+ char * mathml = mtex2MML_parse(s, len, bDelimiters);
125
146
 
126
147
  if (mathml) {
127
148
  fputs (mathml, stdout);
@@ -1,7 +1,7 @@
1
1
  #ifndef MTEX2MML_H
2
2
  #define MTEX2MML_H
3
3
 
4
- #define MTEX2MML_VERSION "1.1.1"
4
+ #define MTEX2MML_VERSION "1.2.2"
5
5
 
6
6
  #ifdef __cplusplus
7
7
  extern "C" {
@@ -11,7 +11,7 @@ extern "C" {
11
11
 
12
12
  /* Step 1. Parse a buffer with mtex source; return value is mathml, or 0 on failure (e.g., parse error).
13
13
  */
14
- extern char * mtex2MML_parse (const char * buffer, unsigned long length);
14
+ extern char * mtex2MML_parse (const char * buffer, unsigned long length, const int options);
15
15
 
16
16
  /* Step 2. Free the string from Step 1.
17
17
  */
@@ -20,11 +20,20 @@ extern void mtex2MML_free_string (char * str);
20
20
 
21
21
  /* Alternatively, to filter generic source and converting embedded equations, use:
22
22
  */
23
- extern int mtex2MML_filter (const char * buffer, unsigned long length);
23
+ extern int mtex2MML_filter (const char * buffer, unsigned long length, const int options);
24
+ extern int mtex2MML_text_filter (const char * buffer, unsigned long length, const int options);
25
+ extern int mtex2MML_strict_filter (const char * buffer, unsigned long length, const int options);
24
26
 
25
- extern int mtex2MML_html_filter (const char * buffer, unsigned long length);
26
- extern int mtex2MML_strict_html_filter (const char * buffer, unsigned long length);
27
+ extern int mtex2MML_do_filter (const char * buffer, unsigned long length, const int forbid_markup, const int write, const int options);
27
28
 
29
+ /** Types of delimiters
30
+ */
31
+ #define MTEX2MML_DELIMITER_DEFAULT 0
32
+ #define MTEX2MML_DELIMITER_DOLLAR 1
33
+ #define MTEX2MML_DELIMITER_DOUBLE 2
34
+ #define MTEX2MML_DELIMITER_PARENS 4
35
+ #define MTEX2MML_DELIMITER_BRACKETS 8
36
+ #define MTEX2MML_DELIMITER_ENVIRONMENTS 16
28
37
 
29
38
  /* To change output methods:
30
39
  *
@@ -38,7 +47,9 @@ extern void (*mtex2MML_error) (const char * msg); /* de
38
47
  /* Other stuff:
39
48
  */
40
49
 
41
- extern char * mtex2MML_global_parse (const char * buffer, unsigned long length, int global_start);
50
+ extern char * mtex2MML_global_parse (const char * buffer, unsigned long length, const int options, const int global_start);
51
+
52
+ extern int mtex2MML_delimiter_type();
42
53
 
43
54
  extern void mtex2MML_setup (const char * buffer, unsigned long length);
44
55
 
@@ -47,7 +58,7 @@ extern void mtex2MML_restart ();
47
58
  extern int mtex2MML_do_capture_eqn();
48
59
  extern int mtex2MML_capture_eqn_src();
49
60
 
50
- extern const char * mtex2MML_output ();
61
+ extern char * mtex2MML_output ();
51
62
 
52
63
  extern char * mtex2MML_copy_string (const char * str);
53
64
  extern char * mtex2MML_copy_string_extra (const char * str, unsigned extra);
@@ -63,6 +74,7 @@ extern int mtex2MML_rowposn;
63
74
  extern int mtex2MML_displaymode;
64
75
  extern int display_style;
65
76
 
77
+ extern int delimiter_options;
66
78
  extern int global_label;
67
79
  extern int line_counter;
68
80
 
@@ -4,11 +4,15 @@
4
4
  #include <stdio.h>
5
5
  #include <string.h>
6
6
  #include <stdlib.h>
7
+ #include <ctype.h>
7
8
 
8
9
  #include "mtex2MML.h"
9
- #include "parse_extras.h"
10
+ #include "colors.h"
11
+ #include "em.h"
12
+ #include "environment.h"
10
13
  #include "string_extras.h"
11
14
 
15
+ #include "../deps/strdup/strdup.h"
12
16
  #include "../deps/uthash/uthash.h"
13
17
 
14
18
  struct css_colors *colors = NULL;
@@ -19,8 +23,8 @@ struct css_colors *colors = NULL;
19
23
  /* set max nesting. utterly arbitrary number determined from http://git.io/FlWHfw */
20
24
  #define YYMAXDEPTH 430
21
25
 
22
- // #define YYDEBUG 1
23
- // yydebug = 1;
26
+ /*#define YYDEBUG 1
27
+ yydebug = 1;*/
24
28
 
25
29
  #define YYERROR_VERBOSE 1
26
30
 
@@ -28,189 +32,188 @@ struct css_colors *colors = NULL;
28
32
 
29
33
  UT_array *environment_data_stack;
30
34
 
31
- encaseType * encase = NONE;
35
+ encaseType encase = NONE;
32
36
 
33
37
  extern int yylex ();
34
38
 
35
39
  extern char * yytext;
36
40
 
37
- global_label = 1;
38
- line_counter = 1;
41
+ int global_label = 1;
42
+ int line_counter = 1;
43
+ int delimiter_options = 0;
39
44
 
40
45
  static void mtex2MML_default_error (const char * msg)
41
- {
42
- if (msg)
43
- fprintf(stderr, "Line: %d Error: %s\n", mtex2MML_lineno, msg);
46
+ {
47
+ if (msg) {
48
+ fprintf(stderr, "Line: %d Error: %s\n", mtex2MML_lineno, msg);
44
49
  }
50
+ }
45
51
 
46
52
  void (*mtex2MML_error) (const char * msg) = mtex2MML_default_error;
47
53
 
48
- static void yyerror (char **ret_str, char * s)
49
- {
50
- char * msg = mtex2MML_copy3 (s, " at token ", yytext);
51
- if (mtex2MML_error)
52
- (*mtex2MML_error) (msg);
53
- mtex2MML_free_string (msg);
54
+ static void yyerror (char **ret_str, const char * s)
55
+ {
56
+ char * msg = mtex2MML_copy3 (s, " at token ", yytext);
57
+ if (mtex2MML_error) {
58
+ (*mtex2MML_error) (msg);
54
59
  }
60
+ mtex2MML_free_string (msg);
61
+ }
55
62
 
56
63
  /* Note: If length is 0, then buffer is treated like a string; otherwise only length bytes are written.
57
64
  */
65
+
58
66
  static void mtex2MML_default_write (const char * buffer, unsigned long length)
59
- {
60
- if (buffer)
61
- {
62
- if (length)
63
- fwrite (buffer, 1, length, stdout);
64
- else
65
- fputs (buffer, stdout);
66
- }
67
+ {
68
+ if (buffer) {
69
+ if (length) {
70
+ fwrite (buffer, 1, length, stdout);
71
+ } else {
72
+ fputs (buffer, stdout);
73
+ }
67
74
  }
75
+ }
68
76
 
69
77
  static void mtex2MML_default_write_mathml (const char * mathml)
70
- {
71
- if (mtex2MML_write)
72
- (*mtex2MML_write) (mathml, 0);
78
+ {
79
+ if (mtex2MML_write) {
80
+ (*mtex2MML_write) (mathml, 0);
73
81
  }
82
+ }
74
83
 
75
- #ifdef mtex2MML_CAPTURE
76
- static char * mtex2MML_output_string = "" ;
77
-
78
- const char * mtex2MML_output ()
79
- {
80
- char * copy = (char *) malloc((mtex2MML_output_string ? strlen(mtex2MML_output_string) : 0) + 1);
81
- if (copy)
82
- {
83
- if (mtex2MML_output_string)
84
- {
85
- strcpy(copy, mtex2MML_output_string);
86
- if (*mtex2MML_output_string != '\0')
87
- mtex2MML_free_string(mtex2MML_output_string);
88
- }
89
- else
90
- copy[0] = 0;
91
- mtex2MML_output_string = "";
92
- }
93
- return copy;
94
- }
84
+ #ifdef mtex2MML_CAPTURE
85
+ static char * mtex2MML_output_string = "" ;
95
86
 
96
- static void mtex2MML_capture (const char * buffer, unsigned long length)
97
- {
98
- if (buffer)
99
- {
100
- if (length)
101
- {
102
- unsigned long first_length = mtex2MML_output_string ? strlen(mtex2MML_output_string) : 0;
103
- char * copy = (char *) malloc(first_length + length + 1);
104
- if (copy)
105
- {
106
- if (mtex2MML_output_string)
107
- {
108
- strcpy(copy, mtex2MML_output_string);
109
- if (*mtex2MML_output_string != '\0')
110
- mtex2MML_free_string(mtex2MML_output_string);
111
- }
112
- else
113
- copy[0] = 0;
114
- strncat(copy, buffer, length);
115
- mtex2MML_output_string = copy;
116
- }
117
- }
118
- else
119
- {
120
- char * copy = mtex2MML_copy2(mtex2MML_output_string, buffer);
121
- if (*mtex2MML_output_string != '\0')
122
- mtex2MML_free_string(mtex2MML_output_string);
123
- mtex2MML_output_string = copy;
124
- }
125
- }
126
- }
87
+ char * mtex2MML_output ()
88
+ {
89
+ char * copy = (char *) malloc((mtex2MML_output_string ? strlen(mtex2MML_output_string) : 0) + 1);
90
+ if (copy) {
91
+ if (mtex2MML_output_string) {
92
+ strcpy(copy, mtex2MML_output_string);
93
+ if (*mtex2MML_output_string != '\0') {
94
+ mtex2MML_free_string(mtex2MML_output_string);
95
+ }
96
+ } else {
97
+ copy[0] = 0;
98
+ }
99
+ mtex2MML_output_string = "";
100
+ }
101
+ return copy;
102
+ }
127
103
 
128
- static void mtex2MML_capture_mathml (const char * buffer)
129
- {
130
- char * temp = mtex2MML_copy2(mtex2MML_output_string, buffer);
131
- if (*mtex2MML_output_string != '\0')
104
+ static void mtex2MML_capture (const char * buffer, unsigned long length)
105
+ {
106
+ if (buffer) {
107
+ if (length) {
108
+ unsigned long first_length = mtex2MML_output_string ? strlen(mtex2MML_output_string) : 0;
109
+ char * copy = (char *) malloc(first_length + length + 1);
110
+ if (copy) {
111
+ if (mtex2MML_output_string) {
112
+ strcpy(copy, mtex2MML_output_string);
113
+ if (*mtex2MML_output_string != '\0') {
114
+ mtex2MML_free_string(mtex2MML_output_string);
115
+ }
116
+ } else {
117
+ copy[0] = 0;
118
+ }
119
+ strncat(copy, buffer, length);
120
+ mtex2MML_output_string = copy;
121
+ }
122
+ } else {
123
+ char * copy = mtex2MML_copy2(mtex2MML_output_string, buffer);
124
+ if (*mtex2MML_output_string != '\0') {
132
125
  mtex2MML_free_string(mtex2MML_output_string);
133
- mtex2MML_output_string = temp;
134
- }
135
- void (*mtex2MML_write) (const char * buffer, unsigned long length) = mtex2MML_capture;
136
- void (*mtex2MML_write_mathml) (const char * mathml) = mtex2MML_capture_mathml;
137
- #else
138
- void (*mtex2MML_write) (const char * buffer, unsigned long length) = mtex2MML_default_write;
139
- void (*mtex2MML_write_mathml) (const char * mathml) = mtex2MML_default_write_mathml;
140
- #endif
126
+ }
127
+ mtex2MML_output_string = copy;
128
+ }
129
+ }
130
+ }
131
+
132
+ static void mtex2MML_capture_mathml (const char * buffer)
133
+ {
134
+ char * temp = mtex2MML_copy2(mtex2MML_output_string, buffer);
135
+ if (*mtex2MML_output_string != '\0') {
136
+ mtex2MML_free_string(mtex2MML_output_string);
137
+ }
138
+ mtex2MML_output_string = temp;
139
+ }
140
+ void (*mtex2MML_write) (const char * buffer, unsigned long length) = mtex2MML_capture;
141
+ void (*mtex2MML_write_mathml) (const char * mathml) = mtex2MML_capture_mathml;
142
+ #else
143
+ void (*mtex2MML_write) (const char * buffer, unsigned long length) = mtex2MML_default_write;
144
+ void (*mtex2MML_write_mathml) (const char * mathml) = mtex2MML_default_write_mathml;
145
+ #endif
141
146
 
142
147
  char * mtex2MML_empty_string = (char *) "";
143
148
 
144
149
  /* Create a copy of a string, adding space for extra chars
145
150
  */
146
151
  char * mtex2MML_copy_string_extra (const char * str, unsigned extra)
147
- {
148
- char * copy = (char *) malloc(extra + (str ? strlen (str) : 0) + 1);
149
- if (copy)
150
- {
151
- if (str)
152
- strcpy(copy, str);
153
- else
154
- copy[0] = 0;
155
- }
156
- return copy ? copy : mtex2MML_empty_string;
152
+ {
153
+ char * copy = (char *) malloc(extra + (str ? strlen (str) : 0) + 1);
154
+ if (copy) {
155
+ if (str) {
156
+ strcpy(copy, str);
157
+ } else {
158
+ copy[0] = 0;
159
+ }
157
160
  }
161
+ return copy ? copy : mtex2MML_empty_string;
162
+ }
158
163
 
159
164
  /* Create a copy of a string, appending two strings
160
165
  */
161
166
  char * mtex2MML_copy3 (const char * first, const char * second, const char * third)
162
- {
163
- int first_length = first ? strlen( first) : 0;
164
- int second_length = second ? strlen(second) : 0;
165
- int third_length = third ? strlen( third) : 0;
166
-
167
- char * copy = (char *) malloc(first_length + second_length + third_length + 1);
168
-
169
- if (copy)
170
- {
171
- if (first)
172
- strcpy(copy, first);
173
- else
174
- copy[0] = 0;
175
-
176
- if (second) strcat(copy, second);
177
- if ( third) strcat(copy, third);
178
- }
179
- return copy ? copy : mtex2MML_empty_string;
167
+ {
168
+ int first_length = first ? strlen( first) : 0;
169
+ int second_length = second ? strlen(second) : 0;
170
+ int third_length = third ? strlen( third) : 0;
171
+
172
+ char * copy = (char *) malloc(first_length + second_length + third_length + 1);
173
+
174
+ if (copy) {
175
+ if (first) {
176
+ strcpy(copy, first);
177
+ } else {
178
+ copy[0] = 0;
179
+ }
180
+
181
+ if (second) { strcat(copy, second); }
182
+ if ( third) { strcat(copy, third); }
180
183
  }
184
+ return copy ? copy : mtex2MML_empty_string;
185
+ }
181
186
 
182
187
  /* Create a copy of a string, appending a second string
183
188
  */
184
189
  char * mtex2MML_copy2 (const char * first, const char * second)
185
- {
186
- return mtex2MML_copy3(first, second, 0);
187
- }
190
+ {
191
+ return mtex2MML_copy3(first, second, 0);
192
+ }
188
193
 
189
194
  /* Create a copy of a string
190
195
  */
191
196
  char * mtex2MML_copy_string (const char * str)
192
- {
193
- return mtex2MML_copy3(str, 0, 0);
194
- }
197
+ {
198
+ return mtex2MML_copy3(str, 0, 0);
199
+ }
195
200
 
196
201
  /* Create a copy of a string, escaping unsafe characters for XML
197
202
  */
198
203
  char * mtex2MML_copy_escaped (const char * str)
199
- {
200
- unsigned long length = 0;
204
+ {
205
+ unsigned long length = 0;
201
206
 
202
- const char * ptr1 = str;
207
+ const char * ptr1 = str;
203
208
 
204
- char * ptr2 = 0;
205
- char * copy = 0;
209
+ char * ptr2 = 0;
210
+ char * copy = 0;
206
211
 
207
- if ( str == 0) return mtex2MML_empty_string;
208
- if (*str == 0) return mtex2MML_empty_string;
212
+ if ( str == 0) { return mtex2MML_empty_string; }
213
+ if (*str == 0) { return mtex2MML_empty_string; }
209
214
 
210
- while (*ptr1)
211
- {
212
- switch (*ptr1)
213
- {
215
+ while (*ptr1) {
216
+ switch (*ptr1) {
214
217
  case '<': /* &lt; */
215
218
  case '>': /* &gt; */
216
219
  length += 4;
@@ -227,57 +230,55 @@ struct css_colors *colors = NULL;
227
230
  length += 1;
228
231
  break;
229
232
  }
230
- ++ptr1;
231
- }
232
-
233
- copy = (char *) malloc (length + 1);
234
-
235
- if (copy)
236
- {
237
- ptr1 = str;
238
- ptr2 = copy;
233
+ ++ptr1;
234
+ }
239
235
 
240
- while (*ptr1)
241
- {
242
- switch (*ptr1)
243
- {
244
- case '<':
245
- strcpy (ptr2, "&lt;");
246
- ptr2 += 4;
247
- break;
248
- case '>':
249
- strcpy (ptr2, "&gt;");
250
- ptr2 += 4;
251
- break;
252
- case '&': /* &amp; */
253
- strcpy (ptr2, "&amp;");
254
- ptr2 += 5;
255
- break;
256
- case '\'': /* &apos; */
257
- strcpy (ptr2, "&apos;");
258
- ptr2 += 6;
259
- break;
260
- case '"': /* &quot; */
261
- strcpy (ptr2, "&quot;");
262
- ptr2 += 6;
263
- break;
264
- case '-': /* &#x2d; */
265
- strcpy (ptr2, "&#x2d;");
266
- ptr2 += 6;
267
- break;
268
- default:
269
- *ptr2++ = *ptr1;
270
- break;
271
- }
236
+ copy = (char *) malloc (length + 1);
237
+
238
+ if (copy) {
239
+ ptr1 = str;
240
+ ptr2 = copy;
241
+
242
+ while (*ptr1) {
243
+ switch (*ptr1) {
244
+ case '<':
245
+ strcpy (ptr2, "&lt;");
246
+ ptr2 += 4;
247
+ break;
248
+ case '>':
249
+ strcpy (ptr2, "&gt;");
250
+ ptr2 += 4;
251
+ break;
252
+ case '&': /* &amp; */
253
+ strcpy (ptr2, "&amp;");
254
+ ptr2 += 5;
255
+ break;
256
+ case '\'': /* &apos; */
257
+ strcpy (ptr2, "&apos;");
258
+ ptr2 += 6;
259
+ break;
260
+ case '"': /* &quot; */
261
+ strcpy (ptr2, "&quot;");
262
+ ptr2 += 6;
263
+ break;
264
+ case '-': /* &#x2d; */
265
+ strcpy (ptr2, "&#x2d;");
266
+ ptr2 += 6;
267
+ break;
268
+ default:
269
+ *ptr2++ = *ptr1;
270
+ break;
271
+ }
272
272
  ++ptr1;
273
273
  }
274
- *ptr2 = 0;
275
- }
276
- return copy ? copy : mtex2MML_empty_string;
274
+ *ptr2 = 0;
277
275
  }
276
+ return copy ? copy : mtex2MML_empty_string;
277
+ }
278
278
 
279
279
  /* Returns a string representation of the global_label, and increments the label */
280
- char * mtex2MML_global_label() {
280
+ char * mtex2MML_global_label()
281
+ {
281
282
  char * n = (char *) malloc(256);
282
283
  snprintf(n, 256, "%d", global_label);
283
284
  global_label++;
@@ -290,18 +291,20 @@ struct css_colors *colors = NULL;
290
291
  /* Create a hex character reference string corresponding to code
291
292
  */
292
293
  char * mtex2MML_character_reference (unsigned long int code)
293
- {
294
- #define ENTITY_LENGTH 10
295
- char * entity = (char *) malloc(ENTITY_LENGTH);
296
- sprintf(entity, "&#x%05lx;", code);
297
- return entity;
298
- }
294
+ {
295
+ #define ENTITY_LENGTH 10
296
+ char * entity = (char *) malloc(ENTITY_LENGTH);
297
+ sprintf(entity, "&#x%05lx;", code);
298
+ return entity;
299
+ }
299
300
 
300
301
  void mtex2MML_free_string (char * str)
301
- {
302
- if (str && str != mtex2MML_empty_string)
303
- free(str);
302
+ {
303
+ if (str && str != mtex2MML_empty_string) {
304
+ free(str);
304
305
  }
306
+ }
307
+
305
308
 
306
309
  %}
307
310
 
@@ -460,7 +463,7 @@ compoundTerm: mob SUB closedTerm SUP closedTerm {
460
463
  mtex2MML_free_string($3);
461
464
  }
462
465
  | mob SUP closedTerm LIMITS SUB closedTerm {
463
- char * mo = str_replace($1, "<mo>", "<mo movablelimits=\"false\">");
466
+ char * mo = mtex2MML_str_replace($1, "<mo>", "<mo movablelimits=\"false\">");
464
467
  char * s1 = mtex2MML_copy2("<munderover>", mo);
465
468
  char * s2 = mtex2MML_copy3($6, " ", $3);
466
469
  $$ = mtex2MML_copy3(s1, s2, "</munderover>");
@@ -473,7 +476,7 @@ compoundTerm: mob SUB closedTerm SUP closedTerm {
473
476
  mtex2MML_free_string($6);
474
477
  }
475
478
  | mob SUP closedTerm NOLIMITS SUB closedTerm {
476
- char * mo = str_replace($1, "<mo>", "<mo movablelimits=\"false\">");
479
+ char * mo = mtex2MML_str_replace($1, "<mo>", "<mo movablelimits=\"false\">");
477
480
  char * s1 = mtex2MML_copy2("<msubsup>", mo);
478
481
  char * s2 = mtex2MML_copy3($6, " ", $3);
479
482
  $$ = mtex2MML_copy3(s1, s2, "</msubsup>");
@@ -1185,9 +1188,9 @@ color: COLOR ATTRLIST compoundTermList {
1185
1188
  mtex2MML_free_string($3);
1186
1189
  }
1187
1190
  | BBOX ST PXSTRING END closedTerm {
1188
- float padding = extract_number_from_pxstring($3);
1189
- char *px = extract_string_from_pxstring($3);
1190
- char *dbl_px = double_pixel(padding, px);
1191
+ float padding = mtex2MML_extract_number_from_pxstring($3);
1192
+ char *px = mtex2MML_extract_string_from_pxstring($3);
1193
+ char *dbl_px = mtex2MML_double_pixel(padding, px);
1191
1194
 
1192
1195
  char *s1 = mtex2MML_copy3("<mpadded width=\"+", dbl_px, "\" height=\"+");
1193
1196
  char *s2 = mtex2MML_copy3(s1, $3, "\" depth=\"+");
@@ -1215,9 +1218,9 @@ color: COLOR ATTRLIST compoundTermList {
1215
1218
  | BBOX ST COLORSTRING PXSTRING END closedTerm {
1216
1219
  char *s1 = mtex2MML_copy3("<mstyle mathbackground=\"", $3, "\">");
1217
1220
 
1218
- float padding = extract_number_from_pxstring($4);
1219
- char *px = extract_string_from_pxstring($4);
1220
- char *dbl_px = double_pixel(padding, px);
1221
+ float padding = mtex2MML_extract_number_from_pxstring($4);
1222
+ char *px = mtex2MML_extract_string_from_pxstring($4);
1223
+ char *dbl_px = mtex2MML_double_pixel(padding, px);
1221
1224
 
1222
1225
  char *s2 = mtex2MML_copy3(s1, "<mpadded width=\"+", dbl_px);
1223
1226
  char *s3 = mtex2MML_copy3(s2, "\" height=\"+", $4);
@@ -1242,9 +1245,9 @@ color: COLOR ATTRLIST compoundTermList {
1242
1245
  char *s1 = mtex2MML_copy3("<mstyle mathbackground=\"", $3, "\" style=\"");
1243
1246
  char *s2 = mtex2MML_copy3(s1, $4, "\">");
1244
1247
 
1245
- float padding = extract_number_from_pxstring($5);
1246
- char *px = extract_string_from_pxstring($5);
1247
- char *dbl_px = double_pixel(padding, px);
1248
+ float padding = mtex2MML_extract_number_from_pxstring($5);
1249
+ char *px = mtex2MML_extract_string_from_pxstring($5);
1250
+ char *dbl_px = mtex2MML_double_pixel(padding, px);
1248
1251
 
1249
1252
  char *s3 = mtex2MML_copy3(s2, "<mpadded width=\"+", dbl_px);
1250
1253
  char *s4 = mtex2MML_copy3(s3, "\" height=\"+", $5);
@@ -1534,7 +1537,7 @@ mathpunct: MATHPUNCT closedTerm {
1534
1537
  };
1535
1538
 
1536
1539
  enclose: ENCLOSE ST ENCLOSENOTATION ST ENCLOSETEXT ST {
1537
- char * notation = str_replace($3, ",", " ");
1540
+ char * notation = mtex2MML_str_replace($3, ",", " ");
1538
1541
  char * s1 = mtex2MML_copy3("<menclose notation=\"", notation, "\"><mi>");
1539
1542
  $$ = mtex2MML_copy3(s1, $5, "</mi></menclose>");
1540
1543
  mtex2MML_free_string(notation);
@@ -1543,11 +1546,11 @@ enclose: ENCLOSE ST ENCLOSENOTATION ST ENCLOSETEXT ST {
1543
1546
  mtex2MML_free_string($5);
1544
1547
  }
1545
1548
  | ENCLOSE ST ENCLOSENOTATION ST ENCLOSEATTR ST ENCLOSETEXT ST {
1546
- char * notation = str_replace($3, ",", " ");
1547
- char * attr = str_replace($5, ",", " ");
1549
+ char * notation = mtex2MML_str_replace($3, ",", " ");
1550
+ char * attr = mtex2MML_str_replace($5, ",", " ");
1548
1551
  if (strstr(attr, "arrow=1") != NULL) {
1549
1552
  mtex2MML_free_string(attr);
1550
- attr = str_replace($5, "arrow=1", "");
1553
+ attr = mtex2MML_str_replace($5, "arrow=1", "");
1551
1554
 
1552
1555
  char *t = mtex2MML_copy_string(notation);
1553
1556
  mtex2MML_free_string(notation);
@@ -1593,7 +1596,7 @@ mbox: MBOX closedTerm {
1593
1596
 
1594
1597
  bold: BOLD closedTerm {
1595
1598
  /* TODO: stupid hack to get bold mover working */
1596
- char * b = str_replace($2, "<mi>", "<mi mathvariant=\"bold\">");
1599
+ char * b = mtex2MML_str_replace($2, "<mi>", "<mi mathvariant=\"bold\">");
1597
1600
 
1598
1601
  $$ = mtex2MML_copy3("<mstyle mathvariant=\"bold\">", b, "</mstyle>");
1599
1602
  mtex2MML_free_string(b);
@@ -2323,117 +2326,117 @@ hat: HAT closedTerm {
2323
2326
  };
2324
2327
 
2325
2328
  skew: SKEW closedTerm ACUTE closedTerm {
2326
- char * em_skew = dbl2em($2);
2329
+ char * em_skew = mtex2MML_dbl2em($2);
2327
2330
 
2328
- $$ = implement_skew($4, em_skew, "&acute;");
2331
+ $$ = mtex2MML_implement_skew($4, em_skew, "&acute;");
2329
2332
 
2330
2333
  mtex2MML_free_string(em_skew);
2331
2334
  mtex2MML_free_string($2);
2332
2335
  mtex2MML_free_string($4);
2333
2336
  }
2334
2337
  | SKEW closedTerm BAR closedTerm {
2335
- char * em_skew = dbl2em($2);
2338
+ char * em_skew = mtex2MML_dbl2em($2);
2336
2339
 
2337
- $$ = implement_skew($4, em_skew, "&#x000AF;");
2340
+ $$ = mtex2MML_implement_skew($4, em_skew, "&#x000AF;");
2338
2341
 
2339
2342
  mtex2MML_free_string(em_skew);
2340
2343
  mtex2MML_free_string($2);
2341
2344
  mtex2MML_free_string($4);
2342
2345
  }
2343
2346
  | SKEW closedTerm BREVE closedTerm {
2344
- char * em_skew = dbl2em($2);
2347
+ char * em_skew = mtex2MML_dbl2em($2);
2345
2348
 
2346
- $$ = implement_skew($4, em_skew, "&#x2d8;");
2349
+ $$ = mtex2MML_implement_skew($4, em_skew, "&#x2d8;");
2347
2350
 
2348
2351
  mtex2MML_free_string(em_skew);
2349
2352
  mtex2MML_free_string($2);
2350
2353
  mtex2MML_free_string($4);
2351
2354
  }
2352
2355
  | SKEW closedTerm CHECK closedTerm {
2353
- char * em_skew = dbl2em($2);
2356
+ char * em_skew = mtex2MML_dbl2em($2);
2354
2357
 
2355
- $$ = implement_skew($4, em_skew, "&#x2c7;");
2358
+ $$ = mtex2MML_implement_skew($4, em_skew, "&#x2c7;");
2356
2359
 
2357
2360
  mtex2MML_free_string(em_skew);
2358
2361
  mtex2MML_free_string($2);
2359
2362
  mtex2MML_free_string($4);
2360
2363
  }
2361
2364
  | SKEW closedTerm DOT closedTerm {
2362
- char * em_skew = dbl2em($2);
2365
+ char * em_skew = mtex2MML_dbl2em($2);
2363
2366
 
2364
- $$ = implement_skew($4, em_skew, "&dot;");
2367
+ $$ = mtex2MML_implement_skew($4, em_skew, "&dot;");
2365
2368
 
2366
2369
  mtex2MML_free_string(em_skew);
2367
2370
  mtex2MML_free_string($2);
2368
2371
  mtex2MML_free_string($4);
2369
2372
  }
2370
2373
  | SKEW closedTerm DDOT closedTerm {
2371
- char * em_skew = dbl2em($2);
2374
+ char * em_skew = mtex2MML_dbl2em($2);
2372
2375
 
2373
- $$ = implement_skew($4, em_skew, "&Dot;");
2376
+ $$ = mtex2MML_implement_skew($4, em_skew, "&Dot;");
2374
2377
 
2375
2378
  mtex2MML_free_string(em_skew);
2376
2379
  mtex2MML_free_string($2);
2377
2380
  mtex2MML_free_string($4);
2378
2381
  }
2379
2382
  | SKEW closedTerm DDDOT closedTerm {
2380
- char * em_skew = dbl2em($2);
2383
+ char * em_skew = mtex2MML_dbl2em($2);
2381
2384
 
2382
- $$ = implement_skew($4, em_skew, "&tdot;");
2385
+ $$ = mtex2MML_implement_skew($4, em_skew, "&tdot;");
2383
2386
 
2384
2387
  mtex2MML_free_string(em_skew);
2385
2388
  mtex2MML_free_string($2);
2386
2389
  mtex2MML_free_string($4);
2387
2390
  }
2388
2391
  | SKEW closedTerm DDDDOT closedTerm {
2389
- char * em_skew = dbl2em($2);
2392
+ char * em_skew = mtex2MML_dbl2em($2);
2390
2393
 
2391
- $$ = implement_skew($4, em_skew, "&DotDot;");
2394
+ $$ = mtex2MML_implement_skew($4, em_skew, "&DotDot;");
2392
2395
 
2393
2396
  mtex2MML_free_string(em_skew);
2394
2397
  mtex2MML_free_string($2);
2395
2398
  mtex2MML_free_string($4);
2396
2399
  }
2397
2400
  | SKEW closedTerm GRAVE closedTerm {
2398
- char * em_skew = dbl2em($2);
2401
+ char * em_skew = mtex2MML_dbl2em($2);
2399
2402
 
2400
- $$ = implement_skew($4, em_skew, "&#x60;");
2403
+ $$ = mtex2MML_implement_skew($4, em_skew, "&#x60;");
2401
2404
 
2402
2405
  mtex2MML_free_string(em_skew);
2403
2406
  mtex2MML_free_string($2);
2404
2407
  mtex2MML_free_string($4);
2405
2408
  }
2406
2409
  | SKEW closedTerm HAT closedTerm {
2407
- char * em_skew = dbl2em($2);
2410
+ char * em_skew = mtex2MML_dbl2em($2);
2408
2411
 
2409
- $$ = implement_skew($4, em_skew, "&#x5E;");
2412
+ $$ = mtex2MML_implement_skew($4, em_skew, "&#x5E;");
2410
2413
 
2411
2414
  mtex2MML_free_string(em_skew);
2412
2415
  mtex2MML_free_string($2);
2413
2416
  mtex2MML_free_string($4);
2414
2417
  }
2415
2418
  | SKEW closedTerm TILDE closedTerm {
2416
- char * em_skew = dbl2em($2);
2419
+ char * em_skew = mtex2MML_dbl2em($2);
2417
2420
 
2418
- $$ = implement_skew($4, em_skew, "&tilde;");
2421
+ $$ = mtex2MML_implement_skew($4, em_skew, "&tilde;");
2419
2422
 
2420
2423
  mtex2MML_free_string(em_skew);
2421
2424
  mtex2MML_free_string($2);
2422
2425
  mtex2MML_free_string($4);
2423
2426
  }
2424
2427
  | SKEW closedTerm WIDEHAT closedTerm {
2425
- char * em_skew = dbl2em($2);
2428
+ char * em_skew = mtex2MML_dbl2em($2);
2426
2429
 
2427
- $$ = implement_skew($4, em_skew, "&#x5E;");
2430
+ $$ = mtex2MML_implement_skew($4, em_skew, "&#x5E;");
2428
2431
 
2429
2432
  mtex2MML_free_string(em_skew);
2430
2433
  mtex2MML_free_string($2);
2431
2434
  mtex2MML_free_string($4);
2432
2435
  }
2433
2436
  | SKEW closedTerm WIDETILDE closedTerm {
2434
- char * em_skew = dbl2em($2);
2437
+ char * em_skew = mtex2MML_dbl2em($2);
2435
2438
 
2436
- $$ = implement_skew($4, em_skew, "&#x5E;");
2439
+ $$ = mtex2MML_implement_skew($4, em_skew, "&#x5E;");
2437
2440
 
2438
2441
  mtex2MML_free_string(em_skew);
2439
2442
  mtex2MML_free_string($2);
@@ -2461,7 +2464,7 @@ mroot: SQRT OPTARGOPEN compoundTermList OPTARGCLOSE closedTerm {
2461
2464
  };
2462
2465
 
2463
2466
  leftroot: LEFTROOT ST NUMBER END closedTerm {
2464
- char * spacing = root_pos_to_em($3);
2467
+ char * spacing = mtex2MML_root_pos_to_em($3);
2465
2468
 
2466
2469
  char *s1 = mtex2MML_copy3("<mpadded width=\"", spacing, "\"><mrow>");
2467
2470
  $$ = mtex2MML_copy3(s1, $5, "</mrow></mpadded>");
@@ -2473,7 +2476,7 @@ leftroot: LEFTROOT ST NUMBER END closedTerm {
2473
2476
  };
2474
2477
 
2475
2478
  uproot: UPROOT ST NUMBER END closedTerm {
2476
- char * spacing = root_pos_to_em($3);
2479
+ char * spacing = mtex2MML_root_pos_to_em($3);
2477
2480
 
2478
2481
  char *s1 = mtex2MML_copy3("<mpadded height=\"", spacing, "\" voffset=\"");
2479
2482
  char *s2 = mtex2MML_copy3(s1, spacing, "\"><mrow>");
@@ -2617,7 +2620,7 @@ mathenv: BEGINENV EQUATION tableRowList ENDENV EQUATION {
2617
2620
  mtex2MML_free_string($3);
2618
2621
  }
2619
2622
  | BEGINENV MATRIX tableRowList ENDENV MATRIX {
2620
- char *row_data = combine_row_data(&environment_data_stack);
2623
+ char *row_data = mtex2MML_combine_row_data(&environment_data_stack);
2621
2624
 
2622
2625
  char * s1 = mtex2MML_copy3("<mrow><mtable displaystyle=\"false\" ", row_data, ">");
2623
2626
  if (encase == TOPENCLOSE) {
@@ -2633,7 +2636,7 @@ mathenv: BEGINENV EQUATION tableRowList ENDENV EQUATION {
2633
2636
  mtex2MML_free_string(row_data);
2634
2637
  }
2635
2638
  | BEGINENV GATHERED ARRAYALIGN END tableRowList ENDENV GATHERED {
2636
- char *row_data = combine_row_data(&environment_data_stack);
2639
+ char *row_data = mtex2MML_combine_row_data(&environment_data_stack);
2637
2640
 
2638
2641
  char * s1 = mtex2MML_copy3("<mrow><mtable displaystyle=\"true\" align=\"", $3, "\" ");
2639
2642
  char * s2 = mtex2MML_copy3(s1, row_data, ">");
@@ -2652,7 +2655,7 @@ mathenv: BEGINENV EQUATION tableRowList ENDENV EQUATION {
2652
2655
  mtex2MML_free_string(row_data);
2653
2656
  }
2654
2657
  | BEGINENV GATHERED tableRowList ENDENV GATHERED {
2655
- char *row_data = combine_row_data(&environment_data_stack);
2658
+ char *row_data = mtex2MML_combine_row_data(&environment_data_stack);
2656
2659
 
2657
2660
  char * s1 = mtex2MML_copy3("<mrow><mtable displaystyle=\"true\" ", row_data, ">");
2658
2661
  if (encase == TOPENCLOSE) {
@@ -2668,7 +2671,7 @@ mathenv: BEGINENV EQUATION tableRowList ENDENV EQUATION {
2668
2671
  mtex2MML_free_string(row_data);
2669
2672
  }
2670
2673
  | BEGINENV EQNARRAY tableRowList ENDENV EQNARRAY {
2671
- char *row_data = combine_row_data(&environment_data_stack);
2674
+ char *row_data = mtex2MML_combine_row_data(&environment_data_stack);
2672
2675
 
2673
2676
  char * s1 = mtex2MML_copy3("<mrow><mtable displaystyle=\"true\" columnalign=\"right center left\" columnspacing=\"thickmathspace\" ", row_data, ">");
2674
2677
 
@@ -2685,7 +2688,7 @@ mathenv: BEGINENV EQUATION tableRowList ENDENV EQUATION {
2685
2688
  mtex2MML_free_string(row_data);
2686
2689
  }
2687
2690
  | BEGINENV EQNARRAY_STAR tableRowList ENDENV EQNARRAY_STAR {
2688
- char *row_data = combine_row_data(&environment_data_stack);
2691
+ char *row_data = mtex2MML_combine_row_data(&environment_data_stack);
2689
2692
 
2690
2693
  char * s1 = mtex2MML_copy3("<mrow><mtable displaystyle=\"true\" columnalign=\"right center left\" columnspacing=\"thickmathspace\" ", row_data, ">");
2691
2694
  if (encase == TOPENCLOSE) {
@@ -2701,7 +2704,7 @@ mathenv: BEGINENV EQUATION tableRowList ENDENV EQUATION {
2701
2704
  mtex2MML_free_string(row_data);
2702
2705
  }
2703
2706
  | BEGINENV GATHER tableRowList ENDENV GATHER {
2704
- char *row_data = combine_row_data(&environment_data_stack);
2707
+ char *row_data = mtex2MML_combine_row_data(&environment_data_stack);
2705
2708
 
2706
2709
  char * s1 = mtex2MML_copy3("<mrow><mtable displaystyle=\"true\" ", row_data, ">");
2707
2710
 
@@ -2718,7 +2721,7 @@ mathenv: BEGINENV EQUATION tableRowList ENDENV EQUATION {
2718
2721
  mtex2MML_free_string(row_data);
2719
2722
  }
2720
2723
  | BEGINENV GATHER_STAR tableRowList ENDENV GATHER_STAR {
2721
- char *row_data = combine_row_data(&environment_data_stack);
2724
+ char *row_data = mtex2MML_combine_row_data(&environment_data_stack);
2722
2725
 
2723
2726
  char * s1 = mtex2MML_copy3("<mrow><mtable displaystyle=\"true\" ", row_data, ">");
2724
2727
  if (encase == TOPENCLOSE) {
@@ -2734,7 +2737,7 @@ mathenv: BEGINENV EQUATION tableRowList ENDENV EQUATION {
2734
2737
  mtex2MML_free_string(row_data);
2735
2738
  }
2736
2739
  | BEGINENV MULTLINE tableRowList ENDENV MULTLINE {
2737
- char *row_data = combine_row_data(&environment_data_stack);
2740
+ char *row_data = mtex2MML_combine_row_data(&environment_data_stack);
2738
2741
 
2739
2742
  char * s1 = mtex2MML_copy3("<mrow><mtable displaystyle=\"true\" ", row_data, ">");
2740
2743
 
@@ -2751,7 +2754,7 @@ mathenv: BEGINENV EQUATION tableRowList ENDENV EQUATION {
2751
2754
  mtex2MML_free_string(row_data);
2752
2755
  }
2753
2756
  | BEGINENV MULTLINE_STAR tableRowList ENDENV MULTLINE_STAR {
2754
- char *row_data = combine_row_data(&environment_data_stack);
2757
+ char *row_data = mtex2MML_combine_row_data(&environment_data_stack);
2755
2758
 
2756
2759
  char * s1 = mtex2MML_copy3("<mrow><mtable displaystyle=\"true\" columnwidth=\"100%\" width=\"85%\" ", row_data, ">");
2757
2760
  if (encase == TOPENCLOSE) {
@@ -2767,7 +2770,7 @@ mathenv: BEGINENV EQUATION tableRowList ENDENV EQUATION {
2767
2770
  mtex2MML_free_string(row_data);
2768
2771
  }
2769
2772
  | BEGINENV PMATRIX tableRowList ENDENV PMATRIX {
2770
- char *row_data = combine_row_data(&environment_data_stack);
2773
+ char *row_data = mtex2MML_combine_row_data(&environment_data_stack);
2771
2774
 
2772
2775
  char * s1 = mtex2MML_copy3("<mrow><mo>(</mo><mrow><mtable displaystyle=\"false\" ", row_data, ">");
2773
2776
 
@@ -2784,7 +2787,7 @@ mathenv: BEGINENV EQUATION tableRowList ENDENV EQUATION {
2784
2787
  mtex2MML_free_string(row_data);
2785
2788
  }
2786
2789
  | BEGINENV BMATRIX tableRowList ENDENV BMATRIX {
2787
- char *row_data = combine_row_data(&environment_data_stack);
2790
+ char *row_data = mtex2MML_combine_row_data(&environment_data_stack);
2788
2791
 
2789
2792
  char * s1 = mtex2MML_copy3("<mrow><mo>[</mo><mrow><mtable displaystyle=\"false\" ", row_data, ">");
2790
2793
 
@@ -2801,7 +2804,7 @@ mathenv: BEGINENV EQUATION tableRowList ENDENV EQUATION {
2801
2804
  mtex2MML_free_string(row_data);
2802
2805
  }
2803
2806
  | BEGINENV VMATRIX tableRowList ENDENV VMATRIX {
2804
- char *row_data = combine_row_data(&environment_data_stack);
2807
+ char *row_data = mtex2MML_combine_row_data(&environment_data_stack);
2805
2808
 
2806
2809
  char * s1 = mtex2MML_copy3("<mrow><mo>&VerticalBar;</mo><mrow><mtable displaystyle=\"false\" ", row_data, ">");
2807
2810
 
@@ -2818,7 +2821,7 @@ mathenv: BEGINENV EQUATION tableRowList ENDENV EQUATION {
2818
2821
  mtex2MML_free_string(row_data);
2819
2822
  }
2820
2823
  | BEGINENV BBMATRIX tableRowList ENDENV BBMATRIX {
2821
- char *row_data = combine_row_data(&environment_data_stack);
2824
+ char *row_data = mtex2MML_combine_row_data(&environment_data_stack);
2822
2825
 
2823
2826
  char * s1 = mtex2MML_copy3("<mrow><mo>{</mo><mrow><mtable displaystyle=\"false\" ", row_data, ">");
2824
2827
 
@@ -2835,7 +2838,7 @@ mathenv: BEGINENV EQUATION tableRowList ENDENV EQUATION {
2835
2838
  mtex2MML_free_string(row_data);
2836
2839
  }
2837
2840
  | BEGINENV VVMATRIX tableRowList ENDENV VVMATRIX {
2838
- char *row_data = combine_row_data(&environment_data_stack);
2841
+ char *row_data = mtex2MML_combine_row_data(&environment_data_stack);
2839
2842
 
2840
2843
  char * s1 = mtex2MML_copy3("<mrow><mo>&DoubleVerticalBar;</mo><mrow><mtable displaystyle=\"false\" ", row_data, ">");
2841
2844
 
@@ -2852,7 +2855,7 @@ mathenv: BEGINENV EQUATION tableRowList ENDENV EQUATION {
2852
2855
  mtex2MML_free_string(row_data);
2853
2856
  }
2854
2857
  | BEGINENV SMALLMATRIX tableRowList ENDENV SMALLMATRIX {
2855
- char *row_data = combine_row_data(&environment_data_stack);
2858
+ char *row_data = mtex2MML_combine_row_data(&environment_data_stack);
2856
2859
 
2857
2860
  char * s1 = mtex2MML_copy3("<mrow><mtable displaystyle=\"false\" columnspacing=\"0.333em\" ", row_data, ">");
2858
2861
  if (encase == TOPENCLOSE) {
@@ -2868,7 +2871,7 @@ mathenv: BEGINENV EQUATION tableRowList ENDENV EQUATION {
2868
2871
  mtex2MML_free_string(row_data);
2869
2872
  }
2870
2873
  | BEGINENV CASES tableRowList ENDENV CASES {
2871
- char *row_data = combine_row_data(&environment_data_stack);
2874
+ char *row_data = mtex2MML_combine_row_data(&environment_data_stack);
2872
2875
 
2873
2876
  char * s1 = mtex2MML_copy3("<mrow><mo>{</mo><mrow><mtable displaystyle=\"false\" columnalign=\"left left\" ", row_data, ">");
2874
2877
 
@@ -2885,7 +2888,7 @@ mathenv: BEGINENV EQUATION tableRowList ENDENV EQUATION {
2885
2888
  mtex2MML_free_string(row_data);
2886
2889
  }
2887
2890
  | BEGINENV ALIGNED ARRAYALIGN END tableRowList ENDENV ALIGNED {
2888
- char *row_data = combine_row_data(&environment_data_stack);
2891
+ char *row_data = mtex2MML_combine_row_data(&environment_data_stack);
2889
2892
 
2890
2893
  char * s1 = mtex2MML_copy3("<mrow><mtable displaystyle=\"true\" align=\"", $3, "\" columnspacing=\"0em 2em 0em 2em 0em 2em 0em 2em 0em 2em 0em\" columnalign=\"right left right left right left right left right left\" ");
2891
2894
  char * s2 = mtex2MML_copy3(s1, row_data, ">");
@@ -2905,7 +2908,7 @@ mathenv: BEGINENV EQUATION tableRowList ENDENV EQUATION {
2905
2908
  mtex2MML_free_string(row_data);
2906
2909
  }
2907
2910
  | BEGINENV ALIGNED tableRowList ENDENV ALIGNED {
2908
- char *row_data = combine_row_data(&environment_data_stack);
2911
+ char *row_data = mtex2MML_combine_row_data(&environment_data_stack);
2909
2912
 
2910
2913
  char * s1 = mtex2MML_copy3("<mrow><mtable displaystyle=\"true\" columnspacing=\"0em 2em 0em 2em 0em 2em 0em 2em 0em 2em 0em\" columnalign=\"right left right left right left right left right left\" ", row_data, ">");
2911
2914
 
@@ -2922,7 +2925,7 @@ mathenv: BEGINENV EQUATION tableRowList ENDENV EQUATION {
2922
2925
  mtex2MML_free_string(row_data);
2923
2926
  }
2924
2927
  | BEGINENV ALIGNENV tableRowList ENDENV ALIGNENV {
2925
- char *row_data = combine_row_data(&environment_data_stack);
2928
+ char *row_data = mtex2MML_combine_row_data(&environment_data_stack);
2926
2929
 
2927
2930
  char * s1 = mtex2MML_copy3("<mrow><mtable displaystyle=\"true\" columnspacing=\"0em 2em 0em 2em 0em 2em 0em 2em 0em 2em 0em\" columnalign=\"right left right left right left right left right left\" ", row_data, ">");
2928
2931
 
@@ -2939,7 +2942,7 @@ mathenv: BEGINENV EQUATION tableRowList ENDENV EQUATION {
2939
2942
  mtex2MML_free_string(row_data);
2940
2943
  }
2941
2944
  | BEGINENV ALIGNENV_STAR tableRowList ENDENV ALIGNENV_STAR {
2942
- char *row_data = combine_row_data(&environment_data_stack);
2945
+ char *row_data = mtex2MML_combine_row_data(&environment_data_stack);
2943
2946
 
2944
2947
  char * s1 = mtex2MML_copy3("<mrow><mtable displaystyle=\"true\" columnspacing=\"0em 2em 0em 2em 0em 2em 0em 2em 0em 2em 0em\" columnalign=\"right left right left right left right left right left\" ", row_data, ">");
2945
2948
 
@@ -2956,7 +2959,7 @@ mathenv: BEGINENV EQUATION tableRowList ENDENV EQUATION {
2956
2959
  mtex2MML_free_string(row_data);
2957
2960
  }
2958
2961
  | BEGINENV ALIGNAT ALIGNATVALUE END tableRowList ENDENV ALIGNAT {
2959
- char *row_data = combine_row_data(&environment_data_stack);
2962
+ char *row_data = mtex2MML_combine_row_data(&environment_data_stack);
2960
2963
 
2961
2964
  char * s1 = mtex2MML_copy3("<mrow><mtable displaystyle=\"true\" columnalign=\"right left right left right left right left right left\" columnspacing=\"0em\" ", row_data, ">");
2962
2965
 
@@ -2974,7 +2977,7 @@ mathenv: BEGINENV EQUATION tableRowList ENDENV EQUATION {
2974
2977
  mtex2MML_free_string(row_data);
2975
2978
  }
2976
2979
  | BEGINENV ALIGNAT_STAR ALIGNATVALUE END tableRowList ENDENV ALIGNAT_STAR {
2977
- char *row_data = combine_row_data(&environment_data_stack);
2980
+ char *row_data = mtex2MML_combine_row_data(&environment_data_stack);
2978
2981
 
2979
2982
  char * s1 = mtex2MML_copy3("<mrow><mtable displaystyle=\"true\" columnalign=\"right left right left right left right left right left\" columnspacing=\"0em\" ", row_data, ">");
2980
2983
 
@@ -2992,7 +2995,7 @@ mathenv: BEGINENV EQUATION tableRowList ENDENV EQUATION {
2992
2995
  mtex2MML_free_string(row_data);
2993
2996
  }
2994
2997
  | BEGINENV ALIGNEDAT ALIGNATVALUE END tableRowList ENDENV ALIGNEDAT {
2995
- char *row_data = combine_row_data(&environment_data_stack);
2998
+ char *row_data = mtex2MML_combine_row_data(&environment_data_stack);
2996
2999
 
2997
3000
  char * s1 = mtex2MML_copy3("<mrow><mtable displaystyle=\"true\" columnalign=\"right left right left right left right left right left\" columnspacing=\"0em\" ", row_data, ">");
2998
3001
 
@@ -3010,9 +3013,9 @@ mathenv: BEGINENV EQUATION tableRowList ENDENV EQUATION {
3010
3013
  mtex2MML_free_string(row_data);
3011
3014
  }
3012
3015
  | BEGINENV ARRAY ARRAYALIGN ST columnAlignList END tableRowList ENDENV ARRAY {
3013
- const char *pipe_chars = vertical_pipe_extract($5);
3014
- const char *column_align = remove_excess_pipe_chars($5);
3015
- char *row_data = combine_row_data(&environment_data_stack);
3016
+ char *pipe_chars = mtex2MML_vertical_pipe_extract($5);
3017
+ char *column_align = mtex2MML_remove_excess_pipe_chars($5);
3018
+ char *row_data = mtex2MML_combine_row_data(&environment_data_stack);
3016
3019
 
3017
3020
  char * s1 = mtex2MML_copy3("<mtable displaystyle=\"false\" align=\"", $3, "\" ");
3018
3021
  char * s2 = mtex2MML_copy3(s1, row_data, " columnalign=\"");
@@ -3039,9 +3042,9 @@ mathenv: BEGINENV EQUATION tableRowList ENDENV EQUATION {
3039
3042
  mtex2MML_free_string(row_data);
3040
3043
  }
3041
3044
  | BEGINENV ARRAY ST columnAlignList END tableRowList ENDENV ARRAY {
3042
- char *pipe_chars = vertical_pipe_extract($4);
3043
- char *column_align = remove_excess_pipe_chars($4);
3044
- char *row_data = combine_row_data(&environment_data_stack);
3045
+ char *pipe_chars = mtex2MML_vertical_pipe_extract($4);
3046
+ char *column_align = mtex2MML_remove_excess_pipe_chars($4);
3047
+ char *row_data = mtex2MML_combine_row_data(&environment_data_stack);
3045
3048
 
3046
3049
  char * s1 = mtex2MML_copy3("<mtable displaystyle=\"false\" ", row_data, " columnalign=\"");
3047
3050
  char * s2 = mtex2MML_copy3(s1, column_align, "\" ");
@@ -3065,8 +3068,8 @@ mathenv: BEGINENV EQUATION tableRowList ENDENV EQUATION {
3065
3068
  mtex2MML_free_string(row_data);
3066
3069
  }
3067
3070
  | BEGINENV SUBARRAY ST columnAlignList END tableRowList ENDENV SUBARRAY {
3068
- char *pipe_chars = vertical_pipe_extract($4);
3069
- char *column_align = remove_excess_pipe_chars($4);
3071
+ char *pipe_chars = mtex2MML_vertical_pipe_extract($4);
3072
+ char *column_align = mtex2MML_remove_excess_pipe_chars($4);
3070
3073
 
3071
3074
  char * s1 = mtex2MML_copy3("<mtable displaystyle=\"false\" columnspacing=\"0em 0em 0em 0em\" rowspacing=\"0.1em\" columnalign=\"", column_align, "\" ");
3072
3075
  char * s2 = mtex2MML_copy3(s1, pipe_chars, "\">");
@@ -3270,7 +3273,7 @@ tableRowList: tableRow {
3270
3273
  };
3271
3274
 
3272
3275
  tableRow: simpleTableRow {
3273
- int has_eqn_number = fetch_eqn_number(&environment_data_stack);
3276
+ int has_eqn_number = mtex2MML_fetch_eqn_number(&environment_data_stack);
3274
3277
 
3275
3278
  if (has_eqn_number && strcmp($1, "<mtd/>") != 0) {
3276
3279
  char * n = mtex2MML_global_label();
@@ -3333,11 +3336,11 @@ tableCell: {
3333
3336
  $$ = mtex2MML_copy_string("<mtd/>");
3334
3337
  }
3335
3338
  | compoundTermList {
3336
- if (current_env_type(&environment_data_stack) != ENV_MULTLINE && current_env_type(&environment_data_stack) != ENV_MULTLINESTAR) {
3339
+ if (mtex2MML_current_env_type(&environment_data_stack) != ENV_MULTLINE && mtex2MML_current_env_type(&environment_data_stack) != ENV_MULTLINESTAR) {
3337
3340
  $$ = mtex2MML_copy3("<mtd>", $1, "</mtd>");
3338
3341
  }
3339
3342
  else {
3340
- int total_lines = current_env_line_count(&environment_data_stack);
3343
+ int total_lines = mtex2MML_current_env_line_count(&environment_data_stack);
3341
3344
  if (line_counter == 1) {
3342
3345
  $$ = mtex2MML_copy3("<mtd columnalign=\"left\">", $1, "</mtd>");
3343
3346
  line_counter++;
@@ -3400,7 +3403,7 @@ colspan: COLSPAN ATTRLIST {
3400
3403
 
3401
3404
  %%
3402
3405
 
3403
- // see http://git.io/vk8Sz
3406
+ /* see http://git.io/vk8Sz */
3404
3407
  void envdata_copy(void *_dst, const void *_src)
3405
3408
  {
3406
3409
  envdata_t *dst = (envdata_t*)_dst, *src = (envdata_t*)_src;
@@ -3422,16 +3425,22 @@ void envdata_dtor(void *_elt)
3422
3425
 
3423
3426
  UT_icd envdata_icd = {sizeof(envdata_t), NULL, envdata_copy, envdata_dtor};
3424
3427
 
3425
- const char *format_additions(const char *buffer)
3428
+ void format_additions(const char *buffer, const int options)
3426
3429
  {
3427
3430
  utarray_new(environment_data_stack, &envdata_icd);
3428
3431
 
3429
3432
  if (colors == NULL)
3430
- create_css_colors(&colors);
3433
+ mtex2MML_create_css_colors(&colors);
3434
+
3435
+ if (options)
3436
+ delimiter_options = options;
3437
+ else
3438
+ delimiter_options = MTEX2MML_DELIMITER_DEFAULT;
3431
3439
 
3432
- encase = NONE;
3440
+ encaseType *encase_pointer = (encaseType *)NONE;
3433
3441
  line_counter = 1;
3434
- env_replacements(&environment_data_stack, &encase, buffer);
3442
+ mtex2MML_env_replacements(&environment_data_stack, &encase_pointer, buffer);
3443
+ encase = (encaseType) encase_pointer;
3435
3444
  }
3436
3445
 
3437
3446
  void free_additions()
@@ -3446,19 +3455,20 @@ void free_additions()
3446
3455
  }
3447
3456
  }
3448
3457
 
3449
- char * mtex2MML_global_parse (const char * buffer, unsigned long length, int global_start)
3458
+ char * mtex2MML_global_parse (const char * buffer, unsigned long length, const int options, const int global_start)
3450
3459
  {
3451
3460
  global_label = global_start;
3452
- return mtex2MML_parse(buffer, length);
3461
+ return mtex2MML_parse(buffer, length, options);
3453
3462
  }
3454
3463
 
3455
- char * mtex2MML_parse (const char * buffer, unsigned long length)
3464
+ char * mtex2MML_parse (const char * buffer, unsigned long length, const int options)
3456
3465
  {
3457
3466
  char * mathml = 0;
3458
3467
 
3459
3468
  int result;
3460
3469
 
3461
- format_additions(buffer);
3470
+ format_additions(buffer, options);
3471
+
3462
3472
  mtex2MML_setup (buffer, length);
3463
3473
  mtex2MML_restart ();
3464
3474
 
@@ -3479,49 +3489,48 @@ char * mtex2MML_parse (const char * buffer, unsigned long length)
3479
3489
  return mathml;
3480
3490
  }
3481
3491
 
3482
- int mtex2MML_filter (const char * buffer, unsigned long length)
3492
+ int mtex2MML_filter (const char * buffer, unsigned long length, const int options)
3483
3493
  {
3484
- global_label = 1;
3485
- format_additions(buffer);
3486
- mtex2MML_setup (buffer, length);
3487
- mtex2MML_restart ();
3488
-
3489
- int result = mtex2MML_yyparse (0);
3490
- free_additions();
3494
+ return mtex2MML_do_filter (buffer, length, 0, 0, options);
3495
+ }
3491
3496
 
3492
- return result;
3497
+ int mtex2MML_text_filter (const char * buffer, unsigned long length, const int options)
3498
+ {
3499
+ return mtex2MML_do_filter (buffer, length, 0, 1, options);
3493
3500
  }
3494
3501
 
3495
- #define MTEX_DELIMITER_DOLLAR 0
3496
- #define MTEX_DELIMITER_DOUBLE 1
3497
- #define MTEX_DELIMITER_SQUARE 2
3502
+ int mtex2MML_strict_filter (const char * buffer, unsigned long length, const int options)
3503
+ {
3504
+ return mtex2MML_do_filter (buffer, length, 1, 1, options);
3505
+ }
3498
3506
 
3499
3507
  static char * mtex2MML_last_error = 0;
3500
3508
 
3501
3509
  static void mtex2MML_keep_error (const char * msg)
3502
3510
  {
3503
- if (mtex2MML_last_error)
3504
- {
3505
- mtex2MML_free_string (mtex2MML_last_error);
3506
- mtex2MML_last_error = 0;
3507
- }
3511
+ if (mtex2MML_last_error) {
3512
+ mtex2MML_free_string (mtex2MML_last_error);
3513
+ mtex2MML_last_error = 0;
3514
+ }
3508
3515
  mtex2MML_last_error = mtex2MML_copy_escaped (msg);
3509
3516
  }
3510
3517
 
3511
- int mtex2MML_html_filter (const char * buffer, unsigned long length)
3518
+ int mtex2MML_delimiter_type(const int type)
3512
3519
  {
3513
- mtex2MML_do_html_filter (buffer, length, 0);
3520
+ if (delimiter_options == MTEX2MML_DELIMITER_DEFAULT) {
3521
+ return type & (MTEX2MML_DELIMITER_DOLLAR | MTEX2MML_DELIMITER_DOUBLE);
3522
+ } else {
3523
+ return delimiter_options & type;
3524
+ }
3514
3525
  }
3515
3526
 
3516
- int mtex2MML_strict_html_filter (const char * buffer, unsigned long length)
3527
+ int mtex2MML_do_filter (const char * buffer, unsigned long length, const int forbid_markup, const int write, const int options)
3517
3528
  {
3518
- mtex2MML_do_html_filter (buffer, length, 1);
3519
- }
3529
+ global_label = 1;
3520
3530
 
3521
- int mtex2MML_do_html_filter (const char * buffer, unsigned long length, const int forbid_markup)
3522
- {
3523
- int result = 0;
3531
+ format_additions(buffer, options);
3524
3532
 
3533
+ int result = 0;
3525
3534
  int type = 0;
3526
3535
  int skip = 0;
3527
3536
  int match = 0;
@@ -3537,189 +3546,185 @@ int mtex2MML_do_html_filter (const char * buffer, unsigned long length, const in
3537
3546
 
3538
3547
  mtex2MML_error = mtex2MML_keep_error;
3539
3548
 
3540
- _until_math:
3549
+ _until_math:
3541
3550
  ptr2 = ptr1;
3542
3551
 
3543
- while (ptr2 < end)
3544
- {
3545
- if (*ptr2 == '$') break;
3546
- if ((*ptr2 == '\\') && (ptr2 + 1 < end))
3547
- {
3548
- if (*(ptr2+1) == '[') break;
3549
- }
3550
- ++ptr2;
3552
+ /* Search for the first math part */
3553
+ while (ptr2 < end) {
3554
+ if (*ptr2 == '$' && (mtex2MML_delimiter_type(MTEX2MML_DELIMITER_DOLLAR) || mtex2MML_delimiter_type(MTEX2MML_DELIMITER_DOUBLE))) { break; }
3555
+ if ((*ptr2 == '\\') && (ptr2 + 1 < end)) {
3556
+ if (*(ptr2+1) == '[' && mtex2MML_delimiter_type(MTEX2MML_DELIMITER_BRACKETS)) { break; }
3557
+ if (*(ptr2+1) == '(' && mtex2MML_delimiter_type(MTEX2MML_DELIMITER_PARENS)) { break; }
3558
+ if (*(ptr2+1) == '$' && mtex2MML_delimiter_type(MTEX2MML_DELIMITER_DOLLAR)) { ptr2++; }
3551
3559
  }
3552
- if (mtex2MML_write && ptr2 > ptr1)
3560
+ ++ptr2;
3561
+ }
3562
+ if (mtex2MML_write && ptr2 > ptr1 && write) {
3553
3563
  (*mtex2MML_write) (ptr1, ptr2 - ptr1);
3564
+ }
3554
3565
 
3555
- if (ptr2 == end) goto _finish;
3566
+ if (ptr2 == end) { goto _finish; }
3556
3567
 
3557
- _until_html:
3568
+ /*_until_html:*/
3558
3569
  ptr1 = ptr2;
3559
3570
 
3560
- if (ptr2 + 1 < end)
3561
- {
3562
- if ((*ptr2 == '\\') && (*(ptr2+1) == '['))
3563
- {
3564
- type = MTEX_DELIMITER_SQUARE;
3565
- ptr2 += 2;
3566
- }
3567
- else if ((*ptr2 == '$') && (*(ptr2+1) == '$'))
3568
- {
3569
- type = MTEX_DELIMITER_DOUBLE;
3570
- ptr2 += 2;
3571
- }
3572
- else
3573
- {
3574
- type = MTEX_DELIMITER_DOLLAR;
3575
- ptr2 += 2;
3576
- }
3571
+ if (ptr2 + 1 < end) {
3572
+ if ((*ptr2 == '\\') && (*(ptr2+1) == '[' && *(ptr2 - 1) != '\\') && mtex2MML_delimiter_type(MTEX2MML_DELIMITER_BRACKETS)) {
3573
+ type = MTEX2MML_DELIMITER_BRACKETS;
3574
+ ptr2 += 2;
3575
+ } else if ((*ptr2 == '$') && (*(ptr2+1) == '$') && mtex2MML_delimiter_type(MTEX2MML_DELIMITER_DOUBLE)) {
3576
+ type = MTEX2MML_DELIMITER_DOUBLE;
3577
+ ptr2 += 2;
3578
+ } else if ((*ptr2 == '\\') && (*(ptr2+1) == '(' && *(ptr2 - 1) != '\\') && mtex2MML_delimiter_type(MTEX2MML_DELIMITER_PARENS)) {
3579
+ type = MTEX2MML_DELIMITER_PARENS;
3580
+ ptr2 += 2;
3581
+ } else if ((*ptr2 == '$') && !isspace(*(ptr2+1)) && mtex2MML_delimiter_type(MTEX2MML_DELIMITER_DOLLAR)) {
3582
+ type = MTEX2MML_DELIMITER_DOLLAR;
3583
+ ptr2++;
3577
3584
  }
3578
- else goto _finish;
3585
+ } else { goto _finish; }
3579
3586
 
3580
3587
  skip = 0;
3581
3588
  match = 0;
3582
3589
 
3583
- while (ptr2 < end)
3584
- {
3585
- switch (*ptr2)
3586
- {
3587
- case '<':
3588
- case '>':
3589
- if (forbid_markup == 1) skip = 1;
3590
- break;
3590
+ while (ptr2 < end) {
3591
+ switch (*ptr2) {
3592
+ case '<':
3593
+ case '>':
3594
+ if (forbid_markup == 1) { skip = 1; }
3595
+ break;
3591
3596
 
3592
- case '\\':
3593
- if (ptr2 + 1 < end)
3594
- {
3595
- if (*(ptr2 + 1) == '[')
3596
- {
3597
- skip = 1;
3598
- }
3599
- else if (*(ptr2 + 1) == ']')
3600
- {
3601
- if (type == MTEX_DELIMITER_SQUARE)
3602
- {
3603
- ptr2 += 2;
3604
- match = 1;
3605
- }
3606
- else
3607
- {
3597
+ case '\\':
3598
+ if (ptr2 + 1 < end) {
3599
+ if (*(ptr2 + 1) == '[' && type == MTEX2MML_DELIMITER_BRACKETS) {
3608
3600
  skip = 1;
3601
+ } else if (*(ptr2 + 1) == ']') {
3602
+ if (type == MTEX2MML_DELIMITER_BRACKETS) {
3603
+ ptr2 += 2;
3604
+ match = 1;
3605
+ } else {
3606
+ skip = 1;
3607
+ }
3608
+ } else if (*(ptr2 + 1) == '(' && type == MTEX2MML_DELIMITER_PARENS) {
3609
+ skip = 1;
3610
+ } else if (*(ptr2 + 1) == ')') {
3611
+ if (type == MTEX2MML_DELIMITER_PARENS) {
3612
+ ptr2 += 2;
3613
+ match = 1;
3614
+ } else {
3615
+ skip = 1;
3616
+ }
3617
+ } else {
3618
+ ptr2++;
3609
3619
  }
3610
- }
3611
3620
  }
3612
- break;
3621
+ break;
3613
3622
 
3614
- case '$':
3615
- if (type == MTEX_DELIMITER_SQUARE)
3616
- {
3623
+ case '\n':
3624
+ /* we hit a newline in an unclosed inline equation -- skip this string */
3625
+ if (type == MTEX2MML_DELIMITER_DOLLAR || type == MTEX2MML_DELIMITER_PARENS) {
3617
3626
  skip = 1;
3618
3627
  }
3619
- else if (ptr2 + 1 < end)
3620
- {
3621
- if (*(ptr2 + 1) == '$')
3622
- {
3623
- if (type == MTEX_DELIMITER_DOLLAR)
3624
- {
3625
- ptr2++;
3626
- match = 1;
3627
- }
3628
- else
3629
- {
3630
- ptr2 += 2;
3631
- match = 1;
3628
+ break;
3629
+
3630
+ case '$':
3631
+ if (type == MTEX2MML_DELIMITER_BRACKETS || type == MTEX2MML_DELIMITER_PARENS) {
3632
+ // no op
3633
+ } else if (ptr2 + 1 < end) {
3634
+ if (*(ptr2 + 1) == '$') {
3635
+ if (type == MTEX2MML_DELIMITER_DOLLAR) {
3636
+ ptr2++;
3637
+ match = 1;
3638
+ } else {
3639
+ ptr2 += 2;
3640
+ match = 1;
3641
+ }
3642
+ } else {
3643
+ if (type == MTEX2MML_DELIMITER_DOLLAR) {
3644
+ if (isspace(*(ptr2 - 1))) {
3645
+ skip = 1;
3646
+ } else if (isdigit(*(ptr2 + 1))) {
3647
+ if (write) {
3648
+ (*mtex2MML_write) (ptr1, ptr2 - ptr1 + 2);
3649
+ }
3650
+ skip = 1;
3651
+ ptr2 += 2;
3652
+ ptr1 = ptr2;
3653
+ } else {
3654
+ ptr2++;
3655
+ match = 1;
3656
+ }
3657
+ } else {
3658
+ if (*(ptr2 - 1) != '\\') {
3659
+ skip = 1;
3660
+ }
3661
+ }
3632
3662
  }
3633
- }
3634
- else
3635
- {
3636
- if (type == MTEX_DELIMITER_DOLLAR)
3637
- {
3663
+ } else {
3664
+ if (type == MTEX2MML_DELIMITER_DOLLAR) {
3638
3665
  ptr2++;
3639
3666
  match = 1;
3640
- }
3641
- else
3642
- {
3667
+ } else {
3643
3668
  skip = 1;
3644
3669
  }
3645
- }
3646
- }
3647
- else
3648
- {
3649
- if (type == MTEX_DELIMITER_DOLLAR)
3650
- {
3651
- ptr2++;
3652
- match = 1;
3653
- }
3654
- else
3655
- {
3656
- skip = 1;
3657
- }
3658
3670
  }
3659
- break;
3660
-
3661
- default:
3662
- break;
3663
- }
3664
- if (skip || match) break;
3671
+ break;
3665
3672
 
3666
- ++ptr2;
3667
- }
3668
- if (skip)
3669
- {
3670
- if (type == MTEX_DELIMITER_DOLLAR)
3671
- {
3672
- if (mtex2MML_write)
3673
- (*mtex2MML_write) (ptr1, 1);
3674
- ptr1++;
3675
- }
3676
- else
3677
- {
3678
- if (mtex2MML_write)
3679
- (*mtex2MML_write) (ptr1, 2);
3680
- ptr1 += 2;
3681
- }
3682
- goto _until_math;
3673
+ default:
3674
+ break;
3683
3675
  }
3684
- if (match)
3685
- {
3686
- mathml = mtex2MML_parse (ptr1, ptr2 - ptr1);
3676
+ if (skip || match) { break; }
3687
3677
 
3688
- if (mathml)
3689
- {
3690
- if (mtex2MML_write_mathml)
3691
- (*mtex2MML_write_mathml) (mathml);
3692
- mtex2MML_free_string (mathml);
3693
- mathml = 0;
3678
+ ++ptr2;
3694
3679
  }
3695
- else
3696
- {
3697
- ++result;
3698
- if (mtex2MML_write)
3699
- {
3700
- if (type == MTEX_DELIMITER_DOLLAR)
3701
- (*mtex2MML_write) ("<math xmlns='http://www.w3.org/1998/Math/MathML' display='inline'><merror><mtext>", 0);
3702
- else
3703
- (*mtex2MML_write) ("<math xmlns='http://www.w3.org/1998/Math/MathML' display='block'><merror><mtext>", 0);
3704
-
3705
- (*mtex2MML_write) (mtex2MML_last_error, 0);
3706
- (*mtex2MML_write) ("</mtext></merror></math>", 0);
3680
+ if (skip) {
3681
+ if (type == MTEX2MML_DELIMITER_DOLLAR) {
3682
+ if (mtex2MML_write && write) {
3683
+ (*mtex2MML_write) (ptr1, 1);
3707
3684
  }
3685
+ ptr1++;
3686
+ } else {
3687
+ if (mtex2MML_write && write) {
3688
+ (*mtex2MML_write) (ptr1, 2);
3689
+ }
3690
+ ptr1 += 2;
3691
+ }
3692
+ goto _until_math;
3708
3693
  }
3709
- ptr1 = ptr2;
3694
+ if (match) {
3695
+ mtex2MML_setup (ptr1, ptr2 - ptr1);
3696
+ mtex2MML_restart ();
3710
3697
 
3711
- goto _until_math;
3698
+ mtex2MML_yyparse (&mathml);
3699
+
3700
+ if (mathml) {
3701
+ if (mtex2MML_write_mathml) {
3702
+ (*mtex2MML_write_mathml) (mathml);
3703
+ }
3704
+ mtex2MML_free_string (mathml);
3705
+ mathml = 0;
3706
+ } else {
3707
+ ++result;
3708
+ if (mtex2MML_write && write) {
3709
+ /* A problematic error? Just leave the text alone. */
3710
+ (*mtex2MML_write) (ptr1, ptr2 - ptr1);
3711
+ }
3712
3712
  }
3713
- if (mtex2MML_write)
3713
+ ptr1 = ptr2;
3714
+
3715
+ goto _until_math;
3716
+ }
3717
+ if (mtex2MML_write) {
3714
3718
  (*mtex2MML_write) (ptr1, ptr2 - ptr1);
3719
+ }
3715
3720
 
3716
- _finish:
3717
- if (mtex2MML_last_error)
3718
- {
3719
- mtex2MML_free_string (mtex2MML_last_error);
3720
- mtex2MML_last_error = 0;
3721
- }
3721
+ _finish:
3722
+ if (mtex2MML_last_error) {
3723
+ mtex2MML_free_string (mtex2MML_last_error);
3724
+ mtex2MML_last_error = 0;
3725
+ }
3722
3726
  mtex2MML_error = save_error_fn;
3723
3727
 
3728
+ free_additions();
3724
3729
  return result;
3725
3730
  }