diff options
author | Denis Bitouzé <dbitouze@wanadoo.fr> | 2021-02-25 18:23:07 +0000 |
---|---|---|
committer | Denis Bitouzé <dbitouze@wanadoo.fr> | 2021-02-25 18:23:07 +0000 |
commit | c6101f91d071883b48b1b4b51e5eba0f36d9a78d (patch) | |
tree | 1bf7f5a881d7a4f5c5bf59d0b2821943dd822372 /Build/source/texk/web2c/luatexdir/tex | |
parent | 07ee7222e389b0777456b427a55c22d0e6ffd267 (diff) |
French translation for tlmgr updated
git-svn-id: svn://tug.org/texlive/trunk@57912 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/tex')
66 files changed, 0 insertions, 52659 deletions
diff --git a/Build/source/texk/web2c/luatexdir/tex/align.c b/Build/source/texk/web2c/luatexdir/tex/align.c deleted file mode 100644 index bb721856fac..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/align.c +++ /dev/null @@ -1,1299 +0,0 @@ -/* - -Copyright 2009-2010 Taco Hoekwater <taco@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your -option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU General Public License along -with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" - -void fin_align(void); -void init_row(void); -void init_col(void); - -#define noDEBUG - -/*tex - - It's sort of a miracle whenever \.{\\halign} and \.{\\valign} work, because - they cut across so many of the control structures of \TeX. Therefore the - present page is probably not the best place for a beginner to start reading - this program; it is better to master everything else first. - - Let us focus our thoughts on an example of what the input might be, in order - to get some idea about how the alignment miracle happens. The example doesn't - do anything useful, but it is sufficiently general to indicate all of the - special cases that must be dealt with; please do not be disturbed by its - apparent complexity and meaninglessness. - - \starttyping - \tabskip 2pt plus 3pt - \halign to 300pt{u1#v1& - \hskip 50pt \tabskip 1pt plus 1fil u2#v2& - \hskip 50pt u3#v3\cr - \hskip 25pt a1&\omit a2&\vrule\cr - \hskip 25pt \noalign\{\vskip 3pt} - \hskip 25pt b1\span b2\cr - \hskip 25pt \omit&c2\span\omit\cr} - \stoptyping - - Here's what happens: - - \startitemize - - \startitem - When `\.{\\halign to 300pt\{}' is scanned, the |scan_spec| routine - places the 300pt dimension onto the |save_stack|, and an - |align_group| code is placed above it. This will make it possible to - complete the alignment when the matching `\.\}' is found. - \stopitem - - \startitem - The preamble is scanned next. Macros in the preamble are not - expanded, except as part of a tabskip specification. For example, if - \.{u2} had been a macro in the preamble above, it would have been - expanded, since \TeX\ must look for `\.{minus...}' as part of the - tabskip glue. A ``preamble list'' is constructed based on the user's - preamble; in our case it contains the following seven items: - - \starttabulate - \NC \type{\glue 2pt plus 3pt} \NC the tabskip preceding column 1 \NC \NR - \NC \type{\alignrecord} of width $-\infty$ \NC preamble info for column 1 \NC \NR - \NC \type{\glue 2pt plus 3pt} \NC the tabskip between columns 1 and 2 \NC \NR - \NC \type{\alignrecord} of width $-\infty$ \NC preamble info for column 2 \NC \NR - \NC \type{\glue 1pt plus 1fil} \NC the tabskip between columns 2 and 3 \NC \NR - \NC \type{\alignrecord} of width $-\infty$ \NC preamble info for column 3 \NC \NR - \NC \type{\glue 1pt plus 1fil} \NC the tabskip following column 3 \NC \NR - \stoptabulate - - These ``alignrecord'' entries have the same size as an |unset_node|, - since they will later be converted into such nodes. These alignrecord - nodes have no |depth| field; this is split into |u_part| and - |v_part|, and they point to token lists for the templates of the - alignment. For example, the |u_part| field in the first alignrecord - points to the token list `\.{u1}', i.e., the template preceding the - `\.\#' for column~1. Furthermore, They have a |span_ptr| instead of a - |node_attr| field, and these |span_ptr| fields are initially set to - the value |end_span|, for reasons explained below. - \stopitem - - \startitem - \TeX\ now looks at what follows the \.{\\cr} that ended the preamble. - It is not `\.{\\noalign}' or `\.{\\omit}', so this input is put back - to be read again, and the template `\.{u1}' is fed to the scanner. - Just before reading `\.{u1}', \TeX\ goes into restricted horizontal - mode. Just after reading `\.{u1}', \TeX\ will see `\.{a1}', and then - (when the {\.\&} is sensed) \TeX\ will see `\.{v1}'. Then \TeX\ scans - an |endv| token, indicating the end of a column. At this point an - |unset_node| is created, containing the contents of the current hlist - (i.e., `\.{u1a1v1}'). The natural width of this unset node replaces - the |width| field of the alignrecord for column~1; in general, the - alignrecords will record the maximum natural width that has occurred - so far in a given column. - \stopitem - - \startitem - Since `\.{\\omit}' follows the `\.\&', the templates for column~2 are - now bypassed. Again \TeX\ goes into restricted horizontal mode and - makes an |unset_node| from the resulting hlist; but this time the - hlist contains simply `\.{a2}'. The natural width of the new unset - box is remembered in the |width| field of the alignrecord for - column~2. - \stopitem - - \startitem - A third |unset_node| is created for column 3, using essentially the - mechanism that worked for column~1; this unset box contains - `\.{u3\\vrule v3}'. The vertical rule in this case has running - dimensions that will later extend to the height and depth of the - whole first row, since each |unset_node| in a row will eventually - inherit the height and depth of its enclosing box. - \stopitem - - \startitem - The first row has now ended; it is made into a single unset box - comprising the following seven items: - - \starttyping - \glue 2pt plus 3pt - \unsetbox for 1 column: u1a1v1 - \glue 2pt plus 3pt - \unsetbox for 1 column: a2 - \glue 1pt plus 1fil - \unsetbox for 1 column: u3\vrule v3 - \glue 1pt plus 1fil - \stoptyping - - The width of this unset row is unimportant, but it has the correct - height and depth, so the correct baselineskip glue will be computed - as the row is inserted into a vertical list. - \stopitem - - \startitem - Since `\.{\\noalign}' follows the current \.{\\cr}, \TeX\ appends - additional material (in this case \.{\\vskip 3pt}) to the vertical - list. While processing this material, \TeX\ will be in internal - vertical mode, and |no_align_group| will be on |save_stack|. - \stopitem - - \startitem - The next row produces an unset box that looks like this: - - \starttyping - \glue 2pt plus 3pt - \unsetbox for 2 columns: u1b1v1u2b2v2 - \glue 1pt plus 1fil - \unsetbox for 1 column: {(empty)} - \glue 1pt plus 1fil - \stoptyping - - The natural width of the unset box that spans columns 1~and~2 is - stored in a ``span node,'' which we will explain later; the - |span_ptr| field of the alignrecord for column~1 now points to the - new span node, and the |span_ptr| of the span node points to - |end_span|. - \stopitem - - \startitem - - The final row produces the unset box - - \starttyping - \glue 2pt plus 3pt\cr - \unsetbox for 1 column: {(empty)} - \glue 2pt plus 3pt\cr - \unsetbox for 2 columns: u2c2v2 - \glue 1pt plus 1fil - \stoptyping - - A new span node is attached to the alignrecord for column 2. - \stopitem - - \startitem - The last step is to compute the true column widths and to change all - the unset boxes to hboxes, appending the whole works to the vertical - list that encloses the \.{\\halign}. The rules for deciding on the - final widths of each unset column box will be explained below. - \stopitem - - \stopitemize - - Note that as \.{\\halign} is being processed, we fearlessly give up control - to the rest of \TeX. At critical junctures, an alignment routine is called - upon to step in and do some little action, but most of the time these - routines just lurk in the background. It's something like post-hypnotic - suggestion. - - We have mentioned that alignrecords contain no |height| or |depth| fields. - Their |glue_sign| and |glue_order| are pre-empted as well, since it is - necessary to store information about what to do when a template ends. This - information is called the |extra_info| field. - -*/ - -/*tex The pointer to \<u_j> token list: */ - -#define u_part(A) vlink((A)+depth_offset) - -/*tex The pointer to \<v_j> token list */ - -#define v_part(A) vinfo((A)+depth_offset) - -/*tex A column spanning list */ - -#define span_ptr(A) vinfo((A)+1) - -/*tex Info to remember during template */ - -#define extra_info(A) vinfo((A)+list_offset) - -/*tex - - Alignments can occur within alignments, so a small stack is used to access - the alignrecord information. At each level we have a |preamble| pointer, - indicating the beginning of the preamble list; a |cur_align| pointer, - indicating the current position in the preamble list; a |cur_span| pointer, - indicating the value of |cur_align| at the beginning of a sequence of spanned - columns; a |cur_loop| pointer, indicating the tabskip glue before an - alignrecord that should be copied next if the current list is extended; and - the |align_state| variable, which indicates the nesting of braces so that - \.{\\cr} and \.{\\span} and tab marks are properly intercepted. There also - are pointers |cur_head| and |cur_tail| to the head and tail of a list of - adjustments being moved out from horizontal mode to vertical~mode, and alike - |cur_pre_head| and |cur_pre_tail| for pre-adjust lists. - - The current values of these nine quantities appear in global variables; when - they have to be pushed down, they are stored in 6-word nodes, and |align_ptr| - points to the topmost such node. - -*/ - -/*tex This could be in |texnodes.h| but it's documented here. */ - -/*tex The current preamble list: */ - -#define preamble vlink(align_head) - -/*tex The current position in the preamble list: */ - -pointer cur_align = null; - -/*tex The start of the currently spanned columns in the preamble list: */ - -pointer cur_span = null; - -/*tex A place to copy when extending a periodic preamble: */ - -pointer cur_loop = null; - -/*tex The most recently pushed-down alignment stack node: */ - -pointer align_ptr = null; - -/*tex Adjustment list pointers: */ - -pointer cur_head = null, cur_tail = null; - -/*tex Pre-adjustment list pointers: */ - -pointer cur_pre_head = null, cur_pre_tail = null; - -/*tex - - The |align_state| and |preamble| variables are initialized elsewhere. - - Alignment stack maintenance is handled by a pair of trivial routines called - |push_alignment| and |pop_alignment|. - - (HH:) It makes not much sense to add support for an \.{attr} keyword to - \.{\\halign} and \.{\\valign} because then we need to decide if we tag rows - or cells or both or come up with \.{cellattr} and \.{rowattr} and such. But - then it even makes sense to have explicit commands (in addition to the - seperator) to tags individual cells. Too muss hassle for now and the - advantages are not that large. - -*/ - -static void push_alignment(void) -{ - /*tex The new alignment stack node: */ - pointer p; - p = new_node(align_stack_node, 0); - vinfo(p + 1) = align_ptr; - vlink(p + 1) = cur_align; - vinfo(p + 2) = preamble; - vlink(p + 2) = cur_span; - vinfo(p + 3) = cur_loop; - vlink(p + 3) = align_state; - vinfo(p + 4) = cur_head; - vlink(p + 4) = cur_tail; - vinfo(p + 5) = cur_pre_head; - vlink(p + 5) = cur_pre_tail; - align_ptr = p; - cur_head = new_node(temp_node, 0); - cur_pre_head = new_node(temp_node, 0); -} - -static void pop_alignment(void) -{ - /*tex The top alignment stack node: */ - pointer p; - flush_node(cur_head); - flush_node(cur_pre_head); - p = align_ptr; - cur_pre_tail = vlink(p + 5); - cur_pre_head = vinfo(p + 5); - cur_tail = vlink(p + 4); - cur_head = vinfo(p + 4); - align_state = vlink(p + 3); - cur_loop = vinfo(p + 3); - cur_span = vlink(p + 2); - preamble = vinfo(p + 2); - cur_align = vlink(p + 1); - align_ptr = vinfo(p + 1); - flush_node(p); -} - -/*tex - - \TeX\ has eight procedures that govern alignments: |init_align| and - |fin_align| are used at the very beginning and the very end; |init_row| and - |fin_row| are used at the beginning and end of individual rows; |init_span| - is used at the beginning of a sequence of spanned columns (possibly involving - only one column); |init_col| and |fin_col| are used at the beginning and end - of individual columns; and |align_peek| is used after \.{\\cr} to see whether - the next item is \.{\\noalign}. - - We shall consider these routines in the order they are first used during the - course of a complete \.{\\halign}, namely |init_align|, |align_peek|, - |init_row|, |init_span|, |init_col|, |fin_col|, |fin_row|, |fin_align|. - - The preamble is copied directly, except that \.{\\tabskip} causes a change to - the tabskip glue, thereby possibly expanding macros that immediately follow - it. An appearance of \.{\\span} also causes such an expansion. - - Note that if the preamble contains `\.{\\global\\tabskip}', the - `\.{\\global}' token survives in the preamble and the `\.{\\tabskip}' defines - new tabskip glue (locally). - -*/ - -static void get_preamble_token(void) -{ - RESTART: - get_token(); - while ((cur_chr == span_code) && (cur_cmd == tab_mark_cmd)) { - /*tex This token will be expanded once. */ - get_token(); - if (cur_cmd > max_command_cmd) { - expand(); - get_token(); - } - } - if (cur_cmd == endv_cmd) - fatal_error("(interwoven alignment preambles are not allowed)"); - if ((cur_cmd == assign_glue_cmd) - && (cur_chr == glue_base + tab_skip_code)) { - scan_optional_equals(); - scan_glue(glue_val_level); - if (global_defs_par > 0) - geq_define(glue_base + tab_skip_code, glue_ref_cmd, cur_val); - else - eq_define(glue_base + tab_skip_code, glue_ref_cmd, cur_val); - goto RESTART; - } -} - -/*tex - - When \.{\\halign} or \.{\\valign} has been scanned in an appropriate mode, - \TeX\ calls |init_align|, whose task is to get everything off to a good - start. This mostly involves scanning the preamble and putting its information - into the preamble list. - -*/ - -void init_align(void) -{ - /*tex |warning_index| value for error messages */ - pointer save_cs_ptr; - /*tex for short-term temporary use */ - pointer p, r; - /*tex \.{\\halign} or \.{\\valign}, usually */ - save_cs_ptr = cur_cs; - push_alignment(); - /*tex enter a new alignment level */ - align_state = -1000000; - /*tex - - When \.{\\halign} is used as a displayed formula, there should be no - other pieces of mlists present. - - */ - if ((cur_list.mode_field == mmode) && ((cur_list.tail_field != cur_list.head_field) || (incompleat_noad_par != null))) { - const char *hlp[] = { - "Displays can use special alignments (like \\eqalignno)", - "only if nothing but the alignment itself is between $$'s.", - "So I've deleted the formulas that preceded this alignment.", - NULL - }; - tex_error("Improper \\halign inside $$'s", hlp); - flush_math(); - } - /*tex Enter a new semantic level. */ - push_nest(); - /*tex - - In vertical modes, |prev_depth| already has the correct value. But if we - are in |mmode| (displayed formula mode), we reach out to the enclosing - vertical mode for the |prev_depth| value that produces the correct - baseline calculations. - */ - if (cur_list.mode_field == mmode) { - cur_list.mode_field = -vmode; - prev_depth_par = nest[nest_ptr - 2].prev_depth_field; - } else if (cur_list.mode_field > 0) { - cur_list.mode_field = -(cur_list.mode_field); - } - scan_spec(align_group); - /*tex Scan the preamble. */ - preamble = null; - cur_align = align_head; - cur_loop = null; - scanner_status = aligning; - warning_index = save_cs_ptr; - align_state = -1000000; - /*tex At this point, |cur_cmd=left_brace|. */ - while (true) { - /*tex Append the current tabskip glue to the preamble list. */ - r = new_param_glue(tab_skip_code); - vlink(cur_align) = r; - cur_align = vlink(cur_align); - if (cur_cmd == car_ret_cmd) { - /*tex \.{\\cr} ends the preamble. */ - break; - } - /*tex - - Scan preamble text until |cur_cmd| is |tab_mark| or |car_ret| and - then scan the template \<u_j>, putting the resulting token list in - |hold_token_head|. Spaces are eliminated from the beginning of a - template. - - */ - p = hold_token_head; - token_link(p) = null; - while (1) { - get_preamble_token(); - if (cur_cmd == mac_param_cmd) - break; - if ((cur_cmd <= car_ret_cmd) && (cur_cmd >= tab_mark_cmd) - && (align_state == -1000000)) { - if ((p == hold_token_head) && (cur_loop == null) && (cur_cmd == tab_mark_cmd)) { - cur_loop = cur_align; - } else { - const char *hlp[] = { - "There should be exactly one # between &'s, when an", - "\\halign or \\valign is being set up. In this case you had", - "none, so I've put one in; maybe that will work.", - NULL - }; - back_input(); - tex_error("Missing # inserted in alignment preamble", hlp); - break; - } - } else if ((cur_cmd != spacer_cmd) || (p != hold_token_head)) { - r = get_avail(); - token_link(p) = r; - p = token_link(p); - token_info(p) = cur_tok; - } - } - r = new_node(align_record_node, 0); - vlink(cur_align) = r; - /*tex A new align record: */ - cur_align = vlink(cur_align); - span_ptr(cur_align) = end_span; - width(cur_align) = null_flag; - u_part(cur_align) = token_link(hold_token_head); - /*tex - - Scan the template \<v_j>, putting the resulting token list in - |hold_token_head|. - - */ - p = hold_token_head; - token_link(p) = null; - while (1) { - CONTINUE: - get_preamble_token(); - if ((cur_cmd <= car_ret_cmd) && (cur_cmd >= tab_mark_cmd) && (align_state == -1000000)) - break; - if (cur_cmd == mac_param_cmd) { - const char *hlp[] = { - "There should be exactly one # between &'s, when an", - "\\halign or \\valign is being set up. In this case you had", - "more than one, so I'm ignoring all but the first.", - NULL - }; - tex_error("Only one # is allowed per tab", hlp); - goto CONTINUE; - } - r = get_avail(); - token_link(p) = r; - p = token_link(p); - token_info(p) = cur_tok; - } - r = get_avail(); - token_link(p) = r; - p = token_link(p); - /*tex Put \.{\\endtemplate} at the end: */ - token_info(p) = end_template_token; - v_part(cur_align) = token_link(hold_token_head); - } - scanner_status = normal; - new_save_level(align_group); - if (every_cr_par != null) - begin_token_list(every_cr_par, every_cr_text); - /*tex Look for \.{\\noalign} or \.{\\omit}. */ - align_peek(); -} - -/*tex - - The tricky part about alignments is getting the templates into the scanner at - the right time, and recovering control when a row or column is finished. - - We usually begin a row after each \.{\\cr} has been sensed, unless that - \.{\\cr} is followed by \.{\\noalign} or by the right brace that terminates - the alignment. The |align_peek| routine is used to look ahead and do the - right thing; it either gets a new row started, or gets a \.{\\noalign} - started, or finishes off the alignment. - -*/ - -void align_peek(void) -{ - RESTART: - align_state = 1000000; - do { - get_x_or_protected(); - } while (cur_cmd == spacer_cmd); - if (cur_cmd == no_align_cmd) { - scan_left_brace(); - new_save_level(no_align_group); - if (cur_list.mode_field == -vmode) - normal_paragraph(); - } else if (cur_cmd == right_brace_cmd) { - fin_align(); - } else if ((cur_cmd == car_ret_cmd) && (cur_chr == cr_cr_code)) { - /*tex Ignore \.{\\crcr}. */ - goto RESTART; - } else { - /*tex Start a new row. */ - init_row(); - /*tex Start a new column and replace what we peeked at. */ - init_col(); - } -} - - -/*tex - - The parameter to |init_span| is a pointer to the alignrecord where the next - column or group of columns will begin. A new semantic level is entered, so - that the columns will generate a list for subsequent packaging. - -*/ - -static void init_span(pointer p) -{ - push_nest(); - if (cur_list.mode_field == -hmode) { - space_factor_par = 1000; - } else { - prev_depth_par = ignore_depth; - normal_paragraph(); - } - cur_span = p; -} - -/*tex - - To start a row (i.e., a `row' that rhymes with `dough' but not with `bough'), - we enter a new semantic level, copy the first tabskip glue, and change from - internal vertical mode to restricted horizontal mode or vice versa. The - |space_factor| and |prev_depth| are not used on this semantic level, but we - clear them to zero just to be tidy. - -*/ - -void init_row(void) -{ - push_nest(); - cur_list.mode_field = (-hmode - vmode) - cur_list.mode_field; - if (cur_list.mode_field == -hmode) - space_factor_par = 0; - else - prev_depth_par = 0; - tail_append(new_glue(preamble)); - subtype(cur_list.tail_field) = tab_skip_code + 1; - cur_align = vlink(preamble); - cur_tail = cur_head; - cur_pre_tail = cur_pre_head; - init_span(cur_align); -} - -/*tex - - When a column begins, we assume that |cur_cmd| is either |omit| or else the - current token should be put back into the input until the \<u_j> template has - been scanned. (Note that |cur_cmd| might be |tab_mark| or |car_ret|.) We also - assume that |align_state| is approximately 1000000 at this time. We remain in - the same mode, and start the template if it is called for. - -*/ - -void init_col(void) -{ - extra_info(cur_align) = cur_cmd; - if (cur_cmd == omit_cmd) - align_state = 0; - else { - back_input(); - begin_token_list(u_part(cur_align), u_template); - } - /*tex now |align_state=1000000| */ -} - - -/*tex - - The scanner sets |align_state| to zero when the \<u_j> template ends. When a - subsequent \.{\\cr} or \.{\\span} or tab mark occurs with |align_state=0|, - the scanner activates the following code, which fires up the \<v_j> template. - We need to remember the |cur_chr|, which is either |cr_cr_code|, |cr_code|, - |span_code|, or a character code, depending on how the column text has ended. - - This part of the program had better not be activated when the preamble to - another alignment is being scanned, or when no alignment preamble is active. - -*/ - -void insert_vj_template(void) -{ - if ((scanner_status == aligning) || (cur_align == null)) - fatal_error("(interwoven alignment preambles are not allowed)"); - cur_cmd = extra_info(cur_align); - extra_info(cur_align) = cur_chr; - if (cur_cmd == omit_cmd) - begin_token_list(omit_template, v_template); - else - begin_token_list(v_part(cur_align), v_template); - align_state = 1000000; -} - -/*tex Determine the stretch order */ - -#define determine_stretch_order() do { \ - if (total_stretch[filll]!= 0) o = filll; \ - else if (total_stretch[fill] != 0) o = fill; \ - else if (total_stretch[fil] != 0) o = fil; \ - else if (total_stretch[sfi] != 0) o = sfi; \ - else o=normal; \ -} while (0) - -/*tex Determine the shrink order */ - -#define determine_shrink_order() do { \ - if (total_shrink[filll] != 0) o = filll; \ - else if (total_shrink[fill] != 0) o = fill; \ - else if (total_shrink[fil] != 0) o = fil; \ - else if (total_shrink[sfi] != 0) o = sfi; \ - else o=normal; \ -} while (0) - -/*tex - - When the |endv| command at the end of a \<v_j> template comes through the - scanner, things really start to happen; and it is the |fin_col| routine that - makes them happen. This routine returns |true| if a row as well as a column - has been finished. - -*/ - -boolean fin_col(void) -{ - /*tex the alignrecord after the current one */ - pointer p; - /*tex temporary pointers for list manipulation */ - pointer q, r; - /*tex a new span node */ - pointer s; - /*tex a new unset box */ - pointer u; - /*tex natural width */ - scaled w; - /*tex order of infinity */ - unsigned char o; - /*tex span counter */ - halfword n; - if (cur_align == null) - confusion("endv"); - q = vlink(cur_align); - if (q == null) - confusion("endv"); - if (align_state < 500000) - fatal_error("(interwoven alignment preambles are not allowed)"); - p = vlink(q); - /*tex If the preamble list has been traversed, check that the row has ended. */ - if ((p == null) && (extra_info(cur_align) < cr_code)) { - if (cur_loop != null) { - /*tex Lengthen the preamble periodically: */ - r = new_node(align_record_node, 0); - vlink(q) = r; - /*tex A new align record: */ - p = vlink(q); - span_ptr(p) = end_span; - width(p) = null_flag; - cur_loop = vlink(cur_loop); - /*tex Copy the templates from node |cur_loop| into node |p|. */ - q = hold_token_head; - r = u_part(cur_loop); - while (r != null) { - s = get_avail(); - token_link(q) = s; - q = token_link(q); - token_info(q) = token_info(r); - r = token_link(r); - } - token_link(q) = null; - u_part(p) = token_link(hold_token_head); - q = hold_token_head; - r = v_part(cur_loop); - while (r != null) { - s = get_avail(); - token_link(q) = s; - q = token_link(q); - token_info(q) = token_info(r); - r = token_link(r); - } - token_link(q) = null; - v_part(p) = token_link(hold_token_head); - cur_loop = vlink(cur_loop); - r = new_glue(cur_loop); - vlink(p) = r; - } else { - const char *hlp[] = { - "You have given more \\span or & marks than there were", - "in the preamble to the \\halign or \\valign now in progress.", - "So I'll assume that you meant to type \\cr instead.", - NULL - }; - extra_info(cur_align) = cr_code; - tex_error("Extra alignment tab has been changed to \\cr", hlp); - } - } - if (extra_info(cur_align) != span_code) { - unsave(); - new_save_level(align_group); - /*tex Package an unset box for the current column and record its width. */ - if (cur_list.mode_field == -hmode) { - adjust_tail = cur_tail; - pre_adjust_tail = cur_pre_tail; - u = filtered_hpack(cur_list.head_field, cur_list.tail_field, 0, additional, align_set_group, -1, 0, 0); - w = width(u); - cur_tail = adjust_tail; - adjust_tail = null; - cur_pre_tail = pre_adjust_tail; - pre_adjust_tail = null; - } else { - u = filtered_vpackage(vlink(cur_list.head_field), 0, additional, 0, align_set_group, -1, 0, 0); - w = height(u); - } - /*tex This represents a span count of 1: */ - n = min_quarterword; - if (cur_span != cur_align) { - /*tex Update width entry for spanned columns. */ - q = cur_span; - do { - incr(n); - q = vlink(vlink(q)); - } while (q != cur_align); - if (n > max_quarterword) { - /*tex This can happen, but won't. */ - confusion("too many spans"); - } - q = cur_span; - while (span_span(span_ptr(q)) < n) { - q = span_ptr(q); - } - if (span_span(span_ptr(q)) > n) { - s = new_span_node(span_ptr(q), n, w); - span_ptr(q) = s; - } else if (width(span_ptr(q)) < w) { - width(span_ptr(q)) = w; - } - } else if (w > width(cur_align)) { - width(cur_align) = w; - } - type(u) = unset_node; - span_count(u) = (quarterword) n; - determine_stretch_order(); - glue_order(u) = o; - glue_stretch(u) = total_stretch[o]; - determine_shrink_order(); - glue_sign(u) = o; - glue_shrink(u) = total_shrink[o]; - pop_nest(); - vlink(cur_list.tail_field) = u; - cur_list.tail_field = u; - /*tex Copy the tabskip glue between columns. */ - tail_append(new_glue(vlink(cur_align))); - subtype(cur_list.tail_field) = tab_skip_code + 1; - if (extra_info(cur_align) >= cr_code) { - return true; - } - init_span(p); - } - align_state = 1000000; - do { - get_x_or_protected(); - } while (cur_cmd == spacer_cmd); - cur_align = p; - init_col(); - return false; -} - -/*tex - - A span node is a 3-word record containing |width|, |span_span|, and - |span_ptr| fields. The |span_span| field indicates the number of spanned - columns; the |span_ptr| field points to a span node for the same starting - column, having a greater extent of spanning, or to |end_span|, which has the - largest possible |span_span| field; the |width| field holds the largest - natural width corresponding to a particular set of spanned columns. - - A list of the maximum widths so far, for spanned columns starting at a given - column, begins with the |span_ptr| field of the alignrecord for that column. - The code has to make sure that there is room for |span_ptr| in both the - alignrecord and the span nodes, which is why |span_ptr| replaces |node_attr|. - - The |new_span_node| function is defined in |texnodes.c|. - -*/ - -/*tex This is normally |alink|: */ - -#ifndef span_span -# define span_span(A) vlink((A)+1) -#endif - -/*tex - - At the end of a row, we append an unset box to the current vlist (for - \.{\\halign}) or the current hlist (for \.{\\valign}). This unset box - contains the unset boxes for the columns, separated by the tabskip glue. - Everything will be set later. - -*/ - -void fin_row(void) -{ - /*tex The new unset box: */ - pointer p; - if (cur_list.mode_field == -hmode) { - p = filtered_hpack(cur_list.head_field, cur_list.tail_field, 0, - additional, fin_row_group, -1, 0, 0); - pop_nest(); - if (cur_pre_head != cur_pre_tail) - append_list(cur_pre_head, cur_pre_tail); - append_to_vlist(p,lua_key_index(alignment)); - if (cur_head != cur_tail) - append_list(cur_head, cur_tail); - } else { - p = filtered_vpackage(vlink(cur_list.head_field), - 0, additional, max_depth_par, fin_row_group, -1, 0, 0); - pop_nest(); - vlink(cur_list.tail_field) = p; - cur_list.tail_field = p; - space_factor_par = 1000; - } - type(p) = unset_node; - glue_stretch(p) = 0; - if (every_cr_par != null) - begin_token_list(every_cr_par, every_cr_text); - align_peek(); - /*tex Note that |glue_shrink(p)=0| since |glue_shrink==shift_amount|. */ -} - -/*tex - - Finally, we will reach the end of the alignment, and we can breathe a sigh of - relief that memory hasn't overflowed. All the unset boxes will now be set so - that the columns line up, taking due account of spanned columns. - -*/ - -void fin_align(void) -{ - /*tex registers for the list operations */ - pointer p, q, r, s, u, rr; - /*tex width of column */ - scaled t, w; - /*tex shift offset for unset boxes */ - scaled o; - /*tex matching span amount */ - halfword n; - /*tex temporary storage for |overfull_rule| */ - scaled rule_save; - /*tex temporary storage for |prev_depth| */ - halfword pd; - /*tex temporary storage for |new_glue| */ - halfword ng; - /*tex The |align_group| was for individual entries: */ - if (cur_group != align_group) - confusion("align1"); - unsave(); - /*tex The |align_group| was for the whole alignment: */ - if (cur_group != align_group) - confusion("align0"); - unsave(); - if (nest[nest_ptr - 1].mode_field == mmode) { - o = display_indent_par; - } else { - o = 0; - } - /*tex - - Go through the preamble list, determining the column widths and - changing the alignrecords to dummy unset boxes. - - It's time now to dismantle the preamble list and to compute the - column widths. Let $w_{ij}$ be the maximum of the natural widths of - all entries that span columns $i$ through $j$, inclusive. The - alignrecord for column~$i$ contains $w_{ii}$ in its |width| field, - and there is also a linked list of the nonzero $w_{ij}$ for - increasing $j$, accessible via the |info| field; these span nodes - contain the value $j-i+|min_quarterword|$ in their |link| fields. The - values of $w_{ii}$ were initialized to |null_flag|, which we regard - as $-\infty$. - - The final column widths are defined by the formula $$w_j=\max_{1\L - i\L j}\biggl( w_{ij}-\sum_{i\L k<j}(t_k+w_k)\biggr),$$ where $t_k$ is - the natural width of the tabskip glue between columns $k$ and~$k+1$. - However, if $w_{ij}=-\infty$ for all |i| in the range |1<=i<=j| - (i.e., if every entry that involved column~|j| also involved - column~|j+1|), we let $w_j=0$, and we zero out the tabskip glue after - column~|j|. - - \TeX\ computes these values by using the following scheme: First - $w_1=w_{11}$. Then replace $w_{2j}$ by $\max(w_{2j},w_{1j}-t_1-w_1)$, - for all $j>1$. Then $w_2=w_{22}$. Then replace $w_{3j}$ by - $\max(w_{3j},w_{2j}-t_2-w_2)$ for all $j>2$; and so on. If any $w_j$ - turns out to be $-\infty$, its value is changed to zero and so is the - next tabskip. - - */ - q = vlink(preamble); - do { - flush_list(u_part(q)); - flush_list(v_part(q)); - p = vlink(vlink(q)); - if (width(q) == null_flag) { - /*tex Nullify |width(q)| and the tabskip glue following this column. */ - width(q) = 0; - r = vlink(q); - reset_glue_to_zero(r); - } - if (span_ptr(q) != end_span) { - /*tex - - Merge the widths in the span nodes of |q| with those of |p|, - destroying the span nodes of |q|. - - Merging of two span-node lists is a typical exercise in the - manipulation of linearly linked data structures. The essential - invariant in the following |repeat| loop is that we want to - dispense with node |r|, in |q|'s list, and |u| is its successor; - all nodes of |p|'s list up to and including |s| have been - processed, and the successor of |s| matches |r| or precedes |r| - or follows |r|, according as |link(r)=n| or |link(r)>n| or - |link(r)<n|. - - */ - t = width(q) + width(vlink(q)); - r = span_ptr(q); - s = end_span; - span_ptr(s) = p; - n = min_quarterword + 1; - do { - width(r) = width(r) - t; - u = span_ptr(r); - while (span_span(r) > n) { - s = span_ptr(s); - n = span_span(span_ptr(s)) + 1; - } - if (span_span(r) < n) { - span_ptr(r) = span_ptr(s); - span_ptr(s) = r; - decr(span_span(r)); - s = r; - } else { - if (width(r) > width(span_ptr(s))) - width(span_ptr(s)) = width(r); - flush_node(r); - } - r = u; - } while (r != end_span); - } - type(q) = unset_node; - span_count(q) = min_quarterword; - height(q) = 0; - depth(q) = 0; - glue_order(q) = normal; - glue_sign(q) = normal; - glue_stretch(q) = 0; - glue_shrink(q) = 0; - q = p; - } while (q != null); - /*tex - - Package the preamble list, to determine the actual tabskip glue amounts, - and let |p| point to this prototype box. - - Now the preamble list has been converted to a list of alternating unset - boxes and tabskip glue, where the box widths are equal to the final - column sizes. In case of \.{\\valign}, we change the widths to heights, - so that a correct error message will be produced if the alignment is - overfull or underfull. - - */ - decr(save_ptr); - pack_begin_line = -cur_list.ml_field; - if (cur_list.mode_field == -vmode) { - rule_save = overfull_rule_par; - /*tex Prevent the rule from being packaged. */ - overfull_rule_par = 0; - p = hpack(preamble, saved_value(0), saved_level(0), -1); - overfull_rule_par = rule_save; - } else { - q = vlink(preamble); - do { - height(q) = width(q); - width(q) = 0; - q = vlink(vlink(q)); - } while (q != null); - p = filtered_vpackage(preamble, - saved_value(0), saved_level(0), max_depth_par, preamble_group, -1, 0, 0); - q = vlink(preamble); - do { - width(q) = height(q); - height(q) = 0; - q = vlink(vlink(q)); - } while (q != null); - } - pack_begin_line = 0; - /*tex Set the glue in all the unset boxes of the current list. */ - q = vlink(cur_list.head_field); - s = cur_list.head_field; - while (q != null) { - if (!is_char_node(q)) { - if (type(q) == unset_node) { - /*tex - - We set the unset box |q| and the unset boxes in it. The unset - box |q| represents a row that contains one or more unset - boxes, depending on how soon \.{\\cr} occurred in that row. - - */ - if (cur_list.mode_field == -vmode) { - type(q) = hlist_node; - subtype(q) = align_row_list; - width(q) = width(p); - } else { - type(q) = vlist_node; - subtype(q) = align_row_list; - height(q) = height(p); - } - glue_order(q) = glue_order(p); - glue_sign(q) = glue_sign(p); - glue_set(q) = glue_set(p); - shift_amount(q) = o; - r = vlink(list_ptr(q)); - if (type(r) != unset_node) { - formatted_error("alignment","bad box"); - } - s = vlink(list_ptr(p)); - do { - /*tex - - We set the glue in node |r| and change it from an unset - node. A box made from spanned columns will be followed by - tabskip glue nodes and by empty boxes as if there were no - spanning. This permits perfect alignment of subsequent - entries, and it prevents values that depend on floating - point arithmetic from entering into the dimensions of any - boxes. - - */ - n = span_count(r); - t = width(s); - w = t; - u = hold_head; - while (n > min_quarterword) { - decr(n); - /*tex - - Append tabskip glue and an empty box to list |u|, and - update |s| and |t| as the prototype nodes are passed. - - */ - s = vlink(s); - ng = new_glue(s); - vlink(u) = ng; - u = vlink(u); - subtype(u) = tab_skip_code + 1; - t = t + width(s); - if (glue_sign(p) == stretching) { - if (stretch_order(s) == glue_order(p)) - t = t + round(float_cast(glue_set(p)) * float_cast(stretch(s))); - } else if (glue_sign(p) == shrinking) { - if (shrink_order(s) == glue_order(p)) - t = t - round(float_cast(glue_set(p)) * float_cast(shrink(s))); - } - s = vlink(s); - rr = new_null_box(); - vlink(u) = rr; - u = vlink(u); - t = t + width(s); - subtype(u) = align_cell_list; - if (cur_list.mode_field == -vmode) { - width(u) = width(s); - } else { - type(u) = vlist_node; - height(u) = width(s); - } - } - if (cur_list.mode_field == -vmode) { - /*tex - - Make the unset node |r| into an |hlist_node| of width - |w|, setting the glue as if the width were |t|. - - */ - height(r) = height(q); - depth(r) = depth(q); - if (t == width(r)) { - glue_sign(r) = normal; - glue_order(r) = normal; - set_glue_ratio_zero(glue_set(r)); - } else if (t > width(r)) { - glue_sign(r) = stretching; - if (glue_stretch(r) == 0) - set_glue_ratio_zero(glue_set(r)); - else - glue_set(r) = unfloat((double) (t - width(r)) / glue_stretch(r)); - } else { - glue_order(r) = glue_sign(r); - glue_sign(r) = shrinking; - if (glue_shrink(r) == 0) - set_glue_ratio_zero(glue_set(r)); - else if ((glue_order(r) == normal) && (width(r) - t > glue_shrink(r))) - set_glue_ratio_one(glue_set(r)); - else - glue_set(r) = unfloat((double) (width(r) - t) / glue_shrink(r)); - } - width(r) = w; - type(r) = hlist_node; - subtype(r) = align_cell_list; - - } else { - /*tex - - Make the unset node |r| into a |vlist_node| of height - |w|, setting the glue as if the height were |t|. - - */ - width(r) = width(q); - if (t == height(r)) { - glue_sign(r) = normal; - glue_order(r) = normal; - set_glue_ratio_zero(glue_set(r)); - } else if (t > height(r)) { - glue_sign(r) = stretching; - if (glue_stretch(r) == 0) - set_glue_ratio_zero(glue_set(r)); - else - glue_set(r) = unfloat((t - height(r)) / glue_stretch(r)); - } else { - glue_order(r) = glue_sign(r); - glue_sign(r) = shrinking; - if (glue_shrink(r) == 0) - set_glue_ratio_zero(glue_set(r)); - else if ((glue_order(r) == normal) && (height(r) - t > glue_shrink(r))) - set_glue_ratio_one(glue_set(r)); - else - glue_set(r) = unfloat((height(r) - t) / glue_shrink(r)); - } - height(r) = w; - type(r) = vlist_node; - subtype(r) = align_cell_list; - } - shift_amount(r) = 0; - if (u != hold_head) { - /*tex Append blank boxes to account for spanned nodes. */ - vlink(u) = vlink(r); - vlink(r) = vlink(hold_head); - r = u; - } - - r = vlink(vlink(r)); - s = vlink(vlink(s)); - } while (r != null); - - } else if (type(q) == rule_node) { - /*tex - - Make the running dimensions in rule |q| extend to the - boundaries of the alignment. - - */ - if (is_running(width(q))) - width(q) = width(p); - if (is_running(height(q))) - height(q) = height(p); - if (is_running(depth(q))) - depth(q) = depth(p); - if (o != 0) { - r = vlink(q); - vlink(q) = null; - q = hpack(q, 0, additional, -1); - shift_amount(q) = o; - subtype(q) = align_cell_list; - vlink(q) = r; - vlink(s) = q; - } - } - } - s = q; - q = vlink(q); - } - flush_node_list(p); - pop_alignment(); - /*tex - - We now have a completed alignment, in the list that starts at - |cur_list.head_field| and ends at |cur_list.tail_field|. This list will - be merged with the one that encloses it. (In case the enclosing mode is - |mmode|, for displayed formulas, we will need to insert glue before and - after the display; that part of the program will be deferred until we're - more familiar with such operations.) - - */ - pd = prev_depth_par; - p = vlink(cur_list.head_field); - q = cur_list.tail_field; - pop_nest(); - if (cur_list.mode_field == mmode) { - finish_display_alignment(p, q, pd); - } else { - prev_depth_par = pd; - vlink(cur_list.tail_field) = p; - if (p != null) - cur_list.tail_field = q; - if (cur_list.mode_field == vmode) { - if (!output_active) - lua_node_filter_s(buildpage_filter_callback,lua_key_index(alignment)); - build_page(); - } - } -} - -/*tex - - The token list |omit_template| just referred to is a constant token list that - contains the special control sequence \.{\\endtemplate} only. - -*/ - -void initialize_alignments(void) -{ - token_info(omit_template) = end_template_token; - span_span(end_span) = max_quarterword + 1; - span_ptr(end_span) = null; -} diff --git a/Build/source/texk/web2c/luatexdir/tex/align.h b/Build/source/texk/web2c/luatexdir/tex/align.h deleted file mode 100644 index a93539f0dc5..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/align.h +++ /dev/null @@ -1,54 +0,0 @@ -/* align.h - - Copyright 2009 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ - - -#ifndef ALIGN_H -# define ALIGN_H 1 - -/* We enter `\.{\\span}' into |eqtb| with |tab_mark| as its command code, -and with |span_code| as the command modifier. This makes \TeX\ interpret it -essentially the same as an alignment delimiter like `\.\&', yet it is -recognizably different when we need to distinguish it from a normal delimiter. -It also turns out to be useful to give a special |cr_code| to `\.{\\cr}', -and an even larger |cr_cr_code| to `\.{\\crcr}'. - -The end of a template is represented by two ``frozen'' control sequences -called \.{\\endtemplate}. The first has the command code |end_template|, which -is |>outer_call|, so it will not easily disappear in the presence of errors. -The |get_x_token| routine converts the first into the second, which has |endv| -as its command code. -*/ - -# define tab_mark_cmd_code 1114113 /* {|biggest_char+2|} */ -# define span_code 1114114 /* {|biggest_char+3|} */ -# define cr_code (span_code+1) /* distinct from |span_code| and from any character */ -# define cr_cr_code (cr_code+1) /* this distinguishes \.{\\crcr} from \.{\\cr} */ - - -extern void init_align(void); -extern void initialize_alignments(void); - -extern boolean fin_col(void); -extern void fin_row(void); - -extern void align_peek(void); -extern void insert_vj_template(void); - - -#endif diff --git a/Build/source/texk/web2c/luatexdir/tex/arithmetic.c b/Build/source/texk/web2c/luatexdir/tex/arithmetic.c deleted file mode 100644 index 2782c253400..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/arithmetic.c +++ /dev/null @@ -1,815 +0,0 @@ -/* - -arithmetic.w - -Copyright 2009-2010 Taco Hoekwater <taco@@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your -option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU General Public License along -with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" - -/*tex - -The principal computations performed by \TeX\ are done entirely in terms of -integers less than $2^{31}$ in magnitude; and divisions are done only when both -dividend and divisor are nonnegative. Thus, the arithmetic specified in this -program can be carried out in exactly the same way on a wide variety of -computers, including some small ones. Why? Because the arithmetic calculations -need to be spelled out precisely in order to guarantee that \TeX\ will produce -identical output on different machines. If some quantities were rounded -differently in different implementations, we would find that line breaks and even -page breaks might occur in different places. Hence the arithmetic of \TeX\ has -been designed with care, and systems that claim to be implementations of \TeX82 -should follow precisely the @:TeX82}{\TeX82@> calculations as they appear in the -present program. - -Actually there are three places where \TeX\ uses |div| with a possibly negative -numerator. These are harmless; see |div| in the index. Also if the user sets the -\.{\\time} or the \.{\\year} to a negative value, some diagnostic information -will involve negative-numerator division. The same remarks apply for |mod| as -well as for |div|. - -Here is a routine that calculates half of an integer, using an unambiguous -convention with respect to signed odd numbers. - -*/ - -int half(int x) -{ - if (odd(x)) - return ((x + 1) / 2); - else - return (x / 2); -} - -/*tex - -The following function is used to create a scaled integer from a given decimal -fraction $(.d_0d_1\ldots d_{k-1})$, where |0<=k<=17|. The digit $d_i$ is -given in |dig[i]|, and the calculation produces a correctly rounded result. - -*/ - -scaled round_decimals(int k) -{ - int a = 0; - while (k-- > 0) { - a = (a + dig[k] * two) / 10; - } - return ((a + 1) / 2); -} - -/*tex - -Conversely, here is a procedure analogous to |print_int|. If the output of this -procedure is subsequently read by \TeX\ and converted by the |round_decimals| -routine above, it turns out that the original value will be reproduced exactly; -the ``simplest'' such decimal number is output, but there is always at least one -digit following the decimal point. - -The invariant relation in the \&{repeat} loop is that a sequence of decimal -digits yet to be printed will yield the original number if and only if they form -a fraction~$f$ in the range $s-\delta\L10\cdot2^{16}f<s$. We can stop if and only -if $f=0$ satisfies this condition; the loop will terminate before $s$ can -possibly become zero. - -The next one prints a scaled real, rounded to five digits. - -*/ - -void print_scaled(scaled s) -{ - /*tex The amount of allowable inaccuracy: */ - scaled delta; - char buffer[20]; - int i = 0; - if (s < 0) { - /*tex Print the sign, if negative. */ - print_char('-'); - negate(s); - } - /*tex Print the integer part. */ - print_int(s / unity); - buffer[i++] = '.'; - s = 10 * (s % unity) + 5; - delta = 10; - do { - if (delta > unity) { - /*tex Round the last digit. */ - s = s + 0100000 - 50000; - } - buffer[i++] = '0' + (s / unity); - s = 10 * (s % unity); - delta = delta * 10; - } while (s > delta); - buffer[i++] = '\0'; - tprint(buffer); -} - -/*tex - -Physical sizes that a \TeX\ user specifies for portions of documents are -represented internally as scaled points. Thus, if we define an `sp' (scaled -@^sp@> point) as a unit equal to $2^{-16}$ printer's points, every dimension -inside of \TeX\ is an integer number of sp. There are exactly 4,736,286.72 sp per -inch. Users are not allowed to specify dimensions larger than $2^{30}-1$ sp, -which is a distance of about 18.892 feet (5.7583 meters); two such quantities can -be added without overflow on a 32-bit computer. - -The present implementation of \TeX\ does not check for overflow when @^overflow -in arithmetic@> dimensions are added or subtracted. This could be done by -inserting a few dozen tests of the form `\ignorespaces|if x>=010000000000 then -@t\\{report\_overflow}@>|', but the chance of overflow is so remote that such -tests do not seem worthwhile. - -\TeX\ needs to do only a few arithmetic operations on scaled quantities, other -than addition and subtraction, and the following subroutines do most of the work. -A single computation might use several subroutine calls, and it is desirable to -avoid producing multiple error messages in case of arithmetic overflow; so the -routines set the global variable |arith_error| to |true| instead of reporting -errors directly to the user. Another global variable, |tex_remainder|, holds the -remainder after a division. - -*/ - -/*tex Has arithmetic overflow occurred recently? */ - -boolean arith_error; - -/*tex The amount subtracted to get an exact division. */ - -scaled tex_remainder; - -/*tex - - The first arithmetical subroutine we need computes $nx+y$, where |x| -and~|y| are |scaled| and |n| is an integer. We will also use it to -multiply integers. - -*/ - -scaled mult_and_add(int n, scaled x, scaled y, scaled max_answer) -{ - if (n == 0) - return y; - if (n < 0) { - negate(x); - negate(n); - } - if (((x <= (max_answer - y) / n) && (-x <= (max_answer + y) / n))) { - return (n * x + y); - } else { - arith_error = true; - return 0; - } -} - -/*tex - -We also need to divide scaled dimensions by integers. - -*/ - -scaled x_over_n(scaled x, int n) -{ - /*tex Should |tex_remainder| be negated? */ - boolean negative = false; - if (n == 0) { - arith_error = true; - tex_remainder = x; - return 0; - } else { - if (n < 0) { - negate(x); - negate(n); - negative = true; - } - if (x >= 0) { - tex_remainder = x % n; - if (negative) - negate(tex_remainder); - return (x / n); - } else { - tex_remainder = -((-x) % n); - if (negative) - negate(tex_remainder); - return (-((-x) / n)); - } - } -} - -/*tex - -Then comes the multiplication of a scaled number by a fraction |n/d|, where |n| -and |d| are nonnegative integers |<=@t$2^{16}$@>| and |d| is positive. It would -be too dangerous to multiply by~|n| and then divide by~|d|, in separate -operations, since overflow might well occur; and it would be too inaccurate to -divide by |d| and then multiply by |n|. Hence this subroutine simulates -1.5-precision arithmetic. - -*/ - -scaled xn_over_d(scaled x, int n, int d) -{ - nonnegative_integer t, u, v, xx, dd; - boolean positive = true; - if (x < 0) { - negate(x); - positive = false; - } - xx = (nonnegative_integer) x; - dd = (nonnegative_integer) d; - t = ((xx % 0100000) * (nonnegative_integer) n); - u = ((xx / 0100000) * (nonnegative_integer) n + (t / 0100000)); - v = (u % dd) * 0100000 + (t % 0100000); - if (u / dd >= 0100000) - arith_error = true; - else - u = 0100000 * (u / dd) + (v / dd); - if (positive) { - tex_remainder = (int) (v % dd); - return (scaled) u; - } else { - /*tex The casts are for ms cl. */ - tex_remainder = -(int) (v % dd); - return -(scaled) (u); - } -} - -/*tex - -The next subroutine is used to compute the ``badness'' of glue, when a total~|t| -is supposed to be made from amounts that sum to~|s|. According to {\sl The \TeX -book}, the badness of this situation is $100(t/s)^3$; however, badness is simply -a heuristic, so we need not squeeze out the last drop of accuracy when computing -it. All we really want is an approximation that has similar properties. -@:TeXbook}{\sl The \TeX book@> - -The actual method used to compute the badness is easier to read from the program -than to describe in words. It produces an integer value that is a reasonably -close approximation to $100(t/s)^3$, and all implementations of \TeX\ should use -precisely this method. Any badness of $2^{13}$ or more is treated as infinitely -bad, and represented by 10000. - -It is not difficult to prove that $$\hbox{|badness(t+1,s)>=badness(t,s) ->= badness(t,s+1)|}.$$ The badness function defined here is capable of computing -at most 1095 distinct values, but that is plenty. - -*/ - -halfword badness(scaled t, scaled s) -{ - /*tex Approximation to $\alpha t/s$, where $\alpha^3\approx 100\cdot2^{18}$ */ - int r; - if (t == 0) { - return 0; - } else if (s <= 0) { - return inf_bad; - } else { - /*tex $297^3=99.94\times2^{18}$ */ - if (t <= 7230584) { - r = (t * 297) / s; - } else if (s >= 1663497) { - r = t / (s / 297); - } else { - r = t; - } - if (r > 1290) { - /*tex $1290^3<2^{31}<1291^3$ */ - return inf_bad; - } else { - /*tex This is $r^3/2^{18}$, rounded to the nearest integer. */ - return ((r * r * r + 0400000) / 01000000); - } - } -} - -/*tex - -When \TeX\ ``packages'' a list into a box, it needs to calculate the -proportionality ratio by which the glue inside the box should stretch or shrink. -This calculation does not affect \TeX's decision making, so the precise details -of rounding, etc., in the glue calculation are not of critical importance for the -consistency of results on different computers. - -We shall use the type |glue_ratio| for such proportionality ratios. A glue ratio -should take the same amount of memory as an |integer| (usually 32 bits) if it is -to blend smoothly with \TeX's other data structures. Thus |glue_ratio| should be -equivalent to |short_real| in some implementations of PASCAL. Alternatively, it -is possible to deal with glue ratios using nothing but fixed-point arithmetic; -see {\sl TUGboat \bf3},1 (March 1982), 10--27. (But the routines cited there must -be modified to allow negative glue ratios.) @^system dependencies@> - -*/ - -/* - -This section is (almost) straight from MetaPost. I (Taco) had to change the types -(use |integer| instead of |fraction|), but that should not have any influence on -the actual calculations (the original comments refer to quantities like -|fraction_four| ($2^{30}$), and that is the same as the numeric representation of -|max_dimen|). - -I've copied the low-level variables and routines that are needed, but only those -(e.g. |m_log|), not the accompanying ones like |m_exp|. Most of the following -low-level numeric routines are only needed within the calculation of |norm_rand|. -I've been forced to rename |make_fraction| to |make_frac| because TeX already has -a routine by that name with a wholly different function (it creates a -|fraction_noad| for math typesetting) - -And now let's complete our collection of numeric utility routines by considering -random number generation. \MP{} generates pseudo-random numbers with the additive -scheme recommended in Section 3.6 of {\sl The Art of Computer Programming}; -however, the results are random fractions between 0 and |fraction_one-1|, -inclusive. - -There's an auxiliary array |randoms| that contains 55 pseudo-random fractions. -Using the recurrence $x_n=(x_{n-55}-x_{n-31})\bmod 2^{28}$, we generate batches -of 55 new $x_n$'s at a time by calling |new_randoms|. The global variable -|j_random| tells which element has most recently been consumed. - -*/ - -/*tex The last 55 random values generated: */ - -static int randoms[55]; - -/*tex The number of unused |randoms|: */ - -static int j_random; - -/*tex The default random seed: */ - -scaled random_seed; - -/*tex A small bit of \METAPOST\ is needed. */ - -#define fraction_half 01000000000 /* $2^{27} $, represents 0.50000000 */ -#define fraction_one 02000000000 /* $2^{28} $, represents 1.00000000 */ -#define fraction_four 010000000000 /* $2^{30} $, represents 4.00000000 */ -#define el_gordo 017777777777 /* $2^{31}-1$, the largest value that \MP\ likes */ - -/*tex - -The |make_frac| routine produces the |fraction| equivalent of |p/q|, given -integers |p| and~|q|; it computes the integer -$f=\lfloor2^{28}p/q+{1\over2}\rfloor$, when $p$ and $q$ are positive. If |p| and -|q| are both of the same scaled type |t|, the ``type relation'' -|make_frac(t,t)=fraction| is valid; and it's also possible to use the subroutine -``backwards,'' using the relation |make_frac(t,fraction)=t| between scaled types. - -If the result would have magnitude $2^{31}$ or more, |make_frac| sets -|arith_error:=true|. Most of \MP's internal computations have been designed to -avoid this sort of error. - -If this subroutine were programmed in assembly language on a typical machine, we -could simply compute |(@t$2^{28}$@>*p)div q|, since a double-precision product -can often be input to a fixed-point division instruction. But when we are -restricted to PASCAL arithmetic it is necessary either to resort to -multiple-precision maneuvering or to use a simple but slow iteration. The -multiple-precision technique would be about three times faster than the code -adopted here, but it would be comparatively long and tricky, involving about -sixteen additional multiplications and divisions. - -This operation is part of \MP's ``inner loop''; indeed, it will consume nearly -10\%! of the running time (exclusive of input and output) if the code below is -left unchanged. A machine-dependent recoding will therefore make \MP\ run faster. -The present implementation is highly portable, but slow; it avoids multiplication -and division except in the initial stage. System wizards should be careful to -replace it with a routine that is guaranteed to produce identical results in all -cases. @^system dependencies@> - -As noted below, a few more routines should also be replaced by machine-dependent -code, for efficiency. But when a procedure is not part of the ``inner loop,'' -such changes aren't advisable; simplicity and robustness are preferable to -trickery, unless the cost is too high. - -*/ - -static int make_frac(int p, int q) -{ - /*tex The fraction bits, with a leading 1 bit: */ - int f; - /*tex The integer part of $\vert p/q\vert$: */ - int n; - /*tex Disables certain compiler optimizations: */ - register int be_careful; - /*tex Should the result be negated? */ - boolean negative = false; - if (p < 0) { - negate(p); - negative = true; - } - if (q <= 0) { - negate(q); - negative = !negative; - } - n = p / q; - p = p % q; - if (n >= 8) { - arith_error = true; - if (negative) - return (-el_gordo); - else - return el_gordo; - } else { - n = (n - 1) * fraction_one; - /*tex_remainder - - Compute $f=\lfloor 2^{28}(1+p/q)+{1\over2}\rfloor$. The |repeat| loop - here preserves the following invariant relations between |f|, |p|, - and~|q|: (i)~|0<=p<q|; (ii)~$fq+p=2^k(q+p_0)$, where $k$ is an - integer and $p_0$ is the original value of~$p$. - - Notice that the computation specifies |(p-q)+p| instead of |(p+p)-q|, - because the latter could overflow. Let us hope that optimizing - compilers do not miss this point; a special variable |be_careful| is - used to emphasize the necessary order of computation. Optimizing - compilers should keep |be_careful| in a register, not store it in - memory. - - */ - f = 1; - do { - be_careful = p - q; - p = be_careful + p; - if (p >= 0) - f = f + f + 1; - else { - f += f; - p = p + q; - } - } while (f < fraction_one); - be_careful = p - q; - if (be_careful + p >= 0) - incr(f); - - if (negative) - return (-(f + n)); - else - return (f + n); - } -} - -static int take_frac(int q, int f) -{ - /*tex The fraction so far: */ - int p; - /*tex Additional multiple of $q$: */ - int n; - /*tex Disables certain compiler optimizations. */ - register int be_careful; - /*tex Should the result be negated? */ - boolean negative = false; - /*tex Reduce to the case that |f>=0| and |q>0|. */ - if (f < 0) { - negate(f); - negative = true; - } - if (q < 0) { - negate(q); - negative = !negative; - } - if (f < fraction_one) { - n = 0; - } else { - n = f / fraction_one; - f = f % fraction_one; - if (q <= el_gordo / n) { - n = n * q; - } else { - arith_error = true; - n = el_gordo; - } - } - f = f + fraction_one; - /*tex - - Compute $p=\lfloor qf/2^{28}+{1\over2}\rfloor-q$. The invariant relations - in this case are (i)~$\lfloor(qf+p)/2^k\rfloor =\lfloor - qf_0/2^{28}+{1\over2}\rfloor$, where $k$ is an integer and $f_0$ is the - original value of~$f$; (ii)~$2^k\L f<2^{k+1}$. - - Here |p| becomes $2^{27}$; the invariants hold now with $k=28$: - - */ - p = fraction_half; - if (q < fraction_four) { - do { - if (odd(f)) - p = halfp(p + q); - else - p = halfp(p); - f = halfp(f); - } while (f != 1); - } else { - do { - if (odd(f)) - p = p + halfp(q - p); - else - p = halfp(p); - f = halfp(f); - } while (f != 1); - } - be_careful = n - el_gordo; - if (be_careful + p > 0) { - arith_error = true; - n = el_gordo - p; - } - if (negative) - return (-(n + p)); - else - return (n + p); -} - -/*tex - -The subroutines for logarithm and exponential involve two tables. The first is -simple: |two_to_the[k]| equals $2^k$. The second involves a bit more calculation, -which the author claims to have done correctly: |spec_log[k]| is $2^{27}$ times -$\ln\bigl(1/(1-2^{-k})\bigr)= 2^{-k}+{1\over2}2^{-2k}+{1\over3}2^{-3k}+\cdots\,$, -rounded to the nearest integer. - -*/ - -/*tex The powers of two: */ - -static int two_to_the[31]; - -/*tex Special logarithms: */ - -static int spec_log[29]; - -void initialize_arithmetic(void) -{ - int k; - two_to_the[0] = 1; - for (k = 1; k <= 30; k++) { - two_to_the[k] = 2 * two_to_the[k - 1]; - } - spec_log [1] = 93032640; - spec_log [2] = 38612034; - spec_log [3] = 17922280; - spec_log [4] = 8662214; - spec_log [5] = 4261238; - spec_log [6] = 2113709; - spec_log [7] = 1052693; - spec_log [8] = 525315; - spec_log [9] = 262400; - spec_log[10] = 131136; - spec_log[11] = 65552; - spec_log[12] = 32772; - spec_log[13] = 16385; - for (k = 14; k <= 27; k++) { - spec_log[k] = two_to_the[27 - k]; - } - spec_log[28] = 1; -} - -static int m_log(int x) -{ - /*tex Auxiliary registers: */ - int y, z; - /*tex Iteration counter: */ - int k; - if (x <= 0) { - /*tex Handle non-positive logarithm. */ - print_err("Logarithm of "); - print_scaled(x); - tprint(" has been replaced by 0"); - help2( - "Since I don't take logs of non-positive numbers,", - "I'm zeroing this one. Proceed, with fingers crossed." - ); - error(); - return 0; - } else { - /*tex $14\times2^{27}\ln2\approx1302456956.421063$ */ - y = 1302456956 + 4 - 100; - /*tex $2^{16}\times .421063\approx 27595$ */ - z = 27595 + 6553600; - while (x < fraction_four) { - x += x; - /*tex $2^{27}\ln2\approx 93032639.74436163$ */ - y = y - 93032639; - /*tex $2^{16}\times.74436163\approx 48782$ */ - z = z - 48782; - } - - y = y + (z / unity); - k = 2; - while (x > fraction_four + 4) { - /*tex - Increase |k| until |x| can be multiplied by a factor of $2^{-k}$, - and adjust $y$ accordingly. Here $z=\lceil x/2^k\rceil$. - */ - z = ((x - 1) / two_to_the[k]) + 1; - while (x < fraction_four + z) { - z = halfp(z + 1); - k = k + 1; - } - y = y + spec_log[k]; - x = x - z; - } - return (y / 8); - } -} - -/*tex - -The following somewhat different subroutine tests rigorously if $ab$ is greater -than, equal to, or less than~$cd$, given integers $(a,b,c,d)$. In most cases a -quick decision is reached. The result is $+1$, 0, or~$-1$ in the three respective -cases. - -*/ - -static int ab_vs_cd(int a, int b, int c, int d) -{ - int q, r; - /*tex Reduce to the case that |a,c>=0| and |b,d>0|. */ - if (a < 0) { - negate(a); - negate(b); - } - if (c < 0) { - negate(c); - negate(d); - } - if (d <= 0) { - if (b >= 0) - return (((a == 0 || b == 0) && (c == 0 || d == 0)) ? 0 : 1); - if (d == 0) - return (a == 0 ? 0 : -1); - q = a; - a = c; - c = q; - q = -b; - b = -d; - d = q; - } else if (b <= 0) { - if (b < 0 && a > 0) - return -1; - return (c == 0 ? 0 : -1); - } - while (1) { - q = a / d; - r = c / b; - if (q != r) - return (q > r ? 1 : -1); - q = a % d; - r = c % b; - if (r == 0) - return (q == 0 ? 0 : 1); - if (q == 0) - return -1; - a = b; - b = q; - c = d; - d = r; - /*tex Now |a>d>0| and |c>b>0|. */ - } -} - -/*tex - -To consume a random integer, the program below will say `|next_random|' and then -it will fetch |randoms[j_random]|. - -*/ - -#define next_random() do { \ - if (j_random==0) \ - new_randoms(); \ - else \ - decr(j_random); \ -} while (0) - -static void new_randoms(void) -{ - /*tex The index into |randoms|. */ - int k; - /*tex The accumulator. */ - int x; - for (k = 0; k <= 23; k++) { - x = randoms[k] - randoms[k + 31]; - if (x < 0) - x = x + fraction_one; - randoms[k] = x; - } - for (k = 24; k <= 54; k++) { - x = randoms[k] - randoms[k - 24]; - if (x < 0) - x = x + fraction_one; - randoms[k] = x; - } - j_random = 54; -} - -/*tex - -To initialize the |randoms| table, we call the following routine. - -*/ - -void init_randoms(int seed) -{ - /*tex Three more or less random integers. */ - int j, jj, k; - /*tex The index into |randoms|. */ - int i; - j = abs(seed); - while (j >= fraction_one) - j = halfp(j); - k = 1; - for (i = 0; i <= 54; i++) { - jj = k; - k = j - k; - j = jj; - if (k < 0) - k = k + fraction_one; - randoms[(i * 21) % 55] = j; - } - /*tex We ``warm up'' the array. */ - new_randoms(); - new_randoms(); - new_randoms(); -} - -/*tex - -To produce a uniform random number in the range |0<=u<x| or |0>=u>x| or |0=u=x|, -given a |scaled| value~|x|, we proceed as shown here. - -Note that the call of |take_frac| will produce the values 0 and~|x| with about -half the probability that it will produce any other particular values between 0 -and~|x|, because it rounds its answers. - -*/ - -int unif_rand(int x) -{ - int y; - next_random(); - y = take_frac(abs(x), randoms[j_random]); - if (y == abs(x)) - return 0; - else if (x > 0) - return y; - else - return -y; -} - -/*tex - -Finally, a normal deviate with mean zero and unit standard deviation can readily -be obtained with the ratio method (Algorithm 3.4.1R in {\sl The Art of Computer -Programming\/}. - -*/ - -int norm_rand(void) -{ - /*tex What the book would call $2^{16}X$, $2^{28}U$, and $-2^{24}\ln U$. */ - int x, u, l; - do { - do { - next_random(); - x = take_frac(112429, randoms[j_random] - fraction_half); - /*tex Which is $2^{16}\sqrt{8/e}\approx 112428.82793$. */ - next_random(); - u = randoms[j_random]; - } while (abs(x) >= u); - x = make_frac(x, u); - /*tex More fuzzyness: $2^{24}\cdot12\ln2\approx139548959.6165$. */ - l = 139548960 - m_log(u); - } while (ab_vs_cd(1024, l, x, x) < 0); - return x; -} - -/*tex - -This function could also be expressed as a macro, but it is a useful breakpoint -for debugging. - -*/ - -int fix_int(int val, int min, int max) -{ - return (val < min ? min : (val > max ? max : val)); -} diff --git a/Build/source/texk/web2c/luatexdir/tex/arithmetic.h b/Build/source/texk/web2c/luatexdir/tex/arithmetic.h deleted file mode 100644 index e5638990e0c..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/arithmetic.h +++ /dev/null @@ -1,80 +0,0 @@ -/* arithmetic.h - - Copyright 2009 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ - - -#ifndef ARITHMETIC_H -# define ARITHMETIC_H - -/* |incr| and |decr| are in texmfmp.h */ - - /* #define incr(A) (A)++ *//* increase a variable by unity */ - /* #define decr(A) (A)-- *//* decrease a variable by unity */ - -# define negate(A) (A)=-(A) /* change the sign of a variable */ - -# undef half -extern int half(int x); - -/* -Fixed-point arithmetic is done on {\sl scaled integers\/} that are multiples -of $2^{-16}$. In other words, a binary point is assumed to be sixteen bit -positions from the right end of a binary computer word. -*/ - -# define unity 0200000 /* $2^{16}$, represents 1.00000 */ -# define two 0400000 /* $2^{17}$, represents 2.00000 */ - -typedef unsigned int nonnegative_integer; /* $0\L x<2^{31}$ */ - -extern scaled round_decimals(int k); -extern void print_scaled(scaled s); - -extern boolean arith_error; -extern scaled tex_remainder; - -extern scaled mult_and_add(int n, scaled x, scaled y, scaled max_answer); - -# define nx_plus_y(A,B,C) mult_and_add((A),(B),(C),07777777777) -# define mult_integers(A,B) mult_and_add((A),(B),0,017777777777) - -extern scaled x_over_n(scaled x, int n); -extern scaled xn_over_d(scaled x, int n, int d); - -# define inf_bad 10000 /* infinitely bad value */ - -extern halfword badness(scaled t, scaled s); - -# define set_glue_ratio_zero(A) (A)=0.0 /* store the representation of zero ratio */ -# define set_glue_ratio_one(A) (A)=1.0 /* store the representation of unit ratio */ -# define float_cast(A) (float)(A) /* convert from |glue_ratio| to type |real| */ -# define unfloat(A) (glue_ratio)(A) /* convert from |real| to type |glue_ratio| */ -# define float_constant(A) (float)A /* convert |integer| constant to |real| */ -# define float_round round - -extern void initialize_arithmetic(void); - -extern scaled random_seed; /* the default random seed */ - -extern void init_randoms(int seed); -extern int unif_rand(int x); -extern int norm_rand(void); - -extern int fix_int(int val, int min, int max); - -#endif diff --git a/Build/source/texk/web2c/luatexdir/tex/backend.c b/Build/source/texk/web2c/luatexdir/tex/backend.c deleted file mode 100644 index 3115a88a7e3..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/backend.c +++ /dev/null @@ -1,124 +0,0 @@ -/* to fill */ - -#include "ptexlib.h" - -scaled max_v = 0; /* maximum height-plus-depth of pages shipped so far */ -scaled max_h = 0; /* maximum width of pages shipped so far */ -boolean doing_leaders = false; /* are we inside a leader box? */ -int cur_s = -1; /* current depth of output box nesting, initially $-1$ */ - -static backend_struct *backend = NULL; -backend_function *backend_out, *backend_out_whatsit, *backend_out_control; - -static void missing_backend_function(PDF pdf, halfword p) -{ - const char *n = get_node_name(type(p), subtype(p)); - if (type(p) == whatsit_node) - formatted_error("pdf backend","no output function for whatsit %s",n); - else - formatted_error("pdf backend","no output function for node %s",n); -} - -static void init_none_backend_functions(void) -{ - backend_struct *p = &backend[OMODE_NONE]; - p->name = strdup("NONE"); -} - -static void init_pdf_backend_functions(void) -{ - backend_struct *p = &backend[OMODE_PDF]; - p->name = strdup("PDF"); - p->node_fu[rule_node] = &pdf_place_rule; - p->node_fu[glyph_node] = &pdf_place_glyph; - p->whatsit_fu[special_node] = &pdf_special; - p->whatsit_fu[pdf_literal_node] = &pdf_out_literal; - p->whatsit_fu[pdf_refobj_node] = &pdf_ref_obj; - p->whatsit_fu[pdf_annot_node] = &do_annot; - p->whatsit_fu[pdf_start_link_node] = &do_link; - p->whatsit_fu[pdf_end_link_node] = &end_link; - p->whatsit_fu[pdf_dest_node] = &do_dest; - p->whatsit_fu[pdf_thread_node] = &do_thread; - p->whatsit_fu[pdf_end_thread_node] = &end_thread; - p->whatsit_fu[late_lua_node] = &late_lua; - p->whatsit_fu[pdf_colorstack_node] = &pdf_out_colorstack; - p->whatsit_fu[pdf_setmatrix_node] = &pdf_out_setmatrix; - p->whatsit_fu[pdf_save_node] = &pdf_out_save; - p->whatsit_fu[pdf_restore_node] = &pdf_out_restore; - p->whatsit_fu[pdf_link_state_node] = &pdf_out_link_state; - p->control_fu[backend_control_push_list] = &pdf_push_list; - p->control_fu[backend_control_pop_list] = &pdf_pop_list; - p->control_fu[backend_control_begin_page] = &pdf_begin_page; - p->control_fu[backend_control_end_page] = &pdf_end_page; - p->control_fu[backend_control_open_file] = &pdf_open_file; - p->control_fu[backend_control_write_header] = &pdf_write_header; - p->control_fu[backend_control_finish_file] = &pdf_finish_file; - p->control_fu[backend_control_set_reference_point] = &pdf_set_reference_point; -} - -static void init_dvi_backend_functions(void) -{ - backend_struct *p = &backend[OMODE_DVI]; - p->name = strdup("DVI"); - p->node_fu[rule_node] = &dvi_place_rule; - p->node_fu[glyph_node] = &dvi_place_glyph; - p->whatsit_fu[special_node] = &dvi_special; - p->whatsit_fu[late_lua_node] = &late_lua; - p->control_fu[backend_control_push_list] = &dvi_push_list; - p->control_fu[backend_control_pop_list] = &dvi_pop_list; - p->control_fu[backend_control_begin_page] = &dvi_begin_page; - p->control_fu[backend_control_end_page] = &dvi_end_page; - p->control_fu[backend_control_open_file] = &dvi_open_file; - p->control_fu[backend_control_write_header] = &dvi_write_header; - p->control_fu[backend_control_finish_file] = &dvi_finish_file; - p->control_fu[backend_control_set_reference_point] = &dvi_set_reference_point; -} - - -void init_backend_functionpointers(output_mode o_mode) -{ - int i, j; - if (backend == NULL) { - backend = xmalloc((MAX_OMODE + 1) * sizeof(backend_struct)); - for (i = 0; i <= MAX_OMODE; i++) { - backend[i].node_fu = xmalloc((MAX_NODE_TYPE + 1) * sizeof(backend_function)); - backend[i].whatsit_fu = xmalloc((MAX_WHATSIT_TYPE + 1) * sizeof(backend_function)); - backend[i].control_fu = xmalloc((MAX_CONTROL_TYPE + 1) * sizeof(backend_function)); - for (j = 0; j < MAX_NODE_TYPE + 1; j++) - backend[i].node_fu[j] = &missing_backend_function; - for (j = 0; j < MAX_WHATSIT_TYPE + 1; j++) - backend[i].whatsit_fu[j] = &missing_backend_function; - for (j = 0; j < MAX_CONTROL_TYPE + 1; j++) - backend[i].control_fu[j] = &missing_backend_function; - } - init_none_backend_functions(); - init_dvi_backend_functions(); - init_pdf_backend_functions(); - } - backend_out = backend[o_mode].node_fu; - backend_out_whatsit = backend[o_mode].whatsit_fu; - backend_out_control = backend[o_mode].control_fu; -} - -output_mode get_o_mode(void) -{ - output_mode o_mode; - if (output_mode_par > 0) { - o_mode = OMODE_PDF; - } else - o_mode = OMODE_DVI; - return o_mode; -} - -void fix_o_mode(void) -{ - output_mode o_mode = get_o_mode(); - if (output_mode_used == OMODE_NONE) { - output_mode_used = o_mode; - /*tex Used by synctex, we need to use output_mode_used there: */ - static_pdf->o_mode = output_mode_used; - } else if (output_mode_used != o_mode) { - normal_error("pdf backend", "\\outputmode can only be changed before anything is written to the output"); - } - init_backend_functionpointers(output_mode_used); -} diff --git a/Build/source/texk/web2c/luatexdir/tex/backend.h b/Build/source/texk/web2c/luatexdir/tex/backend.h deleted file mode 100644 index 5cfbd06fb90..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/backend.h +++ /dev/null @@ -1,54 +0,0 @@ -/* to fill */ - -#ifndef BACKEND_H -# define BACKEND_H - -#include "ptexlib.h" - -extern scaled max_v; -extern scaled max_h; -extern boolean doing_leaders; -extern int cur_s; - -# define MAX_CONTROL_TYPE 7 - -typedef enum { - backend_control_push_list = 0, - backend_control_pop_list, - backend_control_begin_page, - backend_control_end_page, - backend_control_open_file, - backend_control_write_header, - backend_control_finish_file, - backend_control_set_reference_point -} backend_control_types ; - -typedef void (*backend_function) (); /* variadic arguments */ - -typedef struct { - char *name; /* name of the backend */ - backend_function *node_fu; /* array of node output functions */ - backend_function *whatsit_fu; /* array of whatsit output functions */ - backend_function *control_fu; /* array of whatsit output functions */ -} backend_struct; - -/* extern pos_info_structure pos_info; */ - -extern backend_function *backend_out; -extern backend_function *backend_out_whatsit; -extern backend_function *backend_out_control; - -/* get_o_mode translates from output_mode to output_mode_used */ -/* fix_o_mode freezes output_mode as soon as anything goes through the backend */ - -/* - extern void check_o_mode(PDF pdf, const char *s, int o_mode, boolean errorflag); - extern void ensure_output_file_open(PDF pdf, const char *ext); -*/ - -extern void fix_o_mode(void); -extern output_mode get_o_mode(void); - -extern void init_backend_functionpointers(output_mode o_mode); - -#endif diff --git a/Build/source/texk/web2c/luatexdir/tex/buildpage.c b/Build/source/texk/web2c/luatexdir/tex/buildpage.c deleted file mode 100644 index 81e69dc3b2a..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/buildpage.c +++ /dev/null @@ -1,1164 +0,0 @@ -/* - -Copyright 2009-2010 Taco Hoekwater <taco@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your -option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU General Public License along -with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" - - -#define mode mode_par -#define head head_par -#define tail tail_par - -/*tex - - When \TeX\ appends new material to its main vlist in vertical mode, it uses a - method something like |vsplit| to decide where a page ends, except that the - calculations are done ``on line'' as new items come in. The main complication - in this process is that insertions must be put into their boxes and removed - from the vlist, in a more-or-less optimum manner. - - We shall use the term ``current page'' for that part of the main vlist that - is being considered as a candidate for being broken off and sent to the - user's output routine. The current page starts at |vlink(page_head)|, and it - ends at |page_tail|. We have |page_head=page_tail| if this list is empty. - - Utter chaos would reign if the user kept changing page specifications while a - page is being constructed, so the page builder keeps the pertinent - specifications frozen as soon as the page receives its first box or - insertion. The global variable |page_contents| is |empty| when the current - page contains only mark nodes and content-less whatsit nodes; it is - |inserts_only| if the page contains only insertion nodes in addition to marks - and whatsits. Glue nodes, kern nodes, and penalty nodes are discarded until a - box or rule node appears, at which time |page_contents| changes to - |box_there|. As soon as |page_contents| becomes non-|empty|, the current - |vsize| and |max_depth| are squirreled away into |page_goal| and - |page_max_depth|; the latter values will be used until the page has been - forwarded to the user's output routine. The \.{\\topskip} adjustment is made - when |page_contents| changes to |box_there|. - - Although |page_goal| starts out equal to |vsize|, it is decreased by the - scaled natural height-plus-depth of the insertions considered so far, and by - the \.{\\skip} corrections for those insertions. Therefore it represents the - size into which the non-inserted material should fit, assuming that all - insertions in the current page have been made. - - The global variables |best_page_break| and |least_page_cost| correspond - respectively to the local variables |best_place| and |least_cost| in the - |vert_break| routine that we have already studied; i.e., they record the - location and value of the best place currently known for breaking the current - page. The value of |page_goal| at the time of the best break is stored in - |best_size|. - -*/ - -/*tex the final node on the current page */ - -halfword page_tail; - -/*tex what is on the current page so far? */ - -int page_contents; - -/*tex maximum box depth on page being built */ - -scaled page_max_depth; - -/*tex break here to get the best page known so far */ - -halfword best_page_break; - -/*tex the score for this currently best page */ - -int least_page_cost; - -/*tex its |page_goal| */ - -scaled best_size; - -/*tex - - The page builder has another data structure to keep track of insertions. This - is a list of four-word nodes, starting and ending at |page_ins_head|. That - is, the first element of the list is node |t$_1$=vlink(page_ins_head)|; - node $r_j$ is followed by |t$_{j+1}$=vlink(t$_j$)|; and if there are - |n| items we have |$_{n+1}$>=page_ins_head|. The |subtype| field of each - node in this list refers to an insertion number; for example, `\.{\\insert - 250}' would correspond to a node whose |subtype| is |qi(250)| (the same as - the |subtype| field of the relevant |ins_node|). These |subtype| fields are - in increasing order, and |subtype(page_ins_head)=65535|, so |page_ins_head| - serves as a convenient sentinel at the end of the list. A record is present - for each insertion number that appears in the current page. - - The |type| field in these nodes distinguishes two possibilities that might - occur as we look ahead before deciding on the optimum page break. If - |type(r)=inserting_node|, then |height(r)| contains the total of the - height-plus-depth dimensions of the box and all its inserts seen so far. - |type(r)=split_up_node|, then no more insertions will be made into this box, - because at least one previous insertion was too big to fit on the current - page; |broken_ptr(r)| points to the node where that insertion will be split, - if \TeX\ decides to split it, |broken_ins(r)| points to the insertion node - that was tentatively split, and |height(r)| includes also the natural height - plus depth of the part that would be split off. - - In both cases, |last_ins_ptr(r)| points to the last |ins_node| encountered - for box |qo(subtype(r))| that would be at least partially inserted on the - next page; and |best_ins_ptr(r)| points to the last such |ins_node| that - should actually be inserted, to get the page with minimum badness among all - page breaks considered so far. We have |best_ins_ptr(r)=null| if and only if - no insertion for this box should be made to produce this optimum page. - - Pages are built by appending nodes to the current list in \TeX's vertical - mode, which is at the outermost level of the semantic nest. This vlist is - split into two parts; the ``current page'' that we have been talking so much - about already, and the ``contribution list'' that receives new nodes as they - are created. The current page contains everything that the page builder has - accounted for in its data structures, as described above, while the - contribution list contains other things that have been generated by other - parts of \TeX\ but have not yet been seen by the page builder. The - contribution list starts at |vlink(contrib_head)|, and it ends at the current - node in \TeX's vertical mode. - - When \TeX\ has appended new material in vertical mode, it calls the procedure - |build_page|, which tries to catch up by moving nodes from the contribution - list to the current page. This procedure will succeed in its goal of emptying - the contribution list, unless a page break is discovered, i.e., unless the - current page has grown to the point where the optimum next page break has - been determined. In the latter case, the nodes after the optimum break will - go back onto the contribution list, and control will effectively pass to the - user's output routine. - - We make |type(page_head)=glue_node|, so that an initial glue node on the - current page will not be considered a valid breakpoint. - -*/ - -void initialize_buildpage(void) -{ - subtype(page_ins_head) = 65535; - type(page_ins_head) = split_up_node; - vlink(page_ins_head) = page_ins_head; - - type(page_head) = glue_node; - subtype(page_head) = normal; -} - -/*tex - - An array |page_so_far| records the heights and depths of everything on the - current page. This array contains six |scaled| numbers, like the similar - arrays already considered in |line_break| and |vert_break|; and it also - contains |page_goal| and |page_depth|, since these values are all accessible - to the user via |set_page_dimen| commands. The value of |page_so_far[1]| is - also called |page_total|. The stretch and shrink components of the \.{\\skip} - corrections for each insertion are included in |page_so_far|, but the natural - space components of these corrections are not, since they have been - subtracted from |page_goal|. - - The variable |page_depth| records the depth of the current page; it has been - adjusted so that it is at most |page_max_depth|. The variable |last_glue| - points to the glue specification of the most recent node contributed from the - contribution list, if this was a glue node; otherwise - |last_glue=max_halfword|. (If the contribution list is nonempty, however, the - value of |last_glue| is not necessarily accurate.) The variables - |last_penalty|, |last_kern|, and |last_node_type| are similar. And finally, - |insert_penalties| holds the sum of the penalties associated with all split - and floating insertions. - -*/ - -/*tex height and glue of the current page */ - -scaled page_so_far[8]; - -/*tex used to implement \.{\\lastskip} */ - -halfword last_glue; - -/*tex used to implement \.{\\lastpenalty} */ - -int last_penalty; - -/*tex used to implement \.{\\lastkern} */ - -scaled last_kern; - -/*tex used to implement \.{\\lastnodetype} */ - -int last_node_type; - -/*tex sum of the penalties for held-over insertions */ - -int insert_penalties; - -#define print_plus(A,B) do { \ - if (page_so_far[(A)]!=0) { \ - tprint(" plus "); \ - print_scaled(page_so_far[(A)]); \ - tprint((B)); \ - } \ -} while (0) - -void print_totals(void) -{ - print_scaled(page_total); - print_plus(2, ""); - print_plus(3, "fil"); - print_plus(4, "fill"); - print_plus(5, "filll"); - if (page_shrink != 0) { - tprint(" minus "); - print_scaled(page_shrink); - } -} - -/*tex - - Here is a procedure that is called when the |page_contents| is changing from - |empty| to |inserts_only| or |box_there|. - -*/ - -#define do_all_six(A) A(1);A(2);A(3);A(4);A(5);A(6);A(7) -#define set_page_so_far_zero(A) page_so_far[(A)]=0 - -void freeze_page_specs(int s) -{ - page_contents = s; - page_goal = vsize_par; - page_max_depth = max_depth_par; - page_depth = 0; - do_all_six(set_page_so_far_zero); - least_page_cost = awful_bad; - if (tracing_pages_par > 0) { - begin_diagnostic(); - tprint_nl("%% goal height="); - print_scaled(page_goal); - tprint(", max depth="); - print_scaled(page_max_depth); - end_diagnostic(false); - } -} - -/*tex - - The global variable |output_active| is true during the time the user's output - routine is driving \TeX. - -*/ - -/*tex Are we in the midst of an output routine? */ - -boolean output_active; - -/*tex - - The page builder is ready to start a fresh page if we initialize the - following state variables. (However, the page insertion list is initialized - elsewhere.) - -*/ - -void start_new_page(void) -{ - page_contents = empty; - page_tail = page_head; - vlink(page_head) = null; - last_glue = max_halfword; - last_penalty = 0; - last_kern = 0; - last_node_type = -1; - page_depth = 0; - page_max_depth = 0; -} - -/*tex - - At certain times box \.{\\outputbox} is supposed to be void (i.e., |null|), - or an insertion box is supposed to be ready to accept a vertical list. If - not, an error message is printed, and the following subroutine flushes the - unwanted contents, reporting them to the user. - -*/ - -static void box_error(int n) -{ - error(); - begin_diagnostic(); - tprint_nl("The following box has been deleted:"); - show_box(box(n)); - end_diagnostic(true); - flush_node_list(box(n)); - box(n) = null; -} - -/*tex - - The following procedure guarantees that a given box register does not contain - an \.{\\hbox}. - -*/ - -static void ensure_vbox(int n) -{ - halfword p = box(n); - if (p != null && type(p) == hlist_node) { - print_err("Insertions can only be added to a vbox"); - help3( - "Tut tut: You're trying to \\insert into a", - "\\box register that now contains an \\hbox.", - "Proceed, and I'll discard its present contents." - ); - box_error(n); - } -} - -/*tex - - \TeX\ is not always in vertical mode at the time |build_page| is called; the - current mode reflects what \TeX\ should return to, after the contribution - list has been emptied. A call on |build_page| should be immediately followed - by `|goto big_switch|', which is \TeX's central control point. - -*/ - -/*tex Append contributions to the current page. */ - -void build_page(void) -{ - /*tex the node being appended */ - halfword p; - /*tex nodes being examined */ - halfword q, r; - /*tex badness and cost of current page */ - int b, c; - /*tex penalty to be added to the badness */ - int pi = 0; - /*tex insertion box number */ - int n; - /*tex sizes used for insertion calculations */ - scaled delta, h, w; - int id, sk, i; - if ((vlink(contrib_head) == null) || output_active) - return; - do { - CONTINUE: - p = vlink(contrib_head); - /*tex Update the values of |last_glue|, |last_penalty|, and |last_kern|. */ - if (last_glue != max_halfword) { - flush_node(last_glue); - last_glue = max_halfword; - } - last_penalty = 0; - last_kern = 0; - last_node_type = type(p) + 1; - if (type(p) == glue_node) { - last_glue = new_glue(p); - } else if (type(p) == penalty_node) { - last_penalty = penalty(p); - } else if (type(p) == kern_node) { - last_kern = width(p); - } - /*tex - - Move node |p| to the current page; if it is time for a page break, - put the nodes following the break back onto the contribution list, - and |return| to the users output routine if there is one. - - The code here is an example of a many-way switch into routines that - merge together in different places. Some people call this - unstructured programming, but the author doesn't see much wrong with - it, as long as the various labels have a well-understood meaning. - - If the current page is empty and node |p| is to be deleted, |goto - done1|; otherwise use node |p| to update the state of the current - page; if this node is an insertion, |goto contribute|; otherwise if - this node is not a legal breakpoint, |goto contribute| or - |update_heights|; otherwise set |pi| to the penalty associated with - this breakpoint. - - The title of this section is already so long, it seems best to avoid - making it more accurate but still longer, by mentioning the fact that - a kern node at the end of the contribution list will not be - contributed until we know its successor. - - */ - switch (type(p)) { - case hlist_node: - case vlist_node: - case rule_node: - if (page_contents < box_there) { - /*tex - - Initialize the current page, insert the \.{\\topskip} - glue ahead of |p|, and |goto continue|. - - */ - if (page_contents == empty) - freeze_page_specs(box_there); - else - page_contents = box_there; - q = new_skip_param(top_skip_code); - if ((type(p) == hlist_node) && is_mirrored(body_direction_par)) { - if (width(q) > depth(p)) - width(q) = width(q) - depth(p); - else - width(q) = 0; - } else { - if (width(q) > height(p)) - width(q) = width(q) - height(p); - else - width(q) = 0; - } - couple_nodes(q, p); - couple_nodes(contrib_head, q); - goto CONTINUE; - } else { - /*tex - - Prepare to move a box or rule node to the current page, - then |goto contribute|. - - */ - if ((type(p) == hlist_node) && is_mirrored(body_direction_par)) { - page_total = page_total + page_depth + depth(p); - page_depth = height(p); - } else { - page_total = page_total + page_depth + height(p); - page_depth = depth(p); - } - goto CONTRIBUTE; - - } - break; - case boundary_node: - case whatsit_node: - goto CONTRIBUTE; - break; - case glue_node: - if (page_contents < box_there) - goto DONE1; - else if (precedes_break(page_tail)) - pi = 0; - else - goto UPDATE_HEIGHTS; - break; - case kern_node: - if (page_contents < box_there) - goto DONE1; - else if (vlink(p) == null) - goto EXIT; - else if (type(vlink(p)) == glue_node) - pi = 0; - else - goto UPDATE_HEIGHTS; - break; - case penalty_node: - if (page_contents < box_there) - goto DONE1; - else - pi = penalty(p); - break; - case mark_node: - goto CONTRIBUTE; - break; - case ins_node: - /*tex Append an insertion to the current page and |goto contribute|. */ - if (page_contents == empty) - freeze_page_specs(inserts_only); - n = subtype(p); - r = page_ins_head; - i = 1 ; - while (n >= subtype(vlink(r))) { - r = vlink(r); - i = i + 1 ; - } - if (subtype(r) != n) { - /*tex - - Create a page insertion node with |subtype(r)=qi(n)|, and - include the glue correction for box |n| in the current - page state. - - We take note of the value of \.{\\skip} |n| and the - height plus depth of \.{\\box}~|n| only when the first - \.{\\insert}~|n| node is encountered for a new page. A - user who changes the contents of \.{\\box}~|n| after that - first \.{\\insert}~|n| had better be either extremely - careful or extremely lucky, or both. - - */ - id = callback_defined(build_page_insert_callback); - if (id != 0) { - run_callback(id, "dd->d",n,i,&sk); - } else { - sk = n; - } - q = new_node(inserting_node, n); - try_couple_nodes(q, vlink(r)); - couple_nodes(r, q); - r = q; - ensure_vbox(n); - if (box(n) == null) - height(r) = 0; - else - height(r) = height(box(n)) + depth(box(n)); - best_ins_ptr(r) = null; - q = skip(sk); - if (count(n) == 1000) - h = height(r); - else - h = x_over_n(height(r), 1000) * count(n); - page_goal = page_goal - h - width(q); - if (stretch_order(q) > 1) - page_so_far[1 + stretch_order(q)] = page_so_far[1 + stretch_order(q)] + stretch(q); - else - page_so_far[2 + stretch_order(q)] = page_so_far[2 + stretch_order(q)] + stretch(q); - page_shrink = page_shrink + shrink(q); - if ((shrink_order(q) != normal) && (shrink(q) != 0)) { - print_err("Infinite glue shrinkage inserted from \\skip"); - print_int(n); - help3( - "The correction glue for page breaking with insertions", - "must have finite shrinkability. But you may proceed,", - "since the offensive shrinkability has been made finite." - ); - error(); - } - - } - if (type(r) == split_up_node) { - insert_penalties = insert_penalties + float_cost(p); - } else { - last_ins_ptr(r) = p; - delta = page_goal - page_total - page_depth + page_shrink; - /*tex This much room is left if we shrink the maximum. */ - if (count(n) == 1000) { - h = height(p); - } else { - /*tex This much room is needed. */ - h = x_over_n(height(p), 1000) * count(n); - } - if (((h <= 0) || (h <= delta)) - && (height(p) + height(r) <= dimen(n))) { - page_goal = page_goal - h; - height(r) = height(r) + height(p); - } else { - /*tex - - Find the best way to split the insertion, and change - |type(r)| to |split_up_node|. - - Here is the code that will split a long footnote - between pages, in an emergency. The current situation - deserves to be recapitulated: Node |p| is an - insertion into box |n|; the insertion will not fit, - in its entirety, either because it would make the - total contents of box |n| greater than \.{\\dimen} - |n|, or because it would make the incremental amount - of growth |h| greater than the available space - |delta|, or both. (This amount |h| has been weighted - by the insertion scaling factor, i.e., by \.{\\count} - |n| over 1000.) Now we will choose the best way to - break the vlist of the insertion, using the same - criteria as in the \.{\\vsplit} operation. - - */ - if (count(n) <= 0) { - w = max_dimen; - } else { - w = page_goal - page_total - page_depth; - if (count(n) != 1000) - w = x_over_n(w, count(n)) * 1000; - } - if (w > dimen(n) - height(r)) - w = dimen(n) - height(r); - q = vert_break(ins_ptr(p), w, depth(p)); - height(r) = height(r) + best_height_plus_depth; - if (tracing_pages_par > 0) { - /*tex Display the insertion split cost. */ - begin_diagnostic(); - tprint_nl("% split"); - print_int(n); - tprint(" to "); - print_scaled(w); - print_char(','); - print_scaled(best_height_plus_depth); - tprint(" p="); - if (q == null) - print_int(eject_penalty); - else if (type(q) == penalty_node) - print_int(penalty(q)); - else - print_char('0'); - end_diagnostic(false); - } - if (count(n) != 1000) - best_height_plus_depth = x_over_n(best_height_plus_depth, 1000) * count(n); - page_goal = page_goal - best_height_plus_depth; - type(r) = split_up_node; - broken_ptr(r) = q; - broken_ins(r) = p; - if (q == null) - insert_penalties = insert_penalties + eject_penalty; - else if (type(q) == penalty_node) - insert_penalties = insert_penalties + penalty(q); - } - } - goto CONTRIBUTE; - - break; - default: - formatted_error("pagebuilder","invalid node of type %d in vertical mode", type(p)); - break; - } - /*tex - - Check if node |p| is a new champion breakpoint; then if it is time - for a page break, prepare for output, and either fire up the users - output routine and |return| or ship out the page and |goto done|. - - */ - if (pi < inf_penalty) { - /*tex - - Compute the badness, |b|, of the current page, using |awful_bad| - if the box is too full. - - */ - if (page_total < page_goal) { - if ((page_so_far[3] != 0) || (page_so_far[4] != 0) || - (page_so_far[5] != 0)) - b = 0; - else - b = badness(page_goal - page_total, page_so_far[2]); - } else if (page_total - page_goal > page_shrink) { - b = awful_bad; - } else { - b = badness(page_total - page_goal, page_shrink); - } - if (b < awful_bad) { - if (pi <= eject_penalty) - c = pi; - else if (b < inf_bad) - c = b + pi + insert_penalties; - else - c = deplorable; - } else { - c = b; - } - if (insert_penalties >= 10000) - c = awful_bad; - if (tracing_pages_par > 0) { - /*tex Display the page break cost. */ - begin_diagnostic(); - tprint_nl("%"); - tprint(" t="); - print_totals(); - tprint(" g="); - print_scaled(page_goal); - tprint(" b="); - if (b == awful_bad) - print_char('*'); - else - print_int(b); - tprint(" p="); - print_int(pi); - tprint(" c="); - if (c == awful_bad) - print_char('*'); - else - print_int(c); - if (c <= least_page_cost) - print_char('#'); - end_diagnostic(false); - } - if (c <= least_page_cost) { - best_page_break = p; - best_size = page_goal; - least_page_cost = c; - r = vlink(page_ins_head); - while (r != page_ins_head) { - best_ins_ptr(r) = last_ins_ptr(r); - r = vlink(r); - } - } - if ((c == awful_bad) || (pi <= eject_penalty)) { - /*tex Output the current page at the best place. */ - fire_up(p); - if (output_active) { - /*tex User's output routine will act. */ - goto EXIT; - } - /*tex The page has been shipped out by default output routine. */ - goto DONE; - } - } - if ((type(p) < glue_node) || (type(p) > kern_node)) - goto CONTRIBUTE; - UPDATE_HEIGHTS: - /*tex - - Go here to record glue in the |active_height| table. Update the - current page measurements with respect to the glue or kern specified - by node~|p|. - - */ - if (type(p) != kern_node) { - if (stretch_order(p) > 1) - page_so_far[1 + stretch_order(p)] = page_so_far[1 + stretch_order(p)] + stretch(p); - else - page_so_far[2 + stretch_order(p)] = page_so_far[2 + stretch_order(p)] + stretch(p); - page_shrink = page_shrink + shrink(p); - if ((shrink_order(p) != normal) && (shrink(p) != 0)) { - print_err("Infinite glue shrinkage found on current page"); - help4( - "The page about to be output contains some infinitely", - "shrinkable glue, e.g., `\\vss' or `\\vskip 0pt minus 1fil'.", - "Such glue doesn't belong there; but you can safely proceed,", - "since the offensive shrinkability has been made finite." - ); - error(); - reset_glue_to_zero(p); - shrink_order(p) = normal; - } - } - page_total = page_total + page_depth + width(p); - page_depth = 0; - CONTRIBUTE: - /*tex - - Go here to link a node into the current page. Make sure that - |page_max_depth| is not exceeded. - - */ - if (page_depth > page_max_depth) { - page_total = page_total + page_depth - page_max_depth; - page_depth = page_max_depth; - } - /*tex Link node |p| into the current page and |goto done|. */ - couple_nodes(page_tail, p); - page_tail = p; - try_couple_nodes(contrib_head,vlink(p)); - vlink(p) = null; - goto DONE; - DONE1: - /*tex Recycle node |p|. */ - try_couple_nodes(contrib_head,vlink(p)); - vlink(p) = null; - if (saving_vdiscards_par > 0) { - if (page_disc == null) { - page_disc = p; - } else { - couple_nodes(tail_page_disc, p); - } - tail_page_disc = p; - } else { - flush_node_list(p); - } - DONE: - ; - } while (vlink(contrib_head) != null); - /*tex Make the contribution list empty by setting its tail to |contrib_head|. */ - contrib_tail = contrib_head; - EXIT: - ; -} - -/*tex - - When the page builder has looked at as much material as could appear before - the next page break, it makes its decision. The break that gave minimum - badness will be used to put a completed ``page'' into box \.{\\outputbox}, - with insertions appended to their other boxes. - - We also set the values of |top_mark|, |first_mark|, and |bot_mark|. The - program uses the fact that |bot_mark(x)<>null| implies |first_mark(x)<>null|; - it also knows that |bot_mark(x)=null| implies - |top_mark(x)=first_mark(x)=null|. - - The |fire_up| subroutine prepares to output the current page at the best - place; then it fires up the user's output routine, if there is one, or it - simply ships out the page. There is one parameter, |c|, which represents the - node that was being contributed to the page when the decision to force an - output was made. - -*/ - -void fire_up(halfword c) -{ - /*tex nodes being examined and/or changed */ - halfword p, q, r, s; - /*tex predecessor of |p| */ - halfword prev_p; - /*tex insertion box number */ - int n; - /*tex should the present insertion be held over? */ - boolean wait; - /*tex saved value of |vbadness| */ - int save_vbadness; - /*tex saved value of |vfuzz| */ - scaled save_vfuzz; - /*tex saved value of |split_top_skip| */ - halfword save_split_top_skip; - /*tex for looping through the marks */ - halfword i; - /*tex Set the value of |output_penalty|. */ - if (type(best_page_break) == penalty_node) { - geq_word_define(int_base + output_penalty_code, - penalty(best_page_break)); - penalty(best_page_break) = inf_penalty; - } else { - geq_word_define(int_base + output_penalty_code, inf_penalty); - } - - for (i = 0; i <= biggest_used_mark; i++) { - if (bot_mark(i) != null) { - if (top_mark(i) != null) - delete_token_ref(top_mark(i)); - set_top_mark(i, bot_mark(i)); - add_token_ref(top_mark(i)); - delete_first_mark(i); - } - } - /*tex - - Put the optimal current page into box |output_box|, update |first_mark| - and |bot_mark|, append insertions to their boxes, and put the remaining - nodes back on the contribution list. - - As the page is finally being prepared for output, pointer |p| runs - through the vlist, with |prev_p| trailing behind; pointer |q| is the tail - of a list of insertions that are being held over for a subsequent page. - - */ - if (c == best_page_break) { - /*tex |c| not yet linked in */ - best_page_break = null; - } - /*tex Ensure that box |output_box| is empty before output. */ - if (box(output_box_par) != null) { - print_err("\\box"); - print_int(output_box_par); - tprint(" is not void"); - help2( - "You shouldn't use \\box\\outputbox except in \\output routines.", - "Proceed, and I'll discard its present contents." - ); - box_error(output_box_par); - } - /*tex This will count the number of insertions held over. */ - insert_penalties = 0; - save_split_top_skip = split_top_skip_par; - if (holding_inserts_par <= 0) { - /*tex - - Prepare all the boxes involved in insertions to act as queues. If - many insertions are supposed to go into the same box, we want to know - the position of the last node in that box, so that we don't need to - waste time when linking further information into it. The - |last_ins_ptr| fields of the page insertion nodes are therefore used - for this purpose during the packaging phase. - - */ - r = vlink(page_ins_head); - while (r != page_ins_head) { - if (best_ins_ptr(r) != null) { - n = subtype(r); - ensure_vbox(n); - if (box(n) == null) - box(n) = new_null_box(); - p = box(n) + list_offset; - while (vlink(p) != null) - p = vlink(p); - last_ins_ptr(r) = p; - } - r = vlink(r); - } - - } - q = hold_head; - vlink(q) = null; - prev_p = page_head; - p = vlink(prev_p); - while (p != best_page_break) { - if (type(p) == ins_node) { - if (holding_inserts_par <= 0) { - /*tex - - Either insert the material specified by node |p| into the - appropriate box, or hold it for the next page; also delete - node |p| from the current page. - - We will set |best_ins_ptr:=null| and package the box - corresponding to insertion node~|r|, just after making the - final insertion into that box. If this final insertion is - `|split_up_node|', the remainder after splitting and pruning - (if any) will be carried over to the next page. - - */ - r = vlink(page_ins_head); - while (subtype(r) != subtype(p)) - r = vlink(r); - if (best_ins_ptr(r) == null) { - wait = true; - } else { - wait = false; - s = last_ins_ptr(r); - vlink(s) = ins_ptr(p); - if (best_ins_ptr(r) == p) { - halfword t; - /*tex - - Wrap up the box specified by node |r|, splitting node - |p| if called for; set |wait:=true| if node |p| holds - a remainder after splitting. - - */ - if (type(r) == split_up_node) { - if ((broken_ins(r) == p) && (broken_ptr(r) != null)) { - while (vlink(s) != broken_ptr(r)) - s = vlink(s); - vlink(s) = null; - split_top_skip_par = split_top_ptr(p); - ins_ptr(p) = - prune_page_top(broken_ptr(r), false); - if (ins_ptr(p) != null) { - t = vpack(ins_ptr(p), 0, additional, -1); - height(p) = height(t) + depth(t); - list_ptr(t) = null; - flush_node(t); - wait = true; - } - } - } - best_ins_ptr(r) = null; - n = subtype(r); - t = list_ptr(box(n)); - list_ptr(box(n)) = null; - flush_node(box(n)); - box(n) = vpack(t, 0, additional, body_direction_par); - - } else { - while (vlink(s) != null) - s = vlink(s); - last_ins_ptr(r) = s; - } - } - /*tex - - Either append the insertion node |p| after node |q|, and - remove it from the current page, or delete |node(p)|. - - */ - try_couple_nodes(prev_p, vlink(p)); - vlink(p) = null; - if (wait) { - couple_nodes(q, p); - q = p; - incr(insert_penalties); - } else { - ins_ptr(p) = null; - flush_node(p); - } - p = prev_p; - - } - } else if (type(p) == mark_node) { - /*tex Update the values of |first_mark| and |bot_mark|. */ - if (first_mark(mark_class(p)) == null) { - set_first_mark(mark_class(p), mark_ptr(p)); - add_token_ref(first_mark(mark_class(p))); - } - if (bot_mark(mark_class(p)) != null) - delete_token_ref(bot_mark(mark_class(p))); - set_bot_mark(mark_class(p), mark_ptr(p)); - add_token_ref(bot_mark(mark_class(p))); - - } - prev_p = p; - p = vlink(prev_p); - } - split_top_skip_par = save_split_top_skip; - /*tex - - Break the current page at node |p|, put it in box~|output_box|, and put - the remaining nodes on the contribution list. - - When the following code is executed, the current page runs from node - |vlink(page_head)| to node |prev_p|, and the nodes from |p| to - |page_tail| are to be placed back at the front of the contribution list. - Furthermore the heldover insertions appear in a list from - |vlink(hold_head)| to |q|; we will put them into the current page list - for safekeeping while the user's output routine is active. We might have - |q=hold_head|; and |p=null| if and only if |prev_p=page_tail|. Error - messages are suppressed within |vpackage|, since the box might appear to - be overfull or underfull simply because the stretch and shrink from the - \.{\\skip} registers for inserts are not actually present in the box. - - */ - if (p != null) { - if (vlink(contrib_head) == null) { - contrib_tail = page_tail; - } - couple_nodes(page_tail,vlink(contrib_head)); - couple_nodes(contrib_head, p); - vlink(prev_p) = null; - } - save_vbadness = vbadness_par; - vbadness_par = inf_bad; - save_vfuzz = vfuzz_par; - /*tex Inhibit error messages. */ - vfuzz_par = max_dimen; - box(output_box_par) = filtered_vpackage(vlink(page_head), - best_size, exactly, page_max_depth, output_group, body_direction_par, 0, 0); - vbadness_par = save_vbadness; - vfuzz_par = save_vfuzz; - if (last_glue != max_halfword) - flush_node(last_glue); - /*tex Start a new current page. This sets |last_glue:=max_halfword|. */ - start_new_page(); - if (q != hold_head) { - vlink(page_head) = vlink(hold_head); - page_tail = q; - } - /*tex Delete the page-insertion nodes. */ - r = vlink(page_ins_head); - while (r != page_ins_head) { - /*tex Todo: couple. */ - q = vlink(r); - flush_node(r); - r = q; - } - vlink(page_ins_head) = page_ins_head; - for (i = 0; i <= biggest_used_mark; i++) { - if ((top_mark(i) != null) && (first_mark(i) == null)) { - set_first_mark(i, top_mark(i)); - add_token_ref(top_mark(i)); - } - } - if (output_routine_par != null) { - if (dead_cycles >= max_dead_cycles_par) { - /*tex Explain that too many dead cycles have occurred in a row. */ - print_err("Output loop---"); - print_int(dead_cycles); - tprint(" consecutive dead cycles"); - help3( - "I've concluded that your \\output is awry; it never does a", - "\\shipout, so I'm shipping \\box\\outputbox out myself. Next time", - "increase \\maxdeadcycles if you want me to be more patient!" - ); - error(); - } else { - /*tex Fire up the users output routine and |return|. */ - output_active = true; - incr(dead_cycles); - push_nest(); - mode = -vmode; - prev_depth_par = ignore_depth; - mode_line_par = -line; - begin_token_list(output_routine_par, output_text); - new_save_level(output_group); - normal_paragraph(); - scan_left_brace(); - return; - } - } - /*tex - - Perform the default output routine. The list of heldover insertions, - running from |vlink(page_head)| to |page_tail|, must be moved to the - contribution list when the user has specified no output routine. - - */ - if (vlink(page_head) != null) { - if (vlink(contrib_head) == null) { - contrib_tail = page_tail; - } else { - vlink(page_tail) = vlink(contrib_head); - } - vlink(contrib_head) = vlink(page_head); - vlink(page_head) = null; - page_tail = page_head; - } - flush_node_list(page_disc); - page_disc = null; - ship_out(static_pdf, box(output_box_par), SHIPPING_PAGE); - box(output_box_par) = null; -} - -/*tex - - When the user's output routine finishes, it has constructed a vlist in - internal vertical mode, and \TeX\ will do the following: - -*/ - -void resume_after_output(void) -{ - if ((iloc != null) || ((token_type != output_text) && (token_type != backed_up))) { - /*tex Recover from an unbalanced output routine */ - print_err("Unbalanced output routine"); - help2( - "Your sneaky output routine has problematic {'s and/or }'s.", - "I can't handle that very well; good luck." - ); - error(); - /*tex Loops forever if reading from a file, since |null=min_halfword<=0|. */ - do { - get_token(); - } while (iloc != null); - } - /*tex Conserve stack space in case more outputs are triggered. */ - end_token_list(); - end_graf(bottom_level); - unsave(); - output_active = false; - insert_penalties = 0; - /*tex Ensure that box |output_box| is empty after output. */ - if (box(output_box_par) != null) { - print_err("Output routine didn't use all of \\box"); - print_int(output_box_par); - help3( - "Your \\output commands should empty \\box\\outputbox,", - "e.g., by saying `\\shipout\\box\\outputbox'.", - "Proceed; I'll discard its present contents." - ); - box_error(output_box_par); - } - if (tail != head) { - /*tex Current list goes after heldover insertions. */ - try_couple_nodes(page_tail, vlink(head)); - page_tail = tail; - } - if (vlink(page_head) != null) { - /* Both go before heldover contributions. */ - if (vlink(contrib_head) == null) - contrib_tail = page_tail; - try_couple_nodes(page_tail, vlink(contrib_head)); - try_couple_nodes(contrib_head, vlink(page_head)); - vlink(page_head) = null; - page_tail = page_head; - } - flush_node_list(page_disc); - page_disc = null; - pop_nest(); - normal_page_filter(after_output); - build_page(); -} diff --git a/Build/source/texk/web2c/luatexdir/tex/buildpage.h b/Build/source/texk/web2c/luatexdir/tex/buildpage.h deleted file mode 100644 index 9c013514efa..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/buildpage.h +++ /dev/null @@ -1,74 +0,0 @@ -/* buildpage.h - - Copyright 2009 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ - - -#ifndef BUILDPAGE_H -# define BUILDPAGE_H - -/* empty = 0 */ -# define inserts_only 1 /* |page_contents| when an insert node has been contributed, but no boxes */ -# define box_there 2 /* |page_contents| when a box or rule has been contributed */ - -extern halfword page_tail; /* the final node on the current page */ -extern int page_contents; /* what is on the current page so far? */ -extern scaled page_max_depth; /* maximum box depth on page being built */ -extern halfword best_page_break; /* break here to get the best page known so far */ -extern int least_page_cost; /* the score for this currently best page */ -extern scaled best_size; /* its |page_goal| */ - -/* -The data structure definitions here use the fact that the |@!height| field -appears in the fourth word of a box node. -@^data structure assumptions@> -*/ - -# define broken_ptr(A) vlink((A)+2) /* an insertion for this class will break here if anywhere */ -# define broken_ins(A) vinfo((A)+2) /* this insertion might break at |broken_ptr| */ -# define last_ins_ptr(A) vlink((A)+3) /* the most recent insertion for this |subtype| */ -# define best_ins_ptr(A) vinfo((A)+3) /* the optimum most recent insertion */ - -extern void initialize_buildpage(void); - -# define page_goal page_so_far[0] /* desired height of information on page being built */ -# define page_total page_so_far[1] /* height of the current page */ -# define page_shrink page_so_far[6] /* shrinkability of the current page */ -# define page_depth page_so_far[7] /* depth of the current page */ - -extern scaled page_so_far[8]; /* height and glue of the current page */ -extern halfword last_glue; /* used to implement \.{\\lastskip */ -extern int last_penalty; /* used to implement \.{\\lastpenalty} */ -extern scaled last_kern; /* used to implement \.{\\lastkern} */ -extern int last_node_type; /* used to implement \.{\\lastnodetype} */ -extern int insert_penalties; /* sum of the penalties for held-over insertions */ - -extern void print_totals(void); -extern void freeze_page_specs(int s); - -extern boolean output_active; - -extern void start_new_page(void); - -# define contrib_tail nest[0].tail_field - /* tail of the contribution list */ - -extern void build_page(void); /* append contributions to the current page */ -extern void fire_up(halfword c); -extern void resume_after_output(void); - -#endif diff --git a/Build/source/texk/web2c/luatexdir/tex/commands.c b/Build/source/texk/web2c/luatexdir/tex/commands.c deleted file mode 100644 index 261f23f4a83..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/commands.c +++ /dev/null @@ -1,936 +0,0 @@ -/* - -commands.w - -Copyright 2009-2010 Taco Hoekwater <taco@@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your -option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU General Public License along -with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" - -/*tex - -The symbolic names for glue parameters are put into \TeX's hash table by using -the routine called |primitive|, defined below. Let us enter them now, so that we -don't have to list all those parameter names anywhere else. - -*/ - -void initialize_commands(void) -{ - - primitive_tex("lineskip", assign_glue_cmd, glue_base + line_skip_code, glue_base); - primitive_tex("baselineskip", assign_glue_cmd, glue_base + baseline_skip_code, glue_base); - primitive_tex("parskip", assign_glue_cmd, glue_base + par_skip_code, glue_base); - primitive_tex("abovedisplayskip", assign_glue_cmd, glue_base + above_display_skip_code, glue_base); - primitive_tex("belowdisplayskip", assign_glue_cmd, glue_base + below_display_skip_code, glue_base); - primitive_tex("abovedisplayshortskip", assign_glue_cmd, glue_base + above_display_short_skip_code, glue_base); - primitive_tex("belowdisplayshortskip", assign_glue_cmd, glue_base + below_display_short_skip_code, glue_base); - primitive_tex("leftskip", assign_glue_cmd, glue_base + left_skip_code, glue_base); - primitive_tex("rightskip", assign_glue_cmd, glue_base + right_skip_code, glue_base); - primitive_tex("topskip", assign_glue_cmd, glue_base + top_skip_code, glue_base); - primitive_tex("splittopskip", assign_glue_cmd, glue_base + split_top_skip_code, glue_base); - primitive_tex("tabskip", assign_glue_cmd, glue_base + tab_skip_code, glue_base); - primitive_tex("spaceskip", assign_glue_cmd, glue_base + space_skip_code, glue_base); - primitive_tex("xspaceskip", assign_glue_cmd, glue_base + xspace_skip_code, glue_base); - primitive_tex("parfillskip", assign_glue_cmd, glue_base + par_fill_skip_code, glue_base); - primitive_tex("thinmuskip", assign_mu_glue_cmd, glue_base + thin_mu_skip_code, glue_base + thin_mu_skip_code); - primitive_tex("medmuskip", assign_mu_glue_cmd, glue_base + med_mu_skip_code, glue_base + thin_mu_skip_code); - primitive_tex("thickmuskip", assign_mu_glue_cmd, glue_base + thick_mu_skip_code, glue_base + thin_mu_skip_code); - primitive_luatex("mathsurroundskip", assign_glue_cmd, glue_base + math_skip_code, glue_base); - primitive_luatex("mathsurroundmode", assign_int_cmd, int_base + math_skip_mode_code, int_base); - primitive_luatex("mathscriptboxmode", assign_int_cmd, int_base + math_script_box_mode_code, int_base); - primitive_luatex("mathscriptcharmode", assign_int_cmd, int_base + math_script_char_mode_code, int_base); - primitive_luatex("mathrulethicknessmode", assign_int_cmd, int_base + math_rule_thickness_mode_code, int_base); - primitive_luatex("mathflattenmode", assign_int_cmd, int_base + math_flatten_mode_code, int_base); - primitive_tex("output", assign_toks_cmd, output_routine_loc, local_base); - primitive_tex("everypar", assign_toks_cmd, every_par_loc, local_base); - primitive_tex("everymath", assign_toks_cmd, every_math_loc, local_base); - primitive_tex("everydisplay", assign_toks_cmd, every_display_loc, local_base); - primitive_tex("everyhbox", assign_toks_cmd, every_hbox_loc, local_base); - primitive_tex("everyvbox", assign_toks_cmd, every_vbox_loc, local_base); - primitive_tex("everyjob", assign_toks_cmd, every_job_loc, local_base); - primitive_tex("everycr", assign_toks_cmd, every_cr_loc, local_base); - primitive_tex("errhelp", assign_toks_cmd, err_help_loc, local_base); - - /*tex The integer parameter names must be entered into the hash table */ - - primitive_tex("pretolerance", assign_int_cmd, int_base + pretolerance_code, int_base); - primitive_tex("tolerance", assign_int_cmd, int_base + tolerance_code, int_base); - primitive_tex("linepenalty", assign_int_cmd, int_base + line_penalty_code, int_base); - primitive_tex("hyphenpenalty", assign_int_cmd, int_base + hyphen_penalty_code, int_base); - primitive_tex("exhyphenpenalty", assign_int_cmd, int_base + ex_hyphen_penalty_code, int_base); - primitive_tex("clubpenalty", assign_int_cmd, int_base + club_penalty_code, int_base); - primitive_tex("widowpenalty", assign_int_cmd, int_base + widow_penalty_code, int_base); - primitive_tex("displaywidowpenalty", assign_int_cmd, int_base + display_widow_penalty_code, int_base); - primitive_tex("brokenpenalty", assign_int_cmd, int_base + broken_penalty_code, int_base); - primitive_tex("binoppenalty", assign_int_cmd, int_base + bin_op_penalty_code, int_base); - primitive_luatex("prerelpenalty", assign_int_cmd, int_base + pre_rel_penalty_code, int_base); - primitive_luatex("prebinoppenalty", assign_int_cmd, int_base + pre_bin_op_penalty_code, int_base); - primitive_tex("relpenalty", assign_int_cmd, int_base + rel_penalty_code, int_base); - primitive_tex("predisplaypenalty", assign_int_cmd, int_base + pre_display_penalty_code, int_base); - primitive_tex("postdisplaypenalty", assign_int_cmd, int_base + post_display_penalty_code, int_base); - primitive_luatex("mathpenaltiesmode", assign_int_cmd, int_base + math_penalties_mode_code, int_base); - primitive_luatex("mathdelimitersmode", assign_int_cmd, int_base + math_delimiters_mode_code, int_base); - primitive_tex("interlinepenalty", assign_int_cmd, int_base + inter_line_penalty_code, int_base); - primitive_tex("doublehyphendemerits", assign_int_cmd, int_base + double_hyphen_demerits_code, int_base); - primitive_tex("finalhyphendemerits", assign_int_cmd, int_base + final_hyphen_demerits_code, int_base); - primitive_tex("adjdemerits", assign_int_cmd, int_base + adj_demerits_code, int_base); - primitive_tex("mag", assign_int_cmd, int_base + mag_code, int_base); - primitive_tex("delimiterfactor", assign_int_cmd, int_base + delimiter_factor_code, int_base); - primitive_tex("looseness", assign_int_cmd, int_base + looseness_code, int_base); - primitive_tex("time", assign_int_cmd, int_base + time_code, int_base); - primitive_tex("day", assign_int_cmd, int_base + day_code, int_base); - primitive_tex("month", assign_int_cmd, int_base + month_code, int_base); - primitive_tex("year", assign_int_cmd, int_base + year_code, int_base); - primitive_tex("showboxbreadth", assign_int_cmd, int_base + show_box_breadth_code, int_base); - primitive_tex("showboxdepth", assign_int_cmd, int_base + show_box_depth_code, int_base); - primitive_tex("hbadness", assign_int_cmd, int_base + hbadness_code, int_base); - primitive_tex("vbadness", assign_int_cmd, int_base + vbadness_code, int_base); - primitive_tex("pausing", assign_int_cmd, int_base + pausing_code, int_base); - primitive_tex("tracingonline", assign_int_cmd, int_base + tracing_online_code, int_base); - primitive_tex("tracingmacros", assign_int_cmd, int_base + tracing_macros_code, int_base); - primitive_tex("tracingstats", assign_int_cmd, int_base + tracing_stats_code, int_base); - primitive_tex("tracingparagraphs", assign_int_cmd, int_base + tracing_paragraphs_code, int_base); - primitive_tex("tracingpages", assign_int_cmd, int_base + tracing_pages_code, int_base); - primitive_tex("tracingoutput", assign_int_cmd, int_base + tracing_output_code, int_base); - primitive_tex("tracinglostchars", assign_int_cmd, int_base + tracing_lost_chars_code, int_base); - primitive_tex("tracingcommands", assign_int_cmd, int_base + tracing_commands_code, int_base); - primitive_tex("tracingrestores", assign_int_cmd, int_base + tracing_restores_code, int_base); - primitive_tex("uchyph", assign_int_cmd, int_base + uc_hyph_code, int_base); - primitive_tex("outputpenalty", assign_int_cmd, int_base + output_penalty_code, int_base); - primitive_tex("maxdeadcycles", assign_int_cmd, int_base + max_dead_cycles_code, int_base); - primitive_tex("hangafter", assign_int_cmd, int_base + hang_after_code, int_base); - primitive_tex("floatingpenalty", assign_int_cmd, int_base + floating_penalty_code, int_base); - primitive_tex("globaldefs", assign_int_cmd, int_base + global_defs_code, int_base); - primitive_tex("fam", assign_int_cmd, int_base + cur_fam_code, int_base); - primitive_tex("escapechar", assign_int_cmd, int_base + escape_char_code, int_base); - primitive_tex("defaulthyphenchar", assign_int_cmd, int_base + default_hyphen_char_code, int_base); - primitive_tex("defaultskewchar", assign_int_cmd, int_base + default_skew_char_code, int_base); - primitive_tex("endlinechar", assign_int_cmd, int_base + end_line_char_code, int_base); - primitive_tex("newlinechar", assign_int_cmd, int_base + new_line_char_code, int_base); - primitive_tex("language", assign_int_cmd, int_base + language_code, int_base); - primitive_tex("setlanguage", assign_int_cmd, int_base + cur_lang_code, int_base); - primitive_tex("firstvalidlanguage", assign_int_cmd, int_base + first_valid_language_code, int_base); - primitive_tex("exhyphenchar", assign_int_cmd, int_base + ex_hyphen_char_code, int_base); - primitive_tex("lefthyphenmin", assign_int_cmd, int_base + left_hyphen_min_code, int_base); - primitive_tex("righthyphenmin", assign_int_cmd, int_base + right_hyphen_min_code, int_base); - primitive_tex("holdinginserts", assign_int_cmd, int_base + holding_inserts_code, int_base); - primitive_tex("errorcontextlines", assign_int_cmd, int_base + error_context_lines_code, int_base); - primitive_luatex("nokerns", assign_int_cmd, int_base + disable_kern_code, int_base); - primitive_luatex("noligs", assign_int_cmd, int_base + disable_lig_code, int_base); - primitive_luatex("nospaces", assign_int_cmd, int_base + disable_space_code, int_base); - primitive_luatex("catcodetable", assign_int_cmd, int_base + cat_code_table_code, int_base); - primitive_luatex("outputbox", assign_int_cmd, int_base + output_box_code, int_base); - primitive_luatex("outputmode", assign_int_cmd, int_base + output_mode_code, int_base); - primitive_luatex("adjustspacing", assign_int_cmd, int_base + adjust_spacing_code, int_base); - primitive_luatex("protrudechars", assign_int_cmd, int_base + protrude_chars_code, int_base); - primitive_luatex("tracingfonts", assign_int_cmd, int_base + tracing_fonts_code, int_base); - primitive_luatex("draftmode", assign_int_cmd, int_base + draft_mode_code, int_base); - primitive_tex("parindent", assign_dimen_cmd, dimen_base + par_indent_code, dimen_base); - primitive_tex("mathsurround", assign_dimen_cmd, dimen_base + math_surround_code, dimen_base); - primitive_tex("lineskiplimit", assign_dimen_cmd, dimen_base + line_skip_limit_code, dimen_base); - primitive_tex("hsize", assign_dimen_cmd, dimen_base + hsize_code, dimen_base); - primitive_tex("vsize", assign_dimen_cmd, dimen_base + vsize_code, dimen_base); - primitive_tex("maxdepth", assign_dimen_cmd, dimen_base + max_depth_code, dimen_base); - primitive_tex("splitmaxdepth", assign_dimen_cmd, dimen_base + split_max_depth_code, dimen_base); - primitive_tex("boxmaxdepth", assign_dimen_cmd, dimen_base + box_max_depth_code, dimen_base); - primitive_tex("hfuzz", assign_dimen_cmd, dimen_base + hfuzz_code, dimen_base); - primitive_tex("vfuzz", assign_dimen_cmd, dimen_base + vfuzz_code, dimen_base); - primitive_tex("delimitershortfall", assign_dimen_cmd, dimen_base + delimiter_shortfall_code, dimen_base); - primitive_tex("nulldelimiterspace", assign_dimen_cmd, dimen_base + null_delimiter_space_code, dimen_base); - primitive_tex("scriptspace", assign_dimen_cmd, dimen_base + script_space_code, dimen_base); - primitive_tex("predisplaysize", assign_dimen_cmd, dimen_base + pre_display_size_code, dimen_base); - primitive_tex("displaywidth", assign_dimen_cmd, dimen_base + display_width_code, dimen_base); - primitive_tex("displayindent", assign_dimen_cmd, dimen_base + display_indent_code, dimen_base); - primitive_tex("overfullrule", assign_dimen_cmd, dimen_base + overfull_rule_code, dimen_base); - primitive_tex("hangindent", assign_dimen_cmd, dimen_base + hang_indent_code, dimen_base); - primitive_tex("hoffset", assign_dimen_cmd, dimen_base + h_offset_code, dimen_base); - primitive_tex("voffset", assign_dimen_cmd, dimen_base + v_offset_code, dimen_base); - primitive_tex("emergencystretch", assign_dimen_cmd, dimen_base + emergency_stretch_code, dimen_base); - primitive_luatex("pagewidth", assign_dimen_cmd, dimen_base + page_width_code, dimen_base); - primitive_luatex("pageheight", assign_dimen_cmd, dimen_base + page_height_code, dimen_base); - primitive_luatex("pxdimen", assign_dimen_cmd, dimen_base + px_dimen_code, dimen_base); - primitive_luatex("predisplaygapfactor", assign_int_cmd, int_base + math_pre_display_gap_factor_code, int_base); - primitive_luatex("hyphenpenaltymode", assign_int_cmd, int_base + hyphen_penalty_mode_code, int_base); - primitive_luatex("automatichyphenpenalty", assign_int_cmd, int_base + automatic_hyphen_penalty_code, int_base); - primitive_luatex("explicithyphenpenalty", assign_int_cmd, int_base + explicit_hyphen_penalty_code, int_base); - primitive_luatex("automatichyphenmode", assign_int_cmd, int_base + automatic_hyphen_mode_code, int_base); - primitive_luatex("compoundhyphenmode", assign_int_cmd, int_base + compound_hyphen_mode_code, int_base); - primitive_luatex("breakafterdirmode", assign_int_cmd, int_base + break_after_dir_mode_code, int_base); - primitive_luatex("exceptionpenalty", assign_int_cmd, int_base + exception_penalty_code, int_base); - primitive_luatex("fixupboxesmode", assign_int_cmd, int_base + fixup_boxes_code, int_base); - primitive_luatex("glyphdimensionsmode", assign_int_cmd, int_base + glyph_dimensions_code, int_base); - - /*tex - - Many of \TeX's primitives need no |equiv|, since they are identifiable by - their |eq_type| alone. These primitives are loaded into the hash table as - follows: - - */ - - primitive_tex(" ", ex_space_cmd, 0, 0); - primitive_tex("/", ital_corr_cmd, 0, 0); - primitive_tex("accent", accent_cmd, 0, 0); - primitive_tex("advance", advance_cmd, 0, 0); - primitive_tex("afterassignment", after_assignment_cmd, 0, 0); - primitive_tex("aftergroup", after_group_cmd, 0, 0); - primitive_tex("begingroup", begin_group_cmd, 0, 0); - primitive_tex("char", char_num_cmd, 0, 0); - primitive_tex("csname", cs_name_cmd, 0, 0); - primitive_luatex("lastnamedcs", cs_name_cmd, 1, 0); - primitive_luatex("begincsname", cs_name_cmd, 2, 0); - primitive_tex("delimiter", delim_num_cmd, 0, 0); - primitive_luatex("Udelimiter", delim_num_cmd, 1, 0); - primitive_tex("divide", divide_cmd, 0, 0); - primitive_tex("endcsname", end_cs_name_cmd, 0, 0); - primitive_tex("endgroup", end_group_cmd, 0, 0); - cs_text(frozen_end_group) = maketexstring("endgroup"); - eqtb[frozen_end_group] = eqtb[cur_val]; - primitive_tex("expandafter", expand_after_cmd, 0, 0); - primitive_tex("font", def_font_cmd, 0, 0); - primitive_luatex("letterspacefont", letterspace_font_cmd, 0, 0); - primitive_luatex("expandglyphsinfont", normal_cmd, expand_font_code, 0); - primitive_luatex("copyfont", copy_font_cmd, 0, 0); - primitive_luatex("setfontid", set_font_id_cmd, 0, 0); - primitive_tex("fontdimen", assign_font_dimen_cmd, 0, 0); - primitive_tex("halign", halign_cmd, 0, 0); - primitive_tex("hrule", hrule_cmd, 0, 0); - primitive_luatex("nohrule", no_hrule_cmd, 0, 0); - primitive_tex("ignorespaces", ignore_spaces_cmd, 0, 0); - primitive_tex("insert", insert_cmd, 0, 0); - primitive_luatex("leftghost", char_ghost_cmd, 0, 0); - primitive_tex("mark", mark_cmd, 0, 0); - primitive_tex("mathaccent", math_accent_cmd, 0, 0); - primitive_luatex("Umathaccent", math_accent_cmd, 1, 0); - primitive_tex("mathchar", math_char_num_cmd, 0, 0); - primitive_luatex("Umathchar", math_char_num_cmd, 1, 0); - primitive_luatex("Umathcharnum", math_char_num_cmd, 2, 0); - primitive_tex("mathchoice", math_choice_cmd, 0, 0); - primitive_luatex("Ustack", math_choice_cmd, 1, 0); - primitive_tex("multiply", multiply_cmd, 0, 0); - primitive_tex("noalign", no_align_cmd, 0, 0); - primitive_tex("noboundary", boundary_cmd, 0, 0); - primitive_tex("boundary", boundary_cmd, 1, 0); - primitive_tex("protrusionboundary", boundary_cmd, 2, 0); - primitive_tex("wordboundary", boundary_cmd, 3, 0); - primitive_tex("noexpand", no_expand_cmd, 0, 0); - primitive_luatex("primitive", no_expand_cmd, 1, 0); - primitive_tex("nonscript", non_script_cmd, 0, 0); - primitive_tex("omit", omit_cmd, 0, 0); - primitive_tex("parshape", set_tex_shape_cmd, par_shape_loc, par_shape_loc); - primitive_tex("penalty", break_penalty_cmd, 0, 0); - primitive_tex("prevgraf", set_prev_graf_cmd, 0, 0); - primitive_tex("radical", radical_cmd, 0, 0); - primitive_luatex("Uradical", radical_cmd, 1, 0); - primitive_luatex("Uroot", radical_cmd, 2, 0); - primitive_luatex("Uunderdelimiter", radical_cmd, 3, 0); - primitive_luatex("Uoverdelimiter", radical_cmd, 4, 0); - primitive_luatex("Udelimiterunder", radical_cmd, 5, 0); - primitive_luatex("Udelimiterover", radical_cmd, 6, 0); - primitive_luatex("Uhextensible", radical_cmd, 7, 0); - primitive_tex("read", read_to_cs_cmd, 0, 0); - primitive_tex("relax", relax_cmd, too_big_char, too_big_char); - cs_text(frozen_relax) = maketexstring("relax"); - eqtb[frozen_relax] = eqtb[cur_val]; - primitive_luatex("rightghost", char_ghost_cmd, 1, 0); - primitive_tex("setbox", set_box_cmd, 0, 0); - primitive_tex("the", the_cmd, 0, 0); - primitive_luatex("toksapp", combine_toks_cmd, 0, 0); - primitive_luatex("etoksapp", combine_toks_cmd, 1, 0); - primitive_luatex("tokspre", combine_toks_cmd, 2, 0); - primitive_luatex("etokspre", combine_toks_cmd, 3, 0); - primitive_luatex("gtoksapp", combine_toks_cmd, 4, 0); - primitive_luatex("xtoksapp", combine_toks_cmd, 5, 0); - primitive_luatex("gtokspre", combine_toks_cmd, 6, 0); - primitive_luatex("xtokspre", combine_toks_cmd, 7, 0); - primitive_tex("toks", toks_register_cmd, 0, 0); - primitive_tex("vadjust", vadjust_cmd, 0, 0); - primitive_tex("valign", valign_cmd, 0, 0); - primitive_tex("vcenter", vcenter_cmd, 0, 0); - primitive_tex("vrule", vrule_cmd, 0, 0); - primitive_luatex("novrule", no_vrule_cmd, 0, 0); - primitive_luatex("luafunctioncall", lua_function_call_cmd, 0, 0); - primitive_luatex("luabytecodecall", lua_bytecode_call_cmd, 0, 0); - primitive_luatex("luadef", def_lua_call_cmd, 0, 0); - primitive_tex("par", par_end_cmd, too_big_char, too_big_char); - par_loc = cur_val; - par_token = cs_token_flag + par_loc; - - /*tex - The processing of \.{\\input} involves the |start_input| subroutine, - which will be declared later; the processing of \.{\\endinput} is trivial. - */ - - primitive_tex("input", input_cmd, 0, 0); - primitive_tex("endinput", input_cmd, 1, 0); - primitive_tex("topmark", top_bot_mark_cmd, top_mark_code, 0); - primitive_tex("firstmark", top_bot_mark_cmd, first_mark_code, 0); - primitive_tex("botmark", top_bot_mark_cmd, bot_mark_code, 0); - primitive_tex("splitfirstmark", top_bot_mark_cmd, split_first_mark_code, 0); - primitive_tex("splitbotmark", top_bot_mark_cmd, split_bot_mark_code, 0); - primitive_luatex("clearmarks", mark_cmd, clear_marks_code, 0); - primitive_etex("marks", mark_cmd, marks_code, 0); - primitive_etex("topmarks", top_bot_mark_cmd, top_mark_code + marks_code, 0); - primitive_etex("firstmarks", top_bot_mark_cmd, first_mark_code + marks_code, 0); - primitive_etex("botmarks", top_bot_mark_cmd, bot_mark_code + marks_code, 0); - primitive_etex("splitfirstmarks", top_bot_mark_cmd, split_first_mark_code + marks_code, 0); - primitive_etex("splitbotmarks", top_bot_mark_cmd, split_bot_mark_code + marks_code, 0); - - /* - The hash table is initialized with `\.{\\count}', `\.{\\attribute}', - `\.{\\dimen}', `\.{\\skip}', and `\.{\\muskip}' all having |register| - as their command code; they are distinguished by the |chr_code|, which - is either |int_val|, |attr_val|, |dimen_val|, |glue_val|, or |mu_val|. - */ - - primitive_tex("count", register_cmd, int_val_level, 0); - primitive_luatex("attribute", register_cmd, attr_val_level, 0); - primitive_tex("dimen", register_cmd, dimen_val_level, 0); - primitive_tex("skip", register_cmd, glue_val_level, 0); - primitive_tex("muskip", register_cmd, mu_val_level, 0); - - primitive_tex("spacefactor", set_aux_cmd, hmode, 0); - primitive_tex("prevdepth", set_aux_cmd, vmode, 0); - primitive_tex("deadcycles", set_page_int_cmd, 0, 0); - primitive_tex("insertpenalties", set_page_int_cmd, 1, 0); - primitive_tex("wd", set_box_dimen_cmd, width_offset, 0); - primitive_tex("ht", set_box_dimen_cmd, height_offset, 0); - primitive_tex("dp", set_box_dimen_cmd, depth_offset, 0); - primitive_tex("lastpenalty", last_item_cmd, lastpenalty_code, 0); - primitive_tex("lastkern", last_item_cmd, lastkern_code, 0); - primitive_tex("lastskip", last_item_cmd, lastskip_code, 0); - primitive_tex("inputlineno", last_item_cmd, input_line_no_code, 0); - primitive_tex("badness", last_item_cmd, badness_code, 0); - primitive_luatex("luatexversion", last_item_cmd, luatex_version_code, 0); - primitive_luatex("lastsavedboxresourceindex", last_item_cmd, last_saved_box_resource_index_code, 0); - primitive_luatex("lastsavedimageresourceindex", last_item_cmd, last_saved_image_resource_index_code, 0); - primitive_luatex("lastsavedimageresourcepages", last_item_cmd, last_saved_image_resource_pages_code, 0); - primitive_luatex("lastxpos", last_item_cmd, last_x_pos_code, 0); - primitive_luatex("lastypos", last_item_cmd, last_y_pos_code, 0); - primitive_luatex("randomseed", last_item_cmd, random_seed_code, 0); - - primitive_tex("number", convert_cmd, number_code, 0); - primitive_tex("romannumeral", convert_cmd, roman_numeral_code, 0); - primitive_tex("string", convert_cmd, string_code, 0); - primitive_luatex("csstring", convert_cmd, cs_string_code, 0); - primitive_tex("meaning", convert_cmd, meaning_code, 0); - primitive_etex("eTeXVersion", convert_cmd, etex_code, 0); - primitive_tex("fontname", convert_cmd, font_name_code, 0); - primitive_luatex("fontid", convert_cmd, font_id_code, 0); - primitive_luatex("luatexrevision", convert_cmd, luatex_revision_code, 0); - primitive_luatex("luatexbanner", convert_cmd, luatex_banner_code, 0); - primitive_luatex("leftmarginkern", convert_cmd, left_margin_kern_code, 0); - primitive_luatex("rightmarginkern", convert_cmd, right_margin_kern_code, 0); - primitive_luatex("uniformdeviate", convert_cmd, uniform_deviate_code, 0); - primitive_luatex("normaldeviate", convert_cmd, normal_deviate_code, 0); - primitive_core("directlua", convert_cmd, lua_code, 0); - primitive_luatex("luafunction", convert_cmd, lua_function_code, 0); - primitive_luatex("luabytecode", convert_cmd, lua_bytecode_code, 0); - primitive_luatex("luaescapestring", convert_cmd, lua_escape_string_code, 0); - primitive_luatex("mathstyle", convert_cmd, math_style_code, 0); - primitive_luatex("expanded", convert_cmd, expanded_code, 0); - primitive_luatex("immediateassignment", convert_cmd, immediate_assignment_code, 0); - primitive_luatex("immediateassigned", convert_cmd, immediate_assigned_code, 0); - primitive_tex("jobname", convert_cmd, job_name_code, 0); - primitive_luatex("formatname", convert_cmd, format_name_code, 0); - primitive_luatex("Uchar", convert_cmd, uchar_code, 0); - - primitive_luatex("Umathcharclass", convert_cmd, math_char_class_code, 0); - primitive_luatex("Umathcharfam", convert_cmd, math_char_fam_code, 0); - primitive_luatex("Umathcharslot", convert_cmd, math_char_slot_code, 0); - - primitive_tex("if", if_test_cmd, if_char_code, 0); - primitive_tex("ifcat", if_test_cmd, if_cat_code, 0); - primitive_tex("ifnum", if_test_cmd, if_int_code, 0); - primitive_tex("ifdim", if_test_cmd, if_dim_code, 0); - primitive_tex("ifodd", if_test_cmd, if_odd_code, 0); - primitive_tex("ifvmode", if_test_cmd, if_vmode_code, 0); - primitive_tex("ifhmode", if_test_cmd, if_hmode_code, 0); - primitive_tex("ifmmode", if_test_cmd, if_mmode_code, 0); - primitive_tex("ifinner", if_test_cmd, if_inner_code, 0); - primitive_tex("ifvoid", if_test_cmd, if_void_code, 0); - primitive_tex("ifhbox", if_test_cmd, if_hbox_code, 0); - primitive_tex("ifvbox", if_test_cmd, if_vbox_code, 0); - primitive_tex("ifx", if_test_cmd, if_x_code, 0); - primitive_tex("ifeof", if_test_cmd, if_eof_code, 0); - primitive_tex("iftrue", if_test_cmd, if_true_code, 0); - primitive_tex("iffalse", if_test_cmd, if_false_code, 0); - primitive_tex("ifcase", if_test_cmd, if_case_code, 0); - primitive_luatex("ifprimitive", if_test_cmd, if_primitive_code, 0); - primitive_luatex("ifcondition", if_test_cmd, if_condition_code, 0); - primitive_tex("fi", fi_or_else_cmd, fi_code, 0); - cs_text(frozen_fi) = maketexstring("fi"); - eqtb[frozen_fi] = eqtb[cur_val]; - primitive_tex("or", fi_or_else_cmd, or_code, 0); - primitive_tex("else", fi_or_else_cmd, else_code, 0); - - /* - \TeX\ always knows at least one font, namely the null font. It has no - characters, and its seven parameters are all equal to zero. - */ - - primitive_tex("nullfont", set_font_cmd, null_font, 0); - cs_text(frozen_null_font) = maketexstring("nullfont"); - eqtb[frozen_null_font] = eqtb[cur_val]; - - primitive_tex("span", tab_mark_cmd, span_code, tab_mark_cmd_code); - primitive_luatex("aligntab", tab_mark_cmd, tab_mark_cmd_code, tab_mark_cmd_code); - primitive_luatex("alignmark", mac_param_cmd, tab_mark_cmd_code, tab_mark_cmd_code); - primitive_tex("cr", car_ret_cmd, cr_code, cr_code); - cs_text(frozen_cr) = maketexstring("cr"); - eqtb[frozen_cr] = eqtb[cur_val]; - primitive_tex("crcr", car_ret_cmd, cr_cr_code, cr_code); - cs_text(frozen_end_template) = maketexstring("endtemplate"); - cs_text(frozen_endv) = maketexstring("endtemplate"); - set_eq_type(frozen_endv, endv_cmd); - set_equiv(frozen_endv, null_list); - set_eq_level(frozen_endv, level_one); - eqtb[frozen_end_template] = eqtb[frozen_endv]; - set_eq_type(frozen_end_template, end_template_cmd); - - primitive_tex("pagegoal", set_page_dimen_cmd, 0, 0); - primitive_tex("pagetotal", set_page_dimen_cmd, 1, 0); - primitive_tex("pagestretch", set_page_dimen_cmd, 2, 0); - primitive_tex("pagefilstretch", set_page_dimen_cmd, 3, 0); - primitive_tex("pagefillstretch", set_page_dimen_cmd, 4, 0); - primitive_tex("pagefilllstretch", set_page_dimen_cmd, 5, 0); - primitive_tex("pageshrink", set_page_dimen_cmd, 6, 0); - primitive_tex("pagedepth", set_page_dimen_cmd, 7, 0); - - /* - Either \.{\\dump} or \.{\\end} will cause |main_control| to enter the - endgame, since both of them have `|stop|' as their command code. - */ - - primitive_tex("end", stop_cmd, 0, 0); - primitive_tex("dump", stop_cmd, 1, 0); - - primitive_tex("hskip", hskip_cmd, skip_code, 0); - primitive_tex("hfil", hskip_cmd, fil_code, 0); - primitive_tex("hfill", hskip_cmd, fill_code, 0); - primitive_tex("hss", hskip_cmd, ss_code, 0); - primitive_tex("hfilneg", hskip_cmd, fil_neg_code, 0); - primitive_tex("vskip", vskip_cmd, skip_code, 0); - primitive_tex("vfil", vskip_cmd, fil_code, 0); - primitive_tex("vfill", vskip_cmd, fill_code, 0); - primitive_tex("vss", vskip_cmd, ss_code, 0); - primitive_tex("vfilneg", vskip_cmd, fil_neg_code, 0); - primitive_tex("mskip", mskip_cmd, mskip_code, 0); - primitive_tex("kern", kern_cmd, explicit_kern, 0); - primitive_tex("mkern", mkern_cmd, mu_glue, 0); - primitive_tex("moveleft", hmove_cmd, 1, 0); - primitive_tex("moveright", hmove_cmd, 0, 0); - primitive_tex("raise", vmove_cmd, 1, 0); - primitive_tex("lower", vmove_cmd, 0, 0); - primitive_tex("box", make_box_cmd, box_code, 0); - primitive_tex("copy", make_box_cmd, copy_code, 0); - primitive_tex("lastbox", make_box_cmd, last_box_code, 0); - primitive_tex("vsplit", make_box_cmd, vsplit_code, 0); - primitive_tex("tpack", make_box_cmd, tpack_code, 0); - primitive_tex("vpack", make_box_cmd, vpack_code, 0); - primitive_tex("hpack", make_box_cmd, hpack_code, 0); - primitive_tex("vtop", make_box_cmd, vtop_code, 0); - primitive_tex("vbox", make_box_cmd, vtop_code + vmode, 0); - primitive_tex("hbox", make_box_cmd, vtop_code + hmode, 0); - primitive_tex("shipout", leader_ship_cmd, a_leaders - 2, 0); /* |ship_out_flag=leader_flag-2| */ - primitive_tex("leaders", leader_ship_cmd, a_leaders, 0); - primitive_tex("cleaders", leader_ship_cmd, c_leaders, 0); - primitive_tex("xleaders", leader_ship_cmd, x_leaders, 0); - primitive_luatex("gleaders", leader_ship_cmd, g_leaders, 0); - primitive_luatex("boxdir", assign_box_dir_cmd, 0, 0); - primitive_luatex("boxdirection", assign_box_direction_cmd, 0, 0); - primitive_tex("indent", start_par_cmd, 1, 0); - primitive_tex("noindent", start_par_cmd, 0, 0); - primitive_luatex("quitvmode", start_par_cmd, 2, 0); - primitive_tex("unpenalty", remove_item_cmd, penalty_node, 0); - primitive_tex("unkern", remove_item_cmd, kern_node, 0); - primitive_tex("unskip", remove_item_cmd, glue_node, 0); - primitive_tex("unhbox", un_hbox_cmd, box_code, 0); - primitive_tex("unhcopy", un_hbox_cmd, copy_code, 0); - primitive_tex("unvbox", un_vbox_cmd, box_code, 0); - primitive_tex("unvcopy", un_vbox_cmd, copy_code, 0); - primitive_tex("-", discretionary_cmd, explicit_disc, 0); /* good old tex */ - primitive_tex("discretionary", discretionary_cmd, discretionary_disc, 0); - primitive_luatex("explicitdiscretionary", discretionary_cmd, explicit_disc, 0); - primitive_luatex("automaticdiscretionary", discretionary_cmd, automatic_disc, 0); - primitive_luatex("localleftbox", assign_local_box_cmd, 0, 0); - primitive_luatex("localrightbox", assign_local_box_cmd, 1, 0); - - primitive_luatex("Ustartmath", math_shift_cs_cmd, text_style, 0); - primitive_luatex("Ustopmath", math_shift_cs_cmd, cramped_text_style, 0); - primitive_luatex("Ustartdisplaymath", math_shift_cs_cmd, display_style, 0); - primitive_luatex("Ustopdisplaymath", math_shift_cs_cmd, cramped_display_style, 0); - primitive_tex("eqno", eq_no_cmd, 0, 0); - primitive_tex("leqno", eq_no_cmd, 1, 0); - primitive_tex("mathord", math_comp_cmd, ord_noad_type, 0); - primitive_tex("mathop", math_comp_cmd, op_noad_type_normal, 0); - primitive_tex("mathbin", math_comp_cmd, bin_noad_type, 0); - primitive_tex("mathrel", math_comp_cmd, rel_noad_type, 0); - primitive_tex("mathopen", math_comp_cmd, open_noad_type, 0); - primitive_tex("mathclose", math_comp_cmd, close_noad_type, 0); - primitive_tex("mathpunct", math_comp_cmd, punct_noad_type, 0); - primitive_tex("mathinner", math_comp_cmd, inner_noad_type, 0); - primitive_tex("underline", math_comp_cmd, under_noad_type, 0); - primitive_tex("overline", math_comp_cmd, over_noad_type, 0); - primitive_tex("displaylimits", limit_switch_cmd, op_noad_type_normal, 0); - primitive_tex("limits", limit_switch_cmd, op_noad_type_limits, 0); - primitive_tex("nolimits", limit_switch_cmd, op_noad_type_no_limits, 0); - primitive_tex("displaystyle", math_style_cmd, display_style, 0); - primitive_tex("textstyle", math_style_cmd, text_style, 0); - primitive_tex("scriptstyle", math_style_cmd, script_style, 0); - primitive_tex("scriptscriptstyle", math_style_cmd, script_script_style, 0); - primitive_luatex("crampeddisplaystyle", math_style_cmd, cramped_display_style, 0); - primitive_luatex("crampedtextstyle", math_style_cmd, cramped_text_style, 0); - primitive_luatex("crampedscriptstyle", math_style_cmd, cramped_script_style, 0); - primitive_luatex("crampedscriptscriptstyle", math_style_cmd, cramped_script_script_style, 0); - primitive_luatex("Usuperscript", super_sub_script_cmd, sup_mark_cmd, sup_mark_cmd); - primitive_luatex("Usubscript", super_sub_script_cmd, sub_mark_cmd, sup_mark_cmd); - primitive_luatex("Unosuperscript", no_super_sub_script_cmd, sup_mark_cmd, sup_mark_cmd); - primitive_luatex("Unosubscript", no_super_sub_script_cmd, sub_mark_cmd, sup_mark_cmd); - primitive_tex("above", above_cmd, above_code, 0); - primitive_tex("over", above_cmd, over_code, 0); - primitive_tex("atop", above_cmd, atop_code, 0); - primitive_luatex("Uskewed", above_cmd, skewed_code, 0); - primitive_tex("abovewithdelims", above_cmd, delimited_code + above_code, 0); - primitive_tex("overwithdelims", above_cmd, delimited_code + over_code, 0); - primitive_tex("atopwithdelims", above_cmd, delimited_code + atop_code, 0); - primitive_luatex("Uskewedwithdelims", above_cmd, delimited_code + skewed_code, 0); - primitive_tex("left", left_right_cmd, left_noad_side, 0); - primitive_tex("right", left_right_cmd, right_noad_side, 0); - primitive_tex("middle", left_right_cmd, middle_noad_side, 0); - primitive_tex("Uleft", left_right_cmd, 10+left_noad_side, 0); - primitive_tex("Uright", left_right_cmd, 10+right_noad_side, 0); - primitive_tex("Umiddle", left_right_cmd, 10+middle_noad_side, 0); - primitive_luatex("Uvextensible", left_right_cmd, 10+no_noad_side, 0); - cs_text(frozen_right) = maketexstring("right"); - eqtb[frozen_right] = eqtb[cur_val]; - - primitive_tex("long", prefix_cmd, 1, 0); - primitive_tex("outer", prefix_cmd, 2, 0); - primitive_tex("global", prefix_cmd, 4, 0); - primitive_tex("def", def_cmd, 0, 0); - primitive_tex("gdef", def_cmd, 1, 0); - primitive_tex("edef", def_cmd, 2, 0); - primitive_tex("xdef", def_cmd, 3, 0); - primitive_tex("glet", let_cmd, 0, 0); - primitive_tex("let", let_cmd, 1, 0); - primitive_tex("futurelet", let_cmd, 2, 0); - primitive_luatex("letcharcode", let_cmd, 3, 0); - primitive_tex("chardef", shorthand_def_cmd, char_def_code, 0); - primitive_tex("mathchardef", shorthand_def_cmd, math_char_def_code, 0); - primitive_luatex("Umathchardef", shorthand_def_cmd, xmath_char_def_code, 0); - primitive_luatex("Umathcharnumdef", shorthand_def_cmd, umath_char_def_code, 0); - primitive_tex("countdef", shorthand_def_cmd, count_def_code, 0); - primitive_luatex("attributedef", shorthand_def_cmd, attribute_def_code, 0); - primitive_tex("dimendef", shorthand_def_cmd, dimen_def_code, 0); - primitive_tex("skipdef", shorthand_def_cmd, skip_def_code, 0); - primitive_tex("muskipdef", shorthand_def_cmd, mu_skip_def_code, 0); - primitive_tex("toksdef", shorthand_def_cmd, toks_def_code, 0); - primitive_tex("catcode", def_char_code_cmd, cat_code_base, cat_code_base); - primitive_tex("mathcode", def_char_code_cmd, math_code_base, cat_code_base); - primitive_tex("lccode", def_char_code_cmd, lc_code_base, cat_code_base); - primitive_tex("uccode", def_char_code_cmd, uc_code_base, cat_code_base); - primitive_tex("sfcode", def_char_code_cmd, sf_code_base, cat_code_base); - primitive_tex("delcode", def_del_code_cmd, del_code_base, del_code_base); - primitive_tex("textfont", def_family_cmd, text_size, 0); - primitive_tex("scriptfont", def_family_cmd, script_size, 0); - primitive_tex("scriptscriptfont", def_family_cmd, script_script_size, 0); - primitive_luatex("Umathquad", set_math_param_cmd, math_param_quad, 0); - primitive_luatex("Umathaxis", set_math_param_cmd, math_param_axis, 0); - - primitive_luatex("Umathoperatorsize", set_math_param_cmd, math_param_operator_size, 0); - primitive_luatex("Umathoverbarkern", set_math_param_cmd, math_param_overbar_kern, 0); - primitive_luatex("Umathoverbarrule", set_math_param_cmd, math_param_overbar_rule, 0); - primitive_luatex("Umathoverbarvgap", set_math_param_cmd, math_param_overbar_vgap, 0); - primitive_luatex("Umathunderbarkern", set_math_param_cmd, math_param_underbar_kern, 0); - primitive_luatex("Umathunderbarrule", set_math_param_cmd, math_param_underbar_rule, 0); - primitive_luatex("Umathunderbarvgap", set_math_param_cmd, math_param_underbar_vgap, 0); - primitive_luatex("Umathradicalkern", set_math_param_cmd, math_param_radical_kern, 0); - primitive_luatex("Umathradicalrule", set_math_param_cmd, math_param_radical_rule, 0); - primitive_luatex("Umathradicalvgap", set_math_param_cmd, math_param_radical_vgap, 0); - primitive_luatex("Umathradicaldegreebefore", set_math_param_cmd, math_param_radical_degree_before, 0); - primitive_luatex("Umathradicaldegreeafter", set_math_param_cmd, math_param_radical_degree_after, 0); - primitive_luatex("Umathradicaldegreeraise", set_math_param_cmd, math_param_radical_degree_raise, 0); - primitive_luatex("Umathstackvgap", set_math_param_cmd, math_param_stack_vgap, 0); - primitive_luatex("Umathstacknumup", set_math_param_cmd, math_param_stack_num_up, 0); - primitive_luatex("Umathstackdenomdown", set_math_param_cmd, math_param_stack_denom_down, 0); - primitive_luatex("Umathfractionrule", set_math_param_cmd, math_param_fraction_rule, 0); - primitive_luatex("Umathfractionnumvgap", set_math_param_cmd, math_param_fraction_num_vgap, 0); - primitive_luatex("Umathfractionnumup", set_math_param_cmd, math_param_fraction_num_up, 0); - primitive_luatex("Umathfractiondenomvgap", set_math_param_cmd, math_param_fraction_denom_vgap, 0); - primitive_luatex("Umathfractiondenomdown", set_math_param_cmd, math_param_fraction_denom_down, 0); - primitive_luatex("Umathfractiondelsize", set_math_param_cmd, math_param_fraction_del_size, 0); - primitive_luatex("Umathskewedfractionvgap", set_math_param_cmd, math_param_skewed_fraction_vgap, 0); - primitive_luatex("Umathskewedfractionhgap", set_math_param_cmd, math_param_skewed_fraction_hgap, 0); - primitive_luatex("Umathlimitabovevgap", set_math_param_cmd, math_param_limit_above_vgap, 0); - primitive_luatex("Umathlimitabovebgap", set_math_param_cmd, math_param_limit_above_bgap, 0); - primitive_luatex("Umathlimitabovekern", set_math_param_cmd, math_param_limit_above_kern, 0); - primitive_luatex("Umathlimitbelowvgap", set_math_param_cmd, math_param_limit_below_vgap, 0); - primitive_luatex("Umathlimitbelowbgap", set_math_param_cmd, math_param_limit_below_bgap, 0); - primitive_luatex("Umathlimitbelowkern", set_math_param_cmd, math_param_limit_below_kern, 0); - primitive_luatex("Umathnolimitsubfactor", set_math_param_cmd, math_param_nolimit_sub_factor, 0); /* bonus */ - primitive_luatex("Umathnolimitsupfactor", set_math_param_cmd, math_param_nolimit_sup_factor, 0); /* bonus */ - primitive_luatex("Umathunderdelimitervgap", set_math_param_cmd, math_param_under_delimiter_vgap, 0); - primitive_luatex("Umathunderdelimiterbgap", set_math_param_cmd, math_param_under_delimiter_bgap, 0); - primitive_luatex("Umathoverdelimitervgap", set_math_param_cmd, math_param_over_delimiter_vgap, 0); - primitive_luatex("Umathoverdelimiterbgap", set_math_param_cmd, math_param_over_delimiter_bgap, 0); - primitive_luatex("Umathsubshiftdrop", set_math_param_cmd, math_param_sub_shift_drop, 0); - primitive_luatex("Umathsupshiftdrop", set_math_param_cmd, math_param_sup_shift_drop, 0); - primitive_luatex("Umathsubshiftdown", set_math_param_cmd, math_param_sub_shift_down, 0); - primitive_luatex("Umathsubsupshiftdown", set_math_param_cmd, math_param_sub_sup_shift_down, 0); - primitive_luatex("Umathsubtopmax", set_math_param_cmd, math_param_sub_top_max, 0); - primitive_luatex("Umathsupshiftup", set_math_param_cmd, math_param_sup_shift_up, 0); - primitive_luatex("Umathsupbottommin", set_math_param_cmd, math_param_sup_bottom_min, 0); - primitive_luatex("Umathsupsubbottommax", set_math_param_cmd, math_param_sup_sub_bottom_max, 0); - primitive_luatex("Umathsubsupvgap", set_math_param_cmd, math_param_subsup_vgap, 0); - primitive_luatex("Umathspaceafterscript", set_math_param_cmd, math_param_space_after_script, 0); - primitive_luatex("Umathconnectoroverlapmin", set_math_param_cmd, math_param_connector_overlap_min, 0); - primitive_luatex("Umathordordspacing", set_math_param_cmd, math_param_ord_ord_spacing, 0); - primitive_luatex("Umathordopspacing", set_math_param_cmd, math_param_ord_op_spacing, 0); - primitive_luatex("Umathordbinspacing", set_math_param_cmd, math_param_ord_bin_spacing, 0); - primitive_luatex("Umathordrelspacing", set_math_param_cmd, math_param_ord_rel_spacing, 0); - primitive_luatex("Umathordopenspacing", set_math_param_cmd, math_param_ord_open_spacing, 0); - primitive_luatex("Umathordclosespacing", set_math_param_cmd, math_param_ord_close_spacing, 0); - primitive_luatex("Umathordpunctspacing", set_math_param_cmd, math_param_ord_punct_spacing, 0); - primitive_luatex("Umathordinnerspacing", set_math_param_cmd, math_param_ord_inner_spacing, 0); - primitive_luatex("Umathopordspacing", set_math_param_cmd, math_param_op_ord_spacing, 0); - primitive_luatex("Umathopopspacing", set_math_param_cmd, math_param_op_op_spacing, 0); - primitive_luatex("Umathopbinspacing", set_math_param_cmd, math_param_op_bin_spacing, 0); - primitive_luatex("Umathoprelspacing", set_math_param_cmd, math_param_op_rel_spacing, 0); - primitive_luatex("Umathopopenspacing", set_math_param_cmd, math_param_op_open_spacing, 0); - primitive_luatex("Umathopclosespacing", set_math_param_cmd, math_param_op_close_spacing, 0); - primitive_luatex("Umathoppunctspacing", set_math_param_cmd, math_param_op_punct_spacing, 0); - primitive_luatex("Umathopinnerspacing", set_math_param_cmd, math_param_op_inner_spacing, 0); - primitive_luatex("Umathbinordspacing", set_math_param_cmd, math_param_bin_ord_spacing, 0); - primitive_luatex("Umathbinopspacing", set_math_param_cmd, math_param_bin_op_spacing, 0); - primitive_luatex("Umathbinbinspacing", set_math_param_cmd, math_param_bin_bin_spacing, 0); - primitive_luatex("Umathbinrelspacing", set_math_param_cmd, math_param_bin_rel_spacing, 0); - primitive_luatex("Umathbinopenspacing", set_math_param_cmd, math_param_bin_open_spacing, 0); - primitive_luatex("Umathbinclosespacing", set_math_param_cmd, math_param_bin_close_spacing, 0); - primitive_luatex("Umathbinpunctspacing", set_math_param_cmd, math_param_bin_punct_spacing, 0); - primitive_luatex("Umathbininnerspacing", set_math_param_cmd, math_param_bin_inner_spacing, 0); - primitive_luatex("Umathrelordspacing", set_math_param_cmd, math_param_rel_ord_spacing, 0); - primitive_luatex("Umathrelopspacing", set_math_param_cmd, math_param_rel_op_spacing, 0); - primitive_luatex("Umathrelbinspacing", set_math_param_cmd, math_param_rel_bin_spacing, 0); - primitive_luatex("Umathrelrelspacing", set_math_param_cmd, math_param_rel_rel_spacing, 0); - primitive_luatex("Umathrelopenspacing", set_math_param_cmd, math_param_rel_open_spacing, 0); - primitive_luatex("Umathrelclosespacing", set_math_param_cmd, math_param_rel_close_spacing, 0); - primitive_luatex("Umathrelpunctspacing", set_math_param_cmd, math_param_rel_punct_spacing, 0); - primitive_luatex("Umathrelinnerspacing", set_math_param_cmd, math_param_rel_inner_spacing, 0); - primitive_luatex("Umathopenordspacing", set_math_param_cmd, math_param_open_ord_spacing, 0); - primitive_luatex("Umathopenopspacing", set_math_param_cmd, math_param_open_op_spacing, 0); - primitive_luatex("Umathopenbinspacing", set_math_param_cmd, math_param_open_bin_spacing, 0); - primitive_luatex("Umathopenrelspacing", set_math_param_cmd, math_param_open_rel_spacing, 0); - primitive_luatex("Umathopenopenspacing", set_math_param_cmd, math_param_open_open_spacing, 0); - primitive_luatex("Umathopenclosespacing", set_math_param_cmd, math_param_open_close_spacing, 0); - primitive_luatex("Umathopenpunctspacing", set_math_param_cmd, math_param_open_punct_spacing, 0); - primitive_luatex("Umathopeninnerspacing", set_math_param_cmd, math_param_open_inner_spacing, 0); - primitive_luatex("Umathcloseordspacing", set_math_param_cmd, math_param_close_ord_spacing, 0); - primitive_luatex("Umathcloseopspacing", set_math_param_cmd, math_param_close_op_spacing, 0); - primitive_luatex("Umathclosebinspacing", set_math_param_cmd, math_param_close_bin_spacing, 0); - primitive_luatex("Umathcloserelspacing", set_math_param_cmd, math_param_close_rel_spacing, 0); - primitive_luatex("Umathcloseopenspacing", set_math_param_cmd, math_param_close_open_spacing, 0); - primitive_luatex("Umathcloseclosespacing", set_math_param_cmd, math_param_close_close_spacing, 0); - primitive_luatex("Umathclosepunctspacing", set_math_param_cmd, math_param_close_punct_spacing, 0); - primitive_luatex("Umathcloseinnerspacing", set_math_param_cmd, math_param_close_inner_spacing, 0); - primitive_luatex("Umathpunctordspacing", set_math_param_cmd, math_param_punct_ord_spacing, 0); - primitive_luatex("Umathpunctopspacing", set_math_param_cmd, math_param_punct_op_spacing, 0); - primitive_luatex("Umathpunctbinspacing", set_math_param_cmd, math_param_punct_bin_spacing, 0); - primitive_luatex("Umathpunctrelspacing", set_math_param_cmd, math_param_punct_rel_spacing, 0); - primitive_luatex("Umathpunctopenspacing", set_math_param_cmd, math_param_punct_open_spacing, 0); - primitive_luatex("Umathpunctclosespacing", set_math_param_cmd, math_param_punct_close_spacing, 0); - primitive_luatex("Umathpunctpunctspacing", set_math_param_cmd, math_param_punct_punct_spacing, 0); - primitive_luatex("Umathpunctinnerspacing", set_math_param_cmd, math_param_punct_inner_spacing, 0); - primitive_luatex("Umathinnerordspacing", set_math_param_cmd, math_param_inner_ord_spacing, 0); - primitive_luatex("Umathinneropspacing", set_math_param_cmd, math_param_inner_op_spacing, 0); - primitive_luatex("Umathinnerbinspacing", set_math_param_cmd, math_param_inner_bin_spacing, 0); - primitive_luatex("Umathinnerrelspacing", set_math_param_cmd, math_param_inner_rel_spacing, 0); - primitive_luatex("Umathinneropenspacing", set_math_param_cmd, math_param_inner_open_spacing, 0); - primitive_luatex("Umathinnerclosespacing", set_math_param_cmd, math_param_inner_close_spacing, 0); - primitive_luatex("Umathinnerpunctspacing", set_math_param_cmd, math_param_inner_punct_spacing, 0); - primitive_luatex("Umathinnerinnerspacing", set_math_param_cmd, math_param_inner_inner_spacing, 0); - - primitive_luatex("Umathcode", extdef_math_code_cmd, math_code_base, math_code_base); - primitive_luatex("Udelcode", extdef_del_code_cmd, del_code_base, del_code_base); - primitive_luatex("Umathcodenum", extdef_math_code_cmd, math_code_base + 1, math_code_base); - primitive_luatex("Udelcodenum", extdef_del_code_cmd, del_code_base + 1, del_code_base); - primitive_tex("hyphenation", hyph_data_cmd, 0, 0); - primitive_tex("patterns", hyph_data_cmd, 1, 0); - primitive_luatex("prehyphenchar", hyph_data_cmd, 2, 0); - primitive_luatex("posthyphenchar", hyph_data_cmd, 3, 0); - primitive_luatex("preexhyphenchar", hyph_data_cmd, 4, 0); - primitive_luatex("postexhyphenchar", hyph_data_cmd, 5, 0); - primitive_luatex("hyphenationmin", hyph_data_cmd, 6, 0); - primitive_luatex("hjcode", hyph_data_cmd, 7, 0); - primitive_tex("hyphenchar", assign_font_int_cmd, 0, 0); - primitive_tex("skewchar", assign_font_int_cmd, 1, 0); - primitive_luatex("lpcode", assign_font_int_cmd, lp_code_base, 0); - primitive_luatex("rpcode", assign_font_int_cmd, rp_code_base, 0); - primitive_luatex("efcode", assign_font_int_cmd, ef_code_base, 0); - primitive_luatex("tagcode", assign_font_int_cmd, tag_code, 0); - primitive_luatex("ignoreligaturesinfont", assign_font_int_cmd, no_lig_code, 0); - primitive_tex("batchmode", set_interaction_cmd, batch_mode, 0); - primitive_tex("nonstopmode", set_interaction_cmd, nonstop_mode, 0); - primitive_tex("scrollmode", set_interaction_cmd, scroll_mode, 0); - primitive_tex("errorstopmode", set_interaction_cmd, error_stop_mode, 0); - primitive_tex("openin", in_stream_cmd, 1, 0); - primitive_tex("closein", in_stream_cmd, 0, 0); - primitive_tex("message", message_cmd, 0, 0); - primitive_tex("errmessage", message_cmd, 1, 0); - primitive_tex("lowercase", case_shift_cmd, lc_code_base, lc_code_base); - primitive_tex("uppercase", case_shift_cmd, uc_code_base, lc_code_base); - primitive_tex("show", xray_cmd, show_code, 0); - primitive_tex("showbox", xray_cmd, show_box_code, 0); - primitive_tex("showthe", xray_cmd, show_the_code, 0); - primitive_tex("showlists", xray_cmd, show_lists, 0); - - primitive_tex("openout", extension_cmd, open_code, 0); - primitive_tex("write", extension_cmd, write_code, 0); - write_loc = cur_val; - primitive_tex("closeout", extension_cmd, close_code, 0); - primitive_luatex("endlocalcontrol", extension_cmd, end_local_code, 0); - primitive_tex("special", extension_cmd, special_code, 0); - cs_text(frozen_special) = maketexstring("special"); - eqtb[frozen_special] = eqtb[cur_val]; - primitive_tex("immediate", extension_cmd, immediate_code, 0); - primitive_luatex("localinterlinepenalty", assign_int_cmd, int_base + local_inter_line_penalty_code, int_base); - primitive_luatex("localbrokenpenalty", assign_int_cmd, int_base + local_broken_penalty_code, int_base); - primitive_luatex("pagedir", assign_dir_cmd, int_base + page_direction_code, dir_base); - primitive_luatex("bodydir", assign_dir_cmd, int_base + body_direction_code, dir_base); - primitive_luatex("pardir", assign_dir_cmd, int_base + par_direction_code, dir_base); - primitive_luatex("textdir", assign_dir_cmd, int_base + text_direction_code, dir_base); - primitive_luatex("mathdir", assign_dir_cmd, int_base + math_direction_code, dir_base); - primitive_luatex("linedir", assign_dir_cmd, int_base + line_direction_code, dir_base); - primitive_luatex("pageleftoffset", assign_dimen_cmd, dimen_base + page_left_offset_code, dimen_base); - primitive_luatex("pagetopoffset", assign_dimen_cmd, dimen_base + page_top_offset_code, dimen_base); - primitive_luatex("pagerightoffset", assign_dimen_cmd, dimen_base + page_right_offset_code, dimen_base); - primitive_luatex("pagebottomoffset", assign_dimen_cmd, dimen_base + page_bottom_offset_code, dimen_base); - primitive_luatex("saveboxresource", extension_cmd, save_box_resource_code, 0); - primitive_luatex("useboxresource", extension_cmd, use_box_resource_code, 0); - primitive_luatex("saveimageresource", extension_cmd, save_image_resource_code, 0); - primitive_luatex("useimageresource", extension_cmd, use_image_resource_code, 0); - primitive_luatex("savepos", normal_cmd, save_pos_code, 0); - primitive_luatex("savecatcodetable", normal_cmd, save_cat_code_table_code, 0); - primitive_luatex("initcatcodetable", normal_cmd, init_cat_code_table_code, 0); - primitive_luatex("setrandomseed", normal_cmd, set_random_seed_code, 0); - primitive_luatex("latelua", normal_cmd, late_lua_code, 0); - primitive_luatex("lateluafunction", normal_cmd, late_lua_call_code, 0); - primitive_luatex("insertht", convert_cmd, insert_ht_code, 0); - primitive_luatex("dviextension", extension_cmd, dvi_extension_code, 0); - primitive_luatex("dvifeedback", feedback_cmd, dvi_feedback_code, 0); - primitive_luatex("dvivariable", variable_cmd, dvi_variable_code, 0); - primitive_luatex("pdfextension", extension_cmd, pdf_extension_code, 0); - primitive_luatex("pdffeedback", feedback_cmd, pdf_feedback_code, 0); - primitive_luatex("pdfvariable", variable_cmd, pdf_variable_code, 0); - primitive_luatex("mathoption", option_cmd, math_option_code, 0); - - primitive_luatex("luacopyinputnodes", assign_int_cmd, int_base + copy_lua_input_nodes_code, int_base); - - primitive_luatex("pagedirection", assign_direction_cmd, int_base + page_direction_code, dir_base); - primitive_luatex("bodydirection", assign_direction_cmd, int_base + body_direction_code, dir_base); - primitive_luatex("pardirection", assign_direction_cmd, int_base + par_direction_code, dir_base); - primitive_luatex("textdirection", assign_direction_cmd, int_base + text_direction_code, dir_base); - primitive_luatex("mathdirection", assign_direction_cmd, int_base + math_direction_code, dir_base); - primitive_luatex("linedirection", assign_direction_cmd, int_base + line_direction_code, dir_base); - - /* - some of the internal integer parameters are not associated with actual - primitives at all. - */ - - primitive_no("nolocalwhatsits", assign_int_cmd, int_base + no_local_whatsits_code, int_base); - primitive_no("nolocaldirs", assign_int_cmd, int_base + no_local_dirs_code, int_base); - -} - -void initialize_etex_commands(void) -{ - primitive_etex("lastnodetype", last_item_cmd, last_node_type_code, 0); - primitive_etex("eTeXversion", last_item_cmd, eTeX_version_code, 0); - primitive_etex("eTeXminorversion", last_item_cmd, eTeX_minor_version_code, 0); - primitive_etex("eTeXrevision", convert_cmd, eTeX_revision_code, 0); - - /*tex - - First we implement the additional \eTeX\ parameters in the table of - equivalents. - */ - - primitive_etex("everyeof", assign_toks_cmd, every_eof_loc, local_base); - primitive_etex("tracingassigns", assign_int_cmd, int_base + tracing_assigns_code, int_base); - primitive_etex("tracinggroups", assign_int_cmd, int_base + tracing_groups_code, int_base); - primitive_etex("tracingifs", assign_int_cmd, int_base + tracing_ifs_code, int_base); - primitive_etex("tracingscantokens", assign_int_cmd, int_base + tracing_scan_tokens_code, int_base); - primitive_etex("tracingnesting", assign_int_cmd, int_base + tracing_nesting_code, int_base); - primitive_etex("predisplaydirection", assign_int_cmd, int_base + pre_display_direction_code, int_base); - primitive_etex("lastlinefit", assign_int_cmd, int_base + last_line_fit_code, int_base); - primitive_etex("savingvdiscards", assign_int_cmd, int_base + saving_vdiscards_code, int_base); - primitive_etex("savinghyphcodes", assign_int_cmd, int_base + saving_hyph_codes_code, int_base); - primitive_luatex("suppressfontnotfounderror", assign_int_cmd, int_base + suppress_fontnotfound_error_code, int_base); - primitive_luatex("suppresslongerror", assign_int_cmd, int_base + suppress_long_error_code, int_base); - primitive_luatex("suppressprimitiveerror", assign_int_cmd, int_base + suppress_primitive_error_code, int_base); - primitive_luatex("suppressmathparerror", assign_int_cmd, int_base + suppress_mathpar_error_code, int_base); - primitive_luatex("suppressifcsnameerror", assign_int_cmd, int_base + suppress_ifcsname_error_code, int_base); - primitive_luatex("suppressoutererror", assign_int_cmd, int_base + suppress_outer_error_code, int_base); - primitive_luatex("matheqnogapstep", assign_int_cmd, int_base + math_eqno_gap_step_code, int_base); - primitive_luatex("mathdisplayskipmode", assign_int_cmd, int_base + math_display_skip_mode_code, int_base); - primitive_luatex("mathscriptsmode", assign_int_cmd, int_base + math_scripts_mode_code, int_base); - primitive_luatex("mathnolimitsmode", assign_int_cmd, int_base + math_nolimits_mode_code, int_base); - primitive_luatex("mathitalicsmode", assign_int_cmd, int_base + math_italics_mode_code, int_base); - primitive_luatex("mathrulesmode", assign_int_cmd, int_base + math_rules_mode_code, int_base); - primitive_luatex("mathrulesfam", assign_int_cmd, int_base + math_rules_fam_code, int_base); - primitive_luatex("synctex", assign_int_cmd, int_base + synctex_code, int_base); - - primitive_etex("currentgrouplevel", last_item_cmd, current_group_level_code, 0); - primitive_etex("currentgrouptype", last_item_cmd, current_group_type_code, 0); - - primitive_etex("currentiflevel", last_item_cmd, current_if_level_code, 0); - primitive_etex("currentiftype", last_item_cmd, current_if_type_code, 0); - primitive_etex("currentifbranch", last_item_cmd, current_if_branch_code, 0); - primitive_etex("fontcharwd", last_item_cmd, font_char_wd_code, 0); - primitive_etex("fontcharht", last_item_cmd, font_char_ht_code, 0); - primitive_etex("fontchardp", last_item_cmd, font_char_dp_code, 0); - primitive_etex("fontcharic", last_item_cmd, font_char_ic_code, 0); - - primitive_etex("parshapelength", last_item_cmd, par_shape_length_code, 0); - primitive_etex("parshapeindent", last_item_cmd, par_shape_indent_code, 0); - primitive_etex("parshapedimen", last_item_cmd, par_shape_dimen_code, 0); - - primitive_luatex("shapemode", assign_int_cmd, int_base + shape_mode_code, int_base); - primitive_luatex("hyphenationbounds", assign_int_cmd, int_base + hyphenation_bounds_code, int_base); - - primitive_etex("showgroups", xray_cmd, show_groups, 0); - - /*tex - - The \.{\\showtokens} command displays a token list. - - */ - - primitive_etex("showtokens", xray_cmd, show_tokens, 0); - - /*tex - - The \.{\\unexpanded} primitive prevents expansion of tokens much as the - result from \.{\\the} applied to a token variable. The \.{\\detokenize} - primitive converts a token list into a list of character tokens much as - if the token list were written to a file. We use the fact that the - command modifiers for \.{\\unexpanded} and \.{\\detokenize} are odd - whereas those for \.{\\the} and \.{\\showthe} are even. - - */ - - primitive_etex("unexpanded", the_cmd, 1, 0); - primitive_etex("detokenize", the_cmd, show_tokens, 0); - - /*tex - - The \.{\\showifs} command displays all currently active conditionals. - - */ - - primitive_etex("showifs", xray_cmd, show_ifs, 0); - - /*tex - - The \.{\\interactionmode} primitive allows to query and set the interaction mode. - - */ - - primitive_etex("interactionmode", set_page_int_cmd, 2, 0); - - /*tex - - The |scan_tokens| feature of \eTeX\ defines the \.{\\scantokens} primitive. - - */ - - primitive_etex("scantokens", input_cmd, 2, 0); - primitive_luatex("scantextokens", input_cmd, 3, 0); - - primitive_etex("readline", read_to_cs_cmd, 1, 0); - - primitive_etex("unless", expand_after_cmd, 1, 0); - primitive_etex("ifdefined", if_test_cmd, if_def_code, 0); - primitive_etex("ifcsname", if_test_cmd, if_cs_code, 0); - primitive_etex("iffontchar", if_test_cmd, if_font_char_code, 0); - primitive_luatex("ifincsname", if_test_cmd, if_in_csname_code, 0); - primitive_luatex("ifabsnum", if_test_cmd, if_abs_num_code, 0); - primitive_luatex("ifabsdim", if_test_cmd, if_abs_dim_code, 0); - - /*tex - - The |protected| feature of \eTeX\ defines the \.{\\protected} prefix - command for macro definitions. Such macros are protected against - expansions when lists of expanded tokens are built, e.g., for \.{\\edef} - or during \.{\\write}. - */ - - primitive_etex("protected", prefix_cmd, 8, 0); - - /*tex - - Here are the additional \eTeX\ primitives for expressions. - - */ - - primitive_etex("numexpr", last_item_cmd, eTeX_expr - int_val_level + int_val_level, 0); - primitive_etex("dimexpr", last_item_cmd, eTeX_expr - int_val_level + dimen_val_level, 0); - primitive_etex("glueexpr", last_item_cmd, eTeX_expr - int_val_level + glue_val_level, 0); - primitive_etex("muexpr", last_item_cmd, eTeX_expr - int_val_level + mu_val_level, 0); - - primitive_etex("gluestretchorder", last_item_cmd, glue_stretch_order_code, 0); - primitive_etex("glueshrinkorder", last_item_cmd, glue_shrink_order_code, 0); - primitive_etex("gluestretch", last_item_cmd, glue_stretch_code, 0); - primitive_etex("glueshrink", last_item_cmd, glue_shrink_code, 0); - - primitive_luatex("eTeXgluestretchorder", last_item_cmd, eTeX_glue_stretch_order_code, 0); - primitive_luatex("eTeXglueshrinkorder", last_item_cmd, eTeX_glue_shrink_order_code, 0); - - primitive_etex("mutoglue", last_item_cmd, mu_to_glue_code, 0); - primitive_etex("gluetomu", last_item_cmd, glue_to_mu_code, 0); - - /*tex - - The \.{\\pagediscards} and \.{\\splitdiscards} commands share the command - code |un_vbox| with \.{\\unvbox} and \.{\\unvcopy}, they are - distinguished by their |chr_code| values |last_box_code| and - |vsplit_code|. These |chr_code| values are larger than |box_code| and - |copy_code|. - - */ - - primitive_etex("pagediscards", un_vbox_cmd, last_box_code, 0); - primitive_etex("splitdiscards", un_vbox_cmd, vsplit_code, 0); - - /*tex - - The \.{\\interlinepenalties}, \.{\\clubpenalties}, \.{\\widowpenalties}, - and \.{\\displaywidowpenalties} commands allow to define arrays of - penalty values to be used instead of the corresponding single values. - - */ - - primitive_etex("interlinepenalties", set_etex_shape_cmd, inter_line_penalties_loc, etex_pen_base); - primitive_etex("clubpenalties", set_etex_shape_cmd, club_penalties_loc, etex_pen_base); - primitive_etex("widowpenalties", set_etex_shape_cmd, widow_penalties_loc, etex_pen_base); - primitive_etex("displaywidowpenalties", set_etex_shape_cmd, display_widow_penalties_loc, etex_pen_base); - -} diff --git a/Build/source/texk/web2c/luatexdir/tex/commands.h b/Build/source/texk/web2c/luatexdir/tex/commands.h deleted file mode 100644 index 7d7a7056564..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/commands.h +++ /dev/null @@ -1,359 +0,0 @@ -/* commands.h - - Copyright 2008 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ - - -#ifndef COMMANDS_H -# define COMMANDS_H - -/* -Before we can go any further, we need to define symbolic names for the internal -code numbers that represent the various commands obeyed by \TeX. These codes -are somewhat arbitrary, but not completely so. For example, the command -codes for character types are fixed by the language, since a user says, -e.g., `\.{\\catcode \`\\\${} = 3}' to make \.{\char'44} a math delimiter, -and the command code |math_shift| is equal to~3. Some other codes have -been made adjacent so that |case| statements in the program need not consider -cases that are widely spaced, or so that |case| statements can be replaced -by |if| statements. - -At any rate, here is the list, for future reference. First come the -``catcode'' commands, several of which share their numeric codes with -ordinary commands when the catcode cannot emerge from \TeX's scanning routine. - -@ Next are the ordinary run-of-the-mill command codes. Codes that are -|min_internal| or more represent internal quantities that might be -expanded by `\.{\\the}'. - - -@ The next codes are special; they all relate to mode-independent -assignment of values to \TeX's internal registers or tables. -Codes that are |max_internal| or less represent internal quantities -that might be expanded by `\.{\\the}'. - -There is no matching primitive to go with |assign_attr|, but even if -there was no \.{\\attributedef}, a reserved number would still be -needed because there is an implied correspondence between the -|assign_xxx| commands and |xxx_val| expression values. That would -break down otherwise. - -@ The remaining command codes are extra special, since they cannot get through -\TeX's scanner to the main control routine. They have been given values higher -than |max_command| so that their special nature is easily discernible. -The ``expandable'' commands come first. - - -*/ - -typedef enum { - relax_cmd = 0, /* do nothing ( \.{\\relax} ) */ -# define escape_cmd relax_cmd /* escape delimiter (called \.\\ in {\sl The \TeX book\/}) */ - left_brace_cmd, /* beginning of a group ( \.\{ ) */ - right_brace_cmd, /* ending of a group ( \.\} ) */ - math_shift_cmd, /* mathematics shift character ( \.\$ ) */ - tab_mark_cmd, /* alignment delimiter ( \.\&, \.{\\span} ) */ - car_ret_cmd, /* end of line ( |carriage_return|, \.{\\cr}, \.{\\crcr} ) */ -# define out_param_cmd car_ret_cmd /* output a macro parameter */ - mac_param_cmd, /* macro parameter symbol ( \.\# ) */ - sup_mark_cmd, /* superscript ( \.{\char'136} ) */ - sub_mark_cmd, /* subscript ( \.{\char'137} ) */ - endv_cmd, /* end of \<v_j> list in alignment template */ -# define ignore_cmd endv_cmd /* characters to ignore ( \.{\^\^@@} ) */ - spacer_cmd, /* characters equivalent to blank space ( \.{\ } ) */ - letter_cmd, /* characters regarded as letters ( \.{A..Z}, \.{a..z} ) */ - other_char_cmd, /* none of the special character types */ - par_end_cmd, /* end of paragraph ( \.{\\par} ) */ -# define active_char_cmd par_end_cmd /* characters that invoke macros ( \.{\char`\~} ) */ -# define match_cmd par_end_cmd /* match a macro parameter */ - stop_cmd, /* end of job ( \.{\\end}, \.{\\dump} ) */ -# define comment_cmd stop_cmd /* characters that introduce comments ( \.\% ) */ -# define end_match_cmd stop_cmd /* end of parameters to macro */ - delim_num_cmd, /* specify delimiter numerically ( \.{\\delimiter} ) */ -# define invalid_char_cmd delim_num_cmd /* characters that shouldn't appear ( \.{\^\^?} ) */ -# define max_char_code_cmd delim_num_cmd /* largest catcode for individual characters */ - char_num_cmd, /* character specified numerically ( \.{\\char} ) */ - math_char_num_cmd, /* explicit math code ( \.{\\mathchar} ) */ - mark_cmd, /* mark definition ( \.{\\mark} ) */ - node_cmd, - xray_cmd, /* peek inside of \TeX\ ( \.{\\show}, \.{\\showbox}, etc.~) */ - make_box_cmd, /* make a box ( \.{\\box}, \.{\\copy}, \.{\\hbox}, etc.~) */ - hmove_cmd, /* horizontal motion ( \.{\\moveleft}, \.{\\moveright} ) */ - vmove_cmd, /* vertical motion ( \.{\\raise}, \.{\\lower} ) */ - un_hbox_cmd, /* unglue a box ( \.{\\unhbox}, \.{\\unhcopy} ) */ - un_vbox_cmd, /* unglue a box ( \.{\\unvbox}, \.{\\unvcopy} or \.{\\pagediscards}, \.{\\splitdiscards} ) */ - remove_item_cmd, /* nullify last item ( \.{\\unpenalty}, \.{\\unkern}, \.{\\unskip} ) */ - hskip_cmd, /* horizontal glue ( \.{\\hskip}, \.{\\hfil}, etc.~) */ - vskip_cmd, /* vertical glue ( \.{\\vskip}, \.{\\vfil}, etc.~) */ - mskip_cmd, /* math glue ( \.{\\mskip} ) */ - kern_cmd, /* fixed space ( \.{\\kern}) */ - mkern_cmd, /* math kern ( \.{\\mkern} ) */ - leader_ship_cmd, /* use a box ( \.{\\shipout}, \.{\\leaders}, etc.~) */ - halign_cmd, /* horizontal table alignment ( \.{\\halign} ) */ - valign_cmd, /* vertical table alignment ( \.{\\valign} ) */ - no_align_cmd, /* temporary escape from alignment ( \.{\\noalign} ) */ - vrule_cmd, /* vertical rule ( \.{\\vrule} ) */ - hrule_cmd, /* horizontal rule ( \.{\\hrule} ) */ - no_vrule_cmd, /* no rule, just reserve space ( \.{\\novrule} )*/ - no_hrule_cmd, /* no rule, just reserve space ( \.{\\nohrule} )*/ - insert_cmd, /* vlist inserted in box ( \.{\\insert} ) */ - vadjust_cmd, /* vlist inserted in enclosing paragraph ( \.{\\vadjust} ) */ - ignore_spaces_cmd, /* gobble |spacer| tokens ( \.{\\ignorespaces} ) */ - after_assignment_cmd, /* save till assignment is done ( \.{\\afterassignment} ) */ - after_group_cmd, /* save till group is done ( \.{\\aftergroup} ) */ - break_penalty_cmd, /* additional badness ( \.{\\penalty} ) */ - start_par_cmd, /* begin paragraph ( \.{\\indent}, \.{\\noindent} ) */ - ital_corr_cmd, /* italic correction ( \.{\\/} ) */ - accent_cmd, /* attach accent in text ( \.{\\accent} ) */ - math_accent_cmd, /* attach accent in math ( \.{\\mathaccent} ) */ - discretionary_cmd, /* discretionary texts ( \.{\\-}, \.{\\discretionary} ) */ - eq_no_cmd, /* equation number ( \.{\\eqno}, \.{\\leqno} ) */ - left_right_cmd, /* variable delimiter ( \.{\\left}, \.{\\right} or \.{\\middle} ) */ - math_comp_cmd, /* component of formula ( \.{\\mathbin}, etc.~) */ - limit_switch_cmd, /* diddle limit conventions ( \.{\\displaylimits}, etc.~) */ - above_cmd, /* generalized fraction ( \.{\\above}, \.{\\atop}, etc.~) */ - math_style_cmd, /* style specification ( \.{\\displaystyle}, etc.~) */ - math_choice_cmd, /* choice specification ( \.{\\mathchoice} ) */ - non_script_cmd, /* conditional math glue ( \.{\\nonscript} ) */ - vcenter_cmd, /* vertically center a vbox ( \.{\\vcenter} ) */ - case_shift_cmd, /* force specific case ( \.{\\lowercase}, \.{\\uppercase}~) */ - message_cmd, /* send to user ( \.{\\message}, \.{\\errmessage} ) */ - normal_cmd, /* general extensions to \TeX\ that don't fit into a category */ - extension_cmd, /* extensions to \TeX\ ( \.{\\write}, \.{\\special}, etc.~) */ - option_cmd, - lua_function_call_cmd, - lua_bytecode_call_cmd, - lua_call_cmd, - in_stream_cmd, /* files for reading ( \.{\\openin}, \.{\\closein} ) */ - begin_group_cmd, /* begin local grouping ( \.{\\begingroup} ) */ - end_group_cmd, /* end local grouping ( \.{\\endgroup} ) */ - omit_cmd, /* omit alignment template ( \.{\\omit} ) */ - ex_space_cmd, /* explicit space ( \.{\\\ } ) */ - boundary_cmd, /* insert boundry node with value ( \.{\\*boundary} ) */ - radical_cmd, /* square root and similar signs ( \.{\\radical} ) */ - super_sub_script_cmd, /* explicit super- or subscript */ - no_super_sub_script_cmd, /* explicit no super- or subscript */ - math_shift_cs_cmd, /* start- and endmath */ - end_cs_name_cmd, /* end control sequence ( \.{\\endcsname} ) */ - char_ghost_cmd, /* \.{\\leftghost}, \.{\\rightghost} character for kerning */ - assign_local_box_cmd, /* box for guillemets \.{\\localleftbox} or \.{\\localrightbox} */ - char_given_cmd, /* character code defined by \.{\\chardef} */ -# define min_internal_cmd char_given_cmd /* the smallest code that can follow \.{\\the} */ - math_given_cmd, /* math code defined by \.{\\mathchardef} */ - xmath_given_cmd, /* math code defined by \.{\\Umathchardef} or \.{\\Umathcharnumdef} */ - last_item_cmd, /* most recent item ( \.{\\lastpenalty}, \.{\\lastkern}, \.{\\lastskip} ) */ -# define max_non_prefixed_command_cmd last_item_cmd /* largest command code that can't be \.{\\global} */ - toks_register_cmd, /* token list register ( \.{\\toks} ) */ - assign_toks_cmd, /* special token list ( \.{\\output}, \.{\\everypar}, etc.~) */ - assign_int_cmd, /* user-defined integer ( \.{\\tolerance}, \.{\\day}, etc.~) */ - assign_attr_cmd, /* user-defined attributes */ - assign_dimen_cmd, /* user-defined length ( \.{\\hsize}, etc.~) */ - assign_glue_cmd, /* user-defined glue ( \.{\\baselineskip}, etc.~) */ - assign_mu_glue_cmd, /* user-defined muglue ( \.{\\thinmuskip}, etc.~) */ - assign_font_dimen_cmd, /* user-defined font dimension ( \.{\\fontdimen} ) */ - assign_font_int_cmd, /* user-defined font integer ( \.{\\hyphenchar}, \.{\\skewchar} ) */ - assign_hang_indent_cmd, - set_aux_cmd, /* specify state info ( \.{\\spacefactor}, \.{\\prevdepth} ) */ - set_prev_graf_cmd, /* specify state info ( \.{\\prevgraf} ) */ - set_page_dimen_cmd, /* specify state info ( \.{\\pagegoal}, etc.~) */ - set_page_int_cmd, /* specify state info ( \.{\\deadcycles}, \.{\\insertpenalties} ) */ - set_box_dimen_cmd, /* change dimension of box ( \.{\\wd}, \.{\\ht}, \.{\\dp} ) */ - set_tex_shape_cmd, /* specify fancy paragraph shape ( \.{\\parshape} ) */ - set_etex_shape_cmd, /* specify etex extended list ( \.{\\interlinepenalties}, etc.~) */ - def_char_code_cmd, /* define a character code ( \.{\\catcode}, etc.~) */ - def_del_code_cmd, /* define a delimiter code ( \.{\\delcode}) */ - extdef_math_code_cmd, /* define an extended character code ( \.{\\Umathcode}, etc.~) */ - extdef_del_code_cmd, /* define an extended delimiter code ( \.{\\Udelcode}, etc.~) */ - def_family_cmd, /* declare math fonts ( \.{\\textfont}, etc.~) */ - set_math_param_cmd, /* set math parameters ( \.{\\mathquad}, etc.~) */ - set_font_cmd, /* set current font ( font identifiers ) */ - def_font_cmd, /* define a font file ( \.{\\font} ) */ - register_cmd, /* internal register ( \.{\\count}, \.{\\dimen}, etc.~) */ - assign_box_direction_cmd, /* (\.{\\boxdirection}) */ - assign_box_dir_cmd, /* (\.{\\boxdir}) */ - assign_direction_cmd, /* (\.{\\pagedirection}, \.{\\textdirection}) */ - assign_dir_cmd, /* (\.{\\pagedir}, \.{\\textdir}) */ - combine_toks_cmd, -# define max_internal_cmd assign_dir_cmd /* the largest code that can follow \.{\\the} */ - advance_cmd, /* advance a register or parameter ( \.{\\advance} ) */ - multiply_cmd, /* multiply a register or parameter ( \.{\\multiply} ) */ - divide_cmd, /* divide a register or parameter ( \.{\\divide} ) */ - prefix_cmd, /* qualify a definition ( \.{\\global}, \.{\\long}, \.{\\outer} ) */ - let_cmd, /* assign a command code ( \.{\\let}, \.{\\futurelet} ) */ - shorthand_def_cmd, /* code definition ( \.{\\chardef}, \.{\\countdef}, etc.~) */ - def_lua_call_cmd, - read_to_cs_cmd, /* read into a control sequence ( \.{\\read} ) */ - def_cmd, /* macro definition ( \.{\\def}, \.{\\gdef}, \.{\\xdef}, \.{\\edef} ) */ - set_box_cmd, /* set a box ( \.{\\setbox} ) */ - hyph_data_cmd, /* hyphenation data ( \.{\\hyphenation}, \.{\\patterns} ) */ - set_interaction_cmd, /* define level of interaction ( \.{\\batchmode}, etc.~) */ - letterspace_font_cmd, /* letterspace a font ( \.{\\letterspacefont} ) */ - expand_font_cmd, /* expand glyphs ( \.{\\expandglyphsinfont} ) */ - copy_font_cmd, /* create a new font instance ( \.{\\copyfont} ) */ - set_font_id_cmd, - undefined_cs_cmd, /* initial state of most |eq_type| fields */ - expand_after_cmd, /* special expansion ( \.{\\expandafter} ) */ - no_expand_cmd, /* special nonexpansion ( \.{\\noexpand} ) */ - input_cmd, /* input a source file ( \.{\\input}, \.{\\endinput} or \.{\\scantokens} or \.{\\scantextokens} ) */ - lua_expandable_call_cmd, - lua_local_call_cmd, - if_test_cmd, /* conditional text ( \.{\\if}, \.{\\ifcase}, etc.~) */ - fi_or_else_cmd, /* delimiters for conditionals ( \.{\\else}, etc.~) */ - cs_name_cmd, /* make a control sequence from tokens ( \.{\\csname} ) */ - convert_cmd, /* convert to text ( \.{\\number}, \.{\\string}, etc.~) */ - variable_cmd, - feedback_cmd, - the_cmd, /* expand an internal quantity ( \.{\\the} or \.{\\unexpanded}, \.{\\detokenize} ) */ - top_bot_mark_cmd, /* inserted mark ( \.{\\topmark}, etc.~) */ - call_cmd, /* non-long, non-outer control sequence */ - long_call_cmd, /* long, non-outer control sequence */ - outer_call_cmd, /* non-long, outer control sequence */ - long_outer_call_cmd, /* long, outer control sequence */ - end_template_cmd, /* end of an alignment template */ - dont_expand_cmd, /* the following token was marked by \.{\\noexpand} */ - glue_ref_cmd, /* the equivalent points to a glue specification */ - shape_ref_cmd, /* the equivalent points to a parshape specification */ - box_ref_cmd, /* the equivalent points to a box node, or is |null| */ - data_cmd, /* the equivalent is simply a halfword number */ -} tex_command_code; - -# define max_command_cmd set_font_id_cmd /* the largest command code seen at |big_switch| */ -# define last_cmd data_cmd -# define max_non_prefixed_command last_item_cmd - -typedef enum { - above_code = 0, - over_code = 1, - atop_code = 2, - skewed_code = 3, - delimited_code = 4, -} fraction_codes; - -typedef enum { - number_code = 0, /* command code for \.{\\number} */ - lua_code, /* command code for \.{\\directlua} */ - lua_function_code, /* command code for \.{\\luafunction} */ - lua_bytecode_code, /* command code for \.{\\luabytecode} */ - expanded_code, /* command code for \.{\\expanded} */ - immediate_assignment_code, /* command code for \.{\\immediateassignment} */ - immediate_assigned_code, /* command code for \.{\\assigned} */ - math_style_code, /* command code for \.{\\mathstyle} */ - string_code, /* command code for \.{\\string} */ - cs_string_code, /* command code for \.{\\csstring} */ - roman_numeral_code, /* command code for \.{\\romannumeral} */ - meaning_code, /* command code for \.{\\meaning} */ - uchar_code, /* command code for \.{\\Uchar} */ - lua_escape_string_code, /* command code for \.{\\luaescapestring} */ - font_id_code, /* command code for \.{\\fontid} */ - font_name_code, /* command code for \.{\\fontname} */ - left_margin_kern_code, /* command code for \.{\\leftmarginkern} */ - right_margin_kern_code, /* command code for \.{\\rightmarginkern} */ - uniform_deviate_code, /* command code for \.{\\uniformdeviate} */ - normal_deviate_code, /* command code for \.{\\normaldeviate} */ - math_char_class_code, - math_char_fam_code, - math_char_slot_code, - insert_ht_code, /* command code for \.{\\insertht} */ - job_name_code, /* command code for \.{\\jobname} */ - format_name_code, /* command code for \.{\\AlephVersion} */ - luatex_banner_code, /* command code for \.{\\luatexbanner}: */ - luatex_revision_code, /* command code for \.{\\luatexrevision} */ - etex_code, /* command code for \.{\\eTeXVersion} */ - eTeX_revision_code, /* command code for \.{\\eTeXrevision} */ - font_identifier_code, /* command code for \.{tex.fontidentifier} (virtual) */ - /* backend */ - dvi_feedback_code, - pdf_feedback_code, - dvi_variable_code, - pdf_variable_code, -} convert_codes; - -typedef enum { - lastpenalty_code = 0, /* code for \.{\\lastpenalty} */ - lastattr_code, /* not used */ - lastkern_code, /* code for \.{\\lastkern} */ - lastskip_code, /* code for \.{\\lastskip} */ - last_node_type_code, /* code for \.{\\lastnodetype} */ - input_line_no_code, /* code for \.{\\inputlineno} */ - badness_code, /* code for \.{\\badness} */ - last_saved_box_resource_index_code, /* code for \.{\\lastsavedboxresourceindex} */ - last_saved_image_resource_index_code, /* code for \.{\\lastsavedimageresourceindex} */ - last_saved_image_resource_pages_code, /* code for \.{\\lastsavedimageresourcepages} */ - last_x_pos_code, /* code for \.{\\lastxpos} */ - last_y_pos_code, /* code for \.{\\lastypos} */ - random_seed_code, /* code for \.{\\randomseed} */ - luatex_version_code, /* code for \.{\\luatexversion} */ - eTeX_minor_version_code, /* code for \.{\\eTeXminorversion} */ - eTeX_version_code, /* code for \.{\\eTeXversion} */ -# define eTeX_int eTeX_version_code /* first of \eTeX\ codes for integers */ - current_group_level_code, /* code for \.{\\currentgrouplevel} */ - current_group_type_code, /* code for \.{\\currentgrouptype} */ - current_if_level_code, /* code for \.{\\currentiflevel} */ - current_if_type_code, /* code for \.{\\currentiftype} */ - current_if_branch_code, /* code for \.{\\currentifbranch} */ - glue_stretch_order_code, /* code for \.{\\gluestretchorder} */ - glue_shrink_order_code, /* code for \.{\\glueshrinkorder} */ - eTeX_glue_stretch_order_code, /* code for \.{\\eTeXgluestretchorder} */ - eTeX_glue_shrink_order_code, /* code for \.{\\eTeXglueshrinkorder} */ - font_char_wd_code, /* code for \.{\\fontcharwd} */ -# define eTeX_dim font_char_wd_code /* first of \eTeX\ codes for dimensions */ - font_char_ht_code, /* code for \.{\\fontcharht} */ - font_char_dp_code, /* code for \.{\\fontchardp} */ - font_char_ic_code, /* code for \.{\\fontcharic} */ - par_shape_length_code, /* code for \.{\\parshapelength} */ - par_shape_indent_code, /* code for \.{\\parshapeindent} */ - par_shape_dimen_code, /* code for \.{\\parshapedimen} */ - glue_stretch_code, /* code for \.{\\gluestretch} */ - glue_shrink_code, /* code for \.{\\glueshrink} */ - mu_to_glue_code, /* code for \.{\\mutoglue} */ -# define eTeX_glue mu_to_glue_code /* first of \eTeX\ codes for glue */ - glue_to_mu_code, /* code for \.{\\gluetomu} */ -# define eTeX_mu glue_to_mu_code /* first of \eTeX\ codes for muglue */ - numexpr_code, /* code for \.{\\numexpr} */ -# define eTeX_expr numexpr_code /* first of \eTeX\ codes for expressions */ - attrexpr_code, /* not used */ - dimexpr_code, /* code for \.{\\dimexpr} */ - glueexpr_code, /* code for \.{\\glueexpr} */ - muexpr_code, /* code for \.{\\muexpr} */ -} last_item_codes; - - -typedef enum { - save_cat_code_table_code=0, - init_cat_code_table_code, - set_random_seed_code, - save_pos_code, - late_lua_code, - late_lua_call_code, - expand_font_code, -} normal_codes; - -typedef enum { - lp_code_base = 2, - rp_code_base = 3, - ef_code_base = 4, - tag_code = 5, - no_lig_code = 6, - gp_code_base = 7 -} font_codes ; - -# define immediate_code 4 /* command modifier for \.{\\immediate} */ - -extern void initialize_commands(void); -extern void initialize_etex_commands(void); - -#endif diff --git a/Build/source/texk/web2c/luatexdir/tex/conditional.c b/Build/source/texk/web2c/luatexdir/tex/conditional.c deleted file mode 100644 index 948db580340..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/conditional.c +++ /dev/null @@ -1,568 +0,0 @@ -/* - -conditional.w - -Copyright 2009-2010 Taco Hoekwater <taco@@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your -option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU General Public License along -with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" - -/*tex - -@* We consider now the way \TeX\ handles various kinds of \.{\\if} commands. - -Conditions can be inside conditions, and this nesting has a stack that is -independent of the |save_stack|. - -Four global variables represent the top of the condition stack: |cond_ptr| points -to pushed-down entries, if any; |if_limit| specifies the largest code of a -|fi_or_else| command that is syntactically legal; |cur_if| is the name of the -current type of conditional; and |if_line| is the line number at which it began. - -If no conditions are currently in progress, the condition stack has the special -state |cond_ptr=null|, |if_limit=normal|, |cur_if=0|, |if_line=0|. Otherwise -|cond_ptr| points to a two-word node; the |type|, |subtype|, and |link| fields of -the first word contain |if_limit|, |cur_if|, and |cond_ptr| at the next level, -and the second word contains the corresponding |if_line|. - -In |cond_ptr| we keep track of the top of the condition stack while |if_limit| -holds the upper bound on |fi_or_else| codes. The type of conditional being worked -on is stored in cur_if and |if_line| keeps track of the line where that -conditional began. When we skip conditional text, |skip_line| keeps track of the -line number where skipping began, for use in error messages. - -*/ - -halfword cond_ptr; -int if_limit, cur_if, if_line, skip_line; - -/*tex - -Here is a procedure that ignores text until coming to an \.{\\or}, \.{\\else}, or -\.{\\fi} at level zero of $\.{\\if}\ldots\.{\\fi}$ nesting. After it has acted, -|cur_chr| will indicate the token that was found, but |cur_tok| will not be set -(because this makes the procedure run faster). - -With |l| we keep track of the level of $\.{\\if}\ldots\.{\\fi}$ nesting and -|scanner_status| let us return to the entry status. - -*/ - -void pass_text(void) -{ - int l = 0; - int save_scanner_status = scanner_status; - scanner_status = skipping; - skip_line = line; - while (1) { - get_next(); - if (cur_cmd == fi_or_else_cmd) { - if (l == 0) - break; - if (cur_chr == fi_code) - decr(l); - } else if (cur_cmd == if_test_cmd) { - incr(l); - } - } - scanner_status = save_scanner_status; - if (tracing_ifs_par > 0) - show_cur_cmd_chr(); -} - -/*tex - -When we begin to process a new \.{\\if}, we set |if_limit:=if_code|; then if\/ -\.{\\or} or \.{\\else} or \.{\\fi} occurs before the current \.{\\if} condition -has been evaluated, \.{\\relax} will be inserted. For example, a sequence of -commands like `\.{\\ifvoid1\\else...\\fi}' would otherwise require something -after the `\.1'. - -*/ - -void push_condition_stack(void) -{ - halfword p = new_node(if_node, 0); - vlink(p) = cond_ptr; - if_limit_type(p) = (quarterword) if_limit; - if_limit_subtype(p) = (quarterword) cur_if; - if_line_field(p) = if_line; - cond_ptr = p; - cur_if = cur_chr; - if_limit = if_code; - if_line = line; -} - -void pop_condition_stack(void) -{ - halfword p; - if (if_stack[in_open] == cond_ptr) { - /*tex Conditionals are possibly not properly nested with files. */ - if_warning(); - } - p = cond_ptr; - if_line = if_line_field(p); - cur_if = if_limit_subtype(p); - if_limit = if_limit_type(p); - cond_ptr = vlink(p); - flush_node(p); -} - -/*tex - -Here's a procedure that changes the |if_limit| code corresponding to a given -value of |cond_ptr|. - -*/ - -void change_if_limit(int l, halfword p) -{ - if (p == cond_ptr) { - if_limit = l; - } else { - halfword q = cond_ptr; - while (1) { - if (q == null) - confusion("if"); - if (vlink(q) == p) { - if_limit_type(q) = (quarterword) l; - return; - } - q = vlink(q); - } - } -} - -/*tex - -The conditional \.{\\ifcsname} is equivalent to \.{\\expandafter} -\.{\\expandafter} \.{\\ifdefined} \.{\\csname}, except that no new control -sequence will be entered into the hash table (once all tokens preceding the -mandatory \.{\\endcsname} have been expanded). - -*/ - -static halfword last_tested_cs ; - -static boolean test_for_cs(void) -{ - /*tex Is the condition true? */ - boolean b = false; - /*tex To be tested against the second operand: */ - int m, s; - /*tex For traversing token lists in \.{\\ifx} tests: */ - halfword q; - halfword n = get_avail(); - /*tex Head of the list of characters: */ - halfword p = n; - is_in_csname += 1; - while (1) { - get_x_token(); - if (cur_cs != 0) - break; - store_new_token(cur_tok); - } - if (cur_cmd != end_cs_name_cmd) { - last_tested_cs = null_cs; - if (suppress_ifcsname_error_par) { - do { - get_x_token(); - } while (cur_cmd != end_cs_name_cmd); - flush_list(n); - is_in_csname -= 1; - return b; - } else { - complain_missing_csname(); - } - } - /*tex Look up the characters of list |n| in the hash table, and set |cur_cs|. */ - m = first; - p = token_link(n); - while (p != null) { - if (m >= max_buf_stack) { - max_buf_stack = m + 4; - if (max_buf_stack >= buf_size) - check_buffer_overflow(max_buf_stack); - } - s = token_chr(token_info(p)); - if (s <= 0x7F) { - buffer[m++] = (packed_ASCII_code) s; - } else if (s <= 0x7FF) { - buffer[m++] = (packed_ASCII_code) (0xC0 + s / 0x40); - buffer[m++] = (packed_ASCII_code) (0x80 + s % 0x40); - } else if (s <= 0xFFFF) { - buffer[m++] = (packed_ASCII_code) (0xE0 + s / 0x1000); - buffer[m++] = (packed_ASCII_code) (0x80 + (s % 0x1000) / 0x40); - buffer[m++] = (packed_ASCII_code) (0x80 + (s % 0x1000) % 0x40); - } else { - buffer[m++] = (packed_ASCII_code) (0xF0 + s / 0x40000); - buffer[m++] = (packed_ASCII_code) (0x80 + (s % 0x40000) / 0x1000); - buffer[m++] = (packed_ASCII_code) (0x80 + ((s % 0x40000) % 0x1000) / 0x40); - buffer[m++] = (packed_ASCII_code) (0x80 + ((s % 0x40000) % 0x1000) % 0x40); - } - p = token_link(p); - } - if (m > first) { - /*tex |no_new_control_sequence| is |true| */ - cur_cs = id_lookup(first, m - first); - } else if (m == first) { - /*tex the list is empty */ - cur_cs = null_cs; - } - b = (eq_type(cur_cs) != undefined_cs_cmd); - flush_list(n); - last_cs_name = cur_cs; - is_in_csname -= 1; - return b; -} - -/*tex - -An active character will be treated as category 13 following \.{\\if\\noexpand} -or following \.{\\ifcat\\noexpand}. - -*/ - -#define get_x_token_or_active_char() do { \ - get_x_token(); \ - if (cur_cmd==relax_cmd && cur_chr==no_expand_flag) { \ - if (is_active_cs(cs_text(cur_cs))) { \ - cur_cmd=active_char_cmd; \ - cur_chr=active_cs_value(cs_text(cur_tok-cs_token_flag)); \ - } \ - } \ -} while (0) - -/*tex - -A condition is started when the |expand| procedure encounters an |if_test| -command; in that case |expand| reduces to |conditional|, which is a recursive -procedure. @^recursion@> - -*/ - -void conditional(void) -{ - /*tex Is the condition true? */ - boolean b = false; - /*tex The relation to be evaluated: */ - int r; - /*tex To be tested against the second operand: */ - int m, n; - /*tex For traversing token lists in \.{\\ifx} tests: */ - halfword p, q; - /*tex The |scanner_status| upon entry: */ - int save_scanner_status; - /*tex The |cond_ptr| corresponding to this conditional: */ - halfword save_cond_ptr; - /*tex The type of this conditional: */ - int this_if; - /*tex Was this \.{\\if} preceded by \.{\\unless}? */ - boolean is_unless; - if ((tracing_ifs_par > 0) && (tracing_commands_par <= 1)) { - show_cur_cmd_chr(); - } - push_condition_stack(); - save_cond_ptr = cond_ptr; - is_unless = (cur_chr >= unless_code); - this_if = cur_chr % unless_code; - /*tex Either process \.{\\ifcase} or set |b| to the value of a boolean condition. */ - switch (this_if) { - case if_char_code: - case if_cat_code: - /*tex Test if two characters match. */ - get_x_token_or_active_char(); - if ((cur_cmd > active_char_cmd) || (cur_chr > biggest_char)) { - /*tex It's not a character. */ - m = relax_cmd; - n = too_big_char; - } else { - m = cur_cmd; - n = cur_chr; - } - get_x_token_or_active_char(); - if ((cur_cmd > active_char_cmd) || (cur_chr > biggest_char)) { - cur_cmd = relax_cmd; - cur_chr = too_big_char; - } - if (this_if == if_char_code) - b = (n == cur_chr); - else - b = (m == cur_cmd); - break; - case if_int_code: - case if_dim_code: - case if_abs_dim_code: - case if_abs_num_code: - /*tex - Test the relation between integers or dimensions. Here we use the fact - that |<|, |=|, and |>| are consecutive ASCII codes. - */ - if (this_if == if_int_code || this_if == if_abs_num_code) - scan_int(); - else - scan_normal_dimen(); - n = cur_val; - if ((n < 0) && (this_if == if_abs_dim_code || this_if == if_abs_num_code)) - negate(n); - /*tex Get the next non-blank non-call... */ - do { - get_x_token(); - } while (cur_cmd == spacer_cmd); - r = cur_tok - other_token; - if ((r < '<') || (r > '>')) { - print_err("Missing = inserted for "); - print_cmd_chr(if_test_cmd, this_if); - help1("I was expecting to see `<', `=', or `>'. Didn't."); - back_error(); - r = '='; - } - if (this_if == if_int_code || this_if == if_abs_num_code) - scan_int(); - else - scan_normal_dimen(); - if ((cur_val < 0) && (this_if == if_abs_dim_code || this_if == if_abs_num_code)) - negate(cur_val); - switch (r) { - case '<': - b = (n < cur_val); - break; - case '=': - b = (n == cur_val); - break; - case '>': - b = (n > cur_val); - break; - default: - /*tex This can't happen. */ - b = false; - break; - } - break; - case if_odd_code: - /*tex Test if an integer is odd. */ - scan_int(); - b = odd(cur_val); - break; - case if_vmode_code: - b = (abs(cur_list.mode_field) == vmode); - break; - case if_hmode_code: - b = (abs(cur_list.mode_field) == hmode); - break; - case if_mmode_code: - b = (abs(cur_list.mode_field) == mmode); - break; - case if_inner_code: - b = (cur_list.mode_field < 0); - break; - case if_void_code: - scan_register_num(); - p = box(cur_val); - b = (p == null); - break; - case if_hbox_code: - scan_register_num(); - p = box(cur_val); - b = (p != null) && (type(p) == hlist_node); - break; - case if_vbox_code: - scan_register_num(); - p = box(cur_val); - b = (p != null) && (type(p) == vlist_node); - break; - case if_x_code: - /*tex - Test if two tokens match. Note that `\.{\\ifx}' will declare two - macros different if one is \\{long} or \\{outer} and the other - isn't, even though the texts of the macros are the same. - - We need to reset |scanner_status|, since \.{\\outer} control - sequences are allowed, but we might be scanning a macro - definition or preamble. - */ - save_scanner_status = scanner_status; - scanner_status = normal; - get_next(); - n = cur_cs; - p = cur_cmd; - q = cur_chr; - get_next(); - if (cur_cmd != p) { - b = false; - } else if (cur_cmd < call_cmd) { - b = (cur_chr == q); - } else { - /*tex - Test if two macro texts match. Note also that `\.{\\ifx}' - decides that macros \.{\\a} and \.{\\b} are different in - examples like this: - - $$\vbox{\halign{\.{#}\hfil&\qquad\.{#}\hfil\cr - {}\\def\\a\{\\c\}& - {}\\def\\c\{\}\cr - {}\\def\\b\{\\d\}& - {}\\def\\d\{\}\cr}}$$ - */ - p = token_link(cur_chr); - /*tex Omit reference counts. */ - q = token_link(equiv(n)); - if (p == q) { - b = true; - } else { - while ((p != null) && (q != null)) { - if (token_info(p) != token_info(q)) { - p = null; - break; - } else { - p = token_link(p); - q = token_link(q); - } - } - b = ((p == null) && (q == null)); - } - } - scanner_status = save_scanner_status; - break; - case if_eof_code: - scan_four_bit_int(); - b = (read_open[cur_val] == closed); - break; - case if_true_code: - b = true; - break; - case if_false_code: - b = false; - break; - case if_case_code: - /*tex Select the appropriate case and |return| or |goto common_ending|. */ - scan_int(); - /*tex |n| is the number of cases to pass. */ - n = cur_val; - if (tracing_commands_par > 1) { - begin_diagnostic(); - tprint("{case "); - print_int(n); - print_char('}'); - end_diagnostic(false); - } - while (n != 0) { - pass_text(); - if (cond_ptr == save_cond_ptr) { - if (cur_chr == or_code) - decr(n); - else - goto COMMON_ENDING; - } else if (cur_chr == fi_code) { - pop_condition_stack(); - } - } - change_if_limit(or_code, save_cond_ptr); - /*tex Wait for \.{\\or}, \.{\\else}, or \.{\\fi}. */ - return; - break; - case if_primitive_code: - save_scanner_status = scanner_status; - scanner_status = normal; - get_next(); - scanner_status = save_scanner_status; - m = prim_lookup(cs_text(cur_cs)); - b = ((cur_cmd != undefined_cs_cmd) && - (m != undefined_primitive) && - (cur_cmd == get_prim_eq_type(m)) && - (cur_chr == get_prim_equiv(m))); - break; - case if_def_code: - /*tex - The conditional \.{\\ifdefined} tests if a control sequence is - defined. We need to reset |scanner_status|, since \.{\\outer} - control sequences are allowed, but we might be scanning a macro - definition or preamble. - */ - save_scanner_status = scanner_status; - scanner_status = normal; - get_next(); - b = (cur_cmd != undefined_cs_cmd); - scanner_status = save_scanner_status; - break; - case if_cs_code: - b = test_for_cs(); - break; - case if_in_csname_code: - b = is_in_csname; - break; - case if_font_char_code: - /*tex - The conditional \.{\\iffontchar} tests the existence of a - character in a font. - */ - scan_font_ident(); - n = cur_val; - scan_char_num(); - b = char_exists(n, cur_val); - break; - default: - /*tex there are no other cases, but we need to please |-Wall|. */ - b = false; - } - if (is_unless) - b = !b; - if (tracing_commands_par > 1) { - /*tex Display the value of |b|. */ - begin_diagnostic(); - if (b) - tprint("{true}"); - else - tprint("{false}"); - end_diagnostic(false); - } - if (b) { - change_if_limit(else_code, save_cond_ptr); - /*tex Wait for \.{\\else} or \.{\\fi}. */ - return; - } - /*tex - Skip to \.{\\else} or \.{\\fi}, then |goto common_ending|. In a - construction like `\.{\\if\\iftrue abc\\else d\\fi}', the first - \.{\\else} that we come to after learning that the \.{\\if} is false is - not the \.{\\else} we're looking for. Hence the following curious logic - is needed. - */ - while (1) { - pass_text(); - if (cond_ptr == save_cond_ptr) { - if (cur_chr != or_code) - goto COMMON_ENDING; - print_err("Extra \\or"); - help1( - "I'm ignoring this; it doesn't match any \\if." - ); - error(); - } else if (cur_chr == fi_code) { - pop_condition_stack(); - } - } - COMMON_ENDING: - if (cur_chr == fi_code) { - pop_condition_stack(); - } else { - /*tex Wait for \.{\\fi}. */ - if_limit = fi_code; - } -} diff --git a/Build/source/texk/web2c/luatexdir/tex/conditional.h b/Build/source/texk/web2c/luatexdir/tex/conditional.h deleted file mode 100644 index 483496eece2..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/conditional.h +++ /dev/null @@ -1,78 +0,0 @@ -/* conditional.h - - Copyright 2009 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef CONDITIONAL_H -# define CONDITIONAL_H - -# define unless_code 32 /* amount added for `\.{\\unless}' prefix */ - -typedef enum { - if_char_code = 0, /* \.{\\if} */ - if_cat_code = 1, /* \.{\\ifcat} */ - if_int_code = 2, /* \.{\\ifnum} */ - if_dim_code = 3, /* \.{\\ifdim} */ - if_odd_code = 4, /* \.{\\ifodd} */ - if_vmode_code = 5, /* \.{\\ifvmode} */ - if_hmode_code = 6, /* \.{\\ifhmode} */ - if_mmode_code = 7, /* \.{\\ifmmode} */ - if_inner_code = 8, /* \.{\\ifinner} */ - if_void_code = 9, /* \.{\\ifvoid} */ - if_hbox_code = 10, /* \.{\\ifhbox} */ - if_vbox_code = 11, /* \.{\\ifvbox} */ - if_x_code = 12, /* \.{\\ifx} */ - if_eof_code = 13, /* \.{\\ifeof} */ - if_true_code = 14, /* \.{\\iftrue} */ - if_false_code = 15, /* \.{\\iffalse} */ - if_case_code = 16, /* \.{\\ifcase} */ - if_def_code = 17, /* \.{\\ifdefined} */ - if_cs_code = 18, /* \.{\\ifcsname} */ - if_font_char_code = 19, /* \.{\\iffontchar} */ - if_in_csname_code = 20, /* \.{\\ifincsname} */ - if_primitive_code = 21, /* \.{\\ifprimitive} */ - if_abs_num_code = 22, /* \.{\\ifabsnum} */ - if_abs_dim_code = 23, /* \.{\\ifabsdim} */ - if_condition_code = 24, /* \.{\\ifcondition} */ -} if_type_codes; - -# define if_limit_subtype(A) subtype((A)+1) -# define if_limit_type(A) type((A)+1) -# define if_line_field(A) vlink((A)+1) - -typedef enum { - if_code = 1, /* \.{\\if...} */ - fi_code = 2, /* \.{\\fi} */ - else_code = 3, /* \.{\\else} */ - or_code = 4, /* \.{\\or} */ -} else_type_codes; - -extern halfword cond_ptr; /* top of the condition stack */ -extern int if_limit; /* upper bound on |fi_or_else| codes */ -extern int cur_if; /* type of conditional being worked on */ -extern int if_line; /* line where that conditional began */ -extern int skip_line; /* skipping began here */ - -extern void pass_text(void); -extern void push_condition_stack(void); -extern void pop_condition_stack(void); -extern void change_if_limit(int l, halfword p); - -extern void conditional(void); - -#endif diff --git a/Build/source/texk/web2c/luatexdir/tex/directions.c b/Build/source/texk/web2c/luatexdir/tex/directions.c deleted file mode 100644 index 59b2f7dcd85..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/directions.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - -directions.w - -Copyright 2009-2014 Taco Hoekwater <taco@@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your -option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU General Public License along -with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" - -void scan_direction(void) -{ - int save_cur_cmd = cur_cmd; - int save_cur_chr = cur_chr; - get_x_token(); - if (cur_cmd == assign_dir_cmd) { - cur_val = eqtb[cur_chr].cint; - goto EXIT; - } else { - back_input(); - } - if (scan_keyword("tlt")) { - cur_val = dir_TLT; - } else if (scan_keyword("trt")) { - cur_val = dir_TRT; - } else if (scan_keyword("ltl")) { - cur_val = dir_LTL; - } else if (scan_keyword("rtt")) { - cur_val = dir_RTT; - } else { - tex_error("Bad direction", NULL); - cur_val = 0; - } - get_x_token(); - if (cur_cmd != spacer_cmd) - back_input(); - EXIT: - cur_cmd = save_cur_cmd; - cur_chr = save_cur_chr; -} - -/*tex - - The next two are used by |postlinebreak.c|: - -*/ - -halfword do_push_dir_node(halfword p, halfword a) -{ - halfword n = copy_node(a); - vlink(n) = p; - return n; -} - -halfword do_pop_dir_node(halfword p) -{ - halfword n = vlink(p); - flush_node(p); - return n; -} - -halfword dir_ptr; -halfword text_dir_ptr; - -void initialize_directions(void) -{ - /*tex There is no need to do anything here at the moment. */ -} - -halfword new_dir(int s) -{ - halfword p = new_node(dir_node, 0); - dir_dir(p) = s; - dir_level(p) = cur_level; - return p; -} - -const char *dir_strings_par[4] = { [0] = - "TLT","TRT","LTL","RTT", -}; - -const char *dir_strings_text_normal[4] = { [0] = - "+TLT","+TRT","+LTL","+RTT", -}; - -const char *dir_strings_text_cancel[4] = { [0] = - "-TLT","-TRT","-LTL","-RTT", -}; - -void print_dir_par(int d) -{ - tprint(dir_strings_par[d]); -} - -void print_dir_text(halfword d) -{ - if (subtype(d) == cancel_dir) { - tprint(dir_strings_text_cancel[dir_dir(d)]); - } else { - tprint(dir_strings_text_normal[dir_dir(d)]); - } -} - -scaled pack_width(int curdir, int pdir, halfword p, boolean isglyph) -{ - scaled wd = 0; - if (isglyph) { - if (textdir_parallel(curdir, pdir) == textglyphdir_orthogonal(pdir)) { - wd = glyph_width(p); - if (ex_glyph(p) != 0) { - /* wd = round_xn_over_d(wd, 1000 + ex_glyph(p)/1000, 1000); */ - wd = ext_xn_over_d(wd, 1000000+ex_glyph(p), 1000000); - - } - } else { - wd = glyph_depth(p) + glyph_height(p); - } - } else { - if (textdir_parallel(pdir, curdir)) - wd = width(p); - else - wd = depth(p) + height(p); - } - return wd; -} - -scaled_whd pack_width_height_depth(int curdir, int pdir, halfword p, boolean isglyph) -{ - scaled_whd whd = { 0, 0, 0 }; - whd.wd = pack_width(curdir, pdir, p, isglyph); - if (isglyph) { - if (is_rotated(curdir)) { - if (textdir_parallel(curdir, pdir)) - whd.ht = whd.dp = (glyph_height(p) + glyph_depth(p)) / 2; - else - whd.ht = whd.dp = glyph_width(p) / 2; - } else if (is_rotated(pdir)) { - if (textdir_parallel(curdir, pdir)) - whd.ht = whd.dp = (glyph_height(p) + glyph_depth(p)) / 2; - else - whd.ht = glyph_width(p); - } else { - if (glyphdir_eq(curdir, pdir)) { - whd.ht = glyph_height(p); - whd.dp = glyph_depth(p); - } else if (glyphdir_opposite(curdir, pdir)) { - whd.ht = glyph_depth(p); - whd.dp = glyph_height(p); - } else - whd.ht = glyph_width(p); - } - } else { - if (is_rotated(curdir)) { - if (textdir_parallel(curdir, pdir)) - whd.ht = whd.dp = (height(p) + depth(p)) / 2; - else - whd.ht = whd.dp = width(p) / 2; - } else if (pardir_eq(curdir, pdir)) { - whd.ht = height(p); - whd.dp = depth(p); - } else if (pardir_opposite(curdir, pdir)) { - whd.ht = depth(p); - whd.dp = height(p); - } else - whd.ht = width(p); - } - return whd; -} - -void update_text_dir_ptr(int val) -{ - if (dir_level(text_dir_ptr) == cur_level) { - /* update */ - dir_dir(text_dir_ptr) = val; - } else { - /* addition */ - halfword text_dir_tmp = new_dir(val); - vlink(text_dir_tmp) = text_dir_ptr; - text_dir_ptr = text_dir_tmp; - } -} diff --git a/Build/source/texk/web2c/luatexdir/tex/directions.h b/Build/source/texk/web2c/luatexdir/tex/directions.h deleted file mode 100644 index 92d6cc18f12..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/directions.h +++ /dev/null @@ -1,168 +0,0 @@ -/* directions.h - - Copyright 2009 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ - - -#ifndef DIRECTIONS_H -# define DIRECTIONS_H - -/* -#define dir_swap 4 -*/ - -#define dir_min_value 0 -#define dir_max_value 3 - -#define check_dir_value(d) \ - if ((d < dir_min_value) || (d > dir_max_value)) \ - d = dir_min_value; - -#define is_mirrored(a) 0 - -#define is_rotated(a) (a == dir_RTT) - -/* - - # define textdir_parallel(a,b) ( \ - ((a == dir_TLT || a == dir_TRT) && (b == dir_TLT || b == dir_TRT)) || \ - ((a == dir_LTL || a == dir_RTT) && (b == dir_LTL || b == dir_RTT)) \ - ) - - # define pardir_parallel(a,b) ( \ - ((a == dir_TLT || a == dir_TRT) && (b == dir_TLT || b == dir_TRT)) || \ - ((a == dir_LTL || a == dir_RTT) && (b == dir_LTL || b == dir_RTT)) \ - ) - - # define pardir_eq(a,b) ( \ - ((a == dir_TLT || a == dir_TRT) && (b == dir_TLT || b == dir_TRT)) || \ - (a == dir_LTL && b == dir_LTL) || \ - (a == dir_RTT && b == dir_RTT) \ - ) - - # define textdir_eq(a,b) ( \ - (a == dir_TLT && b == dir_TLT) || \ - (a == dir_TRT && b == dir_TRT) || \ - (a == dir_LTL && (b == dir_LTL || b == dir_RTT)) || \ - (a == dir_RTT && (b == dir_LTL || b == dir_RTT)) - - # define partextdir_eq(a,b) ( \ - ((a == dir_TLT || a == dir_TRT) && (b == dir_LTL || b == dir_RTT)) || \ - (a == dir_LTL && b == dir_TLT) || \ - (a == dir_RTT && b == dir_TRT) \ - ) - - # define dir_TLT_or_TRT(a) (a == dir_TLT || a == dir_TRT) - # define dir_LTL_or_RTT(a) (a == dir_LTL || a == dir_RTT) - -*/ - -/* TLT TRT LTL RTT */ - -# define dir_TLT_or_TRT(a) (a < 2) -# define dir_LTL_or_RTT(a) (a > 1) - -# define textdir_parallel(a,b) ( \ - (dir_TLT_or_TRT(a) && dir_TLT_or_TRT(b)) || \ - (dir_LTL_or_RTT(a) && dir_LTL_or_RTT(b)) \ -) - -# define pardir_parallel(a,b) ( \ - (dir_TLT_or_TRT(a) && dir_TLT_or_TRT(b)) || \ - (dir_LTL_or_RTT(a) && dir_LTL_or_RTT(b)) \ -) - -# define pardir_opposite(a,b) ( \ - (a == dir_LTL && b == dir_RTT) || \ - (a == dir_RTT && b == dir_LTL) \ -) - -# define textdir_opposite(a,b) ( \ - (a == dir_TLT && b == dir_TRT) || \ - (a == dir_TRT && b == dir_TLT) \ -) - -# define glyphdir_opposite(a,b) 0 - -# define pardir_eq(a,b) ( \ - (dir_TLT_or_TRT(a) && dir_TLT_or_TRT(b)) || \ - (a == dir_LTL && b == dir_LTL) || \ - (a == dir_RTT && b == dir_RTT) \ -) - -# define textdir_eq(a,b) ( \ - (a == dir_TLT && b == dir_TLT) || \ - (a == dir_TRT && b == dir_TRT) || \ - (a == dir_LTL && dir_LTL_or_RTT(b)) || \ - (a == dir_RTT && dir_LTL_or_RTT(b)) \ -) - -# define glyphdir_eq(a,b) ( \ - (a != dir_LTL && b != dir_LTL) || \ - (a == dir_LTL && b == dir_LTL) \ -) - -# define partextdir_eq(a,b) ( \ - (dir_TLT_or_TRT(a) && dir_LTL_or_RTT(b)) || \ - (a == dir_LTL && b == dir_TLT) || \ - (a == dir_RTT && b == dir_TRT) \ -) - -# define textglyphdir_orthogonal(a) (a != dir_RTT) - -# define textdir_is_L(a) (a == dir_TLT) - -# define push_dir(p,a) { \ - halfword dir_tmp=new_dir((a)); \ - vlink(dir_tmp)=p; \ - p=dir_tmp; \ -} - -# define push_dir_node(p,a) { \ - halfword dir_tmp=copy_node((a)); \ - vlink(dir_tmp)=p; \ - p=dir_tmp; \ -} - -# define pop_dir_node(p) { \ - halfword dir_tmp=p; \ - p=vlink(dir_tmp); \ - flush_node(dir_tmp); \ -} - -extern halfword dir_ptr; - -extern halfword text_dir_ptr; - -extern void initialize_directions(void); -extern halfword new_dir(int s); - -extern const char *string_dir(int d); -extern void print_dir_par(int d); -extern void print_dir_text(halfword d); - -extern void scan_direction(void); - -extern halfword do_push_dir_node(halfword p, halfword a); -extern halfword do_pop_dir_node(halfword p); - -scaled pack_width(int curdir, int pdir, halfword p, boolean isglyph); -scaled_whd pack_width_height_depth(int curdir, int pdir, halfword p, boolean isglyph); - -void update_text_dir_ptr(int val); - -#endif diff --git a/Build/source/texk/web2c/luatexdir/tex/dumpdata.c b/Build/source/texk/web2c/luatexdir/tex/dumpdata.c deleted file mode 100644 index e7d53050b29..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/dumpdata.c +++ /dev/null @@ -1,539 +0,0 @@ -/* - -dumpdata.w - -Copyright 2009-2010 Taco Hoekwater <taco@@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your -option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU General Public License along -with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" - -/*tex - - We use a magic number to register the version of the format. Normally this - number only increments when we add a new primitive of change command codes. - We start with 907 which is the sum of the values of the bytes of \quote - {don knuth}. - -*/ - -#define FORMAT_ID (907+54) -#if ((FORMAT_ID>=0) && (FORMAT_ID<=256)) -#error Wrong value for FORMAT_ID. -#endif - -/*tex - -After \.{INITEX} has seen a collection of fonts and macros, it can write all the -necessary information on an auxiliary file so that production versions of \TeX\ -are able to initialize their memory at high speed. The present section of the -program takes care of such output and input. We shall consider simultaneously the -processes of storing and restoring, so that the inverse relation between them is -clear. @.INITEX@> - -The global variable |format_ident| is a string that is printed right after the -|banner| line when \TeX\ is ready to start. For \.{INITEX} this string says -simply `\.{(INITEX)}'; for other versions of \TeX\ it says, for example, -`\.{(preloaded format=plain 1982.11.19)}', showing the year, month, and day that -the format file was created. We have |format_ident=0| before \TeX's tables are -loaded. |FORMAT_ID| is a new field of type int suitable for the identification of -a format: values between 0 and 256 (included) can not be used because in the -previous format they are used for the length of the name of the engine. - -*/ - -str_number format_ident; -str_number format_name; - - -/*tex - -Format files consist of |memory_word| items, and we use the following macros to -dump words of different types: - -*/ - -FILE *fmt_file; - -void store_fmt_file(void) -{ - int j, k, l, x; - halfword p; - char *format_engine; - int callback_id; - char *fmtname = NULL; - /*tex - If dumping is not allowed, abort. The user is not allowed to dump a - format file unless |save_ptr=0|. This condition implies that - |cur_level=level_one|, hence the |xeq_level| array is constant and it - need not be dumped. - */ - if (save_ptr != 0) { - print_err("You can't dump inside a group"); - help1("`{...\\dump}' is a no-no."); - succumb(); - } - /*tex - Create the |format_ident|, open the format file, and inform the user that - dumping has begun. - */ - callback_id = callback_defined(pre_dump_callback); - if (callback_id > 0) { - (void) run_callback(callback_id, "->"); - } - selector = new_string; - tprint(" (format="); - print(job_name); - print_char(' '); - print_int(year_par); - print_char('.'); - print_int(month_par); - print_char('.'); - print_int(day_par); - print_char(')'); - str_room(2); - format_ident = make_string(); - print(job_name); - format_name = make_string(); - if (interaction == batch_mode) { - selector = log_only; - } else { - selector = term_and_log; - } - fmtname = pack_job_name(format_extension); - while (!zopen_w_output(&fmt_file, fmtname, FOPEN_WBIN_MODE)) { - fmtname = prompt_file_name("format file name", format_extension); - } - tprint_nl("Beginning to dump on file "); - tprint(fmtname); - free(fmtname); - tprint_nl(""); - print(format_ident); - /*tex - Dump constants for consistency check. The next few sections of the - program should make it clear how we use the dump/undump macros. First - comes Web2C \TeX's magic constant: "W2TX" - */ - dump_int(0x57325458); - dump_int(FORMAT_ID); - /*tex - We align |engine_name| to 4 bytes with one or more trailing |NUL|. - */ - x = (int) strlen(engine_name); - format_engine = xmalloc((unsigned) (x + 4)); - strcpy(format_engine, engine_name); - for (k = x; k <= x + 3; k++) - format_engine[k] = 0; - x = x + 4 - (x % 4); - dump_int(x); - dump_things(format_engine[0], x); - xfree(format_engine); - dump_int(0x57325458); - dump_int(max_halfword); - dump_int(hash_high); - dump_int(eqtb_size); - dump_int(hash_prime); - /*tex Dump the string pool. */ - k = dump_string_pool(); - print_ln(); - print_int(k); - tprint(" strings using "); - print_int((longinteger) pool_size); - tprint(" bytes"); - /*tex - Dump the dynamic memory. By sorting the list of available spaces in the - variable-size portion of |mem|, we are usually able to get by without - having to dump very much of the dynamic memory. - - We recompute |var_used| and |dyn_used|, so that \.{INITEX} dumps valid - information even when it has not been gathering statistics. - */ - dump_node_mem(); - dump_int(temp_token_head); - dump_int(hold_token_head); - dump_int(omit_template); - dump_int(null_list); - dump_int(backup_head); - dump_int(garbage); - x = (int) fix_mem_min; - dump_int(x); - x = (int) fix_mem_max; - dump_int(x); - x = (int) fix_mem_end; - dump_int(x); - dump_int(avail); - dyn_used = (int) fix_mem_end + 1; - dump_things(fixmem[fix_mem_min], fix_mem_end - fix_mem_min + 1); - x = x + (int) (fix_mem_end + 1 - fix_mem_min); - p = avail; - while (p != null) { - decr(dyn_used); - p = token_link(p); - } - dump_int(dyn_used); - print_ln(); - print_int(x); - tprint(" memory locations dumped; current usage is "); - print_int(var_used); - print_char('&'); - print_int(dyn_used); - /*tex - Dump regions 1 to 4 of |eqtb|, the table of equivalents. The table of - equivalents usually contains repeated information, so we dump it in - compressed form: The sequence of $n+2$ values $(n,x_1,\ldots,x_n,m)$ in - the format file represents $n+m$ consecutive entries of |eqtb|, with |m| - extra copies of $x_n$, namely $(x_1,\ldots,x_n,x_n,\ldots,x_n)$. - */ - k = null_cs; - do { - j = k; - while (j < int_base - 1) { - if ((equiv(j) == equiv(j + 1)) && (eq_type(j) == eq_type(j + 1)) && - (eq_level(j) == eq_level(j + 1))) - goto FOUND1; - incr(j); - } - l = int_base; - /*tex |j=int_base-1| */ - goto DONE1; - FOUND1: - incr(j); - l = j; - while (j < int_base - 1) { - if ((equiv(j) != equiv(j + 1)) || (eq_type(j) != eq_type(j + 1)) || - (eq_level(j) != eq_level(j + 1))) - goto DONE1; - incr(j); - } - DONE1: - dump_int(l - k); - dump_things(eqtb[k], l - k); - k = j + 1; - dump_int(k - l); - } while (k != int_base); - /*tex Dump regions 5 and 6 of |eqtb|. */ - do { - j = k; - while (j < eqtb_size) { - if (eqtb[j].cint == eqtb[j + 1].cint) - goto FOUND2; - incr(j); - } - l = eqtb_size + 1; - /*tex |j=eqtb_size| */ - goto DONE2; - FOUND2: - incr(j); - l = j; - while (j < eqtb_size) { - if (eqtb[j].cint != eqtb[j + 1].cint) - goto DONE2; - incr(j); - } - DONE2: - dump_int(l - k); - dump_things(eqtb[k], l - k); - k = j + 1; - dump_int(k - l); - } while (k <= eqtb_size); - if (hash_high > 0) { - /*tex Dump the |hash_extra| part: */ - dump_things(eqtb[eqtb_size + 1], hash_high); - } - dump_int(par_loc); - dump_int(write_loc); - dump_math_codes(); - dump_text_codes(); - /*tex - Dump the hash table, A different scheme is used to compress the hash - table, since its lower region is usually sparse. When |text(p)<>0| for - |p<=hash_used|, we output two words, |p| and |hash[p]|. The hash table - is, of course, densely packed for |p>=hash_used|, so the remaining - entries are output in a~block. - */ - dump_primitives(); - dump_int(hash_used); - cs_count = frozen_control_sequence - 1 - hash_used + hash_high; - for (p = hash_base; p <= hash_used; p++) { - if (cs_text(p) != 0) { - dump_int(p); - dump_hh(hash[p]); - incr(cs_count); - } - } - dump_things(hash[hash_used + 1],undefined_control_sequence - 1 - hash_used); - if (hash_high > 0) { - dump_things(hash[eqtb_size + 1], hash_high); - } - dump_int(cs_count); - print_ln(); - print_int(cs_count); - tprint(" multiletter control sequences"); - /*tex Dump the font information. */ - dump_int(max_font_id()); - for (k = 0; k <= max_font_id(); k++) { - /*tex Dump the array info for internal font number |k|. */ - dump_font(k); - tprint_nl("\\font"); - print_esc(font_id_text(k)); - print_char('='); - tprint_file_name((unsigned char *) font_name(k), - (unsigned char *) font_area(k), NULL); - if (font_size(k) != font_dsize(k)) { - tprint(" at "); - print_scaled(font_size(k)); - tprint("pt"); - } - } - print_ln(); - print_int(max_font_id()); - tprint(" preloaded font"); - if (max_font_id() != 1) - print_char('s'); - dump_math_data(); - /*tex Dump the hyphenation tables. */ - dump_language_data(); - /*tex Dump a couple more things and the closing check word. */ - dump_int(interaction); - dump_int(format_ident); - dump_int(format_name); - dump_int(69069); - /*tex - We have already printed a lot of statistics, so we set |tracing_stats:=0| - to prevent them from appearing again. - */ - tracing_stats_par = 0; - /*tex Dump the \LUA\ bytecodes. */ - dump_luac_registers(); - /*tex Close the format file. */ - zwclose(fmt_file); -} - -/*tex - -Corresponding to the procedure that dumps a format file, we have a function that -reads one in. The function returns |false| if the dumped format is incompatible -with the present \TeX\ table sizes, etc. - -*/ - -#define too_small(A) do { \ - wake_up_terminal(); \ - wterm_cr(); \ - fprintf(term_out,"---! Must increase the %s",(A)); \ - goto BAD_FMT; \ -} while (0) - -/*tex - - The inverse macros are slightly more complicated, since we need to check the - range of the values we are reading in. We say `|undump(a)(b)(x)|' to read an - integer value |x| that is supposed to be in the range |a<=x<=b|. - -*/ - -#define undump(A,B,C) do { \ - undump_int(x); \ - if (x<(A) || x>(B)) \ - goto BAD_FMT; \ - else \ - (C) = x; \ -} while (0) - -#define format_debug(A,B) do { \ - if (debug_format_file) { \ - fprintf (stderr, "fmtdebug: %s=%d", (A), (int)(B)); \ - } \ -} while (0) - -#define undump_size(A,B,C,D) do { \ - undump_int(x); \ - if (x<(A)) \ - goto BAD_FMT; \ - if (x>(B)) \ - too_small(C); \ - else \ - format_debug (C,x); \ - (D) = x; \ -} while (0) - -boolean load_fmt_file(const char *fmtname) -{ - int j, k, x; - halfword p; - char *format_engine; - /*tex Undump constants for consistency check .*/ - if (ini_version) { - libcfree(hash); - libcfree(eqtb); - libcfree(fixmem); - libcfree(varmem); - } - undump_int(x); - format_debug("format magic number", x); - if (x != 0x57325458) { - /*tex it's not a format file. */ - goto BAD_FMT; - } - undump_int(x); - format_debug("format id", x); - if (x != FORMAT_ID) { - /*tex We have a |FORMAT_ID| mismatch. */ - goto BAD_FMT; - } - undump_int(x); - format_debug("engine name size", x); - if ((x < 0) || (x > 256)) { - /*tex The format file is corrupt. */ - goto BAD_FMT; - } - format_engine = xmalloc((unsigned) x); - undump_things(format_engine[0], x); - format_engine[x - 1] = 0; - if (strcmp(engine_name, format_engine)) { - wake_up_terminal(); - wterm_cr(); - fprintf(term_out, "---! %s was written by %s", fmtname, format_engine); - xfree(format_engine); - goto BAD_FMT; - } - xfree(format_engine); - undump_int(x); - format_debug("string pool checksum", x); - if (x != 0x57325458) { - wake_up_terminal(); - wterm_cr(); - fprintf(term_out, "---! %s was written by a different version", - fmtname); - goto BAD_FMT; - } - undump_int(x); - if (x != max_halfword) - goto BAD_FMT; - undump_int(hash_high); - if ((hash_high < 0) || (hash_high > sup_hash_extra)) - goto BAD_FMT; - if (hash_extra < hash_high) - hash_extra = hash_high; - eqtb_top = eqtb_size + hash_extra; - if (hash_extra == 0) - hash_top = undefined_control_sequence; - else - hash_top = eqtb_top; - hash = xmallocarray(two_halves, (unsigned) (1 + hash_top)); - memset(hash, 0, sizeof(two_halves) * (unsigned) (hash_top + 1)); - eqtb = xmallocarray(memory_word, (unsigned) (eqtb_top + 1)); - set_eq_type(undefined_control_sequence, undefined_cs_cmd); - set_equiv(undefined_control_sequence, null); - set_eq_level(undefined_control_sequence, level_zero); - for (x = eqtb_size + 1; x <= eqtb_top; x++) - eqtb[x] = eqtb[undefined_control_sequence]; - undump_int(x); - if (x != eqtb_size) - goto BAD_FMT; - undump_int(x); - if (x != hash_prime) - goto BAD_FMT; - /*tex Undump the string pool */ - str_ptr = undump_string_pool(); - /*tex Undump the dynamic memory */ - undump_node_mem(); - undump_int(temp_token_head); - undump_int(hold_token_head); - undump_int(omit_template); - undump_int(null_list); - undump_int(backup_head); - undump_int(garbage); - undump_int(fix_mem_min); - undump_int(fix_mem_max); - fixmem = xmallocarray(smemory_word, fix_mem_max + 1); - memset(voidcast(fixmem), 0, (fix_mem_max + 1) * sizeof(smemory_word)); - undump_int(fix_mem_end); - undump_int(avail); - undump_things(fixmem[fix_mem_min], fix_mem_end - fix_mem_min + 1); - undump_int(dyn_used); - /*tex Undump regions 1 to 6 of the table of equivalents |eqtb|. */ - k = null_cs; - do { - undump_int(x); - if ((x < 1) || (k + x > eqtb_size + 1)) - goto BAD_FMT; - undump_things(eqtb[k], x); - k = k + x; - undump_int(x); - if ((x < 0) || (k + x > eqtb_size + 1)) - goto BAD_FMT; - for (j = k; j <= k + x - 1; j++) - eqtb[j] = eqtb[k - 1]; - k = k + x; - } while (k <= eqtb_size); - if (hash_high > 0) { - /*tex undump |hash_extra| part */ - undump_things(eqtb[eqtb_size + 1], hash_high); - } - undump(hash_base, hash_top, par_loc); - par_token = cs_token_flag + par_loc; - undump(hash_base, hash_top, write_loc); - undump_math_codes(); - undump_text_codes(); - /*tex Undump the hash table */ - undump_primitives(); - undump(hash_base, frozen_control_sequence, hash_used); - p = hash_base - 1; - do { - undump(p + 1, hash_used, p); - undump_hh(hash[p]); - } while (p != hash_used); - undump_things(hash[hash_used + 1], undefined_control_sequence - 1 - hash_used); - if (debug_format_file) - print_csnames(hash_base, undefined_control_sequence - 1); - if (hash_high > 0) { - undump_things(hash[eqtb_size + 1], hash_high); - if (debug_format_file) - print_csnames(eqtb_size + 1, hash_high - (eqtb_size + 1)); - } - undump_int(cs_count); - /*tex Undump the font information */ - undump_int(x); - set_max_font_id(x); - for (k = 0; k <= max_font_id(); k++) { - /*tex Undump the array info for internal font number |k| */ - undump_font(k); - } - undump_math_data(); - /*tex Undump the hyphenation tables */ - undump_language_data(); - /*tex Undump a couple more things and the closing check word */ - undump(batch_mode, error_stop_mode, interaction); - if (interactionoption != unspecified_mode) - interaction = interactionoption; - undump(0, str_ptr, format_ident); - undump(0, str_ptr, format_name); - undump_int(x); - if (x != 69069) - goto BAD_FMT; - /*tex Undump the lua bytecodes. */ - undump_luac_registers(); - prev_depth_par = ignore_depth; - return true; - BAD_FMT: - wake_up_terminal(); - wterm_cr(); - fprintf(term_out, "(Fatal format file error; I'm stymied)"); - return false; -} diff --git a/Build/source/texk/web2c/luatexdir/tex/dumpdata.h b/Build/source/texk/web2c/luatexdir/tex/dumpdata.h deleted file mode 100644 index 933dcfa1f0d..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/dumpdata.h +++ /dev/null @@ -1,114 +0,0 @@ -/* dumpdata.h - - Copyright 2009, 2012 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ - - -#ifndef DUMPDATA_H -# define DUMPDATA_H - -extern str_number format_ident; -extern str_number format_name; /* principal file name */ -extern FILE *fmt_file; /* for input or output of format information */ - -extern void store_fmt_file(void); -extern boolean load_fmt_file(const char *); - -/* (Un)dumping. These are called from the change file. */ -# define dump_things(base, len) \ - do_zdump ((char *) &(base), sizeof (base), (int) (len), DUMP_FILE) -# define undump_things(base, len) \ - do_zundump ((char *) &(base), sizeof (base), (int) (len), DUMP_FILE) - -extern void do_zdump(char *, int, int, FILE *); -extern void do_zundump(char *, int, int, FILE *); - -/* Like do_undump, but check each value against LOW and HIGH. The - slowdown isn't significant, and this improves the chances of - detecting incompatible format files. In fact, Knuth himself noted - this problem with Web2c some years ago, so it seems worth fixing. We - can't make this a subroutine because then we lose the type of BASE. */ -# define undump_checked_things(low, high, base, len) \ - do { \ - unsigned i; \ - undump_things (base, len); \ - for (i = 0; i < (len); i++) { \ - if ((&(base))[i] < (low) || (&(base))[i] > (high)) { \ - FATAL5 ("Item %u (=%ld) of .fmt array at %lx <%ld or >%ld", \ - i, (unsigned long) (&(base))[i], (unsigned long) &(base), \ - (unsigned long) low, (unsigned long) high); \ - } \ - } \ - } while (0) - -/* Like undump_checked_things, but only check the upper value. We use - this when the base type is unsigned, and thus all the values will be - greater than zero by definition. */ -# define undump_upper_check_things(high, base, len) \ - do { \ - unsigned i; \ - undump_things (base, len); \ - for (i = 0; i < (len); i++) { \ - if ((&(base))[i] > (high)) { \ - FATAL4 ("Item %u (=%ld) of .fmt array at %lx >%ld", \ - i, (unsigned long) (&(base))[i], (unsigned long) &(base), \ - (unsigned long) high); \ - } \ - } \ - } while (0) - -/* Use the above for all the other dumping and undumping. */ -# define generic_dump(x) dump_things (x, 1) -# define generic_undump(x) undump_things (x, 1) - -# define dump_wd generic_dump -# define dump_hh generic_dump -# define dump_qqqq generic_dump -# define undump_wd generic_undump -# define undump_hh generic_undump -# define undump_qqqq generic_undump - -/* `dump_int' is called with constant integers, so we put them into a - variable first. */ -# define dump_int(x) \ - do \ - { \ - int x_val = (x); \ - generic_dump (x_val); \ - } \ - while (0) - -/* web2c/regfix puts variables in the format file loading into - registers. Some compilers aren't willing to take addresses of such - variables. So we must kludge. */ -# if defined(REGFIX) || defined(WIN32) -# define undump_int(x) \ - do \ - { \ - int x_val; \ - generic_undump (x_val); \ - x = x_val; \ - } \ - while (0) -# else -# define undump_int generic_undump -# endif /* not (REGFIX || WIN32) */ - - - - -#endif diff --git a/Build/source/texk/web2c/luatexdir/tex/equivalents.c b/Build/source/texk/web2c/luatexdir/tex/equivalents.c deleted file mode 100644 index 3d260d5c5ee..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/equivalents.c +++ /dev/null @@ -1,1220 +0,0 @@ -/* - -equivalents.w - -Copyright 2009-2010 Taco Hoekwater <taco@@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your -option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU General Public License along -with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" - -halfword last_cs_name = null_cs; - -/*tex |eqtb[p]| has just been restored or retained. */ - -static void diagnostic_trace(halfword p, const char *s) -{ - begin_diagnostic(); - print_char('{'); - tprint(s); - print_char(' '); - show_eqtb(p); - print_char('}'); - end_diagnostic(false); -} - -void show_eqtb_meaning(halfword n); - -/*tex - -Now that we have studied the data structures for \TeX's semantic routines, we -ought to consider the data structures used by its syntactic routines. In other -words, our next concern will be the tables that \TeX\ looks at when it is -scanning what the user has written. - -The biggest and most important such table is called |eqtb|. It holds the current -``equivalents'' of things; i.e., it explains what things mean or what their -current values are, for all quantities that are subject to the nesting structure -provided by \TeX's grouping mechanism. There are six parts to |eqtb|: - -1) |eqtb[null_cs]| holds the current equivalent of the zero-length control -sequence. - -2) |eqtb[hash_base..(glue_base-1)]| holds the current equivalents of single- and -multiletter control sequences. - -3) |eqtb[glue_base..(local_base-1)]| holds the current equivalents of glue -parameters like the current baselineskip. - -4) |eqtb[local_base..(int_base-1)]| holds the current equivalents of local -halfword quantities like the current box registers, the current ``catcodes,'' the -current font, and a pointer to the current paragraph shape. - -5) |eqtb[int_base..(dimen_base-1)]| holds the current equivalents of fullword -integer parameters like the current hyphenation penalty. - -6) |eqtb[dimen_base..eqtb_size]| holds the current equivalents of fullword -dimension parameters like the current hsize or amount of hanging indentation. - -Note that, for example, the current amount of baselineskip glue is determined by -the setting of a particular location in region~3 of |eqtb|, while the current -meaning of the control sequence `\.{\\baselineskip}' (which might have been -changed by \.{\\def} or \.{\\let}) appears in region~2. - -The last two regions of |eqtb| have fullword values instead of the three fields -|eq_level|, |eq_type|, and |equiv|. An |eq_type| is unnecessary, but \TeX\ needs -to store the |eq_level| information in another array called |xeq_level|. - -*/ - -memory_word *eqtb; -halfword eqtb_top; -quarterword xeq_level[(eqtb_size + 1)]; - -void initialize_equivalents(void) -{ - int k; - for (k = int_base; k <= eqtb_size; k++) - xeq_level[k] = level_one; -} - -/*tex - -The nested structure provided by `$\.{\char'173}\ldots\.{\char'175}$' groups in -\TeX\ means that |eqtb| entries valid in outer groups should be saved and -restored later if they are overridden inside the braces. When a new |eqtb| value -is being assigned, the program therefore checks to see if the previous entry -belongs to an outer level. In such a case, the old value is placed on the -|save_stack| just before the new value enters |eqtb|. At the end of a grouping -level, i.e., when the right brace is sensed, the |save_stack| is used to restore -the outer values, and the inner ones are destroyed. - -Entries on the |save_stack| are of type |save_record|. The top item on this stack -is |save_stack[p]|, where |p=save_ptr-1|; it contains three fields called -|save_type|, |save_level|, and |save_value|, and it is interpreted in one of four -ways: - -1) If |save_type(p)=restore_old_value|, then |save_value(p)| is a location in -|eqtb| whose current value should be destroyed at the end of the current group -and replaced by |save_word(p-1)| (|save_type(p-1)==saved_eqtb|). Furthermore if -|save_value(p)>=int_base|, then |save_level(p)| should replace the corresponding -entry in |xeq_level| (if |save_value(p)<int_base|, then the level is part of -|save_word(p-1)|). - -2) If |save_type(p)=restore_zero|, then |save_value(p)| is a location in |eqtb| -whose current value should be destroyed at the end of the current group, when it -should be replaced by the current value of |eqtb[undefined_control_sequence]|. - -3) If |save_type(p)=insert_token|, then |save_value(p)| is a token that should be -inserted into \TeX's input when the current group ends. - -4) If |save_type(p)=level_boundary|, then |save_level(p)| is a code explaining -what kind of group we were previously in, and |save_value(p)| points to the level -boundary word at the bottom of the entries for that group. Furthermore, -|save_value(p-1)| contains the source line number at which the current level of -grouping was entered, this field has itself a type: |save_type(p-1)==saved_line|. - -Besides this `official' use, various subroutines push temporary variables on the -save stack when it is handy to do so. These all have an explicit |save_type|, and -they are: - -|saved_adjust| signifies an adjustment is beging scanned, -|saved_insert| an insertion is being scanned, -|saved_disc| the \.{\\discretionary} sublist we are working on right now, -|saved_boxtype| whether a \.{\\localbox} is \.{\\left} or \.{\\right}, -|saved_textdir| a text direction to be restored, -|saved_eqno| diffentiates between \.{\\eqno} and \.{\\leqno}, -|saved_choices| the \.{\\mathchoices} sublist we are working on right now, -|saved_math| and interrupted math list, -|saved_boxcontext| the box context value, -|saved_boxspec| the box \.{to} or \.{spread} specification, -|saved_boxdir| the box \.{dir} specification, -|saved_boxattr| the box \.{attr} specification, -|saved_boxpack| the box \.{pack} specification. - -The global variable |cur_group| keeps track of what sort of group we are -currently in. Another global variable, |cur_boundary|, points to the topmost -|level_boundary| word. And |cur_level| is the current depth of nesting. The -routines are designed to preserve the condition that no entry in the |save_stack| -or in |eqtb| ever has a level greater than |cur_level|. - -*/ - -save_record *save_stack; -int save_ptr; /* first unused entry on the save stack */ -int max_save_stack; /* maximum usage of save stack */ -quarterword cur_level = level_one; /* current nesting level for groups */ -group_code cur_group = bottom_level; /* current group type */ -int cur_boundary; /* where the current level begins */ - -/*tex - -At this time it might be a good idea for the reader to review the introduction to -|eqtb| that was given above just before the long lists of parameter names. Recall -that the ``outer level'' of the program is |level_one|, since undefined control -sequences are assumed to be ``defined'' at |level_zero|. - -The following macro is used to test if there is room for up to eight more entries -on |save_stack|. By making a conservative test like this, we can get by with -testing for overflow in only a few places. - -*/ - -#define check_full_save_stack() do { \ - if (save_ptr>max_save_stack) { \ - max_save_stack=save_ptr; \ - if (max_save_stack>save_size-8) \ - overflow("save size",(unsigned)save_size); \ - } \ -} while (0) - -/*tex - -Procedure |new_save_level| is called when a group begins. The argument is a group -identification code like `|hbox_group|'. After calling this routine, it is safe -to put six more entries on |save_stack|. - -In some cases integer-valued items are placed onto the |save_stack| just below a -|level_boundary| word, because this is a convenient place to keep information -that is supposed to ``pop up'' just when the group has finished. For example, -when `\.{\\hbox to 100pt}' is being treated, the 100pt dimension is stored on -|save_stack| just before |new_save_level| is called. - -*/ - -void new_save_level(group_code c) -{ /*tex We begin a new level of grouping. */ - check_full_save_stack(); - set_saved_record(0, saved_line, 0, line); - incr(save_ptr); - save_type(save_ptr) = level_boundary; - save_level(save_ptr) = cur_group; - save_value(save_ptr) = cur_boundary; - if (cur_level == max_quarterword) { - overflow("grouping levels", max_quarterword - min_quarterword); - } - /*tex We quit if |(cur_level+1)| is too big to be stored in |eqtb|. */ - cur_boundary = save_ptr; - cur_group = c; - if (tracing_groups_par > 0) - group_trace(false); - incr(cur_level); - incr(save_ptr); -} - -static const char *save_stack_type(int v) -{ - const char *s = ""; - switch (save_type(v)) { - case restore_old_value: s = "restore_old_value"; break; - case restore_zero: s = "restore_zero"; break; - case insert_token: s = "insert_token"; break; - case level_boundary: s = "level_boundary"; break; - case saved_line: s = "saved_line"; break; - case saved_adjust: s = "saved_adjust"; break; - case saved_insert: s = "saved_insert"; break; - case saved_disc: s = "saved_disc"; break; - case saved_boxtype: s = "saved_boxtype"; break; - case saved_textdir: s = "saved_textdir"; break; - case saved_eqno: s = "saved_eqno"; break; - case saved_choices: s = "saved_choices"; break; - case saved_math: s = "saved_math"; break; - case saved_boxcontext: s = "saved_boxcontext"; break; - case saved_boxspec: s = "saved_boxspec"; break; - case saved_boxdir: s = "saved_boxdir"; break; - case saved_boxattr: s = "saved_boxattr"; break; - case saved_boxpack: s = "saved_boxpack"; break; - case saved_attrlist: s = "saved_attrlist"; break; - case saved_eqtb: s = "saved_eqtb"; break; - default: break; - } - return s; -} - -void print_save_stack(void) -{ - int i; - begin_diagnostic(); - selector = term_and_log; - print_ln(); - for (i = (save_ptr - 1); i >= 0; i--) { - tprint("save_stack["); - if (i < 100) - print_char(' '); - if (i < 10) - print_char(' '); - print_int(i); - tprint("]: "); - tprint(save_stack_type(i)); - switch (save_type(i)) { - case restore_old_value: - tprint(", "); - show_eqtb_meaning(save_value(i)); - tprint("="); - if (save_value(i) >= int_base) { - print_int(save_word(i - 1).cint); - } else { - print_int(eq_type_field(save_word(i - 1))); - print_char(','); - print_int(equiv_field(save_word(i - 1))); - } - i--; - break; - case restore_zero: - tprint(", "); - show_eqtb_meaning(save_value(i)); - break; - case insert_token: - tprint(", "); - { - halfword p = get_avail(); - set_token_info(p, save_value(i)); - show_token_list(p, null, 1); - free_avail(p); - } - break; - case level_boundary: - tprint(", old group="); - print_int(save_level(i)); - tprint(", boundary = "); - print_int(save_value(i)); - tprint(", line = "); - print_int(save_value(i - 1)); - i--; - break; - case saved_adjust: - tprint(", "); - /*tex vadjust vs vadjust pre */ - print_int(save_level(i)); - break; - case saved_insert: - tprint(", "); - /*tex insert number */ - print_int(save_value(i)); - break; - case saved_boxtype: - /*tex \.{\\localleftbox} vs \.{\\localrightbox} */ - tprint(", "); - print_int(save_value(i)); - break; - case saved_eqno: - /*tex \.{\\eqno} vs \.{\\leqno} */ - tprint(", "); - print_int(save_value(i)); - break; - case saved_disc: - case saved_choices: - tprint(", "); - print_int(save_value(i)); - break; - case saved_math: - tprint(", listptr="); - print_int(save_value(i)); - break; - case saved_boxcontext: - tprint(", "); - print_int(save_value(i)); - break; - case saved_boxspec: - tprint(", spec="); - print_int(save_level(i)); - tprint(", dimen="); - print_int(save_value(i)); - break; - case saved_textdir: - case saved_boxdir: - tprint(", "); - print_dir_text(save_value(i)); - break; - case saved_boxattr: - case saved_boxpack: - case saved_attrlist: - tprint(", "); - print_int(save_value(i)); - break; - case saved_line: - case saved_eqtb: - break; - default: - break; - } - print_ln(); - } - end_diagnostic(true); -} - -/*tex - -The \.{\\showgroups} command displays all currently active grouping levels. - -The modifications of \TeX\ required for the display produced by the -|show_save_groups| procedure were first discussed by Donald~E. Knuth in {\sl -TUGboat\/} {\bf 11}, 165--170 and 499--511, 1990. @^Knuth, Donald Ervin@> - -In order to understand a group type we also have to know its mode. Since -unrestricted horizontal modes are not associated with grouping, they are skipped -when traversing the semantic nest. - -*/ - -void show_save_groups(void) -{ - int p = nest_ptr; - int m; - save_pointer v = save_ptr; - quarterword l = cur_level; - group_code c = cur_group; - int a = 1; /* to keep track of alignments */ - int i; - quarterword j; - const char *s = NULL; - save_ptr = cur_boundary; - decr(cur_level); - tprint_nl(""); - print_ln(); - while (1) { - tprint_nl("### "); - print_group(true); - if (cur_group == bottom_level) - goto DONE; - do { - m = nest[p].mode_field; - if (p > 0) - decr(p); - else - m = vmode; - } while (m == hmode); - tprint(" ("); - switch (cur_group) { - case simple_group: - incr(p); - goto FOUND2; - break; - case hbox_group: - case adjusted_hbox_group: - s = "hbox"; - break; - case vbox_group: - s = "vbox"; - break; - case vtop_group: - s = "vtop"; - break; - case align_group: - if (a == 0) { - if (m == -vmode) - s = "halign"; - else - s = "valign"; - a = 1; - goto FOUND1; - } else { - if (a == 1) - tprint("align entry"); - else - tprint_esc("cr"); - if (p >= a) - p = p - a; - a = 0; - goto FOUND; - } - break; - case no_align_group: - incr(p); - a = -1; - tprint_esc("noalign"); - goto FOUND2; - break; - case output_group: - tprint_esc("output"); - goto FOUND; - break; - case math_group: - goto FOUND2; - break; - case disc_group: - tprint_esc("discretionary"); - for (i = 1; i < 3; i++) { - if (i <= saved_value(-2)) { - tprint("{}"); - } - } - goto FOUND2; - break; - case math_choice_group: - tprint_esc("mathchoice"); - for (i = 1; i < 4; i++) { - /*tex A different offset because |-2==saved_textdir|: */ - if (i <= saved_value(-3)) { - tprint("{}"); - } - } - goto FOUND2; - break; - case insert_group: - if (saved_type(-1) == saved_adjust) { - tprint_esc("vadjust"); - if (saved_level(-1) != 0) - tprint(" pre"); - } else { - tprint_esc("insert"); - print_int(saved_value(-1)); - } - goto FOUND2; - break; - case vcenter_group: - s = "vcenter"; - goto FOUND1; - break; - case semi_simple_group: - incr(p); - tprint_esc("begingroup"); - goto FOUND; - break; - case math_shift_group: - if (m == mmode) { - print_char('$'); - } else if (nest[p].mode_field == mmode) { - print_cmd_chr(eq_no_cmd, saved_value(-2)); - goto FOUND; - } - print_char('$'); - goto FOUND; - break; - case math_left_group: - if (subtype(nest[p + 1].eTeX_aux_field) == left_noad_side) - tprint_esc("left"); - else - tprint_esc("middle"); - goto FOUND; - break; - default: - confusion("showgroups"); - break; - } - /*tex Show the box context */ - i = saved_value(-5); - if (i != 0) { - if (i < box_flag) { - if (abs(nest[p].mode_field) == vmode) - j = hmove_cmd; - else - j = vmove_cmd; - if (i > 0) - print_cmd_chr(j, 0); - else - print_cmd_chr(j, 1); - print_scaled(abs(i)); - tprint("pt"); - } else if (i < ship_out_flag) { - if (i >= global_box_flag) { - tprint_esc("global"); - i = i - (global_box_flag - box_flag); - } - tprint_esc("setbox"); - print_int(i - box_flag); - print_char('='); - } else { - print_cmd_chr(leader_ship_cmd, i - (leader_flag - a_leaders)); - } - } - FOUND1: - tprint_esc(s); - /*tex Show the box packaging info. The offsets may vary. */ - { - int ii = -1; - while (saved_type(ii) != saved_boxspec) - ii--; - if (saved_value(ii) != 0) { - print_char(' '); - if (saved_level(ii) == exactly) - tprint("to"); - else - tprint("spread"); - print_scaled(saved_value(ii)); - tprint("pt"); - } - } - FOUND2: - print_char('{'); - FOUND: - print_char(')'); - decr(cur_level); - cur_group = save_level(save_ptr); - save_ptr = save_value(save_ptr); - } - DONE: - save_ptr = v; - cur_level = l; - cur_group = c; -} - -/*tex - -Just before an entry of |eqtb| is changed, the following procedure should be -called to update the other data structures properly. It is important to keep in -mind that reference counts in |mem| include references from within |save_stack|, -so these counts must be handled carefully. @^reference counts@> - -We don't need to destroy when an assignment has the same node: - -*/ - -void eq_destroy(memory_word w) -{ - halfword q; - switch (eq_type_field(w)) { - case call_cmd: - case long_call_cmd: - case outer_call_cmd: - case long_outer_call_cmd: - delete_token_ref(equiv_field(w)); - break; - case glue_ref_cmd: - flush_node(equiv_field(w)); - break; - case shape_ref_cmd: - q = equiv_field(w); - if (q != null) { - /*tex - We need to free a \.{\\parshape} block. Such a block is - |2n+1| words long, where |n=vinfo(q)|. It happens in the - flush function. - */ - flush_node(q); - } - break; - case box_ref_cmd: - flush_node_list(equiv_field(w)); - break; - default: - break; - } -} - -/*tex - -To save a value of |eqtb[p]| that was established at level |l|, we can use the -following subroutine. - -*/ -void eq_save(halfword p, quarterword l) -{ - check_full_save_stack(); - if (l == level_zero) { - save_type(save_ptr) = restore_zero; - } else { - save_word(save_ptr) = eqtb[p]; - save_type(save_ptr) = saved_eqtb; - incr(save_ptr); - save_type(save_ptr) = restore_old_value; - } - save_level(save_ptr) = l; - save_value(save_ptr) = p; - incr(save_ptr); -} - -/*tex - -The procedure |eq_define| defines an |eqtb| entry having specified |eq_type| and -|equiv| fields, and saves the former value if appropriate. This procedure is used -only for entries in the first four regions of |eqtb|, i.e., only for entries that -have |eq_type| and |equiv| fields. After calling this routine, it is safe to put -four more entries on |save_stack|, provided that there was room for four more -entries before the call, since |eq_save| makes the necessary test. - -*/ - -void eq_define(halfword p, quarterword t, halfword e) -{ - boolean trace = tracing_assigns_par > 0; - if ((eq_type(p) == t) && (equiv(p) == e)) { - if (trace) - diagnostic_trace(p, "reassigning"); - eq_destroy(eqtb[p]); - return; - } - if (trace) - diagnostic_trace(p, "changing"); - if (eq_level(p) == cur_level) - eq_destroy(eqtb[p]); - else if (cur_level > level_one) - eq_save(p, eq_level(p)); - set_eq_level(p, cur_level); - set_eq_type(p, t); - set_equiv(p, e); - if (trace) - diagnostic_trace(p, "into"); -} - -/*tex - -The counterpart of |eq_define| for the remaining (fullword) positions in |eqtb| -is called |eq_word_define|. Since |xeq_level[p]>=level_one| for all |p|, a -`|restore_zero|' will never be used in this case. - -*/ - -void eq_word_define(halfword p, int w) -{ - boolean trace = tracing_assigns_par > 0; - if (eqtb[p].cint == w) { - if (trace) - diagnostic_trace(p, "reassigning"); - return; - } - if (trace) - diagnostic_trace(p, "changing"); - if (xeq_level[p] != cur_level) { - eq_save(p, xeq_level[p]); - xeq_level[p] = cur_level; - } - eqtb[p].cint = w; - if (trace) - diagnostic_trace(p, "into"); -} - -/*tex - -The |eq_define| and |eq_word_define| routines take care of local definitions. -@^global definitions@> Global definitions are done in almost the same way, but -there is no need to save old values, and the new value is associated with -|level_one|. - -*/ - -void geq_define(halfword p, quarterword t, halfword e) -{ - boolean trace = tracing_assigns_par > 0; - if (trace) - diagnostic_trace(p, "globally changing"); - eq_destroy(eqtb[p]); - set_eq_level(p, level_one); - set_eq_type(p, t); - set_equiv(p, e); - if (trace) - diagnostic_trace(p, "into"); -} - -void geq_word_define(halfword p, int w) -{ - boolean trace = tracing_assigns_par > 0; - if (trace) - diagnostic_trace(p, "globally changing"); - eqtb[p].cint = w; - xeq_level[p] = level_one; - if (trace) - diagnostic_trace(p, "into"); -} - -/*tex - -Subroutine |save_for_after| puts a token on the stack for save-keeping. - -*/ - -void save_for_after(halfword t) -{ - if (cur_level > level_one) { - check_full_save_stack(); - save_type(save_ptr) = insert_token; - save_level(save_ptr) = level_zero; - save_value(save_ptr) = t; - incr(save_ptr); - } -} - -/*tex - -The |unsave| routine goes the other way, taking items off of |save_stack|. This -routine takes care of restoration when a level ends; everything belonging to the -topmost group is cleared off of the save stack. - -*/ - -void unsave(void) -{ - halfword p; - quarterword l = level_one; - /*tex Variable |a| registers if we already have processed an \.{\\aftergroup}. */ - boolean a = false; - unsave_math_codes(cur_level); - unsave_cat_codes(cat_code_table_par, cur_level); - unsave_text_codes(cur_level); - unsave_math_data(cur_level); - if (cur_level > level_one) { - boolean trace = tracing_restores_par > 0; - decr(cur_level); - /*tex Clear off top level from |save_stack|. */ - while (true) { - decr(save_ptr); - if (save_type(save_ptr) == level_boundary) - break; - p = save_value(save_ptr); - if (save_type(save_ptr) == insert_token) { - reinsert_token(a, p); - /*tex always |true| as we are always in \ETEX\ now. */ - a = true; - } else { - if (save_type(save_ptr) == restore_old_value) { - l = save_level(save_ptr); - decr(save_ptr); - } else { - save_word(save_ptr) = eqtb[undefined_control_sequence]; - } - /*tex - Store |save_stack[save_ptr]| in |eqtb[p]|, unless |eqtb[p]| - holds a global value A global definition, which sets the - level to |level_one|, will not be undone by |unsave|. If at - least one global definition of |eqtb[p]| has been carried out - within the group that just ended, the last such definition - will therefore survive. - */ - if (p < int_base || p > eqtb_size) { - if (eq_level(p) == level_one) { - /*tex Destroy the saved value: */ - eq_destroy(save_word(save_ptr)); - if (trace) - diagnostic_trace(p, "retaining"); - } else { - /*tex Destroy the current value: */ - eq_destroy(eqtb[p]); - /*tex Restore the saved value: */ - eqtb[p] = save_word(save_ptr); - if (trace) - diagnostic_trace(p, "restoring"); - } - } else if (xeq_level[p] != level_one) { - eqtb[p] = save_word(save_ptr); - xeq_level[p] = l; - if (trace) - diagnostic_trace(p, "restoring"); - } else { - if (trace) - diagnostic_trace(p, "retaining"); - } - } - } - - if (tracing_groups_par > 0) { - group_trace(true); - } - if (grp_stack[in_open] == cur_boundary) { - /*tex Groups are possibly not properly nested with files. */ - group_warning(); - } - cur_group = save_level(save_ptr); - cur_boundary = save_value(save_ptr); - decr(save_ptr); - } else { - /*tex |unsave| is not used when |cur_group=bottom_level| */ - confusion("curlevel"); - } - attr_list_cache = cache_disabled; -} - -/*tex - -Most of the parameters kept in |eqtb| can be changed freely, but there's an -exception: The magnification should not be used with two different values during -any \TeX\ job, since a single magnification is applied to an entire run. The -global variable |mag_set| is set to the current magnification whenever it becomes -necessary to ``freeze'' it at a particular value. - -The |prepare_mag| subroutine is called whenever \TeX\ wants to use |mag| for -magnification. If nonzero, this magnification should be used henceforth. We might -drop magnifaction at some point. - -*/ - -int mag_set = 0; - -void prepare_mag(void) -{ - if ((mag_set > 0) && (mag_par != mag_set)) { - print_err("Incompatible magnification ("); - print_int(mag_par); - tprint(");"); - tprint_nl(" the previous value will be retained"); - help2( - "I can handle only one magnification ratio per job. So I've", - "reverted to the magnification you used earlier on this run." - ); - int_error(mag_set); - geq_word_define(int_base + mag_code, mag_set); /* |mag:=mag_set| */ - } - if ((mag_par <= 0) || (mag_par > 32768)) { - print_err("Illegal magnification has been changed to 1000"); - help1( - "The magnification ratio must be between 1 and 32768." - ); - int_error(mag_par); - geq_word_define(int_base + mag_code, 1000); - } - if ((mag_set == 0) && (mag_par != mag_set)) { - if (mag_par != 1000) - one_true_inch = xn_over_d(one_hundred_inch, 10, mag_par); - else - one_true_inch = one_inch; - } - mag_set = mag_par; -} - -/*tex - -Let's pause a moment now and try to look at the Big Picture. The \TeX\ program -consists of three main parts: syntactic routines, semantic routines, and output -routines. The chief purpose of the syntactic routines is to deliver the user's -input to the semantic routines, one token at a time. The semantic routines act as -an interpreter responding to these tokens, which may be regarded as commands. And -the output routines are periodically called on to convert box-and-glue lists into -a compact set of instructions that will be sent to a typesetter. We have -discussed the basic data structures and utility routines of \TeX, so we are good -and ready to plunge into the real activity by considering the syntactic routines. - -Our current goal is to come to grips with the |get_next| procedure, which is the -keystone of \TeX's input mechanism. Each call of |get_next| sets the value of -three variables |cur_cmd|, |cur_chr|, and |cur_cs|, representing the next input -token. - -$$ - \vbox{\halign{#\hfil\cr - \hbox{|cur_cmd| denotes a command code from the long list of codes given above;}\cr - \hbox{|cur_chr| denotes a character code or other modifier of the command code;}\cr - \hbox{|cur_cs| is the |eqtb| location of the current control sequence,}\cr - \hbox{\qquad if the current token was a control sequence, otherwise it's zero.}\cr}} -$$ - -Underlying this external behavior of |get_next| is all the machinery necessary to -convert from character files to tokens. At a given time we may be only partially -finished with the reading of several files (for which \.{\\input} was specified), -and partially finished with the expansion of some user-defined macros and/or some -macro parameters, and partially finished with the generation of some text in a -template for \.{\\halign}, and so on. When reading a character file, special -characters must be classified as math delimiters, etc.; comments and extra blank -spaces must be removed, paragraphs must be recognized, and control sequences must -be found in the hash table. Furthermore there are occasions in which the scanning -routines have looked ahead for a word like `\.{plus}' but only part of that word -was found, hence a few characters must be put back into the input and scanned -again. - -To handle these situations, which might all be present simultaneously, \TeX\ uses -various stacks that hold information about the incomplete activities, and there -is a finite state control for each level of the input mechanism. These stacks -record the current state of an implicitly recursive process, but the |get_next| -procedure is not recursive. Therefore it will not be difficult to translate these -algorithms into low-level languages that do not support recursion. - -In general, |cur_cmd| is the current command as set by |get_next|, while -|cur_chr| is the operand of the current command. The control sequence found here -is registsred in |cur_cs| and is zero if none found. The |cur_tok| variable -contains the packed representative of |cur_cmd| and |cur_chr| and like the other -ones is global. - -*/ - -int cur_cmd; -halfword cur_chr; -halfword cur_cs; -halfword cur_tok; - -/*tex - -Here is a procedure that displays the current command. The variable |n| holds the -level of \.{\\if...\\fi} nesting and |l| the line where \.{\\if} started. - -*/ - -void show_cur_cmd_chr(void) -{ - int n, l; - halfword p; - begin_diagnostic(); - tprint_nl("{"); - if (mode_par != shown_mode) { - print_mode(mode_par); - tprint(": "); - shown_mode = mode_par; - } - print_cmd_chr((quarterword) cur_cmd, cur_chr); - if (tracing_ifs_par > 0) { - if (cur_cmd >= if_test_cmd) { - if (cur_cmd <= fi_or_else_cmd) { - tprint(": "); - if (cur_cmd == fi_or_else_cmd) { - print_cmd_chr(if_test_cmd, cur_if); - print_char(' '); - n = 0; - l = if_line; - } else { - n = 1; - l = line; - } - p = cond_ptr; - while (p != null) { - incr(n); - p = vlink(p); - } - tprint("(level "); - print_int(n); - print_char(')'); - print_if_line(l); - } - } - } - print_char('}'); - end_diagnostic(false); -} - -/*tex - -Here is a procedure that displays the contents of |eqtb[n]| symbolically. - -*/ - -void show_eqtb(halfword n) -{ - if (n < null_cs) { - /*tex - This can't happen in a pure \TEX\ run, but careless usage of tokens - at the \LUA\ end can make you end up here. - */ - tprint("? bad token, case 1: "); - print_int(n); - } else if ((n < glue_base) || ((n > eqtb_size) && (n <= eqtb_top))) { - /*tex - This routine show the current meaning of |eqtb| entry |n| in region 1 or 2. - Similar routines for the other regions will appear below. - */ - sprint_cs(n); - print_char('='); - print_cmd_chr(eq_type(n), equiv(n)); - if (eq_type(n) >= call_cmd) { - print_char(':'); - show_token_list(token_link(equiv(n)), null, 32); - } - } else if (n < local_base) { - /*tex - Here we show equivalent |n| in region 3. All glue parameters and registers - are initially `\.{0pt plus0pt minus0pt}'. - */ - if (n < skip_base) { - if (n < glue_base + thin_mu_skip_code) - print_cmd_chr(assign_glue_cmd, n); - else - print_cmd_chr(assign_mu_glue_cmd, n); - print_char('='); - if (n < glue_base + thin_mu_skip_code) - print_spec(equiv(n), "pt"); - else - print_spec(equiv(n), "mu"); - } else if (n < mu_skip_base) { - tprint_esc("skip"); - print_int(n - skip_base); - print_char('='); - print_spec(equiv(n), "pt"); - } else { - tprint_esc("muskip"); - print_int(n - mu_skip_base); - print_char('='); - print_spec(equiv(n), "mu"); - } - - } else if (n < int_base) { - /*tex - We're now at equivalent |n| in region 4. First we initialize most - things to null or undefined values. An undefined font is represented - by the internal code |font_base|. - - However, the character code tables are given initial values based on - the conventional interpretation of ASCII code. These initial values - should not be changed when \TeX\ is adapted for use with non-English - languages; all changes to the initialization conventions should be - made in format packages, not in \TeX\ itself, so that global - interchange of formats is possible. - */ - if ((n == par_shape_loc) || ((n >= etex_pen_base) && (n < etex_pens))) { - if (n == par_shape_loc) - print_cmd_chr(set_tex_shape_cmd, n); - else - print_cmd_chr(set_etex_shape_cmd, n); - print_char('='); - if (equiv(n) == null) { - print_char('0'); - } else if (n > par_shape_loc) { - print_int(penalty(equiv(n))); - print_char(' '); - print_int(penalty(equiv(n) + 1)); - if (penalty(equiv(n)) > 1) - tprint_esc("ETC."); - } else { - print_int(vinfo(par_shape_par_ptr + 1)); - } - } else if (n < toks_base) { - print_cmd_chr(assign_toks_cmd, n); - print_char('='); - if (equiv(n) != null) - show_token_list(token_link(equiv(n)), null, 32); - } else if (n < box_base) { - tprint_esc("toks"); - print_int(n - toks_base); - print_char('='); - if (equiv(n) != null) - show_token_list(token_link(equiv(n)), null, 32); - } else if (n < cur_font_loc) { - tprint_esc("box"); - print_int(n - box_base); - print_char('='); - if (equiv(n) == null) { - tprint("void"); - } else { - depth_threshold = 0; - breadth_max = 1; - show_node_list(equiv(n)); - } - } else if (n == cur_font_loc) { - /*tex - Let's show the font identifier in |eqtb[n]|, that's - |font_id_text(equiv(n))| - */ - tprint("current font"); - print_char('='); - print_esc(hash[font_id_base + equiv(n)].rh); - } - } else if (n < dimen_base) { - /*tex Show equivalent |n| in region 5: */ - if (n < dir_base) { - print_cmd_chr(assign_int_cmd, n); - print_char('='); - print_int(eqtb[n].cint); - } else if (n < count_base) { - print_cmd_chr(assign_dir_cmd, n); - print_char(' '); - print_dir_par(eqtb[n].cint); - } else if (n < attribute_base) { - tprint_esc("count"); - print_int(n - count_base); - print_char('='); - print_int(eqtb[n].cint); - } else if (n < del_code_base) { - tprint_esc("attribute"); - print_int(n - attribute_base); - print_char('='); - print_int(eqtb[n].cint); - } - } else if (n <= eqtb_size) { - /*tex Show equivalent |n| in region 6: */ - if (n < scaled_base) { - print_cmd_chr(assign_dimen_cmd, n); - } else { - tprint_esc("dimen"); - print_int(n - scaled_base); - } - print_char('='); - print_scaled(eqtb[n].cint); - tprint("pt"); - } else { - /*tex This can't happen unless you messed up at the \LUA\ end. */ - tprint("? bad token, case 2: "); - print_int(n); - } -} - -void show_eqtb_meaning(halfword n) -{ - if (n < null_cs) { - /*tex This can't happen. */ - print_char('?'); - } else if ((n < glue_base) || ((n > eqtb_size) && (n <= eqtb_top))) { - /*tex - Here is a routine that displays the current meaning of an |eqtb| - entry in region 1 or~2. Similar routines for the other regions will - appear below. - */ - sprint_cs(n); - } else if (n < local_base) { - /* - Show equivalent |n| in region 3. All glue parameters and registers - are initially `\.{0pt plus0pt minus0pt}'. - */ - if (n < skip_base) { - if (n < glue_base + thin_mu_skip_code) - print_cmd_chr(assign_glue_cmd, n); - else - print_cmd_chr(assign_mu_glue_cmd, n); - } else if (n < mu_skip_base) { - tprint_esc("skip"); - print_int(n - skip_base); - } else { - tprint_esc("muskip"); - print_int(n - mu_skip_base); - } - } else if (n < int_base) { - /*tex - Show equivalent |n| in region 4. We initialize most things to null or - undefined values. An undefined font is represented by the internal - code |font_base|. However, the character code tables are given - initial values based on the conventional interpretation of ASCII - code. These initial values should not be changed when \TeX\ is - adapted for use with non-English languages; all changes to the - initialization conventions should be made in format packages, not in - \TeX\ itself, so that global interchange of formats is possible. - */ - if ((n == par_shape_loc) || ((n >= etex_pen_base) && (n < etex_pens))) { - if (n == par_shape_loc) - print_cmd_chr(set_tex_shape_cmd, n); - else - print_cmd_chr(set_etex_shape_cmd, n); - } else if (n < toks_base) { - print_cmd_chr(assign_toks_cmd, n); - } else if (n < box_base) { - tprint_esc("toks"); - print_int(n - toks_base); - } else if (n < cur_font_loc) { - tprint_esc("box"); - print_int(n - box_base); - } else if (n == cur_font_loc) { - /*tex Show the font identifier in |eqtb[n]|. */ - tprint("current font"); - } - } else if (n < dimen_base) { - /*tex Show equivalent |n| in region 5. */ - if (n < dir_base) { - print_cmd_chr(assign_int_cmd, n); - } else if (n < count_base) { - print_cmd_chr(assign_dir_cmd, n); - } else if (n < attribute_base) { - tprint_esc("count"); - print_int(n - count_base); - } else if (n < del_code_base) { - tprint_esc("attribute"); - print_int(n - attribute_base); - } - } else if (n <= eqtb_size) { - /*tex Show equivalent |n| in region 6. */ - if (n < scaled_base) { - print_cmd_chr(assign_dimen_cmd, n); - } else { - tprint_esc("dimen"); - print_int(n - scaled_base); - } - } else { - /*tex This can't happen either. */ - print_char('?'); - } -} diff --git a/Build/source/texk/web2c/luatexdir/tex/equivalents.h b/Build/source/texk/web2c/luatexdir/tex/equivalents.h deleted file mode 100644 index 83117c64fa1..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/equivalents.h +++ /dev/null @@ -1,916 +0,0 @@ -/* equivalents.h - - Copyright 2009 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef EQUIVALENTS_H -# define EQUIVALENTS_H - -/* - -Like the preceding parameters, the following quantities can be changed at compile -time to extend or reduce \TeX's capacity. But if they are changed, it is -necessary to rerun the initialization program \.{INITEX} @.INITEX@> to generate -new tables for the production \TeX\ program. One can't simply make helter-skelter -changes to the following constants, since certain rather complex initialization -numbers are computed from them. They are defined here using \.{WEB} macros, -instead of being put into \PASCAL's |const| list, in order to emphasize this -distinction. - -*/ - -# define font_base 0 /* smallest internal font number; must not be less than |min_quarterword| */ -# define biggest_reg 65535 /* the largest allowed register number; must be |< max_quarterword| */ -# define number_regs 65536 /* |biggest_reg+1| */ -# define number_attrs 65536 /* total numbeer of attributes */ -# define biggest_char 1114111 /* 0x10FFFF, the largest allowed character number; must be |< max_halfword| */ -# define too_big_char (biggest_char+1) /* 1114112, |biggest_char+1| */ -# define special_char (biggest_char+2) /* 1114113, |biggest_char+2| */ -# define number_chars (biggest_char+3) /* 1114112, |biggest_char+1| */ -# define number_fonts (5535-font_base+1) -# define biggest_lang 32767 -# define too_big_lang 32768 -# define text_size 0 /* size code for the largest size in a family */ -# define script_size 1 /* size code for the medium size in a family */ -# define script_script_size 2 /* size code for the smallest size in a family */ - -/* - -Each entry in |eqtb| is a |memory_word|. Most of these words are of type -|two_halves|, and subdivided into three fields: - -\yskip\hangg 1) The |eq_level| (a quarterword) is the level of grouping at which -this equivalent was defined. If the level is |level_zero|, the equivalent has -never been defined; |level_one| refers to the outer level (outside of all -groups), and this level is also used for global definitions that never go away. -Higher levels are for equivalents that will disappear at the end of their group. -@^global definitions@> - -\yskip\hangg 2) The |eq_type| (another quarterword) specifies what kind of entry -this is. There are many types, since each \TeX\ primitive like \.{\\hbox}, -\.{\\def}, etc., has its own special code. The list of command codes above -includes all possible settings of the |eq_type| field. - -\yskip\hangg 3) The |equiv| (a halfword) is the current equivalent value. This -may be a font number, a pointer into |mem|, or a variety of other things. - -Many locations in |eqtb| have symbolic names. The purpose of the next paragraphs -is to define these names, and to set up the initial values of the equivalents. - -In the first region we have a single entry for the `null csname' of length zero. -In luatex, the active characters and and single-letter control sequence names are -part of the next region. - -Then comes region~2, which corresponds to the hash table that we will define -later. The maximum address in this region is used for a dummy control sequence -that is perpetually undefined. There also are several locations for control -sequences that are perpetually defined (since they are used in error recovery). - -@ Region 3 of |eqtb| contains the |number_regs| \.{\\skip} registers, as well as -the glue parameters defined here. It is important that the ``muskip'' parameters -have larger numbers than the others. - -@ Region 4 of |eqtb| contains the local quantities defined here. The bulk of this -region is taken up by five tables that are indexed by eight-bit characters; these -tables are important to both the syntactic and semantic portions of \TeX. There -are also a bunch of special things like font and token parameters, as well as the -tables of \.{\\toks} and \.{\\box} registers. - -@ Region 5 of |eqtb| contains the integer parameters and registers defined here, -as well as the |del_code| table. The latter table differs from the -|cat_code..math_code| tables that precede it, since delimiter codes are fullword -integers while the other kinds of codes occupy at most a halfword. This is what -makes region~5 different from region~4. We will store the |eq_level| information -in an auxiliary array of quarterwords that will be defined later. - -@ The integer parameters should really be initialized by a macro package; the -following initialization does the minimum to keep \TeX\ from complete failure. - -@^null delimiter@> - -@ The final region of |eqtb| contains the dimension parameters defined here, and -the |number_regs| \.{\\dimen} registers. - -*/ - -# define null_cs 1 /* equivalent of \.{\\csname\\endcsname} */ -# define hash_base (null_cs+1) /* beginning of region 2, for the hash table */ -# define frozen_control_sequence (hash_base+hash_size) /* for error recovery */ -# define frozen_protection (frozen_control_sequence) /* inaccessible but definable */ -# define frozen_cr (frozen_control_sequence+1) /* permanent `\.{\\cr}' */ -# define frozen_end_group (frozen_control_sequence+2) /* permanent `\.{\\endgroup}' */ -# define frozen_right (frozen_control_sequence+3) /* permanent `\.{\\right}' */ -# define frozen_fi (frozen_control_sequence+4) /* permanent `\.{\\fi}' */ -# define frozen_end_template (frozen_control_sequence+5) /* permanent `\.{\\endtemplate}' */ -# define frozen_endv (frozen_control_sequence+6) /* second permanent `\.{\\endtemplate}' */ -# define frozen_relax (frozen_control_sequence+7) /* permanent `\.{\\relax}' */ -# define end_write (frozen_control_sequence+8) /* permanent `\.{\\endwrite}' */ -# define frozen_dont_expand (frozen_control_sequence+9 ) /* permanent `\.{\\notexpanded:}' */ -# define frozen_primitive (frozen_control_sequence+11 ) /* permanent `\.{\\primitive}' */ -# define frozen_special (frozen_control_sequence+12 ) /* permanent `\.{\\special}' */ -# define frozen_null_font (frozen_control_sequence+13 ) /* permanent `\.{\\nullfont}' */ -# define font_id_base (frozen_null_font-font_base ) /* begins table of |number_fonts| permanent font identifiers */ -# define undefined_control_sequence (frozen_null_font+number_fonts) -# define glue_base (undefined_control_sequence+1) /* beginning of region 3 */ - -# define line_skip_code 0 /* interline glue if |baseline_skip| is infeasible */ -# define baseline_skip_code 1 /* desired glue between baselines */ -# define par_skip_code 2 /* extra glue just above a paragraph */ -# define above_display_skip_code 3 /* extra glue just above displayed math */ -# define below_display_skip_code 4 /* extra glue just below displayed math */ -# define above_display_short_skip_code 5 /* glue above displayed math following short lines */ -# define below_display_short_skip_code 6 /* glue below displayed math following short lines */ -# define left_skip_code 7 /* glue at left of justified lines */ -# define right_skip_code 8 /* glue at right of justified lines */ -# define top_skip_code 9 /* glue at top of main pages */ -# define split_top_skip_code 10 /* glue at top of split pages */ -# define tab_skip_code 11 /* glue between aligned entries */ -# define space_skip_code 12 /* glue between words (if not |zero_glue|) */ -# define xspace_skip_code 13 /* glue after sentences (if not |zero_glue|) */ -# define par_fill_skip_code 14 /* glue on last line of paragraph */ -# define math_skip_code 15 -# define thin_mu_skip_code 16 /* thin space in math formula */ -# define med_mu_skip_code 17 /* medium space in math formula */ -# define thick_mu_skip_code 18 /* thick space in math formula */ -# define glue_pars 19 /* total number of glue parameters */ - -# define skip_base (glue_base+glue_pars) /* table of |number_regs| ``skip'' registers */ -# define mu_skip_base (skip_base+number_regs) /* table of |number_regs| ``muskip'' registers */ -# define local_base (mu_skip_base+number_regs) /* beginning of region 4 */ - -# define par_shape_loc (local_base) /* specifies paragraph shape */ -# define output_routine_loc (local_base+1) /* points to token list for \.{\\output} */ -# define every_par_loc (local_base+2) /* points to token list for \.{\\everypar} */ -# define every_math_loc (local_base+3) /* points to token list for \.{\\everymath} */ -# define every_display_loc (local_base+4) /* points to token list for \.{\\everydisplay} */ -# define every_hbox_loc (local_base+5) /* points to token list for \.{\\everyhbox} */ -# define every_vbox_loc (local_base+6) /* points to token list for \.{\\everyvbox} */ -# define every_job_loc (local_base+7) /* points to token list for \.{\\everyjob} */ -# define every_cr_loc (local_base+8) /* points to token list for \.{\\everycr} */ -# define err_help_loc (local_base+9) /* points to token list for \.{\\errhelp} */ -# define every_eof_loc (local_base+10) /* points to token list for \.{\\everyeof} */ - -# define backend_toks_base (local_base+11) -# define backend_toks_last (local_base+20) - -# define toks_base (local_base+21) /* table of |number_regs| token list registers */ - -# define etex_pen_base (toks_base+number_regs) /* start of table of \eTeX's penalties */ -# define inter_line_penalties_loc (etex_pen_base) /* additional penalties between lines */ -# define club_penalties_loc (etex_pen_base+1) /* penalties for creating club lines */ -# define widow_penalties_loc (etex_pen_base+2) /* penalties for creating widow lines */ -# define display_widow_penalties_loc (etex_pen_base+3) /* ditto, just before a display */ -# define etex_pens (etex_pen_base+4) /* end of table of \eTeX's penalties */ -# define local_left_box_base (etex_pens) -# define local_right_box_base (local_left_box_base+1) -# define box_base (local_right_box_base+1) /* table of |number_regs| box registers */ -# define cur_font_loc (box_base+number_regs) /* internal font number outside math mode */ -# define internal_math_param_base (cur_font_loc+1 ) /* current math parameter data index */ -# define cat_code_base (internal_math_param_base+1) /* current category code data index */ -# define lc_code_base (cat_code_base+1) /* table of |number_chars| lowercase mappings */ -# define uc_code_base (lc_code_base+1) /* table of |number_chars| uppercase mappings */ -# define sf_code_base (uc_code_base+1) /* table of |number_chars| spacefactor mappings */ -# define math_code_base (sf_code_base+1) /* table of |number_chars| math mode mappings */ -# define int_base (math_code_base+1) /* beginning of region 5 */ - -# define pretolerance_code 0 /* badness tolerance before hyphenation */ -# define tolerance_code 1 /* badness tolerance after hyphenation */ -# define line_penalty_code 2 /* added to the badness of every line */ -# define hyphen_penalty_code 3 /* penalty for break after discretionary hyphen */ -# define ex_hyphen_penalty_code 4 /* penalty for break after explicit hyphen */ -# define club_penalty_code 5 /* penalty for creating a club line */ -# define widow_penalty_code 6 /* penalty for creating a widow line */ -# define display_widow_penalty_code 7 /* ditto, just before a display */ -# define broken_penalty_code 8 /* penalty for breaking a page at a broken line */ -# define bin_op_penalty_code 9 /* penalty for breaking after a binary operation */ -# define rel_penalty_code 10 /* penalty for breaking after a relation */ -# define pre_display_penalty_code 11 /* penalty for breaking just before a displayed formula */ -# define post_display_penalty_code 12 /* penalty for breaking just after a displayed formula */ -# define inter_line_penalty_code 13 /* additional penalty between lines */ -# define double_hyphen_demerits_code 14 /* demerits for double hyphen break */ -# define final_hyphen_demerits_code 15 /* demerits for final hyphen break */ -# define adj_demerits_code 16 /* demerits for adjacent incompatible lines */ -# define mag_code 17 /* magnification ratio */ -# define delimiter_factor_code 18 /* ratio for variable-size delimiters */ -# define looseness_code 19 /* change in number of lines for a paragraph */ -# define time_code 20 /* current time of day */ -# define day_code 21 /* current day of the month */ -# define month_code 22 /* current month of the year */ -# define year_code 23 /* current year of our Lord */ -# define show_box_breadth_code 24 /* nodes per level in |show_box| */ -# define show_box_depth_code 25 /* maximum level in |show_box| */ -# define hbadness_code 26 /* hboxes exceeding this badness will be shown by |hpack| */ -# define vbadness_code 27 /* vboxes exceeding this badness will be shown by |vpack| */ -# define pausing_code 28 /* pause after each line is read from a file */ -# define tracing_online_code 29 /* show diagnostic output on terminal */ -# define tracing_macros_code 30 /* show macros as they are being expanded */ -# define tracing_stats_code 31 /* show memory usage if \TeX\ knows it */ -# define tracing_paragraphs_code 32 /* show line-break calculations */ -# define tracing_pages_code 33 /* show page-break calculations */ -# define tracing_output_code 34 /* show boxes when they are shipped out */ -# define tracing_lost_chars_code 35 /* show characters that aren't in the font */ -# define tracing_commands_code 36 /* show command codes at |big_switch| */ -# define tracing_restores_code 37 /* show equivalents when they are restored */ -# define uc_hyph_code 38 /* hyphenate words beginning with a capital letter */ -# define output_penalty_code 39 /* penalty found at current page break */ -# define max_dead_cycles_code 40 /* bound on consecutive dead cycles of output */ -# define hang_after_code 41 /* hanging indentation changes after this many lines */ -# define floating_penalty_code 42 /* penalty for insertions heldover after a split */ -# define global_defs_code 43 /* override \.{\\global} specifications */ -# define cur_fam_code 44 /* current family */ -# define escape_char_code 45 /* escape character for token output */ -# define default_hyphen_char_code 46 /* value of \.{\\hyphenchar} when a font is loaded */ -# define default_skew_char_code 47 /* value of \.{\\skewchar} when a font is loaded */ -# define end_line_char_code 48 /* character placed at the right end of the buffer */ -# define new_line_char_code 49 /* character that prints as |print_ln| */ -# define language_code 50 /* current hyphenation table */ -# define left_hyphen_min_code 51 /* minimum left hyphenation fragment size */ -# define right_hyphen_min_code 52 /* minimum right hyphenation fragment size */ -# define holding_inserts_code 53 /* do not remove insertion nodes from \.{\\box255} */ -# define error_context_lines_code 54 /* maximum intermediate line pairs shown */ -# define local_inter_line_penalty_code 55 /* local \.{\\interlinepenalty} */ -# define local_broken_penalty_code 56 /* local \.{\\brokenpenalty} */ -# define no_local_whatsits_code 57 /* counts local whatsits */ -# define no_local_dirs_code 58 - -# define disable_lig_code 60 -# define disable_kern_code 61 -# define disable_space_code 62 -# define cat_code_table_code 63 -# define output_box_code 64 -# define cur_lang_code 65 /* current language id */ -# define ex_hyphen_char_code 66 -# define hyphenation_min_code 67 /* minimum word length */ -# define adjust_spacing_code 68 /* level of spacing adjusting */ -# define protrude_chars_code 69 /* protrude chars at left/right edge of paragraphs */ -# define output_mode_code 70 /* switch on PDF output if positive */ -# define draft_mode_code 71 -# define tracing_fonts_code 72 -# define tracing_assigns_code 73 /* show assignments */ -# define tracing_groups_code 74 /* show save/restore groups */ -# define tracing_ifs_code 75 /* show conditionals */ -# define tracing_scan_tokens_code 76 /* show pseudo file open and close */ -# define tracing_nesting_code 77 /* show incomplete groups and ifs within files */ -# define pre_display_direction_code 78 /* text direction preceding a display */ -# define last_line_fit_code 79 /* adjustment for last line of paragraph */ -# define saving_vdiscards_code 80 /* save items discarded from vlists */ -# define saving_hyph_codes_code 81 /* save hyphenation codes for languages */ -# define suppress_fontnotfound_error_code 82 /* suppress errors for missing fonts */ -# define suppress_long_error_code 83 /* suppress errors for missing fonts */ -# define suppress_ifcsname_error_code 84 /* suppress errors for failed \.{\\ifcsname} */ -# define suppress_outer_error_code 85 /* suppress errors for \.{\\outer} */ -# define suppress_mathpar_error_code 86 /* suppress errors for \.{\\par}} in math */ -# define math_eqno_gap_step_code 87 /* factor/1000 used for distance between eq and eqno */ -# define math_display_skip_mode_code 88 -# define math_scripts_mode_code 89 -# define math_nolimits_mode_code 90 -# define math_rules_mode_code 91 -# define math_rules_fam_code 92 -# define math_italics_mode_code 93 -# define synctex_code 94 /* is synctex file generation enabled ? */ -# define shape_mode_code 95 -# define first_valid_language_code 96 -# define hyphenation_bounds_code 97 -# define math_skip_mode_code 98 -# define math_pre_display_gap_factor_code 99 -# define hyphen_penalty_mode_code 100 -# define automatic_hyphen_penalty_code 101 -# define explicit_hyphen_penalty_code 102 -# define automatic_hyphen_mode_code 103 -# define compound_hyphen_mode_code 104 -# define break_after_dir_mode_code 105 -# define exception_penalty_code 106 - -# define pre_bin_op_penalty_code 107 -# define pre_rel_penalty_code 108 -# define math_penalties_mode_code 109 -# define math_delimiters_mode_code 110 -# define math_script_box_mode_code 111 -# define math_script_char_mode_code 112 -# define math_rule_thickness_mode_code 113 -# define math_flatten_mode_code 114 - -# define copy_lua_input_nodes_code 115 -# define suppress_primitive_error_code 116 -# define fixup_boxes_code 117 -# define glyph_dimensions_code 118 - -# define math_option_code 119 - -# define mathoption_int_base_code (math_option_code+1) /* one reserve */ -# define mathoption_int_last_code (mathoption_int_base_code+8) - -# define backend_int_base_code (mathoption_int_last_code+1) -# define backend_int_last_code (backend_int_base_code+32) /* we need some 25 but take some slack */ - -# define tex_int_pars (backend_int_last_code+1) /* total number of integer parameters */ - -# define mathoption_int_base (int_base+mathoption_int_base_code) -# define mathoption_int_last (int_base+mathoption_int_last_code) - -# define backend_int_base (int_base+backend_int_base_code) -# define backend_int_last (int_base+backend_int_last_code) - -# define page_direction_code (tex_int_pars) -# define body_direction_code (tex_int_pars+1) -# define par_direction_code (tex_int_pars+2) -# define text_direction_code (tex_int_pars+3) -# define math_direction_code (tex_int_pars+4) -# define line_direction_code (tex_int_pars+5) /* gets remapped so is no real register */ - -# define int_pars (tex_int_pars+5) /* total number of integer parameters */ - -# define dir_base (int_base+tex_int_pars) -# define count_base (int_base+int_pars) /* |number_regs| user \.{\\count} registers */ -# define attribute_base (count_base+number_regs) /* |number_attrs| user \.{\\attribute} registers */ -# define del_code_base (attribute_base+number_attrs) /* |number_chars| delimiter code mappings */ -# define dimen_base (del_code_base+1) /* beginning of region 6 */ - -# define par_indent_code 0 /* indentation of paragraphs */ -# define math_surround_code 1 /* space around math in text */ -# define line_skip_limit_code 2 /* threshold for |line_skip| instead of |baseline_skip| */ -# define hsize_code 3 /* line width in horizontal mode */ -# define vsize_code 4 /* page height in vertical mode */ -# define max_depth_code 5 /* maximum depth of boxes on main pages */ -# define split_max_depth_code 6 /* maximum depth of boxes on split pages */ -# define box_max_depth_code 7 /* maximum depth of explicit vboxes */ -# define hfuzz_code 8 /* tolerance for overfull hbox messages */ -# define vfuzz_code 9 /* tolerance for overfull vbox messages */ -# define delimiter_shortfall_code 10 /* maximum amount uncovered by variable delimiters */ -# define null_delimiter_space_code 11 /* blank space in null delimiters */ -# define script_space_code 12 /* extra space after subscript or superscript */ -# define pre_display_size_code 13 /* length of text preceding a display */ -# define display_width_code 14 /* length of line for displayed equation */ -# define display_indent_code 15 /* indentation of line for displayed equation */ -# define overfull_rule_code 16 /* width of rule that identifies overfull hboxes */ -# define hang_indent_code 17 /* amount of hanging indentation */ -# define h_offset_code 18 /* amount of horizontal offset when shipping pages out */ -# define v_offset_code 19 /* amount of vertical offset when shipping pages out */ -# define emergency_stretch_code 20 /* reduces badnesses on final pass of line-breaking */ -# define page_left_offset_code 21 -# define page_top_offset_code 22 -# define page_right_offset_code 23 -# define page_bottom_offset_code 24 -# define px_dimen_code 25 -# define page_width_code 26 /* page width of the output */ -# define page_height_code 27 /* page height of the output */ - -# define backend_dimen_base (dimen_base+28) -# define backend_dimen_last (dimen_base+37) - -# define dimen_pars (38) /* total number of dimension parameters */ - -# define scaled_base (dimen_base+dimen_pars) /* table of |number_regs| user-defined \.{\\dimen} registers */ -# define eqtb_size (scaled_base+biggest_reg) /* largest subscript of |eqtb| */ - -extern memory_word *eqtb; - -extern halfword eqtb_top; /* maximum of the |eqtb| */ - -extern quarterword xeq_level[(eqtb_size + 1)]; -extern void initialize_equivalents(void); - -# define eq_level_field(A) (A).hh.b1 -# define eq_type_field(A) (A).hh.b0 -# define equiv_field(A) (A).hh.rh - -# define eq_level(A) eq_level_field(eqtb[(A)]) /* level of definition */ -# define eq_type(A) eq_type_field(eqtb[(A)]) /* command code for equivalent */ -# define equiv(A) equiv_field(eqtb[(A)]) /* equivalent value */ - -# define set_eq_level(A,B) eq_level((A)) = (B) -# define set_eq_type(A,B) eq_type((A)) = (B) -# define set_equiv(A,B) equiv((A)) = (B) - -typedef struct save_record_ { - quarterword type_; - quarterword level_; - memory_word word_; -} save_record; - -extern save_record *save_stack; -extern int save_ptr; /* first unused entry on |save_stack| */ -extern int max_save_stack; /* maximum usage of save stack */ -extern quarterword cur_level; /* current nesting level for groups */ -extern group_code cur_group; /* current group type */ -extern int cur_boundary; /* where the current level begins */ - -# define save_type(A) save_stack[(A)].type_ /* classifies a |save_stack| entry */ -# define save_level(A) save_stack[(A)].level_ /* saved level for regions 5 and 6, or group code */ -# define save_value(A) save_stack[(A)].word_.cint /* |eqtb| location or token or |save_stack| location */ -# define save_word(A) save_stack[(A)].word_ /* |eqtb| entry */ - -/* - -We use the notation |saved(k)| to stand for an item that appears in location -|save_ptr+k| of the save stack. - -*/ - -# define saved_type(A) save_stack[save_ptr+(A)].type_ -# define saved_level(A) save_stack[save_ptr+(A)].level_ -# define saved_value(A) save_stack[save_ptr+(A)].word_.cint - -# define set_saved_record(A,B,C,D) do { \ - saved_type(A) = (quarterword)(B); \ - saved_level(A) = (quarterword)(C); \ - saved_value(A) = (D); \ - } while (0) - -# define restore_old_value 0 /* |save_type| when a value should be restored later */ -# define restore_zero 1 /* |save_type| when an undefined entry should be restored */ -# define insert_token 2 /* |save_type| when a token is being saved for later use */ -# define level_boundary 3 /* |save_type| corresponding to beginning of group */ -# define saved_line 4 -# define saved_adjust 5 -# define saved_insert 6 -# define saved_disc 7 -# define saved_boxtype 8 -# define saved_textdir 9 -# define saved_eqno 10 -# define saved_choices 11 -# define saved_math 12 -# define saved_boxcontext 13 -# define saved_boxspec 14 -# define saved_boxdir 15 -# define saved_boxattr 16 -# define saved_boxpack 17 -# define saved_attrlist 18 -# define saved_eqtb 19 - -extern void print_save_stack(void); - -# define int_par(A) eqtb[int_base+(A)].cint -# define dimen_par(A) eqtb[dimen_base+(A)].cint -# define loc_par(A) equiv(local_base+(A)) -# define glue_par(A) equiv(glue_base+(A)) - -typedef enum { - c_mathoption_old_code = 0, /* this one is stable */ - /* - c_mathoption_umathcode_meaning_code, - */ -} math_option_codes ; - -# define mathoption_int_par(A) eqtb[mathoption_int_base+(A)].cint - -/* if nonzero, this magnification should be used henceforth */ - -extern int mag_set; -extern void prepare_mag(void); - -/* - -@ Here are the group codes that are used to discriminate between different kinds -of groups. They allow \TeX\ to decide what special actions, if any, should be -performed when a group ends. \def\grp{\.{\char'173...\char'175}} - -Some groups are not supposed to be ended by right braces. For example, the `\.\$' -that begins a math formula causes a |math_shift_group| to be started, and this -should be terminated by a matching `\.\$'. Similarly, a group that starts with -\.{\\left} should end with \.{\\right}, and one that starts with \.{\\begingroup} -should end with \.{\\endgroup}. - -*/ - -typedef enum { - bottom_level = 0, /* group code for the outside world */ - simple_group, /* group code for local structure only */ - hbox_group, /* code for `\.{\\hbox}\grp' */ - adjusted_hbox_group, /* code for `\.{\\hbox}\grp' in vertical mode */ - vbox_group, /* code for `\.{\\vbox}\grp' */ - vtop_group, /* code for `\.{\\vtop}\grp' */ - align_group, /* code for `\.{\\halign}\grp', `\.{\\valign}\grp' */ - no_align_group, /* code for `\.{\\noalign}\grp' */ - output_group, /* code for output routine */ - math_group, /* code for, e.g., `\.{\char'136}\grp' */ - disc_group, /* code for `\.{\\discretionary}\grp\grp\grp' */ - insert_group, /* code for `\.{\\insert}\grp', `\.{\\vadjust}\grp' */ - vcenter_group, /* code for `\.{\\vcenter}\grp' */ - math_choice_group, /* code for `\.{\\mathchoice}\grp\grp\grp\grp' */ - semi_simple_group, /* code for `\.{\\begingroup...\\endgroup}' */ - math_shift_group, /* code for `\.{\$...\$}' */ - math_left_group, /* code for `\.{\\left...\\right}' */ - local_box_group, /* code for `\.{\\localleftbox...\\localrightbox}' */ - split_off_group, /* box code for the top part of a \.{\\vsplit} */ - split_keep_group, /* box code for the bottom part of a \.{\\vsplit} */ - preamble_group, /* box code for the preamble processing in an alignment */ - align_set_group, /* box code for the final item pass in an alignment */ - fin_row_group /* box code for a provisory line in an alignment */ -} tex_group_codes; - -typedef enum { - new_graf_par_code = 0, - local_box_par_code, - hmode_par_par_code, - penalty_par_code, - math_par_code, -} tex_par_codes ; - -typedef enum { - display_style = 0, /* |subtype| for \.{\\displaystyle} */ - cramped_display_style, /* |subtype| for \.{\\crampeddisplaystyle} */ - text_style, /* |subtype| for \.{\\textstyle} */ - cramped_text_style, /* |subtype| for \.{\\crampedtextstyle} */ - script_style, /* |subtype| for \.{\\scriptstyle} */ - cramped_script_style, /* |subtype| for \.{\\crampedscriptstyle} */ - script_script_style, /* |subtype| for \.{\\scriptscriptstyle} */ - cramped_script_script_style, /* |subtype| for \.{\\crampedscriptscriptstyle} */ -} math_style_subtypes; - -typedef enum { /* this could move to directions.h */ - dir_TLT = 0, - dir_TRT, - dir_LTL, - dir_RTT, -} dir_codes; - -# define max_group_code local_box_group /* which is wrong, but is what the web says */ - -extern int cur_cmd; /* current command set by |get_next| */ -extern halfword cur_chr; /* operand of current command */ -extern halfword cur_cs; /* control sequence found here, zero if none found */ -extern halfword cur_tok; /* packed representative of |cur_cmd| and |cur_chr| */ - -extern void show_cur_cmd_chr(void); - -extern void new_save_level(group_code c); /* begin a new level of grouping */ -extern void eq_destroy(memory_word w); /* gets ready to forget |w| */ -extern void eq_save(halfword p, quarterword l); /* saves |eqtb[p]| */ -extern void eq_define(halfword p, quarterword t, halfword e); /* new data for |eqtb| */ -extern void eq_word_define(halfword p, int w); -extern void geq_define(halfword p, quarterword t, halfword e); /* global |eq_define| */ -extern void geq_word_define(halfword p, int w); /* global |eq_word_define| */ -extern void save_for_after(halfword t); -extern void unsave(void); /* pops the top level off the save stack */ -extern void show_save_groups(void); - -# define level_zero 0 /* level for undefined quantities */ -# define level_one 1 /* outermost level for defined quantities */ - -extern void show_eqtb(halfword n); - -/* \csname \ifcsname */ - -extern halfword last_cs_name; - -/* - The *_par macros expand to the variables that are (in most cases) also accessible - at the users end. Most are registers but some are in the (stack) lists. - - More *_par will move here : there is no real need for thse macros but because there - were already a bunch and because they were defined all over the place we moved them - here. - -*/ - -#define space_skip_par glue_par(space_skip_code) -#define xspace_skip_par glue_par(xspace_skip_code) -#define math_skip_par glue_par(math_skip_code) -#define math_skip_mode int_par(math_skip_mode_code) - -#define pre_display_size_par dimen_par(pre_display_size_code) -#define display_width_par dimen_par(display_width_code) -#define display_indent_par dimen_par(display_indent_code) -#define math_surround_par dimen_par(math_surround_code) - -#define display_skip_mode_par int_par(math_display_skip_mode_code) -#define math_eqno_gap_step_par int_par(math_eqno_gap_step_code) - -#define body_direction_par int_par(body_direction_code) -#define page_direction_par int_par(page_direction_code) -#define par_direction_par int_par(par_direction_code) -#define text_direction_par int_par(text_direction_code) -#define math_direction_par int_par(math_direction_code) - -#define shape_mode_par int_par(shape_mode_code) -#define hyphenation_bounds_par int_par(hyphenation_bounds_code) -#define first_valid_language_par int_par(first_valid_language_code) - -#define hsize_par dimen_par(hsize_code) -#define vsize_par dimen_par(vsize_code) -#define hfuzz_par dimen_par(hfuzz_code) -#define vfuzz_par dimen_par(vfuzz_code) -#define hbadness_par int_par(hbadness_code) -#define vbadness_par int_par(vbadness_code) - -#define baseline_skip_par glue_par(baseline_skip_code) -#define par_indent_par dimen_par(par_indent_code) -#define hang_indent_par dimen_par(hang_indent_code) -#define hang_after_par int_par(hang_after_code) -#define left_skip_par glue_par(left_skip_code) -#define right_skip_par glue_par(right_skip_code) - -#define emergency_stretch_par dimen_par(emergency_stretch_code) -#define pretolerance_par int_par(pretolerance_code) -#define tolerance_par int_par(tolerance_code) -#define looseness_par int_par(looseness_code) -#define adjust_spacing_par int_par(adjust_spacing_code) -#define adj_demerits_par int_par(adj_demerits_code) -#define protrude_chars_par int_par(protrude_chars_code) -#define line_penalty_par int_par(line_penalty_code) -#define last_line_fit_par int_par(last_line_fit_code) -#define double_hyphen_demerits_par int_par(double_hyphen_demerits_code) -#define final_hyphen_demerits_par int_par(final_hyphen_demerits_code) -#define inter_line_penalty_par int_par(inter_line_penalty_code) -#define club_penalty_par int_par(club_penalty_code) -#define broken_penalty_par int_par(broken_penalty_code) -#define display_widow_penalty_par int_par(display_widow_penalty_code) -#define widow_penalty_par int_par(widow_penalty_code) -#define line_skip_limit_par dimen_par(line_skip_limit_code) - -#define delimiter_shortfall_par dimen_par(delimiter_shortfall_code) -#define null_delimiter_space_par dimen_par(null_delimiter_space_code) -#define script_space_par dimen_par(script_space_code) -#define max_depth_par dimen_par(max_depth_code) -#define box_max_depth_par dimen_par(box_max_depth_code) -#define split_max_depth_par dimen_par(split_max_depth_code) -#define overfull_rule_par dimen_par(overfull_rule_code) -#define box_max_depth_par dimen_par(box_max_depth_code) -#define top_skip_par glue_par(top_skip_code) -#define split_top_skip_par glue_par(split_top_skip_code) - -#define cur_fam_par int_par(cur_fam_code) -#define pre_display_direction_par int_par(pre_display_direction_code) -#define pre_display_penalty_par int_par(pre_display_penalty_code) -#define post_display_penalty_par int_par(post_display_penalty_code) - -#define cur_fam_par_in_range ((cur_fam_par>=0)&&(cur_fam_par<256)) - -#define local_inter_line_penalty_par int_par(local_inter_line_penalty_code) -#define local_broken_penalty_par int_par(local_broken_penalty_code) -#define local_left_box_par equiv(local_left_box_base) -#define local_right_box_par equiv(local_right_box_base) - -#define end_line_char_par int_par(end_line_char_code) -#define new_line_char_par int_par(new_line_char_code) -#define escape_char_par int_par(escape_char_code) - -#define end_line_char_inactive ((end_line_char_par < 0) || (end_line_char_par > 127)) - -#define delimiter_factor_par int_par(delimiter_factor_code) -#define bin_op_penalty_par int_par(bin_op_penalty_code) -#define rel_penalty_par int_par(rel_penalty_code) -#define pre_bin_op_penalty_par int_par(pre_bin_op_penalty_code) -#define pre_rel_penalty_par int_par(pre_rel_penalty_code) -#define math_penalties_mode_par int_par(math_penalties_mode_code) -#define math_delimiters_mode_par int_par(math_delimiters_mode_code) -#define math_script_box_mode_par int_par(math_script_box_mode_code) -#define math_script_char_mode_par int_par(math_script_char_mode_code) -#define math_rule_thickness_mode_par int_par(math_rule_thickness_mode_code) -#define math_flatten_mode_par int_par(math_flatten_mode_code) -#define null_delimiter_space_par dimen_par(null_delimiter_space_code) -#define disable_lig_par int_par(disable_lig_code) -#define disable_kern_par int_par(disable_kern_code) -#define disable_space_par int_par(disable_space_code) -#define math_scripts_mode_par int_par(math_scripts_mode_code) -#define math_nolimits_mode_par int_par(math_nolimits_mode_code) -#define math_italics_mode_par int_par(math_italics_mode_code) -#define math_rules_mode_par int_par(math_rules_mode_code) -#define math_rules_fam_par int_par(math_rules_fam_code) - -#define thin_mu_skip_par glue_par(thin_mu_skip_code) -#define med_mu_skip_par glue_par(med_mu_skip_code) -#define thick_mu_skip_par glue_par(thick_mu_skip_code) - -#define every_math_par equiv(every_math_loc) -#define every_display_par equiv(every_display_loc) -#define every_cr_par equiv(every_cr_loc) -#define every_hbox_par equiv(every_hbox_loc) -#define every_vbox_par equiv(every_vbox_loc) -#define every_eof_par equiv(every_eof_loc) -#define every_par_par equiv(every_par_loc) -#define err_help_par equiv(err_help_loc) - -#define no_local_whatsits_par int_par(no_local_whatsits_code) -#define no_local_dirs_par int_par(no_local_dirs_code) - -#define prev_depth_par cur_list.prev_depth_field -#define prev_graf_par cur_list.pg_field -#define tail_par cur_list.tail_field -#define head_par cur_list.head_field -#define mode_par cur_list.mode_field -#define dirs_par cur_list.dirs_field -#define space_factor_par cur_list.space_factor_field -#define incompleat_noad_par cur_list.incompleat_noad_field -#define mode_line_par cur_list.ml_field -#define aux_par cur_list.eTeX_aux_field -#define delim_par aux_par - -#define par_shape_par_ptr equiv(par_shape_loc) -#define inter_line_penalties_par_ptr equiv(inter_line_penalties_loc) -#define club_penalties_par_ptr equiv(club_penalties_loc) -#define widow_penalties_par_ptr equiv(widow_penalties_loc) -#define display_widow_penalties_par_ptr equiv(display_widow_penalties_loc) - -#define page_width_par dimen_par(page_width_code) -#define page_height_par dimen_par(page_height_code) -#define h_offset_par dimen_par(h_offset_code) -#define v_offset_par dimen_par(v_offset_code) -#define page_left_offset_par dimen_par(page_left_offset_code) -#define page_top_offset_par dimen_par(page_top_offset_code) -#define page_right_offset_par dimen_par(page_right_offset_code) -#define page_bottom_offset_par dimen_par(page_bottom_offset_code) -#define px_dimen_par dimen_par(px_dimen_code) - -#define max_dead_cycles_par int_par(max_dead_cycles_code) -#define output_box_par int_par(output_box_code) -#define holding_inserts_par int_par(holding_inserts_code) -#define output_routine_par equiv(output_routine_loc) -#define floating_penalty_par int_par(floating_penalty_code) - -#define mag_par int_par(mag_code) - -#define global_defs_par int_par(global_defs_code) -#define cat_code_table_par int_par(cat_code_table_code) -#define saving_vdiscards_par int_par(saving_vdiscards_code) - -#define tracing_output_par int_par(tracing_output_code) -#define tracing_stats_par int_par(tracing_stats_code) -#define tracing_online_par int_par(tracing_online_code) -#define tracing_paragraphs_par int_par(tracing_paragraphs_code) -#define tracing_nesting_par int_par(tracing_nesting_code) -#define tracing_lost_chars_par int_par(tracing_lost_chars_code) -#define tracing_scan_tokens_par int_par(tracing_scan_tokens_code) -#define tracing_ifs_par int_par(tracing_ifs_code) -#define tracing_commands_par int_par(tracing_commands_code) -#define tracing_macros_par int_par(tracing_macros_code) -#define tracing_assigns_par int_par(tracing_assigns_code) -#define tracing_fonts_par int_par(tracing_fonts_code) -#define tracing_pages_par int_par(tracing_pages_code) -#define tracing_restores_par int_par(tracing_restores_code) -#define tracing_groups_par int_par(tracing_groups_code) - -#define show_box_depth_par int_par(show_box_depth_code) -#define show_box_breadth_par int_par(show_box_breadth_code) - -#define pausing_par int_par(pausing_code) - -#define suppress_outer_error_par int_par(suppress_outer_error_code) -#define suppress_long_error_par int_par(suppress_long_error_code) -#define suppress_mathpar_error_par int_par(suppress_mathpar_error_code) -#define suppress_fontnotfound_error_par int_par(suppress_fontnotfound_error_code) -#define suppress_ifcsname_error_par int_par(suppress_ifcsname_error_code) -#define suppress_primitive_error_par int_par(suppress_primitive_error_code) -#define error_context_lines_par int_par(error_context_lines_code) -#define copy_lua_input_nodes_par int_par(copy_lua_input_nodes_code) - -#define math_old_par mathoption_int_par(c_mathoption_old_code) - -/* -#define math_umathcode_meaning_par mathoption_int_par(c_mathoption_umathcode_meaning_code) -*/ - -#define math_pre_display_gap_factor_par int_par(math_pre_display_gap_factor_code) - -#define time_par int_par(time_code) -#define day_par int_par(day_code) -#define month_par int_par(month_code) -#define year_par int_par(year_code) - -#define output_mode_par int_par(output_mode_code) -#define draft_mode_par int_par(draft_mode_code) -#define synctex_par int_par(synctex_code) - -#define language_par int_par(language_code) -#define uc_hyph_par int_par(uc_hyph_code) -#define left_hyphen_min_par int_par(left_hyphen_min_code) -#define right_hyphen_min_par int_par(right_hyphen_min_code) -#define ex_hyphen_char_par int_par(ex_hyphen_char_code) -#define hyphen_penalty_par int_par(hyphen_penalty_code) -#define ex_hyphen_penalty_par int_par(ex_hyphen_penalty_code) -#define default_hyphen_char_par int_par(default_hyphen_char_code) -#define default_skew_char_par int_par(default_skew_char_code) -#define saving_hyph_codes_par int_par(saving_hyph_codes_code) - -#define hyphen_penalty_mode_par int_par(hyphen_penalty_mode_code) -#define automatic_hyphen_penalty_par int_par(automatic_hyphen_penalty_code) -#define explicit_hyphen_penalty_par int_par(explicit_hyphen_penalty_code) -#define automatic_hyphen_mode_par int_par(automatic_hyphen_mode_code) -#define compound_hyphen_mode_par int_par(compound_hyphen_mode_code) -#define break_after_dir_mode_par int_par(break_after_dir_mode_code) -#define exception_penalty_par int_par(exception_penalty_code) - -#define cur_lang_par int_par(cur_lang_code) -#define cur_font_par equiv(cur_font_loc) - -#define fixup_boxes_par int_par(fixup_boxes_code) -#define glyph_dimensions_par int_par(glyph_dimensions_code) - -/* */ - -#define math_use_current_family_code 7 - -/* - #define box(A) equiv(box_base+(A)) - #define box(A) eqtb[box_base+(A)].hh.rh -*/ - -#define attribute(A) equiv(attribute_base+(A)) -#define box(A) equiv(box_base+(A)) -#define count(A) equiv(count_base+(A)) -#define dimen(A) equiv(scaled_base+(A)) -#define mu_skip(A) equiv(mu_skip_base+(A)) -#define skip(A) equiv(skip_base+(A)) -#define toks(A) equiv(toks_base+(A)) - -#define get_tex_attribute_register(j) attribute(j) -#define get_tex_box_register(j) box(j) -#define get_tex_count_register(j) count(j) -#define get_tex_dimen_register(j) dimen(j) -#define get_tex_mu_skip_register(j) mu_skip(j) -#define get_tex_skip_register(j) skip(j) - -#define font_id_text(A) cs_text(font_id_base+(A)) - -#define end_template_token (cs_token_flag+frozen_end_template) -#define end_write_token (cs_token_flag+end_write) - -/* for now here */ - -#define xspace_skip_subtype (xspace_skip_code + 1) -#define space_skip_subtype (space_skip_code + 1) - -/* - -hyphen_penalty_mode_par automatic_disc (-) explicit_disc (\-) ---------------------------------------------------------------------------------- -0 (default) ex_hyphen_penalty_par ex_hyphen_penalty_par -1 hyphen_penalty_par hyphen_penalty_par -2 ex_hyphen_penalty_par hyphen_penalty_par -3 hyphen_penalty_par ex_hyphen_penalty_par -4 automatic_hyphen_penalty_par explicit_disc_penalty_par -5 ex_hyphen_penalty_par explicit_disc_penalty_par -6 hyphen_penalty_par explicit_disc_penalty_par -7 automatic_hyphen_penalty_par ex_hyphen_penalty_par -8 automatic_hyphen_penalty_par hyphen_penalty_par -*/ - -#define set_automatic_disc_penalty(n) \ - switch (hyphen_penalty_mode_par) { \ - case 0: \ - case 2: \ - case 5: \ - /* we take ex_hyphen_penalty */ \ - disc_penalty(n) = ex_hyphen_penalty_par; \ - break; \ - case 1: \ - case 3: \ - case 6: \ - /* we take hyphen_penalty */ \ - disc_penalty(n) = hyphen_penalty_par; \ - break; \ - case 4: \ - case 7: \ - case 8: \ - /* we take automatic_hyphen_penalty */ \ - disc_penalty(n) = automatic_hyphen_penalty_par; \ - break; \ - default: \ - /* what we've done since the beginning */ \ - disc_penalty(n) = ex_hyphen_penalty_par; \ - break; \ - } - -#define set_explicit_disc_penalty(n) \ - switch (hyphen_penalty_mode_par) { \ - case 0: \ - case 3: \ - case 7: \ - /* we take ex_hyphen_penalty */ \ - disc_penalty(n) = ex_hyphen_penalty_par; \ - break; \ - case 1: \ - case 2: \ - case 8: \ - /* we take hyphen_penalty */ \ - disc_penalty(n) = hyphen_penalty_par; \ - break; \ - case 4: \ - case 5: \ - case 6: \ - /* we take automatic_hyphen_penalty */ \ - disc_penalty(n) = explicit_hyphen_penalty_par; \ - break; \ - default: \ - /* what we've done since the beginning */ \ - disc_penalty(n) = ex_hyphen_penalty_par; \ - break; \ - } - -#endif diff --git a/Build/source/texk/web2c/luatexdir/tex/errors.c b/Build/source/texk/web2c/luatexdir/tex/errors.c deleted file mode 100644 index ce80df99e7e..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/errors.c +++ /dev/null @@ -1,1055 +0,0 @@ -/* - -errors.w - -Copyright 2009-2010 Taco Hoekwater <taco@@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your -option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU General Public License along -with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" -#define edit_var "TEXEDIT" - -/*tex - -When something anomalous is detected, \TeX\ typically does something like this: -$$\vbox{\halign{#\hfil\cr |print_err("Something anomalous has been -detected");|\cr |help3("This is the first line of my offer to help.")|\cr |("This -is the second line. I'm trying to")|\cr |("explain the best way for you to -proceed.");|\cr |error;|\cr}}$$ A two-line help message would be given using -|help2|, etc.; these informal helps should use simple vocabulary that complements -the words used in the official error message that was printed. (Outside the -U.S.A., the help messages should preferably be translated into the local -vernacular. Each line of help is at most 60 characters long, in the present -implementation, so that |max_print_line| will not be exceeded.) - -The |print_err| procedure supplies a `\.!' before the official message, and makes -sure that the terminal is awake if a stop is going to occur. The |error| -procedure supplies a `\..' after the official message, then it shows the location -of the error; and if |interaction=error_stop_mode|, it also enters into a dialog -with the user, during which time the help message may be printed. @^system -dependencies@> - -*/ - -/*tex The current level of interaction: */ - -int interaction; - -/*tex Set from the command line: */ - -int interactionoption; - -char *last_error = NULL; -char *last_lua_error = NULL; -char *last_warning_tag = NULL; -char *last_warning_str = NULL; -char *last_error_context = NULL; - -int err_old_setting = 0 ; -int in_error = 0 ; - -void set_last_error_context(void) -{ - str_number str; - int sel = selector; - int saved_new_line_char; - int saved_new_string_line; - selector = new_string; - saved_new_line_char = new_line_char_par; - saved_new_string_line = new_string_line; - new_line_char_par = 10; - new_string_line = 10; - show_context(); - xfree(last_error_context); - str = make_string(); - last_error_context = makecstring(str); - flush_str(str); - selector = sel; - new_line_char_par = saved_new_line_char; - new_string_line = saved_new_string_line; - return; -} - -void flush_err(void) -{ - str_number s_error; - char *s = NULL; - int callback_id ; - if (in_error) { - selector = err_old_setting; - str_room(1); - s_error = make_string(); - s = makecstring(s_error); - flush_str(s_error); - if (interaction == error_stop_mode) { - wake_up_terminal(); - } - xfree(last_error); - last_error = (string) xmalloc((unsigned) (strlen(s) + 1)); - strcpy(last_error,s); - callback_id = callback_defined(show_error_message_callback); - if (callback_id > 0) { - run_callback(callback_id, "->"); - } else { - tprint(s); - } - in_error = 0 ; - } -} - -void print_err(const char *s) -{ - int callback_id = callback_defined(show_error_message_callback); - if (interaction == error_stop_mode) { - wake_up_terminal(); - } - if (callback_id > 0) { - err_old_setting = selector; - selector = new_string; - in_error = 1 ; - } - if (filelineerrorstylep) { - print_file_line(); - } else { - tprint_nl("! "); - } - tprint(s); - if (callback_id <= 0) { - xfree(last_error); - last_error = (string) xmalloc((unsigned) (strlen(s) + 1)); - strcpy(last_error,s); - } -} - -/*tex - -\TeX\ is careful not to call |error| when the print |selector| setting might be -unusual. The only possible values of |selector| at the time of error messages are - -|no_print| (when |interaction=batch_mode| and |log_file| not yet open); - -|term_only| (when |interaction>batch_mode| and |log_file| not yet open); - -|log_only| (when |interaction=batch_mode| and |log_file| is open); - -|term_and_log| (when |interaction>batch_mode| and |log_file| is open). - -*/ - -void fixup_selector(boolean logopened) -{ - if (interaction == batch_mode) - selector = no_print; - else - selector = term_only; - if (logopened) - selector = selector + 2; -} - -/*tex - -A global variable |deletions_allowed| is set |false| if the |get_next| routine is -active when |error| is called; this ensures that |get_next| and related routines -like |get_token| will never be called recursively. A similar interlock is -provided by |set_box_allowed|. @^recursion@> - -The global variable |history| records the worst level of error that has been -detected. It has four possible values: |spotless|, |warning_issued|, -|error_message_issued|, and |fatal_error_stop|. - -Another global variable, |error_count|, is increased by one when an |error| -occurs without an interactive dialog, and it is reset to zero at the end of every -paragraph. If |error_count| reaches 100, \TeX\ decides that there is no point in -continuing further. - -*/ - -/*tex Is it safe for |error| to call |get_token|? */ - -boolean deletions_allowed; - -/*tex Is it safe to do a \.{\\setbox} assignment? */ - -boolean set_box_allowed; -/*tex Has the source input been clean so far? */ - -int history; - -/*tex The number of scrolled errors since the last paragraph ended. */ - -int error_count; - -/*tex Should \TeX\ pause for instructions? */ - -int interrupt; - -/*tex Should interrupts be observed? */ - -boolean OK_to_interrupt; - -/*tex - -The value of |history| is initially |fatal_error_stop|, but it will be changed to -|spotless| if \TeX\ survives the initialization process. - -*/ - -void initialize_errors(void) -{ - if (interactionoption == unspecified_mode) - interaction = error_stop_mode; - else - interaction = interactionoption; - deletions_allowed = true; - set_box_allowed = true; - OK_to_interrupt = true; -} - -/*tex - -It is possible for |error| to be called recursively if some error arises when -|get_token| is being used to delete a token, and/or if some fatal error occurs -while \TeX\ is trying to fix a non-fatal one. But such recursion @^recursion@> is -never more than two levels deep. - -Individual lines of help are recorded in the array |help_line|. - -*/ - -const char *help_line[7]; - -/*tex - Should the |err_help| list be shown? -*/ - -boolean use_err_help; - -/*tex - -The |jump_out| procedure just cuts across all active procedure levels and exits -the program. It is used when there is no recovery from a particular error. The -exit code can be overloaded. - -*/ - -int defaultexitcode = 0; - -__attribute__ ((noreturn)) -void do_final_end(void) -{ - update_terminal(); - ready_already = 0; - lua_close(Luas); - if ((history != spotless) && (history != warning_issued)) - uexit(1); - else - uexit(defaultexitcode); -} - -__attribute__ ((noreturn)) -void jump_out(void) -{ - close_files_and_terminate(); - do_final_end(); -} - -/*tex - -Here is the function that calls the editor, if one is defined. This is loosely -based on a similar function in kpathsea, but the calling convention is quite -different. - -*/ - -static const_string edit_value = EDITOR; - -#if defined(WIN32) - -static int Isspace (char c) -{ - return (c == ' ' || c == '\t'); -} - -#endif /* WIN32 */ - -__attribute__ ((noreturn)) -static void luatex_calledit (int baseptr, int linenumber) -{ - char *temp, *command; - char *fullcmd = NULL; /* avoid compiler warning */ - char c; - int sdone, ddone, i; - char *filename = makecstring(input_stack[base_ptr].name_field); - int fnlength = strlen(filename); -#ifdef WIN32 - char *fp, *ffp, *env, editorname[256], buffer[256]; - int cnt = 0; - int dontchange = 0; -#endif - sdone = ddone = 0; - /*tex - Close any open input files, since we're going to kill the job. - */ - close_files_and_terminate(); - /*tex - Replace the default with the value of the appropriate environment - variable or config file value, if it's set. - */ - temp = kpse_var_value (edit_var); - if (temp != NULL) - edit_value = temp; - /*tex - Construct the command string. The `11' is the maximum length an - integer might be. - */ - command = xmalloc (strlen (edit_value) + fnlength + 11); - /*tex - So we can construct it as we go. - */ - temp = command; -#ifdef WIN32 - fp = editorname; - if ((isalpha(*edit_value) && *(edit_value + 1) == ':' && IS_DIR_SEP (*(edit_value + 2))) - || (*edit_value == '"' && isalpha(*(edit_value + 1)) - && *(edit_value + 2) == ':' && IS_DIR_SEP (*(edit_value + 3)))) { - dontchange = 1; - } -#endif - while ((c = *edit_value++) != 0) { - if (c == '%') { - switch (c = *edit_value++) { - case 'd': - if (ddone) - FATAL1 ("call_edit: `%%d' appears twice in editor command: `%s'", edit_value); - sprintf (temp, "%ld", (long int)linenumber); - while (*temp != '\0') - temp++; - ddone = 1; - break; - case 's': - if (sdone) - FATAL1 ("call_edit: `%%s' appears twice in editor command: `%s'", edit_value); - for (i =0; i < fnlength; i++) - *temp++ = filename[i]; - sdone = 1; - break; - case '\0': - *temp++ = '%'; - /*tex - Back up to the null to force termination. - */ - edit_value--; - break; - default: - *temp++ = '%'; - *temp++ = c; - break; - } - } else { -#ifdef WIN32 - if (dontchange) { - *temp++ = c; - } else if(Isspace(c) && cnt == 0) { - cnt++; - temp = command; - *temp++ = c; - *fp = '\0'; - } else if(!Isspace(c) && cnt == 0) { - *fp++ = c; - } else { - *temp++ = c; - } -#else - *temp++ = c; -#endif - } - } - *temp = 0; -#ifdef WIN32 - if (dontchange == 0) { - if(editorname[0] == '.' || editorname[0] == '/' || editorname[0] == '\\') { - fprintf(stderr, "%s is not allowed to execute.\n", editorname); - do_final_end(); - } - env = (char *)getenv("PATH"); - if(SearchPath(env, editorname, ".exe", 256, buffer, &ffp)==0) { - if(SearchPath(env, editorname, ".bat", 256, buffer, &ffp)==0) { - fprintf(stderr, "I cannot find %s in the PATH.\n", editorname); - do_final_end(); - } - } - fullcmd = (char *)xmalloc(strlen(buffer)+strlen(command)+5); - strcpy(fullcmd, "\""); - strcat(fullcmd, buffer); - strcat(fullcmd, "\""); - strcat(fullcmd, command); - } -#else - fullcmd = command; -#endif - /*tex Execute the command. */ - if (system (fullcmd) != 0) { - fprintf (stderr, "! Trouble executing `%s'.\n", command); - } - /*tex Quit, since we found an error. */ - do_final_end (); -} - -/*tex - - This completes the job of error reporting. - -*/ - -void error(void) -{ - /*tex What the user types :*/ - ASCII_code c; - int callback_id; - /*tex Used to save global variables when deleting tokens: */ - int s1, s2, s3, s4; - int i; - flush_err(); - if (history < error_message_issued) - history = error_message_issued; - callback_id = callback_defined(show_error_hook_callback); - if (callback_id > 0) { - set_last_error_context(); - run_callback(callback_id, "->"); - } else { - print_char('.'); - show_context(); - } - if (haltonerrorp) { - history = fatal_error_stop; - jump_out(); - } - if (interaction == error_stop_mode) { - /*tex Get user's advice and |return|. */ - while (1) { - CONTINUE: - /*tex - Original reports: - - https://tex.stackexchange.com/questions/551313/ - https://tug.org/pipermail/tex-live/2020-June/045876.html - - This will probably be fixed by DEK in the 2021 tuneup in a different - way (so we'll have to remove or alter this change), but the interaction - sequence in the reports above causes a segmentation fault in web2c - - writing to the closed \write15 stream because we wrongly decrement - selector from 16 to 15 in term_input, due to the lack of this check in - recursive error() call. - */ - if (interaction !=error_stop_mode) - return; - clear_for_error_prompt(); - prompt_input("? "); - if (last == first) - return; - c = buffer[first]; - if (c >= 'a') - c = c + 'A' - 'a'; - /*tex - Interpret code |c| and |return| if done. It is desirable to - provide an `\.E' option here that gives the user an easy way - to return from \TeX\ to the system editor, with the offending - line ready to be edited. But such an extension requires some - system wizardry, so the present implementation simply types - out the name of the file that should be edited and the - relevant line number. - */ - switch (c) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (deletions_allowed) { - /*tex - Delete |c-"0"| tokens and |goto continue|. We allow - deletion of up to 99 tokens at a time. - */ - s1 = cur_tok; - s2 = cur_cmd; - s3 = cur_chr; - s4 = align_state; - align_state = 1000000; - OK_to_interrupt = false; - if ((last > first + 1) && (buffer[first + 1] >= '0') - && (buffer[first + 1] <= '9')) - c = c * 10 + buffer[first + 1] - '0' * 11; - else - c = c - '0'; - while (c > 0) { - /*tex One-level recursive call of |error| is possible. */ - get_token(); - decr(c); - } - cur_tok = s1; - cur_cmd = s2; - cur_chr = s3; - align_state = s4; - OK_to_interrupt = true; - help2( - "I have just deleted some text, as you asked.", - "You can now delete more, or insert, or whatever." - ); - show_context(); - goto CONTINUE; - } - break; - case 'E': - if (base_ptr > 0) { - int callback_id = callback_defined(call_edit_callback); - if (callback_id>0) { - (void)run_callback(callback_id, "Sd->", makecstring(input_stack[base_ptr].name_field), line); - /*tex This should not be reached. */ - jump_out(); - } else { - tprint_nl("You want to edit file "); - print(input_stack[base_ptr].name_field); - tprint(" at line "); - print_int(line); - interaction = scroll_mode; - if (kpse_init) { - luatex_calledit(base_ptr, line); - } else { - /*tex This should not be reached. */ - tprint_nl("There is no valid callback defined."); - jump_out(); - } - } - } - break; - case 'H': - /*tex Print the help information and |goto continue| */ - if (use_err_help) { - give_err_help(); - } else { - if (help_line[0] == NULL) { - help2( - "Sorry, I don't know how to help in this situation.", - "Maybe you should try asking a human?" - ); - } - i = 0; - while (help_line[i] != NULL) - tprint_nl(help_line[i++]); - help4( - "Sorry, I already gave what help I could...", - "Maybe you should try asking a human?", - "An error might have occurred before I noticed any problems.", - "``If all else fails, read the instructions.''" - ); - goto CONTINUE; - } - break; - case 'I': - /*tex - - Introduce new material from the terminal and |return|. When - the following code is executed, |buffer[(first+1)..(last-1)]| - may contain the material inserted by the user; otherwise - another prompt will be given. In order to understand this - part of the program fully, you need to be familiar with - \TeX's input stacks. - - We enter a new syntactic level for terminal input: - - */ - begin_file_reading(); - /*tex - Now |state=mid_line|, so an initial blank space will count as - a blank. - */ - if (last > first + 1) { - iloc = first + 1; - buffer[first] = ' '; - } else { - prompt_input("insert>"); - iloc = first; - } - first = last; - /*tex No |end_line_char| ends this line. */ - ilimit = last - 1; - return; - break; - case 'Q': - case 'R': - case 'S': - /*tex - - Change the interaction level and |return|. Here the author of - \TeX\ apologizes for making use of the numerical relation - between |"Q"|, |"R"|, |"S"|, and the desired interaction - settings |batch_mode|, |nonstop_mode|, |scroll_mode|. - - */ - error_count = 0; - interaction = batch_mode + c - 'Q'; - tprint("OK, entering "); - switch (c) { - case 'Q': - tprint_esc("batchmode"); - decr(selector); - break; - case 'R': - tprint_esc("nonstopmode"); - break; - case 'S': - tprint_esc("scrollmode"); - break; - } - tprint("..."); - print_ln(); - update_terminal(); - return; - break; - case 'X': - interaction = scroll_mode; - jump_out(); - break; - default: - break; - } - if (!use_err_help) { - /* Print the menu of available options */ - tprint("Type <return> to proceed, S to scroll future error messages,"); - tprint_nl("R to run without stopping, Q to run quietly,"); - tprint_nl("I to insert something, "); - if (base_ptr > 0) - tprint("E to edit your file,"); - if (deletions_allowed) - tprint_nl("1 or ... or 9 to ignore the next 1 to 9 tokens of input,"); - tprint_nl("H for help, X to quit."); - } - use_err_help = false; - } - - } - incr(error_count); - if (error_count == 100) { - tprint_nl("(That makes 100 errors; please try again.)"); - history = fatal_error_stop; - jump_out(); - } - /*tex Put help message on the transcript file. */ - if (interaction > batch_mode) { - /*tex Avoid terminal output: */ - decr(selector); - } - if (use_err_help) { - print_ln(); - give_err_help(); - } else { - int i1 = 0; - while (help_line[i1] != NULL) - tprint_nl(help_line[i1++]); - } - print_ln(); - if (interaction > batch_mode) { - /*tex Re-enable terminal output: */ - incr(selector); - } - print_ln(); -} - -/*tex - -A dozen or so error messages end with a parenthesized integer, so we save a teeny -bit of program space by declaring the following procedure: - -*/ - -void int_error(int n) -{ - tprint(" ("); - print_int(n); - print_char(')'); - error(); -} - -/*tex - -In anomalous cases, the print selector might be in an unknown state; the -following subroutine is called to fix things just enough to keep running a bit -longer. - -*/ - -void normalize_selector(void) -{ - if (log_opened_global) - selector = term_and_log; - else - selector = term_only; - if (job_name == 0) - open_log_file(); - if (interaction == batch_mode) - decr(selector); -} - -/*tex - -The following procedure prints \TeX's last words before dying. - -*/ - -void succumb(void) -{ - if (interaction == error_stop_mode) { - /*tex No more interaction: */ - interaction = scroll_mode; - } - if (log_opened_global) { - error(); - } - history = fatal_error_stop; - /*tex Irrecoverable error: */ - jump_out(); -} - -/*tex - -This prints |s|, and that's it. - -*/ - -void fatal_error(const char *s) -{ - normalize_selector(); - print_err("Emergency stop"); - help1(s); - succumb(); -} - -/*tex - -Here is the most dreaded error message. We stop due to finiteness. - -*/ - -void overflow(const char *s, unsigned int n) -{ - normalize_selector(); - print_err("TeX capacity exceeded, sorry ["); - tprint(s); - print_char('='); - print_int((int) n); - print_char(']'); - if (varmem == NULL) { - print_err("Sorry, I ran out of memory."); - print_ln(); - exit(EXIT_FAILURE); - } - help2( - "If you really absolutely need more capacity,", - "you can ask a wizard to enlarge me." - ); - succumb(); -} - -/*tex - -The program might sometime run completely amok, at which point there is no choice -but to stop. If no previous error has been detected, that's bad news; a message -is printed that is really intended for the \TeX\ maintenance person instead of -the user (unless the user has been particularly diabolical). The index entries -for `this can't happen' may help to pinpoint the problem. @^dry rot@> - -*/ - -void confusion(const char *s) -{ /* consistency check violated; |s| tells where */ - normalize_selector(); - if (history < error_message_issued) { - print_err("This can't happen ("); - tprint(s); - print_char(')'); - help1( - "I'm broken. Please show this to someone who can fix" - ); - } else { - print_err("I can't go on meeting you like this"); - help2( - "One of your faux pas seems to have wounded me deeply...", - "in fact, I'm barely conscious. Please fix it and try again." - ); - } - succumb(); -} - -/*tex - -Users occasionally want to interrupt \TeX\ while it's running. If the runtime -system allows this, one can implement a routine that sets the global variable -|interrupt| to some nonzero value when such an interrupt is signalled. Otherwise -there is probably at least a way to make |interrupt| nonzero using the debugger. -@^system dependencies@> @^debugging@> - -*/ - -void check_interrupt(void) -{ - if (interrupt != 0) - pause_for_instructions(); -} - -/*tex - -When an interrupt has been detected, the program goes into its highest -interaction level and lets the user have nearly the full flexibility of the -|error| routine. \TeX\ checks for interrupts only at times when it is safe to do -this. - -*/ - -void pause_for_instructions(void) -{ - if (OK_to_interrupt) { - interaction = error_stop_mode; - if ((selector == log_only) || (selector == no_print)) - incr(selector); - print_err("Interruption"); - help3( - "You rang?", - "Try to insert some instructions for me (e.g.,`I\\showlists'),", - "unless you just want to quit by typing `X'." - ); - deletions_allowed = false; - error(); - deletions_allowed = true; - interrupt = 0; - } -} - -void tex_error(const char *msg, const char **hlp) -{ - print_err(msg); - if (hlp != NULL) { - int i; - for (i = 0; (hlp[i] != NULL && i <= 5); i++) { - help_line[i] = hlp[i]; - } - help_line[i] = NULL; - } else { - help_line[0] = NULL; - } - error(); -} - -/*tex - -The |back_error| routine is used when we want to replace an offending token just -before issuing an error message. This routine, like |back_input|, requires that -|cur_tok| has been set. We disable interrupts during the call of |back_input| so -that the help message won't be lost. - -*/ - -void back_error(void) -{ - OK_to_interrupt = false; - back_input(); - OK_to_interrupt = true; - error(); -} - -/*tex - - Back up one inserted token and call |error|. -*/ - -void ins_error(void) -{ - OK_to_interrupt = false; - back_input(); - token_type = inserted; - OK_to_interrupt = true; - error(); -} - -/*tex - -When \TeX\ wants to typeset a character that doesn't exist, the character node is -not created; thus the output routine can assume that characters exist when it -sees them. The following procedure prints a warning message unless the user has -suppressed it. -If |tracing_lost_chars_par| (i.e. \.{\\tracinglostchar}) is greater than 2, -it's considered as an error. - -*/ - -void char_warning(internal_font_number f, int c) -{ - /*tex saved value of |tracing_online| */ - int old_setting; - /* index to current digit; we assume that $0\L n<16^{22}$ */ - int k; - if (tracing_lost_chars_par > 0) { - old_setting = tracing_online_par; - if (tracing_lost_chars_par > 1) - tracing_online_par = 1; - begin_diagnostic(); - tprint_nl("Missing character: There is no "); - print(c); - tprint(" (U+"); - k = 0; - if (c < 16) - print_char('0'); - if (c < 256) - print_char('0'); - if (c < 4096) - print_char('0'); - do { - dig[k] = c % 16; - c = c / 16; - incr(k); - } while (c != 0); - print_the_digs((eight_bits) k); - tprint(") in font "); - print_font_name(f); - print_char('!'); - end_diagnostic(false); - tracing_online_par = old_setting; - } - if (tracing_lost_chars_par > 2) { - error(); - } -} - -void wrapup_backend(void) { - ensure_output_state(static_pdf, ST_OMODE_FIX); - if (output_mode_used == OMODE_NONE) { - print_err(" ==> Fatal error occurred, no FMT file produced!"); - } else { - backend_out_control[backend_control_finish_file](static_pdf,history == fatal_error_stop); - } -} - -void normal_error(const char *t, const char *p) -{ - normalize_selector(); - if (interaction == error_stop_mode) { - wake_up_terminal(); - } - if (filelineerrorstylep) { - print_file_line(); - } else { - tprint_nl("! "); - } - tprint("error: "); - if (cur_file_name) { - tprint(" (file "); - tprint(cur_file_name); - tprint(")"); - } - if (t != NULL) { - tprint(" ("); - tprint(t); - tprint(")"); - } - tprint(": "); - if (p != NULL) - tprint(p); - history = fatal_error_stop; - wrapup_backend(); - exit(EXIT_FAILURE); -} - -void normal_warning(const char *t, const char *p) -{ - int report_id ; - if (strcmp(t,"lua") == 0) { - int saved_new_line_char; - saved_new_line_char = new_line_char_par; - new_line_char_par = 10; - report_id = callback_defined(show_lua_error_hook_callback); - if (report_id == 0) { - if (p != NULL) - tprint(p); - help2( - "The lua interpreter ran into a problem, so the", - "remainder of this lua chunk will be ignored." - ); - } else { - (void) run_callback(report_id, "->"); - } - error(); - new_line_char_par = saved_new_line_char; - } else { - report_id = callback_defined(show_warning_message_callback); - if (report_id > 0) { - /*tex Free the last ones, */ - xfree(last_warning_str); - xfree(last_warning_tag); - last_warning_str = (string) xmalloc(strlen(p) + 1); - last_warning_tag = (string) xmalloc(strlen(t) + 1); - strcpy(last_warning_str,p); - strcpy(last_warning_tag,t); - run_callback(report_id, "->"); - } else { - print_ln(); - tprint("warning "); - if (cur_file_name) { - tprint(" (file "); - tprint(cur_file_name); - tprint(")"); - } - if (t != NULL) { - tprint(" ("); - tprint(t); - tprint(")"); - } - tprint(": "); - if (p != NULL) - tprint(p); - print_ln(); - } - if (history == spotless) - history = warning_issued; - } -} - -static char print_buf[PRINTF_BUF_SIZE]; - -__attribute__ ((format(printf, 2,3))) -void formatted_error(const char *t, const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - vsnprintf(print_buf, PRINTF_BUF_SIZE, fmt, args); - normal_error(t,print_buf); - va_end(args); -} - -__attribute__ ((format(printf, 2,3))) -void formatted_warning(const char *t, const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - vsnprintf(print_buf, PRINTF_BUF_SIZE, fmt, args); - normal_warning(t,print_buf); - va_end(args); -} diff --git a/Build/source/texk/web2c/luatexdir/tex/errors.h b/Build/source/texk/web2c/luatexdir/tex/errors.h deleted file mode 100644 index 39fdf6b46e2..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/errors.h +++ /dev/null @@ -1,116 +0,0 @@ -/* errors.h - - Copyright 2009 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ - - -#ifndef ERRORS_H -# define ERRORS_H - -/* -The global variable |interaction| has four settings, representing increasing -amounts of user interaction: -*/ - -typedef enum { - batch_mode = 0, /* omits all stops and omits terminal output */ - nonstop_mode = 1, /* omits all stops */ - scroll_mode = 2, /* omits error stops */ - error_stop_mode = 3, /* stops at every opportunity to interact */ - unspecified_mode = 4, /* extra value for command-line switch */ -} interaction_settings; - -extern int interaction; /* current level of interaction */ -extern int interactionoption; /* set from command line */ - -extern int defaultexitcode; /* the exit code can be overloaded */ - -extern void initialize_errors(void); - -extern char *last_error; -extern char *last_lua_error; -extern char *last_warning_tag; -extern char *last_warning_str; -extern char *last_error_context; - -extern void set_last_error_context(void); - -extern void print_err(const char *s); - -extern void fixup_selector(boolean log_opened); - -extern boolean deletions_allowed; -extern boolean set_box_allowed; -extern int history; -extern int error_count; -extern int interrupt; -extern boolean OK_to_interrupt; - -typedef enum { - spotless = 0, /* |history| value when nothing has been amiss yet */ - warning_issued = 1, /* |history| value when |begin_diagnostic| has been called */ - error_message_issued = 2, /* |history| value when |error| has been called */ - fatal_error_stop = 3, /* |history| value when termination was premature */ -} error_states; - -extern const char *help_line[7]; /* helps for the next |error| */ -extern boolean use_err_help; /* should the |err_help| list be shown? */ - -/* these macros are just temporary, until everything is in C */ - -# define hlp1(A) help_line[0]=A -# define hlp2(A,B) help_line[1]=A; hlp1(B) -# define hlp3(A,B,C) help_line[2]=A; hlp2(B,C) -# define hlp4(A,B,C,D) help_line[3]=A; hlp3(B,C,D) -# define hlp5(A,B,C,D,E) help_line[4]=A; hlp4(B,C,D,E) -# define hlp6(A,B,C,D,E,F) help_line[5]=A; hlp5(B,C,D,E,F) - -# define help0() help_line[0]=NULL /* sometimes there might be no help */ -# define help1(A) do { help_line[1]=NULL; hlp1(A); } while (0) -# define help2(A,B) do { help_line[2]=NULL; hlp2(B,A); } while (0) -# define help3(A,B,C) do { help_line[3]=NULL; hlp3(C,B,A); } while (0) -# define help4(A,B,C,D) do { help_line[4]=NULL; hlp4(D,C,B,A); } while (0) -# define help5(A,B,C,D,E) do { help_line[5]=NULL; hlp5(E,D,C,B,A); } while (0) -# define help6(A,B,C,D,E,F) do { help_line[6]=NULL; hlp6(F,E,D,C,B,A); } while (0) - -extern void do_final_end(void); -extern void jump_out(void); -extern void error(void); -extern void int_error(int n); -extern void normalize_selector(void); -extern void succumb(void); -extern void fatal_error(const char *s); -extern void overflow(const char *s, unsigned int n); -extern void confusion(const char *s); -extern void check_interrupt(void); -extern void pause_for_instructions(void); - -extern void tex_error(const char *msg, const char **hlp); -extern void normal_error(const char *t, const char *p); -extern void normal_warning(const char *t, const char *p); -extern void formatted_error(const char *t, const char *fmt, ...); -extern void formatted_warning(const char *t, const char *fmt, ...); - -extern void back_error(void); -extern void ins_error(void); -extern void flush_err(void); - -extern void char_warning(internal_font_number f, int c); - -extern void wrapup_backend(void); - -#endif diff --git a/Build/source/texk/web2c/luatexdir/tex/expand.c b/Build/source/texk/web2c/luatexdir/tex/expand.c deleted file mode 100644 index e85c8f3bdb6..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/expand.c +++ /dev/null @@ -1,967 +0,0 @@ -/* - -Copyright 2009-2010 Taco Hoekwater <taco@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your -option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU General Public License along -with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" - -/*tex - - Only a dozen or so command codes |>max_command| can possibly be returned by - |get_next|; in increasing order, they are |undefined_cs|, |expand_after|, - |no_expand|, |input|, |if_test|, |fi_or_else|, |cs_name|, |convert|, |the|, - |top_bot_mark|, |call|, |long_call|, |outer_call|, |long_outer_call|, and - |end_template|. - - Sometimes, recursive calls to the following |expand| routine may cause - exhaustion of the run-time calling stack, resulting in forced execution stops - by the operating system. To diminish the chance of this happening, a counter - is used to keep track of the recursion depth, in conjunction with a constant - called |expand_depth|. - - Note that this does not catch all possible infinite recursion loops, just the - ones that exhaust the application calling stack. The actual maximum value of - |expand_depth| is outside of our control, but the initial setting of |100| - should be enough to prevent problems. - -*/ - -static int expand_depth_count = 0; - -/*tex - - The |expand| subroutine is used when |cur_cmd>max_command|. It removes a - ``call'' or a conditional or one of the other special operations just listed. - It follows that |expand| might invoke itself recursively. In all cases, - |expand| destroys the current token, but it sets things up so that the next - |get_next| will deliver the appropriate next token. The value of |cur_tok| - need not be known when |expand| is called. - - Since several of the basic scanning routines communicate via global - variables, their values are saved as local variables of |expand| so that - recursive calls don't invalidate them. - -*/ - -int is_in_csname = 0; - -void expand(void) -{ - /*tex token that is being ``expanded after'' */ - halfword t; - /*tex for list manipulation */ - halfword p; - /*tex for a local token list pointer */ - halfword cur_ptr; - /*tex to save the global quantity |cur_val| */ - int cv_backup; - /*tex to save |cur_val_level|, etc. */ - int cvl_backup, radix_backup, co_backup; - /*tex to save |link(backup_head)| */ - halfword backup_backup; - /*tex temporary storage of |scanner_status| */ - int save_scanner_status; - incr(expand_depth_count); - if (expand_depth_count >= expand_depth) - overflow("expansion depth", (unsigned) expand_depth); - cv_backup = cur_val; - cvl_backup = cur_val_level; - radix_backup = radix; - co_backup = cur_order; - backup_backup = token_link(backup_head); - RESWITCH: - if (cur_cmd < call_cmd) { - /*tex Expand a nonmacro. */ - if (tracing_commands_par > 1) - show_cur_cmd_chr(); - switch (cur_cmd) { - case top_bot_mark_cmd: - /*tex Insert the appropriate mark text into the scanner. */ - t = cur_chr % marks_code; - if (cur_chr >= marks_code) - scan_mark_num(); - else - cur_val = 0; - switch (t) { - case first_mark_code: - cur_ptr = first_mark(cur_val); - break; - case bot_mark_code: - cur_ptr = bot_mark(cur_val); - break; - case split_first_mark_code: - cur_ptr = split_first_mark(cur_val); - break; - case split_bot_mark_code: - cur_ptr = split_bot_mark(cur_val); - break; - default: - cur_ptr = top_mark(cur_val); - break; - } - if (cur_ptr != null) - begin_token_list(cur_ptr, mark_text); - break; - case expand_after_cmd: - if (cur_chr == 0) { - /*tex - - Expand the token after the next token. It takes only a - little shuffling to do what \TeX\ calls - \.{\\expandafter}. - - */ - get_token(); - t = cur_tok; - get_token(); - if (cur_cmd > max_command_cmd) - expand(); - else - back_input(); - cur_tok = t; - back_input(); - } else { - /*tex - - Negate a boolean conditional and |goto reswitch|. The - result of a boolean condition is reversed when the - conditional is preceded by \.{\\unless}. - - */ - get_token(); - if ((cur_cmd == if_test_cmd) && (cur_chr != if_case_code)) { - cur_chr = cur_chr + unless_code; - goto RESWITCH; - } - print_err("You can't use `\\unless' before `"); - print_cmd_chr((quarterword) cur_cmd, cur_chr); - print_char('\''); - help1("Continue, and I'll forget that it ever happened."); - back_error(); - } - break; - case no_expand_cmd: - if (cur_chr == 0) { - /*tex - - Suppress expansion of the next token. The implementation - of \.{\\noexpand} is a bit trickier, because it is - necessary to insert a special `|dont_expand|' marker into - \TeX's reading mechanism. This special marker is - processed by |get_next|, but it does not slow down the - inner loop. - - Since \.{\\outer} macros might arise here, we must also - clear the |scanner_status| temporarily. - - */ - save_scanner_status = scanner_status; - scanner_status = normal; - get_token(); - scanner_status = save_scanner_status; - t = cur_tok; - back_input(); - /*tex Now |start| and |loc| point to the backed-up token |t|. */ - if (t >= cs_token_flag) { - p = get_avail(); - set_token_info(p, cs_token_flag + frozen_dont_expand); - set_token_link(p, iloc); - istart = p; - iloc = p; - } - - } else { - /*tex - - The \.{\\primitive} handling. If the primitive meaning of - the next token is an expandable command, it suffices to - replace the current token with the primitive one and - restart |expand|. - - Otherwise, the token we just read has to be pushed back, - as well as a token matching the internal form of - \.{\\primitive}, that is sneaked in as an alternate form - of |ignore_spaces|. - - An implementation problem surfaces: There really is no - |cur_cs| attached to the inserted primitive command, so - it is safer to set |cur_cs| to zero. |cur_tok| has a - similar problem. And for the non-expanded branch, simply - pushing back a token that matches the correct internal - command does not work, because that approach would not - survive roundtripping to a temporary file or even a token - list. - - It would be smart to create |frozen_| versions of all the - primitives. Then, this problem would not happen, at the - expense of a few hundred extra control sequences. - - */ - save_scanner_status = scanner_status; - scanner_status = normal; - get_token(); - scanner_status = save_scanner_status; - cur_cs = prim_lookup(cs_text(cur_cs)); - if (cur_cs != undefined_primitive) { - t = get_prim_eq_type(cur_cs); - if (t > max_command_cmd) { - cur_cmd = t; - cur_chr = get_prim_equiv(cur_cs); - cur_tok = token_val(cur_cmd, cur_chr); - cur_cs = 0; - goto RESWITCH; - } else { - back_input(); - /*tex Now |loc| and |start| point to a one-item list. */ - p = get_avail(); - set_token_info(p, cs_token_flag + frozen_primitive); - set_token_link(p, iloc); - iloc = p; - istart = p; - } - } else if (suppress_primitive_error_par == 0) { - print_err("Missing primitive name"); - help2( - "The control sequence marked <to be read again> does not", - "represent any known primitive." - ); - back_error(); - } - } - break; - case cs_name_cmd: - /*tex Manufacture a control sequence name. */ - if (cur_chr == 0) { - manufacture_csname(0); - } else if (cur_chr == 1) { - inject_last_tested_cs(); - } else { - manufacture_csname(1); - } - break; - case convert_cmd: - conv_toks(); - break; - case the_cmd: - ins_the_toks(); - break; - case if_test_cmd: - /*tex An experiment. */ - if (cur_chr == if_condition_code) { - break; - } - /*tex End of experiment. */ - conditional(); - break; - case fi_or_else_cmd: - /*tex - - Terminate the current conditional and skip to \.{\\fi} The - processing of conditionals is complete except for the - following code, which is actually part of |expand|. It comes - into play when \.{\\or}, \.{\\else}, or \.{\\fi} is scanned. - - */ - if (tracing_ifs_par > 0) - if (tracing_commands_par <= 1) - show_cur_cmd_chr(); - if (cur_chr > if_limit) { - if (if_limit == if_code) { - /*tex Condition is not yet evaluated. */ - insert_relax(); - } else { - print_err("Extra "); - print_cmd_chr(fi_or_else_cmd, cur_chr); - help1("I'm ignoring this; it doesn't match any \\if."); - error(); - } - } else { - while (cur_chr != fi_code) { - /*tex Skip to \.{\\fi}. */ - pass_text(); - } - pop_condition_stack(); - } - break; - case input_cmd: - /*tex Initiate or terminate input from a file */ - if (cur_chr == 1) - force_eof = true; - else if (cur_chr == 2) - pseudo_start(); - else if (cur_chr == 3) { - pseudo_start(); - iname = 19; - } else if (name_in_progress) - insert_relax(); - else - start_input(); - break; - case lua_expandable_call_cmd: - if (cur_chr <= 0) { - normal_error("luacall", "invalid number"); - } else { - str_number u = save_cur_string(); - luacstrings = 0; - luafunctioncall(cur_chr); - restore_cur_string(u); - if (luacstrings > 0) - lua_string_start(); - } - break; - case lua_local_call_cmd: - if (cur_chr <= 0) { - normal_error("luacall", "invalid number"); - } else { - str_number u = save_cur_string(); - luacstrings = 0; - lua_rawgeti(Luas, LUA_REGISTRYINDEX, cur_chr); - lua_call(Luas,0,0); - restore_cur_string(u); - if (luacstrings > 0) - lua_string_start(); - } - break; - case variable_cmd: - do_variable(); - break; - case feedback_cmd: - do_feedback(); - break; - default: - /*tex Complain about an undefined macro */ - print_err("Undefined control sequence"); - help5( - "The control sequence at the end of the top line", - "of your error message was never \\def'ed. If you have", - "misspelled it (e.g., `\\hobx'), type `I' and the correct", - "spelling (e.g., `I\\hbox'). Otherwise just continue,", - "and I'll forget about whatever was undefined." - ); - error(); - break; - } - } else if (cur_cmd < end_template_cmd) { - macro_call(); - } else { - /*tex - - Insert a token containing |frozen_endv|. An |end_template| command is - effectively changed to an |endv| command by the following code. (The - reason for this is discussed below; the |frozen_end_template| at the - end of the template has passed the |check_outer_validity| test, so - its mission of error detection has been accomplished.) - - */ - cur_tok = cs_token_flag + frozen_endv; - back_input(); - } - cur_val = cv_backup; - cur_val_level = cvl_backup; - radix = radix_backup; - cur_order = co_backup; - set_token_link(backup_head, backup_backup); - decr(expand_depth_count); -} - -void complain_missing_csname(void) -{ - print_err("Missing \\endcsname inserted"); - help2( - "The control sequence marked <to be read again> should", - "not appear between \\csname and \\endcsname." - ); - back_error(); -} - -void manufacture_csname(boolean use) -{ - halfword p, q, r; - lstring *ss; - r = get_avail(); - p = r; - is_in_csname += 1; - do { - get_x_token(); - if (cur_cs == 0) - store_new_token(cur_tok); - } while (cur_cs == 0); - if (cur_cmd != end_cs_name_cmd) { - /*tex Complain about missing \.{\\endcsname}. */ - complain_missing_csname(); - } - /*tex Look up the characters of list |r| in the hash table, and set |cur_cs|. */ - ss = tokenlist_to_lstring(r, true); - is_in_csname -= 1; - if (use) { - if (ss->l > 0) { - cur_cs = string_lookup((char *) ss->s, ss->l); - } else { - cur_cs = null_cs; - } - last_cs_name = cur_cs ; - free_lstring(ss); - flush_list(r); - if (cur_cs == null_cs) { - /*tex skip */ - } else if (eq_type(cur_cs) == undefined_cs_cmd) { - /*tex skip */ - } else { - cur_tok = cur_cs + cs_token_flag; - back_input(); - } - } else { - if (ss->l > 0) { - no_new_control_sequence = false; - cur_cs = string_lookup((char *) ss->s, ss->l); - no_new_control_sequence = true; - } else { - /*tex the list is empty */ - cur_cs = null_cs; - } - last_cs_name = cur_cs ; - free_lstring(ss); - flush_list(r); - if (eq_type(cur_cs) == undefined_cs_cmd) { - /*tex The |save_stack| might change! */ - eq_define(cur_cs, relax_cmd, too_big_char); - }; - /*tex The control sequence will now match \.{\\relax} */ - cur_tok = cur_cs + cs_token_flag; - back_input(); - } -} - -void inject_last_tested_cs(void) -{ - if (last_cs_name != null_cs) { - cur_cs = last_cs_name; - cur_tok = last_cs_name + cs_token_flag; - back_input(); - } -} - -/*tex - - Sometimes the expansion looks too far ahead, so we want to insert a harmless - \.{\\relax} into the user's input. - -*/ - -void insert_relax(void) -{ - cur_tok = cs_token_flag + cur_cs; - back_input(); - cur_tok = cs_token_flag + frozen_relax; - back_input(); - token_type = inserted; -} - - -/*tex - - Here is a recursive procedure that is \TeX's usual way to get the next token - of input. It has been slightly optimized to take account of common cases. - -*/ - -void get_x_token(void) -{ - /*tex This code sets |cur_cmd|, |cur_chr|, |cur_tok|, and expands macros. */ - RESTART: - get_next(); - if (cur_cmd <= max_command_cmd) - goto DONE; - if (cur_cmd >= call_cmd) { - if (cur_cmd < end_template_cmd) { - macro_call(); - } else { - cur_cs = frozen_endv; - cur_cmd = endv_cmd; - /*tex Now |cur_chr=null_list|. */ - goto DONE; - } - } else { - expand(); - } - goto RESTART; - DONE: - if (cur_cs == 0) - cur_tok = token_val(cur_cmd, cur_chr); - else - cur_tok = cs_token_flag + cur_cs; -} - -/*tex - - The |get_x_token| procedure is equivalent to two consecutive procedure calls: - |get_next; x_token|. It's |get_x_token| without the initial |get_next|. - -*/ - -void x_token(void) -{ - while (cur_cmd > max_command_cmd) { - expand(); - get_next(); - } - if (cur_cs == 0) - cur_tok = token_val(cur_cmd, cur_chr); - else - cur_tok = cs_token_flag + cur_cs; -} - -/*tex - - A control sequence that has been \.{\\def}'ed by the user is expanded by - \TeX's |macro_call| procedure. - - Before we get into the details of |macro_call|, however, let's consider the - treatment of primitives like \.{\\topmark}, since they are essentially macros - without parameters. The token lists for such marks are kept in five global - arrays of pointers; we refer to the individual entries of these arrays by - symbolic macros |top_mark|, etc. The value of |top_mark(x)|, etc. is either - |null| or a pointer to the reference count of a token list. - - The variable |biggest_used_mark| is an aid to try and keep the code somehwat - efficient without too much extra work: it registers the highest mark class - ever instantiated by the user, so the loops in |fire_up| and |vsplit| do not - have to traverse the full range |0..biggest_mark|. - -*/ - -halfword top_marks_array[(biggest_mark + 1)]; -halfword first_marks_array[(biggest_mark + 1)]; -halfword bot_marks_array[(biggest_mark + 1)]; -halfword split_first_marks_array[(biggest_mark + 1)]; -halfword split_bot_marks_array[(biggest_mark + 1)]; -halfword biggest_used_mark; - -void initialize_marks(void) -{ - int i; - biggest_used_mark = 0; - for (i = 0; i <= biggest_mark; i++) { - top_mark(i) = null; - first_mark(i) = null; - bot_mark(i) = null; - split_first_mark(i) = null; - split_bot_mark(i) = null; - } -} - -/*tex - - Now let's consider |macro_call| itself, which is invoked when \TeX\ is - scanning a control sequence whose |cur_cmd| is either |call|, |long_call|, - |outer_call|, or |long_outer_call|. The control sequence definition appears - in the token list whose reference count is in location |cur_chr| of |mem|. - - The global variable |long_state| will be set to |call| or to |long_call|, - depending on whether or not the control sequence disallows \.{\\par} in its - parameters. The |get_next| routine will set |long_state| to |outer_call| and - emit \.{\\par}, if a file ends or if an \.{\\outer} control sequence occurs - in the midst of an argument. - -*/ - -/*tex Governs the acceptance of \.{\\par}: */ - -int long_state; - -/*tex - - The parameters, if any, must be scanned before the macro is expanded. - Parameters are token lists without reference counts. They are placed on an - auxiliary stack called |pstack| while they are being scanned, since the - |param_stack| may be losing entries during the matching process. (Note that - |param_stack| can't be gaining entries, since |macro_call| is the only - routine that puts anything onto |param_stack|, and it is not recursive.) - -*/ - -/*tex The arguments supplied to a macro: */ - -halfword pstack[9]; - -/*tex - - After parameter scanning is complete, the parameters are moved to the - |param_stack|. Then the macro body is fed to the scanner; in other words, - |macro_call| places the defined text of the control sequence at the top of\/ - \TeX's input stack, so that |get_next| will proceed to read it next. - - The global variable |cur_cs| contains the |eqtb| address of the control - sequence being expanded, when |macro_call| begins. If this control sequence - has not been declared \.{\\long}, i.e., if its command code in the |eq_type| - field is not |long_call| or |long_outer_call|, its parameters are not allowed - to contain the control sequence \.{\\par}. If an illegal \.{\\par} appears, - the macro call is aborted, and the \.{\\par} will be rescanned. - -*/ - -/*tex This invokes a user-defined control sequence. */ - -void macro_call(void) -{ - /*tex current node in the macro's token list */ - halfword r; - /*tex current node in parameter token list being built */ - halfword p = null; - /*tex new node being put into the token list */ - halfword q; - /*tex backup pointer for parameter matching */ - halfword s; - /*tex cycle pointer for backup recovery */ - halfword t; - /*tex auxiliary pointers for backup recovery */ - halfword u, v; - /*tex one step before the last |right_brace| token */ - halfword rbrace_ptr = null; - /*tex the number of parameters scanned */ - int n = 0; - /*tex unmatched left braces in current parameter */ - halfword unbalance; - /*tex the number of tokens or groups (usually) */ - halfword m = 0; - /*tex start of the token list */ - halfword ref_count; - /*tex |scanner_status| upon entry */ - int save_scanner_status = scanner_status; - /*tex |warning_index| upon entry */ - halfword save_warning_index = warning_index; - /*tex character used in parameter */ - int match_chr = 0; - warning_index = cur_cs; - ref_count = cur_chr; - r = token_link(ref_count); - if (tracing_macros_par > 0) { - /*tex Show the text of the macro being expanded. */ - begin_diagnostic(); - print_input_level(); - // print_ln(); - print_cs(warning_index); - token_show(ref_count); - end_diagnostic(false); - } - if (token_info(r) == protected_token) - r = token_link(r); - if (token_info(r) != end_match_token) { - /*tex - - Scan the parameters and make |link(r)| point to the macro body; but - |return| if an illegal \.{\\par} is detected. - - At this point, the reader will find it advisable to review the - explanation of token list format that was presented earlier, since - many aspects of that format are of importance chiefly in the - |macro_call| routine. - - The token list might begin with a string of compulsory tokens before - the first |match| or |end_match|. In that case the macro name is - supposed to be followed by those tokens; the following program will - set |s=null| to represent this restriction. Otherwise |s| will be set - to the first token of a string that will delimit the next parameter. - - */ - scanner_status = matching; - unbalance = 0; - long_state = eq_type(cur_cs); - if (long_state >= outer_call_cmd) - long_state = long_state - 2; - do { - set_token_link(temp_token_head, null); - if ((token_info(r) >= end_match_token) - || (token_info(r) < match_token)) { - s = null; - } else { - match_chr = token_info(r) - match_token; - s = token_link(r); - r = s; - p = temp_token_head; - m = 0; - } - /*tex - - Scan a parameter until its delimiter string has been found; or, - if |s=null|, simply scan the delimiter string. - - If |info(r)| is a |match| or |end_match| command, it cannot be - equal to any token found by |get_token|. Therefore an undelimited - parameter---i.e., a |match| that is immediately followed by - |match| or |end_match|---will always fail the test - `|cur_tok=info(r)|' in the following algorithm. - - */ - CONTINUE: - /*tex Set |cur_tok| to the next token of input: */ - get_token(); - if (cur_tok == token_info(r)) { - /*tex - - Advance |r|; |goto found| if the parameter delimiter has been - fully matched, otherwise |goto continue|. - - A slightly subtle point arises here: When the parameter - delimiter ends with `\.{\#\{}', the token list will have a - left brace both before and after the |end_match|\kern-.4pt. - Only one of these should affect the |align_state|, but both - will be scanned, so we must make a correction. - - */ - r = token_link(r); - if ((token_info(r) >= match_token) - && (token_info(r) <= end_match_token)) { - if (cur_tok < left_brace_limit) - decr(align_state); - goto FOUND; - } else { - goto CONTINUE; - } - - } - /*tex - - Contribute the recently matched tokens to the current parameter, - and |goto continue| if a partial match is still in effect; but - abort if |s=null|. - - When the following code becomes active, we have matched tokens - from |s| to the predecessor of |r|, and we have found that - |cur_tok<>info(r)|. An interesting situation now presents itself: - If the parameter is to be delimited by a string such as `\.{ab}', - and if we have scanned `\.{aa}', we want to contribute one `\.a' - to the current parameter and resume looking for a `\.b'. The - program must account for such partial matches and for others that - can be quite complex. But most of the time we have |s=r| and - nothing needs to be done. - - Incidentally, it is possible for \.{\\par} tokens to sneak in to - certain parameters of non-\.{\\long} macros. For example, - consider a case like `\.{\\def\\a\#1\\par!\{...\}}' where the - first \.{\\par} is not followed by an exclamation point. In such - situations it does not seem appropriate to prohibit the - \.{\\par}, so \TeX\ keeps quiet about this bending of the rules. - - */ - if (s != r) { - if (s == null) { - /*tex Report an improper use of the macro and abort. */ - print_err("Use of "); - sprint_cs(warning_index); - tprint(" doesn't match its definition"); - help4( - "If you say, e.g., `\\def\\a1{...}', then you must always", - "put `1' after `\\a', since control sequence names are", - "made up of letters only. The macro here has not been", - "followed by the required stuff, so I'm ignoring it." - ); - error(); - goto EXIT; - - } else { - t = s; - do { - store_new_token(token_info(t)); - incr(m); - u = token_link(t); - v = s; - while (1) { - if (u == r) { - if (cur_tok != token_info(v)) { - goto DONE; - } else { - r = token_link(v); - goto CONTINUE; - } - } - if (token_info(u) != token_info(v)) - goto DONE; - u = token_link(u); - v = token_link(v); - } - DONE: - t = token_link(t); - } while (t != r); - r = s; - /*tex At this point, no tokens are recently matched. */ - } - } - if (cur_tok == par_token) - if (long_state != long_call_cmd) - if (!suppress_long_error_par) { - goto RUNAWAY; - } - if (cur_tok < right_brace_limit) { - if (cur_tok < left_brace_limit) { - /*tex Contribute an entire group to the current parameter. */ - unbalance = 1; - while (1) { - fast_store_new_token(cur_tok); - get_token(); - if (cur_tok == par_token) { - if (long_state != long_call_cmd) { - if (!suppress_long_error_par) { - goto RUNAWAY; - - } - } - } - if (cur_tok < right_brace_limit) { - if (cur_tok < left_brace_limit) { - incr(unbalance); - } else { - decr(unbalance); - if (unbalance == 0) - break; - } - } - } - rbrace_ptr = p; - store_new_token(cur_tok); - } else { - /*tex Report an extra right brace and |goto continue|. */ - back_input(); - print_err("Argument of "); - sprint_cs(warning_index); - tprint(" has an extra }"); - help6( - "I've run across a `}' that doesn't seem to match anything.", - "For example, `\\def\\a#1{...}' and `\\a}' would produce", - "this error. If you simply proceed now, the `\\par' that", - "I've just inserted will cause me to report a runaway", - "argument that might be the root of the problem. But if", - "your `}' was spurious, just type `2' and it will go away." - ); - incr(align_state); - long_state = call_cmd; - cur_tok = par_token; - ins_error(); - goto CONTINUE; - /*tex A white lie; the \.{\\par} won't always trigger a runaway. */ - } - } else { - /*tex - - Store the current token, but |goto continue| if it is a blank - space that would become an undelimited parameter. - - */ - if (cur_tok == space_token && token_info(r) <= end_match_token && token_info(r) >= match_token) - goto CONTINUE; - store_new_token(cur_tok); - } - incr(m); - if (token_info(r) > end_match_token) - goto CONTINUE; - if (token_info(r) < match_token) - goto CONTINUE; - FOUND: - if (s != null) { - /* - - Tidy up the parameter just scanned, and tuck it away. If the - parameter consists of a single group enclosed in braces, we - must strip off the enclosing braces. That's why |rbrace_ptr| - was introduced. - - */ - if ((m == 1) && (token_info(p) < right_brace_limit) - && (p != temp_token_head)) { - set_token_link(rbrace_ptr, null); - free_avail(p); - p = token_link(temp_token_head); - pstack[n] = token_link(p); - free_avail(p); - } else { - pstack[n] = token_link(temp_token_head); - } - incr(n); - if (tracing_macros_par > 0) { - begin_diagnostic(); - print_input_level(); - // print_nl(match_chr); - print(match_chr); - print_int(n); - tprint("<-"); - show_token_list(pstack[n - 1], null, 1000); - end_diagnostic(false); - } - } - /*tex - - Now |info(r)| is a token whose command code is either |match| or - |end_match|. - - */ - } while (token_info(r) != end_match_token); - } - /*tex - - Feed the macro body and its parameters to the scanner Before we put a new - token list on the input stack, it is wise to clean off all token lists - that have recently been depleted. Then a user macro that ends with a call - to itself will not require unbounded stack space. - - */ - while ((istate == token_list) && (iloc == null) && (token_type != v_template)) { - /*tex Conserve stack space. */ - end_token_list(); - } - begin_token_list(ref_count, macro); - iname = warning_index; - iloc = token_link(r); - if (n > 0) { - if (param_ptr + n > max_param_stack) { - max_param_stack = param_ptr + n; - if (max_param_stack > param_size) - overflow("parameter stack size", (unsigned) param_size); - } - for (m = 0; m <= n - 1; m++) - param_stack[param_ptr + m] = pstack[m]; - param_ptr = param_ptr + n; - } - goto EXIT; - RUNAWAY: - /*tex - - Report a runaway argument and abort. If |long_state=outer_call|, a - runaway argument has already been reported. - - */ - if (long_state == call_cmd) { - runaway(); - print_err("Paragraph ended before "); - sprint_cs(warning_index); - tprint(" was complete"); - help3( - "I suspect you've forgotten a `}', causing me to apply this", - "control sequence to too much text. How can we recover?", - "My plan is to forget the whole thing and hope for the best." - ); - back_error(); - } - pstack[n] = token_link(temp_token_head); - align_state = align_state - unbalance; - for (m = 0; m <= n; m++) - flush_list(pstack[m]); - EXIT: - scanner_status = save_scanner_status; - warning_index = save_warning_index; -} diff --git a/Build/source/texk/web2c/luatexdir/tex/expand.h b/Build/source/texk/web2c/luatexdir/tex/expand.h deleted file mode 100644 index 18c0514e317..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/expand.h +++ /dev/null @@ -1,102 +0,0 @@ -/* expand.h - - Copyright 2009 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ - - -#ifndef EXPAND_H -# define EXPAND_H - -extern boolean is_in_csname; -extern void expand(void); -extern void complain_missing_csname(void); -extern void manufacture_csname(boolean use); -extern void inject_last_tested_cs(void); -extern void insert_relax(void); -extern void get_x_token(void); -extern void x_token(void); - -# define top_mark_code 0 /* the mark in effect at the previous page break */ -# define first_mark_code 1 /* the first mark between |top_mark| and |bot_mark| */ -# define bot_mark_code 2 /* the mark in effect at the current page break */ -# define split_first_mark_code 3 - /* the first mark found by \.{\\vsplit} */ -# define split_bot_mark_code 4 /* the last mark found by \.{\\vsplit} */ -# define marks_code 5 - -# define top_mark(A) top_marks_array[(A)] -# define first_mark(A) first_marks_array[(A)] -# define bot_mark(A) bot_marks_array[(A)] -# define split_first_mark(A) split_first_marks_array[(A)] -# define split_bot_mark(A) split_bot_marks_array[(A)] - -# define set_top_mark(A,B) top_mark(A)=(B) -# define set_first_mark(A,B) first_mark(A)=(B) -# define set_bot_mark(A,B) bot_mark(A)=(B) -# define set_split_first_mark(A,B) split_first_mark(A)=(B) -# define set_split_bot_mark(A,B) split_bot_mark(A)=(B) - -# define delete_top_mark(A) do { \ - if (top_mark(A)!=null) \ - delete_token_ref(top_mark(A)); \ - top_mark(A)=null; \ - } while (0) - -# define delete_bot_mark(A) do { \ - if (bot_mark(A)!=null) \ - delete_token_ref(bot_mark(A)); \ - bot_mark(A)=null; \ - } while (0) - -# define delete_first_mark(A) do { \ - if (first_mark(A)!=null) \ - delete_token_ref(first_mark(A)); \ - first_mark(A)=null; \ - } while (0) - -# define delete_split_first_mark(A) do { \ - if (split_first_mark(A)!=null) \ - delete_token_ref(split_first_mark(A)); \ - split_first_mark(A)=null; \ - } while (0) - -# define delete_split_bot_mark(A) do { \ - if (split_bot_mark(A)!=null) \ - delete_token_ref(split_bot_mark(A)); \ - split_bot_mark(A)=null; \ -} while (0) - -# define clear_marks_code 1 - -# define biggest_mark 65535 - -extern halfword top_marks_array[(biggest_mark + 1)]; -extern halfword first_marks_array[(biggest_mark + 1)]; -extern halfword bot_marks_array[(biggest_mark + 1)]; -extern halfword split_first_marks_array[(biggest_mark + 1)]; -extern halfword split_bot_marks_array[(biggest_mark + 1)]; -extern halfword biggest_used_mark; - - -extern void initialize_marks(void); - -extern int long_state; -extern halfword pstack[9]; -extern void macro_call(void); - - -#endif diff --git a/Build/source/texk/web2c/luatexdir/tex/extensions.c b/Build/source/texk/web2c/luatexdir/tex/extensions.c deleted file mode 100644 index 19d4e444173..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/extensions.c +++ /dev/null @@ -1,1344 +0,0 @@ -/* - -Copyright 2009-2010 Taco Hoekwater <taco@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under the terms -of the GNU General Public License as published by the Free Software Foundation; -either version 2 of the License, or (at your option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - -You should have received a copy of the GNU General Public License along with -LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" - -#define mode mode_par -#define tail tail_par -#define head head_par -#define dir_save dirs_par - -/*tex - - The program above includes a bunch of ``hooks'' that allow further - capabilities to be added without upsetting \TeX's basic structure. Most of - these hooks are concerned with ``whatsit'' nodes, which are intended to be - used for special purposes; whenever a new extension to \TeX\ involves a new - kind of whatsit node, a corresponding change needs to be made to the routines - below that deal with such nodes, but it will usually be unnecessary to make - many changes to the other parts of this program. - - In order to demonstrate how extensions can be made, we shall treat - `\.{\\write}', `\.{\\openout}', `\.{\\closeout}', `\.{\\immediate}', and - `\.{\\special}' as if they were extensions. These commands are actually - primitives of \TeX, and they should appear in all implementations of the - system; but let's try to imagine that they aren't. Then the program below - illustrates how a person could add them. - - Sometimes, of course, an extension will require changes to \TeX\ itself; no - system of hooks could be complete enough for all conceivable extensions. The - features associated with `\.{\\write}' are almost all confined to the - following paragraphs, but there are small parts of the |print_ln| and - |print_char| procedures that were introduced specifically to \.{\\write} - characters. Furthermore one of the token lists recognized by the scanner is a - |write_text|; and there are a few other miscellaneous places where we have - already provided for some aspect of \.{\\write}. The goal of a \TeX\ extender - should be to minimize alterations to the standard parts of the program, and - to avoid them completely if possible. He or she should also be quite sure - that there's no easy way to accomplish the desired goals with the standard - features that \TeX\ already has. ``Think thrice before extending,'' because - that may save a lot of work, and it will also keep incompatible extensions of - \TeX\ from proliferating. - - First let's consider the format of whatsit nodes that are used to represent - the data associated with \.{\\write} and its relatives. Recall that a whatsit - has |type=whatsit_node|, and the |subtype| is supposed to distinguish - different kinds of whatsits. Each node occupies two or more words; the exact - number is immaterial, as long as it is readily determined from the |subtype| - or other data. - - We shall introduce five |subtype| values here, corresponding to the control - sequences \.{\\openout}, \.{\\write}, \.{\\closeout}, and \.{\\special}. The - second word of I/O whatsits has a |write_stream| field that identifies the - write-stream number (0 to 15, or 16 for out-of-range and positive, or 17 for - out-of-range and negative). In the case of \.{\\write} and \.{\\special}, - there is also a field that points to the reference count of a token list that - should be sent. In the case of \.{\\openout}, we need three words and three - auxiliary subfields to hold the string numbers for name, area, and extension. - - Extensions might introduce new command codes; but it's best to use - |extension| with a modifier, whenever possible, so that |main_control| stays - the same. - - The sixteen possible \.{\\write} streams are represented by the |write_file| - array. The |j|th file is open if and only if |write_open[j]=true|. The last - two streams are special; |write_open[16]| represents a stream number greater - than 15, while |write_open[17]| represents a negative stream number, and both - of these variables are always |false|. - -*/ - -alpha_file write_file[last_file_selector+1]; -halfword write_file_mode[last_file_selector+1]; -halfword write_file_translation[last_file_selector+1]; -boolean write_open[last_file_selector+1]; - -scaled neg_wd; -scaled pos_wd; -scaled neg_ht; - -/*tex - - The variable |write_loc| just introduced is used to provide an appropriate - error message in case of ``runaway'' write texts. - -*/ - -/*tex The |eqtb| address of \.{\\write}: */ - -halfword write_loc; - -/*tex - - When an |extension| command occurs in |main_control|, in any mode, the - |do_extension| routine is called. - -*/ - -int last_saved_image_index ; -int last_saved_image_pages ; -int last_saved_box_index ; -scaledpos last_position = { 0, 0 }; - -static void do_extension_dvi(int immediate) -{ - if (scan_keyword("literal")) { - new_whatsit(special_node); - write_stream(tail) = null; - scan_toks(false, true); - write_tokens(tail) = def_ref; - } else { - tex_error("unexpected use of \\dviextension",null); - } -} - -static void do_extension_pdf(int immediate) -{ - int i; - if (scan_keyword("literal")) { - new_whatsit(pdf_literal_node); - if (scan_keyword("direct")) - set_pdf_literal_mode(tail, direct_always); - else if (scan_keyword("page")) - set_pdf_literal_mode(tail, direct_page); - else if (scan_keyword("text")) - set_pdf_literal_mode(tail, direct_text); - else if (scan_keyword("raw")) - set_pdf_literal_mode(tail, direct_raw); - else if (scan_keyword("origin")) - set_pdf_literal_mode(tail, set_origin); - else - set_pdf_literal_mode(tail, set_origin); - scan_toks(false, true); - set_pdf_literal_type(tail, normal); - set_pdf_literal_data(tail, def_ref); - } else if (scan_keyword("dest")) { - scan_pdfdest(static_pdf); - } else if (scan_keyword("annot")) { - scan_annot(static_pdf); - } else if (scan_keyword("save")) { - new_whatsit(pdf_save_node); - } else if (scan_keyword("restore")) { - new_whatsit(pdf_restore_node); - } else if (scan_keyword("linkstate")) { - new_whatsit(pdf_link_state_node); - scan_int(); - pdf_link_state(tail) = cur_val; - } else if (scan_keyword("setmatrix")) { - new_whatsit(pdf_setmatrix_node); - scan_toks(false, true); - set_pdf_setmatrix_data(tail, def_ref); - } else if (scan_keyword("obj")) { - scan_obj(static_pdf); - if (immediate) { - if (obj_data_ptr(static_pdf, pdf_last_obj) == 0) { - /*tex This object has not been initialized yet. */ - normal_error("pdf backend","\\pdfextension obj 'reserveobjnum' cannot be used with \\immediate"); - } - pdf_write_obj(static_pdf, pdf_last_obj); - } - } else if (scan_keyword("refobj")) { - scan_refobj(static_pdf); - } else if (scan_keyword("colorstack")) { - scan_int(); - if (cur_val >= colorstackused()) { - print_err("Unknown color stack number "); - print_int(cur_val); - help3( - "Allocate and initialize a color stack with \\pdfextension colorstackinit.", - "I'll use default color stack 0 here.", - "Proceed, with fingers crossed." - ); - error(); - cur_val = 0; - } - if (cur_val < 0) { - print_err("Invalid negative color stack number"); - help2( - "I'll use default color stack 0 here.", - "Proceed, with fingers crossed." - ); - error(); - cur_val = 0; - } - if (scan_keyword("set")) - i = colorstack_set; - else if (scan_keyword("push")) - i = colorstack_push; - else if (scan_keyword("pop")) - i = colorstack_pop; - else if (scan_keyword("current")) - i = colorstack_current; - else - i = -1; - if (i >= 0) { - new_whatsit(pdf_colorstack_node); - set_pdf_colorstack_stack(tail, cur_val); - set_pdf_colorstack_cmd(tail, i); - set_pdf_colorstack_data(tail, null); - if (i <= colorstack_data) { - scan_toks(false, true); - set_pdf_colorstack_data(tail, def_ref); - } - } else { - print_err("Color stack action is missing"); - help3( - "The expected actions for \\pdfextension colorstack:", - " set, push, pop, current", - "I'll ignore the color stack command." - ); - error(); - } - } else if (scan_keyword("startlink")) { - scan_startlink(static_pdf); - } else if (scan_keyword("endlink")) { - if (abs(mode) == vmode) - normal_error("pdf backend", "\\pdfextension endlink cannot be used in vertical mode"); - new_whatsit(pdf_end_link_node); - } else if (scan_keyword("startthread")) { - new_annot_whatsit(pdf_start_thread_node); - scan_thread_id(); - } else if (scan_keyword("endthread")) { - new_whatsit(pdf_end_thread_node); - } else if (scan_keyword("thread")) { - new_annot_whatsit(pdf_thread_node); - scan_thread_id(); - } else if (scan_keyword("outline")) { - scan_pdfoutline(static_pdf); - } else if (scan_keyword("glyphtounicode")) { - glyph_to_unicode(); - } else if (scan_keyword("catalog")) { - scan_pdfcatalog(static_pdf); - } else if (scan_keyword("fontattr")) { - /*tex - - The font attributes are simply initialized to zero now, this is - easier to deal with from C than an empty \TeX{} string, and surely - nobody will want to set font attr to a string containing a single - zero, as that would be nonsensical in the PDF output. - - */ - scan_font_ident(); - i = cur_val; - if (i == null_font) - normal_error("pdf backend", "invalid font identifier"); - scan_toks(false, true); - set_pdf_font_attr(i, tokens_to_string(def_ref)); - if (str_length(pdf_font_attr(i)) == 0) { - /*tex From |tokens_to_string|. */ - flush_str((str_ptr - 1)); - set_pdf_font_attr(i, 0); - } - } else if (scan_keyword("mapfile")) { - scan_toks(false, true); - pdfmapfile(def_ref); - delete_token_ref(def_ref); - } else if (scan_keyword("mapline")) { - scan_toks(false, true); - pdfmapline(def_ref); - delete_token_ref(def_ref); - } else if (scan_keyword("includechars")) { - pdf_include_chars(static_pdf); - } else if (scan_keyword("info")) { - scan_toks(false, true); - pdf_info_toks = concat_tokens(pdf_info_toks, def_ref); - } else if (scan_keyword("names")) { - scan_toks(false, true); - pdf_names_toks = concat_tokens(pdf_names_toks, def_ref); - } else if (scan_keyword("trailer")) { - scan_toks(false, true); - pdf_trailer_toks = concat_tokens(pdf_trailer_toks, def_ref); - } else { - tex_error("unexpected use of \\pdfextension",null); - } -} - -static void do_resource_dvi(int immediate, int code) -{ - /*tex Nothing is done here. */ -} - -static void do_resource_pdf(int immediate, int code) -{ - switch (code) { - case use_box_resource_code: - scan_pdfrefxform(static_pdf); - break; - case use_image_resource_code: - scan_pdfrefximage(static_pdf); - break; - case save_box_resource_code: - scan_pdfxform(static_pdf); - if (immediate) { - pdf_cur_form = last_saved_box_index; - ship_out(static_pdf, obj_xform_box(static_pdf, last_saved_box_index), SHIPPING_FORM); - } - break; - case save_image_resource_code: - scan_pdfximage(static_pdf); - if (immediate) { - pdf_write_image(static_pdf, last_saved_image_index); - } - break; - } -} - -/*tex - - Ad immediate: - - To write a token list, we must run it through \TeX's scanner, expanding - macros and \.{\\the} and \.{\\number}, etc. This might cause runaways, if a - delimited macro parameter isn't matched, and runaways would be extremely - confusing since we are calling on \TeX's scanner in the middle of a - \.{\\shipout} command. Therefore we will put a dummy control sequence as a - ``stopper,'' right after the token list. This control sequence is - artificially defined to be \.{\\outer}. - - The presence of `\.{\\immediate}' causes the |do_extension| procedure to - descend to one level of recursion. Nothing happens unless \.{\\immediate} is - followed by `\.{\\openout}', `\.{\\write}', or `\.{\\closeout}'. - -*/ - -/*tex - - The extensions are backend related. The next subroutine uses |cur_chr| to - decide what sort of whatsit is involved, and also inserts a |write_stream| - number. - -*/ - -static void new_write_whatsit(int w, int check) -{ - new_whatsit(cur_chr); - if (check) { - /*tex So we check with open and close. */ - scan_limited_int(last_file_selector,NULL); - } else { - /*tex But we're tolerant with the rest. */ - scan_int(); - if (cur_val < 0) - cur_val = term_only; - else if (cur_val > last_file_selector) { - cur_val = term_and_log; - } - } - write_stream(tail) = cur_val; -} - -void do_extension(int immediate) -{ - /*tex An all-purpose pointer. */ - halfword p; - if (cur_cmd == extension_cmd) { - /*tex These have their own range starting at 0. */ - switch (cur_chr) { - case open_code: - p = tail; - new_write_whatsit(open_node_size,1); - scan_optional_equals(); - /* scan_file_name(); */ - do { - get_x_token(); - } while ((cur_cmd == spacer_cmd) || (cur_cmd == relax_cmd)); - back_input(); - if (cur_cmd != left_brace_cmd) { - scan_file_name(); - } else { - scan_file_name_toks(); - } - /* */ - open_name(tail) = cur_name; - open_area(tail) = cur_area; - open_ext(tail) = cur_ext; - if (immediate) { - wrapup_leader(tail); - flush_node_list(tail); - tail = p; - vlink(p) = null; - } - break; - case write_code: - /*tex - - When `\.{\\write 12\{...\}}' appears, we scan the token list - `\.{\{...\}}' without expanding its macros; the macros will - be expanded later when this token list is rescanned. - - */ - p = tail; - new_write_whatsit(write_node_size,0); - cur_cs = write_stream(tail); - scan_toks(false, false); - write_tokens(tail) = def_ref; - if (immediate) { - wrapup_leader(tail); - flush_node_list(tail); - tail = p; - vlink(p) = null; - } - break; - case close_code: - p = tail; - new_write_whatsit(close_node_size,1); - write_tokens(tail) = null; - if (immediate) { - wrapup_leader(tail); - flush_node_list(tail); - tail = p; - vlink(p) = null; - } - break; - case special_code: - /*tex - - When `\.{\\special\{...\}}' appears, we expand the macros in - the token list as in \.{\\xdef} and \.{\\mark}. - - */ - new_whatsit(special_node); - write_stream(tail) = null; - p = scan_toks(false, true); - write_tokens(tail) = def_ref; - break; - case immediate_code: - get_x_token(); - do_extension(1); - break; - case end_local_code: - if (tracing_nesting_par > 2) { - local_control_message("leaving token scanner"); - } - end_local_control(); - break; - case use_box_resource_code: - case use_image_resource_code: - case save_box_resource_code: - case save_image_resource_code: - switch (get_o_mode()) { - case OMODE_DVI: - do_resource_dvi(immediate,cur_chr); - break; - case OMODE_PDF: - do_resource_pdf(immediate,cur_chr); - break; - default: - break; - } - break; - /*tex Backend extensions have their own range starting at 32. */ - case dvi_extension_code: - if (get_o_mode() == OMODE_DVI) - do_extension_dvi(immediate); - break; - case pdf_extension_code: - if (get_o_mode() == OMODE_PDF) - do_extension_pdf(immediate); - break; - /*tex Done. */ - default: - if (immediate) { - back_input(); - } else { - confusion("invalid extension"); - } - break; - } - } else { - /*tex No extension command, quite certainly following |\immediate|. */ - back_input(); - } -} - -/*tex - - Here is a subroutine that creates a whatsit node having a given |subtype| and - a given number of words. It initializes only the first word of the whatsit, - and appends it to the current list. - -*/ - -void new_whatsit(int s) -{ - halfword p = new_node(whatsit_node, s); - couple_nodes(tail, p); - tail = p; -} - -/*tex - - The final line of this routine is slightly subtle; at least, the author - didn't think about it until getting burnt! There is a used-up token list on - the stack, namely the one that contained |end_write_token|. (We insert this - artificial `\.{\\endwrite}' to prevent runaways, as explained above.) If it - were not removed, and if there were numerous writes on a single page, the - stack would overflow. - -*/ - -void expand_macros_in_tokenlist(halfword p) -{ - int old_mode; - pointer q = get_avail(); - pointer r = get_avail(); - token_info(q) = right_brace_token + '}'; - token_link(q) = r; - token_info(r) = end_write_token; - begin_token_list(q, inserted); - begin_token_list(write_tokens(p), write_text); - q = get_avail(); - token_info(q) = left_brace_token + '{'; - begin_token_list(q, inserted); - /*tex - - Now we're ready to scan `\.\{$\langle\,$token list$\,\rangle$\.{\} - \\endwrite}'. - - */ - old_mode = mode; - mode = 0; - /*tex - - Disable \.{\\prevdepth}, \.{\\spacefactor}, \.{\\lastskip}, - \.{\\prevgraf}. - - */ - cur_cs = write_loc; - /*tex Expand macros, etc. */ - q = scan_toks(false, true); - get_token(); - if (cur_tok != end_write_token) { - /*tex Recover from an unbalanced write command */ - const char *hlp[] = { - "On this page there's a \\write with fewer real {'s than }'s.", - "I can't handle that very well; good luck.", - NULL - }; - tex_error("Unbalanced write command", hlp); - do { - get_token(); - } while (cur_tok != end_write_token); - } - mode = old_mode; - /*tex Conserve stack space. */ - end_token_list(); -} - -void write_out(halfword p) -{ - /*tex holds print |selector| */ - int old_setting; - /*tex write stream number */ - int j; - /*tex line to be written, as a Lua string */ - lstring *ss = NULL; - lstring *s = NULL; - int callback_id; - int lua_retval; - expand_macros_in_tokenlist(p); - old_setting = selector; - j = write_stream(p); - if (file_can_be_written(j)) { - selector = j; - } else if ((j == term_only) && (selector == term_and_log)) { - /*tex write to the terminal if file isn't open */ - selector = log_only; - tprint_nl(""); - } else { - tprint_nl(""); - } - s = tokenlist_to_lstring(def_ref, false); - if (selector < no_print) { - /*tex selector is a file */ - callback_id = callback_defined(process_output_buffer_callback); - if (callback_id > 0) { - /*tex fix up the output buffer using callbacks */ - lua_retval = run_callback(callback_id, "L->L", s, &ss); - if ((lua_retval == true) && (ss != NULL)) { - free_lstring(s); - s = ss; - } - } - } - lprint(s); - free_lstring(s); - print_ln(); - flush_list(def_ref); - selector = old_setting; -} - -void finalize_write_files(void) { - int k; - for (k = 0; k <= last_file_selector; k++) { - if (write_open[k]) { - lua_a_close_out(write_file[k]); - } - } -} - -void initialize_write_files(void) { - int k; - for (k = 0; k <= last_file_selector; k++) { - write_open[k] = false; - } -} - -void close_write_file(int id) { - if (write_open[id]) { - lua_a_close_out(write_file[id]); - write_open[id] = false; - } -} - -boolean open_write_file(int id, char *fn) { - if (lua_a_open_out(&(write_file[id]), fn, (id + 1))) { - write_open[id] = true; - return true; - } else { - return false; - } -} - -/*tex - - To implement primitives as \.{\\pdfextension info}, \.{\\pdfextension - catalog} or \.{\\pdfextension names} we need to concatenate tokens lists. - -*/ - -halfword concat_tokens(halfword q, halfword r) -{ - /*tex concat |q| and |r| and returns the result tokens list */ - halfword p; - if (q == null) - return r; - p = q; - while (token_link(p) != null) - p = token_link(p); - set_token_link(p, token_link(r)); - free_avail(r); - return q; -} - -/*tex - - The \eTeX\ features available in extended mode are grouped into two - categories: (1)~Some of them are permanently enabled and have no semantic - effect as long as none of the additional primitives are executed. (2)~The - remaining \eTeX\ features are optional and can be individually enabled and - disabled. For each optional feature there is an \eTeX\ state variable named - \.{\\...state}; the feature is enabled, resp.\ disabled by assigning a - positive, resp.\ non-positive value to that integer. - - In order to handle \.{\\everyeof} we need an array |eof_seen| of boolean - variables. - -*/ - -boolean *eof_seen; - -/*tex - - The |print_group| procedure prints the current level of grouping and the name - corresponding to |cur_group|. - -*/ - -void print_group(boolean e) -{ - switch (cur_group) { - case bottom_level: - tprint("bottom level"); - return; - break; - case simple_group: - case semi_simple_group: - if (cur_group == semi_simple_group) - tprint("semi "); - tprint("simple"); - break;; - case hbox_group: - case adjusted_hbox_group: - if (cur_group == adjusted_hbox_group) - tprint("adjusted "); - tprint("hbox"); - break; - case vbox_group: - tprint("vbox"); - break; - case vtop_group: - tprint("vtop"); - break; - case align_group: - case no_align_group: - if (cur_group == no_align_group) - tprint("no "); - tprint("align"); - break; - case output_group: - tprint("output"); - break; - case disc_group: - tprint("disc"); - break; - case insert_group: - tprint("insert"); - break; - case vcenter_group: - tprint("vcenter"); - break; - case math_group: - case math_choice_group: - case math_shift_group: - case math_left_group: - tprint("math"); - if (cur_group == math_choice_group) - tprint(" choice"); - else if (cur_group == math_shift_group) - tprint(" shift"); - else if (cur_group == math_left_group) - tprint(" left"); - break; - } - tprint(" group (level "); - print_int(cur_level); - print_char(')'); - if (saved_value(-1) != 0) { - /*tex |saved_line| */ - if (e) - tprint(" entered at line "); - else - tprint(" at line "); - print_int(saved_value(-1)); - } -} - -/*tex - - The |group_trace| procedure is called when a new level of grouping begins - (|e=false|) or ends (|e=true|) with |saved_value(-1)| containing the line - number. - -*/ - -void group_trace(boolean e) -{ - begin_diagnostic(); - print_char('{'); - if (e) - tprint("leaving "); - else - tprint("entering "); - print_group(e); - print_char('}'); - end_diagnostic(false); -} - -/*tex - - A group entered (or a conditional started) in one file may end in a different - file. Such slight anomalies, although perfectly legitimate, may cause errors - that are difficult to locate. In order to be able to give a warning message - when such anomalies occur, \eTeX\ uses the |grp_stack| and |if_stack| arrays - to record the initial |cur_boundary| and |cond_ptr| values for each input - file. - -*/ - -/*tex initial |cur_boundary| */ - -save_pointer *grp_stack; - -/*tex initial |cond_ptr| */ - -halfword *if_stack; - -/*tex - - When a group ends that was apparently entered in a different input file, the - |group_warning| procedure is invoked in order to update the |grp_stack|. If - moreover \.{\\tracingnesting} is positive we want to give a warning message. - The situation is, however, somewhat complicated by two facts: (1)~There may - be |grp_stack| elements without a corresponding \.{\\input} file or - \.{\\scantokens} pseudo file (e.g., error insertions from the terminal); and - (2)~the relevant information is recorded in the |name_field| of the - |input_stack| only loosely synchronized with the |in_open| variable indexing - |grp_stack|. - -*/ - -void group_warning(void) -{ - /*tex do we need a warning? */ - boolean w = false; - /*tex index into |grp_stack| */ - int i = in_open; - base_ptr = input_ptr; - /*tex store current state */ - input_stack[base_ptr] = cur_input; - while ((grp_stack[i] == cur_boundary) && (i > 0)) { - /*tex - - Set variable |w| to indicate if this case should be reported. This - code scans the input stack in order to determine the type of the - current input file. - - */ - if (tracing_nesting_par > 0) { - while ((input_stack[base_ptr].state_field == token_list) || (input_stack[base_ptr].index_field > i)) - decr(base_ptr); - if (input_stack[base_ptr].name_field > 17) - w = true; - } - grp_stack[i] = save_value(save_ptr); - decr(i); - } - if (w) { - tprint_nl("Warning: end of "); - print_group(true); - tprint(" of a different file"); - print_ln(); - if (tracing_nesting_par > 1) - show_context(); - if (history == spotless) - history = warning_issued; - } -} - -/*tex - - When a conditional ends that was apparently started in a different input - file, the |if_warning| procedure is invoked in order to update the - |if_stack|. If moreover \.{\\tracingnesting} is positive we want to give a - warning message (with the same complications as above). - -*/ - -void if_warning(void) -{ - /*tex Do we need a warning? */ - boolean w = false; - int i = in_open; - base_ptr = input_ptr; - /*tex Store current state. */ - input_stack[base_ptr] = cur_input; - while (if_stack[i] == cond_ptr) { - /*tex Set variable |w| to. */ - if (tracing_nesting_par > 0) { - while ((input_stack[base_ptr].state_field == token_list) || (input_stack[base_ptr].index_field > i)) - decr(base_ptr); - if (input_stack[base_ptr].name_field > 17) - w = true; - } - if_stack[i] = vlink(cond_ptr); - decr(i); - } - if (w) { - tprint_nl("Warning: end of "); - print_cmd_chr(if_test_cmd, cur_if); - print_if_line(if_line); - tprint(" of a different file"); - print_ln(); - if (tracing_nesting_par > 1) - show_context(); - if (history == spotless) - history = warning_issued; - } -} - -/*tex - - Conversely, the |file_warning| procedure is invoked when a file ends and some - groups entered or conditionals started while reading from that file are still - incomplete. - -*/ - -void file_warning(void) -{ - /*tex saved value of |save_ptr| or |cond_ptr| */ - halfword p = save_ptr; - /*tex saved value of |cur_level| or |if_limit| */ - int l = cur_level; - /*tex saved value of |cur_group| or |cur_if| */ - int c = cur_group; - /*tex saved value of |if_line| */ - int i; - save_ptr = cur_boundary; - while (grp_stack[in_open] != save_ptr) { - decr(cur_level); - tprint_nl("Warning: end of file when "); - print_group(true); - tprint(" is incomplete"); - cur_group = save_level(save_ptr); - save_ptr = save_value(save_ptr); - } - save_ptr = p; - cur_level = (quarterword) l; - /*tex Restore old values. */ - cur_group = (group_code) c; - p = cond_ptr; - l = if_limit; - c = cur_if; - i = if_line; - while (if_stack[in_open] != cond_ptr) { - tprint_nl("Warning: end of file when "); - print_cmd_chr(if_test_cmd, cur_if); - if (if_limit == fi_code) - tprint_esc("else"); - print_if_line(if_line); - tprint(" is incomplete"); - if_line = if_line_field(cond_ptr); - cur_if = if_limit_subtype(cond_ptr); - if_limit = if_limit_type(cond_ptr); - cond_ptr = vlink(cond_ptr); - } - /*tex restore old values */ - cond_ptr = p; - if_limit = l; - cur_if = c; - if_line = i; - print_ln(); - if (tracing_nesting_par > 1) - show_context(); - if (history == spotless) - history = warning_issued; -} - -/*tex The |par_fill_skip| glue node of the new paragraph. */ - -halfword last_line_fill; - -/*tex - - The lua interface needs some extra functions. The functions themselves are - quite boring, but they are handy because otherwise this internal stuff has to - be accessed from C directly, where lots of the defines are not available. - -*/ - -#define get_tex_dimen_register(j) dimen(j) -#define get_tex_skip_register(j) skip(j) -#define get_tex_mu_skip_register(j) mu_skip(j) -#define get_tex_count_register(j) count(j) -#define get_tex_attribute_register(j) attribute(j) -#define get_tex_box_register(j) box(j) - -/*tex These can now be macros (todo). */ - -int get_tex_extension_count_register(int i) -{ - return (int) int_par(backend_int_base-int_base+i); -} - -void set_tex_extension_count_register(int i, int d) -{ - int_par(backend_int_base-int_base+i) = d; -} - -int get_tex_extension_dimen_register(int i) -{ - return (int) dimen_par(backend_dimen_base-dimen_base+i); -} - -void set_tex_extension_dimen_register(int i, int d) -{ - dimen_par(backend_dimen_base-dimen_base+i) = d; -} - -int get_tex_extension_toks_register(int i) -{ - return equiv(backend_toks_base+i); -} - -int set_tex_dimen_register(int j, scaled v) -{ - int a; - if (global_defs_par > 0) - a = 4; - else - a = 0; - word_define(j + scaled_base, v); - return 0; -} - -int set_tex_skip_register(int j, halfword v) -{ - int a; - if (global_defs_par > 0) - a = 4; - else - a = 0; - if (type(v) != glue_spec_node) - return 1; - word_define(j + skip_base, v); - return 0; -} - -int set_tex_mu_skip_register(int j, halfword v) -{ - int a; - if (global_defs_par > 0) - a = 4; - else - a = 0; - if (type(v) != glue_spec_node) - return 1; - word_define(j + mu_skip_base, v); - return 0; -} - -int set_tex_count_register(int j, scaled v) -{ - int a; - if (global_defs_par > 0) - a = 4; - else - a = 0; - word_define(j + count_base, v); - return 0; -} - -int set_tex_box_register(int j, scaled v) -{ - int a; - if (global_defs_par > 0) - a = 4; - else - a = 0; - define(j + box_base, box_ref_cmd, v); - return 0; -} - -int set_tex_attribute_register(int j, scaled v) -{ - int a; - if (global_defs_par > 0) - a = 4; - else - a = 0; - if (j > max_used_attr) - max_used_attr = j; - attr_list_cache = cache_disabled; - word_define(j + attribute_base, v); - return 0; -} - -int get_tex_toks_register(int j) -{ - str_number s = get_nullstr(); - if (toks(j) != null) { - s = tokens_to_string(toks(j)); - } - return s; -} - -int set_tex_toks_register(int j, lstring s) -{ - int a; - halfword ref = get_avail(); - (void) str_toks(s); - set_token_ref_count(ref, 0); - set_token_link(ref, token_link(temp_token_head)); - if (global_defs_par > 0) - a = 4; - else - a = 0; - define(j + toks_base, call_cmd, ref); - return 0; -} - -int scan_tex_toks_register(int j, int c, lstring s) -{ - int a; - halfword ref = get_avail(); - (void) str_scan_toks(c,s); - set_token_ref_count(ref, 0); - set_token_link(ref, token_link(temp_token_head)); - if (global_defs_par > 0) - a = 4; - else - a = 0; - define(j + toks_base, call_cmd, ref); - return 0; -} - -scaled get_tex_box_width(int j) -{ - halfword q = box(j); - if (q != null) - return width(q); - return 0; -} - -int set_tex_box_width(int j, scaled v) -{ - halfword q = box(j); - if (q == null) - return 1; - width(q) = v; - return 0; -} - -scaled get_tex_box_height(int j) -{ - halfword q = box(j); - if (q != null) - return height(q); - return 0; -} - -int set_tex_box_height(int j, scaled v) -{ - halfword q = box(j); - if (q == null) - return 1; - height(q) = v; - return 0; -} - -scaled get_tex_box_depth(int j) -{ - halfword q = box(j); - if (q != null) - return depth(q); - return 0; -} - -int set_tex_box_depth(int j, scaled v) -{ - halfword q = box(j); - if (q == null) - return 1; - depth(q) = v; - return 0; -} - -/*tex - - This section is devoted to the {\sl Synchronize \TeX nology} - or simply {\sl - Sync\TeX} - used to synchronize between input and output. This section - explains how synchronization basics are implemented. Before we enter into - more technical details, let us recall in a few words what is synchronization. - - \TeX\ typesetting system clearly separates the input and the output material, - and synchronization will provide a new link between both that can help text - editors and viewers to work together. More precisely, forwards - synchronization is the ability, given a location in the input source file, to - find what is the corresponding place in the output. Backwards synchronization - just performs the opposite: given a location in the output, retrieve the - corresponding material in the input source file. - - For better code management and maintainance, we adopt a naming convention. - Throughout this program, code related to the {\sl Synchronize \TeX nology} is - tagged with the ``{\sl synctex}'' key word. Any code extract where {\sl - Sync\TeX} plays its part, either explicitly or implicitly, (should) contain - the string ``{\sl synctex}''. This naming convention also holds for external - files. Moreover, all the code related to {\sl Sync\TeX} is gathered in this - section, except the definitions. - - Enabling synchronization should be performed from the command line, - |synctexoption| is used for that purpose. This global integer variable is - declared here but it is not used here. This is just a placeholder where the - command line controller will put the {\sl Sync\TeX} related options, and the - {\sl Sync\TeX} controller will read them. - -*/ - -int synctexoption; - -/*tex - - A convenient primitive is provided: \.{\\synctex=1} in the input source file - enables synchronization whereas \.{\\synctex=0} disables it. Its memory - address is |synctex_code|. It is initialized by the {\sl Sync\TeX} controller - to the command-line option if given. The controller may filter some reserved - bits. - - In order to give the {\sl Sync\TeX} controller read and write access to the - contents of the \.{\\synctex} primitive, we declare |synctexoffset|, such - that |mem[synctexoffset]| and \.{\\synctex} correspond to the same memory - storage. |synctexoffset| is initialized to the correct value when quite - everything is initialized. - -*/ - -/*tex Holds the true value of |synctex_code|: */ - -int synctexoffset; - -/*tex - - Synchronization is achieved with the help of an auxiliary file named `\.{{\sl - jobname}.synctex}' ({\sl jobname} is the contents of the \.{\\jobname} - macro), where a {\sl Sync\TeX} controller implemented in the external - |synctex.c| file will store geometrical information. This {\sl Sync\TeX} - controller will take care of every technical details concerning the {\sl - Sync\TeX} file, we will only focus on the messages the controller will - receive from the \TeX\ program. - - The most accurate synchronization information should allow to map any - character of the input source file to the corresponding location in the - output, if relevant. Ideally, the synchronization information of the input - material consists of the file name, the line and column numbers of every - character. The synchronization information in the output is simply the page - number and either point coordinates, or box dimensions and position. The - problem is that the mapping between these informations is only known at ship - out time, which means that we must keep track of the input synchronization - information until the pages ship out. - - As \TeX\ only knows about file names and line numbers, but forgets the column - numbers, we only consider a restricted input synchronization information - called {\sl Sync\TeX\ information}. It consists of a unique file name - identifier, the {\sl Sync\TeX\ file tag}, and the line number. - - Keeping track of such information, should be different whether characters or - nodes are involved. Actually, only certain nodes are involved in {\sl - Sync\TeX}, we call them {\sl synchronized nodes}. Synchronized nodes store - the {\sl Sync\TeX} information in their last two words: the first one - contains a {\sl Sync\TeX\ file tag} uniquely identifying the input file, and - the second one contains the current line number, as returned by the - \.{\\inputlineno} primitive. The |synctex_field_size| macro contains the - necessary size to store the {\sl Sync\TeX} information in a node. - - When declaring the size of a new node, it is recommanded to use the following - convention: if the node is synchronized, use a definition similar to - |my_synchronized_node_size|={\sl xxx}+|synctex_field_size|. Moreover, one - should expect that the {\sl Sync\TeX} information is always stored in the - last two words of a synchronized node. - - By default, every node with a sufficiently big size is initialized at - creation time in the |get_node| routine with the current {\sl Sync\TeX} - information, whether or not the node is synchronized. One purpose is to set - this information very early in order to minimize code dependencies, including - forthcoming extensions. Another purpose is to avoid the assumption that every - node type has a dedicated getter, where initialization should take place. - Actually, it appears that some nodes are created using directly the - |get_node| routine and not the dedicated constructor. And finally, - initializing the node at only one place is less error prone. - - Instead of storing the input file name, it is better to store just an - identifier. Each time \TeX\ opens a new file, it notifies the {\sl Sync\TeX} - controller with a |synctex_start_input| message. This controller will create - a new {\sl Sync\TeX} file tag and will update the current input state record - accordingly. If the input comes from the terminal or a pseudo file, the - |synctex_tag| is set to 0. It results in automatically disabling - synchronization for material input from the terminal or pseudo files. - - Synchronized nodes are boxes, math, kern and glue nodes. Other nodes should - be synchronized too, in particular math noads. \TeX\ assumes that math, kern - and glue nodes have the same size, this is why both are synchronized. {\sl In - fine}, only horizontal lists are really used in {\sl Sync\TeX}, but all box - nodes are considered the same with respect to synchronization, because a box - node type is allowed to change at execution time. - - {\em Nota Bene:} The {\sl Sync\TeX} code is very close to the memory model. - It is not connected to any other part of the code, except for memory - management. It is possible to neutralize the {\sl Sync\TeX} code rather - simply. The first step is to define a null |synctex_field_size|. The second - step is to comment out the code in ``Initialize bigger nodes...'' and every - ``Copy ... {\sl Sync\TeX} information''. The last step will be to comment out - the |synctex_tag_field| related code in the definition of |synctex_tag| and - the various ``Prepare ... {\sl Sync\TeX} information''. Then all the - remaining code should be just harmless. The resulting program would behave - exactly the same as if absolutely no {\sl Sync\TeX} related code was there, - including memory management. Of course, all this assumes that {\sl Sync\TeX} - is turned off from the command line. - - Here are extra variables for Web2c. (This numbering of the system-dependent - section allows easy integration of Web2c and e-\TeX, etc.) - -*/ - -/*tex where the filename to switch to starts */ - -pool_pointer edit_name_start; - -/*tex what line to start editing at */ - -int edit_name_length, edit_line; - -/*tex whether |more_name| returns false for space */ - -boolean stop_at_space; - -/*tex - - The |edit_name_start| will be set to point into |str_pool| somewhere after - its beginning if \TeX\ is supposed to switch to an editor on exit. - -*/ - -int shellenabledp; -int restrictedshell; -char *output_comment; - -/*tex - - Are we printing extra info as we read the format file? - -*/ - -boolean debug_format_file; - -void wrapup_leader(halfword p) -{ - /*tex Do some work that has been queued up for \.{\\write}. */ - if (!doing_leaders) { - int j = write_stream(p); - if (subtype(p) == write_node) { - write_out(p); - } else if (subtype(p) == close_node) { - close_write_file(j); - } else if (valid_write_file(j)) { - char *fn; - close_write_file(j); - cur_name = open_name(p); - cur_area = open_area(p); - cur_ext = open_ext(p); - if (cur_ext == get_nullstr()) - cur_ext = maketexstring(".tex"); - fn = pack_file_name(cur_name, cur_area, cur_ext); - while (! open_write_file(j,fn)) { - fn = prompt_file_name("output file name", ".tex"); - } - } - } -} diff --git a/Build/source/texk/web2c/luatexdir/tex/extensions.h b/Build/source/texk/web2c/luatexdir/tex/extensions.h deleted file mode 100644 index 5e22ddf26c3..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/extensions.h +++ /dev/null @@ -1,147 +0,0 @@ -/* extensions.h - - Copyright 2009 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ - - -#ifndef EXTENSIONS_H -# define EXTENSIONS_H - -extern alpha_file write_file[last_file_selector+1]; -extern halfword write_file_mode[last_file_selector+1]; -extern halfword write_file_translation[last_file_selector+1]; -extern boolean write_open[last_file_selector+1]; - -# define valid_write_file(n) ((n>=0) && (n<=last_file_selector)) -# define file_can_be_written(n) (valid_write_file(n) && write_open[n]) - -extern void expand_macros_in_tokenlist(halfword p); -extern void write_out(halfword p); -extern void finalize_write_files(void); -extern void initialize_write_files(void); -extern void close_write_file(int id); -extern boolean open_write_file(int id, char *fn); - -extern scaled neg_wd; -extern scaled pos_wd; -extern scaled neg_ht; - -extern halfword write_loc; - -extern void do_extension(int immediate); - -/* -User defined whatsits can be inserted into node lists to pass data -along from one lua call to another without interference from the -typesetting engine itself. Each has an id, a type, and a value. The -type of the value depends on the |user_node_type| field. -*/ - -extern void new_whatsit(int s); - -extern halfword concat_tokens(halfword q, halfword r); - -/* -The \.{\\pagediscards} and \.{\\splitdiscards} commands share the -command code |un_vbox| with \.{\\unvbox} and \.{\\unvcopy}, they are -distinguished by their |chr_code| values |last_box_code| and -|vsplit_code|. These |chr_code| values are larger than |box_code| and -|copy_code|. -*/ - -extern boolean *eof_seen; /* has eof been seen? */ -extern void print_group(boolean e); -extern void group_trace(boolean e); -extern save_pointer *grp_stack; /* initial |cur_boundary| */ -extern halfword *if_stack; /* initial |cond_ptr| */ -extern void group_warning(void); -extern void if_warning(void); -extern void file_warning(void); - -extern halfword last_line_fill; /* the |par_fill_skip| glue node of the new paragraph */ - -# define get_tex_dimen_register(j) dimen(j) -# define get_tex_skip_register(j) skip(j) -# define get_tex_mu_skip_register(j) mu_skip(j) -# define get_tex_count_register(j) count(j) -# define get_tex_attribute_register(j) attribute(j) -# define get_tex_box_register(j) box(j) - -extern int get_tex_extension_count_register(int i); -extern void set_tex_extension_count_register(int i, int d); -extern int get_tex_extension_dimen_register(int i); -extern void set_tex_extension_dimen_register(int i, int d); -extern int get_tex_extension_toks_register (int i); - -extern int set_tex_dimen_register(int j, scaled v); -extern int set_tex_skip_register(int j, halfword v); -extern int set_tex_mu_skip_register(int j, halfword v); -extern int set_tex_count_register(int j, scaled v); -extern int set_tex_box_register(int j, scaled v); -extern int set_tex_attribute_register(int j, scaled v); -extern int get_tex_toks_register(int l); -extern int set_tex_toks_register(int j, lstring s); -extern int scan_tex_toks_register(int j, int c, lstring s); -extern scaled get_tex_box_width(int j); -extern int set_tex_box_width(int j, scaled v); -extern scaled get_tex_box_height(int j); -extern int set_tex_box_height(int j, scaled v); -extern scaled get_tex_box_depth(int j); -extern int set_tex_box_depth(int j, scaled v); - -/* Synctex variables */ - -extern int synctexoption; -extern int synctexoffset; - -/* Here are extra variables for Web2c. */ - -extern pool_pointer edit_name_start; -extern int edit_name_length, edit_line; -extern boolean stop_at_space; -extern int shellenabledp; -extern int restrictedshell; -extern char *output_comment; -extern boolean debug_format_file; - -extern int last_saved_box_index ; -extern int last_saved_image_index ; -extern int last_saved_image_pages ; -extern scaledpos last_position ; - -typedef enum { - /* traditional extensions */ - open_code = 0, - write_code, - close_code, - reserved_extension_code, // 3: we moved special below immediate // - reserved_immediate_code, // 4: same number as main codes, expected value // - /* backend specific implementations */ - special_code, - save_box_resource_code, - use_box_resource_code, - save_image_resource_code, - use_image_resource_code, - end_local_code, - /* backend */ - dvi_extension_code, - pdf_extension_code, -} extension_codes ; - -extern void wrapup_leader(halfword p); - -#endif diff --git a/Build/source/texk/web2c/luatexdir/tex/filename.c b/Build/source/texk/web2c/luatexdir/tex/filename.c deleted file mode 100644 index 1e06e877ae8..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/filename.c +++ /dev/null @@ -1,383 +0,0 @@ -/* - -filename.w - -Copyright 2009-2010 Taco Hoekwater <taco@@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your -option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU General Public License along -with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" - - -/*tex - - In order to isolate the system-dependent aspects of file names, the @^system - dependencies@> system-independent parts of \TeX\ are expressed in terms of - three system-dependent procedures called |begin_name|, |more_name|, and - |end_name|. In essence, if the user-specified characters of the file name are - $c_1\ldots c_n$, the system-independent driver program does the operations - $$|begin_name|;\,|more_name|(c_1);\,\ldots\,;\,|more_name|(c_n); - \,|end_name|.$$ - - These three procedures communicate with each other via global variables. - Afterwards the file name will appear in the string pool as three strings - called |cur_name|\penalty10000\hskip-.05em, |cur_area|, and |cur_ext|; the - latter two are null (i.e., |""|), unless they were explicitly specified by - the user. - - Actually the situation is slightly more complicated, because \TeX\ needs to - know when the file name ends. The |more_name| routine is a function (with - side effects) that returns |true| on the calls |more_name|$(c_1)$, \dots, - |more_name|$(c_{n-1})$. The final call |more_name|$(c_n)$ returns |false|; - or, it returns |true| and the token following $c_n$ is something like - `\.{\\hbox}' (i.e., not a character). In other words, |more_name| is supposed - to return |true| unless it is sure that the file name has been completely - scanned; and |end_name| is supposed to be able to finish the assembly of - |cur_name|, |cur_area|, and |cur_ext| regardless of whether - $|more_name|(c_n)$ returned |true| or |false|. - - - Here now is the first of the system-dependent routines for file name - scanning. @^system dependencies@> - -*/ - -static void begin_name(void) -{ - area_delimiter = 0; - ext_delimiter = 0; - quoted_filename = false; -} - -/*tex - - And here's the second. The string pool might change as the file name is being - scanned, since a new \.{\\csname} might be entered; therefore we keep - |area_delimiter| and |ext_delimiter| relative to the beginning of the current - string, instead of assigning an absolute address like |pool_ptr| to them. - @^system dependencies@> - -*/ - -static boolean more_name(ASCII_code c) -{ - if (c == ' ' && stop_at_space && (!quoted_filename)) { - return false; - } else if (c == '"') { - quoted_filename = !quoted_filename; - return true; - } else { - str_room(1); - append_char(c); - if (IS_DIR_SEP(c)) { - area_delimiter = (pool_pointer) cur_length; - ext_delimiter = 0; - } else if (c == '.') - ext_delimiter = (pool_pointer) cur_length; - return true; - } -} - -/*tex - - The third. @^system dependencies@> - -*/ - -static void end_name(void) -{ - unsigned char *s; - if (str_ptr + 3 > (max_strings + STRING_OFFSET)) - overflow( - "number of strings", - (unsigned) (max_strings - init_str_ptr + STRING_OFFSET) - ); - /*tex At this point, the full string lives in |cur_string|. */ - if (area_delimiter == 0) { - cur_area = get_nullstr(); - } else { - s = (unsigned char *) xstrdup((char *) (cur_string + area_delimiter)); - cur_string[area_delimiter] = '\0'; - cur_length = (unsigned) strlen((char *) cur_string); - cur_area = make_string(); - xfree(cur_string); - cur_length = (unsigned) strlen((char *) s); - cur_string = s; - } - if (ext_delimiter == 0) { - cur_name = make_string(); - cur_ext = get_nullstr(); - } else { - int l = (ext_delimiter - area_delimiter - 1); - s = (unsigned char *) xstrdup((char *) (cur_string + l)); - cur_string[l] = '\0'; - cur_length = (unsigned) strlen((char *) cur_string); - cur_name = make_string(); - xfree(cur_string); - cur_length = (unsigned) strlen((char *) s); - cur_string = s; - cur_ext = make_string(); - } -} - -/*tex - - Now let's consider the ``driver'' routines by which \TeX\ deals with file - names in a system-independent manner. First comes a procedure that looks for a - file name in the input by calling |get_x_token| for the information. - -*/ - -void scan_file_name(void) -{ - str_number u = 0; - name_in_progress = true; - begin_name(); - /*tex Get the next non-blank non-call token: */ - do { - get_x_token(); - } while ((cur_cmd == spacer_cmd) || (cur_cmd == relax_cmd)); - - while (true) { - if ((cur_cmd > other_char_cmd) || (cur_chr > biggest_char)) { /* not a character */ - back_input(); - break; - } - /*tex - If |cur_chr| is a space and we're not scanning a token list, check - whether we're at the end of the buffer. Otherwise we end up adding - spurious spaces to file names in some cases. - */ - if ((cur_chr == ' ') && (istate != token_list) && (iloc > ilimit) - && !quoted_filename) - break; - if (cur_chr > 127) { - unsigned char *bytes; - unsigned char *thebytes; - thebytes = uni2str((unsigned) cur_chr); - bytes = thebytes; - while (*bytes) { - if (!more_name(*bytes)) - break; - bytes++; - } - xfree(thebytes); - } else { - if (!more_name(cur_chr)) - break; - } - u = save_cur_string(); - get_x_token(); - restore_cur_string(u); - } - end_name(); - name_in_progress = false; -} - -/* - This function constructs a the three file name strings from a token list. -*/ - -void scan_file_name_toks(void) -{ - char *a, *n, *e, *s = NULL; - int i, l = 0; - int save_scanner_status = scanner_status; - halfword save_def_ref = def_ref; - (void) scan_toks(false, true); - s = tokenlist_to_cstring(def_ref, true, &l); - a = n = s; - e = NULL; - for (i = 0; i < l; i++) { - if (IS_DIR_SEP(s[i])) { - n = s + i + 1; - e = NULL; - } else if (s[i] == '.') { - e = s + i; - } - } - if (n != s) { - /*tex explicit area */ - cur_area = maketexlstring(a, (size_t) (n - a)); - } else { - cur_area = get_nullstr(); - } - if (e != NULL) { - /*tex explicit extension */ - cur_name = maketexlstring(n, (size_t) (e - n)); - cur_ext = maketexstring(e); - } else { - cur_name = maketexstring(n); - cur_ext = get_nullstr(); - } - flush_list(def_ref); - scanner_status = save_scanner_status; - def_ref = save_def_ref; - xfree(s); -} - -/*tex - - Here is a routine that manufactures the output file names, assuming that - |job_name<>0|. It ignores and changes the current settings of |cur_area| and - |cur_ext|; |s = ".log"|, |".dvi"|, or |format_extension| -*/ - -char *pack_job_name(const char *s) -{ - cur_area = get_nullstr(); - cur_ext = maketexstring(s); - cur_name = job_name; - return pack_file_name(cur_name, cur_area, cur_ext); -} - -/*tex - - If some trouble arises when \TeX\ tries to open a file, the following routine - calls upon the user to supply another file name. Parameter~|s| is used in the - error message to identify the type of file; parameter~|e| is the default - extension if none is given. Upon exit from the routine, variables |cur_name|, - |cur_area|, and |cur_ext| are ready for another attempt at file opening. - -*/ - -char *prompt_file_name(const char *s, const char *e) -{ - int k; /* index into |buffer| */ - str_number saved_cur_name; /* to catch empty terminal input */ - int callback_id ; - char prompt[256]; - char *ar, *na, *ex; - saved_cur_name = cur_name; - if (interaction == scroll_mode) { - wake_up_terminal(); - } - ar = makecstring(cur_area); - na = makecstring(cur_name); - ex = makecstring(cur_ext); - if (strcmp(s, "input file name") == 0) { - snprintf(prompt, 255, "I can't find file `%s%s%s'.", ar, na, ex); - } else { - snprintf(prompt, 255, "I can't write on file `%s%s%s'.", ar, na, ex); - } - free(ar); - free(na); - free(ex); - print_err(prompt); - callback_id = callback_defined(show_error_hook_callback); - if (callback_id > 0) { - flush_err(); - run_callback(callback_id, "->"); - } else { - if ((strcmp(e, ".tex") == 0) || (strcmp(e, "") == 0)) - show_context(); - if (strcmp(s, "input file name") == 0) - tprint_nl(promptfilenamehelpmsg ")"); - } - tprint_nl("Please type another "); - tprint(s); - if (interaction < scroll_mode) - fatal_error("*** (job aborted, file error in nonstop mode)"); - clear_terminal(); - prompt_input(": "); - begin_name(); - k = first; - while ((buffer[k] == ' ') && (k < last)) - k++; - while (true) { - if (k == last) - break; - if (!more_name(buffer[k])) - break; - k++; - } - end_name(); - if (cur_ext == get_nullstr()) - cur_ext = maketexstring(e); - if (str_length(cur_name) == 0) - cur_name = saved_cur_name; - return pack_file_name(cur_name, cur_area, cur_ext); -} - -void tprint_file_name(unsigned char *n, unsigned char *a, unsigned char *e) -{ - boolean must_quote; /* whether to quote the filename */ - unsigned char *j; /* index into string */ - must_quote = false; - if (a != NULL) { - j = a; - while ((!must_quote) && (*j)) { - must_quote = (*j == ' '); - j++; - } - } - if (n != NULL) { - j = n; - while ((!must_quote) && (*j)) { - must_quote = (*j == ' '); - j++; - } - } - if (e != NULL) { - j = e; - while ((!must_quote) && (*j)) { - must_quote = (*j == ' '); - j++; - } - } - /*tex - Alternative is to assume that any filename that has to be quoted has at - least one quoted component...if we pick this, a number of insertions of - |print_file_name| should go away. - */ - if (must_quote) - print_char('"'); - if (a != NULL) { - for (j = a; *j; j++) - if (*j != '"') - print_char(*j); - } - if (n != NULL) { - for (j = n; *j; j++) - if (*j != '"') - print_char(*j); - } - if (e != NULL) { - for (j = e; *j; j++) - if (*j != '"') - print_char(*j); - } - if (must_quote) - print_char('"'); -} - -void print_file_name(str_number n, str_number a, str_number e) -{ - char *nam, *are, *ext; - nam = makecstring(n); - are = makecstring(a); - ext = makecstring(e); - tprint_file_name( - (unsigned char *) nam, - (unsigned char *) are, - (unsigned char *) ext - ); - free(nam); - free(are); - free(ext); -} diff --git a/Build/source/texk/web2c/luatexdir/tex/filename.h b/Build/source/texk/web2c/luatexdir/tex/filename.h deleted file mode 100644 index cb3d060fd83..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/filename.h +++ /dev/null @@ -1,33 +0,0 @@ -/* filename.h - - Copyright 2009 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ - - -#ifndef FILENAME_H -# define FILENAME_H - -extern void scan_file_name(void); -extern void scan_file_name_toks(void); -extern char *pack_job_name(const char *s); -extern char *prompt_file_name(const char *s, const char *e); -extern void tprint_file_name(unsigned char *n, unsigned char *a, - unsigned char *e); -extern void print_file_name(str_number, str_number, str_number); - - -#endif diff --git a/Build/source/texk/web2c/luatexdir/tex/inputstack.c b/Build/source/texk/web2c/luatexdir/tex/inputstack.c deleted file mode 100644 index 6b0e1a055eb..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/inputstack.c +++ /dev/null @@ -1,960 +0,0 @@ -/* - -inputstack.w - -Copyright 2009-2010 Taco Hoekwater <taco@@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your -option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU General Public License along -with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" - -in_state_record *input_stack = NULL; - -/*tex First unused location of |input_stack|: */ - -int input_ptr = 0; - -/*tex Largest value of |input_ptr| when pushing: */ - -int max_in_stack = 0; - -/*tex The `top' input state: */ - -in_state_record cur_input; - -/*tex The number of lines in the buffer, less one: */ - -int in_open = 0; - -/*tex The number of open text files: */ - -int open_parens = 0; - -alpha_file *input_file = NULL; - -/*tex The current line number in the current source file: */ - -int line = 0; - -int *line_stack = NULL; - -str_number *source_filename_stack = NULL; - -char **full_source_filename_stack = NULL; - -/*tex Can a subfile end now? */ - -int scanner_status = 0; - -/*tex Identifier relevant to non-|normal| scanner status: */ - -pointer warning_index = null; - -/*tex Reference count of token list being defined: */ - -pointer def_ref = null; - -/*tex - -Here is a procedure that uses |scanner_status| to print a warning message when a -subfile has ended, and at certain other crucial times: - -*/ - -void runaway(void) -{ - /*tex The head of the runaway list: */ - pointer p = null; - if (scanner_status > skipping) { - switch (scanner_status) { - case defining: - tprint_nl("Runaway definition"); - p = def_ref; - break; - case matching: - tprint_nl("Runaway argument"); - p = temp_token_head; - break; - case aligning: - tprint_nl("Runaway preamble"); - p = hold_token_head; - break; - case absorbing: - tprint_nl("Runaway text"); - p = def_ref; - break; - default: - /*tex There are no other cases. */ - break; - } - print_char('?'); - print_ln(); - show_token_list(token_link(p), null, error_line - 10); - } -} - -/*tex - -The |param_stack| is an auxiliary array used to hold pointers to the token lists -for parameters at the current level and subsidiary levels of input. This stack is -maintained with convention (2), and it grows at a different rate from the others. - -*/ - -/*tex Token list pointers for parameters: */ - -pointer *param_stack = NULL; - -/*tex First unused entry in |param_stack|: */ - -int param_ptr = 0; - -/*tex Largest value of |param_ptr|, will be |<=param_size+9|: */ - -int max_param_stack = 0; - -/*tex - -The input routines must also interact with the processing of \.{\\halign} and -\.{\\valign}, since the appearance of tab marks and \.{\\cr} in certain places is -supposed to trigger the beginning of special $v_j$ template text in the scanner. -This magic is accomplished by an |align_state| variable that is increased by~1 -when a `\.{\char'173}' is scanned and decreased by~1 when a `\.{\char'175}' is -scanned. The |align_state| is nonzero during the $u_j$ template, after which it -is set to zero; the $v_j$ template begins when a tab mark or \.{\\cr} occurs at a -time that |align_state=0|. - -*/ - -/*tex The group level with respect to current alignment: */ - -int align_state = 0; - -/*tex - -Thus, the ``current input state'' can be very complicated indeed; there can be -many levels and each level can arise in a variety of ways. The |show_context| -procedure, which is used by \TeX's error-reporting routine to print out the -current input state on all levels down to the most recent line of characters from -an input file, illustrates most of these conventions. The global variable -|base_ptr| contains the lowest level that was displayed by this procedure. - -*/ - -/*tex The shallowest level shown by |show_context|: */ - -int base_ptr = 0; - -/*tex - -The status at each level is indicated by printing two lines, where the first line -indicates what was read so far and the second line shows what remains to be read. -The context is cropped, if necessary, so that the first line contains at most -|half_error_line| characters, and the second contains at most |error_line|. -Non-current input levels whose |token_type| is `|backed_up|' are shown only if -they have not been fully read. - -*/ - -static void print_token_list_type(int t) -{ - switch (t) { - case parameter: - tprint_nl("<argument> "); - break; - case u_template: - case v_template: - tprint_nl("<template> "); - break; - case backed_up: - if (iloc == null) - tprint_nl("<recently read> "); - else - tprint_nl("<to be read again> "); - break; - case inserted: - tprint_nl("<inserted text> "); - break; - case macro: - print_ln(); - print_cs(iname); - break; - case output_text: - tprint_nl("<output> "); - break; - case every_par_text: - tprint_nl("<everypar> "); - break; - case every_math_text: - tprint_nl("<everymath> "); - break; - case every_display_text: - tprint_nl("<everydisplay> "); - break; - case every_hbox_text: - tprint_nl("<everyhbox> "); - break; - case every_vbox_text: - tprint_nl("<everyvbox> "); - break; - case every_job_text: - tprint_nl("<everyjob> "); - break; - case every_cr_text: - tprint_nl("<everycr> "); - break; - case mark_text: - tprint_nl("<mark> "); - break; - case every_eof_text: - tprint_nl("<everyeof> "); - break; - case write_text: - tprint_nl("<write> "); - break; - case local_text: - tprint_nl("<local> "); - break; - default: - tprint_nl("?"); - /*tex This should never happen. */ - break; - } -} - -/*tex - -Here it is necessary to explain a little trick. We don't want to store a long -string that corresponds to a token list, because that string might take up lots -of memory; and we are printing during a time when an error message is being -given, so we dare not do anything that might overflow one of \TeX's tables. So -`pseudoprinting' is the answer: We enter a mode of printing that stores -characters into a buffer of length |error_line|, where character $k+1$ is placed -into \hbox{|trick_buf[k mod error_line]|} if |k<trick_count|, otherwise character -|k| is dropped. Initially we set |tally:=0| and |trick_count:=1000000|; then when -we reach the point where transition from line 1 to line 2 should occur, we set -|first_count:=tally| and |trick_count:=@tmax@>(error_line, -tally+1+error_line-half_error_line)|. At the end of the pseudoprinting, the -values of |first_count|, |tally|, and |trick_count| give us all the information -we need to print the two lines, and all of the necessary text is in |trick_buf|. - -Namely, let |l| be the length of the descriptive information that appears on the -first line. The length of the context information gathered for that line is -|k=first_count|, and the length of the context information gathered for line~2 is -$m=\min(|tally|, |trick_count|)-k$. If |l+k<=h|, where |h=half_error_line|, we -print |trick_buf[0..k-1]| after the descriptive information on line~1, and set -|n:=l+k|; here |n| is the length of line~1. If $l+k>h$, some cropping is -necessary, so we set |n:=h| and print `\.{...}' followed by -$$\hbox{|trick_buf[(l+k-h+3)..k-1]|,}$$ where subscripts of |trick_buf| are -circular modulo |error_line|. The second line consists of |n|~spaces followed by -|trick_buf[k..(k+m-1)]|, unless |n+m>error_line|; in the latter case, further -cropping is done. This is easier to program than to explain. - -The following code sets up the print routines so that they will gather the -desired information. - -*/ - -void set_trick_count(void) -{ - first_count = tally; - trick_count = tally + 1 + error_line - half_error_line; - if (trick_count < error_line) - trick_count = error_line; -} - -#define begin_pseudoprint() do { \ - l=tally; \ - tally=0; \ - selector=pseudo; \ - trick_count=1000000; \ - } while (0) - -#define PSEUDO_PRINT_THE_LINE() do { \ - begin_pseudoprint(); \ - if (buffer[ilimit]==end_line_char_par) { \ - j=ilimit; \ - } else { \ - /*tex Determine the effective end of the line. */ \ - j=ilimit+1; \ - } \ - if (j>0) { \ - for (i=istart;i<=j-1;i++) { \ - if (i==iloc) \ - set_trick_count(); \ - print_char(buffer[i]); \ - } \ - } \ -} while (0) - -/*tex - -We don't care too much if we stay a bit too much below the max error_line even if -we have more room on the line. If length is really an issue then any length is. -After all one can set the length larger. - -*/ - -#define print_valid_utf8(q) do { \ - c = (int)trick_buf[q % error_line]; \ - if (c < 128) { \ - print_char(c); \ - } else if (c < 194) { \ - /* invalid */ \ - } else if (c < 224) { \ - print_char(c); \ - print_char(trick_buf[(q+1) % error_line]); \ - } else if (c < 240) { \ - print_char(c); \ - print_char(trick_buf[(q+1) % error_line]); \ - print_char(trick_buf[(q+2) % error_line]); \ - } else if (c < 245) { \ - print_char(c); \ - print_char(trick_buf[(q+1) % error_line]); \ - print_char(trick_buf[(q+2) % error_line]); \ - print_char(trick_buf[(q+3) % error_line]); \ - } else { \ - /*tex Invalid character! */ \ - } \ -} while (0) - -/*tex - -This one prints where the scanner is. - -*/ - -void show_context(void) -{ - /*tex Saved |selector| setting: */ - int old_setting; - /*tex Number of contexts shown so far, less one: */ - int nn = -1; - /*tex Have we reached the final context to be shown? */ - boolean bottom_line = false; - /*tex Index into |buffer|: */ - int i; - /*tex End of current line in |buffer|: */ - int j; - /*tex Length of descriptive information on line 1: */ - int l; - /*tex Context information gathered for line 2: */ - int m; - /*tex Length of line 1: */ - int n; - /*tex Starting or ending place in |trick_buf|: */ - int p; - /*tex Temporary index: */ - int q; - /*tex Used in sanitizer: */ - int c; - base_ptr = input_ptr; - input_stack[base_ptr] = cur_input; - /*tex Store the current state. */ - while (true) { - /*tex Enter into the context. */ - cur_input = input_stack[base_ptr]; - if (istate != token_list) { - if ((iname > 21) || (base_ptr == 0)) - bottom_line = true; - } - if ((base_ptr == input_ptr) || bottom_line || (nn < error_context_lines_par)) { - /*tex Display the current context. */ - if ((base_ptr == input_ptr) || (istate != token_list) || (token_type != backed_up) || (iloc != null)) { - /*tex - We omit backed-up token lists that have already been read. - Get ready to count characters. - */ - tally = 0; - old_setting = selector; - if (istate != token_list) { - /*tex - Print the location of the current line. This routine - should be changed, if necessary, to give the best - possible indication of where the current line resides in - the input file. For example, on some systems it is best - to print both a page and line number. - */ - if (iname <= 17) { - if (terminal_input) { - if (base_ptr == 0) - tprint_nl("<*>"); - else - tprint_nl("<insert> "); - } else { - tprint_nl("<read "); - if (iname == 17) - print_char('*'); - else - print_int(iname - 1); - print_char('>'); - }; - } else { - tprint_nl("l."); - if (iindex == in_open) { - print_int(line); - } else { - /*tex Input from a pseudo file. */ - print_int(line_stack[iindex + 1]); - } - } - print_char(' '); - PSEUDO_PRINT_THE_LINE(); - } else { - print_token_list_type(token_type); - - begin_pseudoprint(); - if (token_type < macro) { - show_token_list(istart, iloc, 100000); - } else { - /*tex Avoid reference count. */ - show_token_list(token_link(istart), iloc, 100000); - } - } - /*tex Stop pseudoprinting. */ - selector = old_setting; - /*tex Print two lines using the tricky pseudoprinted information. */ - if (trick_count == 1000000) { - set_trick_count(); - } - /*tex The |set_trick_count| must be performed. */ - if (tally < trick_count) { - m = tally - first_count; - } else { - /* The context on line 2: */ - m = trick_count - first_count; - } - if (l + first_count <= half_error_line) { - p = 0; - n = l + first_count; - } else { - tprint("..."); - p = l + first_count - half_error_line + 3; - n = half_error_line; - } - for (q = p; q <= first_count - 1; q++) { - print_valid_utf8(q); - } - print_ln(); - /*tex Print |n| spaces to begin line 2. */ - for (q = 1; q <= n; q++) { - print_char(' '); - } - if (m + n <= error_line) - p = first_count + m; - else - p = first_count + (error_line - n - 3); - for (q = first_count; q <= p - 1; q++) - print_valid_utf8(q); - if (m + n > error_line) - tprint("..."); - incr(nn); - } - } else if (nn == error_context_lines_par) { - tprint_nl("..."); - incr(nn); - /*tex Omitted if |error_context_lines_par<0|. */ - } - if (bottom_line) - break; - decr(base_ptr); - } - /*tex Restore the original state. */ - cur_input = input_stack[input_ptr]; -} - -/*tex - -The following subroutines change the input status in commonly needed ways. - -First comes |push_input|, which stores the current state and creates a -new level (having, initially, the same properties as the old). - -Enter a new input level, save the old: - -*/ - -# define pop_input() \ - cur_input=input_stack[--input_ptr] - -# define push_input() \ - if (input_ptr > max_in_stack) { \ - max_in_stack = input_ptr; \ - if (input_ptr == stack_size) \ - overflow("input stack size", (unsigned) stack_size); \ - } \ - input_stack[input_ptr] = cur_input; \ - nofilter = false; \ - incr(input_ptr); - -/*tex - -Here is a procedure that starts a new level of token-list input, given a token -list |p| and its type |t|. If |t=macro|, the calling routine should set |name| -and |loc|. - -*/ - -void begin_token_list(halfword p, quarterword t) -{ - push_input(); - istate = token_list; - istart = p; - token_type = (unsigned char) t; - if (t >= macro) { - /*tex The token list starts with a reference count. */ - add_token_ref(p); - if (t == macro) { - param_start = param_ptr; - } else { - iloc = token_link(p); - if (tracing_macros_par > 1) { - begin_diagnostic(); - // tprint_nl(""); - print_input_level(); - if (t == mark_text) - tprint_esc("mark"); - else if (t == write_text) - tprint_esc("write"); - else - print_cmd_chr(assign_toks_cmd, t - output_text + output_routine_loc); - tprint("->"); - token_show(p); - end_diagnostic(false); - } - } - } else { - iloc = p; - } -} - -/*tex - -When a token list has been fully scanned, the following computations should be -done as we leave that level of input. The |token_type| tends to be equal to -either |backed_up| or |inserted| about 2/3 of the time. @^inner loop@> - -*/ - -void end_token_list(void) -{ - /*tex Leave a token-list input level: */ - if (token_type >= backed_up) { - /*tex The token list to be deleted: */ - if (token_type <= inserted) { - flush_list(istart); - } else { - /*tex Update the reference count: */ - delete_token_ref(istart); - if (token_type == macro) { - /*tex Parameters must be flushed: */ - while (param_ptr > param_start) { - decr(param_ptr); - flush_list(param_stack[param_ptr]); - } - } - } - } else if (token_type == u_template) { - if (align_state > 500000) - align_state = 0; - else - fatal_error("(interwoven alignment preambles are not allowed)"); - } - pop_input(); - check_interrupt(); -} - -/*tex - -Sometimes \TeX\ has read too far and wants to ``unscan'' what it has seen. The -|back_input| procedure takes care of this by putting the token just scanned back -into the input stream, ready to be read again. This procedure can be used only if -|cur_tok| represents the token to be replaced. Some applications of \TeX\ use -this procedure a lot, so it has been slightly optimized for speed. @^inner loop@> - -*/ - -/* undoes one token of input */ - -void back_input(void) -{ - /*tex A token list of length one: */ - halfword p; - while ((istate == token_list) && (iloc == null) && (token_type != v_template)) { - /*tex Conserve stack space. */ - end_token_list(); - } - p = get_avail(); - set_token_info(p, cur_tok); - if (cur_tok < right_brace_limit) { - if (cur_tok < left_brace_limit) - decr(align_state); - else - incr(align_state); - } - push_input(); - /*tex This is |back_list(p)|, without procedure overhead: */ - istate = token_list; - istart = p; - token_type = backed_up; - iloc = p; -} - -/*tex - -Insert token |p| into \TeX's input - -*/ - -void reinsert_token(boolean a, halfword pp) -{ - halfword t; - t = cur_tok; - cur_tok = pp; - if (a) { - halfword p; - p = get_avail(); - set_token_info(p, cur_tok); - set_token_link(p, iloc); - iloc = p; - istart = p; - if (cur_tok < right_brace_limit) { - if (cur_tok < left_brace_limit) - decr(align_state); - else - incr(align_state); - } - } else { - back_input(); - } - cur_tok = t; -} - -/*tex - -The |begin_file_reading| procedure starts a new level of input for lines of -characters to be read from a file, or as an insertion from the terminal. It does -not take care of opening the file, nor does it set |loc| or |limit| or |line|. -@^system dependencies@> - -*/ - -void begin_file_reading(void) -{ - if (in_open == max_in_open) - overflow("text input levels", (unsigned) max_in_open); - if (first == buf_size) - check_buffer_overflow(first); - incr(in_open); - push_input(); - iindex = (unsigned short)(in_open); - source_filename_stack[iindex] = 0; - full_source_filename_stack[iindex] = NULL; - eof_seen[iindex] = false; - grp_stack[iindex] = cur_boundary; - if_stack[iindex] = cond_ptr; - line_stack[iindex] = line; - istart = first; - istate = mid_line; - iname = 0; - /*tex Variable |terminal_input| is now |true|. */ - line_catcode_table = DEFAULT_CAT_TABLE; - line_partial = false; - /*tex Prepare terminal input \SYNCTEX\ information. */ - synctex_tag = 0; -} - -/*tex - -Conversely, the variables must be downdated when such a level of input is -finished: - -*/ - -void end_file_reading(void) -{ - first = istart; - line = line_stack[iindex]; - if ((iname >= 18) && (iname <= 20)) { - pseudo_close(); - } else if (iname == 21) { - luacstring_close(iindex); - } else if (iname > 17) { - /*tex Forget it. */ - lua_a_close_in(cur_file, 0); - source_filename_stack[iindex] = 0; - if (full_source_filename_stack[iindex] != NULL) { - free(full_source_filename_stack[iindex]); - full_source_filename_stack[iindex] = NULL; - } - } - pop_input(); - decr(in_open); -} - -/*tex - -In order to keep the stack from overflowing during a long sequence of -inserted `\.{\\show}' commands, the following routine removes completed -error-inserted lines from memory. - -*/ -void clear_for_error_prompt(void) -{ - while ((istate != token_list) && terminal_input && (input_ptr > 0) && (iloc > ilimit)) { - end_file_reading(); - } - print_ln(); - clear_terminal(); -} - -/*tex - -To get \TeX's whole input mechanism going, we perform the following actions. - -*/ - -void initialize_inputstack(void) -{ - input_ptr = 0; - max_in_stack = 0; - source_filename_stack[0] = 0; - - full_source_filename_stack[0] = NULL; - in_open = 0; - open_parens = 0; - max_buf_stack = 0; - - grp_stack[0] = 0; - if_stack[0] = null; - param_ptr = 0; - max_param_stack = 0; - first = buf_size; - do { - buffer[first] = 0; - decr(first); - } while (first != 0); - scanner_status = normal; - warning_index = null; - first = 1; - istate = new_line; - istart = 1; - iindex = 0; - line = 0; - iname = 0; - nofilter = false; - force_eof = false; - luacstrings = 0; - line_catcode_table = DEFAULT_CAT_TABLE; - line_partial = false; - align_state = 1000000; - if (!init_terminal()) { - /*tex |goto final_end|; */ - exit(EXIT_FAILURE); - } - /* |init_terminal| has set |loc| and |last| */ - ilimit = last; - first = last + 1; -} - -/*tex - -The global variable |pseudo_files| is used to maintain a stack of pseudo files. -The |pseudo_lines| field of each pseudo file points to a linked list of variable -size nodes representing lines not yet processed: the |subtype| field contains the -size of this node, all the following words contain ASCII codes. - -If this is really critical code (which it isn't) then we can consider a c stack -and store a pointer to a line in the line node instead which saves splitting here -and reconstructing later. - -*/ - -halfword pseudo_files; - -static halfword string_to_pseudo(str_number str, int nl) -{ - halfword i, r, q = null; - unsigned l, len; - four_quarters w; - int sz; - halfword h = new_node(pseudo_file_node, 0); - unsigned char *s = str_string(str); - len = (unsigned) str_length(str); - l = 0; - while (l < len) { - /*tex start of current line */ - unsigned m = l; - while ((l < len) && (s[l] != nl)) - l++; - sz = (int) (l - m + 7) / 4; - if (sz == 1) - sz = 2; - r = new_node(pseudo_line_node, sz); - i = r; - while (--sz > 1) { - w.b0 = s[m++]; - w.b1 = s[m++]; - w.b2 = s[m++]; - w.b3 = s[m++]; - varmem[++i].qqqq = w; - } - w.b0 = (quarterword) (l > m ? s[m++] : ' '); - w.b1 = (quarterword) (l > m ? s[m++] : ' '); - w.b2 = (quarterword) (l > m ? s[m++] : ' '); - w.b3 = (quarterword) (l > m ? s[m] : ' '); - varmem[++i].qqqq = w; - if (q == null) { - pseudo_lines(h) = r; - } else { - /*tex There is no |prev| node here so no need to couple_nodes! */ - vlink(q) = r ; - } - q = r ; - if (s[l] == nl) - l++; - } - return h; -} - -/*tex - -The |pseudo_start| procedure initiates reading from a pseudo file. - -*/ - -void pseudo_from_string(void) -{ - /*tex The string to be converted into a pseudo file: */ - str_number s; - /*tex A helper for list construction: */ - halfword p; - s = make_string(); - /*tex Convert string |s| into a new pseudo file */ - p = string_to_pseudo(s, new_line_char_par); - vlink(p) = pseudo_files; - pseudo_files = p; - flush_str(s); - /*tex - Initiate input from new pseudo file. It sets up |cur_file| and a new level - of input - */ - begin_file_reading(); - line = 0; - ilimit = istart; - /*tex force line read */ - iloc = ilimit + 1; - if (tracing_scan_tokens_par > 0) { - if (term_offset > max_print_line - 3) - print_ln(); - else if ((term_offset > 0) || (file_offset > 0)) - print_char(' '); - iname = 20; - tprint("( "); - incr(open_parens); - update_terminal(); - } else { - iname = 18; - } - /*tex Prepare pseudo file \SYNCTEX\ information. */ - synctex_tag = 0; -} - -void pseudo_start(void) -{ - int old_setting; - scan_general_text(); - old_setting = selector; - selector = new_string; - token_show(temp_token_head); - selector = old_setting; - flush_list(token_link(temp_token_head)); - str_room(1); - pseudo_from_string(); -} - -void lua_string_start(void) -{ - /*tex Set up |cur_file| and a new level of input: */ - begin_file_reading(); - line = 0; - ilimit = istart; - /*tex Force line read: */ - iloc = ilimit + 1; - iname = 21; - luacstring_start(iindex); -} - -/*tex - -Here we read a line from the current pseudo file into |buffer|. -It inputs the next line or returns |false|. - -*/ - -boolean pseudo_input(void) -{ - /*tex The current line from pseudo file: */ - halfword p; - /*tex The size of node |p|: */ - int sz; - /*tex Four ASCII codes: */ - four_quarters w; - /*tex The loop index: */ - halfword r; - /*tex cf.\ Matthew 19\thinspace:\thinspace30 */ - last = first; - p = pseudo_lines(pseudo_files); - if (p == null) { - return false; - } else { - pseudo_lines(pseudo_files) = vlink(p); - sz = subtype(p); - if (4 * sz - 3 >= buf_size - last) - check_buffer_overflow(last + 4 * sz); - last = first; - for (r = p + 1; r <= p + sz - 1; r++) { - w = varmem[r].qqqq; - buffer[last] = (packed_ASCII_code) w.b0; - buffer[last + 1] = (packed_ASCII_code) w.b1; - buffer[last + 2] = (packed_ASCII_code) w.b2; - buffer[last + 3] = (packed_ASCII_code) w.b3; - last += 4; - } - if (last >= max_buf_stack) - max_buf_stack = last + 1; - while ((last > first) && (buffer[last - 1] == ' ')) - decr(last); - flush_node(p); - } - return true; -} - -/*tex - -When we are done with a pseudo file we `close' it. - -*/ - -void pseudo_close(void) -{ - halfword p; - p = vlink(pseudo_files); - flush_node(pseudo_files); - pseudo_files = p; -} diff --git a/Build/source/texk/web2c/luatexdir/tex/inputstack.h b/Build/source/texk/web2c/luatexdir/tex/inputstack.h deleted file mode 100644 index 0c7669ff3c8..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/inputstack.h +++ /dev/null @@ -1,344 +0,0 @@ -/* inputstack.h - - Copyright 2009 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ - - -#ifndef INPUTSTACK_H -# define INPUTSTACK_H 1 - -/* - The state of \TeX's input mechanism appears in the input stack, whose - entries are records with six fields, called |state|, |index|, |start|, |loc|, - |limit|, and |name|. -*/ - -typedef struct in_state_record { - halfword start_field; - halfword loc_field; - halfword limit_field; - halfword name_field; - int synctex_tag_field; /* stack the tag of the current file */ - unsigned short state_field:16; - unsigned short index_field:16; - signed short cattable_field:16; /* category table used by the current line (see textoken.c) */ - boolean partial_field:8; /* is the current line partial? (see textoken.c) */ - boolean nofilter_field:8; /* used by token filtering */ -} in_state_record; - -extern in_state_record *input_stack; -extern int input_ptr; -extern int max_in_stack; -extern in_state_record cur_input; /* the ``top'' input state */ - -# define iloc cur_input.loc_field /* location of first unread character in |buffer| */ -# define istate cur_input.state_field /* current scanner state */ -# define iindex cur_input.index_field /* reference for buffer information */ -# define istart cur_input.start_field /* starting position in |buffer| */ -# define ilimit cur_input.limit_field /* end of current line in |buffer| */ -# define iname cur_input.name_field /* name of the current file */ -# define nofilter cur_input.nofilter_field /* is token filtering explicitly disallowed? */ -# define synctex_tag cur_input.synctex_tag_field /* tag of the current file */ -# define line_catcode_table cur_input.cattable_field -# define line_partial cur_input.partial_field - -/* -Let's look more closely now at the control variables -(|state|,~|index|,~|start|,~|loc|,~|limit|,~|name|), -assuming that \TeX\ is reading a line of characters that have been input -from some file or from the user's terminal. There is an array called -|buffer| that acts as a stack of all lines of characters that are -currently being read from files, including all lines on subsidiary -levels of the input stack that are not yet completed. \TeX\ will return to -the other lines when it is finished with the present input file. - -(Incidentally, on a machine with byte-oriented addressing, it might be -appropriate to combine |buffer| with the |str_pool| array, -letting the buffer entries grow downward from the top of the string pool -and checking that these two tables don't bump into each other.) - -The line we are currently working on begins in position |start| of the -buffer; the next character we are about to read is |buffer[loc]|; and -|limit| is the location of the last character present. If |loc>limit|, -the line has been completely read. Usually |buffer[limit]| is the -|end_line_char|, denoting the end of a line, but this is not -true if the current line is an insertion that was entered on the user's -terminal in response to an error message. - -The |name| variable is a string number that designates the name of -the current file, if we are reading a text file. It is zero if we -are reading from the terminal; it is |n+1| if we are reading from -input stream |n|, where |0<=n<=16|. (Input stream 16 stands for -an invalid stream number; in such cases the input is actually from -the terminal, under control of the procedure |read_toks|.) -Finally |18<=name<=20| indicates that we are reading a pseudo file -created by the \.{\\scantokens} or \.{\\scantextokens} command. - -The |state| variable has one of three values, when we are scanning such -files: -$$\baselineskip 15pt\vbox{\halign{#\hfil\cr -1) |state=mid_line| is the normal state.\cr -2) |state=skip_blanks| is like |mid_line|, but blanks are ignored.\cr -3) |state=new_line| is the state at the beginning of a line.\cr}}$$ -These state values are assigned numeric codes so that if we add the state -code to the next character's command code, we get distinct values. For -example, `|mid_line+spacer|' stands for the case that a blank -space character occurs in the middle of a line when it is not being -ignored; after this case is processed, the next value of |state| will -be |skip_blanks|. -*/ - -# define max_char_code 15 /* largest catcode for individual characters */ - -typedef enum { - mid_line = 1, /* |state| code when scanning a line of characters */ - skip_blanks = 2 + max_char_code, /* |state| code when ignoring blanks */ - new_line = 3 + max_char_code + max_char_code, /* |state| code at start of line */ -} state_codes; - -/* -Additional information about the current line is available via the -|index| variable, which counts how many lines of characters are present -in the buffer below the current level. We have |index=0| when reading -from the terminal and prompting the user for each line; then if the user types, -e.g., `\.{\\input paper}', we will have |index=1| while reading -the file \.{paper.tex}. However, it does not follow that |index| is the -same as the input stack pointer, since many of the levels on the input -stack may come from token lists. For example, the instruction `\.{\\input -paper}' might occur in a token list. - -The global variable |in_open| is equal to the |index| -value of the highest non-token-list level. Thus, the number of partially read -lines in the buffer is |in_open+1|, and we have |in_open=index| -when we are not reading a token list. - -If we are not currently reading from the terminal, or from an input -stream, we are reading from the file variable |input_file[index]|. We use -the notation |terminal_input| as a convenient abbreviation for |name=0|, -and |cur_file| as an abbreviation for |input_file[index]|. - -The global variable |line| contains the line number in the topmost -open file, for use in error messages. If we are not reading from -the terminal, |line_stack[index]| holds the line number for the -enclosing level, so that |line| can be restored when the current -file has been read. Line numbers should never be negative, since the -negative of the current line number is used to identify the user's output -routine in the |mode_line| field of the semantic nest entries. - -If more information about the input state is needed, it can be -included in small arrays like those shown here. For example, -the current page or segment number in the input file might be -put into a variable |@!page|, maintained for enclosing levels in -`\ignorespaces|@!page_stack:array[1..max_in_open] of integer|\unskip' -by analogy with |line_stack|. -@^system dependencies@> -*/ - -# define terminal_input (iname==0) /* are we reading from the terminal? */ -# define cur_file input_file[iindex] /* the current |alpha_file| variable */ - -extern int in_open; -extern int open_parens; -extern alpha_file *input_file; -extern int line; -extern int *line_stack; -extern str_number *source_filename_stack; -extern char **full_source_filename_stack; - -/* -Users of \TeX\ sometimes forget to balance left and right braces properly, -and one of the ways \TeX\ tries to spot such errors is by considering an -input file as broken into subfiles by control sequences that -are declared to be \.{\\outer}. - -A variable called |scanner_status| tells \TeX\ whether or not to complain -when a subfile ends. This variable has six possible values: - -\yskip\hang|normal|, means that a subfile can safely end here without incident. - -\yskip\hang|skipping|, means that a subfile can safely end here, but not a file, -because we're reading past some conditional text that was not selected. - -\yskip\hang|defining|, means that a subfile shouldn't end now because a -macro is being defined. - -\yskip\hang|matching|, means that a subfile shouldn't end now because a -macro is being used and we are searching for the end of its arguments. - -\yskip\hang|aligning|, means that a subfile shouldn't end now because we are -not finished with the preamble of an \.{\\halign} or \.{\\valign}. - -\yskip\hang|absorbing|, means that a subfile shouldn't end now because we are -reading a balanced token list for \.{\\message}, \.{\\write}, etc. - -\yskip\noindent -If the |scanner_status| is not |normal|, the variable |warning_index| points -to the |eqtb| location for the relevant control sequence name to print -in an error message. -*/ - -typedef enum { - skipping = 1, /* |scanner_status| when passing conditional text */ - defining = 2, /* |scanner_status| when reading a macro definition */ - matching = 3, /* |scanner_status| when reading macro arguments */ - aligning = 4, /* |scanner_status| when reading an alignment preamble */ - absorbing = 5, /* |scanner_status| when reading a balanced text */ -} scanner_states; - -extern int scanner_status; -extern pointer warning_index; -extern pointer def_ref; - -extern void runaway(void); - -/* -However, the discussion about input state really applies only to the -case that we are inputting from a file. There is another important case, -namely when we are currently getting input from a token list. In this case -|state=token_list|, and the conventions about the other state variables -are different: - -\yskip\hang|loc| is a pointer to the current node in the token list, i.e., -the node that will be read next. If |loc=null|, the token list has been -fully read. - -\yskip\hang|start| points to the first node of the token list; this node -may or may not contain a reference count, depending on the type of token -list involved. - -\yskip\hang|token_type|, which takes the place of |index| in the -discussion above, is a code number that explains what kind of token list -is being scanned. - -\yskip\hang|name| points to the |eqtb| address of the control sequence -being expanded, if the current token list is a macro. - -\yskip\hang|param_start|, which takes the place of |limit|, tells where -the parameters of the current macro begin in the |param_stack|, if the -current token list is a macro. - -\yskip\noindent The |token_type| can take several values, depending on -where the current token list came from: - -\yskip\hang|parameter|, if a parameter is being scanned; - -\hang|u_template|, if the \<u_j> part of an alignment -template is being scanned; - -\hang|v_template|, if the \<v_j> part of an alignment -template is being scanned; - -\hang|backed_up|, if the token list being scanned has been inserted as -`to be read again'. - -\hang|inserted|, if the token list being scanned has been inserted as -the text expansion of a \.{\\count} or similar variable; - -\hang|macro|, if a user-defined control sequence is being scanned; - -\hang|output_text|, if an \.{\\output} routine is being scanned; - -\hang|every_par_text|, if the text of \.{\\everypar} is being scanned; - -\hang|every_math_text|, if the text of \.{\\everymath} is being scanned; - -\hang|every_display_text|, if the text of \.{\\everydisplay} is being scanned; - -\hang|every_hbox_text|, if the text of \.{\\everyhbox} is being scanned; - -\hang|every_vbox_text|, if the text of \.{\\everyvbox} is being scanned; - -\hang|every_job_text|, if the text of \.{\\everyjob} is being scanned; - -\hang|every_cr_text|, if the text of \.{\\everycr} is being scanned; - -\hang|mark_text|, if the text of a \.{\\mark} is being scanned; - -\hang|write_text|, if the text of a \.{\\write} is being scanned. - -\yskip\noindent -The codes for |output_text|, |every_par_text|, etc., are equal to a constant -plus the corresponding codes for token list parameters |output_routine_loc|, -|every_par_loc|, etc. - -The token list begins with a reference count if and -only if |token_type>=macro|. -@^reference counts@> - -Since \eTeX's additional token list parameters precede |toks_base|, the -corresponding token types must precede |write_text|. -*/ - -# define token_list 0 /* |state| code when scanning a token list */ -# define token_type iindex /* type of current token list */ -# define param_start ilimit /* base of macro parameters in |param_stack| */ - - -typedef enum { - parameter = 0, /* |token_type| code for parameter */ - u_template = 1, /* |token_type| code for \<u_j> template */ - v_template = 2, /* |token_type| code for \<v_j> template */ - backed_up = 3, /* |token_type| code for text to be reread */ - inserted = 4, /* |token_type| code for inserted texts */ - macro = 5, /* |token_type| code for defined control sequences */ - output_text = 6, /* |token_type| code for output routines */ - every_par_text = 7, /* |token_type| code for \.{\\everypar} */ - every_math_text = 8, /* |token_type| code for \.{\\everymath} */ - every_display_text = 9, /* |token_type| code for \.{\\everydisplay} */ - every_hbox_text = 10, /* |token_type| code for \.{\\everyhbox} */ - every_vbox_text = 11, /* |token_type| code for \.{\\everyvbox} */ - every_job_text = 12, /* |token_type| code for \.{\\everyjob} */ - every_cr_text = 13, /* |token_type| code for \.{\\everycr} */ - mark_text = 14, /* |token_type| code for \.{\\topmark}, etc. */ - every_eof_text = 15, /* |token_type| code for \.{\\everyeof} */ - write_text = 16, /* |token_type| code for \.{\\write} */ - local_text = 17, /* |token_type| code for special purposed */ -} token_types; - -extern pointer *param_stack; -extern int param_ptr; -extern int max_param_stack; - -extern int align_state; - -extern int base_ptr; - -extern void show_context(void); -extern void set_trick_count(void); - -# define back_list(A) begin_token_list(A,backed_up) /* backs up a simple token list */ -# define ins_list(A) begin_token_list(A,inserted) /* inserts a simple token list */ - -extern void begin_token_list(halfword p, quarterword t); -extern void end_token_list(void); -extern void back_input(void); -extern void reinsert_token(boolean a, halfword pp); -extern void begin_file_reading(void); -extern void end_file_reading(void); -extern void clear_for_error_prompt(void); - -extern void initialize_inputstack(void); - -extern halfword pseudo_files; -extern void pseudo_from_string(void); -extern void pseudo_start(void); -extern void lua_string_start(void); -extern boolean pseudo_input(void); -extern void pseudo_close(void); - - -#endif diff --git a/Build/source/texk/web2c/luatexdir/tex/linebreak.c b/Build/source/texk/web2c/luatexdir/tex/linebreak.c deleted file mode 100644 index 646a5a771f7..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/linebreak.c +++ /dev/null @@ -1,2537 +0,0 @@ -/* - -Copyright 2006-2008 Taco Hoekwater <taco@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your -option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU General Public License along -with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" - -/*tex - - We come now to what is probably the most interesting algorithm of \TeX: the - mechanism for choosing the ``best possible'' breakpoints that yield the - individual lines of a paragraph. \TeX's line-breaking algorithm takes a given - horizontal list and converts it to a sequence of boxes that are appended to - the current vertical list. In the course of doing this, it creates a special - data structure containing three kinds of records that are not used elsewhere - in \TeX. Such nodes are created while a paragraph is being processed, and - they are destroyed afterwards; thus, the other parts of \TeX\ do not need to - know anything about how line-breaking is done. - - The method used here is based on an approach devised by Michael F. Plass and - the author in 1977, subsequently generalized and improved by the same two - people in 1980. A detailed discussion appears in {\sl SOFTWARE---Practice - \AM\ Experience \bf11} (1981), 1119--1184, where it is shown that the - line-breaking problem can be regarded as a special case of the problem of - computing the shortest path in an acyclic network. The cited paper includes - numerous examples and describes the history of line breaking as it has been - practiced by printers through the ages. The present implementation adds two - new ideas to the algorithm of 1980: Memory space requirements are - considerably reduced by using smaller records for inactive nodes than for - active ones, and arithmetic overflow is avoided by using ``delta distances'' - instead of keeping track of the total distance from the beginning of the - paragraph to the current point. - - The |line_break| procedure should be invoked only in horizontal mode; it - leaves that mode and places its output into the current vlist of the - enclosing vertical mode (or internal vertical mode). There is one explicit - parameter: |d| is true for partial paragraphs preceding display math mode; in - this case the amount of additional penalty inserted before the final line is - |display_widow_penalty| instead of |widow_penalty|. - - There are also a number of implicit parameters: The hlist to be broken starts - at |vlink(head)|, and it is nonempty. The value of |prev_graf| in the - enclosing semantic level tells where the paragraph should begin in the - sequence of line numbers, in case hanging indentation or \.{\\parshape} are - in use; |prev_graf| is zero unless this paragraph is being continued after a - displayed formula. Other implicit parameters, such as the |par_shape_ptr| and - various penalties to use for hyphenation, etc., appear in |eqtb|. - - After |line_break| has acted, it will have updated the current vlist and the - value of |prev_graf|. Furthermore, the global variable |just_box| will point - to the final box created by |line_break|, so that the width of this line can - be ascertained when it is necessary to decide whether to use - |above_display_skip| or |above_display_short_skip| before a displayed - formula. - -*/ - -/*tex The |hlist_node| for the last line of the new paragraph: */ - -halfword just_box; - -/*tex - - In it's complete form, |line_break| is a rather lengthy procedure---sort of a - small world unto itself---we must build it up little by little. Below you see - only the general outline. - - The main task performed here is to move the list from |head| to |temp_head| - and go into the enclosing semantic level. We also append the - \.{\\parfillskip} glue to the end of the paragraph, removing a space (or - other glue node) if it was there, since spaces usually precede blank lines - and instances of `\.{\$\$}'. The |par_fill_skip| is preceded by an infinite - penalty, so it will never be considered as a potential breakpoint. - - That code assumes that a |glue_node| and a |penalty_node| occupy the same - number of |mem|~words. - - Most other processing is delegated to external functions. - -*/ - -void line_break(boolean d, int line_break_context) -{ - /*tex Main direction of paragraph: */ - int paragraph_dir = 0; - halfword final_par_glue; - halfword start_of_par; - int callback_id; - /*tex this is for over/underfull box messages */ - pack_begin_line = cur_list.ml_field; - alink(temp_head) = null; - vlink(temp_head) = vlink(cur_list.head_field); - new_hyphenation(temp_head, cur_list.tail_field); - cur_list.tail_field = new_ligkern(temp_head, cur_list.tail_field); - if (is_char_node(cur_list.tail_field)) { - tail_append(new_penalty(inf_penalty,line_penalty)); - } else if (type(cur_list.tail_field) != glue_node) { - tail_append(new_penalty(inf_penalty,line_penalty)); - } else { - halfword t = alink(cur_list.tail_field); - flush_node(cur_list.tail_field); - cur_list.tail_field = t; - tail_append(new_penalty(inf_penalty,line_penalty)); - } - final_par_glue = new_param_glue(par_fill_skip_code); - couple_nodes(cur_list.tail_field, final_par_glue); - cur_list.tail_field = vlink(cur_list.tail_field); - lua_node_filter(pre_linebreak_filter_callback, line_break_context, temp_head, addressof(cur_list.tail_field)); - last_line_fill = cur_list.tail_field; - pop_nest(); - start_of_par = cur_list.tail_field; - callback_id = callback_defined(linebreak_filter_callback); - if (callback_id > 0) { - callback_id = lua_linebreak_callback(d, temp_head, addressof(cur_list.tail_field)); - if (callback_id > 0) { - /*tex find the correct value for the |just_box| */ - halfword box_search = cur_list.tail_field; - just_box = null; - if (box_search != null) { - do { - if (type(box_search) == hlist_node) { - just_box = box_search; - } - box_search = vlink(box_search); - } while (box_search != null); - } - if (just_box == null) { - help3( - "A linebreaking routine should return a non-empty list of nodes", - "and at least one of those has to be a \\hbox.", - "Sorry, I cannot recover from this." - ); - print_err("Invalid linebreak_filter"); - succumb(); - } - } else { - if (tracing_paragraphs_par > 0) { - begin_diagnostic(); - print_int(line); - end_diagnostic(true); - } - } - } - if (callback_id == 0) { - if ((!is_char_node(vlink(temp_head))) && ((type(vlink(temp_head)) == local_par_node))) { - paragraph_dir = local_par_dir(vlink(temp_head)); - } else { - confusion("weird par dir"); - } - ext_do_line_break( - paragraph_dir, - pretolerance_par, - tracing_paragraphs_par, - tolerance_par, - emergency_stretch_par, - looseness_par, - adjust_spacing_par, - par_shape_par_ptr, - adj_demerits_par, - protrude_chars_par, - line_penalty_par, - last_line_fit_par, - double_hyphen_demerits_par, - final_hyphen_demerits_par, - hang_indent_par, - hsize_par, - hang_after_par, - left_skip_par, - right_skip_par, - inter_line_penalties_par_ptr, - inter_line_penalty_par, - club_penalty_par, - club_penalties_par_ptr, - (d ? display_widow_penalties_par_ptr : widow_penalties_par_ptr), - (d ? display_widow_penalty_par : widow_penalty_par), - broken_penalty_par, - final_par_glue - ); - } - lua_node_filter(post_linebreak_filter_callback, line_break_context, start_of_par, addressof(cur_list.tail_field)); - pack_begin_line = 0; -} - -/*tex - - Glue nodes in a horizontal list that is being paragraphed are not supposed to - include ``infinite'' shrinkability; that is why the algorithm maintains four - registers for stretching but only one for shrinking. If the user tries to - introduce infinite shrinkability, the shrinkability will be reset to finite - and an error message will be issued. A boolean variable |no_shrink_error_yet| - prevents this error message from appearing more than once per paragraph. - -*/ - -#define check_shrinkage(a) \ - if ((shrink_order((a))!=normal)&&(shrink((a))!=0)) \ - a=finite_shrink((a)) - -/*tex Have we complained about infinite shrinkage? */ - -static boolean no_shrink_error_yet; - -/*tex Recovers from infinite shrinkage. */ - -static halfword finite_shrink(halfword p) -{ - const char *hlp[] = { - "The paragraph just ended includes some glue that has", - "infinite shrinkability, e.g., `\\hskip 0pt minus 1fil'.", - "Such glue doesn't belong there---it allows a paragraph", - "of any length to fit on one line. But it's safe to proceed,", - "since the offensive shrinkability has been made finite.", - NULL - }; - if (no_shrink_error_yet) { - no_shrink_error_yet = false; - tex_error("Infinite glue shrinkage found in a paragraph", hlp); - } - shrink_order(p) = normal; - return p; -} - -/*tex - - A pointer variable |cur_p| runs through the given horizontal list as we look - for breakpoints. This variable is global, since it is used both by - |line_break| and by its subprocedure |try_break|. - - Another global variable called |threshold| is used to determine the - feasibility of individual lines: breakpoints are feasible if there is a way - to reach them without creating lines whose badness exceeds |threshold|. (The - badness is compared to |threshold| before penalties are added, so that - penalty values do not affect the feasibility of breakpoints, except that no - break is allowed when the penalty is 10000 or more.) If |threshold| is 10000 - or more, all legal breaks are considered feasible, since the |badness| - function specified above never returns a value greater than~10000. - - Up to three passes might be made through the paragraph in an attempt to find - at least one set of feasible breakpoints. On the first pass, we have - |threshold=pretolerance| and |second_pass=final_pass=false|. If this pass - fails to find a feasible solution, |threshold| is set to |tolerance|, - |second_pass| is set |true|, and an attempt is made to hyphenate as many - words as possible. If that fails too, we add |emergency_stretch| to the - background stretchability and set |final_pass=true|. - -*/ - -/*tex is this our second attempt to break this paragraph? */ - -static boolean second_pass; - -/*tex is this our final attempt to break this paragraph? */ - -static boolean final_pass; - -/*tex maximum badness on feasible lines */ - -static int threshold; - -/*tex - - The maximum fill level for |hlist_stack|. Maybe good if larger than |2 * - max_quarterword|, so that box nesting level would overflow first. - -*/ - -#define max_hlist_stack 512 - -/*tex stack for |find_protchar_left()| and |find_protchar_right()| */ - -static halfword hlist_stack[max_hlist_stack]; - -/*tex fill level for |hlist_stack| */ - -static short hlist_stack_level = 0; - -static void push_node(halfword p) -{ - if (hlist_stack_level >= max_hlist_stack) - normal_error("push_node","stack overflow"); - hlist_stack[hlist_stack_level++] = p; -} - -static halfword pop_node(void) -{ - if (hlist_stack_level <= 0) { - /*tex This can point to some bug. */ - normal_error("pop_node","stack underflow (internal error)"); - } - return hlist_stack[--hlist_stack_level]; -} - -/*tex maximal stretch ratio of expanded fonts */ - -static int max_stretch_ratio = 0; - -/*tex maximal shrink ratio of expanded fonts */ - -static int max_shrink_ratio = 0; - -/*tex the current step of expanded fonts */ - -static int cur_font_step = 0; - -static boolean check_expand_pars(internal_font_number f) -{ - int m; - if ((font_step(f) == 0) || ((font_max_stretch(f) == 0) && (font_max_shrink(f) == 0))) - return false; - if (cur_font_step < 0) - cur_font_step = font_step(f); - else if (cur_font_step != font_step(f)) - normal_error("font expansion","using fonts with different step of expansion in one paragraph is not allowed"); - m = font_max_stretch(f); - if (m != 0) { - if (max_stretch_ratio < 0) - max_stretch_ratio = m; - else if (max_stretch_ratio != m) - normal_error("font expansion","using fonts with different limit of expansion in one paragraph is not allowed"); - } - m = font_max_shrink(f); - if (m != 0) { - if (max_shrink_ratio < 0) - max_shrink_ratio = -m; - else if (max_shrink_ratio != -m) - normal_error("font expansion","using fonts with different limit of expansion in one paragraph is not allowed"); - } - return true; -} - -/*tex Search left to right from list head |l|, returns 1st non-skipable item */ - -halfword find_protchar_left(halfword l, boolean d) -{ - halfword t; - boolean run; - boolean done = false ; - while ((vlink(l) != null) && (type(l) == hlist_node) && zero_dimensions(l) && (list_ptr(l) == null)) { - /*tex For paragraph start with \.{\\parindent} = 0pt or any empty hbox. */ - l = vlink(l); - done = true ; - } - if ((!done) && (type(l) == local_par_node)) { - l = vlink(l); - done = true ; - } - if ((!done) && d) { - while ((vlink(l) != null) && (!(is_char_node(l) || non_discardable(l)))) { - /*tex standard discardables at line break, \TeX book, p 95 */ - l = vlink(l); - } - } - if (type(l) != glyph_node) { - hlist_stack_level = 0; - run = true; - do { - t = l; - while (run && (type(l) == hlist_node) && (list_ptr(l) != null)) { - push_node(l); - l = list_ptr(l); - } - while (run && cp_skipable(l)) { - while ((vlink(l) == null) && (hlist_stack_level > 0)) { - /*tex Don't visit this node again. */ - l = pop_node(); - run = false; - } - if ((vlink(l) != null) && (type(l) == boundary_node) && (subtype(l) == protrusion_boundary) && - ((boundary_value(l) == 1) || (boundary_value(l) == 3))) { - /*tex Skip next node. */ - l = vlink(l); - } - if (vlink(l) != null) { - l = vlink(l); - } else if (hlist_stack_level == 0) { - run = false; - } - } - } while (t != l); - } - return l; -} - -/*tex - - Search right to left from list tail |r| to head |l|, returns 1st non-skipable - item. - -*/ - -halfword find_protchar_right(halfword l, halfword r) -{ - halfword t; - boolean run = true; - if (r == null) - return null; - hlist_stack_level = 0; - do { - t = r; - while (run && (type(r) == hlist_node) && (list_ptr(r) != null)) { - push_node(l); - push_node(r); - l = list_ptr(r); - r = l; - while (vlink(r) != null) { - halfword s = r; - r = vlink(r); - alink(r) = s; - } - } - while (run && cp_skipable(r)) { - while ((r == l) && (hlist_stack_level > 0)) { - /*tex Don't visit this node again. */ - r = pop_node(); - l = pop_node(); - } - if ((r != l) && (r != null)) { - if ((alink(r) != null) && (type(r) == boundary_node) && (subtype(r) == protrusion_boundary) && - ((boundary_value(r) == 2) || (boundary_value(r) == 3))) { - /*tex Skip next node. */ - r = alink(r); - } - if (alink(r) != null) { - r = alink(r); - } else { - /*tex This is the input: \.{\\leavevmode\\penalty-10000\\penalty-10000} (bug \#268). */ - run = false; - } - } else if ((r == l) && (hlist_stack_level == 0)) - run = false; - } - } while (t != r); - return r; -} - -#define left_pw(a) char_pw((a), left_side) -#define right_pw(a) char_pw((a), right_side) - -/*tex - - When looking for optimal line breaks, \TeX\ creates a ``break node'' for each - break that is {\sl feasible}, in the sense that there is a way to end a line - at the given place without requiring any line to stretch more than a given - tolerance. A break node is characterized by three things: the position of the - break (which is a pointer to a |glue_node|, |math_node|, |penalty_node|, or - |disc_node|); the ordinal number of the line that will follow this - breakpoint; and the fitness classification of the line that has just ended, - i.e., |tight_fit|, |decent_fit|, |loose_fit|, or |very_loose_fit|. - -*/ - -typedef enum { - /*tex fitness classification for lines stretching more than their stretchability */ - very_loose_fit = 0, - /*tex fitness classification for lines stretching 0.5 to 1.0 of their stretchability */ - loose_fit, - /*tex fitness classification for all other lines */ - decent_fit, - /*tex fitness classification for lines shrinking 0.5 to 1.0 of their shrinkability */ - tight_fit -} fitness_value; - -/*tex - - The algorithm essentially determines the best possible way to achieve each - feasible combination of position, line, and fitness. Thus, it answers - questions like, ``What is the best way to break the opening part of the - paragraph so that the fourth line is a tight line ending at such-and-such a - place?'' However, the fact that all lines are to be the same length after a - certain point makes it possible to regard all sufficiently large line numbers - as equivalent, when the looseness parameter is zero, and this makes it - possible for the algorithm to save space and time. - - An ``active node'' and a ``passive node'' are created in |mem| for each - feasible breakpoint that needs to be considered. Active nodes are three words - long and passive nodes are two words long. We need active nodes only for - breakpoints near the place in the paragraph that is currently being examined, - so they are recycled within a comparatively short time after they are - created. - - An active node for a given breakpoint contains six fields: - - \startitemize[n] - - \startitem - |vlink| points to the next node in the list of active nodes; the last - active node has |vlink=active|. - \stopitem - - \startitem - |break_node| points to the passive node associated with this - breakpoint. - \stopitem - - \startitem - |line_number| is the number of the line that follows this breakpoint. - \stopitem - - \startitem - |fitness| is the fitness classification of the line ending at this - breakpoint. - \stopitem - - \startitem - |type| is either |hyphenated_node| or |unhyphenated_node|, depending - on whether this breakpoint is a |disc_node|. - \stopitem - - \startitem - |total_demerits| is the minimum possible sum of demerits over all - lines leading from the beginning of the paragraph to this breakpoint. - \stopitem - - \stopitemize - - The value of |vlink(active)| points to the first active node on a vlinked - list of all currently active nodes. This list is in order by |line_number|, - except that nodes with |line_number>easy_line| may be in any order relative - to each other. - -*/ - -void initialize_active(void) -{ - type(active) = hyphenated_node; - line_number(active) = max_halfword; - /*tex The |subtype| is never examined. */ - subtype(active) = 0; -} - -/*tex - - The passive node for a given breakpoint contains eight fields: - - \startitemize - - \startitem - |vlink| points to the passive node created just before this one, if - any, otherwise it is |null|. - \stopitem - - \startitem - |cur_break| points to the position of this breakpoint in the - horizontal list for the paragraph being broken. - \stopitem - - \startitem - |prev_break| points to the passive node that should precede this one - in an optimal path to this breakpoint. - \stopitem - - \startitem - |serial| is equal to |n| if this passive node is the |n|th one - created during the current pass. (This field is used only when - printing out detailed statistics about the line-breaking - calculations.) - \stopitem - - \startitem - |passive_pen_inter| holds the current \.{\\localinterlinepenalty} - \stopitem - - \startitem - |passive_pen_broken| holds the current \.{\\localbrokenpenalty} - \stopitem - - \stopitemize - - There is a global variable called |passive| that points to the most recently - created passive node. Another global variable, |printed_node|, is used to - help print out the paragraph when detailed information about the - line-breaking computation is being displayed. - -*/ - -/*tex most recent node on passive list */ - -static halfword passive; - -/*tex most recent node that has been printed */ - -static halfword printed_node; - -/*tex the number of passive nodes allocated on this pass */ - -static halfword pass_number; - -/*tex - - The active list also contains ``delta'' nodes that help the algorithm compute - the badness of individual lines. Such nodes appear only between two active - nodes, and they have |type=delta_node|. If |p| and |r| are active nodes and - if |q| is a delta node between them, so that |vlink(p)=q| and |vlink(q)=r|, - then |q| tells the space difference between lines in the horizontal list that - start after breakpoint |p| and lines that start after breakpoint |r|. In - other words, if we know the length of the line that starts after |p| and ends - at our current position, then the corresponding length of the line that - starts after |r| is obtained by adding the amounts in node~|q|. A delta node - contains seven scaled numbers, since it must record the net change in glue - stretchability with respect to all orders of infinity. The natural width - difference appears in |mem[q+1].sc|; the stretch differences in units of pt, - sfi, fil, fill, and filll appear in |mem[q+2..q+6].sc|; and the shrink - difference appears in |mem[q+7].sc|. The |subtype| field of a delta node is - not used. - - Actually, we have two more fields that are used by |pdftex|. - - As the algorithm runs, it maintains a set of seven delta-like registers for - the length of the line following the first active breakpoint to the current - position in the given hlist. When it makes a pass through the active list, it - also maintains a similar set of seven registers for the length following the - active breakpoint of current interest. A third set holds the length of an - empty line (namely, the sum of \.{\\leftskip} and \.{\\rightskip}); and a - fourth set is used to create new delta nodes. - - When we pass a delta node we want to do operations like: - - \starttyping - for k := 1 to 7 do - cur_active_width[k] := cur_active_width[k] + mem[q+k].sc|}; - \stoptyping - - and we want to do this without the overhead of |for| loops. The |do_all_six| - macro makes such six-tuples convenient. - -*/ - -/*tex distance from first active node to~|cur_p| */ - -static scaled active_width[10] = { 0 }; - -/*tex length of an ``empty'' line */ - -static scaled background[10] = { 0 }; - -/*tex length being computed after current break */ - -static scaled break_width[10] = { 0 }; - -/*tex Make |auto_breaking| accessible out of |line_break|: */ - -static boolean auto_breaking; - -/*tex - - Let's state the principles of the delta nodes more precisely and concisely, - so that the following programs will be less obscure. For each legal - breakpoint~|p| in the paragraph, we define two quantities $\alpha(p)$ and - $\beta(p)$ such that the length of material in a line from breakpoint~|p| to - breakpoint~|q| is $\gamma+\beta(q)-\alpha(p)$, for some fixed $\gamma$. - Intuitively, $\alpha(p)$ and $\beta(q)$ are the total length of material from - the beginning of the paragraph to a point ``after'' a break at |p| and to a - point ``before'' a break at |q|; and $\gamma$ is the width of an empty line, - namely the length contributed by \.{\\leftskip} and \.{\\rightskip}. - - Suppose, for example, that the paragraph consists entirely of alternating - boxes and glue skips; let the boxes have widths $x_1\ldots x_n$ and let the - skips have widths $y_1\ldots y_n$, so that the paragraph can be represented - by $x_1y_1\ldots x_ny_n$. Let $p_i$ be the legal breakpoint at $y_i$; then - $\alpha(p_i)=x_1+y_1+\cdots+x_i+y_i$, and $\beta(p_i)= x_1+y_1+\cdots+x_i$. - To check this, note that the length of material from $p_2$ to $p_5$, say, is - $\gamma+x_3+y_3+x_4+y_4+x_5=\gamma+\beta(p_5) -\alpha(p_2)$. - - The quantities $\alpha$, $\beta$, $\gamma$ involve glue stretchability and - shrinkability as well as a natural width. If we were to compute $\alpha(p)$ - and $\beta(p)$ for each |p|, we would need multiple precision arithmetic, and - the multiprecise numbers would have to be kept in the active nodes. \TeX\ - avoids this problem by working entirely with relative differences or - ``deltas.'' Suppose, for example, that the active list contains - $a_1\,\delta_1\,a_2\,\delta_2\,a_3$, where the |a|'s are active breakpoints - and the $\delta$'s are delta nodes. Then $\delta_1=\alpha(a_1)-\alpha(a_2)$ - and $\delta_2=\alpha(a_2)-\alpha(a_3)$. If the line breaking algorithm is - currently positioned at some other breakpoint |p|, the |active_width| array - contains the value $\gamma+\beta(p)-\alpha(a_1)$. If we are scanning through - the list of active nodes and considering a tentative line that runs from - $a_2$ to~|p|, say, the |cur_active_width| array will contain the value - $\gamma+\beta(p)-\alpha(a_2)$. Thus, when we move from $a_2$ to $a_3$, we - want to add $\alpha(a_2)-\alpha(a_3)$ to |cur_active_width|; and this is just - $\delta_2$, which appears in the active list between $a_2$ and $a_3$. The - |background| array contains $\gamma$. The |break_width| array will be used to - calculate values of new delta nodes when the active list is being updated. - - The heart of the line-breaking procedure is `|try_break|', a subroutine that - tests if the current breakpoint |cur_p| is feasible, by running through the - active list to see what lines of text can be made from active nodes - to~|cur_p|. If feasible breaks are possible, new break nodes are created. If - |cur_p| is too far from an active node, that node is deactivated. - - The parameter |pi| to |try_break| is the penalty associated with a break at - |cur_p|; we have |pi=eject_penalty| if the break is forced, and - |pi=inf_penalty| if the break is illegal. - - The other parameter, |break_type|, is set to |hyphenated_node| or - |unhyphenated_node|, depending on whether or not the current break is at a - |disc_node|. The end of a paragraph is also regarded as `|hyphenated_node|'; - this case is distinguishable by the condition |cur_p=null|. - -*/ - -/*tex running \.{\\localinterlinepenalty} */ - -static int internal_pen_inter; - -/*tex running \.{\\localbrokenpenalty} */ - -static int internal_pen_broken; - -/*tex running \.{\\localleftbox} */ - -static halfword internal_left_box; - -/*tex running \.{\\localleftbox} width */ - -static int internal_left_box_width; - -/*tex running \.{\\localleftbox} */ - -static halfword init_internal_left_box; - -/*tex running \.{\\localleftbox} width */ - -static int init_internal_left_box_width; - -/*tex running \.{\\localrightbox} */ - -static halfword internal_right_box; - -/*tex running \.{\\localrightbox} width */ - -static int internal_right_box_width; - -/*tex the length of discretionary material preceding a break */ - -static scaled disc_width[10] = { 0 }; - -/*tex - - As we consider various ways to end a line at |cur_p|, in a given line number - class, we keep track of the best total demerits known, in an array with one - entry for each of the fitness classifications. For example, - |minimal_demerits[tight_fit]| contains the fewest total demerits of feasible - line breaks ending at |cur_p| with a |tight_fit| line; - |best_place[tight_fit]| points to the passive node for the break - before~|cur_p| that achieves such an optimum; and |best_pl_line[tight_fit]| - is the |line_number| field in the active node corresponding to - |best_place[tight_fit]|. When no feasible break sequence is known, the - |minimal_demerits| entries will be equal to |awful_bad|, which is $2^{30}-1$. - Another variable, |minimum_demerits|, keeps track of the smallest value in - the |minimal_demerits| array. - -*/ - -/*tex best total demerits known for current line class and position, given the fitness */ - -static int minimal_demerits[4]; - -/*tex best total demerits known for current line class and position */ - -static int minimum_demerits; - -/*tex how to achieve |minimal_demerits| */ - -static halfword best_place[4]; - -/*tex corresponding line number */ - -static halfword best_pl_line[4]; - -/*tex - - The length of lines depends on whether the user has specified \.{\\parshape} - or \.{\\hangindent}. If |par_shape_ptr| is not null, it points to a - $(2n+1)$-word record in |mem|, where the |vinfo| in the first word contains - the value of |n|, and the other $2n$ words contain the left margins and line - lengths for the first |n| lines of the paragraph; the specifications for line - |n| apply to all subsequent lines. If |par_shape_ptr=null|, the shape of the - paragraph depends on the value of |n=hang_after|; if |n>=0|, hanging - indentation takes place on lines |n+1|, |n+2|, \dots, otherwise it takes - place on lines 1, \dots, $\vert n\vert$. When hanging indentation is active, - the left margin is |hang_indent|, if |hang_indent>=0|, else it is 0; the line - length is $|hsize|-\vert|hang_indent|\vert$. The normal setting is - |par_shape_ptr=null|, |hang_after=1|, and |hang_indent=0|. Note that if - |hang_indent=0|, the value of |hang_after| is irrelevant. - -*/ - -/*tex line numbers |>easy_line| are equivalent in break nodes */ - -static halfword easy_line; - -/*tex line numbers |>last_special_line| all have the same width */ - -static halfword last_special_line; - -/*tex the width of all lines |<=last_special_line|, if no \.{\\parshape} has been specified */ - -static scaled first_width; - -/*tex the width of all lines |>last_special_line| */ - -static scaled second_width; - -/*tex left margin to go with |first_width| */ - -static scaled first_indent; - -/*tex left margin to go with |second_width| */ - -static scaled second_indent; - -/*tex use this passive node and its predecessors */ - -static halfword best_bet; - -/*tex the demerits associated with |best_bet| */ - -static int fewest_demerits; - -/*tex line number following the last line of the new paragraph */ - -static halfword best_line; - -/*tex the difference between |line_number(best_bet)| and the optimum |best_line| */ - -static int actual_looseness; - -/*tex the difference between the current line number and the optimum |best_line| */ - -static int line_diff; - -/*tex - - \TeX\ makes use of the fact that |hlist_node|, |vlist_node|, |rule_node|, - |ins_node|, |mark_node|, |adjust_node|, |disc_node|, |whatsit_node|, and - |math_node| are at the low end of the type codes, by permitting a break at - glue in a list if and only if the |type| of the previous node is less than - |math_node|. Furthermore, a node is discarded after a break if its type is - |math_node| or~more. - -*/ - -#define do_all_six(a) a(1);a(2);a(3);a(4);a(5);a(6);a(7) -#define do_seven_eight(a) if (adjust_spacing > 1) { a(8);a(9); } -#define do_all_eight(a) do_all_six(a); do_seven_eight(a) -#define do_one_seven_eight(a) a(1); do_seven_eight(a) - -#define store_background(a) {active_width[a]=background[a];} - -#define kern_break() { \ - if ((!is_char_node(vlink(cur_p))) && auto_breaking) \ - if (type(vlink(cur_p))==glue_node) \ - ext_try_break(\ - 0, \ - unhyphenated_node, \ - line_break_dir, \ - adjust_spacing, \ - par_shape_ptr, \ - adj_demerits, \ - tracing_paragraphs, \ - protrude_chars, \ - line_penalty, \ - last_line_fit, \ - double_hyphen_demerits, \ - final_hyphen_demerits, \ - first_p, \ - cur_p \ - ); \ - if (type(cur_p)!=math_node) \ - active_width[1] += width(cur_p); \ - else \ - active_width[1] += surround(cur_p); \ -} - -#define clean_up_the_memory() { \ - q=vlink(active); \ - while (q!=active) { \ - cur_p = vlink(q); \ - if (type(q)==delta_node) \ - flush_node(q); \ - else \ - flush_node(q); \ - q = cur_p; \ - } \ - q = passive; \ - while (q!=null) { \ - cur_p = vlink(q); \ - flush_node(q); \ - q = cur_p; \ - } \ -} - -/*tex special algorithm for last line of paragraph? */ - -static boolean do_last_line_fit; - -/*tex infinite stretch components of |par_fill_skip| */ - -static scaled fill_width[4]; - -/*tex |shortfall| corresponding to |minimal_demerits| */ - -static scaled best_pl_short[4]; - -/*tex corresponding glue stretch or shrink */ - -static scaled best_pl_glue[4]; - -#define reset_disc_width(a) disc_width[(a)] = 0 - -#define add_disc_width_to_break_width(a) break_width[(a)] += disc_width[(a)] -#define sub_disc_width_from_active_width(a) active_width[(a)] -= disc_width[(a)] - -#define add_char_shrink(a,b) a += char_shrink((b)) -#define add_char_stretch(a,b) a += char_stretch((b)) -#define sub_char_shrink(a,b) a -= char_shrink((b)) -#define sub_char_stretch(a,b) a -= char_stretch((b)) - -#define add_kern_shrink(a,b) a += kern_shrink((b)) -#define add_kern_stretch(a,b) a += kern_stretch((b)) -#define sub_kern_shrink(a,b) a -= kern_shrink((b)) -#define sub_kern_stretch(a,b) a -= kern_stretch((b)) - -/*tex - - This function is used to add the width of a list of nodes (from a - discretionary) to one of the width arrays. - - Replacement texts and discretionary texts are supposed to contain only - character nodes, kern nodes, and box or rule nodes. - -*/ - -#define bad_node_in_disc_error(p) { \ - if (type(p) == whatsit_node) { \ - formatted_error("linebreak","invalid node with type %s and subtype %i found in discretionary",node_data[type(p)].name,subtype(p)); \ - } else { \ - formatted_error("linebreak","invalid node with type %s found in discretionary",node_data[type(p)].name); \ - } \ -} - -static void add_to_widths(halfword s, int line_break_dir, int adjust_spacing, scaled * widths) -{ - while (s != null) { - if (is_char_node(s)) { - widths[1] += pack_width(line_break_dir, dir_TRT, s, true); - if ((adjust_spacing > 1) && check_expand_pars(font(s))) { - set_prev_char_p(s); - add_char_stretch(widths[8], s); - add_char_shrink(widths[9], s); - }; - } else { - switch (type(s)) { - case hlist_node: - case vlist_node: - widths[1] += pack_width(line_break_dir, box_dir(s), s, false); - break; - case kern_node: - if ((adjust_spacing == 2) && (subtype(s) == normal)) { - add_kern_stretch(widths[8], s); - add_kern_shrink(widths[9], s); - } - /*tex fall through */ - case rule_node: - widths[1] += width(s); - break; - case disc_node: - break; - default: - bad_node_in_disc_error(s); - break; - } - } - s = vlink(s); - } -} - -/*tex - - This function is used to substract the width of a list of nodes (from a - discretionary) from one of the width arrays. It is used only once, but - deserves it own function because of orthogonality with the |add_to_widths| - function. - -*/ - -static void sub_from_widths(halfword s, int line_break_dir, int adjust_spacing, scaled * widths) -{ - while (s != null) { - /*tex Subtract the width of node |s| from |break_width|; */ - if (is_char_node(s)) { - widths[1] -= pack_width(line_break_dir, dir_TRT, s, true); - if ((adjust_spacing > 1) && check_expand_pars(font(s))) { - set_prev_char_p(s); - sub_char_stretch(widths[8], s); - sub_char_shrink(widths[9], s); - } - } else { - switch (type(s)) { - case hlist_node: - case vlist_node: - widths[1] -= pack_width(line_break_dir, box_dir(s), s, false); - break; - case kern_node: - if ((adjust_spacing == 2) && (subtype(s) == normal)) { - sub_kern_stretch(widths[8], s); - sub_kern_shrink(widths[9], s); - } - /*tex fall through */ - case rule_node: - widths[1] -= width(s); - break; - case disc_node: - break; - default: - bad_node_in_disc_error(s); - break; - } - } - s = vlink(s); - } -} - -/*tex - - When we insert a new active node for a break at |cur_p|, suppose this new - node is to be placed just before active node |a|; then we essentially want to - insert `$\delta\,|cur_p|\,\delta^\prime$' before |a|, where - $\delta=\alpha(a)-\alpha(|cur_p|)$ and - $\delta^\prime=\alpha(|cur_p|)-\alpha(a)$ in the notation explained above. - The |cur_active_width| array now holds $\gamma+\beta(|cur_p|)-\alpha(a)$; so - $\delta$ can be obtained by subtracting |cur_active_width| from the quantity - $\gamma+\beta(|cur_p|)- \alpha(|cur_p|)$. The latter quantity can be regarded - as the length of a line ``from |cur_p| to |cur_p|''; we call it the - |break_width| at |cur_p|. - - The |break_width| is usually negative, since it consists of the background - (which is normally zero) minus the width of nodes following~|cur_p| that are - eliminated after a break. If, for example, node |cur_p| is a glue node, the - width of this glue is subtracted from the background; and we also look ahead - to eliminate all subsequent glue and penalty and kern and math nodes, - subtracting their widths as well. - - Kern nodes do not disappear at a line break unless they are |explicit|. - -*/ - -static void compute_break_width(int break_type, int line_break_dir, int adjust_spacing, halfword p) -{ - /*tex - - Glue and other 'whitespace' to be skipped after a break; used if - unhyphenated, or |post_break==empty|. - - */ - halfword s = p; - if (break_type > unhyphenated_node && p != null) { - /*tex - - Compute the discretionary |break_width| values. - - When |p| is a discretionary break, the length of a line ``from |p| to - |p|'' has to be defined properly so that the other calculations work - out. Suppose that the pre-break text at |p| has length $l_0$, the - post-break text has length $l_1$, and the replacement text has length - |l|. Suppose also that |q| is the node following the replacement - text. Then length of a line from |p| to |q| will be computed as - $\gamma+\beta(q)-\alpha(|p|)$, where $\beta(q)=\beta(|p|)-l_0+l$. The - actual length will be the background plus $l_1$, so the length from - |p| to |p| should be $\gamma+l_0+l_1-l$. If the post-break text of - the discretionary is empty, a break may also discard~|q|; in that - unusual case we subtract the length of~|q| and any other nodes that - will be discarded after the discretionary break. - - The value of $l_0$ need not be computed, since |line_break| will put - it into the global variable |disc_width| before calling |try_break|. - - In case of nested discretionaries, we always follow the no-break - path, as we are talking about the breaking on {\it this} position. - - */ - sub_from_widths(vlink_no_break(p), line_break_dir, adjust_spacing, break_width); - add_to_widths(vlink_post_break(p), line_break_dir, adjust_spacing, break_width); - do_one_seven_eight(add_disc_width_to_break_width); - if (vlink_post_break(p) == null) { - /*tex no |post_break|: 'skip' any 'whitespace' following */ - s = vlink(p); - } else { - s = null; - } - } - while (s != null) { - switch (type(s)) { - case math_node: - /*tex begin mathskip code */ - if (glue_is_zero(s)) { - break_width[1] -= surround(s); - break; - } else { - /*tex fall through */ - } - /*tex end mathskip code */ - case glue_node: - /*tex Subtract glue from |break_width|; */ - break_width[1] -= width(s); - break_width[2 + stretch_order(s)] -= stretch(s); - break_width[7] -= shrink(s); - break; - case penalty_node: - break; - case kern_node: - if (subtype(s) != explicit_kern && subtype(s) != italic_kern) - return; - else - break_width[1] -= width(s); - break; - default: - return; - }; - s = vlink(s); - } -} - -static void print_break_node(halfword q, fitness_value fit_class, quarterword break_type, halfword cur_p) -{ - /*tex Print a symbolic description of the new break node. */ - tprint_nl("@@"); - print_int(serial(passive)); - tprint(": line "); - print_int(line_number(q) - 1); - print_char('.'); - print_int(fit_class); - if (break_type == hyphenated_node) - print_char('-'); - tprint(" t="); - print_int(total_demerits(q)); - if (do_last_line_fit) { - /*tex Print additional data in the new active node. */ - tprint(" s="); - print_scaled(active_short(q)); - if (cur_p == null) - tprint(" a="); - else - tprint(" g="); - print_scaled(active_glue(q)); - } - tprint(" -> @"); - if (prev_break(passive) == null) - print_char('0'); - else - print_int(serial(prev_break(passive))); -} - -static void print_feasible_break(halfword cur_p, pointer r, halfword b, int pi, int d, boolean artificial_demerits) -{ - /*tex - - Print a symbolic description of this feasible break. - - */ - if (printed_node != cur_p) { - /*tex - - Print the list between |printed_node| and |cur_p|, then set - |printed_node:=cur_p|. - - */ - tprint_nl(""); - if (cur_p == null) { - short_display(vlink(printed_node)); - } else { - halfword save_link = vlink(cur_p); - vlink(cur_p) = null; - tprint_nl(""); - short_display(vlink(printed_node)); - vlink(cur_p) = save_link; - } - printed_node = cur_p; - } - tprint_nl("@"); - if (cur_p == null) { - tprint_esc("par"); - } else if (type(cur_p) != glue_node) { - if (type(cur_p) == penalty_node) - tprint_esc("penalty"); - else if (type(cur_p) == disc_node) - tprint_esc("discretionary"); - else if (type(cur_p) == kern_node) - tprint_esc("kern"); - else - tprint_esc("math"); - } - tprint(" via @"); - if (break_node(r) == null) - print_char('0'); - else - print_int(serial(break_node(r))); - tprint(" b="); - if (b > inf_bad) - print_char('*'); - else - print_int(b); - tprint(" p="); - print_int(pi); - tprint(" d="); - if (artificial_demerits) - print_char('*'); - else - print_int(d); -} - -#define add_disc_width_to_active_width(a) active_width[a] += disc_width[a] -#define update_width(a) cur_active_width[a] += varmem[(r+(a))].cint - -#define set_break_width_to_background(a) break_width[a]=background[(a)] - -#define convert_to_break_width(a) \ - varmem[(prev_r+(a))].cint = varmem[(prev_r+(a))].cint-cur_active_width[(a)]+break_width[(a)] - -#define store_break_width(a) active_width[(a)]=break_width[(a)] - -#define new_delta_to_break_width(a) \ - varmem[(q+(a))].cint=break_width[(a)]-cur_active_width[(a)] - -#define new_delta_from_break_width(a) \ - varmem[(q+(a))].cint=cur_active_width[(a)]-break_width[(a)] - -#define copy_to_cur_active(a) cur_active_width[(a)]=active_width[(a)] - -#define combine_two_deltas(a) varmem[(prev_r+(a))].cint += varmem[(r+(a))].cint -#define downdate_width(a) cur_active_width[(a)] -= varmem[(prev_r+(a))].cint -#define update_active(a) active_width[(a)]+=varmem[(r+(a))].cint - -#define total_font_stretch cur_active_width[8] -#define total_font_shrink cur_active_width[9] - -#define cal_margin_kern_var(a) { \ - character(cp) = character((a)); \ - font(cp) = font((a)); \ - do_subst_font(cp, 1000); \ - if (font(cp) != font((a))) \ - margin_kern_stretch += (left_pw((a)) - left_pw(cp)); \ - font(cp) = font((a)); \ - do_subst_font(cp, -1000); \ - if (font(cp) != font((a))) \ - margin_kern_shrink += (left_pw(cp) - left_pw((a))); \ -} - -static void ext_try_break( - int pi, - quarterword break_type, - int line_break_dir, - int adjust_spacing, - int par_shape_ptr, - int adj_demerits, - int tracing_paragraphs, - int protrude_chars, - int line_penalty, - int last_line_fit, - int double_hyphen_demerits, - int final_hyphen_demerits, halfword first_p, halfword cur_p -) -{ - /*tex runs through the active list */ - pointer r; - scaled margin_kern_stretch; - scaled margin_kern_shrink; - halfword lp, rp, cp; - /*tex stays a step behind |r| */ - halfword prev_r = active; - /*tex a step behind |prev_r|, if |type(prev_r)=delta_node| */ - halfword prev_prev_r = null; - /*tex maximum line number in current equivalence class of lines */ - halfword old_l = 0; - /*tex have we found a feasible break at |cur_p|? */ - boolean no_break_yet = true; - /*tex points to a new node being created */ - halfword q; - /*tex line number of current active node */ - halfword l; - /*tex should node |r| remain in the active list? */ - boolean node_r_stays_active; - /*tex the current line will be justified to this width */ - scaled line_width = 0; - /*tex possible fitness class of test line */ - fitness_value fit_class; - /*tex badness of test line */ - halfword b; - /*tex demerits of test line */ - int d; - /*tex has |d| been forced to zero? */ - boolean artificial_demerits; - /*tex used in badness calculations */ - scaled shortfall; - /*tex glue stretch or shrink of test line, adjustment for last line */ - scaled g = 0; - /*tex distance from current active node */ - scaled cur_active_width[10] = { 0 }; - /*tex Make sure that |pi| is in the proper range; */ - if (pi >= inf_penalty) { - /*tex this breakpoint is inhibited by infinite penalty */ - return; - } else if (pi <= -inf_penalty) { - /*tex this breakpoint will be forced */ - pi = eject_penalty; - } - - do_all_eight(copy_to_cur_active); - - while (1) { - r = vlink(prev_r); - /*tex - - If node |r| is of type |delta_node|, update |cur_active_width|, set - |prev_r| and |prev_prev_r|, then |goto continue|. The following code - uses the fact that |type(active)<>delta_node|. - - */ - if (type(r) == delta_node) { - /*tex implicit */ - do_all_eight(update_width); - prev_prev_r = prev_r; - prev_r = r; - continue; - } - /*tex - - If a line number class has ended, create new active nodes for the - best feasible breaks in that class; then |return| if |r=active|, - otherwise compute the new |line_width|. - - The first part of the following code is part of \TeX's inner loop, so - we don't want to waste any time. The current active node, namely node - |r|, contains the line number that will be considered next. At the - end of the list we have arranged the data structure so that - |r=active| and |line_number(active)>old_l|. - - */ - l = line_number(r); - if (l > old_l) { - /*tex now we are no longer in the inner loop */ - if ((minimum_demerits < awful_bad) - && ((old_l != easy_line) || (r == active))) { - /*tex - - Create new active nodes for the best feasible breaks just - found. It is not necessary to create new active nodes having - |minimal_demerits| greater than - |minimum_demerits+abs(adj_demerits)|, since such active nodes - will never be chosen in the final paragraph breaks. This - observation allows us to omit a substantial number of - feasible breakpoints from further consideration. - - */ - if (no_break_yet) { - no_break_yet = false; - do_all_eight(set_break_width_to_background); - compute_break_width(break_type, line_break_dir, adjust_spacing, cur_p); - } - /*tex - - Insert a delta node to prepare for breaks at |cur_p|. We use - the fact that |type(active)<>delta_node|. - - */ - if (type(prev_r) == delta_node) { - /*tex modify an existing delta node */ - do_all_eight(convert_to_break_width); - } else if (prev_r == active) { - /*tex no delta node needed at the beginning */ - do_all_eight(store_break_width); - } else { - q = new_node(delta_node, 0); - vlink(q) = r; - do_all_eight(new_delta_to_break_width); - vlink(prev_r) = q; - prev_prev_r = prev_r; - prev_r = q; - } - if (abs(adj_demerits) >= awful_bad - minimum_demerits) - minimum_demerits = awful_bad - 1; - else - minimum_demerits += abs(adj_demerits); - for (fit_class = very_loose_fit; fit_class <= tight_fit; - fit_class++) { - if (minimal_demerits[fit_class] <= minimum_demerits) { - /*tex - - Insert a new active node from |best_place[fit_class]| - to |cur_p|. When we create an active node, we also - create the corresponding passive node. - - */ - q = new_node(passive_node, 0); - vlink(q) = passive; - passive = q; - cur_break(q) = cur_p; - incr(pass_number); - serial(q) = pass_number; - prev_break(q) = best_place[fit_class]; - /*tex - - Here we keep track of the subparagraph penalties in - the break nodes. - - */ - passive_pen_inter(q) = internal_pen_inter; - passive_pen_broken(q) = internal_pen_broken; - passive_last_left_box(q) = internal_left_box; - passive_last_left_box_width(q) = - internal_left_box_width; - if (prev_break(q) != null) { - passive_left_box(q) = passive_last_left_box(prev_break(q)); - passive_left_box_width(q) = passive_last_left_box_width(prev_break(q)); - } else { - passive_left_box(q) = init_internal_left_box; - passive_left_box_width(q) = init_internal_left_box_width; - } - passive_right_box(q) = internal_right_box; - passive_right_box_width(q) = internal_right_box_width; - q = new_node(break_type, fit_class); - break_node(q) = passive; - line_number(q) = best_pl_line[fit_class] + 1; - total_demerits(q) = minimal_demerits[fit_class]; - if (do_last_line_fit) { - /*tex - - Store additional data in the new active node. - Here we save these data in the active node - representing a potential line break. - - */ - active_short(q) = best_pl_short[fit_class]; - active_glue(q) = best_pl_glue[fit_class]; - } - vlink(q) = r; - vlink(prev_r) = q; - prev_r = q; - if (tracing_paragraphs > 0) - print_break_node(q, fit_class, break_type, cur_p); - } - minimal_demerits[fit_class] = awful_bad; - } - minimum_demerits = awful_bad; - /*tex - - Insert a delta node to prepare for the next active node. When - the following code is performed, we will have just inserted - at least one active node before |r|, so - |type(prev_r)<>delta_node|. - - */ - if (r != active) { - q = new_node(delta_node, 0); - vlink(q) = r; - do_all_eight(new_delta_from_break_width); - vlink(prev_r) = q; - prev_prev_r = prev_r; - prev_r = q; - } - } - if (r == active) - return; - /*tex - - Compute the new line width. When we come to the following code, - we have just encountered the first active node~|r| whose - |line_number| field contains |l|. Thus we want to compute the - length of the $l\mskip1mu$th line of the current paragraph. - Furthermore, we want to set |old_l| to the last number in the - class of line numbers equivalent to~|l|. - - */ - if (l > easy_line) { - old_l = max_halfword - 1; - line_width = second_width; - } else { - old_l = l; - if (l > last_special_line) { - line_width = second_width; - } else if (par_shape_ptr == null) { - line_width = first_width; - } else { - line_width = varmem[(par_shape_ptr + 2 * l + 1)].cint; - } - } - } - /*tex - - If a line number class has ended, create new active nodes for the - best feasible breaks in that class; then |return| if |r=active|, - otherwise compute the new |line_width|. - - Consider the demerits for a line from |r| to |cur_p|; deactivate node - |r| if it should no longer be active; then |goto continue| if a line - from |r| to |cur_p| is infeasible, otherwise record a new feasible - break. - - */ - artificial_demerits = false; - shortfall = line_width - cur_active_width[1]; - if (break_node(r) == null) - shortfall -= init_internal_left_box_width; - else - shortfall -= passive_last_left_box_width(break_node(r)); - shortfall -= internal_right_box_width; - if (protrude_chars > 1) { - halfword l1, o; - l1 = (break_node(r) == null) ? first_p : cur_break(break_node(r)); - if (cur_p == null) { - o = null; - } else { - o = alink(cur_p); - assert(vlink(o) == cur_p); - } - /*tex - - The disc could be a SELECT subtype, to we might need to get the - last character as |pre_break| from either the |pre_break| list - (if the previous INIT disc was taken), or the |no_break| (sic) - list (if the previous INIT disc was not taken). - - The last characters (hyphenation character) if these two list - should always be the same anyway, so we just look at |pre_break|. - - Let's look at the right margin first. - - */ - if ((cur_p != null) && (type(cur_p) == disc_node) && (vlink_pre_break(cur_p) != null)) { - /*tex a |disc_node| with non-empty |pre_break|, protrude the last char of |pre_break| */ - o = tlink_pre_break(cur_p); - } else { - o = find_protchar_right(l1, o); - } - /*tex now the left margin */ - if ((l1 != null) && (type(l1) == disc_node) && (vlink_post_break(l1) != null)) { - /*tex The first char could be a disc! Protrude the first char. */ - l1 = vlink_post_break(l1); - } else { - l1 = find_protchar_left(l1, true); - } - shortfall += (left_pw(l1) + right_pw(o)); - } - if (shortfall != 0) { - margin_kern_stretch = 0; - margin_kern_shrink = 0; - if (protrude_chars > 1) { - /*tex Calculate variations of marginal kerns. */ - lp = last_leftmost_char; - rp = last_rightmost_char; - cp = raw_glyph_node(); - if (lp != null) { - cal_margin_kern_var(lp); - } - if (rp != null) { - cal_margin_kern_var(rp); - } - flush_node(cp); - } - if ((shortfall > 0) && ((total_font_stretch + margin_kern_stretch) > 0)) { - if ((total_font_stretch + margin_kern_stretch) > shortfall) - shortfall = ((total_font_stretch + margin_kern_stretch) / (max_stretch_ratio / cur_font_step)) / 2; - else - shortfall -= (total_font_stretch + margin_kern_stretch); - } else if ((shortfall < 0) && ((total_font_shrink + margin_kern_shrink) > 0)) { - if ((total_font_shrink + margin_kern_shrink) > -shortfall) - shortfall = -((total_font_shrink + margin_kern_shrink) / (max_shrink_ratio / cur_font_step)) / 2; - else - shortfall += (total_font_shrink + margin_kern_shrink); - } - } - if (shortfall > 0) { - /*tex - - Set the value of |b| to the badness for stretching the line, and - compute the corresponding |fit_class|. - - When a line must stretch, the available stretchability can be - found in the subarray |cur_active_width[2..6]|, in units of - points, sfi, fil, fill and filll. - - The present section is part of \TeX's inner loop, and it is most - often performed when the badness is infinite; therefore it is - worth while to make a quick test for large width excess and small - stretchability, before calling the |badness| subroutine. - - */ - if ((cur_active_width[3] != 0) || (cur_active_width[4] != 0) || - (cur_active_width[5] != 0) || (cur_active_width[6] != 0)) { - if (do_last_line_fit) { - if (cur_p == null) { - /*tex - - The last line of a paragraph. Perform computations - for last line and |goto found|. - - Here we compute the adjustment |g| and badness |b| - for a line from |r| to the end of the paragraph. When - any of the criteria for adjustment is violated we - fall through to the normal algorithm. - - The last line must be too short, and have infinite - stretch entirely due to |par_fill_skip|. - - */ - if ((active_short(r) == 0) || (active_glue(r) <= 0)) - /*tex - - Previous line was neither stretched nor shrunk, - or was infinitely bad. - - */ - goto NOT_FOUND; - if ((cur_active_width[3] != fill_width[0]) || (cur_active_width[4] != fill_width[1]) || - (cur_active_width[5] != fill_width[2]) || (cur_active_width[6] != fill_width[3])) - /*tex - - Infinite stretch of this line not entirely due to |par_fill_skip|. - - */ - goto NOT_FOUND; - if (active_short(r) > 0) - g = cur_active_width[2]; - else - g = cur_active_width[7]; - if (g <= 0) - /*tex No finite stretch resp.\ no shrink. */ - goto NOT_FOUND; - arith_error = false; - g = fract(g, active_short(r), active_glue(r), - max_dimen); - if (last_line_fit < 1000) - g = fract(g, last_line_fit, 1000, max_dimen); - if (arith_error) { - if (active_short(r) > 0) - g = max_dimen; - else - g = -max_dimen; - } - if (g > 0) { - /*tex - - Set the value of |b| to the badness of the last - line for stretching, compute the corresponding - |fit_class, and |goto found|. These badness - computations are rather similar to those of the - standard algorithm, with the adjustment amount - |g| replacing the |shortfall|. - - */ - if (g > shortfall) - g = shortfall; - if (g > 7230584) { - if (cur_active_width[2] < 1663497) { - b = inf_bad; - fit_class = very_loose_fit; - goto FOUND; - } - } - b = badness(g, cur_active_width[2]); - if (b > 99) { - fit_class = very_loose_fit; - } else if (b > 12) { - fit_class = loose_fit; - } else { - fit_class = decent_fit; - } - goto FOUND; - } else if (g < 0) { - /*tex - - Set the value of |b| to the badness of the last - line for shrinking, compute the corresponding - |fit_class, and |goto found||. - - */ - if (-g > cur_active_width[7]) - g = -cur_active_width[7]; - b = badness(-g, cur_active_width[7]); - if (b > 12) - fit_class = tight_fit; - else - fit_class = decent_fit; - goto FOUND; - } - } - NOT_FOUND: - shortfall = 0; - } - b = 0; - /*tex Infinite stretch. */ - fit_class = decent_fit; - } else if (shortfall > 7230584 && cur_active_width[2] < 1663497) { - b = inf_bad; - fit_class = very_loose_fit; - } else { - b = badness(shortfall, cur_active_width[2]); - if (b > 99) { - fit_class = very_loose_fit; - } else if (b > 12) { - fit_class = loose_fit; - } else { - fit_class = decent_fit; - } - } - } else { - /*tex - - Set the value of |b| to the badness for shrinking the line, and - compute the corresponding |fit_class|. Shrinkability is never - infinite in a paragraph; we can shrink the line from |r| to - |cur_p| by at most |cur_active_width[7]|. - - */ - if (-shortfall > cur_active_width[7]) - b = inf_bad + 1; - else - b = badness(-shortfall, cur_active_width[7]); - if (b > 12) - fit_class = tight_fit; - else - fit_class = decent_fit; - } - if (do_last_line_fit) { - /*tex Adjust the additional data for last line; */ - if (cur_p == null) - shortfall = 0; - if (shortfall > 0) { - g = cur_active_width[2]; - } else if (shortfall < 0) { - g = cur_active_width[7]; - } else { - g = 0; - } - } - FOUND: - if ((b > inf_bad) || (pi == eject_penalty)) { - /*tex - - Prepare to deactivate node~|r|, and |goto deactivate| unless - there is a reason to consider lines of text from |r| to |cur_p|. - During the final pass, we dare not lose all active nodes, lest we - lose touch with the line breaks already found. The code shown - here makes sure that such a catastrophe does not happen, by - permitting overfull boxes as a last resort. This particular part - of \TeX\ was a source of several subtle bugs before the correct - program logic was finally discovered; readers who seek to - ``improve'' \TeX\ should therefore think thrice before daring to - make any changes here. - - */ - if (final_pass && (minimum_demerits == awful_bad) && - (vlink(r) == active) && (prev_r == active)) { - /*tex Set demerits zero, this break is forced. */ - artificial_demerits = true; - } else if (b > threshold) { - goto DEACTIVATE; - } - node_r_stays_active = false; - } else { - prev_r = r; - if (b > threshold) - continue; - node_r_stays_active = true; - } - /*tex - - Record a new feasible break. When we get to this part of the code, - the line from |r| to |cur_p| is feasible, its badness is~|b|, and its - fitness classification is |fit_class|. We don't want to make an - active node for this break yet, but we will compute the total - demerits and record them in the |minimal_demerits| array, if such a - break is the current champion among all ways to get to |cur_p| in a - given line-number class and fitness class. - - */ - if (artificial_demerits) { - d = 0; - } else { - /*tex Compute the demerits, |d|, from |r| to |cur_p|. */ - d = line_penalty + b; - if (abs(d) >= 10000) - d = 100000000; - else - d = d * d; - if (pi != 0) { - if (pi > 0) { - d += (pi * pi); - } else if (pi > eject_penalty) { - d -= (pi * pi); - } - } - if ((break_type == hyphenated_node) && (type(r) == hyphenated_node)) { - if (cur_p != null) - d += double_hyphen_demerits; - else - d += final_hyphen_demerits; - } - /*tex - - Direct calculation of the absolute value in ((|fit_class| - |fitness(r)|) > 1) - can lead to unexpected results even if the type of the members of |fit_class|, which is |int| - (see C99 §6.7.2.2), and the integer promotion rules for |fitness(r)|, whose also - give an |int| type, should set the expression as substraction between two |int|. - In this case GCC set the type of |fit_class| to |unsigned int| (perhaps because the members are all positives?) - and hence the expression is converted to a sum of |unsigned int|, leading to a different result. - The choice of type is implementation-defined, as stated in C99 §6.7.2.2.4: - - "Each enumerated type shall be compatible with char, a signed integer type, or an unsigned integer type. - The choice of type is implementation-defined, but shall be capable of representing the values - of all the members of the enumeration." - - It's better to use the equivalent expanded expression. - */ - if ( (fit_class>(fitness(r)+1)) || (fitness(r)>(fit_class+1)) ) - d = d + adj_demerits; - - } - if (tracing_paragraphs > 0) { - print_feasible_break(cur_p, r, b, pi, d, artificial_demerits); - } - /*tex This is the minimum total demerits from the beginning to |cur_p| via |r|. */ - d += total_demerits(r); - if (d <= minimal_demerits[fit_class]) { - minimal_demerits[fit_class] = d; - best_place[fit_class] = break_node(r); - best_pl_line[fit_class] = l; - if (do_last_line_fit) { - /*tex - - Store additional data for this feasible break. For each - feasible break we record the shortfall and glue stretch or - shrink (or adjustment). - - */ - best_pl_short[fit_class] = shortfall; - best_pl_glue[fit_class] = g; - } - if (d < minimum_demerits) - minimum_demerits = d; - } - /*tex Record a new feasible break. */ - if (node_r_stays_active) { - /*tex |prev_r| has been set to |r|. */ - continue; - } - DEACTIVATE: - /*tex - - Deactivate node |r|. When an active node disappears, we must delete - an adjacent delta node if the active node was at the beginning or the - end of the active list, or if it was surrounded by delta nodes. We - also must preserve the property that |cur_active_width| represents - the length of material from |vlink(prev_r)| to~|cur_p|. - - */ - vlink(prev_r) = vlink(r); - flush_node(r); - if (prev_r == active) { - /*tex - - Update the active widths, since the first active node has been - deleted. The following code uses the fact that - |type(active)<>delta_node|. If the active list has just become - empty, we do not need to update the |active_width| array, since - it will be initialized when an active node is next inserted. - - */ - r = vlink(active); - if (type(r) == delta_node) { - do_all_eight(update_active); - do_all_eight(copy_to_cur_active); - vlink(active) = vlink(r); - flush_node(r); - } - } else if (type(prev_r) == delta_node) { - r = vlink(prev_r); - if (r == active) { - do_all_eight(downdate_width); - vlink(prev_prev_r) = active; - flush_node(prev_r); - prev_r = prev_prev_r; - } else if (type(r) == delta_node) { - do_all_eight(update_width); - do_all_eight(combine_two_deltas); - vlink(prev_r) = vlink(r); - flush_node(r); - } - } - } -} - -void ext_do_line_break( - int paragraph_dir, - int pretolerance, - int tracing_paragraphs, - int tolerance, - scaled emergency_stretch, - int looseness, - int adjust_spacing, - halfword par_shape_ptr, - int adj_demerits, - int protrude_chars, - int line_penalty, - int last_line_fit, - int double_hyphen_demerits, - int final_hyphen_demerits, - int hang_indent, - int hsize, - int hang_after, - halfword left_skip, - halfword right_skip, - halfword inter_line_penalties_ptr, - int inter_line_penalty, - int club_penalty, - halfword club_penalties_ptr, - halfword widow_penalties_ptr, - int widow_penalty, - int broken_penalty, - halfword final_par_glue -) -{ - /*tex Miscellaneous nodes of temporary interest. */ - halfword cur_p, q, r, s; - int line_break_dir = paragraph_dir; - /*tex Get ready to start */ - minimum_demerits = awful_bad; - minimal_demerits[tight_fit] = awful_bad; - minimal_demerits[decent_fit] = awful_bad; - minimal_demerits[loose_fit] = awful_bad; - minimal_demerits[very_loose_fit] = awful_bad; - fewest_demerits = 0; - actual_looseness = 0; - /*tex - - We compute the values of |easy_line| and the other local variables - relating to line length when the |line_break| procedure is initializing - itself. - - */ - if (par_shape_ptr == null) { - if (hang_indent == 0) { - last_special_line = 0; - second_width = hsize; - second_indent = 0; - } else { - halfword used_hang_indent = swap_hang_indent(hang_indent); - /*tex - - Set line length parameters in preparation for hanging - indentation. We compute the values of |easy_line| and the other - local variables relating to line length when the |line_break| - procedure is initializing itself. - - */ - last_special_line = abs(hang_after); - if (hang_after < 0) { - first_width = hsize - abs(used_hang_indent); - if (used_hang_indent >= 0) - first_indent = used_hang_indent; - else - first_indent = 0; - second_width = hsize; - second_indent = 0; - } else { - first_width = hsize; - first_indent = 0; - second_width = hsize - abs(used_hang_indent); - if (used_hang_indent >= 0) - second_indent = used_hang_indent; - else - second_indent = 0; - } - } - } else { - last_special_line = vinfo(par_shape_ptr + 1) - 1; - second_indent = varmem[(par_shape_ptr + 2 * (last_special_line + 1))].cint; - second_width = varmem[(par_shape_ptr + 2 * (last_special_line + 1) + 1)].cint; - second_indent = swap_parshape_indent(second_indent,second_width); - } - if (looseness == 0) - easy_line = last_special_line; - else - easy_line = max_halfword; - no_shrink_error_yet = true; - check_shrinkage(left_skip); - check_shrinkage(right_skip); - q = left_skip; - r = right_skip; - background[1] = width(q) + width(r); - background[2] = 0; - background[3] = 0; - background[4] = 0; - background[5] = 0; - background[6] = 0; - background[2 + stretch_order(q)] = stretch(q); - background[2 + stretch_order(r)] += stretch(r); - background[7] = shrink(q) + shrink(r); - if (adjust_spacing > 1) { - background[8] = 0; - background[9] = 0; - max_stretch_ratio = -1; - max_shrink_ratio = -1; - cur_font_step = -1; - set_prev_char_p(null); - } - /*tex - - Check for special treatment of last line of paragraph. The new algorithm - for the last line requires that the stretchability |par_fill_skip| is - infinite and the stretchability of |left_skip| plus |right_skip| is - finite. - - */ - do_last_line_fit = false; - if (last_line_fit > 0) { - q = last_line_fill; - if ((stretch(q) > 0) && (stretch_order(q) > normal)) { - if ((background[3] == 0) && (background[4] == 0) && (background[5] == 0) && (background[6] == 0)) { - do_last_line_fit = true; - fill_width[0] = 0; - fill_width[1] = 0; - fill_width[2] = 0; - fill_width[3] = 0; - fill_width[stretch_order(q) - 1] = stretch(q); - } - } - } - /*tex Initialize |dir_ptr| for |line_break|. */ - if (dir_ptr != null) { - flush_node_list(dir_ptr); - dir_ptr = null; - } - /*tex Find optimal breakpoints. */ - threshold = pretolerance; - if (threshold >= 0) { - if (tracing_paragraphs > 0) { - begin_diagnostic(); - tprint_nl("@firstpass"); - } - second_pass = false; - final_pass = false; - } else { - threshold = tolerance; - second_pass = true; - final_pass = (emergency_stretch <= 0); - if (tracing_paragraphs > 0) - begin_diagnostic(); - } - while (1) { - halfword first_p; - halfword nest_stack[10]; - int nest_index = 0; - if (threshold > inf_bad) - threshold = inf_bad; - /*tex Create an active breakpoint representing the beginning of the paragraph. */ - q = new_node(unhyphenated_node, decent_fit); - vlink(q) = active; - break_node(q) = null; - line_number(q) = cur_list.pg_field + 1; - total_demerits(q) = 0; - active_short(q) = 0; - active_glue(q) = 0; - vlink(active) = q; - do_all_eight(store_background); - passive = null; - printed_node = temp_head; - pass_number = 0; - font_in_short_display = null_font; - /*tex Create an active breakpoint representing the beginning of the paragraph. */ - auto_breaking = true; - cur_p = vlink(temp_head); - /*tex Initialize with first |local_paragraph| node. */ - if ((cur_p != null) && (type(cur_p) == local_par_node)) { - /*tex This used to be an assert, but may as well force it. */ - alink(cur_p) = temp_head; - internal_pen_inter = local_pen_inter(cur_p); - internal_pen_broken = local_pen_broken(cur_p); - init_internal_left_box = local_box_left(cur_p); - init_internal_left_box_width = local_box_left_width(cur_p); - internal_left_box = init_internal_left_box; - internal_left_box_width = init_internal_left_box_width; - internal_right_box = local_box_right(cur_p); - internal_right_box_width = local_box_right_width(cur_p); - } else { - internal_pen_inter = 0; - internal_pen_broken = 0; - init_internal_left_box = null; - init_internal_left_box_width = 0; - internal_left_box = init_internal_left_box; - internal_left_box_width = init_internal_left_box_width; - internal_right_box = null; - internal_right_box_width = 0; - } - /*tex Initialize with first |local_paragraph| node. */ - set_prev_char_p(null); - first_p = cur_p; - /*tex - - To access the first node of paragraph as the first active node has - |break_node=null|. - - */ - while ((cur_p != null) && (vlink(active) != active)) { - /*tex - - |try_break| if |cur_p| is a legal breakpoint; on the 2nd pass, - also look at |disc_node|s. - - */ - while (is_char_node(cur_p)) { - /*tex - - Advance |cur_p| to the node following the present string of - characters. The code that passes over the characters of words - in a paragraph is part of \TeX's inner loop, so it has been - streamlined for speed. We use the fact that - `\.{\\parfillskip}' glue appears at the end of each - paragraph; it is therefore unnecessary to check if - |vlink(cur_p)=null| when |cur_p| is a character node. - - */ - active_width[1] += pack_width(line_break_dir, dir_TRT, cur_p, true); - if ((adjust_spacing > 1) && check_expand_pars(font(cur_p))) { - set_prev_char_p(cur_p); - add_char_stretch(active_width[8], cur_p); - add_char_shrink(active_width[9], cur_p); - } - cur_p = vlink(cur_p); - while (cur_p == null && nest_index > 0) { - cur_p = nest_stack[--nest_index]; - } - } - if (cur_p == null) { - normal_error("linebreak","invalid list tail, probably missing glue"); - } - /*tex - - Determine legal breaks: As we move through the hlist, we need to - keep the |active_width| array up to date, so that the badness of - individual lines is readily calculated by |try_break|. It is - convenient to use the short name |active_width[1]| for the - component of active width that represents real width as opposed - to glue. - - */ - switch (type(cur_p)) { - case hlist_node: - case vlist_node: - active_width[1] += pack_width(line_break_dir, box_dir(cur_p), cur_p, false); - break; - case rule_node: - active_width[1] += width(cur_p); - break; - case dir_node: - /*tex Adjust the dir stack for the |line_break| routine. */ - if (subtype(cur_p) == normal_dir) { - line_break_dir = dir_dir(cur_p); - /* Adds to |dir_ptr|. */ - push_dir_node(dir_ptr,cur_p); - } else { - pop_dir_node(dir_ptr); - if (dir_ptr != null) { - line_break_dir = dir_dir(dir_ptr); - } - } - break; - case local_par_node: - /*tex Advance past a |local_paragraph| node. */ - internal_pen_inter = local_pen_inter(cur_p); - internal_pen_broken = local_pen_broken(cur_p); - internal_left_box = local_box_left(cur_p); - internal_left_box_width = local_box_left_width(cur_p); - internal_right_box = local_box_right(cur_p); - internal_right_box_width = local_box_right_width(cur_p); - break; - case math_node: - auto_breaking = (subtype(cur_p) == after); - /*tex begin mathskip code */ - if (glue_is_zero(cur_p) || ignore_math_skip(cur_p)) { - kern_break(); - break; - } else { - /*tex fall through */ - } - /*tex end mathskip code */ - case glue_node: - /*tex - - If node |cur_p| is a legal breakpoint, call |try_break|; - then update the active widths by including the glue in - |glue_ptr(cur_p)|. - - When node |cur_p| is a glue node, we look at the previous - to see whether or not a breakpoint is legal at |cur_p|, - as explained above. - - We only break after certain nodes (see texnodes.h), a - font related kern and a dir node when - |\breakafterdirmode=1|. - - */ - if (auto_breaking) { - halfword prev_p = alink(cur_p); - if (prev_p != temp_head && (is_char_node(prev_p) - || precedes_break(prev_p) || precedes_kern(prev_p) || precedes_dir(prev_p))) { - ext_try_break( - 0, - unhyphenated_node, - line_break_dir, - adjust_spacing, - par_shape_ptr, - adj_demerits, - tracing_paragraphs, - protrude_chars, - line_penalty, - last_line_fit, - double_hyphen_demerits, - final_hyphen_demerits, - first_p, - cur_p - ); - } - } - check_shrinkage(cur_p); - active_width[1] += width(cur_p); - active_width[2 + stretch_order(cur_p)] += stretch(cur_p); - active_width[7] += shrink(cur_p); - break; - case kern_node: - if (subtype(cur_p) == explicit_kern || subtype(cur_p) == italic_kern) { - kern_break(); - } else { - active_width[1] += width(cur_p); - if ((adjust_spacing == 2) && (subtype(cur_p) == normal)) { - add_kern_stretch(active_width[8], cur_p); - add_kern_shrink(active_width[9], cur_p); - } - } - break; - case disc_node: - /*tex - - |select_disc|s are handled by the leading |init_disc|. - - */ - if (subtype(cur_p) == select_disc) - break; - /*tex - - Try to break after a discretionary fragment, then |goto - done5|. The following code knows that discretionary texts - contain only character nodes, kern nodes, box nodes, and - rule nodes. This branch differs a bit from older engines - because in \LUATEX\ we already have hyphenated the list. - This means that we need to skip automatic disc nodes. Of - better, we need to treat discretionaries and explicit - hyphens always, even in the first pass. - - */ - if (second_pass || subtype(cur_p) <= automatic_disc) { - int actual_penalty = (int) disc_penalty(cur_p); - s = vlink_pre_break(cur_p); - do_one_seven_eight(reset_disc_width); - if (s == null) { - /*tex trivial pre-break */ - ext_try_break(actual_penalty, hyphenated_node, - line_break_dir, adjust_spacing, - par_shape_ptr, adj_demerits, - tracing_paragraphs, protrude_chars, - line_penalty, last_line_fit, - double_hyphen_demerits, - final_hyphen_demerits, first_p, cur_p); - } else { - add_to_widths(s, line_break_dir, adjust_spacing, disc_width); - do_one_seven_eight(add_disc_width_to_active_width); - ext_try_break(actual_penalty, hyphenated_node, - line_break_dir, adjust_spacing, - par_shape_ptr, adj_demerits, - tracing_paragraphs, protrude_chars, - line_penalty, last_line_fit, - double_hyphen_demerits, - final_hyphen_demerits, first_p, cur_p); - if (subtype(cur_p) == init_disc) { - /*tex - - We should at two break points after the one - we added above: - - \startitemize[n] - \startitem - which does a possible break in INIT's - |post_break| - \stopitem - \startitem - which means the |no_break| actually - was broken just a character later - \stopitem - \stopitemize - - Do the select-0 case |f-f-i|: - - */ - s = vlink_pre_break(vlink(cur_p)); - add_to_widths(s, line_break_dir, adjust_spacing, disc_width); - ext_try_break(actual_penalty, hyphenated_node, - line_break_dir, adjust_spacing, - par_shape_ptr, adj_demerits, - tracing_paragraphs, - protrude_chars, line_penalty, - last_line_fit, double_hyphen_demerits, - final_hyphen_demerits, first_p, - vlink(cur_p)); - /*tex This does not work. */ -#if 0 - /*tex Go back to the starting situation. */ - do_one_seven_eight(sub_disc_width_from_active_width); - do_one_seven_eight(reset_disc_width); - /*tex Add select |no_break| to |active_width|. */ - s = vlink_no_break(vlink(cur_p)); - add_to_widths(s, line_break_dir, adjust_spacing, disc_width); - ext_try_break(actual_penalty, hyphenated_node, - line_break_dir, adjust_spacing, - par_shape_ptr, adj_demerits, - tracing_paragraphs, - protrude_chars, line_penalty, - last_line_fit, double_hyphen_demerits, - final_hyphen_demerits, first_p, - vlink(cur_p)); -#endif - } - do_one_seven_eight(sub_disc_width_from_active_width); - } - } - s = vlink_no_break(cur_p); - add_to_widths(s, line_break_dir, adjust_spacing, active_width); - break; - case penalty_node: - ext_try_break(penalty(cur_p), unhyphenated_node, line_break_dir, - adjust_spacing, par_shape_ptr, adj_demerits, - tracing_paragraphs, protrude_chars, - line_penalty, last_line_fit, - double_hyphen_demerits, final_hyphen_demerits, - first_p, cur_p); - break; - case boundary_node: - case whatsit_node: - /*tex Advance past a whatsit node in the |line_break| loop. */ - case mark_node: - case ins_node: - case adjust_node: - break; - case glue_spec_node: - normal_warning("parbuilder","found a glue_spec in a paragraph"); - break; - default: - formatted_error("parbuilder","weird node %d in paragraph",type(cur_p)); - } - cur_p = vlink(cur_p); - while (cur_p == null && nest_index > 0) { - cur_p = nest_stack[--nest_index]; - } - } - if (cur_p == null) { - /*tex - - Try the final line break at the end of the paragraph, and |goto - done| if the desired breakpoints have been found. - - The forced line break at the paragraph's end will reduce the list - of breakpoints so that all active nodes represent breaks at - |cur_p=null|. On the first pass, we insist on finding an active - node that has the correct ``looseness.'' On the final pass, there - will be at least one active node, and we will match the desired - looseness as well as we can. - - The global variable |best_bet| will be set to the active node for - the best way to break the paragraph, and a few other variables - are used to help determine what is best. - - */ - ext_try_break(eject_penalty, hyphenated_node, line_break_dir, - adjust_spacing, par_shape_ptr, adj_demerits, - tracing_paragraphs, protrude_chars, line_penalty, - last_line_fit, double_hyphen_demerits, - final_hyphen_demerits, first_p, cur_p); - if (vlink(active) != active) { - /*tex Find an active node with fewest demerits; */ - r = vlink(active); - fewest_demerits = awful_bad; - do { - if (type(r) != delta_node) { - if (total_demerits(r) < fewest_demerits) { - fewest_demerits = total_demerits(r); - best_bet = r; - } - } - r = vlink(r); - } while (r != active); - best_line = line_number(best_bet); - /*tex - Find an active node with fewest demerits; - */ - if (looseness == 0) - goto DONE; - /*tex - - Find the best active node for the desired looseness; - - The adjustment for a desired looseness is a slightly more - complicated version of the loop just considered. Note that if - a paragraph is broken into segments by displayed equations, - each segment will be subject to the looseness calculation, - independently of the other segments. - - */ - r = vlink(active); - actual_looseness = 0; - do { - if (type(r) != delta_node) { - line_diff = line_number(r) - best_line; - if (((line_diff < actual_looseness) - && (looseness <= line_diff)) - || ((line_diff > actual_looseness) - && (looseness >= line_diff))) { - best_bet = r; - actual_looseness = line_diff; - fewest_demerits = total_demerits(r); - } else if ((line_diff == actual_looseness) && - (total_demerits(r) < fewest_demerits)) { - best_bet = r; - fewest_demerits = total_demerits(r); - } - } - r = vlink(r); - } while (r != active); - best_line = line_number(best_bet); - /*tex - Find the best active node for the desired looseness. - */ - if ((actual_looseness == looseness) || final_pass) - goto DONE; - } - } - /*tex Clean up the memory by removing the break nodes. */ - clean_up_the_memory(); - /*tex Clean up the memory by removing the break nodes. */ - if (!second_pass) { - if (tracing_paragraphs > 0) - tprint_nl("@secondpass"); - threshold = tolerance; - second_pass = true; - final_pass = (emergency_stretch <= 0); - } else { - /*tex If at first you do not succeed, then: */ - if (tracing_paragraphs > 0) - tprint_nl("@emergencypass"); - background[2] += emergency_stretch; - final_pass = true; - } - } - - DONE: - if (tracing_paragraphs > 0) { - end_diagnostic(true); - normalize_selector(); - } - if (do_last_line_fit) { - /*tex - Adjust the final line of the paragraph; here we either reset - |do_last_line_fit| or adjust the |par_fill_skip| glue. - */ - if (active_short(best_bet) == 0) { - do_last_line_fit = false; - } else { - width(last_line_fill) += (active_short(best_bet) - active_glue(best_bet)); - stretch(last_line_fill) = 0; - } - } - /*tex - Break the paragraph at the chosen. Once the best sequence of - breakpoints has been found (hurray), we call on the procedure - |post_line_break| to finish the remainder of the work. By introducing - this subprocedure, we are able to keep |line_break| from getting - extremely long. - - the first thing |ext_post_line_break| does is reset |dir_ptr|. - - */ - flush_node_list(dir_ptr); - dir_ptr = null; - ext_post_line_break(paragraph_dir, - right_skip, - left_skip, - protrude_chars, - par_shape_ptr, - adjust_spacing, - inter_line_penalties_par_ptr, - inter_line_penalty, - club_penalty, - club_penalties_ptr, - widow_penalties_ptr, - widow_penalty, - broken_penalty, - final_par_glue, - best_bet, - last_special_line, - second_width, - second_indent, first_width, first_indent, best_line); - /*tex - - Clean up the memory by removing the break nodes. - - */ - clean_up_the_memory(); -} - -void get_linebreak_info (int *f, int *a) -{ - *f = fewest_demerits; - *a = actual_looseness; -} diff --git a/Build/source/texk/web2c/luatexdir/tex/linebreak.h b/Build/source/texk/web2c/luatexdir/tex/linebreak.h deleted file mode 100644 index d1e1768f704..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/linebreak.h +++ /dev/null @@ -1,98 +0,0 @@ -/* linebreak.h - - Copyright 2009 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ - -#ifndef LINEBREAK_H -# define LINEBREAK_H - -extern halfword just_box; /* the |hlist_node| for the last line of the new paragraph */ - -extern void line_break(boolean d, int line_break_context); - -# define inf_bad 10000 /* infinitely bad value */ -# define awful_bad 07777777777 /* more than a billion demerits */ - -extern void initialize_active(void); - -extern void ext_do_line_break(int paragraph_dir, - int pretolerance, - int tracing_paragraphs, - int tolerance, - scaled emergency_stretch, - int looseness, - /* - int hyphen_penalty, - int ex_hyphen_penalty, - */ - int adjust_spacing, - halfword par_shape_ptr, - int adj_demerits, - int protrude_chars, - int line_penalty, - int last_line_fit, - int double_hyphen_demerits, - int final_hyphen_demerits, - int hang_indent, - int hsize, - int hang_after, - halfword left_skip, - halfword right_skip, - halfword inter_line_penalties_ptr, - int inter_line_penalty, - int club_penalty, - halfword club_penalties_ptr, - halfword widow_penalties_ptr, - int widow_penalty, - int broken_penalty, halfword final_par_glue); - -extern void get_linebreak_info(int *, int *); -extern halfword find_protchar_left(halfword l, boolean d); -extern halfword find_protchar_right(halfword l, halfword r); - -/* skipable nodes at the margins during character protrusion */ - -# define zero_dimensions(a) ( \ - (width((a)) == 0) && \ - (height((a)) == 0) && \ - (depth((a)) == 0) \ -) - -# define empty_disc(a) ( \ - (vlink_pre_break(a) == null) && \ - (vlink_post_break(a) == null) && \ - (vlink_no_break(a) == null) \ -) - -# define cp_skipable(a) ( (! is_char_node((a))) && ( \ - ((type((a)) == glue_node) && (glue_is_zero((a)))) \ - || (type((a)) == penalty_node) \ - || ((type((a)) == disc_node) && empty_disc(a)) \ - || ((type((a)) == kern_node) && ((width((a)) == 0) || (subtype((a)) == normal))) \ - || ((type((a)) == rule_node) && zero_dimensions(a)) \ - || ((type((a)) == math_node) && (surround((a)) == 0 || (glue_is_zero((a))))) \ - || (type((a)) == dir_node) \ - || ((type((a)) == hlist_node) && (list_ptr((a)) == null) && zero_dimensions(a)) \ - || (type((a)) == local_par_node) \ - || (type((a)) == ins_node) \ - || (type((a)) == mark_node) \ - || (type((a)) == adjust_node) \ - || (type((a)) == boundary_node) \ - || (type((a)) == whatsit_node) \ -) ) - -#endif diff --git a/Build/source/texk/web2c/luatexdir/tex/mainbody.c b/Build/source/texk/web2c/luatexdir/tex/mainbody.c deleted file mode 100644 index 2f45f9989d2..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/mainbody.c +++ /dev/null @@ -1,780 +0,0 @@ -/* - -mainbody.w - -Copyright 2009-2010 Taco Hoekwater <taco@@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your -option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU General Public License along -with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" - -/*tex - -This is where the action starts. We're speaking of \LUATEX, a continuation of -\PDFTEX\ (which included \ETEX) and \ALEPH. As \TEX, \LUATEX\ is a document -compiler intended to simplify high quality typesetting for many of the world's -languages. It is an extension of D. E. Knuth's \TEX, which was designed -essentially for the typesetting of languages using the Latin alphabet. Although -it is a direct decendant of \TEX, and therefore mostly compatible, there are -some subtle differences that relate to \UNICODE\ support and \OPENTYPE\ math. - -The \ALEPH\ subsystem loosens many of the restrictions imposed by~\TeX: register -numbers are no longer limited to 8~bits. Fonts may have more than 256~characters, -more than 256~fonts may be used, etc. We use a similar model. We also borrowed -the directional model but have upgraded it a bit as well as integrated it more -tightly. - -This program is directly derived from Donald E. Knuth's \TEX; the change history -which follows and the reward offered for finders of bugs refer specifically to -\TEX; they should not be taken as referring to \LUATEX, \PDFTEX, nor \ETEX, -although the change history is relevant in that it demonstrates the evolutionary -path followed. This program is not \TEX; that name is reserved strictly for the -program which is the creation and sole responsibility of Professor Knuth. - -\starttyping -% Version 0 was released in September 1982 after it passed a variety of tests. -% Version 1 was released in November 1983 after thorough testing. -% Version 1.1 fixed ``disappearing font identifiers'' et alia (July 1984). -% Version 1.2 allowed `0' in response to an error, et alia (October 1984). -% Version 1.3 made memory allocation more flexible and local (November 1984). -% Version 1.4 fixed accents right after line breaks, et alia (April 1985). -% Version 1.5 fixed \the\toks after other expansion in \edefs (August 1985). -% Version 2.0 (almost identical to 1.5) corresponds to "Volume B" (April 1986). -% Version 2.1 corrected anomalies in discretionary breaks (January 1987). -% Version 2.2 corrected "(Please type...)" with null \endlinechar (April 1987). -% Version 2.3 avoided incomplete page in premature termination (August 1987). -% Version 2.4 fixed \noaligned rules in indented displays (August 1987). -% Version 2.5 saved cur_order when expanding tokens (September 1987). -% Version 2.6 added 10sp slop when shipping leaders (November 1987). -% Version 2.7 improved rounding of negative-width characters (November 1987). -% Version 2.8 fixed weird bug if no \patterns are used (December 1987). -% Version 2.9 made \csname\endcsname's "relax" local (December 1987). -% Version 2.91 fixed \outer\def\a0{}\a\a bug (April 1988). -% Version 2.92 fixed \patterns, also file names with complex macros (May 1988). -% Version 2.93 fixed negative halving in allocator when mem_min<0 (June 1988). -% Version 2.94 kept open_log_file from calling fatal_error (November 1988). -% Version 2.95 solved that problem a better way (December 1988). -% Version 2.96 corrected bug in "Infinite shrinkage" recovery (January 1989). -% Version 2.97 corrected blunder in creating 2.95 (February 1989). -% Version 2.98 omitted save_for_after at outer level (March 1989). -% Version 2.99 caught $$\begingroup\halign..$$ (June 1989). -% Version 2.991 caught .5\ifdim.6... (June 1989). -% Version 2.992 introduced major changes for 8-bit extensions (September 1989). -% Version 2.993 fixed a save_stack synchronization bug et alia (December 1989). -% Version 3.0 fixed unusual displays; was more \output robust (March 1990). -% Version 3.1 fixed nullfont, disabled \write{\the\prevgraf} (September 1990). -% Version 3.14 fixed unprintable font names and corrected typos (March 1991). -% Version 3.141 more of same; reconstituted ligatures better (March 1992). -% Version 3.1415 preserved nonexplicit kerns, tidied up (February 1993). -% Version 3.14159 allowed fontmemsize to change; bulletproofing (March 1995). -% Version 3.141592 fixed \xleaders, glueset, weird alignments (December 2002). -% Version 3.1415926 was a general cleanup with minor fixes (February 2008). -\stoptyping - -Although considerable effort has been expended to make the LuaTeX program correct -and reliable, no warranty is implied; the authors disclaim any obligation or -liability for damages, including but not limited to special, indirect, or -consequential damages arising out of or in connection with the use or performance -of this software. This work has been a ``labor of love'' and the authors hope -that users enjoy it. - -{\em You will find a lot of comments that originate in original \TEX. We kept them -as a side effect of the conversion from \WEB\ to \CWEB. Because there is not much -webbing going on here eventually the files became regular \CCODE\ files with still -potentially typeset comments. As we add our own comments, and also comments are -there from \PDFTEX, \ALEPH\ and \ETEX, we get a curious mix. The best comments are -of course from Don Knuth. All bad comments are ours. All errors are ours too! - -Not all comments make sense, because some things are implemented differently, for -instance some memory management. But the principles of tokens and nodes stayed. -It anyway means that you sometimes need to keep in mind that the explanation is -more geared to traditional \TEX. But that's not a bad thing. Sorry Don for any -confusion we introduced. The readers should have a copy of the \TEX\ books at hand -anyway.} - -A large piece of software like \TeX\ has inherent complexity that cannot be -reduced below a certain level of difficulty, although each individual part is -fairly simple by itself. The \.{WEB} language is intended to make the algorithms -as readable as possible, by reflecting the way the individual program pieces fit -together and by providing the cross-references that connect different parts. -Detailed comments about what is going on, and about why things were done in -certain ways, have been liberally sprinkled throughout the program. These -comments explain features of the implementation, but they rarely attempt to -explain the \TeX\ language itself, since the reader is supposed to be familiar -with {\sl The \TeX book}. - -The present implementation has a long ancestry, beginning in the summer of~1977, -when Michael~F. Plass and Frank~M. Liang designed and coded a prototype @^Plass, -Michael Frederick@> @^Liang, Franklin Mark@> @^Knuth, Donald Ervin@> based on -some specifications that the author had made in May of that year. This original -proto\TeX\ included macro definitions and elementary manipulations on boxes and -glue, but it did not have line-breaking, page-breaking, mathematical formulas, -alignment routines, error recovery, or the present semantic nest; furthermore, it -used character lists instead of token lists, so that a control sequence like -\.{\\halign} was represented by a list of seven characters. A complete version of -\TeX\ was designed and coded by the author in late 1977 and early 1978; that -program, like its prototype, was written in the {\mc SAIL} language, for which an -excellent debugging system was available. Preliminary plans to convert the {\mc -SAIL} code into a form somewhat like the present ``web'' were developed by Luis -Trabb~Pardo and @^Trabb Pardo, Luis Isidoro@> the author at the beginning of -1979, and a complete implementation was created by Ignacio~A. Zabala in 1979 and -1980. The \TeX82 program, which @^Zabala Salelles, Ignacio Andr\'es@> was written -by the author during the latter part of 1981 and the early part of 1982, also -incorporates ideas from the 1979 implementation of @^Guibas, Leonidas Ioannis@> -@^Sedgewick, Robert@> @^Wyatt, Douglas Kirk@> \TeX\ in {\mc MESA} that was -written by Leonidas Guibas, Robert Sedgewick, and Douglas Wyatt at the Xerox Palo -Alto Research Center. Several hundred refinements were introduced into \TeX82 -based on the experiences gained with the original implementations, so that -essentially every part of the system has been substantially improved. After the -appearance of ``Version 0'' in September 1982, this program benefited greatly -from the comments of many other people, notably David~R. Fuchs and Howard~W. -Trickey. A final revision in September 1989 extended the input character set to -eight-bit codes and introduced the ability to hyphenate words from different -languages, based on some ideas of Michael~J. Ferguson. @^Fuchs, David Raymond@> -@^Trickey, Howard Wellington@> @^Ferguson, Michael John@> - -No doubt there still is plenty of room for improvement, but the author is firmly -committed to keeping \TeX82 ``frozen'' from now on; stability and reliability are -to be its main virtues. -On the other hand, the \.{WEB} description can be extended without changing the -core of \TeX82 itself, and the program has been designed so that such extensions -are not extremely difficult to make. The |banner| string defined here should be -changed whenever \TeX\ undergoes any modifications, so that it will be clear -which version of \TeX\ might be the guilty party when a problem arises. -@^extensions to \TeX@> @^system dependencies@> - -This program contains code for various features extending \TeX, therefore this -program is called `\eTeX' and not `\TeX'; the official name `\TeX' by itself is -reserved for software systems that are fully compatible with each other. A -special test suite called the ``\.{TRIP} test'' is available for helping to -determine whether a particular implementation deserves to be known as `\TeX' -[cf.~Stanford Computer Science report CS1027, November 1984]. - -A similar test suite called the ``\.{e-TRIP} test'' is available for helping to -determine whether a particular implementation deserves to be known as `\eTeX'. - -This is the first of many sections of \TeX\ where global variables are defined. - -*/ - -/*tex Are we using lua for initializations? */ - -boolean luainit; - -/*tex Print file open and close info? */ - -boolean tracefilenames; - -/*tex - -This program has two important variations: (1) There is a long and slow version -called \.{INITEX}, which does the extra calculations needed to @.INITEX@> -initialize \TeX's internal tables; and (2)~there is a shorter and faster -production version, which cuts the initialization to a bare minimum. - -*/ - -/*tex are we \.{INITEX}? */ - -boolean ini_version; - -/*tex was the dump name option used? */ - -boolean dump_option; - -/*tex was a \.{\%\AM format} line seen? */ - -boolean dump_line; - -/*tex temporary for setup */ - -int bound_default; - -/*tex temporary for setup */ - -char *bound_name; - -/*tex width of context lines on terminal error messages */ - -int error_line; - -/*tex - width of first lines of contexts in terminal error messages; should be - between 30 and |error_line-15| -*/ - -int half_error_line; - -/*tex width of longest text lines output; should be at least 60 */ - -int max_print_line; - -/*tex maximum number of strings; must not exceed |max_halfword| */ - -int max_strings; - -/*tex strings available after format loaded */ - -int strings_free; - -/*tex loop variable for initialization */ - -int font_k; - -/*tex - putting a character in front of a macro trace (feature suggested by PO on - tex implementor list -*/ - -int level_max; -int level_chr; - -/*tex - maximum number of characters simultaneously present in current lines of open - files and in control sequences between \.{\\csname} and \.{\\endcsname}; must - not exceed |max_halfword| -*/ - -int buf_size; - -/*tex maximum number of simultaneous input sources */ - -int stack_size; - -/*tex - maximum number of input files and error insertions that can be going on - simultaneously -*/ - -int max_in_open; - -/*tex maximum number of simultaneous macro parameters */ - -int param_size; - -/*tex maximum number of semantic levels simultaneously active */ - -int nest_size; - -/*tex - space for saving values outside of current group; must be at most - |max_halfword| -*/ - -int save_size; - -/*tex limits recursive calls of the |expand| procedure */ - -int expand_depth; - -/*tex parse the first line for options */ - -int parsefirstlinep; - -/*tex format messages as file:line:error */ - -int filelineerrorstylep; - -/*tex stop at first error */ - -int haltonerrorp; - -/*tex current filename is quoted */ - -boolean quoted_filename; - -int get_luatexversion(void) -{ - return luatex_version; -} - -/*tex the number of pages that have been shipped out */ - -int total_pages = 0; - -/*tex recent outputs that didn't ship anything out */ - -int dead_cycles = 0; - -str_number get_luatexrevision(void) -{ - return luatex_revision; -} - -/*tex - -This is it: the part of \TeX\ that executes all those procedures we have written. - -We have noted that there are two versions of \TeX82. One, called \.{INITEX}, -@.INITEX@> has to be run first; it initializes everything from scratch, without -reading a format file, and it has the capability of dumping a format file. The -other one is called `\.{VIRTEX}'; it is a ``virgin'' program that needs -@.VIRTEX@> to input a format file in order to get started. - -For \LUATEX\ it is important to know that we still dump a format. But, in order -to gain speed and a smaller footprint, we gzip the format (level 3). We also -store some information that makes an abort possible in case of an incompatible -engine version, which is important as \LUATEX\ develops. It is possible to store -\LUA\ code in the format but not the current upvalues so you still need to -initialize. Also, traditional fonts are stored, as are extended fonts but any -additional information needed for instance to deal with \OPENTYPE\ fonts is to be -handled by \LUA\ code and therefore not present in the format. - -*/ - -#define const_chk(A) do { \ - if (A < inf_##A) \ - A = inf_##A; \ - if (A > sup_##A) \ - A = sup_##A; \ -} while (0) - -#define setup_bound_var(A,B,C) do { \ - if (luainit>0) { \ - get_lua_number("texconfig",B,&C); \ - if (C==0) \ - C=A; \ - } else { \ - integer x; \ - setupboundvariable(&x, B, A); \ - C = (int)x; \ - } \ -} while (0) - -int ready_already = 0; - -int main_initialize(void) -{ - /* - In case somebody has inadvertently made bad settings of the - ``constants,'' \LUATEX\ checks them using a variable called |bad|. - */ - int bad = 0; - /*tex - Bounds that may be set from the configuration file. We want the user to - be able to specify the names with underscores, but \.{TANGLE} removes - underscores, so we're stuck giving the names twice, once as a string, - once as the identifier. How ugly. (We can change that now.) - */ - setup_bound_var(15000, "max_strings", max_strings); - setup_bound_var(100, "strings_free", strings_free); - setup_bound_var(3000, "buf_size", buf_size); - setup_bound_var(50, "nest_size", nest_size); - setup_bound_var(15, "max_in_open", max_in_open); - setup_bound_var(60, "param_size", param_size); - setup_bound_var(4000, "save_size", save_size); - setup_bound_var(300, "stack_size", stack_size); - setup_bound_var(16384, "dvi_buf_size", dvi_buf_size); - setup_bound_var(79, "error_line", error_line); - setup_bound_var(50, "half_error_line", half_error_line); - setup_bound_var(79, "max_print_line", max_print_line); - setup_bound_var(0, "hash_extra", hash_extra); - setup_bound_var(72, "pk_dpi", pk_dpi); - setup_bound_var(10000, "expand_depth", expand_depth); - setup_bound_var(0, "level_max", level_max); - setup_bound_var('.', "level_chr", level_chr); - /*tex - Check other constants against their sup and inf. - */ - const_chk(buf_size); - const_chk(nest_size); - const_chk(max_in_open); - const_chk(param_size); - const_chk(save_size); - const_chk(stack_size); - const_chk(dvi_buf_size); - const_chk(max_strings); - const_chk(strings_free); - const_chk(hash_extra); - const_chk(pk_dpi); - if (error_line > ssup_error_line) { - error_line = ssup_error_line; - } - /*tex - Array memory allocation - */ - buffer = xmallocarray(packed_ASCII_code, (unsigned) buf_size); - nest = xmallocarray(list_state_record, (unsigned) nest_size); - save_stack = xmallocarray(save_record, (unsigned) save_size); - input_stack = xmallocarray(in_state_record, (unsigned) stack_size); - input_file = xmallocarray(alpha_file, (unsigned) max_in_open); - input_file_callback_id = xmallocarray(int, (unsigned) max_in_open); - line_stack = xmallocarray(int, (unsigned) max_in_open); - eof_seen = xmallocarray(boolean, (unsigned) max_in_open); - grp_stack = xmallocarray(save_pointer, (unsigned) max_in_open); - if_stack = xmallocarray(pointer, (unsigned) max_in_open); - source_filename_stack = xmallocarray(str_number, (unsigned) max_in_open); - full_source_filename_stack = xmallocarray(char *, (unsigned) max_in_open); - param_stack = xmallocarray(halfword, (unsigned) param_size); - dvi_buf = xmallocarray(eight_bits, (unsigned) dvi_buf_size); - /*tex - Only in ini mode: - */ - if (ini_version) { - fixmem = xmallocarray(smemory_word, fix_mem_init + 1); - memset(voidcast(fixmem), 0, (fix_mem_init + 1) * sizeof(smemory_word)); - fix_mem_min = 0; - fix_mem_max = fix_mem_init; - eqtb_top = eqtb_size + hash_extra; - if (hash_extra == 0) - hash_top = undefined_control_sequence; - else - hash_top = eqtb_top; - hash = xmallocarray(two_halves, (unsigned) (hash_top + 1)); - memset(hash, 0, sizeof(two_halves) * (unsigned) (hash_top + 1)); - eqtb = xmallocarray(memory_word, (unsigned) (eqtb_top + 1)); - memset(eqtb, 0, sizeof(memory_word) * (unsigned) (eqtb_top + 1)); - init_string_pool_array((unsigned) max_strings); - reset_cur_string(); - } - /*tex - Check the ``constant'' values... - */ - if ((half_error_line < 30) || (half_error_line > error_line - 15)) - bad = 1; - if (max_print_line < 60) - bad = 2; - if (dvi_buf_size % 8 != 0) - bad = 3; - if (hash_prime > hash_size) - bad = 5; - if (max_in_open >= (sup_max_in_open+1)) /* 128 */ - bad = 6; - /*tex - Here are the inequalities that the quarterword and halfword values - must satisfy (or rather, the inequalities that they mustn't satisfy): - */ - if ((min_quarterword > 0) || (max_quarterword < 0x7FFF)) - bad = 11; - if ((min_halfword > 0) || (max_halfword < 0x3FFFFFFF)) - bad = 12; - if ((min_quarterword < min_halfword) || (max_quarterword > max_halfword)) - bad = 13; - if (font_base < min_quarterword) - bad = 15; - if ((save_size > max_halfword) || (max_strings > max_halfword)) - bad = 17; - if (buf_size > max_halfword) - bad = 18; - if (max_quarterword - min_quarterword < 0xFFFF) - bad = 19; - if (cs_token_flag + eqtb_size + hash_extra > max_halfword) - bad = 21; - if (bad > 0) { - wterm_cr(); - fprintf(term_out, - "Ouch---my internal constants have been clobbered! ---case %d", - (int) bad - ); - } else { - /*tex Set global variables to their starting values. */ - initialize(); - if (ini_version) { - /*tex Initialize all the primitives. */ - no_new_control_sequence = false; - first = 0; - initialize_commands(); - initialize_etex_commands(); - init_str_ptr = str_ptr; - no_new_control_sequence = true; - fix_date_and_time(); - } - ready_already = 314159; - } - return bad; -} - - -void main_body(void) -{ - static char pdftex_map[] = "pdftex.map"; - int bad = main_initialize(); - /*tex in case we quit during initialization */ - history = fatal_error_stop; - /*tex open the terminal for output */ - t_open_out(); - if (!luainit) - tracefilenames = true; - if (bad > 0) { - goto FINAL_END; - } - print_banner(luatex_version_string); - /*tex - Get the first line of input and prepare to start When we begin the - following code, \TeX's tables may still contain garbage; the strings - might not even be present. Thus we must proceed cautiously to get - bootstrapped in. - - But when we finish this part of the program, \TeX\ is ready to call on - the |main_control| routine to do its work. - */ - /*tex - This copies the command line, - */ - initialize_inputstack(); - if (buffer[iloc] == '*') - incr(iloc); - if ((format_ident == 0) || (buffer[iloc] == '&') || dump_line) { - char *fname = NULL; - if (format_ident != 0 && !ini_version) { - /*tex Erase preloaded format. */ - initialize(); - } - if ((fname = open_fmt_file()) == NULL) - goto FINAL_END; - if (!load_fmt_file(fname)) { - zwclose(fmt_file); - goto FINAL_END; - } - zwclose(fmt_file); - while ((iloc < ilimit) && (buffer[iloc] == ' ')) - incr(iloc); - } - if (output_mode_option != 0) - output_mode_par = output_mode_value; - if (draft_mode_option != 0) { - draft_mode_par = draft_mode_value; - } - /*tex can this be moved? */ - pdf_init_map_file((char *) pdftex_map); - /* */ - if (end_line_char_inactive) - decr(ilimit); - else - buffer[ilimit] = (packed_ASCII_code) end_line_char_par; - fix_date_and_time(); - random_seed = (microseconds * 1000) + (epochseconds % 1000000); - init_randoms(random_seed); - initialize_math(); - fixup_selector(log_opened_global); - check_texconfig_init(); - if ((iloc < ilimit) && (get_cat_code(cat_code_table_par, buffer[iloc]) != escape_cmd)) { - /*tex \.{\\input} assumed */ - start_input(); - } - /*tex Initialize |text_dir_ptr| */ - text_dir_ptr = new_dir(0); - /*tex Ready to go! */ - history = spotless; - /*tex Initialize synctex primitive */ - synctexinitcommand(); - /*tex Come to life. */ - main_control(); - flush_node(text_dir_ptr); - /*tex Prepare for death. */ - final_cleanup(); - close_files_and_terminate(); - FINAL_END: - do_final_end(); -} - -/*tex - -Here we do whatever is needed to complete \TeX's job gracefully on the local -operating system. The code here might come into play after a fatal error; it must -therefore consist entirely of ``safe'' operations that cannot produce error -messages. For example, it would be a mistake to call |str_room| or |make_string| -at this time, because a call on |overflow| might lead to an infinite loop. -@^system dependencies@> - -Actually there's one way to get error messages, via |prepare_mag|; but that can't -cause infinite recursion. @^recursion@> - -This program doesn't bother to close the input files that may still be open. - -*/ - -void close_files_and_terminate(void) -{ - int callback_id; - callback_id = callback_defined(stop_run_callback); - finalize_write_files(); - if (tracing_stats_par > 0) { - if (callback_id == 0) { - /*tex - Output statistics about this job. The present section goes - directly to the log file instead of using |print| commands, - because there's no need for these strings to take up - |string_pool| memory when a non-{\bf stat} version of \TeX\ is - being used. - */ - if (log_opened_global) { - fprintf(log_file, - "\n\nHere is how much of LuaTeX's memory you used:\n" - ); - fprintf(log_file, " %d string%s out of %d\n", - (int) (str_ptr - init_str_ptr), - (str_ptr == (init_str_ptr + 1) ? "" : "s"), - (int) (max_strings - init_str_ptr + STRING_OFFSET) - ); - fprintf(log_file, " %d,%d words of node,token memory allocated", - (int) var_mem_max, (int) fix_mem_max - ); - print_node_mem_stats(); - fprintf(log_file, - " %d multiletter control sequences out of %ld+%d\n", - (int) cs_count, (long) hash_size, (int) hash_extra - ); - fprintf(log_file, " %d font%s using %d bytes\n", - (int) max_font_id(), (max_font_id() == 1 ? "" : "s"), - (int) font_bytes - ); - fprintf(log_file, - " %di,%dn,%dp,%db,%ds stack positions out of %di,%dn,%dp,%db,%ds\n", - (int) max_in_stack, (int) max_nest_stack, - (int) max_param_stack, (int) max_buf_stack, - (int) max_save_stack + 6, (int) stack_size, - (int) nest_size, (int) param_size, (int) buf_size, - (int) save_size - ); - } - } - } - wake_up_terminal(); - /*tex - Rubish, these \PDF arguments, passed, needs to be fixed, e.g. with a - dummy in \DVI. - */ - wrapup_backend(); - /*tex - Close {\sl Sync\TeX} file and write status. - */ - synctexterminate(log_opened_global); - /*tex - The following is needed because synctex removes files and we want to keep - them which means renaming a temp file .. we can't bypass the terminate - because it might do mem cleanup. - */ - if (synctex_get_mode() > 0) { - callback_id = callback_defined(finish_synctex_callback); - if (callback_id > 0) { - run_callback(callback_id, "->"); - } - } - /* free_text_codes(); */ - /* free_math_codes(); */ - if (log_opened_global) { - wlog_cr(); - selector = selector - 2; - if ((selector == term_only) && (callback_id == 0)) { - tprint_nl("Transcript written on "); - tprint_file_name(NULL, texmf_log_name, NULL); - print_char('.'); - print_ln(); - } - lua_a_close_out(log_file); - log_opened_global = false; - } - callback_id = callback_defined(wrapup_run_callback); - if (callback_id > 0) { - run_callback(callback_id, "->"); - } - free_text_codes(); - free_math_codes(); -} - -/*tex - -We get to the |final_cleanup| routine when \.{\\end} or \.{\\dump} has been -scanned and |its_all_over|. - -*/ - -void final_cleanup(void) -{ - /*tex This one gets the value 0 for \.{\\end}, 1 for \.{\\dump}. */ - int c; - /*tex Here's one for looping marks: */ - halfword i; - /*tex This was a global temp_ptr: */ - halfword t; - c = cur_chr; - if (job_name == 0) - open_log_file(); - while (input_ptr > 0) - if (istate == token_list) - end_token_list(); - else - end_file_reading(); - while (open_parens > 0) { - report_stop_file(filetype_tex); - decr(open_parens); - } - if (cur_level > level_one) { - tprint_nl("(\\end occurred inside a group at level "); - print_int(cur_level - level_one); - print_char(')'); - show_save_groups(); - } - while (cond_ptr != null) { - tprint_nl("(\\end occurred when "); - print_cmd_chr(if_test_cmd, cur_if); - if (if_line != 0) { - tprint(" on line "); - print_int(if_line); - } - tprint(" was incomplete)"); - if_line = if_line_field(cond_ptr); - cur_if = subtype(cond_ptr); - t = cond_ptr; - cond_ptr = vlink(cond_ptr); - flush_node(t); - } - if (callback_defined(stop_run_callback) == 0) - if (history != spotless) - if ((history == warning_issued) || (interaction < error_stop_mode)) - if (selector == term_and_log) { - selector = term_only; - tprint_nl("(see the transcript file for additional information)"); - selector = term_and_log; - } - if (c == 1) { - if (ini_version) { - for (i = 0; i <= biggest_used_mark; i++) { - delete_top_mark(i); - delete_first_mark(i); - delete_bot_mark(i); - delete_split_first_mark(i); - delete_split_bot_mark(i); - } - for (c = last_box_code; c <= vsplit_code; c++) - flush_node_list(disc_ptr[c]); - if (last_glue != max_halfword) { - flush_node(last_glue); - } - /*tex Flush the pseudo files. */ - while (pseudo_files != null) { - pseudo_close(); - } - store_fmt_file(); - return; - } - tprint_nl("(\\dump is performed only by INITEX)"); - return; - } -} - -/*tex - -Once \TeX\ is working, you should be able to diagnose most errors with the -\.{\\show} commands and other diagnostic features. - -Because we have made some internal changes the optional debug interface -has been removed. - -*/ diff --git a/Build/source/texk/web2c/luatexdir/tex/mainbody.h b/Build/source/texk/web2c/luatexdir/tex/mainbody.h deleted file mode 100644 index 0d274aeffbe..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/mainbody.h +++ /dev/null @@ -1,246 +0,0 @@ -/* mainbody.h - - Copyright 2009 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ - - -#ifndef MAINBODY_H -# define MAINBODY_H - -extern int luatex_version; -extern int luatex_revision; -extern const char *luatex_version_string; -extern const char *engine_name; - -/* -The following parameters can be changed at compile time to extend or -reduce \TeX's capacity. They may have different values in \.{INITEX} and -in production versions of \TeX. -@.INITEX@> -@^system dependencies@> -*/ - -# define ssup_max_strings 2097151 - -# define inf_max_strings 100000 -# define sup_max_strings ssup_max_strings -# define inf_strings_free 100 -# define sup_strings_free sup_max_strings - -# define inf_buf_size 500 -# define sup_buf_size 100000000 - -# define inf_nest_size 40 -# define sup_nest_size 4000 - -# define inf_max_in_open 6 -# define sup_max_in_open 600 /* was 127. now okay for some 512 nested lua calls */ - -# define inf_param_size 60 -# define sup_param_size 32767 - -# define inf_save_size 600 -# define sup_save_size 500000 - -# define inf_stack_size 200 -# define sup_stack_size 50000 - -# define inf_dvi_buf_size 800 -# define sup_dvi_buf_size 65536 - -# define sup_hash_extra sup_max_strings -# define inf_hash_extra 0 - -# define inf_expand_depth 100 -# define sup_expand_depth 10000000 - -# define inf_level_max 0 -# define sup_level_max 500 - -# define inf_level_chr 1 -# define sup_level_chr 126 - -# include <stdio.h> - -/* Types in the outer block */ -typedef int ASCII_code; /* characters */ -typedef unsigned char eight_bits; /* unsigned one-byte quantity */ -typedef FILE *alpha_file; /* files that contain textual data */ -typedef FILE *byte_file; /* files that contain binary data */ - -typedef int str_number; -typedef int pool_pointer; -typedef unsigned char packed_ASCII_code; - -typedef int scaled; /* this type is used for scaled integers */ -typedef char small_number; /* this type is self-explanatory */ - -typedef float glue_ratio; /* one-word representation of a glue expansion factor */ - -typedef unsigned short quarterword; -typedef int halfword; - -typedef unsigned char glue_ord; /* infinity to the 0, 1, 2, 3, or 4 power */ - -typedef unsigned short group_code; /* |save_level| for a level boundary */ - -typedef int font_index; /* index into |font_info| */ - -typedef int save_pointer; - -/* -Characters of text that have been converted to \TeX's internal form -are said to be of type |ASCII_code|, which is a subrange of the integers. - -We are assuming that our runtime system is able to read and write UTF-8. - -Some of the ASCII codes without visible characters have been given symbolic -names in this program because they are used with a special meaning. -*/ - - -# define null_code '\0' /* ASCII code that might disappear */ -# define carriage_return '\r' /* ASCII code used at end of line */ - -/* Global variables */ -extern boolean luainit; /* are we using lua for initializations */ -extern boolean tracefilenames; /* print file open-close info? */ - - -extern boolean ini_version; /* are we \.{INITEX}? */ -extern boolean dump_option; -extern boolean dump_line; -extern int bound_default; -extern char *bound_name; -extern int error_line; -extern int half_error_line; -extern int max_print_line; -extern int max_strings; -extern int level_max; -extern int level_chr; -extern int strings_free; -extern int font_k; -extern int buf_size; -extern int stack_size; -extern int max_in_open; -extern int param_size; -extern int nest_size; -extern int save_size; -extern int expand_depth; -extern int parsefirstlinep; -extern int filelineerrorstylep; -extern int haltonerrorp; -extern boolean quoted_filename; - -extern int total_pages; -extern int dead_cycles; - -/* -In order to make efficient use of storage space, \TeX\ bases its major data -structures on a |memory_word|, which contains either a (signed) integer, -possibly scaled, or a (signed) |glue_ratio|, or a small number of -fields that are one half or one quarter of the size used for storing -integers. - -If |x| is a variable of type |memory_word|, it contains up to four -fields that can be referred to as follows: -$$\vbox{\halign{\hfil#&#\hfil&#\hfil\cr -|x|&.|int|&(an |integer|)\cr -|x|&.|sc|\qquad&(a |scaled| integer)\cr -|x|&.|gr|&(a |glue_ratio|)\cr -|x.hh.lh|, |x.hh|&.|rh|&(two halfword fields)\cr -|x.hh.b0|, |x.hh.b1|, |x.hh|&.|rh|&(two quarterword fields, one halfword - field)\cr -|x.qqqq.b0|, |x.qqqq.b1|, |x.qqqq|&.|b2|, |x.qqqq.b3|\hskip-100pt - &\qquad\qquad\qquad(four quarterword fields)\cr}}$$ -This is somewhat cumbersome to write, and not very readable either, but -macros will be used to make the notation shorter and more transparent. -The \PASCAL\ code below gives a formal definition of |memory_word| and -its subsidiary types, using packed variant records. \TeX\ makes no -assumptions about the relative positions of the fields within a word. - -We are assuming 32-bit integers, a halfword must contain at least -32 bits, and a quarterword must contain at least 16 bits. -@^system dependencies@> - -N.B.: Valuable memory space will be dreadfully wasted unless \TeX\ is compiled -by a \PASCAL\ that packs all of the |memory_word| variants into -the space of a single integer. This means, for example, that |glue_ratio| -words should be |short_real| instead of |real| on some computers. Some -\PASCAL\ compilers will pack an integer whose subrange is `|0..255|' into -an eight-bit field, but others insist on allocating space for an additional -sign bit; on such systems you can get 256 values into a quarterword only -if the subrange is `|-128..127|'. - -The present implementation tries to accommodate as many variations as possible, -so it makes few assumptions. If integers having the subrange -`|min_quarterword..max_quarterword|' can be packed into a quarterword, -and if integers having the subrange `|min_halfword..max_halfword|' -can be packed into a halfword, everything should work satisfactorily. - -It is usually most efficient to have |min_quarterword=min_halfword=0|, -so one should try to achieve this unless it causes a severe problem. -The values defined here are recommended for most 32-bit computers. - -We cannot use the full range of 32 bits in a halfword, because we have -to allow negative values for potential backend tricks like web2c's -dynamic allocation, and parshapes pointers have to be able to store at -least twice the value |max_halfword| (see below). Therefore, -|max_halfword| is $2^{30}-1$ -*/ - -# include "tex/memoryword.h" - -# define min_quarterword 0 /*smallest allowable value in a |quarterword| */ -# define max_quarterword 65535 /* largest allowable value in a |quarterword| */ -# define min_halfword -0x3FFFFFFF /* smallest allowable value in a |halfword| */ -# define max_halfword 0x3FFFFFFF - /* largest allowable value in a |halfword| */ - - -/* -The following procedure, which is called just before \TeX\ initializes its -input and output, establishes the initial values of the date and time. -It calls a macro-defined |dateandtime| routine. |dateandtime| in turn is -also a C macro, which calls |get_date_and_time|, passing it the addresses of -the day, month, etc., so they can be set by the routine. -|get_date_and_time| also sets up interrupt catching if that -is conditionally compiled in the C code. -@^system dependencies@> -*/ - -# define fix_date_and_time() dateandtime(time_par,day_par,month_par,year_par) - -extern int get_luatexversion(void); -extern str_number get_luatexrevision(void); - -extern int ready_already; - -extern void main_body(void); -extern void close_files_and_terminate(void); - -extern void final_cleanup(void); -extern void debug_help(void); /* routine to display various things */ - -extern int main_initialize(void); - -/* lazy me */ -# define get_cur_font() equiv(cur_font_loc) -# define zset_cur_font set_cur_font - - -#endif diff --git a/Build/source/texk/web2c/luatexdir/tex/maincontrol.c b/Build/source/texk/web2c/luatexdir/tex/maincontrol.c deleted file mode 100644 index 22f601ba275..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/maincontrol.c +++ /dev/null @@ -1,4245 +0,0 @@ -/* - -maincontrol.w - -Copyright 2009-2010 Taco Hoekwater <taco@@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your -option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU General Public License along -with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" -#include "lua/luatex-api.h" - -#define mode mode_par -#define tail tail_par -#define head head_par -#define dir_save dirs_par - -/*tex - -We come now to the |main_control| routine, which contains the master switch that -causes all the various pieces of \TeX\ to do their things, in the right order. - -In a sense, this is the grand climax of the program: It applies all the tools -that we have worked so hard to construct. In another sense, this is the messiest -part of the program: It necessarily refers to other pieces of code all over the -place, so that a person can't fully understand what is going on without paging -back and forth to be reminded of conventions that are defined elsewhere. We are -now at the hub of the web, the central nervous system that touches most of the -other parts and ties them together. @^brain@> - -The structure of |main_control| itself is quite simple. There's a label called -|big_switch|, at which point the next token of input is fetched using -|get_x_token|. Then the program branches at high speed into one of about 100 -possible directions, based on the value of the current mode and the newly fetched -command code; the sum |abs(mode)+cur_cmd| indicates what to do next. For example, -the case `|vmode+letter|' arises when a letter occurs in vertical mode (or -internal vertical mode); this case leads to instructions that initialize a new -paragraph and enter horizontal mode. - -The big |case| statement that contains this multiway switch has been labeled -|reswitch|, so that the program can |goto reswitch| when the next token has -already been fetched. Most of the cases are quite short; they call an ``action -procedure'' that does the work for that case, and then they either |goto -reswitch| or they ``fall through'' to the end of the |case| statement, which -returns control back to |big_switch|. Thus, |main_control| is not an extremely -large procedure, in spite of the multiplicity of things it must do; it is small -enough to be handled by PASCAL compilers that put severe restrictions on -procedure size. @!@^action procedure@> - -One case is singled out for special treatment, because it accounts for most of -\TeX's activities in typical applications. The process of reading simple text and -converting it into |char_node| records, while looking for ligatures and kerns, is -part of \TeX's ``inner loop''; the whole program runs efficiently when its inner -loop is fast, so this part has been written with particular care. - -We leave the |space_factor| unchanged if |sf_code(cur_chr)=0|; otherwise we set -it equal to |sf_code(cur_chr)|, except that it should never change from a value -less than 1000 to a value exceeding 1000. The most common case is -|sf_code(cur_chr)=1000|, so we want that case to be fast. - -*/ - -void adjust_space_factor(void) -{ - halfword s = get_sf_code(cur_chr); - if (s == 1000) { - space_factor_par = 1000; - } else if (s < 1000) { - if (s > 0) - space_factor_par = s; - } else if (space_factor_par < 1000) { - space_factor_par = 1000; - } else { - space_factor_par = s; - } -} - -/*tex - -To handle the execution state of |main_control|'s eternal loop, an extra global -variable is used, along with a macro to define its values. - -*/ - -#define goto_next 0 -#define goto_skip_token 1 -#define goto_return 2 - -static int main_control_state; -static int local_level = 0; - -/*tex - -@* Main control helpers. - -Here are all the functions that are called from |main_control| that -are not already defined elsewhere. For the moment, this list simply -in the order that the appear in |init_main_control|, below. - -*/ - -static void run_char_num (void) { - scan_char_num(); - cur_chr = cur_val; - adjust_space_factor(); - tail_append(new_char(cur_font_par, cur_chr)); -} - -static void run_char (void) { - adjust_space_factor(); - tail_append(new_char(cur_font_par, cur_chr)); -} - -static void run_node (void) { - halfword n = cur_chr; - if (copy_lua_input_nodes_par) { - n = copy_node_list(n); - } - tail_append(n); - if (nodetype_has_attributes(type(n)) && node_attr(n) == null) { - build_attribute_list(n); - } - while (vlink(n) != null) { - n = vlink(n); - tail_append(n); - if (nodetype_has_attributes(type(n)) && node_attr(n) == null) { - build_attribute_list(n); - } - } -} - -static void run_lua_call(void) { - if (cur_chr <= 0) { - normal_error("luacall", "invalid number"); - } else { - str_number u = save_cur_string(); - luacstrings = 0; - luafunctioncall(cur_chr); - restore_cur_string(u); - if (luacstrings > 0) - lua_string_start(); - } -} - -/*tex - -The occurrence of blank spaces is almost part of \TeX's inner loop, since we -usually encounter about one space for every five non-blank characters. Therefore -|main_control| gives second-highest priority to ordinary spaces. - -When a glue parameter like \.{\\spaceskip} is set to `\.{0pt}', we will see to it -later that the corresponding glue specification is precisely |zero_glue|, not -merely a pointer to some specification that happens to be full of zeroes. -Therefore it is simple to test whether a glue parameter is zero or~not. - -*/ - -static void run_app_space (void) { - halfword p; /* was a global temp_ptr */ - int method = disable_space_par ; - if (method == 1) { - /*tex Don't inject anything, not even zero skip. */ - } else if (method == 2) { - p = new_glue(zero_glue); - couple_nodes(tail,p); - tail = p; - } else if ((abs(mode) + cur_cmd == hmode + spacer_cmd) && (!(space_factor_par == 1000))) { - app_space(); - } else { - /*tex Append a normal inter-word space to the current list. */ - if (glue_is_zero(space_skip_par)) { - /*tex Find the glue specification for text spaces in the current font. */ - p = new_glue(zero_glue); - width(p) = space(cur_font_par); - stretch(p) = space_stretch(cur_font_par); - shrink(p) = space_shrink(cur_font_par); - - } else { - p = new_param_glue(space_skip_code); - } - /*tex So from now we have a subtype with spaces: */ - subtype(p) = space_skip_code + 1 ; - couple_nodes(tail,p); - tail = p; - } -} - -/*tex - -Append a |boundary_node| - -*/ - -static void run_boundary (void) { - halfword n ; - n = new_node(boundary_node,cur_chr); - if ((cur_chr == 1) || (cur_chr == 2) ) { - /*tex We expect a user boundary or protrusion boundary. */ - scan_int(); - boundary_value(n) = cur_val; - } - couple_nodes(tail, n); - tail = n; -} - -static void run_char_ghost (void) { - int t; - t = cur_chr; - get_x_token(); - if ((cur_cmd == letter_cmd) || (cur_cmd == other_char_cmd) - || (cur_cmd == char_given_cmd) || (cur_cmd == char_num_cmd)) { - halfword p = new_glyph(get_cur_font(), cur_chr); - if (t == 0) { - set_is_leftghost(p); - } else { - set_is_rightghost(p); - } - tail_append(p); - } -} - -static void run_relax (void) { - return; -} - -/*tex - -|ignore_spaces| is a special case: after it has acted, |get_x_token| has already -fetched the next token from the input, so that operation in |main_control| should -be skipped. - -*/ - -static void run_ignore_spaces (void) { - if (cur_chr == 0) { - /*tex Get the next non-blank non-call... */ - do { - get_x_token(); - } while (cur_cmd == spacer_cmd); - main_control_state = goto_skip_token; - } else { - int t = scanner_status; - scanner_status = normal; - get_next(); - scanner_status = t; - cur_cs = prim_lookup(cs_text(cur_cs)); - if (cur_cs != undefined_primitive) { - cur_cmd = get_prim_eq_type(cur_cs); - cur_chr = get_prim_equiv(cur_cs); - cur_tok = (cur_cmd * STRING_OFFSET) + cur_chr; - main_control_state = goto_skip_token; - } - } -} - -/*tex - -|stop| is the second special case. We want |main_control| to return to its caller -if there is nothing left to do. - -*/ - -static void run_stop (void) { - if (its_all_over()) { - /*tex this is the only way out */ - main_control_state= goto_return; - } -} - -static void run_non_math_math (void) { - back_input(); - new_graf(true); -} - -/*tex - - We build up an argument to |set_math_char|: - -*/ - -static void run_math_char_num (void) { - mathcodeval mval; - if (cur_chr == 0) - mval = scan_mathchar(tex_mathcode); - else if (cur_chr == 1) - mval = scan_mathchar(umath_mathcode); - else - mval = scan_mathchar(umathnum_mathcode); - math_char_in_text(mval); -} - -/*tex - - We build up an argument to |set_math_char|: -*/ - -static void run_math_given (void) { - mathcodeval mval; - mval = mathchar_from_integer(cur_chr, tex_mathcode); - math_char_in_text(mval); -} - -/*tex - - We build up an argument to |set_math_char| the \LUATEX\ way: -*/ - -static void run_xmath_given (void) { - mathcodeval mval; - mval = mathchar_from_integer(cur_chr, umath_mathcode); - math_char_in_text(mval); -} - -/*tex - -The most important parts of |main_control| are concerned with \TeX's chief -mission of box-making. We need to control the activities that put entries on -vlists and hlists, as well as the activities that convert those lists into boxes. -All of the necessary machinery has already been developed; it remains for us to -``push the buttons'' at the right times. - -As an introduction to these routines, let's consider one of the simplest cases: -What happens when `\.{\\hrule}' occurs in vertical mode, or `\.{\\vrule}' in -horizontal mode or math mode? The code in |main_control| is short, since the -|scan_rule_spec| routine already does most of what is required; thus, there is no -need for a special action procedure. - -Note that baselineskip calculations are disabled after a rule in vertical mode, -by setting |prev_depth:=ignore_depth|. - -*/ - -static void run_rule (void) { - tail_append(scan_rule_spec()); - if (abs(mode) == vmode) - prev_depth_par = ignore_depth; - else if (abs(mode) == hmode) - space_factor_par = 1000; -} - -/*tex - -Many of the actions related to box-making are triggered by the appearance of -braces in the input. For example, when the user says `\.{\\hbox} \.{to} -\.{100pt\{$\langle\,\hbox{hlist}\,\rangle$\}}' in vertical mode, the information -about the box size (100pt, |exactly|) is put onto |save_stack| with a level -boundary word just above it, and |cur_group:=adjusted_hbox_group|; \TeX\ enters -restricted horizontal mode to process the hlist. The right brace eventually -causes |save_stack| to be restored to its former state, at which time the -information about the box size (100pt, |exactly|) is available once again; a box -is packaged and we leave restricted horizontal mode, appending the new box to the -current list of the enclosing mode (in this case to the current list of vertical -mode), followed by any vertical adjustments that were removed from the box by -|hpack|. - -The next few sections of the program are therefore concerned with the treatment -of left and right curly braces. - -If a left brace occurs in the middle of a page or paragraph, it simply introduces -a new level of grouping, and the matching right brace will not have such a -drastic effect. Such grouping affects neither the mode nor the current list. - -*/ - -static void run_left_brace (void) { - new_save_level(simple_group); - eq_word_define(int_base + no_local_whatsits_code, 0); - eq_word_define(int_base + no_local_dirs_code, 0); -} - -static void run_begin_group (void) { - new_save_level(semi_simple_group); - eq_word_define(int_base + no_local_whatsits_code, 0); - eq_word_define(int_base + no_local_dirs_code, 0); -} - -static void run_end_group (void) { - if (cur_group == semi_simple_group) { - fixup_directions(); - } else { - off_save(); - } -} - -/*tex - -Constructions that require a box are started by calling |scan_box| with a -specified context code. The |scan_box| routine verifies that a |make_box| command -comes next and then it calls |begin_box|. - -*/ - -static void run_move (void) { - int t = cur_chr; - scan_normal_dimen(); - if (t == 0) - scan_box(cur_val); - else - scan_box(-cur_val); -} - -static void run_leader_ship (void) { - scan_box(leader_flag - a_leaders + cur_chr); -} - -static void run_make_box (void) { - begin_box(0); -} - -static void run_box_dir (void) { - scan_register_num(); - cur_box = box(cur_val); - scan_optional_equals(); - scan_direction(); - if (cur_box != null) - box_dir(cur_box) = cur_val; -} - -static void run_box_direction (void) { - scan_register_num(); - cur_box = box(cur_val); - scan_optional_equals(); - scan_int(); - check_dir_value(cur_val); - if (cur_box != null) - box_dir(cur_box) = cur_val; -} - -/*tex - -There is a really small patch to add a new primitive called \.{\\quitvmode}. In -vertical modes, it is identical to \.{\\indent}, but in horizontal and math modes -it is really a no-op (as opposed to \.{\\indent}, which executes the -|indent_in_hmode| procedure). - -A paragraph begins when horizontal-mode material occurs in vertical mode, or when -the paragraph is explicitly started by `\.{\\quitvmode}', `\.{\\indent}' or -`\.{\\noindent}'. - -*/ - -static void run_start_par_vmode (void) { - new_graf((cur_chr > 0)); -} - -static void run_start_par (void) { - if (cur_chr != 2) - indent_in_hmode(); -} - -static void run_new_graf (void) { - back_input(); - new_graf(true); -} - -/*tex - -A paragraph ends when a |par_end| command is sensed, or when we are in horizontal -mode when reaching the right brace of vertical-mode routines like \.{\\vbox}, -\.{\\insert}, or \.{\\output}. - -*/ - -static void run_par_end_vmode (void) { - normal_paragraph(); - if (mode > 0) { - checked_page_filter(vmode_par); - build_page(); - } -} - -static void run_par_end_hmode (void) { - if (align_state < 0) { - /*tex This tries to recover from an alignment that didn't end properly. */ - off_save(); - } - /* This takes us to the enclosing mode, if |mode>0|. */ - end_graf(bottom_level); - if (mode == vmode) { - checked_page_filter(hmode_par); - build_page(); - } -} - -static void append_italic_correction_mmode (void) { - tail_append(new_kern(0)); -} - -static void run_local_box (void) { - append_local_box(cur_chr); -} - -static void run_halign_mmode (void) { - if (privileged()) { - if (cur_group == math_shift_group) - init_align(); - else - off_save(); - } -} - -static void run_eq_no (void) { - if (privileged()) { - if (cur_group == math_shift_group) - start_eq_no(); - else - off_save(); - } -} - -static void run_letter_mmode (void) { - set_math_char(get_math_code(cur_chr)); -} - -static void run_char_num_mmode (void) { - scan_char_num(); - cur_chr = cur_val; - set_math_char(get_math_code(cur_chr)); -} - -static void run_math_char_num_mmode (void) { - mathcodeval mval; - if (cur_chr == 0) - mval = scan_mathchar(tex_mathcode); - else if (cur_chr == 1) - mval = scan_mathchar(umath_mathcode); - else - mval = scan_mathchar(umathnum_mathcode); - set_math_char(mval); -} - -static void run_math_given_mmode (void) { - mathcodeval mval; - mval = mathchar_from_integer(cur_chr, tex_mathcode); - set_math_char(mval); -} - -static void run_xmath_given_mmode (void) { - mathcodeval mval; - mval = mathchar_from_integer(cur_chr, umath_mathcode); - set_math_char(mval); -} - -static void run_delim_num (void) { - mathcodeval mval; - if (cur_chr == 0) - mval = scan_delimiter_as_mathchar(tex_mathcode); - else - mval = scan_delimiter_as_mathchar(umath_mathcode); - set_math_char(mval); -} - -static void run_vcenter (void) { - scan_spec(vcenter_group); - normal_paragraph(); - push_nest(); - mode = -vmode; - prev_depth_par = ignore_depth; - if (every_vbox_par != null) - begin_token_list(every_vbox_par, every_vbox_text); -} - -static void run_math_style (void) { - tail_append(new_style((small_number) cur_chr)); -} - -static void run_non_script (void) { - tail_append(new_glue(zero_glue)); - subtype(tail) = cond_math_glue; -} - -static void run_math_choice (void) { - if (cur_chr == 0) - append_choices(); - else - setup_math_style(); -} - -static void run_math_shift (void) { - if (cur_group == math_shift_group) - after_math(); - else - off_save(); -} - -static void run_after_assignment (void) { - get_token(); - after_token = cur_tok; -} - -static void run_after_group (void) { - get_token(); - save_for_after(cur_tok); -} - -static void run_extension (void) { - do_extension(0); -} - -static void run_normal (void) { -{ - switch (cur_chr) { - case save_pos_code: - new_whatsit(save_pos_node); - break; - case save_cat_code_table_code: - scan_int(); - if ((cur_val < 0) || (cur_val > 0x7FFF)) { - print_err("Invalid \\catcode table"); - help1( - "All \\catcode table ids must be between 0 and 0x7FFF" - ); - error(); - } else { - if (cur_val == cat_code_table_par) { - print_err("Invalid \\catcode table"); - help1( - "You cannot overwrite the current \\catcode table" - ); - error(); - } else { - copy_cat_codes(cat_code_table_par, cur_val); - } - } - break; - case init_cat_code_table_code: - scan_int(); - if ((cur_val < 0) || (cur_val > 0x7FFF)) { - print_err("Invalid \\catcode table"); - help1( - "All \\catcode table ids must be between 0 and 0x7FFF" - ); - error(); - } else { - if (cur_val == cat_code_table_par) { - print_err("Invalid \\catcode table"); - help1( - "You cannot overwrite the current \\catcode table" - ); - error(); - } else { - initex_cat_codes(cur_val); - } - } - break; - case set_random_seed_code: - /* Negative random seed values are silently converted to positive ones */ - scan_int(); - if (cur_val < 0) - negate(cur_val); - random_seed = cur_val; - init_randoms(random_seed); - break; - case late_lua_code: - new_whatsit(late_lua_node); /* type == normal */ - late_lua_name(tail) = scan_lua_state(); - (void) scan_toks(false, false); - late_lua_data(tail) = def_ref; - break; - case late_lua_call_code: - new_whatsit(late_lua_node); - late_lua_type(tail) = lua_refid_call; - scan_int(); - late_lua_data(tail) = cur_val; - break; - case expand_font_code: - read_expand_font(); - break; - default: - confusion("int1"); - break; - } - } -} - -/*tex - -This is experimental and not used for production, only for testing and writing -macros (some options stay). - -*/ - -#define mathoption_set_int(A) \ - scan_int(); \ - word_define(mathoption_int_base+A, cur_val); - -static void run_option(void) { - int a = 0 ; - switch (cur_chr) { - case math_option_code: - if (scan_keyword("old")) { - mathoption_set_int(c_mathoption_old_code); - /* - } else if (scan_keyword("umathcodemeaning")) { - mathoption_set_int(c_mathoption_umathcode_meaning_code); - */ - } else { - normal_warning("mathoption","unknown key"); - } - break; - default: - /* harmless */ - break; - } -} - -static void lua_function_call(void) { - scan_int(); - if (cur_val <= 0) { - normal_error("luafunctioncall", "invalid number"); - } else { - str_number u = save_cur_string(); - luacstrings = 0; - luafunctioncall(cur_val); - restore_cur_string(u); - if (luacstrings > 0) - lua_string_start(); - } -} - -static void lua_bytecode_call(void) { - scan_int(); - if (cur_val < 0 || cur_val > 65535) { - normal_error("luabytecodecall", "invalid number"); - } else { - str_number u = save_cur_string(); - luacstrings = 0; - luabytecodecall(cur_val); - restore_cur_string(u); - if (luacstrings > 0) - lua_string_start(); - } -} - -/*tex - -For mode-independent commands, the following macro is useful. - -Also, there is a list of cases where the user has probably gotten into or out of -math mode by mistake. \TeX\ will insert a dollar sign and rescan the current -token, and it makes sense ot have a macro for that as well. - -*/ - -#define any_mode(A,B) jump_table[vmode+(A)]=B; jump_table[hmode+(A)]=B; jump_table[mmode+(A)]=B -#define non_math(A,B) jump_table[vmode+(A)]=B; jump_table[hmode+(A)]=B; - -/*tex - -The |main_control| uses a jump table, and |init_main_control| sets that table up. - -*/ - -typedef void (*main_control_function) (void); - -main_control_function *jump_table; - -static void init_main_control (void) { - jump_table = xmalloc((mmode+max_command_cmd+1) * sizeof(main_control_function)) ; - - jump_table[hmode + char_num_cmd] = run_char_num; - jump_table[hmode + letter_cmd] = run_char; - jump_table[hmode + other_char_cmd] = run_char; - jump_table[hmode + char_given_cmd] = run_char; - jump_table[hmode + spacer_cmd] = run_app_space; - jump_table[hmode + ex_space_cmd] = run_app_space; - jump_table[mmode + ex_space_cmd] = run_app_space; - jump_table[hmode + boundary_cmd] = run_boundary; - jump_table[hmode + char_ghost_cmd] = run_char_ghost; - jump_table[mmode + char_ghost_cmd] = run_char_ghost; - any_mode(relax_cmd, run_relax); - jump_table[vmode + spacer_cmd] = run_relax; - jump_table[mmode + spacer_cmd] = run_relax; - jump_table[mmode + boundary_cmd] = run_relax; - any_mode(ignore_spaces_cmd,run_ignore_spaces); - jump_table[vmode + stop_cmd] = run_stop; - jump_table[vmode + math_char_num_cmd] = run_non_math_math; - jump_table[vmode + math_given_cmd] = run_non_math_math; - jump_table[vmode + xmath_given_cmd] = run_non_math_math; - jump_table[hmode + math_char_num_cmd] = run_math_char_num; - jump_table[hmode + math_given_cmd] = run_math_given; - jump_table[hmode + xmath_given_cmd] = run_xmath_given; - - jump_table[vmode + vmove_cmd] = report_illegal_case; - jump_table[hmode + hmove_cmd] = report_illegal_case; - jump_table[mmode + hmove_cmd] = report_illegal_case; - any_mode(last_item_cmd, report_illegal_case); - jump_table[vmode + vadjust_cmd] = report_illegal_case; - jump_table[vmode + ital_corr_cmd] = report_illegal_case; - non_math(eq_no_cmd,report_illegal_case); - any_mode(mac_param_cmd,report_illegal_case); - - non_math(sup_mark_cmd, insert_dollar_sign); - non_math(sub_mark_cmd, insert_dollar_sign); - non_math(super_sub_script_cmd, insert_dollar_sign); - non_math(no_super_sub_script_cmd, insert_dollar_sign); - non_math(math_comp_cmd, insert_dollar_sign); - non_math(delim_num_cmd, insert_dollar_sign); - non_math(left_right_cmd, insert_dollar_sign); - non_math(above_cmd, insert_dollar_sign); - non_math(radical_cmd, insert_dollar_sign); - non_math(math_style_cmd, insert_dollar_sign); - non_math(math_choice_cmd, insert_dollar_sign); - non_math(vcenter_cmd, insert_dollar_sign); - non_math(non_script_cmd, insert_dollar_sign); - non_math(mkern_cmd, insert_dollar_sign); - non_math(limit_switch_cmd, insert_dollar_sign); - non_math(mskip_cmd, insert_dollar_sign); - non_math(math_accent_cmd, insert_dollar_sign); - jump_table[mmode + endv_cmd] = insert_dollar_sign; - jump_table[mmode + par_end_cmd] = insert_dollar_sign_par_end; - jump_table[mmode + stop_cmd] = insert_dollar_sign; - jump_table[mmode + vskip_cmd] = insert_dollar_sign; - jump_table[mmode + un_vbox_cmd] = insert_dollar_sign; - jump_table[mmode + valign_cmd] = insert_dollar_sign; - jump_table[mmode + hrule_cmd] = insert_dollar_sign; - jump_table[mmode + no_hrule_cmd] = insert_dollar_sign; - jump_table[vmode + hrule_cmd] = run_rule; - jump_table[vmode + no_hrule_cmd] = run_rule; - jump_table[hmode + vrule_cmd] = run_rule; - jump_table[hmode + no_vrule_cmd] = run_rule; - jump_table[mmode + vrule_cmd] = run_rule; - jump_table[mmode + no_vrule_cmd] = run_rule; - jump_table[vmode + vskip_cmd] = append_glue; - jump_table[hmode + hskip_cmd] = append_glue; - jump_table[mmode + hskip_cmd] = append_glue; - jump_table[mmode + mskip_cmd] = append_glue; - any_mode(kern_cmd, append_kern); - jump_table[mmode + mkern_cmd] = append_kern; - non_math(left_brace_cmd, run_left_brace); - any_mode(begin_group_cmd,run_begin_group); - any_mode(end_group_cmd, run_end_group); - any_mode(right_brace_cmd, handle_right_brace); - jump_table[vmode + hmove_cmd] = run_move; - jump_table[hmode + vmove_cmd] = run_move; - jump_table[mmode + vmove_cmd] = run_move; - any_mode(leader_ship_cmd, run_leader_ship); - any_mode(make_box_cmd, run_make_box); - any_mode(assign_box_dir_cmd, run_box_dir); - any_mode(assign_box_direction_cmd, run_box_direction); - jump_table[vmode + start_par_cmd] = run_start_par_vmode; - jump_table[hmode + start_par_cmd] = run_start_par; - jump_table[mmode + start_par_cmd] = run_start_par; - jump_table[vmode + letter_cmd] = run_new_graf; - jump_table[vmode + other_char_cmd] = run_new_graf; - jump_table[vmode + char_num_cmd] = run_new_graf; - jump_table[vmode + char_given_cmd] = run_new_graf; - jump_table[vmode + char_ghost_cmd] = run_new_graf; - jump_table[vmode + math_shift_cmd] = run_new_graf; - jump_table[vmode + math_shift_cs_cmd] = run_new_graf; - jump_table[vmode + un_hbox_cmd] = run_new_graf; - jump_table[vmode + vrule_cmd] = run_new_graf; - jump_table[vmode + no_vrule_cmd] = run_new_graf; - jump_table[vmode + accent_cmd] = run_new_graf; - jump_table[vmode + discretionary_cmd] = run_new_graf; - jump_table[vmode + hskip_cmd] = run_new_graf; - jump_table[vmode + valign_cmd] = run_new_graf; - jump_table[vmode + ex_space_cmd] = run_new_graf; - jump_table[vmode + boundary_cmd] = run_new_graf; - jump_table[vmode + par_end_cmd] = run_par_end_vmode; - jump_table[hmode + par_end_cmd] = run_par_end_hmode; - jump_table[hmode + stop_cmd] = head_for_vmode; - jump_table[hmode + vskip_cmd] = head_for_vmode; - jump_table[hmode + hrule_cmd] = head_for_vmode; - jump_table[hmode + no_hrule_cmd] = head_for_vmode; - jump_table[hmode + un_vbox_cmd] = head_for_vmode; - jump_table[hmode + halign_cmd] = head_for_vmode; - any_mode(insert_cmd,begin_insert_or_adjust); - jump_table[hmode + vadjust_cmd] = begin_insert_or_adjust; - jump_table[mmode + vadjust_cmd] = begin_insert_or_adjust; - any_mode(mark_cmd, handle_mark); - any_mode(break_penalty_cmd, append_penalty); - any_mode(remove_item_cmd, delete_last); - jump_table[vmode + un_vbox_cmd] = unpackage; - jump_table[hmode + un_hbox_cmd] = unpackage; - jump_table[mmode + un_hbox_cmd] = unpackage; - jump_table[hmode + ital_corr_cmd] = append_italic_correction; - jump_table[mmode + ital_corr_cmd] = append_italic_correction_mmode; - jump_table[hmode + discretionary_cmd] = append_discretionary; - jump_table[mmode + discretionary_cmd] = append_discretionary; - any_mode(assign_local_box_cmd, run_local_box); - jump_table[hmode + accent_cmd] = make_accent; - any_mode(car_ret_cmd,align_error); - any_mode(tab_mark_cmd,align_error); - any_mode(no_align_cmd,no_align_error); - any_mode(omit_cmd, omit_error); - jump_table[vmode + halign_cmd] = init_align; - jump_table[hmode + valign_cmd] = init_align; - jump_table[mmode + halign_cmd] = run_halign_mmode; - jump_table[vmode + endv_cmd] = do_endv; - jump_table[hmode + endv_cmd] = do_endv; - any_mode(end_cs_name_cmd, cs_error); - jump_table[hmode + math_shift_cmd] = init_math; - jump_table[hmode + math_shift_cs_cmd] = init_math; - jump_table[mmode + eq_no_cmd] = run_eq_no; - jump_table[mmode + left_brace_cmd] = math_left_brace; - jump_table[mmode + letter_cmd] = run_letter_mmode; - jump_table[mmode + other_char_cmd] = run_letter_mmode; - jump_table[mmode + char_given_cmd] = run_letter_mmode; - jump_table[mmode + char_num_cmd] = run_char_num_mmode; - jump_table[mmode + math_char_num_cmd] = run_math_char_num_mmode; - jump_table[mmode + math_given_cmd] = run_math_given_mmode; - jump_table[mmode + xmath_given_cmd] = run_xmath_given_mmode; - jump_table[mmode + delim_num_cmd] = run_delim_num; - jump_table[mmode + math_comp_cmd] = math_math_comp; - jump_table[mmode + limit_switch_cmd] = math_limit_switch; - jump_table[mmode + radical_cmd] = math_radical; - jump_table[mmode + accent_cmd] = math_ac; - jump_table[mmode + math_accent_cmd] = math_ac; - jump_table[mmode + vcenter_cmd] = run_vcenter; - jump_table[mmode + math_style_cmd] = run_math_style; - jump_table[mmode + non_script_cmd] = run_non_script; - jump_table[mmode + math_choice_cmd] = run_math_choice; - jump_table[mmode + above_cmd] = math_fraction; - jump_table[mmode + sub_mark_cmd] = sub_sup; - jump_table[mmode + sup_mark_cmd] = sub_sup; - jump_table[mmode + super_sub_script_cmd] = sub_sup; - jump_table[mmode + no_super_sub_script_cmd] = no_sub_sup; - jump_table[mmode + left_right_cmd] = math_left_right; - jump_table[mmode + math_shift_cmd] = run_math_shift; - jump_table[mmode + math_shift_cs_cmd] = run_math_shift; - any_mode(toks_register_cmd, prefixed_command); - any_mode(assign_toks_cmd, prefixed_command); - any_mode(assign_int_cmd, prefixed_command); - any_mode(assign_attr_cmd, prefixed_command); - any_mode(assign_dir_cmd, prefixed_command); - any_mode(assign_direction_cmd, prefixed_command); - any_mode(assign_dimen_cmd, prefixed_command); - any_mode(assign_glue_cmd, prefixed_command); - any_mode(assign_mu_glue_cmd, prefixed_command); - any_mode(assign_font_dimen_cmd, prefixed_command); - any_mode(assign_font_int_cmd, prefixed_command); - any_mode(set_aux_cmd, prefixed_command); - any_mode(set_prev_graf_cmd, prefixed_command); - any_mode(set_page_dimen_cmd, prefixed_command); - any_mode(set_page_int_cmd, prefixed_command); - any_mode(set_box_dimen_cmd, prefixed_command); - any_mode(set_tex_shape_cmd, prefixed_command); - any_mode(set_etex_shape_cmd, prefixed_command); - any_mode(def_char_code_cmd, prefixed_command); - any_mode(def_del_code_cmd, prefixed_command); - any_mode(extdef_math_code_cmd, prefixed_command); - any_mode(extdef_del_code_cmd, prefixed_command); - any_mode(def_family_cmd, prefixed_command); - any_mode(set_math_param_cmd, prefixed_command); - any_mode(set_font_cmd, prefixed_command); - any_mode(def_font_cmd, prefixed_command); - any_mode(letterspace_font_cmd, prefixed_command); - any_mode(copy_font_cmd, prefixed_command); - any_mode(set_font_id_cmd, prefixed_command); - any_mode(register_cmd, prefixed_command); - any_mode(advance_cmd, prefixed_command); - any_mode(multiply_cmd, prefixed_command); - any_mode(divide_cmd, prefixed_command); - any_mode(prefix_cmd, prefixed_command); - any_mode(let_cmd, prefixed_command); - any_mode(shorthand_def_cmd, prefixed_command); - any_mode(read_to_cs_cmd, prefixed_command); - any_mode(def_cmd, prefixed_command); - any_mode(set_box_cmd, prefixed_command); - any_mode(hyph_data_cmd, prefixed_command); - any_mode(set_interaction_cmd, prefixed_command); - any_mode(after_assignment_cmd,run_after_assignment); - any_mode(after_group_cmd,run_after_group); - any_mode(in_stream_cmd,open_or_close_in); - any_mode(message_cmd,issue_message); - any_mode(case_shift_cmd, shift_case); - any_mode(xray_cmd, show_whatever); - any_mode(normal_cmd, run_normal); - any_mode(extension_cmd, run_extension); - any_mode(option_cmd, run_option); - - any_mode(lua_function_call_cmd, lua_function_call); - any_mode(lua_bytecode_call_cmd, lua_bytecode_call); - any_mode(def_lua_call_cmd, prefixed_command); - any_mode(lua_call_cmd, run_lua_call); - /* any_mode(lua_expandable_call_cmd, run_lua_call); */ /* no! outside jump table anyway, handled in expand() */ - any_mode(node_cmd, run_node); - - any_mode(combine_toks_cmd, combine_the_toks); -} - -/*tex - - And here is |main_control| itself. It is quite short nowadays. - -*/ - -void main_control(void) -{ - main_control_state = goto_next; - init_main_control() ; - if (equiv(every_job_loc) != null) { - begin_token_list(equiv(every_job_loc), every_job_text); - } - while (1) { - if (main_control_state == goto_skip_token) { - main_control_state = goto_next; - } else { - get_x_token(); - } - /*tex - Give diagnostic information, if requested When a new token has just - been fetched at |big_switch|, we have an ideal place to monitor - \TeX's activity. - */ - if (interrupt != 0 && OK_to_interrupt) { - back_input(); - check_interrupt(); - continue; - } - if (tracing_commands_par > 0) { - show_cur_cmd_chr(); - } - /*tex run the command */ - (jump_table[(abs(mode) + cur_cmd)])(); - if (main_control_state == goto_return) { - return; - } - } - /*tex not reached */ - return; -} - -/*tex - -We assume a trailing relax: |{...}\relax|, so we don't need a |back_input()| here. - -*/ - -extern void local_control_message(const char *s) -{ - tprint("local control level "); - print_int(local_level); - tprint(": "); - tprint(s); - tprint_nl(""); -} - -/*tex Note for me (HH): in luametatex I have the option to use the save stack which for - some experiments seems to work better. But I'll probably not go forward with - some intended extension anyway (too messy), so we're currently in sync. - Instead there are now two optional parameters in |runtoks|, plus a |quittoks| - companion. I also added some more tracing as well as a warning when we jump - out of control too often. -*/ - -void local_control(void) -{ - /*tex Wrr to saving the state local_control is like some of the conv_toks which - is not entirely correct but good enough for now. Future extensions might - demand another solution. - */ - int save_scanner_status = scanner_status; - halfword save_def_ref = def_ref; - halfword save_warning_index = warning_index; - int ll = local_level; - main_control_state = goto_next; - local_level += 1; - if (tracing_nesting_par > 2) { - local_control_message("entering local control"); - } - while (1) { - if (main_control_state == goto_skip_token) { - main_control_state = goto_next; - } else { - get_x_token(); - } - if (interrupt != 0 && OK_to_interrupt) { - back_input(); - check_interrupt(); - continue; - } - if (tracing_commands_par > 0) { - show_cur_cmd_chr(); - } - (jump_table[(abs(mode) + cur_cmd)])(); - if (local_level <= ll) { - main_control_state = goto_next; - if (tracing_nesting_par > 2) { - local_control_message("leaving local control due to level change"); - } - break; - } else if (main_control_state == goto_return) { - if (tracing_nesting_par > 2) { - local_control_message("leaving local control due to triggering"); - } - break; - } - } - /*tex From the perspective of ending and changing the level this is the - wrong spot, as it should be done in |end_local_control| in which case - we should use the save stack. Maybe some day. - */ - scanner_status = save_scanner_status; - def_ref = save_def_ref; - warning_index = save_warning_index; -} - -void end_local_control(void ) -{ - if (local_level > 0) { - local_level -= 1; - } else { - local_control_message("redundant end local control"); - } -} - -/*tex - We need to go back to the main loop. This is rather nasty and dirty - and counterintuive code and there might be a cleaner way. Basically - we trigger the main control state from here. - - \starttyping - 0 0 \directlua{token.scan_list()}\hbox{!} - -1 0 \setbox0\hbox{x}\directlua{token.scan_list()}\box0 - 1 1 \toks0={\directlua{token.scan_list()}\hbox{x}}\directlua{tex.runtoks(0)} - 0 0 1 1 \directlua{tex.box[0]=token.scan_list()}\hbox{x\directlua{node.write(token.scan_list())}\hbox{x}} - 0 0 0 1 \setbox0\hbox{x}\directlua{tex.box[0]=token.scan_list()}\hbox{x\directlua{node.write(token.scan_list())}\box0} - \stoptyping - - It's rather fragile code so we added some tracing options. - -*/ - -halfword local_scan_box(void) -{ - int old_mode = mode; - int ll = local_level; - mode = -hmode; - scan_box(lua_scan_flag); - if (local_level == ll) { - /*tex |\directlua{print(token.scan_list())}\hbox{!}| (n n) */ - if (tracing_nesting_par > 2) { - local_control_message("entering at end of box scanning"); - } - local_control(); - } else { - /*tex |\directlua{print(token.scan_list())}\box0| (n-1 n) */ - /* - if (tracing_nesting_par > 2) { - local_control_message("setting level after box scanning"); - } - */ - local_level = ll; - } - mode = old_mode; - return cur_box; -} - -/*tex - - We have an issue with modes when we quit here because we're coming - from and still staying at the \LUA\ end. So, unless we're already - nested, we trigger an end_local_level token (an extension code). - -*/ - -static void wrapup_local_scan_box(void) -{ - /* - if (tracing_nesting_par > 2) { - local_control_message("leaving box scanner"); - } - */ - local_level -= 1; -} - -int current_local_level(void) -{ - return local_level; -} - -void app_space(void) -{ /* handle spaces when |space_factor<>1000| */ - halfword q; /* glue node */ - if ((space_factor_par >= 2000) && (! glue_is_zero(xspace_skip_par))) { - q = new_param_glue(xspace_skip_code); - /* so from now we have a subtype with spaces: */ - subtype(q) = xspace_skip_code + 1; - } else { - if (!glue_is_zero(space_skip_par)) { - q = new_glue(space_skip_par); - } else { - q = new_glue(zero_glue); - width(q) = space(cur_font_par); - stretch(q) = space_stretch(cur_font_par); - shrink(q) = space_shrink(cur_font_par); - } - /* Modify the glue specification in |q| according to the space factor */ - if (space_factor_par >= 2000) - width(q) = width(q) + extra_space(cur_font_par); - stretch(q) = xn_over_d(stretch(q), space_factor_par, 1000); - shrink(q) = xn_over_d(shrink(q), 1000, space_factor_par); - - /* so from now we have a subtype with spaces: */ - subtype(q) = space_skip_code + 1; - } - couple_nodes(tail, q); - tail = q; -} - -void insert_dollar_sign(void) -{ - back_input(); - cur_tok = math_shift_token + '$'; - print_err("Missing $ inserted"); - help2( - "I've inserted a begin-math/end-math symbol since I think", - "you left one out. Proceed, with fingers crossed." - ); - ins_error(); -} - -/*tex - - We can silently ignore \.{\\par}s in a math formula. - -*/ - -void insert_dollar_sign_par_end(void) -{ - if (!suppress_mathpar_error_par) { - insert_dollar_sign() ; - } -} - -/*tex - -The `|you_cant|' procedure prints a line saying that the current command is -illegal in the current mode; it identifies these things symbolically. - -*/ - -void you_cant(void) -{ - print_err("You can't use `"); - print_cmd_chr((quarterword) cur_cmd, cur_chr); - print_in_mode(mode); -} - -/*tex - -When erroneous situations arise, \TeX\ usually issues an error message specific -to the particular error. For example, `\.{\\noalign}' should not appear in any -mode, since it is recognized by the |align_peek| routine in all of its legitimate -appearances; a special error message is given when `\.{\\noalign}' occurs -elsewhere. But sometimes the most appropriate error message is simply that the -user is not allowed to do what he or she has attempted. For example, -`\.{\\moveleft}' is allowed only in vertical mode, and `\.{\\lower}' only in -non-vertical modes. Such cases are enumerated here and in the other sections -referred to under `See also \dots.' - -*/ - -void report_illegal_case(void) -{ - you_cant(); - help4( - "Sorry, but I'm not programmed to handle this case;", - "I'll just pretend that you didn''t ask for it.", - "If you're in the wrong mode, you might be able to", - "return to the right one by typing `I}' or `I$' or `I\\par'." - ); - error(); -} - -/*tex - -Some operations are allowed only in privileged modes, i.e., in cases that -|mode>0|. The |privileged| function is used to detect violations of this rule; it -issues an error message and returns |false| if the current |mode| is negative. - -*/ - -boolean privileged(void) -{ - if (mode > 0) { - return true; - } else { - report_illegal_case(); - return false; - } -} - -/*tex - -We don't want to leave |main_control| immediately when a |stop| command is -sensed, because it may be necessary to invoke an \.{\\output} routine several -times before things really grind to a halt. (The output routine might even say -`\.{\\gdef\\end\{...\}}', to prolong the life of the job.) Therefore -|its_all_over| is |true| only when the current page and contribution list are -empty, and when the last output was not a ``dead cycle.'' - -*/ - - -boolean its_all_over(void) -{ /* do this when \.{\\end} or \.{\\dump} occurs */ - if (privileged()) { - if ((page_head == page_tail) && (head == tail) && (dead_cycles == 0)) { - return true; - } - back_input(); /* we will try to end again after ejecting residual material */ - tail_append(new_null_box()); - width(tail) = hsize_par; - tail_append(new_glue(fill_glue)); - tail_append(new_penalty(-010000000000,final_penalty)); - normal_page_filter(end); - build_page(); /* append \.{\\hbox to \\hsize\{\}\\vfill\\penalty-'10000000000} */ - } - return false; -} - -/*tex - -The |hskip| and |vskip| command codes are used for control sequences like -\.{\\hss} and \.{\\vfil} as well as for \.{\\hskip} and \.{\\vskip}. The -difference is in the value of |cur_chr|. - -All the work relating to glue creation has been relegated to the following -subroutine. It does not call |build_page|, because it is used in at least one -place where that would be a mistake. - -*/ - -void append_glue(void) -{ - int s = cur_chr; - switch (s) { - case fil_code: - cur_val = new_glue(fil_glue); - break; - case fill_code: - cur_val = new_glue(fill_glue); - break; - case ss_code: - cur_val = new_glue(ss_glue); - break; - case fil_neg_code: - cur_val = new_glue(fil_neg_glue); - break; - case skip_code: - scan_glue(glue_val_level); - break; - case mskip_code: - scan_glue(mu_val_level); - break; - } - /* now |cur_val| points to the glue specification */ - tail_append(new_glue(cur_val)); - flush_node(cur_val); - if (s > skip_code) { - subtype(tail) = mu_glue; - } -} - -void append_kern(void) -{ - int s = cur_chr; /* |subtype| of the kern node */ - scan_dimen((s == mu_glue), false, false); - tail_append(new_kern(cur_val)); - subtype(tail) = (quarterword) s; -} - -/*tex - -We have to deal with errors in which braces and such things are not properly -nested. Sometimes the user makes an error of commission by inserting an extra -symbol, but sometimes the user makes an error of omission. \TeX\ can't always -tell one from the other, so it makes a guess and tries to avoid getting into a -loop. - -The |off_save| routine is called when the current group code is wrong. It tries -to insert something into the user's input that will help clean off the top level. - -*/ - -void off_save(void) -{ - halfword p, q; - if (cur_group == bottom_level) { - /*tex Drop current token and complain that it was unmatched */ - print_err("Extra "); - print_cmd_chr((quarterword) cur_cmd, cur_chr); - help1( - "Things are pretty mixed up, but I think the worst is over." - ); - error(); - - } else { - back_input(); - p = get_avail(); - set_token_link(temp_token_head, p); - print_err("Missing "); - /*tex - Prepare to insert a token that matches |cur_group|, and print what it - is. At this point, |link(temp_token_head)=p|, a pointer to an empty - one-word node. - */ - switch (cur_group) { - case semi_simple_group: - set_token_info(p, cs_token_flag + frozen_end_group); - tprint_esc("endgroup"); - break; - case math_shift_group: - set_token_info(p, math_shift_token + '$'); - print_char('$'); - break; - case math_left_group: - set_token_info(p, cs_token_flag + frozen_right); - q = get_avail(); - set_token_link(p, q); - p = token_link(p); - set_token_info(p, other_token + '.'); - tprint_esc("right."); - break; - default: - set_token_info(p, right_brace_token + '}'); - print_char('}'); - break; - } - tprint(" inserted"); - ins_list(token_link(temp_token_head)); - help5( - "I've inserted something that you may have forgotten.", - "(See the <inserted text> above.)", - "With luck, this will get me unwedged. But if you", - "really didn't forget anything, try typing `2' now; then", - "my insertion and my current dilemma will both disappear." - ); - error(); - } -} -/*tex - -The routine for a |right_brace| character branches into many subcases, since a -variety of things may happen, depending on |cur_group|. Some types of groups are -not supposed to be ended by a right brace; error messages are given in hopes of -pinpointing the problem. Most branches of this routine will be filled in later, -when we are ready to understand them; meanwhile, we must prepare ourselves to -deal with such errors. - -*/ - -void handle_right_brace(void) -{ - halfword p, q; /* for short-term use */ - scaled d; /* holds |split_max_depth| in |insert_group| */ - int f; /* holds |floating_penalty| in |insert_group| */ - p = null; - switch (cur_group) { - case simple_group: - fixup_directions(); - break; - case bottom_level: - print_err("Too many }'s"); - help2( - "You've closed more groups than you opened.", - "Such booboos are generally harmless, so keep going." - ); - error(); - break; - case semi_simple_group: - case math_shift_group: - case math_left_group: - extra_right_brace(); - break; - /*tex - When the right brace occurs at the end of an \.{\\hbox} or - \.{\\vbox} or \.{\\vtop} construction, the |package| routine - comes into action. We might also have to finish a paragraph that - hasn't ended. - */ - case hbox_group: - if (fixup_boxes_par) { - /*tex - This is unofficial! Fixing up (also elsewhere) might become default - some day but for a while I will test this in ConTeXt. - */ - fixup_directions_only(); - } - package(0); - break; - case adjusted_hbox_group: - adjust_tail = adjust_head; - pre_adjust_tail = pre_adjust_head; - package(0); - break; - case vbox_group: - end_graf(vbox_group); - package(0); - break; - case vtop_group: - end_graf(vtop_group); - package(vtop_code); - break; - case insert_group: - end_graf(insert_group); - q = new_glue(split_top_skip_par); - d = split_max_depth_par; - f = floating_penalty_par; - unsave(); - save_ptr--; - /*tex - Now |saved_value(0)| is the insertion number, or the |vadjust| subtype. - */ - p = vpack(vlink(head), 0, additional, -1); - pop_nest(); - if (saved_type(0) == saved_insert) { - tail_append(new_node(ins_node, saved_value(0))); - height(tail) = height(p) + depth(p); - ins_ptr(tail) = list_ptr(p); - split_top_ptr(tail) = q; - depth(tail) = d; - float_cost(tail) = f; - } else if (saved_type(0) == saved_adjust) { - tail_append(new_node(adjust_node, saved_value(0))); - adjust_ptr(tail) = list_ptr(p); - flush_node(q); - } else { - confusion("insert_group"); - } - list_ptr(p) = null; - flush_node(p); - if (nest_ptr == 0) { - checked_page_filter(insert); - build_page(); - } - break; - case output_group: - /*tex - this is needed in case the \.{\\output} executes a \.{\\textdir} command. - */ - if (dir_level(text_dir_ptr) == cur_level) { - /*tex Remove from |text_dir_ptr| */ - halfword text_dir_tmp = vlink(text_dir_ptr); - flush_node(text_dir_ptr); - text_dir_ptr = text_dir_tmp; - } - resume_after_output(); - break; - case disc_group: - build_discretionary(); - break; - case local_box_group: - build_local_box(); - break; - case align_group: - back_input(); - cur_tok = cs_token_flag + frozen_cr; - print_err("Missing \\cr inserted"); - help1( - "I'm guessing that you meant to end an alignment here." - ); - ins_error(); - break; - case no_align_group: - end_graf(no_align_group); - unsave(); - align_peek(); - break; - case vcenter_group: - end_graf(vcenter_group); - finish_vcenter(); - break; - case math_choice_group: - build_choices(); - break; - case math_group: - close_math_group(p); - break; - default: - confusion("rightbrace"); - break; - } -} - -void extra_right_brace(void) -{ - print_err("Extra }, or forgotten "); - switch (cur_group) { - case semi_simple_group: - tprint_esc("endgroup"); - break; - case math_shift_group: - print_char('$'); - break; - case math_left_group: - tprint_esc("right"); - break; - } - help5( - "I've deleted a group-closing symbol because it seems to be", - "spurious, as in `$x}$'. But perhaps the } is legitimate and", - "you forgot something else, as in `\\hbox{$x}'. In such cases", - "the way to recover is to insert both the forgotten and the", - "deleted material, e.g., by typing `I$}'." - ); - error(); - incr(align_state); -} - -/*tex - -Here is where we clear the parameters that are supposed to revert to their -default values after every paragraph and when internal vertical mode is entered. - -*/ - -void normal_paragraph(void) -{ - if (looseness_par != 0) - eq_word_define(int_base + looseness_code, 0); - if (hang_indent_par != 0) - eq_word_define(dimen_base + hang_indent_code, 0); - if (hang_after_par != 1) - eq_word_define(int_base + hang_after_code, 1); - if (par_shape_par_ptr != null) - eq_define(par_shape_loc, shape_ref_cmd, null); - if (inter_line_penalties_par_ptr != null) - eq_define(inter_line_penalties_loc, shape_ref_cmd, null); - if (shape_mode_par > 0) - eq_word_define(dimen_base + shape_mode_code, 0); -} - -/*tex - -The global variable |cur_box| will point to a newly-made box. If the box is void, -we will have |cur_box=null|. Otherwise we will have |type(cur_box)=hlist_node| or -|vlist_node| or |rule_node|; the |rule_node| case can occur only with leaders. - -*/ - -halfword cur_box; /* box to be placed into its context */ - -/*tex - -The |box_end| procedure does the right thing with |cur_box|, if |box_context| -represents the context as explained above. - -*/ - -void box_end(int box_context) -{ - if (box_context < box_flag) { - /*tex - - Append box |cur_box| to the current list, shifted by |box_context|. - The global variable |adjust_tail| will be non-null if and only if the - current box might include adjustments that should be appended to the - current vertical list. - - */ - - if (cur_box != null) { - shift_amount(cur_box) = box_context; - if (abs(mode) == vmode) { - if (pre_adjust_tail != null) { - if (pre_adjust_head != pre_adjust_tail) - append_list(pre_adjust_head, pre_adjust_tail); - pre_adjust_tail = null; - } - append_to_vlist(cur_box,lua_key_index(box)); - if (adjust_tail != null) { - if (adjust_head != adjust_tail) - append_list(adjust_head, adjust_tail); - adjust_tail = null; - } - if (mode > 0) { - checked_page_filter(box); - build_page(); - } - } else { - if (abs(mode) == hmode) - space_factor_par = 1000; - else - cur_box = new_sub_box(cur_box); - couple_nodes(tail, cur_box); - tail = cur_box; - } - } - } else if (box_context < ship_out_flag) { - /*tex - Store |cur_box| in a box register - */ - if (box_context < global_box_flag) - eq_define(box_base + box_context - box_flag, box_ref_cmd, cur_box); - else - geq_define(box_base + box_context - global_box_flag, box_ref_cmd, cur_box); - } else if (box_context == lua_scan_flag) { - /*tex - We are done with scanning so let's return to the caller. - */ - wrapup_local_scan_box(); - } else if (cur_box != null) { - /*tex - The leaders contexts come after shipout and luascan contexts. - */ - /* if (box_context > lua_scan_flag) { */ - if (box_context >= leader_flag) { - /*tex - Append a new leader node that uses |cur_box| and get the next - non-blank non-relax... - */ - do { - get_x_token(); - } while ((cur_cmd == spacer_cmd) || (cur_cmd == relax_cmd)); - if (((cur_cmd == hskip_cmd) && (abs(mode) != vmode)) || - ((cur_cmd == vskip_cmd) && (abs(mode) == vmode))) { - append_glue(); - subtype(tail) = (quarterword) (box_context - (leader_flag - a_leaders)); - leader_ptr(tail) = cur_box; - } else { - print_err("Leaders not followed by proper glue"); - help3( - "You should say `\\leaders <box or rule><hskip or vskip>'.", - "I found the <box or rule>, but there's no suitable", - "<hskip or vskip>, so I'm ignoring these leaders." - ); - back_error(); - flush_node_list(cur_box); - } - } else { - if (box_context != ship_out_flag) { - normal_error("scanner","shipout expected"); - } - ship_out(static_pdf, cur_box, SHIPPING_PAGE); - } - } -} - -/*tex - -the next input should specify a box or perhaps a rule - -*/ - -void scan_box(int box_context) -{ - /*tex Get the next non-blank non-relax... */ - do { - get_x_token(); - } while ((cur_cmd == spacer_cmd) || (cur_cmd == relax_cmd)); - if (cur_cmd == make_box_cmd) { - begin_box(box_context); - } else if ((box_context >= leader_flag) && - ((cur_cmd == hrule_cmd) || (cur_cmd == vrule_cmd) || - (cur_cmd == no_hrule_cmd) || (cur_cmd == no_vrule_cmd))) { - cur_box = scan_rule_spec(); - box_end(box_context); - } else { - print_err("A <box> was supposed to be here"); - help3( - "I was expecting to see \\hbox or \\vbox or \\copy or \\box or", - "something like that. So you might find something missing in", - "your output. But keep trying; you can fix this later." - ); - back_error(); - if (box_context == lua_scan_flag) { - cur_box = null; - box_end(box_context); - } - } -} - -void new_graf(boolean indented) -{ - halfword p, q, dir_graf_tmp; - halfword dir_rover; - int callback_id; - if ((mode == vmode) || (head != tail)) { - tail_append(new_param_glue(par_skip_code)); - } - callback_id = callback_defined(new_graf_callback); - if (callback_id > 0) { - run_callback(callback_id, "db->b", cur_list.mode_field,indented,&indented); - } - prev_graf_par = 0; - push_nest(); - mode = hmode; - space_factor_par = 1000; - /*tex Add local paragraph node */ - tail_append(make_local_par_node(new_graf_par_code)); - if (indented) { - p = new_null_box(); - box_dir(p) = par_direction_par; - width(p) = par_indent_par; - subtype(p) = indent_list; - q = tail; - tail_append(p); - } else { - q = tail; - } - dir_rover = text_dir_ptr; - while (dir_rover != null) { - if ((vlink(dir_rover) != null) || (dir_dir(dir_rover) != par_direction_par)) { - dir_graf_tmp = new_dir(dir_dir(dir_rover)); - try_couple_nodes(dir_graf_tmp,vlink(q)); - couple_nodes(q,dir_graf_tmp); - } - dir_rover = vlink(dir_rover); - } - q = head; - while (vlink(q) != null) - q = vlink(q); - tail = q; - if (every_par_par != null) - begin_token_list(every_par_par, every_par_text); - if (nest_ptr == 1) { - checked_page_filter(new_graf); - /*tex put |par_skip| glue on current page */ - build_page(); - } -} - -void indent_in_hmode(void) -{ - halfword p; - if (cur_chr > 0) { - /*tex \.{\\indent} */ - p = new_null_box(); - width(p) = par_indent_par; - if (abs(mode) == hmode) - space_factor_par = 1000; - else - p = new_sub_box(p); - tail_append(p); - } -} - -void head_for_vmode(void) -{ - if (mode < 0) { - if ((cur_cmd != hrule_cmd) && (cur_cmd != no_hrule_cmd)) { - off_save(); - } else { - print_err("You can't use `\\hrule' here except with leaders"); - help2( - "To put a horizontal rule in an hbox or an alignment,", - "you should use \\leaders or \\hrulefill (see The TeXbook)." - ); - error(); - } - } else { - back_input(); - cur_tok = par_token; - back_input(); - token_type = inserted; - } -} - -/*tex - -|dir_save| would have been set by |line_break| by means of |post_line_break|, but -this is not done right now, as it introduces pretty heavy memory leaks. This -means the current code might be wrong in some way that relates to in-paragraph -displays. - -*/ - -void end_graf(int line_break_context) -{ - if (mode == hmode) { - if ((head == tail) || (vlink(head) == tail)) { - if (vlink(head) == tail) - flush_node(vlink(head)); - /*tex |null| paragraphs are ignored, all contain a |local_paragraph| node */ - pop_nest(); - } else { - line_break(false, line_break_context); - } - if (dir_save != null) { - flush_node_list(dir_save); - dir_save = null; - } - normal_paragraph(); - error_count = 0; - } -} - -void begin_insert_or_adjust(void) -{ - if (cur_cmd != vadjust_cmd) { - scan_register_num(); - if (cur_val == output_box_par) { - print_err("You can't \\insert"); - print_int(output_box_par); - help1( - "I'm changing to \\insert0; box \\outputbox is special." - ); - error(); - cur_val = 0; - } - set_saved_record(0, saved_insert, 0, cur_val); - } else if (scan_keyword("pre")) { - set_saved_record(0, saved_adjust, 0, 1); - } else { - set_saved_record(0, saved_adjust, 0, 0); - } - save_ptr++; - new_save_level(insert_group); - scan_left_brace(); - normal_paragraph(); - push_nest(); - mode = -vmode; - prev_depth_par = ignore_depth; -} - -/*tex - -I (TH)'ve renamed the |make_mark| procedure to this, because if the current chr -code is 1, then the actual command was \.{\\clearmarks}, which does not generate -a mark node but instead destroys the current mark tokenlists. - -*/ - -void handle_mark(void) -{ - halfword p; /* new node */ - halfword c; /* the mark class */ - if (cur_chr == clear_marks_code) { - scan_mark_num(); - c = cur_val; - delete_top_mark(c); - delete_bot_mark(c); - delete_first_mark(c); - delete_split_first_mark(c); - delete_split_bot_mark(c); - } else { - if (cur_chr == 0) { - c = 0; - } else { - scan_mark_num(); - c = cur_val; - if (c > biggest_used_mark) - biggest_used_mark = c; - } - p = scan_toks(false, true); - p = new_node(mark_node, 0); /* the |subtype| is not used */ - mark_class(p) = c; - mark_ptr(p) = def_ref; - couple_nodes(tail, p); - tail = p; - } -} - -void append_penalty(void) -{ - scan_int(); - tail_append(new_penalty(cur_val,user_penalty)); - if (mode == vmode) { - checked_page_filter(penalty); - build_page(); - } -} - -/*tex - -When |delete_last| is called, |cur_chr| is the |type| of node that will be -deleted, if present. - -The |remove_item| command removes a penalty, kern, or glue node if it appears at -the tail of the current list, using a brute-force linear scan. Like -\.{\\lastbox}, this command is not allowed in vertical mode (except internal -vertical mode), since the current list in vertical mode is sent to the page -builder. But if we happen to be able to implement it in vertical mode, we do. - -*/ - -void delete_last(void) -{ - halfword p, q; /* run through the current list */ - if ((mode == vmode) && (tail == head)) { - /*tex - Apologize for inability to do the operation now, unless \.{\\unskip} - follows non-glue - */ - if ((cur_chr != glue_node) || (last_glue != max_halfword)) { - you_cant(); - if (cur_chr == kern_node) { - help2( - "Sorry...I usually can't take things from the current page.", - "Try `I\\kern-\\lastkern' instead." - ); - } else if (cur_chr != glue_node) { - help2 - ("Sorry...I usually can't take things from the current page.", - "Perhaps you can make the output routine do it."); - } else { - help2 - ("Sorry...I usually can't take things from the current page.", - "Try `I\\vskip-\\lastskip' instead."); - } - error(); - } - } else { - /*tex Todo: clean this up! */ - if (!is_char_node(tail)) { - if (type(tail) == cur_chr) { - q = head; - do { - p = q; - if (!is_char_node(q)) { - if (type(q) == disc_node) { - if (p == tail) - return; - } - } - q = vlink(p); - } while (q != tail); - vlink(p) = null; - flush_node_list(tail); - tail = p; - } - } - } -} - -void unpackage(void) -{ - halfword p; /* the box */ - halfword r; /* to remove marginal kern nodes */ - int c; /* should we copy? */ - halfword s; /* for varmem assignment */ - if (cur_chr > copy_code) { - /*tex Handle saved items and |goto done| */ - try_couple_nodes(tail, disc_ptr[cur_chr]); - disc_ptr[cur_chr] = null; - goto DONE; - } - c = cur_chr; - scan_register_num(); - p = box(cur_val); - if (p == null) - return; - if ((abs(mode) == mmode) - || ((abs(mode) == vmode) && (type(p) != vlist_node)) - || ((abs(mode) == hmode) && (type(p) != hlist_node))) { - print_err("Incompatible list can't be unboxed"); - help3( - "Sorry, Pandora. (You sneaky devil.)", - "I refuse to unbox an \\hbox in vertical mode or vice versa.", - "And I can't open any boxes in math mode." - ); - error(); - return; - } - if (c == copy_code) { - s = copy_node_list(list_ptr(p)); - try_couple_nodes(tail,s); - } else { - try_couple_nodes(tail,list_ptr(p)); - box(cur_val) = null; - list_ptr(p) = null; - flush_node(p); - } - DONE: - while (vlink(tail) != null) { - r = vlink(tail); - if (!is_char_node(r) && (type(r) == margin_kern_node)) { - try_couple_nodes(tail,vlink(r)); - flush_node(r); - } - tail = vlink(tail); - } -} - -/*tex - -Italic corrections are converted to kern nodes when the |ital_corr| command -follows a character. In math mode the same effect is achieved by appending a kern -of zero here, since italic corrections are supplied later. - -*/ - -void append_italic_correction(void) -{ - halfword p; /* |char_node| at the tail of the current list */ - internal_font_number f; /* the font in the |char_node| */ - if (tail != head) { - if (is_char_node(tail)) - p = tail; - else - return; - f = font(p); - tail_append(new_kern(char_italic(f, character(p)))); - subtype(tail) = italic_kern; - } -} - -void append_local_box(int kind) -{ - incr(save_ptr); - set_saved_record(-1, saved_boxtype, 0, kind); - new_save_level(local_box_group); - scan_left_brace(); - push_nest(); - mode = -hmode; - space_factor_par = 1000; -} - -/*tex - -Discretionary nodes are easy in the common case `\.{\\-}', but in the general -case we must process three braces full of items. - -The space factor does not change when we append a discretionary node, but it -starts out as 1000 in the subsidiary lists. - -*/ - -void append_discretionary(void) -{ - int c; - tail_append(new_disc()); - subtype(tail) = (quarterword) cur_chr; - if (cur_chr == explicit_disc) { - /* |\-| */ - c = get_pre_hyphen_char(cur_lang_par); - if (c > 0) { - vlink(pre_break(tail)) = new_char(equiv(cur_font_loc), c); - alink(vlink(pre_break(tail))) = pre_break(tail); - tlink(pre_break(tail)) = vlink(pre_break(tail)); - } - c = get_post_hyphen_char(cur_lang_par); - if (c > 0) { - vlink(post_break(tail)) = new_char(equiv(cur_font_loc), c); - alink(vlink(post_break(tail))) = post_break(tail); - tlink(post_break(tail)) = vlink(post_break(tail)); - } - set_explicit_disc_penalty(tail); - } else if (cur_chr == automatic_disc) { - /*tex As done in hyphenator: */ - c = get_pre_exhyphen_char(cur_lang_par); - if (c <= 0) { - c = ex_hyphen_char_par; - } - if (c > 0) { - vlink(pre_break(tail)) = new_char(equiv(cur_font_loc), c); - alink(vlink(pre_break(tail))) = pre_break(tail); - tlink(pre_break(tail)) = vlink(pre_break(tail)); - } - c = get_post_exhyphen_char(cur_lang_par); - if (c > 0) { - vlink(post_break(tail)) = new_char(equiv(cur_font_loc), c); - alink(vlink(post_break(tail))) = post_break(tail); - tlink(post_break(tail)) = vlink(post_break(tail)); - } - c = ex_hyphen_char_par; - if (c > 0) { - vlink(no_break(tail)) = new_char(equiv(cur_font_loc), c); - alink(vlink(no_break(tail))) = no_break(tail); - tlink(no_break(tail)) = vlink(no_break(tail)); - } - set_automatic_disc_penalty(tail); - } else { - /*tex |\discretionary| */ - if (scan_keyword("penalty")) { - scan_int(); - disc_penalty(tail) = cur_val; - } - incr(save_ptr); - set_saved_record(-1, saved_disc, 0, 0); - new_save_level(disc_group); - scan_left_brace(); - push_nest(); - mode = -hmode; - space_factor_par = 1000; - /*tex Already preset: |disc_penalty(tail) = hyphen_penalty_par;| */ - } -} - -/*tex - -The test for |p != null| ensures that empty \.{\\localleftbox} and -\.{\\localrightbox} commands are not applied. - -*/ - -void build_local_box(void) -{ - halfword p; - int kind; - unsave(); - assert(saved_type(-1) == saved_boxtype); - kind = saved_value(-1); - decr(save_ptr); - p = vlink(head); - pop_nest(); - if (p != null) { - /*tex - Somehow |filtered_hpack| goes beyond the first node so we loose it. - */ - /*tex - There is no need for |new_hyphenation(p, null);| here as we're in - an |\hbox|. - */ - (void) new_ligkern(p, null); - p = lua_hpack_filter(p, 0, additional, local_box_group, -1, null); - /*tex - We really need something packed so we play safe! This feature is inherited - but could have been delegated to a callback anyway. - */ - p = hpack(p, 0, additional, -1); - } - if (kind == 0) - eq_define(local_left_box_base, box_ref_cmd, p); - else - eq_define(local_right_box_base, box_ref_cmd, p); - if (abs(mode) == hmode) { - /*tex Add local paragraph node */ - tail_append(make_local_par_node(local_box_par_code)); - } - eq_word_define(int_base + no_local_whatsits_code, no_local_whatsits_par + 1); -} - -/*tex - -The three discretionary lists are constructed somewhat as if they were hboxes. -A~subroutine called |build_discretionary| handles the transitions. (This is sort -of fun.) - -*/ - -void build_discretionary(void) -{ - halfword p, q; /* for link manipulation */ - int n; /* length of discretionary list */ - unsave(); - /*tex - Prune the current list, if necessary, until it contains only |char_node|, - |kern_node|, |hlist_node|, |vlist_node| and |rule_node| items; set |n| to - the length of the list, and set |q| to the lists tail. During this loop, - |p=vlink(q)| and there are |n| items preceding |p|. - */ - q = head; - p = vlink(q); - n = 0; - while (p != null) { - if (!is_char_node(p) && type(p) > rule_node && type(p) != kern_node) { - print_err("Improper discretionary list"); - help1( - "Discretionary lists must contain only boxes and kerns." - ); - error(); - begin_diagnostic(); - tprint_nl("The following discretionary sublist has been deleted:"); - show_box(p); - end_diagnostic(true); - flush_node_list(p); - vlink(q) = null; - break; - } - alink(p) = q; - q = p; - p = vlink(q); - incr(n); - } - - p = vlink(head); - pop_nest(); - assert(saved_type(-1) == saved_disc); - switch (saved_value(-1)) { - case 0: - if (n > 0) { - vlink(pre_break(tail)) = p; - alink(p) = pre_break(tail); - tlink(pre_break(tail)) = q; - } - break; - case 1: - if (n > 0) { - vlink(post_break(tail)) = p; - alink(p) = post_break(tail); - tlink(post_break(tail)) = q; - } - break; - case 2: - /*tex - Attach list |p| to the current list, and record its length; then - finish up and |return| - */ - if ((n > 0) && (abs(mode) == mmode)) { - print_err("Illegal math \\discretionary"); - help2( - "Sorry: The third part of a discretionary break must be", - "empty, in math formulas. I had to delete your third part." - ); - flush_node_list(p); - error(); - } else { - if (n > 0) { - vlink(no_break(tail)) = p; - alink(p) = no_break(tail); - tlink(no_break(tail)) = q; - } - } - decr(save_ptr); - /*tex There are no other cases. */ - return; - break; - } - set_saved_record(-1, saved_disc, 0, (saved_value(-1) + 1)); - new_save_level(disc_group); - scan_left_brace(); - push_nest(); - mode = -hmode; - space_factor_par = 1000; -} - -/*tex - -The positioning of accents is straightforward but tedious. Given an accent of -width |a|, designed for characters of height |x| and slant |s|; and given a -character of width |w|, height |h|, and slant |t|: We will shift the accent down -by |x-h|, and we will insert kern nodes that have the effect of centering the -accent over the character and shifting the accent to the right by -$\delta={1\over2}(w-a)+h\cdot t-x\cdot s$. If either character is absent from the -font, we will simply use the other, without shifting. - -*/ - -void make_accent(void) -{ - double s, t; /* amount of slant */ - halfword p, q, r; /* character, box, and kern nodes */ - internal_font_number f; /* relevant font */ - scaled a, h, x, w, delta; /* heights and widths, as explained above */ - scan_char_num(); - f = equiv(cur_font_loc); - p = new_glyph(f, cur_val); - if (p != null) { - x = x_height(f); - /*tex real division */ - s = float_cast(slant(f)) / float_constant(65536); - a = glyph_width(p); - do_assignments(); - /*tex - Create a character node |q| for the next character, but set |q:=null| - if problems arise - */ - q = null; - f = equiv(cur_font_loc); - if ((cur_cmd == letter_cmd) || - (cur_cmd == other_char_cmd) || (cur_cmd == char_given_cmd)) { - q = new_glyph(f, cur_chr); - } else if (cur_cmd == char_num_cmd) { - scan_char_num(); - q = new_glyph(f, cur_val); - } else { - back_input(); - } - - if (q != null) { - /*tex - Append the accent with appropriate kerns, then set |p:=q|. The - kern nodes appended here must be distinguished from other kerns, - lest they be wiped away by the hyphenation algorithm or by a - previous line break. The two kerns are computed with - (machine-dependent) |real| arithmetic, but their sum is - machine-independent; the net effect is machine-independent, - because the user cannot remove these nodes nor access them via - \.{\\lastkern}. - */ - t = float_cast(slant(f)) / float_constant(65536); /* real division */ - w = glyph_width(q); - h = glyph_height(q); - if (h != x) { - /*tex the accent must be shifted up or down */ - p = hpack(p, 0, additional, -1); - shift_amount(p) = x - h; - } - /*tex real multiplication */ - delta = round(float_cast(w - a) / float_constant(2) + h * t - x * s); - r = new_kern(delta); - subtype(r) = accent_kern; - couple_nodes(tail, r); - couple_nodes(r, p); - tail = new_kern(-a - delta); - subtype(tail) = accent_kern; - couple_nodes(p, tail); - p = q; - - } - couple_nodes(tail, p); - tail = p; - space_factor_par = 1000; - } -} - -/*tex - -When `\.{\\cr}' or `\.{\\span}' or a tab mark comes through the scanner into -|main_control|, it might be that the user has foolishly inserted one of them into -something that has nothing to do with alignment. But it is far more likely that a -left brace or right brace has been omitted, since |get_next| takes actions -appropriate to alignment only when `\.{\\cr}' or `\.{\\span}' or tab marks occur -with |align_state=0|. The following program attempts to make an appropriate -recovery. - -*/ - -void align_error(void) -{ - if (abs(align_state) > 2) { - /*tex - Express consternation over the fact that no alignment is in progress. - */ - print_err("Misplaced "); - print_cmd_chr((quarterword) cur_cmd, cur_chr); - if (cur_tok == tab_token + '&') { - help6( - "I can't figure out why you would want to use a tab mark", - "here. If you just want an ampersand, the remedy is", - "simple: Just type `I\\&' now. But if some right brace", - "up above has ended a previous alignment prematurely,", - "you're probably due for more error messages, and you", - "might try typing `S' now just to see what is salvageable." - ); - } else { - help5( - "I can't figure out why you would want to use a tab mark", - "or \\cr or \\span just now. If something like a right brace", - "up above has ended a previous alignment prematurely,", - "you're probably due for more error messages, and you", - "might try typing `S' now just to see what is salvageable." - ); - } - error(); - - } else { - back_input(); - if (align_state < 0) { - print_err("Missing { inserted"); - incr(align_state); - cur_tok = left_brace_token + '{'; - } else { - print_err("Missing } inserted"); - decr(align_state); - cur_tok = right_brace_token + '}'; - } - help3( - "I've put in what seems to be necessary to fix", - "the current column of the current alignment.", - "Try to go on, since this might almost work." - ); - ins_error(); - } -} - -/*tex - -The help messages here contain a little white lie, since \.{\\noalign} and -\.{\\omit} are allowed also after `\.{\\noalign\{...\}}'. - -*/ - -void no_align_error(void) -{ - print_err("Misplaced \\noalign"); - help2( - "I expect to see \\noalign only after the \\cr of", - "an alignment. Proceed, and I'll ignore this case." - ); - error(); -} - -void omit_error(void) -{ - print_err("Misplaced \\omit"); - help2( - "I expect to see \\omit only after tab marks or the \\cr of", - "an alignment. Proceed, and I'll ignore this case." - ); - error(); -} - -/*tex - -We've now covered most of the abuses of \.{\\halign} and \.{\\valign}. Let's take -a look at what happens when they are used correctly. - -An |align_group| code is supposed to remain on the |save_stack| during an entire -alignment, until |fin_align| removes it. - -A devious user might force an |endv| command to occur just about anywhere; we -must defeat such hacks. - -*/ - -void do_endv(void) -{ - base_ptr = input_ptr; - input_stack[base_ptr] = cur_input; - while ((input_stack[base_ptr].index_field != v_template) && - (input_stack[base_ptr].loc_field == null) && - (input_stack[base_ptr].state_field == token_list)) - decr(base_ptr); - if ((input_stack[base_ptr].index_field != v_template) || - (input_stack[base_ptr].loc_field != null) || - (input_stack[base_ptr].state_field != token_list)) - fatal_error("(interwoven alignment preambles are not allowed)"); - /*tex interwoven alignment preambles... */ - if (cur_group == align_group) { - end_graf(align_group); - if (fin_col()) - fin_row(); - } else { - off_save(); - } -} - -/*tex - -Finally, \.{\\endcsname} is not supposed to get through to |main_control|. - -*/ - -void cs_error(void) -{ - print_err("Extra \\endcsname"); - help1( - "I'm ignoring this, since I wasn't doing a \\csname." - ); - error(); -} - -/*tex - -Assignments to values in |eqtb| can be global or local. Furthermore, a control -sequence can be defined to be `\.{\\long}', `\.{\\protected}', or `\.{\\outer}', -and it might or might not be expanded. The prefixes `\.{\\global}', `\.{\\long}', -`\.{\\protected}', and `\.{\\outer}' can occur in any order. Therefore we assign -binary numeric codes, making it possible to accumulate the union of all specified -prefixes by adding the corresponding codes. (PASCAL's |set| operations could also -have been used.) - -Every prefix, and every command code that might or might not be prefixed, calls -the action procedure |prefixed_command|. This routine accumulates a sequence of -prefixes until coming to a non-prefix, then it carries out the command. - -*/ - -/*tex - -If the user says, e.g., `\.{\\global\\global}', the redundancy is silently -accepted. The different types of code values have different legal ranges; the -following program is careful to check each case properly. - -*/ - -#define check_def_code(A) do { \ - if (((cur_val<0)&&(p<(A)))||(cur_val>n)) { \ - print_err("Invalid code ("); \ - print_int(cur_val); \ - if (p<(A)) \ - tprint("), should be in the range 0.."); \ - else \ - tprint("), should be at most "); \ - print_int(n); \ - help1( \ - "I'm going to use 0 instead of that illegal code value." \ - ); \ - error(); \ - cur_val=0; \ - } \ -} while (0) - -/* -halfword swap_hang_indent(halfword indentation, halfword shape_mode) { - if (shape_mode == 1 || shape_mode == 3 || shape_mode == -1 || shape_mode == -3) { - return negate(indentation); - } else { - return indentation; - } -} - -halfword swap_parshape_indent(halfword indentation, halfword width, halfword shape_mode) { - if (shape_mode == 2 || shape_mode == 3 || shape_mode == -2 || shape_mode == -3) { - return hsize_par - width - indentation; - } else { - return indentation; - } -} - -*/ - -void prefixed_command(void) -{ - int a; /* accumulated prefix codes so far */ - internal_font_number f; /* identifies a font */ - halfword j; /* index into a \.{\\parshape} specification */ - halfword p, q; /* for temporary short-term use */ - int n; /* ditto */ - boolean e, check_glue; /* should a definition be expanded? or was \.{\\let} not done? */ - mathcodeval mval; /* for handling of \.{\\mathchardef}s */ - a = 0; - while (cur_cmd == prefix_cmd) { - if (!odd(a / cur_chr)) - a = a + cur_chr; - /*tex - Get the next non-blank non-relax... - */ - do { - get_x_token(); - } while ((cur_cmd == spacer_cmd) || (cur_cmd == relax_cmd)); - - if (cur_cmd <= max_non_prefixed_command) { - /*tex - Discard erroneous prefixes and |return| - */ - print_err("You can't use a prefix with `"); - print_cmd_chr((quarterword) cur_cmd, cur_chr); - print_char('\''); - help2( - "I'll pretend you didn't say \\long or \\outer or \\global or", - "\\protected." - ); - back_error(); - return; - } - if (tracing_commands_par > 2) - show_cur_cmd_chr(); - } - /*tex - Discard the prefixes \.{\\long} and \.{\\outer} if they are irrelevant - */ - if (a >= 8) { - j = protected_token; - a = a - 8; - } else { - j = 0; - } - if ((cur_cmd != def_cmd) && (cur_cmd != def_lua_call_cmd) && ((a % 4 != 0) || (j != 0))) { - print_err("You can't use `\\long' or `\\outer' or `\\protected' with `"); - print_cmd_chr((quarterword) cur_cmd, cur_chr); - print_char('\''); - help1( - "I'll pretend you didn't say \\long or \\outer or \\protected here." - ); - error(); - } - /*tex - Adjust for the setting of \.{\\globaldefs} - */ - if (global_defs_par != 0) { - if (global_defs_par < 0) { - if (is_global(a)) - a = a - 4; - } else { - if (!is_global(a)) - a = a + 4; - } - } - switch (cur_cmd) { - case set_font_cmd: - /*tex - Here's an example of the way many of the following routines operate. - (Unfortunately, they aren't all as simple as this.) - */ - define(cur_font_loc, data_cmd, cur_chr); - break; - case def_cmd: - /*tex - When a |def| command has been scanned, |cur_chr| is odd if the - definition is supposed to be global, and |cur_chr>=2| if the - definition is supposed to be expanded. - */ - if (odd(cur_chr) && !is_global(a) && (global_defs_par >= 0)) - a = a + 4; - e = (cur_chr >= 2); - get_r_token(); - p = cur_cs; - q = scan_toks(true, e); - if (j != 0) { - q = get_avail(); - set_token_info(q, j); - set_token_link(q, token_link(def_ref)); - set_token_link(def_ref, q); - } - define(p, call_cmd + (a % 4), def_ref); - break; - case let_cmd: - n = cur_chr; - switch (n) { - case 0: - /*tex |glet| */ - if (!is_global(a) && (global_defs_par >= 0)) { - a = a + 4; - } - case 1: - /*tex |let| */ - get_r_token(); - p = cur_cs; - do { - get_token(); - } while (cur_cmd == spacer_cmd); - if (cur_tok == other_token + '=') { - get_token(); - if (cur_cmd == spacer_cmd) - get_token(); - } - break; - case 2: - /*tex |futurelet| */ - get_r_token(); - p = cur_cs; - get_token(); - q = cur_tok; - get_token(); - back_input(); - cur_tok = q; - /*tex - We look ahead and then back up. Note that |back_input| doesn't - affect |cur_cmd|, |cur_chr| - */ - back_input(); - break; - case 3: - /*tex |letcharcode| */ - scan_int(); - if (cur_val > 0) { - /*tex HH: I need to do a more extensive test later. */ - p = active_to_cs(cur_val, true); - do { - get_token(); - } while (cur_cmd == spacer_cmd); - if (cur_tok == other_token + '=') { - get_token(); - if (cur_cmd == spacer_cmd) - get_token(); - } - } else { - p = null; - tex_error("invalid number for \\letcharcode",NULL); - } - break; - default: - /*tex We please the compiler. */ - p = null; - confusion("let"); - break; - } - if (cur_cmd >= call_cmd) - add_token_ref(cur_chr); - define(p, cur_cmd, cur_chr); - break; - case shorthand_def_cmd: - /*tex - We temporarily define |p| to be |relax|, so that an occurrence of - |p| while scanning the definition will simply stop the scanning - instead of producing an ``undefined control sequence'' error or - expanding the previous meaning. This allows, for instance, - `\.{\\chardef\\foo=123\\foo}'. - */ - n = cur_chr; - get_r_token(); - p = cur_cs; - define(p, relax_cmd, too_big_char); - scan_optional_equals(); - switch (n) { - case char_def_code: - scan_char_num(); - define(p, char_given_cmd, cur_val); - break; - case math_char_def_code: - mval = scan_mathchar(tex_mathcode); - /* if (math_umathcode_meaning_par == 1) { */ - /* cur_val = (mval.class_value + (8 * mval.family_value)) * (65536 * 32) + mval.character_value; */ - /* define(p, xmath_given_cmd, cur_val); */ - /* } else { */ - cur_val = (mval.class_value * 16 + mval.family_value) * 256 + mval.character_value; - define(p, math_given_cmd, cur_val); - /* } */ - break; - case xmath_char_def_code: - mval = scan_mathchar(umath_mathcode); - cur_val = (mval.class_value + (8 * mval.family_value)) * (65536 * 32) + mval.character_value; - define(p, xmath_given_cmd, cur_val); - break; - case umath_char_def_code: - mval = scan_mathchar(umathnum_mathcode); - cur_val = (mval.class_value + (8 * mval.family_value)) * (65536 * 32) + mval.character_value; - define(p, xmath_given_cmd, cur_val); - break; - default: - scan_register_num(); - switch (n) { - case count_def_code: - define(p, assign_int_cmd, count_base + cur_val); - break; - case attribute_def_code: - define(p, assign_attr_cmd, attribute_base + cur_val); - break; - case dimen_def_code: - define(p, assign_dimen_cmd, scaled_base + cur_val); - break; - case skip_def_code: - define(p, assign_glue_cmd, skip_base + cur_val); - break; - case mu_skip_def_code: - define(p, assign_mu_glue_cmd, mu_skip_base + cur_val); - break; - case toks_def_code: - define(p, assign_toks_cmd, toks_base + cur_val); - break; - default: - confusion("shorthand_def"); - break; - } - break; - } - break; - case read_to_cs_cmd: - j = cur_chr; - scan_int(); - n = cur_val; - if (!scan_keyword("to")) { - print_err("Missing `to' inserted"); - help2( - "You should have said `\\read<number> to \\cs'.", - "I'm going to look for the \\cs now." - ); - error(); - } - get_r_token(); - p = cur_cs; - read_toks(n, p, j); - define(p, call_cmd, cur_val); - break; - case toks_register_cmd: - case assign_toks_cmd: - /*tex - The token-list parameters, \.{\\output} and \.{\\everypar}, etc., - receive their values in the following way. (For safety's sake, we - place an enclosing pair of braces around an \.{\\output} list.) - */ - q = cur_cs; - if (cur_cmd == toks_register_cmd) { - scan_register_num(); - p = toks_base + cur_val; - } else { - /*tex |p=every_par_loc| or |output_routine_loc| or \dots */ - p = cur_chr; - } - scan_optional_equals(); - /*tex Get the next non-blank non-relax non-call token */ - do { - get_x_token(); - } while ((cur_cmd == spacer_cmd) || (cur_cmd == relax_cmd)); - - if (cur_cmd != left_brace_cmd) { - /*tex - If the right-hand side is a token parameter or token - register, finish the assignment and |goto done| - */ - if (cur_cmd == toks_register_cmd) { - scan_register_num(); - cur_cmd = assign_toks_cmd; - cur_chr = toks_base + cur_val; - } - if (cur_cmd == assign_toks_cmd) { - q = equiv(cur_chr); - if (q == null) { - define(p, undefined_cs_cmd, null); - } else { - add_token_ref(q); - define(p, call_cmd, q); - } - goto DONE; - } - } - back_input(); - cur_cs = q; - q = scan_toks(false, false); - if (token_link(def_ref) == null) { /* empty list: revert to the default */ - define(p, undefined_cs_cmd, null); - free_avail(def_ref); - } else { - if (p == output_routine_loc) { /* enclose in curlies */ - p = get_avail(); - set_token_link(q, p); - p = output_routine_loc; - q = token_link(q); - set_token_info(q, right_brace_token + '}'); - q = get_avail(); - set_token_info(q, left_brace_token + '{'); - set_token_link(q, token_link(def_ref)); - set_token_link(def_ref, q); - } - define(p, call_cmd, def_ref); - } - break; - case assign_int_cmd: - /*tex Similar routines are used to assign values to the numeric parameters. */ - p = cur_chr; - scan_optional_equals(); - scan_int(); - assign_internal_value(a, p, cur_val); - break; - case assign_attr_cmd: - p = cur_chr; - scan_optional_equals(); - scan_int(); - if ((p - attribute_base) > max_used_attr) - max_used_attr = (p - attribute_base); - attr_list_cache = cache_disabled; - word_define(p, cur_val); - break; - case assign_direction_cmd: - case assign_dir_cmd: - /*tex Assign direction codes. */ - if (cur_cmd == assign_direction_cmd) { - p = cur_chr; - scan_optional_equals(); - scan_int(); - check_dir_value(cur_val); - cur_chr = p; - } else { - scan_direction(); - } - switch (cur_chr) { - case int_base + page_direction_code: - eq_word_define(int_base + page_direction_code, cur_val); - break; - case int_base + body_direction_code: - eq_word_define(int_base + body_direction_code, cur_val); - break; - case int_base + par_direction_code: - eq_word_define(int_base + par_direction_code, cur_val); - break; - case int_base + math_direction_code: - eq_word_define(int_base + math_direction_code, cur_val); - break; - case int_base + text_direction_code: - case int_base + line_direction_code: - /* - pre version 0.97 this was a commented section because various tests hint that this - is unnecessary and sometimes even produces weird results, like: - - (\hbox{\textdir TRT ABC\textdir TLT DEF})) - - becomes - - (DEFCBA) - - in the output when we use - - tail_append(new_dir(text_direction_par) - - but when we append the reverse of the current it goes better - - */ - check_glue = (cur_chr == (int_base + line_direction_code)); - if (check_glue) { - cur_chr = int_base + text_direction_code ; - } - if (abs(mode) == hmode) { - if (no_local_dirs_par > 0) { - /*tex |tail| is non zero but we test anyway. */ - if (check_glue && (tail != null && type(tail) == glue_node)) { - halfword prev = alink(tail); - halfword dirn = new_dir(text_direction_par); - subtype(dirn) = cancel_dir; - couple_nodes(prev,dirn); - couple_nodes(dirn,tail); - } else { - tail_append(new_dir(text_direction_par)); - subtype(tail) = cancel_dir; - } - } else { - /*tex What is the use of nolocaldirs? Maybe we should get rid of it. */ - } - update_text_dir_ptr(cur_val); - tail_append(new_dir(cur_val)); - dir_level(tail) = cur_level; - } else { - update_text_dir_ptr(cur_val); - } - eq_word_define(int_base + text_direction_code, cur_val); - eq_word_define(int_base + no_local_dirs_code, no_local_dirs_par + 1); - break; - } - break; - case assign_dimen_cmd: - p = cur_chr; - scan_optional_equals(); - scan_normal_dimen(); - assign_internal_value(a, p, cur_val); - break; - case assign_glue_cmd: - case assign_mu_glue_cmd: - p = cur_chr; - n = cur_cmd; - scan_optional_equals(); - if (n == assign_mu_glue_cmd) - scan_glue(mu_val_level); - else - scan_glue(glue_val_level); - define(p, glue_ref_cmd, cur_val); - break; - case def_char_code_cmd: - case def_del_code_cmd: - /*tex Let |n| be the largest legal code value, based on |cur_chr| */ - if (cur_chr == cat_code_base) - n = max_char_code; - else if (cur_chr == sf_code_base) - n = 077777; - else - n = biggest_char; - p = cur_chr; - if (cur_chr == math_code_base) { - if (is_global(a)) - cur_val1 = level_one; - else - cur_val1 = cur_level; - scan_extdef_math_code(cur_val1, tex_mathcode); - } else if (cur_chr == lc_code_base) { - scan_char_num(); - p = cur_val; - scan_optional_equals(); - scan_int(); - check_def_code(lc_code_base); - define_lc_code(p, cur_val); - } else if (cur_chr == uc_code_base) { - scan_char_num(); - p = cur_val; - scan_optional_equals(); - scan_int(); - check_def_code(uc_code_base); - define_uc_code(p, cur_val); - } else if (cur_chr == sf_code_base) { - scan_char_num(); - p = cur_val; - scan_optional_equals(); - scan_int(); - check_def_code(sf_code_base); - define_sf_code(p, cur_val); - } else if (cur_chr == cat_code_base) { - scan_char_num(); - p = cur_val; - scan_optional_equals(); - scan_int(); - check_def_code(cat_code_base); - define_cat_code(p, cur_val); - } else if (cur_chr == del_code_base) { - if (is_global(a)) - cur_val1 = level_one; - else - cur_val1 = cur_level; - scan_extdef_del_code(cur_val1, tex_mathcode); - } - break; - case extdef_math_code_cmd: - case extdef_del_code_cmd: - if (is_global(a)) - cur_val1 = level_one; - else - cur_val1 = cur_level; - if (cur_chr == math_code_base) - scan_extdef_math_code(cur_val1, umath_mathcode); - else if (cur_chr == math_code_base + 1) - scan_extdef_math_code(cur_val1, umathnum_mathcode); - else if (cur_chr == del_code_base) - scan_extdef_del_code(cur_val1, umath_mathcode); - else if (cur_chr == del_code_base + 1) - scan_extdef_del_code(cur_val1, umathnum_mathcode); - break; - case def_family_cmd: - p = cur_chr; - scan_math_family_int(); - cur_val1 = cur_val; - scan_optional_equals(); - scan_font_ident(); - define_fam_fnt(cur_val1, p, cur_val); - break; - case set_math_param_cmd: - p = cur_chr; - get_token(); - if (cur_cmd != math_style_cmd) { - print_err("Missing math style, treated as \\displaystyle"); - help1( - "A style should have been here; I inserted `\\displaystyle'." - ); - cur_val1 = display_style; - back_error(); - } else { - cur_val1 = cur_chr; - } - scan_optional_equals(); - if (p < math_param_first_mu_glue) { - if (p == math_param_radical_degree_raise) - scan_int(); - else - scan_dimen(false, false, false); - } else { - scan_glue(mu_val_level); - if (cur_val == thin_mu_skip_par) - cur_val = thin_mu_skip_code; - else if (cur_val == med_mu_skip_par) - cur_val = med_mu_skip_code; - else if (cur_val == thick_mu_skip_par) - cur_val = thick_mu_skip_code; - } - define_math_param(p, cur_val1, cur_val); - break; - case register_cmd: - case advance_cmd: - case multiply_cmd: - case divide_cmd: - do_register_command(a); - break; - case set_box_cmd: - /*tex - The processing of boxes is somewhat different, because we may - need to scan and create an entire box before we actually change - the value of the old one. - */ - scan_register_num(); - if (is_global(a)) - n = global_box_flag + cur_val; - else - n = box_flag + cur_val; - scan_optional_equals(); - if (set_box_allowed) { - scan_box(n); - } else { - print_err("Improper \\setbox"); - help3( - "Sorry, \\setbox is not allowed after \\halign in a display,", - "between \\accent and an accented character, or in immediate", - "assignments." - ); - error(); - } - break; - case set_aux_cmd: - /*tex - The |space_factor| or |prev_depth| settings are changed when a - |set_aux| command is sensed. Similarly, |prev_graf| is changed in - the presence of |set_prev_graf|, and |dead_cycles| or - |insert_penalties| in the presence of |set_page_int|. These - definitions are always global. - */ - alter_aux(); - break; - case set_prev_graf_cmd: - alter_prev_graf(); - break; - case set_page_dimen_cmd: - alter_page_so_far(); - break; - case set_page_int_cmd: - alter_integer(); - break; - case set_box_dimen_cmd: - /*tex - When some dimension of a box register is changed, the change - isn't exactly global; but \TeX\ does not look at the \.{\\global} - switch. - */ - alter_box_dimen(); - break; - case set_tex_shape_cmd: - q = cur_chr; - scan_optional_equals(); - scan_int(); - n = cur_val; - if (n <= 0) { - p = null; - } else { - p = new_node(shape_node, 2 * (n + 1) + 1); - vinfo(p + 1) = n; - for (j = 1; j <= n; j++) { - scan_normal_dimen(); - varmem[p + 2 * j].cint = cur_val; /* indentation */ - scan_normal_dimen(); - varmem[p + 2 * j + 1].cint = cur_val; /* width */ - } - } - define(q, shape_ref_cmd, p); - break; - case set_etex_shape_cmd: - q = cur_chr; - scan_optional_equals(); - scan_int(); - n = cur_val; - if (n <= 0) { - p = null; - } else { - n = (cur_val / 2) + 1; - p = new_node(shape_node, 2 * n + 1 + 1); - vinfo(p + 1) = n; - n = cur_val; - varmem[p + 2].cint = n; /* number of penalties */ - for (j = p + 3; j <= p + n + 2; j++) { - scan_int(); - varmem[j].cint = cur_val; /* penalty values */ - } - if (!odd(n)) - varmem[p + n + 3].cint = 0; /* unused */ - } - define(q, shape_ref_cmd, p); - break; - case hyph_data_cmd: - /*tex - All of \TeX's parameters are kept in |eqtb| except the font - information, the interaction mode, and the hyphenation tables; - these are strictly global. - */ - switch (cur_chr) { - case 0: - new_hyph_exceptions(); - break; - case 1: - new_patterns(); - break; - case 2: - new_pre_hyphen_char(); - break; - case 3: - new_post_hyphen_char(); - break; - case 4: - new_pre_exhyphen_char(); - break; - case 5: - new_post_exhyphen_char(); - break; - case 6: - new_hyphenation_min(); - break; - case 7: - new_hj_code(); - break; - } - break; - case assign_font_dimen_cmd: - set_font_dimen(); - break; - case assign_font_int_cmd: - n = cur_chr; - scan_font_ident(); - f = cur_val; - if (n == no_lig_code) { - set_no_ligatures(f); - } else if (n < lp_code_base) { - scan_optional_equals(); - scan_int(); - if (n == 0) - set_hyphen_char(f, cur_val); - else - set_skew_char(f, cur_val); - } else { - scan_char_num(); - p = cur_val; - scan_optional_equals(); - scan_int(); - switch (n) { - case lp_code_base: - set_lp_code(f, p, cur_val); - break; - case rp_code_base: - set_rp_code(f, p, cur_val); - break; - case ef_code_base: - set_ef_code(f, p, cur_val); - break; - case tag_code: - set_tag_code(f, p, cur_val); - break; - } - } - break; - case def_font_cmd: - /*tex Here is where the information for a new font gets loaded. */ - tex_def_font((small_number) a); - break; - case def_lua_call_cmd: - get_r_token(); - p = cur_cs; - scan_optional_equals(); - scan_int(); - if (j != 0) { - define(p, lua_call_cmd, cur_val); - } else { - define(p, lua_expandable_call_cmd, cur_val); - } - break; - case letterspace_font_cmd: - new_letterspaced_font((small_number) a); - break; - case copy_font_cmd: - make_font_copy((small_number) a); - break; - case set_font_id_cmd: - scan_int(); - if (is_valid_font(cur_val)) - zset_cur_font(cur_val); - break ; - case set_interaction_cmd: - new_interaction(); - break; - default: - confusion("prefix"); - break; - } - /*tex End of assignments cases. */ - DONE: - /*tex Insert a token saved by \.{\\afterassignment}, if any. */ - if (after_token != 0) { - cur_tok = after_token; - back_input(); - after_token = 0; - } -} - -void fixup_directions(void) -{ - int temp_no_whatsits = no_local_whatsits_par; - int temp_no_dirs = no_local_dirs_par; - int temporary_dir = text_direction_par; - if (dir_level(text_dir_ptr) == cur_level) { - /* Remove from |text_dir_ptr|. */ - halfword text_dir_tmp = vlink(text_dir_ptr); - flush_node(text_dir_ptr); - text_dir_ptr = text_dir_tmp; - } - unsave(); - if (abs(mode) == hmode) { - if (temp_no_dirs != 0) { - /* Add local dir node. */ - tail_append(new_dir(text_direction_par)); - dir_dir(tail) = temporary_dir; - subtype(tail) = cancel_dir; - } - if (temp_no_whatsits != 0) { - /*tex Add local paragraph node. */ - tail_append(make_local_par_node(hmode_par_par_code)); - } - } -} - -/*tex - - This is experimental and needs more checking! - -*/ - -void fixup_directions_only(void) -{ - int temp_no_dirs = no_local_dirs_par; - int temporary_dir = text_direction_par; - if (dir_level(text_dir_ptr) == cur_level) { - /* Remove from |text_dir_ptr|. */ - halfword text_dir_tmp = vlink(text_dir_ptr); - flush_node(text_dir_ptr); - text_dir_ptr = text_dir_tmp; - } - if (temp_no_dirs != 0) { - /* Add local dir node. */ - tail_append(new_dir(text_direction_par)); - dir_dir(tail) = temporary_dir; - subtype(tail) = cancel_dir; - } -} - -/*tex - -When a control sequence is to be defined, by \.{\\def} or \.{\\let} or something -similar, the |get_r_token| routine will substitute a special control sequence for -a token that is not redefinable. - -*/ - -void get_r_token(void) -{ - RESTART: - do { - get_token(); - } while (cur_tok == space_token); - if ((cur_cs == 0) || (cur_cs > eqtb_top) || - ((cur_cs > frozen_control_sequence) && (cur_cs <= eqtb_size))) { - print_err("Missing control sequence inserted"); - help5( - "Please don't say `\\def cs{...}', say `\\def\\cs{...}'.", - "I've inserted an inaccessible control sequence so that your", - "definition will be completed without mixing me up too badly.", - "You can recover graciously from this error, if you're", - "careful; see exercise 27.2 in The TeXbook." - ); - if (cur_cs == 0) - back_input(); - cur_tok = cs_token_flag + frozen_protection; - ins_error(); - goto RESTART; - } -} - -void assign_internal_value(int a, halfword p, int val) -{ - halfword n; - if ((p >= int_base) && (p < attribute_base)) { - switch ((p - int_base)) { - case cat_code_table_code: - if (valid_catcode_table(val)) { - if (val != cat_code_table_par) - word_define(p, val); - } else { - print_err("Invalid \\catcode table"); - help2( - "You can only switch to a \\catcode table that is initialized", - "using \\savecatcodetable or \\initcatcodetable, or to table 0" - ); - error(); - } - break; - case output_box_code: - if ((val > 65535) | (val < 0)) { - print_err("Invalid \\outputbox"); - help1( - "The value for \\outputbox has to be between 0 and 65535." - ); - error(); - } else { - word_define(p, val); - } - break; - case new_line_char_code: - if (val > 127) { - print_err("Invalid \\newlinechar"); - help2( - "The value for \\newlinechar has to be no higher than 127.", - "Your invalid assignment will be ignored." - ); - error(); - } else { - word_define(p, val); - } - break; - case end_line_char_code: - if (val > 127) { - print_err("Invalid \\endlinechar"); - help2( - "The value for \\endlinechar has to be no higher than 127.", - "Your invalid assignment will be ignored." - ); - error(); - } else { - word_define(p, val); - } - break; - case language_code: - if (val < 0) { - word_define(int_base + cur_lang_code, -1); - word_define(p, -1); - } else if (val > 16383) { - print_err("Invalid \\language"); - help2( - "The absolute value for \\language has to be no higher than 16383.", - "Your invalid assignment will be ignored." - ); - error(); - } else { - word_define(int_base + cur_lang_code, val); - word_define(p, val); - } - break; - default: - word_define(p, val); - break; - } - /*tex - If we are defining subparagraph penalty levels while we are in hmode, - then we put out a whatsit immediately, otherwise we leave it alone. - This mechanism might not be sufficiently powerful, and some other - algorithm, searching down the stack, might be necessary. Good first - step. - */ - if ((abs(mode) == hmode) && - ((p == (int_base + local_inter_line_penalty_code)) || - (p == (int_base + local_broken_penalty_code)))) { - /*tex Add local paragraph node */ - tail_append(make_local_par_node(penalty_par_code)); - eq_word_define(int_base + no_local_whatsits_code, no_local_whatsits_par + 1); - } - } else if ((p >= dimen_base) && (p <= eqtb_size)) { - if (p == (dimen_base + page_left_offset_code)) { - n = val - one_true_inch; - word_define(dimen_base + h_offset_code, n); - } else if (p == (dimen_base + h_offset_code)) { - n = val + one_true_inch; - word_define(dimen_base + page_left_offset_code, n); - } else if (p == (dimen_base + page_top_offset_code)) { - n = val - one_true_inch; - word_define(dimen_base + v_offset_code, n); - } else if (p == (dimen_base + v_offset_code)) { - n = val + one_true_inch; - word_define(dimen_base + page_top_offset_code, n); - } - word_define(p, val); - } else if ((p >= local_base) && (p < toks_base)) { - /*tex internal locals */ - define(p, call_cmd, val); - } else { - confusion("assign internal value"); - } -} - -/*tex - -We use the fact that |register| $<$ |advance| $<$ |multiply| $<$ |divide|/ We -compute the register location |l| and its type |p| but |return| if invalid. Here -we use the fact that the consecutive codes |int_val..mu_val| and -|assign_int..assign_mu_glue| correspond to each other nicely. - -*/ - -void do_register_command(int a) -{ - int p; - halfword q = cur_cmd; - halfword l = 0; - if (q != register_cmd) { - get_x_token(); - if ((cur_cmd >= assign_int_cmd) && (cur_cmd <= assign_mu_glue_cmd)) { - l = cur_chr; - p = cur_cmd - assign_int_cmd; - goto FOUND; - } - if (cur_cmd != register_cmd) { - print_err("You can't use `"); - print_cmd_chr((quarterword) cur_cmd, cur_chr); - tprint("' after "); - print_cmd_chr((quarterword) q, 0); - help1( - "I'm forgetting what you said and not changing anything." - ); - error(); - return; - } - } - p = cur_chr; - scan_register_num(); - if (p == int_val_level) - l = cur_val + count_base; - else if (p == attr_val_level) - l = cur_val + attribute_base; - else if (p == dimen_val_level) - l = cur_val + scaled_base; - else if (p == glue_val_level) - l = cur_val + skip_base; - else if (p == mu_val_level) - l = cur_val + mu_skip_base; - FOUND: - if (q == register_cmd) { - scan_optional_equals(); - } else if (scan_keyword("by")) { - /*tex optional `\.{by}' */ - } - arith_error = false; - if (q < multiply_cmd) { - /*tex Compute result of |register| or |advance|, put it in |cur_val|. */ - if (p < glue_val_level) { - if ((p == int_val_level) || (p == attr_val_level)) - scan_int(); - else - scan_normal_dimen(); - if (q == advance_cmd) - cur_val = cur_val + eqtb[l].cint; - } else { - scan_glue(p); - if (q == advance_cmd) { - /* Compute the sum of two glue specs */ - halfword r = equiv(l); - q = new_spec(cur_val); - flush_node(cur_val); - width(q) = width(q) + width(r); - if (stretch(q) == 0) { - stretch_order(q) = normal; - } - if (stretch_order(q) == stretch_order(r)) { - stretch(q) = stretch(q) + stretch(r); - } else if ((stretch_order(q) < stretch_order(r)) && (stretch(r) != 0)) { - stretch(q) = stretch(r); - stretch_order(q) = stretch_order(r); - } - if (shrink(q) == 0) { - shrink_order(q) = normal; - } - if (shrink_order(q) == shrink_order(r)) { - shrink(q) = shrink(q) + shrink(r); - } else if ((shrink_order(q) < shrink_order(r)) && (shrink(r) != 0)) { - shrink(q) = shrink(r); - shrink_order(q) = shrink_order(r); - } - cur_val = q; - } - } - } else { - /*tex Compute result of |multiply| or |divide|, put it in |cur_val| */ - scan_int(); - if (p < glue_val_level) { - if (q == multiply_cmd) { - if ((p == int_val_level) || (p == attr_val_level)) { - cur_val = mult_integers(eqtb[l].cint, cur_val); - } else { - cur_val = nx_plus_y(eqtb[l].cint, cur_val, 0); - } - } else { - cur_val = x_over_n(eqtb[l].cint, cur_val); - } - } else { - halfword s = equiv(l); - halfword r = new_spec(s); - if (q == multiply_cmd) { - width(r) = nx_plus_y(width(s), cur_val, 0); - stretch(r) = nx_plus_y(stretch(s), cur_val, 0); - shrink(r) = nx_plus_y(shrink(s), cur_val, 0); - } else { - width(r) = x_over_n(width(s), cur_val); - stretch(r) = x_over_n(stretch(s), cur_val); - shrink(r) = x_over_n(shrink(s), cur_val); - } - cur_val = r; - } - } - if (arith_error) { - print_err("Arithmetic overflow"); - help2( - "I can't carry out that multiplication or division,", - "since the result is out of range." - ); - if (p >= glue_val_level) - flush_node(cur_val); - error(); - return; - } - if (p < glue_val_level) { - if (p == attr_val_level) { - if ((l - attribute_base) > max_used_attr) - max_used_attr = (l - attribute_base); - attr_list_cache = cache_disabled; - } - if ((p == int_val_level) || (p == dimen_val_level)) - assign_internal_value(a, l, cur_val); - else - word_define(l, cur_val); - } else { - define(l, glue_ref_cmd, cur_val); - } -} - -void alter_aux(void) -{ - halfword c; /* |hmode| or |vmode| */ - if (cur_chr != abs(mode)) { - report_illegal_case(); - } else { - c = cur_chr; - scan_optional_equals(); - if (c == vmode) { - scan_normal_dimen(); - prev_depth_par = cur_val; - } else { - scan_int(); - if ((cur_val <= 0) || (cur_val > 32767)) { - print_err("Bad space factor"); - help1( - "I allow only values in the range 1..32767 here." - ); - int_error(cur_val); - } else { - space_factor_par = cur_val; - } - } - } -} - -void alter_prev_graf(void) -{ - int p = nest_ptr; /* index into |nest| */ - while (abs(nest[p].mode_field) != vmode) - decr(p); - scan_optional_equals(); - scan_int(); - if (cur_val < 0) { - print_err("Bad \\prevgraf"); - help1( - "I allow only nonnegative values here." - ); - int_error(cur_val); - } else { - nest[p].pg_field = cur_val; - } -} - -void alter_page_so_far(void) -{ - int c = cur_chr; /* index into |page_so_far| */ - scan_optional_equals(); - scan_normal_dimen(); - page_so_far[c] = cur_val; -} - -/*tex - The value of |c| is 0 for \.{\\deadcycles}, 1 for \.{\\insertpenalties}, etc. -*/ - -void alter_integer(void) -{ - int c = cur_chr; - scan_optional_equals(); - scan_int(); - if (c == 0) { - dead_cycles = cur_val; - } else if (c == 2) { - if ((cur_val < batch_mode) || (cur_val > error_stop_mode)) { - print_err("Bad interaction mode"); - help2( - "Modes are 0=batch, 1=nonstop, 2=scroll, and", - "3=errorstop. Proceed, and I'll ignore this case." - ); - int_error(cur_val); - } else { - cur_chr = cur_val; - new_interaction(); - } - } else { - insert_penalties = cur_val; - } -} - -void alter_box_dimen(void) -{ - int c; /* |width_offset| or |height_offset| or |depth_offset| */ - int b; /* box number */ - c = cur_chr; - scan_register_num(); - b = cur_val; - scan_optional_equals(); - scan_normal_dimen(); - if (box(b) != null) - varmem[box(b) + c].cint = cur_val; -} - -void new_interaction(void) -{ - print_ln(); - interaction = cur_chr; - if (interaction == batch_mode) - kpse_make_tex_discard_errors = 1; - else - kpse_make_tex_discard_errors = 0; - fixup_selector(log_opened_global); -} - -/*tex - -The \.{\\afterassignment} command puts a token into the global variable -|after_token|. This global variable is examined just after every assignment has -been performed. It's value is zero, or a saved token. - -*/ - -halfword after_token; - -/*tex - - Here is a procedure that might be called `Get the next non-blank non-relax - non-call non-assignment token'. - -*/ - -void do_assignments(void) -{ - while (true) { - /*tex Get the next non-blank non-relax... */ - do { - get_x_token(); - } while ((cur_cmd == spacer_cmd) || (cur_cmd == relax_cmd)); - if (cur_cmd <= max_non_prefixed_command) - return; - set_box_allowed = false; - prefixed_command(); - set_box_allowed = true; - } -} - -/*tex |cur_chr| is 1 for \.{\\openin}, 0 for \.{\\closein}: */ - -void open_or_close_in(void) -{ - int c = cur_chr; - int n; - char *fn; - scan_four_bit_int(); - n = cur_val; - if (read_open[n] != closed) { - lua_a_close_in(read_file[n], (n + 1)); - read_open[n] = closed; - } - if (c != 0) { - scan_optional_equals(); - do { - get_x_token(); - } while ((cur_cmd == spacer_cmd) || (cur_cmd == relax_cmd)); - back_input(); - if (cur_cmd != left_brace_cmd) { - /*tex Set |cur_name| to desired file name. */ - scan_file_name(); - } else { - scan_file_name_toks(); - } - fn = pack_file_name(cur_name, cur_area, cur_ext); - if (lua_a_open_in(&(read_file[n]), fn, (n + 1))) { - read_open[n] = just_open; - } - } -} - -/*tex - Has the long \.{\\errmessage} help been used? -*/ - -boolean long_help_seen; - -void issue_message(void) -{ - int old_setting; /* holds |selector| setting */ - int c; /* identifies \.{\\message} and \.{\\errmessage} */ - str_number s; /* the message */ - c = cur_chr; - (void) scan_toks(false, true); - old_setting = selector; - selector = new_string; - token_show(def_ref); - selector = old_setting; - flush_list(def_ref); - str_room(1); - s = make_string(); - if (c == 0) { - /*tex Print string |s| on the terminal */ - if (term_offset + (int) str_length(s) > max_print_line - 2) - print_ln(); - else if ((term_offset > 0) || (file_offset > 0)) - print_char(' '); - print(s); - update_terminal(); - - } else { - /*tex - Print string |s| as an error message. If \.{\\errmessage} occurs - often in |scroll_mode|, without user-defined \.{\\errhelp}, we don't - want to give a long help message each time. So we give a verbose - explanation only once. - */ - print_err(""); - print(s); - if (err_help_par != null) { - use_err_help = true; - } else if (long_help_seen) { - help1( - "(That was another \\errmessage.)" - ); - } else { - if (interaction < error_stop_mode) - long_help_seen = true; - help4( - "This error message was generated by an \\errmessage", - "command, so I can't give any explicit help.", - "Pretend that you're Hercule Poirot: Examine all clues,", - "and deduce the truth by order and method." - ); - } - error(); - use_err_help = false; - - } - flush_str(s); -} - -/*tex - -The |error| routine calls on |give_err_help| if help is requested from the -|err_help| parameter. - -*/ - -void give_err_help(void) -{ - token_show(err_help_par); -} - -/*tex - -The \.{\\uppercase} and \.{\\lowercase} commands are implemented by building a -token list and then changing the cases of the letters in it. - -*/ - -void shift_case(void) -{ - halfword b; /* |lc_code_base| or |uc_code_base| */ - halfword p; /* runs through the token list */ - halfword t; /* token */ - halfword c; /* character code */ - halfword i; /* inbetween */ - b = cur_chr; - p = scan_toks(false, false); - p = token_link(def_ref); - while (p != null) { - /*tex - Change the case of the token in |p|, if a change is appropriate. When - the case of a |chr_code| changes, we don't change the |cmd|. We also - change active characters. - */ - t = token_info(p); - if (t < cs_token_flag) { - c = t % STRING_OFFSET; - if (b == uc_code_base) - i = get_uc_code(c); - else - i = get_lc_code(c); - if (i != 0) - set_token_info(p, t - c + i); - } else if (is_active_cs(cs_text(t - cs_token_flag))) { - c = active_cs_value(cs_text(t - cs_token_flag)); - if (b == uc_code_base) - i = get_uc_code(c); - else - i = get_lc_code(c); - if (i != 0) - set_token_info(p, active_to_cs(i, true) + cs_token_flag); - } - p = token_link(p); - } - back_list(token_link(def_ref)); - free_avail(def_ref); -} - -/*tex - -We come finally to the last pieces missing from |main_control|, namely the -`\.{\\show}' commands that are useful when debugging. - -*/ - -void show_whatever(void) -{ - halfword p; /* tail of a token list to show */ - int t; /* type of conditional being shown */ - int m; /* upper bound on |fi_or_else| codes */ - int l; /* line where that conditional began */ - int n; /* level of \.{\\if...\\fi} nesting */ - switch (cur_chr) { - case show_lists: - begin_diagnostic(); - show_activities(); - break; - case show_box_code: - /*tex Show the current contents of a box. */ - scan_register_num(); - begin_diagnostic(); - tprint_nl("> \\box"); - print_int(cur_val); - print_char('='); - if (box(cur_val) == null) - tprint("void"); - else - show_box(box(cur_val)); - break; - case show_code: - /*tex Show the current meaning of a token, then |goto common_ending|. */ - get_token(); - if (interaction == error_stop_mode) - wake_up_terminal(); - tprint_nl("> "); - if (cur_cs != 0) { - sprint_cs(cur_cs); - print_char('='); - } - print_meaning(); - goto COMMON_ENDING; - break; - /*tex Cases for |show_whatever| */ - case show_groups: - begin_diagnostic(); - show_save_groups(); - break; - case show_ifs: - begin_diagnostic(); - tprint_nl(""); - print_ln(); - if (cond_ptr == null) { - tprint_nl("### "); - tprint("no active conditionals"); - } else { - p = cond_ptr; - n = 0; - do { - incr(n); - p = vlink(p); - } while (p != null); - p = cond_ptr; - t = cur_if; - l = if_line; - m = if_limit; - do { - tprint_nl("### level "); - print_int(n); - tprint(": "); - print_cmd_chr(if_test_cmd, t); - if (m == fi_code) - tprint_esc("else"); - print_if_line(l); - decr(n); - t = if_limit_subtype(p); - l = if_line_field(p); - m = if_limit_type(p); - p = vlink(p); - } while (p != null); - } - break; - default: - /*tex - Show the current value of some parameter or register, then |goto - common_ending|. - */ - p = the_toks(); - if (interaction == error_stop_mode) - wake_up_terminal(); - tprint_nl("> "); - token_show(temp_token_head); - flush_list(token_link(temp_token_head)); - goto COMMON_ENDING; - break; - } - /*tex Complete a potentially long \.{\\show} command: */ - end_diagnostic(true); - print_err("OK"); - if (selector == term_and_log) { - if (tracing_online_par <= 0) { - selector = term_only; - tprint(" (see the transcript file)"); - selector = term_and_log; - } - } - COMMON_ENDING: - if (interaction < error_stop_mode) { - help0(); - decr(error_count); - } else if (tracing_online_par > 0) { - help3( - "This isn't an error message; I'm just \\showing something.", - "Type `I\\show...' to show more (e.g., \\show\\cs,", - "\\showthe\\count10, \\showbox255, \\showlists)." - ); - } else { - help5( - "This isn't an error message; I'm just \\showing something.", - "Type `I\\show...' to show more (e.g., \\show\\cs,", - "\\showthe\\count10, \\showbox255, \\showlists).", - "And type `I\\tracingonline=1\\show...' to show boxes and", - "lists on your terminal as well as in the transcript file." - ); - } - error(); -} - -/*tex - This procedure gets things started properly: -*/ - -void initialize(void) -{ - int k; /* index into |mem|, |eqtb|, etc. */ - /*tex - Initialize whatever \TeX\ might access and set initial values of key - variables - */ - initialize_errors(); - initialize_arithmetic(); - max_used_attr = -1; - attr_list_cache = cache_disabled; - initialize_nesting(); - /*tex Start a new current page: */ - page_contents = empty; - page_tail = page_head; -#if 0 - vlink(page_head) = null; -#endif - last_glue = max_halfword; - last_penalty = 0; - last_kern = 0; - last_node_type = -1; - page_depth = 0; - page_max_depth = 0; - - initialize_equivalents(); - no_new_control_sequence = true; /* new identifiers are usually forbidden */ - init_primitives(); - - mag_set = 0; - initialize_marks(); - initialize_read(); - - static_pdf = init_pdf_struct(static_pdf); /* should be init_backend() */ - - format_ident = 0; - format_name = get_nullstr(); - initialize_directions(); - initialize_write_files(); - seconds_and_micros(epochseconds, microseconds); - initialize_start_time(static_pdf); - - edit_name_start = 0; - stop_at_space = true; - - if (ini_version) { - /*tex Initialize table entries (done by \.{INITEX} only). */ - init_node_mem(500); - initialize_tokens(); - /*tex Initialize the special list heads and constant nodes. */ - initialize_alignments(); - initialize_buildpage(); - - initialize_active(); - - set_eq_type(undefined_control_sequence, undefined_cs_cmd); - set_equiv(undefined_control_sequence, null); - set_eq_level(undefined_control_sequence, level_zero); - for (k = null_cs; k <= (eqtb_top - 1); k++) - eqtb[k] = eqtb[undefined_control_sequence]; - set_equiv(glue_base, zero_glue); - set_eq_level(glue_base, level_one); - set_eq_type(glue_base, glue_ref_cmd); - for (k = glue_base + 1; k <= local_base - 1; k++) { - eqtb[k] = eqtb[glue_base]; - } - par_shape_par_ptr = null; - set_eq_type(par_shape_loc, shape_ref_cmd); - set_eq_level(par_shape_loc, level_one); - for (k = etex_pen_base; k <= (etex_pens - 1); k++) - eqtb[k] = eqtb[par_shape_loc]; - for (k = output_routine_loc; k <= toks_base + biggest_reg; k++) - eqtb[k] = eqtb[undefined_control_sequence]; - box(0) = null; - set_eq_type(box_base, box_ref_cmd); - set_eq_level(box_base, level_one); - for (k = box_base + 1; k <= (box_base + biggest_reg); k++) - eqtb[k] = eqtb[box_base]; - cur_font_par = null_font; - set_eq_type(cur_font_loc, data_cmd); - set_eq_level(cur_font_loc, level_one); - set_equiv(cat_code_base, 0); - set_eq_type(cat_code_base, data_cmd); - set_eq_level(cat_code_base, level_one); - eqtb[internal_math_param_base] = eqtb[cat_code_base]; - eqtb[lc_code_base] = eqtb[cat_code_base]; - eqtb[uc_code_base] = eqtb[cat_code_base]; - eqtb[sf_code_base] = eqtb[cat_code_base]; - eqtb[math_code_base] = eqtb[cat_code_base]; - cat_code_table_par = 0; - initialize_math_codes(); - initialize_text_codes(); - initex_cat_codes(0); - for (k = '0'; k <= '9'; k++) - set_math_code(k, math_use_current_family_code, 0, k, level_one); - for (k = 'A'; k <= 'Z'; k++) { - set_math_code(k, math_use_current_family_code, 1, k, level_one); - set_math_code((k + 32), math_use_current_family_code, 1, (k + 32), level_one); - set_lc_code(k, k + 32, level_one); - set_lc_code(k + 32, k + 32, level_one); - set_uc_code(k, k, level_one); - set_uc_code(k + 32, k, level_one); - set_sf_code(k, 999, level_one); - } - for (k = int_base; k <= attribute_base - 1; k++) - eqtb[k].cint = 0; - for (k = attribute_base; k <= del_code_base - 1; k++) - eqtb[k].cint = UNUSED_ATTRIBUTE; - mag_par = 1000; - tolerance_par = 10000; - hang_after_par = 1; - max_dead_cycles_par = 25; - math_pre_display_gap_factor_par = 2000; - pre_bin_op_penalty_par = inf_penalty; - math_script_box_mode_par = 1; - math_script_char_mode_par = 1; - pre_rel_penalty_par = inf_penalty; - compound_hyphen_mode_par = 1; - escape_char_par = '\\'; - end_line_char_par = carriage_return; - set_del_code('.', 0, 0, 0, 0, level_one); /* this null delimiter is used in error recovery */ - ex_hyphen_char_par = '-'; - output_box_par = 255; - for (k = dimen_base; k <= eqtb_size; k++) - eqtb[k].cint = 0; - page_left_offset_par = one_inch; - page_top_offset_par = one_inch; - page_right_offset_par = one_inch; - page_bottom_offset_par = one_inch; - ini_init_primitives(); - hash_used = frozen_control_sequence; - hash_high = 0; - cs_count = 0; - set_eq_type(frozen_dont_expand, dont_expand_cmd); - cs_text(frozen_dont_expand) = maketexstring("notexpanded:"); - set_eq_type(frozen_primitive, ignore_spaces_cmd); - set_equiv(frozen_primitive, 1); - set_eq_level(frozen_primitive, level_one); - cs_text(frozen_primitive) = maketexstring("primitive"); - create_null_font(); - font_bytes = 0; - px_dimen_par = one_bp; - math_eqno_gap_step_par = 1000 ; - math_flatten_mode_par = 1; /* ord */ - cs_text(frozen_protection) = maketexstring("inaccessible"); - format_ident = maketexstring(" (INITEX)"); - cs_text(end_write) = maketexstring("endwrite"); - set_eq_level(end_write, level_one); - set_eq_type(end_write, outer_call_cmd); - set_equiv(end_write, null); - /*tex Bah, this is a bad place do do this. */ - set_pdf_major_version(1); - set_pdf_minor_version(0); - } - synctexoffset = int_base + synctex_code; -} diff --git a/Build/source/texk/web2c/luatexdir/tex/maincontrol.h b/Build/source/texk/web2c/luatexdir/tex/maincontrol.h deleted file mode 100644 index 04608c11e9b..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/maincontrol.h +++ /dev/null @@ -1,217 +0,0 @@ -/* maincontrol.h - - Copyright 2009 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ - - -#ifndef MAINCONTROL_H -# define MAINCONTROL_H - -# define fil_code 0 /* identifies \.{\\hfil} and \.{\\vfil} */ -# define fill_code 1 /* identifies \.{\\hfill} and \.{\\vfill} */ -# define ss_code 2 /* identifies \.{\\hss} and \.{\\vss} */ -# define fil_neg_code 3 /* identifies \.{\\hfilneg} and \.{\\vfilneg} */ -# define skip_code 4 /* identifies \.{\\hskip} and \.{\\vskip} */ -# define mskip_code 5 /* identifies \.{\\mskip} */ - -/* The |prefixed_command| does not have to adjust |a| so that |a mod 4=0|, -since the following routines test for the \.{\\global} prefix as follows. -*/ - -# define is_global(a) (a>=4) - -# define define(A,B,C) do { \ - if (is_global(a)) \ - geq_define((A),(quarterword)(B),(C)); \ - else \ - eq_define((A),(quarterword)(B),(C)); \ - } while (0) - -# define word_define(A,B) do { \ - if (is_global(a)) \ - geq_word_define((A),(B)); \ - else \ - eq_word_define((A),(B)); \ - } while (0) - -# define define_lc_code(A,B) do { \ - if (is_global(a)) \ - set_lc_code((A),(B),level_one); \ - else \ - set_lc_code((A),(B),cur_level); \ - } while (0) - -# define define_uc_code(A,B) do { \ - if (is_global(a)) \ - set_uc_code((A),(B),level_one); \ - else \ - set_uc_code((A),(B),cur_level); \ -} while (0) - -# define define_sf_code(A,B) do { \ - if (is_global(a)) \ - set_sf_code((A),(B),level_one); \ - else \ - set_sf_code((A),(B),cur_level); \ - } while (0) - -# define define_cat_code(A,B) do { \ - if (is_global(a)) \ - set_cat_code(cat_code_table_par,(A),(B),level_one); \ - else \ - set_cat_code(cat_code_table_par,(A),(B),cur_level); \ - } while (0) - -# define define_fam_fnt(A,B,C) do { \ - if (is_global(a)) \ - def_fam_fnt((A),(B),(C),level_one); \ - else \ - def_fam_fnt((A),(B),(C),cur_level); \ - } while (0) - -# define define_math_param(A,B,C) do { \ - if (is_global(a)) \ - def_math_param((A),(B),(C),level_one); \ - else \ - def_math_param((A),(B),(C),cur_level); \ - } while (0) - -extern halfword cur_box; /* box to be placed into its context */ - -/* -A \.{\\chardef} creates a control sequence whose |cmd| is |char_given|; -a \.{\\mathchardef} creates a control sequence whose |cmd| is |math_given|; -and the corresponding |chr| is the character code or math code. A \.{\\countdef} -or \.{\\dimendef} or \.{\\skipdef} or \.{\\muskipdef} creates a control -sequence whose |cmd| is |assign_int| or \dots\ or |assign_mu_glue|, and the -corresponding |chr| is the |eqtb| location of the internal register in question. -*/ - -# define char_def_code 0 /* |shorthand_def| for \.{\\chardef} */ -# define math_char_def_code 1 /* |shorthand_def| for \.{\\mathchardef} */ -# define xmath_char_def_code 2 /* |shorthand_def| for \.{\\Umathchardef} */ -# define count_def_code 3 /* |shorthand_def| for \.{\\countdef} */ -# define attribute_def_code 4 /* |shorthand_def| for \.{\\attributedef} */ -# define dimen_def_code 5 /* |shorthand_def| for \.{\\dimendef} */ -# define skip_def_code 6 /* |shorthand_def| for \.{\\skipdef} */ -# define mu_skip_def_code 7 /* |shorthand_def| for \.{\\muskipdef} */ -# define toks_def_code 8 /* |shorthand_def| for \.{\\toksdef} */ -# define umath_char_def_code 9 /* |shorthand_def| for \.{\\Umathcharnumdef} */ - -extern void adjust_space_factor(void); -extern void main_control(void); -extern void app_space(void); -extern void insert_dollar_sign(void); -extern void insert_dollar_sign_par_end(void); -extern void you_cant(void); -extern void report_illegal_case(void); -extern boolean privileged(void); -extern boolean its_all_over(void); -extern void append_glue(void); -extern void append_kern(void); -extern void off_save(void); -extern void handle_right_brace(void); -extern void extra_right_brace(void); -extern void normal_paragraph(void); -extern void box_end(int box_context); -extern void scan_box(int box_context); -extern void new_graf(boolean indented); -extern void indent_in_hmode(void); -extern void head_for_vmode(void); -extern void end_graf(int); -extern void begin_insert_or_adjust(void); -extern void handle_mark(void); -extern void append_penalty(void); -extern void delete_last(void); -extern void unpackage(void); -extern void append_italic_correction(void); -extern void append_local_box(int kind); -extern void append_discretionary(void); -extern void build_local_box(void); -extern void build_discretionary(void); -extern void make_accent(void); -extern void align_error(void); -extern void no_align_error(void); -extern void omit_error(void); -extern void do_endv(void); -extern void cs_error(void); -extern void prefixed_command(void); -extern void fixup_directions(void); -extern void fixup_directions_only(void); - - -/* Assignments from Lua need helpers. */ - -# define is_int_assign(cmd) (cmd==assign_int_cmd) -# define is_attr_assign(cmd) (cmd==assign_attr_cmd) -# define is_dim_assign(cmd) (cmd==assign_dimen_cmd) -# define is_glue_assign(cmd) (cmd==assign_glue_cmd) -# define is_mu_glue_assign(cmd) (cmd==assign_mu_glue_cmd) -# define is_toks_assign(cmd) (cmd==assign_toks_cmd) - -# define show_code 0 /* \.{\\show} */ -# define show_box_code 1 /* \.{\\showbox} */ -# define show_the_code 2 /* \.{\\showthe} */ -# define show_lists 3 /* \.{\\showlists} */ -# define show_groups 4 /* \.{\\showgroups} */ -# define show_tokens 5 /* \.{\\showtokens} , must be odd! */ -# define show_ifs 6 /* \.{\\showifs} */ - -# define print_if_line(A) if ((A)!=0) { \ - tprint(" entered on line "); print_int((A)); \ - } - -/* - extern halfword swap_hang_indent(halfword indentation, halfword shape_mode); - extern halfword swap_parshape_indent(halfword indentation, halfword width, halfword shape_mode); -*/ - -#define swap_hang_indent(indentation) \ - ( ((shape_mode_par == 1 || shape_mode_par == 3 || shape_mode_par == -1 || shape_mode_par == -3)) ? negate(indentation) : indentation ) - -#define swap_parshape_indent(indentation,width) \ - ( ((shape_mode_par == 2 || shape_mode_par == 3 || shape_mode_par == -2 || shape_mode_par == -3)) ? (hsize_par - width - indentation) : indentation ) - -extern void get_r_token(void); -extern void assign_internal_value(int a, halfword p, int cur_val); -extern void do_register_command(int a); -extern void alter_aux(void); -extern void alter_prev_graf(void); -extern void alter_page_so_far(void); -extern void alter_integer(void); -extern void alter_box_dimen(void); -extern void new_interaction(void); -extern halfword after_token; -extern void do_assignments(void); -extern void open_or_close_in(void); -extern boolean long_help_seen; -extern void issue_message(void); -extern void give_err_help(void); -extern void shift_case(void); -extern void show_whatever(void); - -extern void initialize(void); /* this procedure gets things started properly */ - -/*extern int local_level;*/ - -extern void local_control(void); -extern halfword local_scan_box(void); -extern int current_local_level(void); -extern void end_local_control(void); -extern void local_control_message(const char *s); - -#endif diff --git a/Build/source/texk/web2c/luatexdir/tex/mathcodes.c b/Build/source/texk/web2c/luatexdir/tex/mathcodes.c deleted file mode 100644 index 42e8b0b15b9..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/mathcodes.c +++ /dev/null @@ -1,360 +0,0 @@ -/* - -mathnodes.w - -Copyright 2006-2010 Taco Hoekwater <taco@@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your -option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU General Public License along -with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" - -/*tex - -We support tre traditional math codes as well as larger ones suitable for -\UNICODE\ input and fonts. - -*/ - -static sa_tree mathcode_head = NULL; - -/*tex the |0xFFFFFFFF| is a flag value. */ - -#define MATHCODESTACK 8 -#define MATHCODEDEFAULT 0xFFFFFFFF -#define MATHCODEACTIVE 0xFFFFFFFE - -/*tex - -Delcodes are also went larger. - -*/ - -static sa_tree delcode_head = NULL; - -#define DELCODESTACK 4 -#define DELCODEDEFAULT 0xFFFFFFFF - -/*tex - -We now get lots of helpers for definitions and printing. The storage model -that we use is different because we can hav emany more so we need to be -sparse. Therefore we use trees. - -*/ - - -#define print_hex_digit(A) do { \ - if ((A)>=10) print_char('A'+(A)-10); \ - else print_char('0'+(A)); \ - } while (0) - -#define two_hex(A) do { \ - print_hex_digit((A)/16); \ - print_hex_digit((A)%16); \ - } while (0) - -#define four_hex(A) do { \ - two_hex((A)/256); \ - two_hex((A)%256); \ - } while (0) - -#define six_hex(A) do { \ - two_hex((A)/65536); \ - two_hex(((A)%65536)/256); \ - two_hex((A)%256); \ - } while (0) - -mathcodeval mathchar_from_integer(int value, int extcode) -{ - mathcodeval mval; - if (extcode == tex_mathcode) { - mval.class_value = (value / 0x1000); - mval.family_value = ((value % 0x1000) / 0x100); - mval.character_value = (value % 0x100); - } else { - int mfam = (value / 0x200000) & 0x7FF; - mval.class_value = mfam % 0x08; - mval.family_value = mfam / 0x08; - mval.character_value = value & 0x1FFFFF; - } - return mval; -} - -void show_mathcode_value_old(int value) -{ - print_char('"'); - four_hex(value); -} - -void show_mathcode_value(mathcodeval c) -{ - print_char('"'); - print_hex_digit(c.class_value); - print_char('"'); - two_hex(c.family_value); - print_char('"'); - six_hex(c.character_value); -} - -static void show_mathcode(int n) -{ - mathcodeval c = get_math_code(n); - tprint_esc("Umathcode"); - print_int(n); - print_char('='); - show_mathcode_value(c); -} - -static void unsavemathcode(quarterword gl) -{ - sa_stack_item st; - if (mathcode_head->stack == NULL) - return; - while (mathcode_head->stack_ptr > 0 && abs(mathcode_head->stack[mathcode_head->stack_ptr].level) >= gl) { - st = mathcode_head->stack[mathcode_head->stack_ptr]; - if (st.level > 0) { - rawset_sa_item(mathcode_head, st.code, st.value); - if (tracing_restores_par > 1) { - begin_diagnostic(); - print_char('{'); - tprint("restoring"); - print_char(' '); - show_mathcode(st.code); - print_char('}'); - end_diagnostic(false); - } - } - (mathcode_head->stack_ptr)--; - } -} - -void set_math_code(int n, int mathclass, int mathfamily, int mathcharacter, quarterword level) -{ - sa_tree_item v; - if (mathclass == 8 && mathfamily == 0 && mathcharacter == 0) { - v.uint_value = MATHCODEACTIVE; - } else { - v.math_code_value.class_value = mathclass; - v.math_code_value.family_value = mathfamily; - v.math_code_value.character_value = mathcharacter; - } - set_sa_item(mathcode_head, n, v, level); - if (tracing_assigns_par > 1) { - begin_diagnostic(); - print_char('{'); - tprint("assigning"); - print_char(' '); - show_mathcode(n); - print_char('}'); - end_diagnostic(false); - } -} - -mathcodeval get_math_code(int n) -{ - mathcodeval d; - sa_tree_item v = get_sa_item(mathcode_head, n); - if (v.uint_value == MATHCODEDEFAULT) { - d.class_value = 0; - d.family_value = 0; - d.character_value = n; - } else if (v.uint_value == MATHCODEACTIVE) { - d.class_value = 8; - d.family_value = 0; - d.character_value = 0; - } else { - d.class_value = v.math_code_value.class_value; - if (d.class_value == 8) { - d.family_value = 0; - d.character_value = n; - } else { - d.family_value = v.math_code_value.family_value; - d.character_value = v.math_code_value.character_value; - } - } - return d; -} - -int get_math_code_num(int n) -{ - mathcodeval d = get_math_code(n); - return (d.class_value + (d.family_value * 8)) * (65536 * 32) + d.character_value; -} - -static void initializemathcode(void) -{ - sa_tree_item sa_value = { 0 }; - sa_value.uint_value = MATHCODEDEFAULT; - mathcode_head = new_sa_tree(MATHCODESTACK, 1, sa_value); -} - -static void dumpmathcode(void) -{ - dump_sa_tree(mathcode_head,"mathcodes"); -} - -static void undumpmathcode(void) -{ - mathcode_head = undump_sa_tree("mathcodes"); -} - -static void show_delcode(int n) -{ - delcodeval c; - c = get_del_code(n); - tprint_esc("Udelcode"); - print_int(n); - print_char('='); - if (c.small_family_value < 0) { - print_char('-'); - print_char('1'); - } else { - print_char('"'); - two_hex(c.small_family_value); - six_hex(c.small_character_value); - } -} - -static void unsavedelcode(quarterword gl) -{ - sa_stack_item st; - if (delcode_head->stack == NULL) - return; - while (delcode_head->stack_ptr > 0 && abs(delcode_head->stack[delcode_head->stack_ptr].level) >= gl) { - st = delcode_head->stack[delcode_head->stack_ptr]; - if (st.level > 0) { - rawset_sa_item(delcode_head, st.code, st.value); - if (tracing_restores_par > 1) { - begin_diagnostic(); - print_char('{'); - tprint("restoring"); - print_char(' '); - show_delcode(st.code); - print_char('}'); - end_diagnostic(false); - } - } - (delcode_head->stack_ptr)--; - } -} - -void set_del_code(int n, int smathfamily, int smathcharacter, int lmathfamily, int lmathcharacter, quarterword gl) -{ - sa_tree_item v; - v.del_code_value.class_value = 0; - v.del_code_value.small_family_value = smathfamily; - v.del_code_value.small_character_value = smathcharacter; - v.del_code_value.dummy_value = 0; - v.del_code_value.large_family_value = lmathfamily; - v.del_code_value.large_character_value = lmathcharacter; - /*tex Always global! */ - set_sa_item(delcode_head, n, v, gl); - if (tracing_assigns_par > 1) { - begin_diagnostic(); - print_char('{'); - tprint("assigning"); - print_char(' '); - show_delcode(n); - print_char('}'); - end_diagnostic(false); - } -} - -delcodeval get_del_code(int n) -{ - delcodeval d; - sa_tree_item v = get_sa_item(delcode_head, n); - if (v.uint_value == DELCODEDEFAULT) { - d.class_value = 0; - d.small_family_value = -1; - d.small_character_value = 0; - d.large_family_value = 0; - d.large_character_value = 0; - } else { - d.class_value = v.del_code_value.class_value; - d.small_family_value = v.del_code_value.small_family_value; - d.small_character_value = v.del_code_value.small_character_value; - d.large_family_value = v.del_code_value.large_family_value; - d.large_character_value = v.del_code_value.large_character_value; - } - return d; -} - -/*tex - -This really only works for old-style delcodes! - -*/ - -int get_del_code_num(int n) -{ - delcodeval d = get_del_code(n); - if (d.small_family_value < 0) { - return -1; - } else { - return ((d.small_family_value * 256 + d.small_character_value) * 4096 + - (d.large_family_value * 256) + d.large_character_value); - } -} - -static void initializedelcode(void) -{ - sa_tree_item sa_value = { 0 }; - sa_value.uint_value = DELCODEDEFAULT; - delcode_head = new_sa_tree(DELCODESTACK, 2, sa_value); -} - -static void dumpdelcode(void) -{ - dump_sa_tree(delcode_head,"delcodes"); -} - -static void undumpdelcode(void) -{ - delcode_head = undump_sa_tree("delcodes"); -} - -void unsave_math_codes(quarterword grouplevel) -{ - unsavemathcode(grouplevel); - unsavedelcode(grouplevel); -} - -void initialize_math_codes(void) -{ - initializemathcode(); - initializedelcode(); -} - -void free_math_codes(void) -{ - destroy_sa_tree(mathcode_head); - destroy_sa_tree(delcode_head); -} - -void dump_math_codes(void) -{ - dumpmathcode(); - dumpdelcode(); -} - -void undump_math_codes(void) -{ - undumpmathcode(); - undumpdelcode(); -} diff --git a/Build/source/texk/web2c/luatexdir/tex/mathcodes.h b/Build/source/texk/web2c/luatexdir/tex/mathcodes.h deleted file mode 100644 index fe731ff2be5..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/mathcodes.h +++ /dev/null @@ -1,67 +0,0 @@ -/* mathcodes.h - - Copyright 2009-2012 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#ifndef MATHCODES_H -# define MATHCODES_H - -/* this is a flag for |scan_delimiter| */ - -# define no_mathcode 0 -# define tex_mathcode 8 -# define umath_mathcode 21 -# define umathnum_mathcode 22 - -typedef struct mathcodeval { - int class_value; - int family_value; - int character_value; -} mathcodeval; - -void set_math_code(int n, int mathclass, int mathfamily, int mathcharacter, quarterword gl); - -mathcodeval get_math_code(int n); -int get_math_code_num(int n); -int get_del_code_num(int n); -mathcodeval scan_mathchar(int extcode); -mathcodeval scan_delimiter_as_mathchar(int extcode); - -mathcodeval mathchar_from_integer(int value, int extcode); -void show_mathcode_value(mathcodeval d); -void show_mathcode_value_old(int value); - -typedef struct delcodeval { - int class_value; - int small_family_value; - int small_character_value; - int large_family_value; - int large_character_value; -} delcodeval; - -void set_del_code(int n, int smathfamily, int smathcharacter, int lmathfamily, int lmathcharacter, quarterword gl); - -delcodeval get_del_code(int n); - -void unsave_math_codes(quarterword grouplevel); -void initialize_math_codes(void); -void dump_math_codes(void); -void undump_math_codes(void); - -#endif diff --git a/Build/source/texk/web2c/luatexdir/tex/memoryword.c b/Build/source/texk/web2c/luatexdir/tex/memoryword.c deleted file mode 100644 index 7bf758dd0d4..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/memoryword.c +++ /dev/null @@ -1,29 +0,0 @@ -/* -memoryword.w - -Copyright 2009-2010 Taco Hoekwater <taco@@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your -option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU General Public License along -with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" - -/*tex - -The debug code is no longer present! - -*/ diff --git a/Build/source/texk/web2c/luatexdir/tex/memoryword.h b/Build/source/texk/web2c/luatexdir/tex/memoryword.h deleted file mode 100644 index 5db2bb8cb36..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/memoryword.h +++ /dev/null @@ -1,128 +0,0 @@ -/* memoryword.h - - Copyright 2009-2010 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ - - -/* This header file is extra special because it is read in from - within the pascal source */ - -#ifndef MEMORYWORD_H -# define MEMORYWORD_H - -/* texmfmem.h: the memory_word type, which is too hard to translate - automatically from Pascal. We have to make sure the byte-swapping - that the (un)dumping routines do suffices to put things in the right - place in memory. - - A memory_word can be broken up into a `twohalves' or a - `fourquarters', and a `twohalves' can be further broken up. Here is - a picture. ..._M = most significant byte, ..._L = least significant - byte. - - - BigEndian: - twohalves.v: RH_MM RH_ML RH_LM RH_LL LH_MM LH_ML LH_LM LH_LL - twohalves.u: ---------JUNK---------- ----B0----- ----B1----- - fourquarters: ----B0----- ----B1----- ----B2----- ----B3----- - twoints: ---------CINT0--------- ---------CINT1--------- - - LittleEndian: - twohalves.v: LH_LL LH_LM LH_ML LH_MM RH_LL RH_LM RH_ML RH_MM - twohalves.u: ----B1----- ----B0----- - fourquarters: ----B3----- ----B2----- ----B1----- ----B0----- - twoints: ---------CINT1--------- ---------CINT0--------- - -*/ - - -typedef union { - struct { -# ifdef WORDS_BIGENDIAN - halfword RH, LH; -# else - halfword LH, RH; -# endif - } v; - - struct { /* Make B0,B1 overlap the most significant bytes of LH. */ -# ifdef WORDS_BIGENDIAN - halfword junk; - quarterword B0, B1; -# else /* not WORDS_BIGENDIAN */ - /* If 32-bit memory words, have to do something. */ - quarterword B1, B0; -# endif /* LittleEndian */ - } u; -} two_halves; - -typedef struct { - struct { -# ifdef WORDS_BIGENDIAN - quarterword B0, B1, B2, B3; -# else - quarterword B3, B2, B1, B0; -# endif - } u; -} four_quarters; - -typedef struct { -# ifdef WORDS_BIGENDIAN - int CINT0, CINT1; -# else - int CINT1, CINT0; -# endif -} two_ints; - -typedef struct { - glue_ratio GLUE; -} glues; - -typedef union { - two_halves hh; - four_quarters qqqq; - two_ints ii; - glues gg; -} memory_word; - -# define b0 u.B0 -# define b1 u.B1 -# define b2 u.B2 -# define b3 u.B3 - -# define rh v.RH -# define lhfield v.LH - -# define cint ii.CINT0 -# define cint1 ii.CINT1 - -# define gr gg.GLUE - -/* the next five defines are needed for the prototypes in web2c's coerce.h */ - -# define memoryword memory_word -# define strnumber str_number -# define packedASCIIcode packed_ASCII_code -# define poolpointer pool_pointer - -typedef FILE *word_file; - -# ifdef DEBUG -extern void print_word(memory_word w); -# endif - -#endif diff --git a/Build/source/texk/web2c/luatexdir/tex/mlist.c b/Build/source/texk/web2c/luatexdir/tex/mlist.c deleted file mode 100644 index 2ac631ea339..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/mlist.c +++ /dev/null @@ -1,4830 +0,0 @@ -/* - -Copyright 2006-2010 Taco Hoekwater <taco@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under the terms -of the GNU General Public License as published by the Free Software Foundation; -either version 2 of the License, or (at your option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - -You should have received a copy of the GNU General Public License along with -LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -/*tex - - In traditional \TeX\ the italic correction is added to the width of the - glyph. This is part of the engine design and related font design. In opentype - math this is different. There the italic correction had more explicit usage. - The 1.7 spec says: - - \startitemize - - \startitem - {\em italic correction:} When a run of slanted characters is followed by - a straight character (such as an operator or a delimiter), the italics - correction of the last glyph is added to its advance width. - - When positioning limits on an N-ary operator (e.g., integral sign), the - horizontal position of the upper limit is moved to the right by ½ of the - italics correction, while the position of the lower limit is moved to the - left by the same distance. - - When positioning superscripts and subscripts, their default horizontal - positions are also different by the amount of the italics correction of - the preceding glyph. - \stopitem - - \startitem - {\em math kerning:} Set the default horizontal position for the - superscript as shifted relative to the position of the subscript by the - italics correction of the base glyph. - \stopitem - - \stopitemize - - Before this was specified we had to gamble a bit and assume that cambria was - the font benchmark and trust our eyes (and msword) for the logic. I must - admit that I have been fighting these italics in fonts (and the heuristics - that Lua\TeX\ provided) right from the start (e.g. using Lua based - postprocessing) but by now we know more and have more fonts to test with. - More fonts are handy because not all fonts are alike when it comes to - italics. Axis are another area of concern, as it looks like opentype math - fonts often already apply that shift. - -*/ - -#define is_new_mathfont(A) ((font_math_params(A) >0) && (math_old_par == 0)) -#define is_old_mathfont(A,B) ((font_math_params(A)==0) && (font_params(A)>=(B))) -#define do_new_math(A) ((font_math_params(A) >0) && (font_oldmath(A) == 0) && (math_old_par == 0)) -#define protect_glyph(A) subtype(A)=256 - -#include "ptexlib.h" -#include "lua/luatex-api.h" - -#define reset_attributes(p,newatt) do { \ - delete_attribute_ref(node_attr(p)); \ - node_attr(p) = newatt; \ - if (newatt!=null) { \ - add_node_attr_ref(node_attr(p)); \ - } \ - } while (0) - -#define DEFINE_MATH_PARAMETERS(A,B,C,D) do { \ - if (B==text_size) { \ - def_math_param(A, text_style, (C),D); \ - def_math_param(A, cramped_text_style, (C),D); \ - } else if (B==script_size) { \ - def_math_param(A, script_style, (C),D); \ - def_math_param(A, cramped_script_style, (C),D); \ - } else if (B==script_script_size) { \ - def_math_param(A, script_script_style, (C),D); \ - def_math_param(A, cramped_script_script_style, (C),D); \ - } \ - } while (0) - -#define DEFINE_DMATH_PARAMETERS(A,B,C,D) do { \ - if (B==text_size) { \ - def_math_param(A, display_style,(C),D); \ - def_math_param(A, cramped_display_style,(C),D); \ - } \ - } while (0) - -#define font_MATH_par(a,b) \ - (font_math_params(a)>=b ? font_math_param(a,b) : undefined_math_parameter) - -/*tex - - Here are the math parameters that are font-dependant. - - Before an mlist is converted to an hlist, \TeX\ makes sure that the fonts in - family~2 have enough parameters to be math-symbol fonts, and that the fonts - in family~3 have enough parameters to be math-extension fonts. The - math-symbol parameters are referred to by using the following macros, which - take a size code as their parameter; for example, |num1(cur_size)| gives the - value of the |num1| parameter for the current size. - -*/ - -#define total_mathsy_params 22 -#define total_mathex_params 13 - -#define mathsy(A,B) font_param(fam_fnt(2,A),B) - -/*tex height of `\.x' */ - -#define math_x_height(A) mathsy(A,5) - -/*tex \.{18mu} */ - -#define math_quad(A) mathsy(A,6) - -/*tex numerator shift-up in display styles */ - -#define num1(A) mathsy(A,8) - -/*tex numerator shift-up in non-display, non-\.{\\atop} */ - -#define num2(A) mathsy(A,9) - -/*tex numerator shift-up in non-display \.{\\atop} */ - -#define num3(A) mathsy(A,10) - -/*tex denominator shift-down in display styles */ - -#define denom1(A) mathsy(A,11) - -/*tex denominator shift-down in non-display styles */ - -#define denom2(A) mathsy(A,12) - -/*tex superscript shift-up in uncramped display style */ - -#define sup1(A) mathsy(A,13) - -/*tex superscript shift-up in uncramped non-display */ - -#define sup2(A) mathsy(A,14) - -/*tex superscript shift-up in cramped styles */ - -#define sup3(A) mathsy(A,15) - -/*tex subscript shift-down if superscript is absent */ - -#define sub1(A) mathsy(A,16) - -/*tex subscript shift-down if superscript is present */ - -#define sub2(A) mathsy(A,17) - -/*tex superscript baseline below top of large box */ - -#define sup_drop(A) mathsy(A,18) - -/*tex subscript baseline below bottom of large box */ - -#define sub_drop(A) mathsy(A,19) - -/*tex size of \.{\\atopwithdelims} delimiters in display styles */ - -#define delim1(A) mathsy(A,20) - -/*tex size of \.{\\atopwithdelims} delimiters in non-displays */ - -#define delim2(A) mathsy(A,21) - -/*tex height of fraction lines above the baseline */ - -#define axis_height(A) mathsy(A,22) - -/*tex - - The math-extension parameters have similar macros, but the size code is - omitted (since it is always |cur_size| when we refer to such parameters). - -*/ - -#define mathex(A,B) font_param(fam_fnt(3,A),B) - -/*tex thickness of \.{\\over} bars */ - -#define default_rule_thickness(A) mathex(A,8) - -/*tex minimum clearance above a displayed op */ - -#define big_op_spacing1(A) mathex(A,9) - -/*tex minimum clearance below a displayed op */ - -#define big_op_spacing2(A) mathex(A,10) - -/*tex minimum baselineskip above displayed op */ - -#define big_op_spacing3(A) mathex(A,11) - -/*tex minimum baselineskip below displayed op */ - -#define big_op_spacing4(A) mathex(A,12) - -/*tex padding above and below displayed limits */ - -#define big_op_spacing5(A) mathex(A,13) - -/*tex - - \LUATEX makes a bunch of extensions cf. the |MATH| table in \OPENTYPE, but - some of the |MathConstants| values have no matching usage in \LUATEX\ right - now. - - \startitemize - - \startitem - |ScriptPercentScaleDown| |ScriptScriptPercentScaleDown|: These should - be handled by the macro package, on the engine side there are three - separate fonts. - \stopitem - - \startitem - |DelimitedSubFormulaMinHeight|: This is perhaps related to word's - natural math input? We have no idea what to do about it. - \stopitem - - \startitem - |MathLeading|: \LUATEX does not currently handle multi-line displays, - and the parameter does not seem to make much sense elsewhere. - \stopitem - - \startitem - |FlattenedAccentBaseHeight|: This is based on the |flac| |GSUB| - feature. It would not be hard to support that, but proper math accent - placements cf.\ |MATH| needs support for |MathTopAccentAttachment| - table to be implemented first. - \stopitem - - \stopitemize - -*/ - -static void math_param_error(const char *param, int style) -{ - char s[256]; - const char *hlp[] = { - "Sorry, but I can't typeset math unless various parameters have", - "been set. This is normally done by loading special math fonts", - "into the math family slots. Your font set is lacking at least", - "the parameter mentioned earlier.", - NULL - }; - snprintf(s, 256, "Math error: parameter \\Umath%s\\%sstyle is not set", param, math_style_names[style]); - tex_error(s, hlp); - return; -} - -static scaled accent_base_height(int f) -{ - scaled a; - if (do_new_math(f)) { - a = font_MATH_par(f, AccentBaseHeight); - if (a == undefined_math_parameter) - a = x_height(f); - } else { - a = x_height(f); - } - return a; -} - -/*tex - - The non-staticness of this function is for the benefit of |texmath.w|. - Watch out, this one uses the style! The style and size numbers don't - match because we have cramped styles. - -*/ - -scaled get_math_quad_style(int var) -{ - scaled a = get_math_param(math_param_quad, var); - if (a == undefined_math_parameter) { - math_param_error("quad", var); - return 0; - } else { - return a; - } -} - -/*tex - - For this reason the next one is different because it is called with a size - specifier instead of a style specifier. - -*/ - -static scaled math_axis_size(int b) -{ - scaled a; - int var; - if (b == script_size) - var = script_style; - else if (b == script_script_size) - var = script_script_style; - else - var = text_style; - a = get_math_param(math_param_axis, var); - if (a == undefined_math_parameter) { - math_param_error("axis", var); - return 0; - } else { - return a; - } -} - -scaled get_math_quad_size(int b) -{ - int var; - if (b == script_size) - var = script_style; - else if (b == script_script_size) - var = script_script_style; - else - var = text_style; - return get_math_param(math_param_quad, var); -} - -static scaled minimum_operator_size(int var) -{ - scaled a = get_math_param(math_param_operator_size, var); - return a; -} - -/*tex - - Old-style fonts do not define the |radical_rule|. This allows |make_radical| - to select the backward compatibility code, and it means that we can't raise - an error here. - -*/ - -static scaled radical_rule_par(int var) -{ - scaled a = get_math_param(math_param_radical_rule, var); - return a; -} - -/*tex - - Now follow all the trivial math parameters. - -*/ - -#define get_math_param_or_error(a,b) do_get_math_param_or_error(a, math_param_##b, #b) -#define get_math_param_or_zero(a,b) do_get_math_param_or_zero(a, math_param_##b, #b) - -static scaled do_get_math_param_or_error(int var, int param, const char *name) -{ - scaled a = get_math_param(param, var); - if (a == undefined_math_parameter) { - math_param_error(name, var); - a = 0; - } - return a; -} - -static scaled do_get_math_param_or_zero(int var, int param, const char *name) -{ - scaled a = get_math_param(param, var); - if (a == undefined_math_parameter) { - a = 0; - } - return a; -} - -/*tex - - A variant on a suggestion on the list based on analysis by UV. - -*/ - -static scaled get_delimiter_height(scaled max_d, scaled max_h, boolean axis) { - scaled delta, delta1, delta2; - if (axis) { - delta2 = max_d + math_axis_size(cur_size); - } else { - delta2 = max_d; - } - delta1 = max_h + max_d - delta2; - if (delta2 > delta1) { - /*tex |delta1| is max distance from axis */ - delta1 = delta2; - } - delta = (delta1 / 500) * delimiter_factor_par; - delta2 = delta1 + delta1 - delimiter_shortfall_par; - if (delta < delta2) { - return delta2; - } else { - return delta; - } -} - -#define radical_degree_before(a) get_math_param_or_error(a, radical_degree_before) -#define radical_degree_after(a) get_math_param_or_error(a, radical_degree_after) -#define radical_degree_raise(a) get_math_param_or_error(a, radical_degree_raise) - -#define connector_overlap_min(a) get_math_param_or_error(a, connector_overlap_min) - -#define overbar_rule(a) get_math_param_or_error(a, overbar_rule) -#define overbar_kern(a) get_math_param_or_error(a, overbar_kern) -#define overbar_vgap(a) get_math_param_or_error(a, overbar_vgap) - -#define underbar_rule(a) get_math_param_or_error(a, underbar_rule) -#define underbar_kern(a) get_math_param_or_error(a, underbar_kern) -#define underbar_vgap(a) get_math_param_or_error(a, underbar_vgap) - -#define under_delimiter_vgap(a) get_math_param_or_error(a, under_delimiter_vgap) -#define under_delimiter_bgap(a) get_math_param_or_error(a, under_delimiter_bgap) - -#define over_delimiter_vgap(a) get_math_param_or_error(a, over_delimiter_vgap) -#define over_delimiter_bgap(a) get_math_param_or_error(a, over_delimiter_bgap) - -#define radical_vgap(a) get_math_param_or_error(a, radical_vgap) -#define radical_kern(a) get_math_param_or_error(a, radical_kern) - -#define stack_vgap(a) get_math_param_or_error(a, stack_vgap) -#define stack_num_up(a) get_math_param_or_error(a, stack_num_up) -#define stack_denom_down(a) get_math_param_or_error(a, stack_denom_down) - -#define fraction_rule(a) get_math_param_or_error(a, fraction_rule) -#define fraction_num_vgap(a) get_math_param_or_error(a, fraction_num_vgap) -#define fraction_denom_vgap(a) get_math_param_or_error(a, fraction_denom_vgap) -#define fraction_num_up(a) get_math_param_or_error(a, fraction_num_up) -#define fraction_denom_down(a) get_math_param_or_error(a, fraction_denom_down) -#define fraction_del_size_new(a) get_math_param_or_error(a, fraction_del_size) -/* fraction_del_size_old(a) get_math_param (a, math_param_fraction_del_size) */ -#define fraction_del_size_old(a) get_math_param_or_error(a, fraction_del_size) - -#define skewed_fraction_hgap(a) get_math_param_or_error(a, skewed_fraction_hgap) -#define skewed_fraction_vgap(a) get_math_param_or_error(a, skewed_fraction_vgap) - -#define limit_above_vgap(a) get_math_param_or_error(a, limit_above_vgap) -#define limit_above_bgap(a) get_math_param_or_error(a, limit_above_bgap) -#define limit_above_kern(a) get_math_param_or_error(a, limit_above_kern) - -#define limit_below_vgap(a) get_math_param_or_error(a, limit_below_vgap) -#define limit_below_bgap(a) get_math_param_or_error(a, limit_below_bgap) -#define limit_below_kern(a) get_math_param_or_error(a, limit_below_kern) - -#define nolimit_sub_factor(a) get_math_param_or_zero(a, nolimit_sub_factor) -#define nolimit_sup_factor(a) get_math_param_or_zero(a, nolimit_sup_factor) - -#define sub_shift_drop(a) get_math_param_or_error(a, sub_shift_drop) -#define sup_shift_drop(a) get_math_param_or_error(a, sup_shift_drop) -#define sub_shift_down(a) get_math_param_or_error(a, sub_shift_down) -#define sub_sup_shift_down(a) get_math_param_or_error(a, sub_sup_shift_down) -#define sup_shift_up(a) get_math_param_or_error(a, sup_shift_up) -#define sub_top_max(a) get_math_param_or_error(a, sub_top_max) -#define sup_bottom_min(a) get_math_param_or_error(a, sup_bottom_min) -#define sup_sub_bottom_max(a) get_math_param_or_error(a, sup_sub_bottom_max) -#define subsup_vgap(a) get_math_param_or_error(a, subsup_vgap) - -#define space_after_script(a) get_math_param_or_error(a, space_after_script) - -void fixup_math_parameters(int fam_id, int size_id, int f, int lvl) -{ - if (is_new_mathfont(f)) { - - /*tex Fix all known parameters. */ - - DEFINE_MATH_PARAMETERS(math_param_quad, size_id, - font_size(f), lvl); - DEFINE_DMATH_PARAMETERS(math_param_quad, size_id, - font_size(f), lvl); - DEFINE_MATH_PARAMETERS(math_param_axis, size_id, - font_MATH_par(f, AxisHeight), lvl); - DEFINE_DMATH_PARAMETERS(math_param_axis, size_id, - font_MATH_par(f, AxisHeight), lvl); - DEFINE_MATH_PARAMETERS(math_param_overbar_kern, size_id, - font_MATH_par(f, OverbarExtraAscender), lvl); - DEFINE_DMATH_PARAMETERS(math_param_overbar_kern, size_id, - font_MATH_par(f, OverbarExtraAscender), lvl); - DEFINE_MATH_PARAMETERS(math_param_overbar_rule, size_id, - font_MATH_par(f, OverbarRuleThickness), lvl); - DEFINE_DMATH_PARAMETERS(math_param_overbar_rule, size_id, - font_MATH_par(f, OverbarRuleThickness), lvl); - DEFINE_MATH_PARAMETERS(math_param_overbar_vgap, size_id, - font_MATH_par(f, OverbarVerticalGap), lvl); - DEFINE_DMATH_PARAMETERS(math_param_overbar_vgap, size_id, - font_MATH_par(f, OverbarVerticalGap), lvl); - DEFINE_MATH_PARAMETERS(math_param_underbar_kern, size_id, - font_MATH_par(f, UnderbarExtraDescender), lvl); - DEFINE_DMATH_PARAMETERS(math_param_underbar_kern, size_id, - font_MATH_par(f, UnderbarExtraDescender), lvl); - DEFINE_MATH_PARAMETERS(math_param_underbar_rule, size_id, - font_MATH_par(f, UnderbarRuleThickness), lvl); - DEFINE_DMATH_PARAMETERS(math_param_underbar_rule, size_id, - font_MATH_par(f, UnderbarRuleThickness), lvl); - DEFINE_MATH_PARAMETERS(math_param_underbar_vgap, size_id, - font_MATH_par(f, UnderbarVerticalGap), lvl); - DEFINE_DMATH_PARAMETERS(math_param_underbar_vgap, size_id, - font_MATH_par(f, UnderbarVerticalGap), lvl); - - DEFINE_MATH_PARAMETERS(math_param_under_delimiter_vgap, size_id, - font_MATH_par(f, StretchStackGapAboveMin), lvl); - DEFINE_DMATH_PARAMETERS(math_param_under_delimiter_vgap, size_id, - font_MATH_par(f, StretchStackGapAboveMin), lvl); - DEFINE_MATH_PARAMETERS(math_param_under_delimiter_bgap, size_id, - font_MATH_par(f, StretchStackBottomShiftDown), lvl); - DEFINE_DMATH_PARAMETERS(math_param_under_delimiter_bgap, size_id, - font_MATH_par(f, StretchStackBottomShiftDown), lvl); - - DEFINE_MATH_PARAMETERS(math_param_over_delimiter_vgap, size_id, - font_MATH_par(f, StretchStackGapBelowMin), lvl); - DEFINE_DMATH_PARAMETERS(math_param_over_delimiter_vgap, size_id, - font_MATH_par(f, StretchStackGapBelowMin), lvl); - DEFINE_MATH_PARAMETERS(math_param_over_delimiter_bgap, size_id, - font_MATH_par(f, StretchStackTopShiftUp), lvl); - DEFINE_DMATH_PARAMETERS(math_param_over_delimiter_bgap, size_id, - font_MATH_par(f, StretchStackTopShiftUp), lvl); - - DEFINE_MATH_PARAMETERS(math_param_stack_num_up, size_id, - font_MATH_par(f, StackTopShiftUp), lvl); - DEFINE_DMATH_PARAMETERS(math_param_stack_num_up, size_id, - font_MATH_par(f, StackTopDisplayStyleShiftUp), lvl); - DEFINE_MATH_PARAMETERS(math_param_stack_denom_down, size_id, - font_MATH_par(f, StackBottomShiftDown), lvl); - DEFINE_DMATH_PARAMETERS(math_param_stack_denom_down, size_id, - font_MATH_par(f, StackBottomDisplayStyleShiftDown), lvl); - DEFINE_MATH_PARAMETERS(math_param_stack_vgap, size_id, - font_MATH_par(f, StackGapMin), lvl); - DEFINE_DMATH_PARAMETERS(math_param_stack_vgap, size_id, - font_MATH_par(f, StackDisplayStyleGapMin), lvl); - - DEFINE_MATH_PARAMETERS(math_param_radical_kern, size_id, - font_MATH_par(f, RadicalExtraAscender), lvl); - DEFINE_DMATH_PARAMETERS(math_param_radical_kern, size_id, - font_MATH_par(f, RadicalExtraAscender), lvl); - - DEFINE_DMATH_PARAMETERS(math_param_operator_size, size_id, - font_MATH_par(f, DisplayOperatorMinHeight), lvl); - - DEFINE_MATH_PARAMETERS(math_param_radical_rule, size_id, - font_MATH_par(f, RadicalRuleThickness), lvl); - DEFINE_DMATH_PARAMETERS(math_param_radical_rule, size_id, - font_MATH_par(f, RadicalRuleThickness), lvl); - DEFINE_MATH_PARAMETERS(math_param_radical_vgap, size_id, - font_MATH_par(f, RadicalVerticalGap), lvl); - DEFINE_DMATH_PARAMETERS(math_param_radical_vgap, size_id, - font_MATH_par(f, RadicalDisplayStyleVerticalGap), lvl); - DEFINE_MATH_PARAMETERS(math_param_radical_degree_before, size_id, - font_MATH_par(f, RadicalKernBeforeDegree), lvl); - DEFINE_DMATH_PARAMETERS(math_param_radical_degree_before, size_id, - font_MATH_par(f, RadicalKernBeforeDegree), lvl); - DEFINE_MATH_PARAMETERS(math_param_radical_degree_after, size_id, - font_MATH_par(f, RadicalKernAfterDegree), lvl); - DEFINE_DMATH_PARAMETERS(math_param_radical_degree_after, size_id, - font_MATH_par(f, RadicalKernAfterDegree), lvl); - DEFINE_MATH_PARAMETERS(math_param_radical_degree_raise, size_id, - font_MATH_par(f, RadicalDegreeBottomRaisePercent), lvl); - DEFINE_DMATH_PARAMETERS(math_param_radical_degree_raise, size_id, - font_MATH_par(f, RadicalDegreeBottomRaisePercent), lvl); - - if (size_id == text_size) { - def_math_param(math_param_sup_shift_up, display_style, - font_MATH_par(f, SuperscriptShiftUp), lvl); - def_math_param(math_param_sup_shift_up, cramped_display_style, - font_MATH_par(f, SuperscriptShiftUpCramped), lvl); - def_math_param(math_param_sup_shift_up, text_style, - font_MATH_par(f, SuperscriptShiftUp), lvl); - def_math_param(math_param_sup_shift_up, cramped_text_style, - font_MATH_par(f, SuperscriptShiftUpCramped), lvl); - } else if (size_id == script_size) { - def_math_param(math_param_sup_shift_up, script_style, - font_MATH_par(f, SuperscriptShiftUp), lvl); - def_math_param(math_param_sup_shift_up, cramped_script_style, - font_MATH_par(f, SuperscriptShiftUpCramped), lvl); - } else if (size_id == script_script_size) { - def_math_param(math_param_sup_shift_up, script_script_style, - font_MATH_par(f, SuperscriptShiftUp), lvl); - def_math_param(math_param_sup_shift_up, cramped_script_script_style, - font_MATH_par(f, SuperscriptShiftUpCramped), lvl); - } - - DEFINE_MATH_PARAMETERS(math_param_sub_shift_drop, size_id, - font_MATH_par(f, SubscriptBaselineDropMin), lvl); - DEFINE_DMATH_PARAMETERS(math_param_sub_shift_drop, size_id, - font_MATH_par(f, SubscriptBaselineDropMin), lvl); - DEFINE_MATH_PARAMETERS(math_param_sup_shift_drop, size_id, - font_MATH_par(f, SuperscriptBaselineDropMax), lvl); - DEFINE_DMATH_PARAMETERS(math_param_sup_shift_drop, size_id, - font_MATH_par(f, SuperscriptBaselineDropMax), lvl); - DEFINE_MATH_PARAMETERS(math_param_sub_shift_down, size_id, - font_MATH_par(f, SubscriptShiftDown), lvl); - DEFINE_DMATH_PARAMETERS(math_param_sub_shift_down, size_id, - font_MATH_par(f, SubscriptShiftDown), lvl); - - if (font_MATH_par(f, SubscriptShiftDownWithSuperscript) != undefined_math_parameter) { - DEFINE_MATH_PARAMETERS(math_param_sub_sup_shift_down, size_id, - font_MATH_par(f, SubscriptShiftDownWithSuperscript), lvl); - DEFINE_DMATH_PARAMETERS(math_param_sub_sup_shift_down, size_id, - font_MATH_par(f, SubscriptShiftDownWithSuperscript), lvl); - } else { - DEFINE_MATH_PARAMETERS(math_param_sub_sup_shift_down, size_id, - font_MATH_par(f, SubscriptShiftDown), lvl); - DEFINE_DMATH_PARAMETERS(math_param_sub_sup_shift_down, size_id, - font_MATH_par(f, SubscriptShiftDown), lvl); - } - - DEFINE_MATH_PARAMETERS(math_param_sub_top_max, size_id, - font_MATH_par(f, SubscriptTopMax), lvl); - DEFINE_DMATH_PARAMETERS(math_param_sub_top_max, size_id, - font_MATH_par(f, SubscriptTopMax), lvl); - DEFINE_MATH_PARAMETERS(math_param_sup_bottom_min, size_id, - font_MATH_par(f, SuperscriptBottomMin), lvl); - DEFINE_DMATH_PARAMETERS(math_param_sup_bottom_min, size_id, - font_MATH_par(f, SuperscriptBottomMin), lvl); - DEFINE_MATH_PARAMETERS(math_param_sup_sub_bottom_max, size_id, - font_MATH_par(f, SuperscriptBottomMaxWithSubscript), lvl); - DEFINE_DMATH_PARAMETERS(math_param_sup_sub_bottom_max, size_id, - font_MATH_par(f, SuperscriptBottomMaxWithSubscript), lvl); - DEFINE_MATH_PARAMETERS(math_param_subsup_vgap, size_id, - font_MATH_par(f, SubSuperscriptGapMin), lvl); - DEFINE_DMATH_PARAMETERS(math_param_subsup_vgap, size_id, - font_MATH_par(f, SubSuperscriptGapMin), lvl); - - DEFINE_MATH_PARAMETERS(math_param_limit_above_vgap, size_id, - font_MATH_par(f, UpperLimitGapMin), lvl); - DEFINE_DMATH_PARAMETERS(math_param_limit_above_vgap, size_id, - font_MATH_par(f, UpperLimitGapMin), lvl); - DEFINE_MATH_PARAMETERS(math_param_limit_above_bgap, size_id, - font_MATH_par(f, UpperLimitBaselineRiseMin), lvl); - DEFINE_DMATH_PARAMETERS(math_param_limit_above_bgap, size_id, - font_MATH_par(f, UpperLimitBaselineRiseMin), lvl); - DEFINE_MATH_PARAMETERS(math_param_limit_above_kern, size_id, - 0, lvl); - DEFINE_DMATH_PARAMETERS(math_param_limit_above_kern, size_id, - 0, lvl); - DEFINE_MATH_PARAMETERS(math_param_limit_below_vgap, size_id, - font_MATH_par(f, LowerLimitGapMin), lvl); - DEFINE_DMATH_PARAMETERS(math_param_limit_below_vgap, size_id, - font_MATH_par(f, LowerLimitGapMin), lvl); - DEFINE_MATH_PARAMETERS(math_param_limit_below_bgap, size_id, - font_MATH_par(f, LowerLimitBaselineDropMin), lvl); - DEFINE_DMATH_PARAMETERS(math_param_limit_below_bgap, size_id, - font_MATH_par(f, LowerLimitBaselineDropMin), lvl); - DEFINE_MATH_PARAMETERS(math_param_limit_below_kern, size_id, - 0, lvl); - DEFINE_DMATH_PARAMETERS(math_param_limit_below_kern, size_id, - 0, lvl); - DEFINE_MATH_PARAMETERS(math_param_nolimit_sub_factor, size_id, - font_MATH_par(f, NoLimitSubFactor), lvl); /* bonus */ - DEFINE_DMATH_PARAMETERS(math_param_nolimit_sub_factor, size_id, - font_MATH_par(f, NoLimitSubFactor), lvl); /* bonus */ - DEFINE_MATH_PARAMETERS(math_param_nolimit_sup_factor, size_id, - font_MATH_par(f, NoLimitSupFactor), lvl); /* bonus */ - DEFINE_DMATH_PARAMETERS(math_param_nolimit_sup_factor, size_id, - font_MATH_par(f, NoLimitSupFactor), lvl); /* bonus */ - - DEFINE_MATH_PARAMETERS(math_param_fraction_rule, size_id, - font_MATH_par(f, FractionRuleThickness), lvl); - DEFINE_DMATH_PARAMETERS(math_param_fraction_rule, size_id, - font_MATH_par(f, FractionRuleThickness), lvl); - DEFINE_MATH_PARAMETERS(math_param_fraction_num_vgap, size_id, - font_MATH_par(f, FractionNumeratorGapMin), lvl); - DEFINE_DMATH_PARAMETERS(math_param_fraction_num_vgap, size_id, - font_MATH_par(f, FractionNumeratorDisplayStyleGapMin), lvl); - DEFINE_MATH_PARAMETERS(math_param_fraction_num_up, size_id, - font_MATH_par(f, FractionNumeratorShiftUp), lvl); - DEFINE_DMATH_PARAMETERS(math_param_fraction_num_up, size_id, - font_MATH_par(f, FractionNumeratorDisplayStyleShiftUp), lvl); - DEFINE_MATH_PARAMETERS(math_param_fraction_denom_vgap, size_id, - font_MATH_par(f, FractionDenominatorGapMin), lvl); - DEFINE_DMATH_PARAMETERS(math_param_fraction_denom_vgap, size_id, - font_MATH_par(f,FractionDenominatorDisplayStyleGapMin), lvl); - DEFINE_MATH_PARAMETERS(math_param_fraction_denom_down, size_id, - font_MATH_par(f, FractionDenominatorShiftDown), lvl); - DEFINE_DMATH_PARAMETERS(math_param_fraction_denom_down, size_id, - font_MATH_par(f, FractionDenominatorDisplayStyleShiftDown), lvl); - - DEFINE_MATH_PARAMETERS(math_param_fraction_del_size, size_id, - font_MATH_par(f, FractionDelimiterSize), lvl); - DEFINE_DMATH_PARAMETERS(math_param_fraction_del_size, size_id, - font_MATH_par(f, FractionDelimiterDisplayStyleSize), lvl); - - DEFINE_MATH_PARAMETERS(math_param_skewed_fraction_hgap, size_id, - font_MATH_par(f, SkewedFractionHorizontalGap), lvl); - DEFINE_DMATH_PARAMETERS(math_param_skewed_fraction_hgap, size_id, - font_MATH_par(f, SkewedFractionHorizontalGap), lvl); - DEFINE_MATH_PARAMETERS(math_param_skewed_fraction_vgap, size_id, - font_MATH_par(f, SkewedFractionVerticalGap), lvl); - DEFINE_DMATH_PARAMETERS(math_param_skewed_fraction_vgap, size_id, - font_MATH_par(f, SkewedFractionVerticalGap), lvl); - - DEFINE_MATH_PARAMETERS(math_param_space_after_script, size_id, - font_MATH_par(f, SpaceAfterScript), lvl); - DEFINE_DMATH_PARAMETERS(math_param_space_after_script, size_id, - font_MATH_par(f, SpaceAfterScript), lvl); - - DEFINE_MATH_PARAMETERS(math_param_connector_overlap_min, size_id, - font_MATH_par(f, MinConnectorOverlap), lvl); - DEFINE_DMATH_PARAMETERS(math_param_connector_overlap_min, size_id, - font_MATH_par(f, MinConnectorOverlap), lvl); - - } else if (fam_id == 2 && is_old_mathfont(f, total_mathsy_params)) { - - /*tex Fix old-style |sy| parameters. */ - - DEFINE_MATH_PARAMETERS(math_param_quad, size_id, - math_quad(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_quad, size_id, - math_quad(size_id), lvl); - DEFINE_MATH_PARAMETERS(math_param_axis, size_id, - axis_height(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_axis, size_id, - axis_height(size_id), lvl); - DEFINE_MATH_PARAMETERS(math_param_stack_num_up, size_id, - num3(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_stack_num_up, size_id, - num1(size_id), lvl); - DEFINE_MATH_PARAMETERS(math_param_stack_denom_down, size_id, - denom2(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_stack_denom_down, size_id, - denom1(size_id), lvl); - DEFINE_MATH_PARAMETERS(math_param_fraction_num_up, size_id, - num2(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_fraction_num_up, size_id, - num1(size_id), lvl); - DEFINE_MATH_PARAMETERS(math_param_fraction_denom_down, size_id, - denom2(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_fraction_denom_down, size_id, - denom1(size_id), lvl); - DEFINE_MATH_PARAMETERS(math_param_fraction_del_size, size_id, - delim2(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_fraction_del_size, size_id, - delim1(size_id), lvl); - - DEFINE_MATH_PARAMETERS(math_param_skewed_fraction_hgap, size_id, - 0, lvl); - DEFINE_DMATH_PARAMETERS(math_param_skewed_fraction_hgap, size_id, - 0, lvl); - DEFINE_MATH_PARAMETERS(math_param_skewed_fraction_vgap, size_id, - 0, lvl); - DEFINE_DMATH_PARAMETERS(math_param_skewed_fraction_vgap, size_id, - 0, lvl); - - if (size_id == text_size) { - def_math_param(math_param_sup_shift_up, display_style, - sup1(size_id), lvl); - def_math_param(math_param_sup_shift_up, cramped_display_style, - sup3(size_id), lvl); - def_math_param(math_param_sup_shift_up, text_style, - sup2(size_id), lvl); - def_math_param(math_param_sup_shift_up, cramped_text_style, - sup3(size_id), lvl); - } else if (size_id == script_size) { - def_math_param(math_param_sub_shift_drop, display_style, - sub_drop(size_id), lvl); - def_math_param(math_param_sub_shift_drop, cramped_display_style, - sub_drop(size_id), lvl); - def_math_param(math_param_sub_shift_drop, text_style, - sub_drop(size_id), lvl); - def_math_param(math_param_sub_shift_drop, cramped_text_style, - sub_drop(size_id), lvl); - def_math_param(math_param_sup_shift_drop, display_style, - sup_drop(size_id), lvl); - def_math_param(math_param_sup_shift_drop, cramped_display_style, - sup_drop(size_id), lvl); - def_math_param(math_param_sup_shift_drop, text_style, - sup_drop(size_id), lvl); - def_math_param(math_param_sup_shift_drop, cramped_text_style, - sup_drop(size_id), lvl); - def_math_param(math_param_sup_shift_up, script_style, - sup2(size_id), lvl); - def_math_param(math_param_sup_shift_up, cramped_script_style, - sup3(size_id), lvl); - } else if (size_id == script_script_size) { - def_math_param(math_param_sub_shift_drop, script_style, - sub_drop(size_id), lvl); - def_math_param(math_param_sub_shift_drop, cramped_script_style, - sub_drop(size_id), lvl); - def_math_param(math_param_sub_shift_drop, script_script_style, - sub_drop(size_id), lvl); - def_math_param(math_param_sub_shift_drop, - cramped_script_script_style, sub_drop(size_id), lvl); - def_math_param(math_param_sup_shift_drop, script_style, - sup_drop(size_id), lvl); - def_math_param(math_param_sup_shift_drop, cramped_script_style, - sup_drop(size_id), lvl); - def_math_param(math_param_sup_shift_drop, script_script_style, - sup_drop(size_id), lvl); - def_math_param(math_param_sup_shift_drop, - cramped_script_script_style, sup_drop(size_id), lvl); - def_math_param(math_param_sup_shift_up, script_script_style, - sup2(size_id), lvl); - def_math_param(math_param_sup_shift_up, cramped_script_script_style, - sup3(size_id), lvl); - } - - DEFINE_MATH_PARAMETERS(math_param_sub_shift_down, size_id, - sub1(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_sub_shift_down, size_id, - sub1(size_id), lvl); - DEFINE_MATH_PARAMETERS(math_param_sub_sup_shift_down, size_id, - sub2(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_sub_sup_shift_down, size_id, - sub2(size_id), lvl); - DEFINE_MATH_PARAMETERS(math_param_sub_top_max, size_id, - (abs(math_x_height(size_id) * 4) / 5), lvl); - DEFINE_DMATH_PARAMETERS(math_param_sub_top_max, size_id, - (abs(math_x_height(size_id) * 4) / 5), lvl); - DEFINE_MATH_PARAMETERS(math_param_sup_bottom_min, size_id, - (abs(math_x_height(size_id)) / 4), lvl); - DEFINE_DMATH_PARAMETERS(math_param_sup_bottom_min, size_id, - (abs(math_x_height(size_id)) / 4), lvl); - DEFINE_MATH_PARAMETERS(math_param_sup_sub_bottom_max, size_id, - (abs(math_x_height(size_id) * 4) / 5), lvl); - DEFINE_DMATH_PARAMETERS(math_param_sup_sub_bottom_max, size_id, - (abs(math_x_height(size_id) * 4) / 5), lvl); - - /*tex - - The display-size |radical_vgap| is done twice because it needs values - from both the sy and the ex font. - - */ - - DEFINE_DMATH_PARAMETERS(math_param_radical_vgap, size_id, - (default_rule_thickness(size_id) + (abs(math_x_height(size_id)) / 4)), lvl); - DEFINE_MATH_PARAMETERS(math_param_radical_degree_raise, size_id, - 60, lvl); - DEFINE_DMATH_PARAMETERS(math_param_radical_degree_raise, size_id, - 60, lvl); - DEFINE_MATH_PARAMETERS(math_param_radical_degree_before, size_id, - xn_over_d(get_math_quad_size(size_id), 5, 18), lvl); - DEFINE_DMATH_PARAMETERS(math_param_radical_degree_before, size_id, - xn_over_d(get_math_quad_size(size_id), 5, 18), lvl); - DEFINE_MATH_PARAMETERS(math_param_radical_degree_after, size_id, - (-xn_over_d (get_math_quad_size(size_id), 10, 18)), lvl); - DEFINE_DMATH_PARAMETERS(math_param_radical_degree_after, size_id, - (-xn_over_d (get_math_quad_size(size_id), 10, 18)), lvl); - - } else if (fam_id == 3 && is_old_mathfont(f, total_mathex_params)) { - - /*tex Fix old-style |ex| parameters. */ - - DEFINE_MATH_PARAMETERS(math_param_overbar_kern, size_id, - default_rule_thickness(size_id), lvl); - DEFINE_MATH_PARAMETERS(math_param_overbar_rule, size_id, - default_rule_thickness(size_id), lvl); - DEFINE_MATH_PARAMETERS(math_param_overbar_vgap, size_id, - 3 * default_rule_thickness(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_overbar_kern, size_id, - default_rule_thickness(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_overbar_rule, size_id, - default_rule_thickness(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_overbar_vgap, size_id, - 3 * default_rule_thickness(size_id), lvl); - DEFINE_MATH_PARAMETERS(math_param_underbar_kern, size_id, - default_rule_thickness(size_id), lvl); - DEFINE_MATH_PARAMETERS(math_param_underbar_rule, size_id, - default_rule_thickness(size_id), lvl); - DEFINE_MATH_PARAMETERS(math_param_underbar_vgap, size_id, - 3 * default_rule_thickness(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_underbar_kern, size_id, - default_rule_thickness(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_underbar_rule, size_id, - default_rule_thickness(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_underbar_vgap, size_id, - 3 * default_rule_thickness(size_id), lvl); - DEFINE_MATH_PARAMETERS(math_param_radical_kern, size_id, - default_rule_thickness(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_radical_kern, size_id, - default_rule_thickness(size_id), lvl); - DEFINE_MATH_PARAMETERS(math_param_radical_vgap, size_id, - (default_rule_thickness(size_id) + (abs(default_rule_thickness(size_id)) / 4)), lvl); - DEFINE_MATH_PARAMETERS(math_param_stack_vgap, size_id, - 3 * default_rule_thickness(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_stack_vgap, size_id, - 7 * default_rule_thickness(size_id), lvl); - DEFINE_MATH_PARAMETERS(math_param_fraction_rule, size_id, - default_rule_thickness(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_fraction_rule, size_id, - default_rule_thickness(size_id), lvl); - DEFINE_MATH_PARAMETERS(math_param_fraction_num_vgap, size_id, - default_rule_thickness(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_fraction_num_vgap, size_id, - 3 * default_rule_thickness(size_id), lvl); - DEFINE_MATH_PARAMETERS(math_param_fraction_denom_vgap, size_id, - default_rule_thickness(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_fraction_denom_vgap, size_id, - 3 * default_rule_thickness(size_id), lvl); - DEFINE_MATH_PARAMETERS(math_param_limit_above_vgap, size_id, - big_op_spacing1(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_limit_above_vgap, size_id, - big_op_spacing1(size_id), lvl); - DEFINE_MATH_PARAMETERS(math_param_limit_above_bgap, size_id, - big_op_spacing3(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_limit_above_bgap, size_id, - big_op_spacing3(size_id), lvl); - DEFINE_MATH_PARAMETERS(math_param_limit_above_kern, size_id, - big_op_spacing5(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_limit_above_kern, size_id, - big_op_spacing5(size_id), lvl); - DEFINE_MATH_PARAMETERS(math_param_limit_below_vgap, size_id, - big_op_spacing2(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_limit_below_vgap, size_id, - big_op_spacing2(size_id), lvl); - DEFINE_MATH_PARAMETERS(math_param_limit_below_bgap, size_id, - big_op_spacing4(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_limit_below_bgap, size_id, - big_op_spacing4(size_id), lvl); - DEFINE_MATH_PARAMETERS(math_param_limit_below_kern, size_id, - big_op_spacing5(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_limit_below_kern, size_id, - big_op_spacing5(size_id), lvl); - DEFINE_MATH_PARAMETERS(math_param_nolimit_sub_factor, size_id, - font_MATH_par(f, NoLimitSubFactor), lvl); /* bonus */ - DEFINE_DMATH_PARAMETERS(math_param_nolimit_sub_factor, size_id, - font_MATH_par(f, NoLimitSubFactor), lvl); /* bonus */ - DEFINE_MATH_PARAMETERS(math_param_nolimit_sup_factor, size_id, - font_MATH_par(f, NoLimitSupFactor), lvl); /* bonus */ - DEFINE_DMATH_PARAMETERS(math_param_nolimit_sup_factor, size_id, - font_MATH_par(f, NoLimitSupFactor), lvl); /* bonus */ - DEFINE_MATH_PARAMETERS(math_param_subsup_vgap, size_id, - 4 * default_rule_thickness(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_subsup_vgap, size_id, - 4 * default_rule_thickness(size_id), lvl); - - /*tex - - All of the |space_after_script|s are done in - |finalize_math_parameters| because the \.{\\scriptspace} may have - been altered by the user. - - */ - - DEFINE_MATH_PARAMETERS(math_param_connector_overlap_min, size_id, - 0, lvl); - DEFINE_DMATH_PARAMETERS(math_param_connector_overlap_min, size_id, - 0, lvl); - - DEFINE_MATH_PARAMETERS(math_param_under_delimiter_vgap, size_id, - big_op_spacing2(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_under_delimiter_vgap, size_id, - big_op_spacing2(size_id), lvl); - DEFINE_MATH_PARAMETERS(math_param_under_delimiter_bgap, size_id, - big_op_spacing4(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_under_delimiter_bgap, size_id, - big_op_spacing4(size_id), lvl); - DEFINE_MATH_PARAMETERS(math_param_over_delimiter_vgap, size_id, - big_op_spacing1(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_over_delimiter_vgap, size_id, - big_op_spacing1(size_id), lvl); - DEFINE_MATH_PARAMETERS(math_param_over_delimiter_bgap, size_id, - big_op_spacing3(size_id), lvl); - DEFINE_DMATH_PARAMETERS(math_param_over_delimiter_bgap, size_id, - big_op_spacing3(size_id), lvl); - - /*tex - - The display-size |radical_vgap| is done twice because it needs values - from both the sy and the ex font. - - */ - - DEFINE_DMATH_PARAMETERS(math_param_radical_vgap, size_id, - (default_rule_thickness(size_id) + (abs(math_x_height(size_id)) / 4)), lvl); - - } -} - -/*tex - - This needs to be called just at the start of |mlist_to_hlist|, for backward - compatibility with \.{\\scriptspace}. - -*/ - -static void finalize_math_parameters(void) -{ - int saved_trace = tracing_assigns_par; - tracing_assigns_par = 0; - if (get_math_param(math_param_space_after_script, display_style) == undefined_math_parameter) { - def_math_param(math_param_space_after_script, display_style, - script_space_par, level_one); - def_math_param(math_param_space_after_script, text_style, - script_space_par, level_one); - def_math_param(math_param_space_after_script, script_style, - script_space_par, level_one); - def_math_param(math_param_space_after_script, script_script_style, - script_space_par, level_one); - def_math_param(math_param_space_after_script, cramped_display_style, - script_space_par, level_one); - def_math_param(math_param_space_after_script, cramped_text_style, - script_space_par, level_one); - def_math_param(math_param_space_after_script, cramped_script_style, - script_space_par, level_one); - def_math_param(math_param_space_after_script, cramped_script_script_style, - script_space_par, level_one); - } - tracing_assigns_par = saved_trace; -} - -/*tex - - In order to convert mlists to hlists, i.e., noads to nodes, we need several - subroutines that are conveniently dealt with now. - - Let us first introduce the macros that make it easy to get at the parameters - and other font information. A size code, which is a multiple of 256, is added - to a family number to get an index into the table of internal font numbers - for each combination of family and size. (Be alert: Size codes get larger as - the type gets smaller.) - -*/ - -static const char *math_size_string(int s) -{ - if (s == text_size) - return "textfont"; - else if (s == script_size) - return "scriptfont"; - else - return "scriptscriptfont"; -} - -/*tex - - When the style changes, the following piece of program computes associated - information: - -*/ - -#define setup_cur_size(a) do { \ - if (a==script_style || a==cramped_script_style) \ - cur_size = script_size; \ - else if (a==script_script_style || a==cramped_script_script_style) \ - cur_size = script_script_size; \ - else \ - cur_size = text_size; \ -} while (0) - - -/*tex - - A simple routine that creates a flat copy of a nucleus. - -*/ - -static pointer math_clone(pointer q) -{ - pointer x; - if (q == null) - return null; - x = new_node(type(q), 0); - reset_attributes(x, node_attr(q)); - if (type(q) == math_char_node) { - math_fam(x) = math_fam(q); - math_character(x) = math_character(q); - } else { - math_list(x) = math_list(q); - } - return x; -} - -/*tex - - Here is a function that returns a pointer to a rule node having a given - thickness |t|. The rule will extend horizontally to the boundary of the vlist - that eventually contains it. - -*/ - -static pointer do_fraction_rule(scaled t, pointer att, halfword some_rule, halfword cur_size, halfword cur_fam) -{ - pointer p; - if (math_rules_mode_par) { - p = new_rule(some_rule); - rule_math_size(p) = cur_size; - rule_math_font(p) = fam_fnt(cur_fam, cur_size); - } else { - p = new_rule(normal_rule); - } - rule_dir(p) = math_direction_par; - height(p) = t; - depth(p) = 0; - reset_attributes(p, att); - return p; -} - -/*tex - - The |overbar| function returns a pointer to a vlist box that consists of a - given box |b|, above which has been placed a kern of height |k| under a - fraction rule of thickness |t| under additional space of height |ht|. - -*/ - -static pointer overbar(pointer b, scaled k, scaled t, scaled ht, pointer att, halfword index, halfword cur_size, halfword cur_fam) -{ - pointer p, q; - p = new_kern(k); - reset_attributes(p, att); - couple_nodes(p,b); - q = do_fraction_rule(t, att, index, cur_size, cur_fam); - couple_nodes(q,p); - p = new_kern(ht); - reset_attributes(p, att); - couple_nodes(p,q); - q = vpackage(p, 0, additional, max_dimen, math_direction_par); - reset_attributes(q, att); - return q; -} - -/*tex - - Here is a subroutine that creates a new box, whose list contains a single - character, and whose width includes the italic correction for that character. - The height or depth of the box will be negative, if the height or depth of - the character is negative; thus, this routine may deliver a slightly - different result than |hpack| would produce. - -*/ - -static pointer char_box(internal_font_number f, int c, pointer bb) -{ - /*tex The new box and its character node. */ - pointer b, p; - b = new_null_box(); - if (do_new_math(f)) - width(b) = char_width(f, c); - else - width(b) = char_width(f, c) + char_italic(f, c); - height(b) = char_height(f, c); - depth(b) = char_depth(f, c); - subtype(b) = math_char_list ; - reset_attributes(b, bb); - p = new_glyph(f, c); - protect_glyph(p); - reset_attributes(p, bb); - list_ptr(b) = p; - return b; -} - -/*tex - - Another handy subroutine computes the height plus depth of a given character: - -*/ - -static scaled height_plus_depth(internal_font_number f, int c) -{ - return (char_height(f, c) + char_depth(f, c)); -} - -/*tex - - When we build an extensible character, it's handy to have the following - subroutine, which puts a given character on top of the characters already in - box |b|: - -*/ - -static scaled stack_into_box(pointer b, internal_font_number f, int c) -{ - /*tex New node placed into |b|: */ - pointer p, q; - /*tex Italic gets added to width. */ - p = char_box(f, c, node_attr(b)); - if (type(b) == vlist_node) { - try_couple_nodes(p,list_ptr(b)); - list_ptr(b) = p; - height(b) = height(p); - if (width(b) < width(p)) - width(b) = width(p); - return height_plus_depth(f, c); - } else { - q = list_ptr(b); - if (q == null) { - list_ptr(b) = p; - } else { - while (vlink(q) != null) - q = vlink(q); - couple_nodes(q,p); - } - if (height(b) < height(p)) - height(b) = height(p); - if (depth(b) < depth(p)) - depth(b) = depth(p); - return char_width(f, c); - } -} - -static void stack_glue_into_box(pointer b, scaled min, scaled max) { - halfword p = new_glue(zero_glue); - width(p) = min; - stretch(p) = max - min; - if (node_attr(b) != null) { - reset_attributes(p, node_attr(b)); - } - if (type(b) == vlist_node) { - try_couple_nodes(p,list_ptr(b)); - list_ptr(b) = p; - } else { - halfword q = list_ptr(b); - if (q == null) { - list_ptr(b) = p; - } else { - while (vlink(q) != null) { - q = vlink(q); - } - couple_nodes(q,p); - } - } -} - -/*tex - - \TeX's most important routine for dealing with formulas is called - |mlist_to_hlist|. After a formula has been scanned and represented as an - mlist, this routine converts it to an hlist that can be placed into a box or - incorporated into the text of a paragraph. The explicit parameter |cur_mlist| - points to the first node or noad in the given mlist (and it might be |null|); - the parameter |penalties| is |true| if penalty nodes for potential line - breaks are to be inserted into the resulting hlist, the parameter |cur_style| - is a style code. After |mlist_to_hlist| has acted, |vlink(temp_head)| points - to the translated hlist. - - Since mlists can be inside mlists, the procedure is recursive. And since this - is not part of \TeX's inner loop, the program has been written in a manner - that stresses compactness over efficiency. - -*/ - -/*tex Size code corresponding to |cur_style|: */ - -int cur_size = 0; - -static pointer get_delim_box(internal_font_number fnt, halfword chr, scaled v, scaled min_overlap, int horizontal, halfword att) -{ - int callback_id = callback_defined(make_extensible_callback); - if (callback_id > 0) { - /*tex - This call is not optimized as it hardly makes sense to use it ... special - and a it of feature creep too. - */ - halfword b = null; - run_callback(callback_id, "ddddbN->N",fnt,chr,v,min_overlap,horizontal,att,&b); - if (b == null) { - /*tex - We see this as a signal to do it the \TEX\ way. - */ - } else if (type(b) == hlist_node || type(b) == vlist_node) { - return b; - } else { - formatted_error("fonts","invalid extensible character %i created for font %i, [h|v]list expected",chr,fnt); - } - } - return make_extensible(fnt, chr, v, min_overlap, horizontal, att); -} - -pointer make_extensible(internal_font_number fnt, halfword chr, scaled v, scaled min_overlap, int horizontal, halfword att) -{ - /*tex new box */ - pointer b; - /*tex natural (maximum) size of the stack */ - scaled b_max; - /*tex amount of possible shrink in the stack */ - scaled s_max; - extinfo *cur; - extinfo *ext; - scaled prev_overlap; - /*tex a temporary counter number of extensible pieces */ - int i; - /*tex number of times to repeat each repeatable item in |ext| */ - int with_extenders; - int num_extenders, num_normal; - scaled a, c, d; - b = new_null_box(); - with_extenders = -1; - num_extenders = 0; - num_normal = 0; - if (min_overlap < 0) { - min_overlap = 0; - } - if (horizontal) { - type(b) = (quarterword) hlist_node; - ext = get_charinfo_hor_variants(char_info(fnt,chr)); - } else { - type(b) = (quarterword) vlist_node; - ext = get_charinfo_vert_variants(char_info(fnt,chr)); - } - if (att != null) { - reset_attributes(b,att); - } - cur = ext; - while (cur != NULL) { - if (!char_exists(fnt, cur->glyph)) { - const char *hlp[] = { - "Each glyph part in an extensible item should exist in the font.", - "I will give up trying to find a suitable size for now. Fix your font!", - NULL - }; - tex_error("Variant part doesn't exist.", hlp); - width(b) = null_delimiter_space_par; - return b; - } - if (cur->extender > 0) - num_extenders++; - else - num_normal++; - /*tex No negative overlaps or advances are allowed. */ - if (cur->start_overlap < 0 || cur->end_overlap < 0 || cur->advance < 0) { - const char *hlp[] = { - "All measurements in extensible items should be positive.", - "To get around this problem, I have changed the font metrics.", - "Fix your font!", - NULL - }; - tex_error("Extensible recipe has negative fields.", hlp); - if (cur->start_overlap < 0) - cur->start_overlap = 0; - if (cur->end_overlap < 0) - cur->end_overlap = 0; - if (cur->advance < 0) - cur->advance = 0; - } - cur = cur->next; - } - if (num_normal == 0) { - const char *hlp[] = { - "Each extensible recipe should have at least one non-repeatable part.", - "To get around this problem, I have changed the first part to be", - "non-repeatable. Fix your font!", - NULL - }; - tex_error("Extensible recipe has no fixed parts.", hlp); - ext->extender = 0; - num_normal = 1; - num_extenders--; - } - /*tex - - |ext| holds a linked list of numerous items that may or may not be - repeatable. For the total height, we have to figure out how many items - are needed to create a stack of at least |v|. - - The next |while| loop does that. It has two goals: it finds out the - natural height |b_max| of the all the parts needed to reach at least |v|, - and it sets |with_extenders| to the number of times each of the - repeatable items in |ext| has to be repeated to reach that height. - - */ - cur = ext; - b_max = 0; - while (b_max < v && num_extenders > 0) { - b_max = 0; - prev_overlap = 0; - with_extenders++; - for (cur = ext; cur != NULL; cur = cur->next) { - if (cur->extender == 0) { - c = cur->start_overlap; - if (min_overlap < c) - c = min_overlap; - if (prev_overlap < c) - c = prev_overlap; - a = cur->advance; - if (a == 0) { - /*tex for tfm fonts */ - if (horizontal) { - a = char_width(fnt, cur->glyph); - } else { - a = height_plus_depth(fnt, cur->glyph); - } - if (a < 0) { - formatted_error("fonts","bad extensible character %i in font %i",chr,fnt); - } - } - b_max += a - c; - prev_overlap = cur->end_overlap; - } else { - i = with_extenders; - while (i > 0) { - c = cur->start_overlap; - if (min_overlap < c) - c = min_overlap; - if (prev_overlap < c) - c = prev_overlap; - a = cur->advance; - if (a == 0) { - /*tex for tfm fonts */ - if (horizontal) { - a = char_width(fnt, cur->glyph); - } else { - a = height_plus_depth(fnt, cur->glyph); - } - if (a < 0) { - formatted_error("fonts","bad extensible character %i in font %i",chr,fnt); - } - } - b_max += a - c; - prev_overlap = cur->end_overlap; - i--; - } - } - } - } - /*tex - - Assemble box using |with_extenders| copies of each extender, with - appropriate glue wherever an overlap occurs. - - */ - prev_overlap = 0; - b_max = 0; - s_max = 0; - for (cur = ext; cur != NULL; cur = cur->next) { - if (cur->extender == 0) { - c = cur->start_overlap; - if (prev_overlap < c) - c = prev_overlap; - d = c; - if (min_overlap < c) - c = min_overlap; - if (d > 0) { - stack_glue_into_box(b, -d, -c); - s_max += (-c) - (-d); - b_max -= d; - } - b_max += stack_into_box(b, fnt, cur->glyph); - prev_overlap = cur->end_overlap; - i--; - } else { - i = with_extenders; - while (i > 0) { - c = cur->start_overlap; - if (prev_overlap < c) - c = prev_overlap; - d = c; - if (min_overlap < c) - c = min_overlap; - if (d > 0) { - stack_glue_into_box(b, -d, -c); - s_max += (-c) - (-d); - b_max -= d; - } - b_max += stack_into_box(b, fnt, cur->glyph); - prev_overlap = cur->end_overlap; - i--; - } - } - } - /*tex Set glue so as to stretch the connections if needed. */ - d = 0; - if (v > b_max && s_max > 0) { - d = v-b_max; - /*tex Don't stretch more than |s_max|. */ - if (d > s_max) - d = s_max; - glue_order(b) = normal; - glue_sign(b) = stretching; - glue_set(b) = unfloat(d/(float) s_max); - b_max += d; - } - if (horizontal) { - width(b) = b_max; - subtype(b) = math_h_extensible_list; - } else { - height(b) = b_max; - subtype(b) = math_v_extensible_list; - } - return b; -} - -/*tex - - The |var_delimiter| function, which finds or constructs a sufficiently large - delimiter, is the most interesting of the auxiliary functions that currently - concern us. Given a pointer |d| to a delimiter field in some noad, together - with a size code |s| and a vertical distance |v|, this function returns a - pointer to a box that contains the smallest variant of |d| whose height plus - depth is |v| or more. (And if no variant is large enough, it returns the - largest available variant.) In particular, this routine will construct - arbitrarily large delimiters from extensible components, if |d| leads to such - characters. - - The value returned is a box whose |shift_amount| has been set so that the box - is vertically centered with respect to the axis in the given size. If a - built-up symbol is returned, the height of the box before shifting will be - the height of its topmost component. - -*/ - -static void endless_loop_error(internal_font_number g, int y) -{ - char s[256]; - const char *hlp[] = { - "You managed to create a seemingly endless charlist chain in the current", - "font. I have counted until 10000 already and still have not escaped, so" - "I will jump out of the loop all by myself now. Fix your font!", - NULL - }; - snprintf(s, 256, "Math error: endless loop in charlist (U+%04x in %s)", (int) y, font_name(g)); - tex_error(s, hlp); -} - -static pointer do_delimiter(pointer q, pointer d, int s, scaled v, boolean flat, int cur_style, boolean shift, boolean *stack, scaled *delta, int *same) -{ - /*tex the box that will be constructed */ - pointer b; - /*tex best-so-far and tentative font codes */ - internal_font_number f, g; - /*tex best-so-far and tentative character codes */ - int c, i, x, y; - /*tex height-plus-depth of a tentative character */ - scaled u; - /*tex largest height-plus-depth so far */ - scaled w = 0; - /*tex runs through font family members */ - int z; - /*tex are we trying the ``large'' variant? */ - boolean large_attempt = false; - /*tex to save the current attribute list */ - pointer att = null; - int emas = 0 ; - boolean do_parts = false; - boolean parts_done = false; - extinfo *ext; - - if (d && ! small_fam(d) && ! large_fam(d) && ! small_char(d) && ! large_char(d)) { - halfword b = new_null_box(); - subtype(b) = math_v_delimiter_list; - if (! flat) - width(b) = null_delimiter_space_par; - node_attr(b) = node_attr(d); - node_attr(d) = null; - flush_node(d); - return b; - } - - f = null_font; - c = 0; - if (d == null) { - goto FOUND; - } - z = small_fam(d); - x = small_char(d); - i = 0; - if (same != NULL) { - emas = *same ; - same = 0; - } - while (true) { - /*tex - - The search process is complicated slightly by the facts that some of - the characters might not be present in some of the fonts, and they - might not be probed in increasing order of height. - - */ - if ((z != 0) || (x != 0)) { - g = fam_fnt(z, s); - if (g != null_font) { - y = x; - CONTINUE: - i++; - if (char_exists(g, y)) { - if (flat) - u = char_width(g, y); - else - u = height_plus_depth(g, y); - if (u > w) { - f = g; - c = y; - w = u; - if (u >= v) - goto FOUND; - } - if (char_tag(g, y) == ext_tag) { - f = g; - c = y; - do_parts = true; - goto FOUND; - } - if (i > 10000) { - endless_loop_error(g, y); - goto FOUND; - } - if (char_tag(g, y) == list_tag) { - y = char_remainder(g, y); - goto CONTINUE; - } - } - } - } - if (large_attempt) { - /*tex There were none large enough. */ - goto FOUND; - } - large_attempt = true; - z = large_fam(d); - x = large_char(d); - } - FOUND: - if (d != null) { - att = node_attr(d); - node_attr(d) = null; - flush_node(d); - } - if (f != null_font) { - /*tex - - When the following code is executed, |do_parts| will be true if a - built-up symbol is supposed to be returned. - - */ - ext = NULL; - if ((do_parts) && ((!flat && (ext = get_charinfo_vert_variants(char_info(f,c))) != NULL) - || ( flat && (ext = get_charinfo_hor_variants (char_info(f,c))) != NULL))) { - parts_done = true; - if (flat) { - b = get_delim_box(f, c, v, connector_overlap_min(cur_style), 1, att); - } else { - b = get_delim_box(f, c, v, connector_overlap_min(cur_style), 0, att); - } - if (delta != NULL) { - if (do_new_math(f)) { - *delta = char_vert_italic(f,x); - } else { - *delta = char_italic(f,x); - } - } - if (stack != NULL) - *stack = true ; - } else { - parts_done = false; - if (same != NULL && x == c) { - *same = emas; - } - /*tex - Here italic is added to width in traditional fonts which makes the delimiter get - the real width. An \OPENTYPE\ font already has the right width. - */ - b = char_box(f, c, att); - /*tex - There is one case where |delta| (ic) gets subtracted but only for a traditional - font. In that case the traditional width (which is fake width + italic) becomes - less and the delta is added. See (**). (On the mailing list font |ntxexx| was - mentioned as test case by MK.) - */ - if (delta != NULL) { - *delta = char_italic(f, c); - } - if (stack != NULL) - *stack = false ; - } - } else { - b = new_null_box(); - reset_attributes(b, att); - if (flat) { - width(b) = 0; - subtype(b) = math_h_delimiter_list; - } else { - /*tex Use this width if no delimiter was found. */ - width(b) = null_delimiter_space_par; - subtype(b) = math_v_delimiter_list; - } - if (delta != NULL) { - *delta = 0; - } - if (stack != NULL) - *stack = false ; - } - if (!flat) { - /*tex when emas ~= 0 then we have a non scaled character */ - if (emas != 0 && delimitermodesamenos) { - /*tex same character and no shift when same forced */ - goto DONE; - } - if (! parts_done && delimitermodecharnos) { - /*tex same character and no shift when same forced */ - goto DONE; - } - if (delimitermodenoshift) { - /*tex no shift forced */ - goto DONE; - } - /*tex vertical variant */ - shift_amount(b) = half(height(b) - depth(b)); - if (shift) { - shift_amount(b) -= math_axis_size(s); - } - } - DONE: - delete_attribute_ref(att); - return b; -} - -/*tex - - The next subroutine is much simpler; it is used for numerators and - denominators of fractions as well as for displayed operators and their limits - above and below. It takes a given box~|b| and changes it so that the new box - is centered in a box of width~|w|. The centering is done by putting \.{\\hss} - glue at the left and right of the list inside |b|, then packaging the new - box; thus, the actual box might not really be centered, if it already - contains infinite glue. - - The given box might contain a single character whose italic correction has - been added to the width of the box; in this case a compensating kern is - inserted. - -*/ - -static pointer rebox(pointer b, scaled w) -{ - /*tex temporary registers for list manipulation */ - pointer p, q, r, att; - /*tex font in a one-character box */ - internal_font_number f; - /*tex width of a character without italic correction */ - scaled v; - if ((width(b) != w) && (list_ptr(b) != null)) { - if (type(b) == vlist_node) { - p = hpack(b, 0, additional, -1); - reset_attributes(p, node_attr(b)); - b = p; - } - p = list_ptr(b); - att = node_attr(b); - add_node_attr_ref(att); - if ((is_char_node(p)) && (vlink(p) == null)) { - f = font(p); - v = char_width(f, character(p)); - if (v != width(b)) { - q = new_kern(width(b) - v); - reset_attributes(q, att); - couple_nodes(p,q); - } - } - list_ptr(b) = null; - flush_node(b); - b = new_glue(ss_glue); - reset_attributes(b, att); - couple_nodes(b,p); - while (vlink(p) != null) - p = vlink(p); - q = new_glue(ss_glue); - reset_attributes(q, att); - couple_nodes(p,q); - r = hpack(b, w, exactly, -1); - reset_attributes(r, att); - delete_attribute_ref(att); - return r; - } else { - width(b) = w; - return b; - } -} - -/*tex - - Here is a subroutine that creates a new glue specification from another one - that is expressed in `\.{mu}', given the value of the math unit. - -*/ - -#define mu_mult(A) mult_and_add(n,(A),xn_over_d((A),f,unity),max_dimen) - -static pointer math_glue(pointer g, scaled m) -{ - /*tex integer part of |m| */ - int n = x_over_n(m, unity); - /*tex fraction part of |m| */ - scaled f = tex_remainder; - /*tex the new glue specification */ - pointer p; - if (f < 0) { - decr(n); - f = f + unity; - } - p = new_node(glue_node, 0); - /* convert \.{mu} to \.{pt} */ - width(p) = mu_mult(width(g)); - stretch_order(p) = stretch_order(g); - if (stretch_order(p) == normal) - stretch(p) = mu_mult(stretch(g)); - else - stretch(p) = stretch(g); - shrink_order(p) = shrink_order(g); - if (shrink_order(p) == normal) - shrink(p) = mu_mult(shrink(g)); - else - shrink(p) = shrink(g); - return p; -} - -static void math_glue_to_glue(pointer p, scaled m) -{ - /*tex integer part of |m| */ - int n = x_over_n(m, unity); - /*tex fraction part of |m| */ - scaled f = tex_remainder; - if (f < 0) { - decr(n); - f = f + unity; - } - /* convert \.{mu} to \.{pt} */ - width(p) = mu_mult(width(p)); - if (stretch_order(p) == normal) - stretch(p) = mu_mult(stretch(p)); - if (shrink_order(p) == normal) - shrink(p) = mu_mult(shrink(p)); - subtype(p) = normal; -} - -/*tex - - The |math_kern| subroutine removes |mu_glue| from a kern node, given the - value of the math unit. - -*/ -static void math_kern(pointer p, scaled m) -{ - /*tex integer part of |m| */ - int n; - /*tex fraction part of |m| */ - scaled f; - if (subtype(p) == mu_glue) { - n = x_over_n(m, unity); - f = tex_remainder; - if (f < 0) { - decr(n); - f = f + unity; - } - width(p) = mu_mult(width(p)); - /* this is weird, it's not a italic but explicit_kern */ - subtype(p) = italic_kern; - } -} - -void run_mlist_to_hlist(halfword p, boolean penalties, int mstyle) -{ - int callback_id; - int a, sfix, i; - if (p == null) { - vlink(temp_head) = null; - return; - } - finalize_math_parameters(); - callback_id = callback_defined(mlist_to_hlist_callback); - if (callback_id > 0) { - sfix = lua_gettop(Luas); - if (!get_callback(Luas, callback_id)) { - lua_settop(Luas, sfix); - return; - } - alink(p) = null ; - nodelist_to_lua(Luas, p); - lua_push_math_style_name(Luas, mstyle); - lua_pushboolean(Luas, penalties); - if ((i=lua_pcall(Luas, 3, 1, 0)) != 0) { - formatted_warning("mlist to hlist","error: %s",lua_tostring(Luas, -1)); - lua_settop(Luas, sfix); - luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1)); - return; - } - a = nodelist_from_lua(Luas,-1); - /* alink(vlink(a)) = null; */ - vlink(temp_head) = a; - lua_settop(Luas, sfix); - } else if (callback_id == 0) { - mlist_to_hlist(p, penalties, mstyle); - } else { - vlink(temp_head) = null; - } -} - -/*tex - - The recursion in |mlist_to_hlist| is due primarily to a subroutine called - |clean_box| that puts a given noad field into a box using a given math style; - |mlist_to_hlist| can call |clean_box|, which can call |mlist_to_hlist|. - - The box returned by |clean_box| is ``clean'' in the sense that its - |shift_amount| is zero. - -*/ - -static pointer clean_box(pointer p, int s, int cur_style, halfword st) -{ - /*tex beginning of a list to be boxed */ - pointer q; - /*tex box to be returned */ - pointer x; - /*tex temporary pointer */ - pointer r; - /*tex beginning of mlist to be translated */ - pointer mlist = null; - switch (type(p)) { - case math_char_node: - mlist = new_noad(); - r = math_clone(p); - nucleus(mlist) = r; - break; - case sub_box_node: - q = math_list(p); - goto FOUND; - break; - case sub_mlist_node: - mlist = math_list(p); - break; - default: - q = new_null_box(); - subtype(q) = math_list_list; - goto FOUND; - } - mlist_to_hlist(mlist, false, s); - /*tex recursive call */ - q = vlink(temp_head); - setup_cur_size(cur_style); - FOUND: - if (is_char_node(q) || (q == null)) - x = hpack(q, 0, additional, -1); - else if ((vlink(q) == null) && (type(q) <= vlist_node) && (shift_amount(q) == 0)) - /*tex It's already clean. */ - x = q; - else - x = hpack(q, 0, additional, -1); - if (x != q && q != null) - reset_attributes(x, node_attr(q)); - subtype(x) = st; - /*tex Here we save memory space in a common case. */ - q = list_ptr(x); - if (is_char_node(q)) { - r = vlink(q); - if (r != null) { - if (vlink(r) == null) { - if (!is_char_node(r)) { - if (type(r) == kern_node) { - /*tex Unneeded italic correction. */ - flush_node(r); - vlink(q) = null; - } - } - } - } - } - return x; -} - -/*tex - - It is convenient to have a procedure that converts a |math_char| field to an - ``unpacked'' form. The |fetch| routine sets |cur_f| and |cur_c| to the font - code and character code of a given noad field. It also takes care of issuing - error messages for nonexistent characters; in such cases, - |char_exists(cur_f,cur_c)| will be |false| after |fetch| has acted, and the - field will also have been reset to |null|. - - The outputs of |fetch| are placed in global variables. - -*/ - -/*tex the |font| field of a |math_char| */ - -internal_font_number cur_f; - -/*tex the |character| field of a |math_char| */ - -int cur_c; - -/*tex Here we unpack the |math_char| field |a|. */ - -static void fetch(pointer a) -{ - cur_c = math_character(a); - cur_f = fam_fnt(math_fam(a), cur_size); - if (cur_f == null_font) { - char *msg; - const char *hlp[] = { - "Somewhere in the math formula just ended, you used the", - "stated character from an undefined font family. For example,", - "plain TeX doesn't allow \\it or \\sl in subscripts. Proceed,", - "and I'll try to forget that I needed that character.", - NULL - }; - msg = xmalloc(256); - snprintf(msg, 255, "\\%s%d is undefined (character %d)", - math_size_string(cur_size), (int) math_fam(a), (int) cur_c); - tex_error(msg, hlp); - free(msg); - } else if (!(char_exists(cur_f, cur_c))) { - char_warning(cur_f, cur_c); - } -} - -/*tex - - We need to do a lot of different things, so |mlist_to_hlist| makes two passes - over the given mlist. - - The first pass does most of the processing: It removes ``mu'' spacing from - glue, it recursively evaluates all subsidiary mlists so that only the - top-level mlist remains to be handled, it puts fractions and square roots and - such things into boxes, it attaches subscripts and superscripts, and it - computes the overall height and depth of the top-level mlist so that the size - of delimiters for a |fence_noad| will be known. The hlist resulting from each - noad is recorded in that noad's |new_hlist| field, an integer field that - replaces the |nucleus| or |thickness|. - - The second pass eliminates all noads and inserts the correct glue and - penalties between nodes. - -*/ - -static void assign_new_hlist(pointer q, pointer r) -{ - switch (type(q)) { - case fraction_noad: - math_list(numerator(q)) = null; - flush_node(numerator(q)); - numerator(q) = null; - math_list(denominator(q)) = null; - flush_node(denominator(q)); - denominator(q) = null; - break; - case radical_noad: - case simple_noad: - case accent_noad: - if (nucleus(q) != null) { - math_list(nucleus(q)) = null; - flush_node(nucleus(q)); - nucleus(q) = null; - } - break; - } - new_hlist(q) = r; -} - -#define choose_mlist(A) do { p=A(q); A(q)=null; } while (0) - -/*tex - - Most of the actual construction work of |mlist_to_hlist| is done by - procedures with names like |make_fraction|, |make_radical|, etc. To - illustrate the general setup of such procedures, let's begin with a couple of - simple ones. - -*/ - -static void make_over(pointer q, int cur_style, int cur_size, int cur_fam) -{ - /*tex - - No rule adaption yet, maybe never as overbars should be proper - extensibles. - - */ - pointer p; - scaled f, t; - scaled used_thickness = overbar_rule(cur_style); - scaled used_fam = cur_fam; - if (math_rule_thickness_mode_par > 0) { - f = noad_fam(q); - if (f >= 0) { - t = fam_fnt(f,cur_size); - if (do_new_math(t)) { - t = font_MATH_par(t, OverbarRuleThickness); - if (t != undefined_math_parameter) { - used_thickness = t; - used_fam = f; - } - } - } - } - p = overbar(clean_box(nucleus(q), cramped_style(cur_style), cur_style, math_nucleus_list), - overbar_vgap(cur_style), used_thickness, overbar_kern(cur_style), - node_attr(nucleus(q)), math_over_rule, cur_size, used_fam); - subtype(p) = math_over_list; - math_list(nucleus(q)) = p; - type(nucleus(q)) = sub_box_node; -} - -static void make_under(pointer q, int cur_style, int cur_size, int cur_fam) -{ - /*tex - - No rule adaption yet, maybe never as underbars should be proper - extensibles. - - */ - /*tex temporary registers for box construction */ - pointer p, x, y, r; - /*tex overall height plus depth */ - scaled delta; - scaled f, t; - scaled used_thickness = underbar_rule(cur_style); - scaled used_fam = cur_fam; - x = clean_box(nucleus(q), cur_style, cur_style, math_nucleus_list); - p = new_kern(underbar_vgap(cur_style)); - reset_attributes(p, node_attr(q)); - couple_nodes(x,p); - if (math_rule_thickness_mode_par > 0) { - f = noad_fam(q); - if (f >= 0) { - t = fam_fnt(f,cur_size); - if (do_new_math(t)) { - t = font_MATH_par(t, UnderbarRuleThickness); - if (t != undefined_math_parameter) { - used_thickness = t; - used_fam = f; - } - } - } - } - r = do_fraction_rule(used_thickness, node_attr(q), math_under_rule, cur_size, used_fam); - couple_nodes(p,r); - y = vpackage(x, 0, additional, max_dimen, math_direction_par); - reset_attributes(y, node_attr(q)); - subtype(y) = math_under_list; - delta = height(y) + depth(y) + underbar_kern(cur_style); - height(y) = height(x); - depth(y) = delta - height(y); - math_list(nucleus(q)) = y; - type(nucleus(q)) = sub_box_node; -} - -static void make_vcenter(pointer q) -{ - /*tex the box that should be centered vertically */ - pointer v; - /*tex its height plus depth */ - scaled delta; - v = math_list(nucleus(q)); - if (type(v) != vlist_node) - confusion("vcenter"); - delta = height(v) + depth(v); - height(v) = math_axis_size(cur_size) + half(delta); - depth(v) = delta - height(v); -} - -/*tex - - According to the rules in the \.{DVI} file specifications, we ensure - alignment between a square root sign and the rule above its nucleus by - assuming that the baseline of the square-root symbol is the same as the - bottom of the rule. The height of the square-root symbol will be the - thickness of the rule, and the depth of the square-root symbol should exceed - or equal the height-plus-depth of the nucleus plus a certain minimum - clearance~|psi|. The symbol will be placed so that the actual clearance is - |psi| plus half the excess. - -*/ - -static void make_hextension(pointer q, int cur_style) -{ - pointer e, p; - halfword w; - boolean stack = false; - e = do_delimiter(q, left_delimiter(q), cur_size, radicalwidth(q), true, cur_style, true, &stack, NULL, NULL); - w = width(e); - if (!stack&& (radicalwidth(q) != 0) && (radicalwidth(q) != width(e))) { - if (radicalmiddle(q)) { - p = new_kern(half(radicalwidth(q)-w)); - reset_attributes(p, node_attr(q)); - couple_nodes(p,e); - e = p; - w = radicalwidth(q); - } else if (radicalexact(q)) { - w = radicalwidth(q); - } - } - e = hpack(e, 0, additional, -1); - width(e) = w ; - reset_attributes(e, node_attr(q)); - math_list(nucleus(q)) = e; - left_delimiter(q) = null; -} - -static void make_radical(pointer q, int cur_style) -{ - /*tex temporary registers for box construction */ - pointer x, y, p, l1, l2; - /*tex dimensions involved in the calculation */ - scaled delta, clr, theta, h, f; - scaled t, used_fam ; - x = clean_box(nucleus(q), cramped_style(cur_style), cur_style, math_nucleus_list); - clr = radical_vgap(cur_style); - theta = radical_rule_par(cur_style); - used_fam = small_fam(left_delimiter(q)); - /*tex - - We can take the rule width from the fam/style of the delimiter or use the - most recent math parameters value. - - */ - if (math_rule_thickness_mode_par > 0) { - f = small_fam(left_delimiter(q)); - if (f >= 0) { - t = fam_fnt(f,cur_size); - if (do_new_math(t)) { - t = font_MATH_par(t, RadicalRuleThickness); - if (t != undefined_math_parameter) { - theta = t; - used_fam = f; - } - } - } - } - if (theta == undefined_math_parameter) { - /*tex a real radical */ - theta = fraction_rule(cur_style); - y = do_delimiter(q, left_delimiter(q), cur_size, height(x) + depth(x) + clr + theta, false, cur_style, true, NULL, NULL, NULL); - /*tex - - If |y| is a composite then set |theta| to the height of its top - character, else set it to the height of |y|. - - */ - l1 = list_ptr(y); - if ((l1 != null) && (type(l1) == hlist_node)) { - /*tex possible composite */ - l2 = list_ptr(l1); - if ((l2 != null) && (type(l2) == glyph_node)) { - /*tex top character */ - theta = char_height(font(l2), character(l2)); - } else { - theta = height(y); - } - } else { - theta = height(y); - } - } else { - /*tex - - Not really a radical but we use its node, historical sharing (like in - mathml). - - */ - y = do_delimiter(q, left_delimiter(q), cur_size, height(x) + depth(x) + clr + theta, false, cur_style, true, NULL, NULL, NULL); - } - /*tex - - Weird hack, in overbar we use small_fam(left_delimiter(q)) so actually - small_fam(0). - - */ - left_delimiter(q) = null; - delta = (depth(y) + height(y) - theta) - (height(x) + depth(x) + clr); - if (delta > 0) { - /*tex increase the actual clearance */ - clr = clr + half(delta); - } - shift_amount(y) = (height(y) - theta) - (height(x) + clr); - h = depth(y) + height(y); - p = overbar(x, clr, theta, radical_kern(cur_style), node_attr(y), math_radical_rule, cur_size, used_fam); - subtype(p) = math_radical_list; - couple_nodes(y,p); - if (degree(q) != null) { - scaled wr, br, ar; - pointer r = clean_box(degree(q), script_script_style, cur_style, math_degree_list); - reset_attributes(r, node_attr(degree(q))); - wr = width(r); - if (wr == 0) { - flush_node(r); - } else { - br = radical_degree_before(cur_style); - ar = radical_degree_after(cur_style); - if (-ar > (wr + br)) - ar = -(wr + br); - x = new_kern(ar); - reset_attributes(x, node_attr(degree(q))); - couple_nodes(x,y); - shift_amount(r) = - -((xn_over_d(h, radical_degree_raise(cur_style), 100)) - - depth(y) - shift_amount(y)); - couple_nodes(r,x); - x = new_kern(br); - reset_attributes(x, node_attr(degree(q))); - couple_nodes(x,r); - y = x; - } - /*tex for \.{\\Uroot ..{<list>}{}} : */ - math_list(degree(q)) = null; - flush_node(degree(q)); - } - p = hpack(y, 0, additional, -1); - reset_attributes(p, node_attr(q)); - math_list(nucleus(q)) = p; - type(nucleus(q)) = sub_box_node; -} - -/*tex Construct a vlist box: */ - -static pointer wrapup_over_under_delimiter(pointer x, pointer y, pointer q, scaled shift_up, scaled shift_down, halfword st) -{ - pointer p; - pointer v = new_null_box(); - type(v) = vlist_node; - subtype(v) = st; - height(v) = shift_up + height(x); - depth(v) = depth(y) + shift_down; - reset_attributes(v, node_attr(q)); - p = new_kern((shift_up - depth(x)) - (height(y) - shift_down)); - reset_attributes(p, node_attr(q)); - couple_nodes(p,y); - couple_nodes(x,p); - list_ptr(v) = x; - return v; -} - -/*tex When |exact| use radicalwidth (|y| is delimiter). */ - -#define fixup_widths(q,x,y) do { \ - if (width(y) >= width(x)) { \ - if (radicalwidth(q) != 0) { \ - shift_amount(x) += half(width(y)-width(x)) ; \ - } \ - width(x) = width(y); \ - } else { \ - if (radicalwidth(q) != 0) { \ - shift_amount(y) += half(width(x)-width(y)) ; \ - } \ - width(y) = width(x); \ - } \ -} while (0) - - -#define check_radical(q,stack,r,t) do { \ - if (!stack && (width(r) >= width(t)) && (radicalwidth(q) != 0) && (radicalwidth(q) != width(r))) { \ - if (radicalleft(q)) { \ - halfword p = new_kern(radicalwidth(q)-width(r)); \ - reset_attributes(p, node_attr(q)); \ - couple_nodes(p,r); \ - r = hpack(p, 0, additional, -1); \ - width(r) = radicalwidth(q); \ - reset_attributes(r, node_attr(q)); \ - } else if (radicalmiddle(q)) { \ - halfword p = new_kern(half(radicalwidth(q)-width(r))); \ - reset_attributes(p, node_attr(q)); \ - couple_nodes(p,r); \ - r = hpack(p, 0, additional, -1); \ - width(r) = radicalwidth(q); \ - reset_attributes(r, node_attr(q)); \ - } else if (radicalright(q)) { \ - /*tex also kind of exact compared to vertical */ \ - r = hpack(r, 0, additional, -1); \ - width(r) = radicalwidth(q); \ - reset_attributes(r, node_attr(q)); \ - } \ - } \ -} while (0) - -#define check_widths(q,p) do { \ - if (radicalwidth(q) != 0) { \ - wd = radicalwidth(q); \ - } else { \ - wd = width(p); \ - } \ -} while (0) - -/*tex - - This has the |nucleus| box |x| as a limit above an extensible delimiter |y|. - -*/ - -static void make_over_delimiter(pointer q, int cur_style) -{ - pointer x, y, v; - scaled shift_up, shift_down, clr, delta, wd; - boolean stack; - x = clean_box(nucleus(q), sub_style(cur_style), cur_style, math_nucleus_list); - check_widths(q,x); - y = do_delimiter(q, left_delimiter(q), cur_size, wd, true, cur_style, true, &stack, NULL, NULL); - left_delimiter(q) = null; - check_radical(q,stack,y,x); - fixup_widths(q, x, y); - shift_up = over_delimiter_bgap(cur_style); - shift_down = 0; - clr = over_delimiter_vgap(cur_style); - delta = clr - ((shift_up - depth(x)) - (height(y) - shift_down)); - if (delta > 0) { - shift_up = shift_up + delta; - } - v = wrapup_over_under_delimiter(x, y, q, shift_up, shift_down, math_over_delimiter_list); - /*tex This also equals |width(y)|: */ - width(v) = width(x); - math_list(nucleus(q)) = v; - type(nucleus(q)) = sub_box_node; -} - -/*tex - - This has the extensible delimiter |x| as a limit below |nucleus| box |y|. - -*/ - -static void make_under_delimiter(pointer q, int cur_style) -{ - pointer x, y, v; - scaled shift_up, shift_down, clr, delta, wd; - boolean stack; - y = clean_box(nucleus(q), sup_style(cur_style), cur_style, math_nucleus_list); - check_widths(q,y); - x = do_delimiter(q, left_delimiter(q), cur_size, wd, true, cur_style, true, &stack, NULL, NULL); - left_delimiter(q) = null; - check_radical(q,stack,x,y); - fixup_widths(q, x, y); - shift_up = 0; - shift_down = under_delimiter_bgap(cur_style); - clr = under_delimiter_vgap(cur_style); - delta = clr - ((shift_up - depth(x)) - (height(y) - shift_down)); - if (delta > 0) { - shift_down = shift_down + delta; - } - v = wrapup_over_under_delimiter(x, y, q, shift_up, shift_down, math_under_delimiter_list); - /*tex This also equals |width(y)|: */ - width(v) = width(y); - math_list(nucleus(q)) = v; - type(nucleus(q)) = sub_box_node; -} - -/*tex - - This has the extensible delimiter |x| as a limit above |nucleus| box |y|. - -*/ - -static void make_delimiter_over(pointer q, int cur_style) -{ - pointer x, y, v; - scaled shift_up, shift_down, clr, actual, wd; - boolean stack; - y = clean_box(nucleus(q), cur_style, cur_style, math_nucleus_list); - check_widths(q,y); - x = do_delimiter(q, left_delimiter(q), cur_size + (cur_size == script_script_size ? 0 : 1), wd, true, cur_style, true, &stack, NULL, NULL); - left_delimiter(q) = null; - check_radical(q,stack,x,y); - fixup_widths(q, x, y); - shift_up = over_delimiter_bgap(cur_style)-height(x)-depth(x); - shift_down = 0; - clr = over_delimiter_vgap(cur_style); - actual = shift_up - height(y); - if (actual < clr) { - shift_up = shift_up + (clr-actual); - } - v = wrapup_over_under_delimiter(x, y, q, shift_up, shift_down, math_over_delimiter_list); - /*tex This also equals |width(y)|: */ - width(v) = width(x); - math_list(nucleus(q)) = v; - type(nucleus(q)) = sub_box_node; -} - -/*tex - - This has the extensible delimiter |y| as a limit below a |nucleus| box |x|. - -*/ - -static void make_delimiter_under(pointer q, int cur_style) -{ - pointer x, y, v; - scaled shift_up, shift_down, clr, actual, wd; - boolean stack; - x = clean_box(nucleus(q), cur_style, cur_style, math_nucleus_list); - check_widths(q,x); - y = do_delimiter(q, left_delimiter(q), cur_size + (cur_size == script_script_size ? 0 : 1), wd, true, cur_style, true, &stack, NULL, NULL); - left_delimiter(q) = null; - check_radical(q,stack,y,x); - fixup_widths(q, x, y); - shift_up = 0; - shift_down = under_delimiter_bgap(cur_style) - height(y)-depth(y); - clr = under_delimiter_vgap(cur_style); - actual = shift_down - depth(x); - if (actual<clr) { - shift_down += (clr-actual); - } - v = wrapup_over_under_delimiter(x, y, q, shift_up, shift_down, math_under_delimiter_list); - /*tex This also equals |width(y)|: */ - width(v) = width(y); - math_list(nucleus(q)) = v; - type(nucleus(q)) = sub_box_node; -} - -/*tex - - Slants are not considered when placing accents in math mode. The accenter is - centered over the accentee, and the accent width is treated as zero with - respect to the size of the final box. - -*/ - -#define TOP_CODE 1 -#define BOT_CODE 2 -#define OVERLAY_CODE 4 -#define STRETCH_ACCENT_CODE 8 - -static boolean compute_accent_skew(pointer q, int flags, scaled *s) -{ - /*tex temporary register for box construction */ - pointer p; - /*tex will be true if a top-accent is placed in |s| */ - boolean s_is_absolute = false; - if (type(nucleus(q)) == math_char_node) { - fetch(nucleus(q)); - if (do_new_math(cur_f)) { - /*tex - There is no bot_accent so let's assume similarity - - \starttyping - if (flags & (TOP_CODE | OVERLAY_CODE)) { - *s = char_top_accent(cur_f, cur_c); - if (*s != INT_MIN) { - s_is_absolute = true; - } - } else { - *s = char_bot_accent(cur_f, cur_c); - if (*s != INT_MIN) { - s_is_absolute = true; - } - } - \stoptyping - */ - *s = char_top_accent(cur_f, cur_c); - if (*s != INT_MIN) { - s_is_absolute = true; - } - } else { - if (flags & TOP_CODE) { - *s = get_kern(cur_f, cur_c, skew_char(cur_f)); - } else { - *s = 0; - } - } - } else if (type(nucleus(q)) == sub_mlist_node) { - /*tex - If |nucleus(q)| is a |sub_mlist_node| composed of an |accent_noad| we: - - \startitemize - \startitem - use the positioning of the nucleus of that noad, recursing until - \stopitem - \startitem - the inner most |accent_noad|. This way multiple stacked accents - are - \stopitem - \startitem - aligned to the inner most one. - \stopitem - \stoptitemize - - The vlink test was added in version 1.06, so that we only consider a - lone noad: - - $ - \Umathaccent bottom 0 0 "023DF { \Umathaccent fixed 0 0 "00302 { m } r } \quad - \Umathaccent bottom 0 0 "023DF { l \Umathaccent fixed 0 0 "00302 { m } r } \quad - \Umathaccent bottom 0 0 "023DF { l \Umathaccent fixed 0 0 "00302 { m } } \quad - \Umathaccent bottom 0 0 "023DF { \Umathaccent fixed 0 0 "00302 { m } } \quad - \Umathaccent bottom 0 0 "023DF { l r } - $ - - */ - p = math_list(nucleus(q)); - if (type(p) == accent_noad && vlink(p) == null) { - s_is_absolute = compute_accent_skew(p, flags, s); - } - } else { - } - - return s_is_absolute; -} - -static void do_make_math_accent(pointer q, internal_font_number f, int c, int flags, int cur_style) -{ - /*tex temporary registers for box construction */ - pointer p, r, x, y; - /*tex amount to skew the accent to the right */ - scaled s; - /*tex height of character being accented */ - scaled h; - /*tex space to remove between accent and accentee */ - scaled delta; - /*tex width of the accentee, not including sub/superscripts */ - scaled w; - /*tex will be true if a top-accent is placed in |s| */ - boolean s_is_absolute; - scaled fraction ; - scaled ic = 0; - scaled target ; - extinfo *ext; - pointer attr_p; - attr_p = (flags & TOP_CODE ? top_accent_chr(q) : flags & BOT_CODE ? bot_accent_chr(q) : overlay_accent_chr(q)); - fraction = accentfraction(q); - c = cur_c; - f = cur_f; - s = 1; - if (fraction == 0) { - fraction = 1000; - } - /*tex Compute the amount of skew, or set |s| to an alignment point */ - s_is_absolute = compute_accent_skew(q, flags, &s); - x = clean_box(nucleus(q), cramped_style(cur_style), cur_style, math_nucleus_list); - w = width(x); - h = height(x); - if (do_new_math(cur_f) && !s_is_absolute) { - s = half(w); - s_is_absolute = true; - } - /*tex Switch to a larger accent if available and appropriate */ - y = null; - ext = NULL; - if (flags & OVERLAY_CODE) { - if (fraction > 0) { - target = xn_over_d(h,fraction,1000); - } else { - target = h; - } - } else { - if (fraction > 0) { - target = xn_over_d(w,fraction,1000); - } else { - target = w; - } - } - if ((flags & STRETCH_ACCENT_CODE) && (char_width(f, c) < w)) { - while (1) { - if ((char_tag(f, c) == ext_tag) && ((ext = get_charinfo_hor_variants(char_info(f, c))) != NULL)) { - /*tex a bit weird for an overlay but anyway, here we don't need a factor as we don't step */ - y = get_delim_box(f, c, w, connector_overlap_min(cur_style), 1, node_attr(attr_p)); - break; - } else if (char_tag(f, c) != list_tag) { - break; - } else { - int yy = char_remainder(f, c); - if (!char_exists(f, yy)) { - break; - } else if (flags & OVERLAY_CODE) { - if (char_height(f, yy) > target) { - break; - } - } else { - if (char_width(f, yy) > target) - break; - } - c = yy; - } - } - } - if (y == null) { - /*tex italic gets added to width */ - y = char_box(f, c, node_attr(attr_p)); - } - if (flags & TOP_CODE) { - if (h < accent_base_height(f)) { - delta = h; - } else { - delta = accent_base_height(f); - } - } else if (flags & OVERLAY_CODE) { - /*tex center the accent vertically around the accentee */ - delta = half(height(y) + depth(y) + height(x) + depth(x)); - } else { - delta = 0; /* hm */ - } - if ((supscr(q) != null) || (subscr(q) != null)) { - if (type(nucleus(q)) == math_char_node) { - /*tex swap the subscript and superscript into box |x| */ - flush_node_list(x); - x = new_noad(); - r = math_clone(nucleus(q)); - nucleus(x) = r; - supscr(x) = supscr(q); - supscr(q) = null; - subscr(x) = subscr(q); - subscr(q) = null; - type(nucleus(q)) = sub_mlist_node; - math_list(nucleus(q)) = x; - x = clean_box(nucleus(q), cur_style, cur_style, math_nucleus_list); - delta = delta + height(x) - h; - h = height(x); - } - } else if ((vlink(q) != null) && (type(nucleus(q)) == math_char_node)) { - /*tex only pure math char nodes */ - internal_font_number f = fam_fnt(math_fam(nucleus(q)),cur_size); - if (do_new_math(f)) { - ic = char_italic(f,math_character(nucleus(q))); - } - } - /*tex the top accents of both characters are aligned */ - if (s_is_absolute) { - scaled sa; - if (ext != NULL) { - /*tex if the accent is extensible just take the center */ - sa = half(width(y)); - } else { - /*tex - There is no bot_accent so let's assume similarity - - \starttyping - if (flags & BOT_CODE) { - sa = char_bot_accent(f, c); - } else { - sa = char_top_accent(f, c); - } - \stoptyping - */ - sa = char_top_accent(f, c); - } - if (sa == INT_MIN) { - /*tex just take the center */ - sa = half(width(y)); - } - if (math_direction_par == dir_TRT) { - shift_amount(y) = s + sa - width(y); - } else { - shift_amount(y) = s - sa; - } - } else { - if (width(y)== 0) { - shift_amount(y) = s + w; - } else if (math_direction_par == dir_TRT) { - shift_amount(y) = s + width(y); /* ok? */ - } else { - shift_amount(y) = s + half(w - width(y)); - } - } - width(y) = 0; - if (flags & (TOP_CODE | OVERLAY_CODE)) { - p = new_kern(-delta); - reset_attributes(p, node_attr(q)); - couple_nodes(p,x); - couple_nodes(y,p); - } else { - couple_nodes(x,y); - y = x; - } - r = vpackage(y, 0, additional, max_dimen, math_direction_par); - reset_attributes(r, node_attr(q)); - subtype(r) = math_accent_list; - width(r) = width(x); - y = r; - if (flags & (TOP_CODE | OVERLAY_CODE)) { - if (height(y) < h) { - /*tex make the height of box |y| equal to |h| */ - p = new_kern(h - height(y)); - reset_attributes(p, node_attr(q)); - try_couple_nodes(p,list_ptr(y)); - list_ptr(y) = p; - height(y) = h; - } - } else { - shift_amount(y) = -(h - height(y)); - } - if (ic != 0) { - /*tex old font codepath has ic built in, new font code doesn't */ - width(r) += ic ; - } - math_list(nucleus(q)) = y; - type(nucleus(q)) = sub_box_node; -} - -static void make_math_accent(pointer q, int cur_style) -{ - int topstretch = !(subtype(q) % 2); - int botstretch = !(subtype(q) / 2); - - if (top_accent_chr(q) != null) { - fetch(top_accent_chr(q)); - if (char_exists(cur_f, cur_c)) { - do_make_math_accent(q, cur_f, cur_c, TOP_CODE | (topstretch ? STRETCH_ACCENT_CODE : 0), cur_style); - } - flush_node(top_accent_chr(q)); - top_accent_chr(q) = null; - } - if (bot_accent_chr(q) != null) { - fetch(bot_accent_chr(q)); - if (char_exists(cur_f, cur_c)) { - do_make_math_accent(q, cur_f, cur_c, BOT_CODE | (botstretch ? STRETCH_ACCENT_CODE : 0), cur_style); - } - flush_node(bot_accent_chr(q)); - bot_accent_chr(q) = null; - } - if (overlay_accent_chr(q) != null) { - fetch(overlay_accent_chr(q)); - if (char_exists(cur_f, cur_c)) { - do_make_math_accent(q, cur_f, cur_c, OVERLAY_CODE | STRETCH_ACCENT_CODE, cur_style); - } - flush_node(overlay_accent_chr(q)); - overlay_accent_chr(q) = null; - } -} - -/*tex - - The |make_fraction| procedure is a bit different because it sets - |new_hlist(q)| directly rather than making a sub-box. - -*/ - -static void make_fraction(pointer q, int cur_style) -{ - pointer p, p1, p2, v, x, y, z, l, r, m; - scaled delta, delta1, delta2, shift_up, shift_down, clr1, clr2, f, t;\ - /*tex - - We can take the rule width from an explicitly set fam, even if a fraction - itself has no character, otherwise we just use the math parameter. - - */ - scaled used_fam = math_rules_fam_par; - if (math_rule_thickness_mode_par > 0 && thickness(q) != 0) { - f = fraction_fam(q); - if (f >= 0) { - t = fam_fnt(f,cur_size); - if (do_new_math(t)) { - t = font_MATH_par(t, FractionRuleThickness); - if (t != undefined_math_parameter) { - thickness(q) = t; - used_fam = f; - } - } - } - } - if (thickness(q) == default_code) - thickness(q) = fraction_rule(cur_style); - /*tex - - Create equal-width boxes |x| and |z| for the numerator and denominator, - and compute the default amounts |shift_up| and |shift_down| by which they - are displaced from the baseline. - - */ - x = clean_box(numerator(q), num_style(cur_style), cur_style, math_numerator_list); - z = clean_box(denominator(q), denom_style(cur_style), cur_style, math_denominator_list); - if (middle_delimiter(q) != null) { - delta = 0; - m = do_delimiter(q, middle_delimiter(q), cur_size, delta, false, cur_style, true, NULL, NULL, NULL); - middle_delimiter(q) = null; - } else { - m = null ; - if (width(x) < width(z)) { - x = rebox(x, width(z)); - } else { - z = rebox(z, width(x)); - } - } - if (m != null) { - shift_up = 0; - shift_down = 0; - } else if (thickness(q) == 0) { - shift_up = stack_num_up(cur_style); - shift_down = stack_denom_down(cur_style); - /*tex - - The numerator and denominator must be separated by a certain minimum - clearance, called |clr| in the following program. The difference - between |clr| and the actual clearance is |2delta|. - - */ - clr1 = stack_vgap(cur_style); - delta = half(clr1 - ((shift_up - depth(x)) - (height(z) - shift_down))); - if (delta > 0) { - shift_up = shift_up + delta; - shift_down = shift_down + delta; - } - } else { - shift_up = fraction_num_up(cur_style); - shift_down = fraction_denom_down(cur_style); - /*tex - - In the case of a fraction line, the minimum clearance depends on the - actual thickness of the line. - - */ - clr1 = fraction_num_vgap(cur_style); - clr2 = fraction_denom_vgap(cur_style); - delta = half(thickness(q)); - if (fractionexact(q)) { - delta1 = clr1 - ((shift_up - depth(x) ) - (math_axis_size(cur_size) + delta)); - delta2 = clr2 - ((shift_down - height(z)) + (math_axis_size(cur_size) - delta)); - } else { - clr1 = ext_xn_over_d(clr1, thickness(q), fraction_rule(cur_style)); - clr2 = ext_xn_over_d(clr2, thickness(q), fraction_rule(cur_style)); - delta1 = clr1 - ((shift_up - depth(x) ) - (math_axis_size(cur_size) + delta)); - delta2 = clr2 - ((shift_down - height(z)) + (math_axis_size(cur_size) - delta)); - } - if (delta1 > 0) { - shift_up = shift_up + delta1; - } - if (delta2 > 0) { - shift_down = shift_down + delta2; - } - } - if (m != null) { - /*tex - - Construct a hlist box for the fraction, according to |hgap| and - |vgap|. - - */ - shift_up = skewed_fraction_vgap(cur_style); - - if (!fractionnoaxis(q)) { - shift_up += half(math_axis_size(cur_size)); - } - shift_down = shift_up; - v = new_null_box(); - reset_attributes(v, node_attr(q)); - type(v) = hlist_node; - subtype(v) = math_numerator_list; - list_ptr(v) = x; - width(v) = width(x); - height(v) = height(x) + shift_up; - depth(v) = depth(x); - shift_amount(v) = - shift_up; - x = v; - v = new_null_box(); - reset_attributes(v, node_attr(q)); - type(v) = hlist_node; - subtype(v) = math_denominator_list; - list_ptr(v) = z; - width(v) = width(z); - height(v) = height(z); - depth(v) = depth(z) + shift_down; - shift_amount(v) = shift_down; - z = v; - v = new_null_box(); - subtype(v) = math_fraction_list; - reset_attributes(v, node_attr(q)); - type(v) = hlist_node; - if (height(x) > height(z)) { - height(v) = height(x); - } else { - height(v) = height(z); - } - if (depth(x) > depth(z)) { - depth(v) = depth(x); - } else { - depth(v) = depth(z); - } - if (height(m) > height(v)) { - height(v) = height(m); - } - if (depth(m) > depth(v)) { - depth(v) = depth(m); - } - if (fractionexact(q)) { - delta1 = -half(skewed_fraction_hgap(cur_style)); - delta2 = delta1; - width(v) = width(x) + width(z) + width(m) - skewed_fraction_hgap(cur_style); - } else { - delta1 = half(skewed_fraction_hgap(cur_style)-width(m)); - delta2 = half(skewed_fraction_hgap(cur_style)+width(m)); - width(v) = width(x) + width(z) + skewed_fraction_hgap(cur_style); - width(m) = 0; - } - p1 = new_kern(delta1); - reset_attributes(p1, node_attr(q)); - p2 = new_kern(delta2); - reset_attributes(p2, node_attr(q)); - couple_nodes(x,p1); - couple_nodes(p1,m); - couple_nodes(m,p2); - couple_nodes(p2,z); - list_ptr(v) = x; - } else { - /*tex - - Construct a vlist box for the fraction, according to |shift_up| and - |shift_down|. - - */ - v = new_null_box(); - type(v) = vlist_node; - subtype(v) = math_fraction_list; - height(v) = shift_up + height(x); - depth(v) = depth(z) + shift_down; - /*tex This also equals |width(z)|. */ - width(v) = width(x); - reset_attributes(v, node_attr(q)); - if (thickness(q) && ! fractionnorule(q)) { - y = do_fraction_rule(thickness(q), node_attr(q), math_fraction_rule, cur_size, used_fam); - p = new_kern((math_axis_size(cur_size) - delta) - (height(z) - shift_down)); - reset_attributes(p, node_attr(q)); - couple_nodes(y,p); - couple_nodes(p,z); - p = new_kern((shift_up - depth(x)) - (math_axis_size(cur_size) + delta)); - couple_nodes(p,y); - } else { - p = new_kern((shift_up - depth(x)) - (height(z) - shift_down)); - couple_nodes(p,z); - } - reset_attributes(p, node_attr(q)); - couple_nodes(x,p); - list_ptr(v) = x; - } - /*tex - - Put the fraction into a box with its delimiters, and make |new_hlist(q)| - point to it. - - */ - if (do_new_math(cur_f)) { - delta = fraction_del_size_new(cur_style); - if (delta == undefined_math_parameter) { - delta = get_delimiter_height(depth(v), height(v), true); - } - } else { - delta = fraction_del_size_old(cur_style); - } - l = do_delimiter(q, left_delimiter(q), cur_size, delta, false, cur_style, true, NULL, NULL, NULL); - left_delimiter(q) = null; - r = do_delimiter(q, right_delimiter(q), cur_size, delta, false, cur_style, true, NULL, NULL, NULL); - right_delimiter(q) = null; - couple_nodes(l,v); - couple_nodes(v,r); - y = hpack(l, 0, additional, -1); - reset_attributes(y, node_attr(q)); - /*tex There can also be a nested one: */ - subtype(y) = math_fraction_list; - assign_new_hlist(q, y); -} - -/*tex - - If the nucleus of an |op_noad| is a single character, it is to be centered - vertically with respect to the axis, after first being enlarged (via a - character list in the font) if we are in display style. The normal convention - for placing displayed limits is to put them above and below the operator in - display style. - - The italic correction is removed from the character if there is a subscript - and the limits are not being displayed. The |make_op| routine returns the - value that should be used as an offset between subscript and superscript. - - After |make_op| has acted, |subtype(q)| will be |limits| if and only if the - limits have been set above and below the operator. In that case, - |new_hlist(q)| will already contain the desired final box. - -*/ - -static void make_scripts(pointer q, pointer p, scaled it, int cur_style, scaled supshift, scaled subshift); -static pointer check_nucleus_complexity(halfword q, scaled * delta, int cur_style, int *same); - -static scaled make_op(pointer q, int cur_style) -{ - /*tex offset between subscript and superscript */ - scaled delta = 0; - scaled dummy = 0; - /*tex temporary registers for box construction */ - pointer p, v, x, y, z, n; - /*tex register for character examination */ - int c; - /*tex dimensions for box calculation */ - scaled shift_up, shift_down; - boolean axis_shift = false; - scaled ok_size; - if ((subtype(q) == op_noad_type_normal) && (cur_style < text_style)) { - subtype(q) = op_noad_type_limits; - } - if (type(nucleus(q)) == math_char_node) { - fetch(nucleus(q)); - if (cur_style < text_style) { - /*tex try to make it larger */ - ok_size = minimum_operator_size(cur_style); - if (ok_size != undefined_math_parameter) { - /*tex creating a temporary delimiter is the cleanest way */ - y = new_node(delim_node, 0); - reset_attributes(y, node_attr(nucleus(q))); - small_fam(y) = math_fam(nucleus(q)); - small_char(y) = math_character(nucleus(q)); - x = do_delimiter(q, y, text_size, ok_size, false, cur_style, true, NULL, &delta, NULL); - if (delta != 0) { - if (do_new_math(cur_f)) { - /*tex - As we never added italic correction we don't need to compensate. The ic - is stored in a special field of the node and applied in some occasions. - */ - } else if ((subscr(q) != null) && (subtype(q) != op_noad_type_limits)) { - /*tex - Here we (selectively) remove the italic correction that always gets added - in a traditional font. See (**). In \OPENTYPE\ mode we insert italic kerns, - but in traditional mode it's width manipulation. This actually makes sense - because those fonts have a fake width and the italic correction sets that - right. - */ - width(x) -= delta; - } - } - } else { - ok_size = height_plus_depth(cur_f, cur_c) + 1; - while ((char_tag(cur_f, cur_c) == list_tag) && height_plus_depth(cur_f, cur_c) < ok_size) { - c = char_remainder(cur_f, cur_c); - if (!char_exists(cur_f, c)) - break; - cur_c = c; - math_character(nucleus(q)) = c; - } - delta = char_italic(cur_f, cur_c); - x = clean_box(nucleus(q), cur_style, cur_style, math_nucleus_list); - if (delta != 0) { - if (do_new_math(cur_f)) { - /*tex we never added italic correction */ - } else if ((subscr(q) != null) && (subtype(q) != op_noad_type_limits)) { - /*tex remove italic correction */ - width(x) -= delta; - } - } - axis_shift = true; - } - } else { - /*tex normal size */ - delta = char_italic(cur_f, cur_c); - x = clean_box(nucleus(q), cur_style, cur_style, math_nucleus_list); - if (delta != 0) { - if (do_new_math(cur_f)) { - /*tex we never added italic correction */ - } else if ((subscr(q) != null) && (subtype(q) != op_noad_type_limits)) { - /*tex remove italic correction */ - width(x) -= delta; - } - } - axis_shift = true; - } - if (axis_shift) { - /*tex center vertically */ - shift_amount(x) = half(height(x) - depth(x)) - math_axis_size(cur_size); - } - type(nucleus(q)) = sub_box_node; - math_list(nucleus(q)) = x; - } - /*tex we now handle op_nod_type_no_limits here too */ - if (subtype(q) == op_noad_type_no_limits) { - if (do_new_math(cur_f)) { - /*tex - Not: - - \starttyping - if (delta != 0) { - delta = half(delta) ; - } - \stoptyping - */ - p = check_nucleus_complexity(q, &dummy, cur_style, NULL); - if ((subscr(q) == null) && (supscr(q) == null)) { - assign_new_hlist(q, p); - } else { - /*tex - Not: - - \starttyping - make_scripts(q, p, 0, cur_style, delta, -delta); - \stoptyping - */ - int mode = math_nolimits_mode_par; /* wins */ - /*tex - - For easy configuration ... fonts are somewhat inconsistent - and the values for italic correction run from 30 to 60\% of. - the width. - - */ - switch (mode) { - case 0 : - /*tex full bottom correction */ - make_scripts(q, p, 0, cur_style, 0, -delta); - break; - case 1 : - /*tex |MathConstants| driven */ - make_scripts(q, p, 0, cur_style, - round_xn_over_d(delta, nolimit_sup_factor(cur_style), 1000), - -round_xn_over_d(delta, nolimit_sub_factor(cur_style), 1000)); - break ; - case 2 : - /*tex no correction */ - make_scripts(q, p, 0, cur_style, 0, 0); - break ; - case 3 : - /*tex half bottom correction */ - make_scripts(q, p, 0, cur_style, 0, -half(delta)); - break; - case 4 : - /*tex half bottom and top correction */ - make_scripts(q, p, 0, cur_style, half(delta), -half(delta)); - break; - default : - if (mode > 15) { - /*tex for quickly testing values */ - make_scripts(q, p, 0, cur_style, 0, -round_xn_over_d(delta, mode, 1000)); - } else { - make_scripts(q, p, 0, cur_style, 0, 0); - } - break; - } - } - delta = 0; - } else { - /*tex similar code then the caller (before CHECK_DIMENSIONS) */ - p = check_nucleus_complexity(q, &delta, cur_style, NULL); - if ((subscr(q) == null) && (supscr(q) == null)) { - assign_new_hlist(q, p); - } else { - make_scripts(q, p, delta, cur_style, 0, 0); - } - } - } else if (subtype(q) == op_noad_type_limits) { - /*tex - - The following program builds a vlist box |v| for displayed limits. - The width of the box is not affected by the fact that the limits may - be skewed. - - */ - x = clean_box(supscr(q), sup_style(cur_style), cur_style, math_sup_list); - y = clean_box(nucleus(q), cur_style, cur_style, math_nucleus_list); - z = clean_box(subscr(q), sub_style(cur_style), cur_style, math_sub_list); - v = new_null_box(); - reset_attributes(v, node_attr(q)); - type(v) = vlist_node; - subtype(v) = math_limits_list; - if (do_new_math(cur_f)) { - n = nucleus(q); - if (n != null) { - if ((type(n) == sub_mlist_node) || (type(n) == sub_box_node)) { - n = math_list(n); - if (n != null) { - if (type(n) == hlist_node) { - /*tex just a not scaled char */ - n = list_ptr(n); - while (n != null) { - if (type(n) == glyph_node) { - delta = char_italic(font(n),character(n)); - } - n = vlink(n); - } - } else { - while (n != null) { - if (type(n) == fence_noad) { - if (delimiteritalic(n) > delta) { - /*tex we can have dummies, the period ones */ - delta = delimiteritalic(n); - } - } - n = vlink(n); - } - } - } - } else { - n = nucleus(q); - if (type(n) == math_char_node) { - delta = char_italic(fam_fnt(math_fam(n),cur_size),math_character(n)); - } - } - } - } - width(v) = width(y); - if (width(x) > width(v)) - width(v) = width(x); - if (width(z) > width(v)) - width(v) = width(z); - x = rebox(x, width(v)); - y = rebox(y, width(v)); - z = rebox(z, width(v)); - shift_amount(x) = half(delta); - shift_amount(z) = -shift_amount(x); - /*tex v is the still empty target */ - height(v) = height(y); - depth(v) = depth(y); - /*tex - - Attach the limits to |y| and adjust |height(v)|, |depth(v)| to - account for their presence. - - We use |shift_up| and |shift_down| in the following program for the - amount of glue between the displayed operator |y| and its limits |x| - and |z|. - - The vlist inside box |v| will consist of |x| followed by |y| followed - by |z|, with kern nodes for the spaces between and around them; - |b| is baseline and |v| is the minumum gap. - - */ - if (supscr(q) == null) { - list_ptr(x) = null; - flush_node(x); - list_ptr(v) = y; - } else { - shift_up = limit_above_bgap(cur_style) - depth(x); - if (shift_up < limit_above_vgap(cur_style)) - shift_up = limit_above_vgap(cur_style); - p = new_kern(shift_up); - reset_attributes(p, node_attr(q)); - couple_nodes(p,y); - couple_nodes(x,p); - p = new_kern(limit_above_kern(cur_style)); - reset_attributes(p, node_attr(q)); - couple_nodes(p,x); - list_ptr(v) = p; - height(v) = height(v) + limit_above_kern(cur_style) + height(x) + depth(x) + shift_up; - } - if (subscr(q) == null) { - list_ptr(z) = null; - flush_node(z); - } else { - shift_down = limit_below_bgap(cur_style) - height(z); - if (shift_down < limit_below_vgap(cur_style)) - shift_down = limit_below_vgap(cur_style); - p = new_kern(shift_down); - reset_attributes(p, node_attr(q)); - couple_nodes(y,p); - couple_nodes(p,z); - p = new_kern(limit_below_kern(cur_style)); - reset_attributes(p, node_attr(q)); - couple_nodes(z,p); - depth(v) = depth(v) + limit_below_kern(cur_style) + height(z) + depth(z) + shift_down; - } - if (subscr(q) != null) { - math_list(subscr(q)) = null; - flush_node(subscr(q)); - subscr(q) = null; - } - if (supscr(q) != null) { - math_list(supscr(q)) = null; - flush_node(supscr(q)); - supscr(q) = null; - } - assign_new_hlist(q, v); - if (do_new_math(cur_f)) { - delta = 0; - } - } - return delta; -} - -/*tex - - A ligature found in a math formula does not create a ligature, because there - is no question of hyphenation afterwards; the ligature will simply be stored - in an ordinary |glyph_node|, after residing in an |ord_noad|. - - The |type| is converted to |math_text_char| here if we would not want to - apply an italic correction to the current character unless it belongs to a - math font (i.e., a font with |space=0|). - - No boundary characters enter into these ligatures. - -*/ - -#define simple_char_noad(p) (\ - (p != null) && \ - (type(p) == simple_noad) && \ - (subtype(p) <= punct_noad_type) && \ - (type(nucleus(p)) == math_char_node) \ -) - -#define same_nucleus_fam(p,q) \ - (math_fam(nucleus(p)) == math_fam(nucleus(q))) - -static void make_ord(pointer q) -{ - /*tex the left-side character for lig/kern testing */ - int a; - /*tex temporary registers for list manipulation */ - pointer p, r, s; - /*tex a kern */ - scaled k; - /*tex a ligature */ - liginfo lig; - RESTART: - if (subscr(q) == null && supscr(q) == null && type(nucleus(q)) == math_char_node) { - p = vlink(q); - if (simple_char_noad(p) && same_nucleus_fam(p,q)) { - type(nucleus(q)) = math_text_char_node; - fetch(nucleus(q)); - a = cur_c; - /*tex add italic correction */ - if (do_new_math(cur_f) && (char_italic(cur_f,math_character(nucleus(q))) != 0)) { - p = new_kern(char_italic(cur_f,math_character(nucleus(q)))); - subtype(p) = italic_kern; - reset_attributes(p, node_attr(q)); - couple_nodes(p,vlink(q)); - couple_nodes(q,p); - return; - } - /*tex construct ligatures, quite unlikely in new math fonts */ - if ((has_kern(cur_f, a)) || (has_lig(cur_f, a))) { - cur_c = math_character(nucleus(p)); - /*tex - - If character |a| has a kern with |cur_c|, attach the kern - after~|q|; or if it has a ligature with |cur_c|, combine - noads |q| and~|p| appropriately; then |return| if the cursor - has moved past a noad, or |goto restart|. - - Note that a ligature between an |ord_noad| and another kind - of noad is replaced by an |ord_noad|, when the two noads - collapse into one. - - We could make a parenthesis (say) change shape when it - follows certain letters. Presumably a font designer will - define such ligatures only when this convention makes sense. - - */ - if (disable_lig_par == 0 && has_lig(cur_f, a)) { - lig = get_ligature(cur_f, a, cur_c); - if (is_valid_ligature(lig)) { - /*tex allow a way out of infinite ligature loop */ - check_interrupt(); - switch (lig_type(lig)) { - case 1: - /*tex \.{=:\char`\|} */ - case 5: - /*tex \.{=:\char`\|>} */ - math_character(nucleus(q)) = lig_replacement(lig); - break; - case 2: - /*tex \.{\char`\|=:} */ - case 6: - /*tex \.{\char`\|=:>} */ - math_character(nucleus(p)) = lig_replacement(lig); - break; - case 3: - /*tex \.{\char`\|=:\char`\|} */ - case 7: - /*tex \.{\char`\|=:\char`\|>} */ - case 11: - /*tex \.{\char`\|=:\char`\|>>} */ - r = new_noad(); - reset_attributes(r, node_attr(q)); - s = new_node(math_char_node, 0); - reset_attributes(s, node_attr(q)); - nucleus(r) = s; - math_character(nucleus(r)) = lig_replacement(lig); - math_fam(nucleus(r)) = math_fam(nucleus(q)); - couple_nodes(q,r); - couple_nodes(r,p); - if (lig_type(lig) < 11) { - type(nucleus(r)) = math_char_node; - } else { - /*tex prevent combination */ - type(nucleus(r)) = math_text_char_node; - } - break; - default: - try_couple_nodes(q,vlink(p)); - math_character(nucleus(q)) = lig_replacement(lig); /* \.{=:} */ - subscr(q) = subscr(p); - supscr(q) = supscr(p); - subscr(p) = null ; - supscr(p) = null ; - flush_node(p); - break; - } - if (lig_type(lig) > 3) - return; - type(nucleus(q)) = math_char_node; - goto RESTART; - } - } - if (disable_kern_par == 0 && has_kern(cur_f, a)) { - /*tex todo: should this use mathkerns? */ - k = get_kern(cur_f, a, cur_c); - if (k != 0) { - p = new_kern(k); - reset_attributes(p, node_attr(q)); - couple_nodes(p,vlink(q)); - couple_nodes(q,p); - return; - } - } - } - } - } -} - -/*tex - - If the fonts for the left and right bits of a mathkern are not both new-style - fonts, then return a sentinel value meaning: please use old-style italic - correction placement - -*/ - -#define MATH_KERN_NOT_FOUND 0x7FFFFFFF - -/*tex - - This function tries to find the kern needed for proper cut-ins. The left side - doesn't move, but the right side does, so the first order of business is to - create a staggered fence line on the left side of the right character. - - The microsoft spec says that there are four quadrants, but the actual images - say. - -*/ - -static scaled math_kern_at(internal_font_number f, int c, int side, int v) -{ - int h, k, numkerns; - scaled *kerns_heights; - scaled kern = 0; - /*tex Known to exist: */ - charinfo *co = char_info(f, c); - numkerns = get_charinfo_math_kerns(co, side); - if (numkerns == 0) - return kern; - if (side == top_left_kern) { - kerns_heights = co->top_left_math_kern_array; - } else if (side == bottom_left_kern) { - kerns_heights = co->bottom_left_math_kern_array; - } else if (side == top_right_kern) { - kerns_heights = co->top_right_math_kern_array; - } else if (side == bottom_right_kern) { - kerns_heights = co->bottom_right_math_kern_array; - } else { - /*tex Not reached: */ - confusion("math_kern_at"); - kerns_heights = NULL; - } - if (v < kerns_heights[0]) - return kerns_heights[1]; - for (k = 0; k < numkerns; k++) { - h = kerns_heights[(k * 2)]; - kern = kerns_heights[(k * 2) + 1]; - if (h > v) { - return kern; - } - } - return kern; -} - -static scaled find_math_kern(internal_font_number l_f, int l_c, internal_font_number r_f, int r_c, int cmd, scaled shift) -{ - scaled corr_height_top = 0, corr_height_bot = 0; - scaled krn_l = 0, krn_r = 0, krn = 0; - if ((!do_new_math(l_f)) || (!do_new_math(r_f)) || (!char_exists(l_f,l_c)) || (!char_exists(r_f,r_c))) - return MATH_KERN_NOT_FOUND; - if (cmd == sup_mark_cmd) { - corr_height_top = char_height(l_f, l_c); - /*tex bottom of superscript */ - corr_height_bot = -char_depth(r_f, r_c) + shift; - krn_l = math_kern_at(l_f, l_c, top_right_kern, corr_height_top); - krn_r = math_kern_at(r_f, r_c, bottom_left_kern, corr_height_top); - krn = (krn_l + krn_r); - krn_l = math_kern_at(l_f, l_c, top_right_kern, corr_height_bot); - krn_r = math_kern_at(r_f, r_c, bottom_left_kern, corr_height_bot); - if ((krn_l + krn_r) < krn) - krn = (krn_l + krn_r); - return (krn); - } else if (cmd == sub_mark_cmd) { - /*tex top of subscript */ - corr_height_top = char_height(r_f, r_c) - shift; - corr_height_bot = -char_depth(l_f, l_c); - krn_l = math_kern_at(l_f, l_c, bottom_right_kern, corr_height_top); - krn_r = math_kern_at(r_f, r_c, top_left_kern, corr_height_top); - krn = (krn_l + krn_r); - krn_l = math_kern_at(l_f, l_c, bottom_right_kern, corr_height_bot); - krn_r = math_kern_at(r_f, r_c, top_left_kern, corr_height_bot); - if ((krn_l + krn_r) < krn) - krn = (krn_l + krn_r); - return (krn); - } else { - confusion("find_math_kern"); - } - /*tex Not reached: */ - return 0; -} - -/*tex Just a small helper: */ - -static pointer attach_hkern_to_new_hlist(pointer q, scaled delta2, halfword subtyp) -{ - pointer y; - pointer z = new_kern(delta2); - if (subtyp != 0) { - subtype(z) = subtyp; - } - reset_attributes(z, node_attr(q)); - if (new_hlist(q) == null) { - /*tex this is somewhat weird */ - new_hlist(q) = z; - } else { - y = new_hlist(q); - while (vlink(y) != null) - y = vlink(y); - couple_nodes(y,z); - } - return new_hlist(q); -} - -/*tex - - The purpose of |make_scripts(q,it)| is to attach the subscript and/or - superscript of noad |q| to the list that starts at |new_hlist(q)|, given that - subscript and superscript aren't both empty. The superscript will be - horizontally shifted over |delta1|, the subscript over |delta2|. - - We set |shift_down| and |shift_up| to the minimum amounts to shift the - baseline of subscripts and superscripts based on the given nucleus. - - Note: We need to look at a character but also at the first one in a sub list - and there we ignore leading kerns and glue. Elsewhere is code that removes - kerns assuming that is italic correction. The heuristics are unreliable for - the new fonts so eventualy there will be an option to ignore such - corrections. - -*/ - -#define analyze_script(init,su_n,su_f,su_c) do { \ - su_n = init; \ - if (su_n != null) { \ - if (math_script_char_mode_par > 0 && type(su_n) == math_char_node) { \ - fetch(su_n); \ - if (char_exists(cur_f, cur_c)) { \ - su_f = cur_f; \ - su_c = cur_c; \ - } else { \ - su_n = null; \ - } \ - } else if (math_script_box_mode_par > 0 && type(su_n) == sub_mlist_node) { \ - su_n = math_list(su_n); \ - while (su_n != null) { \ - if ((type(su_n) == kern_node) || (type(su_n) == glue_node)) { \ - su_n = vlink(su_n); \ - } else if (type(su_n) == simple_noad) { \ - su_n = nucleus(su_n); \ - if (type(su_n) == math_char_node) { \ - fetch(su_n); \ - if (char_exists(cur_f, cur_c)) { \ - su_f = cur_f; \ - su_c = cur_c; \ - } else { \ - su_n = null; \ - } \ - } else { \ - su_n = null; \ - } \ - break; \ - } else { \ - su_n = null; \ - break; \ - } \ - } \ - } else if (type(su_n) == sub_box_node) { \ - su_n = math_list(su_n); \ - if (su_n != null) { \ - if (type(su_n) == hlist_node) { \ - su_n = list_ptr(su_n); \ - } \ - if (su_n != null) { \ - if (math_script_box_mode_par == 2) { \ - while (su_n != null) { \ - if ((type(su_n) == kern_node) || (type(su_n) == glue_node)) { \ - su_n = vlink(su_n); \ - } else if (type(su_n) == glyph_node) { \ - if (char_exists(font(su_n), character(su_n))) { \ - su_f = font(su_n); \ - su_c = character(su_n); \ - } else { \ - su_n = null; \ - } \ - break ; \ - } else { \ - su_n = null; \ - break; \ - } \ - } \ - } else if (math_script_box_mode_par == 3) { \ - int boundary = -1; \ - while (su_n != null) { \ - if ((type(su_n) == boundary_node) && (subtype(su_n) == user_boundary)) { \ - boundary = boundary_value(su_n); \ - su_n = vlink(su_n); \ - } else if ((type(su_n) == kern_node) || (type(su_n) == glue_node)) { \ - su_n = vlink(su_n); \ - } else if ((boundary > -1) && (type(su_n) == glyph_node)) { \ - if (char_exists(font(su_n), character(su_n))) { \ - su_f = font(su_n); \ - su_c = character(su_n); \ - } else { \ - su_n = null; \ - } \ - break ; \ - } else { \ - su_n = null; \ - break; \ - } \ - } \ - } \ - } \ - } else { \ - su_n = null; \ - } \ - } else { \ - su_n = null; \ - } \ - } \ - } while (0) \ - -#define x_su_style(n,cur_style,su_style) \ - (noadoptionnosubscript(n) ? cur_style : su_style(cur_style)) - -static void make_scripts(pointer q, pointer p, scaled it, int cur_style, scaled supshift, scaled subshift) -{ - pointer x, y, z; - scaled shift_up, shift_down, clr; - scaled delta1, delta2; - halfword sub_n, sup_n, subtyp; - internal_font_number sub_f, sup_f; - int sub_c, sup_c; - sub_n = null; - sup_n = null; - sub_f = 0; - sup_f = 0; - sub_c = 0; - sup_c = 0; - delta1 = it; - delta2 = 0; - subtyp = 0; - switch (type(nucleus(q))) { - case math_char_node: - case math_text_char_node: - if ((subscr(q) == null) && (delta1 != 0)) { - /*tex todo: selective italic correction */ - x = new_kern(delta1); - subtype(x) = italic_kern; - reset_attributes(x, node_attr(nucleus(q))); - couple_nodes(p,x); - delta1 = 0; - } - } - assign_new_hlist(q, p); - if (is_char_node(p)) { - shift_up = 0; - shift_down = 0; - } else { - z = hpack(p, 0, additional, -1); - shift_up = height(z) - sup_shift_drop(cur_style); /* r18 */ - shift_down = depth(z) + sub_shift_drop(cur_style); /* r19 */ - list_ptr(z) = null; - flush_node(z); - } - if (is_char_node(p)) { - /*tex We look at the subscript character (_i) or first character in a list (_{ij}). */ - analyze_script(subscr(q),sub_n,sub_f,sub_c); - /*tex We look at the superscript character (^i) or first character in a list (^{ij}). */ - analyze_script(supscr(q),sup_n,sup_f,sup_c); - } - if (supscr(q) == null) { - /*tex - - Construct a subscript box |x| when there is no superscript. When - there is a subscript without a superscript, the top of the subscript - should not exceed the baseline plus four-fifths of the x-height. - - */ - x = clean_box(subscr(q), (noadoptionnosubscript(q) ? cur_style : sub_style(cur_style)), cur_style, math_sub_list); - width(x) = width(x) + space_after_script(cur_style); - switch (math_scripts_mode_par) { - case 1: - shift_down = sub_shift_down(cur_style) ; - break; - case 2: - shift_down = sub_sup_shift_down(cur_style) ; - break; - case 3: - shift_down = sub_sup_shift_down(cur_style) ; - break; - case 4: - shift_down = sub_shift_down(cur_style) + half(sub_sup_shift_down(cur_style)-sub_shift_down(cur_style)) ; - break; - case 5: - shift_down = sub_shift_down(cur_style) ; - break; - default: - if (shift_down < sub_shift_down(cur_style)) - shift_down = sub_shift_down(cur_style); - clr = height(x) - sub_top_max(cur_style); - if (shift_down < clr) - shift_down = clr; - break; - } - shift_amount(x) = shift_down; - /*tex Now find and correct for horizontal shift. */ - subtyp = 0; - if (sub_n != null) { - delta2 = find_math_kern(font(p), character(p),sub_f,sub_c,sub_mark_cmd, shift_down); - if (delta2 == MATH_KERN_NOT_FOUND) { - delta2 = subshift ; - } else { - delta2 = delta2 + subshift ; - subtyp = font_kern; - } - } else { - delta2 = subshift ; - } - if (delta2 != 0) { - p = attach_hkern_to_new_hlist(q, delta2, subtyp); - } - } else { - /*tex - - Construct a superscript box |x|. The bottom of a superscript should - never descend below the baseline plus one-fourth of the x-height. - - */ - x = clean_box(supscr(q), (noadoptionnosupscript(q) ? cur_style : sup_style(cur_style)), cur_style, math_sup_list); - width(x) = width(x) + space_after_script(cur_style); - switch (math_scripts_mode_par) { - case 1: - shift_up = sup_shift_up(cur_style); - break; - case 2: - shift_up = sup_shift_up(cur_style) ; - break; - case 3: - shift_up = sup_shift_up(cur_style) + sub_sup_shift_down(cur_style) - sub_shift_down(cur_style) ; - break; - case 4: - shift_up = sup_shift_up(cur_style) + half(sub_sup_shift_down(cur_style)-sub_shift_down(cur_style)) ; - break; - case 5: - shift_up = sup_shift_up(cur_style) + sub_sup_shift_down(cur_style)-sub_shift_down(cur_style) ; - break; - default: - clr = sup_shift_up(cur_style); - if (shift_up < clr) - shift_up = clr; - clr = depth(x) + sup_bottom_min(cur_style); - if (shift_up < clr) - shift_up = clr; - break; - } - if (subscr(q) == null) { - shift_amount(x) = -shift_up; - /*tex Now find and correct for horizontal shift. */ - subtyp = 0; - if (sup_n != null) { - clr = find_math_kern(font(p),character(p),sup_f,sup_c,sup_mark_cmd,shift_up); - if (clr == MATH_KERN_NOT_FOUND) { - clr = supshift ; - } else { - clr = clr + supshift ; - subtyp = font_kern; - } - } else { - clr = supshift; - } - if (clr != 0) { - p = attach_hkern_to_new_hlist(q, clr, subtyp); - } - } else { - /*tex - - Construct a sub/superscript combination box |x|, with the - superscript offset by |delta|. When both subscript and - superscript are present, the subscript must be separated from the - superscript by at least four times |default_rule_thickness| If - this condition would be violated, the subscript moves down, after - which both subscript and superscript move up so that the bottom - of the superscript is at least as high as the baseline plus - four-fifths of the x-height. - - */ - y = clean_box(subscr(q), (noadoptionnosubscript(q) ? cur_style : sub_style(cur_style)), cur_style, math_sub_list); - width(y) = width(y) + space_after_script(cur_style); - switch (math_scripts_mode_par) { - case 1: - shift_down = sub_shift_down(cur_style) ; - break; - case 2: - shift_down = sub_sup_shift_down(cur_style) ; - break; - case 3: - shift_down = sub_sup_shift_down(cur_style) ; - break; - case 4: - shift_down = sub_shift_down(cur_style) + half(sub_sup_shift_down(cur_style)-sub_shift_down(cur_style)) ; - break; - case 5: - shift_down = sub_shift_down(cur_style) ; - break; - default: - if (shift_down < sub_sup_shift_down(cur_style)) - shift_down = sub_sup_shift_down(cur_style); - clr = subsup_vgap(cur_style) - ((shift_up - depth(x)) - (height(y) - shift_down)); - if (clr > 0) { - shift_down = shift_down + clr; - clr = sup_sub_bottom_max(cur_style) - (shift_up - depth(x)); - if (clr > 0) { - shift_up = shift_up + clr; - shift_down = shift_down - clr; - } - } - break; - } - /*tex Now find and correct for horizontal shift. */ - subtyp = 0; - if (sub_n != null) { - delta2 = find_math_kern(font(p), character(p),sub_f,sub_c,sub_mark_cmd, shift_down); - if (delta2 == MATH_KERN_NOT_FOUND) { - delta2 = subshift ; - } else { - delta2 = delta2 + subshift ; - subtyp = font_kern; - } - } else { - delta2 = subshift ; - } - if (delta2 != 0) { - p = attach_hkern_to_new_hlist(q, delta2, subtyp); - } - /*tex - - Now the horizontal shift for the superscript; the superscript is - also to be shifted by |delta1| (the italic correction). - - */ - clr = MATH_KERN_NOT_FOUND; - if (sup_n != null) { - clr = find_math_kern(font(p),character(p),sup_f,sup_c,sup_mark_cmd,shift_up); - } - /*tex - - The delta can already have been applied and now be 0. - - */ - if (delta2 == MATH_KERN_NOT_FOUND) - delta2 = - supshift ; - else - delta2 = delta2 - supshift ; - if (clr != MATH_KERN_NOT_FOUND) { - shift_amount(x) = clr + delta1 - delta2; - } else { - shift_amount(x) = delta1 - delta2; - } - /*tex todo: only if kern != 0 */ - p = new_kern((shift_up - depth(x)) - (height(y) - shift_down)); - reset_attributes(p, node_attr(q)); - couple_nodes(x,p); - couple_nodes(p,y); - /*tex We end up with funny dimensions. */ - x = vpackage(x, 0, additional, max_dimen, math_direction_par); - reset_attributes(x, node_attr(q)); - subtype(x) = math_scripts_list; - shift_amount(x) = shift_down; - } - } - if (new_hlist(q) == null) { - new_hlist(q) = x; - } else { - p = new_hlist(q); - while (vlink(p) != null) - p = vlink(p); - couple_nodes(p,x); - } - if (subscr(q) != null) { - math_list(subscr(q)) = null; - flush_node(subscr(q)); - subscr(q) = null; - } - if (supscr(q) != null) { - math_list(supscr(q)) = null; - flush_node(supscr(q)); - supscr(q) = null; - } -} - -/*tex - - The |make_left_right| function constructs a left or right delimiter of the - required size and returns the value |open_noad| or |close_noad|. The - |left_noad_side| and |right_noad_side| will both be based on the original - |style|, so they will have consistent sizes. - -*/ - -static small_number make_left_right(pointer q, int style, scaled max_d, scaled max_h) -{ - scaled delta; - pointer tmp, lst; - scaled ic = 0; - boolean stack = false; - boolean axis = false; - int same = subtype(q); - setup_cur_size(style); - if ((delimiterheight(q)!=0) || (delimiterdepth(q)!=0)) { - - delta = delimiterheight(q) + delimiterdepth(q); - tmp = do_delimiter(q, delimiter(q), cur_size, delta, false, style, false, &stack, &ic, &same); - delimiteritalic(q) = ic; - /*tex - - Beware, a stacked delimiter has a shift but no corrected height/depth - (yet). - - */ - if (stack) { - shift_amount(tmp) = delimiterdepth(q); - } - if (delimiterexact(q)) { - delimiterheight(q) = height(tmp) - shift_amount(tmp); - delimiterdepth(q) = depth(tmp) + shift_amount(tmp); - } - if (delimiteraxis(q)) { - delimiterheight(q) += math_axis_size(cur_size); - delimiterdepth(q) -= math_axis_size(cur_size); - shift_amount(tmp) -= math_axis_size(cur_size); - } - lst = new_node(hlist_node,0); - reset_attributes(lst, node_attr(q)); - box_dir(lst) = dir_TLT ; - height(lst) = delimiterheight(q); - depth(lst) = delimiterdepth(q); - width(lst) = width(tmp); - list_ptr(lst) = tmp; - tmp = lst ; - } else { - axis = ! delimiternoaxis(q); - delta = get_delimiter_height(max_d,max_h,axis); - tmp = do_delimiter(q, delimiter(q), cur_size, delta, false, style, axis, &stack, &ic, &same); - delimiteritalic(q) = ic; - } - delimiter(q) = null; - assign_new_hlist(q, tmp); - delimitersamesize(q) = same; - if (delimiterclass(q) >= ord_noad_type) { - if (delimiterclass(q) <= inner_noad_type) { - return delimiterclass(q); - } else { - return ord_noad_type; - } - } else if (subtype(q) == left_noad_side) { - return open_noad_type; - } else { - return close_noad_type; - } -} - -#define TEXT_STYLES(A,B) do { \ - def_math_param(A,display_style,(B),level_one); \ - def_math_param(A,cramped_display_style,(B),level_one); \ - def_math_param(A,text_style,(B),level_one); \ - def_math_param(A,cramped_text_style,(B),level_one); \ - } while (0) - -#define SCRIPT_STYLES(A,B) do { \ - def_math_param(A,script_style,(B),level_one); \ - def_math_param(A,cramped_script_style,(B),level_one); \ - def_math_param(A,script_script_style,(B),level_one); \ - def_math_param(A,cramped_script_script_style,(B),level_one); \ - } while (0) - -#define ALL_STYLES(A,B) do { \ - TEXT_STYLES(A,(B)); \ - SCRIPT_STYLES(A,(B)); \ - } while (0) - -#define SPLIT_STYLES(A,B,C) do { \ - TEXT_STYLES(A,(B)); \ - SCRIPT_STYLES(A,(C)); \ - } while (0) - -void initialize_math_spacing(void) -{ - ALL_STYLES (math_param_ord_ord_spacing, 0); - ALL_STYLES (math_param_ord_op_spacing, thin_mu_skip_code); - SPLIT_STYLES (math_param_ord_bin_spacing, med_mu_skip_code, 0); - SPLIT_STYLES (math_param_ord_rel_spacing, thick_mu_skip_code, 0); - ALL_STYLES (math_param_ord_open_spacing, 0); - ALL_STYLES (math_param_ord_close_spacing, 0); - ALL_STYLES (math_param_ord_punct_spacing, 0); - SPLIT_STYLES (math_param_ord_inner_spacing, thin_mu_skip_code, 0); - - ALL_STYLES (math_param_op_ord_spacing, thin_mu_skip_code); - ALL_STYLES (math_param_op_op_spacing, thin_mu_skip_code); - ALL_STYLES (math_param_op_bin_spacing, 0); - SPLIT_STYLES (math_param_op_rel_spacing, thick_mu_skip_code, 0); - ALL_STYLES (math_param_op_open_spacing, 0); - ALL_STYLES (math_param_op_close_spacing, 0); - ALL_STYLES (math_param_op_punct_spacing, 0); - SPLIT_STYLES (math_param_op_inner_spacing, thin_mu_skip_code, 0); - - SPLIT_STYLES (math_param_bin_ord_spacing, med_mu_skip_code, 0); - SPLIT_STYLES (math_param_bin_op_spacing, med_mu_skip_code, 0); - ALL_STYLES (math_param_bin_bin_spacing, 0); - ALL_STYLES (math_param_bin_rel_spacing, 0); - SPLIT_STYLES (math_param_bin_open_spacing, med_mu_skip_code, 0); - ALL_STYLES (math_param_bin_close_spacing, 0); - ALL_STYLES (math_param_bin_punct_spacing, 0); - SPLIT_STYLES (math_param_bin_inner_spacing, med_mu_skip_code, 0); - - SPLIT_STYLES (math_param_rel_ord_spacing, thick_mu_skip_code, 0); - SPLIT_STYLES (math_param_rel_op_spacing, thick_mu_skip_code, 0); - ALL_STYLES (math_param_rel_bin_spacing, 0); - ALL_STYLES (math_param_rel_rel_spacing, 0); - SPLIT_STYLES (math_param_rel_open_spacing, thick_mu_skip_code, 0); - ALL_STYLES (math_param_rel_close_spacing, 0); - ALL_STYLES (math_param_rel_punct_spacing, 0); - SPLIT_STYLES (math_param_rel_inner_spacing, thick_mu_skip_code, 0); - - ALL_STYLES (math_param_open_ord_spacing, 0); - ALL_STYLES (math_param_open_op_spacing, 0); - ALL_STYLES (math_param_open_bin_spacing, 0); - ALL_STYLES (math_param_open_rel_spacing, 0); - ALL_STYLES (math_param_open_open_spacing, 0); - ALL_STYLES (math_param_open_close_spacing, 0); - ALL_STYLES (math_param_open_punct_spacing, 0); - ALL_STYLES (math_param_open_inner_spacing, 0); - - ALL_STYLES (math_param_close_ord_spacing, 0); - ALL_STYLES (math_param_close_op_spacing, thin_mu_skip_code); - SPLIT_STYLES (math_param_close_bin_spacing, med_mu_skip_code, 0); - SPLIT_STYLES (math_param_close_rel_spacing, thick_mu_skip_code, 0); - ALL_STYLES (math_param_close_open_spacing, 0); - ALL_STYLES (math_param_close_close_spacing, 0); - ALL_STYLES (math_param_close_punct_spacing, 0); - SPLIT_STYLES (math_param_close_inner_spacing, thin_mu_skip_code, 0); - - SPLIT_STYLES (math_param_punct_ord_spacing, thin_mu_skip_code, 0); - SPLIT_STYLES (math_param_punct_op_spacing, thin_mu_skip_code, 0); - ALL_STYLES (math_param_punct_bin_spacing, 0); - SPLIT_STYLES (math_param_punct_rel_spacing, thin_mu_skip_code, 0); - SPLIT_STYLES (math_param_punct_open_spacing, thin_mu_skip_code, 0); - SPLIT_STYLES (math_param_punct_close_spacing, thin_mu_skip_code, 0); - SPLIT_STYLES (math_param_punct_punct_spacing, thin_mu_skip_code, 0); - SPLIT_STYLES (math_param_punct_inner_spacing, thin_mu_skip_code, 0); - - SPLIT_STYLES (math_param_inner_ord_spacing, thin_mu_skip_code, 0); - ALL_STYLES (math_param_inner_op_spacing, thin_mu_skip_code); - SPLIT_STYLES (math_param_inner_bin_spacing, med_mu_skip_code, 0); - SPLIT_STYLES (math_param_inner_rel_spacing, thick_mu_skip_code, 0); - SPLIT_STYLES (math_param_inner_open_spacing, thin_mu_skip_code, 0); - ALL_STYLES (math_param_inner_close_spacing, 0); - SPLIT_STYLES (math_param_inner_punct_spacing, thin_mu_skip_code, 0); - SPLIT_STYLES (math_param_inner_inner_spacing, thin_mu_skip_code, 0); -} - -#define both_types(A,B) ((A)*16+(B)) - -static pointer math_spacing_glue(int l_type, int r_type, int mstyle, scaled mmu) -{ - int x = -1; - pointer z = null; - if (l_type == op_noad_type_limits || l_type == op_noad_type_no_limits) - l_type = op_noad_type_normal; - if (r_type == op_noad_type_limits || r_type == op_noad_type_no_limits) - r_type = op_noad_type_normal; - switch (both_types(l_type, r_type)) { - case both_types(ord_noad_type, ord_noad_type ): x = get_math_param(math_param_ord_ord_spacing,mstyle); break; - case both_types(ord_noad_type, op_noad_type_normal): x = get_math_param(math_param_ord_op_spacing,mstyle); break; - case both_types(ord_noad_type, bin_noad_type ): x = get_math_param(math_param_ord_bin_spacing,mstyle); break; - case both_types(ord_noad_type, rel_noad_type ): x = get_math_param(math_param_ord_rel_spacing,mstyle); break; - case both_types(ord_noad_type, open_noad_type ): x = get_math_param(math_param_ord_open_spacing,mstyle); break; - case both_types(ord_noad_type, close_noad_type ): x = get_math_param(math_param_ord_close_spacing,mstyle); break; - case both_types(ord_noad_type, punct_noad_type ): x = get_math_param(math_param_ord_punct_spacing,mstyle); break; - case both_types(ord_noad_type, inner_noad_type ): x = get_math_param(math_param_ord_inner_spacing,mstyle); break; - case both_types(op_noad_type_normal, ord_noad_type ): x = get_math_param(math_param_op_ord_spacing,mstyle); break; - case both_types(op_noad_type_normal, op_noad_type_normal): x = get_math_param(math_param_op_op_spacing,mstyle); break; - /* shouldn't happen */ - case both_types(op_noad_type_normal, bin_noad_type ): x = get_math_param(math_param_op_bin_spacing,mstyle); break; - /* */ - case both_types(op_noad_type_normal, rel_noad_type ): x = get_math_param(math_param_op_rel_spacing,mstyle); break; - case both_types(op_noad_type_normal, open_noad_type ): x = get_math_param(math_param_op_open_spacing,mstyle); break; - case both_types(op_noad_type_normal, close_noad_type ): x = get_math_param(math_param_op_close_spacing,mstyle); break; - case both_types(op_noad_type_normal, punct_noad_type ): x = get_math_param(math_param_op_punct_spacing,mstyle); break; - case both_types(op_noad_type_normal, inner_noad_type ): x = get_math_param(math_param_op_inner_spacing,mstyle); break; - case both_types(bin_noad_type, ord_noad_type ): x = get_math_param(math_param_bin_ord_spacing,mstyle); break; - case both_types(bin_noad_type, op_noad_type_normal): x = get_math_param(math_param_bin_op_spacing,mstyle); break; - /* shouldn't happen */ - case both_types(bin_noad_type, bin_noad_type ): x = get_math_param(math_param_bin_bin_spacing,mstyle); break; - case both_types(bin_noad_type, rel_noad_type ): x = get_math_param(math_param_bin_rel_spacing,mstyle); break; - /* */ - case both_types(bin_noad_type, open_noad_type ): x = get_math_param(math_param_bin_open_spacing,mstyle); break; - /* shouldn't happen */ - case both_types(bin_noad_type, close_noad_type ): x = get_math_param(math_param_bin_close_spacing,mstyle); break; - case both_types(bin_noad_type, punct_noad_type ): x = get_math_param(math_param_bin_punct_spacing,mstyle); break; - /* */ - case both_types(bin_noad_type, inner_noad_type ): x = get_math_param(math_param_bin_inner_spacing,mstyle); break; - case both_types(rel_noad_type, ord_noad_type ): x = get_math_param(math_param_rel_ord_spacing,mstyle); break; - case both_types(rel_noad_type, op_noad_type_normal): x = get_math_param(math_param_rel_op_spacing,mstyle); break; - /* shouldn't happen */ - case both_types(rel_noad_type, bin_noad_type ): x = get_math_param(math_param_rel_bin_spacing,mstyle); break; - /* */ - case both_types(rel_noad_type, rel_noad_type ): x = get_math_param(math_param_rel_rel_spacing,mstyle); break; - case both_types(rel_noad_type, open_noad_type ): x = get_math_param(math_param_rel_open_spacing,mstyle); break; - case both_types(rel_noad_type, close_noad_type ): x = get_math_param(math_param_rel_close_spacing,mstyle); break; - case both_types(rel_noad_type, punct_noad_type ): x = get_math_param(math_param_rel_punct_spacing,mstyle); break; - case both_types(rel_noad_type, inner_noad_type ): x = get_math_param(math_param_rel_inner_spacing,mstyle); break; - case both_types(open_noad_type, ord_noad_type ): x = get_math_param(math_param_open_ord_spacing,mstyle); break; - case both_types(open_noad_type, op_noad_type_normal): x = get_math_param(math_param_open_op_spacing,mstyle); break; - /* shouldn't happen */ - case both_types(open_noad_type, bin_noad_type ): x = get_math_param(math_param_open_bin_spacing,mstyle); break; - /* */ - case both_types(open_noad_type, rel_noad_type ): x = get_math_param(math_param_open_rel_spacing,mstyle); break; - case both_types(open_noad_type, open_noad_type ): x = get_math_param(math_param_open_open_spacing,mstyle); break; - case both_types(open_noad_type, close_noad_type ): x = get_math_param(math_param_open_close_spacing,mstyle); break; - case both_types(open_noad_type, punct_noad_type ): x = get_math_param(math_param_open_punct_spacing,mstyle); break; - case both_types(open_noad_type, inner_noad_type ): x = get_math_param(math_param_open_inner_spacing,mstyle); break; - case both_types(close_noad_type, ord_noad_type ): x = get_math_param(math_param_close_ord_spacing,mstyle); break; - case both_types(close_noad_type, op_noad_type_normal): x = get_math_param(math_param_close_op_spacing,mstyle); break; - case both_types(close_noad_type, bin_noad_type ): x = get_math_param(math_param_close_bin_spacing,mstyle); break; - case both_types(close_noad_type, rel_noad_type ): x = get_math_param(math_param_close_rel_spacing,mstyle); break; - case both_types(close_noad_type, open_noad_type ): x = get_math_param(math_param_close_open_spacing,mstyle); break; - case both_types(close_noad_type, close_noad_type ): x = get_math_param(math_param_close_close_spacing,mstyle); break; - case both_types(close_noad_type, punct_noad_type ): x = get_math_param(math_param_close_punct_spacing,mstyle); break; - case both_types(close_noad_type, inner_noad_type ): x = get_math_param(math_param_close_inner_spacing,mstyle); break; - case both_types(punct_noad_type, ord_noad_type ): x = get_math_param(math_param_punct_ord_spacing,mstyle); break; - case both_types(punct_noad_type, op_noad_type_normal): x = get_math_param(math_param_punct_op_spacing,mstyle); break; - /* shouldn't happen */ - case both_types(punct_noad_type, bin_noad_type ): x = get_math_param(math_param_punct_bin_spacing,mstyle); break; - /* */ - case both_types(punct_noad_type, rel_noad_type ): x = get_math_param(math_param_punct_rel_spacing,mstyle); break; - case both_types(punct_noad_type, open_noad_type ): x = get_math_param(math_param_punct_open_spacing,mstyle); break; - case both_types(punct_noad_type, close_noad_type ): x = get_math_param(math_param_punct_close_spacing,mstyle); break; - case both_types(punct_noad_type, punct_noad_type ): x = get_math_param(math_param_punct_punct_spacing,mstyle); break; - case both_types(punct_noad_type, inner_noad_type ): x = get_math_param(math_param_punct_inner_spacing,mstyle); break; - case both_types(inner_noad_type, ord_noad_type ): x = get_math_param(math_param_inner_ord_spacing,mstyle); break; - case both_types(inner_noad_type, op_noad_type_normal): x = get_math_param(math_param_inner_op_spacing,mstyle); break; - case both_types(inner_noad_type, bin_noad_type ): x = get_math_param(math_param_inner_bin_spacing,mstyle); break; - case both_types(inner_noad_type, rel_noad_type ): x = get_math_param(math_param_inner_rel_spacing,mstyle); break; - case both_types(inner_noad_type, open_noad_type ): x = get_math_param(math_param_inner_open_spacing,mstyle); break; - case both_types(inner_noad_type, close_noad_type ): x = get_math_param(math_param_inner_close_spacing,mstyle); break; - case both_types(inner_noad_type, punct_noad_type ): x = get_math_param(math_param_inner_punct_spacing,mstyle); break; - case both_types(inner_noad_type, inner_noad_type ): x = get_math_param(math_param_inner_inner_spacing,mstyle); break; - } - if (x < 0) { - confusion("mathspacing"); - } - if (x != 0) { - if (x <= thick_mu_skip_code) { - /*tex trap thin/med/thick settings cf.\ old \TeX */ - z = math_glue(glue_par(x), mmu); - /*tex store a symbolic subtype */ - subtype(z) = (quarterword) (x + 1); - } else { - z = math_glue(x, mmu); - } - } - return z; -} - -static pointer check_nucleus_complexity(halfword q, scaled * delta, int cur_style, int *same) -{ - pointer p = null; - pointer t = null; - if (same != NULL) { - *same = 0; - } - switch (type(nucleus(q))) { - case math_char_node: - case math_text_char_node: - fetch(nucleus(q)); - if (char_exists(cur_f, cur_c)) { - /*tex we could look at neighbours */ - if (do_new_math(cur_f)) { - /*tex cf spec only the last one */ - *delta = 0 ; - } else { - *delta = char_italic(cur_f, cur_c); - } - p = new_glyph(cur_f, cur_c); - protect_glyph(p); - reset_attributes(p, node_attr(nucleus(q))); - if (do_new_math(cur_f)) { - if (get_char_cat_code(cur_c) == 11) { - /*tex no italic correction in mid-word of text font */ - *delta = 0; - } - } else { - /*tex no italic correction in mid-word of text font */ - if (((type(nucleus(q))) == math_text_char_node) && (space(cur_f) != 0)) { - *delta = 0; - } - } - /*tex so we only add italic correction when we have no scripts */ - if ((subscr(q) == null) && (supscr(q) == null) && (*delta != 0)) { - pointer x = new_kern(*delta); - subtype(x) = italic_kern; - reset_attributes(x, node_attr(nucleus(q))); - couple_nodes(p,x); - *delta = 0; - } else if (do_new_math(cur_f)) { - /*tex Needs checking but looks ok. It must be more selective. */ - *delta = char_italic(cur_f, cur_c); - } - } - break; - case sub_box_node: - p = math_list(nucleus(q)); - break; - case sub_mlist_node: - t = math_list(nucleus(q)); - /*tex Recursive call: */ - mlist_to_hlist(t, false, cur_style); - if (same != NULL && type(t) == fence_noad && delimitersamesize(t)) { - *same = delimitersamesize(t) ; - } - setup_cur_size(cur_style); - p = hpack(vlink(temp_head), 0, additional, -1); - reset_attributes(p, node_attr(nucleus(q))); - break; - default: - confusion("mlist2"); - } - return p; -} - -/*tex - - Here is the overall plan of |mlist_to_hlist|, and the list of its local - variables. - -*/ - -void mlist_to_hlist(pointer mlist, boolean penalties, int cur_style) -{ - /*tex runs through the mlist */ - pointer q = mlist; - /*tex the most recent noad preceding |q| */ - pointer r = null; - /*tex tuck global parameter away as local variable */ - int style = cur_style; - /*tex the |type| of noad |r|, or |op_noad| if |r=null| */ - int r_type = simple_noad; - /*tex the |subtype| of noad |r| if |r_type| is |fence_noad| */ - int r_subtype = op_noad_type_normal; - /*tex the effective |type| of noad |q| during the second pass */ - int t; - /*tex the effective |subtype| of noad |q| during the second pass */ - int t_subtype; - pointer p = null; - pointer pp = null; - pointer z = null; - halfword nxt ; - int same = 0; - /*tex a penalty to be inserted */ - int pen; - /*tex a penalty to be inserted */ - int prepen; - /*tex maximum height of the list translated so far */ - scaled max_hl = 0; - /*tex maximum depth of the list translated so far */ - scaled max_d = 0; - /*tex italic correction offset for subscript and superscript */ - scaled delta; - /*tex the math unit width corresponding to |cur_size| */ - scaled cur_mu; - r_subtype = op_noad_type_normal; - setup_cur_size(cur_style); - cur_mu = x_over_n(get_math_quad_size(cur_size), 18); - if (math_penalties_mode_par) { - /*tex - We could do this via the callback but it's nice to have it as - primitive too. - */ - penalties = 1; - } - while (q != null) { - /*tex - - We use the fact that no character nodes appear in an mlist, hence the - field |type(q)| is always present.One of the things we must do on the - first pass is change a |bin_noad| to an |ord_noad| if the |bin_noad| - is not in the context of a binary operator. The values of |r| and - |r_type| make this fairly easy. - - */ - RESWITCH: - delta = 0; - nxt = vlink(q); - switch (type(q)) { - case simple_noad: - switch (subtype(q)) { - case bin_noad_type: - switch (r_type) { - case simple_noad: - switch (r_subtype) { - case bin_noad_type: - case op_noad_type_normal: - case op_noad_type_limits: - case op_noad_type_no_limits: - case rel_noad_type: - case open_noad_type: - case punct_noad_type: - subtype(q) = ord_noad_type; - goto RESWITCH; - break; - } - break; - case fence_noad: - if (r_subtype == left_noad_side) { - /*tex So these can best be the same size. */ - subtype(q) = ord_noad_type; - goto RESWITCH; - } - break; - } - break; - case over_noad_type: - make_over(q, cur_style, cur_size, math_rules_fam_par); - break; - case under_noad_type: - make_under(q, cur_style, cur_size, math_rules_fam_par); - break; - case vcenter_noad_type: - make_vcenter(q); - break; - case rel_noad_type: - case close_noad_type: - case punct_noad_type: - if (r_type == simple_noad && r_subtype == bin_noad_type) { - /*tex Assumes the same size; can't this go. */ - type(r) = simple_noad; - subtype(r) = ord_noad_type; - } - break; - case op_noad_type_normal: - case op_noad_type_limits: - case op_noad_type_no_limits: - delta = make_op(q, cur_style); - if ((subtype(q) == op_noad_type_limits) || (subtype(q) == op_noad_type_no_limits)) - goto CHECK_DIMENSIONS; - break; - case ord_noad_type: - make_ord(q); - break; - case open_noad_type: - case inner_noad_type: - break; - } - break; - case fence_noad: - if (subtype(q) != left_noad_side) { - if (r_type == simple_noad && r_subtype == bin_noad_type) { - /*tex Assumes the same size. */ - type(r) = simple_noad; - subtype(r) = ord_noad_type; - } - } - goto DONE_WITH_NOAD; - break; - case fraction_noad: - make_fraction(q, cur_style); - goto CHECK_DIMENSIONS; - break; - case radical_noad: - if (subtype(q) == 7) - make_hextension(q, cur_style); - else if (subtype(q) == 6) - make_delimiter_over(q, cur_style); - else if (subtype(q) == 5) - make_delimiter_under(q, cur_style); - else if (subtype(q) == 4) - make_over_delimiter(q, cur_style); - else if (subtype(q) == 3) - make_under_delimiter(q, cur_style); - else - make_radical(q, cur_style); - break; - case accent_noad: - make_math_accent(q, cur_style); - break; - case style_node: - cur_style = subtype(q); - setup_cur_size(cur_style); - cur_mu = x_over_n(get_math_quad_style(cur_style), 18); - goto DONE_WITH_NODE; - break; - case choice_node: - switch (cur_style / 2) { - case 0: - /*tex |display_style=0| */ - choose_mlist(display_mlist); - break; - case 1: - /*tex |text_style=2| */ - choose_mlist(text_mlist); - break; - case 2: - /*tex |script_style=4| */ - choose_mlist(script_mlist); - break; - case 3: - /*tex |script_script_style=6| */ - choose_mlist(script_script_mlist); - break; - } - flush_node_list(display_mlist(q)); - flush_node_list(text_mlist(q)); - flush_node_list(script_mlist(q)); - flush_node_list(script_script_mlist(q)); - type(q) = style_node; - subtype(q) = (quarterword) cur_style; - if (p != null) { - z = vlink(q); - couple_nodes(q,p); - while (vlink(p) != null) - p = vlink(p); - try_couple_nodes(p,z); - } - goto DONE_WITH_NODE; - break; - case ins_node: - case mark_node: - case adjust_node: - case boundary_node: - case whatsit_node: - case penalty_node: - case disc_node: - goto DONE_WITH_NODE; - break; - case rule_node: - if (height(q) > max_hl) - max_hl = height(q); - if (depth(q) > max_d) - max_d = depth(q); - goto DONE_WITH_NODE; - break; - case glue_node: - /*tex - - Conditional math glue (`\.{\\nonscript}') results in a - |glue_node| pointing to |zero_glue|, with - |subtype(q)=cond_math_glue|; in such a case the node - following will be eliminated if it is a glue or kern node and - if the current size is different from |text_size|. - - Unconditional math glue (`\.{\\muskip}') is converted to - normal glue by multiplying the dimensions by |cur_mu|. - - */ - if (subtype(q) == mu_glue) { - math_glue_to_glue(q, cur_mu); - } else if ((cur_size != text_size) && (subtype(q) == cond_math_glue)) { - p = vlink(q); - if (p != null) - if ((type(p) == glue_node) || (type(p) == kern_node)) { - if (vlink(p) != null) { - couple_nodes(q,vlink(p)); - vlink(p) = null; - } else { - vlink(q) = null; - } - flush_node_list(p); - } - } - goto DONE_WITH_NODE; - break; - case kern_node: - math_kern(q, cur_mu); - goto DONE_WITH_NODE; - break; - default: - confusion("mlist1"); - } - /*tex - - When we get to the following part of the program, we have ``fallen - through'' from cases that did not lead to |check_dimensions| or - |done_with_noad| or |done_with_node|. Thus, |q|~points to a noad - whose nucleus may need to be converted to an hlist, and whose - subscripts and superscripts need to be appended if they are present. - - If |nucleus(q)| is not a |math_char|, the variable |delta| is the - amount by which a superscript should be moved right with respect to a - subscript when both are present. - - */ - same = 0 ; - p = check_nucleus_complexity(q, &delta, cur_style, &same); - if (same) { - noadextra4(q) = same ; - } - if ((subscr(q) == null) && (supscr(q) == null)) { - /*tex - - Adding italic correction here is kind of fuzzy because some - characters already have that built in. However, we also add it in - the scripts so if it's optional here it also should be there. - - */ - if (nxt && (math_italics_mode_par > 0) && (delta != 0)) { - if (type(nxt) == simple_noad) { - switch (subtype(nxt)) { - case ord_noad_type: - case bin_noad_type: - case rel_noad_type: - case open_noad_type: - case close_noad_type: - case punct_noad_type: - delta = 0; - break; - case inner_noad_type: - if (! delimitermodeitalics) { - delta = 0; - } - break; - case op_noad_type_normal: - case op_noad_type_limits: - case op_noad_type_no_limits: - case under_noad_type: - case over_noad_type: - case vcenter_noad_type: - break; - default: - break; - } - } - if (delta != 0) { - pointer d = new_kern(delta); - subtype(d) = italic_kern; - reset_attributes(d, node_attr(q)); - couple_nodes(p,d); - } - } - assign_new_hlist(q, p); - } else { - /*tex top, bottom */ - make_scripts(q, p, delta, cur_style, 0, 0); - } - CHECK_DIMENSIONS: - z = hpack(new_hlist(q), 0, additional, -1); - if (height(z) > max_hl) - max_hl = height(z); - if (depth(z) > max_d) - max_d = depth(z); - list_ptr(z) = null; - /*tex only drop the \.{\\hbox} */ - flush_node(z); - DONE_WITH_NOAD: - r = q; - r_type = type(r); - r_subtype = subtype(r); - if (r_type == fence_noad) { - r_subtype = left_noad_side; - cur_style = style; - setup_cur_size(cur_style); - /*tex style */ - cur_mu = x_over_n(get_math_quad_size(cur_size), 18); - } - DONE_WITH_NODE: - q = vlink(q); - } - if (r_type == simple_noad && r_subtype == bin_noad_type) { - type(r) = simple_noad; - subtype(r) = ord_noad_type; - } - /*tex - - Make a second pass over the mlist, removing all noads and inserting the - proper spacing and penalties. - - We have now tied up all the loose ends of the first pass of - |mlist_to_hlist|. The second pass simply goes through and hooks - everything together with the proper glue and penalties. It also handles - the |fence_noad|s that might be present, since |max_hl| and |max_d| are - now known. Variable |p| points to a node at the current end of the final - hlist. - - */ - p = temp_head; - vlink(p) = null; - q = mlist; - r_type = 0; - r_subtype = 0; - cur_style = style; - setup_cur_size(cur_style); - cur_mu = x_over_n(get_math_quad_size(cur_size), 18); - NEXT_NODE: - while (q != null) { - /*tex - - If node |q| is a style node, change the style and |goto delete_q|; - otherwise if it is not a noad, put it into the hlist, advance |q|, - and |goto done|; otherwise set |s| to the size of noad |q|, set |t| - to the associated type (|ord_noad.. inner_noad|), and set |pen| to - the associated penalty. - - Just before doing the big |case| switch in the second pass, the - program sets up default values so that most of the branches are - short. - - */ - t = simple_noad; - t_subtype = ord_noad_type; - pen = inf_penalty; - prepen = inf_penalty; - switch (type(q)) { - case simple_noad: - t_subtype = subtype(q); - switch (t_subtype) { - case bin_noad_type: - pen = bin_op_penalty_par; - prepen = pre_bin_op_penalty_par; - break; - case rel_noad_type: - pen = rel_penalty_par; - prepen = pre_rel_penalty_par; - break; - case vcenter_noad_type: - case over_noad_type: - case under_noad_type: - t_subtype = ord_noad_type; - break; - } - case radical_noad: - break; - case accent_noad: - break; - case fraction_noad: - t = simple_noad; - t_subtype = inner_noad_type; - break; - case fence_noad: - t_subtype = make_left_right(q, style, max_d, max_hl); - break; - case style_node: - /*tex Change the current style and |goto delete_q| */ - cur_style = subtype(q); - setup_cur_size(cur_style); - cur_mu = x_over_n(get_math_quad_style(cur_style), 18); - goto DELETE_Q; - break; - case whatsit_node: - case penalty_node: - case rule_node: - case disc_node: - case adjust_node: - case ins_node: - case mark_node: - case glue_node: - case kern_node: - couple_nodes(p,q); - p = q; - q = vlink(q); - vlink(p) = null; - goto NEXT_NODE; - break; - default: - confusion("mlist3"); - } - /*tex Append inter-element spacing based on |r_type| and |t| */ - if (r_type > 0) { - /*tex not the first noad */ - pp = p; - if (delimitermodeordinal && t_subtype == inner_noad_type && noadextra4(q) == 1) { - z = math_spacing_glue(r_subtype, ord_noad_type, cur_style, cur_mu); - } else { - z = math_spacing_glue(r_subtype, t_subtype, cur_style, cur_mu); - } - if (z != null) { - reset_attributes(z, node_attr(p)); - couple_nodes(p,z); - p = z; - } - if (penalties && prepen < inf_penalty && type(pp) != penalty_node) { - /*tex no checking of prev node type */ - z = new_penalty(prepen,noad_penalty); - reset_attributes(z, node_attr(p)); - couple_nodes(p,z); - p = z; - } - } - /*tex - - Append any |new_hlist| entries for |q|, and any appropriate - penalties. We insert a penalty node after the hlist entries of noad - |q| if |pen| is not an ``infinite'' penalty, and if the node - immediately following |q| is not a penalty node or a |rel_noad| or - absent entirely. - - */ - if (new_hlist(q) != null) { - couple_nodes(p,new_hlist(q)); - do { - p = vlink(p); - } while (vlink(p) != null); - } - if (penalties && vlink(q) != null && pen < inf_penalty) { - r_type = type(vlink(q)); - r_subtype = subtype(vlink(q)); - if (r_type != penalty_node && (r_type != simple_noad || r_subtype != rel_noad_type)) { - z = new_penalty(pen,noad_penalty); - reset_attributes(z, node_attr(q)); - couple_nodes(p,z); - p = z; - } - } - if (type(q) == fence_noad && subtype(q) == right_noad_side) { - t = simple_noad; - t_subtype = open_noad_type; - } - r_type = t; - r_subtype = t_subtype; - DELETE_Q: - r = q; - q = vlink(q); - /*tex - - The m-to-hlist conversion takes place in-place, so the various - dependant fields may not be freed (as would happen if |flush_node| - was called). A low-level |free_node| is easier than attempting to - nullify such dependant fields for all possible node and noad types. - - */ - if (nodetype_has_attributes(type(r))) { - delete_attribute_ref(node_attr(r)); - } - reset_node_properties(r); - free_node(r, get_node_size(type(r), subtype(r))); - } -} diff --git a/Build/source/texk/web2c/luatexdir/tex/mlist.h b/Build/source/texk/web2c/luatexdir/tex/mlist.h deleted file mode 100644 index dc08e0cdd6f..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/mlist.h +++ /dev/null @@ -1,41 +0,0 @@ -/* mlist.h - - Copyright 1996-2006 Han The Thanh <thanh@pdftex.org> - Copyright 2006-2009 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ - - -#ifndef MLIST_H -# define MLIST_H 1 - -extern int cur_size; - -extern halfword del_width; -extern halfword del_height; -extern halfword del_depth; -extern halfword del_shift; - -extern void run_mlist_to_hlist(halfword, boolean, int); -extern void mlist_to_hlist(halfword, boolean, int); -extern void fixup_math_parameters(int fam_id, int size_id, int f, int lvl); - -extern scaled get_math_quad_style(int a); -extern scaled get_math_quad_size(int a); - -extern pointer make_extensible(internal_font_number fnt, halfword chr, scaled v, scaled min_overlap, int horizontal, halfword att); - -#endif diff --git a/Build/source/texk/web2c/luatexdir/tex/nesting.c b/Build/source/texk/web2c/luatexdir/tex/nesting.c deleted file mode 100644 index bbad50b3cdb..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/nesting.c +++ /dev/null @@ -1,429 +0,0 @@ -/* - -nesting.w - -Copyright 2009-2010 Taco Hoekwater <taco@@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your -option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU General Public License along -with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" - -/*tex These are for |show_activities|: */ - -#define page_goal page_so_far[0] - -/*tex - -\TeX\ is typically in the midst of building many lists at once. For example, when -a math formula is being processed, \TeX\ is in math mode and working on an mlist; -this formula has temporarily interrupted \TeX\ from being in horizontal mode and -building the hlist of a paragraph; and this paragraph has temporarily interrupted -\TeX\ from being in vertical mode and building the vlist for the next page of a -document. Similarly, when a \.{\\vbox} occurs inside of an \.{\\hbox}, \TeX\ is -temporarily interrupted from working in restricted horizontal mode, and it enters -internal vertical mode. The ``semantic nest'' is a stack that keeps track of what -lists and modes are currently suspended. - -At each level of processing we are in one of six modes: - -|vmode| stands for vertical mode (the page builder); - -|hmode| stands for horizontal mode (the paragraph builder); - -|mmode| stands for displayed formula mode; - -|-vmode| stands for internal vertical mode (e.g., in a \.{\\vbox}); - -|-hmode| stands for restricted horizontal mode (e.g., in an \.{\\hbox}); - -|-mmode| stands for math formula mode (not displayed). - -The mode is temporarily set to zero while processing \.{\\write} texts in the -|ship_out| routine. - -Numeric values are assigned to |vmode|, |hmode|, and |mmode| so that \TeX's ``big -semantic switch'' can select the appropriate thing to do by computing the value -|abs(mode)+cur_cmd|, where |mode| is the current mode and |cur_cmd| is the -current command code. - -*/ - -static const char *string_mode(int m) -{ - if (m > 0) { - switch (m / (max_command_cmd + 1)) { - case 0: - return "vertical mode"; - break; - case 1: - return "horizontal mode"; - break; - case 2: - return "display math mode"; - break; - default: - break; - } - } else if (m == 0) { - return "no mode"; - } else { - switch ((-m) / (max_command_cmd + 1)) { - case 0: - return "internal vertical mode"; - break; - case 1: - return "restricted horizontal mode"; - break; - case 2: - return "math mode"; - break; - default: - break; - } - } - return "unknown mode"; -} - -void print_mode(int m) -{ - tprint(string_mode(m)); -} - -void print_in_mode(int m) -{ - tprint("' in "); - tprint(string_mode(m)); -} - -int get_mode_id(void) -{ - int m = cur_list.mode_field; - if (m > 0) { - switch (m / (max_command_cmd + 1)) { - case 0: - return 'v'; - break; - case 1: - return 'h'; - break; - case 2: - return 'm'; - break; - default: - return '\0'; - break; - } - } else if (m == 0) { - return 'n';; - } else { - switch ((-m) / (max_command_cmd + 1)) { - case 0: - return 'V'; - break; - case 1: - return 'H'; - break; - case 2: - return 'M'; - break; - default: - return '\0'; - break; - } - } -} - -/*tex - -The state of affairs at any semantic level can be represented by five values: - -|mode| is the number representing the semantic mode, as just explained. - -|head| is a |pointer| to a list head for the list being built; |link(head)| -therefore points to the first element of the list, or to |null| if the list is -empty. - -|tail| is a |pointer| to the final node of the list being built; thus, -|tail=head| if and only if the list is empty. - -|prev_graf| is the number of lines of the current paragraph that have already -been put into the present vertical list. - -|aux| is an auxiliary |memory_word| that gives further information that is needed -to characterize the situation. - -In vertical mode, |aux| is also known as |prev_depth|; it is the scaled value -representing the depth of the previous box, for use in baseline calculations, or -it is |<=-1000|pt if the next box on the vertical list is to be exempt from -baseline calculations. In horizontal mode, |aux| is also known as |space_factor|; -it holds the current space factor used in spacing calculations. In math mode, -|aux| is also known as |incompleat_noad|; if not |null|, it points to a record -that represents the numerator of a generalized fraction for which the denominator -is currently being formed in the current list. - -There is also a sixth quantity, |mode_line|, which correlates the semantic nest -with the user's input; |mode_line| contains the source line number at which the -current level of nesting was entered. The negative of this line number is the -|mode_line| at the level of the user's output routine. - -A seventh quantity, |eTeX_aux|, is used by the extended features eTeX. In math -mode it is known as |delim_ptr| and points to the most recent |fence_noad| of a -|math_left_group|. - -In horizontal mode, the |prev_graf| field is used for initial language data. - -The semantic nest is an array called |nest| that holds the |mode|, |head|, -|tail|, |prev_graf|, |aux|, and |mode_line| values for all semantic levels below -the currently active one. Information about the currently active level is kept in -the global quantities |mode|, |head|, |tail|, |prev_graf|, |aux|, and -|mode_line|, which live in a struct that is ready to be pushed onto |nest| if -necessary. - -The math field is used by various bits and pieces in |texmath.w| - -This implementation of \TeX\ uses two different conventions for representing -sequential stacks. @^stack conventions@>@^conventions for representing stacks@> - -1) If there is frequent access to the top entry, and if the stack is essentially -never empty, then the top entry is kept in a global variable (even better would -be a machine register), and the other entries appear in the array -$\\{stack}[0\to(\\{ptr}-1)]$. The semantic stack is handled this way. - -2) If there is infrequent top access, the entire stack contents are in the array -$\\{stack}[0\to(\\{ptr}-1)]$. For example, the |save_stack| is treated this way, -as we have seen. - -In |nest_ptr| we have the first unused location of |nest|, and |max_nest_stack| -has the maximum of |nest_ptr| when pushing. In |shown_mode| we store the most -recent mode shown by \.{\\tracingcommands} and with |save_tail| we can examine -whether we have an auto kern before a glue. - -*/ - -list_state_record *nest; -int nest_ptr, max_nest_stack, shown_mode; -halfword save_tail; - -/*tex - -We will see later that the vertical list at the bottom semantic level is split -into two parts; the ``current page'' runs from |page_head| to |page_tail|, and -the ``contribution list'' runs from |contrib_head| to |tail| of semantic level -zero. The idea is that contributions are first formed in vertical mode, then -``contributed'' to the current page (during which time the page-breaking -decisions are made). For now, we don't need to know any more details about the -page-building process. - -*/ - -void initialize_nesting(void) -{ - nest_ptr = 0; - max_nest_stack = 0; - shown_mode = 0; - cur_list.mode_field = vmode; - cur_list.head_field = contrib_head; - cur_list.tail_field = contrib_head; - cur_list.eTeX_aux_field = null; - cur_list.prev_depth_field = ignore_depth; - cur_list.space_factor_field = 1000; - cur_list.incompleat_noad_field = null; - cur_list.ml_field = 0; - cur_list.pg_field = 0; - cur_list.dirs_field = null; - init_math_fields(); -} - -/*tex - -Here is a common way to make the current list grow: - -*/ - -void tail_append(halfword p) -{ - couple_nodes(cur_list.tail_field, p); - cur_list.tail_field = vlink(cur_list.tail_field); -} - -halfword pop_tail(void) -{ - halfword n, r; - if (cur_list.tail_field != cur_list.head_field) { - r = cur_list.tail_field; - if (vlink(alink(cur_list.tail_field)) == cur_list.tail_field) { - n = alink(cur_list.tail_field); - } else { - n = cur_list.head_field; - while (vlink(n) != cur_list.tail_field) - n = vlink(n); - } - cur_list.tail_field = n; - alink(r) = null; - vlink(n) = null; - return r; - } else { - return null; - } -} - -/*tex - -When \TeX's work on one level is interrupted, the state is saved by calling -|push_nest|. This routine changes |head| and |tail| so that a new (empty) list is -begun; it does not change |mode| or |aux|. - -*/ - -void push_nest(void) -{ - if (nest_ptr > max_nest_stack) { - max_nest_stack = nest_ptr; - if (nest_ptr == nest_size) - overflow("semantic nest size", (unsigned) nest_size); - } - incr(nest_ptr); - cur_list.mode_field = nest[nest_ptr - 1].mode_field; - cur_list.head_field = new_node(temp_node, 0); - cur_list.tail_field = cur_list.head_field; - cur_list.eTeX_aux_field = null; - cur_list.ml_field = line; - cur_list.pg_field = 0; - cur_list.dirs_field = null; - cur_list.prev_depth_field = nest[nest_ptr - 1].prev_depth_field; - cur_list.space_factor_field = nest[nest_ptr - 1].space_factor_field; - cur_list.incompleat_noad_field = nest[nest_ptr - 1].incompleat_noad_field; - init_math_fields(); -} - -/*tex - -Conversely, when \TeX\ is finished on the current level, the former state is -restored by calling |pop_nest|. This routine will never be called at the lowest -semantic level, nor will it be called unless |head| is a node that should be -returned to free memory. - -*/ - -void pop_nest(void) -{ - flush_node(cur_list.head_field); - decr(nest_ptr); -} - -/*tex - -Here is a procedure that displays what \TeX\ is working on, at all levels. - -*/ - -void show_activities(void) -{ - /*tex Index into |nest|: */ - int p; - /*tex The mode: */ - int m; - /*tex For showing the current page: */ - halfword q, r; - /*tex Ditto: */ - int t; - tprint_nl(""); - print_ln(); - for (p = nest_ptr; p >= 0; p--) { - m = nest[p].mode_field; - tprint_nl("### "); - print_mode(m); - tprint(" entered at line "); - print_int(abs(nest[p].ml_field)); - if (nest[p].ml_field < 0) - tprint(" (\\output routine)"); - if (p == 0) { - /*tex Show the status of the current page */ - if (page_head != page_tail) { - tprint_nl("### current page:"); - if (output_active) - tprint(" (held over for next output)"); - show_box(vlink(page_head)); - if (page_contents > empty) { - tprint_nl("total height "); - print_totals(); - tprint_nl(" goal height "); - print_scaled(page_goal); - r = vlink(page_ins_head); - while (r != page_ins_head) { - print_ln(); - tprint_esc("insert"); - t = subtype(r); - print_int(t); - tprint(" adds "); - if (count(t) == 1000) - t = height(r); - else - t = x_over_n(height(r), 1000) * count(t); - print_scaled(t); - if (type(r) == split_up_node) { - q = page_head; - t = 0; - do { - q = vlink(q); - if ((type(q) == ins_node) - && (subtype(q) == subtype(r))) - incr(t); - } while (q != broken_ins(r)); - tprint(", #"); - print_int(t); - tprint(" might split"); - } - r = vlink(r); - } - } - } - if (vlink(contrib_head) != null) - tprint_nl("### recent contributions:"); - } - show_box(vlink(nest[p].head_field)); - /*tex Show the auxiliary field, |a|. */ - switch (abs(m) / (max_command_cmd + 1)) { - case 0: - tprint_nl("prevdepth "); - if (nest[p].prev_depth_field <= ignore_depth) - tprint("ignored"); - else - print_scaled(nest[p].prev_depth_field); - if (nest[p].pg_field != 0) { - tprint(", prevgraf "); - print_int(nest[p].pg_field); - if (nest[p].pg_field != 1) - tprint(" lines"); - else - tprint(" line"); - } - break; - case 1: - tprint_nl("spacefactor "); - print_int(nest[p].space_factor_field); - break; - case 2: - if (nest[p].incompleat_noad_field != null) { - tprint("this will be denominator of:"); - show_box(nest[p].incompleat_noad_field); - } - break; - } - } -} diff --git a/Build/source/texk/web2c/luatexdir/tex/nesting.h b/Build/source/texk/web2c/luatexdir/tex/nesting.h deleted file mode 100644 index 238522a77d1..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/nesting.h +++ /dev/null @@ -1,70 +0,0 @@ -/* nesting.h - - Copyright 2009 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ - - -#ifndef NESTING_H -# define NESTING_H - -# define vmode 1 /* vertical mode */ -# define hmode (vmode+max_command_cmd+1) - /* horizontal mode */ -# define mmode (hmode+max_command_cmd+1) - /* math mode */ - -extern void print_mode(int m); -extern void print_in_mode(int m); -extern int get_mode_id(void); - -# define ignore_depth -65536000 /* magic dimension value to mean `ignore me' */ - -typedef struct list_state_record_ { - int mode_field; - halfword head_field; - halfword tail_field; - halfword eTeX_aux_field; - int pg_field; - int ml_field; - halfword prev_depth_field; - halfword space_factor_field; - halfword incompleat_noad_field; - halfword dirs_field; - int math_field; - int math_style_field; -} list_state_record; - -extern list_state_record *nest; -extern int nest_ptr; -extern int max_nest_stack; -# define cur_list nest[nest_ptr] - /* the ``top'' semantic state */ -extern int shown_mode; -extern halfword save_tail; - -extern void push_nest(void); -extern void pop_nest(void); -extern void initialize_nesting(void); - -extern void tail_append(halfword p); -extern halfword pop_tail(void); - - -extern void show_activities(void); - - -#endif diff --git a/Build/source/texk/web2c/luatexdir/tex/packaging.c b/Build/source/texk/web2c/luatexdir/tex/packaging.c deleted file mode 100644 index 3d23c8b7320..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/packaging.c +++ /dev/null @@ -1,2145 +0,0 @@ -/* - -Copyright 2009-2010 Taco Hoekwater <taco@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under the terms -of the GNU General Public License as published by the Free Software Foundation; -either version 2 of the License, or (at your option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - -You should have received a copy of the GNU General Public License along with -LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" - -/*tex - - We're essentially done with the parts of \TeX\ that are concerned with the - input (|get_next|) and the output (|ship_out|). So it's time to get heavily - into the remaining part, which does the real work of typesetting. - - After lists are constructed, \TeX\ wraps them up and puts them into boxes. - Two major subroutines are given the responsibility for this task: |hpack| - applies to horizontal lists (hlists) and |vpack| applies to vertical lists - (vlists). The main duty of |hpack| and |vpack| is to compute the dimensions - of the resulting boxes, and to adjust the glue if one of those dimensions is - pre-specified. The computed sizes normally enclose all of the material inside - the new box; but some items may stick out if negative glue is used, if the - box is overfull, or if a \.{\\vbox} includes other boxes that have been - shifted left. - - The subroutine call |hpack(p,w,m)| returns a pointer to an |hlist_node| for a - box containing the hlist that starts at |p|. Parameter |w| specifies a width; - and parameter |m| is either `|exactly|' or `|additional|'. Thus, - |hpack(p,w,exactly)| produces a box whose width is exactly |w|, while - |hpack(p,w,additional)| yields a box whose width is the natural width plus - |w|. It is convenient to define a macro called `|natural|' to cover the most - common case, so that we can say |hpack(p,natural)| to get a box that has the - natural width of list |p|. - - Similarly, |vpack(p,w,m)| returns a pointer to a |vlist_node| for a box - containing the vlist that starts at |p|. In this case |w| represents a height - instead of a width; the parameter |m| is interpreted as in |hpack|. - - The parameters to |hpack| and |vpack| correspond to \TeX's primitives like - `\.{\\hbox} \.{to} \.{300pt}', `\.{\\hbox} \.{spread} \.{10pt}'; note that - `\.{\\hbox}' with no dimension following it is equivalent to `\.{\\hbox} - \.{spread} \.{0pt}'. The |scan_spec| subroutine scans such constructions in - the user's input, including the mandatory left brace that follows them, and - it puts the specification onto |save_stack| so that the desired box can later - be obtained by executing the following code: $$\vbox{\halign{#\hfil\cr - |save_ptr:=save_ptr-1;|\cr |hpack(p,saved_value(0),saved_level(0)).|\cr}}$$ - -*/ - -/*tex Scan a box specification and left brace: */ - -void scan_spec(group_code c) -{ - int spec_code; - boolean done = false ; - do { - get_x_token(); - } while ((cur_cmd == spacer_cmd) || (cur_cmd == relax_cmd)); - if (cur_cmd == left_brace_cmd) { - spec_code = additional; - cur_val = 0; - done = true; - } else { - /*tex todo: attr */ - back_input(); - if (scan_keyword("to")) { - spec_code = exactly; - scan_normal_dimen(); - } else if (scan_keyword("spread")) { - spec_code = additional; - scan_normal_dimen(); - } else { - spec_code = additional; - cur_val = 0; - } - } - set_saved_record(0, saved_boxspec, spec_code, cur_val); - save_ptr++; - new_save_level(c); - if (!done) { - scan_left_brace(); - } -} - -/*tex - - When scanning, special care is necessary to ensure that the special - |save_stack| codes are placed just below the new group code, because scanning - can change |save_stack| when \.{\\csname} appears. - - This coincides with the text on |dir| and |attr| keywords, as these are - exaclty the uses of \.{\\hbox}, \.{\\vbox}, and \.{\\vtop} in the input - stream (the others are \.{\\vcenter}, \.{\\valign}, and \.{\\halign}). - -*/ - -/*tex Scan a box specification and left brace: */ - -#define first_char_is(a,A) (cur_cs == 0 && (cur_chr == a || cur_chr == A)) - -void scan_full_spec(group_code c, int spec_direction, int just_pack) -{ - int s, i, v, spec_code; - boolean done = false ; - halfword attr_list; - boolean attr_done = false ; - boolean dir_done = false ; - if (attr_list_cache == cache_disabled) - update_attribute_cache(); - attr_list = attr_list_cache; - /*tex The box context: */ - s = saved_value(0); - do { - get_x_token(); - } while ((cur_cmd == spacer_cmd) || (cur_cmd == relax_cmd)); - if (cur_cmd == left_brace_cmd) { - goto QUICK; - } else { - back_input(); - goto KEYWORDS; - } - CONTINUE: - while (cur_cmd == relax_cmd || cur_cmd == spacer_cmd) { - get_x_token(); - if (cur_cmd == left_brace_cmd) { - goto QUICK; - } else if (cur_cmd != relax_cmd && cur_cmd != spacer_cmd) { - back_input(); - break; - } - } - KEYWORDS: - /*tex Multiple |attr| keys possible (before or after dir). */ - if (scan_keyword("attr")) { - scan_register_num(); - i = cur_val; - scan_optional_equals(); - scan_int(); - v = cur_val; - if (! attr_done) { - attr_list = copy_attribute_list(attr_list_cache); - attr_done = true; - } - attr_list = do_set_attribute(attr_list, i, v); - goto CONTINUE; - } - /*tex We only permit one |(b)dir| directive. */ - if (! dir_done) { - if (scan_keyword("bdir")) { - scan_int(); - check_dir_value(cur_val); - spec_direction = cur_val; - dir_done = true; - goto CONTINUE; - } - if (scan_keyword("dir")) { - scan_direction(); - spec_direction = cur_val; - dir_done = true; - goto CONTINUE; - } - } - /*tex Only one |to| or |spread| key possible and it comes last. */ - if (scan_keyword("to")) { - spec_code = exactly; - } else if (scan_keyword("spread")) { - spec_code = additional; - } else { - spec_code = additional; - cur_val = 0; - goto FOUND; - } - scan_normal_dimen(); - goto FOUND; - QUICK: - spec_code = additional; - cur_val = 0; - done = true; - FOUND: - add_node_attr_ref(attr_list); - set_saved_record(0, saved_boxcontext, 0, s); - set_saved_record(1, saved_boxspec, spec_code, cur_val); - /*tex Adjust |text_dir_ptr| for |scan_spec|. */ - if (spec_direction != -1) { - set_saved_record(2, saved_boxdir, spec_direction, text_dir_ptr); - text_dir_ptr = new_dir(spec_direction); - } else { - set_saved_record(2, saved_boxdir, spec_direction, null); - } - set_saved_record(3, saved_boxattr, 0, attr_list); - set_saved_record(4, saved_boxpack, 0, just_pack); - save_ptr += 5; - new_save_level(c); - if (! done) { - scan_left_brace(); - } - /*tex No gain in |if (body_direction_par != spec_direction)| etc. */ - eq_word_define(int_base + body_direction_code, spec_direction); - eq_word_define(int_base + par_direction_code, spec_direction); - eq_word_define(int_base + text_direction_code, spec_direction); -} - -/*tex - - To figure out the glue setting, |hpack| and |vpack| determine how much - stretchability and shrinkability are present, considering all four orders of - infinity. The highest order of infinity that has a nonzero coefficient is - then used as if no other orders were present. - - For example, suppose that the given list contains six glue nodes with the - respective stretchabilities 3pt, 8fill, 5fil, 6pt, $-3$fil, $-8$fill. Then - the total is essentially 2fil; and if a total additional space of 6pt is to - be achieved by stretching, the actual amounts of stretch will be 0pt, 0pt, - 15pt, 0pt, $-9$pt, and 0pt, since only `fil' glue will be considered. (The - `fill' glue is therefore not really stretching infinitely with respect to - `fil'; nobody would actually want that to happen.) - - The arrays |total_stretch| and |total_shrink| are used to determine how much - glue of each kind is present. A global variable |last_badness| is used to - implement \.{\\badness}. - -*/ - -/*tex Glue found by |hpack| or |vpack|. */ - -scaled total_stretch[5]; -scaled total_shrink[5]; - -/*tex Badness of the most recently packaged box. */ - -int last_badness; - -/*tex - - If the global variable |adjust_tail| is non-null, the |hpack| routine also - removes all occurrences of |ins_node|, |mark_node|, and |adjust_node| items - and appends the resulting material onto the list that ends at location - |adjust_tail|. - -*/ - -/*tex Tail of adjustment list. */ - -halfword adjust_tail; - -/*tex - - Materials in \.{\\vadjust} used with \.{pre} keyword will be appended to - |pre_adjust_tail| instead of |adjust_tail|. - -*/ - -halfword pre_adjust_tail; - -halfword last_leftmost_char; -halfword last_rightmost_char; - -/*tex Pointers to the prev and next char of an implicit kern. */ - -halfword next_char_p; -halfword prev_char_p; - -/*tex This procedure is called repeatedly from inside the line break algorithm. */ - -void set_prev_char_p(halfword p) -{ - prev_char_p = p; -} - -/*tex - - The kern stretch / shrink code was (or had become) rather weird ... the width - field is set, and then used in a second calculation, repeatedly, so why is - that ... maybe some some weird left-over ... anyway, the values are so small - that in practice they are not significant at all when the backend sees them - because a few hundred sp positive or negative are just noise there (so - adjustlevel 3 has hardly any consequence for the result but is more - efficient). - -*/ - -scaled char_stretch(halfword p) -{ - internal_font_number f = font(p); - int m = font_max_stretch(f); - if (m > 0) { - int c = character(p); - int ef = get_ef_code(f, c); - if (ef > 0) { - scaled dw = calc_char_width(f, c, m) - char_width(f, c); - if (dw > 0) { - return round_xn_over_d(dw, ef, 1000); - } - } - } - return 0; -} - -scaled char_shrink(halfword p) -{ - internal_font_number f = font(p); - int m = font_max_shrink(f); - if (m > 0) { - int c = character(p); - int ef = get_ef_code(f, c); - if (ef > 0) { - scaled dw = char_width(f, c) - calc_char_width(f, c, -m); - if (dw > 0) { - return round_xn_over_d(dw, ef, 1000); - } - } - } - return 0; -} - -scaled kern_stretch(halfword p) -{ - int m; - scaled d, e, x; - scaled w = width(p) ; - halfword l; - halfword r; - if (w == 0) { - /*tex Why bother about zero kerns. */ - return 0; - } - l = prev_char_p ; - if ((l == null) || (vlink(l) != p)) { - /*tex We only care about kerns following a char. */ - return 0; - } - r = vlink(p); - if (r == null) { - /*tex We only care about kerns between a char and something else. */ - } - if (!(is_char_node(l) && is_char_node(r))) { - /*tex We want two chars (but but don't care about the fonts). */ - return 0; - } - /*tex We use the old logic, kind of, but average the ef as we might depend on proper overlap. */ - m = (font_max_stretch(font(l)) + font_max_stretch(font(r)))/2; - if (m == 0) { - /*tex nothing to kern */ - return 0; - } - d = round_xn_over_d(w, 1000 + m, 1000); - /*tex We use the old logic, kind of, but average the ef as we might depend on proper overlap. */ - e = (get_ef_code(font(l), character(l)) + get_ef_code(font(r), character(r)))/2 ; - if (e == 1000) { - x = d - w; - } else { - x = round_xn_over_d(d - w, e, 1000); - } - return x; -} - -scaled kern_shrink(halfword p) -{ - int m; - scaled d, e, x; - scaled w = width(p) ; - halfword l; - halfword r; - if (w == 0) { - /*tex Why bother about zero kerns. */ - return 0; - } - l = prev_char_p ; - if ((l == null) || (vlink(l) != p)) { - /*tex We only care about kerns following a char. */ - return 0; - } - r = vlink(p); - if (r == null) { - /*tex We only care about kerns between a char and something else. */ - } - if (!(is_char_node(l) && is_char_node(r))) { - /*tex We want two chars (but but don't care about the fonts). */ - return 0; - } - /*tex We use the old logic, kind of, but average the ef as we might depend on proper overlap. */ - m = (font_max_shrink(font(l)) + font_max_shrink(font(r)))/2; - if (m == 0) { - /*tex Nothing to kern. */ - return 0; - } - d = round_xn_over_d(w, 1000 - m, 1000); - e = (get_ef_code(font(l), character(l)) + get_ef_code(font(r), character(r)))/2 ; - if (e == 1000) { - x = w - d ; - } else { - x = round_xn_over_d(w - d, e, 1000); - } - return x; -} - -void do_subst_font(halfword p, int ex_ratio) -{ - if (type(p) == disc_node) { - halfword r = vlink(pre_break(p)); - while (r != null) { - if (is_char_node(r)) - do_subst_font(r, ex_ratio); - r = vlink(r); - } - r = vlink(post_break(p)); - while (r != null) { - if (is_char_node(r)) - do_subst_font(r, ex_ratio); - r = vlink(r); - } - r = vlink(no_break(p)); - while (r != null) { - if (is_char_node(r)) - do_subst_font(r, ex_ratio); - r = vlink(r); - } - return; - } - if (! is_char_node(p)) { - normal_error("font expansion", "invalid node type"); - return; - } else { - internal_font_number f = font(p); - int ef = get_ef_code(f, character(p)); - if (ef == 0) - return; - if ((font_max_stretch(f) > 0) && (ex_ratio > 0)) { - int ex_stretch = ext_xn_over_d(ex_ratio * ef, font_max_stretch(f), 1000000); - ex_glyph(p) = fix_expand_value(f, ex_stretch)*1000; - } else if ((font_max_shrink(f) > 0) && (ex_ratio < 0)) { - int ex_shrink = ext_xn_over_d(ex_ratio * ef, font_max_shrink(f), 1000000); - ex_glyph(p) = fix_expand_value(f, ex_shrink)*1000; - } - } -} - -scaled char_pw(halfword p, int side) -{ - internal_font_number f; - int c, w; - if (side == left_side) - last_leftmost_char = null; - else - last_rightmost_char = null; - if (p == null) - return 0; - if (!is_char_node(p)) - return 0; - f = font(p); - if (side == left_side) { - c = get_lp_code(f, character(p)); - last_leftmost_char = p; - } else { - c = get_rp_code(f, character(p)); - last_rightmost_char = p; - } - if (c == 0) - return 0; - w = quad(f); - return round_xn_over_d(w, c, 1000); -} - -halfword new_margin_kern(scaled w, halfword p, int side) -{ - halfword k, q; - k = new_node(margin_kern_node, side); - width(k) = w; - if (p == null) - normal_error("margin kerning", "invalid pointer to marginal char node"); - q = new_char(font(p), character(p)); - margin_char(k) = q; - return k; -} - -/*tex - - Here we prepare for |hpack|, which is place where we do font substituting - when font expansion is being used. - -*/ - -/*tex The current expansion ratio, needed for recursive call. */ - -int font_expand_ratio = 0; - -int ignore_math_skip(halfword p) -{ - if (math_skip_mode == 6) { - if (subtype(p) == after) { - if (math_skip_boundary(vlink(p))) { - return 0; - } - } else { - if (math_skip_boundary(alink(p))) { - return 0; - } - } - } else if (math_skip_mode == 7) { - if (subtype(p) == after) { - if (! math_skip_boundary(vlink(p))) { - return 0; - } - } else { - if (! math_skip_boundary(alink(p))) { - return 0; - } - } - } else { - return 0; - } - reset_glue_to_zero(p); - return 1; -} - -halfword hpack(halfword p, scaled w, int m, int pack_direction) -{ - /*tex the box node that will be returned */ - halfword r; - /*tex trails behind |p| */ - halfword q; - /*tex height */ - scaled h = 0; - /*tex depth */ - scaled d = 0; - /*tex natural width */ - scaled x = 0; - scaled_whd whd; - /*tex shift amount */ - scaled s; - /*tex order of infinity */ - int o; - /*tex for managing the direction stack */ - halfword dir_ptr1 = null; - /*tex the current direction */ - int hpack_dir; - int disc_level = 0; - halfword pack_interrupt[8]; - scaled font_stretch = 0; - scaled font_shrink = 0; - int adjust_spacing = adjust_spacing_par; - last_badness = 0; - /*tex the box node that will be returned */ - r = new_node(hlist_node, min_quarterword); - if (pack_direction == -1) { - hpack_dir = text_direction_par; - } else { - hpack_dir = pack_direction; - } - box_dir(r) = hpack_dir; - /*tex - - A potential optimimization, save a little but neglectable in practice - (not so many empty boxes are used): - - \starttyping - if (p == null) { - width(r) = w; - return r; - } - \stoptyping - - */ - /*tex push null */ - push_dir(dir_ptr1,hpack_dir); - /*tex hm, adding something to a node address? */ - q = r + list_offset; - vlink(q) = p; - if (m == cal_expand_ratio) { - /*tex Why not always: */ - prev_char_p = null; - } - if (adjust_spacing > 2) { - adjust_spacing = 0; - } - total_stretch[normal] = 0; - total_shrink[normal] = 0; - total_stretch[sfi] = 0; - total_shrink[sfi] = 0; - total_stretch[fil] = 0; - total_shrink[fil] = 0; - total_stretch[fill] = 0; - total_shrink[fill] = 0; - total_stretch[filll] = 0; - total_shrink[filll] = 0; - RESWITCH: - while ((p != null) || (disc_level > 0)) { - if (p == null) { - decr(disc_level); - p = pack_interrupt[disc_level]; - goto RESWITCH; - } - /*tex - - Examine node |p| in the hlist, taking account of its effect on the - dimensions of the new box, or moving it to the adjustment list; then - advance |p| to the next node. - - */ - while (is_char_node(p)) { - /*tex - - Incorporate character dimensions into the dimensions of the hbox - that will contain~it, then move to the next node. - - The following code is part of \TeX's inner loop; i.e., adding - another character of text to the user's input will cause each of - these instructions to be exercised one more time. - - */ - if (m >= cal_expand_ratio) { - prev_char_p = p; - if (m == cal_expand_ratio) { - font_stretch += char_stretch(p); - font_shrink += char_shrink(p); - } else if (m == subst_ex_font) { - do_subst_font(p, font_expand_ratio); - } - } - whd = pack_width_height_depth(hpack_dir, dir_TRT, p, true); - x += whd.wd; - if (whd.ht > h) - h = whd.ht; - if (whd.dp > d) - d = whd.dp; - p = vlink(p); - } - if (p != null) { - switch (type(p)) { - case hlist_node: - case vlist_node: - /*tex - - Incorporate box dimensions into the dimensions of the - hbox that will contain~it - - The code here implicitly uses the fact that running - dimensions are indicated by |null_flag|, which will be - ignored in the calculations because it is a highly - negative number. - - */ - s = shift_amount(p); - whd = pack_width_height_depth(hpack_dir, box_dir(p), p, false); - x += whd.wd; - if (whd.ht - s > h) - h = whd.ht - s; - if (whd.dp + s > d) - d = whd.dp + s; - break; - case rule_node: - case unset_node: - x += width(p); - if (height(p) > h) - h = height(p); - if (depth(p) > d) - d = depth(p); - break; - case math_node: - /*tex Begin mathskip code. */ - if (glue_is_zero(p) || ignore_math_skip(p)) { - x += surround(p); - break; - } else { - /*tex Fall through. */ - } - /*tex End mathskip code. */ - case glue_node: - /*tex Incorporate glue into the horizontal totals. */ - x += width(p); - o = stretch_order(p); - total_stretch[o] = total_stretch[o] + stretch(p); - o = shrink_order(p); - total_shrink[o] = total_shrink[o] + shrink(p); - if (subtype(p) >= a_leaders) { - halfword g = leader_ptr(p); - if (height(g) > h) - h = height(g); - if (depth(g) > d) - d = depth(g); - } - break; - case kern_node: - x += width(p); - if (subtype(p) == font_kern && adjust_spacing) { - /*tex So only when 1 or 2. */ - if (m == cal_expand_ratio) { - font_stretch = font_stretch + kern_stretch(p); - font_shrink = font_shrink + kern_shrink(p); - } else if (m == subst_ex_font) { - /*tex This is the finalizer. */ - int k = 0; - if (font_expand_ratio > 0) { - k = kern_stretch(p); - } else if (font_expand_ratio < 0) { - k = kern_shrink(p); - } - ex_kern(p) = k; - x += k; - } - } - break; - case disc_node: - if (m == subst_ex_font) - do_subst_font(p, font_expand_ratio); - if ((subtype(p) != select_disc) && (vlink(no_break(p)) != null)) { - pack_interrupt[disc_level] = vlink(p); - incr(disc_level); - p = no_break(p); - } - break; - case dir_node: - /*tex Adjust the dir stack for the |hpack| routine. */ - if (subtype(p) == normal_dir) { - hpack_dir = dir_dir(p); - push_dir_node(dir_ptr1,p); - } else { - pop_dir_node(dir_ptr1); - if (dir_ptr1 != null) - hpack_dir = dir_dir(dir_ptr1); - } - break; - case margin_kern_node: - if (m == cal_expand_ratio) { - int f = font(margin_char(p)); - do_subst_font(margin_char(p), 1000); - if (f != font(margin_char(p))) - font_stretch = font_stretch - width(p) - char_pw(margin_char(p), subtype(p)); - font(margin_char(p)) = f; - do_subst_font(margin_char(p), -1000); - if (f != font(margin_char(p))) - font_shrink = font_shrink - width(p) - char_pw(margin_char(p), subtype(p)); - font(margin_char(p)) = f; - } else if (m == subst_ex_font) { - do_subst_font(margin_char(p), font_expand_ratio); - width(p) = -char_pw(margin_char(p), subtype(p)); - } - x += width(p); - break; - case ins_node: - case mark_node: - case adjust_node: - /*tex - - Transfer node |p| to the adjustment list.\Although node - |q| is not necessarily the immediate predecessor of node - |p|, it always points to some node in the list preceding - |p|. Thus, we can delete nodes by moving |q| when - necessary. The algorithm takes linear time, and the extra - computation does not intrude on the inner loop unless it - is necessary to make a deletion. - - */ - if (adjust_tail != null || pre_adjust_tail != null) { - while (vlink(q) != p) - q = vlink(q); - if (type(p) == adjust_node) { - if (adjust_pre(p) != 0) - update_adjust_list(pre_adjust_tail); - else - update_adjust_list(adjust_tail); - p = vlink(p); - adjust_ptr(vlink(q)) = null; - flush_node(vlink(q)); - } else { - vlink(adjust_tail) = p; - adjust_tail = p; - p = vlink(p); - } - vlink(q) = p; - p = q; - } - break; - default: - break; - } - p = vlink(p); - } - } - - if (adjust_tail != null) - vlink(adjust_tail) = null; - if (pre_adjust_tail != null) - vlink(pre_adjust_tail) = null; - height(r) = h; - depth(r) = d; - /*tex - - Determine the value of |width(r)| and the appropriate glue setting; then - |return| or |goto common_ending|. - - When we get to the present part of the program, |x| is the natural width - of the box being packaged. - - */ - if (m == additional) - w = x + w; - width(r) = w; - x = w - x; - /*tex Now |x| is the excess to be made up. */ - if (x == 0) { - glue_sign(r) = normal; - glue_order(r) = normal; - set_glue_ratio_zero(glue_set(r)); - goto EXIT; - } else if (x > 0) { - /*tex - - Determine horizontal glue stretch setting, then |return| or - |goto common_ending|. - - If |hpack| is called with |m=cal_expand_ratio| we calculate - |font_expand_ratio| and return without checking for overfull or - underfull box. - - */ - if (total_stretch[filll] != 0) - o = filll; - else if (total_stretch[fill] != 0) - o = fill; - else if (total_stretch[fil] != 0) - o = fil; - else if (total_stretch[sfi] != 0) - o = sfi; - else - o = normal; - if ((m == cal_expand_ratio) && (o == normal) && (font_stretch > 0)) { - font_expand_ratio = divide_scaled_n(x, font_stretch, 1000.0); - goto EXIT; - } - glue_order(r) = (quarterword) o; - glue_sign(r) = stretching; - if (total_stretch[o] != 0) { - glue_set(r) = unfloat((double) x / total_stretch[o]); - } else { - /*tex There's nothing to stretch. */ - glue_sign(r) = normal; - set_glue_ratio_zero(glue_set(r)); - } - if (o == normal) { - if (list_ptr(r) != null) { - /*tex - - Report an underfull hbox and |goto common_ending|, if this - box is sufficiently bad. - - */ - last_badness = badness(x, total_stretch[normal]); - if (last_badness > hbadness_par) { - int callback_id = callback_defined(hpack_quality_callback); - if (callback_id > 0) { - halfword rule = null; - if (last_badness > 100) { - run_callback(callback_id, "SdNdd->N","underfull",last_badness,r,abs(pack_begin_line),line,&rule); - } else { - run_callback(callback_id, "SdNdd->N","loose",last_badness,r,abs(pack_begin_line),line,&rule); - } - if (rule != null) { - while (vlink(q) != null) { - q = vlink(q); - } - couple_nodes(q,rule); - } - } else { - print_ln(); - if (last_badness > 100) { - tprint_nl("Underfull \\hbox (badness "); - } else { - tprint_nl("Loose \\hbox (badness "); - } - print_int(last_badness); - goto COMMON_ENDING; - } - } - } - } - goto EXIT; - } else { - /*tex - - Determine horizontal glue shrink setting, then |return| or |goto - common_ending|, - - */ - if (total_shrink[filll] != 0) - o = filll; - else if (total_shrink[fill] != 0) - o = fill; - else if (total_shrink[fil] != 0) - o = fil; - else if (total_shrink[sfi] != 0) - o = sfi; - else - o = normal; - if ((m == cal_expand_ratio) && (o == normal) && (font_shrink > 0)) { - font_expand_ratio = divide_scaled_n(x, font_shrink, 1000.0); - goto EXIT; - } - glue_order(r) = (quarterword) o; - glue_sign(r) = shrinking; - if (total_shrink[o] != 0) { - glue_set(r) = unfloat((double) (-x) / (double) total_shrink[o]); - } else { - /*tex There's nothing to shrink. */ - glue_sign(r) = normal; - set_glue_ratio_zero(glue_set(r)); - } - if ((total_shrink[o] < -x) && (o == normal) && (list_ptr(r) != null)) { - int overshoot = -x - total_shrink[normal] ; - last_badness = 1000000; - /*tex Use the maximum shrinkage */ - set_glue_ratio_one(glue_set(r)); - /*tex - - Report an overfull hbox and |goto common_ending|, if this box is - sufficiently bad. - - */ - if ((overshoot > hfuzz_par) || (hbadness_par < 100)) { - int callback_id = callback_defined(hpack_quality_callback); - halfword rule = null; - if (callback_id > 0) { - run_callback(callback_id, "SdNdd->N","overfull",overshoot,r,abs(pack_begin_line),line,&rule); - } else if (overfull_rule_par > 0) { - rule = new_rule(normal_rule); - rule_dir(rule) = box_dir(r); - width(rule) = overfull_rule_par; - } - if (rule != null) { - while (vlink(q) != null) { - q = vlink(q); - } - couple_nodes(q,rule); - } - if (callback_id == 0) { - print_ln(); - tprint_nl("Overfull \\hbox ("); - print_scaled(overshoot); - tprint("pt too wide"); - goto COMMON_ENDING; - } - } - } else if (o == normal) { - if (list_ptr(r) != null) { - /*tex - - Report a tight hbox and |goto common_ending|, if this box is - sufficiently bad. - - */ - last_badness = badness(-x, total_shrink[normal]); - if (last_badness > hbadness_par) { - int callback_id = callback_defined(hpack_quality_callback); - if (callback_id > 0) { - halfword rule = null; - run_callback(callback_id, "SdNdd->N","tight",last_badness,r,abs(pack_begin_line),line,&rule); - if (rule != null) { - while (vlink(q) != null) { - q = vlink(q); - } - couple_nodes(q,rule); - } - } else { - print_ln(); - tprint_nl("Tight \\hbox (badness "); - print_int(last_badness); - goto COMMON_ENDING; - } - } - } - } - goto EXIT; - } - - COMMON_ENDING: - /*tex Finish issuing a diagnostic message for an overfull or underfull hbox. */ - if (output_active) { - tprint(") has occurred while \\output is active"); - } else { - if (pack_begin_line != 0) { - if (pack_begin_line > 0) { - tprint(") in paragraph at lines "); - } else { - tprint(") in alignment at lines "); - } - print_int(abs(pack_begin_line)); - tprint("--"); - } else { - tprint(") detected at line "); - } - print_int(line); - } - - print_ln(); - font_in_short_display = null_font; - short_display(list_ptr(r)); - print_ln(); - begin_diagnostic(); - show_box(r); - end_diagnostic(true); - EXIT: - if ((m == cal_expand_ratio) && (font_expand_ratio != 0)) { - font_expand_ratio = fix_int(font_expand_ratio, -1000, 1000); - q = list_ptr(r); - list_ptr(r) = null; - flush_node(r); - /*tex This nested call uses the more or less global font_expand_ratio. */ - r = hpack(q, w, subst_ex_font, hpack_dir); - } - while (dir_ptr1 != null) - pop_dir_node(dir_ptr1); - /*tex Here we reset the |font_expand_ratio|. */ - font_expand_ratio = 0; - return r; -} - -halfword filtered_hpack(halfword p, halfword qt, scaled w, int m, int grp, int pac, int just_pack, halfword attr) -{ - halfword q; - if (just_pack) { - q = vlink(p); - } else if (type(p) == temp_node && vlink(p) == null) { - q = vlink(p); - } else { - new_hyphenation(p, qt); - /*tex We don't care about the tail in this case. */ - (void) new_ligkern(p, qt); - q = vlink(p); - /*tex Maybe here: |alink(p) = null|. */ - /*tex ignores empty anyway. Maybe also pass tail? */ - q = lua_hpack_filter(q, w, m, grp, pac, attr); - } - return hpack(q, w, m, pac); -} - -/*tex - - Here is a function to calculate the natural whd of a (horizontal) node list. - -*/ - -scaled_whd natural_sizes(halfword p, halfword pp, glue_ratio g_mult, int g_sign, int g_order, int pack_direction) -{ - /*tex shift amount */ - scaled s; - /*tex points to a glue specification */ - halfword g; - int hpack_dir; - /*tex For recursion */ - scaled_whd xx; - scaled_whd whd, siz = { 0, 0, 0 }; - scaled gp = 0; - scaled gm = 0; - if (pack_direction == -1) { - hpack_dir = text_direction_par; - } else { - hpack_dir = pack_direction; - } - while (p != pp && p != null) { - while (is_char_node(p) && p != pp) { - whd = pack_width_height_depth(hpack_dir, dir_TRT, p, true); - siz.wd += whd.wd; - if (whd.ht > siz.ht) - siz.ht = whd.ht; - if (whd.dp > siz.dp) - siz.dp = whd.dp; - p = vlink(p); - } - if (p != pp && p != null) { - switch (type(p)) { - case hlist_node: - case vlist_node: - s = shift_amount(p); - whd = pack_width_height_depth(hpack_dir, box_dir(p), p, false); - siz.wd += whd.wd; - if (whd.ht - s > siz.ht) - siz.ht = whd.ht - s; - if (whd.dp + s > siz.dp) - siz.dp = whd.dp + s; - break; - case rule_node: - case unset_node: - siz.wd += width(p); - if (height(p) > siz.ht) - siz.ht = height(p); - if (depth(p) > siz.dp) - siz.dp = depth(p); - break; - case math_node: - /*tex Begin mathskip code. */ - if (glue_is_zero(p) || ignore_math_skip(p)) { - siz.wd += surround(p); - break; - } else { - /*tex Fall through. */ - } - /*tex End mathskip code. */ - case glue_node: - siz.wd += width(p); - if (g_sign != normal) { - if (g_sign == stretching) { - if (stretch_order(p) == g_order) { - /*tex - |siz.wd += float_round(float_cast(g_mult) * float_cast(stretch(p)))| - */ - gp += stretch(p); - } - } else if (shrink_order(p) == g_order) { - /*tex - |siz.wd -= float_round(float_cast(g_mult) * float_cast(shrink(p)));| - */ - gm += shrink(p); - } - } - if (subtype(p) >= a_leaders) { - g = leader_ptr(p); - if (height(g) > siz.ht) - siz.ht = height(g); - if (depth(g) > siz.dp) - siz.dp = depth(g); - } - break; - case margin_kern_node: - siz.wd += width(p); - break; - case kern_node: - siz.wd += width(p) + ex_kern(p); - break; - case disc_node: - xx = natural_sizes(no_break(p), null, g_mult, g_sign, g_order, hpack_dir); - siz.wd += xx.wd; - if (xx.ht > siz.ht) - siz.ht = xx.ht; - if (xx.dp > siz.dp) - siz.dp = xx.dp; - break; - default: - break; - } - p = vlink(p); - } - - } - if (g_sign != normal) { - if (g_sign == stretching) { - siz.wd += float_round(float_cast(g_mult) * float_cast(gp)); - } else { - siz.wd -= float_round(float_cast(g_mult) * float_cast(gm)); - } - } - return siz; -} - -/*tex - - In order to provide a decent indication of where an overfull or underfull box - originated, we use a global variable |pack_begin_line| that is set nonzero - only when |hpack| is being called by the paragraph builder or the alignment - finishing routine. - - The source file line where the current paragraph or alignment began; a - negative value denotes alignment: - -*/ - -int pack_begin_line; - -/*tex - - The |vpack| subroutine is actually a special case of a slightly more general - routine called |vpackage|, which has four parameters. The fourth parameter, - which is |max_dimen| in the case of |vpack|, specifies the maximum depth of - the page box that is constructed. The depth is first computed by the normal - rules; if it exceeds this limit, the reference point is simply moved down - until the limiting depth is attained. - -*/ - -halfword vpackage(halfword p, scaled h, int m, scaled l, int pack_direction) -{ - /*tex the box node that will be returned */ - halfword r; - /*tex width */ - scaled w = 0; - /*tex depth */ - scaled d = 0; - /*tex natural height */ - scaled x = 0; - scaled_whd whd; - /*tex shift amount */ - scaled s; - /*tex order of infinity */ - int o; - last_badness = 0; - r = new_node(vlist_node, 0); - if (pack_direction == -1) { - box_dir(r) = body_direction_par; - } else { - box_dir(r) = pack_direction; - } - subtype(r) = min_quarterword; - shift_amount(r) = 0; - list_ptr(r) = p; - total_stretch[normal] = 0; - total_shrink[normal] = 0; - total_stretch[sfi] = 0; - total_shrink[sfi] = 0; - total_stretch[fil] = 0; - total_shrink[fil] = 0; - total_stretch[fill] = 0; - total_shrink[fill] = 0; - total_stretch[filll] = 0; - total_shrink[filll] = 0; - while (p != null) { - /*tex - - Examine node |p| in the vlist, taking account of its effect on the - dimensions of the new box; then advance |p| to the next node. - - */ - if (is_char_node(p)) { - confusion("vpack"); - } else { - switch (type(p)) { - case hlist_node: - case vlist_node: - /*tex - - Incorporate box dimensions into the dimensions of the vbox - that will contain it. - - */ - s = shift_amount(p); - whd = pack_width_height_depth(box_dir(r), box_dir(p), p, false); - if (whd.wd + s > w) - w = whd.wd + s; - x += d + whd.ht; - d = whd.dp; - break; - case rule_node: - case unset_node: - x += d + height(p); - d = depth(p); - if (width(p) > w) - w = width(p); - break; - case glue_node: - /*tex Incorporate glue into the vertical totals. */ - x += d; - d = 0; - x += width(p); - o = stretch_order(p); - total_stretch[o] = total_stretch[o] + stretch(p); - o = shrink_order(p); - total_shrink[o] = total_shrink[o] + shrink(p); - if (subtype(p) >= a_leaders) { - halfword g = leader_ptr(p); - if (width(g) > w) - w = width(g); - } - break; - case kern_node: - x += d + width(p); - d = 0; - break; - default: - break; - } - } - p = vlink(p); - } - width(r) = w; - if (d > l) { - x += d - l; - depth(r) = l; - } else { - depth(r) = d; - } - /*tex - - Determine the value of |height(r)| and the appropriate glue setting; then - |return| or |goto common_ending|. - - When we get to the present part of the program, |x| is the natural height - of the box being packaged. - */ - if (m == additional) - h = x + h; - height(r) = h; - x = h - x; - /*tex Now |x| is the excess to be made up. */ - if (x == 0) { - glue_sign(r) = normal; - glue_order(r) = normal; - set_glue_ratio_zero(glue_set(r)); - return r; - } else if (x > 0) { - /*tex - - Determine vertical glue stretch setting, then |return| or |goto - common_ending|. - - */ - if (total_stretch[filll] != 0) - o = filll; - else if (total_stretch[fill] != 0) - o = fill; - else if (total_stretch[fil] != 0) - o = fil; - else if (total_stretch[sfi] != 0) - o = sfi; - else - o = normal; - glue_order(r) = (quarterword) o; - glue_sign(r) = stretching; - if (total_stretch[o] != 0) { - glue_set(r) = unfloat((double) x / total_stretch[o]); - } else { - /*tex There's nothing to stretch. */ - glue_sign(r) = normal; - set_glue_ratio_zero(glue_set(r)); - } - if (o == normal) { - if (list_ptr(r) != null) { - /*tex - - Report an underfull vbox and |goto common_ending|, if this - box is sufficiently bad. - - */ - last_badness = badness(x, total_stretch[normal]); - if (last_badness > vbadness_par) { - int callback_id = callback_defined(vpack_quality_callback); - if (callback_id > 0) { - if (last_badness > 100) { - run_callback(callback_id, "SdNdd->","underfull",last_badness,r,abs(pack_begin_line),line); - } else { - run_callback(callback_id, "SdNdd->","loose",last_badness,r,abs(pack_begin_line),line); - } - goto EXIT; - } else { - print_ln(); - if (last_badness > 100) { - tprint_nl("Underfull \\vbox (badness "); - } else { - tprint_nl("Loose \\vbox (badness "); - } - print_int(last_badness); - goto COMMON_ENDING; - } - } - } - } - return r; - } else { - /*tex - - Determine vertical glue shrink setting, then |return| or |goto - common_ending|. - - */ - if (total_shrink[filll] != 0) - o = filll; - else if (total_shrink[fill] != 0) - o = fill; - else if (total_shrink[fil] != 0) - o = fil; - else if (total_shrink[sfi] != 0) - o = sfi; - else - o = normal; - glue_order(r) = (quarterword) o; - glue_sign(r) = shrinking; - if (total_shrink[o] != 0) { - glue_set(r) = unfloat((double) (-x) / total_shrink[o]); - } else { - /*tex There's nothing to shrink. */ - glue_sign(r) = normal; - set_glue_ratio_zero(glue_set(r)); - } - if ((total_shrink[o] < -x) && (o == normal) && (list_ptr(r) != null)) { - int overshoot = -x - total_shrink[normal]; - last_badness = 1000000; - /*tex Use the maximum shrinkage */ - set_glue_ratio_one(glue_set(r)); - /*tex - - Report an overfull vbox and |goto common_ending|, if this box is - sufficiently bad. - - */ - if ((overshoot > vfuzz_par) || (vbadness_par < 100)) { - int callback_id = callback_defined(vpack_quality_callback); - if (callback_id > 0) { - run_callback(callback_id, "SdNdd->","overfull",overshoot,r,abs(pack_begin_line),line); - goto EXIT; - } else { - print_ln(); - tprint_nl("Overfull \\vbox ("); - print_scaled(-x - total_shrink[normal]); - tprint("pt too high"); - goto COMMON_ENDING; - } - } - } else if (o == normal) { - if (list_ptr(r) != null) { - /*tex - - Report a tight vbox and |goto common_ending|, if this box is - sufficiently bad. - - */ - last_badness = badness(-x, total_shrink[normal]); - if (last_badness > vbadness_par) { - int callback_id = callback_defined(vpack_quality_callback); - if (callback_id > 0) { - run_callback(callback_id, "SdNdd->","tight",last_badness,r,abs(pack_begin_line),line); - goto EXIT; - } else { - print_ln(); - tprint_nl("Tight \\vbox (badness "); - print_int(last_badness); - goto COMMON_ENDING; - } - } - } - } - return r; - } - - COMMON_ENDING: - /*tex Finish issuing a diagnostic message or an overfull or underfull vbox. */ - if (output_active) { - tprint(") has occurred while \\output is active"); - } else { - if (pack_begin_line != 0) { - /*tex It's actually negative. */ - tprint(") in alignment at lines "); - print_int(abs(pack_begin_line)); - tprint("--"); - } else { - tprint(") detected at line "); - } - print_int(line); - print_ln(); - } - begin_diagnostic(); - show_box(r); - end_diagnostic(true); - EXIT: - return r; -} - -halfword filtered_vpackage(halfword p, scaled h, int m, scaled l, int grp, int pack_direction, int just_pack, halfword attr) -{ - halfword q = p; - if (!just_pack) - q = lua_vpack_filter(q, h, m, l, grp, pack_direction, attr); - return vpackage(q, h, m, l, pack_direction); -} - -void finish_vcenter(void) -{ - halfword p; - unsave(); - save_ptr--; - p = vpack(vlink(cur_list.head_field), saved_value(0), saved_level(0), -1); - pop_nest(); - p = math_vcenter_group(p); - tail_append(p); -} - -void package(int c) -{ - halfword saved0, saved2, saved3, saved4; - int grp = cur_group; - scaled d = box_max_depth_par; - unsave(); - save_ptr -= 5; - saved0 = saved_value(0); - saved2 = saved_value(2); - saved3 = saved_value(3); - saved4 = saved_value(4); - if (cur_list.mode_field == -hmode) { - cur_box = filtered_hpack(cur_list.head_field, cur_list.tail_field, - saved_value(1), saved_level(1), grp, saved_level(2), saved4, saved3); - subtype(cur_box) = hbox_list; - } else { - cur_box = filtered_vpackage(vlink(cur_list.head_field), - saved_value(1), saved_level(1), d, grp, saved_level(2), saved4, saved3); - if (c == vtop_code) { - /*tex - - Read just the height and depth of |cur_box|, for \.{\\vtop}. The - height of a `\.{\\vtop}' box is inherited from the first item on - its list, if that item is an |hlist_node|, |vlist_node|, or - |rule_node|; otherwise the \.{\\vtop} height is zero. - - */ - scaled h = 0; - halfword p = list_ptr(cur_box); - if ((p != null) && (type(p) <= rule_node)) { - /* hlist, vlist, rule */ - h = height(p); - } - depth(cur_box) = depth(cur_box) - h + height(cur_box); - height(cur_box) = h; - } - } - if (saved2 != null) { - /*tex Adjust back |text_dir_ptr| for |scan_spec| */ - flush_node_list(text_dir_ptr); - text_dir_ptr = saved2; - - } - replace_attribute_list(cur_box, saved3); - pop_nest(); - box_end(saved0); -} - -/*tex - - When a box is being appended to the current vertical list, the baselineskip - calculation is handled by the |append_to_vlist| routine. - -*/ - -void append_to_vlist(halfword b, int location) -{ - /*tex The deficiency of space between baselines: */ - scaled d; - /*tex A new glue node. */ - halfword p; - boolean mirrored = (type(b) == hlist_node) && is_mirrored(box_dir(b)) ; - halfword result = null; - halfword next_depth = ignore_depth; - boolean prev_set = false ; - if (lua_appendtovlist_callback(b,location,prev_depth_par,mirrored,&result,&next_depth,&prev_set)) { - while (result != null) { - couple_nodes(cur_list.tail_field, result); - cur_list.tail_field = result; - result = vlink(result); - } - if (prev_set) { - prev_depth_par = next_depth; - } - } else { - if (prev_depth_par > ignore_depth) { - if (mirrored) { - d = width(baseline_skip_par) - prev_depth_par - depth(b); - } else { - d = width(baseline_skip_par) - prev_depth_par - height(b); - } - if (d < line_skip_limit_par) { - p = new_param_glue(line_skip_code); - } else { - p = new_skip_param(baseline_skip_code); - width(p) = d; - } - couple_nodes(cur_list.tail_field, p); - cur_list.tail_field = p; - } - couple_nodes(cur_list.tail_field, b); - cur_list.tail_field = b; - if (mirrored) { - prev_depth_par = height(b); - } else { - prev_depth_par = depth(b); - } - } -} - -/*tex - - When |saving_vdiscards| is positive then the glue, kern, and penalty nodes - removed by the page builder or by \.{\\vsplit} from the top of a vertical - list are saved in special lists instead of being discarded. - -*/ - -/*tex last item removed by page builder */ - -#define tail_page_disc disc_ptr[copy_code] - -/*tex first item removed by page builder */ - -#define page_disc disc_ptr[last_box_code] - -/*tex first item removed by \.{\\vsplit} */ - -#define split_disc disc_ptr[vsplit_code] - -/*tex List pointers. */ - -halfword disc_ptr[(vsplit_code + 1)]; - -/*tex - - The |vsplit| procedure, which implements \TeX's \.{\\vsplit} operation, is - considerably simpler than |line_break| because it doesn't have to worry about - hyphenation, and because its mission is to discover a single break instead of - an optimum sequence of breakpoints. But before we get into the details of - |vsplit|, we need to consider a few more basic things. - - A subroutine called |prune_page_top| takes a pointer to a vlist and returns a - pointer to a modified vlist in which all glue, kern, and penalty nodes have - been deleted before the first box or rule node. However, the first box or - rule is actually preceded by a newly created glue node designed so that the - topmost baseline will be at distance |split_top_skip| from the top, whenever - this is possible without backspacing. - - When the second argument |s| is |false| the deleted nodes are destroyed, - otherwise they are collected in a list starting at |split_disc|. - -*/ - -halfword prune_page_top(halfword p, boolean s) -{ - halfword q; - /*tex Lags one step behind |p|. */ - halfword prev_p = temp_head; - halfword r = null; - vlink(temp_head) = p; - while (p != null) { - switch (type(p)) { - case hlist_node: - case vlist_node: - case rule_node: - /*tex Insert glue for |split_top_skip| and set |p:=null|. */ - q = new_skip_param(split_top_skip_code); - vlink(prev_p) = q; - vlink(q) = p; - if (width(q) > height(p)) - width(q) = width(q) - height(p); - else - width(q) = 0; - p = null; - break; - case boundary_node: - case whatsit_node: - case mark_node: - case ins_node: - prev_p = p; - p = vlink(prev_p); - break; - case glue_node: - case kern_node: - case penalty_node: - q = p; - p = vlink(q); - vlink(q) = null; - vlink(prev_p) = p; - if (s) { - if (split_disc == null) - split_disc = q; - else - vlink(r) = q; - r = q; - } else { - flush_node_list(q); - } - break; - default: - confusion("pruning"); - break; - } - } - return vlink(temp_head); -} - -/*tex - - The next subroutine finds the best place to break a given vertical list so as - to obtain a box of height~|h|, with maximum depth~|d|. A pointer to the - beginning of the vertical list is given, and a pointer to the optimum - breakpoint is returned. The list is effectively followed by a forced break, - i.e., a penalty node with the |eject_penalty|; if the best break occurs at - this artificial node, the value |null| is returned. - -*/ - -/*tex The distance from first active node to |cur_p|: */ - -scaled active_height[10]; - -/*tex - - An array of six |scaled| distances is used to keep track of the height from - the beginning of the list to the current place, just as in |line_break|. In - fact, we use one of the same arrays, only changing its name to reflect its - new significance. - -*/ - -#define do_all_six(A) A(1);A(2);A(3);A(4);A(5);A(6);A(7) -#define set_height_zero(A) active_height[A]=0 /* initialize the height to zero */ - -/*tex - - A global variable |best_height_plus_depth| will be set to the natural size of - the box that corresponds to the optimum breakpoint found by |vert_break|. - (This value is used by the insertion-splitting algorithm of the page - builder.) - -*/ - -/*tex The height of the best box, without stretching or shrinking: */ - -scaled best_height_plus_depth; - -halfword vert_break(halfword p, scaled h, scaled d) -{ - /*tex - If |p| is a glue node, |type(prev_p)| determines whether |p| is a legal - breakpoint, an initial glue node is not a legal breakpoint. - */ - halfword prev_p = p; - /*tex penalty value */ - int pi = 0; - /*tex badness at a trial breakpoint */ - int b; - /*tex |type| of the node following a kern */ - int t; - /*tex the smallest badness plus penalties found so far */ - int least_cost; - /*tex the most recent break that leads to |least_cost| */ - halfword best_place = null; - /*tex depth of previous box in the list */ - scaled prev_dp = 0; - least_cost = awful_bad; - do_all_six(set_height_zero); - while (1) { - /*tex - - If node |p| is a legal breakpoint, check if this break is the best - known, and |goto done| if |p| is null or if the page-so-far is - already too full to accept more stuff. - - A subtle point to be noted here is that the maximum depth~|d| might - be negative, so |cur_height| and |prev_dp| might need to be corrected - even after a glue or kern node. - */ - if (p == null) { - pi = eject_penalty; - } else { - /*tex - - Use node |p| to update the current height and depth measurements; - if this node is not a legal breakpoint, |goto not_found| or - |update_heights|, otherwise set |pi| to the associated penalty at - the break. - - */ - switch (type(p)) { - case hlist_node: - case vlist_node: - case rule_node: - cur_height = cur_height + prev_dp + height(p); - prev_dp = depth(p); - goto NOT_FOUND; - break; - case boundary_node: - case whatsit_node: - goto NOT_FOUND; - break; - case glue_node: - if (precedes_break(prev_p)) - pi = 0; - else - goto UPDATE_HEIGHTS; - break; - case kern_node: - if (vlink(p) == null) - t = penalty_node; - else - t = type(vlink(p)); - if (t == glue_node) - pi = 0; - else - goto UPDATE_HEIGHTS; - break; - case penalty_node: - pi = penalty(p); - break; - case mark_node: - case ins_node: - goto NOT_FOUND; - break; - default: - confusion("vertbreak"); - break; - } - } - /*tex - - Check if node |p| is a new champion breakpoint; then |goto done| if - |p| is a forced break or if the page-so-far is already too full. - - */ - if (pi < inf_penalty) { - /*tex Compute the badness, |b|, using |awful_bad| if the box is too full. */ - if (cur_height < h) { - if ((active_height[3] != 0) || (active_height[4] != 0) || - (active_height[5] != 0) || (active_height[6] != 0)) - b = 0; - else - b = badness(h - cur_height, active_height[2]); - } else if (cur_height - h > active_height[7]) { - b = awful_bad; - } else { - b = badness(cur_height - h, active_height[7]); - } - if (b < awful_bad) { - if (pi <= eject_penalty) - b = pi; - else if (b < inf_bad) - b = b + pi; - else - b = deplorable; - } - if (b <= least_cost) { - best_place = p; - least_cost = b; - best_height_plus_depth = cur_height + prev_dp; - } - if ((b == awful_bad) || (pi <= eject_penalty)) - goto DONE; - } - if ((type(p) < glue_node) || (type(p) > kern_node)) - goto NOT_FOUND; - UPDATE_HEIGHTS: - /*tex - - Update the current height and depth measurements with respect to a - glue or kern node~|p|. Vertical lists that are subject to the - |vert_break| procedure should not contain infinite shrinkability, - since that would permit any amount of information to ``fit'' on one - page. - - */ - if (type(p) != kern_node) { - active_height[2 + stretch_order(p)] += stretch(p); - active_height[7] += shrink(p); - if ((shrink_order(p) != normal) && (shrink(p) != 0)) { - print_err("Infinite glue shrinkage found in box being split"); - help4( - "The box you are \\vsplitting contains some infinitely", - "shrinkable glue, e.g., `\\vss' or `\\vskip 0pt minus 1fil'.", - "Such glue doesn't belong there; but you can safely proceed,", - "since the offensive shrinkability has been made finite." - ); - error(); - shrink_order(p) = normal; - } - } - cur_height = cur_height + prev_dp + width(p); - prev_dp = 0; - NOT_FOUND: - if (prev_dp > d) { - cur_height = cur_height + prev_dp - d; - prev_dp = d; - } - prev_p = p; - p = vlink(prev_p); - } - DONE: - return best_place; -} - -/*tex - - Now we are ready to consider |vsplit| itself. Most of its work is - accomplished by the two subroutines that we have just considered. - - Given the number of a vlist box |n|, and given a desired page height |h|, the - |vsplit| function finds the best initial segment of the vlist and returns a - box for a page of height~|h|. The remainder of the vlist, if any, replaces - the original box, after removing glue and penalties and adjusting for - |split_top_skip|. Mark nodes in the split-off box are used to set the values - of |split_first_mark| and |split_bot_mark|; we use the fact that - |split_first_mark(x)=null| if and only if |split_bot_mark(x)=null|. - - The original box becomes ``void'' if and only if it has been entirely - extracted. The extracted box is ``void'' if and only if the original box was - void (or if it was, erroneously, an hlist box). - -*/ - -/*tex Extract a page of height |h| from box |n|: */ - -halfword vsplit(halfword n, scaled h, int m) -{ - /*tex the box to be split */ - halfword v; - /*tex the direction of the box to be split */ - int vdir; - /*tex runs through the vlist */ - halfword p; - /*tex points to where the break occurs */ - halfword q; - /*tex for traversing marks lists */ - halfword i; - v = box(n); - vdir = box_dir(v); - flush_node_list(split_disc); - split_disc = null; - for (i = 0; i <= biggest_used_mark; i++) { - delete_split_first_mark(i); - delete_split_bot_mark(i); - } - /*tex Dispense with trivial cases of void or bad boxes. */ - if (v == null) { - return null; - } - if (type(v) != vlist_node) { - print_err("\\vsplit needs a \\vbox"); - help2( - "The box you are trying to split is an \\hbox.", - "i can't split such a box, so I''ll leave it alone." - ); - error(); - return null; - } - q = vert_break(list_ptr(v), h, split_max_depth_par); - /*tex - - Look at all the marks in nodes before the break, and set the final link - to |null| at the break. It's possible that the box begins with a penalty - node that is the ``best'' break, so we must be careful to handle this - special case correctly. - - */ - p = list_ptr(v); - if (p == q) { - list_ptr(v) = null; - } else { - while (1) { - if (type(p) == mark_node) { - if (split_first_mark(mark_class(p)) == null) { - set_split_first_mark(mark_class(p), mark_ptr(p)); - set_split_bot_mark(mark_class(p), split_first_mark(mark_class(p))); - set_token_ref_count(split_first_mark(mark_class(p)), - token_ref_count(split_first_mark(mark_class(p))) + 2); - } else { - delete_token_ref(split_bot_mark(mark_class(p))); - set_split_bot_mark(mark_class(p), mark_ptr(p)); - add_token_ref(split_bot_mark(mark_class(p))); - } - } - if (vlink(p) == q) { - vlink(p) = null; - break; - } - p = vlink(p); - } - } - q = prune_page_top(q, saving_vdiscards_par > 0); - p = list_ptr(v); - list_ptr(v) = null; - flush_node(v); - if (q == null) { - /*tex The |eq_level| of the box stays the same. */ - box(n) = null; - } else { - box(n) = filtered_vpackage(q, 0, additional, max_depth_par, split_keep_group, vdir, 0, 0); - } - if (m == exactly) { - return filtered_vpackage(p, h, exactly, split_max_depth_par, split_off_group, vdir, 0, 0); - } else { - return filtered_vpackage(p, 0, additional, max_depth_par, split_off_group, vdir, 0, 0); - } -} - -/*tex - - Now that we can see what eventually happens to boxes, we can consider the - first steps in their creation. The |begin_box| routine is called when - |box_context| is a context specification, |cur_chr| specifies the type of box - desired, and |cur_cmd=make_box|. - -*/ - -void begin_box(int box_context) -{ - /*tex run through the current list */ - halfword q; - /*tex 0 or |vmode| or |hmode| */ - halfword k; - /*tex a box number */ - int n; - int spec_direction = -1; - int just_pack = 0; - int split_mode = exactly ; - switch (cur_chr) { - case box_code: - scan_register_num(); - cur_box = box(cur_val); - /*tex The box becomes void, at the same level. */ - box(cur_val) = null; - break; - case copy_code: - scan_register_num(); - cur_box = copy_node_list(box(cur_val)); - break; - case last_box_code: - /*tex - - If the current list ends with a box node, delete it from the list - and make |cur_box| point to it; otherwise set |cur_box:=null|. - - */ - cur_box = null; - if (abs(cur_list.mode_field) == mmode) { - you_cant(); - help1("Sorry; this \\lastbox will be void."); - error(); - } else if ((cur_list.mode_field == vmode) && (cur_list.head_field == cur_list.tail_field)) { - you_cant(); - help2( - "Sorry...I usually can't take things from the current page.", - "This \\lastbox will therefore be void." - ); - error(); - } else { - if (cur_list.head_field != cur_list.tail_field) { - if ((type(cur_list.tail_field) == hlist_node) || (type(cur_list.tail_field) == vlist_node)) { - /*tex Remove the last box */ - q = alink(cur_list.tail_field); - if (q == null || vlink(q) != cur_list.tail_field) { - q = cur_list.head_field; - while (vlink(q) != cur_list.tail_field) - q = vlink(q); - } - uncouple_node(cur_list.tail_field); - cur_box = cur_list.tail_field; - shift_amount(cur_box) = 0; - cur_list.tail_field = q; - vlink(cur_list.tail_field) = null; - } - } - } - break; - case vsplit_code: - /*tex - - Split off part of a vertical box, make |cur_box| point to it. - Here we deal with things like `\.{\\vsplit 13 to 100pt}'. - - */ - scan_register_num(); - n = cur_val; - if (scan_keyword("upto")) { - split_mode = additional ; - } else if (!scan_keyword("to")) { - print_err("Missing `to' inserted"); - help2( - "I'm working on `\\vsplit<box number> to <dimen>';", - "will look for the <dimen> next." - ); - error(); - } - scan_normal_dimen(); - cur_box = vsplit(n, cur_val, split_mode); - break; - default: - /*tex - - Initiate the construction of an hbox or vbox, then |return|. Here - is where we enter restricted horizontal mode or internal vertical - mode, in order to make a box. - - */ - switch (cur_chr) { - case tpack_code: - cur_chr = vtop_code; - just_pack = 1; - break; - case vpack_code: - cur_chr = vtop_code + vmode; - just_pack = 1; - break; - case hpack_code: - cur_chr = vtop_code + hmode; - just_pack = 1; - break; - } - k = cur_chr - vtop_code; - set_saved_record(0, saved_boxcontext, 0, box_context); - switch (abs(cur_list.mode_field)) { - case vmode: - spec_direction = body_direction_par; - break; - case hmode: - spec_direction = text_direction_par; - break; - case mmode: - spec_direction = math_direction_par; - break; - } - if (k == hmode) { - if ((box_context < box_flag) && (abs(cur_list.mode_field) == vmode)) - scan_full_spec(adjusted_hbox_group, spec_direction,just_pack); - else - scan_full_spec(hbox_group, spec_direction,just_pack); - } else { - if (k == vmode) { - scan_full_spec(vbox_group, spec_direction,just_pack); - } else { - scan_full_spec(vtop_group, spec_direction,just_pack); - k = vmode; - } - normal_paragraph(); - } - push_nest(); -/* new */ -/* eq_word_define(int_base + no_local_whatsits_code, 0); */ -eq_word_define(int_base + no_local_dirs_code, 0); - cur_list.mode_field = -k; - if (k == vmode) { - prev_depth_par = ignore_depth; - if (every_vbox_par != null) - begin_token_list(every_vbox_par, every_vbox_text); - } else { - space_factor_par = 1000; - if (every_hbox_par != null) - begin_token_list(every_hbox_par, every_hbox_text); - } - return; - break; - } - /*tex In simple cases, we use the box immediately. */ - box_end(box_context); -} diff --git a/Build/source/texk/web2c/luatexdir/tex/packaging.h b/Build/source/texk/web2c/luatexdir/tex/packaging.h deleted file mode 100644 index 9353afeaf20..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/packaging.h +++ /dev/null @@ -1,156 +0,0 @@ -/* packaging.h - - Copyright 2009 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef PACKAGING_H -# define PACKAGING_H - -/* We define some constants used when calling |hpack| to deal with font expansion. */ - -typedef enum { - exactly = 0, /*a box dimension is pre-specified */ - additional, /*a box dimension is increased from the natural one */ - cal_expand_ratio, /* calculate amount for font expansion after breaking paragraph into lines */ - subst_ex_font /* substitute fonts */ -} hpack_subtypes; - -# define substituted 3 /* |subtype| of kern nodes that should be substituted */ - -extern void scan_spec(group_code c); -extern void scan_full_spec(group_code c, int spec_direction, int justpack); - -extern scaled total_stretch[5]; -extern scaled total_shrink[5]; /* glue found by |hpack| or |vpack| */ -extern int last_badness; /* badness of the most recently packaged box */ -extern halfword adjust_tail; /* tail of adjustment list */ -extern halfword pre_adjust_tail; -extern int font_expand_ratio; /* current expansion ratio */ -extern halfword last_leftmost_char; -extern halfword last_rightmost_char; -extern halfword next_char_p; /* pointer to the next char of an implicit kern */ -extern halfword prev_char_p; /* pointer to the previous char of an implicit kern */ - -extern void set_prev_char_p(halfword p); -extern scaled char_stretch(halfword p); -extern scaled char_shrink(halfword p); -extern scaled kern_stretch(halfword p); -extern scaled kern_shrink(halfword p); -extern void do_subst_font(halfword p, int ex_ratio); -extern scaled char_pw(halfword p, int side); -extern halfword new_margin_kern(scaled w, halfword p, int side); - -# define update_adjust_list(A) do { \ - if (A == null) \ - normal_error("pre vadjust", "adjust_tail or pre_adjust_tail is null"); \ - vlink(A) = adjust_ptr(p); \ - while (vlink(A) != null) \ - A = vlink(A); \ - } while (0) - -extern halfword filtered_hpack(halfword p, halfword qt, scaled w, int m, int grp, int d, int just_pack, halfword attr); -extern scaled_whd natural_sizes(halfword p, halfword pp, glue_ratio g_mult, int g_sign, int g_order, int d); -extern halfword hpack(halfword p, scaled w, int m, int d); - -extern int pack_begin_line; - -extern halfword vpackage(halfword p, scaled h, int m, scaled l, int d); -extern halfword filtered_vpackage(halfword p, scaled h, int m, scaled l, int grp, int d, int just_pack, halfword attr); -extern void finish_vcenter(void); -extern void package(int c); -extern void append_to_vlist(halfword b, int location); - -# define vpack(A,B,C,D) vpackage(A,B,C,max_dimen,D) /* special case of unconstrained depth */ - -extern halfword prune_page_top(halfword p, boolean s); -extern scaled active_height[10]; /* distance from first active node to~|cur_p| */ - -# define cur_height active_height[1] /* the natural height */ -# define awful_bad 07777777777 /* more than a billion demerits */ -# define deplorable 100000 /* more than |inf_bad|, but less than |awful_bad| */ - -extern scaled best_height_plus_depth; /* height of the best box, without stretching or shrinking */ - -extern halfword vert_break(halfword p, scaled h, scaled d); -extern halfword vsplit(halfword n, scaled h, int m); /* extracts a page of height |h| from box |n| */ - -# define box_code 0 /* |chr_code| for `\.{\\box}' */ -# define copy_code 1 /* |chr_code| for `\.{\\copy}' */ -# define last_box_code 2 /* |chr_code| for `\.{\\lastbox}' */ -# define vsplit_code 3 /* |chr_code| for `\.{\\vsplit}' */ -# define tpack_code 4 -# define vpack_code 5 -# define hpack_code 6 -# define vtop_code 7 /* |chr_code| for `\.{\\vtop}' */ - -# define tail_page_disc disc_ptr[copy_code] /* last item removed by page builder */ -# define page_disc disc_ptr[last_box_code] /* first item removed by page builder */ -# define split_disc disc_ptr[vsplit_code] /* first item removed by \.{\\vsplit} */ - -extern halfword disc_ptr[(vsplit_code + 1)]; /* list pointers */ - -/* - -Now let's turn to the question of how \.{\\hbox} is treated. We actually need to -consider also a slightly larger context, since constructions like - -`\.{\\setbox3=}\penalty0\.{\\hbox...}' and -`\.{\\leaders}\penalty0\.{\\hbox...}' and -`\.{\\lower3.8pt\\hbox...}' - -are supposed to invoke quite different actions after the box has been packaged. -Conversely, constructions like `\.{\\setbox3=}' can be followed by a variety of -different kinds of boxes, and we would like to encode such things in an efficient -way. - -In other words, there are two problems: To represent the context of a box, and to -represent its type. The first problem is solved by putting a ``context code'' on -the |save_stack|, just below the two entries that give the dimensions produced by -|scan_spec|. The context code is either a (signed) shift amount, or it is a large -integer |>=box_flag|, where |box_flag=@t$2^{30}$@>|. Codes |box_flag| through -|box_flag+biggest_reg| represent `\.{\\setbox0}' through -`\.{\\setbox}|biggest_reg|'; codes |box_flag+biggest_reg+1| through -|box_flag+2*biggest_reg| represent `\.{\\global\\setbox0}' through -`\.{\\global\\setbox}|biggest_reg|'; code |box_flag+2*number_regs| represents -`\.{\\shipout}'; and codes |box_flag+2*number_regs+1| through -|box_flag+2*number_regs+3| represent `\.{\\leaders}', `\.{\\cleaders}', and -`\.{\\xleaders}'. - -The second problem is solved by giving the command code |make_box| to all control -sequences that produce a box, and by using the following |chr_code| values to -distinguish between them: |box_code|, |copy_code|, |last_box_code|, -|vsplit_code|, |vtop_code|, |vtop_code+vmode|, and |vtop_code+hmode|, where the -latter two are used denote \.{\\vbox} and \.{\\hbox}, respectively. - -*/ - -# define box_flag 010000000000 /* context code for `\.{\\setbox0}' */ -# define global_box_flag (box_flag+number_regs) /* context code for `\.{\\global\\setbox0}' */ -# define max_global_box_flag (global_box_flag+number_regs) -# define ship_out_flag (max_global_box_flag+1) /* context code for `\.{\\shipout}' */ -# define lua_scan_flag (max_global_box_flag+2) /* context code for |scan_list| */ -# define leader_flag (max_global_box_flag+3) /* context code for `\.{\\leaders}' */ - -extern void begin_box(int box_context); - -#define math_skip_boundary(n) \ -(n && type(n) == glue_node && (subtype(n) == space_skip_subtype || subtype(n) == xspace_skip_subtype)) - -extern int ignore_math_skip(halfword p) ; - -#endif diff --git a/Build/source/texk/web2c/luatexdir/tex/postlinebreak.c b/Build/source/texk/web2c/luatexdir/tex/postlinebreak.c deleted file mode 100644 index c6f82d56052..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/postlinebreak.c +++ /dev/null @@ -1,603 +0,0 @@ -/* - -postlinebreak.w - -Copyright 2006-2010 Taco Hoekwater <taco@@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your -option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU General Public License along -with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" - -/*tex - -So far we have gotten a little way into the |line_break| routine, having covered -its important |try_break| subroutine. Now let's consider the rest of the process. - -The main loop of |line_break| traverses the given hlist, starting at -|vlink(temp_head)|, and calls |try_break| at each legal breakpoint. A variable -called |auto_breaking| is set to true except within math formulas, since glue -nodes are not legal breakpoints when they appear in formulas. - -The current node of interest in the hlist is pointed to by |cur_p|. Another -variable, |prev_p|, is usually one step behind |cur_p|, but the real meaning of -|prev_p| is this: If |type(cur_p)=glue_node| then |cur_p| is a legal breakpoint -if and only if |auto_breaking| is true and |prev_p| does not point to a glue -node, penalty node, explicit kern node, or math node. - -The total number of lines that will be set by |post_line_break| is -|best_line-prev_graf-1|. The last breakpoint is specified by -|break_node(best_bet)|, and this passive node points to the other breakpoints via -the |prev_break| links. The finishing-up phase starts by linking the relevant -passive nodes in forward order, changing |prev_break| to |next_break|. (The -|next_break| fields actually reside in the same memory space as the |prev_break| -fields did, but we give them a new name because of their new significance.) Then -the lines are justified, one by one. - -The |post_line_break| must also keep an dir stack, so that it can output end -direction instructions at the ends of lines and begin direction instructions at -the beginnings of lines. - -*/ - -/*tex The new name for |prev_break| after links are reversed: */ - -#define next_break prev_break - -/*tex The |int|s are actually halfwords. */ - -void ext_post_line_break(int paragraph_dir, - int right_skip, - int left_skip, - int protrude_chars, - halfword par_shape_ptr, - int adjust_spacing, - halfword inter_line_penalties_ptr, - int inter_line_penalty, - int club_penalty, - halfword club_penalties_ptr, - halfword widow_penalties_ptr, - int widow_penalty, - int broken_penalty, - halfword final_par_glue, - halfword best_bet, - halfword last_special_line, - scaled second_width, - scaled second_indent, - scaled first_width, - scaled first_indent, halfword best_line) -{ - - boolean have_directional = true; - /*tex temporary registers for list manipulation */ - halfword q, r; - halfword k; - scaled w; - /*tex was a break at glue? */ - boolean glue_break; - /*tex was the current break at a discretionary node? */ - boolean disc_break; - /*tex and did it have a nonempty post-break part? */ - boolean post_disc_break; - /*tex width of line number |cur_line| */ - scaled cur_width; - /*tex left margin of line number |cur_line| */ - scaled cur_indent; - /*tex use when calculating penalties between lines */ - int pen; - /*tex |cur_p|, but localized */ - halfword cur_p; - /*tex the current line number being justified */ - halfword cur_line; - /*tex the current direction: */ - dir_ptr = cur_list.dirs_field; - /*tex - Reverse the links of the relevant passive nodes, setting |cur_p| to the - first breakpoint. The job of reversing links in a list is conveniently - regarded as the job of taking items off one stack and putting them on - another. In this case we take them off a stack pointed to by |q| and - having |prev_break| fields; we put them on a stack pointed to by |cur_p| - and having |next_break| fields. Node |r| is the passive node being moved - from stack to stack. - */ - q = break_node(best_bet); - /*tex |cur_p| will become the first breakpoint; */ - cur_p = null; - do { - r = q; - q = prev_break(q); - next_break(r) = cur_p; - cur_p = r; - } while (q != null); - /*tex prevgraf + 1 */ - cur_line = cur_list.pg_field + 1; - do { - /*tex - Justify the line ending at breakpoint |cur_p|, and append it to the - current vertical list, together with associated penalties and other - insertions. - - The current line to be justified appears in a horizontal list - starting at |vlink(temp_head)| and ending at |cur_break(cur_p)|. If - |cur_break(cur_p)| is a glue node, we reset the glue to equal the - |right_skip| glue; otherwise we append the |right_skip| glue at the - right. If |cur_break(cur_p)| is a discretionary node, we modify the - list so that the discretionary break is compulsory, and we set - |disc_break| to |true|. We also append the |left_skip| glue at the - left of the line, unless it is zero. - */ - if (dir_ptr != null) { - /*tex Insert dir nodes at the beginning of the current line. */ - for (q = dir_ptr; q != null; q = vlink(q)) { - halfword tmp = new_dir(dir_dir(q)); - halfword nxt = vlink(temp_head); - delete_attribute_ref(node_attr(tmp)); - node_attr(tmp) = node_attr(temp_head); - add_node_attr_ref(node_attr(tmp)); - couple_nodes(temp_head, tmp); - /*tex \.{\\break}\.{\\par} */ - try_couple_nodes(tmp, nxt); - } - flush_node_list(dir_ptr); - dir_ptr = null; - } - /*tex - Modify the end of the line to reflect the nature of the break and to - include \.{\\rightskip}; also set the proper value of |disc_break|. - At the end of the following code, |q| will point to the final node on - the list about to be justified. In the meanwhile |r| will point to - the node we will use to insert end-of-line stuff after. |q==null| - means we use the final position of |r|. - */ - - if (temp_head != null) { - /*tex begin mathskip code */ - q = temp_head; - while(q != null) { - if (type(q) == math_node) { - surround(q) = 0 ; - reset_glue_to_zero(q); - break; - } else if ((type(q) == hlist_node) && (subtype(q) == indent_list)) { - /* go on */ - } else if (is_char_node(q)) { - break; - } else if (non_discardable(q)) { - break; - } else if (type(q) == kern_node && subtype(q) != explicit_kern && subtype(q) != italic_kern) { - break; - } - q = vlink(q); - } - /*tex end mathskip code */ - } - - r = cur_break(cur_p); - q = null; - disc_break = false; - post_disc_break = false; - glue_break = false; - - - if (r == null) { - for (r = temp_head; vlink(r) != null; r = vlink(r)); - if (r == final_par_glue) { - /*tex This should almost always be true... */ - q = r; - /*tex |q| refers to the last node of the line (and paragraph) */ - r = alink(r); - } - /*tex |r| refers to the node after which the dir nodes should be closed */ - } else if (type(r) == math_node) { - surround(r) = 0; - /*tex begin mathskip code */ - reset_glue_to_zero(r); - /*tex end mathskip code */ - } else if (type(r) == glue_node) { - copy_glue_values(r,right_skip); - subtype(r) = right_skip_code + 1; - glue_break = true; - /*tex |q| refers to the last node of the line */ - q = r; - r = alink(r); - assert(vlink(r) == q); - /*tex |r| refers to the node after which the dir nodes should be closed */ - } else if (type(r) == disc_node) { - halfword a = alink(r); - halfword v = vlink(r); - assert(a != null); - assert(v != null); - switch (subtype(r)) { - case select_disc: - if (vlink_pre_break(r) != null) { - flush_node_list(vlink_pre_break(r)); - vlink_pre_break(r) = null; - tlink_pre_break(r) = null; - } - if (vlink_no_break(r) != null) { - couple_nodes(a, vlink_no_break(r)); - couple_nodes(tlink_no_break(r), r); - vlink_no_break(r) = null; - tlink_no_break(r) = null; - } - assert(type(a) == disc_node && subtype(a) == init_disc); - flush_node_list(vlink_no_break(a)); - vlink_no_break(a) = null; - tlink_no_break(a) = null; - flush_node_list(vlink_pre_break(a)); - vlink_pre_break(a) = null; - tlink_pre_break(a) = null; - flush_node_list(vlink_post_break(a)); - vlink_post_break(a) = null; - tlink_post_break(a) = null; - break; - case init_disc: - assert(type(v) == disc_node && subtype(v) == select_disc); - subtype(v) = syllable_disc; - flush_node_list(vlink_no_break(v)); - vlink_no_break(v) = vlink_post_break(r); - tlink_no_break(v) = tlink_post_break(r); - vlink_post_break(r) = null; - tlink_post_break(r) = null; - default: - if (vlink_no_break(r) != null) { - flush_node_list(vlink_no_break(r)); - vlink_no_break(r) = null; - tlink_no_break(r) = null; - } - if (vlink_pre_break(r) != null) { - couple_nodes(a, vlink_pre_break(r)); - couple_nodes(tlink_pre_break(r), r); - vlink_pre_break(r) = null; - tlink_pre_break(r) = null; - } - } - if (vlink_post_break(r) != null) { - couple_nodes(r, vlink_post_break(r)); - couple_nodes(tlink_post_break(r), v); - vlink_post_break(r) = null; - tlink_post_break(r) = null; - post_disc_break = true; - } - disc_break = true; - } else if (type(r) == kern_node) { - width(r) = 0; - } - /*tex Adjust the dir stack based on dir nodes in this line. */ - if (have_directional) { - halfword e, p; - for (e = vlink(temp_head); e != null && e != cur_break(cur_p); e = vlink(e)) { - if (type(e) == dir_node) { - if (subtype(e) == normal_dir) { - dir_ptr = do_push_dir_node(dir_ptr, e); - } else if (dir_ptr != null && dir_dir(dir_ptr) == dir_dir(e)) { - dir_ptr = do_pop_dir_node(dir_ptr); - } - } - } - assert(e == cur_break(cur_p)); - /*tex Insert dir nodes at the end of the current line. */ - e = vlink(r); - for (p = dir_ptr; p != null; p = vlink(p)) { - halfword s = new_dir(dir_dir(p)); - subtype(s) = cancel_dir; - delete_attribute_ref(node_attr(s)); - node_attr(s) = node_attr(r); - add_node_attr_ref(node_attr(s)); - couple_nodes(r, s); - try_couple_nodes(s, e); - r = s; - } - } - if (passive_right_box(cur_p) != null) { - halfword s = copy_node_list(passive_right_box(cur_p)); - halfword e = vlink(r); - couple_nodes(r, s); - try_couple_nodes(s, e); - r = s; - } - if (q == null) { - q = r; - } - /*tex - Now [q] refers to the last node on the line and therefore the - rightmost breakpoint. The only exception is the case of a - discretionary break with non-empty |pre_break|, then |q| has been - changed to the last node of the |pre_break| list. If the par ends - with a \break command, the last line is utterly empty. That is the - case of |q==temp_head|. - */ - if (q != temp_head && protrude_chars > 0) { - halfword p, ptmp; - if (disc_break && (is_char_node(q) || (type(q) != disc_node))) { - /*tex |q| is reset to the last node of |pre_break| */ - p = q; - ptmp = p; - } else { - /*tex get |vlink(p) = q| */ - p = alink(q); - assert(vlink(p) == q); - ptmp = p; - } - p = find_protchar_right(vlink(temp_head), p); - w = char_pw(p, right_side); - if (w != 0) { - /*tex we have found a marginal kern, append it after |ptmp| */ - k = new_margin_kern(-w, last_rightmost_char, right_side); - delete_attribute_ref(node_attr(k)); - node_attr(k) = node_attr(p); - add_node_attr_ref(node_attr(k)); - try_couple_nodes(k, vlink(ptmp)); - couple_nodes(ptmp,k); - if (ptmp == q) - q = vlink(q); - } - } - /*tex - If |q| was not a breakpoint at glue and has been reset to |rightskip| - then we append |rightskip| after |q| now. - */ - if (!glue_break) { - /*tex Put the \.{\\rightskip} glue after node |q|. */ - halfword r1 = new_glue((right_skip == null ? zero_glue : right_skip)); - subtype(r1) = right_skip_code+1; - try_couple_nodes(r1,vlink(q)); - delete_attribute_ref(node_attr(r1)); - node_attr(r1) = node_attr(q); - add_node_attr_ref(node_attr(r1)); - couple_nodes(q,r1); - q = r1; - } - /*tex - Modify the end of the line to reflect the nature of the break and to - include \.{\\rightskip}; also set the proper value of |disc_break|; - Also put the \.{\\leftskip} glue at the left and detach this line. - - The following code begins with |q| at the end of the list to be - justified. It ends with |q| at the beginning of that list, and with - |vlink(temp_head)| pointing to the remainder of the paragraph, if - any. - */ - r = vlink(q); - vlink(q) = null; - - q = vlink(temp_head); - try_couple_nodes(temp_head, r); - if (passive_left_box(cur_p) != null && passive_left_box(cur_p) != 0) { - halfword s; - r = copy_node_list(passive_left_box(cur_p)); - s = vlink(q); - couple_nodes(r,q); - q = r; - if ((cur_line == cur_list.pg_field + 1) && (s != null)) { - if (type(s) == hlist_node) { - if (list_ptr(s) == null) { - q = vlink(q); - try_couple_nodes(r,vlink(s)); - try_couple_nodes(s, r); - } - } - } - } - /*tex - At this point |q| is the leftmost node; all discardable nodes have - been discarded - */ - if (protrude_chars > 0) { - halfword p; - p = q; - p = find_protchar_left(p, false); - w = char_pw(p, left_side); - if (w != 0) { - k = new_margin_kern(-w, last_leftmost_char, left_side); - delete_attribute_ref(node_attr(k)); - node_attr(k) = node_attr(q); - add_node_attr_ref(node_attr(k)); - couple_nodes(k,q); - q = k; - } - } - if (! glue_is_zero(left_skip)) { - r = new_glue(left_skip); - subtype(r) = left_skip_code+1; - delete_attribute_ref(node_attr(r)); - node_attr(r) = node_attr(q); - add_node_attr_ref(node_attr(r)); - couple_nodes(r,q); - q = r; - } - /*tex - Put the \.{\\leftskip} glue at the left and detach this line. Call - the packaging subroutine, setting |just_box| to the justified box. - Now |q| points to the hlist that represents the current line of the - paragraph. We need to compute the appropriate line width, pack the - line into a box of this size, and shift the box by the appropriate - amount of indentation. - */ - if (cur_line > last_special_line) { - cur_width = second_width; - cur_indent = second_indent; - } else if (par_shape_ptr == null) { - cur_width = first_width; - cur_indent = first_indent; - } else { - cur_indent = varmem[(par_shape_ptr + 2 * cur_line)].cint; - cur_width = varmem[(par_shape_ptr + 2 * cur_line + 1)].cint; - /* needs checking */ - cur_indent = swap_parshape_indent(cur_indent,cur_width); - } - adjust_tail = adjust_head; - pre_adjust_tail = pre_adjust_head; - if (adjust_spacing > 0) { - just_box = hpack(q, cur_width, cal_expand_ratio, paragraph_dir); - } else { - just_box = hpack(q, cur_width, exactly, paragraph_dir); - } - shift_amount(just_box) = cur_indent; - subtype(just_box) = line_list; - /*tex - Call the packaging subroutine, setting |just_box| to the justified - box. - */ - if ((vlink(contrib_head) != null)) - checked_break_filter(pre_box); - if (pre_adjust_head != pre_adjust_tail) { - append_list(pre_adjust_head, pre_adjust_tail); - checked_break_filter(pre_adjust); - } - pre_adjust_tail = null; - append_to_vlist(just_box,lua_key_index(post_linebreak)); - checked_break_filter(box); - if (adjust_head != adjust_tail) { - append_list(adjust_head, adjust_tail); - checked_break_filter(adjust); - } - adjust_tail = null; - /*tex - Append the new box to the current vertical list, followed by the list - of special nodes taken out of the box by the packager. Append a - penalty node, if a nonzero penalty is appropriate. Penalties between - the lines of a paragraph come from club and widow lines, from the - |inter_line_penalty| parameter, and from lines that end at - discretionary breaks. Breaking between lines of a two-line paragraph - gets both club-line and widow-line penalties. The local variable - |pen| will be set to the sum of all relevant penalties for the - current line, except that the final line is never penalized. - */ - if (cur_line + 1 != best_line) { - q = inter_line_penalties_ptr; - if (q != null) { - r = cur_line; - if (r > penalty(q)) - r = penalty(q); - pen = penalty(q + r); - } else { - if (passive_pen_inter(cur_p) != 0) { - pen = passive_pen_inter(cur_p); - } else { - pen = inter_line_penalty; - } - } - q = club_penalties_ptr; - if (q != null) { - /*tex prevgraf */ - r = cur_line - cur_list.pg_field; - if (r > penalty(q)) - r = penalty(q); - pen += penalty(q + r); - } else if (cur_line == cur_list.pg_field + 1) { - /*tex prevgraf */ - pen += club_penalty; - } - q = widow_penalties_ptr; - if (q != null) { - r = best_line - cur_line - 1; - if (r > penalty(q)) - r = penalty(q); - pen += penalty(q + r); - } else if (cur_line + 2 == best_line) { - pen += widow_penalty; - } - if (disc_break) { - if (passive_pen_broken(cur_p) != 0) { - pen += passive_pen_broken(cur_p); - } else { - pen += broken_penalty; - } - } - if (pen != 0) { - r = new_penalty(pen,linebreak_penalty); - couple_nodes(cur_list.tail_field, r); - cur_list.tail_field = r; - } - } - /*tex - Append a penalty node, if a nonzero penalty is appropriate. Justify - the line ending at breakpoint |cur_p|, and append it to the current - vertical list, together with associated penalties and other - insertions. - */ - incr(cur_line); - cur_p = next_break(cur_p); - if (cur_p != null && !post_disc_break) { - /*tex - Prune unwanted nodes at the beginning of the next line. Glue and - penalty and kern and math nodes are deleted at the beginning of a - line, except in the anomalous case that the node to be deleted is - actually one of the chosen breakpoints. Otherwise the pruning - done here is designed to match the lookahead computation in - |try_break|, where the |break_width| values are computed for - non-discretionary breakpoints. - */ - r = temp_head; - /*tex - Normally we have a matching math open and math close node but - when we cross a line the open node is removed, including any glue - or penalties following it. This is however not that nice for - callbacks that rely on symmetry. Of course this only counts for - one liners, as we can still have only a begin or end node on a - line. The end_of_math lua helper is made robust against this - although there you should be aware of the fact that one can end - up in the middle of math in callbacks that don't work on whole - paragraphs, but at least this branch makes sure that some proper - analysis is possible. (todo: check if math glyphs have the - subtype marked done). - */ - while (1) { - q = vlink(r); - /* - if (q == cur_break(cur_p) || is_char_node(q)) - break; - if (!((type(q) == local_par_node))) { - if (non_discardable(q) || (type(q) == kern_node && subtype(q) != explicit_kern && subtype(q) != italic_kern)) - break; - } - */ - if (type(q) == math_node) { - /*tex begin mathskip code */ - surround(q) = 0 ; - reset_glue_to_zero(q); - /*tex end mathskip code */ - } - if (q == cur_break(cur_p)) { - break; - } else if (is_char_node(q)) { - break; - } else if (type(q) == local_par_node) { - /*tex weird, in the middle somewhere */ - } else if (non_discardable(q)) { - break; - } else if (type(q) == kern_node && subtype(q) != explicit_kern && subtype(q) != italic_kern) { - break; - } - r = q; - } - if (r != temp_head) { - vlink(r) = null; - flush_node_list(vlink(temp_head)); - try_couple_nodes(temp_head, q); - } - } - } while (cur_p != null); - if ((cur_line != best_line) || (vlink(temp_head) != null)) - confusion("line breaking"); - /*tex prevgraf */ - cur_list.pg_field = best_line - 1; - /*tex |dir_save| */ - cur_list.dirs_field = dir_ptr; - dir_ptr = null; -} diff --git a/Build/source/texk/web2c/luatexdir/tex/postlinebreak.h b/Build/source/texk/web2c/luatexdir/tex/postlinebreak.h deleted file mode 100644 index 4aee1492c71..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/postlinebreak.h +++ /dev/null @@ -1,50 +0,0 @@ -/* postlinebreak.h - - Copyright 2009 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ - - -#ifndef POSTLINEBREAK_H -# define POSTLINEBREAK_H - -# define append_list(A,B) do { \ - couple_nodes(cur_list.tail_field,vlink((A))); \ - cur_list.tail_field = (B); \ -} while (0) - -void ext_post_line_break(int paragraph_dir, - int right_skip, - int left_skip, - int protrude_chars, - halfword par_shape_ptr, - int adjust_spacing, - halfword inter_line_penalties_ptr, - int inter_line_penalty, - int club_penalty, - halfword club_penalties_ptr, - halfword widow_penalties_ptr, - int widow_penalty, - int broken_penalty, - halfword final_par_glue, - halfword best_bet, - halfword last_special_line, - scaled second_width, - scaled second_indent, - scaled first_width, - scaled first_indent, halfword best_line); - -#endif diff --git a/Build/source/texk/web2c/luatexdir/tex/primitive.c b/Build/source/texk/web2c/luatexdir/tex/primitive.c deleted file mode 100644 index f16d69a333c..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/primitive.c +++ /dev/null @@ -1,785 +0,0 @@ -/* - -primitive.w - -Copyright 2008-2010 Taco Hoekwater <taco@@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your -option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU General Public License along -with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" - -/*tex - -Control sequences are stored and retrieved by means of a fairly standard hash -table algorithm called the method of ``coalescing lists'' (cf.\ Algorithm 6.4C in -{\sl The Art of Computer Programming\/}). Once a control sequence enters the -table, it is never removed, because there are complicated situations involving -\.{\\gdef} where the removal of a control sequence at the end of a group would be -a mistake preventable only by the introduction of a complicated reference-count -mechanism. - -The actual sequence of letters forming a control sequence identifier is stored in -the |str_pool| array together with all the other strings. An auxiliary array -|hash| consists of items with two halfword fields per word. The first of these, -called |next(p)|, points to the next identifier belonging to the same coalesced -list as the identifier corresponding to~|p|; and the other, called |text(p)|, -points to the |str_start| entry for |p|'s identifier. If position~|p| of the hash -table is empty, we have |text(p)=0|; if position |p| is either empty or the end -of a coalesced hash list, we have |next(p)=0|. An auxiliary pointer variable -called |hash_used| is maintained in such a way that all locations |p>=hash_used| -are nonempty. The global variable |cs_count| tells how many multiletter control -sequences have been defined, if statistics are being kept. - -A global boolean variable called |no_new_control_sequence| is set to |true| -during the time that new hash table entries are forbidden. - -*/ - -/*tex The hash table: */ - -two_halves *hash; - -/*tex Allocation pointer for |hash|: */ - -halfword hash_used; - -/*tex |hash_extra=hash| above |eqtb_size|: */ - -int hash_extra; - -/*tex Maximum of the hash array: */ - -halfword hash_top; - -/*tex Pointer to next high hash location: */ - -halfword hash_high; - -/*tex Are new identifiers legal? */ - -boolean no_new_control_sequence; - -/*tex Total number of known identifiers: */ - -int cs_count; - -/*tex Test if all positions are occupied: */ - -#define hash_is_full (hash_used==hash_base) - -/*tex - - \.{\\primitive} support needs a few extra variables and definitions, - like: - -*/ - -#define prim_base 1 - -/*tex - -The arrays |prim| and |prim_eqtb| are used for name -> cmd,chr lookups. The are -modelled after |hash| and |eqtb|, except that primitives do not have an -|eq_level|, that field is replaced by |origin|. - -*/ - -/*tex Link for coalesced lists: */ - -#define prim_next(a) prim[(a)].lhfield - -/*tex String number for control sequence name: */ - -#define prim_text(a) prim[(a)].rh - -/*tex Test if all positions are occupied: */ - -#define prim_is_full (prim_used==prim_base) - -#define prim_origin_field(a) (a).hh.b1 - -#define prim_eq_type_field(a) (a).hh.b0 - -#define prim_equiv_field(a) (a).hh.rh - -/*tex Level of definition: */ - -#define prim_origin(a) prim_origin_field(prim_eqtb[(a)]) - -/*tex Command code for equivalent: */ - -#define prim_eq_type(a) prim_eq_type_field(prim_eqtb[(a)]) - -/*tex Equivalent value: */ - -#define prim_equiv(a) prim_equiv_field(prim_eqtb[(a)]) - -/*tex Allocation pointer for |prim|: */ - -static pointer prim_used; - -/*tex The primitives table: */ - -static two_halves prim[(prim_size + 1)]; - -static memory_word prim_eqtb[(prim_size + 1)]; - -/*tex - -The array |prim_data| works the other way around, it is used for cmd,chr -> name -lookups. - -*/ - -typedef struct prim_info { - /*tex Number of name entries: */ - halfword subids; - /*tex Offset to be used for |chr_code|s: */ - halfword offset; - /*tex Array of names: */ - str_number *names; -} prim_info; - -static prim_info prim_data[(last_cmd + 1)]; - -/*tex - -Initialize the memory arrays: - -*/ - -void init_primitives(void) -{ - int k; - memset(prim_data, 0, (sizeof(prim_info) * (last_cmd + 1))); - memset(prim, 0, (sizeof(two_halves) * (prim_size + 1))); - memset(prim_eqtb, 0, (sizeof(memory_word) * (prim_size + 1))); - for (k = 0; k <= prim_size; k++) { - prim_eq_type(k) = undefined_cs_cmd; - } -} - -/*tex Nothing is used (yet). */ - -void ini_init_primitives(void) -{ - prim_used = prim_size; -} - - -/*tex - -The value of |hash_prime| should be roughly 85\%! of |hash_size|, and it should -be a prime number. The theory of hashing tells us to expect fewer than two table -probes, on the average, when the search is successful. [See J.~S. Vitter, {\sl -Journal of the ACM\/ \bf30} (1983), 231--258.] @^Vitter, Jeffrey Scott@> - -*/ - -static halfword compute_hash(const char *j, unsigned int l, halfword prime_number) -{ - int k; - halfword h = (unsigned char) *j; - for (k = 1; k <= (int)(l - 1); k++) { - h = h + h + (unsigned char) *(j + k); - while (h >= prime_number) { - h = h - prime_number; - } - } - return h; -} - -/*tex - -Here is the subroutine that searches the primitive table for an identifier. - -*/ - -pointer prim_lookup(str_number s) -{ - /*tex The hash code: */ - int h; - /*tex The index in the |hash| array: */ - pointer p; - unsigned char *j; - unsigned l; - if (s < STRING_OFFSET) { - p = s; - if ((p < 0) || (get_prim_eq_type(p) == undefined_cs_cmd)) { - p = undefined_primitive; - } - } else { - j = str_string(s); - l = (unsigned) str_length(s); - h = compute_hash((char *) j, l, prim_prime); - /*tex We start searching here; note that |0<=h<hash_prime|. */ - p = h + prim_base; - while (1) { - if (prim_text(p) > 0) - if (str_length(prim_text(p)) == l) - if (str_eq_str(prim_text(p), s)) - goto FOUND; - if (prim_next(p) == 0) { - if (no_new_control_sequence) { - p = undefined_primitive; - } else { - /*tex Insert a new primitive after |p|, then make |p| point to it. */ - if (prim_text(p) > 0) { - do { - /*tex Search for an empty location in |prim| */ - if (prim_is_full) { - overflow("primitive size", prim_size); - } - decr(prim_used); - } while (prim_text(prim_used) != 0); - prim_next(p) = prim_used; - p = prim_used; - } - prim_text(p) = s; - } - goto FOUND; - } - p = prim_next(p); - } - } - FOUND: - return p; -} - -/*tex - -How to test a csname for primitive-ness? - -*/ - -boolean is_primitive(str_number csname) -{ - int n, m; - char *ss; - m = prim_lookup(csname); - ss = makecstring(csname); - n = string_lookup(ss, str_length(csname)); - free(ss); - return ((n != undefined_cs_cmd) && (m != undefined_primitive) && - (eq_type(n) == prim_eq_type(m)) && (equiv(n) == prim_equiv(m))); -} - - -/*tex - -A few simple accessors. - -*/ - -quarterword get_prim_eq_type(int p) -{ - return prim_eq_type(p); -} - -quarterword get_prim_origin(int p) -{ - return prim_origin(p); -} - -halfword get_prim_equiv(int p) -{ - return prim_equiv(p); -} - -str_number get_prim_text(int p) -{ - return prim_text(p); -} - - -/*tex - -Dumping and undumping. - -*/ - -void dump_primitives(void) -{ - int p, q; - for (p = 0; p <= prim_size; p++) { - dump_hh(prim[p]); - } - for (p = 0; p <= prim_size; p++) { - dump_wd(prim_eqtb[p]); - } - for (p = 0; p <= last_cmd; p++) { - dump_int(prim_data[p].offset); - dump_int(prim_data[p].subids); - for (q = 0; q < prim_data[p].subids; q++) { - dump_int(prim_data[p].names[q]); - } - } -} - -void undump_primitives(void) -{ - int p, q; - for (p = 0; p <= prim_size; p++) { - undump_hh(prim[p]); - } - for (p = 0; p <= prim_size; p++) { - undump_wd(prim_eqtb[p]); - } - for (p = 0; p <= last_cmd; p++) { - undump_int(prim_data[p].offset); - undump_int(prim_data[p].subids); - if (prim_data[p].subids > 0) { - prim_data[p].names = (str_number *) xmalloc((unsigned) ((unsigned) prim_data[p].subids * sizeof(str_number *))); - for (q = 0; q < prim_data[p].subids; q++) { - undump_int(prim_data[p].names[q]); - } - } - } -} - -/*tex - -We need to put \TeX's ``primitive'' control sequences into the hash table, -together with their command code (which will be the |eq_type|) and an operand -(which will be the |equiv|). The |primitive| procedure does this, in a way that -no \TeX\ user can. The global value |cur_val| contains the new |eqtb| pointer -after |primitive| has acted. - -Because the definitions of the actual user-accessible name of a primitive can be -postponed until runtime, the function |primitive_def| is needed that does nothing -except creating the control sequence name. - -*/ - -void primitive_def(const char *s, size_t l, quarterword c, halfword o) -{ - int nncs = no_new_control_sequence; - no_new_control_sequence = false; - /*tex This creates the |text()| string: */ - cur_val = string_lookup(s, l); - no_new_control_sequence = nncs; - eq_level(cur_val) = level_one; - eq_type(cur_val) = c; - equiv(cur_val) = o; -} - -/*tex - -The function |store_primitive_name| sets up the bookkeeping for the reverse -lookup. It is quite paranoid, because it is easy to mess this up accidentally. - -The |offset| is needed because sometimes character codes (in |o|) are indices -into |eqtb| or are offset by a magical value to make sure they do not conflict -with something else. We don't want the |prim_data[c].names| to have too many -entries as it will just be wasted room, so |offset| is substracted from |o| -because creating or accessing the array. The |assert(idx<=0xFFFF)| is not -strictly needed, but it helps catch errors of this kind. - -*/ - -static void store_primitive_name(str_number s, quarterword c, halfword o, halfword offset) -{ - int idx; - /* - if (prim_data[c].offset != 0 && prim_data[c].offset != offset) { - assert(false); - } - */ - prim_data[c].offset = offset; - idx = ((int) o - offset); - /* - assert(idx >= 0); - assert(idx <= 0xFFFF); - */ - if (prim_data[c].subids < (idx + 1)) { - str_number *new = (str_number *) xcalloc((unsigned) (idx + 1), sizeof(str_number *)); - if (prim_data[c].names != NULL) { - /* - assert(prim_data[c].subids); - */ - memcpy(new, (prim_data[c].names), (unsigned) (prim_data[c].subids) * sizeof(str_number)); - free(prim_data[c].names); - } - prim_data[c].names = new; - prim_data[c].subids = idx + 1; - } - prim_data[c].names[idx] = s; -} - -/*tex - -Compared to tex82, |primitive| has two extra parameters. The |off| is an offset -that will be passed on to |store_primitive_name|, the |cmd_origin| is the bit -that is used to group primitives by originator. - -*/ - -void primitive(const char *thes, quarterword c, halfword o, halfword off, int cmd_origin) -{ - /*tex Needed to fill |prim_eqtb|: */ - int prim_val; - str_number ss; - ss = maketexstring(thes); - if (cmd_origin == tex_command || cmd_origin == core_command) { - primitive_def(thes, strlen(thes), c, o); - } - prim_val = prim_lookup(ss); - prim_origin(prim_val) = (quarterword) cmd_origin; - prim_eq_type(prim_val) = c; - prim_equiv(prim_val) = o; - store_primitive_name(ss, c, o, off); -} - -/*tex - -Here is a helper that does the actual hash insertion. This code far from ideal: -the existance of |hash_extra| changes all the potential (short) coalesced lists -into a single (long) one. This will create a slowdown. - -*/ - -static halfword insert_id(halfword p, const unsigned char *j, unsigned int l) -{ - unsigned saved_cur_length; - unsigned saved_cur_string_size; - unsigned char *saved_cur_string; - const unsigned char *k; - if (cs_text(p) > 0) { - if (hash_high < hash_extra) { - incr(hash_high); - /*tex - Can't we use |eqtb_top| here (perhaps because that is not - finalized yet when called from |primitive|? - */ - cs_next(p) = hash_high + eqtb_size; - p = cs_next(p); - } else { - /*tex - Search for an empty location in |hash|. - */ - do { - if (hash_is_full) - overflow("hash size", (unsigned) (hash_size + hash_extra)); - decr(hash_used); - } while (cs_text(hash_used) != 0); - cs_next(p) = hash_used; - p = hash_used; - } - } - saved_cur_length = cur_length; - saved_cur_string = cur_string; - saved_cur_string_size = cur_string_size; - reset_cur_string(); - for (k = j; k <= j + l - 1; k++) { - append_char(*k); - } - cs_text(p) = make_string(); - cur_length = saved_cur_length; - xfree(cur_string); - cur_string = saved_cur_string; - cur_string_size = saved_cur_string_size; - incr(cs_count); - return p; -} - - -/*tex - -Here is the subroutine that searches the hash table for an identifier that -matches a given string of length |l>1| appearing in |buffer[j.. (j+l-1)]|. If the -identifier is found, the corresponding hash table address is returned. Otherwise, -if the global variable |no_new_control_sequence| is |true|, the dummy address -|undefined_control_sequence| is returned. Otherwise the identifier is inserted -into the hash table and its location is returned. - -*/ - -pointer id_lookup(int j, int l) -{ - /*tex The hash code: */ - int h; - /*tex The index in |hash| array: */ - pointer p; - h = compute_hash((char *) (buffer + j), (unsigned) l, hash_prime); - /*tex We start searching here. Note that |0<=h<hash_prime|: */ - p = h + hash_base; - while (1) { - if (cs_text(p) > 0) - if (str_length(cs_text(p)) == (unsigned) l) - if (str_eq_buf(cs_text(p), j)) - goto FOUND; - if (cs_next(p) == 0) { - if (no_new_control_sequence) { - p = undefined_control_sequence; - } else { - p = insert_id(p, (buffer + j), (unsigned) l); - } - goto FOUND; - } - p = cs_next(p); - } - FOUND: - return p; -} - -/*tex - -Here is a similar subroutine for finding a primitive in the hash. -This one is based on a C string. - -*/ - -pointer string_lookup(const char *s, size_t l) -{ - /*tex The hash code: */ - int h; - /*tex The index in |hash| array: */ - pointer p; - h = compute_hash(s, (unsigned) l, hash_prime); - /*tex We start searching here. Note that |0<=h<hash_prime|: */ - p = h + hash_base; - while (1) { - if (cs_text(p) > 0) - if (str_eq_cstr(cs_text(p), s, l)) - goto FOUND; - if (cs_next(p) == 0) { - if (no_new_control_sequence) { - p = undefined_control_sequence; - } else { - p = insert_id(p, (const unsigned char *) s, (unsigned) l); - } - goto FOUND; - } - p = cs_next(p); - } - FOUND: - return p; -} - -/*tex - -The |print_cmd_chr| routine prints a symbolic interpretation of a command code -and its modifier. This is used in certain `\.{You can\'t}' error messages, and in -the implementation of diagnostic routines like \.{\\show}. - -The body of |print_cmd_chr| use to be a rather tedious listing of print commands, -and most of it was essentially an inverse to the |primitive| routine that enters -a \TeX\ primitive into |eqtb|. - -Thanks to |prim_data|, there is no need for all that tediousness. What is left of -|primt_cnd_chr| are just the exceptions to the general rule that the -|cmd,chr_code| pair represents in a single primitive command. - -*/ - -#define chr_cmd(A) do { tprint(A); print(chr_code); } while (0) - -static void prim_cmd_chr(quarterword cmd, halfword chr_code) -{ - int idx = chr_code - prim_data[cmd].offset; - if (cmd <= last_cmd && - idx >= 0 && idx < prim_data[cmd].subids && - prim_data[cmd].names != NULL && prim_data[cmd].names[idx] != 0) { - tprint_esc(""); - print(prim_data[cmd].names[idx]); - } else { - /* \TEX82 didn't print the |cmd,idx| information, but it may be useful. */ - tprint("[unknown command code! ("); - print_int(cmd); - tprint(", "); - print_int(idx); - tprint(")]"); - } -} - -void print_cmd_chr(quarterword cmd, halfword chr_code) -{ - int n; - switch (cmd) { - case left_brace_cmd: - chr_cmd("begin-group character "); - break; - case right_brace_cmd: - chr_cmd("end-group character "); - break; - case math_shift_cmd: - chr_cmd("math shift character "); - break; - case mac_param_cmd: - if (chr_code == tab_mark_cmd_code) - tprint_esc("alignmark"); - else - chr_cmd("macro parameter character "); - break; - case sup_mark_cmd: - chr_cmd("superscript character "); - break; - case sub_mark_cmd: - chr_cmd("subscript character "); - break; - case endv_cmd: - tprint("end of alignment template"); - break; - case spacer_cmd: - chr_cmd("blank space "); - break; - case letter_cmd: - chr_cmd("the letter "); - break; - case other_char_cmd: - chr_cmd("the character "); - break; - case tab_mark_cmd: - if (chr_code == span_code) - tprint_esc("span"); - else if (chr_code == tab_mark_cmd_code) - tprint_esc("aligntab"); - else - chr_cmd("alignment tab character "); - break; - case if_test_cmd: - if (chr_code >= unless_code) - tprint_esc("unless"); - prim_cmd_chr(cmd, (chr_code % unless_code)); - break; - case char_given_cmd: - tprint_esc("char"); - print_qhex(chr_code); - break; - case math_given_cmd: - /*tex - Okay, it's better for old macro packages that mess with meaning - to report a traditional value. A compromise. - */ - tprint_esc("mathchar"); - show_mathcode_value_old(chr_code); - break; - case xmath_given_cmd: - tprint_esc("Umathchar"); - show_mathcode_value(mathchar_from_integer(chr_code, umath_mathcode)); - break; - case lua_expandable_call_cmd: - tprint("expandable luacall "); - print_int(chr_code); - break; - case lua_local_call_cmd: - tprint("local luacall "); - print_int(chr_code); - break; - case lua_call_cmd: - tprint("luacall "); - print_int(chr_code); - break; - case set_font_cmd: - tprint("select font "); - tprint(font_name(chr_code)); - if (font_size(chr_code) != font_dsize(chr_code)) { - tprint(" at "); - print_scaled(font_size(chr_code)); - tprint("pt"); - } - break; - case undefined_cs_cmd: - tprint("undefined"); - break; - case call_cmd: - case long_call_cmd: - case outer_call_cmd: - case long_outer_call_cmd: - n = cmd - call_cmd; - if (token_info(token_link(chr_code)) == protected_token) - n = n + 4; - if (odd(n / 4)) - tprint_esc("protected"); - if (odd(n)) - tprint_esc("long"); - if (odd(n / 2)) - tprint_esc("outer"); - if (n > 0) - tprint(" "); - tprint("macro"); - break; - case assign_glue_cmd: - case assign_mu_glue_cmd: - if (chr_code < skip_base) { - prim_cmd_chr(cmd, chr_code); - } else if (chr_code < mu_skip_base) { - tprint_esc("skip"); - print_int(chr_code - skip_base); - } else { - tprint_esc("muskip"); - print_int(chr_code - mu_skip_base); - } - break; - case assign_toks_cmd: - if (chr_code >= toks_base) { - tprint_esc("toks"); - print_int(chr_code - toks_base); - } else { - prim_cmd_chr(cmd, chr_code); - } - break; - case assign_int_cmd: - if (chr_code < count_base) { - prim_cmd_chr(cmd, chr_code); - } else { - tprint_esc("count"); - print_int(chr_code - count_base); - } - break; - case assign_attr_cmd: - tprint_esc("attribute"); - print_int(chr_code - attribute_base); - break; - case assign_dimen_cmd: - if (chr_code < scaled_base) { - prim_cmd_chr(cmd, chr_code); - } else { - tprint_esc("dimen"); - print_int(chr_code - scaled_base); - } - break; - case normal_cmd: - if (chr_code < prim_data[cmd].subids && prim_data[cmd].names[chr_code] != 0) { - prim_cmd_chr(cmd, chr_code); - } else { - tprint("[unknown command! ("); - print_int(chr_code); - tprint(")]"); - } - break; - case extension_cmd: - if (chr_code < prim_data[cmd].subids && prim_data[cmd].names[chr_code] != 0) { - prim_cmd_chr(cmd, chr_code); - } else { - tprint("[unknown extension! ("); - print_int(chr_code); - tprint(")]"); - - } - break; - case node_cmd: - tprint("node "); - print_int(chr_code); - break; - default: - /*tex These are most commands, actually. */ - prim_cmd_chr(cmd, chr_code); - break; - } -} diff --git a/Build/source/texk/web2c/luatexdir/tex/primitive.h b/Build/source/texk/web2c/luatexdir/tex/primitive.h deleted file mode 100644 index b6b13c74f73..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/primitive.h +++ /dev/null @@ -1,89 +0,0 @@ -/* primitive.h - - Copyright 2008-2009 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ - - -#ifndef LUATEX_PRIMITIVE_H -# define LUATEX_PRIMITIVE_H 1 - -/* This enum is a list of origins for primitive commands */ - -typedef enum { - /* Can be modified as suggested ?*/ - tex_command = 1, /* 1 */ - etex_command = 2, /* 2 */ - pdftex_command = 16, /* 4 */ /* obsolete */ - luatex_command = 32, /* 8 */ - core_command = 64, /* 16 */ - no_command = 128, /* 32 */ - umath_command = 256, /* 64 */ /* obsolete */ -} command_origin; - -# define hash_size 65536 /* maximum number of control sequences; it should be at most about |(fix_mem_max-fix_mem_min)/10| */ -# define hash_prime 55711 /* a prime number equal to about 85\pct! of |hash_size| */ - -extern two_halves *hash; /* the hash table */ -extern halfword hash_used; /* allocation pointer for |hash| */ -extern int hash_extra; /* |hash_extra=hash| above |eqtb_size| */ -extern halfword hash_top; /* maximum of the hash array */ -extern halfword hash_high; /* pointer to next high hash location */ -extern boolean no_new_control_sequence; /* are new identifiers legal? */ -extern int cs_count; /* total number of known identifiers */ - -# define cs_next(a) hash[(a)].lhfield /* link for coalesced lists */ -# define cs_text(a) hash[(a)].rh - /* string number for control sequence name */ - -# define undefined_primitive 0 -# define prim_size 2100 /* maximum number of primitives */ -# define prim_prime 1777 /* about 85\pct! of |primitive_size| */ - -extern void init_primitives(void); -extern void ini_init_primitives(void); - -extern halfword compute_pool_hash(pool_pointer j, pool_pointer l, - halfword prime_number); -extern pointer prim_lookup(str_number s); - -extern boolean is_primitive(str_number csname); - -extern quarterword get_prim_eq_type(int p); -extern halfword get_prim_equiv(int p); -extern str_number get_prim_text(int p); -extern quarterword get_prim_origin(int p); - -extern void dump_primitives(void); -extern void undump_primitives(void); - -# define primitive_tex(a,b,c,d) primitive((a),(b),(c),(d),tex_command) -# define primitive_etex(a,b,c,d) primitive((a),(b),(c),(d),etex_command) -# define primitive_pdftex(a,b,c,d) primitive((a),(b),(c),(d),pdftex_command) -# define primitive_luatex(a,b,c,d) primitive((a),(b),(c),(d),luatex_command) -# define primitive_umath(a,b,c,d) primitive((a),(b),(c),(d),umath_command) -# define primitive_core(a,b,c,d) primitive((a),(b),(c),(d),core_command) -# define primitive_no(a,b,c,d) primitive((a),(b),(c),(d),no_command) - -extern void primitive(const char *ss, quarterword c, halfword o, halfword off, - int cmd_origin); -extern void primitive_def(const char *s, size_t l, quarterword c, halfword o); -extern void print_cmd_chr(quarterword cmd, halfword chr_code); - -extern pointer string_lookup(const char *s, size_t l); -extern pointer id_lookup(int j, int l); - -#endif /* LUATEX_PRIMITIVE_H */ diff --git a/Build/source/texk/web2c/luatexdir/tex/printing.c b/Build/source/texk/web2c/luatexdir/tex/printing.c deleted file mode 100644 index 31125d2ebca..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/printing.c +++ /dev/null @@ -1,1350 +0,0 @@ -/* - -printing.w - -Copyright 2009-2013 Taco Hoekwater <taco@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your -option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU General Public License along -with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" -#include "lua/luatex-api.h" - -#define wlog(A) fputc(A,log_file) -#define wterm(A) fputc(A,term_out) - -int new_string_line = 0; -int escape_controls = 1; - -/*tex - -Messages that are sent to a user's terminal and to the transcript-log file are -produced by several `|print|' procedures. These procedures will direct their -output to a variety of places, based on the setting of the global variable -|selector|, which has the following possible values: - -\startitemize - -\startitem - |term_and_log|, the normal setting, prints on the terminal and on the - transcript file. -\stopitem - -\startitem - |log_only|, prints only on the transcript file. -\stopitem - -\startitem - |term_only|, prints only on the terminal. -\stopitem - -\startitem - |no_print|, doesn't print at all. This is used only in rare cases before the - transcript file is open. -\stopitem - -\startitem - |pseudo|, puts output into a cyclic buffer that is used by the |show_context| - routine; when we get to that routine we shall discuss the reasoning behind - this curious mode. -\stopitem - -\startitem - |new_string|, appends the output to the current string in the string pool. -\stopitem - -\startitem - 0 to 15, prints on one of the sixteen files for \.{\\write} output. -\stopitem - -\stopitemize - -The symbolic names `|term_and_log|', etc., have been assigned numeric codes that -satisfy the convenient relations |no_print+1=term_only|, |no_print+2=log_only|, -|term_only+2=log_only+1=term_and_log|. - -Three additional global variables, |tally| and |term_offset| and |file_offset|, -record the number of characters that have been printed since they were most -recently cleared to zero. We use |tally| to record the length of (possibly very -long) stretches of printing; |term_offset| and |file_offset|, on the other hand, -keep track of how many characters have appeared so far on the current line that -has been output to the terminal or to the transcript file, respectively. - -*/ - -/*tex transcript of \TeX\ session */ - -alpha_file log_file; - -/*tex where to print a message */ - -int selector = term_only; - -/*tex digits in a number being output */ - -int dig[23]; - -/*tex the number of characters recently printed */ - -int tally = 0; - -/*tex the number of characters on the current terminal line */ - -int term_offset = 0; - -/*tex the number of characters on the current file line */ - -int file_offset = 0; - -/*tex circular buffer for pseudoprinting */ - -packed_ASCII_code trick_buf[(ssup_error_line + 1)]; - -/*tex threshold for pseudoprinting, explained later */ - -int trick_count; - -/*tex another variable for pseudoprinting */ - -int first_count; - -/*tex for minor adjustments to |show_token_list| */ - -boolean inhibit_par_tokens = false; - -/*tex - -To end a line of text output, we call |print_ln| - -*/ - -void print_ln(void) -{ - switch (selector) { - case no_print: - break; - case term_only: - wterm_cr(); - term_offset = 0; - break; - case log_only: - wlog_cr(); - file_offset = 0; - break; - case term_and_log: - wterm_cr(); - wlog_cr(); - term_offset = 0; - file_offset = 0; - break; - case pseudo: - break; - case new_string: - if (new_string_line > 0) - print_char(new_string_line); - break; - default: - fprintf(write_file[selector], "\n"); - break; - } - /*tex |tally| is not affected */ -} - -/*tex - -The |print_char| procedure sends one byte to the desired destination. All -printing comes through |print_ln| or |print_char|, except for the case of -|tprint| (see below). - -The checking of the line length is an inheritance from previosu engines and we -might drop it after release 1.0. We're not too picky about the exact match of -that length because we have utf output so length is then a bit fuzzy anyway. - -*/ - -#define needs_escaping(A) \ - ((! escape_controls) || (A>=0x20) || (A==0x0A) || (A==0x0D) || (A==0x09)) - -#define escaped_char(A) \ - A+64 - -#define wterm_char(A) \ - if (needs_escaping(A)) { \ - wterm(A); \ - } else { \ - if (term_offset+2>=max_print_line) { \ - wterm_cr(); \ - term_offset=0; \ - } \ - wterm('^'); \ - wterm('^'); \ - wterm(escaped_char(A)); \ - term_offset += 2; \ - } - -#define needs_wrapping(A,B) \ - ( (A>=0xC0) && \ - (((A>=0xF0) && (B+4>=max_print_line)) || \ - ((A>=0xE0) && (B+3>=max_print_line)) || \ - ( (B+2>=max_print_line))) \ - ) - -#define fix_term_offset(A) \ - if (needs_wrapping(A,term_offset)){ \ - wterm_cr(); \ - term_offset=0; \ - } - -#define fix_log_offset(A) \ - if (needs_wrapping(A,file_offset)){ \ - wlog_cr(); \ - file_offset=0; \ - } - -void print_char(int s) -{ - if (s < 0 || s > 255) { - formatted_warning("print","weird character %i",s); - return; - } - if (s == new_line_char_par) { - if (selector < pseudo) { - print_ln(); - return; - } - } - switch (selector) { - case no_print: - break; - case term_only: - fix_term_offset(s); - wterm_char(s); - incr(term_offset); - if (term_offset == max_print_line) { - wterm_cr(); - term_offset = 0; - } - break; - case log_only: - fix_log_offset(s); - wlog(s); - incr(file_offset); - if (file_offset == max_print_line) { - wlog_cr(); - file_offset = 0; - } - break; - case term_and_log: - fix_term_offset(s); - fix_log_offset(s); - wterm_char(s); - wlog(s); - incr(term_offset); - incr(file_offset); - if (term_offset == max_print_line) { - wterm_cr(); - term_offset = 0; - } - if (file_offset == max_print_line) { - wlog_cr(); - file_offset = 0; - } - break; - case pseudo: - if (tally < trick_count) - trick_buf[tally % error_line] = (packed_ASCII_code) s; - break; - case new_string: - append_char(s); - break; - default: - fprintf(write_file[selector], "%c", s); - } - incr(tally); -} - -/*tex - -An entire string is output by calling |print|. Note that if we are outputting the -single standard ASCII character \.c, we could call |print("c")|, since |"c"=99| -is the number of a single-character string, as explained above. But -|print_char("c")| is quicker, so \TeX\ goes directly to the |print_char| routine -when it knows that this is safe. (The present implementation assumes that it is -always safe to print a visible ASCII character.) - -The first 256 entries above the 17th unicode plane are used for a special trick: -when \TeX\ has to print items in that range, it will instead print the character -that results from substracting 0x110000 from that value. This allows -byte-oriented output to things like \.{\\specials} and \.{\\pdfextension -literals}. Todo: Perhaps it would be useful to do the same substraction while -typesetting. - - -*/ - -void print(int s) -{ - if (s >= str_ptr) { - normal_warning("print","bad string pointer"); - return; - } else if (s < STRING_OFFSET) { - if (s < 0) { - normal_warning("print","bad string offset"); - } else { - /*tex We're not sure about this so it's disabled for now! */ - if ((false) && (selector > pseudo)) { - /*tex internal strings are not expanded */ - print_char(s); - return; - } - if (s == new_line_char_par) { - if (selector < pseudo) { - print_ln(); - return; - } - } - if (s <= 0x7F) { - print_char(s); - } else if (s <= 0x7FF) { - print_char(0xC0 + (s / 0x40)); - print_char(0x80 + (s % 0x40)); - } else if (s <= 0xFFFF) { - print_char(0xE0 + (s / 0x1000)); - print_char(0x80 + ((s % 0x1000) / 0x40)); - print_char(0x80 + ((s % 0x1000) % 0x40)); - } else if (s >= 0x110000) { - int c = s - 0x110000; - if (c >= 256) { - formatted_warning("print", "bad raw byte to print (c=%d), skipped",c); - } else { - print_char(c); - } - } else { - print_char(0xF0 + (s / 0x40000)); - print_char(0x80 + ((s % 0x40000) / 0x1000)); - print_char(0x80 + (((s % 0x40000) % 0x1000) / 0x40)); - print_char(0x80 + (((s % 0x40000) % 0x1000) % 0x40)); - } - } - return; - } - if (selector == new_string) { - append_string(str_string(s), (unsigned) str_length(s)); - return; - } - lprint(&str_lstring(s)); -} - -void lprint (lstring *ss) { - /*tex current character code position */ - unsigned char *j, *l; - j = ss->s; - l = j + ss->l; - while (j < l) { - /*tex I don't bother checking the last two bytes explicitly */ - /* 0x110000 in utf=8: 0xF4 0x90 0x80 0x80 */ - if ((j < l - 4) && (*j == 0xF4) && (*(j + 1) == 0x90)) { - int c = (*(j + 2) - 128) * 64 + (*(j + 3) - 128); - assert(c >= 0 && c < 256); - print_char(c); - j = j + 4; - } else { - print_char(*j); - incr(j); - } - } -} - -/*tex - -The procedure |print_nl| is like |print|, but it makes sure that the string -appears at the beginning of a new line. - -*/ - -/*tex Moev to the beginning of the next line. */ - -void print_nlp(void) -{ - if (new_string_line > 0) { - print_char(new_string_line); - } else if (((term_offset > 0) && (odd(selector))) || - ((file_offset > 0) && (selector >= log_only))) { - print_ln(); - } -} - -/*tex Prints string |s| at beginning of the next line. */ - -void print_nl(str_number s) -{ - print_nlp(); - print(s); -} - -/*tex - -|char *| versions of the same procedures. |tprint| is different because it uses -buffering, which works well because most of the output actually comes through -|tprint|. - -*/ - -#define t_flush_buffer(target,offset) \ - buffer[i++] = '\n'; \ - buffer[i++] = '\0';\ - fputs(buffer, target); \ - i = 0; \ - buffer[0] = '\0'; \ - offset=0; - -void tprint(const char *sss) -{ - char *buffer = NULL; - int i = 0; - int newlinechar = (lua_only == 1) ? 10 : new_line_char_par; - int dolog = 0; - int doterm = 0; - switch (selector) { - case no_print: - return; - break; - case term_only: - doterm = 1; - break; - case log_only: - dolog = 1; - break; - case term_and_log: - dolog = 1; - doterm = 1; - break; - case pseudo: - while (*sss) { - if (tally < trick_count) { - trick_buf[tally % error_line] = (packed_ASCII_code) *sss++; - tally++; - } else { - return; - } - } - return; - break; - case new_string: - append_string((const unsigned char *)sss, (unsigned) strlen(sss)); - return; - break; - default: - { - char *newstr = xstrdup(sss); - char *s; - for (s=newstr;*s;s++) { - if (*s == newlinechar) { - *s = '\n'; - } - } - fputs(newstr, write_file[selector]); - free(newstr); - return; - } - break; - } - /*tex What is left is the 3 term/log settings. */ - if (dolog || doterm) { - buffer = xmalloc(strlen(sss)*3); - /*tex The |wrapup_run| callback acts when the log file is already closed.*/ - if (dolog && log_opened_global) { - const unsigned char *ss = (const unsigned char *) sss; - while (*ss) { - int s = *ss++; - if (needs_wrapping(s,file_offset) || s == newlinechar) { - t_flush_buffer(log_file,file_offset); - } - if (s != newlinechar) { - buffer[i++] = s; - if (file_offset++ == max_print_line) { - t_flush_buffer(log_file,file_offset); - } - } - } - if (*buffer) { - buffer[i++] = '\0'; - fputs(buffer, log_file); - buffer[0] = '\0'; - } - i = 0; - } - if (doterm) { - const unsigned char *ss = (const unsigned char *) sss; - while (*ss) { - int s = *ss++; - if (needs_wrapping(s,term_offset) || s == newlinechar) { - t_flush_buffer(term_out,term_offset); - } - if (s != newlinechar) { - if (needs_escaping(s)) { - buffer[i++] = s; - } else { - buffer[i++] = '^'; - buffer[i++] = '^'; - buffer[i++] = escaped_char(s); - term_offset += 2; - } - if (++term_offset == max_print_line) { - t_flush_buffer(term_out,term_offset); - } - } - } - if (*buffer) { - buffer[i++] = '\0'; - fputs(buffer, term_out); - } - } - free(buffer); - } -} - -void tprint_nl(const char *s) -{ - print_nlp(); - tprint(s); -} - -/*tex - -Here is the very first thing that \TeX\ prints: a headline that identifies the -version number and format package. The |term_offset| variable is temporarily -incorrect, but the discrepancy is not serious since we assume that the banner and -format identifier together will occupy at most |max_print_line| character -positions. - -*/ - -void print_banner(const char *v) -{ - int callback_id = callback_defined(start_run_callback); - if (callback_id == 0) { - fprintf(term_out, "This is " MyName ", Version %s%s ", v, WEB2CVERSION); - if (format_ident > 0) - print(format_ident); - print_ln(); - if (show_luahashchars) { - wterm(' '); - fprintf(term_out,"Number of bits used by the hash function (" my_name "): %d",LUAI_HASHLIMIT); - print_ln(); - } - if (shellenabledp) { - wterm(' '); - if (restrictedshell) { - fprintf(term_out, "restricted "); - } - fprintf(term_out, "system commands enabled.\n"); - } - } else if (callback_id > 0) { - run_callback(callback_id, "->"); - } -} - -void log_banner(const char *v) -{ - const char *months[] = { " ", - "JAN", "FEB", "MAR", "APR", "MAY", "JUN", - "JUL", "AUG", "SEP", "OCT", "NOV", "DEC" - }; - unsigned month = (unsigned) month_par; - if (month > 12) - month = 0; - fprintf(log_file, "This is " MyName ", Version %s%s ", v, WEB2CVERSION); - print(format_ident); - print_char(' '); - print_char(' '); - print_int(day_par); - print_char(' '); - fprintf(log_file, "%s", months[month]); - print_char(' '); - print_int(year_par); - print_char(' '); - print_two(time_par / 60); - print_char(':'); - print_two(time_par % 60); - if (shellenabledp) { - wlog_cr(); - wlog(' '); - if (restrictedshell) - fprintf(log_file, "restricted "); - fprintf(log_file, "system commands enabled."); - } - if (filelineerrorstylep) { - wlog_cr(); - fprintf(log_file, " file:line:error style messages enabled."); - } -} - -void print_version_banner(void) -{ - fprintf(term_out, "%s", luatex_banner); -} - -/*tex - -The procedure |print_esc| prints a string that is preceded by the user's escape -character (which is usually a backslash). - -*/ - -void print_esc(str_number s) -{ - /*tex Set variable |c| to the current escape character: */ - int c = escape_char_par; - if (c >= 0 && c < 0x110000) - print(c); - print(s); -} - -/*tex - -This prints escape character, then |s|. - -*/ - -void tprint_esc(const char *s) -{ - /*tex Set variable |c| to the current escape character: */ - int c = escape_char_par; - if (c >= 0 && c < 0x110000) - print(c); - tprint(s); -} - -/*tex - -An array of digits in the range |0..15| is printed by |print_the_digs|. - -*/ - -void print_the_digs(eight_bits k) -{ - /*tex prints |dig[k-1]|$\,\ldots\,$|dig[0]| */ - while (k-- > 0) { - if (dig[k] < 10) - print_char('0' + dig[k]); - else - print_char('A' - 10 + dig[k]); - } -} - -/*tex - -The following procedure, which prints out the decimal representation of a given -integer |n|, has been written carefully so that it works properly if |n=0| or if -|(-n)| would cause overflow. It does not apply |mod| or |div| to negative -arguments, since such operations are not implemented consistently by all PASCAL -compilers. - -*/ - -void print_int(longinteger n) -{ - /*tex index to current digit; we assume that $|n|<10^{23}$ */ - int k = 0; - /*tex used to negate |n| in possibly dangerous cases */ - longinteger m; - if (n < 0) { - print_char('-'); - if (n > -100000000) { - n = -n; - } else { - m = -1 - n; - n = m / 10; - m = (m % 10) + 1; - k = 1; - if (m < 10) - dig[0] = (int) m; - else { - dig[0] = 0; - incr(n); - } - } - } - do { - dig[k] = (int) (n % 10); - n = n / 10; - incr(k); - } while (n != 0); - print_the_digs((eight_bits) k); -} - -/*tex - -Here is a trivial procedure to print two digits; it is usually called with a -parameter in the range |0<=n<=99|. - -*/ - -void print_two(int n) -{ - n = abs(n) % 100; - print_char('0' + (n / 10)); - print_char('0' + (n % 10)); -} - -/*tex - -Hexadecimal printing of nonnegative integers is accomplished by |print_hex|. - -*/ - -void print_qhex(int n) -{ - /*tex index to current digit; we assume that $0\L n<16^{22}$ */ - int k = 0 ; - print_char('"'); - do { - dig[k] = n % 16; - n = n / 16; - incr(k); - } while (n != 0); - print_the_digs((eight_bits) k); -} - -/*tex - -Roman numerals are produced by the |print_roman_int| routine. Readers who like -puzzles might enjoy trying to figure out how this tricky code works; therefore no -explanation will be given. Notice that 1990 yields \.{mcmxc}, not \.{mxm}. - -*/ - -void print_roman_int(int n) -{ - char *j, *k; - int u, v; - char mystery[] = "m2d5c2l5x2v5i"; - j = (char *) mystery; - v = 1000; - while (1) { - while (n >= v) { - print_char(*j); - n = n - v; - } - if (n <= 0) { - /*tex nonpositive input produces no output */ - return; - } - k = j + 2; - u = v / (*(k - 1) - '0'); - if (*(k - 1) == '2') { - k = k + 2; - u = u / (*(k - 1) - '0'); - } - if (n + u >= v) { - print_char(*k); - n = n + u; - } else { - j = j + 2; - v = v / (*(j - 1) - '0'); - } - } -} - -/*tex - -The |print| subroutine will not print a string that is still being created. The -following procedure will. - -*/ - -void print_current_string(void) -{ - /*tex points to current character code */ - unsigned j = 0; - while (j < cur_length) - print_char(cur_string[j++]); -} - -/*tex - -The procedure |print_cs| prints the name of a control sequence, given a pointer -to its address in |eqtb|. A space is printed after the name unless it is a single -nonletter or an active character. This procedure might be invoked with invalid -data, so it is ``extra robust.'' The individual characters must be printed one at -a time using |print|, since they may be unprintable. - -*/ - -void print_cs(int p) -{ - str_number t = cs_text(p); - if (p < hash_base) { - /* nullcs */ - if (p == null_cs) { - tprint_esc("csname"); - tprint_esc("endcsname"); - print_char(' '); - } else { - tprint_esc("IMPOSSIBLE."); - } - } else if ((p >= undefined_control_sequence) && - ((p <= eqtb_size) || p > eqtb_size + hash_extra)) { - tprint_esc("IMPOSSIBLE."); - } else if (t >= str_ptr) { - tprint_esc("NONEXISTENT."); - } else { - if (is_active_cs(t)) { - print(active_cs_value(t)); - } else { - print_esc(t); - if (single_letter(t)) { - if (get_cat_code(cat_code_table_par, pool_to_unichar(str_string(t))) == letter_cmd) - print_char(' '); - } else { - print_char(' '); - } - } - } -} - -/*tex - -Here is a similar procedure; it avoids the error checks, and it never prints a -space after the control sequence. - -*/ -void sprint_cs(pointer p) -{ - str_number t; - if (p == null_cs) { - tprint_esc("csname"); - tprint_esc("endcsname"); - } else { - t = cs_text(p); - if (is_active_cs(t)) - print(active_cs_value(t)); - else - print_esc(t); - } -} - -void sprint_cs_name(pointer p) -{ - str_number t; - if (p != null_cs) { - t = cs_text(p); - if (is_active_cs(t)) - print(active_cs_value(t)); - else - print(t); - } -} - -/*tex - -This procedure is never called when |interaction<scroll_mode|. - -*/ - -void prompt_input(const char *s) -{ - wake_up_terminal(); - tprint(s); - term_input(); -} - -/*tex - -Then there is a subroutine that prints glue stretch and shrink, possibly followed -by the name of finite units: - -*/ - -void print_glue(scaled d, int order, const char *s) -{ - print_scaled(d); - if ((order < normal) || (order > filll)) { - tprint("foul"); - } else if (order > normal) { - tprint("fi"); - while (order > sfi) { - print_char('l'); - decr(order); - } - } else if (s != NULL) { - tprint(s); - } -} - -/*tex - -The next subroutine prints a whole glue specification - -*/ - -void print_spec(int p, const char *s) -{ - if (p < 0) { - print_char('*'); - } else { - print_scaled(width(p)); - if (s != NULL) - tprint(s); - if (stretch(p) != 0) { - tprint(" plus "); - print_glue(stretch(p), stretch_order(p), s); - } - if (shrink(p) != 0) { - tprint(" minus "); - print_glue(shrink(p), shrink_order(p), s); - } - } -} - -/*tex - -We can reinforce our knowledge of the data structures just introduced by -considering two procedures that display a list in symbolic form. The first of -these, called |short_display|, is used in ``overfull box'' messages to give the -top-level description of a list. The other one, called |show_node_list|, prints a -detailed description of exactly what is in the data structure. - -The philosophy of |short_display| is to ignore the fine points about exactly what -is inside boxes, except that ligatures and discretionary breaks are expanded. As -a result, |short_display| is a recursive procedure, but the recursion is never -more than one level deep. @^recursion@> - -A global variable |font_in_short_display| keeps track of the font code that is -assumed to be present when |short_display| begins; deviations from this font will -be printed. - -*/ - -/*tex An internal font number: */ - -int font_in_short_display; - -/*tex - -Boxes, rules, inserts, whatsits, marks, and things in general that are sort of -``complicated'' are indicated only by printing `\.{[]}'. - -We print a bit more than original \TEX. A value of 0 or 1 or any large value will -behave the same as before. The reason for this extension is that a |name| not -always makes sense. - -\starttyping -0 \foo xyz -1 \foo (bar) -2 <bar> xyz -3 <bar @ ..> xyz -4 <id> -5 <id: bar> -6 <id: bar @ ..> xyz -\stoptyping - -*/ - -void print_font_identifier(internal_font_number f) -{ - str_number fonttext; - fonttext = font_id_text(f); - if (tracing_fonts_par >= 2 && tracing_fonts_par <= 6) { - /*tex < > is less likely to clash with text parenthesis */ - tprint("<"); - if (tracing_fonts_par >= 2 && tracing_fonts_par <= 3) { - print_font_name(f); - if (tracing_fonts_par >= 3 || font_size(f) != font_dsize(f)) { - tprint(" @ "); - print_scaled(font_size(f)); - tprint("pt"); - } - } else if (tracing_fonts_par >= 4 && tracing_fonts_par <= 6) { - print_int(f); - if (tracing_fonts_par >= 5) { - tprint(": "); - print_font_name(f); - if (tracing_fonts_par >= 6 || font_size(f) != font_dsize(f)) { - tprint(" @ "); - print_scaled(font_size(f)); - tprint("pt"); - } - } - } - print_char('>'); - } else { - /*tex old method, inherited from pdftex */ - if (fonttext > 0) { - print_esc(fonttext); - } else { - tprint_esc("FONT"); - print_int(f); - } - if (tracing_fonts_par > 0) { - tprint(" ("); - print_font_name(f); - if (font_size(f) != font_dsize(f)) { - tprint("@"); - print_scaled(font_size(f)); - tprint("pt"); - } - print_char(')'); - } - } -} - -/*tex - We could do this much nicer but then we need to also adapt short_display a - bit and we have to be as compatible as possible in the log for some macro - packages. - - The callback is also responsible for either or not reporting the character - number itself. -*/ - -void print_character_info(halfword p) -{ - int callback_id = callback_defined(glyph_info_callback); - if (callback_id) { - char* str = NULL; - run_callback(callback_id, "N->R", p, &str); - if (str == NULL) { - print_qhex(character(p)); - } else { - tprint(str); - free(str); - } - } else { - print(character(p)); - } -} - -/*tex - This prints highlights of list |p|. -*/ - -void short_display(int p) -{ - while (p != null) { - if (is_char_node(p)) { - if (lig_ptr(p) != null) { - short_display(lig_ptr(p)); - } else { - if (font(p) != font_in_short_display) { - if (!is_valid_font(font(p))) { - print_char('*'); - } else { - print_font_identifier(font(p)); - } - print_char(' '); - font_in_short_display = font(p); - } - print_character_info(p); - } - } else { - /*tex Print a short indication of the contents of node |p| */ - print_short_node_contents(p); - } - p = vlink(p); - } -} - -/*tex - -The |show_node_list| routine requires some auxiliary subroutines: one to print a -font-and-character combination, one to print a token list without its reference -count, and one to print a rule dimension. - -*/ - -/*tex - -This prints |char_node| data. - -*/ - -void print_font_and_char(int p) -{ - if (!is_valid_font(font(p))) - print_char('*'); - else - print_font_identifier(font(p)); - print_char(' '); - print_character_info(p); -} - -/*tex - -This prints token list data in braces - -*/ - -void print_mark(int p) -{ - print_char('{'); - if ((p < (int) fix_mem_min) || (p > (int) fix_mem_end)) - tprint_esc("CLOBBERED."); - else - show_token_list(token_link(p), null, max_print_line - 10); - print_char('}'); -} - -/*tex - -This prints dimensions of a rule node. - -*/ - -void print_rule_dimen(scaled d) -{ - if (is_running(d)) - print_char('*'); - else - print_scaled(d); -} - -/*tex - -Since boxes can be inside of boxes, |show_node_list| is inherently recursive, -@^recursion@> up to a given maximum number of levels. The history of nesting is -indicated by the current string, which will be printed at the beginning of each -line; the length of this string, namely |cur_length|, is the depth of nesting. - -A global variable called |depth_threshold| is used to record the maximum depth of -nesting for which |show_node_list| will show information. If we have -|depth_threshold=0|, for example, only the top level information will be given -and no sublists will be traversed. Another global variable, called |breadth_max|, -tells the maximum number of items to show at each level; |breadth_max| had better -be positive, or you won't see anything. - -*/ - -/*tex The maximum nesting depth in box displays: */ - -int depth_threshold; - -/*tex The maximum number of items shown at the same list level: */ - -int breadth_max; - -/*tex - -The recursive machinery is started by calling |show_box|. Assign the values -|depth_threshold:=show_box_depth| and |breadth_max:=show_box_breadth| - -*/ - -void show_box(halfword p) -{ - depth_threshold = show_box_depth_par; - breadth_max = show_box_breadth_par; - if (breadth_max <= 0) - breadth_max = 5; - /*tex the show starts at |p| */ - show_node_list(p); - print_ln(); -} - -/*tex - -Helper for debugging purposes. It prints highlights of list |p| - -*/ - -void short_display_n(int p, int m) -{ - int i = 0; - font_in_short_display = null_font; - if (p == null) - return; - while (p != null) { - if (is_char_node(p)) { - if (p <= max_halfword) { - if (font(p) != font_in_short_display) { - if (!is_valid_font(font(p))) - print_char('*'); - else - print_font_identifier(font(p)); - print_char(' '); - font_in_short_display = font(p); - } - print_character_info(p); - } - } else { - if ( (type(p) == glue_node) || - (type(p) == disc_node) || - (type(p) == penalty_node) || - ((type(p) == kern_node) && (subtype(p) == explicit_kern || - subtype(p) == italic_kern ))) { - incr(i); - } - if (i >= m) - return; - if (type(p) == disc_node) { - print_char('|'); - short_display(vlink(pre_break(p))); - print_char('|'); - short_display(vlink(post_break(p))); - print_char('|'); - } else { - /*tex Print a short indication of the contents of node |p| */ - print_short_node_contents(p); - } - } - p = vlink(p); - if (p == null) - return; - } - update_terminal(); -} - -/*tex - -When debugging a macro package, it can be useful to see the exact control -sequence names in the format file. For example, if ten new csnames appear, it's -nice to know what they are, to help pinpoint where they came from. (This isn't a -truly ``basic'' printing procedure, but that's a convenient module in which to -put it.) - -*/ - -void print_csnames(int hstart, int hfinish) -{ - int h; - unsigned char *c, *l; - fprintf(stderr, "fmtdebug:csnames from %d to %d:", (int) hstart, (int) hfinish); - for (h = hstart; h <= hfinish; h++) { - if (cs_text(h) > 0) { - /*tex We have anything at this position. */ - c = str_string(cs_text(h)); - l = c + str_length(cs_text(h)); - while (c < l) { - /*tex Print the characters. */ - fputc(*c++, stderr); - } - fprintf(stderr, "|"); - } - } -} - -/*tex - -A helper for printing file:line:error style messages. Look for a filename in -|full_source_filename_stack|, and if we fail to find one fall back on the -non-file:line:error style. - -*/ - -void print_file_line(void) -{ - int level = in_open; - while ((level > 0) && (full_source_filename_stack[level] == 0)) - decr(level); - if (level == 0) { - tprint_nl("! "); - } else { - tprint_nl(""); - tprint(full_source_filename_stack[level]); - print_char(':'); - if (level == in_open) - print_int(line); - else - print_int(line_stack[level + 1]); - tprint(": "); - } -} - -/*tex - -\TeX\ is occasionally supposed to print diagnostic information that goes only -into the transcript file, unless |tracing_online| is positive. Here are two -routines that adjust the destination of print commands: - -*/ - -void begin_diagnostic(void) -{ - global_old_setting = selector; - if ((tracing_online_par <= 0) && (selector == term_and_log)) { - decr(selector); - if (history == spotless) - history = warning_issued; - } -} - -/*tex - -Restore proper conditions after tracing. - -*/ - -void end_diagnostic(boolean blank_line) -{ - tprint_nl(""); - if (blank_line) - print_ln(); - selector = global_old_setting; -} - -/* - Indentation (based on a suggestion by PO on tex-implementors but adapted to - out situation and with built-in limits and so. -*/ - -void print_input_level(void) -{ - int callback_id = callback_defined(input_level_string_callback); - if (callback_id>0) { - char *s = NULL; - if (run_callback(callback_id, "d->S", input_ptr, &s)) { - if (s && strlen(s) > 0) { - tprint_nl(s); - free(s); - } else { - print_ln(); - } - } else { - print_ln(); - } - } else { - int m = level_max; - if (m) { - int l = input_ptr; - int c = level_chr > 0 ? level_chr : '.'; - if (l > m) { - tprint_nl("["); - print_int((l/m)*m); - print(']'); - l = l % m; - } else { - print_ln(); - } - while (l > 0) { - print(c); - l--; - } - } else { - print_ln(); - } - } -} - -/*tex - -Of course we had better declare another global variable, if the previous routines -are going to work. - -*/ - -int global_old_setting; diff --git a/Build/source/texk/web2c/luatexdir/tex/printing.h b/Build/source/texk/web2c/luatexdir/tex/printing.h deleted file mode 100644 index 0d87f3d4ae7..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/printing.h +++ /dev/null @@ -1,133 +0,0 @@ -/* printing.h - - Copyright 2009 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ - -#ifndef PRINTING_H -# define PRINTING_H - -#define last_file_selector 127 /* was 15 */ - -/* - Nicer will be to start these with 0 and then use an offset for the write - registers internally. -*/ - -typedef enum { - no_print = last_file_selector + 1, /* 16 */ /* |selector| setting that makes data disappear */ - term_only = last_file_selector + 2, /* 17 */ /* printing is destined for the terminal only */ - log_only = last_file_selector + 3, /* 18 */ /* printing is destined for the transcript file only */ - term_and_log = last_file_selector + 4, /* 19 */ /* normal |selector| setting */ - pseudo = last_file_selector + 5, /* 20 */ /* special |selector| setting for |show_context| */ - new_string = last_file_selector + 6, /* 21 */ /* printing is deflected to the string pool */ -} selector_settings; - -extern int escape_controls; -extern int new_string_line; - -# define ssup_error_line 255 -# define max_selector new_string /* highest selector setting */ - -extern alpha_file log_file; -extern int selector; -extern int dig[23]; -extern int tally; -extern int term_offset; -extern int file_offset; -extern packed_ASCII_code trick_buf[(ssup_error_line + 1)]; -extern int trick_count; -extern int first_count; -extern boolean inhibit_par_tokens; - -/* - Macro abbreviations for output to the terminal and to the log file are - defined here for convenience. Some systems need special conventions - for terminal output, and it is possible to adhere to those conventions - by changing |wterm|, |wterm_ln|, and |wterm_cr| in this section. - @^system dependencies@> -*/ - -# define wterm_cr() fprintf(term_out,"\n") -# define wlog_cr() fprintf(log_file,"\n") - -extern void print_ln(void); -extern void print_char(int s); -extern void print(int s); -extern void lprint (lstring *ss); -extern void print_nl(str_number s); -extern void print_nlp(void); -extern void print_banner(const char *); -extern void log_banner(const char *); -extern void print_version_banner(void); -extern void print_esc(str_number s); -extern void print_the_digs(eight_bits k); -extern void print_int(longinteger n); -extern void print_two(int n); -extern void print_qhex(int n); -extern void print_roman_int(int n); -extern void print_current_string(void); - -# define print_font_name(A) tprint(font_name(A)) - -extern void print_cs(int p); -extern void sprint_cs(pointer p); -extern void sprint_cs_name(pointer p); -extern void tprint(const char *s); -extern void tprint_nl(const char *s); -extern void tprint_esc(const char *s); - -extern void prompt_input(const char *s); - -# define single_letter(A) \ - ((str_length(A)==1)|| \ - ((str_length(A)==4)&&*(str_string((A)))>=0xF0)|| \ - ((str_length(A)==3)&&*(str_string((A)))>=0xE0)|| \ - ((str_length(A)==2)&&*(str_string((A)))>=0xC0)) - -# define is_active_cs(a) \ - (a && str_length(a)>3 && \ - ( *str_string(a) == 0xEF) && \ - (*(str_string(a)+1) == 0xBF) && \ - (*(str_string(a)+2) == 0xBF)) - -# define active_cs_value(A) pool_to_unichar((str_string((A))+3)) - -extern void print_glue(scaled d, int order, const char *s); /* prints a glue component */ -extern void print_spec(int p, const char *s); /* prints a glue specification */ - -extern int font_in_short_display; /* an internal font number */ -extern void print_font_identifier(internal_font_number f); -extern void short_display(int p); /* prints highlights of list |p| */ -extern void print_font_and_char(int p); /* prints |char_node| data */ -extern void print_mark(int p); /* prints token list data in braces */ -extern void print_rule_dimen(scaled d); /* prints dimension in rule node */ -extern int depth_threshold; /* maximum nesting depth in box displays */ -extern int breadth_max; /* maximum number of items shown at the same list level */ -extern void show_box(halfword p); -extern void short_display_n(int p, int m); /* prints highlights of list |p| */ - -extern void print_csnames(int hstart, int hfinish); -extern void print_file_line(void); - -extern void begin_diagnostic(void); -extern void print_input_level(void); -extern void end_diagnostic(boolean blank_line); -extern int global_old_setting; - -extern void print_character_info(halfword p); - -#endif diff --git a/Build/source/texk/web2c/luatexdir/tex/scanning.c b/Build/source/texk/web2c/luatexdir/tex/scanning.c deleted file mode 100644 index deddbf5649b..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/scanning.c +++ /dev/null @@ -1,2751 +0,0 @@ -/* - -Copyright 2009-2012 Taco Hoekwater <taco@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under the terms -of the GNU General Public License as published by the Free Software Foundation; -either version 2 of the License, or (at your option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - -You should have received a copy of the GNU General Public License along with -LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" - -static void scan_expr(void); - -/*tex - - Let's turn now to some procedures that \TeX\ calls upon frequently to digest - certain kinds of patterns in the input. Most of these are quite simple; some - are quite elaborate. Almost all of the routines call |get_x_token|, which can - cause them to be invoked recursively. - - The |scan_left_brace| routine is called when a left brace is supposed to be - the next non-blank token. (The term ``left brace'' means, more precisely, a - character whose catcode is |left_brace|.) \TeX\ allows \.{\\relax} to appear - before the |left_brace|. - -*/ - -/* This reads a mandatory |left_brace|: */ - -void scan_left_brace(void) -{ - /*tex Get the next non-blank non-relax non-call token */ - do { - get_x_token(); - } while ((cur_cmd == spacer_cmd) || (cur_cmd == relax_cmd)); - if (cur_cmd != left_brace_cmd) { - print_err("Missing { inserted"); - help4( - "A left brace was mandatory here, so I've put one in.", - "You might want to delete and/or insert some corrections", - "so that I will find a matching right brace soon.", - "If you're confused by all this, try typing `I}' now." - ); - back_error(); - cur_tok = left_brace_token + '{'; - cur_cmd = left_brace_cmd; - cur_chr = '{'; - incr(align_state); - } -} - -/*tex - - The |scan_optional_equals| routine looks for an optional `\.=' sign preceded - by optional spaces; `\.{\\relax}' is not ignored here. - -*/ - -void scan_optional_equals(void) -{ - /*tex Get the next non-blank non-call token */ - do { - get_x_token(); - } while (cur_cmd == spacer_cmd); - if (cur_tok != other_token + '=') - back_input(); -} - -/*tex - - Here is a procedure that sounds an alarm when mu and non-mu units are being - switched. - -*/ - -static void mu_error(void) -{ - print_err("Incompatible glue units"); - help1("I'm going to assume that 1mu=1pt when they're mixed."); - error(); -} - -/*tex - - The next routine `|scan_something_internal|' is used to fetch internal - numeric quantities like `\.{\\hsize}', and also to handle the `\.{\\the}' - when expanding constructions like `\.{\\the\\toks0}' and - `\.{\\the\\baselineskip}'. Soon we will be considering the |scan_int| - procedure, which calls |scan_something_internal|; on the other hand, - |scan_something_internal| also calls |scan_int|, for constructions like - `\.{\\catcode\`\\\$}' or `\.{\\fontdimen} \.3 \.{\\ff}'. So we have to - declare |scan_int| as a |forward| procedure. A few other procedures are also - declared at this point. - - \TeX\ doesn't know exactly what to expect when |scan_something_internal| - begins. For example, an integer or dimension or glue value could occur - immediately after `\.{\\hskip}'; and one can even say \.{\\the} with respect - to token lists in constructions like `\.{\\xdef\\o\{\\the\\output\}}'. On the - other hand, only integers are allowed after a construction like - `\.{\\count}'. To handle the various possibilities, |scan_something_internal| - has a |level| parameter, which tells the ``highest'' kind of quantity that - |scan_something_internal| is allowed to produce. Eight levels are - distinguished, namely |int_val|, |attr_val|, |dimen_val|, |glue_val|, - |mu_val|, |dir_val|, |ident_val|, and |tok_val|. - - The output of |scan_something_internal| (and of the other routines - |scan_int|, |scan_dimen|, and |scan_glue| below) is put into the global - variable |cur_val|, and its level is put into |cur_val_level|. The highest - values of |cur_val_level| are special: |mu_val| is used only when |cur_val| - points to something in a ``muskip'' register, or to one of the three - parameters \.{\\thinmuskip}, \.{\\medmuskip}, \.{\\thickmuskip}; |ident_val| - is used only when |cur_val| points to a font identifier; |tok_val| is used - only when |cur_val| points to |null| or to the reference count of a token - list. The last two cases are allowed only when |scan_something_internal| is - called with |level=tok_val|. - - If the output is glue, |cur_val| will point to a glue specification, and the - reference count of that glue will have been updated to reflect this - reference; if the output is a nonempty token list, |cur_val| will point to - its reference count, but in this case the count will not have been updated. - Otherwise |cur_val| will contain the integer or scaled value in question. - -*/ - -/*tex The value returned by numeric scanners: */ - -int cur_val; - -/*tex Delcodes are sometimes 51 digits: */ - -int cur_val1; - -/*tex The level of this value: */ - -int cur_val_level; - -#define scanned_result(A,B) do { \ - cur_val=A; \ - cur_val_level=B; \ -} while (0) - -/*tex - - When a |glue_val| changes to a |dimen_val|, we use the width component of the - glue; there is no need to decrease the reference count, since it has not yet - been increased. When a |dimen_val| changes to an |int_val|, we use scaled - points so that the value doesn't actually change. And when a |mu_val| changes - to a |glue_val|, the value doesn't change either. - -*/ - -static void downgrade_cur_val(boolean delete_glue) -{ - if (cur_val_level == glue_val_level) { - halfword m = cur_val; - cur_val = width(m); - if (delete_glue) - flush_node(m); - } else if (cur_val_level == mu_val_level) { - mu_error(); - } - decr(cur_val_level); -} - -void negate_cur_val(boolean modify_glue) -{ - if (cur_val_level >= glue_val_level) { - if (modify_glue) { - /*tex We modify in-place. */ - } else { - cur_val = new_spec(cur_val); - } - negate(width(cur_val)); - negate(stretch(cur_val)); - negate(shrink(cur_val)); - } else { - negate(cur_val); - } -} - -/*tex - - Some of the internal items can be fetched both routines, and these have been - split off into the next routine, that returns true if the command code was - understood. - -*/ - -static boolean short_scan_something_internal(int cmd, int chr, int level, boolean negative) -{ - /*tex |chr_code| part of the operand token */ - halfword m; - /*tex general purpose index */ - halfword q; - /*tex index into |nest| */ - int p; - int save_cur_chr; - boolean succeeded = true; - m = chr; - switch (cmd) { - case assign_toks_cmd: - scanned_result(equiv(m), tok_val_level); - break; - case assign_int_cmd: - scanned_result(eqtb[m].cint, int_val_level); - break; - case assign_attr_cmd: - scanned_result(eqtb[m].cint, int_val_level); - break; - case assign_dimen_cmd: - scanned_result(eqtb[m].cint, dimen_val_level); - break; - case assign_glue_cmd: - scanned_result(equiv(m), glue_val_level); - break; - case assign_mu_glue_cmd: - scanned_result(equiv(m), mu_val_level); - break; - case assign_direction_cmd: - if (m == (int_base + line_direction_code)) { - m = int_base + text_direction_code; - } - scanned_result(eqtb[m].cint, int_val_level); - break; - case assign_dir_cmd: - if (m == (int_base + line_direction_code)) { - m = int_base + text_direction_code; - } - scanned_result(eqtb[m].cint, dir_val_level); - break; - case math_style_cmd: - scanned_result(m, int_val_level); - break; - case set_aux_cmd: - /*tex Fetch the |space_factor| or the |prev_depth|. */ - if (abs(cur_list.mode_field) != m) { - print_err("Improper "); - print_cmd_chr(set_aux_cmd, m); - help4( - "You can refer to \\spacefactor only in horizontal mode;", - "you can refer to \\prevdepth only in vertical mode; and", - "neither of these is meaningful inside \\write. So", - "I'm forgetting what you said and using zero instead." - ); - error(); - if (level != tok_val_level) - scanned_result(0, dimen_val_level); - else - scanned_result(0, int_val_level); - } else if (m == vmode) { - scanned_result(prev_depth_par, dimen_val_level); - } else { - scanned_result(space_factor_par, int_val_level); - } - break; - case set_prev_graf_cmd: - /*tex Fetch the |prev_graf| */ - if (cur_list.mode_field == 0) { - /*tex |prev_graf=0| within \.{\\write} */ - scanned_result(0, int_val_level); - } else { - p = nest_ptr; - while (abs(nest[p].mode_field) != vmode) - decr(p); - scanned_result(nest[p].pg_field, int_val_level); - } - break; - case set_page_int_cmd: - /*tex Fetch the |dead_cycles| or the |insert_penalties| */ - if (m == 0) - cur_val = dead_cycles; - else if (m == 2) - cur_val = interaction; - else - cur_val = insert_penalties; - cur_val_level = int_val_level; - break; - case set_page_dimen_cmd: - /*tex Fetch something on the |page_so_far|. */ - if ((page_contents == empty) && (!output_active)) { - if (m == 0) - cur_val = max_dimen; - else - cur_val = 0; - } else { - cur_val = page_so_far[m]; - } - cur_val_level = dimen_val_level; - break; - case set_tex_shape_cmd: - /*tex Fetch the |par_shape| size. */ - if (par_shape_par_ptr == null) - cur_val = 0; - else - cur_val = vinfo(par_shape_par_ptr + 1); - cur_val_level = int_val_level; - break; - case set_etex_shape_cmd: - /*tex Fetch a penalties array element. */ - scan_int(); - if ((equiv(m) == null) || (cur_val < 0)) { - cur_val = 0; - } else { - if (cur_val > penalty(equiv(m))) - cur_val = penalty(equiv(m)); - cur_val = penalty(equiv(m) + cur_val); - } - cur_val_level = int_val_level; - break; - case char_given_cmd: - case math_given_cmd: - case xmath_given_cmd: - scanned_result(cur_chr, int_val_level); - break; - case last_item_cmd: - /*tex - - Because the items in this case directly refer to |cur_chr|, it - needs to be saved and restored. - - */ - save_cur_chr = cur_chr; - cur_chr = chr; - /*tex - - Fetch an item in the current node, if appropriate. Here is where - \.{\\lastpenalty}, \.{\\lastkern}, and \.{\\ } are implemented. - The reference count for \.{\\lastskip} will be updated later. - - We also handle \.{\\inputlineno} and \.{\\badness} here, because - they are legal in similar contexts. - - */ - if (m >= input_line_no_code) { - if (m >= eTeX_glue) { - /*tex Process an expression and |return|. */ - if (m < eTeX_mu) { - if (m == mu_to_glue_code) { - scan_mu_glue(); - }; - cur_val_level = glue_val_level; - } else if (m < eTeX_expr) { - if (m == glue_to_mu_code) { - scan_normal_glue(); - } - cur_val_level = mu_val_level; - } else { - cur_val_level = m - eTeX_expr + int_val_level; - scan_expr(); - } - /*tex - - This code for reducing |cur_val_level| and\slash or - negating the result is similar to the one for all the - other cases of |scan_something_internal|; we free a - glue_spec when needed. - - */ - while (cur_val_level > level) { - downgrade_cur_val(true); - } - if (negative) { - /*tex - - We get a new glue spec node with negated values and - the old intermediate is deleted. - - */ - negate_cur_val(true); - } - return succeeded; - } else if (m >= eTeX_dim) { - switch (m) { - case font_char_wd_code: - case font_char_ht_code: - case font_char_dp_code: - case font_char_ic_code: - scan_font_ident(); - q = cur_val; - scan_char_num(); - if (char_exists(q, cur_val)) { - switch (m) { - case font_char_wd_code: - cur_val = char_width(q, cur_val); - break; - case font_char_ht_code: - cur_val = char_height(q, cur_val); - break; - case font_char_dp_code: - cur_val = char_depth(q, cur_val); - break; - case font_char_ic_code: - cur_val = char_italic(q, cur_val); - break; - } - } else { - cur_val = 0; - } - break; - case par_shape_length_code: - case par_shape_indent_code: - case par_shape_dimen_code: - q = cur_chr - par_shape_length_code; - scan_int(); - if ((par_shape_par_ptr == null) || (cur_val <= 0)) { - cur_val = 0; - } else { - if (q == 2) { - q = cur_val % 2; - cur_val = (cur_val + q) / 2; - } - if (cur_val > vinfo(par_shape_par_ptr + 1)) - cur_val = vinfo(par_shape_par_ptr + 1); - cur_val = - varmem[par_shape_par_ptr + 2 * cur_val - q + 1].cint; - } - cur_val_level = dimen_val_level; - break; - case glue_stretch_code: - case glue_shrink_code: - scan_normal_glue(); - q = cur_val; - if (m == glue_stretch_code) - cur_val = stretch(q); - else - cur_val = shrink(q); - flush_node(q); - break; - } - cur_val_level = dimen_val_level; - } else { - switch (m) { - case input_line_no_code: - cur_val = line; - break; - case badness_code: - cur_val = last_badness; - break; - case luatex_version_code: - cur_val = get_luatexversion(); - break; - case last_saved_box_resource_index_code: - cur_val = last_saved_box_index; - break; - case last_saved_image_resource_index_code: - cur_val = last_saved_image_index; - break; - case last_saved_image_resource_pages_code: - cur_val = last_saved_image_pages; - break; - case last_x_pos_code: - cur_val = last_position.h; - break; - case last_y_pos_code: - cur_val = last_position.v; - break; - case random_seed_code: - cur_val = random_seed; - break; - case eTeX_version_code: - cur_val = eTeX_version; - break; - case eTeX_minor_version_code: - cur_val = eTeX_minor_version; - break; - case current_group_level_code: - cur_val = cur_level - level_one; - break; - case current_group_type_code: - cur_val = cur_group; - break; - case current_if_level_code: - q = cond_ptr; - cur_val = 0; - while (q != null) { - incr(cur_val); - q = vlink(q); - } - break; - case current_if_type_code: - if (cond_ptr == null) - cur_val = 0; - else if (cur_if < unless_code) - cur_val = cur_if + 1; - else - cur_val = -(cur_if - unless_code + 1); - break; - case current_if_branch_code: - if ((if_limit == or_code) || (if_limit == else_code)) - cur_val = 1; - else if (if_limit == fi_code) - cur_val = -1; - else - cur_val = 0; - break; - case glue_stretch_order_code: - case glue_shrink_order_code: - case eTeX_glue_stretch_order_code: - case eTeX_glue_shrink_order_code: - scan_normal_glue(); - q = cur_val; - if (m == glue_stretch_order_code || m == eTeX_glue_stretch_order_code) { - cur_val = stretch_order(q); - } else { - cur_val = shrink_order(q); - } - if (cur_val && (m == eTeX_glue_stretch_order_code || m == eTeX_glue_shrink_order_code)) { - cur_val = (cur_val == 1) ? - 1 : cur_val - 1; - } - flush_node(q); - break; - } - cur_val_level = int_val_level; - } - } else { - if (cur_chr == glue_val_level) - cur_val = zero_glue; - else - cur_val = 0; - if (cur_chr == last_node_type_code) { - cur_val_level = int_val_level; - if ((cur_list.tail_field == cur_list.head_field) - || (cur_list.mode_field == 0)) - cur_val = -1; - } else { - /*tex assumes identical values */ - cur_val_level = cur_chr; - } - if ((cur_list.tail_field != contrib_head) && (cur_list.mode_field != 0)) { - switch (cur_chr) { - case lastpenalty_code: - if (type(cur_list.tail_field) == penalty_node) - cur_val = penalty(cur_list.tail_field); - break; - case lastkern_code: - if (type(cur_list.tail_field) == kern_node) - cur_val = width(cur_list.tail_field); - break; - case lastskip_code: - if (type(cur_list.tail_field) == glue_node) - cur_val = cur_list.tail_field; - if (subtype(cur_list.tail_field) == mu_glue) - cur_val_level = mu_val_level; - break; - case last_node_type_code: - cur_val = visible_last_node_type(cur_list.tail_field); - break; - } - } else if ((cur_list.mode_field == vmode) && (cur_list.tail_field == cur_list.head_field)) { - switch (cur_chr) { - case lastpenalty_code: - cur_val = last_penalty; - break; - case lastkern_code: - cur_val = last_kern; - break; - case lastskip_code: - if (last_glue != max_halfword) - cur_val = last_glue; - break; - case last_node_type_code: - cur_val = last_node_type; - break; - } - } - } - cur_chr = save_cur_chr; - break; - default: - succeeded = false; - } - if (succeeded) { - while (cur_val_level > level) { - /*tex Convert |cur_val| to a lower level. */ - downgrade_cur_val(false); - } - /*tex - - Fix the reference count, if any, and negate |cur_val| if |negative|. - If |cur_val| points to a glue specification at this point, the - reference count for the glue does not yet include the reference by - |cur_val|. If |negative| is |true|, |cur_val_level| is known to be - |<=mu_val|. - - */ - if (negative) { - /*tex We create a new (negated) glue spec and keep the old one. */ - negate_cur_val(false); - } else if ((cur_val_level >= glue_val_level) && (cur_val_level <= mu_val_level)) { - cur_val = new_spec(cur_val); - } - } - return succeeded; -} - -/*tex - - First, here is a short routine that is called from lua code. All the real - work is delegated to |short_scan_something_internal| that is shared between - this routine and |scan_something_internal|. - -*/ - -void scan_something_simple(halfword cmd, halfword subitem) -{ - /*tex Negative is never true. */ - if (!short_scan_something_internal(cmd, subitem, tok_val_level, false)) { - /*tex Complain that |texlib| can not do this; give zero result. */ - print_err("You can't use `"); - print_cmd_chr((quarterword) cmd, subitem); - tprint("' as tex library index"); - help1("I'm forgetting what you said and using zero instead."); - error(); - scanned_result(0, int_val_level); - } -} - -/*tex - - OK, we're ready for |scan_something_internal| itself. A second parameter, - |negative|, is set |true| if the value that is found should be negated. It is - assumed that |cur_cmd| and |cur_chr| represent the first token of the - internal quantity to be scanned; an error will be signalled if - |cur_cmd<min_internal| or |cur_cmd>max_internal|. - -*/ - -/*tex Fetch an internal parameter: */ - -void scan_something_internal(int level, boolean negative) -{ - /*tex |chr_code| part of the operand token */ - halfword m; - /*tex accumulators */ - int n, k; - RESTART: - m = cur_chr; - if (!short_scan_something_internal(cur_cmd, cur_chr, level, negative)) { - switch (cur_cmd) { - case def_char_code_cmd: - /*tex Fetch a character code from some table */ - scan_char_num(); - if (m == math_code_base) { - cur_val1 = get_math_code_num(cur_val); - scanned_result(cur_val1, int_val_level); - } else if (m == lc_code_base) { - cur_val1 = get_lc_code(cur_val); - scanned_result(cur_val1, int_val_level); - } else if (m == uc_code_base) { - cur_val1 = get_uc_code(cur_val); - scanned_result(cur_val1, int_val_level); - } else if (m == sf_code_base) { - cur_val1 = get_sf_code(cur_val); - scanned_result(cur_val1, int_val_level); - } else if (m == cat_code_base) { - cur_val1 = get_cat_code(cat_code_table_par, cur_val); - scanned_result(cur_val1, int_val_level); - } else { - confusion("def_char"); - } - break; - case def_del_code_cmd: - case extdef_del_code_cmd: - /*tex Fetch a character code from some table. */ - scan_char_num(); - cur_val1 = get_del_code_num(cur_val); - scanned_result(cur_val1, int_val_level); - break; - case extdef_math_code_cmd: - /*tex Fetch an extended math code table value. */ - scan_char_num(); - cur_val1 = get_math_code_num(cur_val); - scanned_result(cur_val1, int_val_level); - break; - case toks_register_cmd: - case set_font_cmd: - case def_font_cmd: - case letterspace_font_cmd: - case copy_font_cmd: - /*tex Fetch a token list or font identifier, provided that |level=tok_val|. */ - if (level != tok_val_level) { - print_err("Missing number, treated as zero"); - help3( - "A number should have been here; I inserted `0'.", - "(If you can't figure out why I needed to see a number,", - "look up `weird error' in the index to The TeXbook.)" - ); - back_error(); - scanned_result(0, dimen_val_level); - } else if (cur_cmd == toks_register_cmd) { - scan_register_num(); - m = toks_base + cur_val; - scanned_result(equiv(m), tok_val_level); - } else { - back_input(); - scan_font_ident(); - scanned_result(font_id_base + cur_val, ident_val_level); - } - break; - case set_font_id_cmd: - scan_int(); - scanned_result(font_id_base + cur_val, ident_val_level); - break; - case def_family_cmd: - /*tex Fetch a math font identifier. */ - scan_char_num(); - cur_val1 = fam_fnt(cur_val, m); - scanned_result(font_id_base + cur_val1, ident_val_level); - break; - case set_math_param_cmd: - /*tex Fetch a math parameter. */ - cur_val1 = cur_chr; - get_token(); - if (cur_cmd != math_style_cmd) { - print_err("Missing math style, treated as \\displaystyle"); - help1("A style should have been here; I inserted `\\displaystyle'."); - cur_val = display_style; - back_error(); - } else { - cur_val = cur_chr; - } - if (cur_val1 < math_param_first_mu_glue) { - if (cur_val1 == math_param_radical_degree_raise) { - cur_val1 = get_math_param(cur_val1, cur_chr); - scanned_result(cur_val1, int_val_level); - } else { - cur_val1 = get_math_param(cur_val1, cur_chr); - scanned_result(cur_val1, dimen_val_level); - } - } else { - cur_val1 = get_math_param(cur_val1, cur_chr); - if (cur_val1 == thin_mu_skip_code) - cur_val1 = thin_mu_skip_par; - else if (cur_val1 == med_mu_skip_code) - cur_val1 = med_mu_skip_par; - else if (cur_val1 == thick_mu_skip_code) - cur_val1 = thick_mu_skip_par; - scanned_result(cur_val1, mu_val_level); - } - break; - case assign_box_dir_cmd: - scan_register_num(); - m = cur_val; - if (box(m) != null) - cur_val = box_dir(box(m)); - else - cur_val = 0; - cur_val_level = dir_val_level; - break; - case set_box_dimen_cmd: - /*tex Fetch a box dimension. */ - scan_register_num(); - if (box(cur_val) == null) - cur_val = 0; - else - cur_val = varmem[box(cur_val) + m].cint; - cur_val_level = dimen_val_level; - break; - case assign_font_dimen_cmd: - /*tex Fetch a font dimension. */ - get_font_dimen(); - break; - case assign_font_int_cmd: - /*tex Fetch a font integer. */ - scan_font_ident(); - if (m == 0) { - scanned_result(hyphen_char(cur_val), int_val_level); - } else if (m == 1) { - scanned_result(skew_char(cur_val), int_val_level); - } else if (m == no_lig_code) { - scanned_result(test_no_ligatures(cur_val), int_val_level); - } else { - n = cur_val; - scan_char_num(); - k = cur_val; - switch (m) { - case lp_code_base: - scanned_result(get_lp_code(n, k), int_val_level); - break; - case rp_code_base: - scanned_result(get_rp_code(n, k), int_val_level); - break; - case ef_code_base: - scanned_result(get_ef_code(n, k), int_val_level); - break; - case tag_code: - scanned_result(get_tag_code(n, k), int_val_level); - break; - } - } - break; - case register_cmd: - /*tex Fetch a register */ - scan_register_num(); - switch (m) { - case int_val_level: - cur_val = count(cur_val); - break; - case attr_val_level: - cur_val = attribute(cur_val); - break; - case dimen_val_level: - cur_val = dimen(cur_val); - break; - case glue_val_level: - cur_val = skip(cur_val); - break; - case mu_val_level: - cur_val = mu_skip(cur_val); - break; - } - cur_val_level = m; - break; - case ignore_spaces_cmd: - /*tex Trap unexpandable primitives. */ - if (cur_chr == 1) { - /*tex - - Reset |cur_tok| for unexpandable primitives, goto - restart. This block deals with unexpandable - \.{\\primitive} appearing at a spot where an integer or - an internal values should have been found. It fetches the - next token then resets |cur_cmd|, |cur_cs|, and - |cur_tok|, based on the primitive value of that token. No - expansion takes place, because the next token may be all - sorts of things. This could trigger further expansion - creating new errors. - - */ - get_token(); - cur_cs = prim_lookup(cs_text(cur_cs)); - if (cur_cs != undefined_primitive) { - cur_cmd = get_prim_eq_type(cur_cs); - cur_chr = get_prim_equiv(cur_cs); - cur_tok = token_val(cur_cmd, cur_chr); - } else { - cur_cmd = relax_cmd; - cur_chr = 0; - cur_tok = cs_token_flag + frozen_relax; - cur_cs = frozen_relax; - } - goto RESTART; - } - break; - case hyph_data_cmd: - switch (cur_chr) { - case 0: - case 1: - goto DEFAULT; - break; - case 2: - cur_val = get_pre_hyphen_char(language_par); - cur_val_level = int_val_level; - break; - case 3: - cur_val = get_post_hyphen_char(language_par); - cur_val_level = int_val_level; - break; - case 4: - cur_val = get_pre_exhyphen_char(language_par); - cur_val_level = int_val_level; - break; - case 5: - cur_val = get_post_exhyphen_char(language_par); - cur_val_level = int_val_level; - break; - case 6: - cur_val = get_hyphenation_min(language_par); - cur_val_level = int_val_level; - break; - case 7: - scan_int(); - cur_val = get_hj_code(language_par,cur_val); - cur_val_level = int_val_level; - break; - } - break; - default: - DEFAULT: - /*tex Complain that \.{\\the} can not do this; give zero result. */ - print_err("You can't use `"); - print_cmd_chr((quarterword) cur_cmd, cur_chr); - tprint("' after \\the"); - help1("I'm forgetting what you said and using zero instead."); - error(); - if (level != tok_val_level) - scanned_result(0, dimen_val_level); - else - scanned_result(0, int_val_level); - break; - } - while (cur_val_level > level) { - /*tex Convert |cur_val| to a lower level. */ - downgrade_cur_val(false); - } - /*tex - - Fix the reference count, if any, and negate |cur_val| if |negative|. - If |cur_val| points to a glue specification at this point, the - reference count for the glue does not yet include the reference by - |cur_val|. If |negative| is |true|, |cur_val_level| is known to be - |<=mu_val|. - - */ - if (negative) { - /*tex We create a new (negated) glue spec and keep the old one. */ - negate_cur_val(false); - } else if ((cur_val_level >= glue_val_level) && (cur_val_level <= mu_val_level)) { - cur_val = new_spec(cur_val); - } - } -} - -/*tex - - It is nice to have routines that say what they do, so the original - |scan_eight_bit_int| is superceded by |scan_register_num| and - |scan_mark_num|. It may become split up even further in the future. - - Many of the |restricted classes| routines are the essentially the same except - for the upper limit and the error message, so it makes sense to combine these - all into one function. - -*/ - -void scan_limited_int(int max, const char *name) -{ - char hlp[80]; - scan_int(); - if ((cur_val < 0) || (cur_val > max)) { - if (name == NULL) { - snprintf(hlp, 80, "Since I expected to read a number between 0 and %d,", max); - print_err("Bad number"); - } else { - char msg[80]; - snprintf(hlp, 80, "A %s must be between 0 and %d.", name, max); - snprintf(msg, 80, "Bad %s", name); - print_err(msg); - } - help2(hlp, "I changed this one to zero."); - int_error(cur_val); - cur_val = 0; - } -} - -void scan_fifteen_bit_int(void) -{ - scan_real_fifteen_bit_int(); - cur_val = ((cur_val / 0x1000) * 0x1000000) + (((cur_val % 0x1000) / 0x100) * 0x10000) + (cur_val % 0x100); -} - -void scan_fifty_one_bit_int(void) -{ - int iiii; - scan_int(); - if ((cur_val < 0) || (cur_val > 0777777777)) { - print_err("Bad delimiter code"); - help2( - "A numeric delimiter (first part) must be between 0 and 2^{27}-1.", - "I changed this one to zero." - ); - int_error(cur_val); - cur_val = 0; - } - iiii = cur_val; - scan_int(); - if ((cur_val < 0) || (cur_val > 0xFFFFFF)) { - print_err("Bad delimiter code"); - help2( - "A numeric delimiter (second part) must be between 0 and 2^{24}-1.", - "I changed this one to zero." - ); - int_error(cur_val); - cur_val = 0; - } - cur_val1 = cur_val; - cur_val = iiii; -} - -/*tex - - An integer number can be preceded by any number of spaces and `\.+' or `\.-' - signs. Then comes either a decimal constant (i.e., radix 10), an octal - constant (i.e., radix 8, preceded by~'), a hexadecimal constant (radix 16, - preceded by~"), an alphabetic constant (preceded by~`), or an internal - variable. After scanning is complete, |cur_val| will contain the answer, - which must be at most $2^{31}-1=2147483647$ in absolute value. The value of - |radix| is set to 10, 8, or 16 in the cases of decimal, octal, or hexadecimal - constants, otherwise |radix| is set to zero. An optional space follows a - constant. - -*/ - -/*tex |scan_int| sets this to 8, 10, 16, or zero */ - -int radix; - -/*tex - - The |scan_int| routine is used also to scan the integer part of a fraction; - for example, the `\.3' in `\.{3.14159}' will be found by |scan_int|. The - |scan_dimen| routine assumes that |cur_tok=point_token| after the integer - part of such a fraction has been scanned by |scan_int|, and that the decimal - point has been backed up to be scanned again. - -*/ - -/*tex Sets |cur_val| to an integer: */ - -void scan_int(void) -{ - /*tex should the answer be negated? */ - boolean negative; - /*tex |$2^{31}$ / radix|, the threshold of danger */ - int m; - /*tex the digit just scanned */ - int d; - /*tex have no digits appeared? */ - boolean vacuous; - /*tex has an error message been issued? */ - boolean OK_so_far; - radix = 0; - OK_so_far = true; - /*tex Get the next non-blank non-sign token; set |negative| appropriately. */ - negative = false; - do { - /*tex Get the next non-blank non-call token. */ - do { - get_x_token(); - } while (cur_cmd == spacer_cmd); - if (cur_tok == other_token + '-') { - negative = !negative; - cur_tok = other_token + '+'; - } - } while (cur_tok == other_token + '+'); - - RESTART: - if (cur_tok == alpha_token) { - /*tex - - Scan an alphabetic character code into |cur_val|. A space is ignored - after an alphabetic character constant, so that such constants behave - like numeric ones. - - */ - /*tex Suppress macro expansion: */ - get_token(); - if (cur_tok < cs_token_flag) { - cur_val = cur_chr; - if (cur_cmd <= right_brace_cmd) { - if (cur_cmd == right_brace_cmd) - incr(align_state); - else - decr(align_state); - } - } else { - /*tex The value of a csname in this context is its name. */ - str_number txt = cs_text(cur_tok - cs_token_flag); - if (is_active_cs(txt)) - cur_val = active_cs_value(txt); - else if (single_letter(txt)) - cur_val = pool_to_unichar(str_string(txt)); - else - cur_val = (biggest_char + 1); - } - if (cur_val > biggest_char) { - print_err("Improper alphabetic constant"); - help2( - "A one-character control sequence belongs after a ` mark.", - "So I'm essentially inserting \\0 here." - ); - cur_val = '0'; - back_error(); - } else { - /*tex Scan an optional space. */ - get_x_token(); - if (cur_cmd != spacer_cmd) - back_input(); - } - - } else if (cur_tok == cs_token_flag + frozen_primitive) { - /*tex - - Reset |cur_tok| for unexpandable primitives, goto restart This block - deals with unexpandable \.{\\primitive} appearing at a spot where an - integer or an internal values should have been found. It fetches the - next token then resets |cur_cmd|, |cur_cs|, and |cur_tok|, based on - the primitive value of that token. No expansion takes place, because - the next token may be all sorts of things. This could trigger further - expansion creating new errors. - - */ - get_token(); - cur_cs = prim_lookup(cs_text(cur_cs)); - if (cur_cs != undefined_primitive) { - cur_cmd = get_prim_eq_type(cur_cs); - cur_chr = get_prim_equiv(cur_cs); - cur_tok = token_val(cur_cmd, cur_chr); - } else { - cur_cmd = relax_cmd; - cur_chr = 0; - cur_tok = cs_token_flag + frozen_relax; - cur_cs = frozen_relax; - } - goto RESTART; - } else if (cur_cmd == math_style_cmd) { - cur_val = cur_chr; - } else if ((cur_cmd >= min_internal_cmd) && (cur_cmd <= max_internal_cmd)) { - scan_something_internal(int_val_level, false); - } else { - /*tex Scan a numeric constant. */ - radix = 10; - m = 214748364; - if (cur_tok == octal_token) { - radix = 8; - m = 02000000000; - get_x_token(); - } else if (cur_tok == hex_token) { - radix = 16; - m = 01000000000; - get_x_token(); - } - vacuous = true; - cur_val = 0; - /*tex Accumulate the constant until |cur_tok| is not a suitable digit. */ - while (1) { - if ((cur_tok < zero_token + radix) && (cur_tok >= zero_token) && (cur_tok <= nine_token)) { - d = cur_tok - zero_token; - } else if (radix == 16) { - if ((cur_tok <= A_token + 5) && (cur_tok >= A_token)) { - d = cur_tok - A_token + 10; - } else if ((cur_tok <= other_A_token + 5) && (cur_tok >= other_A_token)) { - d = cur_tok - other_A_token + 10; - } else { - break; - } - } else { - break; - } - vacuous = false; - if ((cur_val >= m) && ((cur_val > m) || (d > 7) || (radix != 10))) { - if (OK_so_far) { - print_err("Number too big"); - help2( - "I can only go up to 2147483647='17777777777=\"7FFFFFFF,", - "so I'm using that number instead of yours." - ); - error(); - cur_val = infinity; - OK_so_far = false; - } - } else { - cur_val = cur_val * radix + d; - } - get_x_token(); - } - if (vacuous) { - /*tex Express astonishment that no number was here */ - print_err("Missing number, treated as zero"); - help3( - "A number should have been here; I inserted `0'.", - "(If you can't figure out why I needed to see a number,", - "look up `weird error' in the index to The TeXbook.)" - ); - back_error(); - } else if (cur_cmd != spacer_cmd) { - back_input(); - } - } - if (negative) - negate(cur_val); -} - -/*tex - - The following code is executed when |scan_something_internal| was called - asking for |mu_val|, when we really wanted a ``mudimen'' instead of - ``muglue.'' - -*/ - -static void coerce_glue(void) -{ - int v; - if (cur_val_level >= glue_val_level) { - v = width(cur_val); - flush_node(cur_val); - cur_val = v; - } -} - -/*tex - - The |scan_dimen| routine is similar to |scan_int|, but it sets |cur_val| to a - |scaled| value, i.e., an integral number of sp. One of its main tasks is - therefore to interpret the abbreviations for various kinds of units and to - convert measurements to scaled points. - - There are three parameters: |mu| is |true| if the finite units must be - `\.{mu}', while |mu| is |false| if `\.{mu}' units are disallowed; |inf| is - |true| if the infinite units `\.{fil}', `\.{fill}', `\.{filll}' are - permitted; and |shortcut| is |true| if |cur_val| already contains an integer - and only the units need to be considered. - - The order of infinity that was found in the case of infinite glue is returned - in the global variable |cur_order|. - -*/ - -/*tex The order of infinity found by |scan_dimen|: */ - -int cur_order; - -/*tex - - Constructions like `\.{-\'77 pt}' are legal dimensions, so |scan_dimen| may - begin with |scan_int|. This explains why it is convenient to use |scan_int| - also for the integer part of a decimal fraction. - - Several branches of |scan_dimen| work with |cur_val| as an integer and with - an auxiliary fraction |f|, so that the actual quantity of interest is - $|cur_val|+|f|/2^{16}$. At the end of the routine, this ``unpacked'' - representation is put into the single word |cur_val|, which suddenly switches - significance from |integer| to |scaled|. - - The necessary conversion factors can all be specified exactly as fractions - whose numerator and denominator add to 32768 or less. According to the - definitions here, $\rm2660\,dd\approx1000.33297\,mm$; this agrees well with - the value $\rm1000.333\,mm$ cited by Bosshard \^{Bosshard, Hans Rudolf} in - {\sl Technische Grundlagen zur Satzherstellung\/} (Bern, 1980). The Didot - point has been newly standardized in 1978; it's now exactly $\rm - 1\,nd=0.375\,mm$. Conversion uses the equation - $0.375=21681/20320/72.27\cdot25.4$. The new Cicero follows the new Didot - point; $\rm 1\,nc=12\,nd$. These would lead to the ratios $21681/20320$ and - $65043/5080$, respectively. The closest approximations supported by the - algorithm would be $11183/10481$ and $1370/107$. In order to maintain the - relation $\rm 1\,nc=12\,nd$, we pick the ratio $685/642$ for $\rm nd$, - however. - -*/ - -static void scan_dimen_mu_error(void) { - print_err("Illegal unit of measure (mu inserted)"); - help4( - "The unit of measurement in math glue must be mu.", - "To recover gracefully from this error, it's best to", - "delete the erroneous units; e.g., type `2' to delete", - "two letters. (See Chapter 27 of The TeXbook.)" - ); - error(); -} - -static void scan_dimen_unknown_unit_error(void) { - print_err("Illegal unit of measure (pt inserted)"); - help6( - "Dimensions can be in units of em, ex, in, pt, pc,", - "cm, mm, dd, cc, nd, nc, bp, or sp; but yours is a new one!", - "I'll assume that you meant to say pt, for printer's points.", - "To recover gracefully from this error, it's best to", - "delete the erroneous units; e.g., type `2' to delete", - "two letters. (See Chapter 27 of The TeXbook.)" - ); - error(); -} - -static void scan_dimen_out_of_range_error(void) { - print_err("Dimension too large"); - help2( - "I can't work with sizes bigger than about 19 feet.", - "Continue and I'll use the largest value I can." - ); - error(); -} - -#define set_conversion(A,B) do { num=(A); denom=(B); } while(0) - -/*tex - - This function sets |cur_val| to a dimension. It could be optimized a bit more - (but not now, something for luatex > 1). - -*/ - -void scan_dimen(boolean mu, boolean inf, boolean shortcut) -{ - /*tex should the answer be negated? */ - boolean negative = false; - boolean is_true = false; - /*tex numerator of a fraction whose denominator is $2^{16}$ */ - int f = 0; - /*tex conversion ratio for the scanned units */ - int num = 0; - int denom = 0; - /*tex top of decimal digit stack */ - halfword q; - /*tex an internal dimension */ - scaled v; - /*tex temporary storage of |cur_val| */ - int save_cur_val; - arith_error = false; - cur_order = normal; - if (!shortcut) { - /*tex Get the next non-blank non-sign. */ - do { - /*tex Get the next non-blank non-call token. */ - do { - get_x_token(); - } while (cur_cmd == spacer_cmd); - if (cur_tok == minus_token) { - negative = !negative; - cur_tok = plus_token; - } - } while (cur_tok == plus_token); - if ((cur_cmd >= min_internal_cmd) && (cur_cmd <= max_internal_cmd)) { - /*tex Fetch an internal dimension and |goto attach_sign|, or fetch an internal integer. */ - if (mu) { - scan_something_internal(mu_val_level, false); - coerce_glue(); - if (cur_val_level == mu_val_level) { - goto ATTACH_SIGN; - } else if (cur_val_level != int_val_level) { - mu_error(); - } - } else { - scan_something_internal(dimen_val_level, false); - if (cur_val_level == dimen_val_level) { - goto ATTACH_SIGN; - } - } - } else { - back_input(); - if (cur_tok == continental_point_token) { - cur_tok = point_token; - } - if (cur_tok != point_token) { - scan_int(); - } else { - radix = 10; - cur_val = 0; - } - if (cur_tok == continental_point_token) { - cur_tok = point_token; - } - if ((radix == 10) && (cur_tok == point_token)) { - /*tex - - Scan decimal fraction. When the following code is executed, - we have |cur_tok=point_token|, but this token has been backed - up using |back_input|; we must first discard it. It turns out - that a decimal point all by itself is equivalent to - `\.{0.0}'. Let's hope people don't use that fact. - - */ - int k = 0; - halfword p = null; - int kk; - /*tex The |point_token| is being re-scanned. */ - get_token(); - while (1) { - get_x_token(); - if ((cur_tok > nine_token) || (cur_tok < zero_token)) - break; - if (k < 17) { - /*tex Digits for |k>=17| cannot affect the result. */ - q = get_avail(); - set_token_link(q, p); - set_token_info(q, cur_tok - zero_token); - p = q; - incr(k); - } - } - for (kk = k; kk >= 1; kk--) { - dig[kk - 1] = token_info(p); - q = p; - p = token_link(p); - free_avail(q); - } - f = round_decimals(k); - if (cur_cmd != spacer_cmd) { - back_input(); - } - } - } - } - if (cur_val < 0) { - /*tex In this case |f=0|. */ - negative = !negative; - negate(cur_val); - } - /*tex - - Scan units and set |cur_val| to $x\cdot(|cur_val|+f/2^{16})$, where there - are |x| sp per unit; |goto attach_sign| if the units are internal. Now - comes the harder part: At this point in the program, |cur_val| is a - nonnegative integer and $f/2^{16}$ is a nonnegative fraction less than 1; - we want to multiply the sum of these two quantities by the appropriate - factor, based on the specified units, in order to produce a |scaled| - result, and we want to do the calculation with fixed point arithmetic - that does not overflow. - - */ - if (inf) { - if (scan_keyword("fi")) { - cur_order = sfi; - if (scan_keyword("l")) { - cur_order = fil; - if (scan_keyword("l")) { - cur_order = fill; - if (scan_keyword("l")) { - cur_order = filll; - } - } - } - goto ATTACH_FRACTION; - } - } - /*tex - - Scan for (u)units that are internal dimensions; |goto attach_sign| with - |cur_val| set if found. - - */ - save_cur_val = cur_val; - /*tex - - Get the next non-blank non-call; a pitty if just backed up the input. - - */ - do { - get_x_token(); - } while (cur_cmd == spacer_cmd); - - if ((cur_cmd < min_internal_cmd) || (cur_cmd > max_internal_cmd)) { - back_input(); - } else { - /*tex |math_given_cmd|, |xmath_given_cmd| and |last_item_cmd} */ - if (mu) { - scan_something_internal(mu_val_level, false); - coerce_glue(); - if (cur_val_level != mu_val_level) { - mu_error(); - } - } else { - scan_something_internal(dimen_val_level, false); - } - v = cur_val; - goto FOUND; - } - /*tex Bah |true| forces to split the unit scanner. */ - if (mu) { - /*tex Scan for (m)\.{mu} units and |goto attach_fraction|. */ - if (! scan_keyword("mu")) { - scan_dimen_mu_error(); - } - goto ATTACH_FRACTION; - } else if (scan_keyword("em")) { - v = quad(get_cur_font()); - } else if (scan_keyword("ex")) { - v = x_height(get_cur_font()); - } else if (scan_keyword("px")) { - v = px_dimen_par; - } else { - goto PICKUP_UNIT; - } - /*tex Scan an optional space (after em, ex or px) */ - get_x_token(); - if (cur_cmd != spacer_cmd) { - back_input(); - } - FOUND: - cur_val = nx_plus_y(save_cur_val, v, xn_over_d(v, f, 0200000)); - goto ATTACH_SIGN; - /*tex - - Scan for (a)all other units and adjust |cur_val| and |f| accordingly; - |goto done| in the case of scaled points. - - */ - PICKUP_UNIT: - if (scan_keyword("pt")) { - /*tex The easy case: */ - goto SCALE_VALUE; - } else if (scan_keyword("mm")) { - set_conversion(7227, 2540); - goto SCALE_VALUE; - } else if (scan_keyword("cm")) { - set_conversion(7227, 254); - goto SCALE_VALUE; - } else if (scan_keyword("sp")) { - goto DONE; - } else if (scan_keyword("bp")) { - set_conversion(7227, 7200); - goto SCALE_VALUE; - } else if (scan_keyword("in")) { - set_conversion(7227, 100); - goto SCALE_VALUE; - } else if (scan_keyword("dd")) { - set_conversion(1238, 1157); - goto SCALE_VALUE; - } else if (scan_keyword("cc")) { - set_conversion(14856, 1157); - goto SCALE_VALUE; - } else if (scan_keyword("pc")) { - set_conversion(12, 1); - goto SCALE_VALUE; - } else if (scan_keyword("nd")) { - set_conversion(685, 642); - goto SCALE_VALUE; - } else if (scan_keyword("nc")) { - set_conversion(1370, 107); - goto SCALE_VALUE; - } else if (!is_true && scan_keyword("true")) { - is_true = true; - goto PICKUP_UNIT; - } - /*tex Complain about unknown unit and |goto done2|. */ - scan_dimen_unknown_unit_error(); - goto BAD_NEWS; - SCALE_VALUE: - /*tex Adjust |f| for the magnification ratio. */ - if (is_true) { - /*tex Maybe at some point we will drop mag completely, even in \DVI\ mode. */ - if (output_mode_used <= OMODE_DVI) { - prepare_mag(); - if (mag_par != 1000) { - cur_val = xn_over_d(cur_val, 1000, mag_par); - f = (1000 * f + 0200000 * tex_remainder) / mag_par; - cur_val = cur_val + (f / 0200000); - f = f % 0200000; - } - } else { - /*tex in \PDF\ mode we're always |true|. */ - one_true_inch = one_inch; - } - } - if (num) { - cur_val = xn_over_d(cur_val, num, denom); - f = (num * f + 0200000 * tex_remainder) / denom; - cur_val = cur_val + (f / 0200000); - f = f % 0200000; - } - BAD_NEWS: - ATTACH_FRACTION: - if (cur_val >= 040000) { - arith_error = true; - } else { - cur_val = cur_val * unity + f; - } - DONE: - /*tex Scan an optional space; this happens too often. */ - get_x_token(); - if (cur_cmd != spacer_cmd) { - back_input(); - } - ATTACH_SIGN: - if (arith_error || (abs(cur_val) >= 010000000000)) { - /*tex Report that this dimension is out of range. */ - scan_dimen_out_of_range_error(); - cur_val = max_dimen; - arith_error = false; - } - if (negative) { - negate(cur_val); - } -} - -/*tex - - The final member of \TeX's value-scanning trio is |scan_glue|, which makes - |cur_val| point to a glue specification. The reference count of that glue - spec will take account of the fact that |cur_val| is pointing to~it. - - The |level| parameter should be either |glue_val| or |mu_val|. - - Since |scan_dimen| was so much more complex than |scan_int|, we might expect - |scan_glue| to be even worse. But fortunately, it is very simple, since most - of the work has already been done. - -*/ - -void scan_glue(int level) -{ - /*tex should the answer be negated? */ - boolean negative = false; - /*tex new glue specification */ - halfword q = null; - /*tex does |level=mu_val|? */ - boolean mu = (level == mu_val_level); - /*tex Get the next non-blank non-sign. */ - do { - /*tex Get the next non-blank non-call token. */ - do { - get_x_token(); - } while (cur_cmd == spacer_cmd); - if (cur_tok == minus_token) { - negative = !negative; - cur_tok = plus_token; - } - } while (cur_tok == plus_token); - if ((cur_cmd >= min_internal_cmd) && (cur_cmd <= max_internal_cmd)) { - scan_something_internal(level, negative); - if (cur_val_level >= glue_val_level) { - if (cur_val_level != level) - mu_error(); - return; - } - if (cur_val_level == int_val_level) - scan_dimen(mu, false, true); - else if (level == mu_val_level) - mu_error(); - } else { - back_input(); - scan_dimen(mu, false, false); - if (negative) - negate(cur_val); - } - /*tex - - Create a new glue specification whose width is |cur_val|; scan for its - stretch and shrink components. - - */ - q = new_spec(zero_glue); - width(q) = cur_val; - if (scan_keyword("plus")) { - scan_dimen(mu, true, false); - stretch(q) = cur_val; - stretch_order(q) = (quarterword) cur_order; - } - if (scan_keyword("minus")) { - scan_dimen(mu, true, false); - shrink(q) = cur_val; - shrink_order(q) = (quarterword) cur_order; - } - cur_val = q; -} - -/*tex - - This procedure is supposed to scan something like `\.{\\skip\\count12}', - i.e., whatever can follow `\.{\\the}', and it constructs a token list - containing something like `\.{-3.0pt minus 0.5fill}'. - -*/ - -halfword the_toks(void) -{ - /*tex holds |selector| setting */ - int old_setting; - /*tex used for copying a token list */ - halfword p, q, r; - /*tex value of |cur_chr| */ - int c; - str_number s; - halfword retval; - /*tex Handle \.{\\unexpanded} or \.{\\detokenize} and |return|. */ - if (odd(cur_chr)) { - c = cur_chr; - scan_general_text(); - if (c == 1) { - return cur_val; - } else { - old_setting = selector; - selector = new_string; - p = get_avail(); - set_token_link(p, token_link(temp_token_head)); - token_show(p); - flush_list(p); - selector = old_setting; - s = make_string(); - retval = str_toks(str_lstring(s)); - flush_str(s); - return retval; - } - } - get_x_token(); - scan_something_internal(tok_val_level, false); - if (cur_val_level >= ident_val_level) { - /*tex Copy the token list */ - p = temp_token_head; - set_token_link(p, null); - if (cur_val_level == ident_val_level) { - store_new_token(cs_token_flag + cur_val); - } else if (cur_val != null) { - /*tex Do not copy the reference count! */ - r = token_link(cur_val); - while (r != null) { - fast_store_new_token(token_info(r)); - r = token_link(r); - } - } - return p; - } else { - old_setting = selector; - selector = new_string; - switch (cur_val_level) { - case int_val_level: - print_int(cur_val); - break; - case attr_val_level: - print_int(cur_val); - break; - case dir_val_level: - print_dir_par(cur_val); - break; - case dimen_val_level: - print_scaled(cur_val); - tprint("pt"); - break; - case glue_val_level: - print_spec(cur_val, "pt"); - flush_node(cur_val); - break; - case mu_val_level: - print_spec(cur_val, "mu"); - flush_node(cur_val); - break; - } - selector = old_setting; - s = make_string(); - retval = str_toks(str_lstring(s)); - flush_str(s); - return retval; - } -} - -str_number the_scanned_result(void) -{ - /*tex holds |selector| setting */ - int old_setting; - /*tex return value */ - str_number r; - old_setting = selector; - selector = new_string; - if (cur_val_level >= ident_val_level) { - if (cur_val != null) { - show_token_list(token_link(cur_val), null, -1); - r = make_string(); - } else { - r = get_nullstr(); - } - } else { - switch (cur_val_level) { - case int_val_level: - print_int(cur_val); - break; - case attr_val_level: - print_int(cur_val); - break; - case dir_val_level: - print_dir_par(cur_val); - break; - case dimen_val_level: - print_scaled(cur_val); - tprint("pt"); - break; - case glue_val_level: - print_spec(cur_val, "pt"); - flush_node(cur_val); - break; - case mu_val_level: - print_spec(cur_val, "mu"); - flush_node(cur_val); - break; - } - r = make_string(); - } - selector = old_setting; - return r; -} - -/*tex - - The following routine is used to implement `\.{\\fontdimen} |n| |f|'. The - boolean parameter |writing| is set |true| if the calling program intends to - change the parameter value. - -*/ - -static void font_param_error(int f) -{ - print_err("Font "); - print_esc(font_id_text(f)); - tprint(" has only "); - print_int(font_params(f)); - tprint(" fontdimen parameters"); - help2( - "To increase the number of font parameters, you must", - "use \\fontdimen immediately after the \\font is loaded." - ); - error(); -} - -void set_font_dimen(void) -{ - internal_font_number f; - int n; - scan_int(); - n = cur_val; - scan_font_ident(); - f = cur_val; - if (n <= 0) { - font_param_error(f); - } else if (n > font_params(f)) { - if (font_used(f)) { - font_param_error(f); - } else { - /*tex Increase the number of parameters in the font. */ - do { - set_font_param(f, (font_params(f) + 1), 0); - } while (n != font_params(f)); - } - } - scan_optional_equals(); - scan_normal_dimen(); - set_font_param(f, n, cur_val); -} - -void get_font_dimen(void) -{ - internal_font_number f; - /*tex The parameter number: */ - int n; - scan_int(); - n = cur_val; - scan_font_ident(); - f = cur_val; - /*tex Initialize return value: */ - cur_val = 0; - if (n <= 0) { - font_param_error(f); - goto EXIT; - } else if (n > font_params(f)) { - if (font_used(f)) { - font_param_error(f); - goto EXIT; - } else { - /*tex Increase the number of parameters in the font. */ - do { - set_font_param(f, (font_params(f) + 1), 0); - } while (n != font_params(f)); - } - } - cur_val = font_param(f, n); - EXIT: - scanned_result(cur_val, dimen_val_level); -} - -/*tex - - Here's a similar procedure that returns a pointer to a rule node. This - routine is called just after \TeX\ has seen \.{\\hrule} or \.{\\vrule}; - therefore |cur_cmd| will be either |hrule| or |vrule|. The idea is to store - the default rule dimensions in the node, then to override them if - `\.{height}' or `\.{width}' or `\.{depth}' specifications are found (in any - order). - -*/ - -halfword scan_rule_spec(void) -{ - /*tex |width|, |depth|, and |height| all equal |null_flag| now */ - halfword q; - if (cur_cmd == no_vrule_cmd) { - q = new_rule(empty_rule); - cur_cmd = vrule_cmd; - } else if (cur_cmd == no_hrule_cmd) { - q = new_rule(empty_rule); - cur_cmd = hrule_cmd; - } else { - q = new_rule(normal_rule); - } - if (cur_cmd == vrule_cmd) { - width(q) = default_rule; - rule_dir(q) = body_direction_par; - } else { - height(q) = default_rule; - depth(q) = 0; - rule_dir(q) = text_direction_par; - } - RESWITCH: - if (scan_keyword("width")) { - scan_normal_dimen(); - width(q) = cur_val; - goto RESWITCH; - } - if (scan_keyword("height")) { - scan_normal_dimen(); - height(q) = cur_val; - goto RESWITCH; - } - if (scan_keyword("depth")) { - scan_normal_dimen(); - depth(q) = cur_val; - goto RESWITCH; - } - return q; -} - -/*tex Declare procedures that scan font-related stuff. */ - -void scan_font_ident(void) -{ - internal_font_number f; - halfword m; - /*tex Get the next non-blank non-call. */ - do { - get_x_token(); - } while (cur_cmd == spacer_cmd); - if ((cur_cmd == def_font_cmd) || (cur_cmd == letterspace_font_cmd) || (cur_cmd == copy_font_cmd)) { - f = get_cur_font(); - } else if (cur_cmd == set_font_cmd) { - f = cur_chr; - set_font_touched(f, 1); - } else if (cur_cmd == def_family_cmd) { - m = cur_chr; - scan_math_family_int(); - f = fam_fnt(cur_val, m); - set_font_touched(f, 1); - } else { - print_err("Missing font identifier"); - help2( - "I was looking for a control sequence whose", - "current meaning has been defined by \\font." - ); - back_error(); - f = null_font; - } - cur_val = f; -} - -/*tex - - The |scan_general_text| procedure is much like |scan_toks(false,false)|, but - will be invoked via |expand|, i.e., recursively. - - The token list (balanced text) created by |scan_general_text| begins at - |link(temp_token_head)| and ends at |cur_val|. (If |cur_val=temp_token_head|, - the list is empty.) - -*/ - -void scan_general_text(void) -{ - /*tex Here we save |scanner_status|: */ - int s; - /*tex Here we save |warning_index|: */ - halfword w; - /*tex Here we save |def_ref|: */ - halfword d; - /*tex The tail of the token list being built: */ - halfword p; - /*tex The new node being added to the token list via |store_new_token|: */ - halfword q; - /*tex The number of unmatched left braces: */ - halfword unbalance; - s = scanner_status; - w = warning_index; - d = def_ref; - scanner_status = absorbing; - warning_index = cur_cs; - p = get_avail(); - def_ref = p; - set_token_ref_count(def_ref, 0); - p = def_ref; - /*tex Remove the compulsory left brace. */ - scan_left_brace(); - unbalance = 1; - while (1) { - get_token(); - if (cur_tok < right_brace_limit) { - if (cur_cmd < right_brace_cmd) { - incr(unbalance); - } else { - decr(unbalance); - if (unbalance == 0) - break; - } - } - store_new_token(cur_tok); - } - q = token_link(def_ref); - /*tex Discard reference count. */ - free_avail(def_ref); - if (q == null) - cur_val = temp_token_head; - else - cur_val = p; - set_token_link(temp_token_head, q); - scanner_status = s; - warning_index = w; - def_ref = d; -} - -/*tex - - The |get_x_or_protected| procedure is like |get_x_token| except that - protected macros are not expanded. It sets |cur_cmd|, |cur_chr|, - |cur_tok|,and expands non-protected macros. - -*/ - -void get_x_or_protected(void) -{ - - while (1) { - get_token(); - if (cur_cmd <= max_command_cmd) - return; - if ((cur_cmd >= call_cmd) && (cur_cmd < end_template_cmd)) { - if (token_info(token_link(cur_chr)) == protected_token) - return; - } - expand(); - } -} - -/*tex - - |scan_toks|. This function returns a pointer to the tail of a new token list, - and it also makes |def_ref| point to the reference count at the head of that - list. - - There are two boolean parameters, |macro_def| and |xpand|. If |macro_def| is - true, the goal is to create the token list for a macro definition; otherwise - the goal is to create the token list for some other \TeX\ primitive: - \.{\\mark}, \.{\\output}, \.{\\everypar}, \.{\\lowercase}, \.{\\uppercase}, - \.{\\message}, \.{\\errmessage}, \.{\\write}, or \.{\\special}. In the latter - cases a left brace must be scanned next; this left brace will not be part of - the token list, nor will the matching right brace that comes at the end. If - |xpand| is false, the token list will simply be copied from the input using - |get_token|. Otherwise all expandable tokens will be expanded until - unexpandable tokens are left, except that the results of expanding - `\.{\\the}' are not expanded further. If both |macro_def| and |xpand| are - true, the expansion applies only to the macro body (i.e., to the material - following the first |left_brace| character). - - The value of |cur_cs| when |scan_toks| begins should be the |eqtb| address of - the control sequence to display in ``runaway'' error messages. - -*/ - -halfword scan_toks(boolean macro_def, boolean xpand) -{ - /*tex token representing the highest parameter number */ - halfword t; - /*tex saved token */ - halfword s; - /*tex tail of the token list being built */ - halfword p; - /*tex new node being added to the token list via |store_new_token| */ - halfword q; - /*tex number of unmatched left braces */ - halfword unbalance; - /*tex possible `\.{\#\{}' token */ - halfword hash_brace; - if (macro_def) - scanner_status = defining; - else - scanner_status = absorbing; - warning_index = cur_cs; - p = get_avail(); - def_ref = p; - set_token_ref_count(def_ref, 0); - p = def_ref; - hash_brace = 0; - t = zero_token; - if (macro_def) { - /*tex Scan and build the parameter part of the macro definition. */ - while (1) { - /*tex Set |cur_cmd|, |cur_chr|, |cur_tok|: */ - get_token(); - if (cur_tok < right_brace_limit) - break; - if (cur_cmd == mac_param_cmd) { - /*tex - - If the next character is a parameter number, make - |cur_tok| a |match| token; but if it is a left brace, - store `|left_brace|, |end_match|', set |hash_brace|, and - |goto done|. - - */ - s = match_token + cur_chr; - get_token(); - /* if (cur_cmd == left_brace_cmd) { */ - if (cur_tok < left_brace_limit) { - hash_brace = cur_tok; - store_new_token(cur_tok); - store_new_token(end_match_token); - goto DONE; - } - if (t == nine_token) { - print_err("You already have nine parameters"); - help2( - "I'm going to ignore the # sign you just used,", - "as well as the token that followed it." - ); - error(); - } else { - incr(t); - if (cur_tok != t) { - print_err("Parameters must be numbered consecutively"); - help2( - "I've inserted the digit you should have used after the #.", - "Type `1' to delete what you did use." - ); - back_error(); - } - cur_tok = s; - } - } - store_new_token(cur_tok); - } - store_new_token(end_match_token); - if (cur_cmd == right_brace_cmd) { - /*tex Express shock at the missing left brace; |goto found|. */ - print_err("Missing { inserted"); - incr(align_state); - help2( - "Where was the left brace? You said something like `\\def\\a}',", - "which I'm going to interpret as `\\def\\a{}'." - ); - error(); - goto FOUND; - } - - } else { - /*tex Remove the compulsory left brace. */ - scan_left_brace(); - } - DONE: - /*tex Scan and build the body of the token list; |goto found| when finished. */ - unbalance = 1; - while (1) { - if (xpand) { - /*tex - - Expand the next part of the input. Here we insert an entire token - list created by |the_toks| without expanding it further. - - */ - while (1) { - get_next(); - if (cur_cmd >= call_cmd) { - if (token_info(token_link(cur_chr)) == protected_token) { - cur_cmd = relax_cmd; - cur_chr = no_expand_flag; - } - } - if (cur_cmd <= max_command_cmd) - break; - if (cur_cmd != the_cmd) { - expand(); - } else { - q = the_toks(); - if (token_link(temp_token_head) != null) { - set_token_link(p, token_link(temp_token_head)); - p = q; - } - } - } - x_token(); - } else { - get_token(); - } - if (cur_tok < right_brace_limit) { - if (cur_cmd < right_brace_cmd) { - incr(unbalance); - } else { - decr(unbalance); - if (unbalance == 0) - goto FOUND; - } - } else if (cur_cmd == mac_param_cmd) { - if (macro_def) { - /*tex Look for parameter number or \.{\#\#}. */ - s = cur_tok; - if (xpand) - get_x_token(); - else - get_token(); - if (cur_cmd != mac_param_cmd) { - if ((cur_tok <= zero_token) || (cur_tok > t)) { - print_err("Illegal parameter number in definition of "); - sprint_cs(warning_index); - help3( - "You meant to type ## instead of #, right?", - "Or maybe a } was forgotten somewhere earlier, and things", - "are all screwed up? I'm going to assume that you meant ##." - ); - back_error(); - cur_tok = s; - } else { - cur_tok = out_param_token - '0' + cur_chr; - } - } - } - } - store_new_token(cur_tok); - } - FOUND: - scanner_status = normal; - if (hash_brace != 0) - store_new_token(hash_brace); - return p; -} - -/*tex - - Here we declare two trivial procedures in order to avoid mutually recursive - procedures with parameters. - -*/ - -void scan_normal_glue(void) -{ - scan_glue(glue_val_level); -} - -void scan_mu_glue(void) -{ - scan_glue(mu_val_level); -} - -/*tex - - The |scan_expr| procedure scans and evaluates an expression. Evaluating an - expression is a recursive process: When the left parenthesis of a - subexpression is scanned we descend to the next level of recursion; the - previous level is resumed with the matching right parenthesis. - -*/ - -typedef enum { - /*tex \.( seen, or \.( $\langle\it expr\rangle$ \.) seen */ - expr_none = 0, - /*tex \.( $\langle\it expr\rangle$ \.+ seen */ - expr_add = 1, - /*tex \.( $\langle\it expr\rangle$ \.- seen */ - expr_sub = 2, - /*tex $\langle\it term\rangle$ \.* seen */ - expr_mult = 3, - /*tex $\langle\it term\rangle$ \./ seen */ - expr_div = 4, - /*tex $\langle\it term\rangle$ \.* $\langle\it factor\rangle$ \./ seen */ - expr_scale = 5, -} expression_states; - -/*tex - - We want to make sure that each term and (intermediate) result is in the - proper range. Integer values must not exceed |infinity| ($2^{31}-1$) in - absolute value, dimensions must not exceed |max_dimen| ($2^{30}-1$). We avoid - the absolute value of an integer, because this might fail for the value - $-2^{31}$ using 32-bit arithmetic. - -*/ - -/* Clear a number or dimension and set |arith_error|: */ - -#define num_error(A) do { \ - arith_error=true; \ - A=0; \ -} while (0) - -/*tex Clear a glue spec and set |arith_error|: */ - -#define glue_error(A) do { \ - arith_error=true; \ - reset_glue_to_zero(A); \ -} while (0) - -#define normalize_glue(A) do { \ - if (stretch(A)==0) stretch_order(A)=normal; \ - if (shrink(A)==0) shrink_order(A)=normal; \ -} while (0) - -/*tex - - Parenthesized subexpressions can be inside expressions, and this nesting has - a stack. Seven local variables represent the top of the expression stack: |p| - points to pushed-down entries, if any; |l| specifies the type of expression - currently beeing evaluated; |e| is the expression so far and |r| is the state - of its evaluation; |t| is the term so far and |s| is the state of its - evaluation; finally |n| is the numerator for a combined multiplication and - division, if any. - -*/ - -#define expr_add_sub(A,B,C) add_or_sub((A),(B),(C),(r==expr_sub)) -#define expr_a(A,B) expr_add_sub((A),(B),max_dimen) - -/*tex - - The function |add_or_sub(x,y,max_answer,negative)| computes the sum (for - |negative=false|) or difference (for |negative=true|) of |x| and |y|, - provided the absolute value of the result does not exceed |max_answer|. - -*/ - -inline static int add_or_sub(int x, int y, int max_answer, boolean negative) -{ - int a; - if (negative) - negate(y); - if (x >= 0) { - if (y <= max_answer - x) - a = x + y; - else - num_error(a); - } else if (y >= -max_answer - x) { - a = x + y; - } else { - num_error(a); - } - return a; -} - -#define expr_m(A) A = nx_plus_y((A),f,0) -#define expr_d(A) A=quotient((A),f) - -/*tex - - The function |quotient(n,d)| computes the rounded quotient $q=\lfloor - n/d+{1\over2}\rfloor$, when $n$ and $d$ are positive. - -*/ - -inline static int quotient(int n, int d) -{ - /*tex Should the answer be negated? */ - boolean negative; - /*tex The answer: */ - int a; - if (d == 0) { - num_error(a); - } else { - if (d > 0) { - negative = false; - } else { - negate(d); - negative = true; - } - if (n < 0) { - negate(n); - negative = !negative; - } - a = n / d; - n = n - a * d; - /*tex Avoid certain compiler optimizations! */ - d = n - d; - if (d + n >= 0) - incr(a); - if (negative) - negate(a); - } - return a; -} - -#define expr_s(A) A=fract((A),n,f,max_dimen) - -/*tex - - Finally, the function |fract(x,n,d,max_answer)| computes the integer - $q=\lfloor xn/d+{1\over2}\rfloor$, when $x$, $n$, and $d$ are positive and - the result does not exceed |max_answer|. We can't use floating point - arithmetic since the routine must produce identical results in all cases; and - it would be too dangerous to multiply by~|n| and then divide by~|d|, in - separate operations, since overflow might well occur. Hence this subroutine - simulates double precision arithmetic, somewhat analogous to Metafont's - |make_fraction| and |take_fraction| routines. - -*/ - -int fract(int x, int n, int d, int max_answer) -{ - /*tex should the answer be negated? */ - boolean negative; - /*tex the answer */ - int a; - /*tex a proper fraction */ - int f; - /*tex smallest integer such that |2*h>=d| */ - int h; - /*tex intermediate remainder */ - int r; - /*tex temp variable */ - int t; - if (d == 0) - goto TOO_BIG; - a = 0; - if (d > 0) { - negative = false; - } else { - negate(d); - negative = true; - } - if (x < 0) { - negate(x); - negative = !negative; - } else if (x == 0) { - goto DONE; - } - if (n < 0) { - negate(n); - negative = !negative; - } - t = n / d; - if (t > max_answer / x) - goto TOO_BIG; - a = t * x; - n = n - t * d; - if (n == 0) - goto FOUND; - t = x / d; - if (t > (max_answer - a) / n) - goto TOO_BIG; - a = a + t * n; - x = x - t * d; - if (x == 0) - goto FOUND; - if (x < n) { - t = x; - x = n; - n = t; - } - /*tex - - Now |0<n<=x<d| and we compute $f=\lfloor xn/d+{1\over2}\rfloor$. The loop - here preserves the following invariant relations between |f|, |x|, |n|, - and~|r|: (i)~$f+\lfloor(xn+(r+d))/d\rfloor=\lfloor - x_0n_0/d+{1\over2}\rfloor$; (ii)~|-d<=r<0<n<=x<d|, where $x_0$, $n_0$ are - the original values of~$x$ and $n$. - - Notice that the computation specifies |(x-d)+x| instead of |(x+x)-d|, - because the latter could overflow. - - */ - f = 0; - r = (d / 2) - d; - h = -r; - while (1) { - if (odd(n)) { - r = r + x; - if (r >= 0) { - r = r - d; - incr(f); - } - } - n = n / 2; - if (n == 0) - break; - if (x < h) { - x = x + x; - } else { - t = x - d; - x = t + x; - f = f + n; - if (x < n) { - if (x == 0) - break; - t = x; - x = n; - n = t; - } - } - } - if (f > (max_answer - a)) - goto TOO_BIG; - a = a + f; - FOUND: - if (negative) - negate(a); - goto DONE; - TOO_BIG: - num_error(a); - DONE: - return a; -} - -/*tex Scans and evaluates an expression: */ - -static void scan_expr(void) -{ - /*tex saved values of |arith_error| */ - boolean a, b; - /*tex type of expression */ - int l; - /*tex state of expression so far */ - int r; - /*tex state of term so far */ - int s; - /*tex next operation or type of next factor */ - int o; - /*tex expression so far */ - int e; - /*tex term so far */ - int t; - /*tex current factor */ - int f; - /*tex numerator of combined multiplication and division */ - int n; - /*tex top of expression stack */ - halfword p; - /*tex for stack manipulations */ - halfword q; - l = cur_val_level; - a = arith_error; - b = false; - p = null; - /*tex Scan and evaluate an expression |e| of type |l|. */ - RESTART: - r = expr_none; - e = 0; - s = expr_none; - t = 0; - n = 0; - CONTINUE: - if (s == expr_none) - o = l; - else - o = int_val_level; - /*tex - - Scan a factor |f| of type |o| or start a subexpression. Get the next - non-blank non-call token. - - */ - do { - get_x_token(); - } while (cur_cmd == spacer_cmd); - - if (cur_tok == other_token + '(') { - /*tex Push the expression stack and |goto restart|. */ - q = new_node(expr_node, 0); - vlink(q) = p; - expr_type(q) = (quarterword) l; - expr_state(q) = (quarterword) (4 * s + r); - expr_e_field(q) = e; - expr_t_field(q) = t; - expr_n_field(q) = n; - p = q; - l = o; - goto RESTART; - } - back_input(); - if ((o == int_val_level) || (o == attr_val_level)) - scan_int(); - else if (o == dimen_val_level) - scan_normal_dimen(); - else if (o == glue_val_level) - scan_normal_glue(); - else - scan_mu_glue(); - f = cur_val; - - FOUND: - /*tex - - Scan the next operator and set |o| and Get the next non-blank non-call - token. - - */ - do { - get_x_token(); - } while (cur_cmd == spacer_cmd); - - if (cur_tok == other_token + '+') { - o = expr_add; - } else if (cur_tok == other_token + '-') { - o = expr_sub; - } else if (cur_tok == other_token + '*') { - o = expr_mult; - } else if (cur_tok == other_token + '/') { - o = expr_div; - } else { - o = expr_none; - if (p == null) { - if (cur_cmd != relax_cmd) - back_input(); - } else if (cur_tok != other_token + ')') { - print_err("Missing ) inserted for expression"); - help1("I was expecting to see `+', `-', `*', `/', or `)'. Didn't."); - back_error(); - } - } - arith_error = b; - /*tex Make sure that |f| is in the proper range. */ - if (((l == int_val_level) || (l == attr_val_level)) || (s > expr_sub)) { - if ((f > infinity) || (f < -infinity)) - num_error(f); - } else if (l == dimen_val_level) { - if (abs(f) > max_dimen) - num_error(f); - } else { - if ((abs(width(f)) > max_dimen) || (abs(stretch(f)) > max_dimen) || (abs(shrink(f)) > max_dimen)) - glue_error(f); - } - /*tex Cases for evaluation of the current term. */ - switch (s) { - case expr_none: - /*tex - - Applying the factor |f| to the partial term |t| (with the - operator |s|) is delayed until the next operator |o| has been - scanned. Here we handle the first factor of a partial term. A - glue spec has to be copied unless the next operator is a right - parenthesis; this allows us later on to simply modify the glue - components. - - */ - t = f; - if ((l >= glue_val_level) && (o != expr_none)) { - /*tex Do we really need to copy here? */ - normalize_glue(t); - } else { - t = f; - } - break; - case expr_mult: - /*tex - - If a multiplication is followed by a division, the two operations - are combined into a `scaling' operation. Otherwise the term |t| - is multiplied by the factor |f|. - - */ - if (o == expr_div) { - n = f; - o = expr_scale; - } else if ((l == int_val_level) || (l == attr_val_level)) { - t = mult_integers(t, f); - } else if (l == dimen_val_level) { - expr_m(t); - } else { - expr_m(width(t)); - expr_m(stretch(t)); - expr_m(shrink(t)); - } - break; - case expr_div: - /*tex Here we divide the term |t| by the factor |f|. */ - if (l < glue_val_level) { - expr_d(t); - } else { - expr_d(width(t)); - expr_d(stretch(t)); - expr_d(shrink(t)); - } - break; - case expr_scale: - /*tex Here the term |t| is multiplied by the quotient $n/f$. */ - if ((l == int_val_level) || (l == attr_val_level)) { - t = fract(t, n, f, infinity); - } else if (l == dimen_val_level) { - expr_s(t); - } else { - expr_s(width(t)); - expr_s(stretch(t)); - expr_s(shrink(t)); - } - break; - } - if (o > expr_sub) { - s = o; - } else { - /*tex - - Evaluate the current expression. When a term |t| has been completed - it is copied to, added to, or subtracted from the expression |e|. - - */ - s = expr_none; - if (r == expr_none) { - e = t; - } else if ((l == int_val_level) || (l == attr_val_level)) { - e = expr_add_sub(e, t, infinity); - } else if (l == dimen_val_level) { - e = expr_a(e, t); - } else { - /*tex - - Compute the sum or difference of two glue specs. We know that - |stretch_order(e)>normal| implies |stretch(e)<>0| and - |shrink_order(e)>normal| implies |shrink(e)<>0|. - - */ - width(e) = expr_a(width(e), width(t)); - if (stretch_order(e) == stretch_order(t)) { - stretch(e) = expr_a(stretch(e), stretch(t)); - } else if ((stretch_order(e) < stretch_order(t)) && (stretch(t) != 0)) { - stretch(e) = stretch(t); - stretch_order(e) = stretch_order(t); - } - if (shrink_order(e) == shrink_order(t)) { - shrink(e) = expr_a(shrink(e), shrink(t)); - } else if ((shrink_order(e) < shrink_order(t)) && (shrink(t) != 0)) { - shrink(e) = shrink(t); - shrink_order(e) = shrink_order(t); - } - flush_node(t); - normalize_glue(e); - } - r = o; - } - b = arith_error; - if (o != expr_none) - goto CONTINUE; - if (p != null) { - /*tex Pop the expression stack and |goto found|. */ - f = e; - q = p; - e = expr_e_field(q); - t = expr_t_field(q); - n = expr_n_field(q); - s = expr_state(q) / 4; - r = expr_state(q) % 4; - l = expr_type(q); - p = vlink(q); - flush_node(q); - goto FOUND; - } - - if (b) { - print_err("Arithmetic overflow"); - help2( - "I can't evaluate this expression,", - "since the result is out of range." - ); - error(); - if (l >= glue_val_level) { - reset_glue_to_zero(e); - } else { - e = 0; - } - } - arith_error = a; - cur_val = e; - cur_val_level = l; -} diff --git a/Build/source/texk/web2c/luatexdir/tex/scanning.h b/Build/source/texk/web2c/luatexdir/tex/scanning.h deleted file mode 100644 index e4189a0f67a..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/scanning.h +++ /dev/null @@ -1,109 +0,0 @@ -/* scanning.h - - Copyright 2009 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#ifndef SCANNING_H -# define SCANNING_H - -typedef enum { - int_val_level = 0, /* integer values */ - attr_val_level, /* integer values */ - dimen_val_level, /* dimension values */ - glue_val_level, /* glue specifications */ - mu_val_level, /* math glue specifications */ - dir_val_level, /* directions */ - ident_val_level, /* font identifier */ - tok_val_level, /* token lists */ -} value_level_code; - -extern void scan_left_brace(void); -extern void scan_optional_equals(void); - -extern int cur_val; /* value returned by numeric scanners */ -extern int cur_val1; /* delcodes are sometimes 51 digits */ -extern int cur_val_level; /* the ``level'' of this value */ - -extern void scan_something_simple(halfword cmd, halfword subitem); -extern void scan_something_internal(int level, boolean negative); - -extern void scan_limited_int(int max, const char *name); - -extern void negate_cur_val(boolean delete_glue); - -# define scan_register_num() scan_limited_int(65535,"register code") -# define scan_mark_num() scan_limited_int(65535,"marks code") -# define scan_char_num() scan_limited_int(biggest_char,"character code") -# define scan_four_bit_int() scan_limited_int(15,NULL) -# define scan_math_family_int() scan_limited_int(255,"math family") -# define scan_real_fifteen_bit_int() scan_limited_int(32767,"mathchar") -# define scan_big_fifteen_bit_int() scan_limited_int(0x7FFFFFF,"extended mathchar") -# define scan_twenty_seven_bit_int() scan_limited_int(0777777777,"delimiter code") - -extern void scan_fifteen_bit_int(void); -extern void scan_fifty_one_bit_int(void); - -# define octal_token (other_token+'\'') /* apostrophe, indicates an octal constant */ -# define hex_token (other_token+'"') /* double quote, indicates a hex constant */ -# define alpha_token (other_token+'`') /* reverse apostrophe, precedes alpha constants */ -# define point_token (other_token+'.') /* decimal point */ -# define comma_token (other_token+',') /* decimal comma */ -# define plus_token (other_token + '+') -# define minus_token (other_token + '-') -# define continental_point_token (other_token+',') /* decimal point, Eurostyle */ -# define infinity 017777777777 /* the largest positive value that \TeX\ knows */ -# define zero_token (other_token+'0') /* zero, the smallest digit */ -# define nine_token (other_token+'9') /* zero, the smallest digit */ -# define A_token (letter_token+'A') /* the smallest special hex digit */ -# define other_A_token (other_token+'A') /* special hex digit of type |other_char| */ -extern int radix; - -extern void scan_int(void); - -extern int cur_order; - -# define scan_normal_dimen() scan_dimen(false,false,false) - -extern void scan_dimen(boolean mu, boolean inf, boolean shortcut); -extern void scan_glue(int level); - -extern halfword the_toks(void); -extern str_number the_scanned_result(void); -extern void set_font_dimen(void); -extern void get_font_dimen(void); - -# define default_rule 26214 /* 0.4\thinspace pt */ - -extern halfword scan_rule_spec(void); - -extern void scan_font_ident(void); -extern void scan_general_text(void); -extern void get_x_or_protected(void); -extern halfword scan_toks(boolean macrodef, boolean xpand); - -extern void scan_normal_glue(void); -extern void scan_mu_glue(void); - -/* extern int add_or_sub(int x, int y, int max_answer, boolean negative); */ -/* extern int quotient(int n, int d); */ -extern int fract(int x, int n, int d, int max_answer); - -/* extern void scan_expr(void); */ - -#endif diff --git a/Build/source/texk/web2c/luatexdir/tex/stringpool.c b/Build/source/texk/web2c/luatexdir/tex/stringpool.c deleted file mode 100644 index bc09f814b00..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/stringpool.c +++ /dev/null @@ -1,375 +0,0 @@ -/* - -stringpool.w - -Copyright 2009-2010 Taco Hoekwater <taco@@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your -option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU General Public License along -with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" - -/*tex - -Control sequence names and diagnostic messages are variable-length strings of -eight-bit characters. Since PASCAL did not have a well-developed string -mechanism, \TeX\ did all of its string processing by homegrown methods. - -Elaborate facilities for dynamic strings are not needed, so all of the necessary -operations can be handled with a simple data structure. The array |str_pool| -contains all of the (eight-bit) bytes off all of the strings, and the array -|str_start| contains indices of the starting points of each string. Strings are -referred to by integer numbers, so that string number |s| comprises the -characters |str_pool[j]| for |str_start_macro(s)<=j<str_start_macro(s+1)|. -Additional integer variables |pool_ptr| and |str_ptr| indicate the number of -entries used so far in |str_pool| and |str_start|, respectively; locations -|str_pool[pool_ptr]| and |str_start_macro(str_ptr)| are ready for the next string -to be allocated. - -String numbers 0 to |biggest_char| are reserved for strings that correspond to -single UNICODE characters. This is in accordance with the conventions of \.{WEB} -which converts single-character strings into the ASCII code number of the single -character involved. - -*/ - -/*tex The array of strings: */ - -lstring *string_pool; - -/*tex - This variable lives |STRING_OFFSET| below |string_pool| (handy for debugging: - |_string_pool[str_ptr] == str_string(str_ptr)|: -*/ - -lstring *_string_pool; - -/*tex The number of the current string being created: */ - -str_number str_ptr = (STRING_OFFSET + 1); - -/*tex The starting value of |str_ptr|: */ - -str_number init_str_ptr; - -/*tex - The current string buffer, the current index in that buffer, the malloced - size of |cur_string| and the occupied byte count: -*/ - -unsigned char *cur_string; -unsigned cur_length; -unsigned cur_string_size; -unsigned pool_size; - -/*tex - -Once a sequence of characters has been appended to |cur_string|, it officially -becomes a string when the function |make_string| is called. This function returns -the identification number of the new string as its value. - -*/ - -void reset_cur_string(void) -{ - cur_length = 0; - cur_string_size = 255; - cur_string = (unsigned char *) xmalloc(256); - memset(cur_string, 0, 256); -} - -str_number make_string(void) -{ - if (str_ptr == (max_strings + STRING_OFFSET)) { - overflow( - "number of strings", - (unsigned) (max_strings - init_str_ptr + STRING_OFFSET) - ); - } - str_room(1); - cur_string[cur_length] = '\0'; /* now |lstring.s| is always a valid C string */ - str_string(str_ptr) = (unsigned char *) cur_string; - str_length(str_ptr) = cur_length; - pool_size += cur_length; - reset_cur_string(); - str_ptr++; - return (str_ptr - 1); -} - -int pool_to_unichar(unsigned char *t) -{ - return (int) str2uni(t); -} - -/*tex - -The following subroutine compares string |s| with another string of the same -length that appears in |buffer| starting at position |k|; the result is |true| if -and only if the strings are equal. Empirical tests indicate that |str_eq_buf| is -used in such a way that it tends to return |true| about 80 percent of the time. - -*/ - -boolean str_eq_buf(str_number s, int k) -{ - int a; - if (s < STRING_OFFSET) { - a = buffer_to_unichar(k); - if (a != s) - return false; - } else { - unsigned char *j = str_string(s); - unsigned char *l = j + str_length(s); - while (j < l) { - if (*j++ != buffer[k++]) - return false; - } - } - return true; -} - -/*tex - -Here is a similar routine, but it compares two strings in the string pool, and it -does not assume that they have the same length. - -*/ - -boolean str_eq_str(str_number s, str_number t) -{ - int a = 0; - unsigned char *j, *k, *l; - if (s < STRING_OFFSET) { - if (t >= STRING_OFFSET) { - k = str_string(t); - if (s <= 0x7F && (str_length(t) == 1) && *k == s) - return true; - a = pool_to_unichar(k); - if (a != s) - return false; - } else { - if (t != s) - return false; - } - } else if (t < STRING_OFFSET) { - j = str_string(s); - if (t <= 0x7F && (str_length(s) == 1) && *j == t) - return true; - a = pool_to_unichar(j); - if (a != t) - return false; - } else { - if (str_length(s) != str_length(t)) - return false; - k = str_string(t); - j = str_string(s); - l = j + str_length(s); - while (j < l) { - if (*j++ != *k++) - return false; - } - } - return true; -} - -/*tex A string compare helper: */ - -boolean str_eq_cstr(str_number r, const char *s, size_t l) -{ - if (l != (size_t) str_length(r)) - return false; - return (strncmp((const char *) (str_string(r)), s, l) == 0); -} - - -/*tex - -The initial values of |str_pool|, |str_start|, |pool_ptr|, and |str_ptr| are -computed by the \.{INITEX} program, based in part on the information that \.{WEB} -has output while processing \TeX. - -The first |string_offset| strings are single-characters strings matching Unicode. -There is no point in generating all of these. But |str_ptr| has initialized -properly, otherwise |print_char| cannot see the difference between characters and -strings. - -*/ - -boolean get_strings_started(void) -{ - reset_cur_string(); - return true; -} - -/*tex - -The string recycling routines. \TeX{} uses 2 upto 4 {\it new\/} strings when -scanning a filename in an \.{\\input}, \.{\\openin}, or \.{\\openout} operation. -These strings are normally lost because the reference to them are not saved after -finishing the operation. |search_string| searches through the string pool for the -given string and returns either 0 or the found string number. - -*/ - -str_number search_string(str_number search) -{ - str_number s; - size_t len; - len = str_length(search); - if (len == 0) { - return get_nullstr(); - } else { - /*tex We start the search with newest string below |s|; |search>1|! */ - s = search - 1; - while (s >= STRING_OFFSET) { - /* The first |string_offset| of strings depend on the implementation! */ - if (str_length(s) == len) - if (str_eq_str(s, search)) - return s; - s--; - } - } - return 0; -} - -str_number maketexstring(const char *s) -{ - if (s == NULL || *s == 0) - return get_nullstr(); - return maketexlstring(s, strlen(s)); -} - -str_number maketexlstring(const char *s, size_t l) -{ - if (s == NULL || l == 0) - return get_nullstr(); - str_string(str_ptr) = xmalloc((unsigned) (l + 1)); - memcpy(str_string(str_ptr), s, (l + 1)); - str_length(str_ptr) = (unsigned) l; - str_ptr++; - return (str_ptr - 1); -} - -/*tex - - This appends a C string to a \TEX\ string: - -*/ - -void append_string(const unsigned char *s, unsigned l) -{ - if (s == NULL || *s == 0) - return; - l = (unsigned) strlen((const char *) s); - str_room(l); - memcpy(cur_string + cur_length, s, l); - cur_length += l; - return; -} - -char *makecstring(int s) -{ - size_t l; - return makeclstring(s, &l); -} - -char *makeclstring(int s, size_t * len) -{ - if (s < STRING_OFFSET) { - *len = (size_t) utf8_size(s); - return (char *) uni2str((unsigned) s); - } else { - unsigned l = (unsigned) str_length(s); - char *cstrbuf = xmalloc(l + 1); - memcpy(cstrbuf, str_string(s), l); - cstrbuf[l] = '\0'; - *len = (size_t) l; - return cstrbuf; - } -} - -int dump_string_pool(void) -{ - int j; - int l; - int k = str_ptr; - dump_int(k - STRING_OFFSET); - for (j = STRING_OFFSET + 1; j < k; j++) { - l = (int) str_length(j); - if (str_string(j) == NULL) - l = -1; - dump_int(l); - if (l > 0) - dump_things(*str_string(j), str_length(j)); - } - return (k - STRING_OFFSET); -} - -int undump_string_pool(void) -{ - int j; - int x; - undump_int(str_ptr); - if (max_strings < str_ptr + strings_free) - max_strings = str_ptr + strings_free; - str_ptr += STRING_OFFSET; - if (ini_version) - libcfree(string_pool); - init_string_pool_array((unsigned) max_strings); - for (j = STRING_OFFSET + 1; j < str_ptr; j++) { - undump_int(x); - if (x >= 0) { - str_length(j) = (unsigned) x; - pool_size += (unsigned) x; - str_string(j) = xmallocarray(unsigned char, (unsigned) (x + 1)); - undump_things(*str_string(j), (unsigned) x); - *(str_string(j) + str_length(j)) = '\0'; - } else { - str_length(j) = 0; - } - } - init_str_ptr = str_ptr; - return str_ptr; -} - -void init_string_pool_array(unsigned s) -{ - string_pool = xmallocarray(lstring, s); - _string_pool = string_pool - STRING_OFFSET; - memset(string_pool, 0, s * sizeof(lstring)); - /* seed the null string */ - string_pool[0].s = xmalloc(1); - string_pool[0].s[0] = '\0'; -} - -/*tex - - To destroy an already made string, we say |flush_str|. - -*/ - -void flush_str(str_number s) -{ - if (s > STRING_OFFSET) { - /*tex Don't ever delete the null string! */ - pool_size -= (unsigned) str_length(s); - str_length(s) = 0; - xfree(str_string(s)); - } - while (str_string((str_ptr - 1)) == NULL) - str_ptr--; -} diff --git a/Build/source/texk/web2c/luatexdir/tex/stringpool.h b/Build/source/texk/web2c/luatexdir/tex/stringpool.h deleted file mode 100644 index 2ba156046fd..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/stringpool.h +++ /dev/null @@ -1,142 +0,0 @@ -/* stringpool.h - - Copyright 2009 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ - - -#ifndef STRINGPOOL_H -# define STRINGPOOL_H - -/* Both lua and tex strings can contains null, but C strings cannot, so: */ - -typedef struct { - unsigned char *s; - size_t l; -} lstring; - -typedef struct { - const char *s; - size_t l; -} const_lstring; - -extern lstring *string_pool; - -extern str_number str_ptr; -extern str_number init_str_ptr; - -# define STRING_OFFSET 0x200000 -# define STRING_OFFSET_BITS 21 - -# define get_nullstr() STRING_OFFSET - -# define biggest_char 1114111 /* 0x10FFFF, the largest allowed character number; must be |< max_halfword| */ -# define too_big_char (biggest_char+1) /* 1114112, |biggest_char+1| */ -# define special_char (biggest_char+2) /* 1114113, |biggest_char+2| */ -# define number_chars (biggest_char+3) /* 1114112, |biggest_char+1| */ - -/* - Several of the elementary string operations are performed using - macros instead of procedures, because many of the - operations are done quite frequently and we want to avoid the - overhead of procedure calls. For example, here is - a simple macro that computes the length of a string. -*/ - -# define str_length(a) string_pool[(a)-STRING_OFFSET].l -# define str_string(a) string_pool[(a)-STRING_OFFSET].s -# define str_lstring(a) string_pool[(a)-STRING_OFFSET] - -/* Strings are created by appending character codes to |str_pool|. - The |append_char| macro, defined here, does not check to see if the - value of |pool_ptr| has gotten too high; this test is supposed to be - made before |append_char| is used. There is also a |flush_char| - macro, which erases the last character appended. - - To test if there is room to append |l| more characters to |str_pool|, - we shall write |str_room(l)|, which aborts \TeX\ and gives an - apologetic error message if there isn't enough room. -*/ - -/* The length of the current string is called |cur_length|: */ - -extern unsigned char *cur_string; -extern unsigned cur_length; -extern unsigned cur_string_size; -extern unsigned pool_size; - -# define EXTRA_STRING 500 - -/* put |ASCII_code| \# at the end of |str_pool| */ -# define append_char(A) do { \ - if (cur_string==NULL) reset_cur_string(); \ - else str_room(1); \ - cur_string[cur_length++]=(unsigned char)(A); \ - } while (0) - -# define str_room(wsize) do { \ - unsigned nsize; \ - if ((cur_length+wsize) > cur_string_size) { \ - nsize = cur_string_size + cur_string_size / 5 + EXTRA_STRING; \ - if (nsize < (unsigned)(wsize)) { \ - nsize = wsize + EXTRA_STRING; \ - } \ - cur_string = (unsigned char *) xreallocarray(cur_string, unsigned char, nsize); \ - memset (cur_string+cur_length,0,nsize-cur_length); \ - cur_string_size = nsize; \ - } \ - } while (0) - -# define flush_char() --cur_length /* forget the last character in the pool */ - -extern str_number make_string(void); -extern boolean str_eq_buf(str_number s, int k); -extern boolean str_eq_str(str_number s, str_number t); -extern boolean str_eq_cstr(str_number, const char *, size_t); -extern boolean get_strings_started(void); -extern void reset_cur_string(void); - -# define save_cur_string() (cur_length>0 ? make_string() : 0) - -# define restore_cur_string(u) if (u!=0) { \ - unsigned l = (unsigned)str_length(u); \ - xfree(cur_string); \ - reset_cur_string(); \ - str_room(l); \ - memcpy(cur_string, str_string(u),l); \ - cur_length = l; \ - flush_str(u); \ - u=0; \ - } - - -extern str_number search_string(str_number search); -extern int pool_to_unichar(unsigned char *t); - -extern str_number maketexstring(const char *); -extern str_number maketexlstring(const char *, size_t); -extern void append_string(const unsigned char *s, unsigned l); - -extern char *makecstring(int); -extern char *makeclstring(int, size_t *); - -extern int dump_string_pool(void); -extern int undump_string_pool(void); - -extern void init_string_pool_array(unsigned s); -extern void flush_str(str_number s); - -#endif diff --git a/Build/source/texk/web2c/luatexdir/tex/texdeffont.c b/Build/source/texk/web2c/luatexdir/tex/texdeffont.c deleted file mode 100644 index 1ec4b12bf06..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/texdeffont.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - -texdeffont.w - -Copyright 2008-2010 Taco Hoekwater <taco@@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your -option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU General Public License along -with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" - -/*tex - -When the user defines \.{\\font\\f}, say, \TeX\ assigns an internal number to the -user's font~\.{\\f}. Adding this number to |font_id_base| gives the |eqtb| -location of a ``frozen'' control sequence that will always select the font. - -The variable |a| in the following code indicates the global nature of the value -to be set. It's used in the |define| macro. Here we're never global. - -There's not much scanner code here because the other scanners are defined where -they make most sense. - -*/ - -int font_bytes; - -void set_cur_font(internal_font_number f) -{ - int a = 0; - define(cur_font_loc, data_cmd, f); -} - -/*tex - - This prints a scaled real, rounded to five digits. - -*/ - -static char *scaled_to_string(scaled s) -{ - static char result[16]; - int n, k; - /*tex The amount of allowable inaccuracy: */ - scaled delta; - k = 0; - if (s < 0) { - /*tex Only print the sign, if negative */ - result[k++] = '-'; - s = -s; - } - { - int l = 0; - char digs[8] = { 0 }; - n = s / unity; - /*tex Process the integer part: */ - do { - digs[l++] = (char) (n % 10); - n = n / 10;; - } while (n > 0); - while (l > 0) { - result[k++] = (char) (digs[--l] + '0'); - } - } - result[k++] = '.'; - s = 10 * (s % unity) + 5; - delta = 10; - do { - if (delta > unity) { - /*tex Round the last digit: */ - s = s + 0100000 - 050000; - } - result[k++] = (char) ('0' + (s / unity)); - s = 10 * (s % unity); - delta = delta * 10; - } while (s > delta); - result[k] = 0; - return (char *) result; -} - -void tex_def_font(small_number a) -{ - /*tex The user's font identifier. */ - pointer u; - /*tex This runs through existing fonts. */ - internal_font_number f; - /*tex The name for the frozen font identifier. */ - str_number t, d; - /*tex Thos holds the |selector| setting. */ - int old_setting; - /*tex Stated `at' size, or negative of scaled magnification. */ - scaled s = -1000; - /*tex The natural direction of the font. */ - int natural_dir = -1; - char *fn; - if (job_name == 0) { - /*tex Avoid confusing \.{texput} with the font name. */ - open_log_file(); - } - get_r_token(); - u = cur_cs; - if (a >= 4) { - geq_define(u, set_font_cmd, null_font); - } else { - eq_define(u, set_font_cmd, null_font); - } - scan_optional_equals(); - /*tex Get the next non-blank non-call token. */ - do { - get_x_token(); - } while ((cur_cmd == spacer_cmd) || (cur_cmd == relax_cmd)); - - if (cur_cmd != left_brace_cmd) { - back_input(); - scan_file_name(); - if (cur_area != get_nullstr() || cur_ext != get_nullstr()) { - /*tex - Have to do some rescue-ing here, fonts only have a name, no area - nor extension. - */ - old_setting = selector; - selector = new_string; - if (cur_area != get_nullstr()) { - print(cur_area); - flush_str(cur_area); - } - if (cur_name != get_nullstr()) { - print(cur_name); - flush_str(cur_name); - } - if (cur_ext != get_nullstr()) { - print(cur_ext); - flush_str(cur_ext); - } - selector = old_setting; - cur_area = get_nullstr(); - cur_name = make_string(); - cur_ext = get_nullstr(); - } - } else { - back_input(); - (void) scan_toks(false, true); - old_setting = selector; - selector = new_string; - token_show(def_ref); - selector = old_setting; - flush_list(def_ref); - cur_area = get_nullstr(); - cur_name = make_string(); - cur_ext = get_nullstr(); - } - /*tex - Scan the font size specification. The next variable keeps |cur_name| from - being changed - */ - name_in_progress = true; - if (scan_keyword("at")) { - /*tex Put the positive `at' size into |s|. */ - scan_normal_dimen(); - s = cur_val; - if ((s <= 0) || (s >= 01000000000)) { - char err[256]; - const char *errhelp[] = { - "I can only handle fonts at positive sizes that are", - "less than 2048pt, so I've changed what you said to 10pt.", - NULL - }; - snprintf(err, 255, "Improper `at' size (%spt), replaced by 10pt", scaled_to_string(s)); - tex_error(err, errhelp); - s = 10 * unity; - } - } else if (scan_keyword("scaled")) { - scan_int(); - s = -cur_val; - if ((cur_val <= 0) || (cur_val > 32768)) { - char err[256]; - const char *errhelp[] = { - "The magnification ratio must be between 1 and 32768.", - NULL - }; - snprintf(err, 255, "Illegal magnification has been changed to 1000 (%d)", (int) cur_val); - tex_error(err, errhelp); - s = -1000; - } - } - /*tex - There is no real reason to support this obsolete key as there are no useful - fonts out there so let's get rid of this overhead. This also means that - |natural_dir| can go away. - */ - /* - if (scan_keyword("naturaldir")) { - scan_direction(); - natural_dir = cur_val; - } - */ - name_in_progress = false; - fn = makecstring(cur_name); - f = read_font_info(u, fn, s, natural_dir); - xfree(fn); - equiv(u) = f; - eqtb[font_id_base + f] = eqtb[u]; - /*tex - - This is tricky: when we redefine a string we loose the old one. So this - will change as it's only used to display the |\fontname| so we can store - that with the font. - - */ - d = cs_text(font_id_base + f); - t = (u >= null_cs) ? cs_text(u) : maketexstring("FONT"); - if (!d) { - /*tex We have a new string. */ - cs_text(font_id_base + f) = t; - } else if ((d!=t) && str_eq_str(d,t)){ - /*tex We have a duplicate string. */ - flush_str(t); - } else if (d!=t){ - d = search_string(t); - if (d) { - /*tex We have already such a string. */ - cs_text(font_id_base + f) = d; - flush_str(t); - } else { - /*tex The old value is lost but still in the pool. */ - cs_text(font_id_base + f) = t; - } - } - if (cur_name == str_ptr-1) { - flush_str(cur_name); - cur_name = get_nullstr(); - } -} diff --git a/Build/source/texk/web2c/luatexdir/tex/texdeffont.h b/Build/source/texk/web2c/luatexdir/tex/texdeffont.h deleted file mode 100644 index 24782f5fbe4..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/texdeffont.h +++ /dev/null @@ -1,30 +0,0 @@ -/* texdeffont.h - - Copyright 2009 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ - - -#ifndef TEXDEFFONT_H -# define TEXDEFFONT_H - -extern int font_bytes; - -extern void set_cur_font(internal_font_number f); - -extern void tex_def_font(small_number a); - -#endif diff --git a/Build/source/texk/web2c/luatexdir/tex/texfileio.c b/Build/source/texk/web2c/luatexdir/tex/texfileio.c deleted file mode 100644 index 4e0677a564b..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/texfileio.c +++ /dev/null @@ -1,1509 +0,0 @@ -/* - -Copyright 2009-2010 Taco Hoekwater <taco@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your -option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU General Public License along -with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" - -#include <string.h> -#include <kpathsea/absolute.h> - -/*tex - -The bane of portability is the fact that different operating systems treat input -and output quite differently, perhaps because computer scientists have not given -sufficient attention to this problem. People have felt somehow that input and -output are not part of ``real'' programming. Well, it is true that some kinds of -programming are more fun than others. With existing input/output conventions -being so diverse and so messy, the only sources of joy in such parts of the code -are the rare occasions when one can find a way to make the program a little less -bad than it might have been. We have two choices, either to attack I/O now and -get it over with, or to postpone I/O until near the end. Neither prospect is very -attractive, so let's get it over with. - -The basic operations we need to do are (1)~inputting and outputting of text, to -or from a file or the user's terminal; (2)~inputting and outputting of eight-bit -bytes, to or from a file; (3)~instructing the operating system to initiate -(``open'') or to terminate (``close'') input or output from a specified file; -(4)~testing whether the end of an input file has been reached. - -\TeX\ needs to deal with two kinds of files. We shall use the term |alpha_file| -for a file that contains textual data, and the term |byte_file| for a file that -contains eight-bit binary information. These two types turn out to be the same on -many computers, but sometimes there is a significant distinction, so we shall be -careful to distinguish between them. Standard protocols for transferring such -files from computer to computer, via high-speed networks, are now becoming -available to more and more communities of users. - -The program actually makes use also of a third kind of file, called a -|word_file|, when dumping and reloading base information for its own -initialization. We shall define a word file later; but it will be possible for us -to specify simple operations on word files before they are defined. - -We finally did away with |nameoffile| and |namelength|, but the variables have to -be kept otherwise there will be link errors from |openclose.c| in the web2c -library - -*/ - -char *nameoffile; -int namelength; - -/*tex - - When input files are opened via a callback, they will also be read using - callbacks. for that purpose, the |open_read_file_callback| returns an integer - to uniquely identify a callback table. This id replaces the file point |f| in - this case, because the input does not have to be a file in the traditional - sense. - - Signalling this fact is achieved by having two arrays of integers. - -*/ - -int *input_file_callback_id; -int read_file_callback_id[17]; - -/*tex - - Here we handle |-output-directory|. We assume that it is OK to look here - first. Possibly it would be better to replace lookups in "." with lookups in - the |output_directory| followed by "." but to do this requires much more - invasive surgery in libkpathsea. - -*/ - -static char *find_in_output_directory(const char *s) -{ - if (output_directory && !kpse_absolute_p(s, false)) { - FILE *f_ptr; - char *ftemp = concat3(output_directory, DIR_SEP_STRING, s); - /*tex This code is used for input files only. */ - f_ptr = fopen(ftemp, "rb"); - if (f_ptr) { - fclose(f_ptr); - return ftemp; - } else { - free(ftemp); - - } - } - return NULL; -} - -/*tex - - Find an \.{\\input} or \.{\\read} file. |n| differentiates between those - case. - -*/ - -int kpse_available(const char *m) { - if (!kpse_init) { - fprintf(stdout,"missing kpse replacement callback '%s', quitting\n",m); - exit(1); - } - return 1 ; -} - -char *luatex_find_read_file(const char *s, int n, int callback_index) -{ - char *ftemp = NULL; - int callback_id = callback_defined(callback_index); - if (callback_id > 0) { - (void) run_callback(callback_id, "dS->R", n, s, &ftemp); - } else if (kpse_available("find_read_file")) { - /*tex Use kpathsea here. */ - ftemp = find_in_output_directory(s); - if (!ftemp) - ftemp = kpse_find_file(s, kpse_tex_format, 1); - } - if (ftemp) { - if (fullnameoffile) - free(fullnameoffile); - fullnameoffile = xstrdup(ftemp); - } - return ftemp; -} - -/*tex Find other files types. */ - -char *luatex_find_file(const char *s, int callback_index) -{ - char *ftemp = NULL; - int callback_id = callback_defined(callback_index); - if (callback_id > 0) { - (void) run_callback(callback_id, "S->R", s, &ftemp); - } else if (kpse_available("find_read_file")) { - /*tex Use kpathsea here. */ - switch (callback_index) { - case find_enc_file_callback: - ftemp = kpse_find_file(s, kpse_enc_format, 0); - break; - case find_map_file_callback: - ftemp = kpse_find_file(s, kpse_fontmap_format, 0); - break; - case find_type1_file_callback: - ftemp = kpse_find_file(s, kpse_type1_format, 0); - break; - case find_truetype_file_callback: - ftemp = kpse_find_file(s, kpse_truetype_format, 0); - break; - case find_opentype_file_callback: - ftemp = kpse_find_file(s, kpse_opentype_format, 0); - if (ftemp == NULL) - ftemp = kpse_find_file(s, kpse_truetype_format, 0); - break; - case find_data_file_callback: - ftemp = find_in_output_directory(s); - if (!ftemp) - ftemp = kpse_find_file(s, kpse_tex_format, 1); - break; - case find_font_file_callback: - ftemp = kpse_find_file(s, kpse_ofm_format, 1); - if (ftemp == NULL) - ftemp = kpse_find_file(s, kpse_tfm_format, 1); - break; - case find_vf_file_callback: - ftemp = kpse_find_file(s, kpse_ovf_format, 0); - if (ftemp == NULL) - ftemp = kpse_find_file(s, kpse_vf_format, 0); - break; - case find_cidmap_file_callback: - ftemp = kpse_find_file(s, kpse_cid_format, 0); - break; - default: - printf("luatex_find_file(): do not know how to handle file %s of type %d\n", s, callback_index); - break; - } - } - return ftemp; -} - -/*tex - - \LUATEX\ used to have private functions for these that did not use kpathsea, - but since the file paranoia tests have to come from kpathsea anyway, that is - no longer useful. The only downside to using luatex is that if one wants to - disable kpathsea via the Lua startup script, it is now an absolute - requirement that all file discovery callbacks are specified. Just using the - find_read_file, but not setting open_read_file, for example, does not work - any more if kpathsea is not to be used at all. - -*/ - -#define openoutnameok(A) kpse_out_name_ok (A) -#define openinnameok(A) kpse_in_name_ok (A) - -/*tex - - Open an input file F, using the kpathsea format FILEFMT and passing - |FOPEN_MODE| to fopen. The filename is in `fn'. We return whether or not the - open succeeded. - -*/ - -boolean luatex_open_input(FILE ** f_ptr, const char *fn, int filefmt, const_string fopen_mode, boolean must_exist) -{ - /*tex We haven't found anything yet. */ - string fname = NULL; - *f_ptr = NULL; - if (fullnameoffile) - free(fullnameoffile); - fullnameoffile = NULL; - fname = kpse_find_file(fn, (kpse_file_format_type) filefmt, must_exist); - if (fname) { - fullnameoffile = xstrdup(fname); - /*tex - - If we found the file in the current directory, don't leave the `./' - at the beginning of `fn', since it looks dumb when `tex foo' says - `(./foo.tex ... )'. On the other hand, if the user said `tex ./foo', - and that's what we opened, then keep it -- the user specified it, so - we shouldn't remove it. - - */ - if (fname[0] == '.' && IS_DIR_SEP(fname[1]) && (fn[0] != '.' || !IS_DIR_SEP(fn[1]))) { - unsigned i = 0; - while (fname[i + 2] != 0) { - fname[i] = fname[i + 2]; - i++; - } - fname[i] = 0; - } - /*tex This fopen is not allowed to fail. */ - *f_ptr = xfopen(fname, fopen_mode); - } - if (*f_ptr) { - recorder_record_input(fname); - } - return *f_ptr != NULL; -} - -boolean luatex_open_output(FILE ** f_ptr, const char *fn, const_string fopen_mode) -{ - char *fname; - boolean absolute = kpse_absolute_p(fn, false); - /*tex If we have an explicit output directory, use it. */ - if (output_directory && !absolute) { - fname = concat3(output_directory, DIR_SEP_STRING, fn); - } else { - fname = xstrdup(fn); - } - /*tex Is the filename openable as given? */ - *f_ptr = fopen(fname, fopen_mode); - if (!*f_ptr) { - /*tex Can't open as given. Try the envvar. */ - string texmfoutput = kpse_var_value("TEXMFOUTPUT"); - if (texmfoutput && *texmfoutput && !absolute) { - fname = concat3(texmfoutput, DIR_SEP_STRING, fn); - *f_ptr = fopen(fname, fopen_mode); - } - } - if (*f_ptr) { - recorder_record_output(fname); - } - free(fname); - return *f_ptr != NULL; -} - -boolean lua_a_open_in(alpha_file * f, char *fn, int n) -{ - int k; - char *fnam; - int callback_id; - boolean ret = true; - boolean file_ok = true; - if (n == 0) { - input_file_callback_id[iindex] = 0; - } else { - read_file_callback_id[n] = 0; - } - if (*fn == '|') - fnam = fn; - else - fnam = luatex_find_read_file(fn, n, find_read_file_callback); - if (!fnam) - return false; - callback_id = callback_defined(open_read_file_callback); - if (callback_id > 0) { - k = run_and_save_callback(callback_id, "S->", fnam); - if (k > 0) { - ret = true; - if (n == 0) - input_file_callback_id[iindex] = k; - else - read_file_callback_id[n] = k; - } else { - /*tex read failed */ - file_ok = false; - } - } else { - /*tex no read callback */ - if (openinnameok(fn)) { - ret = open_in_or_pipe(f, fnam, kpse_tex_format, FOPEN_RBIN_MODE, (n == 0 ? true : false)); - } else { - /*tex open failed */ - file_ok = false; - } - } - if (!file_ok) { - ret = false; - } - return ret; -} - -boolean lua_a_open_out(alpha_file * f, char *fn, int n) -{ - boolean test; - char *fnam = NULL; - int callback_id; - boolean ret = false; - callback_id = callback_defined(find_write_file_callback); - if (callback_id > 0) { - test = run_callback(callback_id, "dS->R", n, fn, &fnam); - if ((test) && (fnam != NULL) && (strlen(fnam) > 0)) { - /*tex - - There is no message here because if that is needed the macro - package should do that in the callback code. As elsewhere, - messaging is left to \LUA\ then. - - */ - ret = open_outfile(f, fnam, FOPEN_W_MODE); - free(fnam); - } - } else { - if (openoutnameok(fn)) { - if (n > 0 && selector != term_only) { - /*tex - - This message to the log is for downward compatibility with - other tex's as there are scripts out there that act on this - message. An alternative is to let a macro package write an - explicit message. - - */ - fprintf(log_file,"\n\\openout%i = %s\n",n-1,fn); - } - ret = open_out_or_pipe(f, fn, FOPEN_W_MODE); - } - } - return ret; -} - -boolean lua_b_open_out(alpha_file * f, char *fn) -{ - boolean test; - char *fnam = NULL; - int callback_id; - boolean ret = false; - callback_id = callback_defined(find_output_file_callback); - if (callback_id > 0) { - test = run_callback(callback_id, "S->R", fn, &fnam); - if ((test) && (fnam != NULL) && (strlen(fnam) > 0)) { - ret = open_outfile(f, fnam, FOPEN_WBIN_MODE); - free(fnam); - } - } else { - if (openoutnameok(fn)) { - ret = luatex_open_output(f, fn, FOPEN_WBIN_MODE); - } - } - return ret; -} - -void lua_a_close_in(alpha_file f, int n) -{ - int callback_id; - if (n == 0) - callback_id = input_file_callback_id[iindex]; - else - callback_id = read_file_callback_id[n]; - if (callback_id > 0) { - run_saved_callback(callback_id, "close", "->"); - destroy_saved_callback(callback_id); - if (n == 0) - input_file_callback_id[iindex] = 0; - else - read_file_callback_id[n] = 0; - } else { - close_file_or_pipe(f); - } -} - -void lua_a_close_out(alpha_file f) -{ - close_file_or_pipe(f); -} - -/*tex - - Binary input and output are done with C's ordinary procedures, so we don't - have to make any other special arrangements for binary~I/O. Text output is - also easy to do with standard routines. The treatment of text input is more - difficult, however, because of the necessary translation to |ASCII_code| - values. \TeX's conventions should be efficient, and they should blend nicely - with the user's operating environment. - - Input from text files is read one line at a time, using a routine called - |lua_input_ln|. This function is defined in terms of global variables called - |buffer|, |first|, and |last| that will be described in detail later; for - now, it suffices for us to know that |buffer| is an array of |ASCII_code| - values, and that |first| and |last| are indices into this array representing - the beginning and ending of a line of text. - -*/ - -/*tex lines of characters being read */ - -packed_ASCII_code *buffer; - -/*tex the first unused position in |buffer| */ - -int first; - -/*tex end of the line just input to |buffer| */ - -int last; - -/*tex largest index used in |buffer| */ - -int max_buf_stack; - -/*tex - - The |lua_input_ln| function brings the next line of input from the specified - file into available positions of the buffer array and returns the value - |true|, unless the file has already been entirely read, in which case it - returns |false| and sets |last:=first|. In general, the |ASCII_code| numbers - that represent the next line of the file are input into |buffer[first]|, - |buffer[first+1]|, \dots, |buffer[last-1]|; and the global variable |last| is - set equal to |first| plus the length of the line. Trailing blanks are removed - from the line; thus, either |last=first| (in which case the line was entirely - blank) or |buffer[last-1]<>" "|. - - An overflow error is given, however, if the normal actions of |lua_input_ln| - would make |last>=buf_size|; this is done so that other parts of \TeX\ can - safely look at the contents of |buffer[last+1]| without overstepping the - bounds of the |buffer| array. Upon entry to |lua_input_ln|, the condition - |first<buf_size| will always hold, so that there is always room for an - ``empty'' line. - - The variable |max_buf_stack|, which is used to keep track of how large the - |buf_size| parameter must be to accommodate the present job, is also kept up - to date by |lua_input_ln|. - - If the |bypass_eoln| parameter is |true|, |lua_input_ln| will do a |get| - before looking at the first character of the line; this skips over an |eoln| - that was in |f^|. The procedure does not do a |get| when it reaches the end - of the line; therefore it can be used to acquire input from the user's - terminal as well as from ordinary text files. - - Since the inner loop of |lua_input_ln| is part of \TeX's ``inner - loop''---each character of input comes in at this place---it is wise to - reduce system overhead by making use of special routines that read in an - entire array of characters at once, if such routines are available. - -*/ - -boolean lua_input_ln(alpha_file f, int n, boolean bypass_eoln) -{ - boolean lua_result; - int last_ptr; - int callback_id; - /*tex Todo: variable can be removed: */ - (void) bypass_eoln; - if (n == 0) - callback_id = input_file_callback_id[iindex]; - else - callback_id = read_file_callback_id[n]; - if (callback_id > 0) { - last = first; - last_ptr = first; - lua_result = - run_saved_callback(callback_id, "reader", "->l", &last_ptr); - if ((lua_result == true) && (last_ptr != 0)) { - last = last_ptr; - if (last > max_buf_stack) - max_buf_stack = last; - } else { - lua_result = false; - } - } else { - lua_result = input_ln(f, bypass_eoln); - } - if (lua_result == true) { - /*tex Fix up the input buffer using callbacks */ - if (last >= first) { - callback_id = callback_defined(process_input_buffer_callback); - if (callback_id > 0) { - last_ptr = first; - lua_result = - run_callback(callback_id, "l->l", (last - first), - &last_ptr); - if ((lua_result == true) && (last_ptr != 0)) { - last = last_ptr; - if (last > max_buf_stack) - max_buf_stack = last; - } - } - } - return true; - } - return false; -} - -/*tex - - We need a special routine to read the first line of \TeX\ input from the - user's terminal. This line is different because it is read before we have - opened the transcript file; there is sort of a ``chicken and egg'' problem - here. If the user types `\.{\\input paper}' on the first line, or if some - macro invoked by that line does such an \.{\\input}, the transcript file will - be named `\.{paper.log}'; but if no \.{\\input} commands are performed during - the first line of terminal input, the transcript file will acquire its - default name `\.{texput.log}'. (The transcript file will not contain error - messages generated by the first line before the first \.{\\input} command.) - - The first line is special also because it may be read before \TeX\ has input - a format file. In such cases, normal error messages cannot yet be given. The - following code uses concepts that will be explained later. - - Different systems have different ways to get started. But regardless of what - conventions are adopted, the routine that initializes the terminal should - satisfy the following specifications: - - \startitemize[n] - - \startitem - It should open file |term_in| for input from the terminal. (The file - |term_out| will already be open for output to the terminal.) - \stopitem - - \startitem - If the user has given a command line, this line should be considered - the first line of terminal input. Otherwise the user should be - prompted with `\.{**}', and the first line of input should be - whatever is typed in response. - \stopitem - - \startitem - The first line of input, which might or might not be a command line, - should appear in locations |first| to |last-1| of the |buffer| array. - \stopitem - - \startitem - The global variable |loc| should be set so that the character to be - read next by \TeX\ is in |buffer[loc]|. This character should not be - blank, and we should have |loc<last|. - \stopitem - - \stopitemize - - It may be necessary to prompt the user several times before a non-blank line - comes in. The prompt is `\.{**}' instead of the later `\.*' because the - meaning is slightly different: `\.{\\input}' need not be typed immediately - after~`\.{**}'.) - - The following program does the required initialization. Iff anything has been - specified on the command line, then |t_open_in| will return with |last > - first|. - -*/ - -boolean init_terminal(void) -{ - /*tex This gets the terminal input started. */ - t_open_in(); - if (last > first) { - iloc = first; - while ((iloc < last) && (buffer[iloc] == ' ')) - incr(iloc); - if (iloc < last) { - return true; - } - } - while (1) { - wake_up_terminal(); - fputs("**", term_out); - update_terminal(); - if (!input_ln(term_in, true)) { - /*tex This shouldn't happen. */ - fputs("\n! End of file on the terminal... why?\n", term_out); - return false; - } - iloc = first; - while ((iloc < last) && (buffer[iloc] == ' ')) { - incr(iloc); - } - /*tex Return unless the line was all blank. */ - if (iloc < last) { - return true; - } - fputs("Please type the name of your input file.\n", term_out); - } -} - - -/*tex - - Here is a procedure that asks the user to type a line of input, assuming that - the |selector| setting is either |term_only| or |term_and_log|. The input is - placed into locations |first| through |last-1| of the |buffer| array, and - echoed on the transcript file if appropriate. - -*/ - -void term_input(void) -{ - /*tex Index into |buffer|: */ - int k; - /*tex Now the user sees the prompt for sure: */ - update_terminal(); - if (!input_ln(term_in, true)) - fatal_error("End of file on the terminal!"); - /*tex The user's line ended with \.{<return>}: */ - term_offset = 0; - /*tex Prepare to echo the input. */ - decr(selector); - if (last != first) { - for (k = first; k <= last - 1; k++) - print_char(buffer[k]); - } - print_ln(); - /*tex Restore previous status. */ - incr(selector); -} - -/*tex - - It's time now to fret about file names. Besides the fact that different - operating systems treat files in different ways, we must cope with the fact - that completely different naming conventions are used by different groups of - people. The following programs show what is required for one particular - operating system; similar routines for other systems are not difficult to - devise. - - \TeX\ assumes that a file name has three parts: the name proper; its - ``extension''; and a ``file area'' where it is found in an external file - system. The extension of an input file or a write file is assumed to be - `\.{.tex}' unless otherwise specified; it is `\.{.log}' on the transcript - file that records each run of \TeX; it is `\.{.tfm}' on the font metric files - that describe characters in the fonts \TeX\ uses; it is `\.{.dvi}' on the - output files that specify typesetting information; and it is `\.{.fmt}' on - the format files written by \.{INITEX} to initialize \TeX. The file area can - be arbitrary on input files, but files are usually output to the user's - current area. If an input file cannot be found on the specified area, \TeX\ - will look for it on a special system area; this special area is intended for - commonly used input files like \.{webmac.tex}. - - Simple uses of \TeX\ refer only to file names that have no explicit extension - or area. For example, a person usually says `\.{\\input} \.{paper}' or - `\.{\\font\\tenrm} \.= \.{helvetica}' instead of `\.{\\input} \.{paper.new}' - or `\.{\\font\\tenrm} \.= \.{<csd.knuth>test}'. Simple file names are best, - because they make the \TeX\ source files portable; whenever a file name - consists entirely of letters and digits, it should be treated in the same way - by all implementations of \TeX. However, users need the ability to refer to - other files in their environment, especially when responding to error - messages concerning unopenable files; therefore we want to let them use the - syntax that appears in their favorite operating system. - - The following procedures don't allow spaces to be part of file names; but - some users seem to like names that are spaced-out. System-dependent changes - to allow such things should probably be made with reluctance, and only when - an entire file name that includes spaces is ``quoted'' somehow. - - Here are the global values that file names will be scanned into. - -*/ - -/*tex name of file just scanned */ - -str_number cur_name; - -/*tex file area just scanned, or \.{""} */ - -str_number cur_area; - -/*tex file extension just scanned, or \.{""} */ - -str_number cur_ext; - -/*tex - - The file names we shall deal with have the following structure: If the name - contains `\./' or `\.:' (for Amiga only), the file area consists of all - characters up to and including the final such character; otherwise the file - area is null. If the remaining file name contains `\..', the file extension - consists of all such characters from the last `\..' to the end, otherwise the - file extension is null. - - We can scan such file names easily by using two global variables that keep - track of the occurrences of area and extension delimiters: - -*/ - -/*tex the most recent `\./', if any */ - -pool_pointer area_delimiter; - -/*tex the relevant `\..', if any */ - -pool_pointer ext_delimiter; - -/*tex - - Input files that can't be found in the user's area may appear in a standard - system area called |TEX_area|. Font metric files whose areas are not given - explicitly are assumed to appear in a standard system area called - |TEX_font_area|. $\Omega$'s compiled translation process files whose areas - are not given explicitly are assumed to appear in a standard system area. - These system area names will, of course, vary from place to place. - -*/ - -#define append_to_fn(A) do { \ - c=(A); \ - if (c!='"') { \ - if (k<file_name_size) fn[k++]=(unsigned char)(c); \ - } \ - } while (0) - - -char *pack_file_name(str_number n, str_number a, str_number e) -{ - /*tex character being packed */ - ASCII_code c; - /*tex index into |str_pool| */ - unsigned char *j; - /*tex number of positions filled in |fn| */ - int k = 0; - unsigned char *fn = xmallocarray(packed_ASCII_code, str_length(a) + str_length(n) + str_length(e) + 1); - for (j = str_string(a); j < str_string(a) + str_length(a); j++) - append_to_fn(*j); - for (j = str_string(n); j < str_string(n) + str_length(n); j++) - append_to_fn(*j); - for (j = str_string(e); j < str_string(e) + str_length(e); j++) - append_to_fn(*j); - fn[k] = 0; - return (char *) fn; -} - -/*tex - - A messier routine is also needed, since format file names must be scanned - before \TeX's string mechanism has been initialized. We shall use the global - variable |TEX_format_default| to supply the text for default system areas and - extensions related to format files. - - Under \UNIX\ we don't give the area part, instead depending on the path - searching that will happen during file opening. Also, the length will be set - in the main program. - -*/ - -char *TEX_format_default; - - -/*tex - - This part of the program becomes active when a ``virgin'' \TeX\ is trying to - get going, just after the preliminary initialization, or when the user is - substituting another format file by typing `\.\&' after the initial `\.{**}' - prompt. The buffer contains the first line of input in - |buffer[loc..(last-1)]|, where |loc<last| and |buffer[loc]<>" "|. - -*/ - -char *open_fmt_file(void) -{ - /*tex The first space after the format file name: */ - int j; - char *fmt = NULL; - int dist; - j = iloc; - if (buffer[iloc] == '&') { - incr(iloc); - j = iloc; - buffer[last] = ' '; - while (buffer[j] != ' ') - incr(j); - fmt = xmalloc((unsigned) (j - iloc + 1)); - strncpy(fmt, (char *) (buffer + iloc), (size_t) (j - iloc)); - fmt[j - iloc] = 0; - dist = (int) (strlen(fmt) - strlen(DUMP_EXT)); - if (!(strstr(fmt, DUMP_EXT) == fmt + dist)) - fmt = concat(fmt, DUMP_EXT); - if (zopen_w_input(&fmt_file, fmt, DUMP_FORMAT, FOPEN_RBIN_MODE)) - goto FOUND; - wake_up_terminal(); - fprintf(stdout, "Sorry, I can't find the format `%s'; will try `%s'.\n", - fmt, TEX_format_default); - update_terminal(); - } - /*tex Now pull out all the stops: try for the system \.{plain} file. */ - fmt = TEX_format_default; - if (!zopen_w_input(&fmt_file, fmt, DUMP_FORMAT, FOPEN_RBIN_MODE)) { - wake_up_terminal(); - fprintf(stdout, "I can't find the format file `%s'!\n", - TEX_format_default); - return NULL; - } - FOUND: - iloc = j; - return fmt; -} - -/*tex - - The global variable |name_in_progress| is used to prevent recursive use of - |scan_file_name|, since the |begin_name| and other procedures communicate via - global variables. Recursion would arise only by devious tricks like - `\.{\\input\\input f}'; such attempts at sabotage must be thwarted. - Furthermore, |name_in_progress| prevents \.{\\input} from being initiated - when a font size specification is being scanned. - - Another global variable, |job_name|, contains the file name that was first - \.{\\input} by the user. This name is extended by `\.{.log}' and `\.{.dvi}' - and `\.{.fmt}' in the names of \TeX's output files. - -*/ - -/*tex is a file name being scanned? */ - -boolean name_in_progress; - -/*tex principal file name */ - -str_number job_name; - -/*tex has the transcript file been opened? */ - -boolean log_opened_global; - -/*tex - - Initially |job_name=0|; it becomes nonzero as soon as the true name is known. - We have |job_name=0| if and only if the `\.{log}' file has not been opened, - except of course for a short time just after |job_name| has become nonzero. - -*/ - -/*tex full name of the log file */ - -unsigned char *texmf_log_name; - -/*tex - - The |open_log_file| routine is used to open the transcript file and to help - it catch up to what has previously been printed on the terminal. - -*/ - -void open_log_file(void) -{ - /*tex previous |selector| setting */ - int old_setting; - /*tex index into |buffer| */ - int k; - /*tex end of first input line */ - int l; - char *fn; - old_setting = selector; - if (job_name == 0) - job_name = getjobname(maketexstring("texput")); - fn = pack_job_name(".fls"); - recorder_change_filename(fn); - fn = pack_job_name(".log"); - while (!lua_a_open_out(&log_file, fn, 0)) { - /*tex - - Try to get a different log file name. Sometimes |open_log_file| is - called at awkward moments when \TeX\ is unable to print error - messages or even to |show_context|. The |prompt_file_name| routine - can result in a |fatal_error|, but the |error| routine will not be - invoked because |log_opened| will be false. - - The normal idea of |batch_mode| is that nothing at all should be - written on the terminal. However, in the unusual case that no log - file could be opened, we make an exception and allow an explanatory - message to be seen. - - Incidentally, the program always refers to the log file as a - `\.{transcript file}', because some systems cannot use the extension - `\.{.log}' for this file. - */ - selector = term_only; - fn = prompt_file_name("transcript file name", ".log"); - } - texmf_log_name = (unsigned char *) xstrdup(fn); - selector = log_only; - log_opened_global = true; - if (callback_defined(start_run_callback) == 0) { - /*tex Print the banner line, including current date and time. */ - log_banner(luatex_version_string); - /*tex Make sure bottom level is in memory. */ - input_stack[input_ptr] = cur_input; - tprint_nl("**"); - /*tex The last position of first line. */ - l = input_stack[0].limit_field; - if (buffer[l] == end_line_char_par) { - /*tex maybe also handle multichar endlinechar */ - decr(l); - } - for (k = 1; k <= l; k++) { - print_char(buffer[k]); - } - /*tex now the transcript file contains the first line of input */ - print_ln(); - } - /*tex should be done always */ - flush_loggable_info(); - /*tex should be done always */ - selector = old_setting + 2; -} - -/*tex - - This function is needed by synctex to make its log appear in the right spot - when |output_directory| is set. - -*/ - -char *get_full_log_name (void) -{ - if (output_directory) { - char *ret = xmalloc(strlen((char *)texmf_log_name)+2+strlen(output_directory)); - ret = strcpy(ret, output_directory); - strcat(ret, "/"); - strcat(ret, (char *)texmf_log_name); - return ret; - } else { - return xstrdup((const char*)texmf_log_name); - } -} - -/*tex Synctex uses this to get the anchored path of an input file. */ - -char *luatex_synctex_get_current_name (void) -{ - char *pwdbuf = NULL, *ret; - if (kpse_absolute_p(fullnameoffile, false)) { - return xstrdup(fullnameoffile); - } - pwdbuf = xgetcwd(); - ret = concat3(pwdbuf, DIR_SEP_STRING, fullnameoffile); - free(pwdbuf) ; - return ret; -} - -/*tex - - Let's turn now to the procedure that is used to initiate file reading when an - `\.{\\input}' command is being processed. - -*/ - -void start_input(void) -{ - str_number temp_str; - char *fn; - do { - get_x_token(); - } while ((cur_cmd == spacer_cmd) || (cur_cmd == relax_cmd)); - - back_input(); - if (cur_cmd != left_brace_cmd) { - /*tex Set |cur_name| to desired file name. */ - scan_file_name(); - } else { - scan_file_name_toks(); - } - fn = pack_file_name(cur_name, cur_area, cur_ext); - while (1) { - /*tex Set up |cur_file| and new level of input. */ - begin_file_reading(); - if (lua_a_open_in(&cur_file, fn, 0)) { - break; - } - /*tex Remove the level that didn't work. */ - end_file_reading(); - fn = prompt_file_name("input file name", ""); - } - iname = maketexstring(fullnameoffile); - /*tex - - Now that we have |fullnameoffile|, it is time to post-adjust |cur_name| - and |cur_ext| for trailing |.tex|. - - */ - { - char *n, *p; - n = p = fullnameoffile + strlen(fullnameoffile); - while (p>fullnameoffile) { - p--; - if (IS_DIR_SEP(*p)) { - break; - } - } - if (IS_DIR_SEP(*p)) { - p++; - } - while (n>fullnameoffile) { - n--; - if (*n == '.') { - break; - } - } - if (n>p) { - int q = *n; - cur_ext = maketexstring(n); - *n = 0; - cur_name = maketexstring(p); - *n = q; - } - } - source_filename_stack[in_open] = iname; - full_source_filename_stack[in_open] = xstrdup(fullnameoffile); - /*tex We can try to conserve string pool space now. */ - temp_str = search_string(iname); - if (temp_str > 0) { - flush_str(iname); - iname = temp_str; - } - if (job_name == 0) { - job_name = getjobname(cur_name); - open_log_file(); - } - /*tex - - |open_log_file| doesn't |show_context|, so |limit| and |loc| needn't be - set to meaningful values yet. - - */ - report_start_file(filetype_tex,fullnameoffile); - incr(open_parens); - update_terminal(); - istate = new_line; - /*tex Prepare new file {\sl Sync\TeX} information. */ - if (! synctex_get_no_files()) { - /*tex Give control to the {\sl Sync\TeX} controller. */ - synctexstartinput(); - } - /*tex - - Read the first line of the new file. Here we have to remember to tell the - |lua_input_ln| routine not to start with a |get|. If the file is empty, - it is considered to contain a single blank line. - - */ - line = 1; - if (lua_input_ln(cur_file, 0, false)) { - ; - } - firm_up_the_line(); - if (end_line_char_inactive) - decr(ilimit); - else - buffer[ilimit] = (packed_ASCII_code) end_line_char_par; - first = ilimit + 1; - iloc = istart; -} - -/*tex - - Because the format is zipped we read and write dump files through zlib. - Earlier versions recast |*f| from |FILE *| to |gzFile|, but there is no - guarantee that these have the same size, so a static variable is needed. - -*/ - -static gzFile gz_fmtfile = NULL; - -/*tex - - As distributed, the dump files are architecture dependent; specifically, - BigEndian and LittleEndian architectures produce different files. These - routines always output BigEndian files. This still does not guarantee them to - be architecture-independent, because it is possible to make a format that - dumps a glue ratio, i.e., a floating-point number. Fortunately, none of the - standard formats do that. - -*/ - -#if !defined (WORDS_BIGENDIAN) && !defined (NO_DUMP_SHARE) - -/*tex - - This macro is always invoked as a statement. It assumes a variable `temp'. - -*/ - -# define SWAP(x, y) do { temp = x; x = y; y = temp; } while (0) - -/*tex - - Make the NITEMS items pointed at by P, each of size SIZE, be the - opposite-endianness of whatever they are now. - -*/ - -static void swap_items(char *pp, int nitems, int size) -{ - char temp; - unsigned total = (unsigned) (nitems * size); - char *q = xmalloc(total); - char *p = q; - memcpy(p,pp,total); - /*tex - - Since `size' does not change, we can write a while loop for each case, - and avoid testing `size' for each time. - - */ - switch (size) { - case 16: - /*tex - - 16-byte items happen on the DEC Alpha machine when we are not doing - sharable memory dumps. - - */ - while (nitems--) { - SWAP(p[0], p[15]); - SWAP(p[1], p[14]); - SWAP(p[2], p[13]); - SWAP(p[3], p[12]); - SWAP(p[4], p[11]); - SWAP(p[5], p[10]); - SWAP(p[6], p[9]); - SWAP(p[7], p[8]); - p += size; - } - break; - - case 12: - while (nitems--) { - SWAP(p[0], p[11]); - SWAP(p[1], p[10]); - SWAP(p[2], p[9]); - SWAP(p[3], p[8]); - SWAP(p[4], p[7]); - SWAP(p[5], p[6]); - p += size; - } - break; - - case 8: - while (nitems--) { - SWAP(p[0], p[7]); - SWAP(p[1], p[6]); - SWAP(p[2], p[5]); - SWAP(p[3], p[4]); - p += size; - } - break; - - case 4: - while (nitems--) { - SWAP(p[0], p[3]); - SWAP(p[1], p[2]); - p += size; - } - break; - - case 2: - while (nitems--) { - SWAP(p[0], p[1]); - p += size; - } - break; - case 1: - /*tex Nothing to do. */ - break; - default: - FATAL1("Can't swap a %d-byte item for (un)dumping", size); - } - memcpy(pp,q,total); - xfree(q); -} -#endif - -/*tex - - That second swap is to make sure following calls don't get confused in the - case of |dump_things|. - -*/ - -void do_zdump(char *p, int item_size, int nitems, FILE * out_file) -{ - int err; - (void) out_file; - if (nitems == 0) - return; -#if !defined (WORDS_BIGENDIAN) && !defined (NO_DUMP_SHARE) - swap_items(p, nitems, item_size); -#endif - if (gzwrite(gz_fmtfile, (void *) p, (unsigned) (item_size * nitems)) != - item_size * nitems) { - fprintf(stderr, "! Could not write %d %d-byte item(s): %s.\n", nitems, item_size, gzerror(gz_fmtfile, &err)); - uexit(1); - } -#if !defined (WORDS_BIGENDIAN) && !defined (NO_DUMP_SHARE) - swap_items(p, nitems, item_size); -#endif -} - -void do_zundump(char *p, int item_size, int nitems, FILE * in_file) -{ - int err; - (void) in_file; - if (nitems == 0) - return; - if (gzread(gz_fmtfile, (void *) p, (unsigned) (item_size * nitems)) <= 0) { - fprintf(stderr, "Could not undump %d %d-byte item(s): %s.\n", nitems, item_size, gzerror(gz_fmtfile, &err)); - uexit(1); - } -#if !defined (WORDS_BIGENDIAN) && !defined (NO_DUMP_SHARE) - swap_items(p, nitems, item_size); -#endif -} - -/*tex - - Tests has shown that a level 3 compression is the most optimal tradeoff - between file size and load time. - -*/ - -#define COMPRESSION "R3" - -boolean zopen_w_input(FILE ** f, const char *fname, int format, const_string fopen_mode) -{ - int callbackid; - int res; - char *fnam; - callbackid = callback_defined(find_format_file_callback); - if (callbackid > 0) { - res = run_callback(callbackid, "S->R", fname, &fnam); - if (res && fnam && strlen(fnam) > 0) { - *f = fopen(fnam, fopen_mode); - if (*f == NULL) { - return 0; - } - } else { - return 0; - } - } else { - res = luatex_open_input(f, fname, format, fopen_mode, true); - } - if (res) { - gz_fmtfile = gzdopen(fileno(*f), "rb" COMPRESSION); - } - return res; -} - -boolean zopen_w_output(FILE ** f, const char *s, const_string fopen_mode) -{ - int res = 1; - if (luainit) { - *f = fopen(s, fopen_mode); - if (*f == NULL) { - return 0; - } - } else { - res = luatex_open_output(f, s, fopen_mode); - } - if (res) { - gz_fmtfile = gzdopen(fileno(*f), "wb" COMPRESSION); - } - return res; -} - -void zwclose(FILE * f) -{ - (void) f; - gzclose(gz_fmtfile); -} - -/*tex Create the \DVI\ or \PDF\ file. */ - -int open_outfile(FILE ** f, const char *name, const char *mode) -{ - FILE *res; - res = fopen(name, mode); - if (res != NULL) { - *f = res; - return 1; - } - return 0; -} - -/*tex The caller should set |tfm_buffer=NULL| and |tfm_size=0|. */ - -int readbinfile(FILE * f, unsigned char **tfm_buffer, int *tfm_size) -{ - void *buf; - int size; - if (fseek(f, 0, SEEK_END) == 0) { - size = (int) ftell(f); - if (size > 0) { - buf = xmalloc((unsigned) size); - if (fseek(f, 0, SEEK_SET) == 0) { - if (fread((void *) buf, (size_t) size, 1, f) == 1) { - *tfm_buffer = (unsigned char *) buf; - *tfm_size = size; - return 1; - } - } - } else { - *tfm_buffer = NULL; - *tfm_size = 0; - return 1; - } - } - /*tex Either seek failed or we have a zero-sized file. */ - return 0; -} - -/*tex - - Like |os.execute()|, the |runpopen()| function is called only when - |shellenabledp == 1|. Unlike |os.execute()| we write errors to stderr, since - we have nowhere better to use; and of course we return a file handle (or - NULL) instead of a status indicator. - -*/ - -static FILE *runpopen(char *cmd, const char *mode) -{ - FILE *f = NULL; - char *safecmd = NULL; - char *cmdname = NULL; - int allow; -#ifdef WIN32 - char *pp; - - for (pp = cmd; *pp; pp++) { - if (*pp == '\'') *pp = '"'; - } -#endif - /*tex If |restrictedshell| is zero, any command is allowed. */ - if (restrictedshell == 0) { - allow = 1; - } else { - const char *thecmd = cmd; - allow = shell_cmd_is_allowed(thecmd, &safecmd, &cmdname); - } - if (allow == 1) - f = popen(cmd, mode); - else if (allow == 2) - f = popen(safecmd, mode); - else if (allow == -1) - fprintf(stderr, "\nrunpopen quotation error in command line: %s\n", cmd); - else - fprintf(stderr, "\nrunpopen command not allowed: %s\n", cmdname); - if (safecmd) - free(safecmd); - if (cmdname) - free(cmdname); - return f; -} - -/*tex - - The code that implements |popen()| needs an array for tracking possible pipe - file pointers, because these need to be closed using |pclose()|. - -*/ - -#define NUM_PIPES 16 -static FILE *pipes[NUM_PIPES]; - -#ifdef WIN32 -FILE *Poptr; -#endif - -boolean open_in_or_pipe(FILE ** f_ptr, char *fn, int filefmt, const_string fopen_mode, boolean must_exist) -{ - string fname = NULL; - int i; - /*tex - - Opening a read pipe is straightforward, only have to skip past the pipe - symbol in the file name. filename quoting is assumed to happen elsewhere - (it does :-)) - - */ - if (shellenabledp && *fn == '|') { - /*tex The user requested a pipe. */ - *f_ptr = NULL; - fname = (string) xmalloc((unsigned) (strlen(fn) + 1)); - strcpy(fname, fn); - if (fullnameoffile) - free(fullnameoffile); - fullnameoffile = xstrdup(fname); - recorder_record_input(fname + 1); - *f_ptr = runpopen(fname + 1, "r"); - free(fname); - for (i = 0; i < NUM_PIPES; i++) { - if (pipes[i] == NULL) { - pipes[i] = *f_ptr; - break; - } - } - if (*f_ptr) - setvbuf(*f_ptr, (char *) NULL, _IONBF, 0); -#ifdef WIN32 - Poptr = *f_ptr; -#endif - return *f_ptr != NULL; - } - return luatex_open_input(f_ptr, fn, filefmt, fopen_mode, must_exist); -} - - -boolean open_out_or_pipe(FILE ** f_ptr, char *fn, const_string fopen_mode) -{ - string fname; - int i; - /*tex - - Opening a write pipe takes a little bit more work, because TeX will - perhaps have appended ".tex". To avoid user confusion as much as - possible, this extension is stripped only when the command is a bare - word. Some small string trickery is needed to make sure the correct - number of bytes is free()-d afterwards. - */ - if (shellenabledp && *fn == '|') { - /*tex The user requested a pipe. */ - fname = (string) xmalloc((unsigned) (strlen(fn) + 1)); - strcpy(fname, fn); - if (strchr(fname, ' ') == NULL && strchr(fname, '>') == NULL) { - /*tex - - \METAPOST\ and \METAFIONT\ currently do not use this code, but it - is better to be prepared. Hm, what has this todo with \LUATEX ? - - */ - if (STREQ((fname + strlen(fname) - 3), "tex")) - *(fname + strlen(fname) - 4) = 0; - *f_ptr = runpopen(fname + 1, "w"); - *(fname + strlen(fname)) = '.'; - } else { - *f_ptr = runpopen(fname + 1, "w"); - } - recorder_record_output(fname + 1); - free(fname); - for (i = 0; i < NUM_PIPES; i++) { - if (pipes[i] == NULL) { - pipes[i] = *f_ptr; - break; - } - } - if (*f_ptr) - setvbuf(*f_ptr, (char *) NULL, _IONBF, 0); - return *f_ptr != NULL; - } - return luatex_open_output(f_ptr, fn, fopen_mode); -} - - -void close_file_or_pipe(FILE * f) -{ - int i; - if (shellenabledp) { - for (i = 0; i <= 15; i++) { - /*tex If this file was a pipe, |pclose()| it and return. */ - if (pipes[i] == f) { - if (f) { - pclose(f); -#ifdef WIN32 - Poptr = NULL; -#endif - } - pipes[i] = NULL; - return; - } - } - } - close_file(f); -} diff --git a/Build/source/texk/web2c/luatexdir/tex/texfileio.h b/Build/source/texk/web2c/luatexdir/tex/texfileio.h deleted file mode 100644 index c6366500766..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/texfileio.h +++ /dev/null @@ -1,145 +0,0 @@ -/* texfileio.h - - Copyright 2009 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ - - -#ifndef TEXFILEIO_H -# define TEXFILEIO_H - -extern int *input_file_callback_id; -extern int read_file_callback_id[17]; - -extern char *luatex_find_read_file(const char *s, int n, int callback_index); -extern boolean luatex_open_input(FILE ** f_ptr, const char *fn, int filefmt, - const_string fopen_mode, boolean must_exist); -extern boolean luatex_open_output(FILE ** f_ptr, const char *fn, - const_string fopen_mode); - -extern boolean lua_a_open_in(alpha_file * f, char *fn, int n); -extern boolean lua_a_open_out(alpha_file * f, char *fn, int n); -extern boolean lua_b_open_out(alpha_file * f, char *fn); -extern void lua_a_close_in(alpha_file f, int n); -extern void lua_a_close_out(alpha_file f); - -extern packed_ASCII_code *buffer; -extern int first; -extern int last; -extern int max_buf_stack; - -extern boolean lua_input_ln(alpha_file f, int n, boolean bypass_eoln); - -/* -The user's terminal acts essentially like other files of text, except -that it is used both for input and for output. When the terminal is -considered an input file, the file variable is called |term_in|, and when it -is considered an output file the file variable is |term_out|. -@^system dependencies@> -*/ - -# define term_in stdin /* the terminal as an input file */ -# define term_out stdout /* the terminal as an output file */ - - -/* -Here is how to open the terminal files. |t_open_out| does nothing. -|t_open_in|, on the other hand, does the work of ``rescanning,'' or getting -any command line arguments the user has provided. It's defined in C. -*/ - -# define t_open_out() /* output already open for text output */ - -/* -Sometimes it is necessary to synchronize the input/output mixture that -happens on the user's terminal, and three system-dependent -procedures are used for this -purpose. The first of these, |update_terminal|, is called when we want -to make sure that everything we have output to the terminal so far has -actually left the computer's internal buffers and been sent. -The second, |clear_terminal|, is called when we wish to cancel any -input that the user may have typed ahead (since we are about to -issue an unexpected error message). The third, |wake_up_terminal|, -is supposed to revive the terminal if the user has disabled it by -some instruction to the operating system. The following macros show how -these operations can be specified with {\mc UNIX}. |update_terminal| -does an |fflush|. |clear_terminal| is redefined -to do nothing, since the user should control the terminal. -@^system dependencies@> -*/ - -# define update_terminal() fflush (term_out) -# define clear_terminal() do { ; } while (0) -# define wake_up_terminal() do { ; } while (0) /* cancel the user's cancellation of output */ - -extern boolean init_terminal(void); -extern void term_input(void); - -extern str_number cur_name; -extern str_number cur_area; -extern str_number cur_ext; -extern pool_pointer area_delimiter; -extern pool_pointer ext_delimiter; - -extern char *pack_file_name(str_number n, str_number a, str_number e); - -# define file_name_size 512 - -# define format_area_length 0 /* length of its area part */ -# define format_ext_length 4 /* length of its `\.{.fmt}' part */ -# define format_extension ".fmt" - /* the extension, as a constant */ - -extern char *TEX_format_default; - -extern char *open_fmt_file(void); - -extern boolean name_in_progress; /* is a file name being scanned? */ -extern str_number job_name; /* principal file name */ -extern boolean log_opened_global; /* has the transcript file been opened? */ - -extern unsigned char *texmf_log_name; /* full name of the log file */ - -extern void open_log_file(void); -extern char *get_full_log_name (void); -extern void start_input(void); - -extern int open_outfile(FILE ** f, const char *name, const char *mode); - -extern boolean zopen_w_input(FILE **, const char *, int, - const_string fopen_mode); -extern boolean zopen_w_output(FILE **, const char *, const_string fopen_mode); -extern void zwclose(FILE *); - -# define read_tfm_file readbinfile -# define read_vf_file readbinfile -# define read_data_file readbinfile - -extern boolean openinnameok(const_string); -extern boolean openoutnameok(const_string); - -# ifdef WIN32 -extern FILE *Poptr; -# endif - -extern boolean open_in_or_pipe(FILE **, char *, int, const_string fopen_mode, - boolean must_exist); -extern boolean open_out_or_pipe(FILE **, char *, const_string fopen_mode); -extern void close_file_or_pipe(FILE *); - -extern char *luatex_synctex_get_current_name(void); - -#endif diff --git a/Build/source/texk/web2c/luatexdir/tex/texmath.c b/Build/source/texk/web2c/luatexdir/tex/texmath.c deleted file mode 100644 index 4d2bf80ecd6..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/texmath.c +++ /dev/null @@ -1,2727 +0,0 @@ -/* - -Copyright 2008-2010 Taco Hoekwater <taco@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under the terms -of the GNU General Public License as published by the Free Software Foundation; -either version 2 of the License, or (at your option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - -You should have received a copy of the GNU General Public License along with -LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" - -#define mode mode_par -#define tail tail_par -#define head head_par -#define dir_save dirs_par - -/*tex - - Concerning display skips, \TEX\ normally always inserts before and only after - when larger than zero. THis can ow be controlled with |\mathdisplayskipmode|: - - \starttabulate - \NC 0 \NC normal \TEX \NC \NR - \NC 1 \NC always \NC \NR - \NC 2 \NC non-zero \NC \NR - \NC 3 \NC ignore \NC \NR - \stoptabulate - -*/ - -#define back_error(A,B) do { \ - OK_to_interrupt=false; \ - back_input(); \ - OK_to_interrupt=true; \ - tex_error(A,B); \ - } while (0) - -int scan_math(pointer, int); -int scan_math_style(pointer, int); -pointer fin_mlist(pointer); - -/*tex - - When \TeX\ reads a formula that is enclosed between \.\$'s, it constructs an - {\sl mlist}, which is essentially a tree structure representing that formula. - An mlist is a linear sequence of items, but we can regard it as a tree - structure because mlists can appear within mlists. For example, many of the - entries can be subscripted or superscripted, and such ``scripts'' are mlists - in their own right. - - An entire formula is parsed into such a tree before any of the actual - typesetting is done, because the current style of type is usually not known - until the formula has been fully scanned. For example, when the formula - `\.{\$a+b \\over c+d\$}' is being read, there is no way to tell that - `\.{a+b}' will be in script size until `\.{\\over}' has appeared. - - During the scanning process, each element of the mlist being built is - classified as a relation, a binary operator, an open parenthesis, etc., or as - a construct like `\.{\\sqrt}' that must be built up. This classification - appears in the mlist data structure. - - After a formula has been fully scanned, the mlist is converted to an hlist so - that it can be incorporated into the surrounding text. This conversion is - controlled by a recursive procedure that decides all of the appropriate - styles by a ``top-down'' process starting at the outermost level and working - in towards the subformulas. The formula is ultimately pasted together using - combinations of horizontal and vertical boxes, with glue and penalty nodes - inserted as necessary. - - An mlist is represented internally as a linked list consisting chiefly of - ``noads'' (pronounced ``no-adds''), to distinguish them from the somewhat - similar ``nodes'' in hlists and vlists. Certain kinds of ordinary nodes are - allowed to appear in mlists together with the noads; \TeX\ tells the - difference by means of the |type| field, since a noad's |type| is always - greater than that of a node. An mlist does not contain character nodes, hlist - nodes, vlist nodes, math nodes or unset nodes; in particular, each mlist item - appears in the variable-size part of |mem|, so the |type| field is always - present. - - Each noad is five or more words long. The first word contains the |type| and - |subtype| and |link| fields that are already so familiar to us; the second - contains the attribute list pointer, and the third, fourth an fifth words are - called the noad's |nucleus|, |subscr|, and |supscr| fields. (This use of a - combined attribute list is temporary. Eventually, each of fields need their - own list) - - Consider, for example, the simple formula `\.{\$x\^2\$}', which would be - parsed into an mlist containing a single element called an |ord_noad|. The - |nucleus| of this noad is a representation of `\.x', the |subscr| is empty, - and the |supscr| is a representation of `\.2'. - - The |nucleus|, |subscr|, and |supscr| fields are further broken into - subfields. If |p| points to a noad, and if |q| is one of its principal fields - (e.g., |q=subscr(p)|), |q=null| indicates a field with no value (the - corresponding attribute of noad |p| is not present). Otherwise, there are - several possibilities for the subfields, depending on the |type| of |q|. - - \startitemize - - \startitem - |type(q)=math_char_node| means that |math_fam(q)| refers to one of - the sixteen font families, and |character(q)| is the number of a - character within a font of that family, as in a character node. - \stopitem - - \startitem - |type(q)=math_text_char_node| is similar, but the character is - unsubscripted and unsuperscripted and it is followed immediately by - another character from the same font. (This |type| setting appears - only briefly during the processing; it is used to suppress unwanted - italic corrections.) - \stopitem - - \startitem - |type(q)=sub_box_node| means that |math_list(q)| points to a box node - (either an |hlist_node| or a |vlist_node|) that should be used as the - value of the field. The |shift_amount| in the subsidiary box node is - the amount by which that box will be shifted downward. - \stopitem - - \startitem - |type(q)=sub_mlist_node| means that |math_list(q)| points to an - mlist; the mlist must be converted to an hlist in order to obtain the - value of this field. - \stopitem - - \startitem - In the latter case, we might have |math_list(q)=null|. This is not - the same as |q=null|; for example, `\.{\$P\_\{\}\$}' and `\.{\$P\$}' - produce different results (the former will not have the ``italic - correction'' added to the width of |P|, but the ``script skip'' will - be added). - \stopitem - - \startitemize - -*/ - -static void unsave_math(void) -{ - unsave(); - decr(save_ptr); - flush_node_list(text_dir_ptr); - assert(saved_type(0) == saved_textdir); - text_dir_ptr = saved_value(0); -} - -/*tex - - Sometimes it is necessary to destroy an mlist. The following subroutine - empties the current list, assuming that |abs(mode)=mmode|. - -*/ - -void flush_math(void) -{ - flush_node_list(vlink(head)); - flush_node_list(incompleat_noad_par); - vlink(head) = null; - tail = head; - incompleat_noad_par = null; -} - -/*tex Before we can do anything in math mode, we need fonts. */ - -#define MATHFONTSTACK 8 -#define MATHFONTDEFAULT 0 - -static sa_tree math_fam_head = NULL; - -int fam_fnt(int fam_id, int size_id) -{ - int n = fam_id + (256 * size_id); - return (int) get_sa_item(math_fam_head, n).int_value; -} - -void def_fam_fnt(int fam_id, int size_id, int f, int lvl) -{ - int n = fam_id + (256 * size_id); - sa_tree_item sa_value = { 0 }; - sa_value.int_value = f; - set_sa_item(math_fam_head, n, sa_value, lvl); - fixup_math_parameters(fam_id, size_id, f, lvl); - if (tracing_assigns_par > 1) { - begin_diagnostic(); - tprint("{assigning"); - print_char(' '); - print_cmd_chr(def_family_cmd, size_id); - print_int(fam_id); - print_char('='); - print_font_identifier(fam_fnt(fam_id, size_id)); - print_char('}'); - end_diagnostic(false); - } -} - -static void unsave_math_fam_data(int gl) -{ - sa_stack_item st; - if (math_fam_head->stack == NULL) - return; - while (math_fam_head->stack_ptr > 0 && - abs(math_fam_head->stack[math_fam_head->stack_ptr].level) - >= (int) gl) { - st = math_fam_head->stack[math_fam_head->stack_ptr]; - if (st.level > 0) { - rawset_sa_item(math_fam_head, st.code, st.value); - /*tex Now do a trace message, if requested. */ - if (tracing_restores_par > 1) { - int size_id = st.code / 256; - int fam_id = st.code % 256; - begin_diagnostic(); - tprint("{restoring"); - print_char(' '); - print_cmd_chr(def_family_cmd, size_id); - print_int(fam_id); - print_char('='); - print_font_identifier(fam_fnt(fam_id, size_id)); - print_char('}'); - end_diagnostic(false); - } - } - (math_fam_head->stack_ptr)--; - } -} - -/*tex Parameters */ - -#define MATHPARAMSTACK 8 -#define MATHPARAMDEFAULT undefined_math_parameter - -static sa_tree math_param_head = NULL; - -void def_math_param(int param_id, int style_id, scaled value, int lvl) -{ - int n = param_id + (256 * style_id); - sa_tree_item sa_value = { 0 }; - sa_value.int_value = (int) value; - set_sa_item(math_param_head, n, sa_value, lvl); - if (tracing_assigns_par > 1) { - begin_diagnostic(); - tprint("{assigning"); - print_char(' '); - print_cmd_chr(set_math_param_cmd, param_id); - print_cmd_chr(math_style_cmd, style_id); - print_char('='); - print_int(value); - print_char('}'); - end_diagnostic(false); - } -} - -scaled get_math_param(int param_id, int style_id) -{ - int n = param_id + (256 * style_id); - return (scaled) get_sa_item(math_param_head, n).int_value; -} - -static void unsave_math_param_data(int gl) -{ - sa_stack_item st; - if (math_param_head->stack == NULL) - return; - while (math_param_head->stack_ptr > 0 && - abs(math_param_head->stack[math_param_head->stack_ptr].level) - >= (int) gl) { - st = math_param_head->stack[math_param_head->stack_ptr]; - if (st.level > 0) { - rawset_sa_item(math_param_head, st.code, st.value); - /*tex Do a trace message, if requested. */ - if (tracing_restores_par > 1) { - int param_id = st.code % 256; - int style_id = st.code / 256; - begin_diagnostic(); - tprint("{restoring"); - print_char(' '); - print_cmd_chr(set_math_param_cmd, param_id); - print_cmd_chr(math_style_cmd, style_id); - print_char('='); - print_int(get_math_param(param_id, style_id)); - print_char('}'); - end_diagnostic(false); - } - } - (math_param_head->stack_ptr)--; - } -} - -/*tex Saving and unsaving of both: */ - -void unsave_math_data(int gl) -{ - unsave_math_fam_data(gl); - unsave_math_param_data(gl); -} - -/*tex Dumping and undumping: */ - -void dump_math_data(void) -{ - sa_tree_item sa_value = { 0 }; - if (math_fam_head == NULL) { - sa_value.int_value = MATHFONTDEFAULT; - math_fam_head = new_sa_tree(MATHFONTSTACK, 1, sa_value); - } - dump_sa_tree(math_fam_head, "mathfonts"); - if (math_param_head == NULL) { - sa_value.int_value = MATHPARAMDEFAULT; - math_param_head = new_sa_tree(MATHPARAMSTACK, 1, sa_value); - } - dump_sa_tree(math_param_head, "mathparameters"); -} - -void undump_math_data(void) -{ - math_fam_head = undump_sa_tree("mathfonts"); - math_param_head = undump_sa_tree("mathparameters"); -} - -void initialize_math(void) -{ - sa_tree_item sa_value = { 0 }; - if (math_fam_head == NULL) { - sa_value.int_value = MATHFONTDEFAULT; - math_fam_head = new_sa_tree(MATHFONTSTACK, 1, sa_value); - } - if (math_param_head == NULL) { - sa_value.int_value = MATHPARAMDEFAULT; - math_param_head = new_sa_tree(MATHPARAMSTACK, 1, sa_value); - initialize_math_spacing(); - } - return; -} - -/*tex - - Each portion of a formula is classified as Ord, Op, Bin, Rel, Ope, Clo, Pun, - or Inn, for purposes of spacing and line breaking. An |ord_noad|, |op_noad|, - |bin_noad|, |rel_noad|, |open_noad|, |close_noad|, |punct_noad|, or - |inner_noad| is used to represent portions of the various types. For example, - an `\.=' sign in a formula leads to the creation of a |rel_noad| whose - |nucleus| field is a representation of an equals sign (usually |fam=0|, - |character=075|). A formula preceded by \.{\\mathrel} also results in a - |rel_noad|. When a |rel_noad| is followed by an |op_noad|, say, and possibly - separated by one or more ordinary nodes (not noads), \TeX\ will insert a - penalty node (with the current |rel_penalty|) just after the formula that - corresponds to the |rel_noad|, unless there already was a penalty immediately - following; and a ``thick space'' will be inserted just before the formula - that corresponds to the |op_noad|. - - A noad of type |ord_noad|, |op_noad|, \dots, |inner_noad| usually has a - |subtype=normal|. The only exception is that an |op_noad| might have - |subtype=limits| or |no_limits|, if the normal positioning of limits has been - overridden for this operator. - - A |radical_noad| also has a |left_delimiter| field, which usually represents - a square root sign. - - A |fraction_noad| has a |right_delimiter| field as well as a - |left_delimiter|. - - Delimiter fields have four subfields called |small_fam|, |small_char|, - |large_fam|, |large_char|. These subfields represent variable-size delimiters - by giving the ``small'' and ``large'' starting characters, as explained in - Chapter~17 of {\sl The \TeX book}. - - A |fraction_noad| is actually quite different from all other noads. It has - |thickness|, |denominator|, and |numerator| fields instead of |nucleus|, - |subscr|, and |supscr|. The |thickness| is a scaled value that tells how - thick to make a fraction rule; however, the special value |default_code| is - used to stand for the |default_rule_thickness| of the current size. The - |numerator| and |denominator| point to mlists that define a fraction; we - always have $$\hbox{|type(numerator)=type(denominator)=sub_mlist|}.$$ The - |left_delimiter| and |right_delimiter| fields specify delimiters that will be - placed at the left and right of the fraction. In this way, a |fraction_noad| - is able to represent all of \TeX's operators \.{\\over}, \.{\\atop}, - \.{\\above}, \.{\\overwithdelims}, \.{\\atopwithdelims}, and - \.{\\abovewithdelims}. - - The |new_noad| function creates an |ord_noad| that is completely null - -*/ - -pointer new_noad(void) -{ - pointer p; - p = new_node(simple_noad, ord_noad_type); - /*tex All noad fields are zero after this. */ - return p; -} - -pointer new_sub_box(pointer curbox) -{ - pointer p, q; - p = new_noad(); - q = new_node(sub_box_node, 0); - nucleus(p) = q; - math_list(nucleus(p)) = curbox; - return p; -} - -/*tex - - A few more kinds of noads will complete the set: An |under_noad| has its - nucleus underlined; an |over_noad| has it overlined. An |accent_noad| places - an accent over its nucleus; the accent character appears as - |math_fam(accent_chr(p))| and |math_character(accent_chr(p))|. A - |vcenter_noad| centers its nucleus vertically with respect to the axis of the - formula; in such noads we always have |type(nucleus(p))=sub_box|. - - And finally, we have the |fence_noad| type, to implement \TeX's \.{\\left} - and \.{\\right} as well as eTeX's \.{\\middle}. The |nucleus| of such noads - is replaced by a |delimiter| field; thus, for example, `\.{\\left(}' produces - a |fence_noad| such that |delimiter(p)| holds the family and character codes - for all left parentheses. A |fence_noad| of subtype |left_noad_side| never - appears in an mlist except as the first element, and a |fence_noad| with - subtype |right_noad_side| never appears in an mlist except as the last - element; furthermore, we either have both a |left_noad_side| and a - |right_noad_side|, or neither one is present. - - Math formulas can also contain instructions like \.{\\textstyle} that - override \TeX's normal style rules. A |style_node| is inserted into the data - structure to record such instructions; it is three words long, so it is - considered a node instead of a noad. The |subtype| is either |display_style| - or |text_style| or |script_style| or |script_script_style|. The second and - third words of a |style_node| are not used, but they are present because a - |choice_node| is converted to a |style_node|. - - \TeX\ uses even numbers 0, 2, 4, 6 to encode the basic styles - |display_style|, \dots, |script_script_style|, and adds~1 to get the - ``cramped'' versions of these styles. This gives a numerical order that is - backwards from the convention of Appendix~G in {\sl The \TeX book\/}; i.e., a - smaller style has a larger numerical value. - -*/ - -const char *math_style_names[] = { - "display", "crampeddisplay", - "text", "crampedtext", - "script", "crampedscript", - "scriptscript", "crampedscriptscript", - NULL -}; - -const char *math_param_names[] = { - "quad", "axis", "operatorsize", - "overbarkern", "overbarrule", "overbarvgap", - "underbarkern", "underbarrule", "underbarvgap", - "radicalkern", "radicalrule", "radicalvgap", - "radicaldegreebefore", "radicaldegreeafter", "radicaldegreeraise", - "stackvgap", "stacknumup", "stackdenomdown", - "fractionrule", "fractionnumvgap", "fractionnumup", - "fractiondenomvgap", "fractiondenomdown", "fractiondelsize", - "skewedfractionhgap", "skewedfractionvgap", - "limitabovevgap", "limitabovebgap", "limitabovekern", - "limitbelowvgap", "limitbelowbgap", "limitbelowkern", - "nolimitsubfactor", "nolimitsupfactor", /* bonus */ - "underdelimitervgap", "underdelimiterbgap", - "overdelimitervgap", "overdelimiterbgap", - "subshiftdrop", "supshiftdrop", "subshiftdown", - "subsupshiftdown", "subtopmax", "supshiftup", - "supbottommin", "supsubbottommax", "subsupvgap", - "spaceafterscript", "connectoroverlapmin", - "ordordspacing", "ordopspacing", "ordbinspacing", "ordrelspacing", - "ordopenspacing", "ordclosespacing", "ordpunctspacing", "ordinnerspacing", - "opordspacing", "opopspacing", "opbinspacing", "oprelspacing", - "opopenspacing", "opclosespacing", "oppunctspacing", "opinnerspacing", - "binordspacing", "binopspacing", "binbinspacing", "binrelspacing", - "binopenspacing", "binclosespacing", "binpunctspacing", "bininnerspacing", - "relordspacing", "relopspacing", "relbinspacing", "relrelspacing", - "relopenspacing", "relclosespacing", "relpunctspacing", "relinnerspacing", - "openordspacing", "openopspacing", "openbinspacing", "openrelspacing", - "openopenspacing", "openclosespacing", "openpunctspacing", - "openinnerspacing", - "closeordspacing", "closeopspacing", "closebinspacing", "closerelspacing", - "closeopenspacing", "closeclosespacing", "closepunctspacing", - "closeinnerspacing", - "punctordspacing", "punctopspacing", "punctbinspacing", "punctrelspacing", - "punctopenspacing", "punctclosespacing", "punctpunctspacing", - "punctinnerspacing", - "innerordspacing", "inneropspacing", "innerbinspacing", "innerrelspacing", - "inneropenspacing", "innerclosespacing", "innerpunctspacing", - "innerinnerspacing", - NULL -}; - -pointer new_style(small_number s) -{ - m_style = s; - return new_node(style_node, s); -} - -/*tex - - Finally, the \.{\\mathchoice} primitive creates a |choice_node|, which has - special subfields |display_mlist|, |text_mlist|, |script_mlist|, and - |script_script_mlist| pointing to the mlists for each style. - -*/ - -static pointer new_choice(void) -{ - return new_node(choice_node, 0); -} - -/*tex - - Let's consider now the previously unwritten part of |show_node_list| that - displays the things that can only be present in mlists; this program - illustrates how to access the data structures just defined. - - In the context of the following program, |p| points to a node or noad that - should be displayed, and the current string contains the ``recursion - history'' that leads to this point. The recursion history consists of a dot - for each outer level in which |p| is subsidiary to some node, or in which |p| - is subsidiary to the |nucleus| field of some noad; the dot is replaced by - `\.\_' or `\.\^' or `\./' or `\.\\' if |p| is descended from the |subscr| or - |supscr| or |denominator| or |numerator| fields of noads. For example, the - current string would be `\.{.\^.\_/}' if |p| points to the |ord_noad| for |x| - in the (ridiculous) formula `\.{\$\\sqrt\{a\^\{\\mathinner\{b\_\{c\\over - x+y\}\}\}\}\$}'. - -*/ - -void display_normal_noad(pointer p); -void display_fence_noad(pointer p); -void display_fraction_noad(pointer p); - -void show_math_node(pointer p) -{ - switch (type(p)) { - case style_node: - print_cmd_chr(math_style_cmd, subtype(p)); - break; - case choice_node: - tprint_esc("mathchoice"); - append_char('D'); - show_node_list(display_mlist(p)); - flush_char(); - append_char('T'); - show_node_list(text_mlist(p)); - flush_char(); - append_char('S'); - show_node_list(script_mlist(p)); - flush_char(); - append_char('s'); - show_node_list(script_script_mlist(p)); - flush_char(); - break; - case simple_noad: - case radical_noad: - case accent_noad: - display_normal_noad(p); - break; - case fence_noad: - display_fence_noad(p); - break; - case fraction_noad: - display_fraction_noad(p); - break; - default: - tprint("Unknown node type!"); - break; - } -} - -/*tex Here are some simple routines used in the display of noads. */ - -static void print_fam_and_char(pointer p) -{ - tprint_esc("fam"); - print_int(math_fam(p)); - print_char(' '); - print(math_character(p)); -} - -static void print_delimiter(pointer p) -{ - int a; - if (delimiteroptionset(p)) { - tprint(" [ "); - if (delimiteraxis(p)) - tprint("axis "); - if (delimiternoaxis(p)) - tprint("noaxis "); - if (delimiterexact(p)) - tprint("exact "); - tprint("]"); - } - if (delimiterheight(p)) { - tprint("height="); - print_scaled(delimiterheight(p)); - tprint(" "); - } - if (delimiterdepth(p)) { - tprint("depth="); - print_scaled(delimiterdepth(p)); - tprint(" "); - } - if (delimiterclass(p)) { - tprint("class="); - print_int(delimiterclass(p)); - tprint(" "); - } - if (small_fam(p) < 0) { - /*tex This should never happen. */ - print_int(-1); - } else if (small_fam(p) < 16 && large_fam(p) < 16 && small_char(p) < 256 && large_char(p) < 256) { - /*tex Traditional tex style. */ - a = small_fam(p) * 256 + small_char(p); - a = a * 0x1000 + large_fam(p) * 256 + large_char(p); - print_qhex(a); - } else if ((large_fam(p) == 0 && large_char(p) == 0) || small_char(p) > 65535 || large_char(p) > 65535) { - /*tex \LUATEX\ style. */ - print_qhex(small_fam(p)); - print_qhex(small_char(p)); - } -} - -/*tex - - The next subroutine will descend to another level of recursion when a - subsidiary mlist needs to be displayed. The parameter |c| indicates what - character is to become part of the recursion history. An empty mlist is - distinguished from a missing field, because these are not equivalent (as - explained above). - -*/ - -static void print_subsidiary_data(pointer p, ASCII_code c) -{ - if ((int) cur_length >= depth_threshold) { - if (p != null) - tprint(" []"); - } else { - /*tex Include |c| in the recursion history. */ - append_char(c); - if (p != null) { - switch (type(p)) { - case math_char_node: - print_ln(); - print_current_string(); - print_fam_and_char(p); - break; - case sub_box_node: - show_node_list(math_list(p)); - break; - case sub_mlist_node: - if (math_list(p) == null) { - print_ln(); - print_current_string(); - tprint("{}"); - } else { - show_node_list(math_list(p)); - } - break; - } - } - /*tex Remove |c| from the recursion history. */ - flush_char(); - } -} - -void display_normal_noad(pointer p) -{ - switch (type(p)) { - case simple_noad: - switch (subtype(p)) { - case ord_noad_type: - tprint_esc("mathord"); - break; - case op_noad_type_normal: - case op_noad_type_limits: - case op_noad_type_no_limits: - tprint_esc("mathop"); - if (subtype(p) == op_noad_type_limits) - tprint_esc("limits"); - else if (subtype(p) == op_noad_type_no_limits) - tprint_esc("nolimits"); - break; - case bin_noad_type: - tprint_esc("mathbin"); - break; - case rel_noad_type: - tprint_esc("mathrel"); - break; - case open_noad_type: - tprint_esc("mathopen"); - break; - case close_noad_type: - tprint_esc("mathclose"); - break; - case punct_noad_type: - tprint_esc("mathpunct"); - break; - case inner_noad_type: - tprint_esc("mathinner"); - break; - case over_noad_type: - tprint_esc("overline"); - break; - case under_noad_type: - tprint_esc("underline"); - break; - case vcenter_noad_type: - tprint_esc("vcenter"); - break; - default: - tprint("<unknown noad type!>"); - break; - } - break; - case radical_noad: - if (subtype(p) == 7) - tprint_esc("Uhextensible"); - else if (subtype(p) == 6) - tprint_esc("Udelimiterover"); - else if (subtype(p) == 5) - tprint_esc("Udelimiterunder"); - else if (subtype(p) == 4) - tprint_esc("Uoverdelimiter"); - else if (subtype(p) == 3) - tprint_esc("Uunderdelimiter"); - else if (subtype(p) == 2) - tprint_esc("Uroot"); - else - tprint_esc("radical"); - print_delimiter(left_delimiter(p)); - if (degree(p) != null) { - print_subsidiary_data(degree(p), '/'); - } - if (radicalwidth(p)) { - tprint("width="); - print_scaled(radicalwidth(p)); - tprint(" "); - } - if (radicaloptionset(p)) { - tprint(" [ "); - if (radicalexact(p)) - tprint("exact "); - if (radicalleft(p)) - tprint("left "); - if (radicalmiddle(p)) - tprint("middle "); - if (radicalright(p)) - tprint("right "); - tprint("]"); - } - break; - case accent_noad: - if (top_accent_chr(p) != null) { - if (bot_accent_chr(p) != null) { - tprint_esc("Umathaccent both"); - } else { - tprint_esc("Umathaccent"); - } - } else if (bot_accent_chr(p) != null) { - tprint_esc("Umathaccent bottom"); - } else { - tprint_esc("Umathaccent overlay"); - } - if (accentfraction(p)) { - tprint(" fraction="); - print_int(accentfraction(p)); - tprint(" "); - } - switch (subtype(p)) { - case 0: - if (top_accent_chr(p) != null) { - if (bot_accent_chr(p) != null) { - print_fam_and_char(top_accent_chr(p)); - print_fam_and_char(bot_accent_chr(p)); - } else { - print_fam_and_char(top_accent_chr(p)); - } - } else if (bot_accent_chr(p) != null) { - print_fam_and_char(bot_accent_chr(p)); - } else { - print_fam_and_char(overlay_accent_chr(p)); - } - break; - case 1: - if (top_accent_chr(p) != null) { - tprint(" fixed "); - print_fam_and_char(top_accent_chr(p)); - if (bot_accent_chr(p) != null) { - print_fam_and_char(bot_accent_chr(p)); - } - } else { - confusion("display_accent_noad"); - } - break; - case 2: - if (bot_accent_chr(p) != null) { - if (top_accent_chr(p) != null) { - print_fam_and_char(top_accent_chr(p)); - } - tprint(" fixed "); - print_fam_and_char(bot_accent_chr(p)); - } else{ - confusion("display_accent_noad"); - } - break; - case 3: - if (top_accent_chr(p) != null && bot_accent_chr(p) != null) { - tprint(" fixed "); - print_fam_and_char(top_accent_chr(p)); - tprint(" fixed "); - print_fam_and_char(bot_accent_chr(p)); - } else { - confusion("display_accent_noad"); - } - break; - } - break; - } - print_subsidiary_data(nucleus(p), '.'); - print_subsidiary_data(supscr(p), '^'); - print_subsidiary_data(subscr(p), '_'); -} - -void display_fence_noad(pointer p) -{ - if (subtype(p) == right_noad_side) - tprint_esc("right"); - else if (subtype(p) == left_noad_side) - tprint_esc("left"); - else - tprint_esc("middle"); - print_delimiter(delimiter(p)); -} - -void display_fraction_noad(pointer p) -{ - tprint_esc("fraction, thickness "); - if (thickness(p) == default_code) - tprint("= default"); - else - print_scaled(thickness(p)); - if ((left_delimiter(p) != null) && - ((small_fam(left_delimiter(p)) != 0) || (small_char(left_delimiter(p)) != 0) || - (large_fam(left_delimiter(p)) != 0) || (large_char(left_delimiter(p)) != 0))) { - tprint(", left-delimiter "); - print_delimiter(left_delimiter(p)); - } - if ((right_delimiter(p) != null) && - ((small_fam(right_delimiter(p)) != 0) || (small_char(right_delimiter(p)) != 0) || - (large_fam(right_delimiter(p)) != 0) || (large_char(right_delimiter(p)) != 0))) { - tprint(", right-delimiter "); - print_delimiter(right_delimiter(p)); - } - print_subsidiary_data(numerator(p), '\\'); - print_subsidiary_data(denominator(p), '/'); -} - -/*tex - - The routines that \TeX\ uses to create mlists are similar to those we have - just seen for the generation of hlists and vlists. But it is necessary to - make ``noads'' as well as nodes, so the reader should review the discussion - of math mode data structures before trying to make sense out of the following - program. - - Here is a little routine that needs to be done whenever a subformula is about - to be processed. The parameter is a code like |math_group|. - -*/ - -static void new_save_level_math(group_code c) -{ - set_saved_record(0, saved_textdir, 0, text_dir_ptr); - text_dir_ptr = new_dir(math_direction_par); - incr(save_ptr); - new_save_level(c); - eq_word_define(int_base + body_direction_code, math_direction_par); - eq_word_define(int_base + par_direction_code, math_direction_par); - eq_word_define(int_base + text_direction_code, math_direction_par); -} - -static void push_math(group_code c, int mstyle) -{ - if (math_direction_par != text_direction_par) - dir_math_save = true; - push_nest(); - mode = -mmode; - incompleat_noad_par = null; - m_style = mstyle; - new_save_level_math(c); -} - -static void enter_ordinary_math(void) -{ - push_math(math_shift_group, text_style); - eq_word_define(int_base + cur_fam_code, -1); - if (every_math_par != null) - begin_token_list(every_math_par, every_math_text); -} - -void enter_display_math(void); - -/*tex - - We get into math mode from horizontal mode when a `\.\$' (i.e., a - |math_shift| character) is scanned. We must check to see whether this `\.\$' - is immediately followed by another, in case display math mode is called for. - -*/ - -void init_math(void) -{ - if (cur_cmd == math_shift_cmd) { - /*tex |get_x_token| would fail on \.{\\ifmmode}\thinspace! */ - get_token(); - if ((cur_cmd == math_shift_cmd) && (mode > 0)) { - enter_display_math(); - } else { - back_input(); - enter_ordinary_math(); - } - } else if (cur_cmd == math_shift_cs_cmd && cur_chr == display_style && (mode > 0)) { - enter_display_math(); - } else if (cur_cmd == math_shift_cs_cmd && cur_chr == text_style) { - enter_ordinary_math(); - } else { - you_cant(); - } -} - -/*tex - - We get into ordinary math mode from display math mode when `\.{\\eqno}' or - `\.{\\leqno}' appears. In such cases |cur_chr| will be 0 or~1, respectively; - the value of |cur_chr| is placed onto |save_stack| for safe keeping. - - When \TeX\ is in display math mode, |cur_group=math_shift_group|, so it is - not necessary for the |start_eq_no| procedure to test for this condition. - -*/ - -void start_eq_no(void) -{ - set_saved_record(0, saved_eqno, 0, cur_chr); - incr(save_ptr); - enter_ordinary_math(); -} - -/*tex - - Subformulas of math formulas cause a new level of math mode to be entered, on - the semantic nest as well as the save stack. These subformulas arise in - several ways: (1)~A left brace by itself indicates the beginning of a - subformula that will be put into a box, thereby freezing its glue and - preventing line breaks. (2)~A subscript or superscript is treated as a - subformula if it is not a single character; the same applies to the nucleus - of things like \.{\\underline}. (3)~The \.{\\left} primitive initiates a - subformula that will be terminated by a matching \.{\\right}. The group codes - placed on |save_stack| in these three cases are |math_group|, |math_group|, - and |math_left_group|, respectively. - - Here is the code that handles case (1); the other cases are not quite as - trivial, so we shall consider them later. - -*/ - -void math_left_brace(void) -{ - pointer q; - tail_append(new_noad()); - q = new_node(math_char_node, 0); - nucleus(tail) = q; - back_input(); - (void) scan_math(nucleus(tail), m_style); -} - -/*tex - - If the inline directions of \.{\\pardir} and \.{\\mathdir} are opposite, then - this function will return true. Discovering that fact is somewhat odd because - it needs traversal of the |save_stack|. The occurance of displayed equations - is weird enough that this is probably still better than having yet another - field in the |input_stack| structures. - - None of this makes much sense if the inline direction of either one of - \.{\\pardir} or \.{\\mathdir} is vertical, but in that case the current math - machinery is ill suited anyway so I do not bother to test that. - -*/ - -static boolean math_and_text_reversed_p(void) -{ - int i = save_ptr - 1; - while (save_type(i) != level_boundary) - i--; - while (i < save_ptr) { - if (save_type(i) == restore_old_value && - save_value(i) == int_base + par_direction_code) { - if (textdir_opposite(math_direction_par, save_value(i - 1))) - return true; - } - i++; - } - return false; -} - -/*tex - - When we enter display math mode, we need to call |line_break| to process the - partial paragraph that has just been interrupted by the display. Then we can - set the proper values of |display_width| and |display_indent| and - |pre_display_size|. - -*/ - -void enter_display_math(void) -{ - /*tex new or partial |pre_display_size| */ - scaled w; - /*tex new |display_width| */ - scaled l; - /*tex new |display_indent| */ - scaled s; - pointer p; - /*tex scope of paragraph shape specification */ - int n; - /*tex - - `\.{\\noindent\$\$}' or `\.{\$\${ }\$\$}' or the 2nd of \.{\$\${ }\$\$} - \.{\$\${ }\$\$} - - */ - if (head == tail || - (vlink(head) == tail && - type(tail) == local_par_node && vlink(tail) == null)) { - if (vlink(head) == tail) { - /*tex - - |resume_after_display| inserts a |local_par_node|, but if there - is another display immediately following, we have to get rid of - that node. - - */ - flush_node(tail); - } - pop_nest(); - w = -max_dimen; - } else { - line_break(true, math_shift_group); - w = actual_box_width(just_box, x_over_n(quad(get_cur_font()),1000) * math_pre_display_gap_factor_par); - } - /*tex - - Now we are in vertical mode, working on the list that will contain the - display. A displayed equation is considered to be three lines long, so we - calculate the length and offset of line number |prev_graf+2|. - - */ - if (par_shape_par_ptr == null) { - if ((hang_indent_par != 0) && (((hang_after_par >= 0) && (prev_graf_par + 2 > hang_after_par)) || (prev_graf_par + 1 < -hang_after_par))) { - halfword used_hang_indent = swap_hang_indent(hang_indent_par); - l = hsize_par - abs(used_hang_indent); - if (used_hang_indent > 0) - s = used_hang_indent; - else - s = 0; - } else { - l = hsize_par; - s = 0; - } - } else { - n = vinfo(par_shape_par_ptr + 1); - if (prev_graf_par + 2 >= n) - p = par_shape_par_ptr + 2 * n + 1; - else - p = par_shape_par_ptr + 2 * (prev_graf_par + 2) + 1; - s = varmem[(p - 1)].cint; - l = varmem[p].cint; - s = swap_parshape_indent(s,l); - } - push_math(math_shift_group, display_style); - mode = mmode; - eq_word_define(int_base + cur_fam_code, -1); - eq_word_define(dimen_base + pre_display_size_code, w); - eq_word_define(dimen_base + display_width_code, l); - eq_word_define(dimen_base + display_indent_code, s); - eq_word_define(int_base + pre_display_direction_code, (math_and_text_reversed_p() ? -1 : 0)); - if (every_display_par != null) - begin_token_list(every_display_par, every_display_text); - if (nest_ptr == 1) { - checked_page_filter(before_display); - build_page(); - } -} - -/*tex - - The next routine parses all variations of a delimiter code. The |extcode| - tells what syntax form to use (\TeX, XeTeX, XeTeXnum, ...) , the |doclass| - tells whether or not read a math class also (for \.{\\delimiter} c.s.). (the - class is passed on for conversion to \.{\\mathchar}). - -*/ - -static delcodeval do_scan_extdef_del_code(int extcode, boolean doclass) -{ - const char *hlp[] = { - "I'm going to use 0 instead of that illegal code value.", - NULL - }; - delcodeval d; - int mcls = 0, msfam = 0, mschr = 0, mlfam = 0, mlchr = 0; - if (extcode == tex_mathcode) { - /*tex - - \.{\\delcode}, this is the easiest - - */ - scan_int(); - /*tex "MFCCFCC or "FCCFCC */ - if (doclass) { - mcls = (cur_val / 0x1000000); - cur_val = (cur_val & 0xFFFFFF); - } - if (cur_val > 0xFFFFFF) { - tex_error("Invalid delimiter code", hlp); - cur_val = 0; - } - msfam = (cur_val / 0x100000); - mschr = (cur_val % 0x100000) / 0x1000; - mlfam = (cur_val & 0xFFF) / 0x100; - mlchr = (cur_val % 0x100); - } else if (extcode == umath_mathcode) { - /*tex - - \.{\\Udelcode}: <0-7>,<0-0xFF>,<0-0x10FFFF> or <0-0xFF>,<0-0x10FFFF> - - */ - if (doclass) { - scan_int(); - mcls = cur_val; - } - scan_int(); - msfam = cur_val; - scan_char_num(); - mschr = cur_val; - if (msfam < 0 || msfam > 255) { - tex_error("Invalid delimiter code", hlp); - msfam = 0; - mschr = 0; - } - mlfam = 0; - mlchr = 0; - } else if (extcode == umathnum_mathcode) { - /*tex - - \.{\\Udelcodenum}:"FF<21bits>; the largest numeric value is $2^29-1$, - but the top of bit 21 can't be used as it contains invalid USV's. - - */ - if (doclass) { /* such a primitive doesn't exist */ - confusion("umathnum_mathcode"); - } - scan_int(); - msfam = (cur_val / 0x200000); - mschr = cur_val & 0x1FFFFF; - if (msfam < 0 || msfam > 255 || mschr > 0x10FFFF) { - tex_error("Invalid delimiter code", hlp); - msfam = 0; - mschr = 0; - } - mlfam = 0; - mlchr = 0; - } else { - /*tex Something's gone wrong! */ - confusion("unknown_extcode"); - } - d.class_value = mcls; - d.small_family_value = msfam; - d.small_character_value = mschr; - d.large_family_value = mlfam; - d.large_character_value = mlchr; - return d; -} - -void scan_extdef_del_code(int level, int extcode) -{ - delcodeval d; - int p; - scan_char_num(); - p = cur_val; - scan_optional_equals(); - d = do_scan_extdef_del_code(extcode, false); - set_del_code(p, d.small_family_value, d.small_character_value, - d.large_family_value, d.large_character_value, (quarterword) (level)); -} - -mathcodeval scan_mathchar(int extcode) -{ - char errstr[255] = { 0 }; - const char *hlp[] = { - "I'm going to use 0 instead of that illegal code value.", - NULL - }; - mathcodeval d; - int mcls = 0, mfam = 0, mchr = 0; - if (extcode == tex_mathcode) { - /*tex \.{\\mathcode}: "TFCC */ - scan_int(); - if (cur_val > 0x8000) { - /*tex Needed for latex: fallback to umathnum_mathcode. */ - mfam = (cur_val / 0x200000) & 0x7FF; - mcls = mfam % 0x08; - mfam = mfam / 0x08; - mchr = cur_val & 0x1FFFFF; - if (mchr > 0x10FFFF) { - tex_error("Invalid math code during > 0x8000 mathcode fallback", hlp); - mcls = 0; - mfam = 0; - mchr = 0; - } - } else { - if (cur_val < 0) { - snprintf(errstr, 255, "Bad mathchar (%d)", (int)cur_val); - tex_error(errstr, hlp); - cur_val = 0; - } - mcls = (cur_val / 0x1000); - mfam = ((cur_val % 0x1000) / 0x100); - mchr = (cur_val % 0x100); - } - } else if (extcode == umath_mathcode) { - /*tex <0-0x7> <0-0xFF> <0-0x10FFFF> */ - scan_int(); - mcls = cur_val; - scan_int(); - mfam = cur_val; - scan_char_num(); - mchr = cur_val; - if (mcls < 0 || mcls > 7 || mfam > 255) { - tex_error("Invalid math code", hlp); - mchr = 0; - mfam = 0; - mcls = 0; - } - } else if (extcode == umathnum_mathcode) { - /*tex - - "FFT<21bits>: the largest numeric value is $2^32-1$, but the top of - bit 21 can't be used as it contains invalid USV's - - Note: |scan_int| won't accept families 128-255 because these use bit 32 - - */ - scan_int(); - mfam = (cur_val / 0x200000) & 0x7FF; - mcls = mfam % 0x08; - mfam = mfam / 0x08; - mchr = cur_val & 0x1FFFFF; - if (mchr > 0x10FFFF) { - tex_error("Invalid math code", hlp); - mcls = 0; - mfam = 0; - mchr = 0; - } - } else { - /*tex Something's gone wrong. */ - confusion("unknown_extcode"); - } - d.class_value = mcls; - d.family_value = mfam; - d.character_value = mchr; - return d; -} - -void scan_extdef_math_code(int level, int extcode) -{ - mathcodeval d; - int p; - scan_char_num(); - p = cur_val; - scan_optional_equals(); - d = scan_mathchar(extcode); - set_math_code(p, d.class_value, d.family_value, d.character_value, (quarterword) (level)); -} - -/*tex This reads in a delcode when actually a mathcode is needed. */ - -mathcodeval scan_delimiter_as_mathchar(int extcode) -{ - delcodeval dval; - mathcodeval mval; - dval = do_scan_extdef_del_code(extcode, true); - mval.class_value = dval.class_value; - mval.family_value = dval.small_family_value; - mval.character_value = dval.small_character_value; - return mval; -} - -/*tex - - Recall that the |nucleus|, |subscr|, and |supscr| fields in a noad are broken - down into subfields called |type| and either |math_list| or - |(math_fam,math_character)|. The job of |scan_math| is to figure out what to - place in one of these principal fields; it looks at the subformula that comes - next in the input, and places an encoding of that subformula into a given - word of |mem|. - -*/ - -#define get_next_nb_nr() do { get_x_token(); } while (cur_cmd==spacer_cmd||cur_cmd==relax_cmd) - -int scan_math_style(pointer p, int mstyle) -{ - get_next_nb_nr(); - back_input(); - scan_left_brace(); - set_saved_record(0, saved_math, 0, p); - incr(save_ptr); - push_math(math_group, mstyle); - return 1; -} - -int scan_math(pointer p, int mstyle) -{ - mathcodeval mval = { 0, 0, 0 }; - assert(p != null); - RESTART: - get_next_nb_nr(); - RESWITCH: - switch (cur_cmd) { - case letter_cmd: - case other_char_cmd: - case char_given_cmd: - mval = get_math_code(cur_chr); - if (mval.class_value == 8) { - /*tex An active character that is an |outer_call| is allowed here. */ - cur_cs = active_to_cs(cur_chr, true); - cur_cmd = eq_type(cur_cs); - cur_chr = equiv(cur_cs); - x_token(); - back_input(); - goto RESTART; - } - break; - case char_num_cmd: - scan_char_num(); - cur_chr = cur_val; - cur_cmd = char_given_cmd; - goto RESWITCH; - break; - case math_char_num_cmd: - if (cur_chr == 0) - mval = scan_mathchar(tex_mathcode); - else if (cur_chr == 1) - mval = scan_mathchar(umath_mathcode); - else if (cur_chr == 2) - mval = scan_mathchar(umathnum_mathcode); - else - confusion("scan_math"); - break; - case math_given_cmd: - mval = mathchar_from_integer(cur_chr, tex_mathcode); - break; - case xmath_given_cmd: - mval = mathchar_from_integer(cur_chr, umath_mathcode); - break; - case delim_num_cmd: - if (cur_chr == 0) - mval = scan_delimiter_as_mathchar(tex_mathcode); - else if (cur_chr == 1) - mval = scan_delimiter_as_mathchar(umath_mathcode); - else - confusion("scan_math"); - break; - default: - /*tex - - The pointer |p| is placed on |save_stack| while a complex subformula - is being scanned. - - */ - back_input(); - scan_left_brace(); - set_saved_record(0, saved_math, 0, p); - incr(save_ptr); - push_math(math_group, mstyle); - return 1; - } - type(p) = math_char_node; - math_character(p) = mval.character_value; - if ((mval.class_value == math_use_current_family_code) && cur_fam_par_in_range) - math_fam(p) = cur_fam_par; - else - math_fam(p) = mval.family_value; - return 0; -} - -/*tex - - The |set_math_char| procedure creates a new noad appropriate to a given math - code, and appends it to the current mlist. However, if the math code is - sufficiently large, the |cur_chr| is treated as an active character and - nothing is appended. - -*/ - -#define math_class_to_type(target,source) \ - switch (source) { \ - case 0: target = ord_noad_type; break; \ - case 1: target = op_noad_type_normal; break; \ - case 2: target = bin_noad_type; break; \ - case 3: target = rel_noad_type; break; \ - case 4: target = open_noad_type; break; \ - case 5: target = close_noad_type; break; \ - case 6: target = punct_noad_type; break; \ - } - -void set_math_char(mathcodeval mval) -{ - pointer p; - if (mval.class_value == 8) { - /*tex An active character that is an |outer_call| is allowed here */ - cur_cs = active_to_cs(cur_chr, true); - cur_cmd = eq_type(cur_cs); - cur_chr = equiv(cur_cs); - x_token(); - back_input(); - } else { - pointer q; - p = new_noad(); - q = new_node(math_char_node, 0); - nucleus(p) = q; - math_character(nucleus(p)) = mval.character_value; - math_fam(nucleus(p)) = mval.family_value; - if (mval.class_value == math_use_current_family_code) { - if (cur_fam_par_in_range) - math_fam(nucleus(p)) = cur_fam_par; - subtype(p) = ord_noad_type; - } else { - math_class_to_type(subtype(p),mval.class_value); - } - tail_append(p); - } -} - -/*tex - - The |math_char_in_text| procedure creates a new node representing a math char - in text code, and appends it to the current list. However, if the math code - is sufficiently large, the |cur_chr| is treated as an active character and - nothing is appended. - -*/ - -void math_char_in_text(mathcodeval mval) -{ - pointer p; - if (mval.class_value == 8) { - /*tex An active character that is an |outer_call| is allowed here */ - cur_cs = active_to_cs(cur_chr, true); - cur_cmd = eq_type(cur_cs); - cur_chr = equiv(cur_cs); - x_token(); - back_input(); - } else { - p = new_char(fam_fnt(mval.family_value, text_size), mval.character_value); - tail_append(p); - } -} - -void math_math_comp(void) -{ - pointer q; - tail_append(new_noad()); - subtype(tail) = (quarterword) cur_chr; - q = new_node(math_char_node, 0); - nucleus(tail) = q; - if (cur_chr == over_noad_type) - (void) scan_math(nucleus(tail), cramped_style(m_style)); - else - (void) scan_math(nucleus(tail), m_style); -} - -void math_limit_switch(void) -{ - const char *hlp[] = { - "I'm ignoring this misplaced \\limits or \\nolimits command.", - NULL - }; - if (head != tail) { - if (type(tail) == simple_noad && - (subtype(tail) == op_noad_type_normal || - subtype(tail) == op_noad_type_limits || - subtype(tail) == op_noad_type_no_limits)) { - subtype(tail) = (quarterword) cur_chr; - return; - } - } - tex_error("Limit controls must follow a math operator", hlp); -} - -/*tex - - Delimiter fields of noads are filled in by the |scan_delimiter| routine. The - first parameter of this procedure is the |mem| address where the delimiter - is to be placed; the second tells if this delimiter follows \.{\\radical} or - not. - -*/ - -static void scan_delimiter(pointer p, int r) -{ - delcodeval dval = { 0, 0, 0, 0, 0 }; - if (r == tex_mathcode) { - /*tex \.{\\radical} */ - dval = do_scan_extdef_del_code(tex_mathcode, true); - } else if (r == umath_mathcode) { - /*tex \.{\\Uradical} */ - dval = do_scan_extdef_del_code(umath_mathcode, false); - } else if (r == no_mathcode) { - get_next_nb_nr(); - switch (cur_cmd) { - case letter_cmd: - case other_char_cmd: - dval = get_del_code(cur_chr); - break; - case delim_num_cmd: - if (cur_chr == 0) { - /*tex \.{\\delimiter} */ - dval = do_scan_extdef_del_code(tex_mathcode, true); - } else if (cur_chr == 1) { - /*tex \.{\\Udelimiter} */ - dval = do_scan_extdef_del_code(umath_mathcode, true); - } else { - confusion("scan_delimiter1"); - } - break; - default: - dval.small_family_value = -1; - break; - } - } else { - confusion("scan_delimiter2"); - } - if (p == null) - return; - if (dval.small_family_value < 0) { - const char *hlp[] = { - "I was expecting to see something like `(' or `\\{' or", - "`\\}' here. If you typed, e.g., `{' instead of `\\{', you", - "should probably delete the `{' by typing `1' now, so that", - "braces don't get unbalanced. Otherwise just proceed", - "Acceptable delimiters are characters whose \\delcode is", - "nonnegative, or you can use `\\delimiter <delimiter code>'.", - NULL - }; - back_error("Missing delimiter (. inserted)", hlp); - small_fam(p) = 0; - small_char(p) = 0; - large_fam(p) = 0; - large_char(p) = 0; - } else { - small_fam(p) = dval.small_family_value; - small_char(p) = dval.small_character_value; - large_fam(p) = dval.large_family_value; - large_char(p) = dval.large_character_value; - } - return; -} - -void math_radical(void) -{ - halfword q; - int chr_code = cur_chr; - halfword options = 0; - tail_append(new_node(radical_noad, chr_code)); - q = new_node(delim_node, 0); - left_delimiter(tail) = q; - while (1) { - if (scan_keyword("width")) { - scan_dimen(false,false,false); - radicalwidth(tail) = cur_val ; - } else if (scan_keyword("left")) { - options = options | noad_option_left ; - } else if (scan_keyword("middle")) { - options = options | noad_option_middle ; - } else if (scan_keyword("right")) { - options = options | noad_option_right ; - } else { - break; - } - } - radicaloptions(tail) = options; - if (chr_code == 0) - /*tex \.{\\radical} */ - scan_delimiter(left_delimiter(tail), tex_mathcode); - else if (chr_code == 1) - /*tex \.{\\Uradical} */ - scan_delimiter(left_delimiter(tail), umath_mathcode); - else if (chr_code == 2) - /*tex \.{\\Uroot} */ - scan_delimiter(left_delimiter(tail), umath_mathcode); - else if (chr_code == 3) - /*tex \.{\\Uunderdelimiter} */ - scan_delimiter(left_delimiter(tail), umath_mathcode); - else if (chr_code == 4) - /*tex \.{\\Uoverdelimiter} */ - scan_delimiter(left_delimiter(tail), umath_mathcode); - else if (chr_code == 5) - /*tex \.{\\Udelimiterunder} */ - scan_delimiter(left_delimiter(tail), umath_mathcode); - else if (chr_code == 6) - /*tex \.{\\Udelimiterover} */ - scan_delimiter(left_delimiter(tail), umath_mathcode); - else if (chr_code == 7) - /*tex \.{\\Uhextensible} */ - scan_delimiter(left_delimiter(tail), umath_mathcode); - else - confusion("math_radical"); - if (chr_code == 7) { - /*tex type will change */ - q = new_node(sub_box_node, 0); - nucleus(tail) = q; - return; - } else if (chr_code == 2) { - /*tex - - The trick with the |vlink(q)| is used by |scan_math| to decide - whether it needs to go on. - - */ - q = new_node(math_char_node, 0); - vlink(q) = tail; - degree(tail) = q; - if (!scan_math(degree(tail), sup_sup_style(m_style))) { - vlink(degree(tail)) = null; - q = new_node(math_char_node, 0); - nucleus(tail) = q; - (void) scan_math(nucleus(tail), cramped_style(m_style)); - } - } else { - q = new_node(math_char_node, 0); - nucleus(tail) = q; - (void) scan_math(nucleus(tail), cramped_style(m_style)); - } -} - -void math_ac(void) -{ - halfword q; - mathcodeval t = { 0, 0, 0 }; - mathcodeval b = { 0, 0, 0 }; - mathcodeval o = { 0, 0, 0 }; - if (cur_cmd == accent_cmd) { - const char *hlp[] = { - "I'm changing \\accent to \\mathaccent here; wish me luck.", - "(Accents are not the same in formulas as they are in text.)", - NULL - }; - tex_error("Please use \\mathaccent for accents in math mode", hlp); - } - tail_append(new_node(accent_noad, 0)); - if (cur_chr == 0) { - /*tex \.{\\mathaccent} */ - t = scan_mathchar(tex_mathcode); - } else if (cur_chr == 1) { - /*tex \.{\\Umathaccent} */ - if (scan_keyword("fixed")) { - /*tex top */ - subtype(tail) = 1; - t = scan_mathchar(umath_mathcode); - } else if (scan_keyword("both")) { - /*tex top bottom */ - if (scan_keyword("fixed")) { - subtype(tail) = 1; - } - t = scan_mathchar(umath_mathcode); - if (scan_keyword("fixed")) { - subtype(tail) += 2; - } - b = scan_mathchar(umath_mathcode); - } else if (scan_keyword("bottom")) { - /*tex bottom */ - if (scan_keyword("fixed")) { - subtype(tail) = 2; - } - b = scan_mathchar(umath_mathcode); - } else if (scan_keyword("top")) { - /*tex top */ - if (scan_keyword("fixed")) { - subtype(tail) = 1; - } - t = scan_mathchar(umath_mathcode); - } else if (scan_keyword("overlay")) { - /* overlay */ - if (scan_keyword("fixed")) { - subtype(tail) = 1; - } - o = scan_mathchar(umath_mathcode); - } else { - /*tex top */ - t = scan_mathchar(umath_mathcode); - } - if (scan_keyword("fraction")) { - scan_int(); - accentfraction(tail) = cur_val; - } - } else { - confusion("mathaccent"); - } - if (!(t.character_value == 0 && t.family_value == 0)) { - q = new_node(math_char_node, 0); - top_accent_chr(tail) = q; - math_character(top_accent_chr(tail)) = t.character_value; - if ((t.class_value == math_use_current_family_code) && cur_fam_par_in_range) - math_fam(top_accent_chr(tail)) = cur_fam_par; - else - math_fam(top_accent_chr(tail)) = t.family_value; - } - if (!(b.character_value == 0 && b.family_value == 0)) { - q = new_node(math_char_node, 0); - bot_accent_chr(tail) = q; - math_character(bot_accent_chr(tail)) = b.character_value; - if ((b.class_value == math_use_current_family_code) && cur_fam_par_in_range) - math_fam(bot_accent_chr(tail)) = cur_fam_par; - else - math_fam(bot_accent_chr(tail)) = b.family_value; - } - if (!(o.character_value == 0 && o.family_value == 0)) { - q = new_node(math_char_node, 0); - overlay_accent_chr(tail) = q; - math_character(overlay_accent_chr(tail)) = o.character_value; - if ((o.class_value == math_use_current_family_code) && cur_fam_par_in_range) - math_fam(overlay_accent_chr(tail)) = cur_fam_par; - else - math_fam(overlay_accent_chr(tail)) = o.family_value; - } - q = new_node(math_char_node, 0); - nucleus(tail) = q; - (void) scan_math(nucleus(tail), cramped_style(m_style)); -} - -pointer math_vcenter_group(pointer p) -{ - pointer q, r; - q = new_noad(); - subtype(q) = vcenter_noad_type; - r = new_node(sub_box_node, 0); - nucleus(q) = r; - math_list(nucleus(q)) = p; - return q; -} - -/*tex - - The routine that scans the four mlists of a \.{\\mathchoice} is very much - like the routine that builds discretionary nodes. - -*/ - -void append_choices(void) -{ - tail_append(new_choice()); - incr(save_ptr); - set_saved_record(-1, saved_choices, 0, 0); - push_math(math_choice_group, display_style); - scan_left_brace(); -} - -void build_choices(void) -{ - pointer p; - int prev_style; - prev_style = m_style; - unsave_math(); - p = fin_mlist(null); - assert(saved_type(-1) == saved_choices); - switch (saved_value(-1)) { - case 0: - display_mlist(tail) = p; - break; - case 1: - text_mlist(tail) = p; - break; - case 2: - script_mlist(tail) = p; - break; - case 3: - script_script_mlist(tail) = p; - decr(save_ptr); - return; - break; - } - set_saved_record(-1, saved_choices, 0, (saved_value(-1) + 1)); - push_math(math_choice_group, (prev_style + 2)); - scan_left_brace(); -} - -/*tex - - Subscripts and superscripts are attached to the previous nucleus by the - action procedure called |sub_sup|. - -*/ - -static void do_sub_sup(int no) -{ - pointer q; - if (tail == head || (!scripts_allowed(tail))) { - tail_append(new_noad()); - q = new_node(sub_mlist_node, 0); - nucleus(tail) = q; - } - if (cur_cmd == sup_mark_cmd || cur_chr == sup_mark_cmd) { - /*tex |super_sub_script| */ - if (supscr(tail) != null) { - const char *hlp[] = { - "I treat `x^1^2' essentially like `x^1{}^2'.", NULL - }; - tail_append(new_noad()); - q = new_node(sub_mlist_node, 0); - nucleus(tail) = q; - tex_error("Double superscript", hlp); - } - if (no) { - noadoptions(tail) = noadoptions(tail) | noad_option_no_super_script ; - } - q = new_node(math_char_node, 0); - supscr(tail) = q; - (void) scan_math(supscr(tail), sup_style(m_style)); - } else if (cur_cmd == sub_mark_cmd || cur_chr == sub_mark_cmd) { - if (subscr(tail) != null) { - const char *hlp[] = { - "I treat `x_1_2' essentially like `x_1{}_2'.", NULL - }; - tail_append(new_noad()); - q = new_node(sub_mlist_node, 0); - nucleus(tail) = q; - tex_error("Double subscript", hlp); - } - if (no) { - noadoptions(tail) = noadoptions(tail) | noad_option_no_sub_script ; - } - q = new_node(math_char_node, 0); - subscr(tail) = q; - (void) scan_math(subscr(tail), sub_style(m_style)); - } -} - -void sub_sup(void) -{ - do_sub_sup(0); -} - -void no_sub_sup(void) -{ - do_sub_sup(1); -} - -/*tex - - An operation like `\.{\\over}' causes the current mlist to go into a state of - suspended animation: |incompleat_noad| points to a |fraction_noad| that - contains the mlist-so-far as its numerator, while the denominator is yet to - come. Finally when the mlist is finished, the denominator will go into the - incompleat fraction noad, and that noad will become the whole formula, unless - it is surrounded by `\.{\\left}' and `\.{\\right}' delimiters. - -*/ - -void math_fraction(void) -{ - /*tex The type of generalized fraction we are scanning: */ - halfword c; - pointer q; - halfword options = 0; - halfword temp_value; - c = cur_chr; - if (incompleat_noad_par != null) { - const char *hlp[] = { - "I'm ignoring this fraction specification, since I don't", - "know whether a construction like `x \\over y \\over z'", - "means `{x \\over y} \\over z' or `x \\over {y \\over z}'.", - NULL - }; - if (c >= delimited_code) { - scan_delimiter(null, no_mathcode); - scan_delimiter(null, no_mathcode); - } - if ((c % delimited_code) == above_code) - scan_normal_dimen(); - tex_error("Ambiguous; you need another { and }", hlp); - } else { - incompleat_noad_par = new_node(fraction_noad, 0); - temp_value = new_node(sub_mlist_node, 0); - numerator(incompleat_noad_par) = temp_value; - math_list(numerator(incompleat_noad_par)) = vlink(head); - vlink(head) = null; - tail = head; - m_style = cramped_style(m_style); - - if ((c % delimited_code) == skewed_code) { - q = new_node(delim_node, 0); - middle_delimiter(incompleat_noad_par) = q; - scan_delimiter(middle_delimiter(incompleat_noad_par), no_mathcode); - } - if (c >= delimited_code) { - q = new_node(delim_node, 0); - left_delimiter(incompleat_noad_par) = q; - q = new_node(delim_node, 0); - right_delimiter(incompleat_noad_par) = q; - scan_delimiter(left_delimiter(incompleat_noad_par), no_mathcode); - scan_delimiter(right_delimiter(incompleat_noad_par), no_mathcode); - } - switch (c % delimited_code) { - case above_code: - while (1) { - if (scan_keyword("exact")) { - options = options | noad_option_exact ; - } else if (scan_keyword("norule")) { - options = options | noad_option_no_rule ; - } else { - break; - } - } - fractionoptions(incompleat_noad_par) = options; - scan_normal_dimen(); - thickness(incompleat_noad_par) = cur_val; - break; - case over_code: - thickness(incompleat_noad_par) = default_code; - break; - case atop_code: - thickness(incompleat_noad_par) = 0; - break; - case skewed_code: - while (1) { - if (scan_keyword("exact")) { - options = options | noad_option_exact ; - } else if (scan_keyword("noaxis")) { - options = options | noad_option_no_axis ; - } else { - break; - } - } - fractionoptions(incompleat_noad_par) = options; - thickness(incompleat_noad_par) = 0; - break; - } - } -} - -/*tex - - At the end of a math formula or subformula, the |fin_mlist| routine is called - upon to return a pointer to the newly completed mlist, and to pop the nest - back to the enclosing semantic level. The parameter to |fin_mlist|, if not - null, points to a |fence_noad| that ends the current mlist; this |fence_noad| - has not yet been appended. - -*/ - -pointer fin_mlist(pointer p) -{ - pointer q; - if (incompleat_noad_par != null) { - if (denominator(incompleat_noad_par) != null) { - type(denominator(incompleat_noad_par)) = sub_mlist_node; - } else { - q = new_node(sub_mlist_node, 0); - denominator(incompleat_noad_par) = q; - } - math_list(denominator(incompleat_noad_par)) = vlink(head); - if (p == null) { - q = incompleat_noad_par; - } else { - q = math_list(numerator(incompleat_noad_par)); - if ((type(q) != fence_noad) || (subtype(q) != left_noad_side) || (delim_par == null)) - confusion("right"); - math_list(numerator(incompleat_noad_par)) = vlink(delim_par); - vlink(delim_par) = incompleat_noad_par; - vlink(incompleat_noad_par) = p; - } - } else { - vlink(tail) = p; - q = vlink(head); - } - pop_nest(); - return q; -} - -/*tex - - Now at last we're ready to see what happens when a right brace occurs in a - math formula. Two special cases are simplified here: Braces are effectively - removed when they surround a single Ord without sub/superscripts, or when - they surround an accent that is the nucleus of an Ord atom. - -*/ - -void close_math_group(pointer p) -{ - int old_style = m_style; - unsave_math(); - decr(save_ptr); - assert(saved_type(0) == saved_math); - type(saved_value(0)) = sub_mlist_node; - p = fin_mlist(null); - math_list(saved_value(0)) = p; - if (p != null && vlink(p) == null) { - if (type(p) == simple_noad) { - if (subscr(p) == null && supscr(p) == null) { - /*tex (subtype(p) == ord_noad_type) */ - int flatten = 0; - int modepar = math_flatten_mode_par; - switch (subtype(p)) { - case ord_noad_type : - flatten = (modepar & 1) == 1; - break; - case bin_noad_type : - flatten = (modepar & 2) == 2; - break; - case rel_noad_type : - flatten = (modepar & 4) == 4; - break; - case punct_noad_type : - flatten = (modepar & 8) == 8; - break; - case inner_noad_type : - flatten = (modepar & 16) == 16; - break; - default: - break; - } - if (flatten) { - type(saved_value(0)) = type(nucleus(p)); - if (type(nucleus(p)) == math_char_node) { - math_fam(saved_value(0)) = math_fam(nucleus(p)); - math_character(saved_value(0)) = - math_character(nucleus(p)); - } else { - math_list(saved_value(0)) = math_list(nucleus(p)); - math_list(nucleus(p)) = null; - } - delete_attribute_ref(node_attr(saved_value(0))); - node_attr(saved_value(0)) = node_attr(nucleus(p)); - node_attr(nucleus(p)) = null; - flush_node(p); - } - } - } else if (type(p) == accent_noad) { - if (saved_value(0) == nucleus(tail) && type(tail) == simple_noad && subtype(tail) == ord_noad_type) { - pointer q = head; - while (vlink(q) != tail) - q = vlink(q); - vlink(q) = p; - nucleus(tail) = null; - subscr(tail) = null; - supscr(tail) = null; - delete_attribute_ref(node_attr(p)); - node_attr(p) = node_attr(tail); - node_attr(tail) = null; - flush_node(tail); - tail = p; - } - } - } - if (vlink(saved_value(0)) > 0) { - pointer q; - q = new_node(math_char_node, 0); - nucleus(vlink(saved_value(0))) = q; - vlink(saved_value(0)) = null; - saved_value(0) = q; - (void) scan_math(saved_value(0), old_style); - /*tex restart */ - } -} - -/*tex - - We have dealt with all constructions of math mode except `\.{\\left}' and - `\.{\\right}', so the picture is completed by the following sections of the - program. The |middle| feature of eTeX allows one ore several \.{\\middle} - delimiters to appear between \.{\\left} and \.{\\right}. - -*/ - -void math_left_right(void) -{ - /*tex |left_noad_side| .. |right_noad_side| */ - halfword t; - /*tex new noad */ - pointer p; - /*tex resulting mlist */ - pointer q; - /*tex temporary */ - pointer r; - halfword ht = 0; - halfword dp = 0; - halfword options = 0; - halfword type = -1 ; - t = cur_chr; - if (t > 10) { - /*tex we have \Uleft \Uright \Umiddle */ - t = t - 10; - while (1) { - if (scan_keyword("height")) { - scan_dimen(false,false,false); - ht = cur_val ; - } else if (scan_keyword("depth")) { - scan_dimen(false,false,false); - dp = cur_val ; - } else if (scan_keyword("axis")) { - options = options | noad_option_axis ; - } else if (scan_keyword("noaxis")) { - options = options | noad_option_no_axis ; - } else if (scan_keyword("exact")) { - options = options | noad_option_exact ; - } else if (scan_keyword("class")) { - scan_int(); - math_class_to_type(type,cur_val); - } else { - break; - } - } - } - if ((t != no_noad_side) && (t != left_noad_side) && (cur_group != math_left_group)) { - if (cur_group == math_shift_group) { - scan_delimiter(null, no_mathcode); - if (t == middle_noad_side) { - const char *hlp[] = { - "I'm ignoring a \\middle that had no matching \\left.", - NULL - }; - tex_error("Extra \\middle", hlp); - } else { - const char *hlp[] = { - "I'm ignoring a \\right that had no matching \\left.", - NULL - }; - tex_error("Extra \\right", hlp); - } - } else { - off_save(); - } - } else { - p = new_noad(); - type(p) = fence_noad; - subtype(p) = (quarterword) t; - r = new_node(delim_node, 0); - delimiter(p) = r; - delimiterheight(p) = ht; - delimiterdepth(p) = dp; - delimiteroptions(p) = options; - delimiterclass(p) = type; - delimiteritalic(p) = 0; - delimitersamesize(p) = 0; - scan_delimiter(delimiter(p), no_mathcode); - if (t == no_noad_side) { - tail_append(new_noad()); - subtype(tail) = inner_noad_type; - r = new_node(sub_mlist_node, 0); - nucleus(tail) = r; - math_list(nucleus(tail)) = p; - return ; - } - if (t == left_noad_side) { - q = p; - } else { - q = fin_mlist(p); - unsave_math(); - } - if (t != right_noad_side) { - push_math(math_left_group, m_style); - vlink(head) = q; - tail = p; - delim_par = p; - } else { - tail_append(new_noad()); - subtype(tail) = inner_noad_type; - r = new_node(sub_mlist_node, 0); - nucleus(tail) = r; - math_list(nucleus(tail)) = q; - } - } -} - -/*tex - - \TeX\ gets to the following part of the program when the first `\.\$' ending - a display has been scanned. - -*/ - -static void check_second_math_shift(void) -{ - get_x_token(); - if (cur_cmd != math_shift_cmd) { - const char *hlp[] = { - "The `$' that I just saw supposedly matches a previous `$$'.", - "So I shall assume that you typed `$$' both times.", - NULL - }; - back_error("Display math should end with $$", hlp); - } -} - -static void check_display_math_end(void) -{ - if (cur_chr != cramped_display_style) { - const char *hlp[] = { - "I shall assume that you typed that.", - NULL - }; - tex_error("Display math should end with \\Ustopdisplaymath", hlp); - } -} - -static void check_inline_math_end(void) -{ - if (cur_chr != cramped_text_style) { - const char *hlp[] = { - "I shall assume that you typed that.", - NULL - }; - tex_error("Inline math should end with \\Ustopmath", hlp); - } -} - -static void resume_after_display(void) -{ - if (cur_group != math_shift_group) - confusion("display"); - unsave_math(); - prev_graf_par = prev_graf_par + 3; - push_nest(); - mode = hmode; - space_factor_par = 1000; - /*tex This needs to be intercepted in the display math start! */ - tail_append(make_local_par_node(penalty_par_code)); - get_x_token(); - if (cur_cmd != spacer_cmd) - back_input(); - if (nest_ptr == 1) { - normal_page_filter(after_display); - build_page(); - } -} - -/*tex - - The fussiest part of math mode processing occurs when a displayed formula is - being centered and placed with an optional equation number. - - At this time we are in vertical mode (or internal vertical mode). - - \starttabulate - \NC \type {p} \NC points to the mlist for the formula \NC \NR - \NC \type {a} \NC is either |null| or it points to a box containing the equation number \NC \NR - \NC \type {l} \NC is true if there was an \.{\\leqno}/ (so |a| is a horizontal box) \NC \NR - \stoptabulate - -*/ - -#define inject_display_skip_before(g) \ - if (g > 0) { \ - switch (display_skip_mode_par) { \ - case 0 : \ - /*tex normal tex | always */ \ - case 1 : \ - /*tex always */ \ - tail_append(new_param_glue(g)); \ - break; \ - case 2 : \ - /*tex non-zero */ \ - if (! glue_is_zero(glue_par(g))) \ - tail_append(new_param_glue(g)); \ - break; \ - case 3: \ - /*tex ignore */ \ - break; \ - default: \ - /*tex > 3 reserved for future use */ \ - tail_append(new_param_glue(g)); \ - break; \ - } \ - } - -#define inject_display_skip_after(g) \ - if (g > 0) { \ - switch (display_skip_mode_par) { \ - case 0 : \ - /*tex normal tex | always */ \ - case 1 : \ - /*tex always */ \ - tail_append(new_param_glue(g)); \ - break; \ - case 2 : \ - /*tex non-zero */ \ - if (! glue_is_zero(glue_par(g))) \ - tail_append(new_param_glue(g)); \ - break; \ - case 3: \ - /*tex ignore */ \ - break; \ - default: \ - /*tex > 3 reserved for future use */ \ - tail_append(new_param_glue(g)); \ - break; \ - } \ - } - -static void finish_displayed_math(boolean l, pointer eqno_box, pointer p) -{ - /*tex box containing the equation */ - pointer eq_box; - /*tex width of the equation */ - scaled eq_w; - /*tex width of the line */ - scaled line_w; - /*tex width of equation number */ - scaled eqno_w; - /*tex width of equation number plus space to separate from equation */ - scaled eqno_w2; - /*tex move the line right this much */ - scaled line_s; - /*tex displacement of equation in the line */ - scaled d; - /*tex glue parameter codes for before and after */ - small_number g1, g2; - /*tex kern nodes used to position the display */ - pointer r,s; - /*tex tail of adjustment list */ - pointer t; - /*tex tail of pre-adjustment list */ - pointer pre_t; - /*tex true if the math and surrounding text dirs are opposed */ - boolean swap_dir; - scaled eqno_width; - swap_dir = (pre_display_direction_par < 0 ? true : false ); - if (eqno_box != null && swap_dir) - l = !l; - adjust_tail = adjust_head; - pre_adjust_tail = pre_adjust_head; - eq_box = hpack(p, 0, additional, -1); - subtype(eq_box) = equation_list; - build_attribute_list(eq_box); - p = list_ptr(eq_box); - t = adjust_tail; - adjust_tail = null; - pre_t = pre_adjust_tail; - pre_adjust_tail = null; - eq_w = width(eq_box); - line_w = display_width_par; - line_s = display_indent_par; - if (eqno_box == null) { - eqno_w = 0; - eqno_width = 0; - eqno_w2 = 0; - } else { - eqno_w = width(eqno_box); - eqno_width = eqno_w; - eqno_w2 = eqno_w + round_xn_over_d(math_eqno_gap_step_par, get_math_quad_style(text_style), 1000); - subtype(eqno_box) = equation_number_list; - /*tex build_attribute_list(eqno_box); */ - } - if (eq_w + eqno_w2 > line_w) { - /*tex - - The user can force the equation number to go on a separate line by - causing its width to be zero. - - */ - if ((eqno_w != 0) && ((eq_w - total_shrink[normal] + eqno_w2 <= line_w) - || (total_shrink[sfi] != 0) || (total_shrink[fil] != 0) - || (total_shrink[fill] != 0) || (total_shrink[filll] != 0))) { - list_ptr(eq_box) = null; - flush_node(eq_box); - eq_box = hpack(p, line_w - eqno_w2, exactly, -1); - subtype(eq_box) = equation_list; - build_attribute_list(eq_box); - } else { - eqno_w = 0; - if (eq_w > line_w) { - list_ptr(eq_box) = null; - flush_node(eq_box); - eq_box = hpack(p, line_w, exactly, -1); - subtype(eq_box) = equation_list; - build_attribute_list(eq_box); - } - } - eq_w = width(eq_box); - } - /*tex - - We try first to center the display without regard to the existence of the - equation number. If that would make it too close (where ``too close'' - means that the space between display and equation number is less than the - width of the equation number), we either center it in the remaining space - or move it as far from the equation number as possible. The latter - alternative is taken only if the display begins with glue, since we - assume that the user put glue there to control the spacing precisely. - - */ - d = half(line_w - eq_w); - if ((eqno_w > 0) && (d < 2 * eqno_w)) { - /*tex too close */ - d = half(line_w - eq_w - eqno_w); - if (p != null) - if (!is_char_node(p)) - if (type(p) == glue_node) - d = 0; - } - tail_append(new_penalty(pre_display_penalty_par,after_display_penalty)); - if ((d + line_s <= pre_display_size_par) || l) { - /*tex not enough clearance */ - g1 = above_display_skip_code; - g2 = below_display_skip_code; - } else { - g1 = above_display_short_skip_code; - g2 = below_display_short_skip_code; - } - /*tex - - If the equation number is set on a line by itself, either before or after - the formula, we append an infinite penalty so that no page break will - separate the display from its number; and we use the same size and - displacement for all three potential lines of the display, even though - `\.{\\parshape}' may specify them differently. - - \.{\\leqno} on a forced single line due to |width=0|; it follows that |type(a)=hlist_node| - - */ - if (eqno_box && l && (eqno_w == 0)) { - /* if (math_direction_par==dir_TLT) { */ - shift_amount(eqno_box) = 0; - /* } else { */ - /* } */ - append_to_vlist(eqno_box,lua_key_index(equation_number)); - tail_append(new_penalty(inf_penalty,equation_number_penalty)); - } else { - inject_display_skip_before(g1); - } - if (eqno_w != 0) { - r = new_kern(line_w - eq_w - eqno_w - d); - if (l) { - if (swap_dir) { - if (math_direction_par==dir_TLT) { - /*tex TRT + TLT + \eqno: (swap_dir=true, math_direction_par=TLT, l=true) */ - s = new_kern(width(r) + eqno_w); - try_couple_nodes(eqno_box,r); - try_couple_nodes(r,eq_box); - try_couple_nodes(eq_box,s); - } else { - /*tex TLT + TRT + \eqno: (swap_dir=true, math_direction_par=TRT, l=true) */ - try_couple_nodes(eqno_box,r); - try_couple_nodes(r,eq_box); - } - } else { - if (math_direction_par==dir_TLT) { - /*tex TLT + TLT + \leqno: (swap_dir=false, math_direction_par=TLT, l=true) */ - s = new_kern(width(r) + eqno_w); - } else { - /*tex TRT + TRT + \leqno: (swap_dir=false, math_direction_par=TRT, l=true) */ - s = new_kern(width(r)); - } - try_couple_nodes(eqno_box,r); - try_couple_nodes(r,eq_box); - try_couple_nodes(eq_box,s); - } - eq_box = eqno_box; - } else { - if (swap_dir) { - if (math_direction_par==dir_TLT) { - /*tex TRT + TLT + \leqno: (swap_dir=true, math_direction_par=TLT, l=false) */ - } else { - /*tex TLT + TRT + \leqno: (swap_dir=true, math_direction_par=TRT, l=false) */ - } - try_couple_nodes(eq_box,r); - try_couple_nodes(r,eqno_box); - } else { - if (math_direction_par==dir_TLT) { - /*tex TLT + TLT + \eqno: (swap_dir=false, math_direction_par=TLT, l=false) */ - s = new_kern(d); - } else { - /*tex TRT + TRT + \eqno: (swap_dir=false, math_direction_par=TRT, l=false) */ - s = new_kern(width(r) + eqno_w); - } - try_couple_nodes(s,eq_box); - try_couple_nodes(eq_box,r); - try_couple_nodes(r,eqno_box); - eq_box = s; - } - } - eq_box = hpack(eq_box, 0, additional, -1); - subtype(eq_box) = equation_list; /* new */ - build_attribute_list(eq_box); - shift_amount(eq_box) = line_s; - } else { - shift_amount(eq_box) = line_s + d; - } - /*tex check for prev: */ - append_to_vlist(eq_box,lua_key_index(equation)); - if ((eqno_box != null) && (eqno_w == 0) && !l) { - tail_append(new_penalty(inf_penalty,equation_number_penalty)); - /* if (math_direction_par==dir_TLT) { */ - shift_amount(eqno_box) = line_s + line_w - eqno_width ; - /* } else { */ - /* } */ - append_to_vlist(eqno_box,lua_key_index(equation_number)); - g2 = 0; - } - if (t != adjust_head) { - /*tex migrating material comes after equation number */ - vlink(tail) = vlink(adjust_head); - alink(adjust_tail) = alink(tail); - tail = t; - } - if (pre_t != pre_adjust_head) { - vlink(tail) = vlink(pre_adjust_head); - alink(pre_adjust_tail) = alink(tail); - tail = pre_t; - } - tail_append(new_penalty(post_display_penalty_par,after_display_penalty)); - inject_display_skip_after(g2); - resume_after_display(); -} - -void after_math(void) -{ - /*tex |mmode| or |-mmode| */ - int m; - /*tex the formula */ - pointer p; - /*tex box containing equation number */ - pointer a = null; - /*tex `\.{\\leqno}' instead of `\.{\\eqno}' */ - boolean l = false; - m = mode; - /*tex this pops the nest */ - p = fin_mlist(null); - if (cur_cmd == math_shift_cs_cmd && - (cur_chr == text_style || cur_chr == display_style)) { - you_cant(); - } - if (mode == -m) { - /*tex end of equation number */ - if (cur_cmd == math_shift_cmd) { - check_second_math_shift(); - } else { - check_display_math_end(); - } - run_mlist_to_hlist(p, false, text_style); - a = hpack(vlink(temp_head), 0, additional, -1); - build_attribute_list(a); - unsave_math(); - /*tex now |cur_group=math_shift_group| */ - decr(save_ptr); - assert(saved_type(0) == saved_eqno); - if (saved_value(0) == 1) - l = true; - m = mode; - p = fin_mlist(null); - - } - if (m < 0) { - /*tex - - The |unsave| is done after everything else here; hence an appearance - of `\.{\\mathsurround}' inside of `\.{\$...\$}' affects the spacing - at these particular \.\$'s. This is consistent with the conventions - of `\.{\$\$...\$\$}', since `\.{\\abovedisplayskip}' inside a display - affects the space above that display. - - */ - if (cur_cmd == math_shift_cs_cmd) { - check_inline_math_end(); - } - tail_append(new_math(math_surround_par, before)); - /*tex begin mathskip code */ - switch (math_skip_mode) { - case 0 : - /*tex obey mathsurround when zero glue */ - if (! glue_is_zero(math_skip_par)) { - copy_glue_values(tail,math_skip_par); - surround(tail) = 0; - } - break ; - case 1 : - /*tex always left */ - case 3 : - /*tex always both */ - case 6 : - /*tex only when skip */ - copy_glue_values(tail,math_skip_par); - surround(tail) = 0; - break ; - case 2 : - /*tex only right */ - surround(tail) = 0; - break ; - case 4 : - /*tex ignore, obey marthsurround */ - break ; - case 5: - /*tex all spacing disabled */ - surround(tail) = 0; - break ; - } - /*tex end mathskip code */ - if (dir_math_save) { - tail_append(new_dir(math_direction_par)); - } - run_mlist_to_hlist(p, (mode > 0), text_style); - try_couple_nodes(tail,vlink(temp_head)); - - while (vlink(tail) != null) { - tail = vlink(tail); - } - if (dir_math_save) { - tail_append(new_dir(math_direction_par)); - subtype(tail) = cancel_dir; - } - dir_math_save = false; - tail_append(new_math(math_surround_par, after)); - /*tex begin mathskip code */ - switch (math_skip_mode) { - case 0 : - /*tex obey mathsurround when zero glue */ - if (! glue_is_zero(math_skip_par)) { - copy_glue_values(tail,math_skip_par); - surround(tail) = 0; - } - break ; - case 2 : - /*tex always right */ - case 3 : - /*tex always both */ - case 6 : - /*tex only when skip */ - copy_glue_values(tail,math_skip_par); - surround(tail) = 0; - break ; - case 1 : - /*tex only left */ - surround(tail) = 0; - break ; - case 4 : - /*tex ignore, obey marthsurround */ - break ; - case 5: - /*tex all spacing disabled */ - surround(tail) = 0; - break ; - } - /*tex end mathskip code */ - space_factor_par = 1000; - unsave_math(); - } else { - if (a == null) { - if (cur_cmd == math_shift_cmd) { - check_second_math_shift(); - } else { - check_display_math_end(); - } - } - run_mlist_to_hlist(p, false, display_style); - finish_displayed_math(l, a, vlink(temp_head)); - } -} - -/*tex - - When \.{\\halign} appears in a display, the alignment routines operate - essentially as they do in vertical mode. Then the following program is - activated, with |p| and |q| pointing to the beginning and end of the - resulting list, and with |aux_save| holding the |prev_depth| value. - -*/ - -void finish_display_alignment(pointer p, pointer q, halfword saved_prevdepth) -{ - do_assignments(); - if (cur_cmd == math_shift_cmd) { - check_second_math_shift(); - } else { - check_display_math_end(); - } - pop_nest(); - tail_append(new_penalty(pre_display_penalty_par,before_display_penalty)); - inject_display_skip_before(above_display_skip_code); - vlink(tail) = p; - if (p != null) - tail = q; - tail_append(new_penalty(post_display_penalty_par,after_display_penalty)); - inject_display_skip_after(below_display_skip_code); - cur_list.prev_depth_field = saved_prevdepth; - resume_after_display(); -} - -/*tex Interface to \.{\\Umath} and \.{\\mathstyle}: */ - -void setup_math_style(void) -{ - pointer q; - tail_append(new_noad()); - q = new_node(math_char_node, 0); - nucleus(tail) = q; - (void) scan_math_style(nucleus(tail), num_style(m_style)); -} - -void print_math_style(void) -{ - if (abs(mode) == mmode) - print_int(m_style); - else - print_int(-1); -} diff --git a/Build/source/texk/web2c/luatexdir/tex/texmath.h b/Build/source/texk/web2c/luatexdir/tex/texmath.h deleted file mode 100644 index 23fc5a0e42e..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/texmath.h +++ /dev/null @@ -1,306 +0,0 @@ -/* texmath.h - - Copyright 1996-2006 Han The Thanh <thanh@pdftex.org> - Copyright 2006-2009 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ - - -#ifndef TEXMATH_H -# define TEXMATH_H 1 - -# define empty 0 - -extern pointer new_noad(void); - -extern void show_math_node(halfword); -extern void flush_math(void); -extern void math_left_brace(void); -extern void finish_display_alignment(halfword, halfword, halfword); -extern halfword new_sub_box(halfword); - -# define math_reset(p) do { if (p!=null) flush_node(p); p = null; } while (0) - -# define scripts_allowed(A) ((type((A))>=simple_noad)&&(type((A))<fence_noad)) - -# define default_code 010000000000 /* denotes |default_rule_thickness| */ - -extern void initialize_math(void); -extern void initialize_math_spacing(void); -extern halfword math_vcenter_group(halfword); -extern void build_choices(void); -extern void close_math_group(halfword); -extern void init_math(void); -extern void start_eq_no(void); -extern void set_math_char(mathcodeval); -extern void math_char_in_text(mathcodeval); -extern void math_math_comp(void); -extern void math_limit_switch(void); -extern void math_radical(void); -extern void math_ac(void); -extern pointer new_style(small_number); -extern void append_choices(void); -extern void sub_sup(void); -extern void no_sub_sup(void); -extern void math_fraction(void); -extern void math_left_right(void); -extern void after_math(void); - -extern void scan_extdef_del_code(int level, int extcode); -extern void scan_extdef_math_code(int level, int extcode); - -extern int fam_fnt(int fam_id, int size_id); -extern void def_fam_fnt(int fam_id, int size_id, int f, int lvl); -extern void dump_math_data(void); -extern void undump_math_data(void); -void unsave_math_data(int lvl); - -/* - @ We also need to compute the change in style between mlists and their - subsidiaries. The following macros define the subsidiary style for - an overlined nucleus (|cramped_style|), for a subscript or a superscript - (|sub_style| or |sup_style|), or for a numerator or denominator (|num_style| - or |denom_style|). -*/ - -extern const char *math_style_names[]; - -# define cramped 1 /* add this to an uncramped style if you want to cramp it */ - -# define cramped_style(A) 2*((A)/2)+cramped /* cramp the style */ -# define sub_style(A) 2*((A)/4)+script_style+cramped /* smaller and cramped */ -# define sup_style(A) 2*((A)/4)+script_style+((A)%2) /* smaller */ -# define num_style(A) (A)+2-2*((A)/6) /* smaller unless already script-script */ -# define denom_style(A) 2*((A)/2)+cramped+2-2*((A)/6) /* smaller, cramped */ -# define sup_sup_style(A) sup_style(sup_style((A))) /* smaller */ - -void setup_math_style(void); -void print_math_style(void); - -# define text_size 0 -# define script_size 1 -# define script_script_size 2 - -# define dir_math_save cur_list.math_field -# define m_style cur_list.math_style_field -# define init_math_fields() do { \ - dir_math_save=false; \ - m_style=-1; \ - } while (0) - - -# define null_font 0 -# define min_quarterword 0 - -# define undefined_math_parameter max_dimen - -typedef enum { - math_param_quad, - math_param_axis, - math_param_operator_size, - math_param_overbar_kern, - math_param_overbar_rule, - math_param_overbar_vgap, - math_param_underbar_kern, - math_param_underbar_rule, - math_param_underbar_vgap, - math_param_radical_kern, - math_param_radical_rule, - math_param_radical_vgap, - math_param_radical_degree_before, - math_param_radical_degree_after, - math_param_radical_degree_raise, - math_param_stack_vgap, - math_param_stack_num_up, - math_param_stack_denom_down, - math_param_fraction_rule, - math_param_fraction_num_vgap, - math_param_fraction_num_up, - math_param_fraction_denom_vgap, - math_param_fraction_denom_down, - math_param_fraction_del_size, - math_param_skewed_fraction_hgap, - math_param_skewed_fraction_vgap, - math_param_limit_above_vgap, - math_param_limit_above_bgap, - math_param_limit_above_kern, - math_param_limit_below_vgap, - math_param_limit_below_bgap, - math_param_limit_below_kern, - math_param_nolimit_sub_factor, /* bonus */ - math_param_nolimit_sup_factor, /* bonus */ - math_param_under_delimiter_vgap, - math_param_under_delimiter_bgap, - math_param_over_delimiter_vgap, - math_param_over_delimiter_bgap, - math_param_sub_shift_drop, - math_param_sup_shift_drop, - math_param_sub_shift_down, - math_param_sub_sup_shift_down, - math_param_sub_top_max, - math_param_sup_shift_up, - math_param_sup_bottom_min, - math_param_sup_sub_bottom_max, - math_param_subsup_vgap, - math_param_space_after_script, - math_param_connector_overlap_min, - math_param_ord_ord_spacing, - math_param_ord_op_spacing, - math_param_ord_bin_spacing, - math_param_ord_rel_spacing, - math_param_ord_open_spacing, - math_param_ord_close_spacing, - math_param_ord_punct_spacing, - math_param_ord_inner_spacing, - math_param_op_ord_spacing, - math_param_op_op_spacing, - math_param_op_bin_spacing, - math_param_op_rel_spacing, - math_param_op_open_spacing, - math_param_op_close_spacing, - math_param_op_punct_spacing, - math_param_op_inner_spacing, - math_param_bin_ord_spacing, - math_param_bin_op_spacing, - math_param_bin_bin_spacing, - math_param_bin_rel_spacing, - math_param_bin_open_spacing, - math_param_bin_close_spacing, - math_param_bin_punct_spacing, - math_param_bin_inner_spacing, - math_param_rel_ord_spacing, - math_param_rel_op_spacing, - math_param_rel_bin_spacing, - math_param_rel_rel_spacing, - math_param_rel_open_spacing, - math_param_rel_close_spacing, - math_param_rel_punct_spacing, - math_param_rel_inner_spacing, - math_param_open_ord_spacing, - math_param_open_op_spacing, - math_param_open_bin_spacing, - math_param_open_rel_spacing, - math_param_open_open_spacing, - math_param_open_close_spacing, - math_param_open_punct_spacing, - math_param_open_inner_spacing, - math_param_close_ord_spacing, - math_param_close_op_spacing, - math_param_close_bin_spacing, - math_param_close_rel_spacing, - math_param_close_open_spacing, - math_param_close_close_spacing, - math_param_close_punct_spacing, - math_param_close_inner_spacing, - math_param_punct_ord_spacing, - math_param_punct_op_spacing, - math_param_punct_bin_spacing, - math_param_punct_rel_spacing, - math_param_punct_open_spacing, - math_param_punct_close_spacing, - math_param_punct_punct_spacing, - math_param_punct_inner_spacing, - math_param_inner_ord_spacing, - math_param_inner_op_spacing, - math_param_inner_bin_spacing, - math_param_inner_rel_spacing, - math_param_inner_open_spacing, - math_param_inner_close_spacing, - math_param_inner_punct_spacing, - math_param_inner_inner_spacing, - math_param_last -} math_parameters; - -extern const char *math_param_names[]; - -# define math_param_first_mu_glue math_param_ord_ord_spacing - -extern void def_math_param(int param_code, int style_code, scaled value, - int lvl); -extern scaled get_math_param(int param_code, int style_code); - - -typedef enum { - ScriptPercentScaleDown = 1, - ScriptScriptPercentScaleDown, - DelimitedSubFormulaMinHeight, - DisplayOperatorMinHeight, - MathLeading, - AxisHeight, - AccentBaseHeight, - FlattenedAccentBaseHeight, - SubscriptShiftDown, - SubscriptTopMax, - SubscriptBaselineDropMin, - SuperscriptShiftUp, - SuperscriptShiftUpCramped, - SuperscriptBottomMin, - SuperscriptBaselineDropMax, - SubSuperscriptGapMin, - SuperscriptBottomMaxWithSubscript, - SpaceAfterScript, - UpperLimitGapMin, - UpperLimitBaselineRiseMin, - LowerLimitGapMin, - LowerLimitBaselineDropMin, - StackTopShiftUp, - StackTopDisplayStyleShiftUp, - StackBottomShiftDown, - StackBottomDisplayStyleShiftDown, - StackGapMin, - StackDisplayStyleGapMin, - StretchStackTopShiftUp, - StretchStackBottomShiftDown, - StretchStackGapAboveMin, - StretchStackGapBelowMin, - FractionNumeratorShiftUp, - FractionNumeratorDisplayStyleShiftUp, - FractionDenominatorShiftDown, - FractionDenominatorDisplayStyleShiftDown, - FractionNumeratorGapMin, - FractionNumeratorDisplayStyleGapMin, - FractionRuleThickness, - FractionDenominatorGapMin, - FractionDenominatorDisplayStyleGapMin, - SkewedFractionHorizontalGap, - SkewedFractionVerticalGap, - OverbarVerticalGap, - OverbarRuleThickness, - OverbarExtraAscender, - UnderbarVerticalGap, - UnderbarRuleThickness, - UnderbarExtraDescender, - RadicalVerticalGap, - RadicalDisplayStyleVerticalGap, - RadicalRuleThickness, - RadicalExtraAscender, - RadicalKernBeforeDegree, - RadicalKernAfterDegree, - RadicalDegreeBottomRaisePercent, - MinConnectorOverlap, - SubscriptShiftDownWithSuperscript, - FractionDelimiterSize, - FractionDelimiterDisplayStyleSize, - NoLimitSubFactor, - NoLimitSupFactor, - MATH_param_last, -} MATH_param_codes; - -# define MATH_param_max MATH_param_last - -extern const char *MATH_param_names[]; - -#endif diff --git a/Build/source/texk/web2c/luatexdir/tex/texnodes.c b/Build/source/texk/web2c/luatexdir/tex/texnodes.c deleted file mode 100644 index 02e117a876b..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/texnodes.c +++ /dev/null @@ -1,4840 +0,0 @@ -/* - -Copyright 2006-2010 Taco Hoekwater <taco@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under the terms -of the GNU General Public License as published by the Free Software Foundation; -either version 2 of the License, or (at your option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - -You should have received a copy of the GNU General Public License along with -LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" -#include "lua/luatex-api.h" - -/*tex - - This module started out using NDEBUG to trigger checking invalid node usage, - something that is needed because users can mess up nodes in Lua. At some - point that code was always enabled so it is now always on but still can be - recognized as additional code. And as the performance hit is close to zero so - disabling makes no sense, not even to make it configureable. There is a - little more memory used but that is neglectable compared to other memory - usage. - -*/ - -#define MAX_CHAIN_SIZE 13 /* why not a bit larger */ -#define CHECK_NODE_USAGE 1 /* this triggers checking */ - -memory_word *volatile varmem = NULL; - -#ifdef CHECK_NODE_USAGE - char *varmem_sizes = NULL; -#endif - -halfword var_mem_max = 0; -halfword rover = 0; - -halfword free_chain[MAX_CHAIN_SIZE] = { null }; - -static int my_prealloc = 0; - -/*tex Used in font and lang: */ - -int fix_node_lists = 1; - -/*tex Defined below. */ - -halfword slow_get_node(int s); - -#define fake_node 100 -#define fake_node_size 2 -#define fake_node_name "fake" - -#define variable_node_size 2 - -/*tex - - The following definitions are used for keys at the \LUA\ end and - provide an efficient way to share hashed strings. - -*/ - -# define init_node_key(target,n,key) \ - target[n].lua = luaS_##key##_index; \ - target[n].name = luaS_##key##_ptr; - -# define init_field_key(target,n,key) \ - target[n].lua = luaS_##key##_index; \ - target[n].name = luaS_##key##_ptr; - -# define init_field_nop(target,n) \ - target[n].lua = 0; \ - target[n].name = NULL; - -/*tex The fields of nodes. */ - -field_info node_fields_accent[10]; -field_info node_fields_adjust[3]; -field_info node_fields_attribute[3]; -field_info node_fields_attribute_list[1]; -field_info node_fields_boundary[3]; -field_info node_fields_choice[6]; -field_info node_fields_delim[6]; -field_info node_fields_dir[4]; -field_info node_fields_disc[6]; -field_info node_fields_fence[8]; -field_info node_fields_fraction[10]; -field_info node_fields_glue[8]; -field_info node_fields_glue_spec[6]; -field_info node_fields_glyph[16]; -field_info node_fields_insert[7]; -field_info node_fields_inserting[9]; -field_info node_fields_kern[4]; -field_info node_fields_list[11]; -field_info node_fields_local_par[9]; -field_info node_fields_margin_kern[4]; -field_info node_fields_mark[4]; -field_info node_fields_math[8]; -field_info node_fields_math_char[4]; -field_info node_fields_math_text_char[4]; -field_info node_fields_noad[5]; -field_info node_fields_penalty[3]; -field_info node_fields_radical[9]; -field_info node_fields_rule[9]; -field_info node_fields_splitup[6]; -field_info node_fields_style[3]; -field_info node_fields_sub_box[3]; -field_info node_fields_sub_mlist[3]; -field_info node_fields_unset[12]; - -/*tex The fields of whatsit nodes. */ - -field_info node_fields_whatsit_close[3]; -field_info node_fields_whatsit_late_lua[6]; -field_info node_fields_whatsit_open[6]; -field_info node_fields_whatsit_save_pos[2]; -field_info node_fields_whatsit_special[3]; -field_info node_fields_whatsit_user_defined[5]; -field_info node_fields_whatsit_write[4]; - -field_info node_fields_whatsit_pdf_action[7]; -field_info node_fields_whatsit_pdf_annot[7]; -field_info node_fields_whatsit_pdf_colorstack[5]; -field_info node_fields_whatsit_pdf_dest[10]; -field_info node_fields_whatsit_pdf_end_link[2]; -field_info node_fields_whatsit_pdf_end_thread[2]; -field_info node_fields_whatsit_pdf_literal[4]; -field_info node_fields_whatsit_pdf_refobj[3]; -field_info node_fields_whatsit_pdf_restore[2]; -field_info node_fields_whatsit_pdf_link_state[3]; -field_info node_fields_whatsit_pdf_save[2]; -field_info node_fields_whatsit_pdf_setmatrix[3]; -field_info node_fields_whatsit_pdf_start_link[8]; -field_info node_fields_whatsit_pdf_start_thread[8]; -field_info node_fields_whatsit_pdf_thread[8]; - - -/*tex The values of fields. */ - -subtype_info node_values_dir[] = { - { 0, NULL, 0 }, - { 1, NULL, 0 }, - { 2, NULL, 0 }, - { 3, NULL, 0 }, - { -1, NULL, 0 }, -}; - -subtype_info node_values_pdf_destination[] = { - { 0, NULL, 0 }, - { 1, NULL, 0 }, - { 2, NULL, 0 }, - { 3, NULL, 0 }, - { 4, NULL, 0 }, - { 5, NULL, 0 }, - { 6, NULL, 0 }, - { 7, NULL, 0 }, - { -1, NULL, 0 }, -}; - -subtype_info node_values_pdf_action[] = { - { 0, NULL, 0 }, - { 1, NULL, 0 }, - { 2, NULL, 0 }, - { 3, NULL, 0 }, - { -1, NULL, 0 }, -}; - -subtype_info node_values_pdf_window[] = { - { 0, NULL, 0 }, - { 1, NULL, 0 }, - { 2, NULL, 0 }, - { -1, NULL, 0 }, -}; - -subtype_info node_values_color_stack[] = { - { 0, NULL, 0 }, - { 1, NULL, 0 }, - { 2, NULL, 0 }, - { 3, NULL, 0 }, - { -1, NULL, 0 }, -}; - -subtype_info node_values_fill[] = { - { normal, NULL, 0 }, - { sfi, NULL, 0 }, - { fil, NULL, 0 }, - { fill, NULL, 0 }, - { filll, NULL, 0 }, - { -1, NULL, 0 }, -}; - -subtype_info node_values_pdf_literal[] = { - { set_origin, NULL, 0 }, - { direct_page, NULL, 0 }, - { direct_always, NULL, 0 }, - { direct_raw, NULL, 0 }, - { direct_text, NULL, 0 }, - { direct_font, NULL, 0 }, - { scan_special, NULL, 0 }, - { -1, NULL, 0 }, -}; - -subtype_info other_values_page_states[] = { - { 0, NULL, 0 }, - { 1, NULL, 0 }, - { 2, NULL, 0 }, - { -1, NULL, 0 }, -}; - -/*tex The subtypes of nodes (most have one). */ - -subtype_info node_subtypes_dir[] = { - { normal_dir, NULL, 0 }, - { cancel_dir, NULL, 0 }, - { -1, NULL, 0 }, -}; - -subtype_info node_subtypes_glue[] = { - { user_skip_glue, NULL, 0 }, - { line_skip_glue, NULL, 0 }, - { baseline_skip_glue, NULL, 0 }, - { par_skip_glue, NULL, 0 }, - { above_display_skip_glue, NULL, 0 }, - { below_display_skip_glue, NULL, 0 }, - { above_display_short_skip_glue, NULL, 0 }, - { below_display_short_skip_glue, NULL, 0 }, - { left_skip_glue, NULL, 0 }, - { right_skip_glue, NULL, 0 }, - { top_skip_glue, NULL, 0 }, - { split_top_skip_glue, NULL, 0 }, - { tab_skip_glue, NULL, 0 }, - { space_skip_glue, NULL, 0 }, - { xspace_skip_glue, NULL, 0 }, - { par_fill_skip_glue, NULL, 0 }, - { math_skip_glue, NULL, 0 }, - { thin_mu_skip_glue, NULL, 0 }, - { med_mu_skip_glue, NULL, 0 }, - { thick_mu_skip_glue, NULL, 0 }, - /* math */ - { cond_math_glue, NULL, 0 }, - { mu_glue, NULL, 0 }, - /* leaders */ - { a_leaders, NULL, 0 }, - { c_leaders, NULL, 0 }, - { x_leaders, NULL, 0 }, - { g_leaders, NULL, 0 }, - { -1, NULL, 0 }, -}; - -/*tex - - Math glue and leaders have special numbers. At some point we might decide to - move them down so best don't use hard coded numbers! - -*/ - -subtype_info node_subtypes_mathglue[] = { /* 98+ */ - { cond_math_glue, NULL, 0 }, - { mu_glue, NULL, 0 }, - { -1, NULL, 0 }, -}; - -subtype_info node_subtypes_leader[] = { /* 100+ */ - { a_leaders, NULL, 0 }, - { c_leaders, NULL, 0 }, - { x_leaders, NULL, 0 }, - { g_leaders, NULL, 0 }, - { -1, NULL, 0 }, -}; - -subtype_info node_subtypes_boundary[] = { - { cancel_boundary, NULL, 0 }, - { user_boundary, NULL, 0 }, - { protrusion_boundary, NULL, 0 }, - { word_boundary, NULL, 0 }, - { -1, NULL, 0 }, -}; - -subtype_info node_subtypes_penalty[] = { - { user_penalty, NULL, 0 }, - { linebreak_penalty, NULL, 0 }, - { line_penalty, NULL, 0 }, - { word_penalty, NULL, 0 }, - { final_penalty, NULL, 0 }, - { noad_penalty, NULL, 0 }, - { before_display_penalty, NULL, 0 }, - { after_display_penalty, NULL, 0 }, - { equation_number_penalty, NULL, 0 }, - { -1, NULL, 0 }, -}; - -subtype_info node_subtypes_kern[] = { - { font_kern, NULL, 0 }, - { explicit_kern, NULL, 0 }, - { accent_kern, NULL, 0 }, - { italic_kern, NULL, 0 }, - { -1, NULL, 0 }, -}; - -subtype_info node_subtypes_rule[] = { - { normal_rule, NULL, 0 }, - { box_rule, NULL, 0 }, - { image_rule, NULL, 0 }, - { empty_rule, NULL, 0 }, - { user_rule, NULL, 0 }, - { math_over_rule, NULL, 0 }, - { math_under_rule, NULL, 0 }, - { math_fraction_rule, NULL, 0 }, - { math_radical_rule, NULL, 0 }, - { outline_rule, NULL, 0 }, - { -1, NULL, 0 }, -}; - -subtype_info node_subtypes_glyph[] = { - { glyph_unset, NULL, 0 }, - { glyph_character, NULL, 0 }, - { glyph_ligature, NULL, 0 }, - { glyph_ghost, NULL, 0 }, - { glyph_left, NULL, 0 }, - { glyph_right, NULL, 0 }, - { -1, NULL, 0 }, -}; - -subtype_info node_subtypes_disc[] = { - { discretionary_disc, NULL, 0 }, - { explicit_disc, NULL, 0 }, - { automatic_disc, NULL, 0 }, - { syllable_disc, NULL, 0 }, - { init_disc, NULL, 0 }, - { select_disc, NULL, 0 }, - { -1, NULL, 0 }, -}; - -subtype_info node_subtypes_marginkern[] = { - { left_side, NULL, 0 }, - { right_side, NULL, 0 }, - { -1, NULL, 0 }, -}; - -subtype_info node_subtypes_list[] = { - { unknown_list, NULL, 0 }, - { line_list, NULL, 0 }, - { hbox_list, NULL, 0 }, - { indent_list, NULL, 0 }, - { align_row_list, NULL, 0 }, - { align_cell_list, NULL, 0 }, - { equation_list, NULL, 0 }, - { equation_number_list, NULL, 0 }, - { math_list_list, NULL, 0 }, - { math_char_list, NULL, 0 }, - { math_h_extensible_list, NULL, 0 }, - { math_v_extensible_list, NULL, 0 }, - { math_h_delimiter_list, NULL, 0 }, - { math_v_delimiter_list, NULL, 0 }, - { math_over_delimiter_list, NULL, 0 }, - { math_under_delimiter_list, NULL, 0 }, - { math_numerator_list, NULL, 0 }, - { math_denominator_list, NULL, 0 }, - { math_limits_list, NULL, 0 }, - { math_fraction_list, NULL, 0 }, - { math_nucleus_list, NULL, 0 }, - { math_sup_list, NULL, 0 }, - { math_sub_list, NULL, 0 }, - { math_degree_list, NULL, 0 }, - { math_scripts_list, NULL, 0 }, - { math_over_list, NULL, 0 }, - { math_under_list, NULL, 0 }, - { math_accent_list, NULL, 0 }, - { math_radical_list, NULL, 0 }, - { -1, NULL, 0 }, -}; - -subtype_info node_subtypes_adjust[] = { - { 0, NULL, 0 }, - { 1, NULL, 0 }, - { -1, NULL, 0 }, -}; - -subtype_info node_subtypes_math[] = { - { before, NULL, 0 }, - { after, NULL, 0 }, - { -1, NULL, 0 }, -}; - -subtype_info node_subtypes_noad[] = { - { ord_noad_type, NULL, 0 }, - { op_noad_type_normal, NULL, 0 }, - { op_noad_type_limits, NULL, 0 }, - { op_noad_type_no_limits, NULL, 0 }, - { bin_noad_type, NULL, 0 }, - { rel_noad_type, NULL, 0 }, - { open_noad_type, NULL, 0 }, - { close_noad_type, NULL, 0 }, - { punct_noad_type, NULL, 0 }, - { inner_noad_type, NULL, 0 }, - { under_noad_type, NULL, 0 }, - { over_noad_type, NULL, 0 }, - { vcenter_noad_type, NULL, 0 }, - { -1, NULL, 0 }, -}; - -subtype_info node_subtypes_radical[] = { - { radical_noad_type, NULL, 0 }, - { uradical_noad_type, NULL, 0 }, - { uroot_noad_type, NULL, 0 }, - { uunderdelimiter_noad_type, NULL, 0 }, - { uoverdelimiter_noad_type, NULL, 0 }, - { udelimiterunder_noad_type, NULL, 0 }, - { udelimiterover_noad_type, NULL, 0 }, - { -1, NULL, 0 }, -}; - -subtype_info node_subtypes_accent[] = { - { bothflexible_accent, NULL, 0 }, - { fixedtop_accent, NULL, 0 }, - { fixedbottom_accent, NULL, 0 }, - { fixedboth_accent, NULL, 0 }, - { -1, NULL, 0 }, -}; - -subtype_info node_subtypes_fence[] = { - { unset_noad_side, NULL, 0 }, - { left_noad_side, NULL, 0 }, - { middle_noad_side, NULL, 0 }, - { right_noad_side, NULL, 0 }, - { no_noad_side, NULL, 0 }, - { -1, NULL, 0 }, -}; - -/*tes This brings all together */ - -node_info node_data[] = { - { hlist_node, box_node_size, node_subtypes_list, node_fields_list, NULL, 1, 0 }, - { vlist_node, box_node_size, node_subtypes_list, node_fields_list, NULL, 2, 0 }, - { rule_node, rule_node_size, node_subtypes_rule, node_fields_rule, NULL, 3, 0 }, - { ins_node, ins_node_size, NULL, node_fields_insert, NULL, 4, 0 }, - { mark_node, mark_node_size, NULL, node_fields_mark, NULL, 5, 0 }, - { adjust_node, adjust_node_size, node_subtypes_adjust, node_fields_adjust, NULL, 6, 0 }, - { boundary_node, boundary_node_size, node_subtypes_boundary, node_fields_boundary, NULL, -1, 0 }, - { disc_node, disc_node_size, node_subtypes_disc, node_fields_disc, NULL, 8, 0 }, - { whatsit_node, -1, NULL, NULL, NULL, 9, 0 }, - { local_par_node, local_par_size, NULL, node_fields_local_par, NULL, -1, 0 }, - { dir_node, dir_node_size, node_subtypes_dir, node_fields_dir, NULL, -1, 0 }, - { math_node, math_node_size, node_subtypes_math, node_fields_math, NULL, 10, 0 }, - { glue_node, glue_node_size, node_subtypes_glue, node_fields_glue, NULL, 11, 0 }, - { kern_node, kern_node_size, node_subtypes_kern, node_fields_kern, NULL, 12, 0 }, - { penalty_node, penalty_node_size, node_subtypes_penalty, node_fields_penalty, NULL, 13, 0 }, - { unset_node, box_node_size, NULL, node_fields_unset, NULL, 14, 0 }, - { style_node, style_node_size, NULL, node_fields_style, NULL, 15, 0 }, - { choice_node, style_node_size, NULL, node_fields_choice, NULL, 15, 0 }, - { simple_noad, noad_size, node_subtypes_noad, node_fields_noad, NULL, 15, 0 }, - { radical_noad, radical_noad_size, node_subtypes_radical, node_fields_radical, NULL, 15, 0 }, - { fraction_noad, fraction_noad_size, NULL, node_fields_fraction, NULL, 15, 0 }, - { accent_noad, accent_noad_size, node_subtypes_accent, node_fields_accent, NULL, 15, 0 }, - { fence_noad, fence_noad_size, node_subtypes_fence, node_fields_fence, NULL, 15, 0 }, - { math_char_node, math_kernel_node_size, NULL, node_fields_math_char, NULL, 15, 0 }, - { sub_box_node, math_kernel_node_size, NULL, node_fields_sub_box, NULL, 15, 0 }, - { sub_mlist_node, math_kernel_node_size, NULL, node_fields_sub_mlist, NULL, 15, 0 }, - { math_text_char_node, math_kernel_node_size, NULL, node_fields_math_text_char, NULL, 15, 0 }, - { delim_node, math_shield_node_size, NULL, node_fields_delim, NULL, 15, 0 }, - { margin_kern_node, margin_kern_node_size, node_subtypes_marginkern, node_fields_margin_kern, NULL, -1, 0 }, - { glyph_node, glyph_node_size, node_subtypes_glyph, node_fields_glyph, NULL, 0, 0 }, - { align_record_node, box_node_size, NULL, NULL, NULL, -1, 0 }, - { pseudo_file_node, pseudo_file_node_size, NULL, NULL, NULL, -1, 0 }, - { pseudo_line_node, variable_node_size, NULL, NULL, NULL, -1, 0 }, - { inserting_node, page_ins_node_size, NULL, node_fields_inserting, NULL, -1, 0 }, - { split_up_node, page_ins_node_size, NULL, node_fields_splitup, NULL, -1, 0 }, - { expr_node, expr_node_size, NULL, NULL, NULL, -1, 0 }, - { nesting_node, nesting_node_size, NULL, NULL, NULL, -1, 0 }, - { span_node, span_node_size, NULL, NULL, NULL, -1, 0 }, - { attribute_node, attribute_node_size, NULL, node_fields_attribute, NULL, -1, 0 }, - { glue_spec_node, glue_spec_size, NULL, node_fields_glue_spec, NULL, -1, 0 }, - { attribute_list_node, attribute_node_size, NULL, node_fields_attribute_list, NULL, -1, 0 }, - { temp_node, temp_node_size, NULL, NULL, NULL, -1, 0 }, - { align_stack_node, align_stack_node_size, NULL, NULL, NULL, -1, 0 }, - { movement_node, movement_node_size, NULL, NULL, NULL, -1, 0 }, - { if_node, if_node_size, NULL, NULL, NULL, -1, 0 }, - { unhyphenated_node, active_node_size, NULL, NULL, NULL, -1, 0 }, - { hyphenated_node, active_node_size, NULL, NULL, NULL, -1, 0 }, - { delta_node, delta_node_size, NULL, NULL, NULL, -1, 0 }, - { passive_node, passive_node_size, NULL, NULL, NULL, -1, 0 }, - { shape_node, variable_node_size, NULL, NULL, NULL, -1, 0 }, - { -1, -1, NULL, NULL, NULL, -1, 0 } -}; - -void l_set_node_data(void) { - init_node_key(node_data, hlist_node, hlist) - init_node_key(node_data, vlist_node, vlist) - init_node_key(node_data, rule_node, rule) - init_node_key(node_data, ins_node, ins) - init_node_key(node_data, mark_node, mark) - init_node_key(node_data, adjust_node, adjust) - init_node_key(node_data, boundary_node, boundary) - init_node_key(node_data, disc_node, disc) - init_node_key(node_data, whatsit_node, whatsit) - init_node_key(node_data, local_par_node, local_par) - init_node_key(node_data, dir_node, dir) - init_node_key(node_data, math_node, math) - init_node_key(node_data, glue_node, glue) - init_node_key(node_data, kern_node, kern) - init_node_key(node_data, penalty_node, penalty) - init_node_key(node_data, unset_node, unset) - init_node_key(node_data, style_node, style) - init_node_key(node_data, choice_node, choice) - init_node_key(node_data, simple_noad, noad) - init_node_key(node_data, radical_noad, radical) - init_node_key(node_data, fraction_noad, fraction) - init_node_key(node_data, accent_noad, accent) - init_node_key(node_data, fence_noad, fence) - init_node_key(node_data, math_char_node, math_char) - init_node_key(node_data, sub_box_node, sub_box) - init_node_key(node_data, sub_mlist_node, sub_mlist) - init_node_key(node_data, math_text_char_node, math_text_char) - init_node_key(node_data, delim_node, delim) - init_node_key(node_data, margin_kern_node, margin_kern) - init_node_key(node_data, glyph_node, glyph) - init_node_key(node_data, align_record_node, align_record) - init_node_key(node_data, pseudo_file_node, pseudo_file) - init_node_key(node_data, pseudo_line_node, pseudo_line) - init_node_key(node_data, inserting_node, page_insert) - init_node_key(node_data, split_up_node, split_insert) - init_node_key(node_data, expr_node, expr_stack) - init_node_key(node_data, nesting_node, nested_list) - init_node_key(node_data, span_node, span) - init_node_key(node_data, attribute_node, attribute) - init_node_key(node_data, glue_spec_node, glue_spec) - init_node_key(node_data, attribute_list_node, attribute_list) - init_node_key(node_data, temp_node, temp) - init_node_key(node_data, align_stack_node, align_stack) - init_node_key(node_data, movement_node, movement_stack) - init_node_key(node_data, if_node, if_stack) - init_node_key(node_data, unhyphenated_node, unhyphenated) - init_node_key(node_data, hyphenated_node, hyphenated) - init_node_key(node_data, delta_node, delta) - init_node_key(node_data, passive_node, passive) - init_node_key(node_data, shape_node, shape) - - init_node_key(node_subtypes_dir, normal_dir, normal) - init_node_key(node_subtypes_dir, cancel_dir, cancel) - - init_node_key(node_subtypes_glue, user_skip_glue, userskip) - init_node_key(node_subtypes_glue, line_skip_glue, lineskip) - init_node_key(node_subtypes_glue, baseline_skip_glue, baselineskip) - init_node_key(node_subtypes_glue, par_skip_glue, parskip) - init_node_key(node_subtypes_glue, above_display_skip_glue, abovedisplayskip) - init_node_key(node_subtypes_glue, below_display_skip_glue, belowdisplayskip) - init_node_key(node_subtypes_glue, above_display_short_skip_glue, abovedisplayshortskip) - init_node_key(node_subtypes_glue, below_display_short_skip_glue, belowdisplayshortskip) - init_node_key(node_subtypes_glue, left_skip_glue, leftskip) - init_node_key(node_subtypes_glue, right_skip_glue, rightskip) - init_node_key(node_subtypes_glue, top_skip_glue, topskip) - init_node_key(node_subtypes_glue, split_top_skip_glue, splittopskip) - init_node_key(node_subtypes_glue, tab_skip_glue, tabskip) - init_node_key(node_subtypes_glue, space_skip_glue, spaceskip) - init_node_key(node_subtypes_glue, xspace_skip_glue, xspaceskip) - init_node_key(node_subtypes_glue, par_fill_skip_glue, parfillskip) - init_node_key(node_subtypes_glue, math_skip_glue, mathskip) - init_node_key(node_subtypes_glue, thin_mu_skip_glue, thinmuskip) - init_node_key(node_subtypes_glue, med_mu_skip_glue, medmuskip) - init_node_key(node_subtypes_glue, thick_mu_skip_glue, thickmuskip) - init_node_key(node_subtypes_glue, thick_mu_skip_glue + 1, conditionalmathskip) - init_node_key(node_subtypes_glue, thick_mu_skip_glue + 2, muglue) - init_node_key(node_subtypes_glue, thick_mu_skip_glue + 3, leaders) - init_node_key(node_subtypes_glue, thick_mu_skip_glue + 4, cleaders) - init_node_key(node_subtypes_glue, thick_mu_skip_glue + 5, xleaders) - init_node_key(node_subtypes_glue, thick_mu_skip_glue + 6, gleaders) - - init_node_key(node_subtypes_mathglue, 0, conditionalmathskip) - init_node_key(node_subtypes_mathglue, 1, muglue) - - init_node_key(node_subtypes_leader, 0, leaders) - init_node_key(node_subtypes_leader, 1, cleaders) - init_node_key(node_subtypes_leader, 2, xleaders) - init_node_key(node_subtypes_leader, 3, gleaders) - - init_node_key(node_subtypes_boundary, cancel_boundary, cancel) - init_node_key(node_subtypes_boundary, user_boundary, user) - init_node_key(node_subtypes_boundary, protrusion_boundary, protrusion) - init_node_key(node_subtypes_boundary, word_boundary, word) - - init_node_key(node_subtypes_penalty, user_penalty, userpenalty) - init_node_key(node_subtypes_penalty, linebreak_penalty, linebreakpenalty) - init_node_key(node_subtypes_penalty, line_penalty, linepenalty) - init_node_key(node_subtypes_penalty, word_penalty, wordpenalty) - init_node_key(node_subtypes_penalty, final_penalty, finalpenalty) - init_node_key(node_subtypes_penalty, noad_penalty, noadpenalty) - init_node_key(node_subtypes_penalty, before_display_penalty, beforedisplaypenalty) - init_node_key(node_subtypes_penalty, after_display_penalty, afterdisplaypenalty) - init_node_key(node_subtypes_penalty, equation_number_penalty, equationnumberpenalty) - - init_node_key(node_subtypes_kern, font_kern, fontkern) - init_node_key(node_subtypes_kern, explicit_kern, userkern) - init_node_key(node_subtypes_kern, accent_kern, accentkern) - init_node_key(node_subtypes_kern, italic_kern, italiccorrection) - - init_node_key(node_subtypes_rule, normal_rule, normal) - init_node_key(node_subtypes_rule, box_rule, box) - init_node_key(node_subtypes_rule, image_rule, image) - init_node_key(node_subtypes_rule, empty_rule, empty) - init_node_key(node_subtypes_rule, user_rule, user) - init_node_key(node_subtypes_rule, math_over_rule, over) - init_node_key(node_subtypes_rule, math_under_rule, under) - init_node_key(node_subtypes_rule, math_fraction_rule, fraction) - init_node_key(node_subtypes_rule, math_radical_rule, radical) - init_node_key(node_subtypes_rule, outline_rule, outline) - - init_node_key(node_subtypes_glyph, 0, unset) - init_node_key(node_subtypes_glyph, 1, character) - init_node_key(node_subtypes_glyph, 2, ligature) - init_node_key(node_subtypes_glyph, 3, ghost) - init_node_key(node_subtypes_glyph, 4, left) - init_node_key(node_subtypes_glyph, 5, right) - - init_node_key(node_subtypes_disc, discretionary_disc, discretionary) - init_node_key(node_subtypes_disc, explicit_disc, explicit) - init_node_key(node_subtypes_disc, automatic_disc, automatic) - init_node_key(node_subtypes_disc, syllable_disc, regular) - init_node_key(node_subtypes_disc, init_disc, first) - init_node_key(node_subtypes_disc, select_disc, second) - - init_node_key(node_subtypes_fence, unset_noad_side, unset) - init_node_key(node_subtypes_fence, left_noad_side, left) - init_node_key(node_subtypes_fence, middle_noad_side, middle) - init_node_key(node_subtypes_fence, right_noad_side, right) - init_node_key(node_subtypes_fence, no_noad_side, no) - - init_node_key(node_subtypes_list, unknown_list, unknown) - init_node_key(node_subtypes_list, line_list, line) - init_node_key(node_subtypes_list, hbox_list, box) - init_node_key(node_subtypes_list, indent_list, indent) - init_node_key(node_subtypes_list, align_row_list, alignment) - init_node_key(node_subtypes_list, align_cell_list, cell) - init_node_key(node_subtypes_list, equation_list, equation) - init_node_key(node_subtypes_list, equation_number_list, equationnumber) - init_node_key(node_subtypes_list, math_list_list, math) - init_node_key(node_subtypes_list, math_char_list, mathchar) - init_node_key(node_subtypes_list, math_h_extensible_list, hextensible) - init_node_key(node_subtypes_list, math_v_extensible_list, vextensible) - init_node_key(node_subtypes_list, math_h_delimiter_list, hdelimiter) - init_node_key(node_subtypes_list, math_v_delimiter_list, vdelimiter) - init_node_key(node_subtypes_list, math_over_delimiter_list, overdelimiter) - init_node_key(node_subtypes_list, math_under_delimiter_list, underdelimiter) - init_node_key(node_subtypes_list, math_numerator_list, numerator) - init_node_key(node_subtypes_list, math_denominator_list, denominator) - init_node_key(node_subtypes_list, math_limits_list, limits) - init_node_key(node_subtypes_list, math_fraction_list, fraction) - init_node_key(node_subtypes_list, math_nucleus_list, nucleus) - init_node_key(node_subtypes_list, math_sup_list, sup) - init_node_key(node_subtypes_list, math_sub_list, sub) - init_node_key(node_subtypes_list, math_degree_list, degree) - init_node_key(node_subtypes_list, math_scripts_list, scripts) - init_node_key(node_subtypes_list, math_over_list, over) - init_node_key(node_subtypes_list, math_under_list, under) - init_node_key(node_subtypes_list, math_accent_list, accent) - init_node_key(node_subtypes_list, math_radical_list, radical) - - init_node_key(node_subtypes_math, before, beginmath) - init_node_key(node_subtypes_math, after, endmath) - - init_node_key(node_subtypes_marginkern, left_side, left) - init_node_key(node_subtypes_marginkern, right_side, right) - - init_node_key(node_subtypes_adjust, 0, normal) - init_node_key(node_subtypes_adjust, 1, pre) - - init_node_key(node_subtypes_noad, ord_noad_type, ord) - init_node_key(node_subtypes_noad, op_noad_type_normal, opdisplaylimits) - init_node_key(node_subtypes_noad, op_noad_type_limits, oplimits) - init_node_key(node_subtypes_noad, op_noad_type_no_limits, opnolimits) - init_node_key(node_subtypes_noad, bin_noad_type, bin) - init_node_key(node_subtypes_noad, rel_noad_type, rel) - init_node_key(node_subtypes_noad, open_noad_type, open) - init_node_key(node_subtypes_noad, close_noad_type, close) - init_node_key(node_subtypes_noad, punct_noad_type, punct) - init_node_key(node_subtypes_noad, inner_noad_type, inner) - init_node_key(node_subtypes_noad, under_noad_type, under) - init_node_key(node_subtypes_noad, over_noad_type, over) - init_node_key(node_subtypes_noad, vcenter_noad_type, vcenter) - - init_node_key(node_subtypes_radical, radical_noad_type, radical) - init_node_key(node_subtypes_radical, uradical_noad_type, uradical) - init_node_key(node_subtypes_radical, uroot_noad_type, uroot) - init_node_key(node_subtypes_radical, uunderdelimiter_noad_type, uunderdelimiter) - init_node_key(node_subtypes_radical, uoverdelimiter_noad_type, uoverdelimiter) - init_node_key(node_subtypes_radical, udelimiterunder_noad_type, udelimiterunder) - init_node_key(node_subtypes_radical, udelimiterover_noad_type, udelimiterover) - - init_node_key(node_subtypes_accent, bothflexible_accent, bothflexible) - init_node_key(node_subtypes_accent, fixedtop_accent, fixedtop) - init_node_key(node_subtypes_accent, fixedbottom_accent, fixedbottom) - init_node_key(node_subtypes_accent, fixedboth_accent, fixedboth) - - init_node_key(node_values_fill, normal, normal) - init_node_key(node_values_fill, sfi, fi) - init_node_key(node_values_fill, fil, fil) - init_node_key(node_values_fill, fill, fill) - init_node_key(node_values_fill, filll, filll) - - init_node_key(node_values_dir, 0, TLT) - init_node_key(node_values_dir, 1, TRT) - init_node_key(node_values_dir, 2, LTL) - init_node_key(node_values_dir, 3, RTT) - - init_node_key(other_values_page_states, 0, empty) - init_node_key(other_values_page_states, 1, box_there) - init_node_key(other_values_page_states, 2, inserts_only) - - init_field_key(node_fields_accent, 0, attr); - init_field_key(node_fields_accent, 1, nucleus); - init_field_key(node_fields_accent, 2, sub); - init_field_key(node_fields_accent, 3, sup); - init_field_key(node_fields_accent, 4, accent); - init_field_key(node_fields_accent, 5, bot_accent); - init_field_key(node_fields_accent, 6, top_accent); - init_field_key(node_fields_accent, 7, overlay_accent); - init_field_key(node_fields_accent, 8, fraction); - init_field_nop(node_fields_accent, 9); - - init_field_key(node_fields_adjust, 0, attr); - init_field_key(node_fields_adjust, 1, head); - init_field_nop(node_fields_adjust, 2); - - init_field_key(node_fields_attribute, 0, number); - init_field_key(node_fields_attribute, 1, value); - init_field_nop(node_fields_attribute, 2); - - init_field_nop(node_fields_attribute_list,0); - - init_field_key(node_fields_boundary, 0, attr); - init_field_key(node_fields_boundary, 1, value); - init_field_nop(node_fields_boundary, 2); - - init_field_key(node_fields_choice, 0, attr); - init_field_key(node_fields_choice, 1, display); - init_field_key(node_fields_choice, 2, text); - init_field_key(node_fields_choice, 3, script); - init_field_key(node_fields_choice, 4, scriptscript); - init_field_nop(node_fields_choice, 5); - - init_field_key(node_fields_delim, 0, attr); - init_field_key(node_fields_delim, 1, small_fam); - init_field_key(node_fields_delim, 2, small_char); - init_field_key(node_fields_delim, 3, large_fam); - init_field_key(node_fields_delim, 4, large_char); - init_field_nop(node_fields_delim, 5); - - init_field_key(node_fields_dir, 0, attr); - init_field_key(node_fields_dir, 1, dir); - init_field_key(node_fields_dir, 2, level); - init_field_nop(node_fields_dir, 3); - - init_field_key(node_fields_disc, 0, attr); - init_field_key(node_fields_disc, 1, pre); - init_field_key(node_fields_disc, 2, post); - init_field_key(node_fields_disc, 3, replace); - init_field_key(node_fields_disc, 4, penalty); - init_field_nop(node_fields_disc, 5); - - init_field_key(node_fields_fence, 0, attr); - init_field_key(node_fields_fence, 1, delim); - init_field_key(node_fields_fence, 2, italic); - init_field_key(node_fields_fence, 3, height); - init_field_key(node_fields_fence, 4, depth); - init_field_key(node_fields_fence, 5, options); - init_field_key(node_fields_fence, 6, class); - init_field_nop(node_fields_fence, 7); - - init_field_key(node_fields_fraction, 0, attr); - init_field_key(node_fields_fraction, 1, width); - init_field_key(node_fields_fraction, 2, num); - init_field_key(node_fields_fraction, 3, denom); - init_field_key(node_fields_fraction, 4, left); - init_field_key(node_fields_fraction, 5, right); - init_field_key(node_fields_fraction, 6, middle); - init_field_key(node_fields_fraction, 7, fam); - init_field_key(node_fields_fraction, 8, options); - init_field_nop(node_fields_fraction, 9); - - init_field_key(node_fields_glue, 0, attr); - init_field_key(node_fields_glue, 1, leader); - init_field_key(node_fields_glue, 2, width); - init_field_key(node_fields_glue, 3, stretch); - init_field_key(node_fields_glue, 4, shrink); - init_field_key(node_fields_glue, 5, stretch_order); - init_field_key(node_fields_glue, 6, shrink_order); - init_field_nop(node_fields_glue, 7); - - init_field_key(node_fields_glue_spec, 0, width); - init_field_key(node_fields_glue_spec, 1, stretch); - init_field_key(node_fields_glue_spec, 2, shrink); - init_field_key(node_fields_glue_spec, 3, stretch_order); - init_field_key(node_fields_glue_spec, 4, shrink_order); - init_field_nop(node_fields_glue_spec, 5); - - init_field_key(node_fields_glyph, 0, attr); - init_field_key(node_fields_glyph, 1, char); - init_field_key(node_fields_glyph, 2, font); - init_field_key(node_fields_glyph, 3, lang); - init_field_key(node_fields_glyph, 4, left); - init_field_key(node_fields_glyph, 5, right); - init_field_key(node_fields_glyph, 6, uchyph); - init_field_key(node_fields_glyph, 7, components); - init_field_key(node_fields_glyph, 8, xoffset); - init_field_key(node_fields_glyph, 9, yoffset); - init_field_key(node_fields_glyph, 10, width); - init_field_key(node_fields_glyph, 11, height); - init_field_key(node_fields_glyph, 12, depth); - init_field_key(node_fields_glyph, 13, expansion_factor); - init_field_key(node_fields_glyph, 14, data); - init_field_nop(node_fields_glyph, 15); - - init_field_key(node_fields_insert, 0, attr); - init_field_key(node_fields_insert, 1, cost); - init_field_key(node_fields_insert, 2, depth); - init_field_key(node_fields_insert, 3, height); - init_field_key(node_fields_insert, 4, spec); - init_field_key(node_fields_insert, 5, head); - init_field_nop(node_fields_insert, 6); - - init_field_key(node_fields_inserting, 0, height); - init_field_key(node_fields_inserting, 1, last_ins_ptr); - init_field_key(node_fields_inserting, 2, best_ins_ptr); - init_field_key(node_fields_inserting, 3, width); - init_field_key(node_fields_inserting, 4, stretch); - init_field_key(node_fields_inserting, 5, shrink); - init_field_key(node_fields_inserting, 6, stretch_order); - init_field_key(node_fields_inserting, 7, shrink_order); - init_field_nop(node_fields_inserting, 8); - - init_field_key(node_fields_kern, 0, attr); - init_field_key(node_fields_kern, 1, kern); - init_field_key(node_fields_kern, 2, expansion_factor); - init_field_nop(node_fields_kern, 3); - - init_field_key(node_fields_list, 0, attr); - init_field_key(node_fields_list, 1, width); - init_field_key(node_fields_list, 2, depth); - init_field_key(node_fields_list, 3, height); - init_field_key(node_fields_list, 4, dir); - init_field_key(node_fields_list, 5, shift); - init_field_key(node_fields_list, 6, glue_order); - init_field_key(node_fields_list, 7, glue_sign); - init_field_key(node_fields_list, 8, glue_set); - init_field_key(node_fields_list, 9, head); - init_field_nop(node_fields_list, 10); - - init_field_key(node_fields_local_par, 0, attr); - init_field_key(node_fields_local_par, 1, pen_inter); - init_field_key(node_fields_local_par, 2, pen_broken); - init_field_key(node_fields_local_par, 3, dir); - init_field_key(node_fields_local_par, 4, box_left); - init_field_key(node_fields_local_par, 5, box_left_width); - init_field_key(node_fields_local_par, 6, box_right); - init_field_key(node_fields_local_par, 7, box_right_width); - init_field_nop(node_fields_local_par, 8); - - init_field_key(node_fields_margin_kern, 0, attr); - init_field_key(node_fields_margin_kern, 1, width); - init_field_key(node_fields_margin_kern, 2, glyph); - init_field_nop(node_fields_margin_kern, 3); - - init_field_key(node_fields_mark, 0, attr); - init_field_key(node_fields_mark, 1, class); - init_field_key(node_fields_mark, 2, mark); - init_field_nop(node_fields_mark, 3); - - init_field_key(node_fields_math, 0, attr); - init_field_key(node_fields_math, 1, surround); - init_field_key(node_fields_math, 2, width); - init_field_key(node_fields_math, 3, stretch); - init_field_key(node_fields_math, 4, shrink); - init_field_key(node_fields_math, 5, stretch_order); - init_field_key(node_fields_math, 6, shrink_order); - init_field_nop(node_fields_math, 7); - - init_field_key(node_fields_math_char, 0, attr); - init_field_key(node_fields_math_char, 1, fam); - init_field_key(node_fields_math_char, 2, char); - init_field_nop(node_fields_math_char, 3); - - init_field_key(node_fields_math_text_char, 0, attr); - init_field_key(node_fields_math_text_char, 1, fam); - init_field_key(node_fields_math_text_char, 2, char); - init_field_nop(node_fields_math_text_char, 3); - - init_field_key(node_fields_noad, 0, attr); - init_field_key(node_fields_noad, 1, nucleus); - init_field_key(node_fields_noad, 2, sub); - init_field_key(node_fields_noad, 3, sup); - init_field_nop(node_fields_noad, 4); - - init_field_key(node_fields_penalty, 0, attr); - init_field_key(node_fields_penalty, 1, penalty); - init_field_nop(node_fields_penalty, 2); - - init_field_key(node_fields_radical, 0, attr); - init_field_key(node_fields_radical, 1, nucleus); - init_field_key(node_fields_radical, 2, sub); - init_field_key(node_fields_radical, 3, sup); - init_field_key(node_fields_radical, 4, left); - init_field_key(node_fields_radical, 5, degree); - init_field_key(node_fields_radical, 6, width); - init_field_key(node_fields_radical, 7, options); - init_field_nop(node_fields_radical, 8); - - init_field_key(node_fields_rule, 0, attr); - init_field_key(node_fields_rule, 1, width); - init_field_key(node_fields_rule, 2, depth); - init_field_key(node_fields_rule, 3, height); - init_field_key(node_fields_rule, 4, dir); - init_field_key(node_fields_rule, 5, index); - init_field_key(node_fields_rule, 6, left); - init_field_key(node_fields_rule, 7, right); - init_field_nop(node_fields_rule, 8); - - init_field_key(node_fields_splitup, 0, height); - init_field_key(node_fields_splitup, 1, last_ins_ptr); - init_field_key(node_fields_splitup, 2, best_ins_ptr); - init_field_key(node_fields_splitup, 3, broken_ptr); - init_field_key(node_fields_splitup, 4, broken_ins); - init_field_nop(node_fields_splitup, 5); - - init_field_key(node_fields_style, 0, attr); - init_field_key(node_fields_style, 1, style); - init_field_nop(node_fields_style, 2); - - init_field_key(node_fields_sub_box, 0, attr); - init_field_key(node_fields_sub_box, 1, head); - init_field_nop(node_fields_sub_box, 2); - - init_field_key(node_fields_sub_mlist, 0, attr); - init_field_key(node_fields_sub_mlist, 1, head); - init_field_nop(node_fields_sub_mlist, 2); - - init_field_key(node_fields_unset, 0, attr); - init_field_key(node_fields_unset, 1, width); - init_field_key(node_fields_unset, 2, depth); - init_field_key(node_fields_unset, 3, height); - init_field_key(node_fields_unset, 4, dir); - init_field_key(node_fields_unset, 5, shrink); - init_field_key(node_fields_unset, 6, glue_order); - init_field_key(node_fields_unset, 7, glue_sign); - init_field_key(node_fields_unset, 8, stretch); - init_field_key(node_fields_unset, 9, span); - init_field_key(node_fields_unset, 10, head); - init_field_nop(node_fields_unset, 11); - -} - -node_info whatsit_node_data[] = { - - /*tex These are always there. The fake nodes are historical. */ - - { open_node, open_node_size, NULL, node_fields_whatsit_open, NULL, -1, 0 }, - { write_node, write_node_size, NULL, node_fields_whatsit_write, NULL, -1, 0 }, - { close_node, close_node_size, NULL, node_fields_whatsit_close, NULL, -1, 0 }, - { special_node, special_node_size, NULL, node_fields_whatsit_special, NULL, -1, 0 }, - { fake_node, fake_node_size, NULL, NULL, NULL, -1, 0 }, - { fake_node, fake_node_size, NULL, NULL, NULL, -1, 0 }, - { save_pos_node, save_pos_node_size, NULL, node_fields_whatsit_save_pos, NULL, -1, 0 }, - { late_lua_node, late_lua_node_size, NULL, node_fields_whatsit_late_lua, NULL, -1, 0 }, - { user_defined_node, user_defined_node_size, NULL, node_fields_whatsit_user_defined, NULL, -1, 0 }, - { fake_node, fake_node_size, NULL, NULL, NULL, -1, 0 }, - { fake_node, fake_node_size, NULL, NULL, NULL, -1, 0 }, - { fake_node, fake_node_size, NULL, NULL, NULL, -1, 0 }, - { fake_node, fake_node_size, NULL, NULL, NULL, -1, 0 }, - { fake_node, fake_node_size, NULL, NULL, NULL, -1, 0 }, - { fake_node, fake_node_size, NULL, NULL, NULL, -1, 0 }, - { fake_node, fake_node_size, NULL, NULL, NULL, -1, 0 }, - - /*tex Here starts the \DVI\ backend section, todo: a separate list. */ - - /*tex {\em There is nothing here.} */ - - /*tex Here starts the \PDF\ backend section, todo: a separate list. */ - - { pdf_literal_node, write_node_size, NULL, node_fields_whatsit_pdf_literal, NULL, -1, 0 }, - { pdf_refobj_node, pdf_refobj_node_size, NULL, node_fields_whatsit_pdf_refobj, NULL, -1, 0 }, - { pdf_annot_node, pdf_annot_node_size, NULL, node_fields_whatsit_pdf_annot, NULL, -1, 0 }, - { pdf_start_link_node, pdf_annot_node_size, NULL, node_fields_whatsit_pdf_start_link, NULL, -1, 0 }, - { pdf_end_link_node, pdf_end_link_node_size, NULL, node_fields_whatsit_pdf_end_link, NULL, -1, 0 }, - { pdf_dest_node, pdf_dest_node_size, NULL, node_fields_whatsit_pdf_dest, NULL, -1, 0 }, - { pdf_action_node, pdf_action_size, NULL, node_fields_whatsit_pdf_action, NULL, -1, 0 }, - { pdf_thread_node, pdf_thread_node_size, NULL, node_fields_whatsit_pdf_thread, NULL, -1, 0 }, - { pdf_start_thread_node, pdf_thread_node_size, NULL, node_fields_whatsit_pdf_start_thread, NULL, -1, 0 }, - { pdf_end_thread_node, pdf_end_thread_node_size, NULL, node_fields_whatsit_pdf_end_thread, NULL, -1, 0 }, - { pdf_thread_data_node, pdf_thread_node_size, NULL, NULL, NULL, -1, 0 }, - { pdf_link_data_node, pdf_annot_node_size, NULL, NULL, NULL, -1, 0 }, - { pdf_colorstack_node, pdf_colorstack_node_size, NULL, node_fields_whatsit_pdf_colorstack, NULL, -1, 0 }, - { pdf_setmatrix_node, pdf_setmatrix_node_size, NULL, node_fields_whatsit_pdf_setmatrix, NULL, -1, 0 }, - { pdf_save_node, pdf_save_node_size, NULL, node_fields_whatsit_pdf_save, NULL, -1, 0 }, - { pdf_restore_node, pdf_restore_node_size, NULL, node_fields_whatsit_pdf_restore, NULL, -1, 0 }, - { pdf_link_state_node, pdf_link_state_node_size, NULL, node_fields_whatsit_pdf_link_state, NULL, -1, 0 }, - - /*tex That's it. */ - - { -1, -1, NULL, NULL, NULL, -1, 0 }, - -}; - -void l_set_whatsit_data(void) { - init_node_key(whatsit_node_data, open_node, open) - init_node_key(whatsit_node_data, write_node, write) - init_node_key(whatsit_node_data, close_node, close) - init_node_key(whatsit_node_data, special_node, special) - init_node_key(whatsit_node_data, save_pos_node, save_pos) - init_node_key(whatsit_node_data, late_lua_node, late_lua) - init_node_key(whatsit_node_data, user_defined_node, user_defined) - - init_field_key(node_fields_whatsit_close, 0, attr); - init_field_key(node_fields_whatsit_close, 1, stream); - init_field_nop(node_fields_whatsit_close, 2); - - init_field_key(node_fields_whatsit_late_lua, 0, attr); - init_field_key(node_fields_whatsit_late_lua, 1, reg); - init_field_key(node_fields_whatsit_late_lua, 2, data); - init_field_key(node_fields_whatsit_late_lua, 3, name); - init_field_key(node_fields_whatsit_late_lua, 4, string); - init_field_nop(node_fields_whatsit_late_lua, 5); - - init_field_key(node_fields_whatsit_open, 0, attr); - init_field_key(node_fields_whatsit_open, 1, stream); - init_field_key(node_fields_whatsit_open, 2, name); - init_field_key(node_fields_whatsit_open, 3, area); - init_field_key(node_fields_whatsit_open, 4, ext); - init_field_nop(node_fields_whatsit_open, 5); - - init_field_key(node_fields_whatsit_save_pos, 0, attr); - init_field_nop(node_fields_whatsit_save_pos, 1); - - init_field_key(node_fields_whatsit_special, 0, attr); - init_field_key(node_fields_whatsit_special, 1, data); - init_field_nop(node_fields_whatsit_special, 2); - - init_field_key(node_fields_whatsit_user_defined, 0, attr); - init_field_key(node_fields_whatsit_user_defined, 1, user_id); - init_field_key(node_fields_whatsit_user_defined, 2, type); - init_field_key(node_fields_whatsit_user_defined, 3, value); - init_field_nop(node_fields_whatsit_user_defined, 4); - - init_field_key(node_fields_whatsit_write, 0, attr); - init_field_key(node_fields_whatsit_write, 1, stream); - init_field_key(node_fields_whatsit_write, 2, data); - init_field_nop(node_fields_whatsit_write, 3); - - init_node_key(whatsit_node_data, pdf_literal_node, pdf_literal) - init_node_key(whatsit_node_data, pdf_refobj_node, pdf_refobj) - init_node_key(whatsit_node_data, pdf_annot_node, pdf_annot) - init_node_key(whatsit_node_data, pdf_start_link_node, pdf_start_link) - init_node_key(whatsit_node_data, pdf_end_link_node, pdf_end_link) - init_node_key(whatsit_node_data, pdf_dest_node, pdf_dest) - init_node_key(whatsit_node_data, pdf_action_node, pdf_action) - init_node_key(whatsit_node_data, pdf_thread_node, pdf_thread) - init_node_key(whatsit_node_data, pdf_start_thread_node,pdf_start_thread) - init_node_key(whatsit_node_data, pdf_end_thread_node, pdf_end_thread) - init_node_key(whatsit_node_data, pdf_thread_data_node, pdf_thread_data) - init_node_key(whatsit_node_data, pdf_link_data_node, pdf_link_data) - init_node_key(whatsit_node_data, pdf_colorstack_node, pdf_colorstack) - init_node_key(whatsit_node_data, pdf_setmatrix_node, pdf_setmatrix) - init_node_key(whatsit_node_data, pdf_save_node, pdf_save) - init_node_key(whatsit_node_data, pdf_restore_node, pdf_restore) - init_node_key(whatsit_node_data, pdf_link_state_node, pdf_link_state) - - init_node_key(node_values_pdf_destination, 0, xyz) - init_node_key(node_values_pdf_destination, 1, fit) - init_node_key(node_values_pdf_destination, 2, fith) - init_node_key(node_values_pdf_destination, 3, fitv) - init_node_key(node_values_pdf_destination, 4, fitb) - init_node_key(node_values_pdf_destination, 5, fitbh) - init_node_key(node_values_pdf_destination, 6, fitbv) - init_node_key(node_values_pdf_destination, 7, fitr) - - init_node_key(node_values_pdf_literal, set_origin, origin) - init_node_key(node_values_pdf_literal, direct_page, page) - init_node_key(node_values_pdf_literal, direct_always, always) - init_node_key(node_values_pdf_literal, direct_raw, raw) - init_node_key(node_values_pdf_literal, direct_text, text) - init_node_key(node_values_pdf_literal, direct_font, font) - init_node_key(node_values_pdf_literal, scan_special, special) - - init_node_key(node_values_pdf_action, 0, page) - init_node_key(node_values_pdf_action, 1, goto) - init_node_key(node_values_pdf_action, 2, thread) - init_node_key(node_values_pdf_action, 3, user) - - init_node_key(node_values_pdf_window, 0, unset) - init_node_key(node_values_pdf_window, 1, new) - init_node_key(node_values_pdf_window, 2, nonew) - - init_node_key(node_values_color_stack, 0, set) - init_node_key(node_values_color_stack, 1, push) - init_node_key(node_values_color_stack, 2, pop) - init_node_key(node_values_color_stack, 3, current) - - init_field_key(node_fields_whatsit_pdf_action, 0, action_type); - init_field_key(node_fields_whatsit_pdf_action, 1, named_id); - init_field_key(node_fields_whatsit_pdf_action, 2, action_id); - init_field_key(node_fields_whatsit_pdf_action, 3, file); - init_field_key(node_fields_whatsit_pdf_action, 4, new_window); - init_field_key(node_fields_whatsit_pdf_action, 5, data); - init_field_nop(node_fields_whatsit_pdf_action, 6); - - init_field_key(node_fields_whatsit_pdf_annot, 0, attr); - init_field_key(node_fields_whatsit_pdf_annot, 1, width); - init_field_key(node_fields_whatsit_pdf_annot, 2, depth); - init_field_key(node_fields_whatsit_pdf_annot, 3, height); - init_field_key(node_fields_whatsit_pdf_annot, 4, objnum); - init_field_key(node_fields_whatsit_pdf_annot, 5, data); - init_field_nop(node_fields_whatsit_pdf_annot, 6); - - init_field_key(node_fields_whatsit_pdf_colorstack, 0, attr); - init_field_key(node_fields_whatsit_pdf_colorstack, 1, stack); - init_field_key(node_fields_whatsit_pdf_colorstack, 2, cmd); - init_field_key(node_fields_whatsit_pdf_colorstack, 3, data); - init_field_nop(node_fields_whatsit_pdf_colorstack, 4); - - init_field_key(node_fields_whatsit_pdf_dest, 0, attr); - init_field_key(node_fields_whatsit_pdf_dest, 1, width); - init_field_key(node_fields_whatsit_pdf_dest, 2, depth); - init_field_key(node_fields_whatsit_pdf_dest, 3, height); - init_field_key(node_fields_whatsit_pdf_dest, 4, named_id); - init_field_key(node_fields_whatsit_pdf_dest, 5, dest_id); - init_field_key(node_fields_whatsit_pdf_dest, 6, dest_type); - init_field_key(node_fields_whatsit_pdf_dest, 7, xyz_zoom); - init_field_key(node_fields_whatsit_pdf_dest, 8, objnum); - init_field_nop(node_fields_whatsit_pdf_dest, 9); - - init_field_key(node_fields_whatsit_pdf_end_link, 0, attr); - init_field_nop(node_fields_whatsit_pdf_end_link, 1); - - init_field_key(node_fields_whatsit_pdf_link_state, 0, attr); - init_field_key(node_fields_whatsit_pdf_link_state, 1, value); - init_field_nop(node_fields_whatsit_pdf_link_state, 2); - - init_field_key(node_fields_whatsit_pdf_end_thread, 0, attr); - init_field_nop(node_fields_whatsit_pdf_end_thread, 1); - - init_field_key(node_fields_whatsit_pdf_literal, 0, attr); - init_field_key(node_fields_whatsit_pdf_literal, 1, mode); - init_field_key(node_fields_whatsit_pdf_literal, 2, data); - init_field_nop(node_fields_whatsit_pdf_literal, 3); - - init_field_key(node_fields_whatsit_pdf_refobj, 0, attr); - init_field_key(node_fields_whatsit_pdf_refobj, 1, objnum); - init_field_nop(node_fields_whatsit_pdf_refobj, 2); - - init_field_key(node_fields_whatsit_pdf_restore, 0, attr); - init_field_nop(node_fields_whatsit_pdf_restore, 1); - - init_field_key(node_fields_whatsit_pdf_save, 0, attr); - init_field_nop(node_fields_whatsit_pdf_save, 1); - - init_field_key(node_fields_whatsit_pdf_setmatrix, 0, attr); - init_field_key(node_fields_whatsit_pdf_setmatrix, 1, data); - init_field_nop(node_fields_whatsit_pdf_setmatrix, 2); - - init_field_key(node_fields_whatsit_pdf_start_link, 0, attr); - init_field_key(node_fields_whatsit_pdf_start_link, 1, width); - init_field_key(node_fields_whatsit_pdf_start_link, 2, depth); - init_field_key(node_fields_whatsit_pdf_start_link, 3, height); - init_field_key(node_fields_whatsit_pdf_start_link, 4, objnum); - init_field_key(node_fields_whatsit_pdf_start_link, 5, link_attr); - init_field_key(node_fields_whatsit_pdf_start_link, 6, action); - init_field_nop(node_fields_whatsit_pdf_start_link, 7); - - init_field_key(node_fields_whatsit_pdf_start_thread, 0, attr); - init_field_key(node_fields_whatsit_pdf_start_thread, 1, width); - init_field_key(node_fields_whatsit_pdf_start_thread, 2, depth); - init_field_key(node_fields_whatsit_pdf_start_thread, 3, height); - init_field_key(node_fields_whatsit_pdf_start_thread, 4, named_id); - init_field_key(node_fields_whatsit_pdf_start_thread, 5, thread_id); - init_field_key(node_fields_whatsit_pdf_start_thread, 6, thread_attr); - init_field_nop(node_fields_whatsit_pdf_start_thread, 7); - - init_field_key(node_fields_whatsit_pdf_thread, 0, attr); - init_field_key(node_fields_whatsit_pdf_thread, 1, width); - init_field_key(node_fields_whatsit_pdf_thread, 2, depth); - init_field_key(node_fields_whatsit_pdf_thread, 3, height); - init_field_key(node_fields_whatsit_pdf_thread, 4, named_id); - init_field_key(node_fields_whatsit_pdf_thread, 5, thread_id); - init_field_key(node_fields_whatsit_pdf_thread, 6, thread_attr); - init_field_nop(node_fields_whatsit_pdf_thread, 7); - -} - -#define last_whatsit_node pdf_restore_node - -/*tex - - When we copy a node list, there are several possibilities: we do the same as - a new node, we copy the entry to the table in properties (a reference), we do - a deep copy of a table in the properties, we create a new table and give it - the original one as a metatable. After some experiments (that also included - timing) with these scenarios I decided that a deep copy made no sense, nor - did nilling. In the end both the shallow copy and the metatable variant were - both ok, although the second ons is slower. The most important aspect to keep - in mind is that references to other nodes in properties no longer can be - valid for that copy. We could use two tables (one unique and one shared) or - metatables but that only complicates matters. - - When defining a new node, we could already allocate a table but it is rather - easy to do that at the lua end e.g. using a metatable __index method. That - way it is under macro package control. - - When deleting a node, we could keep the slot (e.g. setting it to false) but - it could make memory consumption raise unneeded when we have temporary large - node lists and after that only small lists. - - So, in the end this is what we ended up with. For the record, I also - experimented with the following: - - \startitemize - - \startitem - Copy attributes to the properties so that we have fast access at the - lua end: in the end the overhead is not compensated by speed and - convenience, in fact, attributes are not that slow when it comes to - accessing them. - \stopitem - - \startitem - A bitset in the node but again the gain compared to attributes is - neglectable and it also demands a pretty string agreement over what - bit represents what, and this is unlikely to succeed in the tex - community (I could use it for font handling, which is cross package, - but decided that it doesn't pay off. - \stopitem - - \stopitemize - - In case one wonders why properties make sense then, well, it is not so much - speed that we gain, but more convenience: storing all kind of (temporary) - data in attributes is no fun and this mechanism makes sure that properties - are cleaned up when a node is freed. Also, the advantage of a more or less - global properties table is that we stay at the lua end. An alternative is to - store a reference in the node itself but that is complicated by the fact that - the register has some limitations (no numeric keys) and we also don't want to - mess with it too much. - -*/ - -int lua_properties_level = 0 ; -int lua_properties_enabled = 0 ; -int lua_properties_use_metatable = 0 ; - -/*tex - - We keep track of nesting so that we don't oveflow the stack, and, what is - more important, don't keep resolving the registry index. - -*/ - -#define lua_properties_push do { \ - if (lua_properties_enabled) { \ - lua_properties_level = lua_properties_level + 1 ; \ - if (lua_properties_level == 1) { \ - lua_get_metatablelua_l(Luas,node_properties); \ - } \ - } \ -} while(0) - -#define lua_properties_pop do { \ - if (lua_properties_enabled) { \ - if (lua_properties_level == 1) \ - lua_pop(Luas,1); \ - lua_properties_level = lua_properties_level - 1 ; \ - } \ -} while(0) - -/*tex No setting is needed: */ - -#define lua_properties_set(target) do { \ -} while(0) - -/*tex Resetting boils down to nilling. */ - -#define lua_properties_reset(target) do { \ - if (lua_properties_enabled) { \ - if (lua_properties_level == 0) { \ - lua_get_metatablelua_l(Luas,node_properties); \ - lua_pushnil(Luas); \ - lua_rawseti(Luas,-2,target); \ - lua_pop(Luas,1); \ - } else { \ - lua_pushnil(Luas); \ - lua_rawseti(Luas,-2,target); \ - } \ - } \ -} while(0) - -/*tex - - For a moment I considered supporting all kind of data types but in practice - that makes no sense. So we stick to a cheap shallow copy with as option a - metatable. BTW, a deep copy would look like this: - - \starttyping - static void copy_lua_table(lua_State* L, int index) { - lua_newtable(L); - lua_pushnil(L); - while(lua_next(L, index-1) != 0) { - lua_pushvalue(L, -2); - lua_insert(L, -2); - if (lua_type(L,-1)==LUA_TTABLE) - copy_lua_table(L,-1); - lua_settable(L, -4); - } - lua_pop(L,1); - } - - #define lua_properties_copy(target, source) do { \ - if (lua_properties_enabled) { \ - lua_pushinteger(Luas,source); \ - lua_rawget(Luas,-2); \ - if (lua_type(Luas,-1)==LUA_TTABLE) { \ - copy_lua_table(Luas,-1); \ - lua_pushinteger(Luas,target); \ - lua_insert(Luas,-2); \ - lua_rawset(Luas,-3); \ - } else { \ - lua_pop(Luas,1); \ - } \ - } \ - } while(0) - \stoptyping - -*/ - -/*tex Isn't there a faster way to metatable? */ - -/*tex - - \starttyping - #define lua_properties_copy(target,source) do { \ - if (lua_properties_enabled) { \ - if (lua_properties_level == 0) { \ - lua_get_metatablelua_l(Luas,node_properties); \ - lua_rawgeti(Luas,-1,source); \ - if (lua_type(Luas,-1)==LUA_TTABLE) { \ - if (lua_properties_use_metatable) { \ - lua_newtable(Luas); \ - lua_insert(Luas,-2); \ - lua_setfield(Luas,-2,"__index"); \ - lua_newtable(Luas); \ - lua_insert(Luas,-2); \ - lua_setmetatable(Luas,-2); \ - } \ - lua_rawseti(Luas,-2,target); \ - } else { \ - lua_pop(Luas,1); \ - } \ - lua_pop(Luas,1); \ - } else { \ - lua_rawgeti(Luas,-1,source); \ - if (lua_type(Luas,-1)==LUA_TTABLE) { \ - if (lua_properties_use_metatable) { \ - lua_newtable(Luas); \ - lua_insert(Luas,-2); \ - lua_setfield(Luas,-2,"__index"); \ - lua_newtable(Luas); \ - lua_insert(Luas,-2); \ - lua_setmetatable(Luas,-2); \ - } \ - lua_rawseti(Luas,-2,target); \ - } else { \ - lua_pop(Luas,1); \ - } \ - } \ - } \ - } while(0) - \stoptyping - -*/ - -/*tex - - A simple testrun on many pages of dumb text shows 1% gain (of course it - depends on how properties are used but some other tests confirm it). - -*/ - -#define lua_properties_copy(target,source) do { \ - if (lua_properties_enabled) { \ - if (lua_properties_level == 0) { \ - lua_get_metatablelua_l(Luas,node_properties); \ - lua_rawgeti(Luas,-1,source); \ - if (lua_type(Luas,-1)==LUA_TTABLE) { \ - if (lua_properties_use_metatable) { \ - lua_newtable(Luas); \ - lua_insert(Luas,-2); \ - lua_push_string_by_name(Luas,__index); \ - lua_insert(Luas,-2); \ - lua_rawset(Luas, -3); \ - lua_newtable(Luas); \ - lua_insert(Luas,-2); \ - lua_setmetatable(Luas,-2); \ - } \ - lua_rawseti(Luas,-2,target); \ - } else { \ - lua_pop(Luas,1); \ - } \ - lua_pop(Luas,1); \ - } else { \ - lua_rawgeti(Luas,-1,source); \ - if (lua_type(Luas,-1)==LUA_TTABLE) { \ - if (lua_properties_use_metatable) { \ - lua_newtable(Luas); \ - lua_insert(Luas,-2); \ - lua_push_string_by_name(Luas,__index); \ - lua_insert(Luas,-2); \ - lua_rawset(Luas, -3); \ - lua_newtable(Luas); \ - lua_insert(Luas,-2); \ - lua_setmetatable(Luas,-2); \ - } \ - lua_rawseti(Luas,-2,target); \ - } else { \ - lua_pop(Luas,1); \ - } \ - } \ - } \ -} while(0) - -/*tex Here end the property handlers. */ - -int valid_node(halfword p) -{ - if (p > my_prealloc && p < var_mem_max) { -#ifdef CHECK_NODE_USAGE - if (varmem_sizes[p] > 0) { - return 1; - } -#else - return 1; -#endif - } - return 0; -} - -static int test_count = 1; - -#define dorangetest(a,b,c) do { \ - if (!(b>=0 && b<c)) { \ - fprintf(stdout,"For node p:=%d, 0<=%d<%d (l.%d,r.%d)\n", \ - (int)a, (int)b, (int)c, __LINE__,test_count); \ - confusion("node range test failed"); \ - } } while (0) - -#define dotest(a,b,c) do { \ - if (b!=c) { \ - fprintf(stdout,"For node p:=%d, %d==%d (l.%d,r.%d)\n", \ - (int)a, (int)b, (int)c, __LINE__,test_count); \ - confusion("node test failed"); \ - } } while (0) - -#define check_action_ref(a) { dorangetest(p,a,var_mem_max); } -#define check_attribute_ref(a) { dorangetest(p,a,var_mem_max); } - -/*tex hm, we can just pass |p| then. */ - -#define check_token_ref(p) { \ - if (type(p) == whatsit_node) { \ - formatted_error("nodes","fuzzy token cleanup in whatsit node with type %s and subtype %i",node_data[type(p)].name,subtype(p)); \ - } else { \ - formatted_error("nodes","fuzzy token cleanup in node with type %s",node_data[type(p)].name); \ - } \ -} - -#ifdef CHECK_NODE_USAGE - -static void check_static_node_mem(void) -{ - dotest(zero_glue, width(zero_glue), 0); - dotest(zero_glue, type(zero_glue), glue_spec_node); - dotest(zero_glue, vlink(zero_glue), null); - dotest(zero_glue, stretch(zero_glue), 0); - dotest(zero_glue, stretch_order(zero_glue), normal); - dotest(zero_glue, shrink(zero_glue), 0); - dotest(zero_glue, shrink_order(zero_glue), normal); - - dotest(sfi_glue, width(sfi_glue), 0); - dotest(sfi_glue, type(sfi_glue), glue_spec_node); - dotest(sfi_glue, vlink(sfi_glue), null); - dotest(sfi_glue, stretch(sfi_glue), 0); - dotest(sfi_glue, stretch_order(sfi_glue), sfi); - dotest(sfi_glue, shrink(sfi_glue), 0); - dotest(sfi_glue, shrink_order(sfi_glue), normal); - - dotest(fil_glue, width(fil_glue), 0); - dotest(fil_glue, type(fil_glue), glue_spec_node); - dotest(fil_glue, vlink(fil_glue), null); - dotest(fil_glue, stretch(fil_glue), unity); - dotest(fil_glue, stretch_order(fil_glue), fil); - dotest(fil_glue, shrink(fil_glue), 0); - dotest(fil_glue, shrink_order(fil_glue), normal); - - dotest(fill_glue, width(fill_glue), 0); - dotest(fill_glue, type(fill_glue), glue_spec_node); - dotest(fill_glue, vlink(fill_glue), null); - dotest(fill_glue, stretch(fill_glue), unity); - dotest(fill_glue, stretch_order(fill_glue), fill); - dotest(fill_glue, shrink(fill_glue), 0); - dotest(fill_glue, shrink_order(fill_glue), normal); - - dotest(ss_glue, width(ss_glue), 0); - dotest(ss_glue, type(ss_glue), glue_spec_node); - dotest(ss_glue, vlink(ss_glue), null); - dotest(ss_glue, stretch(ss_glue), unity); - dotest(ss_glue, stretch_order(ss_glue), fil); - dotest(ss_glue, shrink(ss_glue), unity); - dotest(ss_glue, shrink_order(ss_glue), fil); - - dotest(fil_neg_glue, width(fil_neg_glue), 0); - dotest(fil_neg_glue, type(fil_neg_glue), glue_spec_node); - dotest(fil_neg_glue, vlink(fil_neg_glue), null); - dotest(fil_neg_glue, stretch(fil_neg_glue), -unity); - dotest(fil_neg_glue, stretch_order(fil_neg_glue), fil); - dotest(fil_neg_glue, shrink(fil_neg_glue), 0); - dotest(fil_neg_glue, shrink_order(fil_neg_glue), normal); -} - -static void node_mem_dump(halfword p) -{ - halfword r; - for (r = my_prealloc + 1; r < var_mem_max; r++) { - if (vlink(r) == p) { - halfword s = r; - while (s > my_prealloc && varmem_sizes[s] == 0) { - s--; - } - if (s != null - && s != my_prealloc - && s != var_mem_max - && (r - s) < get_node_size(type(s), subtype(s)) - && alink(s) != p) { - if (type(s) == disc_node) { - fprintf(stdout," pointed to from %s node %d (vlink %d, alink %d): ", - get_node_name(type(s), subtype(s)), (int) s, - (int) vlink(s), (int) alink(s)); - fprintf(stdout, "pre_break(%d,%d,%d), ", - (int) vlink_pre_break(s), (int) tlink(pre_break(s)), - (int) alink(pre_break(s))); - fprintf(stdout, "post_break(%d,%d,%d), ", - (int) vlink_post_break(s), - (int) tlink(post_break(s)), - (int) alink(post_break(s))); - fprintf(stdout, "no_break(%d,%d,%d)", - (int) vlink_no_break(s), (int) tlink(no_break(s)), - (int) alink(no_break(s))); - fprintf(stdout, "\n"); - } else { - if (vlink(s) == p - || (type(s) == glyph_node && lig_ptr (s) == p) - || (type(s) == vlist_node && list_ptr(s) == p) - || (type(s) == hlist_node && list_ptr(s) == p) - || (type(s) == unset_node && list_ptr(s) == p) - || (type(s) == ins_node && ins_ptr (s) == p) - ) { - fprintf(stdout," pointed to from %s node %d (vlink %d, alink %d): ", - get_node_name(type(s), subtype(s)), (int) s, - (int) vlink(s), (int) alink(s)); - if (type(s) == glyph_node) { - fprintf(stdout, "lig_ptr(%d)", (int) lig_ptr(s)); - } else if (type(s) == vlist_node || type(s) == hlist_node) { - fprintf(stdout, "list_ptr(%d)", (int) list_ptr(s)); - } - fprintf(stdout, "\n"); - } else { - if ((type(s) != penalty_node) && (type(s) != math_node) && (type(s) != kern_node)) { - fprintf(stdout, " pointed to from %s node %d\n", - get_node_name(type(s), subtype(s)), (int) s); - } - } - } - } - } - } -} - -#endif - -static int free_error(halfword p) -{ - if (p > my_prealloc && p < var_mem_max) { -#ifdef CHECK_NODE_USAGE - int i; - if (varmem_sizes[p] == 0) { - check_static_node_mem(); - for (i = (my_prealloc + 1); i < var_mem_max; i++) { - if (varmem_sizes[i] > 0) { - check_node(i); - } - } - test_count++; - if (type(p) == glyph_node) { - formatted_error("nodes", "attempt to double-free glyph (%c) node %d, ignored", (int) character(p), (int) p); - } else { - formatted_error("nodes", "attempt to double-free %s node %d, ignored", get_node_name(type(p), subtype(p)), (int) p); - } - node_mem_dump(p); - return 1; - } -#endif - } else { - formatted_error("nodes", "attempt to free an impossible node %d", (int) p); - return 1; - } - return 0; -} - -static int copy_error(halfword p) -{ - if (p >= 0 && p < var_mem_max) { -#ifdef CHECK_NODE_USAGE - if (p > my_prealloc && varmem_sizes[p] == 0) { - if (type(p) == glyph_node) { - formatted_warning("nodes", "attempt to copy free glyph (%c) node %d, ignored", (int) character(p), (int) p); - } else { - formatted_warning("nodes", "attempt to copy free %s node %d, ignored", get_node_name(type(p), subtype(p)), (int) p); - } - return 1; - } -#endif - } else { - formatted_error("nodes", "attempt to copy an impossible node %d", (int) p); - return 1; - } - return 0; -} - -/*tex - - Because of the 5-10\% overhead that \SYNTEX\ creates some options have been - implemented controlled by |synctex_anyway_mode|. - - \startabulate - \NC \type {1} \NC all but glyphs \NC \NR - \NC \type {2} \NC also glyphs \NC \NR - \NC \type {3} \NC glyphs and glue \NC \NR - \NC \type {4} \NC only glyphs \NC \NR - \stoptabulate - -*/ - -static halfword synctex_anyway_mode = 0; -static halfword synctex_line_field = 0; -static halfword synctex_no_files = 0; - -void synctex_set_mode(int m) -{ - synctex_anyway_mode = m; -}; - -int synctex_get_mode(void) -{ - return synctex_anyway_mode; -}; - -void synctex_set_no_files(int f) -{ - synctex_no_files = f; -}; - -int synctex_get_no_files(void) -{ - return (int) synctex_no_files ; -}; - -void synctex_set_tag(int t) -{ - cur_input.synctex_tag_field = t; -}; - -int synctex_get_tag(void) -{ - return (int) cur_input.synctex_tag_field; -}; - -int synctex_get_line(void) -{ - return (int) synctex_line_field; -}; - -static int forced_tag = 0; -static int forced_line = 0; - -void synctex_force_tag(int t) -{ - forced_tag = t; -}; - -void synctex_force_line(int t) -{ - forced_line = t; -}; - -void synctex_set_line(int l) -{ - synctex_line_field = l; -}; - -/*tex |if_stack| is called a lot so maybe optimize that one. */ - -halfword new_node(int i, int j) -{ - int s = get_node_size(i, j); - halfword n = get_node(s); - /*tex - - It should be possible to do this memset at |free_node()|. Both type() and - subtype() will be set below, and vlink() is set to null by |get_node()|, - so we can do we clearing one word less than |s|. - - */ - (void) memset((void *) (varmem + n + 1), 0, (sizeof(memory_word) * ((unsigned) s - 1))); - switch (i) { - case glyph_node: - init_lang_data(n); - break; - case hlist_node: - case vlist_node: - box_dir(n) = -1; - break; - case disc_node: - pre_break(n) = pre_break_head(n); - type(pre_break(n)) = nesting_node; - subtype(pre_break(n)) = pre_break_head(0); - post_break(n) = post_break_head(n); - type(post_break(n)) = nesting_node; - subtype(post_break(n)) = post_break_head(0); - no_break(n) = no_break_head(n); - type(no_break(n)) = nesting_node; - subtype(no_break(n)) = no_break_head(0); - break; - case rule_node: - depth(n) = null_flag; - height(n) = null_flag; - width(n) = null_flag; - rule_dir(n) = -1; - rule_index(n) = 0; - rule_transform(n) = 0; - break; - case whatsit_node: - if (j == open_node) { - open_name(n) = get_nullstr(); - open_area(n) = open_name(n); - open_ext(n) = open_name(n); - } - break; - case unset_node: - width(n) = null_flag; - break; - case pseudo_line_node: - case shape_node: - /*tex - - This is a trick that makes |pseudo_files| slightly slower, but - the overall allocation faster then an explicit test at the top of - |new_node()|. - - */ - if (j>0) { - free_node(n, variable_node_size); - n = slow_get_node(j); - (void) memset((void *) (varmem + n + 1), 0, (sizeof(memory_word) * ((unsigned) j - 1))); - } - break; - case fraction_noad: - fraction_fam(n) = -1; - break; - case simple_noad: - noad_fam(n) = -1; - break; - default: - break; - } - if (synctex_anyway_mode) { - /*tex See table above. */ - switch (i) { - case glyph_node: - if (synctex_anyway_mode > 1) { - synctex_tag_glyph(n) = forced_tag ? forced_tag : cur_input.synctex_tag_field; - synctex_line_glyph(n) = forced_line ? forced_line : synctex_line_field ? synctex_line_field : line; - } - break; - case glue_node: - if (synctex_anyway_mode < 4) { - synctex_tag_glue(n) = forced_tag ? forced_tag : cur_input.synctex_tag_field; - synctex_line_glue(n) = forced_line ? forced_line : synctex_line_field ? synctex_line_field : line; - } - break; - case kern_node: - if (synctex_anyway_mode < 3) { - synctex_tag_kern(n) = forced_tag ? forced_tag : cur_input.synctex_tag_field; - synctex_line_kern(n) = forced_line ? forced_line : synctex_line_field ? synctex_line_field : line; - } - break; - case hlist_node: - case vlist_node: - case unset_node: - /*tex Rather useless: */ - if (synctex_anyway_mode < 3) { - synctex_tag_box(n) = forced_tag ? forced_tag : cur_input.synctex_tag_field; - synctex_line_box(n) = forced_line ? forced_line : synctex_line_field ? synctex_line_field : line; - } - break; - case rule_node: - if (synctex_anyway_mode < 3) { - synctex_tag_rule(n) = forced_tag ? forced_tag : cur_input.synctex_tag_field; - synctex_line_rule(n) = forced_line ? forced_line : synctex_line_field ? synctex_line_field : line; - } - break; - case math_node: - /*tex Noads probably make more sense but let's not change that. */ - if (synctex_anyway_mode < 3) { - synctex_tag_math(n) = forced_tag ? forced_tag : cur_input.synctex_tag_field; - synctex_line_math(n) = forced_line ? forced_line : synctex_line_field ? synctex_line_field : line; - } - break; - } - } else if (synctex_par) { - /*tex Handle the \SYNTEX\ extension. */ - switch (i) { - case glue_node: - synctex_tag_glue(n) = cur_input.synctex_tag_field; - synctex_line_glue(n) = line; - break; - case kern_node: - if (j != 0) { - synctex_tag_kern(n) = cur_input.synctex_tag_field; - synctex_line_kern(n) = line; - } - break; - case hlist_node: - case vlist_node: - case unset_node: - synctex_tag_box(n) = cur_input.synctex_tag_field; - synctex_line_box(n) = line; - break; - case rule_node: - synctex_tag_rule(n) = cur_input.synctex_tag_field; - synctex_line_rule(n) = line; - break; - case math_node: - synctex_tag_math(n) = cur_input.synctex_tag_field; - synctex_line_math(n) = line; - break; - } - } - /*tex Take care of attributes. */ - if (nodetype_has_attributes(i)) { - build_attribute_list(n); - /*tex No need for |lua_properties_set|. */ - } - type(n) = (quarterword) i; - subtype(n) = (quarterword) j; - return n; -} - -halfword raw_glyph_node(void) -{ - register halfword n = get_node(glyph_node_size); - (void) memset((void *) (varmem + n + 1), 0, (sizeof(memory_word) * (glyph_node_size - 1))); - if (synctex_anyway_mode > 1) { - synctex_tag_glyph(n) = forced_tag ? forced_tag : cur_input.synctex_tag_field; - synctex_line_glyph(n) = forced_line ? forced_line : synctex_line_field ? synctex_line_field : line; - } - type(n) = glyph_node; - subtype(n) = 0; - return n; -} - -halfword new_glyph_node(void) -{ - register halfword n = get_node(glyph_node_size); - (void) memset((void *) (varmem + n + 1), 0, (sizeof(memory_word) * (glyph_node_size - 1))); - if (synctex_anyway_mode > 1) { - synctex_tag_glyph(n) = forced_tag ? forced_tag : cur_input.synctex_tag_field; - synctex_line_glyph(n) = forced_line ? forced_line : synctex_line_field ? synctex_line_field : line; - } - type(n) = glyph_node; - subtype(n) = 0; - build_attribute_list(n); - /*tex No need for |lua_properties_set|. */ - return n; -} - -/*tex - - This makes a duplicate of the node list that starts at |p| and returns a - pointer to the new list. - -*/ - -halfword do_copy_node_list(halfword p, halfword end) -{ - /*tex previous position in new list */ - halfword q = null; - /*tex head of the list */ - halfword h = null; - register halfword s ; - /*tex saves stack and time */ - lua_properties_push; - while (p != end) { - s = copy_node(p); - if (h == null) { - h = s; - } else { - couple_nodes(q, s); - } - q = s; - p = vlink(p); - } - /*tex saves stack and time */ - lua_properties_pop; - return h; -} - -halfword copy_node_list(halfword p) -{ - return do_copy_node_list(p, null); -} - -#define copy_sub_list(target,source) do { \ - if (source != null) { \ - s = do_copy_node_list(source, null); \ - target = s; \ - } else { \ - target = null; \ - } \ - } while (0) - -#define copy_sub_node(target,source) do { \ - if (source != null) { \ - s = copy_node(source); \ - target = s ; \ - } else { \ - target = null; \ - } \ -} while (0) - -/*tex Make a dupe of a single node. */ - -static void copy_node_wrapup_core(halfword p, halfword r) -{ - halfword s ; - switch (subtype(p)) { - case write_node: - case special_node: - add_token_ref(write_tokens(p)); - break; - case late_lua_node: - copy_late_lua(r, p); - break; - case user_defined_node: - switch (user_node_type(p)) { - case 'a': - add_node_attr_ref(user_node_value(p)); - break; - case 'l': - copy_user_lua(r, p); - break; - case 'n': - s = copy_node_list(user_node_value(p)); - user_node_value(r) = s; - break; - case 's': - /* |add_string_ref(user_node_value(p));| */ - break; - case 't': - add_token_ref(user_node_value(p)); - break; - } - break; - default: - break ; - } -} - -void copy_node_wrapup_dvi(halfword p, halfword r) -{ -} - -void copy_node_wrapup_pdf(halfword p, halfword r) -{ - switch(subtype(p)) { - case pdf_literal_node: - copy_pdf_literal(r, p); - break; - case pdf_colorstack_node: - if (pdf_colorstack_cmd(p) <= colorstack_data) - add_token_ref(pdf_colorstack_data(p)); - break; - case pdf_setmatrix_node: - add_token_ref(pdf_setmatrix_data(p)); - break; - case pdf_annot_node: - add_token_ref(pdf_annot_data(p)); - break; - case pdf_start_link_node: - if (pdf_link_attr(r) != null) - add_token_ref(pdf_link_attr(r)); - add_action_ref(pdf_link_action(r)); - break; - case pdf_dest_node: - if (pdf_dest_named_id(p) > 0) - add_token_ref(pdf_dest_id(p)); - break; - case pdf_thread_node: - case pdf_start_thread_node: - if (pdf_thread_named_id(p) > 0) - add_token_ref(pdf_thread_id(p)); - if (pdf_thread_attr(p) != null) - add_token_ref(pdf_thread_attr(p)); - break; - default: - break; - } -} - -halfword copy_node(const halfword p) -{ - /*tex current node being fabricated for new list */ - halfword r; - /*tex whatsit subtype */ - halfword w; - /*tex type of node */ - halfword t; - /*tex a helper variable for copying into variable mem */ - register halfword s; - register int i; - if (copy_error(p)) { - r = new_node(temp_node, 0); - return r; - } - t = type(p); - i = get_node_size(t,subtype(p)); - r = get_node(i); - (void) memcpy((void *) (varmem + r), (void *) (varmem + p), (sizeof(memory_word) * (unsigned) i)); - /*tex A possible speedup: - - \starttyping - if t == glue_spec) { - return r; - } - \stoptyping - - */ - if (synctex_anyway_mode) { - /*tex Not: - - \starttyping - if (t == glyph_node) { - if (synctex_anyway_mode > 1) { - synctex_tag_glyph(r) = forced_tag ? forced_tag : cur_input.synctex_tag_field; - synctex_line_glyph(r) = forced_line ? forced_line : synctex_line_field ? synctex_line_field : line; - } - } - \stoptyping - */ - } else if (synctex_par) { - /*tex Handle synctex extension. */ - switch (t) { - case math_node: - synctex_tag_math(r) = cur_input.synctex_tag_field; - synctex_line_math(r) = line; - break; - case kern_node: - synctex_tag_kern(r) = cur_input.synctex_tag_field; - synctex_line_kern(r) = line; - break; - } - } - if (nodetype_has_attributes(t)) { - add_node_attr_ref(node_attr(p)); - alink(r) = null; - lua_properties_copy(r,p); - } - vlink(r) = null; - switch (t) { - case glyph_node: - copy_sub_list(lig_ptr(r),lig_ptr(p)) ; - break; - case glue_node: - copy_sub_list(leader_ptr(r),leader_ptr(p)) ; - break; - case hlist_node: - case vlist_node: - case unset_node: - copy_sub_list(list_ptr(r),list_ptr(p)) ; - break; - case disc_node: - pre_break(r) = pre_break_head(r); - if (vlink_pre_break(p) != null) { - s = copy_node_list(vlink_pre_break(p)); - alink(s) = pre_break(r); - tlink_pre_break(r) = tail_of_list(s); - vlink_pre_break(r) = s; - } else { - assert(tlink(pre_break(r)) == null); - } - post_break(r) = post_break_head(r); - if (vlink_post_break(p) != null) { - s = copy_node_list(vlink_post_break(p)); - alink(s) = post_break(r); - tlink_post_break(r) = tail_of_list(s); - vlink_post_break(r) = s; - } else { - assert(tlink_post_break(r) == null); - } - no_break(r) = no_break_head(r); - if (vlink(no_break(p)) != null) { - s = copy_node_list(vlink_no_break(p)); - alink(s) = no_break(r); - tlink_no_break(r) = tail_of_list(s); - vlink_no_break(r) = s; - } else { - assert(tlink_no_break(r) == null); - } - break; - case math_node: - break; - case ins_node: - copy_sub_list(ins_ptr(r),ins_ptr(p)) ; - break; - case margin_kern_node: - copy_sub_node(margin_char(r),margin_char(p)); - break; - case mark_node: - add_token_ref(mark_ptr(p)); - break; - case adjust_node: - copy_sub_list(adjust_ptr(r),adjust_ptr(p)); - break; - case choice_node: - copy_sub_list(display_mlist(r),display_mlist(p)) ; - copy_sub_list(text_mlist(r),text_mlist(p)) ; - copy_sub_list(script_mlist(r),script_mlist(p)) ; - copy_sub_list(script_script_mlist(r),script_script_mlist(p)) ; - break; - case simple_noad: - copy_sub_list(nucleus(r),nucleus(p)) ; - copy_sub_list(subscr(r),subscr(p)) ; - copy_sub_list(supscr(r),supscr(p)) ; - break; - case radical_noad: - copy_sub_list(nucleus(r),nucleus(p)) ; - copy_sub_list(subscr(r),subscr(p)) ; - copy_sub_list(supscr(r),supscr(p)) ; - copy_sub_node(left_delimiter(r),left_delimiter(p)) ; - copy_sub_list(degree(r),degree(p)) ; - break; - case accent_noad: - copy_sub_list(nucleus(r),nucleus(p)) ; - copy_sub_list(subscr(r),subscr(p)) ; - copy_sub_list(supscr(r),supscr(p)) ; - copy_sub_list(top_accent_chr(r),top_accent_chr(p)) ; - copy_sub_list(bot_accent_chr(r),bot_accent_chr(p)) ; - copy_sub_list(overlay_accent_chr(r),overlay_accent_chr(p)) ; - break; - case fence_noad: - copy_sub_node(delimiter(r),delimiter(p)) ; - break; - case sub_box_node: - case sub_mlist_node: - copy_sub_list(math_list(r),math_list(p)) ; - break; - case fraction_noad: - copy_sub_list(numerator(r),numerator(p)) ; - copy_sub_list(denominator(r),denominator(p)) ; - copy_sub_node(left_delimiter(r),left_delimiter(p)) ; - copy_sub_node(right_delimiter(r),right_delimiter(p)) ; - break; - case glue_spec_node: - break; - case dir_node: - break; - case local_par_node: - copy_sub_list(local_box_left(r),local_box_left(p)); - copy_sub_list(local_box_right(r),local_box_right(p)); - case boundary_node: - break; - case whatsit_node: - w = subtype(p) ; - if (w >= backend_first_pdf_whatsit) { - copy_node_wrapup_pdf(p,r); - } else if (w >= backend_first_dvi_whatsit) { - copy_node_wrapup_dvi(p,r); - } else { - copy_node_wrapup_core(p,r); - } - break; - } - return r; -} - -#define free_sub_list(source) if (source != null) flush_node_list(source); -#define free_sub_node(source) if (source != null) flush_node(source); - -static void flush_node_wrapup_core(halfword p) -{ - switch (subtype(p)) { - case open_node: - case write_node: - case close_node: - case save_pos_node: - break; - case special_node: - delete_token_ref(write_tokens(p)); - break; - case late_lua_node: - free_late_lua(p); - break; - case user_defined_node: - switch (user_node_type(p)) { - case 'a': - delete_attribute_ref(user_node_value(p)); - break; - case 'd': - break; - case 'l': - free_user_lua(p); - break; - case 'n': - flush_node_list(user_node_value(p)); - break; - case 's': - /*tex |delete_string_ref(user_node_value(p));| *//* if this was mpost .. */ - break; - case 't': - delete_token_ref(user_node_value(p)); - break; - default: - { - const char *hlp[] = { - "The type of the value in a user defined whatsit node should be one", - "of 'a' (attribute list), 'd' (number), 'n' (node list), 's' (string),", - "or 't' (tokenlist). Yours has an unknown type, and therefore I don't", - "know how to free the node's value. A memory leak may result.", - NULL - }; - tex_error("Unidentified user defined whatsit", hlp); - } - break; - } - break; - } -} - -void flush_node_wrapup_dvi(halfword p) -{ -} - -void flush_node_wrapup_pdf(halfword p) -{ - switch(subtype(p)) { - case pdf_save_node: - case pdf_restore_node: - case pdf_link_state_node: - case pdf_refobj_node: - case pdf_end_link_node: - case pdf_end_thread_node: - break; - case pdf_literal_node: - free_pdf_literal(p); - break; - case pdf_colorstack_node: - if (pdf_colorstack_cmd(p) <= colorstack_data) - delete_token_ref(pdf_colorstack_data(p)); - break; - case pdf_setmatrix_node: - delete_token_ref(pdf_setmatrix_data(p)); - break; - case pdf_annot_node: - delete_token_ref(pdf_annot_data(p)); - break; - case pdf_link_data_node: - break; - case pdf_start_link_node: - if (pdf_link_attr(p) != null) - delete_token_ref(pdf_link_attr(p)); - delete_action_ref(pdf_link_action(p)); - break; - case pdf_dest_node: - if (pdf_dest_named_id(p) > 0) - delete_token_ref(pdf_dest_id(p)); - break; - case pdf_action_node: - if (pdf_action_type(p) == pdf_action_user) { - delete_token_ref(pdf_action_tokens(p)); - } else { - if (pdf_action_file(p) != null) - delete_token_ref(pdf_action_file(p)); - if (pdf_action_type(p) == pdf_action_page) - delete_token_ref(pdf_action_tokens(p)); - else if (pdf_action_named_id(p) > 0) - delete_token_ref(pdf_action_id(p)); - } - break; - case pdf_thread_data_node: - break; - case pdf_thread_node: - case pdf_start_thread_node: - if (pdf_thread_named_id(p) > 0) - delete_token_ref(pdf_thread_id(p)); - if (pdf_thread_attr(p) != null) - delete_token_ref(pdf_thread_attr(p)); - break; - } -} - -void flush_node(halfword p) -{ - halfword w; - if (p == null){ - /*tex legal, but no-op. */ - return; - } - if (free_error(p)) - return; - switch (type(p)) { - case glyph_node: - free_sub_list(lig_ptr(p)); - break; - case glue_node: - free_sub_list(leader_ptr(p)); - break; - case hlist_node: - case vlist_node: - case unset_node: - free_sub_list(list_ptr(p)); - break; - case disc_node: - /*tex Watch the start at temp node hack! */ - free_sub_list(vlink(pre_break(p))); - free_sub_list(vlink(post_break(p))); - free_sub_list(vlink(no_break(p))); - break; - case rule_node: - case kern_node: - case penalty_node: - case math_node: - break; - case glue_spec_node: - /*tex This allows free-ing of lua-allocated glue specs. */ - break ; - case dir_node: - break; - case local_par_node: - free_sub_list(local_box_left(p)); - free_sub_list(local_box_right(p)); - break; - case boundary_node: - break; - case whatsit_node: - w = subtype(p) ; - if (w >= backend_first_pdf_whatsit) { - flush_node_wrapup_pdf(p); - } else if (w >= backend_first_dvi_whatsit) { - flush_node_wrapup_dvi(p); - } else { - flush_node_wrapup_core(p); - } - break; - case ins_node: - flush_node_list(ins_ptr(p)); - break; - case margin_kern_node: - flush_node(margin_char(p)); - break; - case mark_node: - delete_token_ref(mark_ptr(p)); - break; - case adjust_node: - flush_node_list(adjust_ptr(p)); - break; - case style_node: - /*tex Nothing to do. */ - break; - case choice_node: - free_sub_list(display_mlist(p)); - free_sub_list(text_mlist(p)); - free_sub_list(script_mlist(p)); - free_sub_list(script_script_mlist(p)); - break; - case simple_noad: - free_sub_list(nucleus(p)); - free_sub_list(subscr(p)); - free_sub_list(supscr(p)); - break; - case radical_noad: - free_sub_list(nucleus(p)); - free_sub_list(subscr(p)); - free_sub_list(supscr(p)); - free_sub_node(left_delimiter(p)); - free_sub_list(degree(p)); - break; - case accent_noad: - free_sub_list(nucleus(p)); - free_sub_list(subscr(p)); - free_sub_list(supscr(p)); - free_sub_list(top_accent_chr(p)); - free_sub_list(bot_accent_chr(p)); - free_sub_list(overlay_accent_chr(p)); - break; - case fence_noad: - free_sub_list(delimiter(p)); - break; - case delim_node: - case math_char_node: - case math_text_char_node: - /*tex Nothing to do. */ - break; - case sub_box_node: - case sub_mlist_node: - free_sub_list(math_list(p)); - break; - case fraction_noad: - free_sub_list(numerator(p)); - free_sub_list(denominator(p)); - free_sub_node(left_delimiter(p)); - free_sub_node(right_delimiter(p)); - break; - case pseudo_file_node: - free_sub_list(pseudo_lines(p)); - break; - case pseudo_line_node: - case shape_node: - free_node(p, subtype(p)); - return; - break; - case align_stack_node: - case span_node: - case movement_node: - case if_node: - case nesting_node: - case unhyphenated_node: - case hyphenated_node: - case delta_node: - case passive_node: - case inserting_node: - case split_up_node: - case expr_node: - case attribute_node: - case attribute_list_node: - case temp_node: - break; - default: - formatted_error("nodes","flushing weird node type %d", type(p)); - return; - } - if (nodetype_has_attributes(type(p))) { - delete_attribute_ref(node_attr(p)); - lua_properties_reset(p); - } - free_node(p, get_node_size(type(p), subtype(p))); - return; -} - -/*tex Erase the list of nodes starting at |pp|. */ - -void flush_node_list(halfword pp) -{ - register halfword p = pp; - if (p == null) { - /*tex Legal, but no-op. */ - return; - } - if (free_error(p)) - return; - /*tex Saves stack and time. */ - lua_properties_push; - while (p != null) { - register halfword q = vlink(p); - flush_node(p); - p = q; - } - /*tex Saves stack and time. */ - lua_properties_pop; -} - -static void check_node_wrapup_core(halfword p) -{ - switch (subtype(p)) { - /*tex Frontend code. */ - case special_node: - check_token_ref(p); - break; - case user_defined_node: - switch (user_node_type(p)) { - case 'a': - check_attribute_ref(user_node_value(p)); - break; - case 't': - check_token_ref(p); - break; - case 'n': - dorangetest(p, user_node_value(p), var_mem_max); - break; - case 's': - case 'd': - case 'l': - break; - default: - confusion("unknown user node type"); - break; - } - break; - case open_node: - case write_node: - case close_node: - case save_pos_node: - break; - } -} - -void check_node_wrapup_dvi(halfword p) -{ -} - -void check_node_wrapup_pdf(halfword p) -{ - switch (subtype(p)) { - case pdf_literal_node: - if (pdf_literal_type(p) == normal) - check_token_ref(p); - break; - case pdf_colorstack_node: - if (pdf_colorstack_cmd(p) <= colorstack_data) - check_token_ref(p); - break; - case pdf_setmatrix_node: - check_token_ref(p); - break; - case late_lua_node: - if (late_lua_name(p) > 0) - check_token_ref(p); - if (late_lua_type(p) == normal) - check_token_ref(p); - break; - case pdf_annot_node: - check_token_ref(p); - break; - case pdf_start_link_node: - if (pdf_link_attr(p) != null) - check_token_ref(p); - check_action_ref(pdf_link_action(p)); - break; - case pdf_dest_node: - if (pdf_dest_named_id(p) > 0) - check_token_ref(p); - break; - case pdf_thread_node: - case pdf_start_thread_node: - if (pdf_thread_named_id(p) > 0) - check_token_ref(p); - if (pdf_thread_attr(p) != null) - check_token_ref(p); - break; - case pdf_save_node: - case pdf_restore_node: - case pdf_link_state_node: - case pdf_refobj_node: - case pdf_end_link_node: - case pdf_end_thread_node: - break; - default: - confusion("wrapup pdf nodes"); - break; - } -} - -void check_node(halfword p) -{ - halfword w ; - switch (type(p)) { - case glyph_node: - dorangetest(p, lig_ptr(p), var_mem_max); - break; - case glue_node: - dorangetest(p, leader_ptr(p), var_mem_max); - break; - case hlist_node: - case vlist_node: - case unset_node: - case align_record_node: - dorangetest(p, list_ptr(p), var_mem_max); - break; - case ins_node: - dorangetest(p, ins_ptr(p), var_mem_max); - break; - case whatsit_node: - w = subtype(p) ; - if (w >= backend_first_pdf_whatsit) { - check_node_wrapup_pdf(p); - } else if (w >= backend_first_dvi_whatsit) { - check_node_wrapup_dvi(p); - } else { - check_node_wrapup_core(p); - } - break; - case margin_kern_node: - check_node(margin_char(p)); - break; - case math_node: - break; - case disc_node: - dorangetest(p, vlink(pre_break(p)), var_mem_max); - dorangetest(p, vlink(post_break(p)), var_mem_max); - dorangetest(p, vlink(no_break(p)), var_mem_max); - break; - case adjust_node: - dorangetest(p, adjust_ptr(p), var_mem_max); - break; - case pseudo_file_node: - dorangetest(p, pseudo_lines(p), var_mem_max); - break; - case pseudo_line_node: - case shape_node: - break; - case choice_node: - dorangetest(p, display_mlist(p), var_mem_max); - dorangetest(p, text_mlist(p), var_mem_max); - dorangetest(p, script_mlist(p), var_mem_max); - dorangetest(p, script_script_mlist(p), var_mem_max); - break; - case fraction_noad: - dorangetest(p, numerator(p), var_mem_max); - dorangetest(p, denominator(p), var_mem_max); - dorangetest(p, left_delimiter(p), var_mem_max); - dorangetest(p, right_delimiter(p), var_mem_max); - break; - case simple_noad: - dorangetest(p, nucleus(p), var_mem_max); - dorangetest(p, subscr(p), var_mem_max); - dorangetest(p, supscr(p), var_mem_max); - break; - case radical_noad: - dorangetest(p, nucleus(p), var_mem_max); - dorangetest(p, subscr(p), var_mem_max); - dorangetest(p, supscr(p), var_mem_max); - dorangetest(p, degree(p), var_mem_max); - dorangetest(p, left_delimiter(p), var_mem_max); - break; - case accent_noad: - dorangetest(p, nucleus(p), var_mem_max); - dorangetest(p, subscr(p), var_mem_max); - dorangetest(p, supscr(p), var_mem_max); - dorangetest(p, top_accent_chr(p), var_mem_max); - dorangetest(p, bot_accent_chr(p), var_mem_max); - dorangetest(p, overlay_accent_chr(p), var_mem_max); - break; - case fence_noad: - dorangetest(p, delimiter(p), var_mem_max); - break; - case local_par_node: - dorangetest(p, local_box_left(p), var_mem_max); - dorangetest(p, local_box_right(p), var_mem_max); - break; - /*tex - - There is no need for useless cases: - - \starttyping - case rule_node: - case kern_node: - case penalty_node: - case mark_node: - case style_node: - case attribute_list_node: - case attribute_node: - case glue_spec_node: - case temp_node: - case align_stack_node: - case movement_node: - case if_node: - case nesting_node: - case span_node: - case unhyphenated_node: - case hyphenated_node: - case delta_node: - case passive_node: - case expr_node: - case dir_node: - case boundary_node: - break; - default: - fprintf(stdout, "check_node: type is %d\n", type(p)); - \stoptyping - - */ - } -} - -halfword fix_node_list(halfword head) -{ - halfword next, tail; - if (head == null) - return null; - tail = head; - next = vlink(head); - while (next != null) { - alink(next) = tail; - tail = next; - next = vlink(tail); - } - return tail; -} - -halfword get_node(int s) -{ - register halfword r; - - if (s < MAX_CHAIN_SIZE) { - r = free_chain[s]; - if (r != null) { - free_chain[s] = vlink(r); -#ifdef CHECK_NODE_USAGE - varmem_sizes[r] = (char) s; -#endif - vlink(r) = null; - /*tex Maintain usage statistics. */ - var_used += s; - return r; - } - /*tex This is the end of the \quote {inner loop}. */ - return slow_get_node(s); - } else { - normal_error("nodes","there is a problem in getting a node, case 1"); - return null; - } -} - -void free_node(halfword p, int s) -{ - if (p <= my_prealloc) { - formatted_error("nodes", "node number %d of type %d should not be freed", (int) p, type(p)); - return; - } -#ifdef CHECK_NODE_USAGE - varmem_sizes[p] = 0; -#endif - if (s < MAX_CHAIN_SIZE) { - vlink(p) = free_chain[s]; - free_chain[s] = p; - } else { - /*tex Todo: it is perhaps possible to merge this node with an existing rover? */ - node_size(p) = s; - vlink(p) = rover; - while (vlink(rover) != vlink(p)) { - rover = vlink(rover); - } - vlink(rover) = p; - } - /*tex Maintain statistics. */ - var_used -= s; -} - -static void free_node_chain(halfword q, int s) -{ - register halfword p = q; - while (vlink(p) != null) { -#ifdef CHECK_NODE_USAGE - varmem_sizes[p] = 0; -#endif - var_used -= s; - p = vlink(p); - } - var_used -= s; -#ifdef CHECK_NODE_USAGE - varmem_sizes[p] = 0; -#endif - vlink(p) = free_chain[s]; - free_chain[s] = q; -} - -/*tex - - At the start of the node memory area we reserve some special nodes, for - instance frequently used glue specifications. We could as well just use - new_glue here but for the moment we stick to the traditional approach. - -*/ - -#define initialize_glue(n,wi,st,sh,sto,sho) \ - vlink(n) = null; \ - type(n) = glue_spec_node; \ - width(n) = wi; \ - stretch(n) = st; \ - shrink(n) = sh; \ - stretch_order(n) = sto; \ - shrink_order(n) = sho; - -#define initialize_whatever(n,t) \ - vinfo(n) = 0; \ - type(n) = t; \ - vlink(n) = null; \ - alink(n) = null; - -#define initialize_point(n) \ - type(n) = glyph_node; \ - subtype(n) = 0; \ - vlink(n) = null; \ - vinfo(n + 1) = null; \ - alink(n) = null; \ - font(n) = 0; \ - character(n) = '.'; \ - vinfo(n + 3) = 0; \ - vlink(n + 3) = 0; \ - vinfo(n + 4) = 0; \ - vlink(n + 4) = 0; - -void init_node_mem(int t) -{ - my_prealloc = var_mem_stat_max; - - varmem = (memory_word *) realloc((void *) varmem, sizeof(memory_word) * (unsigned) t); - if (varmem == NULL) { - overflow("node memory size", (unsigned) var_mem_max); - } - memset((void *) (varmem), 0, (unsigned) t * sizeof(memory_word)); -#ifdef CHECK_NODE_USAGE - varmem_sizes = (char *) realloc(varmem_sizes, sizeof(char) * (unsigned) t); - if (varmem_sizes == NULL) { - overflow("node memory size", (unsigned) var_mem_max); - } - memset((void *) varmem_sizes, 0, sizeof(char) * (unsigned) t); -#endif - var_mem_max = t; - rover = var_mem_stat_max + 1; - vlink(rover) = rover; - node_size(rover) = (t - rover); - var_used = 0; - - /*tex Initialize static glue specs. */ - - initialize_glue(zero_glue,0,0,0,0,0); - initialize_glue(sfi_glue,0,0,0,sfi,0); - initialize_glue(fil_glue,0,unity,0,fil,0); - initialize_glue(fill_glue,0,unity,0,fill,0); - initialize_glue(ss_glue,0,unity,unity,fil,fil); - initialize_glue(fil_neg_glue,0,-unity,0,fil,0); - - /*tex Initialize node list heads. */ - - initialize_whatever(page_ins_head,temp_node); - initialize_whatever(contrib_head,temp_node); - initialize_whatever(page_head,temp_node); - initialize_whatever(temp_head,temp_node); - initialize_whatever(hold_head,temp_node); - initialize_whatever(adjust_head,temp_node); - initialize_whatever(pre_adjust_head,temp_node); - initialize_whatever(align_head,temp_node); - - initialize_whatever(active,unhyphenated_node); - initialize_whatever(end_span,span_node); - - initialize_point(begin_point); - initialize_point(end_point); -} - -void dump_node_mem(void) -{ - dump_int(var_mem_max); - dump_int(rover); - dump_things(varmem[0], var_mem_max); -#ifdef CHECK_NODE_USAGE - dump_things(varmem_sizes[0], var_mem_max); -#endif - dump_things(free_chain[0], MAX_CHAIN_SIZE); - dump_int(var_used); - dump_int(my_prealloc); -} - -/*tex - - It makes sense to enlarge the varmem array immediately. - -*/ - -void undump_node_mem(void) -{ - int x; - undump_int(x); - undump_int(rover); - var_mem_max = (x < 100000 ? 100000 : x); - varmem = xmallocarray(memory_word, (unsigned) var_mem_max); - undump_things(varmem[0], x); -#ifdef CHECK_NODE_USAGE - varmem_sizes = xmallocarray(char, (unsigned) var_mem_max); - memset((void *) varmem_sizes, 0, (unsigned) var_mem_max * sizeof(char)); - undump_things(varmem_sizes[0], x); -#endif - undump_things(free_chain[0], MAX_CHAIN_SIZE); - undump_int(var_used); - undump_int(my_prealloc); - if (var_mem_max > x) { - /*tex Todo: is it perhaps possible to merge the new node with an existing rover? */ - vlink(x) = rover; - node_size(x) = (var_mem_max - x); - while (vlink(rover) != vlink(x)) { - rover = vlink(rover); - } - vlink(rover) = x; - } -} - -halfword slow_get_node(int s) -{ - register int t; - - RETRY: - t = node_size(rover); - if (vlink(rover) < var_mem_max && vlink(rover) != 0) { - if (t > s) { - /*tex Allocating from the bottom helps decrease page faults. */ - register halfword r = rover; - rover += s; - vlink(rover) = vlink(r); - node_size(rover) = node_size(r) - s; - if (vlink(rover) != r) { - /*tex The list is longer than one. */ - halfword q = r; - while (vlink(q) != r) { - q = vlink(q); - } - vlink(q) += s; - } else { - vlink(rover) += s; - } - if (vlink(rover) < var_mem_max) { -#ifdef CHECK_NODE_USAGE - varmem_sizes[r] = (char) (s > 127 ? 127 : s); -#endif - vlink(r) = null; - /*tex Maintain usage statistics. */ - var_used += s; - /*tex This is the only exit. */ - return r; - } else { - normal_error("nodes","there is a problem in getting a node, case 2"); - return null; - } - } else { - /*tex Attempt to keep the free list small. */ - int x; - if (vlink(rover) != rover) { - if (t < MAX_CHAIN_SIZE) { - halfword l = vlink(rover); - vlink(rover) = free_chain[t]; - free_chain[t] = rover; - rover = l; - while (vlink(l) != free_chain[t]) { - l = vlink(l); - } - vlink(l) = rover; - goto RETRY; - } else { - halfword l = rover; - while (vlink(rover) != l) { - if (node_size(rover) > s) { - goto RETRY; - } - rover = vlink(rover); - } - } - } - /*tex If we are still here, it was apparently impossible to get a match. */ - x = (var_mem_max >> 2) + s; - varmem = (memory_word *) realloc((void *) varmem, sizeof(memory_word) * (unsigned) (var_mem_max + x)); - if (varmem == NULL) { - overflow("node memory size", (unsigned) var_mem_max); - } - memset((void *) (varmem + var_mem_max), 0, (unsigned) x * sizeof(memory_word)); -#ifdef CHECK_NODE_USAGE - varmem_sizes = (char *) realloc(varmem_sizes, sizeof(char) * (unsigned) (var_mem_max + x)); - if (varmem_sizes == NULL) { - overflow("node memory size", (unsigned) var_mem_max); - } - memset((void *) (varmem_sizes + var_mem_max), 0, (unsigned) (x) * sizeof(char)); -#endif - /*tex Todo: is it perhaps possible to merge the new memory with an existing rover? */ - vlink(var_mem_max) = rover; - node_size(var_mem_max) = x; - while (vlink(rover) != vlink(var_mem_max)) { - rover = vlink(rover); - } - vlink(rover) = var_mem_max; - rover = var_mem_max; - var_mem_max += x; - goto RETRY; - } - } else { - normal_error("nodes","there is a problem in getting a node, case 3"); - return null; - } -} - -char *sprint_node_mem_usage(void) -{ - char *s; -#ifdef CHECK_NODE_USAGE - char *ss; - int i; - int b = 0; - char msg[256]; - int node_counts[last_normal_node + last_whatsit_node + 2] = { 0 }; - s = strdup(""); - for (i = (var_mem_max - 1); i > my_prealloc; i--) { - if (varmem_sizes[i] > 0) { - if (type(i) > last_normal_node + last_whatsit_node) { - node_counts[last_normal_node + last_whatsit_node + 1]++; - } else if (type(i) == whatsit_node) { - node_counts[(subtype(i) + last_normal_node + 1)]++; - } else { - node_counts[type(i)]++; - } - } - } - for (i = 0; i < last_normal_node + last_whatsit_node + 2; i++) { - if (node_counts[i] > 0) { - int j = - (i > (last_normal_node + 1) ? (i - last_normal_node - 1) : 0); - snprintf(msg, 255, "%s%d %s", (b ? ", " : ""), (int) node_counts[i], - get_node_name((i > last_normal_node ? whatsit_node : i), j)); - ss = xmalloc((unsigned) (strlen(s) + strlen(msg) + 1)); - strcpy(ss, s); - strcat(ss, msg); - free(s); - s = ss; - b = 1; - } - } -#else - s = strdup(""); -#endif - return s; -} - -halfword list_node_mem_usage(void) -{ - halfword q = null; -#ifdef CHECK_NODE_USAGE - halfword p = null; - halfword i, j; - char *saved_varmem_sizes = xmallocarray(char, (unsigned) var_mem_max); - memcpy(saved_varmem_sizes, varmem_sizes, (size_t) var_mem_max); - for (i = my_prealloc + 1; i < (var_mem_max - 1); i++) { - if (saved_varmem_sizes[i] > 0) { - j = copy_node(i); - if (p == null) { - q = j; - } else { - vlink(p) = j; - } - p = j; - } - } - free(saved_varmem_sizes); -#endif - return q; -} - -void print_node_mem_stats(void) -{ - int i, b; - halfword j; - char msg[256]; - char *s; - int free_chain_counts[MAX_CHAIN_SIZE] = { 0 }; - snprintf(msg, 255, " %d words of node memory still in use:", (int) (var_used + my_prealloc)); - tprint_nl(msg); - s = sprint_node_mem_usage(); - tprint_nl(" "); - tprint(s); - free(s); - tprint(" nodes"); - tprint_nl(" avail lists: "); - b = 0; - for (i = 1; i < MAX_CHAIN_SIZE; i++) { - for (j = free_chain[i]; j != null; j = vlink(j)) - free_chain_counts[i]++; - if (free_chain_counts[i] > 0) { - snprintf(msg, 255, "%s%d:%d", (b ? "," : ""), i, (int) free_chain_counts[i]); - tprint(msg); - b = 1; - } - } - /*tex A newline, if needed: */ - print_nlp(); -} - -halfword new_span_node(halfword n, int s, scaled w) -{ - halfword p = new_node(span_node, 0); - span_link(p) = n; - span_span(p) = s; - width(p) = w; - return p; -} - -/* Now comes some attribute stuff. */ - -static halfword new_attribute_node(unsigned int i, int v) -{ - register halfword r = get_node(attribute_node_size); - type(r) = attribute_node; - attribute_id(r) = (halfword) i; - attribute_value(r) = v; - /* not used but nicer in print */ - subtype(r) = 0; - return r; -} - -halfword copy_attribute_list(halfword n) -{ - halfword q = get_node(attribute_node_size); - register halfword p = q; - type(p) = attribute_list_node; - attr_list_ref(p) = 0; - n = vlink(n); - while (n != null) { - register halfword r = get_node(attribute_node_size); - /*tex The link will be fixed automatically in the next loop. */ - (void) memcpy((void *) (varmem + r), (void *) (varmem + n), (sizeof(memory_word) * attribute_node_size)); - vlink(p) = r; - p = r; - n = vlink(n); - } - return q; -} - -void update_attribute_cache(void) -{ - halfword p; - register int i; - attr_list_cache = get_node(attribute_node_size); - type(attr_list_cache) = attribute_list_node; - attr_list_ref(attr_list_cache) = 0; - p = attr_list_cache; - for (i = 0; i <= max_used_attr; i++) { - register int v = attribute(i); - if (v > UNUSED_ATTRIBUTE) { - register halfword r = new_attribute_node((unsigned) i, v); - vlink(p) = r; - p = r; - } - } - if (vlink(attr_list_cache) == null) { - free_node(attr_list_cache, attribute_node_size); - attr_list_cache = null; - } - return; -} - -void build_attribute_list(halfword b) -{ - if (max_used_attr >= 0) { - if (attr_list_cache == cache_disabled|| attr_list_cache == null) { - update_attribute_cache(); - if (attr_list_cache == null) - return; - } - attr_list_ref(attr_list_cache)++; - node_attr(b) = attr_list_cache; - } -} - -halfword current_attribute_list(void) -{ - if (max_used_attr >= 0) { - if (attr_list_cache == cache_disabled) { - update_attribute_cache(); - } - return attr_list_cache ; - } - return null ; -} - -void reassign_attribute(halfword n, halfword new) -{ - halfword old; - old = node_attr(n); - if (new == null) { - /*tex There is nothing to assign but we need to check for an old value. */ - if (old != null) { - /*tex This also nulls |attr| field of |n|. */ - delete_attribute_ref(old); - } - } else if (old == null) { - /*tex Nothing is assigned so we just do that now. */ - assign_attribute_ref(n,new); - } else if (old != new) { - /*tex Something is assigned so we need to clean up and assign then. */ - delete_attribute_ref(old); - assign_attribute_ref(n,new); - } - /*tex The same value so there is no need to assign and change the refcount. */ - node_attr(n) = new ; -} - -void delete_attribute_ref(halfword b) -{ - if (b != null) { - if (type(b) == attribute_list_node){ - attr_list_ref(b)--; - if (attr_list_ref(b) == 0) { - if (b == attr_list_cache) - attr_list_cache = cache_disabled; - free_node_chain(b, attribute_node_size); - } - /*tex Maintain sanity. */ - if (attr_list_ref(b) < 0) { - attr_list_ref(b) = 0; - } - } else { - normal_error("nodes","trying to delete an attribute reference of a non attribute node"); - } - } -} - -void reset_node_properties(halfword b) -{ - if (b != null) { - lua_properties_reset(b); - } -} - -/*tex Here |p| is an attr list head, or zero. */ - -halfword do_set_attribute(halfword p, int i, int val) -{ - register halfword q; - register int j = 0; - if (p == null) { - /*tex Add a new head \& node. */ - q = get_node(attribute_node_size); - type(q) = attribute_list_node; - attr_list_ref(q) = 1; - p = new_attribute_node((unsigned) i, val); - vlink(q) = p; - return q; - } - q = p; - if (vlink(p) != null) { - while (vlink(p) != null) { - int t = attribute_id(vlink(p)); - if (t == i && attribute_value(vlink(p)) == val) { - /*tex There is no need to do anything. */ - return q; - } - if (t >= i) - break; - j++; - p = vlink(p); - } - p = q; - while (j-- > 0) - p = vlink(p); - if (attribute_id(vlink(p)) == i) { - attribute_value(vlink(p)) = val; - } else { - /*tex Add a new node. */ - halfword r = new_attribute_node((unsigned) i, val); - vlink(r) = vlink(p); - vlink(p) = r; - } - return q; - } else { - normal_error("nodes","trying to set an attribute fails, case 1"); - return null ; - } -} - -void set_attribute(halfword n, int i, int val) -{ - register halfword p; - register int j = 0; - /*tex Not all nodes can have an attribute list. */ - if (!nodetype_has_attributes(type(n))) - return; - /*tex If we have no list, we create one and quit. */ - p = node_attr(n); - if (p == null) { /* add a new head \& node */ - p = get_node(attribute_node_size); - type(p) = attribute_list_node; - attr_list_ref(p) = 1; - node_attr(n) = p; - p = new_attribute_node((unsigned) i, val); - vlink(node_attr(n)) = p; - return; - } - /*tex We check if we have this attribute already and quit if the value stays the same. */ - if (vlink(p) != null) { - while (vlink(p) != null) { - int t = attribute_id(vlink(p)); - if (t == i && attribute_value(vlink(p)) == val) - return; - if (t >= i) - break; - j++; - p = vlink(p); - } - /*tex If found |j| has now the position and we assume a sorted list ! */ - p = node_attr(n); - if (attr_list_ref(p) == 0 ) { - /*tex The list is invalid i.e. freed already. */ - formatted_warning("nodes","node %d has an attribute list that is free already, case 1",(int) n); - /*tex The still dangling list gets ref count 1. */ - attr_list_ref(p) = 1; - } else if (attr_list_ref(p) == 1) { - /*tex This can really happen! */ - if (p == attr_list_cache) { - /*tex - - We can invalidate the cache setting with |attr_list_cache = - cache_disabled| or or save the list, as done below. - - */ - p = copy_attribute_list(p); - node_attr(n) = p; - /*tex The copied list gets ref count 1. */ - attr_list_ref(p) = 1; - } - } else { - /*tex The list is used multiple times so we make a copy. */ - p = copy_attribute_list(p); - /*tex We decrement the ref count or the original. */ - delete_attribute_ref(node_attr(n)); - node_attr(n) = p; - /*tex The copied list gets ref count 1. */ - attr_list_ref(p) = 1; - } - /*tex We go to position |j| in the list. */ - while (j-- > 0) - p = vlink(p); - /*tex If we have a hit we just set the value otherwise we add a new node. */ - if (attribute_id(vlink(p)) == i) { - attribute_value(vlink(p)) = val; - } else { - /*tex Add a new node. */ - halfword r = new_attribute_node((unsigned) i, val); - vlink(r) = vlink(p); - vlink(p) = r; - } - } else { - normal_error("nodes","trying to set an attribute fails, case 2"); - } -} - -int unset_attribute(halfword n, int i, int val) -{ - register halfword p; - register int t; - register int j = 0; - if (!nodetype_has_attributes(type(n))) - return null; - p = node_attr(n); - if (p == null) - return UNUSED_ATTRIBUTE; - if (attr_list_ref(p) == 0) { - formatted_warning("nodes","node %d has an attribute list that is free already, case 2", (int) n); - return UNUSED_ATTRIBUTE; - } - if (vlink(p) != null) { - while (vlink(p) != null) { - t = attribute_id(vlink(p)); - if (t > i) - return UNUSED_ATTRIBUTE; - if (t == i) { - p = vlink(p); - break; - } - j++; - p = vlink(p); - } - if (attribute_id(p) != i) - return UNUSED_ATTRIBUTE; - /*tex If we are still here, the attribute exists. */ - p = node_attr(n); - if (attr_list_ref(p) > 1 || p == attr_list_cache) { - halfword q = copy_attribute_list(p); - if (attr_list_ref(p) > 1) { - delete_attribute_ref(node_attr(n)); - } - attr_list_ref(q) = 1; - node_attr(n) = q; - } - p = vlink(node_attr(n)); - while (j-- > 0) - p = vlink(p); - t = attribute_value(p); - if (val == UNUSED_ATTRIBUTE || t == val) { - attribute_value(p) = UNUSED_ATTRIBUTE; - } - return t; - } else { - normal_error("nodes","trying to unset an attribute fails"); - return null; - } -} - -int has_attribute(halfword n, int i, int val) -{ - register halfword p; - if (!nodetype_has_attributes(type(n))) - return UNUSED_ATTRIBUTE; - p = node_attr(n); - if (p == null || vlink(p) == null) - return UNUSED_ATTRIBUTE; - p = vlink(p); - while (p != null) { - if (attribute_id(p) == i) { - int ret = attribute_value(p); - if (val == UNUSED_ATTRIBUTE || val == ret) - return ret; - return UNUSED_ATTRIBUTE; - } else if (attribute_id(p) > i) { - return UNUSED_ATTRIBUTE; - } - p = vlink(p); - } - return UNUSED_ATTRIBUTE; -} - -void print_short_node_contents(halfword p) -{ - switch (type(p)) { - case hlist_node: - case vlist_node: - case ins_node: - case whatsit_node: - case mark_node: - case adjust_node: - case unset_node: - print_char('['); - print_char(']'); - break; - case rule_node: - print_char('|'); - break; - case glue_node: - if (! glue_is_zero(p)) - print_char(' '); - break; - case math_node: - print_char('$'); - break; - case disc_node: - short_display(vlink(pre_break(p))); - short_display(vlink(post_break(p))); - break; - } -} - -static void show_pdftex_whatsit_rule_spec(int p) -{ - tprint("("); - print_rule_dimen(height(p)); - print_char('+'); - print_rule_dimen(depth(p)); - tprint(")x"); - print_rule_dimen(width(p)); -} - -/*tex - - Each new type of node that appears in our data structure must be capable of - being displayed, copied, destroyed, and so on. The routines that we need for - write-oriented whatsits are somewhat like those for mark nodes; other - extensions might, of course, involve more subtlety here. - -*/ - -static void print_write_whatsit(const char *s, pointer p) -{ - tprint_esc(s); - if (write_stream(p) < 16) - print_int(write_stream(p)); - else if (write_stream(p) == 16) - print_char('*'); - else - print_char('-'); -} - -static void show_node_wrapup_core(int p) -{ - switch (subtype(p)) { - case open_node: - print_write_whatsit("openout", p); - print_char('='); - print_file_name(open_name(p), open_area(p), open_ext(p)); - break; - case write_node: - print_write_whatsit("write", p); - print_mark(write_tokens(p)); - break; - case close_node: - print_write_whatsit("closeout", p); - break; - case special_node: - tprint_esc("special"); - print_mark(write_tokens(p)); - break; - case late_lua_node: - show_late_lua(p); - break; - case save_pos_node: - tprint_esc("savepos"); - break; - case user_defined_node: - tprint_esc("whatsit"); - print_int(user_node_id(p)); - print_char('='); - switch (user_node_type(p)) { - case 'a': - tprint("<>"); - break; - case 'n': - tprint("["); - show_node_list(user_node_value(p)); - tprint("]"); - break; - case 's': - print_char('"'); - print(user_node_value(p)); - print_char('"'); - break; - case 't': - print_mark(user_node_value(p)); - break; - default: /* only 'd' */ - print_int(user_node_value(p)); - break; - } - break; - } -} - -void show_node_wrapup_dvi(int p) -{ -} - -void show_node_wrapup_pdf(int p) -{ - switch (subtype(p)) { - case pdf_literal_node: - show_pdf_literal(p); - break; - case pdf_colorstack_node: - tprint_esc("pdfcolorstack "); - print_int(pdf_colorstack_stack(p)); - switch (pdf_colorstack_cmd(p)) { - case colorstack_set: - tprint(" set "); - break; - case colorstack_push: - tprint(" push "); - break; - case colorstack_pop: - tprint(" pop"); - break; - case colorstack_current: - tprint(" current"); - break; - default: - confusion("colorstack"); - break; - } - if (pdf_colorstack_cmd(p) <= colorstack_data) - print_mark(pdf_colorstack_data(p)); - break; - case pdf_setmatrix_node: - tprint_esc("pdfsetmatrix"); - print_mark(pdf_setmatrix_data(p)); - break; - case pdf_save_node: - tprint_esc("pdfsave"); - break; - case pdf_restore_node: - tprint_esc("pdfrestore"); - break; - case pdf_link_state_node: - tprint_esc("pdflinkstate "); - print_int(pdf_link_state(p)); - break; - case pdf_refobj_node: - tprint_esc("pdfrefobj"); - if (obj_obj_is_stream(static_pdf, pdf_obj_objnum(p))) { - if (obj_obj_stream_attr(static_pdf, pdf_obj_objnum(p)) != LUA_NOREF) { - tprint(" attr"); - lua_rawgeti(Luas, LUA_REGISTRYINDEX, obj_obj_stream_attr(static_pdf, pdf_obj_objnum(p))); - print_char(' '); - tprint((const char *) lua_tostring(Luas, -1)); - lua_pop(Luas, 1); - } - tprint(" stream"); - } - if (obj_obj_is_file(static_pdf, pdf_obj_objnum(p))) - tprint(" file"); - if (obj_obj_data(static_pdf, pdf_obj_objnum(p)) != LUA_NOREF) { - lua_rawgeti(Luas, LUA_REGISTRYINDEX, obj_obj_data(static_pdf, pdf_obj_objnum(p))); - print_char(' '); - tprint((const char *) lua_tostring(Luas, -1)); - lua_pop(Luas, 1); - } - break; - case pdf_annot_node: - tprint_esc("pdfannot"); - show_pdftex_whatsit_rule_spec(p); - print_mark(pdf_annot_data(p)); - break; - case pdf_start_link_node: - tprint_esc("pdfstartlink"); - show_pdftex_whatsit_rule_spec(p); - if (pdf_link_attr(p) != null) { - tprint(" attr"); - print_mark(pdf_link_attr(p)); - } - tprint(" action"); - if (pdf_action_type(pdf_link_action(p)) == pdf_action_user) { - tprint(" user"); - print_mark(pdf_action_tokens(pdf_link_action(p))); - return; - } - if (pdf_action_file(pdf_link_action(p)) != null) { - tprint(" file"); - print_mark(pdf_action_file(pdf_link_action(p))); - } - switch (pdf_action_type(pdf_link_action(p))) { - case pdf_action_goto: - if (pdf_action_named_id(pdf_link_action(p)) > 0) { - tprint(" goto name"); - print_mark(pdf_action_id(pdf_link_action(p))); - } else { - tprint(" goto num"); - print_int(pdf_action_id(pdf_link_action(p))); - } - break; - case pdf_action_page: - tprint(" page"); - print_int(pdf_action_id(pdf_link_action(p))); - print_mark(pdf_action_tokens(pdf_link_action(p))); - break; - case pdf_action_thread: - if (pdf_action_named_id(pdf_link_action(p)) > 0) { - tprint(" thread name"); - print_mark(pdf_action_id(pdf_link_action(p))); - } else { - tprint(" thread num"); - print_int(pdf_action_id(pdf_link_action(p))); - } - break; - default: - normal_error("pdf backend", "unknown action type for link"); - break; - } - break; - case pdf_end_link_node: - tprint_esc("pdfendlink"); - break; - case pdf_dest_node: - tprint_esc("pdfdest"); - if (pdf_dest_named_id(p) > 0) { - tprint(" name"); - print_mark(pdf_dest_id(p)); - } else { - tprint(" num"); - print_int(pdf_dest_id(p)); - } - print_char(' '); - switch (pdf_dest_type(p)) { - case pdf_dest_xyz: - tprint("xyz"); - if (pdf_dest_xyz_zoom(p) != null) { - tprint(" zoom"); - print_int(pdf_dest_xyz_zoom(p)); - } - break; - case pdf_dest_fitbh: - tprint("fitbh"); - break; - case pdf_dest_fitbv: - tprint("fitbv"); - break; - case pdf_dest_fitb: - tprint("fitb"); - break; - case pdf_dest_fith: - tprint("fith"); - break; - case pdf_dest_fitv: - tprint("fitv"); - break; - case pdf_dest_fitr: - tprint("fitr"); - show_pdftex_whatsit_rule_spec(p); - break; - case pdf_dest_fit: - tprint("fit"); - break; - default: - tprint("unknown!"); - break; - } - break; - case pdf_thread_node: - case pdf_start_thread_node: - if (subtype(p) == pdf_thread_node) - tprint_esc("pdfthread"); - else - tprint_esc("pdfstartthread"); - tprint("("); - print_rule_dimen(height(p)); - print_char('+'); - print_rule_dimen(depth(p)); - tprint(")x"); - print_rule_dimen(width(p)); - if (pdf_thread_attr(p) != null) { - tprint(" attr"); - print_mark(pdf_thread_attr(p)); - } - if (pdf_thread_named_id(p) > 0) { - tprint(" name"); - print_mark(pdf_thread_id(p)); - } else { - tprint(" num"); - print_int(pdf_thread_id(p)); - } - break; - case pdf_end_thread_node: - tprint_esc("pdfendthread"); - break; - default: - break; - } -} - -/*tex - - Now we are ready for |show_node_list| itself. This procedure has been written - to be ``extra robust'' in the sense that it should not crash or get into a - loop even if the data structures have been messed up by bugs in the rest of - the program. You can safely call its parent routine |show_box(p)| for - arbitrary values of |p| when you are debugging \TeX. However, in the presence - of bad data, the procedure may fetch a |memory_word| whose variant is - different from the way it was stored; for example, it might try to read - |mem[p].hh| when |mem[p]| contains a scaled integer, if |p| is a pointer that - has been clobbered or chosen at random. - -*/ - -#define node_list_display(A) do { \ - append_char('.'); \ - show_node_list(A); \ - flush_char(); \ -} while (0) - -#define node_list_display_x(A,B) do { \ - if ((B) != null) { \ - append_char('.'); \ - append_char(A); \ - append_char(' '); \ - show_node_list(B); \ - flush_char(); \ - flush_char(); \ - flush_char(); \ - } \ -} while (0) - -/*tex Print a node list symbolically: */ - -void show_node_list(int p) -{ - /*tex The number of items already printed at this level: */ - int n = 0; - halfword w; - /*tex A glue ratio, as a floating point number: */ - real g; - if ((int) cur_length > depth_threshold) { - if (p > null) { - /*tex Indicate that there's been some truncation. */ - tprint(" []"); - } - return; - } - while (p != null) { - print_ln(); - print_current_string(); - /*tex Display the nesting history. */ - if (tracing_online_par < -2) - print_int(p); - incr(n); - if (n > breadth_max) { - /*tex Time to stop. */ - tprint("etc."); - return; - } - /*tex Display node |p|. */ - if (is_char_node(p)) { - print_font_and_char(p); - if (is_ligature(p)) { - /*tex Display ligature |p|. */ - tprint(" (ligature "); - if (is_leftboundary(p)) - print_char('|'); - font_in_short_display = font(p); - short_display(lig_ptr(p)); - if (is_rightboundary(p)) - print_char('|'); - print_char(')'); - } - } else { - switch (type(p)) { - case hlist_node: - case vlist_node: - case unset_node: - /*tex Display box |p|. */ - if (type(p) == hlist_node) - tprint_esc("h"); - else if (type(p) == vlist_node) - tprint_esc("v"); - else - tprint_esc("unset"); - tprint("box("); - print_scaled(height(p)); - print_char('+'); - print_scaled(depth(p)); - tprint(")x"); - print_scaled(width(p)); - if (type(p) == unset_node) { - /*tex Display special fields of the unset node |p|. */ - if (span_count(p) != min_quarterword) { - tprint(" ("); - print_int(span_count(p) + 1); - tprint(" columns)"); - } - if (glue_stretch(p) != 0) { - tprint(", stretch "); - print_glue(glue_stretch(p), glue_order(p), NULL); - } - if (glue_shrink(p) != 0) { - tprint(", shrink "); - print_glue(glue_shrink(p), glue_sign(p), NULL); - } - } else { - /*tex - - Display the value of |glue_set(p)|. The code will - have to change in this place if |glue_ratio| is a - structured type instead of an ordinary |real|. Note - that this routine should avoid arithmetic errors even - if the |glue_set| field holds an arbitrary random - value. The following code assumes that a properly - formed nonzero |real| number has absolute value - $2^{20}$ or more when it is regarded as an integer; - this precaution was adequate to prevent floating - point underflow on the author's computer. - - */ - g = (real) (glue_set(p)); - if ((g != 0.0) && (glue_sign(p) != normal)) { - tprint(", glue set "); - if (glue_sign(p) == shrinking) - tprint("- "); - if (g > 20000.0 || g < -20000.0) { - if (g > 0.0) - print_char('>'); - else - tprint("< -"); - print_glue(20000 * unity, glue_order(p), NULL); - } else { - print_glue(round(unity * g), glue_order(p), NULL); - } - } - if (shift_amount(p) != 0) { - tprint(", shifted "); - print_scaled(shift_amount(p)); - } - tprint(", direction "); - print_dir_par(box_dir(p)); - } - /*tex Recursive call: */ - node_list_display(list_ptr(p)); - break; - case rule_node: - /*tex Display rule |p|. */ - if (subtype(p) == normal_rule) { - tprint_esc("rule("); - } else if (subtype(p) == empty_rule) { - tprint_esc("norule("); - } else if (subtype(p) == user_rule) { - tprint_esc("userrule("); - } else if (subtype(p) == box_rule) { - tprint_esc("box("); - } else if (subtype(p) == image_rule) { - tprint_esc("image("); - } - print_rule_dimen(height(p)); - print_char('+'); - print_rule_dimen(depth(p)); - tprint(")x"); - print_rule_dimen(width(p)); - break; - case ins_node: - /*tex Display insertion |p|. */ - tprint_esc("insert"); - print_int(subtype(p)); - tprint(", natural size "); - print_scaled(height(p)); - tprint("; split("); - print_spec(split_top_ptr(p), NULL); - print_char(','); - print_scaled(depth(p)); - tprint("); float cost "); - print_int(float_cost(p)); - /*tex Recursive call. */ - node_list_display(ins_ptr(p)); - break; - case dir_node: - if (subtype(p) == cancel_dir) { - tprint_esc("enddir"); - } else { - tprint_esc("begindir"); - } - print_char(' '); - print_dir_par(dir_dir(p)); - break; - case local_par_node: - tprint_esc("localpar"); - append_char('.'); - print_ln(); - print_current_string(); - tprint_esc("localinterlinepenalty"); - print_char('='); - print_int(local_pen_inter(p)); - print_ln(); - print_current_string(); - tprint_esc("localbrokenpenalty"); - print_char('='); - print_int(local_pen_broken(p)); - print_ln(); - print_current_string(); - tprint_esc("localleftbox"); - if (local_box_left(p) == null) { - tprint("=null"); - } else { - append_char('.'); - show_node_list(local_box_left(p)); - decr(cur_length); - } - print_ln(); - print_current_string(); - tprint_esc("localrightbox"); - if (local_box_right(p) == null) { - tprint("=null"); - } else { - append_char('.'); - show_node_list(local_box_right(p)); - decr(cur_length); - } - decr(cur_length); - break; - case boundary_node: - if (subtype(p)==0) { - tprint_esc("noboundary"); - } else { - switch (subtype(p)) { - case 1: - tprint_esc("boundary"); - break; - case 2: - tprint_esc("protrusionboundary"); - break; - case 3: - tprint_esc("wordboundary"); - break; - default: - tprint_esc("boundary"); - print_char(':'); - print_int(subtype(p)); - break; - } - print_char('='); - print_int(boundary_value(p)); - } - break; - case whatsit_node: - w = subtype(p) ; - if (w >= backend_first_pdf_whatsit) { - show_node_wrapup_pdf(p); - } else if (w >= backend_first_dvi_whatsit) { - show_node_wrapup_dvi(p); - } else { - show_node_wrapup_core(p); - } - break; - case glue_node: - /*tex Display glue |p|. */ - if (subtype(p) >= a_leaders) { - /*tex Display leaders |p|. */ - tprint_esc(""); - switch (subtype(p)) { - case a_leaders: - break; - case c_leaders: - print_char('c'); - break; - case x_leaders: - print_char('x'); - break; - case g_leaders: - print_char('g'); - break; - default: - normal_warning("nodes","weird glue leader subtype ignored"); - } - tprint("leaders "); - print_spec(p, NULL); - /*tex Recursive call: */ - node_list_display(leader_ptr(p)); - } else { - tprint_esc("glue"); - if (subtype(p) != normal) { - print_char('('); - if ((subtype(p) - 1) < thin_mu_skip_code) { - print_cmd_chr(assign_glue_cmd, glue_base + (subtype(p) - 1)); - } else if (subtype(p) < cond_math_glue) { - print_cmd_chr(assign_mu_glue_cmd, glue_base + (subtype(p) - 1)); - } else if (subtype(p) == cond_math_glue) { - tprint_esc("nonscript"); - } else { - tprint_esc("mskip"); - } - print_char(')'); - } - if (subtype(p) != cond_math_glue) { - print_char(' '); - if (subtype(p) < cond_math_glue) - print_spec(p, NULL); - else - print_spec(p, "mu"); - } - } - break; - case margin_kern_node: - tprint_esc("kern"); - print_scaled(width(p)); - if (subtype(p) == left_side) - tprint(" (left margin)"); - else - tprint(" (right margin)"); - break; - case kern_node: - /*tex Display kern |p| */ - if (subtype(p) != mu_glue) { - tprint_esc("kern"); - /*tex - - \starttyping - if (subtype(p) != normal) { - print_char(' '); - } - \stoptyping - - */ - print_scaled(width(p)); - if (subtype(p) == font_kern) - tprint(" (font)"); - else if (subtype(p) == italic_kern) - tprint(" (italic)"); - else if (subtype(p) == accent_kern) - tprint(" (accent)"); - } else { - tprint_esc("mkern"); - print_scaled(width(p)); - tprint("mu"); - } - break; - case math_node: - /*tex Display math node |p|. */ - tprint_esc("math"); - if (subtype(p) == before) - tprint("on"); - else - tprint("off"); - if (!glue_is_zero(p)) { - tprint(", glued "); - print_spec(p, NULL); - } else if (surround(p) != 0) { - tprint(", surrounded "); - print_scaled(surround(p)); - } - break; - case penalty_node: - /*tex Display penalty |p|. */ - tprint_esc("penalty "); - print_int(penalty(p)); - break; - case disc_node: - /*tex - - Display discretionary |p|. The |post_break| list of a - discretionary node is indicated by a prefixed - `\.{\char'174}' instead of the `\..' before the - |pre_break| list. - - We're not compatible anyway so ... - - \starttyping - tprint_esc("discretionary"); - print_int(disc_penalty(p)); - print_char('|'); - if (vlink(no_break(p)) != null) { - tprint(" replacing "); - node_list_display(vlink(no_break(p))); - } - node_list_display(vlink(pre_break(p))); - append_char('|'); - show_node_list(vlink(post_break(p))); - flush_char(); - \stoptyping - - has become: - - */ - tprint_esc("discretionary"); - tprint(" (penalty "); - print_int(disc_penalty(p)); - print_char(')'); - node_list_display_x('<',vlink(pre_break(p))); - node_list_display_x('>',vlink(post_break(p))); - node_list_display_x('=',vlink(no_break(p))); - break; - case mark_node: - /*tex Display mark |p|. */ - tprint_esc("mark"); - if (mark_class(p) != 0) { - print_char('s'); - print_int(mark_class(p)); - } - print_mark(mark_ptr(p)); - break; - case adjust_node: - /*tex Display adjustment |p|. */ - tprint_esc("vadjust"); - if (subtype(p) != 0) - tprint(" pre "); - /*tex Recursive call. */ - node_list_display(adjust_ptr(p)); - break; - case glue_spec_node: - tprint("<glue_spec "); - print_spec(p, NULL); - tprint(">"); - break; - default: - show_math_node(p); - break; - } - } - p = vlink(p); - } -} - -/*tex - - This routine finds the 'base' width of a horizontal box, using the same logic - that \TeX82 used for \.{\\predisplaywidth}. - -*/ - -static pointer get_actual_box_width(pointer r,pointer p, scaled initial_width) -{ - /*tex increment to |v| */ - scaled d; - /*tex calculated |size| */ - scaled w = -max_dimen; - /*tex |w| plus possible glue amount */ - scaled v = initial_width; - while (p != null) { - if (is_char_node(p)) { - d = glyph_width(p); - goto FOUND; - } - switch (type(p)) { - case hlist_node: - case vlist_node: - case rule_node: - d = width(p); - goto FOUND; - break; - case margin_kern_node: - d = width(p); - break; - case kern_node: - d = width(p); - break; - case disc_node: - /*tex At the end of the line we should actually take the |pre|. */ - if (no_break(p) != null) { - d = get_actual_box_width(r,vlink_no_break(p),0); - if (d <= -max_dimen || d >= max_dimen) { - d = 0; - } - } else { - d = 0; - } - goto FOUND; - break; - case math_node: - /*tex Begin mathskip code. */ - if (glue_is_zero(p)) { - d = surround(p); - break; - } else { - /*tex Fall through. */ - } - /*tex End mathskip code. */ - case glue_node: - /*tex - - We need to be careful that |w|, |v|, and |d| do not depend on - any |glue_set| values, since such values are subject to - system-dependent rounding. System-dependent numbers are not - allowed to infiltrate parameters like |pre_display_size|, - since \TeX82 is supposed to make the same decisions on all - machines. - - */ - d = width(p); - if (glue_sign(r) == stretching) { - if ((glue_order(r) == stretch_order(p)) && (stretch(p) != 0)) - v = max_dimen; - } else if (glue_sign(r) == shrinking) { - if ((glue_order(r) == shrink_order(p)) && (shrink(p) != 0)) - v = max_dimen; - } - if (subtype(p) >= a_leaders) - goto FOUND; - break; - default: - d = 0; - break; - } - if (v < max_dimen) - v = v + d; - goto NOT_FOUND; - FOUND: - if (v < max_dimen) { - v = v + d; - w = v; - } else { - w = max_dimen; - break; - } - NOT_FOUND: - p = vlink(p); - } - return w; -} - -pointer actual_box_width(pointer r, scaled base_width) -{ - /*tex - - Often this is the same as: - - \starttyping - return + shift_amount(r) + base_width + - natural_sizes(list_ptr(r),null,(glue_ratio) glue_set(r),glue_sign(r),glue_order(r),box_dir(r)); - \stoptyping - */ - return get_actual_box_width(r,list_ptr(r),shift_amount(r) + base_width); -} - -halfword tail_of_list(halfword p) -{ - halfword q = p; - while (vlink(q) != null) - q = vlink(q); - return q; -} - -int var_used; - -/*tex - - Attribute lists need two extra globals to increase processing efficiency. - |max_used_attr| limits the test loop that checks for set attributes, and - |attr_list_cache| contains a pointer to an already created attribute list. It - is set to the special value |cache_disabled| when the current value can no - longer be trusted: after an assignment to an attribute register, and after a - group has ended. - -*/ - -/*tex The maximum assigned attribute id: */ - -int max_used_attr; -halfword attr_list_cache; - -/*tex - - From the computer's standpoint, \TeX's chief mission is to create horizontal - and vertical lists. We shall now investigate how the elements of these lists - are represented internally as nodes in the dynamic memory. - - A horizontal or vertical list is linked together by |link| fields in the - first word of each node. Individual nodes represent boxes, glue, penalties, - or special things like discretionary hyphens; because of this variety, some - nodes are longer than others, and we must distinguish different kinds of - nodes. We do this by putting a `|type|' field in the first word, together - with the link and an optional `|subtype|'. - - Character nodes appear only in horizontal lists, never in vertical lists. - - An |hlist_node| stands for a box that was made from a horizontal list. Each - |hlist_node| is seven words long, and contains the following fields (in - addition to the mandatory |type| and |link|, which we shall not mention - explicitly when discussing the other node types): The |height| and |width| - and |depth| are scaled integers denoting the dimensions of the box. There is - also a |shift_amount| field, a scaled integer indicating how much this box - should be lowered (if it appears in a horizontal list), or how much it should - be moved to the right (if it appears in a vertical list). There is a - |list_ptr| field, which points to the beginning of the list from which this - box was fabricated; if |list_ptr| is |null|, the box is empty. Finally, there - are three fields that represent the setting of the glue: |glue_set(p)| is a - word of type |glue_ratio| that represents the proportionality constant for - glue setting; |glue_sign(p)| is |stretching| or |shrinking| or |normal| - depending on whether or not the glue should stretch or shrink or remain - rigid; and |glue_order(p)| specifies the order of infinity to which glue - setting applies (|normal|, |sfi|, |fil|, |fill|, or |filll|). The |subtype| - field is not used. - - The |new_null_box| function returns a pointer to an |hlist_node| in which all - subfields have the values corresponding to `\.{\\hbox\{\}}'. The |subtype| - field is set to |min_quarterword|, since that's the desired |span_count| - value if this |hlist_node| is changed to an |unset_node|. - -*/ - -/*tex Create a new box node. */ - -halfword new_null_box(void) -{ - halfword p = new_node(hlist_node, min_quarterword); - box_dir(p) = text_direction_par; - return p; -} - -/*tex - - A |vlist_node| is like an |hlist_node| in all respects except that it - contains a vertical list. - - A |rule_node| stands for a solid black rectangle; it has |width|, |depth|, - and |height| fields just as in an |hlist_node|. However, if any of these - dimensions is $-2^{30}$, the actual value will be determined by running the - rule up to the boundary of the innermost enclosing box. This is called a - ``running dimension.'' The |width| is never running in an hlist; the |height| - and |depth| are never running in a~vlist. - - A new rule node is delivered by the |new_rule| function. It makes all the - dimensions ``running,'' so you have to change the ones that are not allowed - to run. - -*/ - -halfword new_rule(int s) -{ - halfword p = new_node(rule_node,s); - return p; -} - -/*tex - - Insertions are represented by |ins_node| records, where the |subtype| - indicates the corresponding box number. For example, `\.{\\insert 250}' leads - to an |ins_node| whose |subtype| is |250+min_quarterword|. The |height| field - of an |ins_node| is slightly misnamed; it actually holds the natural height - plus depth of the vertical list being inserted. The |depth| field holds the - |split_max_depth| to be used in case this insertion is split, and the - |split_top_ptr| points to the corresponding |split_top_skip|. The - |float_cost| field holds the |floating_penalty| that will be used if this - insertion floats to a subsequent page after a split insertion of the same - class. There is one more field, the |ins_ptr|, which points to the beginning - of the vlist for the insertion. - - A |mark_node| has a |mark_ptr| field that points to the reference count of a - token list that contains the user's \.{\\mark} text. In addition there is a - |mark_class| field that contains the mark class. - - An |adjust_node|, which occurs only in horizontal lists, specifies material - that will be moved out into the surrounding vertical list; i.e., it is used - to implement \TeX's `\.{\\vadjust}' operation. The |adjust_ptr| field points - to the vlist containing this material. - - A |glyph_node|, which occurs only in horizontal lists, specifies a glyph in a - particular font, along with its attribute list. Older versions of \TeX\ could - use token memory for characters, because the font,char combination would fit - in a single word (both values were required to be strictly less than - $2^{16}$). In LuaTeX, room is needed for characters that are larger than - that, as well as a pointer to a potential attribute list, and the two - displacement values. - - In turn, that made the node so large that it made sense to merge ligature - glyphs as well, as that requires only one extra pointer. A few extra classes - of glyph nodes will be introduced later. The unification of all those types - makes it easier to manipulate lists of glyphs. The subtype differentiates - various glyph kinds. - - First, here is a function that returns a pointer to a glyph node for a given - glyph in a given font. If that glyph doesn't exist, |null| is returned - instead. Nodes of this subtype are directly created only for accents and - their base (through |make_accent|), and math nucleus items (in the conversion - from |mlist| to |hlist|). - -*/ - -halfword new_glyph(int f, int c) -{ - halfword p = null; - if ((f == 0) || (char_exists(f, c))) { - p = new_glyph_node(); - set_to_glyph(p); - font(p) = f; - character(p) = c; - } - return p; -} - -/*tex - - A subset of the glyphs nodes represent ligatures: characters fabricated from - the interaction of two or more actual characters. The characters that - generated the ligature have not been forgotten, since they are needed for - diagnostic messages; the |lig_ptr| field points to a linked list of character - nodes for all original characters that have been deleted. (This list might be - empty if the characters that generated the ligature were retained in other - nodes.) - - The |subtype| field of these |glyph_node|s is 1, plus 2 and/or 1 if the - original source of the ligature included implicit left and/or right - boundaries. These nodes are created by the C function |new_ligkern|. - - A third general type of glyphs could be called a character, as it only - appears in lists that are not yet processed by the ligaturing and kerning - steps of the program. - - |main_control| inserts these, and they are later converted to - |subtype_normal| by |new_ligkern|. - -*/ - -quarterword norm_min(int h) -{ - if (h <= 0) - return 1; - else if (h >= 255) - return 255; - else - return (quarterword) h; -} - -halfword new_char(int f, int c) -{ - halfword p; - p = new_glyph_node(); - set_to_character(p); - font(p) = f; - character(p) = c; - lang_data(p) = make_lang_data(uc_hyph_par, cur_lang_par, left_hyphen_min_par, right_hyphen_min_par); - return p; -} - -/*tex - - Left and right ghost glyph nodes are the result of \.{\\leftghost} and - \.{\\rightghost}, respectively. They are going to be removed by - |new_ligkern|, at the end of which they are no longer needed. - - Here are a few handy helpers used by the list output routines. The yoffset - has some history but we now give some control over its treatment: - - 0: what we had before - 1: compensate height and depth - 2: compensate height and depth, take max - 3: we keep height and depth - - The modes are controlled by a variable because we need to retain downward - compatibility. - -*/ - -scaled glyph_width(halfword p) -{ - scaled w = char_width(font(p), character(p)); - return w; -} - -scaled glyph_height(halfword p) -{ - scaled h = char_height(font(p), character(p)); - scaled y = y_displace(p); - if ((glyph_dimensions_par == 0) || (glyph_dimensions_par == 1) || (glyph_dimensions_par == 2 && y > 0)) - h += y; - if (h < 0) - h = 0; - return h; -} - -scaled glyph_depth(halfword p) /* not used */ -{ - scaled d = char_depth(font(p), character(p)); - scaled y = y_displace(p); - if ((glyph_dimensions_par == 0 && y > 0) || (glyph_dimensions_par == 1) || (glyph_dimensions_par == 2 && y < 0)) - d -= y; - if (d < 0) - d = 0; - return d; -} - -/*tex - - A |disc_node|, which occurs only in horizontal lists, specifies a - ``dis\-cretion\-ary'' line break. If such a break occurs at node |p|, the - text that starts at |pre_break(p)| will precede the break, the text that - starts at |post_break(p)| will follow the break, and text that appears in - |no_break(p)| nodes will be ignored. For example, an ordinary discretionary - hyphen, indicated by `\.{\\-}', yields a |disc_node| with |pre_break| - pointing to a |char_node| containing a hyphen, |post_break=null|, and - |no_break=null|. - - If |subtype(p)=automatic_disc|, the |ex_hyphen_penalty| will be charged for - this break. Otherwise the |hyphen_penalty| will be charged. The texts will - actually be substituted into the list by the line-breaking algorithm if it - decides to make the break, and the discretionary node will disappear at that - time; thus, the output routine sees only discretionaries that were not - chosen. - -*/ - -halfword new_disc(void) -{ - halfword p = new_node(disc_node, 0); - disc_penalty(p) = hyphen_penalty_par; - return p; -} - -/* - - A |whatsit_node| is a wild card reserved for extensions to \TeX. The - |subtype| field in its first word says what `\\{whatsit}' it is, and - implicitly determines the node size (which must be 2 or more) and the format - of the remaining words. When a |whatsit_node| is encountered in a list, - special actions are invoked; knowledgeable people who are careful not to mess - up the rest of \TeX\ are able to make \TeX\ do new things by adding code at - the end of the program. For example, there might be a `\TeX nicolor' - extension to specify different colors of ink, and the whatsit node might - contain the desired parameters. - - The present implementation of \TeX\ treats the features associated with - `\.{\\write}' and `\.{\\special}' as if they were extensions, in order to - illustrate how such routines might be coded. We shall defer further - discussion of extensions until the end of this program. - - A |math_node|, which occurs only in horizontal lists, appears before and - after mathematical formulas. The |subtype| field is |before| before the - formula and |after| after it. There is a |surround| field, which represents - the amount of surrounding space inserted by \.{\\mathsurround}. - -*/ - -halfword new_math(scaled w, int s) -{ - halfword p = new_node(math_node, s); - surround(p) = w; - return p; -} - -/*tex - - \TeX\ makes use of the fact that |hlist_node|, |vlist_node|, |rule_node|, - |ins_node|, |mark_node|, |adjust_node|, |disc_node|, |whatsit_node|, and - |math_node| are at the low end of the type codes, by permitting a break at - glue in a list if and only if the |type| of the previous node is less than - |math_node|. Furthermore, a node is discarded after a break if its type is - |math_node| or~more. - - A |glue_node| represents glue in a list. However, it is really only a pointer - to a separate glue specification, since \TeX\ makes use of the fact that many - essentially identical nodes of glue are usually present. If |p| points to a - |glue_node|, |glue_ptr(p)| points to another packet of words that specify the - stretch and shrink components, etc. - - Glue nodes also serve to represent leaders; the |subtype| is used to - distinguish between ordinary glue (which is called |normal|) and the three - kinds of leaders (which are called |a_leaders|, |c_leaders|, and - |x_leaders|). The |leader_ptr| field points to a rule node or to a box node - containing the leaders; it is set to |null| in ordinary glue nodes. - - Many kinds of glue are computed from \TeX's ``skip'' parameters, and it is - helpful to know which parameter has led to a particular glue node. Therefore - the |subtype| is set to indicate the source of glue, whenever it originated - as a parameter. We will be defining symbolic names for the parameter numbers - later (e.g., |line_skip_code=0|, |baseline_skip_code=1|, etc.); it suffices - for now to say that the |subtype| of parametric glue will be the same as the - parameter number, plus~one. - - In math formulas there are two more possibilities for the |subtype| in a glue - node: |mu_glue| denotes an \.{\\mskip} (where the units are scaled \.{mu} - instead of scaled \.{pt}); and |cond_math_glue| denotes the `\.{\\nonscript}' - feature that cancels the glue node immediately following if it appears in a - subscript. - - A glue specification has a halfword reference count in its first word, - representing |null| plus the number of glue nodes that point to it (less - one). Note that the reference count appears in the same position as the - |link| field in list nodes; this is the field that is initialized to |null| - when a node is allocated, and it is also the field that is flagged by - |empty_flag| in empty nodes. - - Glue specifications also contain three |scaled| fields, for the |width|, - |stretch|, and |shrink| dimensions. Finally, there are two one-byte fields - called |stretch_order| and |shrink_order|; these contain the orders of - infinity (|normal|, |sfi|, |fil|, |fill|, or |filll|) corresponding to the - stretch and shrink values. - - Here is a function that returns a pointer to a copy of a glue spec. The - reference count in the copy is |null|, because there is assumed to be exactly - one reference to the new specification. - -*/ - -halfword new_spec(halfword q) -{ - if (q == null) { - return copy_node(zero_glue); - } else if (type(q) == glue_spec_node) { - return copy_node(q); - } else if (type(q) == glue_node) { - halfword p = copy_node(zero_glue); - width(p) = width(q); - stretch(p) = stretch(q); - shrink(p) = shrink(q); - stretch_order(p) = stretch_order(q); - shrink_order(p) = shrink_order(q); - return p; - } else { - /*tex Alternatively we can issue a warning. */ - return copy_node(zero_glue); - } -} - -/*tex - - And here's a function that creates a glue node for a given parameter - identified by its code number; for example, |new_param_glue(line_skip_code)| - returns a pointer to a glue node for the current \.{\\lineskip}. - -*/ - -halfword new_param_glue(int n) -{ - halfword p = new_node(glue_node, n + 1); - halfword q = glue_par(n); - width(p) = width(q); - stretch(p) = stretch(q); - shrink(p) = shrink(q); - stretch_order(p) = stretch_order(q); - shrink_order(p) = shrink_order(q); - return p; -} - -/*tex - - Glue nodes that are more or less anonymous are created by |new_glue|, whose - argument points to a glue specification. - -*/ - -halfword new_glue(halfword q) -{ - halfword p = new_node(glue_node, normal); - width(p) = width(q); - stretch(p) = stretch(q); - shrink(p) = shrink(q); - stretch_order(p) = stretch_order(q); - shrink_order(p) = shrink_order(q); - return p; -} - -/*tex - - Still another subroutine is needed: This one is sort of a combination of - |new_param_glue| and |new_glue|. It creates a glue node for one of the - current glue parameters, but it makes a fresh copy of the glue specification, - since that specification will probably be subject to change, while the - parameter will stay put. - - The global variable |temp_ptr| is set to the address of the new spec. - -*/ - -halfword new_skip_param(int n) -{ - halfword p = new_node(glue_node, n + 1); - halfword q = glue_par(n); - width(p) = width(q); - stretch(p) = stretch(q); - shrink(p) = shrink(q); - stretch_order(p) = stretch_order(q); - shrink_order(p) = shrink_order(q); - return p; -} - -/*tex - - A |kern_node| has a |width| field to specify a (normally negative) amount of - spacing. This spacing correction appears in horizontal lists between letters - like A and V when the font designer said that it looks better to move them - closer together or further apart. A kern node can also appear in a vertical - list, when its `|width|' denotes additional spacing in the vertical - direction. The |subtype| is either |normal| (for kerns inserted from font - information or math mode calculations) or |explicit| (for kerns inserted from - \.{\\kern} and \.{\\/} commands) or |acc_kern| (for kerns inserted from - non-math accents) or |mu_glue| (for kerns inserted from \.{\\mkern} - specifications in math formulas). - - The |new_kern| function creates a kern node having a given width. - -*/ - -halfword new_kern(scaled w) -{ - halfword p = new_node(kern_node, normal); - width(p) = w; - return p; -} - -/*tex - - A |penalty_node| specifies the penalty associated with line or page breaking, - in its |penalty| field. This field is a fullword integer, but the full range - of integer values is not used: Any penalty |>=10000| is treated as infinity, - and no break will be allowed for such high values. Similarly, any penalty - |<=-10000| is treated as negative infinity, and a break will be forced. - - Anyone who has been reading the last few sections of the program will be able - to guess what comes next. - -*/ - -halfword new_penalty(int m, int s) -{ - halfword p = new_node(penalty_node, 0); - penalty(p) = m; - subtype(p) = s; - return p; -} - -/*tex - - You might think that we have introduced enough node types by now. Well, - almost, but there is one more: An |unset_node| has nearly the same format as - an |hlist_node| or |vlist_node|; it is used for entries in \.{\\halign} or - \.{\\valign} that are not yet in their final form, since the box dimensions - are their ``natural'' sizes before any glue adjustment has been made. The - |glue_set| word is not present; instead, we have a |glue_stretch| field, - which contains the total stretch of order |glue_order| that is present in the - hlist or vlist being boxed. Similarly, the |shift_amount| field is replaced - by a |glue_shrink| field, containing the total shrink of order |glue_sign| - that is present. The |subtype| field is called |span_count|; an unset box - typically contains the data for |qo(span_count)+1| columns. Unset nodes will - be changed to box nodes when alignment is completed. - - In fact, there are still more types coming. When we get to math formula - processing we will see that a |style_node| has |type=14|; and a number of - larger type codes will also be defined, for use in math mode only. - - Warning: If any changes are made to these data structure layouts, such as - changing any of the node sizes or even reordering the words of nodes, the - |copy_node_list| procedure and the memory initialization code below may have - to be changed. Such potentially dangerous parts of the program are listed in - the index under `data structure assumptions'. However, other references to - the nodes are made symbolically in terms of the \.{WEB} macro definitions - above, so that format changes will leave \TeX's other algorithms intact. - -*/ - -halfword make_local_par_node(int mode) -{ - int callback_id; - halfword q; - halfword p = new_node(local_par_node,mode); - local_pen_inter(p) = local_inter_line_penalty_par; - local_pen_broken(p) = local_broken_penalty_par; - if (local_left_box_par != null) { - q = copy_node_list(local_left_box_par); - local_box_left(p) = q; - local_box_left_width(p) = width(local_left_box_par); - } - if (local_right_box_par != null) { - q = copy_node_list(local_right_box_par); - local_box_right(p) = q; - local_box_right_width(p) = width(local_right_box_par); - } - local_par_dir(p) = par_direction_par; - /*tex Callback with node passed: */ - callback_id = callback_defined(insert_local_par_callback); - if (callback_id > 0) { - /*tex Todo: use general mechanism/wrapper. */ - int sfix = lua_gettop(Luas); - if (!get_callback(Luas, callback_id)) { - lua_settop(Luas, sfix); - } else { - int i; - nodelist_to_lua(Luas, p); - lua_push_local_par_mode(Luas,mode) - /*tex 2 arg, 0 result */ - i = lua_pcall(Luas, 2, 0, 0); - if (i != 0) { - lua_gc(Luas, LUA_GCCOLLECT, 0); - Luas = luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1)); - } - lua_settop(Luas, sfix); - } - } - return p; -} diff --git a/Build/source/texk/web2c/luatexdir/tex/texnodes.h b/Build/source/texk/web2c/luatexdir/tex/texnodes.h deleted file mode 100644 index 9742ca4966c..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/texnodes.h +++ /dev/null @@ -1,1188 +0,0 @@ -/* texnodes.h - - Copyright 2006-2008 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ - - -#include <stdarg.h> - -#ifndef __NODES_H__ -# define __NODES_H__ - -# define varmemcast(a) (memory_word *)(a) - -extern memory_word *volatile varmem; -extern halfword var_mem_max; - -extern halfword get_node(int s); -extern void free_node(halfword p, int s); -extern void init_node_mem(int s); -extern void dump_node_mem(void); -extern void undump_node_mem(void); - -# define max_halfword 0x3FFFFFFF -# define max_dimen 0x3FFFFFFF -# ifndef null -# define null 0 -# endif -# define null_flag -0x40000000 -# define zero_glue 0 -# define normal 0 - -# define vinfo(a) varmem[(a)].hh.v.LH -# define vlink(a) varmem[(a)].hh.v.RH -# define type(a) varmem[(a)].hh.u.B0 -# define subtype(a) varmem[(a)].hh.u.B1 -# define node_attr(a) vinfo((a)+1) -# define alink(a) vlink((a)+1) - -# define node_size(a) varmem[(a)].hh.v.LH - -# define rlink(a) vlink((a)+1) /* aka alink() */ -# define tlink(a) vinfo((a)+1) /* overlaps with node_attr() */ - -/* really special head node pointers that only need links */ - -# define temp_node_size 2 - -/* attribute lists */ - -# define UNUSED_ATTRIBUTE -0x7FFFFFFF /* as low as it goes */ - -/* it is convenient to have attribute list nodes and attribute node - * be the same size - */ - -# define attribute_node_size 2 -# define cache_disabled max_halfword - -# define attr_list_ref(a) vinfo((a)+1) /* the reference count */ -# define attribute_id(a) vinfo((a)+1) -# define attribute_value(a) vlink((a)+1) - -# define assign_attribute_ref(n,p) do { \ - node_attr(n) = p;attr_list_ref(p)++; \ -} while (0) - -# define add_node_attr_ref(a) do { \ - if (a!=null) attr_list_ref((a))++; \ -} while (0) - -# define replace_attribute_list(a,b) do { \ - delete_attribute_ref(node_attr(a)); \ - node_attr(a)=b; \ -} while (0) - -extern void update_attribute_cache(void); -extern halfword copy_attribute_list(halfword n); -extern halfword do_set_attribute(halfword p, int i, int val); - -# define width_offset 2 -# define depth_offset 3 -# define height_offset 4 -# define list_offset 6 - -typedef enum { - user_skip_glue, - line_skip_glue, - baseline_skip_glue, - par_skip_glue, - above_display_skip_glue, - below_display_skip_glue, - above_display_short_skip_glue, - below_display_short_skip_glue, - left_skip_glue, - right_skip_glue, - top_skip_glue, - split_top_skip_glue, - tab_skip_glue, - space_skip_glue, - xspace_skip_glue, - par_fill_skip_glue, - math_skip_glue, - thin_mu_skip_glue, - med_mu_skip_glue, - thick_mu_skip_glue, - /* math */ - cond_math_glue = 98, /* special |subtype| to suppress glue in the next node */ - mu_glue, /* |subtype| for math glue */ - /* leaders */ - a_leaders, /* |subtype| for aligned leaders */ - c_leaders, /* |subtype| for centered leaders */ - x_leaders, /* |subtype| for expanded leaders */ - g_leaders /* |subtype| for global (page) leaders */ -} glue_subtypes; - -/* normal nodes */ - -# define inf_bad 10000 /* infinitely bad value */ -# define inf_penalty inf_bad /* ``infinite'' penalty value */ -# define eject_penalty -(inf_penalty) /* ``negatively infinite'' penalty value */ - -# define penalty_node_size 3 -# define penalty(a) vlink((a)+2) - -typedef enum { - user_penalty, - linebreak_penalty, /* includes widow, club, broken ect */ - line_penalty, - word_penalty, - final_penalty, - noad_penalty, - before_display_penalty, - after_display_penalty, - equation_number_penalty, -} penalty_subtypes ; - -/* -# define glue_node_size 4 -# define glue_ptr(a) vinfo((a)+2) -# define leader_ptr(a) vlink((a)+2) -# define synctex_tag_glue(a) vinfo((a)+3) -# define synctex_line_glue(a) vlink((a)+3) -*/ - -# define glue_node_size 7 -# define glue_spec_size 5 -/* define width(a) vinfo((a)+2) */ -/* define leader_ptr(a) vlink((a)+2) */ -# define shrink(a) vinfo((a)+3) -# define stretch(a) vlink((a)+3) -# define stretch_order(a) vinfo((a)+4) -# define shrink_order(a) vlink((a)+4) -# define leader_ptr(a) vlink((a)+5) /* should be in vlink((a)+2) but fails */ -# define synctex_tag_glue(a) vinfo((a)+6) -# define synctex_line_glue(a) vlink((a)+6) - -#define glue_is_zero(p) \ - ((p == null) || (width(p) == 0 && stretch(p) == 0 && shrink(p) == 0)) - -#define glue_is_positive(p) \ - ((p == null) || (width(p) > 0)) - -#define reset_glue_to_zero(p) \ - if (p != null) { \ - width(p) = 0; \ - stretch(p) = 0; \ - shrink(p) = 0; \ - stretch_order(p) = 0; \ - shrink_order(p) = 0; \ - } - -#define copy_glue_values(p,q) \ - if (q == null) { \ - width(p) = 0; \ - stretch(p) = 0; \ - shrink(p) = 0; \ - stretch_order(p) = 0; \ - shrink_order(p) = 0; \ - } else { \ - width(p) = width(q); \ - stretch(p) = stretch(q); \ - shrink(p) = shrink(q); \ - stretch_order(p) = stretch_order(q); \ - shrink_order(p) = shrink_order(q); \ - } - - -/* - disc nodes could eventually be smaller, because the indirect - pointers are not really needed (8 instead of 10). -*/ - -typedef enum { - discretionary_disc = 0, - explicit_disc, - automatic_disc, - syllable_disc, - init_disc, /* first of a duo of syllable_discs */ - select_disc, /* second of a duo of syllable_discs */ -} discretionary_subtypes; - -# define disc_node_size 11 -# define pre_break_head(a) ((a)+5) -# define post_break_head(a) ((a)+7) -# define no_break_head(a) ((a)+9) - -# define disc_penalty(a) vlink((a)+2) -# define pre_break(a) vinfo((a)+3) -# define post_break(a) vlink((a)+3) -# define no_break(a) vlink((a)+4) /* we have vinfo((a)+4) for later usage */ - -# define vlink_pre_break(a) vlink(pre_break_head(a)) -# define vlink_post_break(a) vlink(post_break_head(a)) -# define vlink_no_break(a) vlink(no_break_head(a)) - -# define tlink_pre_break(a) tlink(pre_break_head(a)) -# define tlink_post_break(a) tlink(post_break_head(a)) -# define tlink_no_break(a) tlink(no_break_head(a)) - -typedef enum { - font_kern = 0, - explicit_kern, /* |subtype| of kern nodes from \.{\\kern} and \.{\\/} */ - accent_kern, /* |subtype| of kern nodes from accents */ - italic_kern, -} kern_subtypes; - -# define kern_node_size 5 -# define ex_kern(a) vinfo((a)+3) /* expansion factor (hz) */ -# define synctex_tag_kern(a) vinfo((a)+4) -# define synctex_line_kern(a) vlink((a)+4) - -# define box_node_size 9 - -/* todo, make an enum of this */ - -typedef enum { - unknown_list = 0, - line_list = 1, /* paragraph lines */ - hbox_list = 2, /* \.{\\hbox} */ - indent_list = 3, /* indentation box */ - align_row_list = 4, /* row from a \.{\\halign} or \.{\\valign} */ - align_cell_list = 5, /* cell from a \.{\\halign} or \.{\\valign} */ - equation_list = 6, /* display equation */ - equation_number_list = 7, /* display equation number */ - math_list_list = 8, - math_char_list = 9, - math_h_extensible_list = 10, - math_v_extensible_list = 11, - math_h_delimiter_list = 12, - math_v_delimiter_list = 13, - math_over_delimiter_list = 14, - math_under_delimiter_list = 15, - math_numerator_list = 16, - math_denominator_list = 17, - math_limits_list = 18, - math_fraction_list = 19, - math_nucleus_list = 20, - math_sup_list = 21, - math_sub_list = 22, - math_degree_list = 23, - math_scripts_list = 24, - math_over_list = 25, - math_under_list = 26, - math_accent_list = 27, - math_radical_list = 28, -} list_subtypes ; - -# define width(a) varmem[(a)+2].cint -# define depth(a) varmem[(a)+3].cint -# define height(a) varmem[(a)+4].cint -# define shift_amount(a) vlink((a)+5) -# define box_dir(a) vinfo((a)+5) -# define list_ptr(a) vlink((a)+6) -# define glue_order(a) subtype((a)+6) -# define glue_sign(a) type((a)+6) -# define glue_set(a) varmem[(a)+7].gr -# define synctex_tag_box(a) vinfo((a)+8) -# define synctex_line_box(a) vlink((a)+8) - -/* unset nodes */ - -# define glue_stretch(a) varmem[(a)+7].cint -# define glue_shrink shift_amount -# define span_count subtype - -typedef enum { - normal_rule = 0, - box_rule, - image_rule, - empty_rule, - user_rule, - math_over_rule, - math_under_rule, - math_fraction_rule, - math_radical_rule, - outline_rule, -} rule_subtypes; - -# define rule_node_size 9 -# define rule_dir(a) vlink((a)+5) -# define rule_index(a) vinfo((a)+6) -# define rule_transform(a) vlink((a)+6) -# define rule_left(a) vinfo((a)+7) -# define rule_right(a) vlink((a)+7) -# define synctex_tag_rule(a) vinfo((a)+8) -# define synctex_line_rule(a) vlink((a)+8) - -# define rule_math_size rule_index -# define rule_math_font rule_transform - -# define mark_node_size 3 -# define mark_ptr(a) vlink((a)+2) -# define mark_class(a) vinfo((a)+2) - -# define adjust_node_size 3 -# define adjust_pre subtype -# define adjust_ptr(a) vlink(a+2) - -# define glyph_node_size 7 -# define character(a) vinfo((a)+2) -# define font(a) vlink((a)+2) -# define lang_data(a) vinfo((a)+3) -# define lig_ptr(a) vlink((a)+3) -# define x_displace(a) vinfo((a)+4) -# define y_displace(a) vlink((a)+4) -# define ex_glyph(a) vinfo((a)+5) /* expansion factor (hz) */ -# define glyph_node_data(a) vlink((a)+5) -# define synctex_tag_glyph(a) vinfo((a)+6) -# define synctex_line_glyph(a) vlink((a)+6) - -# define is_char_node(a) (a!=null && type(a)==glyph_node) - -# define char_lang(a) ((const int)(signed short)(((signed int)((unsigned)lang_data(a)&0x7FFF0000)<<1)>>17)) -# define char_lhmin(a) ((const int)(((unsigned)lang_data(a) & 0x0000FF00)>>8)) -# define char_rhmin(a) ((const int)(((unsigned)lang_data(a) & 0x000000FF))) -# define char_uchyph(a) ((const int)(((unsigned)lang_data(a) & 0x80000000)>>31)) - -# define make_lang_data(a,b,c,d) (a>0 ? (1<<31): 0)+ \ - (b<<16)+ (((c>0 && c<256) ? c : 255)<<8)+(((d>0 && d<256) ? d : 255)) - -# define init_lang_data(a) lang_data(a)=256+1 - -# define set_char_lang(a,b) lang_data(a)=make_lang_data(char_uchyph(a),b,char_lhmin(a),char_rhmin(a)) -# define set_char_lhmin(a,b) lang_data(a)=make_lang_data(char_uchyph(a),char_lang(a),b,char_rhmin(a)) -# define set_char_rhmin(a,b) lang_data(a)=make_lang_data(char_uchyph(a),char_lang(a),char_lhmin(a),b) -# define set_char_uchyph(a,b) lang_data(a)=make_lang_data(b,char_lang(a),char_lhmin(a),char_rhmin(a)) - -# define margin_kern_node_size 4 -# define margin_char(a) vlink((a)+3) - -/*@# {|subtype| of marginal kerns}*/ - -typedef enum { - left_side = 0, - right_side -} margin_kern_subtypes ; - -typedef enum { - before = 0, - after -} math_subtypes ; - -# define math_node_size 7 -/* define width(a) vinfo((a)+2) */ -/* overlaps width */ -/* define shrink(a) vinfo((a)+3) */ -/* define stretch(a) vlink((a)+3) */ -/* define stretch_order(a) vinfo((a)+4) */ -/* define shrink_order(a) vlink((a)+4) */ -/* leader_ptr slot */ -# define surround(a) vinfo((a)+5) -# define synctex_tag_math(a) vinfo((a)+6) -# define synctex_line_math(a) vlink((a)+6) - -# define ins_node_size 6 -# define float_cost(a) varmem[(a)+2].cint -# define ins_ptr(a) vinfo((a)+5) -# define split_top_ptr(a) vlink((a)+5) - -# define page_ins_node_size 5 - -/* height = 4 */ - -typedef enum { - hlist_node = 0, - vlist_node, - rule_node, - ins_node, - mark_node, - adjust_node, - boundary_node, - disc_node, - whatsit_node, -#define last_preceding_break_node whatsit_node - local_par_node, - dir_node, -#define last_non_discardable_node dir_node - math_node, - glue_node, - kern_node, - penalty_node, - unset_node, - style_node, - choice_node, - simple_noad, - radical_noad, - fraction_noad, - accent_noad, - fence_noad, - math_char_node, /* kernel fields */ - sub_box_node, - sub_mlist_node, - math_text_char_node, - delim_node, /* shield fields */ - margin_kern_node, - glyph_node, /* this and below have attributes */ - align_record_node, - pseudo_file_node, - pseudo_line_node, - inserting_node, - split_up_node, - expr_node, - nesting_node, - span_node, - attribute_node, - glue_spec_node, - attribute_list_node, - temp_node, - align_stack_node, - movement_node, - if_node, - unhyphenated_node, - hyphenated_node, - delta_node, - passive_node, - shape_node, -} node_types; - -# define MAX_NODE_TYPE shape_node /* 60 */ - -/* - TH: these two defines still need checking. The node ordering in luatex is not - quite the same as in tex82, HH: but it's probably ok -*/ - -/* - - # define precedes_break(a) \ - # (type(a)<math_node && \ - # (type(a)!=whatsit_node || (subtype(a)!=dir_node && subtype(a)!=local_par_node))) - -*/ - -/* - # define precedes_break(a) (type(a)<math_node) - # define non_discardable(a) (type(a)<math_node || type(a) == dir_node || type(a) == local_par_node) -*/ - -# define precedes_break(a) (type(a)<=last_preceding_break_node) -# define precedes_kern(a) ((type(a) == kern_node) && (subtype(a) == font_kern || subtype(a) == accent_kern)) -# define precedes_dir(a) ((type(a) == dir_node) && (break_after_dir_mode_par == 1)) -# define non_discardable(a) (type(a)<=last_non_discardable_node) - -# define known_node_type(i) ( i >= 0 && i <= MAX_NODE_TYPE) - -# define last_known_node temp_node /* used by \lastnodetype */ - -# define movement_node_size 3 -# define if_node_size 2 -# define align_stack_node_size 6 -# define nesting_node_size 2 - -# define expr_node_size 3 -# define expr_type(A) type((A)+1) -# define expr_state(A) subtype((A)+1) /* enum defined in scanning.w */ -# define expr_e_field(A) vlink((A)+1) /* saved expression so far */ -# define expr_t_field(A) vlink((A)+2) /* saved term so far */ -# define expr_n_field(A) vinfo((A)+2) /* saved numerator */ - -# define span_node_size 3 -# define span_span(a) vlink((a)+1) -# define span_link(a) vinfo((a)+1) - -# define pseudo_file_node_size 2 -# define pseudo_lines(a) vlink((a)+1) - -# define nodetype_has_attributes(t) (((t)<=glyph_node) && ((t)!=unset_node)) - -# define nodetype_has_subtype(t) ((t)!=attribute_list_node && (t)!=attribute_node && (t)!=glue_spec_node) -# define nodetype_has_prev(t) nodetype_has_subtype((t)) - -/* - style and choice nodes; style nodes can be smaller, the information is encoded in - |subtype|, but choice nodes are on-the-spot converted to style nodes -*/ - -# define style_node_size 4 -# define display_mlist(a) vinfo((a)+2) /* mlist to be used in display style */ -# define text_mlist(a) vlink((a)+2) /* mlist to be used in text style */ -# define script_mlist(a) vinfo((a)+3) /* mlist to be used in script style */ -# define script_script_mlist(a) vlink((a)+3) /* mlist to be used in scriptscript style */ - -/* - because noad types get changed when processing we need to make sure some if the node - sizes match and that we don't share slots with different properties - - once it's sorted out we can go smaller and also adapt the flush etc code to it -*/ - -/* regular noads */ - -# define noad_size 8 -# define new_hlist(a) vlink((a)+2) /* the translation of an mlist */ -# define nucleus(a) vinfo((a)+2) /* the |nucleus| field of a noad */ -# define supscr(a) vlink((a)+3) /* the |supscr| field of a noad */ -# define subscr(a) vinfo((a)+3) /* the |subscr| field of a noad */ -# define noaditalic(a) vlink((a)+4) -# define noadwidth(a) vinfo((a)+4) -# define noadheight(a) vlink((a)+5) -# define noaddepth(a) vinfo((a)+5) -# define noadextra1(a) vlink((a)+6) /* we need to match delimiter (saves copy) */ -# define noadoptions(a) vinfo((a)+6) -# define noadextra3(a) vlink((a)+7) /* see (!) below */ -# define noadextra4(a) vinfo((a)+7) /* used to store samesize */ - -# define noad_fam(a) vlink((a)+6) /* noadextra1 */ - -typedef enum { - ord_noad_type = 0, - op_noad_type_normal, - op_noad_type_limits, - op_noad_type_no_limits, - bin_noad_type, - rel_noad_type, - open_noad_type, - close_noad_type, - punct_noad_type, - inner_noad_type, - under_noad_type, - over_noad_type, - vcenter_noad_type, -} noad_types; - -/* accent noads */ - -# define accent_noad_size 8 -# define top_accent_chr(a) vinfo((a)+6) /* the |top_accent_chr| field of an accent noad */ -# define bot_accent_chr(a) vlink((a)+6) /* the |bot_accent_chr| field of an accent noad */ -# define overlay_accent_chr(a) vinfo((a)+7) /* the |overlay_accent_chr| field of an accent noad */ -# define accentfraction(a) vlink((a)+7) - -typedef enum { - bothflexible_accent, - fixedtop_accent, - fixedbottom_accent, - fixedboth_accent, -} math_accent_subtypes ; - -/* left and right noads */ - -# define fence_noad_size 8 /* needs to match noad size */ -# define delimiteritalic(a) vlink((a)+4) -/* define delimiterwidth(a) vinfo((a)+4) */ -# define delimiterheight(a) vlink((a)+5) -# define delimiterdepth(a) vinfo((a)+5) -# define delimiter(a) vlink((a)+6) /* |delimiter| field in left and right noads */ -# define delimiteroptions(a) vinfo((a)+6) -# define delimiterclass(a) vlink((a)+7) /* (!) we could probably pack some more in 6 */ -# define delimitersamesize(a) vinfo((a)+7) /* set by engine */ - -/* when dimensions then axis else noaxis */ - -typedef enum { - noad_option_set = 0x08, - noad_option_unused_1 = 0x00 + 0x08, - noad_option_unused_2 = 0x01 + 0x08, - noad_option_axis = 0x02 + 0x08, - noad_option_no_axis = 0x04 + 0x08, - noad_option_exact = 0x10 + 0x08, - noad_option_left = 0x11 + 0x08, - noad_option_middle = 0x12 + 0x08, - noad_option_right = 0x14 + 0x08, - noad_option_no_sub_script = 0x21 + 0x08, - noad_option_no_super_script = 0x22 + 0x08, - noad_option_no_script = 0x23 + 0x08, - noad_option_no_rule = 0x24 + 0x08, -} delimiter_options ; - -# define delimiteroptionset(a) ((delimiteroptions(a) & noad_option_set ) == noad_option_set ) -# define delimiteraxis(a) ((delimiteroptions(a) & noad_option_axis ) == noad_option_axis ) -# define delimiternoaxis(a) ((delimiteroptions(a) & noad_option_no_axis) == noad_option_no_axis) -# define delimiterexact(a) ((delimiteroptions(a) & noad_option_exact ) == noad_option_exact ) - -# define noadoptionnosubscript(a) ( (type(a) == simple_noad) && ( \ - ((delimiteroptions(a) & noad_option_no_sub_script ) == noad_option_no_sub_script) || \ - ((delimiteroptions(a) & noad_option_no_script ) == noad_option_no_script ) )) -# define noadoptionnosupscript(a) ( (type(a) == simple_noad) && ( \ - ((delimiteroptions(a) & noad_option_no_super_script) == noad_option_no_super_script) || \ - ((delimiteroptions(a) & noad_option_no_script ) == noad_option_no_script ) )) - -typedef enum { - noad_delimiter_mode_noshift = 0x01, - noad_delimiter_mode_italics = 0x02, - noad_delimiter_mode_ordinal = 0x04, - noad_delimiter_mode_samenos = 0x08, - noad_delimiter_mode_charnos = 0x10, -} delimiter_modes ; - -# define delimitermodenoshift ((math_delimiters_mode_par & noad_delimiter_mode_noshift) == noad_delimiter_mode_noshift) -# define delimitermodeitalics ((math_delimiters_mode_par & noad_delimiter_mode_italics) == noad_delimiter_mode_italics) -# define delimitermodeordinal ((math_delimiters_mode_par & noad_delimiter_mode_ordinal) == noad_delimiter_mode_ordinal) -# define delimitermodesamenos ((math_delimiters_mode_par & noad_delimiter_mode_samenos) == noad_delimiter_mode_samenos) -# define delimitermodecharnos ((math_delimiters_mode_par & noad_delimiter_mode_charnos) == noad_delimiter_mode_charnos) - -/* subtype of fence noads */ - -/* -# define left_noad_side 1 -# define middle_noad_side 2 -# define right_noad_side 3 -# define no_noad_side 4 -*/ - -typedef enum { - unset_noad_side = 0, - left_noad_side = 1, - middle_noad_side = 2, - right_noad_side = 3, - no_noad_side = 4, -} fence_subtypes ; - -/* fraction noads */ - -# define fraction_noad_size 8 -# define thickness(a) vlink((a)+2) /* |thickness| field in a fraction noad */ -# define numerator(a) vlink((a)+3) /* |numerator| field in a fraction noad */ -# define denominator(a) vinfo((a)+3) /* |denominator| field in a fraction noad */ -# define left_delimiter(a) vlink((a)+5) /* first delimiter field of a noad */ -# define right_delimiter(a) vinfo((a)+5) /* second delimiter field of a fraction noad */ -# define middle_delimiter(a) vlink((a)+6) -# define fractionoptions(a) vinfo((a)+6) -# define fraction_fam(a) vlink((a)+7) - -# define fractionoptionset(a) ((fractionoptions(a) & noad_option_set ) == noad_option_set ) -# define fractionexact(a) ((fractionoptions(a) & noad_option_exact ) == noad_option_exact ) -# define fractionnoaxis(a) ((fractionoptions(a) & noad_option_no_axis) == noad_option_no_axis) -# define fractionnorule(a) ((fractionoptions(a) & noad_option_no_rule) == noad_option_no_rule) - -/* radical noads */ -/* this is like a fraction, but it only stores a |left_delimiter| */ - -# define radical_noad_size 7 -# define radicalwidth(a) vinfo((a)+4) -# define degree(a) vlink((a)+6) /* the root degree in a radical noad */ -# define radicaloptions(a) vinfo((a)+6) - -# define radicaloptionset(a) ((radicaloptions(a) & noad_option_set ) == noad_option_set) -# define radicalexact(a) ((radicaloptions(a) & noad_option_exact ) == noad_option_exact) -# define radicalleft(a) ((radicaloptions(a) & noad_option_left ) == noad_option_left) -# define radicalmiddle(a) ((radicaloptions(a) & noad_option_middle) == noad_option_middle) -# define radicalright(a) ((radicaloptions(a) & noad_option_right ) == noad_option_right) - -typedef enum { - radical_noad_type, - uradical_noad_type, - uroot_noad_type, - uunderdelimiter_noad_type, - uoverdelimiter_noad_type, - udelimiterunder_noad_type, - udelimiterover_noad_type, -} radical_subtypes; - -/* accessors for the |nucleus|-style node fields */ - -# define math_kernel_node_size 3 -# define math_fam(a) vinfo((a)+2) -# define math_character(a) vlink((a)+2) -# define math_list(a) vlink((a)+2) - -/* accessors for the |delimiter|-style two-word subnode fields */ - -# define math_shield_node_size 4 /* not used yet */ - -# define small_fam(A) vinfo((A)+2) /* |fam| for ``small'' delimiter */ -# define small_char(A) vlink((A)+2) /* |character| for ``small'' delimiter */ -# define large_fam(A) vinfo((A)+3) /* |fam| for ``large'' delimiter */ -# define large_char(A) vlink((A)+3) /* |character| for ``large'' delimiter */ - -/* we should have the codes in a separate enum: extension_codes */ - -/* be careful: must be in sync with whatsit_node_data[] ! (at least) */ - -typedef enum { - /* core */ - open_node = 0, - write_node, - close_node, - special_node, - use_box_resource_node, - use_image_resource_node, - save_pos_node, - late_lua_node, - user_defined_node, - /* dvi backend */ - dvi_literal_node = 15, - /* pdf backend */ - pdf_literal_node = 16, - pdf_refobj_node, - pdf_annot_node, - pdf_start_link_node, - pdf_end_link_node, - pdf_dest_node, - pdf_action_node, - pdf_thread_node, - pdf_start_thread_node, - pdf_end_thread_node, - pdf_thread_data_node, - pdf_link_data_node, - pdf_colorstack_node, - pdf_setmatrix_node, - pdf_save_node, - pdf_restore_node, - pdf_link_state_node, -} whatsit_types; - -# define first_common_whatsit 0 -# define last_common_whatsit user_defined_node -# define backend_first_dvi_whatsit 15 -# define backend_last_dvi_whatsit 15 -# define backend_first_pdf_whatsit 16 -# define backend_last_pdf_whatsit 32 - -/* add some slack for the future */ - -# define MAX_WHATSIT_TYPE 34 - -# define known_whatsit_type(i) ( \ - (i >= first_common_whatsit && i <= last_common_whatsit) || \ - (i >= backend_first_dvi_whatsit && i <= backend_last_dvi_whatsit) || \ - (i >= backend_first_pdf_whatsit && i <= backend_last_pdf_whatsit) \ -) - -# define get_node_size(i,j) (i!=whatsit_node ? node_data[i].size : whatsit_node_data[j].size) -# define get_node_name(i,j) (i!=whatsit_node ? node_data[i].name : whatsit_node_data[j].name) -# define get_etex_code(i) (node_data[i].etex) - -# define GLYPH_CHARACTER (1 << 0) -# define GLYPH_LIGATURE (1 << 1) -# define GLYPH_GHOST (1 << 2) -# define GLYPH_LEFT (1 << 3) -# define GLYPH_RIGHT (1 << 4) - -typedef enum { - glyph_unset = 0, - glyph_character = GLYPH_CHARACTER, - glyph_ligature = GLYPH_LIGATURE, - glyph_ghost = GLYPH_GHOST, - glyph_left = GLYPH_LEFT, - glyph_right = GLYPH_RIGHT, -} glyph_subtypes; - -# define is_character(p) ((subtype(p)) & GLYPH_CHARACTER) -# define is_ligature(p) ((subtype(p)) & GLYPH_LIGATURE ) -# define is_ghost(p) ((subtype(p)) & GLYPH_GHOST ) - -# define is_simple_character(p) (is_character(p) && !is_ligature(p) && !is_ghost(p)) - -# define is_leftboundary(p) (is_ligature(p) && ((subtype(p)) & GLYPH_LEFT )) -# define is_rightboundary(p) (is_ligature(p) && ((subtype(p)) & GLYPH_RIGHT )) -# define is_leftghost(p) (is_ghost(p) && ((subtype(p)) & GLYPH_LEFT )) -# define is_rightghost(p) (is_ghost(p) && ((subtype(p)) & GLYPH_RIGHT )) - - -# define set_is_glyph(p) subtype(p) = (quarterword) (subtype(p) & ~GLYPH_CHARACTER) -# define set_is_character(p) subtype(p) = (quarterword) (subtype(p) | GLYPH_CHARACTER) -# define set_is_ligature(p) subtype(p) = (quarterword) (subtype(p) | GLYPH_LIGATURE) -# define set_is_ghost(p) subtype(p) = (quarterword) (subtype(p) |GLYPH_GHOST) - -# define set_to_glyph(p) subtype(p) = (quarterword)(subtype(p) & 0xFF00) -# define set_to_character(p) subtype(p) = (quarterword)((subtype(p) & 0xFF00) | GLYPH_CHARACTER) -# define set_to_ligature(p) subtype(p) = (quarterword)((subtype(p) & 0xFF00) | GLYPH_LIGATURE) -# define set_to_ghost(p) subtype(p) = (quarterword)((subtype(p) & 0xFF00) | GLYPH_GHOST) - -# define set_is_leftboundary(p) { set_to_ligature(p); subtype(p) |= GLYPH_LEFT; } -# define set_is_rightboundary(p) { set_to_ligature(p); subtype(p) |= GLYPH_RIGHT; } -# define set_is_leftghost(p) { set_to_ghost(p); subtype(p) |= GLYPH_LEFT; } -# define set_is_rightghost(p) { set_to_ghost(p); subtype(p) |= GLYPH_RIGHT; } - -typedef enum { - cancel_boundary = 0, - user_boundary, - protrusion_boundary, - word_boundary, -} boundary_subtypes ; - -# define boundary_node_size 3 -# define boundary_value(a) vinfo((a)+2) - -# define special_node_size 3 - -typedef enum { - normal_dir = 0, - cancel_dir, -} dir_subtypes ; - -# define dir_node_size 5 -# define dir_dir(a) vinfo((a)+2) -# define dir_level(a) vlink((a)+2) -# define dir_refpos_h(a) vinfo((a)+3) -# define dir_refpos_v(a) vlink((a)+3) -# define dir_cur_h(a) vinfo((a)+4) -# define dir_cur_v(a) vlink((a)+4) - -# define write_node_size 3 -# define close_node_size 3 -# define write_tokens(a) vlink(a+2) -# define write_stream(a) vinfo(a+2) - -# define open_node_size 4 -# define open_name(a) vlink((a)+2) -# define open_area(a) vinfo((a)+3) -# define open_ext(a) vlink((a)+3) - -# define late_lua_node_size 4 -# define late_lua_data(a) vlink((a)+2) -# define late_lua_reg(a) vinfo((a)+2) -# define late_lua_name(a) vlink((a)+3) -# define late_lua_type(a) subtype((a)+3) - -# define save_pos_node_size 3 - -# define local_par_size 6 - -# define local_pen_inter(a) vinfo((a)+2) -# define local_pen_broken(a) vlink((a)+2) -# define local_box_left(a) vlink((a)+3) -# define local_box_left_width(a) vinfo((a)+3) -# define local_box_right(a) vlink((a)+4) -# define local_box_right_width(a) vinfo((a)+4) -# define local_par_dir(a) vinfo((a)+5) - -/* type of literal data */ - -# define lua_refid_literal 1 /* not a |normal| string */ -# define lua_refid_call 2 /* not a |normal| string */ - -/* begin of pdf backend nodes */ - -/* literal ctm types */ - -typedef enum { - set_origin = 0, - direct_page, - direct_always, - direct_raw, - direct_text, - direct_font, - scan_special, -} ctm_transform_modes; - -# define pdf_refobj_node_size 3 - -# define pdf_obj_objnum(a) vinfo((a) + 2) - -# define pdf_annot_node_size 8 -# define pdf_dest_node_size 8 -# define pdf_thread_node_size 8 - -/* - when a whatsit node representing annotation is created, words |1..3| are - width, height and depth of this annotation; after shipping out words |1..4| - are rectangle specification of annotation. For whatsit node representing - destination |pdf_ann_left| and |pdf_ann_top| are used for some types of destinations -*/ - -/* - coordinates of destinations/threads/annotations (in whatsit node) -*/ - -# define pdf_ann_left(a) varmem[(a) + 2].cint -# define pdf_ann_top(a) varmem[(a) + 3].cint -# define pdf_ann_right(a) varmem[(a) + 4].cint -# define pdf_ann_bottom(a) varmem[(a) + 5].cint - -# define pdf_literal_data(a) vlink((a)+2) -# define pdf_literal_mode(a) type((a)+2) -# define pdf_literal_type(a) subtype((a)+2) - -# define pdf_annot_data(a) vinfo((a) + 6) -# define pdf_link_attr(a) vinfo((a) + 6) -# define pdf_link_action(a) vlink((a) + 6) -# define pdf_annot_objnum(a) varmem[(a) + 7].cint -# define pdf_link_objnum(a) varmem[(a) + 7].cint - -# define pdf_dest_type(a) type((a) + 6) -# define pdf_dest_named_id(a) subtype((a) + 6) -# define pdf_dest_id(a) vlink((a) + 6) -# define pdf_dest_xyz_zoom(a) vinfo((a) + 7) -# define pdf_dest_objnum(a) vlink((a) + 7) - -# define pdf_thread_named_id(a) subtype((a) + 6) -# define pdf_thread_id(a) vlink((a) + 6) -# define pdf_thread_attr(a) vinfo((a) + 7) - -# define pdf_end_link_node_size 3 -# define pdf_end_thread_node_size 3 - -# define pdf_setmatrix_node_size 3 -# define pdf_save_node_size 3 -# define pdf_restore_node_size 3 - -# define pdf_link_state_node_size 3 - -# define pdf_link_state(a) vinfo((a) + 2) - -# define pdf_colorstack_node_size 4 -# define pdf_colorstack_stack(a) vlink((a)+2) -# define pdf_colorstack_cmd(a) vinfo((a)+2) -# define pdf_colorstack_data(a) vlink((a)+3) -# define pdf_setmatrix_data(a) vlink((a)+2) - -typedef enum { - pdf_action_page = 0, - pdf_action_goto, - pdf_action_thread, - pdf_action_user -} pdf_action_type; - -typedef enum { - pdf_window_notset, - pdf_window_new, - pdf_window_nonew, -} pdf_window_type; - -# define pdf_action_size 6 - -# define pdf_action_type(a) vlink((a)+2) /* enum pdf_action_type */ -# define pdf_action_named_id(a) vinfo((a)+2) /* boolean */ -# define pdf_action_id(a) vlink((a)+3) /* number or toks */ -# define pdf_action_file(a) vinfo((a)+3) /* toks */ -# define pdf_action_new_window(a) vlink((a)+4) /* enum pdf_window_type */ -# define pdf_action_tokens(a) vinfo((a)+4) /* toks */ -# define pdf_action_refcount(a) vlink((a)+5) /* number */ - -typedef enum { - colorstack_set = 0, - colorstack_push, - colorstack_pop, - colorstack_current -} colorstack_commands; - -# define colorstack_data colorstack_push /* last value where data field is set */ - -/* end of pdf backend nodes */ - -/* user defined nodes */ - -# define user_defined_node_size 4 -# define user_node_type(a) vinfo((a)+2) -# define user_node_id(a) vlink((a)+2) -# define user_node_value(a) vinfo((a)+3) - -/* node sused in the parbuilder */ - -# define active_node_size 4 /*number of words in extended active nodes */ -# define fitness subtype /*|very_loose_fit..tight_fit| on final line for this break */ -# define break_node(a) vlink((a)+1) /*pointer to the corresponding passive node */ -# define line_number(a) vinfo((a)+1) /*line that begins at this breakpoint */ -# define total_demerits(a) varmem[(a)+2].cint /* the quantity that \TeX\ minimizes */ -# define active_short(a) vinfo(a+3) /* |shortfall| of this line */ -# define active_glue(a) vlink(a+3) /*corresponding glue stretch or shrink */ - -# define passive_node_size 7 -# define cur_break(a) vlink((a)+1) /*in passive node, points to position of this breakpoint */ -# define prev_break(a) vinfo((a)+1) /*points to passive node that should precede this one */ -# define passive_pen_inter(a) vinfo((a)+2) -# define passive_pen_broken(a) vlink((a)+2) -# define passive_left_box(a) vlink((a)+3) -# define passive_left_box_width(a) vinfo((a)+3) -# define passive_last_left_box(a) vlink((a)+4) -# define passive_last_left_box_width(a) vinfo((a)+4) -# define passive_right_box(a) vlink((a)+5) -# define passive_right_box_width(a) vinfo((a)+5) -# define serial(a) vlink((a)+6) /* serial number for symbolic identification */ - -# define delta_node_size 10 /* 8 fields, stored in a+1..9 */ - -/* helpers */ - -# define couple_nodes(a,b) {assert(b!=null);vlink(a)=b;alink(b)=a;} -# define try_couple_nodes(a,b) if (b==null) vlink(a)=b; else {couple_nodes(a,b);} -# define uncouple_node(a) {assert(a!=null);vlink(a)=null;alink(a)=null;} - -# define cache_disabled max_halfword - -extern void delete_attribute_ref(halfword b); -extern void reset_node_properties(halfword b); -extern void reassign_attribute(halfword n,halfword new); -extern void build_attribute_list(halfword b); -extern halfword current_attribute_list(void); - -extern int unset_attribute(halfword n, int c, int w); -extern void set_attribute(halfword n, int c, int w); -extern int has_attribute(halfword n, int c, int w); - -extern halfword new_span_node(halfword n, int c, scaled w); - -extern void print_short_node_contents(halfword n); -extern void show_node_list(int i); -extern pointer actual_box_width(pointer r, scaled base_width); - -typedef struct _subtype_info { - int id; - const char *name; - int lua; -} subtype_info; - -typedef struct _field_info { - const char *name; - int lua; -} field_info; - -typedef struct _node_info { - int id; - int size; - subtype_info *subtypes; - field_info *fields; - const char *name; - int etex; - int lua; -} node_info; - -extern node_info node_data[]; -extern node_info whatsit_node_data[]; - -extern subtype_info node_subtypes_dir[]; -extern subtype_info node_subtypes_glue[]; -extern subtype_info node_subtypes_mathglue[]; -extern subtype_info node_subtypes_leader[]; -extern subtype_info node_subtypes_boundary[]; -extern subtype_info node_subtypes_penalty[]; -extern subtype_info node_subtypes_kern[]; -extern subtype_info node_subtypes_rule[]; -extern subtype_info node_subtypes_glyph[]; -extern subtype_info node_subtypes_disc[]; -extern subtype_info node_subtypes_marginkern[]; -extern subtype_info node_subtypes_list[]; -extern subtype_info node_subtypes_adjust[]; -extern subtype_info node_subtypes_math[]; -extern subtype_info node_subtypes_noad[]; -extern subtype_info node_subtypes_radical[]; -extern subtype_info node_subtypes_accent[]; -extern subtype_info node_subtypes_fence[]; - -extern subtype_info node_values_pdf_destination[]; -extern subtype_info node_values_pdf_literal[]; -extern subtype_info node_values_pdf_literal[]; -extern subtype_info node_values_pdf_action[]; -extern subtype_info node_values_pdf_window[]; - -extern subtype_info node_values_fill[]; -extern subtype_info node_values_dir[]; -extern subtype_info node_values_color_stack[]; - -extern subtype_info other_values_page_states[]; - -extern halfword new_node(int i, int j); -extern void flush_node_list(halfword); -extern void flush_node(halfword); -extern halfword do_copy_node_list(halfword, halfword); -extern halfword copy_node_list(halfword); -extern halfword copy_node(const halfword); -extern void check_node(halfword); -extern halfword fix_node_list(halfword); -extern int fix_node_lists; -extern char *sprint_node_mem_usage(void); -extern halfword raw_glyph_node(void); -extern halfword new_glyph_node(void); -extern int valid_node(halfword); - -extern void flush_node_wrapup_dvi(halfword); -extern void flush_node_wrapup_pdf(halfword); -extern void copy_node_wrapup_dvi(halfword, halfword); /* original target */ -extern void copy_node_wrapup_pdf(halfword, halfword); /* original target */ -extern void check_node_wrapup_dvi(halfword); /* DEBUG_NODES mode */ -extern void check_node_wrapup_pdf(halfword); /* DEBUG_NODES mode */ -extern void show_node_wrapup_dvi(halfword); -extern void show_node_wrapup_pdf(halfword); - -typedef enum { - normal_g = 0, /* normal */ - sfi, - fil, - fill, - filll -} glue_orders; - -# define zero_glue 0 -# define sfi_glue zero_glue+glue_spec_size -# define fil_glue sfi_glue+glue_spec_size -# define fill_glue fil_glue+glue_spec_size -# define ss_glue fill_glue+glue_spec_size -# define fil_neg_glue ss_glue+glue_spec_size -# define page_ins_head fil_neg_glue+glue_spec_size - -# define contrib_head page_ins_head+temp_node_size -# define page_head contrib_head+temp_node_size -# define temp_head page_head+temp_node_size -# define hold_head temp_head+temp_node_size -# define adjust_head hold_head+temp_node_size -# define pre_adjust_head adjust_head+temp_node_size -# define active pre_adjust_head+temp_node_size -# define align_head active+active_node_size -# define end_span align_head+temp_node_size -# define begin_point end_span+span_node_size -# define end_point begin_point+glyph_node_size -# define var_mem_stat_max (end_point+glyph_node_size-1) - -# define stretching 1 -# define shrinking 2 - -# define last_normal_node shape_node -# define last_whatsit_node pdf_restore_node - -# define is_running(A) ((A)==null_flag) /* tests for a running dimension */ - -extern halfword tail_of_list(halfword p); - -extern int var_used; - -# define cache_disabled max_halfword - -extern int max_used_attr; -extern halfword attr_list_cache; - -extern halfword new_null_box(void); -extern halfword new_rule(int s); -extern halfword new_glyph(int f, int c); -extern quarterword norm_min(int h); -extern halfword new_char(int f, int c); -extern scaled glyph_width(halfword p); -extern scaled glyph_height(halfword p); -extern scaled glyph_depth(halfword p); -extern halfword new_disc(void); -extern halfword new_math(scaled w, int s); -extern halfword new_spec(halfword p); -extern halfword new_param_glue(int n); -extern halfword new_glue(halfword q); -extern halfword new_skip_param(int n); -extern halfword new_kern(scaled w); -extern halfword new_penalty(int m, int s); - -extern int lua_properties_enabled ; -extern int lua_properties_level ; -extern int lua_properties_use_metatable ; - -extern halfword make_local_par_node(int mode); - -extern void synctex_set_mode(int mode); -extern int synctex_get_mode(void); -extern void synctex_set_tag(int tag); -extern void synctex_set_line(int line); -extern void synctex_force_tag(int tag); -extern void synctex_force_line(int tag); -extern int synctex_get_tag(void); -extern void synctex_set_no_files(int flag); -extern int synctex_get_no_files(void); -extern int synctex_get_line(void); - -extern void l_set_node_data(void) ; -extern void l_set_whatsit_data(void) ; - -#endif - diff --git a/Build/source/texk/web2c/luatexdir/tex/textcodes.c b/Build/source/texk/web2c/luatexdir/tex/textcodes.c deleted file mode 100644 index a6a0b3a55e3..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/textcodes.c +++ /dev/null @@ -1,530 +0,0 @@ -/* - -textcodes.w - -Copyright 2006-2010 Taco Hoekwater <taco@@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 of the License, or (at your -option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -License for more details. - -You should have received a copy of the GNU General Public License along -with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" - -/*tex - -Contrary to traditional \TEX\ we have catcode tables so that we can switch -catcode regimes very fast. We can have many such regimes and they're stored in -trees. - -*/ - -#define CATCODESTACK 8 -#define CATCODEDEFAULT 12 -#define CATCODE_MAX 32767 - -static sa_tree *catcode_heads = NULL; -static int catcode_max = 0; -static unsigned char *catcode_valid = NULL; - -void set_cat_code(int h, int n, halfword v, quarterword gl) -{ - sa_tree_item sa_value = { 0 }; - sa_tree s = catcode_heads[h]; - if (h > catcode_max) - catcode_max = h; - if (s == NULL) { - sa_value.int_value = CATCODEDEFAULT; - s = new_sa_tree(CATCODESTACK, 1, sa_value); - catcode_heads[h] = s; - } - sa_value.int_value = (int) v; - set_sa_item(s, n, sa_value, gl); -} - -halfword get_cat_code(int h, int n) -{ - sa_tree_item sa_value = { 0 }; - sa_tree s = catcode_heads[h]; - if (h > catcode_max) - catcode_max = h; - if (s == NULL) { - sa_value.int_value = CATCODEDEFAULT; - s = new_sa_tree(CATCODESTACK, 1, sa_value); - catcode_heads[h] = s; - } - return (halfword) get_sa_item(s, n).int_value; -} - -void unsave_cat_codes(int h, quarterword gl) -{ - int k; - if (h > catcode_max) - catcode_max = h; - for (k = 0; k <= catcode_max; k++) { - if (catcode_heads[k] != NULL) - restore_sa_stack(catcode_heads[k], gl); - } -} - -static void initializecatcodes(void) -{ - sa_tree_item sa_value = { 0 }; - catcode_max = 0; - catcode_heads = Mxmalloc_array(sa_tree, (CATCODE_MAX + 1)); - catcode_valid = Mxmalloc_array(unsigned char, (CATCODE_MAX + 1)); - memset(catcode_heads, 0, sizeof(sa_tree) * (CATCODE_MAX + 1)); - memset(catcode_valid, 0, sizeof(unsigned char) * (CATCODE_MAX + 1)); - catcode_valid[0] = 1; - sa_value.int_value = CATCODEDEFAULT; - catcode_heads[0] = new_sa_tree(CATCODESTACK, 1, sa_value); -} - -static void dumpcatcodes(void) -{ - int total = 0; - int k; - for (k = 0; k <= catcode_max; k++) { - if (catcode_valid[k]) { - total++; - } - } - dump_int(catcode_max); - dump_int(total); - for (k = 0; k <= catcode_max; k++) { - if (catcode_valid[k]) { - dump_int(k); - dump_sa_tree(catcode_heads[k],"catcodes"); - } - } -} - -static void undumpcatcodes(void) -{ - int total, k, x; - xfree(catcode_heads); - xfree(catcode_valid); - catcode_heads = Mxmalloc_array(sa_tree, (CATCODE_MAX + 1)); - catcode_valid = Mxmalloc_array(unsigned char, (CATCODE_MAX + 1)); - memset(catcode_heads, 0, sizeof(sa_tree) * (CATCODE_MAX + 1)); - memset(catcode_valid, 0, sizeof(unsigned char) * (CATCODE_MAX + 1)); - undump_int(catcode_max); - undump_int(total); - for (k = 0; k < total; k++) { - undump_int(x); - catcode_heads[x] = undump_sa_tree("catcodes"); - catcode_valid[x] = 1; - } -} - -int valid_catcode_table(int h) -{ - if (h <= CATCODE_MAX && h >= 0 && catcode_valid[h]) { - return 1; - } - return 0; -} - -void copy_cat_codes(int from, int to) -{ - if (from < 0 || from > CATCODE_MAX || catcode_valid[from] == 0) { - uexit(1); - } - if (to > catcode_max) - catcode_max = to; - destroy_sa_tree(catcode_heads[to]); - catcode_heads[to] = copy_sa_tree(catcode_heads[from]); - catcode_valid[to] = 1; -} - -void initex_cat_codes(int h) -{ - int k; - if (h > catcode_max) - catcode_max = h; - destroy_sa_tree(catcode_heads[h]); - catcode_heads[h] = NULL; - set_cat_code(h, '\r', car_ret_cmd, 1); - set_cat_code(h, ' ', spacer_cmd, 1); - set_cat_code(h, '\\', escape_cmd, 1); - set_cat_code(h, '%', comment_cmd, 1); - set_cat_code(h, 127, invalid_char_cmd, 1); - set_cat_code(h, 0, ignore_cmd, 1); - set_cat_code(h, 0xFEFF, ignore_cmd, 1); - for (k = 'A'; k <= 'Z'; k++) { - set_cat_code(h, k, letter_cmd, 1); - set_cat_code(h, k + 'a' - 'A', letter_cmd, 1); - } - catcode_valid[h] = 1; -} - -static void freecatcodes(void) -{ - int k; - for (k = 0; k <= catcode_max; k++) { - if (catcode_valid[k]) { - destroy_sa_tree(catcode_heads[k]); - } - } - xfree(catcode_heads); - xfree(catcode_valid); -} - -/*tex - -The lowercase mapping codes are also stored in a tree. - -*/ - -#define LCCODESTACK 8 -#define LCCODEDEFAULT 0 - -static sa_tree lccode_head = NULL; - -void set_lc_code(int n, halfword v, quarterword gl) -{ - sa_tree_item sa_value = { 0 }; - sa_value.int_value = (int) v; - set_sa_item(lccode_head, n, sa_value, gl); -} - -halfword get_lc_code(int n) -{ - return (halfword) get_sa_item(lccode_head, n).int_value; -} - -static void unsavelccodes(quarterword gl) -{ - restore_sa_stack(lccode_head, gl); -} - -static void initializelccodes(void) -{ - sa_tree_item sa_value = { 0 }; - sa_value.int_value = LCCODEDEFAULT; - lccode_head = new_sa_tree(LCCODESTACK, 1, sa_value); -} - -static void dumplccodes(void) -{ - dump_sa_tree(lccode_head,"lccodes"); -} - -static void undumplccodes(void) -{ - lccode_head = undump_sa_tree("lccodes"); -} - -static void freelccodes(void) -{ - destroy_sa_tree(lccode_head); -} - -/*tex - -And the uppercase mapping codes are again stored in a tree. - -*/ - -#define UCCODESTACK 8 -#define UCCODEDEFAULT 0 - -static sa_tree uccode_head = NULL; - -void set_uc_code(int n, halfword v, quarterword gl) -{ - sa_tree_item sa_value = { 0 }; - sa_value.int_value = (int) v; - set_sa_item(uccode_head, n, sa_value, gl); -} - -halfword get_uc_code(int n) -{ - return (halfword) get_sa_item(uccode_head, n).int_value; -} - -static void unsaveuccodes(quarterword gl) -{ - restore_sa_stack(uccode_head, gl); -} - -static void initializeuccodes(void) -{ - sa_tree_item sa_value = { 0 }; - sa_value.int_value = UCCODEDEFAULT; - uccode_head = new_sa_tree(UCCODESTACK, 1, sa_value); -} - -static void dumpuccodes(void) -{ - dump_sa_tree(uccode_head,"uccodes"); -} - -static void undumpuccodes(void) -{ - uccode_head = undump_sa_tree("uccodes"); -} - -static void freeuccodes(void) -{ - destroy_sa_tree(uccode_head); -} - -/*tex - -By now it will be no surprise that the space factors get stored in a tree. - -*/ - -#define SFCODESTACK 8 -#define SFCODEDEFAULT 1000 - -static sa_tree sfcode_head = NULL; - -void set_sf_code(int n, halfword v, quarterword gl) -{ - sa_tree_item sa_value = { 0 }; - sa_value.int_value = (int) v; - set_sa_item(sfcode_head, n, sa_value, gl); -} - -halfword get_sf_code(int n) -{ - return (halfword) get_sa_item(sfcode_head, n).int_value; -} - -static void unsavesfcodes(quarterword gl) -{ - restore_sa_stack(sfcode_head, gl); -} - -static void initializesfcodes(void) -{ - sa_tree_item sa_value = { 0 }; - sa_value.int_value = SFCODEDEFAULT; - sfcode_head = new_sa_tree(SFCODESTACK, 1, sa_value); -} - -static void dumpsfcodes(void) -{ - dump_sa_tree(sfcode_head,"sfcodes"); -} - -static void undumpsfcodes(void) -{ - sfcode_head = undump_sa_tree("sfcodes"); -} - -static void freesfcodes(void) -{ - destroy_sa_tree(sfcode_head); -} - -/*tex - -The hyphenation codes are indeed stored in a tree and are used instead of -lowercase codes when deciding what characters to take into acccount when -hyphenating. They are bound to upto |HJCODE_MAX| languages. - -*/ - -#define HJCODESTACK 8 -#define HJCODEDEFAULT 0 -#define HJCODE_MAX 16383 - -static sa_tree *hjcode_heads = NULL; -static int hjcode_max = 0; -static unsigned char *hjcode_valid = NULL; - -/*tex - -Here we set codes but we don't initialize from lccodes. - -*/ - -void set_hj_code(int h, int n, halfword v, quarterword gl) -{ - sa_tree_item sa_value = { 0 }; - sa_tree s = hjcode_heads[h]; - if (h > hjcode_max) - hjcode_max = h; - if (s == NULL) { - sa_value.int_value = HJCODEDEFAULT; - s = new_sa_tree(HJCODESTACK, 1, sa_value); - hjcode_heads[h] = s; - } - sa_value.int_value = (int) v; - set_sa_item(s, n, sa_value, gl); -} - -/*tex - -We just return the lccodes when nothing is set. - -*/ - -halfword get_hj_code(int h, int n) -{ - sa_tree s = hjcode_heads[h]; - if (s == NULL) { - s = lccode_head; - } - return (halfword) get_sa_item(s, n).int_value; -} - -/*tex - -We don't restore as we can have more languages in a paragraph and hyphenation -takes place at a later stage so we would get weird grouping side effects .. so, -one can overload settings but management is then upto the used, so no: - -*/ - -/* - static void unsavehjcodes(quarterword gl) { } -*/ - -static void initializehjcodes(void) -{ - /* - sa_tree_item sa_value = { 0 }; - */ - hjcode_max = 0; - hjcode_heads = Mxmalloc_array(sa_tree, (HJCODE_MAX + 1)); - hjcode_valid = Mxmalloc_array(unsigned char, (HJCODE_MAX + 1)); - memset(hjcode_heads, 0, sizeof(sa_tree) * (HJCODE_MAX + 1)); - memset(hjcode_valid, 0, sizeof(unsigned char) * (HJCODE_MAX + 1)); - /* - hjcode_valid[0] = 1; - sa_value.int_value = HJCODEDEFAULT; - hjcode_heads[0] = new_sa_tree(HJCODESTACK, 1, sa_value); - */ -} - -void hj_codes_from_lc_codes(int h) -{ - sa_tree_item sa_value = { 0 }; - sa_tree s = hjcode_heads[h]; - if (s != NULL) { - destroy_sa_tree(s); - } else if (h > hjcode_max) { - hjcode_max = h; - } - if (s == NULL) { - sa_value.int_value = HJCODEDEFAULT; - s = new_sa_tree(HJCODESTACK, 1, sa_value); - hjcode_heads[h] = s; - } - hjcode_heads[h] = copy_sa_tree(lccode_head); - hjcode_valid[h] = 1; -} - -static void dumphjcodes(void) -{ - int total = 0; - int k; - for (k = 0; k <= hjcode_max; k++) { - if (hjcode_valid[k]) { - total++; - } - } - dump_int(hjcode_max); - dump_int(total); - for (k = 0; k <= hjcode_max; k++) { - if (hjcode_valid[k]) { - dump_int(k); - dump_sa_tree(hjcode_heads[k],"hjcodes"); - } - } -} - -static void undumphjcodes(void) -{ - int total, k, x; - xfree(hjcode_heads); - xfree(hjcode_valid); - hjcode_heads = Mxmalloc_array(sa_tree, (HJCODE_MAX + 1)); - hjcode_valid = Mxmalloc_array(unsigned char, (HJCODE_MAX + 1)); - memset(hjcode_heads, 0, sizeof(sa_tree) * (HJCODE_MAX + 1)); - memset(hjcode_valid, 0, sizeof(unsigned char) * (HJCODE_MAX + 1)); - undump_int(hjcode_max); - undump_int(total); - for (k = 0; k < total; k++) { - undump_int(x); - hjcode_heads[x] = undump_sa_tree("hjcodes"); - hjcode_valid[x] = 1; - } -} - -static void freehjcodes(void) -{ - int k; - for (k = 0; k <= hjcode_max; k++) { - if (hjcode_valid[k]) { - destroy_sa_tree(hjcode_heads[k]); - } - } - xfree(hjcode_heads); - xfree(hjcode_valid); -} - -/*tex - -The public management functions. - -*/ - -void unsave_text_codes(quarterword grouplevel) -{ - unsavelccodes(grouplevel); - unsaveuccodes(grouplevel); - unsavesfcodes(grouplevel); -} - -void initialize_text_codes(void) -{ - initializecatcodes(); - initializelccodes(); - initializeuccodes(); - initializesfcodes(); - initializehjcodes(); -} - -void free_text_codes(void) -{ - freecatcodes(); - freelccodes(); - freeuccodes(); - freesfcodes(); - freehjcodes(); -} - -void dump_text_codes(void) -{ - dumpcatcodes(); - dumplccodes(); - dumpuccodes(); - dumpsfcodes(); - dumphjcodes(); -} - -void undump_text_codes(void) -{ - undumpcatcodes(); - undumplccodes(); - undumpuccodes(); - undumpsfcodes(); - undumphjcodes(); -} diff --git a/Build/source/texk/web2c/luatexdir/tex/textcodes.h b/Build/source/texk/web2c/luatexdir/tex/textcodes.h deleted file mode 100644 index 759d9ee740e..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/textcodes.h +++ /dev/null @@ -1,54 +0,0 @@ -/* textcodes.h - - Copyright 2009 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#ifndef TEXTCODES_H -# define TEXTCODES_H - -void set_cat_code(int h, int n, halfword v, quarterword gl); -halfword get_cat_code(int h, int n); -int valid_catcode_table(int h); -void unsave_cat_codes(int h, quarterword gl); -void copy_cat_codes(int from, int to); -void initex_cat_codes(int h); - -void set_lc_code(int n, halfword v, quarterword gl); -halfword get_lc_code(int n); - -void set_uc_code(int n, halfword v, quarterword gl); -halfword get_uc_code(int n); - -void set_sf_code(int n, halfword v, quarterword gl); -halfword get_sf_code(int n); - -void set_hj_code(int l, int n, halfword v, quarterword gl); -halfword get_hj_code(int l, int n); -void hj_codes_from_lc_codes(int h); - -void initialize_text_codes(void); -void unsave_text_codes(quarterword grouplevel); - -void dump_text_codes(void); -void undump_text_codes(void); - -void free_math_codes(void); -void free_text_codes(void); - -#endif diff --git a/Build/source/texk/web2c/luatexdir/tex/textoken.c b/Build/source/texk/web2c/luatexdir/tex/textoken.c deleted file mode 100644 index e28626bbd26..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/textoken.c +++ /dev/null @@ -1,3920 +0,0 @@ -/* - -Copyright 2006-2011 Taco Hoekwater <taco@luatex.org> - -This file is part of LuaTeX. - -LuaTeX is free software; you can redistribute it and/or modify it under the terms -of the GNU General Public License as published by the Free Software Foundation; -either version 2 of the License, or (at your option) any later version. - -LuaTeX is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - -You should have received a copy of the GNU General Public License along with -LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -*/ - -#include "ptexlib.h" - -#define detokenized_line() (line_catcode_table==NO_CAT_TABLE) - -#define do_get_cat_code(a,b) do { \ - if (line_catcode_table==DEFAULT_CAT_TABLE) \ - a=get_cat_code(cat_code_table_par,b); \ - else if (line_catcode_table>-0xFF) \ - a=get_cat_code(line_catcode_table,b); \ - else \ - a= - line_catcode_table - 0xFF ; \ - } while (0) - - -/*tex - - The \TeX\ system does nearly all of its own memory allocation, so that it can - readily be transported into environments that do not have automatic - facilities for strings, garbage collection, etc., and so that it can be in - control of what error messages the user receives. The dynamic storage - requirements of \TeX\ are handled by providing two large arrays called - |fixmem| and |varmem| in which consecutive blocks of words are used as nodes - by the \TeX\ routines. - - Pointer variables are indices into this array, or into another array called - |eqtb| that will be explained later. A pointer variable might also be a - special flag that lies outside the bounds of |mem|, so we allow pointers to - assume any |halfword| value. The minimum halfword value represents a null - pointer. \TeX\ does not assume that |mem[null]| exists. - - Locations in |fixmem| are used for storing one-word records; a conventional - \.{AVAIL} stack is used for allocation in this array. - -*/ - -/*tex the big dynamic storage area */ - -smemory_word *fixmem; - -/*tex the smallest location of one-word memory in use */ - -unsigned fix_mem_min; - -/*tex the largest location of one-word memory in use */ - -unsigned fix_mem_max; - -/*tex - - In order to study the memory requirements of particular applications, it is - possible to prepare a version of \TeX\ that keeps track of current and - maximum memory usage. When code between the delimiters |stat| $\ldots$ - |tats| is not commented out, \TeX\ will run a bit slower but it will report - these statistics when |tracing_stats| is sufficiently large. - -*/ - -/*tex how much memory is in use */ - -int dyn_used; - -/*tex head of the list of available one-word nodes */ - -halfword avail; - -/*tex the last one-word node used in |mem| */ - -unsigned fix_mem_end; - -/*tex head of a junk list, write only */ - -halfword garbage; - -/*tex head of a temporary list of some kind */ - -halfword temp_token_head; - -/*tex head of a temporary list of another kind */ - -halfword hold_token_head; - -/*tex a constant token list */ - -halfword omit_template; - -/*tex permanently empty list */ - -halfword null_list; - -/*tex head of token list built by |scan_keyword| */ - -halfword backup_head; - -void initialize_tokens(void) -{ - halfword p; - avail = null; - fix_mem_end = 0; - p = get_avail(); - temp_token_head = p; - set_token_info(temp_token_head, 0); - p = get_avail(); - hold_token_head = p; - set_token_info(hold_token_head, 0); - p = get_avail(); - omit_template = p; - set_token_info(omit_template, 0); - p = get_avail(); - null_list = p; - set_token_info(null_list, 0); - p = get_avail(); - backup_head = p; - set_token_info(backup_head, 0); - p = get_avail(); - garbage = p; - set_token_info(garbage, 0); - dyn_used = 0; -} - -/*tex - - The function |get_avail| returns a pointer to a new one-word node whose - |link| field is null. However, \TeX\ will halt if there is no more room left. - - If the available-space list is empty, i.e., if |avail=null|, we try first to - increase |fix_mem_end|. If that cannot be done, i.e., if - |fix_mem_end=fix_mem_max|, we try to reallocate array |fixmem|. If, that - doesn't work, we have to quit. - - Single-word node allocation: -*/ - -halfword get_avail(void) -{ - /*tex The new node being got: */ - unsigned p; - unsigned t; - /*tex Get top location in the |avail| stack. */ - p = (unsigned) avail; - if (p != null) { - /*tex Pop it off. */ - avail = token_link(avail); - } else if (fix_mem_end < fix_mem_max) { - /*tex Go into virgin territory. */ - incr(fix_mem_end); - p = fix_mem_end; - } else { - /*tex The big dynamic storage area. */ - smemory_word *new_fixmem; - t = (fix_mem_max / 5); - new_fixmem = fixmemcast(realloc(fixmem, sizeof(smemory_word) * (fix_mem_max + t + 1))); - if (new_fixmem == NULL) { - /*tex If memory is exhausted, display possible runaway text. */ - runaway(); - overflow("token memory size", fix_mem_max); - } else { - fixmem = new_fixmem; - } - memset(voidcast(fixmem + fix_mem_max + 1), 0, t * sizeof(smemory_word)); - fix_mem_max += t; - p = ++fix_mem_end; - } - /*tex Provide an oft-desired initialization of the new node. */ - token_link(p) = null; - /*tex Maintain statistics. */ - incr(dyn_used); - return (halfword) p; -} - -/*tex - - The procedure |flush_list(p)| frees an entire linked list of one-word nodes - that starts at position |p|. - - This makes list of single-word nodes available: - -*/ - -void flush_list(halfword p) -{ - halfword q, r; - if (p != null) { - r = p; - do { - q = r; - r = token_link(r); - decr(dyn_used); - } while (r != null); - /*tex Now |q| is the last node on the list. */ - token_link(q) = avail; - avail = p; - } -} - -/*tex - - A \TeX\ token is either a character or a control sequence, and it is - represented internally in one of two ways: (1)~A character whose ASCII code - number is |c| and whose command code is |m| is represented as the number - $2^{21}m+c$; the command code is in the range |1<=m<=14|. (2)~A control - sequence whose |eqtb| address is |p| is represented as the number - |cs_token_flag+p|. Here |cs_token_flag=t=| $2^{25}-1$ is larger than - $2^{21}m+c$, yet it is small enough that |cs_token_flag+p< max_halfword|; - thus, a token fits comfortably in a halfword. - - A token |t| represents a |left_brace| command if and only if - |t<left_brace_limit|; it represents a |right_brace| command if and only if we - have |left_brace_limit<=t<right_brace_limit|; and it represents a |match| or - |end_match| command if and only if |match_token<=t<=end_match_token|. The - following definitions take care of these token-oriented constants and a few - others. - - A token list is a singly linked list of one-word nodes in |mem|, where each - word contains a token and a link. Macro definitions, output-routine - definitions, marks, \.{\\write} texts, and a few other things are remembered - by \TeX\ in the form of token lists, usually preceded by a node with a - reference count in its |token_ref_count| field. The token stored in location - |p| is called |info(p)|. - - Three special commands appear in the token lists of macro definitions. When - |m=match|, it means that \TeX\ should scan a parameter for the current macro; - when |m=end_match|, it means that parameter matching should end and \TeX\ - should start reading the macro text; and when |m=out_param|, it means that - \TeX\ should insert parameter number |c| into the text at this point. - - The enclosing \.{\char'173} and \.{\char'175} characters of a macro - definition are omitted, but the final right brace of an output routine is - included at the end of its token list. - - Here is an example macro definition that illustrates these conventions. After - \TeX\ processes the text - - \starttyping - \def\mac a#1#2 \b {#1\-a ##1#2 \#2\} - \stoptyping - - the definition of \.{\\mac} is represented as a token list containing - - \starttyping - (reference count) |letter|a |match|# |match|# |spacer| \b |end_match| - |out_param|1 \- |letter|a |spacer|, |mac_param|# |other_char|1 - |out_param|2 |spacer| |out_param|2 - \stoptyping - - The procedure |scan_toks| builds such token lists, and |macro_call| does the - parameter matching. - - Examples such as \type{\def\m{\def\m{a} b}} explain why reference - counts would be needed even if \TeX\ had no \.{\\let} operation: When the - token list for \.{\\m} is being read, the redefinition of \.{\\m} changes the - |eqtb| entry before the token list has been fully consumed, so we dare not - simply destroy a token list when its control sequence is being redefined. - - If the parameter-matching part of a definition ends with `\.{\#\{}', the - corresponding token list will have `\.\{' just before the `|end_match|' and - also at the very end. The first `\.\{' is used to delimit the parameter; the - second one keeps the first from disappearing. - - The |print_meaning| subroutine displays |cur_cmd| and |cur_chr| in symbolic - form, including the expansion of a macro or mark. - -*/ - -void print_meaning(void) -{ - /*tex - - This would make sense but some macro packages don't like it: - - \starttyping - if (cur_cmd == math_given_cmd) { - cur_cmd = xmath_given_cmd ; - } - \stoptyping - - */ - print_cmd_chr((quarterword) cur_cmd, cur_chr); - if (cur_cmd >= call_cmd) { - print_char(':'); - print_ln(); - token_show(cur_chr); - } else { - /*tex Show the meaning of a mark node. */ - if ((cur_cmd == top_bot_mark_cmd) && (cur_chr < marks_code)) { - print_char(':'); - print_ln(); - switch (cur_chr) { - case first_mark_code: - token_show(first_mark(0)); - break; - case bot_mark_code: - token_show(bot_mark(0)); - break; - case split_first_mark_code: - token_show(split_first_mark(0)); - break; - case split_bot_mark_code: - token_show(split_bot_mark(0)); - break; - default: - token_show(top_mark(0)); - break; - } - } - } -} - -/*tex - - The procedure |show_token_list|, which prints a symbolic form of the token - list that starts at a given node |p|, illustrates these conventions. The - token list being displayed should not begin with a reference count. However, - the procedure is intended to be robust, so that if the memory links are awry - or if |p| is not really a pointer to a token list, nothing catastrophic will - happen. - - An additional parameter |q| is also given; this parameter is either null or - it points to a node in the token list where a certain magic computation takes - place that will be explained later. (Basically, |q| is non-null when we are - printing the two-line context information at the time of an error message; - |q| marks the place corresponding to where the second line should begin.) - - For example, if |p| points to the node containing the first \.a in the token - list above, then |show_token_list| will print the string $$\hbox{`\.{a\#1\#2\ - \\b\ ->\#1\\-a\ \#\#1\#2\ \#2}';}$$ and if |q| points to the node containing - the second \.a, the magic computation will be performed just before the - second \.a is printed. - - The generation will stop, and `\.{\\ETC.}' will be printed, if the length of - printing exceeds a given limit~|l|. Anomalous entries are printed in the form - of control sequences that are not followed by a blank space, e.g., - `\.{\\BAD.}'; this cannot be confused with actual control sequences because a - real control sequence named \.{BAD} would come out `\.{\\BAD\ }'. - -*/ - -#define not_so_bad(p) \ - switch (m) { \ - case assign_int_cmd: \ - if (c >= (backend_int_base) && c <= (backend_int_last)) \ - p("[internal backend integer]"); \ - break; \ - case assign_dimen_cmd: \ - if (c >= (backend_dimen_base) && c <= (backend_dimen_last)) \ - p("[internal backend dimension]"); \ - break; \ - case assign_toks_cmd: \ - if (c >= (backend_toks_base) && c <= (backend_toks_last)) \ - p("[internal backend tokenlist]"); \ - break; \ - case node_cmd: \ - p("[internal node pointer]"); \ - break; \ - case lua_call_cmd: \ - p("[internal lua function call]"); \ - break; \ - case lua_expandable_call_cmd: \ - p("[internal expandable lua function call]"); \ - break; \ - case lua_local_call_cmd: \ - p("[internal local lua function call]"); \ - break; \ - default: \ - p("BAD"); \ - break; \ - } - -void show_token_list(int p, int q, int l) -{ - /*tex pieces of a token */ - int m, c; - /*tex character used in a `|match|' */ - ASCII_code match_chr = '#'; - /*tex the highest parameter number, as an ASCII digit */ - ASCII_code n = '0'; - tally = 0; - if (l < 0) - l = 0x3FFFFFFF; - while ((p != null) && (tally < l)) { - if (p == q) { - /*tex Do magic computation. */ - set_trick_count(); - } - /*tex Display token |p|, and |return| if there are problems. */ - if ((p < (int) fix_mem_min) || (p > (int) fix_mem_end)) { - tprint_esc("CLOBBERED."); - return; - } - if (token_info(p) >= cs_token_flag) { - if (!((inhibit_par_tokens) && (token_info(p) == par_token))) - print_cs(token_info(p) - cs_token_flag); - } else { - m = token_cmd(token_info(p)); - c = token_chr(token_info(p)); - if (token_info(p) < 0) { - tprint_esc("BAD"); - } else { - /* - Display the token \type {(|m|,|c|)}. The procedure usually - ``learns'' the character code used for macro parameters by - seeing one in a |match| command before it runs into any - |out_param| commands. - - */ - switch (m) { - case left_brace_cmd: - case right_brace_cmd: - case math_shift_cmd: - case tab_mark_cmd: - case sup_mark_cmd: - case sub_mark_cmd: - case spacer_cmd: - case letter_cmd: - case other_char_cmd: - print(c); - break; - case mac_param_cmd: - if (!in_lua_escape && (is_in_csname==0)) - print(c); - print(c); - break; - case out_param_cmd: - print(match_chr); - if (c <= 9) { - print_char(c + '0'); - } else { - print_char('!'); - return; - } - break; - case match_cmd: - match_chr = c; - print(c); - incr(n); - print_char(n); - if (n > '9') - return; - break; - case end_match_cmd: - if (c == 0) - tprint("->"); - break; - default: - not_so_bad(tprint); - break; - } - } - } - p = token_link(p); - } - if (p != null) - tprint_esc("ETC."); -} - -#define do_buffer_to_unichar(a,b) do { \ - a = (halfword)str2uni(buffer+b); \ - b += utf8_size(a); \ -} while (0) - -/*tex - - Here's the way we sometimes want to display a token list, given a pointer to - its reference count; the pointer may be null. - -*/ - -void token_show(halfword p) -{ - if (p != null) - show_token_list(token_link(p), null, 10000000); -} - -/*tex - - |delete_token_ref|, is called when a pointer to a token list's reference - count is being removed. This means that the token list should disappear if - the reference count was |null|, otherwise the count should be decreased by - one. - - |p| points to the reference count of a token list that is losing one - reference. - -*/ - -void delete_token_ref(halfword p) -{ - if (token_ref_count(p) == 0) - flush_list(p); - else - decr(token_ref_count(p)); -} - -int get_char_cat_code(int curchr) -{ - int a; - do_get_cat_code(a,curchr); - return a; -} - -static void invalid_character_error(void) -{ - const char *hlp[] = { - "A funny symbol that I can't read has just been input.", - "Continue, and I'll forget that it ever happened.", - NULL - }; - deletions_allowed = false; - tex_error("Text line contains an invalid character", hlp); - deletions_allowed = true; -} - -static boolean process_sup_mark(void); - -static int scan_control_sequence(void); - -typedef enum { - next_line_ok, - next_line_return, - next_line_restart -} next_line_retval; - -static next_line_retval next_line(void); - -/*tex - - In case you are getting bored, here is a slightly less trivial routine: Given - a string of lowercase letters, like `\.{pt}' or `\.{plus}' or `\.{width}', - the |scan_keyword| routine checks to see whether the next tokens of input - match this string. The match must be exact, except that uppercase letters - will match their lowercase counterparts; uppercase equivalents are determined - by subtracting |"a"-"A"|, rather than using the |uc_code| table, since \TeX\ - uses this routine only for its own limited set of keywords. - - If a match is found, the characters are effectively removed from the input - and |true| is returned. Otherwise |false| is returned, and the input is left - essentially unchanged (except for the fact that some macros may have been - expanded, etc.). - -*/ - -boolean scan_keyword(const char *s) -{ - /*tex tail of the backup list */ - halfword p; - /*tex new node being added to the token list via |store_new_token| */ - halfword q; - /*tex index into |str_pool| */ - const char *k; - halfword save_cur_cs = cur_cs; - if (strlen(s) == 0) { - /*tex but not with newtokenlib zero keyword simply doesn't match */ - return false ; - } - p = backup_head; - token_link(p) = null; - k = s; - while (*k) { - /*tex Recursion is possible here! */ - get_x_token(); - if ((cur_cs == 0) && ((cur_chr == *k) || (cur_chr == *k - 'a' + 'A'))) { - store_new_token(cur_tok); - k++; - } else if ((cur_cmd != spacer_cmd) || (p != backup_head)) { - back_input(); - if (p != backup_head) { - begin_token_list(token_link(backup_head), backed_up); - } - cur_cs = save_cur_cs; - return false; - } - } - if (token_link(backup_head) != null) - flush_list(token_link(backup_head)); - cur_cs = save_cur_cs; - return true; -} - -boolean scan_keyword_case_sensitive(const char *s) -{ - halfword p; - halfword q; - const char *k; - halfword save_cur_cs = cur_cs; - if (strlen(s) == 0) - return false ; - p = backup_head; - token_link(p) = null; - k = s; - while (*k) { - get_x_token(); - if ((cur_cs == 0) && (cur_chr == *k)) { - store_new_token(cur_tok); - k++; - } else if ((cur_cmd != spacer_cmd) || (p != backup_head)) { - back_input(); - if (p != backup_head) { - begin_token_list(token_link(backup_head), backed_up); - } - cur_cs = save_cur_cs; - return false; - } - } - if (token_link(backup_head) != null) - flush_list(token_link(backup_head)); - cur_cs = save_cur_cs; - return true; -} - -/*tex - - We can not return |undefined_control_sequence| under some conditions (inside - |shift_case|, for example). This needs thinking. - -*/ - -/*static char * FFFF = "\xEF\xBF\xBF";*/ /* 0xFFFF */ - -halfword active_to_cs(int curchr, int force) -{ - halfword curcs; - int nncs = no_new_control_sequence; - if (force) { - no_new_control_sequence = false; - } - if (curchr > 0) { - char *b = (char *) uni2str((unsigned) curchr); - char *utfbytes = xmalloc(8); - utfbytes = strcpy(utfbytes, "\xEF\xBF\xBF"); - utfbytes = strcat(utfbytes, b); - free(b); - curcs = string_lookup(utfbytes, utf8_size(curchr)+3); - free(utfbytes); - } else { - /*tex 0xFFFF ... why not 3 ? */ - curcs = string_lookup("\xEF\xBF\xBF", 4); - } - no_new_control_sequence = nncs; - return curcs; -} - -/* - - static unsigned char *uni2csstr(unsigned unic) - { - unsigned char *buf = xmalloc(8); - unsigned char *pt = buf; - *pt++ = 239; *pt++ = 191; *pt++ = 191; // 0xFFFF - if (unic < 0x80) - *pt++ = (unsigned char) unic; - else if (unic < 0x800) { - *pt++ = (unsigned char) (0xc0 | (unic >> 6)); - *pt++ = (unsigned char) (0x80 | (unic & 0x3f)); - } else if (unic >= 0x110000) { - *pt++ = (unsigned char) (unic - 0x110000); - } else if (unic < 0x10000) { - *pt++ = (unsigned char) (0xe0 | (unic >> 12)); - *pt++ = (unsigned char) (0x80 | ((unic >> 6) & 0x3f)); - *pt++ = (unsigned char) (0x80 | (unic & 0x3f)); - } else { - int u, z, y, x; - unsigned val = unic - 0x10000; - u = (int) (((val & 0xf0000) >> 16) + 1); - z = (int) ((val & 0x0f000) >> 12); - y = (int) ((val & 0x00fc0) >> 6); - x = (int) (val & 0x0003f); - *pt++ = (unsigned char) (0xf0 | (u >> 2)); - *pt++ = (unsigned char) (0x80 | ((u & 3) << 4) | z); - *pt++ = (unsigned char) (0x80 | y); - *pt++ = (unsigned char) (0x80 | x); - } - *pt = '\0'; - return buf; - } - - halfword active_to_cs(int curchr, int force) - { - halfword curcs; - int nncs = no_new_control_sequence; - if (force) { - no_new_control_sequence = false; - } - if (curchr > 0) { - char * utfbytes = (char *) uni2csstr((unsigned) curchr); - curcs = string_lookup(utfbytes, utf8_size(curchr)+3); - free(utfbytes); - } else { - curcs = string_lookup(FFFF, 4); // 0xFFFF ... why not 3 ? - } - no_new_control_sequence = nncs; - return curcs; - } - -*/ - -/*tex - - Maybe this function should listen to \.{\\escapechar} but we can do without. - -*/ - -static char *cs_to_string(halfword p) -{ - const char *s; - char *sh; - int k = 0; - static char ret[256] = { 0 }; - if (p == 0 || p == null_cs) { - ret[k++] = '\\'; - s = "csname"; - while (*s) { - ret[k++] = *s++; - } - ret[k++] = '\\'; - s = "endcsname"; - while (*s) { - ret[k++] = *s++; - } - ret[k] = 0; - - } else { - str_number txt = cs_text(p); - sh = makecstring(txt); - s = sh; - if (is_active_cs(txt)) { - s = s + 3; - while (*s) { - ret[k++] = *s++; - } - ret[k] = 0; - } else { - ret[k++] = '\\'; - while (*s) { - ret[k++] = *s++; - } - ret[k] = 0; - } - free(sh); - } - return (char *) ret; -} - -/*tex This is sort of a hack. */ - -static char *cmd_chr_to_string(int cmd, int chr) -{ - char *s; - str_number str; - int sel = selector; - selector = new_string; - print_cmd_chr((quarterword) cmd, chr); - str = make_string(); - s = makecstring(str); - selector = sel; - flush_str(str); - return s; -} - -/*tex - - The heart of \TeX's input mechanism is the |get_next| procedure, which we - shall develop in the next few sections of the program. Perhaps we shouldn't - actually call it the ``heart,'' however, because it really acts as \TeX's - eyes and mouth, reading the source files and gobbling them up. And it also - helps \TeX\ to regurgitate stored token lists that are to be processed again. - - The main duty of |get_next| is to input one token and to set |cur_cmd| and - |cur_chr| to that token's command code and modifier. Furthermore, if the - input token is a control sequence, the |eqtb| location of that control - sequence is stored in |cur_cs|; otherwise |cur_cs| is set to zero. - - Underlying this simple description is a certain amount of complexity because - of all the cases that need to be handled. However, the inner loop of - |get_next| is reasonably short and fast. - - When |get_next| is asked to get the next token of a \.{\\read} line, it sets - |cur_cmd=cur_chr=cur_cs=0| in the case that no more tokens appear on that - line. (There might not be any tokens at all, if the |end_line_char| has - |ignore| as its catcode.) - - The value of |par_loc| is the |eqtb| address of `\.{\\par}'. This quantity is - needed because a blank line of input is supposed to be exactly equivalent to - the appearance of \.{\\par}; we must set |cur_cs:=par_loc| when detecting a - blank line. - -*/ - -/*tex - - The location of `\.{\\par}' in |eqtb| adn the token representing `\.{\\par}. - -*/ - -halfword par_loc; -halfword par_token; - -/*tex - - Parts |get_next| are executed more often than any other instructions of \TeX. - - The global variable |force_eof| is normally |false|; it is set |true| by an - \.{\\endinput} command. |luacstrings| is the number of lua print statements - waiting to be input, it is changed by |luatokencall|. - - -*/ - -/*tex Should the next \.{\\input} be aborted early? */ -boolean force_eof; - -/*tex How many lua strings are waiting to be input? */ - -int luacstrings; - -/*tex - - If the user has set the |pausing| parameter to some positive value, and if - nonstop mode has not been selected, each line of input is displayed on the - terminal and the transcript file, followed by `\.{=>}'. \TeX\ waits for a - response. If the response is simply |carriage_return|, the line is accepted - as it stands, otherwise the line typed is used instead of the line in the - file. - -*/ - -void firm_up_the_line(void) -{ - int k; - ilimit = last; - if (pausing_par > 0) { - if (interaction > nonstop_mode) { - wake_up_terminal(); - print_ln(); - if (istart < ilimit) { - for (k = istart; k <= ilimit - 1; k++) - print_char(buffer[k]); - } - first = ilimit; - prompt_input("=>"); - if (last > first) { - /*tex Move line down in buffer. */ - for (k = first; k < +last - 1; k++) - buffer[k + istart - first] = buffer[k]; - ilimit = istart + last - first; - } - } - } -} - -/*tex - - Before getting into |get_next|, let's consider the subroutine that is called - when an `\.{\\outer}' control sequence has been scanned or when the end of a - file has been reached. These two cases are distinguished by |cur_cs|, which - is zero at the end of a file. - -*/ - -void check_outer_validity(void) -{ - /*tex points to inserted token list */ - halfword p; - /*tex auxiliary pointer */ - halfword q; - if (suppress_outer_error_par) - return; - if (scanner_status != normal) { - deletions_allowed = false; - /*tex - - Back up an outer control sequence so that it can be reread. An - outer control sequence that occurs in a \.{\\read} will not be - reread, since the error recovery for \.{\\read} is not very powerful. - - */ - if (cur_cs != 0) { - if ((istate == token_list) || (iname < 1) || (iname > 17)) { - p = get_avail(); - token_info(p) = cs_token_flag + cur_cs; - /*tex prepare to read the control sequence again */ - begin_token_list(p, backed_up); - } - /*tex replace it by a space */ - cur_cmd = spacer_cmd; - cur_chr = ' '; - } - if (scanner_status > skipping) { - const char *errhlp[] = { - "I suspect you have forgotten a `}', causing me", - "to read past where you wanted me to stop.", - "I'll try to recover; but if the error is serious,", - "you'd better type `E' or `X' now and fix your file.", - NULL - }; - char errmsg[318]; - const char *startmsg; - const char *scannermsg; - /*tex - - Tell the user what has run away and try to recover Print a - definition, argument, or preamble. - - */ - runaway(); - if (cur_cs == 0) { - startmsg = "File ended"; - } else { - cur_cs = 0; - startmsg = "Forbidden control sequence found"; - } - /*tex - - Print either `\.{definition}' or `\.{use}' or `\.{preamble}' or - `\.{text}', and insert tokens that should lead to recovery. The - recovery procedure can't be fully understood without knowing more - about the \TeX\ routines that should be aborted, but we can - sketch the ideas here: For a runaway definition we will insert a - right brace; for a runaway preamble, we will insert a special - \.{\\cr} token and a right brace; and for a runaway argument, we - will set |long_state| to |outer_call| and insert \.{\\par}. - - */ - p = get_avail(); - switch (scanner_status) { - case defining: - scannermsg = "definition"; - token_info(p) = right_brace_token + '}'; - break; - case matching: - scannermsg = "use"; - token_info(p) = par_token; - long_state = outer_call_cmd; - break; - case aligning: - scannermsg = "preamble"; - token_info(p) = right_brace_token + '}'; - q = p; - p = get_avail(); - token_link(p) = q; - token_info(p) = cs_token_flag + frozen_cr; - align_state = -1000000; - break; - case absorbing: - scannermsg = "text"; - token_info(p) = right_brace_token + '}'; - break; - default: - scannermsg = "unknown"; - break; - } - begin_token_list(p, inserted); - snprintf(errmsg, 318, "%s while scanning %s of %s", startmsg, scannermsg, cs_to_string(warning_index)); - tex_error(errmsg, errhlp); - } else { - char errmsg[256]; - const char *errhlp_no[] = { - "The file ended while I was skipping conditional text.", - "This kind of error happens when you say `\\if...' and forget", - "the matching `\\fi'. I've inserted a `\\fi'; this might work.", - NULL - }; - const char *errhlp_cs[] = { - "A forbidden control sequence occurred in skipped text.", - "This kind of error happens when you say `\\if...' and forget", - "the matching `\\fi'. I've inserted a `\\fi'; this might work.", - NULL - }; - const char **errhlp = (const char **) errhlp_no; - char *ss; - if (cur_cs != 0) { - errhlp = errhlp_cs; - cur_cs = 0; - } - ss = cmd_chr_to_string(if_test_cmd, cur_if); - snprintf(errmsg, 255, "Incomplete %s; all text was ignored after line %d", - ss, (int) skip_line); - free(ss); - /*tex Incomplete |\if...| */ - cur_tok = cs_token_flag + frozen_fi; - /*tex back up one inserted token and call |error|. */ - { - OK_to_interrupt = false; - back_input(); - token_type = inserted; - OK_to_interrupt = true; - tex_error(errmsg, errhlp); - } - } - deletions_allowed = true; - } -} - -#if 0 - -/*tex - - The other variant gives less clutter in tracing cache usage when profiling - and for some files (like the manual) also a bit of a speedup. - -*/ - -static boolean get_next_file(void) -{ - SWITCH: - if (iloc <= ilimit) { - /*tex current line not yet finished */ - do_buffer_to_unichar(cur_chr, iloc); - RESWITCH: - if (detokenized_line()) { - cur_cmd = (cur_chr == ' ' ? 10 : 12); - } else { - do_get_cat_code(cur_cmd, cur_chr); - } - /*tex - - Change state if necessary, and |goto switch| if the current - character should be ignored, or |goto reswitch| if the current - character changes to another; - - The following 48-way switch accomplishes the scanning quickly, - assuming that a decent C compiler has translated the code. Note that - the numeric values for |mid_line|, |skip_blanks|, and |new_line| are - spaced apart from each other by |max_char_code+1|, so we can add a - character's command code to the state to get a single number that - characterizes both. - - Remark [ls/hh]: checking performance indicated that this switch was - the cause of many branch prediction errors but changing it to: - - \starttyping - c = istate + cur_cmd; - if (c == (mid_line + letter_cmd) || c == (mid_line + other_char_cmd)) { - return true; - } else if (c >= new_line) { - switch (c) { - } - } else if (c >= skip_blanks) { - switch (c) { - } - } else if (c >= mid_line) { - switch (c) { - } - } else { - istate = mid_line; - return true; - } - \stoptyping - - gives as many prediction errors. So, we can indeed assume that the - compiler does the right job, or that there is simply no other way. - - */ - - switch (istate + cur_cmd) { - case mid_line + ignore_cmd: - case skip_blanks + ignore_cmd: - case new_line + ignore_cmd: - case skip_blanks + spacer_cmd: - case new_line + spacer_cmd: - /*tex Cases where character is ignored. */ - goto SWITCH; - break; - case mid_line + escape_cmd: - case new_line + escape_cmd: - case skip_blanks + escape_cmd: - /*tex Scan a control sequence. */ - istate = (unsigned char) scan_control_sequence(); - if (! suppress_outer_error_par && cur_cmd >= outer_call_cmd) - check_outer_validity(); - break; - case mid_line + active_char_cmd: - case new_line + active_char_cmd: - case skip_blanks + active_char_cmd: - /*tex Process an active-character. */ - cur_cs = active_to_cs(cur_chr, false); - cur_cmd = eq_type(cur_cs); - cur_chr = equiv(cur_cs); - istate = mid_line; - if (! suppress_outer_error_par && cur_cmd >= outer_call_cmd) - check_outer_validity(); - break; - case mid_line + sup_mark_cmd: - case new_line + sup_mark_cmd: - case skip_blanks + sup_mark_cmd: - /*tex If this |sup_mark| starts. */ - if (process_sup_mark()) - goto RESWITCH; - else - istate = mid_line; - break; - case mid_line + invalid_char_cmd: - case new_line + invalid_char_cmd: - case skip_blanks + invalid_char_cmd: - /*tex Decry the invalid character and |goto restart|. */ - invalid_character_error(); - /*tex Because state may be |token_list| now: */ - return false; - break; - case mid_line + spacer_cmd: - /*tex Enter |skip_blanks| state, emit a space. */ - istate = skip_blanks; - cur_chr = ' '; - break; - case mid_line + car_ret_cmd: - /*tex - - Finish line, emit a space. When a character of type |spacer| - gets through, its character code is changed to $\.{"\ - "}=040$. This means that the ASCII codes for tab and space, - and for the space inserted at the end of a line, will be - treated alike when macro parameters are being matched. We do - this since such characters are indistinguishable on most - computer terminal displays. - - */ - iloc = ilimit + 1; - cur_cmd = spacer_cmd; - cur_chr = ' '; - break; - case skip_blanks + car_ret_cmd: - case mid_line + comment_cmd: - case new_line + comment_cmd: - case skip_blanks + comment_cmd: - /*tex Finish line, |goto switch|; */ - iloc = ilimit + 1; - goto SWITCH; - break; - case new_line + car_ret_cmd: - /*tex Finish line, emit a \.{\\par}; */ - iloc = ilimit + 1; - cur_cs = par_loc; - cur_cmd = eq_type(cur_cs); - cur_chr = equiv(cur_cs); - if (! suppress_outer_error_par && cur_cmd >= outer_call_cmd) - check_outer_validity(); - break; - case skip_blanks + left_brace_cmd: - case new_line + left_brace_cmd: - istate = mid_line; - /*tex Fall through. */ - case mid_line + left_brace_cmd: - align_state++; - break; - case skip_blanks + right_brace_cmd: - case new_line + right_brace_cmd: - istate = mid_line; - /*tex Fall through. */ - case mid_line + right_brace_cmd: - align_state--; - break; - case mid_line + math_shift_cmd: - case mid_line + tab_mark_cmd: - case mid_line + mac_param_cmd: - case mid_line + sub_mark_cmd: - case mid_line + letter_cmd: - case mid_line + other_char_cmd: - break; - /* - case skip_blanks + math_shift: - case skip_blanks + tab_mark: - case skip_blanks + mac_param: - case skip_blanks + sub_mark: - case skip_blanks + letter: - case skip_blanks + other_char: - case new_line + math_shift: - case new_line + tab_mark: - case new_line + mac_param: - case new_line + sub_mark: - case new_line + letter: - case new_line + other_char: - */ - default: - istate = mid_line; - break; - } - } else { - if (iname != 21) - istate = new_line; - /*tex - - Move to next line of file, or |goto restart| if there is no next line, - or |return| if a \.{\\read} line has finished; - - */ - do { - next_line_retval r = next_line(); - if (r == next_line_return) { - return true; - } else if (r == next_line_restart) { - return false; - } - } while (0); - check_interrupt(); - goto SWITCH; - } - return true; -} - -#else - -/*tex - - This variant gives 10 times less Bim in vallgrind! - -*/ - -static boolean get_next_file(void) -{ - int c = 0; - SWITCH: - if (iloc <= ilimit) { - /*tex current line not yet finished */ - do_buffer_to_unichar(cur_chr, iloc); - RESWITCH: - if (detokenized_line()) { - cur_cmd = (cur_chr == ' ' ? 10 : 12); - } else { - do_get_cat_code(cur_cmd, cur_chr); - } - /*tex - - Change state if necessary, and |goto switch| if the current character - should be ignored, or |goto reswitch| if the current character changes - to another. - - */ - c = istate + cur_cmd; - if (c == (mid_line + letter_cmd) || c == (mid_line + other_char_cmd)) { - return true; - } else if (c >= new_line) { - switch (c-new_line) { - case escape_cmd: - istate = (unsigned char) scan_control_sequence(); - if (! suppress_outer_error_par && cur_cmd >= outer_call_cmd) - check_outer_validity(); - return true; - case left_brace_cmd: - istate = mid_line; - align_state++; - return true; - case right_brace_cmd: - istate = mid_line; - align_state--; - return true; - case math_shift_cmd: - istate = mid_line; - return true; - case tab_mark_cmd: - istate = mid_line; - return true; - case car_ret_cmd: - /*tex Finish line, emit a \.{\\par}. */ - iloc = ilimit + 1; - cur_cs = par_loc; - cur_cmd = eq_type(cur_cs); - cur_chr = equiv(cur_cs); - if (! suppress_outer_error_par && cur_cmd >= outer_call_cmd) - check_outer_validity(); - return true; - case mac_param_cmd: - istate = mid_line; - return true; - case sup_mark_cmd: - if (process_sup_mark()) - goto RESWITCH; - else - istate = mid_line; - return true; - case sub_mark_cmd: - istate = mid_line; - return true; - case ignore_cmd: - goto SWITCH; - return true; - case spacer_cmd: - /*tex Cases where character is ignored. */ - goto SWITCH; - case letter_cmd: - istate = mid_line; - return true; - case other_char_cmd: - istate = mid_line; - return true; - case active_char_cmd: - cur_cs = active_to_cs(cur_chr, false); - cur_cmd = eq_type(cur_cs); - cur_chr = equiv(cur_cs); - istate = mid_line; - if (! suppress_outer_error_par && cur_cmd >= outer_call_cmd) - check_outer_validity(); - return true; - case comment_cmd: - iloc = ilimit + 1; - goto SWITCH; - case invalid_char_cmd: - /*tex Because state may be |token_list| now. */ - invalid_character_error(); - return false; - default: - istate = mid_line; - return true; - } - } else if (c >= skip_blanks) { - switch (c-skip_blanks) { - case escape_cmd: - /*tex Scan a control sequence. */ - istate = (unsigned char) scan_control_sequence(); - if (! suppress_outer_error_par && cur_cmd >= outer_call_cmd) - check_outer_validity(); - return true; - case left_brace_cmd: - istate = mid_line; - align_state++; - return true; - case right_brace_cmd: - istate = mid_line; - align_state--; - return true; - case math_shift_cmd: - istate = mid_line; - return true; - case tab_mark_cmd: - istate = mid_line; - return true; - case car_ret_cmd: - iloc = ilimit + 1; - goto SWITCH; - case mac_param_cmd: - istate = mid_line; - return true; - case sup_mark_cmd: - if (process_sup_mark()) - goto RESWITCH; - else - istate = mid_line; - return true; - case sub_mark_cmd: - istate = mid_line; - return true; - case ignore_cmd: - goto SWITCH; - case spacer_cmd: - goto SWITCH; - case letter_cmd: - istate = mid_line; - return true; - case other_char_cmd: - istate = mid_line; - return true; - case active_char_cmd: - cur_cs = active_to_cs(cur_chr, false); - cur_cmd = eq_type(cur_cs); - cur_chr = equiv(cur_cs); - istate = mid_line; - if (! suppress_outer_error_par && cur_cmd >= outer_call_cmd) - check_outer_validity(); - return true; - case comment_cmd: - /*tex Finish line, |goto switch|. */ - iloc = ilimit + 1; - goto SWITCH; - case invalid_char_cmd: - /*tex Decry the invalid character and |goto restart|. */ - invalid_character_error(); - /*tex Because state may be |token_list| now. */ - return false; - default: - istate = mid_line; - return true; - } - } else if (c >= mid_line) { - switch (c-mid_line) { - case escape_cmd: - istate = (unsigned char) scan_control_sequence(); - if (! suppress_outer_error_par && cur_cmd >= outer_call_cmd) - check_outer_validity(); - return true; - case left_brace_cmd: - align_state++; - return true; - case right_brace_cmd: - align_state--; - return true; - case math_shift_cmd: - return true; - case tab_mark_cmd: - return true; - case car_ret_cmd: - /*tex - - Finish line, emit a space. When a character of type - |spacer| gets through, its character code is changed to - $\.{"\ "}=040$. This means that the ASCII codes for tab - and space, and for the space inserted at the end of a - line, will be treated alike when macro parameters are - being matched. We do this since such characters are - indistinguishable on most computer terminal displays. - - */ - iloc = ilimit + 1; - cur_cmd = spacer_cmd; - cur_chr = ' '; - return true; - case mac_param_cmd: - return true; - case sup_mark_cmd: - if (process_sup_mark()) - goto RESWITCH; - else - istate = mid_line; - return true; - case sub_mark_cmd: - return true; - case ignore_cmd: - goto SWITCH; - case spacer_cmd: - /*tex Enter |skip_blanks| state, emit a space. */ - istate = skip_blanks; - cur_chr = ' '; - return true; - case letter_cmd: - istate = mid_line; - return true; - case other_char_cmd: - istate = mid_line; - return true; - case active_char_cmd: - cur_cs = active_to_cs(cur_chr, false); - cur_cmd = eq_type(cur_cs); - cur_chr = equiv(cur_cs); - istate = mid_line; - if (! suppress_outer_error_par && cur_cmd >= outer_call_cmd) - check_outer_validity(); - return true; - case comment_cmd: - iloc = ilimit + 1; - goto SWITCH; - case invalid_char_cmd: - /*tex Because state may be |token_list| now. */ - invalid_character_error(); - return false; - default: - istate = mid_line; - return true; - } - } else { - istate = mid_line; - return true; - } - } else { - if (iname != 21) { - istate = new_line; - } - /*tex - - Move to next line of file, or |goto restart| if there is no next - line, or |return| if a \.{\\read} line has finished; - - */ - do { - next_line_retval r = next_line(); - if (r == next_line_return) { - return true; - } else if (r == next_line_restart) { - return false; - } - } while (0); - check_interrupt(); - goto SWITCH; - } - return true; -} - -#endif - -/*tex - - Notice that a code like \.{\^\^8} becomes \.x if not followed by a hex digit. - We only support a limited set: - - \starttyping - ^^^^^^XXXXXX - ^^^^XXXXXX - ^^XX ^^<char> - \stoptyping - -*/ - -#define is_hex(a) ((a>='0'&&a<='9')||(a>='a'&&a<='f')) - -#define add_nybble(c) \ - if (c<='9') { \ - cur_chr=(cur_chr<<4)+c-'0'; \ - } else { \ - cur_chr=(cur_chr<<4)+c-'a'+10; \ - } - -#define set_nybble(c) \ - if (c<='9') { \ - cur_chr=c-'0'; \ - } else { \ - cur_chr=c-'a'+10; \ - } - -#define one_hex_to_cur_chr(c1) \ - set_nybble(c1); - -#define two_hex_to_cur_chr(c1,c2) \ - set_nybble(c1); \ - add_nybble(c2); - -#define four_hex_to_cur_chr(c1,c2,c3,c4) \ - two_hex_to_cur_chr(c1,c2); \ - add_nybble(c3); \ - add_nybble(c4); - -#define six_hex_to_cur_chr(c1,c2,c3,c4,c5,c6) \ - four_hex_to_cur_chr(c1,c2,c3,c4); \ - add_nybble(c5); \ - add_nybble(c6); - -static boolean process_sup_mark(void) -{ - if (cur_chr == buffer[iloc]) { - if (iloc < ilimit) { - if ((cur_chr == buffer[iloc + 1]) && (cur_chr == buffer[iloc + 2])) { - if ((cur_chr == buffer[iloc + 3]) && (cur_chr == buffer[iloc + 4])) { - /*tex |^^^^^^XXXXXX| */ - if ((iloc + 10) <= ilimit) { - int c1 = buffer[iloc + 5]; - int c2 = buffer[iloc + 6]; - int c3 = buffer[iloc + 7]; - int c4 = buffer[iloc + 8]; - int c5 = buffer[iloc + 9]; - int c6 = buffer[iloc + 10]; - if (is_hex(c1) && is_hex(c2) && is_hex(c3) && - is_hex(c4) && is_hex(c5) && is_hex(c6)) { - iloc = iloc + 11; - six_hex_to_cur_chr(c1,c2,c3,c4,c5,c6); - return true; - } else { - tex_error("^^^^^^ needs six hex digits", NULL); - } - } else { - tex_error("^^^^^^ needs six hex digits, end of input", NULL); - } - } else { - /*tex |^^^^XXXX| */ - if ((iloc + 6) <= ilimit) { - int c1 = buffer[iloc + 3]; - int c2 = buffer[iloc + 4]; - int c3 = buffer[iloc + 5]; - int c4 = buffer[iloc + 6]; - if (is_hex(c1) && is_hex(c2) && is_hex(c3) && is_hex(c4)) { - iloc = iloc + 7; - four_hex_to_cur_chr(c1,c2,c3,c4); - return true; - } else { - tex_error("^^^^ needs four hex digits", NULL); - } - } else { - tex_error("^^^^ needs four hex digits, end of input", NULL); - } - } - } else { - /*tex |^^XX| */ - if ((iloc + 2) <= ilimit) { - int c1 = buffer[iloc + 1]; - int c2 = buffer[iloc + 2]; - if (is_hex(c1) && is_hex(c2)) { - iloc = iloc + 3; - two_hex_to_cur_chr(c1,c2); - return true; - } - } - /*tex Go on, no error, good old \TEX . */ - } - } - /*tex The rest. */ - { - int c1 = buffer[iloc + 1]; - if (c1 < 0200) { - iloc = iloc + 2; - if (is_hex(c1) && (iloc <= ilimit)) { - int c2 = buffer[iloc]; - if (is_hex(c2)) { - incr(iloc); - two_hex_to_cur_chr(c1,c2); - return true; - } - } - cur_chr = (c1 < 0100 ? c1 + 0100 : c1 - 0100); - return true; - } - } - } - return false; -} - -/*tex - - Control sequence names are scanned only when they appear in some line of a - file; once they have been scanned the first time, their |eqtb| location - serves as a unique identification, so \TeX\ doesn't need to refer to the - original name any more except when it prints the equivalent in symbolic form. - - The program that scans a control sequence has been written carefully in order - to avoid the blowups that might otherwise occur if a malicious user tried - something like `\.{\\catcode\'15=0}'. The algorithm might look at - |buffer[ilimit+1]|, but it never looks at |buffer[ilimit+2]|. - - If expanded characters like `\.{\^\^A}' or `\.{\^\^df}' appear in or just - following a control sequence name, they are converted to single characters in - the buffer and the process is repeated, slowly but surely. - -*/ - -static boolean check_expanded_code(int *kk); /* below */ - -static int scan_control_sequence(void) -{ - int retval = mid_line; - if (iloc > ilimit) { - /*tex |state| is irrelevant in this case. */ - cur_cs = null_cs; - } else { - /*tex |cat_code(cur_chr)|, usually: */ - register int cat; - while (1) { - int k = iloc; - do_buffer_to_unichar(cur_chr, k); - do_get_cat_code(cat, cur_chr); - if (cat != letter_cmd || k > ilimit) { - retval = (cat == spacer_cmd ? skip_blanks : mid_line); - /*tex If an expanded \unknown */ - if (cat == sup_mark_cmd && check_expanded_code(&k)) - continue; - } else { - retval = skip_blanks; - do { - do_buffer_to_unichar(cur_chr, k); - do_get_cat_code(cat, cur_chr); - } while (cat == letter_cmd && k <= ilimit); - /*tex If an expanded \unknown */ - if (cat == sup_mark_cmd && check_expanded_code(&k)) - continue; - if (cat != letter_cmd) { - /*tex Backtrack one character which can be \UTF. */ - if (cur_chr <= 0x7F) { - k -= 1; /* in most cases */ - } else if (cur_chr > 0xFFFF) { - k -= 4; - } else if (cur_chr > 0x7FF) { - k -= 3; - } else /* if (cur_chr > 0x7F) */ { - k -= 2; - } - /*tex Now |k| points to first nonletter. */ - } - } - cur_cs = id_lookup(iloc, k - iloc); - iloc = k; - break; - } - } - cur_cmd = eq_type(cur_cs); - cur_chr = equiv(cur_cs); - return retval; -} - -/*tex - - Whenever we reach the following piece of code, we will have - |cur_chr=buffer[k-1]| and |k<=ilimit+1| and - |cat=get_cat_code(cat_code_table,cur_chr)|. If an expanded code like - \.{\^\^A} or \.{\^\^df} appears in |buffer[(k-1)..(k+1)]| or - |buffer[(k-1)..(k+2)]|, we will store the corresponding code in |buffer[k-1]| - and shift the rest of the buffer left two or three places. - -*/ - -static boolean check_expanded_code(int *kk) -{ - int l; - int k = *kk; - int d = 1; - if (buffer[k] == cur_chr && k < ilimit) { - if ((cur_chr == buffer[k + 1]) && (cur_chr == buffer[k + 2])) { - if ((cur_chr == buffer[k + 3]) && (cur_chr == buffer[k + 4])) { - if ((k + 10) <= ilimit) { - int c1 = buffer[k + 6 - 1]; - int c2 = buffer[k + 6]; - int c3 = buffer[k + 6 + 1]; - int c4 = buffer[k + 6 + 2]; - int c5 = buffer[k + 6 + 3]; - int c6 = buffer[k + 6 + 4]; - if (is_hex(c1) && is_hex(c2) && is_hex(c3) && is_hex(c4) && is_hex(c5) && is_hex(c6)) { - d = 6; - six_hex_to_cur_chr(c1,c2,c3,c4,c5,c6); - } else { - tex_error("^^^^^^ needs six hex digits", NULL); - } - } else { - tex_error("^^^^^^ needs six hex digits, end of input", NULL); - } - } else { - if ((k + 6) <= ilimit) { - int c1 = buffer[k + 4 - 1]; - int c2 = buffer[k + 4]; - int c3 = buffer[k + 4 + 1]; - int c4 = buffer[k + 4 + 2]; - if (is_hex(c1) && is_hex(c2) && is_hex(c3) && is_hex(c4)) { - d = 4; - four_hex_to_cur_chr(c1,c2,c3,c4); - } else { - tex_error("^^^^ needs four hex digits", NULL); - } - } else { - tex_error("^^^^ needs four hex digits, end of input", NULL); - } - } - } else { - int c1 = buffer[k + 1]; - if (c1 < 0200) { - d = 1; - if (is_hex(c1) && (k + 2) <= ilimit) { - int c2 = buffer[k + 2]; - if (is_hex(c2)) { - d = 2; - two_hex_to_cur_chr(c1,c2); - } else { - cur_chr = (c1 < 0100 ? c1 + 0100 : c1 - 0100); - } - } else { - cur_chr = (c1 < 0100 ? c1 + 0100 : c1 - 0100); - } - } - } - if (d > 2) - d = 2 * d - 1; - else - d++; - if (cur_chr <= 0x7F) { - buffer[k - 1] = (packed_ASCII_code) cur_chr; - } else if (cur_chr <= 0x7FF) { - buffer[k - 1] = (packed_ASCII_code) (0xC0 + cur_chr / 0x40); - k++; - d--; - buffer[k - 1] = (packed_ASCII_code) (0x80 + cur_chr % 0x40); - } else if (cur_chr <= 0xFFFF) { - buffer[k - 1] = (packed_ASCII_code) (0xE0 + cur_chr / 0x1000); - k++; - d--; - buffer[k - 1] = (packed_ASCII_code) (0x80 + (cur_chr % 0x1000) / 0x40); - k++; - d--; - buffer[k - 1] = (packed_ASCII_code) (0x80 + (cur_chr % 0x1000) % 0x40); - } else { - buffer[k - 1] = (packed_ASCII_code) (0xF0 + cur_chr / 0x40000); - k++; - d--; - buffer[k - 1] = (packed_ASCII_code) (0x80 + (cur_chr % 0x40000) / 0x1000); - k++; - d--; - buffer[k - 1] = (packed_ASCII_code) (0x80 + ((cur_chr % 0x40000) % 0x1000) / 0x40); - k++; - d--; - buffer[k - 1] = (packed_ASCII_code) (0x80 + ((cur_chr % 0x40000) % 0x1000) % 0x40); - } - l = k; - ilimit = ilimit - d; - while (l <= ilimit) { - buffer[l] = buffer[l + d]; - l++; - } - *kk = k; - return true; - } - return false; -} - -/*tex - - All of the easy branches of |get_next| have now been taken care of. There is - one more branch. - -*/ - -static next_line_retval next_line(void) -{ - /*tex A way to end a pseudo file without trailing space: */ - boolean inhibit_eol = false; - if (iname > 17) { - /*tex - - Read next line of file into |buffer|, or |goto restart| if the file - has ended. - - */ - incr(line); - first = istart; - if (!force_eof) { - if (iname <= 20) { - if (pseudo_input()) { - /*tex Not end of file; set |ilimit|. */ - firm_up_the_line(); - line_catcode_table = DEFAULT_CAT_TABLE; - if ((iname == 19) && (pseudo_lines(pseudo_files) == null)) - inhibit_eol = true; - } else if ((every_eof_par != null) && !eof_seen[iindex]) { - ilimit = first - 1; - /*tex Fake one empty line. */ - eof_seen[iindex] = true; - if (iname != 19) - begin_token_list(every_eof_par, every_eof_text); - return next_line_restart; - } else { - force_eof = true; - } - } else { - if (iname == 21) { - halfword n = null; - int t = luacstring_input(&n); - switch (t) { - case 0: - force_eof = true; - break; - case 1: - /*tex string */ - firm_up_the_line(); - line_catcode_table = (short) luacstring_cattable(); - line_partial = (signed char) luacstring_partial(); - if (luacstring_final_line() || line_partial || line_catcode_table == NO_CAT_TABLE) - inhibit_eol = true; - if (!line_partial) - istate = new_line; - break; - case 2: - /*tex token */ - cur_tok = n; - back_input(); - /*tex Needs checking. */ - return next_line_restart; - break; - case 3: - /*tex node */ - if (n < biggest_char) { - /*tex |0x10FFFF == 1114111| */ - cur_tok = token_val(node_cmd, n); - back_input(); - /*tex Needs checking. */ - return next_line_restart; - } else { - normal_warning("nodes","unable to store reference from lua in tex"); - force_eof = true; - } - break; - default: - force_eof = true; - break; - } - } else if (lua_input_ln(cur_file, 0, true)) { - /*tex Not end of file, set |ilimit|. */ - firm_up_the_line(); - line_catcode_table = DEFAULT_CAT_TABLE; - } else if ((every_eof_par != null) && (!eof_seen[iindex])) { - ilimit = first - 1; - /* tex Fake one empty line. */ - eof_seen[iindex] = true; - begin_token_list(every_eof_par, every_eof_text); - return next_line_restart; - } else { - force_eof = true; - } - } - } - if (force_eof) { - if (tracing_nesting_par > 0) - if ((grp_stack[in_open] != cur_boundary) || (if_stack[in_open] != cond_ptr)) - if (!((iname == 19) || (iname == 21))) { - /*tex Give warning for some unfinished groups and/or conditionals. */ - file_warning(); - } - if ((iname > 21) || (iname == 20)) { - report_stop_file(filetype_tex); - decr(open_parens); - } - force_eof = false; - /*tex \LUA\ input or \.{\\scantextokens} */ - if (iname == 21 || iname == 19) { - end_file_reading(); - } else { - end_file_reading(); - if (! suppress_outer_error_par) - check_outer_validity(); - } - return next_line_restart; - } - if (inhibit_eol || end_line_char_inactive) - ilimit--; - else - buffer[ilimit] = (packed_ASCII_code) end_line_char_par; - first = ilimit + 1; - iloc = istart; - /*tex We're ready to read. */ - } else { - if (!terminal_input) { - /*tex \.{\\read} line has ended */ - cur_cmd = 0; - cur_chr = 0; - return next_line_return; - } - if (input_ptr > 0) { - /*tex Text was inserted during error recovery. */ - end_file_reading(); - /*tex Resume previous level. */ - return next_line_restart; - } - if (selector < log_only) - open_log_file(); - if (interaction > nonstop_mode) { - if (end_line_char_inactive) - ilimit++; - if (ilimit == istart) { - /*tex Previous line was empty. */ - tprint_nl("(Please type a command or say `\\end')"); - } - print_ln(); - first = istart; - /*tex Input on-line into |buffer| */ - prompt_input("*"); - ilimit = last; - if (end_line_char_inactive) - ilimit--; - else - buffer[ilimit] = (packed_ASCII_code) end_line_char_par; - first = ilimit + 1; - iloc = istart; - } else { - /*tex - - Nonstop mode, which is intended for overnight batch processing, - never waits for on-line input. - - */ - fatal_error("*** (job aborted, no legal \\end found)"); - } - } - return next_line_ok; -} - -/*tex - - Let's consider now what happens when |get_next| is looking at a token list. - -*/ - -static boolean get_next_tokenlist(void) -{ - register halfword t = token_info(iloc); - /*tex Move to next. */ - iloc = token_link(iloc); - if (t >= cs_token_flag) { - /*tex A control sequence token */ - cur_cs = t - cs_token_flag; - cur_cmd = eq_type(cur_cs); - if (cur_cmd >= outer_call_cmd) { - if (cur_cmd == dont_expand_cmd) { - /*tex - - Get the next token, suppressing expansion. The present point - in the program is reached only when the |expand| routine has - inserted a special marker into the input. In this special - case, |token_info(iloc)| is known to be a control sequence - token, and |token_link(iloc)=null|. - - */ - cur_cs = token_info(iloc) - cs_token_flag; - iloc = null; - cur_cmd = eq_type(cur_cs); - if (cur_cmd > max_command_cmd) { - cur_cmd = relax_cmd; - cur_chr = no_expand_flag; - return true; - } - } else if (! suppress_outer_error_par) { - check_outer_validity(); - } - } - cur_chr = equiv(cur_cs); - } else { - cur_cmd = token_cmd(t); - cur_chr = token_chr(t); - switch (cur_cmd) { - case left_brace_cmd: - align_state++; - break; - case right_brace_cmd: - align_state--; - break; - case out_param_cmd: - /*tex Insert macro parameter and |goto restart|. */ - begin_token_list(param_stack[param_start + cur_chr - 1], parameter); - return false; - break; - } - } - return true; -} - -/*tex - - Now we're ready to take the plunge into |get_next| itself. Parts of this - routine are executed more often than any other instructions of \TeX. - - This sets |cur_cmd|, |cur_chr|, |cur_cs| to next token: - -*/ - -void get_next(void) -{ - RESTART: - cur_cs = 0; - if (istate != token_list) { - /*tex Input from external file, |goto restart| if no input found. */ - if (!get_next_file()) - goto RESTART; - } else { - if (iloc == null) { - end_token_list(); - /*tex List exhausted, resume previous level. */ - goto RESTART; - } else if (!get_next_tokenlist()) { - /*tex Parameter needs to be expanded. */ - goto RESTART; - } - } - /*tex If an alignment entry has just ended, take appropriate action. */ - if ((cur_cmd == tab_mark_cmd || cur_cmd == car_ret_cmd) && align_state == 0) { - insert_vj_template(); - goto RESTART; - } -} - -/*tex - - Since |get_next| is used so frequently in \TeX, it is convenient to define - three related procedures that do a little more: - - \startitemize - \startitem - |get_token| not only sets |cur_cmd| and |cur_chr|, it also sets - |cur_tok|, a packed halfword version of the current token. - \stopitem - \startitem - |get_x_token|, meaning ``get an expanded token,'' is like - |get_token|, but if the current token turns out to be a user-defined - control sequence (i.e., a macro call), or a conditional, or something - like \.{\\topmark} or \.{\\expandafter} or \.{\\csname}, it is - eliminated from the input by beginning the expansion of the macro or - the evaluation of the conditional. - \stopitem - \startitem - |x_token| is like |get_x_token| except that it assumes that - |get_next| has already been called. - \stopitem - \stopitemize - - In fact, these three procedures account for almost every use of |get_next|. - No new control sequences will be defined except during a call of |get_token|, - or when \.{\\csname} compresses a token list, because - |no_new_control_sequence| is always |true| at other times. - - This sets |cur_cmd|, |cur_chr|, |cur_tok|: - -*/ - -void get_token(void) -{ - no_new_control_sequence = false; - get_next(); - no_new_control_sequence = true; - if (cur_cs == 0) - cur_tok = token_val(cur_cmd, cur_chr); - else - cur_tok = cs_token_flag + cur_cs; -} - -/*tex This changes the string |s| to a token list. */ - -halfword string_to_toks(const char *ss) -{ - /*tex tail of the token list */ - halfword p; - /*tex new node being added to the token list via |store_new_token| */ - halfword q; - /*tex token being appended */ - halfword t; - const char *s = ss; - const char *se = ss + strlen(s); - p = temp_token_head; - set_token_link(p, null); - while (s < se) { - t = (halfword) str2uni((const unsigned char *) s); - s += utf8_size(t); - if (t == ' ') - t = space_token; - else - t = other_token + t; - fast_store_new_token(t); - } - return token_link(temp_token_head); -} - -/*tex - - The token lists for macros and for other things like \.{\\mark} and - \.{\\output} and \.{\\write} are produced by a procedure called |scan_toks|. - - Before we get into the details of |scan_toks|, let's consider a much simpler - task, that of converting the current string into a token list. The |str_toks| - function does this; it classifies spaces as type |spacer| and everything else - as type |other_char|. - - The token list created by |str_toks| begins at |link(temp_token_head)| and - ends at the value |p| that is returned. (If |p=temp_token_head|, the list is - empty.) - - |lua_str_toks| is almost identical, but it also escapes the three symbols - that |lua| considers special while scanning a literal string. - - This changes the string |str_pool[b..pool_ptr]| to a token list: - -*/ - -halfword lua_str_toks(lstring b) -{ - /*tex tail of the token list */ - halfword p; - /*tex new node being added to the token list via |store_new_token| */ - halfword q; - /*tex token being appended */ - halfword t; - /*tex index into string */ - unsigned char *k; - p = temp_token_head; - set_token_link(p, null); - k = (unsigned char *) b.s; - while (k < (unsigned char *) b.s + b.l) { - t = pool_to_unichar(k); - k += utf8_size(t); - if (t == ' ') { - t = space_token; - } else { - if ((t == '\\') || (t == '"') || (t == '\'') || (t == 10) || (t == 13)) - fast_store_new_token(other_token + '\\'); - if (t == 10) - t = 'n'; - if (t == 13) - t = 'r'; - t = other_token + t; - } - fast_store_new_token(t); - } - return p; -} - -/*tex - - Incidentally, the main reason for wanting |str_toks| is the function - |the_toks|, which has similar input/output characteristics. - - This changes the string |str_pool[b..pool_ptr]| to a token list: - -*/ - -halfword str_toks(lstring s) -{ - /*tex tail of the token list */ - halfword p; - /*tex new node being added to the token list via |store_new_token| */ - halfword q; - /*tex token being appended */ - halfword t; - /*tex index into string */ - unsigned char *k, *l; - p = temp_token_head; - set_token_link(p, null); - k = s.s; - l = k + s.l; - while (k < l) { - t = pool_to_unichar(k); - k += utf8_size(t); - if (t == ' ') - t = space_token; - else - t = other_token + t; - fast_store_new_token(t); - } - return p; -} - -/*tex - - Most of the converter is similar to the one i made for macro so at some point - I can make a helper; also todo: there is no need to go through the pool. - -*/ - -/*tex Change the string |str_pool[b..pool_ptr]| to a token list. */ - -halfword str_scan_toks(int ct, lstring s) -{ - /*tex tail of the token list */ - halfword p; - /*tex new node being added to the token list via |store_new_token| */ - halfword q; - /*tex token being appended */ - halfword t; - /*tex index into string */ - unsigned char *k, *l; - int cc; - p = temp_token_head; - set_token_link(p, null); - k = s.s; - l = k + s.l; - while (k < l) { - t = pool_to_unichar(k); - k += utf8_size(t); - cc = get_cat_code(ct,t); - if (cc == 0) { - /*tex We have a potential control sequence so we check for it. */ - int _lname = 0 ; - int _s = 0 ; - int _c = 0 ; - halfword _cs = null ; - unsigned char *_name = k ; - while (k < l) { - t = (halfword) str2uni((const unsigned char *) k); - _s = utf8_size(t); - _c = get_cat_code(ct,t); - if (_c == 11) { - k += _s ; - _lname = _lname + _s ; - } else if (_c == 10) { - /*tex We ignore a trailing space like normal scanning does. */ - k += _s ; - break ; - } else { - break ; - } - } - if (_s > 0) { - /*tex We have a potential |\cs|. */ - _cs = string_lookup((const char *) _name, _lname); - if (_cs == undefined_control_sequence) { - /* let's play safe and backtrack */ - t = cc * (1<<21) + t ; - k = _name ; - } else { - t = cs_token_flag + _cs; - } - } else { - /*tex - - Just a character with some meaning, so |\unknown| becomes - effectively |\unknown| assuming that |\\| has some useful - meaning of course. - - */ - t = cc * (1<<21) + t ; - k = _name ; - } - - } else { - /*tex - - Whatever token, so for instance $x^2$ just works given a \TEX\ - catcode regime. - - */ - t = cc * (1<<21) + t ; - } - fast_store_new_token(t); - - } - return p; -} - -/*tex - - Here's part of the |expand| subroutine that we are now ready to complete: - -*/ - -void ins_the_toks(void) -{ - (void) the_toks(); - ins_list(token_link(temp_token_head)); -} - -#define set_toks_register(n,t,g) do { \ - int a = (g>0) ? 4 : 0; \ - halfword ref = get_avail(); \ - set_token_ref_count(ref, 0); \ - set_token_link(ref, token_link(t)); \ - define(n + toks_base, call_cmd, ref); \ -} while (0) - -#define append_copied_toks_list(s,t) do { \ - halfword p; \ - halfword q; \ - p = temp_token_head; \ - set_token_link(p, null); \ - while (s != null) { \ - fast_store_new_token(token_info(s)); \ - s = token_link(s); \ - } \ - while (t != null) { \ - fast_store_new_token(token_info(t)); \ - t = token_link(t); \ - } \ - } while (0) - - -/*tex - - \starttabulate[|T||T||] - \NC 0 \NC \type {toksapp} \NC 1 \NC \type {etoksapp} \NC \NR - \NC 2 \NC \type {tokspre} \NC 3 \NC \type {etokspre} \NC \NR - \NC 4 \NC \type {gtoksapp} \NC 5 \NC \type {xtoksapp} \NC \NR - \NC 6 \NC \type {gtokspre} \NC 7 \NC \type {xtokspre} \NC \NR - \stoptabulate - -*/ - -# define immediate_permitted(n,target) ((eq_level(toks_base + n) == cur_level) && (token_ref_count(target) == 0)) - -void combine_the_toks(void) -{ - halfword how = cur_chr; - halfword source = null; - halfword target = null; - halfword append = (how == 0) || (how == 1) || (how == 4) || (how == 5); - halfword expand = odd(how); - halfword global = how > 3; - halfword nt, ns, s, t, p, q, h; - get_x_token(); - /*tex The target. */ - if (cur_cmd == assign_toks_cmd) { - /*tex Check range. */ - nt = equiv(cur_cs) - toks_base; - } else { - back_input(); - scan_register_num(); - nt = cur_val; - } - /*tex The source. */ - do { - get_x_token(); - } while (cur_cmd == spacer_cmd); - if (cur_cmd == left_brace_cmd) { - back_input(); - scan_toks(false,expand); - source = def_ref; - /*tex The action. */ - if (source != null) { - target = toks(nt); - if (target == null) { - set_toks_register(nt,source,global); - token_link(source) = null; - } else { - s = token_link(source); - if (s != null) { - t = token_link(target); - if (t == null) { - /*tex Can this happen? */ - set_token_link(target, s); - token_link(source) = null; - } else if (append) { - /*tex Append. */ - if (immediate_permitted(nt,target)) { - p = t; - while (token_link(p) != null) { - p = token_link(p); - } - while (s != null) { - fast_store_new_token(token_info(s)); - s = token_link(s); - } - } else { - append_copied_toks_list(t,s); - set_toks_register(nt,temp_token_head,global); - } - } else { - /* prepend */ - if (immediate_permitted(nt,target)) { - h = null; - p = null ; - while (s != null) { - fast_store_new_token(token_info(s)); - if (h == null) { - h = p; - } - s = token_link(s); - } - set_token_link(p,t); - set_token_link(target,h); - } else { - append_copied_toks_list(s,t); - set_toks_register(nt,temp_token_head,global); - } - } - } - } - flush_list(source); - } - } else { - if (cur_cmd == assign_toks_cmd) { - ns = equiv(cur_cs) - toks_base; - /*tex Check range. */ - } else { - scan_register_num(); - ns = cur_val; - } - /*tex The action. */ - source = toks(ns); - if (source != null) { - target = toks(nt); - if (target == null) { - /*tex The assign. */ - token_ref_count(source)++; - equiv(toks_base+nt) = source; - return; - } - s = token_link(source); - t = token_link(target); - if (append) { - /*tex Append. */ - if (immediate_permitted(nt,target)) { - p = t; - while (token_link(p) != null) { - p = token_link(p); - } - while (s != null) { - fast_store_new_token(token_info(s)); - s = token_link(s); - } - } else { - append_copied_toks_list(t,s); - set_toks_register(nt,temp_token_head,global); - } - } else { - /*tex Prepend. */ - if (immediate_permitted(nt,target)) { - h = null; - p = null; - while (s != null) { - fast_store_new_token(token_info(s)); - if (h == null) { - h = p; - } - s = token_link(s); - } - set_token_link(p,t); - set_token_link(target,h); - } else { - append_copied_toks_list(s,t); - set_toks_register(nt,temp_token_head,global); - } - } - } - } -} - -/*tex - - This routine, used in the next one, prints the job name, possibly modified by - the |process_jobname| callback. - -*/ - -static void print_job_name(void) -{ - if (job_name) { - /*tex C strings for jobname before and after processing. */ - char *s, *ss; - int callback_id, lua_retval; - s = (char*)str_string(job_name); - callback_id = callback_defined(process_jobname_callback); - if (callback_id > 0) { - lua_retval = run_callback(callback_id, "S->S", s, &ss); - if ((lua_retval == true) && (ss != NULL)) - s = ss; - } - tprint(s); - } else { - print(job_name); - } -} - -/*tex - - Here is a routine that print the result of a convert command, using the - argument |i|. It returns |false | if it does not know to print the code |c|. - The function exists because lua code and tex code can both call it to convert - something. - - Parse optional \LUA\ state integer, or an instance name to be stored in |sn| - and get the next non-blank non-relax non-call token. - -*/ - -int scan_lua_state(void) -{ - int sn = 0; - do { - get_x_token(); - } while ((cur_cmd == spacer_cmd) || (cur_cmd == relax_cmd)); - back_input(); - if (cur_cmd != left_brace_cmd) { - if (scan_keyword("name")) { - (void) scan_toks(false, true); - sn = def_ref; - } else { - scan_register_num(); - if (get_lua_name(cur_val)) - sn = (cur_val - 65536); - } - } - return sn; -} - -/*tex - - The procedure |conv_toks| uses |str_toks| to insert the token list for - |convert| functions into the scanner; `\.{\\outer}' control sequences are - allowed to follow `\.{\\string}' and `\.{\\meaning}'. - - The extra temp string |u| is needed because |pdf_scan_ext_toks| incorporates - any pending string in its output. In order to save such a pending string, we - have to create a temporary string that is destroyed immediately after. - -*/ - -#define push_selector { \ - old_setting = selector; \ - selector = new_string; \ -} - -#define pop_selector { \ - selector = old_setting; \ -} - -static int do_variable_dvi(halfword c) -{ - return 0; -} - -#define do_variable_backend_int(i) \ - cur_cmd = assign_int_cmd; \ - cur_val = backend_int_base + i; \ - cur_tok = token_val(cur_cmd, cur_val); \ - back_input(); - -#define do_variable_backend_dimen(i) \ - cur_cmd = assign_dimen_cmd; \ - cur_val = backend_dimen_base + i; \ - cur_tok = token_val(cur_cmd, cur_val); \ - back_input(); - -#define do_variable_backend_toks(i) \ - cur_cmd = assign_toks_cmd; \ - cur_val = backend_toks_base + i ; \ - cur_tok = token_val(cur_cmd, cur_val); \ - back_input(); - -static int do_variable_pdf(halfword c) -{ - if (scan_keyword("compresslevel")) { do_variable_backend_int(c_pdf_compress_level); } - else if (scan_keyword("decimaldigits")) { do_variable_backend_int(c_pdf_decimal_digits); } - else if (scan_keyword("imageresolution")) { do_variable_backend_int(c_pdf_image_resolution); } - else if (scan_keyword("pkresolution")) { do_variable_backend_int(c_pdf_pk_resolution); } - else if (scan_keyword("uniqueresname")) { do_variable_backend_int(c_pdf_unique_resname); } - else if (scan_keyword("majorversion")) { do_variable_backend_int(c_pdf_major_version); } - else if (scan_keyword("minorversion")) { do_variable_backend_int(c_pdf_minor_version); } - else if (scan_keyword("pagebox")) { do_variable_backend_int(c_pdf_pagebox); } - else if (scan_keyword("inclusionerrorlevel")) { do_variable_backend_int(c_pdf_inclusion_errorlevel); } - else if (scan_keyword("ignoreunknownimages")) { do_variable_backend_int(c_pdf_ignore_unknown_images); } - else if (scan_keyword("gamma")) { do_variable_backend_int(c_pdf_gamma); } - else if (scan_keyword("imageapplygamma")) { do_variable_backend_int(c_pdf_image_apply_gamma); } - else if (scan_keyword("imagegamma")) { do_variable_backend_int(c_pdf_image_gamma); } - else if (scan_keyword("imagehicolor")) { do_variable_backend_int(c_pdf_image_hicolor); } - else if (scan_keyword("imageaddfilename")) { do_variable_backend_int(c_pdf_image_addfilename); } - else if (scan_keyword("objcompresslevel")) { do_variable_backend_int(c_pdf_obj_compress_level); } - else if (scan_keyword("inclusioncopyfonts")) { do_variable_backend_int(c_pdf_inclusion_copy_font); } - else if (scan_keyword("gentounicode")) { do_variable_backend_int(c_pdf_gen_tounicode); } - else if (scan_keyword("pkfixeddpi")) { do_variable_backend_int(c_pdf_pk_fixed_dpi); } - else if (scan_keyword("suppressoptionalinfo")) { do_variable_backend_int(c_pdf_suppress_optional_info); } - else if (scan_keyword("omitcidset")) { do_variable_backend_int(c_pdf_omit_cidset); } - else if (scan_keyword("omitcharset")) { do_variable_backend_int(c_pdf_omit_charset); } - else if (scan_keyword("recompress")) { do_variable_backend_int(c_pdf_recompress); } - - else if (scan_keyword("horigin")) { do_variable_backend_dimen(d_pdf_h_origin); } - else if (scan_keyword("vorigin")) { do_variable_backend_dimen(d_pdf_v_origin); } - else if (scan_keyword("threadmargin")) { do_variable_backend_dimen(d_pdf_thread_margin); } - else if (scan_keyword("destmargin")) { do_variable_backend_dimen(d_pdf_dest_margin); } - else if (scan_keyword("linkmargin")) { do_variable_backend_dimen(d_pdf_link_margin); } - else if (scan_keyword("xformmargin")) { do_variable_backend_dimen(d_pdf_xform_margin); } - - else if (scan_keyword("pageattr")) { do_variable_backend_toks(t_pdf_page_attr); } - else if (scan_keyword("pageresources")) { do_variable_backend_toks(t_pdf_page_resources); } - else if (scan_keyword("pagesattr")) { do_variable_backend_toks(t_pdf_pages_attr); } - else if (scan_keyword("xformattr")) { do_variable_backend_toks(t_pdf_xform_attr); } - else if (scan_keyword("xformresources")) { do_variable_backend_toks(t_pdf_xform_resources); } - else if (scan_keyword("pkmode")) { do_variable_backend_toks(t_pdf_pk_mode); } - else if (scan_keyword("trailerid")) { do_variable_backend_toks(t_pdf_trailer_id); } - - else - return 0; - return 1; -} - -static int do_feedback_dvi(halfword c) -{ - return 0; -} - -/*tex Codes not really needed but cleaner when testing */ - -#define pdftex_version 140 /* these values will not change any more */ -#define pdftex_revision "0" /* these values will not change any more */ - -static int do_feedback_pdf(halfword c) -{ - /*tex holds |selector| setting */ - int old_setting; - /*tex |scanner_status| upon entry */ - int save_scanner_status; - /*tex |def_ref| upon entry, important if inside `\.{\\message}' */ - halfword save_def_ref; - halfword save_warning_index; - /*tex temp boolean */ - boolean bool; - /*tex first temp string */ - str_number s; - /*tex for use with |set_ff| */ - int ff; - /*tex third temp string, will become non-nil if a string is already being built */ - str_number u = 0; - /*tex color stack init str */ - char *str; - if (scan_keyword("lastlink")) { - push_selector; - print_int(pdf_last_link); - pop_selector; - } else if (scan_keyword("retval")) { - push_selector; - print_int(pdf_retval); - pop_selector; - } else if (scan_keyword("lastobj")) { - push_selector; - print_int(pdf_last_obj); - pop_selector; - } else if (scan_keyword("lastannot")) { - push_selector; - print_int(pdf_last_annot); - pop_selector; - } else if (scan_keyword("xformname")) { - scan_int(); - check_obj_type(static_pdf, obj_type_xform, cur_val); - push_selector; - print_int(obj_info(static_pdf, cur_val)); - pop_selector; - } else if (scan_keyword("creationdate")) { - ins_list(string_to_toks(getcreationdate(static_pdf))); - /*tex No further action. */ - return 2; - } else if (scan_keyword("fontname")) { - scan_font_ident(); - if (cur_val == null_font) - normal_error("pdf backend", "invalid font identifier when asking 'fontname'"); - pdf_check_vf(cur_val); - if (!font_used(cur_val)) - pdf_init_font(static_pdf, cur_val); - push_selector; - set_ff(cur_val); - print_int(obj_info(static_pdf, pdf_font_num(ff))); - pop_selector; - } else if (scan_keyword("fontobjnum")) { - scan_font_ident(); - if (cur_val == null_font) - normal_error("pdf backend", "invalid font identifier when asking 'objnum'"); - pdf_check_vf(cur_val); - if (!font_used(cur_val)) - pdf_init_font(static_pdf, cur_val); - push_selector; - set_ff(cur_val); - print_int(pdf_font_num(ff)); - pop_selector; - } else if (scan_keyword("fontsize")) { - scan_font_ident(); - if (cur_val == null_font) - normal_error("pdf backend", "invalid font identifier when asking 'fontsize'"); - push_selector; - print_scaled(font_size(cur_val)); - tprint("pt"); - pop_selector; - } else if (scan_keyword("pageref")) { - scan_int(); - if (cur_val <= 0) - normal_error("pdf backend", "invalid page number when asking 'pageref'"); - push_selector; - print_int(pdf_get_obj(static_pdf, obj_type_page, cur_val, false)); - pop_selector; - } else if (scan_keyword("colorstackinit")) { - bool = scan_keyword("page"); - if (scan_keyword("direct")) - cur_val = direct_always; - else if (scan_keyword("page")) - cur_val = direct_page; - else if (scan_keyword("text")) - cur_val = direct_text; - else if (scan_keyword("raw")) - cur_val = direct_raw; - else if (scan_keyword("origin")) - cur_val = set_origin; - else - cur_val = set_origin; - save_scanner_status = scanner_status; - save_warning_index = warning_index; - save_def_ref = def_ref; - u = save_cur_string(); - scan_toks(false, true); - s = tokens_to_string(def_ref); - delete_token_ref(def_ref); - def_ref = save_def_ref; - warning_index = save_warning_index; - scanner_status = save_scanner_status; - str = makecstring(s); - cur_val = newcolorstack(str, cur_val, bool); - free(str); - flush_str(s); - cur_val_level = int_val_level; - if (cur_val < 0) { - print_err("Too many color stacks"); - help2("The number of color stacks is limited to 32768.", - "I'll use the default color stack 0 here."); - error(); - cur_val = 0; - restore_cur_string(u); - } - push_selector; - print_int(cur_val); - pop_selector; - } else if (scan_keyword("version")) { - push_selector; - print_int(pdftex_version); - pop_selector; - } else if (scan_keyword("revision")) { - ins_list(string_to_toks(pdftex_revision)); - return 2; - } else { - return 0; - } - return 1; -} - -void conv_toks(void) -{ - /*tex holds |selector| setting */ - int old_setting; - halfword p, q; - /*tex |scanner_status| upon entry */ - int save_scanner_status; - /*tex |def_ref| upon entry, important if inside `\.{\\message}' */ - halfword save_def_ref; - halfword save_warning_index; - /*tex temp boolean */ - boolean bool; - /*tex first temp string */ - str_number s; - /*tex lua chunk name */ - int sn; - /*tex third temp string, will become non-nil if a string is already being built */ - str_number u = 0; - /*tex desired type of conversion */ - int c = cur_chr; - str_number str; - int i = 0; - /*tex Scan the argument for command |c|. */ - switch (c) { - case number_code: - scan_int(); - push_selector; - print_int(cur_val); - pop_selector; - break; - case lua_function_code: - scan_int(); - if (cur_val <= 0) { - normal_error("luafunction", "invalid number"); - } else { - u = save_cur_string(); - luacstrings = 0; - luafunctioncall(cur_val); - restore_cur_string(u); - if (luacstrings > 0) - lua_string_start(); - } - return; - break; - case lua_bytecode_code: - scan_int(); - if (cur_val < 0 || cur_val > 65535) { - normal_error("luabytecode", "invalid number"); - } else { - u = save_cur_string(); - luacstrings = 0; - luabytecodecall(cur_val); - restore_cur_string(u); - if (luacstrings > 0) - lua_string_start(); - } - return; - break; - case lua_code: - u = save_cur_string(); - save_scanner_status = scanner_status; - save_def_ref = def_ref; - save_warning_index = warning_index; - sn = scan_lua_state(); - scan_toks(false, true); - s = def_ref; - warning_index = save_warning_index; - def_ref = save_def_ref; - scanner_status = save_scanner_status; - luacstrings = 0; - luatokencall(s, sn); - delete_token_ref(s); - restore_cur_string(u); - if (luacstrings > 0) - lua_string_start(); - /*tex No further action. */ - return; - break; - case expanded_code: - save_scanner_status = scanner_status; - save_warning_index = warning_index; - save_def_ref = def_ref; - u = save_cur_string(); - scan_toks(false, true); - warning_index = save_warning_index; - scanner_status = save_scanner_status; - ins_list(token_link(def_ref)); - token_link(def_ref) = null; - free_avail(def_ref); - def_ref = save_def_ref; - restore_cur_string(u); - /*tex No further action. */ - return; - break; - case immediate_assignment_code: - case immediate_assigned_code: - /*tex - - This is on-the-road-to-bachotex brain-wave but it needs a bit - more testing. A first variant did more in sequence till a relax - of spacer was seen (like do_assignments). It permits for instance - setting counters in full expansion. - - */ - save_scanner_status = scanner_status; - save_warning_index = warning_index; - save_def_ref = def_ref; - u = save_cur_string(); - do { - get_x_token(); - } while ((cur_cmd == spacer_cmd) || (cur_cmd == relax_cmd)); - if (c == immediate_assignment_code) { - /*tex one-step do_assignment */ - if (cur_cmd > max_non_prefixed_command) { - set_box_allowed = false; - prefixed_command(); - set_box_allowed = true; - } - /*tex done */ - } else { - /*tex pseudo token list do_assignment */ - if (cur_cmd == left_brace_cmd) { - while (1) { - do { - get_x_token(); - } while ((cur_cmd == spacer_cmd) || (cur_cmd == relax_cmd)); - if (cur_cmd == right_brace_cmd) { - break; - } else { - set_box_allowed = false; - prefixed_command(); - set_box_allowed = true; - } - } - } - /*tex done */ - } - warning_index = save_warning_index; - scanner_status = save_scanner_status; - def_ref = save_def_ref; - restore_cur_string(u); - return; - break; - case math_style_code: - push_selector; - print_math_style(); - pop_selector; - break; - case string_code: - save_scanner_status = scanner_status; - scanner_status = normal; - get_token(); - scanner_status = save_scanner_status; - push_selector; - if (cur_cs != 0) - sprint_cs(cur_cs); - else - print(cur_chr); - pop_selector; - break; - case cs_string_code: - save_scanner_status = scanner_status; - scanner_status = normal; - get_token(); - scanner_status = save_scanner_status; - push_selector; - if (cur_cs != 0) - sprint_cs_name(cur_cs); - else - print(cur_chr); - pop_selector; - break; - case roman_numeral_code: - scan_int(); - push_selector; - print_roman_int(cur_val); - pop_selector; - break; - case meaning_code: - save_scanner_status = scanner_status; - scanner_status = normal; - get_token(); - scanner_status = save_scanner_status; - push_selector; - print_meaning(); - pop_selector; - break; - case uchar_code: - scan_char_num(); - push_selector; - print(cur_val); - pop_selector; - break; - case lua_escape_string_code: - { - lstring escstr; - int l = 0; - save_scanner_status = scanner_status; - save_def_ref = def_ref; - save_warning_index = warning_index; - scan_toks(false, true); - bool = in_lua_escape; - in_lua_escape = true; - escstr.s = (unsigned char *) tokenlist_to_cstring(def_ref, false, &l); - escstr.l = (unsigned) l; - in_lua_escape = bool; - delete_token_ref(def_ref); - def_ref = save_def_ref; - warning_index = save_warning_index; - scanner_status = save_scanner_status; - (void) lua_str_toks(escstr); - ins_list(token_link(temp_token_head)); - free(escstr.s); - return; - } - /*tex no further action */ - break; - case font_id_code: - scan_font_ident(); - push_selector; - print_int(cur_val); - pop_selector; - break; - case font_name_code: - scan_font_ident(); - push_selector; - append_string((unsigned char *) font_name(cur_val),(unsigned) strlen(font_name(cur_val))); - if (font_size(cur_val) != font_dsize(cur_val)) { - tprint(" at "); - print_scaled(font_size(cur_val)); - tprint("pt"); - } - pop_selector; - break; - case left_margin_kern_code: - scan_int(); - if ((box(cur_val) == null) || (type(box(cur_val)) != hlist_node)) - normal_error("marginkern", "a non-empty hbox expected"); - push_selector; - p = list_ptr(box(cur_val)); - while ((p != null) && (type(p) == glue_node)) { - p = vlink(p); - } - if ((p != null) && (type(p) == margin_kern_node) && (subtype(p) == left_side)) - print_scaled(width(p)); - else - print_char('0'); - tprint("pt"); - pop_selector; - break; - case right_margin_kern_code: - scan_int(); - if ((box(cur_val) == null) || (type(box(cur_val)) != hlist_node)) - normal_error("marginkern", "a non-empty hbox expected"); - push_selector; - p = list_ptr(box(cur_val)); - if (p != null) { - p = tail_of_list(p); - /*tex - - There can be a leftskip, rightskip, penalty and yes, also a - disc node with a nesting node that points to glue spec ... - and we don't want to analyze that messy lot. - - */ - while ((p != null) && (type(p) == glue_node)) { - p = alink(p); - } - if ((p != null) && ! ((type(p) == margin_kern_node) && (subtype(p) == right_side))) { - if (type(p) == disc_node) { - q = alink(p); - if ((q != null) && ((type(q) == margin_kern_node) && (subtype(q) == right_side))) { - p = q; - } else { - /*tex - - Officially we should look in the replace but - currently protrusion doesn't work anyway with - "foo\discretionary{}{}{bar-} " (no following - char) so we don't need it now. - */ - } - } - } - } - if ((p != null) && (type(p) == margin_kern_node) && (subtype(p) == right_side)) - print_scaled(width(p)); - else - print_char('0'); - tprint("pt"); - pop_selector; - break; - case uniform_deviate_code: - scan_int(); - push_selector; - print_int(unif_rand(cur_val)); - pop_selector; - break; - case normal_deviate_code: - push_selector; - print_int(norm_rand()); - pop_selector; - break; - case math_char_class_code: - { - mathcodeval mval; - scan_int(); - mval = get_math_code(cur_val); - push_selector; - print_int(mval.class_value); - pop_selector; - } - break; - case math_char_fam_code: - { - mathcodeval mval; - scan_int(); - mval = get_math_code(cur_val); - push_selector; - print_int(mval.family_value); - pop_selector; - } - break; - case math_char_slot_code: - { - mathcodeval mval; - scan_int(); - mval = get_math_code(cur_val); - push_selector; - print_int(mval.character_value); - pop_selector; - } - break; - case insert_ht_code: - scan_register_num(); - push_selector; - i = cur_val; - p = page_ins_head; - while (i >= subtype(vlink(p))) - p = vlink(p); - if (subtype(p) == i) - print_scaled(height(p)); - else - print_char('0'); - tprint("pt"); - pop_selector; - break; - case job_name_code: - if (job_name == 0) - open_log_file(); - push_selector; - print_job_name(); - pop_selector; - break; - case format_name_code: - if (job_name == 0) - open_log_file(); - push_selector; - print(format_name); - pop_selector; - break; - case luatex_banner_code: - push_selector; - tprint(luatex_banner); - pop_selector; - break; - case luatex_revision_code: - push_selector; - print(get_luatexrevision()); - pop_selector; - break; - case etex_code: - push_selector; - tprint(eTeX_version_string); - pop_selector; - break; - case eTeX_revision_code: - push_selector; - tprint(eTeX_revision); - pop_selector; - break; - case font_identifier_code: - confusion("convert"); - break; - default: - confusion("convert"); - break; - } - str = make_string(); - (void) str_toks(str_lstring(str)); - flush_str(str); - ins_list(token_link(temp_token_head)); -} - -void do_feedback(void) -{ - int c = cur_chr; - str_number str; - int done = 1; - switch (c) { - case dvi_feedback_code: - if (get_o_mode() == OMODE_DVI) { - done = do_feedback_dvi(c); - } else { - tex_error("unexpected use of \\dvifeedback",null); - return ; - } - if (done==0) { - /* we recover */ - normal_warning("dvi backend","unexpected use of \\dvifeedback"); - return; - } else if (done==2) { - return; - } - break; - case pdf_feedback_code: - if (get_o_mode() == OMODE_PDF) { - done = do_feedback_pdf(c); - } else { - tex_error("unexpected use of \\pdffeedback",null); - return ; - } - if (done==0) { - /*tex We recover. */ - normal_warning("pdf backend","unexpected use of \\pdffeedback"); - return; - } else if (done==2) { - return; - } - break; - default: - confusion("feedback"); - break; - } - str = make_string(); - (void) str_toks(str_lstring(str)); - flush_str(str); - ins_list(token_link(temp_token_head)); -} - -void do_variable(void) -{ - int c = cur_chr; - int done = 1; - switch (c) { - case dvi_variable_code: - done = do_variable_dvi(c); - if (done==0) { - /*tex We recover. */ - normal_warning("dvi backend","unexpected use of \\dvivariable"); - } - return; - break; - case pdf_variable_code: - done = do_variable_pdf(c); - if (done==0) { - /*tex We recover. */ - normal_warning("pdf backend","unexpected use of \\pdfvariable"); - } - return; - break; - default: - confusion("variable"); - break; - } -} - -/*tex This boolean is keeping track of the lua string escape state */ - -boolean in_lua_escape; - -static int the_convert_string_dvi(halfword c, int i) -{ - return 0 ; -} - -static int the_convert_string_pdf(halfword c, int i) -{ - int ff; - if (get_o_mode() != OMODE_PDF) { - return 0; - } else if (scan_keyword("lastlink")) { - print_int(pdf_last_link); - } else if (scan_keyword("retval")) { - print_int(pdf_retval); - } else if (scan_keyword("lastobj")) { - print_int(pdf_last_obj); - } else if (scan_keyword("lastannot")) { - print_int(pdf_last_annot); - } else if (scan_keyword("xformname")) { - print_int(obj_info(static_pdf, i)); - } else if (scan_keyword("creationdate")) { - return 0; - } else if (scan_keyword("fontname")) { - set_ff(i); - print_int(obj_info(static_pdf, pdf_font_num(ff))); - } else if (scan_keyword("fontobjnum")) { - set_ff(i); - print_int(pdf_font_num(ff)); - } else if (scan_keyword("fontsize")) { - print_scaled(font_size(i)); - tprint("pt"); - } else if (scan_keyword("pageref")) { - print_int(pdf_get_obj(static_pdf, obj_type_page, i, false)); - } else if (scan_keyword("colorstackinit")) { - return 0; - } else { - return 0; - } - return 1; -} - -str_number the_convert_string(halfword c, int i) -{ - int old_setting; - str_number ret = 0; - boolean done = true ; - old_setting = selector; - selector = new_string; - switch (c) { - case number_code: - print_int(i); - break; - /* case lua_function_code: */ - /* case lua_code: */ - /* case expanded_code: */ - case math_style_code: - print_math_style(); - break; - /* case string_code: */ - /* case cs_string_code: */ - case roman_numeral_code: - print_roman_int(i); - break; - /* case meaning_code: */ - case uchar_code: - print(i); - break; - /* lua_escape_string_code: */ - case font_id_code: - print_int(i); - break; - case font_name_code: - append_string((unsigned char *) font_name(i),(unsigned) strlen(font_name(i))); - if (font_size(i) != font_dsize(i)) { - tprint(" at "); - print_scaled(font_size(i)); - tprint("pt"); - } - break; - /* left_margin_kern_code: */ - /* right_margin_kern_code: */ - case uniform_deviate_code: - print_int(unif_rand(i)); - break; - case normal_deviate_code: - print_int(norm_rand()); - break; - /* math_char_class_code: */ - /* math_char_fam_code: */ - /* math_char_slot_code: */ - /* insert_ht_code: */ - case job_name_code: - print_job_name(); - break; - case format_name_code: - print(format_name); - break; - case luatex_banner_code: - tprint(luatex_banner); - break; - case luatex_revision_code: - print(get_luatexrevision()); - break; - case etex_code: - tprint(eTeX_version_string); - break; - case eTeX_revision_code: - tprint(eTeX_revision); - break; - case font_identifier_code: - print_font_identifier(i); - break; - /*tex Backend: this might become obsolete! */ - case dvi_feedback_code: - done = the_convert_string_dvi(c,i); - break; - case pdf_feedback_code: - done = the_convert_string_pdf(c,i); - break; - /*tex done */ - default: - done = false; - break; - } - if (done) { - ret = make_string(); - } - selector = old_setting; - return ret; -} - -/*tex - - Another way to create a token list is via the \.{\\read} command. The sixteen - files potentially usable for reading appear in the following global - variables. The value of |read_open[n]| will be |closed| if stream number |n| - has not been opened or if it has been fully read; |just_open| if an - \.{\\openin} but not a \.{\\read} has been done; and |normal| if it is open - and ready to read the next line. - -*/ - -/*tex used for \.{\\read} */ - -FILE *read_file[16]; - -/*tex state of |read_file[n]| */ - -int read_open[17]; - -void initialize_read(void) -{ - int k; - for (k = 0; k <= 16; k++) - read_open[k] = closed; -} - -/*tex - - The |read_toks| procedure constructs a token list like that for any macro - definition, and makes |cur_val| point to it. Parameter |r| points to the - control sequence that will receive this token list. - -*/ - -void read_toks(int n, halfword r, halfword j) -{ - /*tex tail of the token list */ - halfword p; - /*tex new node being added to the token list via |store_new_token| */ - halfword q; - /*tex saved value of |align_state| */ - int s; - /*tex stream number */ - int m; - scanner_status = defining; - warning_index = r; - p = get_avail(); - def_ref = p; - set_token_ref_count(def_ref, 0); - /*tex the reference count */ - p = def_ref; - store_new_token(end_match_token); - if ((n < 0) || (n > 15)) - m = 16; - else - m = n; - s = align_state; - /*tex disable tab marks, etc. */ - align_state = 1000000; - do { - /*tex Input and store tokens from the next line of the file. */ - begin_file_reading(); - iname = m + 1; - if (read_open[m] == closed) { - /*tex - - Input for \.{\\read} from the terminal. We input on-line into the - |buffer| array, prompting the user explicitly if |n>=0|. The - value of |n| is set negative so that additional prompts will not - be given in the case of multi-line input. - - */ - if (interaction > nonstop_mode) { - if (n < 0) { - prompt_input(""); - } else { - wake_up_terminal(); - print_ln(); - sprint_cs(r); - prompt_input(" ="); - n = -1; - } - } else { - fatal_error - ("*** (cannot \\read from terminal in nonstop modes)"); - } - - } else if (read_open[m] == just_open) { - /*tex - - Input the first line of |read_file[m]|. The first line of a file - must be treated specially, since |lua_input_ln| must be told not - to start with |get|. - - */ - if (lua_input_ln(read_file[m], (m + 1), false)) { - read_open[m] = normal; - } else { - lua_a_close_in(read_file[m], (m + 1)); - read_open[m] = closed; - } - - } else { - /*tex - - Input the next line of |read_file[m]|. An empty line is appended - at the end of a |read_file|. - - */ - if (!lua_input_ln(read_file[m], (m + 1), true)) { - lua_a_close_in(read_file[m], (m + 1)); - read_open[m] = closed; - if (align_state != 1000000) { - runaway(); - print_err("File ended within \\read"); - help1("This \\read has unbalanced braces."); - align_state = 1000000; - error(); - } - } - - } - ilimit = last; - if (end_line_char_inactive) - decr(ilimit); - else - buffer[ilimit] = (packed_ASCII_code) end_line_char_par; - first = ilimit + 1; - iloc = istart; - istate = new_line; - /*tex Handle \.{\\readline} and |goto done|. */ - if (j == 1) { - while (iloc <= ilimit) { - /*tex Current line not yet finished. */ - do_buffer_to_unichar(cur_chr, iloc); - if (cur_chr == ' ') - cur_tok = space_token; - else - cur_tok = cur_chr + other_token; - store_new_token(cur_tok); - } - } else { - while (1) { - get_token(); - if (cur_tok == 0) { - /*tex |cur_cmd=cur_chr=0| will occur at the end of the line. */ - break; - } - if (align_state < 1000000) { - /*tex Unmatched right brace aborts the line. */ - do { - get_token(); - } while (cur_tok != 0); - align_state = 1000000; - break; - } - store_new_token(cur_tok); - } - } - end_file_reading(); - - } while (align_state != 1000000); - cur_val = def_ref; - scanner_status = normal; - align_state = s; -} - -/*tex Return a string from tokens list: */ - -str_number tokens_to_string(halfword p) -{ - int old_setting; - if (selector == new_string) - normal_error("tokens","tokens_to_string() called while selector = new_string"); - old_setting = selector; - selector = new_string; - show_token_list(token_link(p), null, -1); - selector = old_setting; - return make_string(); -} - -/*tex - - Values like 512 and 128 also work ok. There is not much to gain in - optimization here. - -*/ - -#define alloci_default 1024 -#define alloci_step 256 - -#define make_room(a) \ - if ((unsigned)i+a+1>alloci) { \ - ret = xrealloc(ret,(alloci+alloci_step)); \ - alloci = alloci + alloci_step; \ - } - -#define append_i_byte(a) ret[i++] = (char)(a) - -#define Print_char(a) make_room(1); append_i_byte(a) - -#define Print_uchar(s) { \ - make_room(4); \ - if (s<=0x7F) { \ - append_i_byte(s); \ - } else if (s<=0x7FF) { \ - append_i_byte(0xC0 + (s / 0x40)); \ - append_i_byte(0x80 + (s % 0x40)); \ - } else if (s<=0xFFFF) { \ - append_i_byte(0xE0 + (s / 0x1000)); \ - append_i_byte(0x80 + ((s % 0x1000) / 0x40)); \ - append_i_byte(0x80 + ((s % 0x1000) % 0x40)); \ - } else if (s>=0x110000) { \ - append_i_byte(s-0x11000); \ - } else { \ - append_i_byte(0xF0 + (s / 0x40000)); \ - append_i_byte(0x80 + ((s % 0x40000) / 0x1000)); \ - append_i_byte(0x80 + (((s % 0x40000) % 0x1000) / 0x40)); \ - append_i_byte(0x80 + (((s % 0x40000) % 0x1000) % 0x40)); \ - } } - -#define Print_esc(b) { \ - const char *v = b; \ - if (e>0 && e<STRING_OFFSET) { \ - Print_uchar (e); \ - } \ - make_room(strlen(v)); \ - while (*v) { append_i_byte(*v); v++; } \ - } - -#define Print_str(b) { \ - const char *v = b; \ - make_room(strlen(v)); \ - while (*v) { append_i_byte(*v); v++; } \ - } - -#define is_cat_letter(a) \ - (get_char_cat_code(pool_to_unichar(str_string((a)))) == 11) - -/*tex - - The actual token conversion in this function is now functionally equivalent - to |show_token_list|, except that it always prints the whole token list. - TODO: check whether this causes problems in the lua library. - -*/ - -char *tokenlist_to_cstring(int pp, int inhibit_par, int *siz) -{ - register int p, c, m; - int q; - int infop; - char *s, *sh; - int e = 0; - char *ret; - int match_chr = '#'; - int n = '0'; - unsigned alloci = alloci_default; - int i = 0; - p = pp; - if (p == null) { - if (siz != NULL) - *siz = 0; - return NULL; - } - ret = xmalloc(alloci); - /*tex Skip refcount. */ - p = token_link(p); - if (p != null) { - e = escape_char_par; - } - while (p != null) { - if (p < (int) fix_mem_min || p > (int) fix_mem_end) { - Print_esc("CLOBBERED."); - break; - } - infop = token_info(p); - if (infop >= cs_token_flag) { - if (!(inhibit_par && infop == par_token)) { - q = infop - cs_token_flag; - if (q < hash_base) { - if (q == null_cs) { - Print_esc("csname"); - Print_esc("endcsname"); - } else { - Print_esc("IMPOSSIBLE."); - } - } else if ((q >= undefined_control_sequence) && ((q <= eqtb_size) || (q > eqtb_size + hash_extra))) { - Print_esc("IMPOSSIBLE."); - } else if ((cs_text(q) < 0) || (cs_text(q) >= str_ptr)) { - Print_esc("NONEXISTENT."); - } else { - str_number txt = cs_text(q); - sh = makecstring(txt); - s = sh; - if (is_active_cs(txt)) { - s = s + 3; - while (*s) { - Print_char(*s); - s++; - } - } else { - if (e>=0 && e<0x110000) Print_uchar(e); - while (*s) { - Print_char(*s); - s++; - } - if ((!single_letter(txt)) || is_cat_letter(txt)) { - Print_char(' '); - } - } - free(sh); - } - } - } else { - if (infop < 0) { - Print_esc("BAD"); - } else { - m = token_cmd(infop); - c = token_chr(infop); - switch (m) { - case left_brace_cmd: - case right_brace_cmd: - case math_shift_cmd: - case tab_mark_cmd: - case sup_mark_cmd: - case sub_mark_cmd: - case spacer_cmd: - case letter_cmd: - case other_char_cmd: - Print_uchar(c); - break; - case mac_param_cmd: - if (!in_lua_escape && (is_in_csname==0)) - Print_uchar(c); - Print_uchar(c); - break; - case out_param_cmd: - Print_uchar(match_chr); - if (c <= 9) { - Print_char(c + '0'); - } else { - Print_char('!'); - goto EXIT; - } - break; - case match_cmd: - match_chr = c; - Print_uchar(c); - n++; - Print_char(n); - if (n > '9') - goto EXIT; - break; - case end_match_cmd: - if (c == 0) { - Print_char('-'); - Print_char('>'); - } - break; - default: - not_so_bad(Print_esc); - break; - } - } - } - p = token_link(p); - } - EXIT: - ret[i] = '\0'; - if (siz != NULL) - *siz = i; - return ret; -} - -char *tokenlist_to_xstring(int pp, int inhibit_par, int *siz) -{ - register int p, c, m; - int q; - int infop; - char *s, *sh; - int e = 0; - char *ret; - int match_chr = '#'; - int n = '0'; - unsigned alloci = alloci_default; - int i = 0; - int skipping = 1; - p = pp; - if (p == null) { - if (siz != NULL) - *siz = 0; - return NULL; - } - ret = xmalloc(alloci); - /*tex Skip refcount. */ - p = token_link(p); - if (p != null) { - e = escape_char_par; - } - while (p != null) { - if (p < (int) fix_mem_min || p > (int) fix_mem_end) { - /*tex Nothing done. */ - break; - } - infop = token_info(p); - if (infop >= cs_token_flag) { - if (!(inhibit_par && infop == par_token)) { - q = infop - cs_token_flag; - if (q < hash_base) { - /*tex Nothing done. */ - } else if ((q >= undefined_control_sequence) && ((q <= eqtb_size) || (q > eqtb_size + hash_extra))) { - /*tex Nothing done. */ - } else if ((cs_text(q) < 0) || (cs_text(q) >= str_ptr)) { - /*tex Nothing done. */ - } else if (!skipping) { - str_number txt = cs_text(q); - sh = makecstring(txt); - s = sh; - if (is_active_cs(txt)) { - s = s + 3; - while (*s) { - Print_char(*s); - s++; - } - } else { - if (e>=0 && e<0x110000) Print_uchar(e); - while (*s) { - Print_char(*s); - s++; - } - if ((!single_letter(txt)) || is_cat_letter(txt)) { - Print_char(' '); - } - } - free(sh); - } - } - } else { - if (infop < 0) { - /*tex Nothing done. */ - } else { - m = token_cmd(infop); - c = token_chr(infop); - switch (m) { - case left_brace_cmd: - case right_brace_cmd: - case math_shift_cmd: - case tab_mark_cmd: - case sup_mark_cmd: - case sub_mark_cmd: - case spacer_cmd: - case letter_cmd: - case other_char_cmd: - if (!skipping) { - Print_uchar(c); - } - break; - case mac_param_cmd: - if (!skipping) { - if (!in_lua_escape && (is_in_csname==0)) - Print_uchar(c); - Print_uchar(c); - } - break; - case out_param_cmd: - if (!skipping) { - Print_uchar(match_chr); - } - if (c <= 9) { - if (!skipping) { - Print_char(c + '0'); - } - } else { - /*tex Nothing done. */ - goto EXIT; - } - break; - case match_cmd: - match_chr = c; - if (!skipping) { - Print_uchar(c); - } - n++; - if (!skipping) { - Print_char(n); - } - if (n > '9') - goto EXIT; - break; - case end_match_cmd: - if (c == 0) { - if (!skipping) { - Print_char('-'); - Print_char('>'); - } - i = 0; - skipping = 0 ; - } - break; - default: - /*tex Nothing done. */ - break; - } - } - } - p = token_link(p); - } - EXIT: - ret[i] = '\0'; - if (siz != NULL) - *siz = i; - return ret; -} - -lstring *tokenlist_to_lstring(int pp, int inhibit_par) -{ - int siz; - lstring *ret = xmalloc(sizeof(lstring)); - ret->s = (unsigned char *) tokenlist_to_cstring(pp, inhibit_par, &siz); - ret->l = (size_t) siz; - return ret; -} - -void free_lstring(lstring * ls) -{ - if (ls == NULL) - return; - if (ls->s != NULL) - free(ls->s); - free(ls); -} diff --git a/Build/source/texk/web2c/luatexdir/tex/textoken.h b/Build/source/texk/web2c/luatexdir/tex/textoken.h deleted file mode 100644 index 248a12168cf..00000000000 --- a/Build/source/texk/web2c/luatexdir/tex/textoken.h +++ /dev/null @@ -1,189 +0,0 @@ -/* textoken.h - - Copyright 2006-2008 Taco Hoekwater <taco@luatex.org> - - This file is part of LuaTeX. - - LuaTeX is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your - option) any later version. - - LuaTeX is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - License for more details. - - You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ - - -#ifndef TEXTOKEN_H -# define TEXTOKEN_H - -# define token_list 0 -# define null 0 -# define cs_token_flag 0x1FFFFFFF - -# define left_brace_token 0x0200000 /* $2^{21}\cdot|left_brace|$ */ -# define right_brace_token 0x0400000 /* $2^{21}\cdot|right_brace|$ */ -# define left_brace_limit 0x0400000 /* $2^{21}\cdot(|left_brace|+1)$ */ -# define right_brace_limit 0x0600000 /* $2^{21}\cdot(|right_brace|+1)$ */ -# define math_shift_token 0x0600000 /* $2^{21}\cdot|math_shift|$ */ -# define tab_token 0x0800000 /* $2^{21}\cdot|tab_mark|$ */ -# define out_param_token 0x0A00000 /* $2^{21}\cdot|out_param|$ */ -# define space_token 0x1400020 /* $2^{21}\cdot|spacer|+|" "|$ */ -# define letter_token 0x1600000 /* $2^{21}\cdot|letter|$ */ -# define other_token 0x1800000 /* $2^{21}\cdot|other_char|$ */ -# define match_token 0x1A00000 /* $2^{21}\cdot|match|$ */ -# define end_match_token 0x1C00000 /* $2^{21}\cdot|end_match|$ */ -# define protected_token 0x1C00001 /* $2^{21}\cdot|end_match|+1$ */ - -# include "tex/stringpool.h" - -typedef struct smemory_word_ { -# ifdef WORDS_BIGENDIAN - halfword hhrh; - halfword hhlh; -# else - halfword hhlh; - halfword hhrh; -# endif -} smemory_word; - -# define fix_mem_init 10000 - -extern smemory_word *fixmem; -extern unsigned fix_mem_min; -extern unsigned fix_mem_max; - -extern halfword garbage; /* head of a junk list, write only */ -extern halfword temp_token_head; /* head of a temporary list of some kind */ -extern halfword hold_token_head; /* head of a temporary list of another kind */ -extern halfword omit_template; /* a constant token list */ -extern halfword null_list; /* permanently empty list */ -extern halfword backup_head; /* head of token list built by |scan_keyword| */ - -extern void initialize_tokens(void); - -extern int dyn_used; - -# define token_info(a) fixmem[(a)].hhlh -# define token_link(a) fixmem[(a)].hhrh -# define set_token_info(a,b) fixmem[(a)].hhlh=(b) -# define set_token_link(a,b) fixmem[(a)].hhrh=(b) - -extern halfword avail; /* head of the list of available one-word nodes */ -extern unsigned fix_mem_end; /* the last one-word node used in |mem| */ - -extern halfword get_avail(void); - -/* A one-word node is recycled by calling |free_avail|. -This routine is part of \TeX's ``inner loop,'' so we want it to be fast. -*/ - -# define free_avail(A) do { /* single-word node liberation */ \ - token_link(A)=avail; avail=(A); decr(dyn_used); \ - } while (0) - -/* -There's also a |fast_get_avail| routine, which saves the procedure-call -overhead at the expense of extra programming. This routine is used in -the places that would otherwise account for the most calls of |get_avail|. -*/ - -# define fast_get_avail(A) do { \ - (A)=avail; /* avoid |get_avail| if possible, to save time */ \ - if ((A)==null) { (A)=get_avail(); } \ - else { avail=token_link((A)); token_link((A))=null; incr(dyn_used); } \ - } while (0) - -extern void print_meaning(void); - -extern void flush_list(halfword p); -extern void show_token_list(int p, int q, int l); -extern void token_show(halfword p); - -# define token_ref_count(a) token_info((a)) /* reference count preceding a token list */ -# define set_token_ref_count(a,b) token_info((a))=b -# define add_token_ref(a) token_ref_count(a)++ /* new reference to a token list */ - -# define store_new_token(a) do { \ - q=get_avail(); token_link(p)=q; token_info(q)=(a); p=q; \ - } while (0) - -# define fast_store_new_token(a) do { \ - fast_get_avail(q); token_link(p)=q; token_info(q)=(a); p=q; \ - } while (0) - -extern void delete_token_ref(halfword p); - -extern void make_token_table(lua_State * L, int cmd, int chr, int cs); - -# define NO_CAT_TABLE -2 -# define DEFAULT_CAT_TABLE -1 - -extern void get_next(void); -extern void check_outer_validity(void); -extern boolean scan_keyword(const char *); -extern boolean scan_keyword_case_sensitive(const char *); -extern halfword active_to_cs(int, int); -extern void get_token_lua(void); -halfword string_to_toks(const char *); -extern int get_char_cat_code(int); - -/* -|no_expand_flag| is a special character value that is inserted by -|get_next| if it wants to suppress expansion. -*/ - -# define no_expand_flag special_char - -extern halfword par_loc; -extern halfword par_token; -extern boolean force_eof; -extern int luacstrings; - -extern void firm_up_the_line(void); -extern void get_token(void); - -extern halfword str_toks(lstring b); -extern halfword str_scan_toks(int c, lstring b); -extern void ins_the_toks(void); -extern void combine_the_toks(void); - -extern int scan_lua_state(void); - -extern void conv_toks(void); -extern str_number the_convert_string(halfword c, int i); -extern void do_variable(void); -extern void do_feedback(void); -extern void do_mathoption(void); - -extern halfword lua_str_toks(lstring b); -extern boolean in_lua_escape; - -# define closed 2 /* not open, or at end of file */ -# define just_open 1 /* newly opened, first line not yet read */ - -extern FILE *read_file[16]; /* used for \.{\\read} */ -extern int read_open[17]; /* state of |read_file[n]| */ - -extern void initialize_read(void); - -extern void read_toks(int n, halfword r, halfword j); - -extern str_number tokens_to_string(halfword p); /* return a string from tokens list */ - -extern char *tokenlist_to_xstring(int p, int inhibit_par, int *siz); -extern char *tokenlist_to_cstring(int p, int inhibit_par, int *siz); -extern lstring *tokenlist_to_lstring(int pp, int inhibit_par); -extern void free_lstring(lstring * ls); - -# define token_cmd(A) ((A) >> STRING_OFFSET_BITS) -# define token_chr(A) ((A) & (STRING_OFFSET - 1)) -# define token_val(A,B) (((A)<<STRING_OFFSET_BITS)+(B)) - -extern void l_set_token_data(void) ; - -#endif |