1
4
5# include "luametatex.h"
6
7
25
26mark_state_info lmt_mark_state = {
27 .data = NULL,
28 .min_used = -1,
29 .max_used = -1,
30 .mark_data = {
31 .minimum = min_mark_size,
32 .maximum = max_mark_size,
33 .size = memory_data_unset,
34 .step = stp_mark_size,
35 .allocated = 0,
36 .itemsize = sizeof(mark_record),
37 .top = 0,
38 .ptr = 0,
39 .initial = memory_data_unset,
40 .offset = 0,
41 },
42};
43
44void tex_initialize_marks(void)
45{
46
47 lmt_mark_state.data = aux_allocate_clear_array(sizeof(mark_record), lmt_mark_state.mark_data.minimum, 1);
48 if (lmt_mark_state.data) {
49 lmt_mark_state.mark_data.allocated = sizeof(mark_record) * lmt_mark_state.mark_data.minimum;
50 lmt_mark_state.mark_data.top = lmt_mark_state.mark_data.minimum;
51 }
52}
53
54void tex_reset_mark(halfword m)
55{
56 if (m >= lmt_mark_state.mark_data.top) {
57 int step = lmt_mark_state.mark_data.step;
58 int size = lmt_mark_state.mark_data.top;
59
60 while (m >= size) {
61 size += step;
62 }
63
64 if (size > lmt_mark_state.mark_data.maximum) {
65 size = m;
66 }
67 if (size <= lmt_mark_state.mark_data.maximum) {
68 mark_record *tmp = aux_reallocate_array(lmt_mark_state.data, sizeof(mark_record), size, 1);
69 if (tmp) {
70 lmt_mark_state.data = tmp;
71 memset(&lmt_mark_state.data[lmt_mark_state.mark_data.top], 0, sizeof(mark_record) * (size - lmt_mark_state.mark_data.top));
72 lmt_mark_state.mark_data.top = size;
73 lmt_mark_state.mark_data.allocated = sizeof(mark_record) * size;
74 } else {
75 tex_overflow_error("marks", size);
76 }
77 } else {
78 tex_overflow_error("marks", lmt_mark_state.mark_data.maximum);
79 }
80 }
81 if (m > lmt_mark_state.mark_data.ptr) {
82 lmt_mark_state.mark_data.ptr = m;
83 }
84 tex_wipe_mark(m);
85}
86
87halfword tex_get_mark(halfword m, halfword s)
88{
89 if (s >= 0 && s <= last_unique_mark_code) {
90 return lmt_mark_state.data[m][s];
91 } else {
92 return null;
93 }
94}
95
96void tex_set_mark(halfword m, halfword s, halfword v)
97{
98 if (s >= 0 && s <= last_unique_mark_code) {
99 if (lmt_mark_state.data[m][s]) {
100 tex_delete_token_reference(lmt_mark_state.data[m][s]);
101 }
102 if (v) {
103 tex_add_token_reference(v);
104 }
105 lmt_mark_state.data[m][s] = v;
106 }
107}
108
109int tex_valid_mark(halfword m) {
110 if (m >= lmt_mark_state.mark_data.top) {
111 tex_reset_mark(m);
112 }
113 return m < lmt_mark_state.mark_data.top;
114}
115
116halfword tex_new_mark(quarterword subtype, halfword index, halfword ptr)
117{
118 halfword mark = tex_new_node(mark_node, subtype);
119 mark_index(mark) = index;
120 mark_ptr(mark) = ptr;
121 if (lmt_mark_state.min_used < 0) {
122 lmt_mark_state.min_used = index;
123 lmt_mark_state.max_used = index;
124 } else {
125 if (index < lmt_mark_state.min_used) {
126 lmt_mark_state.min_used = index;
127 }
128 if (index > lmt_mark_state.max_used) {
129 lmt_mark_state.max_used = index;
130 }
131 }
132 tex_set_mark(index, current_marks_code, ptr);
133 return mark;
134}
135
136static void tex_aux_print_mark(const char *s, halfword t)
137{
138 if (t) {
139 tex_print_token_list(s, token_link(t));
140 }
141}
142
143void tex_show_marks()
144{
145 if (tracing_marks_par > 0 && lmt_mark_state.min_used >= 0) {
146 tex_begin_diagnostic();
147 for (halfword m = lmt_mark_state.min_used; m <= lmt_mark_state.max_used; m++) {
148 if (tex_has_mark(m)) {
149 tex_print_format("[mark: class %i, page state]",m);
150 tex_aux_print_mark("top", tex_get_mark(m, top_marks_code));
151 tex_aux_print_mark("first", tex_get_mark(m, first_marks_code));
152 tex_aux_print_mark("bot", tex_get_mark(m, bot_marks_code));
153 tex_aux_print_mark("split first", tex_get_mark(m, split_first_marks_code));
154 tex_aux_print_mark("split bot", tex_get_mark(m, split_bot_marks_code));
155 tex_aux_print_mark("current", tex_get_mark(m, current_marks_code));
156 }
157 }
158 tex_end_diagnostic();
159 }
160}
161
162void tex_update_top_marks()
163{
164 if (lmt_mark_state.min_used >= 0) {
165 for (halfword m = lmt_mark_state.min_used; m <= lmt_mark_state.max_used; m++) {
166 halfword bot = tex_get_mark(m, bot_marks_code);
167 if (bot) {
168 tex_set_mark(m, top_marks_code, bot);
169 if (tracing_marks_par > 1) {
170 tex_begin_diagnostic();
171 tex_print_format("[mark: class %i, top becomes bot]", m);
172 tex_aux_print_mark(NULL, bot);
173 tex_end_diagnostic();
174 }
175 tex_delete_mark(m, first_marks_code);
176 }
177 }
178 }
179}
180
181void tex_update_first_and_bot_mark(halfword n)
182{
183 halfword index = mark_index(n);
184 halfword ptr = mark_ptr(n);
185 if (node_subtype(n) == reset_mark_value_code) {
186
187 if (tracing_marks_par > 1) {
188 tex_begin_diagnostic();
189 tex_print_format("[mark: index %i, reset]", index);
190 tex_end_diagnostic();
191 }
192 tex_reset_mark(index);
193 } else {
194
195 halfword first = tex_get_mark(index, first_marks_code);
196 if (! first) {
197 tex_set_mark(index, first_marks_code, ptr);
198 if (tracing_marks_par > 1) {
199 tex_begin_diagnostic();
200 tex_print_format("[mark: index %i, first becomes mark]", index);
201 tex_aux_print_mark(NULL, ptr);
202 tex_end_diagnostic();
203 }
204 }
205 tex_set_mark(index, bot_marks_code, ptr);
206 if (tracing_marks_par > 1) {
207 tex_begin_diagnostic();
208 tex_print_format("[mark: index %i, bot becomes mark]", index);
209 tex_aux_print_mark(NULL, ptr);
210 tex_end_diagnostic();
211 }
212 }
213}
214
215void tex_update_first_marks(void)
216{
217 if (lmt_mark_state.min_used >= 0) {
218 for (halfword m = lmt_mark_state.min_used; m <= lmt_mark_state.max_used; m++) {
219 halfword top = tex_get_mark(m, top_marks_code);
220 halfword first = tex_get_mark(m, first_marks_code);
221 if (top && ! first) {
222 tex_set_mark(m, first_marks_code, top);
223 if (tracing_marks_par > 1) {
224 tex_begin_diagnostic();
225 tex_print_format("[mark: class %i, first becomes top]", m);
226 tex_aux_print_mark(NULL, top);
227 tex_end_diagnostic();
228 }
229 }
230 }
231 }
232}
233
234void tex_update_split_mark(halfword n)
235{
236 halfword index = mark_index(n);
237 halfword ptr = mark_ptr(n);
238 if (node_subtype(n) == reset_mark_value_code) {
239 tex_reset_mark(index);
240 } else {
241 if (tex_get_mark(index, split_first_marks_code)) {
242 tex_set_mark(index, split_bot_marks_code, ptr);
243 if (tracing_marks_par > 1) {
244 tex_begin_diagnostic();
245 tex_print_format("[mark: index %i, split bot becomes mark]", index);
246 tex_aux_print_mark(NULL, tex_get_mark(index, split_bot_marks_code));
247 tex_end_diagnostic();
248 }
249 } else {
250 tex_set_mark(index, split_first_marks_code, ptr);
251 tex_set_mark(index, split_bot_marks_code, ptr);
252 if (tracing_marks_par > 1) {
253 tex_begin_diagnostic();
254 tex_print_format("[mark: index %i, split first becomes mark]", index);
255 tex_aux_print_mark(NULL, tex_get_mark(index, split_first_marks_code));
256 tex_print_format("[mark: index %i, split bot becomes split first]", index);
257 tex_aux_print_mark(NULL, tex_get_mark(index, split_bot_marks_code));
258 tex_end_diagnostic();
259 }
260 }
261 }
262}
263
264
265void tex_delete_mark(halfword m, int what)
266{
267 switch (what) {
268 case top_mark_code : what = top_marks_code;
269 case first_mark_code : what = first_marks_code;
270 case bot_mark_code : what = bot_marks_code;
271 case split_first_mark_code: what = split_first_marks_code;
272 case split_bot_mark_code : what = split_bot_marks_code;
273 }
274 tex_set_mark(m, what, null);
275}
276
277halfword tex_get_some_mark(halfword chr, halfword val)
278{
279 switch (chr) {
280 case top_mark_code : val = top_marks_code;
281 case first_mark_code : val = first_marks_code;
282 case bot_mark_code : val = bot_marks_code;
283 case split_first_mark_code: val = split_first_marks_code;
284 case split_bot_mark_code : val = split_bot_marks_code;
285 }
286 return tex_get_mark(val, chr);
287}
288
289void tex_wipe_mark(halfword m)
290{
291 for (int what = 0; what <= last_unique_mark_code; what++) {
292 tex_set_mark(m, what, null);
293 }
294}
295
296int tex_has_mark(halfword m)
297{
298 for (int what = 0; what <= last_unique_mark_code; what++) {
299 if (lmt_mark_state.data[m][what]) {
300 return 1;
301 }
302 }
303 return 0;
304}
305
306
313
314void tex_run_mark(void)
315{
316 halfword index = 0;
317 halfword code = cur_chr;
318 switch (code) {
319 case set_marks_code:
320 case clear_marks_code:
321 case flush_marks_code:
322 index = tex_scan_mark_number();
323 break;
324 }
325 if (tex_valid_mark(index)) {
326 quarterword subtype = set_mark_value_code;
327 halfword ptr = null;
328 switch (code) {
329 case set_marks_code:
330 case set_mark_code:
331 ptr = tex_scan_toks_expand(0, NULL, 0, 0);
332 break;
333 case clear_marks_code:
334 tex_wipe_mark(index);
335 return;
336 case flush_marks_code:
337 subtype = reset_mark_value_code;
338 break;
339 }
340 tex_tail_append(tex_new_mark(subtype, index, ptr));
341 } else {
342
343 }
344}
345 |