sync with experimental
[luatex.git] / source / texk / web2c / luatexdir / tex / mathcodes.w
bloba0a357e53193f48e4e3c93be78b0b02ca77311f3
1 % mathnodes.w
3 % Copyright 2006-2012 Taco Hoekwater <taco@@luatex.org>
4 % Copyright 2012 Khaled Hosny <khaledhosny@@eglug.org>
6 % This file is part of LuaTeX.
8 % LuaTeX is free software; you can redistribute it and/or modify it under
9 % the terms of the GNU General Public License as published by the Free
10 % Software Foundation; either version 2 of the License, or (at your
11 % option) any later version.
13 % LuaTeX is distributed in the hope that it will be useful, but WITHOUT
14 % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 % FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16 % License for more details.
18 % You should have received a copy of the GNU General Public License along
19 % with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
21 @ @c
23 #include "ptexlib.h"
25 @ math codes
27 static sa_tree mathcode_head = NULL;
29 /* the 0xFFFFFFFF is a flag value */
31 #define MATHCODESTACK 8
32 #define MATHCODEDEFAULT 0xFFFFFFFF
33 #define MATHCODEACTIVE 0xFFFFFFFE
35 @ delcodes
37 static sa_tree delcode_head = NULL;
39 #define DELCODESTACK 4
40 #define DELCODEDEFAULT 0xFFFFFFFF
42 @ some helpers for mathcode printing
45 #define print_hex_digit(A) do { \
46 if ((A)>=10) print_char('A'+(A)-10); \
47 else print_char('0'+(A)); \
48 } while (0)
50 #define two_hex(A) do { \
51 print_hex_digit((A)/16); \
52 print_hex_digit((A)%16); \
53 } while (0)
55 #define four_hex(A) do { \
56 two_hex((A)/256); \
57 two_hex((A)%256); \
58 } while (0)
60 #define six_hex(A) do { \
61 two_hex((A)/65536); \
62 two_hex(((A)%65536)/256); \
63 two_hex((A)%256); \
64 } while (0)
67 At some point we will drop the mathchardef 8 bit storage (c_mathoption_umathcode_meaning_code => 1)
68 and then some of the conversion can go away. Like mathchar_from_integer: only wide characters are
69 possible then.
73 @ @c
74 mathcodeval mathchar_from_integer(int value, int extcode)
76 mathcodeval mval;
77 if (extcode == tex_mathcode) {
78 /* printf("can't happen: tex_mathcode\n"); */
79 mval.class_value = (value / 0x1000);
80 mval.family_value = ((value % 0x1000) / 0x100);
81 mval.character_value = (value % 0x100);
82 } else {
83 int mfam = (value / 0x200000) & 0x7FF;
84 mval.class_value = mfam % 0x08;
85 mval.family_value = mfam / 0x08;
86 mval.character_value = value & 0x1FFFFF;
88 return mval;
91 @ @c
92 void show_mathcode_value_old(int value)
94 print_char('"');
95 four_hex(value);
97 void show_mathcode_value(mathcodeval c)
99 print_char('"');
100 print_hex_digit(c.class_value);
101 print_char('"');
102 two_hex(c.family_value);
103 print_char('"');
104 six_hex(c.character_value);
107 @ @c
108 static void show_mathcode(int n)
110 mathcodeval c = get_math_code(n);
111 tprint_esc("Umathcode");
112 print_int(n);
113 print_char('=');
114 show_mathcode_value(c);
117 @ @c
118 static void unsavemathcode(quarterword gl)
120 sa_stack_item st;
121 if (mathcode_head->stack == NULL)
122 return;
123 while (mathcode_head->stack_ptr > 0 && abs(mathcode_head->stack[mathcode_head->stack_ptr].level) >= gl) {
124 st = mathcode_head->stack[mathcode_head->stack_ptr];
125 if (st.level > 0) {
126 rawset_sa_item(mathcode_head, st.code, st.value);
127 if (tracing_restores_par > 1) {
128 begin_diagnostic();
129 print_char('{');
130 tprint("restoring");
131 print_char(' ');
132 show_mathcode(st.code);
133 print_char('}');
134 end_diagnostic(false);
137 (mathcode_head->stack_ptr)--;
141 @ @c
142 void set_math_code(int n, int mathclass, int mathfamily, int mathcharacter, quarterword level)
144 sa_tree_item v;
145 if (mathclass == 8 && mathfamily == 0 && mathcharacter == 0) {
146 v.uint_value = MATHCODEACTIVE;
147 } else {
148 v.math_code_value.class_value = mathclass;
149 v.math_code_value.family_value = mathfamily;
150 v.math_code_value.character_value = mathcharacter;
152 set_sa_item(mathcode_head, n, v, level);
153 if (tracing_assigns_par > 1) {
154 begin_diagnostic();
155 print_char('{');
156 tprint("assigning");
157 print_char(' ');
158 show_mathcode(n);
159 print_char('}');
160 end_diagnostic(false);
164 @ @c
165 /* we could use two structs ... tex and umath */
167 mathcodeval get_math_code(int n)
169 mathcodeval d;
170 sa_tree_item v = get_sa_item(mathcode_head, n);
171 if (v.uint_value == MATHCODEDEFAULT) {
172 d.class_value = 0;
173 d.family_value = 0;
174 d.character_value = n;
175 } else if (v.uint_value == MATHCODEACTIVE) {
176 d.class_value = 8;
177 d.family_value = 0;
178 d.character_value = 0;
179 } else {
180 d.class_value = v.math_code_value.class_value;
181 if (d.class_value == 8) {
182 d.family_value = 0;
183 d.character_value = n;
184 } else {
185 d.family_value = v.math_code_value.family_value;
186 d.character_value = v.math_code_value.character_value;
189 return d;
192 @ @c
193 int get_math_code_num(int n)
195 mathcodeval d = get_math_code(n);
196 return (d.class_value + (d.family_value * 8)) * (65536 * 32) + d.character_value;
199 @ @c
200 static void initializemathcode(void)
202 sa_tree_item sa_value = { 0 };
203 sa_value.uint_value = MATHCODEDEFAULT;
204 mathcode_head = new_sa_tree(MATHCODESTACK, 1, sa_value);
207 static void dumpmathcode(void)
209 dump_sa_tree(mathcode_head,"mathcodes");
212 static void undumpmathcode(void)
214 mathcode_head = undump_sa_tree("mathcodes");
217 @ @c
218 static void show_delcode(int n)
220 delcodeval c;
221 c = get_del_code(n);
222 tprint_esc("Udelcode");
223 print_int(n);
224 print_char('=');
225 if (c.small_family_value < 0) {
226 print_char('-');
227 print_char('1');
228 } else {
229 print_char('"');
230 two_hex(c.small_family_value);
231 six_hex(c.small_character_value);
235 @ @c
236 static void unsavedelcode(quarterword gl)
238 sa_stack_item st;
239 if (delcode_head->stack == NULL)
240 return;
241 while (delcode_head->stack_ptr > 0 && abs(delcode_head->stack[delcode_head->stack_ptr].level) >= gl) {
242 st = delcode_head->stack[delcode_head->stack_ptr];
243 if (st.level > 0) {
244 rawset_sa_item(delcode_head, st.code, st.value);
245 if (tracing_restores_par > 1) {
246 begin_diagnostic();
247 print_char('{');
248 tprint("restoring");
249 print_char(' ');
250 show_delcode(st.code);
251 print_char('}');
252 end_diagnostic(false);
255 (delcode_head->stack_ptr)--;
259 @ @c
260 void set_del_code(int n, int smathfamily, int smathcharacter, int lmathfamily, int lmathcharacter, quarterword gl)
262 sa_tree_item v;
263 v.del_code_value.class_value = 0;
264 v.del_code_value.small_family_value = smathfamily;
265 v.del_code_value.small_character_value = smathcharacter;
266 v.del_code_value.dummy_value = 0;
267 v.del_code_value.large_family_value = lmathfamily;
268 v.del_code_value.large_character_value = lmathcharacter;
269 set_sa_item(delcode_head, n, v, gl); /* always global */
270 if (tracing_assigns_par > 1) {
271 begin_diagnostic();
272 print_char('{');
273 tprint("assigning");
274 print_char(' ');
275 show_delcode(n);
276 print_char('}');
277 end_diagnostic(false);
281 @ @c
282 delcodeval get_del_code(int n)
284 delcodeval d;
285 sa_tree_item v = get_sa_item(delcode_head, n);
286 if (v.uint_value == DELCODEDEFAULT) {
287 d.class_value = 0;
288 d.small_family_value = -1;
289 d.small_character_value = 0;
290 d.large_family_value = 0;
291 d.large_character_value = 0;
292 } else {
293 d.class_value = v.del_code_value.class_value;
294 d.small_family_value = v.del_code_value.small_family_value;
295 d.small_character_value = v.del_code_value.small_character_value;
296 d.large_family_value = v.del_code_value.large_family_value;
297 d.large_character_value = v.del_code_value.large_character_value;
299 return d;
302 @ this really only works for old-style delcodes!
305 int get_del_code_num(int n)
307 delcodeval d = get_del_code(n);
308 if (d.small_family_value < 0) {
309 return -1;
310 } else {
311 return ((d.small_family_value * 256 + d.small_character_value) * 4096 +
312 (d.large_family_value * 256) + d.large_character_value);
316 @ @c
317 static void initializedelcode(void)
319 sa_tree_item sa_value = { 0 };
320 sa_value.uint_value = DELCODEDEFAULT;
321 delcode_head = new_sa_tree(DELCODESTACK, 2, sa_value);
324 @ @c
325 static void dumpdelcode(void)
327 dump_sa_tree(delcode_head,"delcodes");
330 static void undumpdelcode(void)
332 delcode_head = undump_sa_tree("delcodes");
335 @ @c
336 void unsave_math_codes(quarterword grouplevel)
338 unsavemathcode(grouplevel);
339 unsavedelcode(grouplevel);
342 @ @c
343 void initialize_math_codes(void)
345 initializemathcode();
346 initializedelcode();
349 @ @c
350 void free_math_codes(void)
352 destroy_sa_tree(mathcode_head);
353 destroy_sa_tree(delcode_head);
356 @ @c
357 void dump_math_codes(void)
359 dumpmathcode();
360 dumpdelcode();
363 void undump_math_codes(void)
365 undumpmathcode();
366 undumpdelcode();