mathematical 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,281 +1,229 @@
1
1
  #include <stdio.h>
2
2
  #include <stdlib.h>
3
3
  #include <string.h>
4
+
4
5
  #include "parse_extras.h"
5
6
  #include "string_extras.h"
6
- #include "stack.h"
7
-
8
- #ifdef FLIP_OFFSET_VAL
9
- #define OFFSET_VAL 0
10
- #else
11
- #define OFFSET_VAL 1
12
- #endif
13
-
14
- void initSymbolDataArray(symbolDataArray *a, size_t initialSize)
15
- {
16
- // Allocate initial space
17
- a->array = (symbolData *)malloc(initialSize * sizeof(symbolData));
18
-
19
- a->used = 0; // no elements used
20
- a->size = initialSize; // available number of elements
21
-
22
- // Initialize all elements of the array at once: they are contiguous
23
- memset(&a->array[0], 0, sizeof(symbolData) * initialSize);
24
- }
25
7
 
26
- void insertSymbolDataArray(symbolDataArray *a, symbolData element)
8
+ void env_replacements(UT_array **environment_data_stack, const char *environment)
27
9
  {
28
- if (a->used == a->size) {
29
- a->size *= 2;
30
- a->array = (symbolData *)realloc(a->array, a->size * sizeof(symbolData));
31
- // Initialize the last/new elements of the reallocated array
32
- memset(&a->array[a->used],0, sizeof(symbolData) * (a->size - a->used));
33
- }
34
-
35
- a->array[a->used].attribute = (char*)malloc(strlen(element.attribute) + 1);
36
- strcpy(a->array[a->used].attribute, element.attribute);
37
-
38
- a->array[a->used].offset_pos = element.offset_pos;
39
-
40
- a->used++;
41
- }
42
-
43
- void sortSymbolDataArray(symbolDataArray *a) {
44
- int i, j, n = a->used;
45
-
46
- for(i = 1; i < n; i++) {
47
- for(j = 0; j < n - i; j++) {
48
- if(a->array[j].offset_pos < a->array[j+1].offset_pos) {
49
- symbolData temp = a->array[j];
50
- a->array[j] = a->array[j+1];
51
- a->array[j+1] = temp;
52
- }
53
- }
54
- }
55
- }
56
-
57
- void deleteSymbolDataArray(symbolDataArray *a)
58
- {
59
- int i;
60
-
61
- // Free all name variables of each array element first
62
- for(i = 0; i <a->used; i++)
63
- {
64
- free(a->array[i].attribute);
65
- a->array[i].attribute = NULL;
66
- }
67
-
68
- // Now free the array
69
- free(a->array);
70
- a->array = NULL;
71
-
72
- a->used = 0;
73
- a->size = 0;
74
- }
75
-
76
- char * env_replacements(const char *string) {
77
- stackT array_stack;
78
- stackElementT stack_item, last_stack_item;
10
+ UT_array *array_stack;
11
+ UT_array *row_spacing_stack;
12
+ UT_array *rowlines_stack;
79
13
 
80
14
  char *tok = NULL, *at_top = NULL;
81
- char *new_environment = dupe_string(string), *dupe_str = dupe_string(string);
82
- char *line = strtok(dupe_str, "\n");
83
- char *attr_rowlines = "", *attr_rowspacing = "", *em_str, *temp = "";
84
15
 
16
+ char *temp = "", **last_stack_item;
17
+ char *a, *em_str;
85
18
  const char *from = "\\begin", *until = "\\end", *hline = "\\hline", *hdashline = "\\hdashline",
86
- *line_separator = "\\\\",
87
- *em_pattern_begin = "\\[", *em_pattern_end = "]";
19
+ *line_separator = "\\\\",
20
+ *em_pattern_begin = "\\[", *em_pattern_end = "]",
21
+ *is_smallmatrix = NULL, *is_gathered = NULL;
88
22
 
89
- int start = 0, offset = 0, attr_rowlines_len = 0, str_len = 0, i = 0;
90
- symbolDataArray hline_data_array;
91
- symbolData hline_data;
92
-
93
- symbolDataArray row_spacing_data_array;
94
- symbolData row_spacing_data;
95
-
96
- // set up the array stack
97
- StackInit(&array_stack, strlen(new_environment));
98
- initSymbolDataArray(&hline_data_array, 5);
99
- initSymbolDataArray(&row_spacing_data_array, 1);
23
+ int rowlines_stack_len = 0, em_offset = 0;
100
24
 
101
25
  // if not an environment, don't bother going on
102
- if ((strstr(string, from) == NULL && strstr(string, until) == NULL)) {
103
- StackDestroy(&array_stack);
104
- deleteSymbolDataArray(&hline_data_array);
105
- deleteSymbolDataArray(&row_spacing_data_array);
106
- free(dupe_str);
107
-
108
- return string;
26
+ if ( ((strstr(environment, from) == NULL && strstr(environment, until) == NULL)) || strstr(environment, "begin{svg}")) {
27
+ return;
109
28
  }
110
29
 
111
- while (line != NULL) {
112
- str_len = strlen(line) + 1;
113
-
114
- stack_item.line = line;
115
- stack_item.line_pos = start + 1;
30
+ char *dupe_environment = dupe_string(environment);
31
+ char *line = strtok(dupe_environment, "\n");
116
32
 
117
- start += str_len;
33
+ // set up the array stack
34
+ utarray_new(array_stack, &ut_str_icd);
35
+ utarray_new(row_spacing_stack, &ut_str_icd);
36
+ utarray_new(rowlines_stack, &ut_str_icd);
118
37
 
119
- StackPush(&array_stack, stack_item);
38
+ while (line != NULL) {
39
+ utarray_push_back(array_stack, &line);
120
40
 
121
41
  if (strstr(line, until) != NULL) {
122
- while (!StackIsEmpty(&array_stack)) {
123
- last_stack_item = StackPop(&array_stack);
124
- attr_rowlines_len = strlen(attr_rowlines);
125
- at_top = strstr(last_stack_item.line, from);
42
+ while (utarray_len(array_stack) > 0) {
43
+ last_stack_item = (char **)utarray_back(array_stack);
44
+
45
+ rowlines_stack_len = utarray_len(rowlines_stack);
46
+ at_top = strstr(*last_stack_item, from);
126
47
 
127
48
  // we've reached the top, but there looks like there might be some data
128
- if (at_top != NULL && strstr(last_stack_item.line, line_separator) == NULL) {
49
+ if (at_top != NULL && strstr(*last_stack_item, line_separator) == NULL) {
129
50
  break;
130
51
  }
131
52
 
132
- // looking for a line match
133
- if (strstr(last_stack_item.line, hline) != NULL) {
134
- if (attr_rowlines_len > 0)
135
- remove_last_char(attr_rowlines);
136
- attr_rowlines = join(attr_rowlines, "s");
137
- }
138
- else if (strstr(last_stack_item.line, hdashline) != NULL) {
139
- if (attr_rowlines_len > 0)
140
- remove_last_char(attr_rowlines);
141
- attr_rowlines = join(attr_rowlines, "d");
142
- }
143
- else {
144
- attr_rowlines = join(attr_rowlines, "0");
53
+ // looking for a hline/hdashline match
54
+ if (strstr(*last_stack_item, hline) != NULL) {
55
+ if (rowlines_stack_len > 0) {
56
+ utarray_pop_back(rowlines_stack);
57
+ }
58
+ a = "solid";
59
+ utarray_push_back(rowlines_stack, &a);
60
+ } else if (strstr(*last_stack_item, hdashline) != NULL) {
61
+ if (rowlines_stack_len > 0) {
62
+ utarray_pop_back(rowlines_stack);
63
+ }
64
+ a = "dashed";
65
+ utarray_push_back(rowlines_stack, &a);
66
+ } else {
67
+ a = "none";
68
+ utarray_push_back(rowlines_stack, &a);
145
69
  }
146
70
 
147
- if (strstr(last_stack_item.line, line_separator) != NULL) {
148
- if ( (tok = strstr(last_stack_item.line, em_pattern_begin)) != NULL) {
149
- temp = tok + 2;
71
+ // if there's a line break...
72
+ if (strstr(*last_stack_item, line_separator) != NULL) {
73
+ // when an emphasis match, add it...
74
+ if ( (tok = strstr(*last_stack_item, em_pattern_begin)) != NULL) {
75
+ temp = tok + 2; // skip the first part ("\[")
150
76
  if ( (tok = strstr(temp, em_pattern_end)) != NULL) {
151
- offset = (int)(tok - temp);
152
- em_str = malloc(offset);
153
- if (strlen(em_str) != 0) {
154
- em_str = dupe_string_n(temp, offset);
155
- // MathML always expectes "em" points
156
- convertToEm(em_str);
157
- row_spacing_data.attribute = em_str;
158
- row_spacing_data.offset_pos = -1; // this value is not really important
159
- insertSymbolDataArray(&row_spacing_data_array, row_spacing_data);
160
- free(em_str);
161
- }
77
+ em_offset = (int)(tok - temp);
78
+ char *s = dupe_string_n(temp, em_offset);
79
+ utarray_push_back(row_spacing_stack, &s);
80
+ free(s);
162
81
  }
163
82
  }
83
+ // otherwise, use the default
164
84
  else {
165
- row_spacing_data.attribute = "0em";
166
- row_spacing_data.offset_pos = -1; // this value is not really important
167
- insertSymbolDataArray(&row_spacing_data_array, row_spacing_data);
85
+ if (strstr(*last_stack_item, "\\begin{smallmatrix}") != NULL) {
86
+ em_str = "0.2em";
87
+ } else if (strstr(*last_stack_item, "\\begin{gathered}") != NULL) {
88
+ em_str = "1.0ex";
89
+ } else {
90
+ em_str = "0.5ex";
91
+ }
92
+ utarray_push_back(row_spacing_stack, &em_str);
168
93
  }
169
94
  }
170
95
 
96
+ // make sure to pop at the end here; it messes with some references in Travis/Ubuntu for some reason
97
+ utarray_pop_back(array_stack);
98
+
171
99
  // we've reached the top, so stop.
172
- if (at_top != NULL)
100
+ if (at_top != NULL) {
173
101
  break;
102
+ }
103
+ }
104
+ if (at_top != NULL) {
105
+ is_smallmatrix = strstr(at_top, "\\begin{smallmatrix}");
106
+ is_gathered = strstr(at_top, "\\begin{gathered}");
174
107
  }
175
108
 
176
- if (attr_rowlines_len != 0) {
177
- // array is form of \begin{array}[t]{cc..c}
178
- tok = strstr(last_stack_item.line, "]{");
179
- if (tok == NULL) {
180
- // array is form of \begin{array}{cc..c}
181
- tok = strstr(last_stack_item.line, "}{");
182
- }
183
- if (tok == NULL) {
184
- // not an array, but rather, some env, like \begin{cases}
185
- tok = strstr(last_stack_item.line, "}");
186
- }
109
+ // TODO: we are skipping equation environments
110
+ if ((rowlines_stack_len != 0 || utarray_len(row_spacing_stack)) && strstr(*last_stack_item, "\\begin{equation}") == NULL) {
111
+ perform_replacement(environment_data_stack, rowlines_stack, is_smallmatrix, is_gathered, row_spacing_stack);
112
+ }
187
113
 
188
- offset = last_stack_item.line_pos + (tok - last_stack_item.line);
189
- // we cut the last char because we can skip the first row
190
- remove_last_char(attr_rowlines);
114
+ utarray_clear(row_spacing_stack);
115
+ utarray_clear(rowlines_stack);
116
+ rowlines_stack_len = 0;
117
+ }
191
118
 
192
- // we reverse the string, because we're going backwards
193
- strrev(attr_rowlines);
119
+ line = strtok(NULL, "\n");
120
+ }
194
121
 
195
- // empty rowlines should be reset
196
- if (strlen(attr_rowlines) == 0)
197
- attr_rowlines = join(attr_rowlines, "0");
122
+ utarray_free(array_stack);
123
+ utarray_free(row_spacing_stack);
124
+ utarray_free(rowlines_stack);
125
+ free(dupe_environment);
126
+ }
198
127
 
199
- attr_rowlines = join(join("(", attr_rowlines), ")");
128
+ void perform_replacement(UT_array **environment_data_stack, UT_array *rowlines_stack, const char *is_smallmatrix, const char *is_gathered, UT_array *row_spacing_stack)
129
+ {
130
+ char *a, *attr_rowlines, *attr_rowspacing;
131
+ envdata_t row_data;
200
132
 
201
- for (i = row_spacing_data_array.used - 1; i >= 0; i--) {
202
- attr_rowspacing = join(join(attr_rowspacing, row_spacing_data_array.array[i].attribute), "|");
203
- }
133
+ // we cut the last char because we can always skip the first row
134
+ utarray_pop_back(rowlines_stack);
204
135
 
205
- if (strlen(attr_rowspacing) > 0) {
206
- if (empty_row_spacings(attr_rowspacing) == 1) {
207
- attr_rowspacing = "0.5ex";
208
- }
209
- else {
210
- // last char is a pipe (|)
211
- remove_last_char(attr_rowspacing);
212
- }
136
+ // empty rowlines should be reset
137
+ if (utarray_len(rowlines_stack) == 0) {
138
+ a = "none";
139
+ utarray_push_back(rowlines_stack, &a);
140
+ }
213
141
 
214
- attr_rowspacing = join(join("<", attr_rowspacing), ">");
215
- }
142
+ // given the row_attribute values, construct an attribute list (separated by spaces)
143
+ UT_string *l;
144
+ utstring_new(l);
145
+ char **o=NULL;
146
+ a = "rowlines=\"";
147
+ utstring_printf(l, "%s", a);
148
+ while ( (o=(char**)utarray_prev(rowlines_stack,o))) {
149
+ utstring_printf(l, "%s ", *o);
150
+ }
216
151
 
217
- hline_data.attribute = join(attr_rowspacing, attr_rowlines);
218
- hline_data.offset_pos = offset + OFFSET_VAL;
219
- insertSymbolDataArray(&hline_data_array, hline_data);
220
- }
152
+ attr_rowlines = utstring_body(l);
153
+ if (strlen(attr_rowlines) > 0) {
154
+ remove_last_char(attr_rowlines); // remove the final space
155
+ }
221
156
 
222
- attr_rowlines = "";
223
- attr_rowspacing = "";
224
- attr_rowlines_len = 0;
157
+ // given the row_spacing values, construct an attribute list (separated by spaces)
158
+ UT_string *s;
159
+ utstring_new(s);
160
+ char **p=NULL;
161
+ while ( (p=(char**)utarray_prev(row_spacing_stack,p))) {
162
+ if (is_smallmatrix && strcmp(*p, "0.5ex") == 0) {
163
+ utstring_printf(s, "%s ", "0.2em");
164
+ } else if (is_gathered && strcmp(*p, "0.5ex") == 0) {
165
+ utstring_printf(s, "%s ", "1.0ex");
166
+ } else {
167
+ utstring_printf(s, "%s ", *p);
225
168
  }
226
-
227
- line = strtok(NULL, "\n");
228
169
  }
229
170
 
230
- // sort array by highest values first, so that we can insert to new_environment from
231
- // the bottom to the top (ensuring line numbers don't shift)
232
- sortSymbolDataArray(&hline_data_array);
233
-
234
- for (i = 0; i < hline_data_array.used; i++) {
235
- insert_substring(&new_environment, hline_data_array.array[i].attribute, hline_data_array.array[i].offset_pos);
171
+ attr_rowspacing = utstring_body(s);
172
+ if (strlen(attr_rowspacing) > 0) {
173
+ remove_last_char(attr_rowspacing); // remove the final space
174
+ } else {
175
+ if (is_smallmatrix != NULL) {
176
+ attr_rowspacing = "0.2em";
177
+ } else if (is_gathered != NULL) {
178
+ attr_rowspacing = "1.0ex";
179
+ } else {
180
+ attr_rowspacing = "0.5ex";
181
+ }
236
182
  }
237
183
 
238
- StackDestroy(&array_stack);
239
- deleteSymbolDataArray(&hline_data_array);
240
- deleteSymbolDataArray(&row_spacing_data_array);
241
- free(dupe_str);
184
+ row_data.rowspacing = attr_rowspacing;
185
+ row_data.rowlines = attr_rowlines;
242
186
 
243
- return new_environment;
187
+ utarray_push_back(*environment_data_stack, &row_data);
188
+ utstring_free(l);
189
+ utstring_free(s);
244
190
  }
245
191
 
246
- const char *vertical_pipe_extract(const char *string) {
247
- char *orig = dupe_string(string);
248
- char *columnlines = "", *previous_column = "";
192
+ const char *vertical_pipe_extract(const char *string)
193
+ {
194
+ char *dupe = dupe_string(string);
195
+ UT_string *columnlines, *border;
196
+ char *previous_column = "", *attr_columnlines, *attr_border;
249
197
  int i = 0;
250
198
 
251
- if (strncmp(orig, "s", 1) == 0) {
252
- columnlines = "frame=\"solid\" columnlines=\"";
253
- remove_first_char(orig);
254
- }
255
- else if (strncmp(orig, "d", 1) == 0) {
256
- columnlines = "frame=\"dashed\" columnlines=\"";
257
- remove_first_char(orig);
258
- }
259
- else {
260
- columnlines = "columnlines=\"";
199
+ utstring_new(columnlines);
200
+ utstring_new(border);
201
+
202
+ // the first character (if it exists) determines the frame border
203
+ if (strncmp(dupe, "s", 1) == 0) {
204
+ utstring_printf(columnlines, "%s", "frame=\"solid\" columnlines=\"");
205
+ remove_first_char(dupe);
206
+ } else if (strncmp(dupe, "d", 1) == 0) {
207
+ utstring_printf(columnlines, "%s", "frame=\"dashed\" columnlines=\"");
208
+ remove_first_char(dupe);
209
+ } else {
210
+ utstring_printf(columnlines, "%s", "columnlines=\"");
261
211
  }
262
212
 
263
- char *token = strtok(orig, " ");
213
+ char *token = strtok(dupe, " ");
264
214
 
265
215
  while (token != NULL) {
266
216
  if (strncmp(token, "s", 1) == 0) {
267
217
  previous_column = "s";
268
- columnlines = join(columnlines, "solid ");
269
- }
270
- else if (strncmp(token, "d", 1) == 0) {
218
+ utstring_printf(border, "%s ", "solid");
219
+ } else if (strncmp(token, "d", 1) == 0) {
271
220
  previous_column = "d";
272
- columnlines = join(columnlines, "dashed ");
273
- }
274
- else {
221
+ utstring_printf(border, "%s ", "dashed");
222
+ } else {
275
223
  if (i >= 1) { // we must skip the first blank col
276
224
  // only if there is no previous border should a border be considered, eg. "cc", not "c|c"
277
225
  if (strncmp(previous_column, "s", 1) != 0 && strncmp(previous_column, "d", 1) != 0) {
278
- columnlines = join(columnlines, "none ");
226
+ utstring_printf(border, "%s ", "none");
279
227
  }
280
228
  previous_column = "0";
281
229
  }
@@ -285,22 +233,73 @@ const char *vertical_pipe_extract(const char *string) {
285
233
  token = strtok(NULL, " ");
286
234
  }
287
235
 
288
- // an empty string here angers Lasem
289
- if (strncmp(columnlines, "columnlines=\"\0", 14) == 0)
290
- columnlines = "columnlines=\"none";
291
- // an empty space also angers Lasem
292
- else
293
- remove_last_char(columnlines);
236
+ attr_border = utstring_body(border);
237
+ if (strlen(attr_border) > 0) {
238
+ remove_last_char(attr_border); // remove the final space
239
+ }
240
+ utstring_printf(columnlines, "%s", attr_border);
241
+
242
+ // an empty string here angers Lasem, so let's remember to add 'none'
243
+ if (utstring_len(border) == 0) {
244
+ utstring_printf(columnlines, "%s", "none");
245
+ }
246
+
247
+ attr_columnlines = utstring_body(columnlines);
248
+ free(dupe);
249
+ utstring_free(border);
250
+
251
+ return attr_columnlines;
252
+ }
253
+
254
+ const char *remove_excess_pipe_chars(const char *string)
255
+ {
256
+ UT_string *columnalign;
257
+ utstring_new(columnalign);
258
+
259
+ char *dupe = dupe_string(string);
260
+ char *token = strtok(dupe, " ");
261
+ char *attr_columnalign;
262
+
263
+ while (token != NULL) {
264
+ if (strncmp(token, "s", 1) != 0 && strncmp(token, "d", 1) != 0) {
265
+ utstring_printf(columnalign, "%s ", token);
266
+ }
267
+ token = strtok(NULL, " ");
268
+ }
269
+
270
+ attr_columnalign = utstring_body(columnalign);
271
+ free(dupe);
272
+
273
+ if (strlen(attr_columnalign) > 0) {
274
+ remove_last_char(attr_columnalign); // remove the final space
275
+ }
294
276
 
295
- free(orig);
296
- return columnlines;
277
+ return attr_columnalign;
297
278
  }
298
279
 
299
- const char *remove_excess_pipe_chars(const char *string) {
300
- char *dup = dupe_string(string);
280
+ const char *combine_row_data(UT_array **environment_data_stack)
281
+ {
282
+ // if no information was provided, give a standard sizing
283
+ if (utarray_len(*environment_data_stack) == 0) {
284
+ const char* s = "rowspacing=\"0.5ex\" rowlines=\"none\"";
285
+ char* c = (char*)malloc(strlen(s) + 1);
286
+ strcpy(c, s);
287
+ return c;
288
+ }
289
+ envdata_t *row_data_elem = (envdata_t*) utarray_front(*environment_data_stack);
290
+
291
+ char *row_spacing_data = row_data_elem->rowspacing,
292
+ *row_lines_data = row_data_elem->rowlines,
293
+ *row_attr;
294
+
295
+ UT_string *row_attr_data;
296
+ utstring_new(row_attr_data);
297
+
298
+ // combine the row spacing and row lines data
299
+ utstring_printf(row_attr_data, "%s%s\" %s\"", "rowspacing=\"", row_spacing_data, row_lines_data);
301
300
 
302
- dup = replace_str(dup, "s", "");
303
- dup = replace_str(dup, "d", "");
301
+ row_attr = dupe_string(utstring_body(row_attr_data));
302
+ utarray_erase(*environment_data_stack, 0, 1);
304
303
 
305
- return dup;
304
+ return row_attr;
306
305
  }