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 .extra = 0,
42 },
43};
44
45void tex_initialize_marks(void)
46{
47
48 lmt_mark_state.data = aux_allocate_clear_array(sizeof(mark_record), lmt_mark_state.mark_data.minimum, 1);
49 if (lmt_mark_state.data) {
50 lmt_mark_state.mark_data.allocated = lmt_mark_state.mark_data.minimum;
51 lmt_mark_state.mark_data.top = lmt_mark_state.mark_data.minimum;
52 }
53}
54
55void tex_reset_mark(halfword m)
56{
57 if (m >= lmt_mark_state.mark_data.top) {
58 int step = lmt_mark_state.mark_data.step;
59 int size = lmt_mark_state.mark_data.top;
60
61 while (m >= size) {
62 size += step;
63 }
64
65 if (size > lmt_mark_state.mark_data.maximum) {
66 size = m;
67 }
68 if (size <= lmt_mark_state.mark_data.maximum) {
69 mark_record *tmp = aux_reallocate_array(lmt_mark_state.data, sizeof(mark_record), size, 1);
70 if (tmp) {
71 lmt_mark_state.data = tmp;
72 memset(&lmt_mark_state.data[lmt_mark_state.mark_data.top], 0, sizeof(mark_record) * (size - lmt_mark_state.mark_data.top));
73 lmt_mark_state.mark_data.top = size;
74 lmt_mark_state.mark_data.allocated = size;
75 } else {
76 tex_overflow_error("marks", size);
77 }
78 } else {
79 tex_overflow_error("marks", lmt_mark_state.mark_data.maximum);
80 }
81 }
82 if (m > lmt_mark_state.mark_data.ptr) {
83 lmt_mark_state.mark_data.ptr = m;
84 }
85 tex_wipe_mark(m);
86}
87
88halfword tex_get_mark(halfword m, halfword s)
89{
90 if (s >= 0 && s <= last_unique_mark_code) {
91 return lmt_mark_state.data[m].marks[s];
92 } else {
93 return null;
94 }
95}
96
97void tex_set_mark(halfword m, halfword s, halfword v)
98{
99 if (s >= 0 && s <= last_unique_mark_code) {
100 if (lmt_mark_state.data[m].marks[s]) {
101 tex_delete_token_reference(lmt_mark_state.data[m].marks[s]);
102 }
103 if (v) {
104 tex_add_token_reference(v);
105 }
106 lmt_mark_state.data[m].marks[s] = v;
107 lmt_mark_state.data[m].state = 1;
108 }
109}
110
111int tex_valid_mark(halfword m) {
112 if (m >= lmt_mark_state.mark_data.top) {
113 tex_reset_mark(m);
114 }
115 return m < lmt_mark_state.mark_data.top;
116}
117
118halfword tex_new_mark(quarterword subtype, halfword index, halfword ptr)
119{
120 halfword mark = tex_new_node(mark_node, subtype);
121 mark_index(mark) = index;
122 mark_ptr(mark) = ptr;
123 if (lmt_mark_state.min_used < 0) {
124 lmt_mark_state.min_used = index;
125 lmt_mark_state.max_used = index;
126 } else {
127 if (index < lmt_mark_state.min_used) {
128 lmt_mark_state.min_used = index;
129 }
130 if (index > lmt_mark_state.max_used) {
131 lmt_mark_state.max_used = index;
132 }
133 }
134 tex_set_mark(index, current_marks_code, ptr);
135 return mark;
136}
137
138static void tex_aux_print_mark(const char *s, halfword t)
139{
140 if (t) {
141
142 tex_print_token_list(s, token_link(t));
143 }
144}
145
146void tex_show_marks()
147{
148 if (tracing_marks_par > 0 && lmt_mark_state.min_used >= 0) {
149 tex_begin_diagnostic();
150 for (halfword m = lmt_mark_state.min_used; m <= lmt_mark_state.max_used; m++) {
151 if (tex_has_mark(m)) {
152 tex_print_format("[mark: class %i, page state]",m);
153 tex_aux_print_mark("top", tex_get_mark(m, top_marks_code));
154 tex_aux_print_mark("first", tex_get_mark(m, first_marks_code));
155 tex_aux_print_mark("bot", tex_get_mark(m, bot_marks_code));
156 tex_aux_print_mark("split first", tex_get_mark(m, split_first_marks_code));
157 tex_aux_print_mark("split bot", tex_get_mark(m, split_bot_marks_code));
158 tex_aux_print_mark("current", tex_get_mark(m, current_marks_code));
159 }
160 }
161 tex_end_diagnostic();
162 }
163}
164
165int tex_update_top_marks()
166{
167 int done = 0;
168 if (lmt_mark_state.min_used >= 0) {
169 for (halfword m = lmt_mark_state.min_used; m <= lmt_mark_state.max_used; m++) {
170 halfword bot = tex_get_mark(m, bot_marks_code);
171 if (bot) {
172 tex_set_mark(m, top_marks_code, bot);
173 if (tracing_marks_par > 1) {
174 tex_begin_diagnostic();
175 tex_print_format("[mark: class %i, top becomes bot]", m);
176 tex_aux_print_mark(NULL, bot);
177 tex_end_diagnostic();
178 }
179 tex_delete_mark(m, first_marks_code);
180 done = 1;
181 }
182 }
183 }
184 return done;
185}
186
187void tex_update_first_and_bot_mark(halfword n)
188{
189 halfword index = mark_index(n);
190 halfword ptr = mark_ptr(n);
191 if (node_subtype(n) == reset_mark_value_code) {
192
193 if (tracing_marks_par > 1) {
194 tex_begin_diagnostic();
195 tex_print_format("[mark: index %i, reset]", index);
196 tex_end_diagnostic();
197 }
198 tex_reset_mark(index);
199 } else {
200
201 halfword first = tex_get_mark(index, first_marks_code);
202 if (! first) {
203 tex_set_mark(index, first_marks_code, ptr);
204 if (tracing_marks_par > 1) {
205 tex_begin_diagnostic();
206 tex_print_format("[mark: index %i, first becomes mark]", index);
207 tex_aux_print_mark(NULL, ptr);
208 tex_end_diagnostic();
209 }
210 }
211 tex_set_mark(index, bot_marks_code, ptr);
212 if (tracing_marks_par > 1) {
213 tex_begin_diagnostic();
214 tex_print_format("[mark: index %i, bot becomes mark]", index);
215 tex_aux_print_mark(NULL, ptr);
216 tex_end_diagnostic();
217 }
218 }
219}
220
221int tex_update_first_marks(void)
222{
223 int done = 0;
224 if (lmt_mark_state.min_used >= 0) {
225 for (halfword m = lmt_mark_state.min_used; m <= lmt_mark_state.max_used; m++) {
226 halfword top = tex_get_mark(m, top_marks_code);
227 halfword first = tex_get_mark(m, first_marks_code);
228 if (top && ! first) {
229 tex_set_mark(m, first_marks_code, top);
230 if (tracing_marks_par > 1) {
231 tex_begin_diagnostic();
232 tex_print_format("[mark: class %i, first becomes top]", m);
233 tex_aux_print_mark(NULL, top);
234 tex_end_diagnostic();
235 }
236 done = 1;
237 }
238 }
239 }
240 return done;
241}
242
243int tex_update_marks(
244 halfword n
245)
246{
247 int done = 0;
248 if (n && node_type(n) == vlist_node) {
249 halfword list = box_list(n);
250 while (list) {
251 if (node_type(list) == mark_node) {
252 tex_update_first_and_bot_mark(list);
253 done = 1;
254 }
255 list = node_next(list);
256 }
257 }
258 return done;
259}
260
261void tex_update_split_mark(halfword n)
262{
263 halfword index = mark_index(n);
264 halfword ptr = mark_ptr(n);
265 if (node_subtype(n) == reset_mark_value_code) {
266 tex_reset_mark(index);
267 } else if (tex_get_mark(index, split_first_marks_code)) {
268 tex_set_mark(index, split_bot_marks_code, ptr);
269 if (tracing_marks_par > 1) {
270 tex_begin_diagnostic();
271 tex_print_format("[mark: index %i, split bot becomes mark]", index);
272 tex_aux_print_mark(NULL, tex_get_mark(index, split_bot_marks_code));
273 tex_end_diagnostic();
274 }
275 } else {
276 tex_set_mark(index, split_first_marks_code, ptr);
277 tex_set_mark(index, split_bot_marks_code, ptr);
278 if (tracing_marks_par > 1) {
279 tex_begin_diagnostic();
280 tex_print_format("[mark: index %i, split first becomes mark]", index);
281 tex_aux_print_mark(NULL, tex_get_mark(index, split_first_marks_code));
282 tex_print_format("[mark: index %i, split bot becomes split first]", index);
283 tex_aux_print_mark(NULL, tex_get_mark(index, split_bot_marks_code));
284 tex_end_diagnostic();
285 }
286 }
287}
288
289void tex_delete_mark(halfword m, int what)
290{
291 switch (what) {
292 case top_mark_code : what = top_marks_code;
293 case first_mark_code : what = first_marks_code;
294 case bot_mark_code : what = bot_marks_code;
295 case split_first_mark_code: what = split_first_marks_code;
296 case split_bot_mark_code : what = split_bot_marks_code;
297 }
298 tex_set_mark(m, what, null);
299}
300
301halfword tex_get_some_mark(halfword chr, halfword val)
302{
303 switch (chr) {
304 case top_mark_code : val = top_marks_code;
305 case first_mark_code : val = first_marks_code;
306 case bot_mark_code : val = bot_marks_code;
307 case split_first_mark_code: val = split_first_marks_code;
308 case split_bot_mark_code : val = split_bot_marks_code;
309 }
310 return tex_get_mark(val, chr);
311}
312
313void tex_wipe_mark(halfword m)
314{
315 for (int what = 0; what <= last_unique_mark_code; what++) {
316 tex_set_mark(m, what, null);
317 }
318 lmt_mark_state.data[m].state = 0;
319}
320
321int tex_has_mark(halfword m)
322{
323 if (lmt_mark_state.data[m].state) {
324 for (int what = 0; what <= last_unique_mark_code; what++) {
325 if (lmt_mark_state.data[m].marks[what]) {
326 return 1;
327 }
328 }
329 }
330 return 0;
331}
332
333
340
341void tex_run_mark(void)
342{
343 halfword index = 0;
344 halfword code = cur_chr;
345 switch (code) {
346 case set_marks_code:
347 case clear_marks_code:
348 case flush_marks_code:
349 index = tex_scan_mark_number();
350 break;
351 }
352 if (tex_valid_mark(index)) {
353 quarterword subtype = set_mark_value_code;
354 halfword ptr = null;
355 switch (code) {
356 case set_marks_code:
357 case set_mark_code:
358 ptr = tex_scan_toks_expand(0, NULL, 0, 0);
359 break;
360 case clear_marks_code:
361 tex_wipe_mark(index);
362 return;
363 case flush_marks_code:
364 subtype = reset_mark_value_code;
365 break;
366 }
367 tex_tail_append(tex_new_mark(subtype, index, ptr));
368 } else {
369
370 }
371}
372
373extern halfword lmt_get_mark_class(lua_State *L, int index)
374{
375 switch (lua_type(L, index)) {
376 case LUA_TSTRING:
377 {
378 const char *s = lua_tostring(L, index);
379 if (lua_key_eq(s, top)) {
380 return top_marks_code;
381 } else if (lua_key_eq(s, first)) {
382 return first_marks_code;
383 } else if (lua_key_eq(s, bottom)) {
384 return bot_marks_code;
385 } else if (lua_key_eq(s, splitfirst)) {
386 return split_first_marks_code;
387 } else if (lua_key_eq(s, splitbottom)) {
388 return split_bot_marks_code;
389 } else if (lua_key_eq(s, current)) {
390 return current_marks_code;
391 } else {
392 return -1;
393 }
394 }
395 case LUA_TNUMBER:
396 {
397 halfword m = lmt_tohalfword(L, index);
398 if (m >= 0 && m <= last_unique_mark_code) {
399 return m;
400 } else {
401 return -1;
402 }
403 }
404 default:
405 return -1;
406 }
407}
408 |