mathematical 0.4.2 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +20 -9
- data/Rakefile +5 -24
- data/ext/mathematical/extconf.rb +8 -3
- data/ext/mathematical/lasem/src/lsmdomparser.c +7 -7
- data/ext/mathematical/lasem/src/lsmdomparser.h +2 -2
- data/ext/mathematical/lasem/src/lsmitex.c +8 -5
- data/ext/mathematical/lasem/src/lsmitex.h +1 -1
- data/ext/mathematical/lasem/src/lsmmathmldocument.c +2 -2
- data/ext/mathematical/lasem/src/lsmmathmldocument.h +1 -1
- data/ext/mathematical/lasem/tests/lsmtest.c +2 -2
- data/ext/mathematical/mathematical.c +119 -10
- data/ext/mathematical/mtex2MML/ext/extconf.rb +4 -0
- data/ext/mathematical/mtex2MML/src/lex.yy.c +6791 -0
- data/ext/mathematical/mtex2MML/src/mtex2MML.h +59 -0
- data/ext/mathematical/mtex2MML/src/parse_extras.c +306 -0
- data/ext/mathematical/mtex2MML/src/parse_extras.h +78 -0
- data/ext/mathematical/mtex2MML/src/stack.c +80 -0
- data/ext/mathematical/mtex2MML/src/stack.h +101 -0
- data/ext/mathematical/mtex2MML/src/string_extras.c +211 -0
- data/ext/mathematical/mtex2MML/src/string_extras.h +46 -0
- data/ext/mathematical/mtex2MML/src/y.tab.c +7090 -0
- data/ext/mathematical/mtex2MML/src/y.tab.h +393 -0
- data/lib/mathematical.rb +1 -0
- data/lib/mathematical/corrections.rb +34 -0
- data/lib/mathematical/render.rb +21 -12
- data/lib/mathematical/version.rb +1 -1
- data/mathematical.gemspec +2 -2
- data/test/mathematical/corrections_test.rb +56 -0
- data/test/mathematical/fixtures/png/pmatrix.png +0 -0
- data/test/mathematical/fixtures_test.rb +11 -1
- data/test/mathematical/maliciousness_test.rb +10 -2
- data/test/mathematical/mathml_test.rb +22 -0
- data/test/mathematical/png_test.rb +26 -0
- data/test/test_helper.rb +13 -0
- metadata +150 -134
- data/ext/mathematical/itexToMML/itex2MML.h +0 -63
- data/ext/mathematical/itexToMML/lex.yy.c +0 -6548
- data/ext/mathematical/itexToMML/y.tab.c +0 -6179
- data/ext/mathematical/itexToMML/y.tab.h +0 -389
@@ -0,0 +1,59 @@
|
|
1
|
+
#ifndef MTEX2MML_H
|
2
|
+
#define MTEX2MML_H
|
3
|
+
|
4
|
+
#define MTEX2MML_VERSION "1.0.0"
|
5
|
+
|
6
|
+
#ifdef __cplusplus
|
7
|
+
extern "C" {
|
8
|
+
#endif
|
9
|
+
|
10
|
+
/* Step 1. Parse a buffer with mtex source; return value is mathml, or 0 on failure (e.g., parse error).
|
11
|
+
*/
|
12
|
+
extern char * mtex2MML_parse (const char * buffer, unsigned long length);
|
13
|
+
|
14
|
+
/* Step 2. Free the string from Step 1.
|
15
|
+
*/
|
16
|
+
extern void mtex2MML_free_string (char * str);
|
17
|
+
|
18
|
+
|
19
|
+
/* Alternatively, to filter generic source and converting embedded equations, use:
|
20
|
+
*/
|
21
|
+
extern int mtex2MML_filter (const char * buffer, unsigned long length);
|
22
|
+
|
23
|
+
extern int mtex2MML_html_filter (const char * buffer, unsigned long length);
|
24
|
+
extern int mtex2MML_strict_html_filter (const char * buffer, unsigned long length);
|
25
|
+
|
26
|
+
|
27
|
+
/* To change output methods:
|
28
|
+
*
|
29
|
+
* Note: If length is 0, then buffer is treated like a string; otherwise only length bytes are written.
|
30
|
+
*/
|
31
|
+
extern void (*mtex2MML_write) (const char * buffer, unsigned long length); /* default writes to stdout */
|
32
|
+
extern void (*mtex2MML_write_mathml) (const char * mathml); /* default calls mtex2MML_write(mathml,0) */
|
33
|
+
extern void (*mtex2MML_error) (const char * msg); /* default writes to stderr */
|
34
|
+
|
35
|
+
|
36
|
+
/* Other stuff:
|
37
|
+
*/
|
38
|
+
extern void mtex2MML_setup (const char * buffer, unsigned long length);
|
39
|
+
|
40
|
+
extern void mtex2MML_restart ();
|
41
|
+
|
42
|
+
extern char * mtex2MML_copy_string (const char * str);
|
43
|
+
extern char * mtex2MML_copy_string_extra (const char * str, unsigned extra);
|
44
|
+
extern char * mtex2MML_copy2 (const char * first, const char * second);
|
45
|
+
extern char * mtex2MML_copy3 (const char * first, const char * second, const char * third);
|
46
|
+
extern char * mtex2MML_copy_escaped (const char * str);
|
47
|
+
|
48
|
+
extern char * mtex2MML_empty_string;
|
49
|
+
|
50
|
+
extern int mtex2MML_lineno;
|
51
|
+
|
52
|
+
extern int mtex2MML_rowposn;
|
53
|
+
extern int mtex2MML_displaymode;
|
54
|
+
|
55
|
+
#ifdef __cplusplus
|
56
|
+
}
|
57
|
+
#endif
|
58
|
+
|
59
|
+
#endif /* ! MTEX2MML_H */
|
@@ -0,0 +1,306 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
#include <stdlib.h>
|
3
|
+
#include <string.h>
|
4
|
+
#include "parse_extras.h"
|
5
|
+
#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
|
+
|
26
|
+
void insertSymbolDataArray(symbolDataArray *a, symbolData element)
|
27
|
+
{
|
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;
|
79
|
+
|
80
|
+
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
|
+
|
85
|
+
const char *from = "\\begin", *until = "\\end", *hline = "\\hline", *hdashline = "\\hdashline",
|
86
|
+
*line_separator = "\\\\",
|
87
|
+
*em_pattern_begin = "\\[", *em_pattern_end = "]";
|
88
|
+
|
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);
|
100
|
+
|
101
|
+
// 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;
|
109
|
+
}
|
110
|
+
|
111
|
+
while (line != NULL) {
|
112
|
+
str_len = strlen(line) + 1;
|
113
|
+
|
114
|
+
stack_item.line = line;
|
115
|
+
stack_item.line_pos = start + 1;
|
116
|
+
|
117
|
+
start += str_len;
|
118
|
+
|
119
|
+
StackPush(&array_stack, stack_item);
|
120
|
+
|
121
|
+
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);
|
126
|
+
|
127
|
+
// 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) {
|
129
|
+
break;
|
130
|
+
}
|
131
|
+
|
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");
|
145
|
+
}
|
146
|
+
|
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;
|
150
|
+
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
|
+
}
|
162
|
+
}
|
163
|
+
}
|
164
|
+
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);
|
168
|
+
}
|
169
|
+
}
|
170
|
+
|
171
|
+
// we've reached the top, so stop.
|
172
|
+
if (at_top != NULL)
|
173
|
+
break;
|
174
|
+
}
|
175
|
+
|
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
|
+
}
|
187
|
+
|
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);
|
191
|
+
|
192
|
+
// we reverse the string, because we're going backwards
|
193
|
+
strrev(attr_rowlines);
|
194
|
+
|
195
|
+
// empty rowlines should be reset
|
196
|
+
if (strlen(attr_rowlines) == 0)
|
197
|
+
attr_rowlines = join(attr_rowlines, "0");
|
198
|
+
|
199
|
+
attr_rowlines = join(join("(", attr_rowlines), ")");
|
200
|
+
|
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
|
+
}
|
204
|
+
|
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
|
+
}
|
213
|
+
|
214
|
+
attr_rowspacing = join(join("<", attr_rowspacing), ">");
|
215
|
+
}
|
216
|
+
|
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
|
+
}
|
221
|
+
|
222
|
+
attr_rowlines = "";
|
223
|
+
attr_rowspacing = "";
|
224
|
+
attr_rowlines_len = 0;
|
225
|
+
}
|
226
|
+
|
227
|
+
line = strtok(NULL, "\n");
|
228
|
+
}
|
229
|
+
|
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);
|
236
|
+
}
|
237
|
+
|
238
|
+
StackDestroy(&array_stack);
|
239
|
+
deleteSymbolDataArray(&hline_data_array);
|
240
|
+
deleteSymbolDataArray(&row_spacing_data_array);
|
241
|
+
free(dupe_str);
|
242
|
+
|
243
|
+
return new_environment;
|
244
|
+
}
|
245
|
+
|
246
|
+
const char *vertical_pipe_extract(const char *string) {
|
247
|
+
char *orig = dupe_string(string);
|
248
|
+
char *columnlines = "", *previous_column = "";
|
249
|
+
int i = 0;
|
250
|
+
|
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=\"";
|
261
|
+
}
|
262
|
+
|
263
|
+
char *token = strtok(orig, " ");
|
264
|
+
|
265
|
+
while (token != NULL) {
|
266
|
+
if (strncmp(token, "s", 1) == 0) {
|
267
|
+
previous_column = "s";
|
268
|
+
columnlines = join(columnlines, "solid ");
|
269
|
+
}
|
270
|
+
else if (strncmp(token, "d", 1) == 0) {
|
271
|
+
previous_column = "d";
|
272
|
+
columnlines = join(columnlines, "dashed ");
|
273
|
+
}
|
274
|
+
else {
|
275
|
+
if (i >= 1) { // we must skip the first blank col
|
276
|
+
// only if there is no previous border should a border be considered, eg. "cc", not "c|c"
|
277
|
+
if (strncmp(previous_column, "s", 1) != 0 && strncmp(previous_column, "d", 1) != 0) {
|
278
|
+
columnlines = join(columnlines, "none ");
|
279
|
+
}
|
280
|
+
previous_column = "0";
|
281
|
+
}
|
282
|
+
}
|
283
|
+
|
284
|
+
i++;
|
285
|
+
token = strtok(NULL, " ");
|
286
|
+
}
|
287
|
+
|
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);
|
294
|
+
|
295
|
+
free(orig);
|
296
|
+
return columnlines;
|
297
|
+
}
|
298
|
+
|
299
|
+
const char *remove_excess_pipe_chars(const char *string) {
|
300
|
+
char *dup = dupe_string(string);
|
301
|
+
|
302
|
+
dup = replace_str(dup, "s", "");
|
303
|
+
dup = replace_str(dup, "d", "");
|
304
|
+
|
305
|
+
return dup;
|
306
|
+
}
|
@@ -0,0 +1,78 @@
|
|
1
|
+
#ifndef PARSE_EXTRAS_H
|
2
|
+
#define PARSE_EXTRAS_H
|
3
|
+
|
4
|
+
#ifdef __cplusplus
|
5
|
+
extern "C" {
|
6
|
+
#endif
|
7
|
+
|
8
|
+
typedef struct {
|
9
|
+
char *attribute;
|
10
|
+
int offset_pos;
|
11
|
+
} symbolData;
|
12
|
+
|
13
|
+
// array of structs
|
14
|
+
typedef struct
|
15
|
+
{
|
16
|
+
symbolData *array;
|
17
|
+
size_t used;
|
18
|
+
size_t size;
|
19
|
+
} symbolDataArray;
|
20
|
+
|
21
|
+
// set up array of symbols (like hlines)
|
22
|
+
extern void initSymbolDataArray(symbolDataArray *a, size_t initialSize);
|
23
|
+
|
24
|
+
// insert into symbol array
|
25
|
+
extern void insertSymbolDataArray(symbolDataArray *a, symbolData element);
|
26
|
+
|
27
|
+
// sort the array based on offset_pos
|
28
|
+
extern void sortSymbolDataArray(symbolDataArray *a);
|
29
|
+
|
30
|
+
// destroyes the array
|
31
|
+
extern void deleteSymbolDataArray(symbolDataArray *a);
|
32
|
+
|
33
|
+
// Move various symbols not easily supported inline with the `\begin` line
|
34
|
+
// This is so that the Bison parser can properly act on these. For example,
|
35
|
+
// `\hline`, `\hlinedash`, or `\\[2ex]` declerations.
|
36
|
+
//
|
37
|
+
// In order to properly address these situations, we need to parse them, find their symbols,
|
38
|
+
// and then modify the starting environment declaration to point out where those symbols are.
|
39
|
+
//
|
40
|
+
// Suppose there is an array like:
|
41
|
+
//
|
42
|
+
// \begin{array}{c:c}
|
43
|
+
// \begin{array}{c|cclc}
|
44
|
+
// \text{min} & 0 & 1 & 2 & 3\\\\
|
45
|
+
// \hline
|
46
|
+
// 0 & 0 & 0 & 0 & 0\\\\
|
47
|
+
// 1 & 0 & 1 & 1 & 1\\\\
|
48
|
+
// 2 & 0 & 1 & 2 & 2\\\\
|
49
|
+
// 3 & 0 & 1 & 2 & 3
|
50
|
+
// \end{array}
|
51
|
+
// &
|
52
|
+
// \begin{array}{c|cccl}
|
53
|
+
// \text{max}&0&1&2&3\\\\
|
54
|
+
// \hline
|
55
|
+
// 0 & 0 & 1 & 2 & 3\\\\
|
56
|
+
// 1 & 1 & 1 & 2 & 3\\\\
|
57
|
+
// 2 & 2 & 2 & 2 & 3\\\\
|
58
|
+
// 3 & 3 & 3 & 3 & 3
|
59
|
+
// \end{array}
|
60
|
+
// \end{array}
|
61
|
+
//
|
62
|
+
// The env_replacements function will push every line onto a stack. When an \end
|
63
|
+
// is detected, it starts popping off the stack until it reaches the corresponding
|
64
|
+
// \begin. It then modifies that line with attribute strings, an arrangement of the
|
65
|
+
// the symbols encountered while popping lines off.
|
66
|
+
extern char * env_replacements(const char *string);
|
67
|
+
|
68
|
+
// determines the column border arrangement from the array environment definition
|
69
|
+
extern const char *vertical_pipe_extract(const char *string);
|
70
|
+
|
71
|
+
// removes placeholder pipe characters from columnalign
|
72
|
+
extern const char *remove_excess_pipe_chars(const char *string);
|
73
|
+
|
74
|
+
#ifdef __cplusplus
|
75
|
+
}
|
76
|
+
#endif
|
77
|
+
|
78
|
+
#endif /* ! PARSE_EXTRAS_H */
|
@@ -0,0 +1,80 @@
|
|
1
|
+
/*
|
2
|
+
* File: stack.c
|
3
|
+
* Author: Robert I. Pitts <rip@cs.bu.edu>
|
4
|
+
* Last Modified: March 7, 2000
|
5
|
+
* Topic: Stack - Array Implementation
|
6
|
+
* ----------------------------------------------------------------
|
7
|
+
*
|
8
|
+
* This is an array implementation of a character stack.
|
9
|
+
*/
|
10
|
+
|
11
|
+
#include <stdio.h>
|
12
|
+
#include <stdlib.h>
|
13
|
+
#include "stack.h"
|
14
|
+
|
15
|
+
/************************ Function Definitions **********************/
|
16
|
+
|
17
|
+
void StackInit(stackT *stackP, int maxSize)
|
18
|
+
{
|
19
|
+
stackElementT *newContents;
|
20
|
+
|
21
|
+
/* Allocate a new array to hold the contents. */
|
22
|
+
|
23
|
+
newContents = (stackElementT *)malloc(sizeof(stackElementT) * maxSize);
|
24
|
+
|
25
|
+
if (newContents == NULL) {
|
26
|
+
fprintf(stderr, "Insufficient memory to initialize stack.\n");
|
27
|
+
exit(1); /* Exit, returning error code. */
|
28
|
+
}
|
29
|
+
|
30
|
+
stackP->contents = newContents;
|
31
|
+
stackP->maxSize = maxSize;
|
32
|
+
stackP->top = -1; /* I.e., empty */
|
33
|
+
}
|
34
|
+
|
35
|
+
void StackDestroy(stackT *stackP)
|
36
|
+
{
|
37
|
+
/* Get rid of array. */
|
38
|
+
free(stackP->contents);
|
39
|
+
|
40
|
+
stackP->contents = NULL;
|
41
|
+
stackP->maxSize = 0;
|
42
|
+
stackP->top = -1; /* I.e., empty */
|
43
|
+
}
|
44
|
+
|
45
|
+
void StackPush(stackT *stackP, stackElementT element)
|
46
|
+
{
|
47
|
+
if (StackIsFull(stackP)) {
|
48
|
+
fprintf(stderr, "Can't push element on stack: stack is full.\n");
|
49
|
+
exit(1); /* Exit, returning error code. */
|
50
|
+
}
|
51
|
+
|
52
|
+
/* Put information in array; update top. */
|
53
|
+
|
54
|
+
stackP->contents[++stackP->top] = element;
|
55
|
+
}
|
56
|
+
|
57
|
+
stackElementT StackPop(stackT *stackP)
|
58
|
+
{
|
59
|
+
if (StackIsEmpty(stackP)) {
|
60
|
+
fprintf(stderr, "Can't pop element from stack: stack is empty.\n");
|
61
|
+
exit(1); /* Exit, returning error code. */
|
62
|
+
}
|
63
|
+
|
64
|
+
return stackP->contents[stackP->top--];
|
65
|
+
}
|
66
|
+
|
67
|
+
int StackIsEmpty(stackT *stackP)
|
68
|
+
{
|
69
|
+
return stackP->top < 0;
|
70
|
+
}
|
71
|
+
|
72
|
+
int StackIsFull(stackT *stackP)
|
73
|
+
{
|
74
|
+
return stackP->top >= stackP->maxSize - 1;
|
75
|
+
}
|
76
|
+
|
77
|
+
stackElementT StackTop(stackT *stackP)
|
78
|
+
{
|
79
|
+
return stackP->contents[stackP->top];
|
80
|
+
}
|