summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/luatexdir/tex
diff options
context:
space:
mode:
authorAkira Kakuto <kakuto@fuk.kindai.ac.jp>2015-12-16 14:50:11 +0000
committerAkira Kakuto <kakuto@fuk.kindai.ac.jp>2015-12-16 14:50:11 +0000
commit621273b5ef8cc9e83d9aca07bf012f727ba26f15 (patch)
tree0b5cb28eec37e3e0e93a09729cbc30834166a5f9 /Build/source/texk/web2c/luatexdir/tex
parentf04f01782aebac8cb2fcde278c02a4fb3be4bb12 (diff)
web2c/luatexdir: LuaTeX beta-0.86.0 (Sync with the upstream).
git-svn-id: svn://tug.org/texlive/trunk@39116 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/tex')
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/align.w16
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/buildpage.w35
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/commands.h34
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/commands.w19
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/conditional.h76
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/conditional.w556
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/directions.h74
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/directions.w59
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/dumpdata.w23
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/equivalents.h328
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/equivalents.w713
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/errors.h6
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/errors.w70
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/expand.h5
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/expand.w76
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/extensions.h8
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/extensions.w180
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/inputstack.h13
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/inputstack.w292
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/linebreak.h22
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/linebreak.w876
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/mainbody.h2
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/mainbody.w32
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/maincontrol.w1453
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/mathcodes.h28
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/mathcodes.w329
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/mlist.h4
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/mlist.w56
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/packaging.h141
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/packaging.w1577
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/printing.h6
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/printing.w633
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/scanning.h32
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/scanning.w349
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/texfileio.w4
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/texmath.w106
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/texnodes.h68
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/texnodes.w2382
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/textcodes.h29
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/textcodes.w445
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/textoken.h1
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/textoken.w2614
42 files changed, 7171 insertions, 6601 deletions
diff --git a/Build/source/texk/web2c/luatexdir/tex/align.w b/Build/source/texk/web2c/luatexdir/tex/align.w
index 75c3f932252..f1984a88c50 100644
--- a/Build/source/texk/web2c/luatexdir/tex/align.w
+++ b/Build/source/texk/web2c/luatexdir/tex/align.w
@@ -671,15 +671,15 @@ boolean fin_col(void)
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);
+ additional, align_set_group, -1, 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);
+ u = filtered_vpackage(vlink(cur_list.head_field),
+ 0, additional, 0, align_set_group, -1, 0);
w = height(u);
}
n = min_quarterword; /* this represents a span count of 1 */
@@ -772,7 +772,7 @@ void fin_row(void)
pointer p; /* the new unset box */
if (cur_list.mode_field == -hmode) {
p = filtered_hpack(cur_list.head_field, cur_list.tail_field, 0,
- additional, fin_row_group, -1);
+ additional, fin_row_group, -1, 0);
pop_nest();
if (cur_pre_head != cur_pre_tail)
append_list(cur_pre_head, cur_pre_tail);
@@ -780,8 +780,8 @@ void fin_row(void)
if (cur_head != cur_tail)
append_list(cur_head, cur_tail);
} else {
- p = filtered_vpackage(vlink(cur_list.head_field), 0, additional,
- max_depth, fin_row_group, -1);
+ p = filtered_vpackage(vlink(cur_list.head_field),
+ 0, additional, max_depth, fin_row_group, -1, 0);
pop_nest();
vlink(cur_list.tail_field) = p;
cur_list.tail_field = p;
@@ -932,8 +932,8 @@ value is changed to zero and so is the next tabskip.
width(q) = 0;
q = vlink(vlink(q));
} while (q != null);
- p = filtered_vpackage(preamble, saved_value(0), saved_level(0),
- max_depth, preamble_group, -1);
+ p = filtered_vpackage(preamble,
+ saved_value(0), saved_level(0), max_depth, preamble_group, -1, 0);
q = vlink(preamble);
do {
width(q) = height(q);
diff --git a/Build/source/texk/web2c/luatexdir/tex/buildpage.w b/Build/source/texk/web2c/luatexdir/tex/buildpage.w
index a1807b91993..409a10c33ba 100644
--- a/Build/source/texk/web2c/luatexdir/tex/buildpage.w
+++ b/Build/source/texk/web2c/luatexdir/tex/buildpage.w
@@ -19,7 +19,6 @@
@ @c
-
#include "ptexlib.h"
@ @c
@@ -32,7 +31,6 @@
#define vbadness int_par(vbadness_code)
#define max_dead_cycles int_par(max_dead_cycles_code)
#define output_box int_par(output_box_code)
-#define body_direction int_par(body_direction_code)
#define holding_inserts int_par(holding_inserts_code)
#define vsize dimen_par(vsize_code)
@@ -95,7 +93,6 @@ halfword best_page_break; /* break here to get the best page known so far
int least_page_cost; /* the score for this currently best page */
scaled best_size; /* its |page_goal| */
-
@ 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 |r@t$_1$@>=vlink(page_ins_head)|;
@@ -128,8 +125,6 @@ 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
@@ -195,13 +190,13 @@ scaled last_kern; /* used to implement \.{\\lastkern} */
int last_node_type; /* used to implement \.{\\lastnodetype} */
int insert_penalties; /* sum of the penalties for held-over insertions */
-#define print_plus(A,B) do { \
- if (page_so_far[(A)]!=0) { \
- tprint(" plus "); \
- print_scaled(page_so_far[(A)]); \
- tprint((B)); \
- } \
- } while (0)
+#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)
{
@@ -216,7 +211,6 @@ void print_totals(void)
}
}
-
@ Here is a procedure that is called when the |page_contents| is changing
from |empty| to |inserts_only| or |box_there|.
@@ -242,14 +236,12 @@ void freeze_page_specs(int s)
}
}
-
@ The global variable |output_active| is true during the time the
user's output routine is driving \TeX.
@c
boolean output_active; /* are we in the midst of an output routine? */
-
@ 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.)
@@ -268,7 +260,6 @@ void start_new_page(void)
page_max_depth = 0;
}
-
@ 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
@@ -286,7 +277,6 @@ static void box_error(int n)
box(n) = null;
}
-
@ The following procedure guarantees that a given box register
does not contain an \.{\\hbox}.
@@ -304,7 +294,6 @@ static void ensure_vbox(int n)
}
}
-
@ \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
@@ -317,10 +306,9 @@ void build_page(void)
halfword p; /* the node being appended */
halfword q, r; /* nodes being examined */
int b, c; /* badness and cost of current page */
- int pi; /* penalty to be added to the badness */
+ int pi = 0; /* penalty to be added to the badness */
int n; /* insertion box number */
scaled delta, h, w; /* sizes used for insertion calculations */
- pi = 0;
if ((vlink(contrib_head) == null) || output_active)
return;
do {
@@ -917,9 +905,8 @@ void fire_up(halfword c)
vbadness = inf_bad;
save_vfuzz = vfuzz;
vfuzz = max_dimen; /* inhibit error messages */
- box(output_box) =
- filtered_vpackage(vlink(page_head), best_size, exactly, page_max_depth,
- output_group, body_direction);
+ box(output_box) = filtered_vpackage(vlink(page_head),
+ best_size, exactly, page_max_depth, output_group, body_direction, 0);
vbadness = save_vbadness;
vfuzz = save_vfuzz;
if (last_glue != max_halfword)
@@ -993,7 +980,6 @@ void fire_up(halfword c)
box(output_box) = null;
}
-
@ When the user's output routine finishes, it has constructed a vlist
in internal vertical mode, and \TeX\ will do the following:
@@ -1045,5 +1031,4 @@ void resume_after_output(void)
pop_nest();
lua_node_filter_s(buildpage_filter_callback,lua_key_index(after_output));
build_page();
-
}
diff --git a/Build/source/texk/web2c/luatexdir/tex/commands.h b/Build/source/texk/web2c/luatexdir/tex/commands.h
index ef0e5d796df..d2a7779a0e1 100644
--- a/Build/source/texk/web2c/luatexdir/tex/commands.h
+++ b/Build/source/texk/web2c/luatexdir/tex/commands.h
@@ -207,6 +207,7 @@ typedef enum {
variable_cmd,
feedback_cmd,
the_cmd, /* expand an internal quantity ( \.{\\the} or \.{\\unexpanded}, \.{\\detokenize} ) */
+ combine_toks_cmd,
top_bot_mark_cmd, /* inserted mark ( \.{\\topmark}, etc.~) */
call_cmd, /* non-long, non-outer control sequence */
long_call_cmd, /* long, non-outer control sequence */
@@ -234,33 +235,34 @@ typedef enum {
typedef enum {
number_code = 0, /* command code for \.{\\number} */
- roman_numeral_code, /* command code for \.{\\romannumeral} */
+ lua_function_code, /* command code for \.{\\luafunction} */
+ lua_code, /* command code for \.{\\directlua} */
+ expanded_code, /* command code for \.{\\expanded} */
+ 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} */
- etex_code, /* command code for \.{\\eTeXVersion} */
- format_name_code, /* command code for \.{\\AlephVersion} */
- luatex_banner_code, /* command code for \.{\\luatexbanner}: */
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} */
- lua_code, /* command code for \.{\\directlua} */
- lua_escape_string_code, /* command code for \.{\\luaescapestring} */
+ 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} */
luatex_date_code, /* command code for \.{\\luatexdate} */
- math_style_code, /* command code for \.{\\mathstyle} */
- expanded_code, /* command code for \.{\\expanded} */
- job_name_code, /* command code for \.{\\jobname} */
+ etex_code, /* command code for \.{\\eTeXVersion} */
eTeX_revision_code, /* command code for \.{\\eTeXrevision} */
font_identifier_code, /* command code for \.{tex.fontidentifier} (virtual) */
- font_id_code, /* command code for \.{\\fontid} */
- uchar_code, /* command code for \.{\\Uchar} */
- lua_function_code, /* command code for \.{\\luafunction} */
- insert_ht_code, /* command code for \.{\\insertht} */
- math_char_class_code,
- math_char_fam_code,
- math_char_slot_code,
/* backend */
dvi_feedback_code,
pdf_feedback_code,
diff --git a/Build/source/texk/web2c/luatexdir/tex/commands.w b/Build/source/texk/web2c/luatexdir/tex/commands.w
index 8cd6128b54d..02c2e4a74ae 100644
--- a/Build/source/texk/web2c/luatexdir/tex/commands.w
+++ b/Build/source/texk/web2c/luatexdir/tex/commands.w
@@ -1,4 +1,4 @@
- % commands.w
+% commands.w
%
% Copyright 2009-2010 Taco Hoekwater <taco@@luatex.org>
%
@@ -123,6 +123,7 @@ void initialize_commands(void)
primitive_luatex("luastartup", assign_int_cmd, int_base + luastartup_id_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);
@@ -168,6 +169,8 @@ void initialize_commands(void)
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);
@@ -184,6 +187,7 @@ void initialize_commands(void)
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_vrule_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);
@@ -197,8 +201,6 @@ void initialize_commands(void)
primitive_luatex("Ustack", math_choice_cmd, 1, 0);
primitive_tex("multiply", multiply_cmd, 0, 0);
primitive_tex("noalign", no_align_cmd, 0, 0);
- primitive_luatex("nohrule", no_vrule_cmd, 0, 0);
- primitive_luatex("novrule", no_hrule_cmd, 0, 0);
primitive_tex("boundary", boundary_cmd, 0, 0);
primitive_tex("noboundary", no_boundary_cmd, 0, 0);
primitive_tex("noexpand", no_expand_cmd, 0, 0);
@@ -223,11 +225,16 @@ void initialize_commands(void)
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("tokspre", combine_toks_cmd, 1, 0);
+ primitive_luatex("etoksapp", combine_toks_cmd, 2, 0);
+ primitive_luatex("etokspre", combine_toks_cmd, 3, 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_hrule_cmd, 0, 0);
primitive_tex("par", par_end_cmd, too_big_char, too_big_char); /* cf.\ |scan_file_name| */
par_loc = cur_val;
par_token = cs_token_flag + par_loc;
@@ -297,6 +304,7 @@ void initialize_commands(void)
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_tex("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);
@@ -408,6 +416,9 @@ void initialize_commands(void)
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);
@@ -488,6 +499,7 @@ void initialize_commands(void)
primitive_tex("xdef", def_cmd, 3, 0);
primitive_tex("let", let_cmd, normal, 0);
primitive_tex("futurelet", let_cmd, normal + 1, 0);
+ primitive_luatex("letcharcode", let_cmd, normal + 2, 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);
@@ -637,6 +649,7 @@ void initialize_commands(void)
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);
diff --git a/Build/source/texk/web2c/luatexdir/tex/conditional.h b/Build/source/texk/web2c/luatexdir/tex/conditional.h
index 13e822a1bf9..b6abe7578d3 100644
--- a/Build/source/texk/web2c/luatexdir/tex/conditional.h
+++ b/Build/source/texk/web2c/luatexdir/tex/conditional.h
@@ -1,5 +1,5 @@
/* conditional.h
-
+
Copyright 2009 Taco Hoekwater <taco@luatex.org>
This file is part of LuaTeX.
@@ -15,61 +15,57 @@
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/>. */
-
+ 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}' */
- ifx_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_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} */
+ ifx_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_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, /* code for \.{\\if...} being evaluated */
- fi_code = 2, /* code for \.{\\fi} */
- else_code = 3, /* code for \.{\\else} */
- or_code = 4, /* code for \.{\\or} */
+ 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 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);
diff --git a/Build/source/texk/web2c/luatexdir/tex/conditional.w b/Build/source/texk/web2c/luatexdir/tex/conditional.w
index 53967087102..fa4e73b49cb 100644
--- a/Build/source/texk/web2c/luatexdir/tex/conditional.w
+++ b/Build/source/texk/web2c/luatexdir/tex/conditional.w
@@ -19,7 +19,6 @@
@ @c
-
#include "ptexlib.h"
@ @c
@@ -49,14 +48,12 @@ int if_limit; /* upper bound on |fi_or_else| codes */
int cur_if; /* type of conditional being worked on */
int if_line; /* line where that conditional began */
-
@ When we skip conditional text, we keep track of the line number
where skipping began, for use in error messages.
@c
int skip_line; /* skipping began here */
-
@ 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
@@ -66,14 +63,12 @@ procedure run faster).
@c
void pass_text(void)
{
- int l; /* level of $\.{\\if}\ldots\.{\\fi}$ nesting */
- int save_scanner_status; /* |scanner_status| upon entry */
- save_scanner_status = scanner_status;
+ int l = 0; /* level of $\.{\\if}\ldots\.{\\fi}$ nesting */
+ int save_scanner_status = scanner_status; /* |scanner_status| upon entry */
scanner_status = skipping;
- l = 0;
skip_line = line;
while (1) {
- get_next(); /* get_token_lua(); */
+ get_next();
if (cur_cmd == fi_or_else_cmd) {
if (l == 0)
break;
@@ -88,7 +83,6 @@ void pass_text(void)
show_cur_cmd_chr();
}
-
@ 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.
@@ -123,18 +117,17 @@ void pop_condition_stack(void)
flush_node(p);
}
-
@ Here's a procedure that changes the |if_limit| code corresponding to
a given value of |cond_ptr|.
@c
void change_if_limit(int l, halfword p)
{
- halfword q;
if (p == cond_ptr) {
- if_limit = l; /* that's the easy case */
+ /* that's the easy case */
+ if_limit = l;
} else {
- q = cond_ptr;
+ halfword q = cond_ptr;
while (1) {
if (q == null)
confusion("if");
@@ -147,21 +140,21 @@ void change_if_limit(int l, halfword p)
}
}
-
@ 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).
@c
+static halfword last_tested_cs ;
+
static boolean test_for_cs(void)
{
- boolean b; /*is the condition true? */
+ boolean b = false; /*is the condition true? */
int m, s; /*to be tested against the second operand */
- halfword n, p, q; /*for traversing token lists in \.{\\ifx} tests */
- n = get_avail();
- p = n; /*head of the list of characters */
- b = false;
+ halfword q; /*for traversing token lists in \.{\\ifx} tests */
+ halfword n = get_avail();
+ halfword p = n; /*head of the list of characters */
while (1) {
get_x_token();
if (cur_cs != 0)
@@ -169,6 +162,7 @@ static boolean test_for_cs(void)
store_new_token(cur_tok);
}
if (cur_cmd != end_cs_name_cmd) {
+ last_tested_cs = null_cs;
if (int_par(suppress_ifcsname_error_code)) {
do {
get_x_token();
@@ -201,41 +195,35 @@ static boolean test_for_cs(void)
} 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);
+ 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) {
- cur_cs = id_lookup(first, m - first); /*|no_new_control_sequence| is |true| */
+ cur_cs = id_lookup(first, m - first); /* |no_new_control_sequence| is |true| */
} else if (m == first) {
- cur_cs = null_cs; /*the list is empty */
+ cur_cs = null_cs; /* the list is empty */
}
b = (eq_type(cur_cs) != undefined_cs_cmd);
flush_list(n);
+ last_cs_name = cur_cs;
return b;
}
-
@ An active character will be treated as category 13 following
\.{\\if\\noexpand} or following \.{\\ifcat\\noexpand}.
@c
-#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)
-
-
-
-
+#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)
@ A condition is started when the |expand| procedure encounters
an |if_test| command; in that case |expand| reduces to |conditional|,
@@ -245,7 +233,7 @@ which is a recursive procedure.
@c
void conditional(void)
{
- boolean b; /*is the condition true? */
+ boolean b = false; /*is the condition true? */
int r; /*relation to be evaluated */
int m, n; /*to be tested against the second operand */
halfword p, q; /*for traversing token lists in \.{\\ifx} tests */
@@ -253,245 +241,271 @@ void conditional(void)
halfword save_cond_ptr; /*|cond_ptr| corresponding to this conditional */
int this_if; /*type of this conditional */
boolean is_unless; /*was this if preceded by `\.{\\unless}' ? */
- b = false; /*default is false, just in case */
- if (int_par(tracing_ifs_code) > 0)
- if (int_par(tracing_commands_code) <= 1)
- show_cur_cmd_chr();
+ if ((int_par(tracing_ifs_code) > 0) && (int_par(tracing_commands_code) <= 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;
/* Either process \.{\\ifcase} or set |b| to the value of a boolean condition */
switch (this_if) {
- case if_char_code:
- case if_cat_code:
- /* Test if two characters match */
- get_x_token_or_active_char();
- if ((cur_cmd > active_char_cmd) || (cur_chr > biggest_char)) { /*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:
- /* Test 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)
- if (this_if == if_abs_dim_code || this_if == if_abs_num_code)
+ case if_char_code:
+ case if_cat_code:
+ /* Test if two characters match */
+ get_x_token_or_active_char();
+ if ((cur_cmd > active_char_cmd) || (cur_chr > biggest_char)) {
+ /*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:
+ /* Test 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);
-
- /* Get the next non-blank non-call... */
- do {
- get_x_token();
- } while (cur_cmd == spacer_cmd);
-
- if ((cur_tok >= other_token + '<') && (cur_tok <= other_token + '>')) {
+ /* Get the next non-blank non-call... */
+ do {
+ get_x_token();
+ } while (cur_cmd == spacer_cmd);
+ /*
+ if ((cur_tok >= other_token + '<') && (cur_tok <= other_token + '>')) {
+ r = cur_tok - other_token;
+ } else {
+ */
r = cur_tok - other_token;
- } else {
- 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)
- if (this_if == if_abs_dim_code || this_if == if_abs_num_code)
+ 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);
+ switch (r) {
+ case '<':
+ b = (n < cur_val);
+ break;
+ case '=':
+ b = (n == cur_val);
+ break;
+ case '>':
+ b = (n > cur_val);
+ break;
+ default:
+ /* can't happen */
+ b = false;
+ break;
+ }
+ break;
+ case if_odd_code:
+ /* Test if an integer is odd */
+ scan_int();
+ b = odd(cur_val);
break;
- case '=':
- b = (n == cur_val);
+ case if_vmode_code:
+ b = (abs(cur_list.mode_field) == vmode);
break;
- case '>':
- b = (n > cur_val);
+ case if_hmode_code:
+ b = (abs(cur_list.mode_field) == hmode);
break;
- default:
- b = false;
- break; /*can't happen */
- }
- break;
- case if_odd_code:
- /* 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:
- case if_hbox_code:
- case if_vbox_code:
- /* Test box register status */
- scan_register_num();
- p = box(cur_val);
- if (this_if == if_void_code)
+ 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:
+ case if_hbox_code:
+ case if_vbox_code:
+ scan_register_num();
+ p = box(cur_val);
+ if (this_if == if_void_code)
+ b = (p == null);
+ else if (p == null)
+ b = false;
+ else if (this_if == if_hbox_code)
+ b = (type(p) == hlist_node);
+ else
+ b = (type(p) == vlist_node);
+ break;
+ */
+ case if_void_code:
+ scan_register_num();
+ p = box(cur_val);
b = (p == null);
- else if (p == null)
- b = false;
- else if (this_if == if_hbox_code)
- b = (type(p) == hlist_node);
- else
- b = (type(p) == vlist_node);
- break;
- case ifx_code:
- /* 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(); /* get_token_lua(); */
- n = cur_cs;
- p = cur_cmd;
- q = cur_chr;
- get_next(); /* get_token_lua(); */
- if (cur_cmd != p) {
- b = false;
- } else if (cur_cmd < call_cmd) {
- b = (cur_chr == q);
- } else {
- /* 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);
- q = token_link(equiv(n)); /*omit reference counts */
- if (p == q) {
- b = true;
+ 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 ifx_code:
+ /*
+ 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 {
- while ((p != null) && (q != null)) {
- if (token_info(p) != token_info(q)) {
- p = null;
- } else {
- p = token_link(p);
- q = token_link(q);
+ /*
+ 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);
+ /*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));
}
- 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:
- /* Select the appropriate case
- and |return| or |goto common_ending| */
- scan_int();
- n = cur_val; /*|n| is the number of cases to pass */
- if (int_par(tracing_commands_code) > 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();
+ 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:
+ /* Select the appropriate case and |return| or |goto common_ending| */
+ scan_int();
+ /* |n| is the number of cases to pass */
+ n = cur_val;
+ if (int_par(tracing_commands_code) > 1) {
+ begin_diagnostic();
+ tprint("{case ");
+ print_int(n);
+ print_char('}');
+ end_diagnostic(false);
}
- }
- change_if_limit(or_code, save_cond_ptr);
- return; /*wait for \.{\\or}, \.{\\else}, or \.{\\fi} */
- break;
- case if_primitive_code:
- save_scanner_status = scanner_status;
- scanner_status = normal;
- get_next(); /* get_token_lua(); */
- 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:
- /* 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(); /* get_token_lua(); */
- 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:
- /* 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: /* there are no other cases, but for -Wall: */
- b = 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);
+ /*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:
+ /*
+ 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:
+ /*
+ 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:
+ /* there are no other cases, but for -Wall: */
+ b = false;
}
-
if (is_unless)
b = !b;
if (int_par(tracing_commands_code) > 1) {
@@ -505,14 +519,16 @@ void conditional(void)
}
if (b) {
change_if_limit(else_code, save_cond_ptr);
- return; /*wait for \.{\\else} or \.{\\fi} */
+ /*wait for \.{\\else} or \.{\\fi} */
+ return;
}
- /* 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.
+ 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();
@@ -527,8 +543,10 @@ void conditional(void)
}
}
COMMON_ENDING:
- if (cur_chr == fi_code)
+ if (cur_chr == fi_code) {
pop_condition_stack();
- else
- if_limit = fi_code; /*wait for \.{\\fi} */
+ } else {
+ /*wait for \.{\\fi} */
+ if_limit = fi_code;
+ }
}
diff --git a/Build/source/texk/web2c/luatexdir/tex/directions.h b/Build/source/texk/web2c/luatexdir/tex/directions.h
index 34a89cc29a2..e4cea9014dd 100644
--- a/Build/source/texk/web2c/luatexdir/tex/directions.h
+++ b/Build/source/texk/web2c/luatexdir/tex/directions.h
@@ -31,7 +31,7 @@
*/
# define dir_TLT 0 /* maybe use this one as unset value */
-# define dir_TRT 1 /* or swhould we avoid that one because it's a signal too */
+# define dir_TRT 1 /* or should we avoid that one because it's a signal too */
# define dir_LTL 2
# define dir_RTT 3
@@ -56,14 +56,52 @@ extern int dir_swap;
# 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) */
+
+# define dir_TLT_or_TRT(a) (a < 2)
+# define dir_LTL_or_RTT(a) (a > 1)
+
# 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)) \
+ (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) ( \
- ((a == dir_TLT || a == dir_TRT) && (b == dir_TLT || b == dir_TRT)) || \
- ((a == dir_LTL || a == dir_RTT) && (b == dir_LTL || b == dir_RTT)) \
+ (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) ( \
@@ -79,7 +117,7 @@ extern int dir_swap;
# define glyphdir_opposite(a,b) 0
# define pardir_eq(a,b) ( \
- ((a == dir_TLT || a == dir_TRT) && (b == dir_TLT || b == dir_TRT)) || \
+ (dir_TLT_or_TRT(a) && dir_TLT_or_TRT(b)) || \
(a == dir_LTL && b == dir_LTL) || \
(a == dir_RTT && b == dir_RTT) \
)
@@ -87,8 +125,8 @@ extern int dir_swap;
# 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) \
+ (a == dir_LTL && dir_LTL_or_RTT(b)) || \
+ (a == dir_RTT && dir_LTL_or_RTT(b)) \
)
# define glyphdir_eq(a,b) ( \
@@ -97,7 +135,7 @@ extern int dir_swap;
)
# define partextdir_eq(a,b) ( \
- ((a == dir_TLT || a == dir_TRT)&&(b == dir_LTL || b == dir_RTT)) || \
+ (dir_TLT_or_TRT(a) && dir_LTL_or_RTT(b)) || \
(a == dir_LTL && b == dir_TLT) || \
(a == dir_RTT && b == dir_TRT) \
)
@@ -106,21 +144,21 @@ extern int dir_swap;
# define textdir_is_L(a) (a == dir_TLT)
-# define push_dir(a,b) { \
+# define push_dir(p,a) { \
halfword dir_tmp=new_dir((a)); \
- vlink(dir_tmp)=b; \
- b=dir_tmp; \
+ vlink(dir_tmp)=p; \
+ p=dir_tmp; \
}
-# define push_dir_node(a,b) { \
+# define push_dir_node(p,a) { \
halfword dir_tmp=copy_node((a)); \
- vlink(dir_tmp)=b; \
- b=dir_tmp; \
+ vlink(dir_tmp)=p; \
+ p=dir_tmp; \
}
-# define pop_dir_node(b) { \
- halfword dir_tmp=b; \
- b=vlink(dir_tmp); \
+# define pop_dir_node(p) { \
+ halfword dir_tmp=p; \
+ p=vlink(dir_tmp); \
flush_node(dir_tmp); \
}
diff --git a/Build/source/texk/web2c/luatexdir/tex/directions.w b/Build/source/texk/web2c/luatexdir/tex/directions.w
index addde937df7..b010eb4a9cc 100644
--- a/Build/source/texk/web2c/luatexdir/tex/directions.w
+++ b/Build/source/texk/web2c/luatexdir/tex/directions.w
@@ -19,7 +19,6 @@
@ @c
-
#include "ptexlib.h"
@ @c
@@ -59,8 +58,7 @@ void scan_direction(void)
@c
halfword do_push_dir_node(halfword p, halfword a)
{
- halfword n;
- n = copy_node(a);
+ halfword n = copy_node(a);
vlink(n) = p;
return n;
}
@@ -86,8 +84,7 @@ void initialize_directions(void)
@ @c
halfword new_dir(int s)
{
- halfword p; /* the new node */
- p = new_node(dir_node, 0);
+ halfword p = new_node(dir_node, 0);
dir_dir(p) = s;
dir_dvi_ptr(p) = -1;
dir_level(p) = cur_level;
@@ -150,10 +147,10 @@ scaled pack_width(int curdir, int pdir, halfword p, boolean 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);
+ /* 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);
}
@@ -178,22 +175,20 @@ scaled_whd pack_width_height_depth(int curdir, int pdir, halfword p,
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 (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);
- }
+ 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)) {
@@ -201,16 +196,14 @@ scaled_whd pack_width_height_depth(int curdir, int pdir, halfword p,
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);
- }
+ } 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;
}
diff --git a/Build/source/texk/web2c/luatexdir/tex/dumpdata.w b/Build/source/texk/web2c/luatexdir/tex/dumpdata.w
index 727951b9f32..ea882a74040 100644
--- a/Build/source/texk/web2c/luatexdir/tex/dumpdata.w
+++ b/Build/source/texk/web2c/luatexdir/tex/dumpdata.w
@@ -26,8 +26,9 @@
#define prev_depth cur_list.prev_depth_field
/* 907 = sum of the values of the bytes of "don knuth" */
-/* The next FORMAT_ID will be 907+7 */
-#define FORMAT_ID (907+6)
+/* The next FORMAT_ID will be 907+10 */
+
+#define FORMAT_ID (907+10)
#if ((FORMAT_ID>=0) && (FORMAT_ID<=256))
#error Wrong value for FORMAT_ID.
#endif
@@ -47,8 +48,8 @@ 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
+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.
@c
@@ -81,7 +82,7 @@ void store_fmt_file(void)
succumb();
}
- /* Create the |format_ident|, open the format file, and inform the user
+ /* 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) {
@@ -121,7 +122,7 @@ void store_fmt_file(void)
dump/undump macros. */
dump_int(0x57325458); /* Web2C \TeX's magic constant: "W2TX" */
- dump_int(FORMAT_ID);
+ dump_int(FORMAT_ID);
/* Align engine to 4 bytes with one or more trailing NUL */
x = (int) strlen(engine_name);
@@ -150,7 +151,7 @@ void store_fmt_file(void)
/* 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.
+ 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.
@@ -301,9 +302,6 @@ void store_fmt_file(void)
/* Dump the hyphenation tables */
dump_language_data();
- /* Dump pdftex data */
- dump_pdftex_data(static_pdf);
-
/* Dump a couple more things and the closing check word */
dump_int(interaction);
dump_int(format_ident);
@@ -387,7 +385,7 @@ boolean load_fmt_file(const char *fmtname)
format_debug("engine name size", x);
if ((x < 0) || (x > 256))
goto BAD_FMT; /* corrupted format file */
-
+
format_engine = xmalloc((unsigned) x);
undump_things(format_engine[0], x);
format_engine[x - 1] = 0; /* force string termination, just in case */
@@ -510,9 +508,6 @@ boolean load_fmt_file(const char *fmtname)
/* Undump the hyphenation tables */
undump_language_data();
- /* Undump pdftex data */
- undump_pdftex_data(static_pdf);
-
/* Undump a couple more things and the closing check word */
undump(batch_mode, error_stop_mode, interaction);
if (interactionoption != unspecified_mode)
diff --git a/Build/source/texk/web2c/luatexdir/tex/equivalents.h b/Build/source/texk/web2c/luatexdir/tex/equivalents.h
index 8a7debe8345..9f604ab8be6 100644
--- a/Build/source/texk/web2c/luatexdir/tex/equivalents.h
+++ b/Build/source/texk/web2c/luatexdir/tex/equivalents.h
@@ -15,104 +15,97 @@
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/>. */
-
+ 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.
+
+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 /* the largest allowed character number; must be |< max_halfword| */
-# define too_big_char 1114112 /* |biggest_char+1| */
-# define special_char 1114113 /* |biggest_char+2| */
-# define number_chars 1114112 /* |biggest_char+1| */
+# 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 /* the largest allowed character number; must be |< max_halfword| */
+# define too_big_char 1114112 /* |biggest_char+1| */
+# define special_char 1114113 /* |biggest_char+2| */
+# define number_chars 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 */
+# 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.
-*/
+\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.
-/*
-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.
+@ 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} */
@@ -258,45 +251,46 @@ here, and the |number_regs| \.{\\dimen} registers.
# define luastartup_id_code 60
# define disable_lig_code 61
# define disable_kern_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 synctex_code 90 /* is synctex file generation enabled ? */
-
-# define math_no_italic_compensation_code 91 /* just for tracing, can change */
-# define math_no_char_italic_code 92 /* just for tracing, can change */
-# define math_use_old_fraction_scaling_code 93 /* just for tracing, can change */
-# define math_old_code 94 /* this one is stable */
-# define math_option_code 95
-
-# define backend_int_base (int_base+96)
-# define backend_int_last (int_base+115)
-
-# define tex_int_pars (116) /* total number of integer parameters */
+# define disable_space_code 63
+# define cat_code_table_code 64
+# define output_box_code 65
+# define cur_lang_code 66 /* current language id */
+# define ex_hyphen_char_code 67
+# define hyphenation_min_code 68 /* minimum word length */
+# define adjust_spacing_code 69 /* level of spacing adjusting */
+# define protrude_chars_code 70 /* protrude chars at left/right edge of paragraphs */
+# define output_mode_code 71 /* switch on PDF output if positive */
+# define draft_mode_code 72
+# define tracing_fonts_code 73
+# define tracing_assigns_code 74 /* show assignments */
+# define tracing_groups_code 75 /* show save/restore groups */
+# define tracing_ifs_code 76 /* show conditionals */
+# define tracing_scan_tokens_code 77 /* show pseudo file open and close */
+# define tracing_nesting_code 78 /* show incomplete groups and ifs within files */
+# define pre_display_direction_code 79 /* text direction preceding a display */
+# define last_line_fit_code 80 /* adjustment for last line of paragraph */
+# define saving_vdiscards_code 81 /* save items discarded from vlists */
+# define saving_hyph_codes_code 82 /* save hyphenation codes for languages */
+# define suppress_fontnotfound_error_code 83 /* suppress errors for missing fonts */
+# define suppress_long_error_code 84 /* suppress errors for missing fonts */
+# define suppress_ifcsname_error_code 85 /* suppress errors for failed \.{\\ifcsname} */
+# define suppress_outer_error_code 86 /* suppress errors for \.{\\outer} */
+# define suppress_mathpar_error_code 87 /* suppress errors for \.{\\par}} in math */
+# define math_eqno_gap_step_code 88 /* factor/1000 used for distance between eq and eqno */
+# define math_display_skip_mode_code 89
+# define math_scripts_mode_code 90
+# define synctex_code 91 /* is synctex file generation enabled ? */
+
+# define math_no_italic_compensation_code 92 /* just for tracing, can change */
+# define math_no_char_italic_code 93 /* just for tracing, can change */
+# define math_use_old_fraction_scaling_code 94 /* just for tracing, can change */
+# define math_old_code 95 /* this one is stable */
+# define math_option_code 96
+
+# define backend_int_base (int_base+97)
+# define backend_int_last (int_base+116)
+
+# define tex_int_pars (117) /* total number of integer parameters */
# define page_direction_code (tex_int_pars)
# define body_direction_code (tex_int_pars+1)
@@ -339,7 +333,7 @@ here, and the |number_regs| \.{\\dimen} registers.
# 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 */ /* total number of dimension parameters */
+# define page_height_code 27 /* page height of the output */
# define backend_dimen_base (dimen_base+28)
# define backend_dimen_last (dimen_base+37)
@@ -387,8 +381,10 @@ extern int cur_boundary; /* where
# 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.
+
+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_
@@ -418,58 +414,59 @@ appears in location |save_ptr+k| of the save stack.
# define saved_boxspec 14
# define saved_boxdir 15
# define saved_boxattr 16
-# define saved_eqtb 17
+# define saved_boxpack 18
+# define saved_eqtb 19
extern void print_save_stack(void);
-# define assign_trace(A,B) if (int_par(tracing_assigns_code)>0) restore_trace((A),(B))
-
# 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))
-extern int mag_set; /* if nonzero, this magnification should be used henceforth */
+/* 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}.
+@ 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 */
+ 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;
# define max_group_code local_box_group /* which is wrong, but is what the web says */
@@ -490,7 +487,6 @@ extern void geq_define(halfword p, quarterword t, halfword e); /* global |eq_de
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 restore_trace(halfword p, const char *s); /* |eqtb[p]| has just been restored or retained */
extern void show_save_groups(void);
# define level_zero 0 /* level for undefined quantities */
@@ -498,10 +494,20 @@ extern void show_save_groups(void);
extern void show_eqtb(halfword n);
+/* \csname \ifcsname */
+
+extern halfword last_cs_name;
+
/* more will move here */
#define space_skip glue_par(space_skip_code)
#define xspace_skip glue_par(xspace_skip_code)
#define math_skip glue_par(math_skip_code)
+#define body_direction int_par(body_direction_code)
+#define page_direction int_par(page_direction_code)
+#define par_direction int_par(par_direction_code)
+#define text_direction int_par(text_direction_code)
+#define math_direction int_par(math_direction_code)
+
#endif
diff --git a/Build/source/texk/web2c/luatexdir/tex/equivalents.w b/Build/source/texk/web2c/luatexdir/tex/equivalents.w
index 5fe8b4ec500..d88b7322a76 100644
--- a/Build/source/texk/web2c/luatexdir/tex/equivalents.w
+++ b/Build/source/texk/web2c/luatexdir/tex/equivalents.w
@@ -19,9 +19,23 @@
@ @c
-
#include "ptexlib.h"
+halfword last_cs_name = null_cs;
+
+/* |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);
+}
+
@ @c
#define par_shape_ptr equiv(par_shape_loc)
@@ -85,7 +99,6 @@ void initialize_equivalents(void)
xeq_level[k] = level_one;
}
-
@ 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|
@@ -105,9 +118,9 @@ interpreted in one of four ways:
|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
+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)|).
+then the level is part of |save_word(p-1)|).
\yskip\hang 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
@@ -125,7 +138,6 @@ 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:
@@ -141,7 +153,8 @@ an explicit |save_type|, and they are:
|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_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
@@ -151,12 +164,11 @@ in the |save_stack| or in |eqtb| ever has a level greater than |cur_level|.
@c
save_record *save_stack;
-int save_ptr; /* first unused entry on |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 */
-
+int save_ptr; /* first unused entry on |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 */
@ 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.
@@ -170,14 +182,13 @@ entries on |save_stack|. By making a conservative test like this, we can
get by with testing for overflow in only a few places.
@c
-#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)
-
+#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)
@ Procedure |new_save_level| is called when a group begins. The
argument is a group identification code like `|hbox_group|'. After
@@ -193,7 +204,7 @@ called.
@c
void new_save_level(group_code c)
-{ /* begin a new level of grouping */
+{ /* begin a new level of grouping */
check_full_save_stack();
set_saved_record(0, saved_line, 0, line);
incr(save_ptr);
@@ -216,27 +227,26 @@ static const char *save_stack_type(int v)
{
const char *s = "";
switch (save_type(v)) {
-/* *INDENT-OFF* */
- 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_eqtb: s = "saved_eqtb"; break;
- default: break;
-/* *INDENT-ON* */
+ 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_eqtb: s = "saved_eqtb"; break;
+ default: break;
}
return s;
}
@@ -258,106 +268,105 @@ void print_save_stack(void)
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(eq_level_field(save_word(i-1)));| */
- 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(", ");
- print_int(save_level(i)); /* vadjust vs vadjust pre */
- break;
- case saved_insert:
- tprint(", ");
- print_int(save_value(i)); /* insert number */
- break;
- case saved_boxtype: /* \.{\\localleftbox} vs \.{\\localrightbox} */
- tprint(", ");
- print_int(save_value(i));
- break;
- case saved_eqno: /* \.{\\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(dir_dir(save_value(i)));
- break;
- case saved_boxattr:
- tprint(", ");
- print_int(save_value(i));
- break;
- case saved_line:
- case saved_eqtb:
- break;
- default:
- break;
+ 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(eq_level_field(save_word(i-1)));| */
+ 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(", ");
+ print_int(save_level(i)); /* vadjust vs vadjust pre */
+ break;
+ case saved_insert:
+ tprint(", ");
+ print_int(save_value(i)); /* insert number */
+ break;
+ case saved_boxtype: /* \.{\\localleftbox} vs \.{\\localrightbox} */
+ tprint(", ");
+ print_int(save_value(i));
+ break;
+ case saved_eqno: /* \.{\\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(dir_dir(save_value(i)));
+ break;
+ case saved_boxattr:
+ case saved_boxpack:
+ tprint(", ");
+ print_int(save_value(i));
+ break;
+ case saved_line:
+ case saved_eqtb:
+ break;
+ default:
+ break;
}
print_ln();
}
end_diagnostic(true);
}
-
@ 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.
@@ -365,26 +374,17 @@ void print_save_stack(void)
@c
void show_save_groups(void)
{
- int p; /* index into |nest| */
+ int p = nest_ptr; /* index into |nest| */
int m; /* mode */
- save_pointer v; /* saved value of |save_ptr| */
- quarterword l; /* saved value of |cur_level| */
- group_code c; /* saved value of |cur_group| */
- int a; /* to keep track of alignments */
+ save_pointer v = save_ptr; /* saved value of |save_ptr| */
+ quarterword l = cur_level; /* saved value of |cur_level| */
+ group_code c = cur_group; /* saved value of |cur_group| */
+ int a = 1; /* to keep track of alignments */
int i;
quarterword j;
- const char *s;
-#ifdef DEBUG
- print_save_stack();
-#endif
- p = nest_ptr;
- v = save_ptr;
- l = cur_level;
- c = cur_group;
+ const char *s = NULL;
save_ptr = cur_boundary;
decr(cur_level);
- a = 1;
- s = NULL;
tprint_nl("");
print_ln();
while (1) {
@@ -401,106 +401,106 @@ void show_save_groups(void)
} 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;
+ 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++)
+ if (i <= saved_value(-3)) /* different offset because |-2==saved_textdir| */
+ 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;
- } else {
- if (a == 1)
- tprint("align entry");
- else
- tprint_esc("cr");
- if (p >= a)
- p = p - a;
- a = 0;
+ break;
+ case semi_simple_group:
+ incr(p);
+ tprint_esc("begingroup");
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++)
- if (i <= saved_value(-3)) /* different offset because |-2==saved_textdir| */
- 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) {
+ 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('$');
- } 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;
+ 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;
}
/* Show the box context */
i = saved_value(-5);
@@ -560,8 +560,6 @@ void show_save_groups(void)
cur_group = c;
}
-
-
@ 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
@@ -573,29 +571,28 @@ void eq_destroy(memory_word w)
{ /* gets ready to forget |w| */
halfword q; /* |equiv| field of |w| */
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:
- delete_glue_ref(equiv_field(w));
- break;
- case shape_ref_cmd:
- q = equiv_field(w); /* we need to free a \.{\\parshape} block */
- if (q != null)
- flush_node(q);
- break; /* such a block is |2n+1| words long, where |n=vinfo(q)| */
- case box_ref_cmd:
- flush_node_list(equiv_field(w));
- break;
- default:
- break;
+ 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:
+ delete_glue_ref(equiv_field(w));
+ break;
+ case shape_ref_cmd:
+ q = equiv_field(w); /* we need to free a \.{\\parshape} block */
+ if (q != null)
+ flush_node(q);
+ break; /* such a block is |2n+1| words long, where |n=vinfo(q)| */
+ case box_ref_cmd:
+ flush_node_list(equiv_field(w));
+ break;
+ default:
+ break;
}
}
-
@ To save a value of |eqtb[p]| that was established at level |l|, we
can use the following subroutine.
@@ -616,7 +613,6 @@ void eq_save(halfword p, quarterword l)
incr(save_ptr);
}
-
@ 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|,
@@ -625,15 +621,19 @@ 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.
+@ new data for |eqtb|
@c
void eq_define(halfword p, quarterword t, halfword e)
-{ /* new data for |eqtb| */
+{
+ boolean trace = int_par(tracing_assigns_code) > 0;
if ((eq_type(p) == t) && (equiv(p) == e)) {
- assign_trace(p, "reassigning");
+ if (trace)
+ diagnostic_trace(p, "reassigning");
eq_destroy(eqtb[p]);
return;
}
- assign_trace(p, "changing");
+ if (trace)
+ diagnostic_trace(p, "changing");
if (eq_level(p) == cur_level)
eq_destroy(eqtb[p]);
else if (cur_level > level_one)
@@ -641,10 +641,10 @@ void eq_define(halfword p, quarterword t, halfword e)
set_eq_level(p, cur_level);
set_eq_type(p, t);
set_equiv(p, e);
- assign_trace(p, "into");
+ if (trace)
+ diagnostic_trace(p, "into");
}
-
@ 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.
@@ -652,17 +652,21 @@ void eq_define(halfword p, quarterword t, halfword e)
@c
void eq_word_define(halfword p, int w)
{
+ boolean trace = int_par(tracing_assigns_code) > 0;
if (eqtb[p].cint == w) {
- assign_trace(p, "reassigning");
+ if (trace)
+ diagnostic_trace(p, "reassigning");
return;
}
- assign_trace(p, "changing");
+ 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;
- assign_trace(p, "into");
+ if (trace)
+ diagnostic_trace(p, "into");
}
@@ -674,24 +678,29 @@ to save old values, and the new value is associated with |level_one|.
@c
void geq_define(halfword p, quarterword t, halfword e)
{ /* global |eq_define| */
- assign_trace(p, "globally changing");
+ boolean trace = int_par(tracing_assigns_code) > 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);
- assign_trace(p, "into");
+ if (trace)
+ diagnostic_trace(p, "into");
}
void geq_word_define(halfword p, int w)
{ /* global |eq_word_define| */
- assign_trace(p, "globally changing");
+ boolean trace = int_par(tracing_assigns_code) > 0;
+ if (trace)
+ diagnostic_trace(p, "globally changing");
eqtb[p].cint = w;
xeq_level[p] = level_one;
- assign_trace(p, "into");
+ if (trace)
+ diagnostic_trace(p, "into");
}
-
-@ Subroutine |save_for_after| puts a token on the stack for save-keeping.
+@ Subroutine |save_for_after| puts a token on the stack for save-keeping.
@c
void save_for_after(halfword t)
@@ -705,7 +714,6 @@ void save_for_after(halfword t)
}
}
-
@ 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.
@@ -714,15 +722,14 @@ belonging to the topmost group is cleared off of the save stack.
void unsave(void)
{ /* pops the top level off the save stack */
halfword p; /* position to be restored */
- quarterword l; /* saved level, if in fullword regions of |eqtb| */
- boolean a; /* have we already processed an \.{\\aftergroup} ? */
- a = false;
- l = level_one; /* just in case */
+ quarterword l = level_one; /* saved level, if in fullword regions of |eqtb| */
+ boolean a = false; /* have we already processed an \.{\\aftergroup} ? */
unsave_math_codes(cur_level);
unsave_cat_codes(int_par(cat_code_table_code), cur_level);
unsave_text_codes(cur_level);
unsave_math_data(cur_level);
if (cur_level > level_one) {
+ boolean trace = int_par(tracing_restores_code) > 0;
decr(cur_level);
/* Clear off top level from |save_stack| */
while (true) {
@@ -731,7 +738,8 @@ void unsave(void)
break;
p = save_value(save_ptr);
if (save_type(save_ptr) == insert_token) {
- a = reinsert_token(a, p);
+ reinsert_token(a, p);
+ a = true; /* always ... always etex now */
} else {
if (save_type(save_ptr) == restore_old_value) {
l = save_level(save_ptr);
@@ -749,24 +757,23 @@ void unsave(void)
if (p < int_base || p > eqtb_size) {
if (eq_level(p) == level_one) {
eq_destroy(save_word(save_ptr)); /* destroy the saved value */
- if (int_par(tracing_restores_code) > 0)
- restore_trace(p, "retaining");
+ if (trace)
+ diagnostic_trace(p, "retaining");
} else {
eq_destroy(eqtb[p]); /* destroy the current value */
eqtb[p] = save_word(save_ptr); /* restore the saved value */
- if (int_par(tracing_restores_code) > 0)
- restore_trace(p, "restoring");
+ if (trace)
+ diagnostic_trace(p, "restoring");
}
} else if (xeq_level[p] != level_one) {
eqtb[p] = save_word(save_ptr);
xeq_level[p] = l;
- if (int_par(tracing_restores_code) > 0)
- restore_trace(p, "restoring");
+ if (trace)
+ diagnostic_trace(p, "restoring");
} else {
- if (int_par(tracing_restores_code) > 0)
- restore_trace(p, "retaining");
+ if (trace)
+ diagnostic_trace(p, "retaining");
}
-
}
}
if (int_par(tracing_groups_code) > 0)
@@ -776,26 +783,12 @@ void unsave(void)
cur_group = save_level(save_ptr);
cur_boundary = save_value(save_ptr);
decr(save_ptr);
-
} else {
confusion("curlevel"); /* |unsave| is not used when |cur_group=bottom_level| */
}
attr_list_cache = cache_disabled;
}
-@ @c
-void restore_trace(halfword p, const char *s)
-{ /* |eqtb[p]| has just been restored or retained */
- begin_diagnostic();
- print_char('{');
- tprint(s);
- print_char(' ');
- show_eqtb(p);
- print_char('}');
- end_diagnostic(false);
-}
-
-
@ 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
@@ -803,8 +796,7 @@ entire run. The global variable |mag_set| is set to the current magnification
whenever it becomes necessary to ``freeze'' it at a particular value.
@c
-int mag_set; /* if nonzero, this magnification should be used henceforth */
-
+int mag_set; /* if nonzero, this magnification should be used henceforth */
@ The |prepare_mag| subroutine is called whenever \TeX\ wants to use |mag|
for magnification.
@@ -839,7 +831,6 @@ void prepare_mag(void)
mag_set = mag;
}
-
@ 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
@@ -892,7 +883,7 @@ halfword cur_chr; /* operand of current command */
halfword cur_cs; /* control sequence found here, zero if none found */
halfword cur_tok; /* packed representative of |cur_cmd| and |cur_chr| */
-@ Here is a procedure that displays the current command.
+@ Here is a procedure that displays the current command.
@c
#define mode cur_list.mode_field
@@ -939,20 +930,22 @@ void show_cur_cmd_chr(void)
end_diagnostic(false);
}
-
-@ Here is a procedure that displays the contents of |eqtb[n]|
- symbolically.
+@ Here is a procedure that displays the contents of |eqtb[n]| symbolically.
@c
void show_eqtb(halfword n)
{
if (n < null_cs) {
- print_char('?'); /* this can't happen */
+ /* this can't happen */
+ print_char('?');
} else if ((n < glue_base) || ((n > eqtb_size) && (n <= eqtb_top))) {
- /* Show equivalent |n|, in region 1 or 2 */
- /* 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.) */
+ /*
+ Show equivalent |n|, in region 1 or 2
+
+ 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);
print_char('=');
@@ -962,8 +955,11 @@ void show_eqtb(halfword n)
show_token_list(token_link(equiv(n)), null, 32);
}
} else if (n < local_base) {
- /* Show equivalent |n|, in region 3 */
- /* All glue parameters and registers are initially `\.{0pt plus0pt minus0pt}'. */
+ /*
+ 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);
@@ -987,16 +983,19 @@ void show_eqtb(halfword n)
}
} else if (n < int_base) {
- /* 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. */
+ /*
+ 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);
@@ -1042,7 +1041,6 @@ void show_eqtb(halfword n)
print_char('=');
print_esc(hash[font_id_base + equiv(n)].rh); /* that's |font_id_text(equiv(n))| */
}
-
} else if (n < dimen_base) {
/* Show equivalent |n|, in region 5 */
if (n < dir_base) {
@@ -1064,7 +1062,6 @@ void show_eqtb(halfword n)
print_char('=');
print_int(eqtb[n].cint);
}
-
} else if (n <= eqtb_size) {
/* Show equivalent |n|, in region 6 */
if (n < scaled_base) {
@@ -1076,9 +1073,9 @@ void show_eqtb(halfword n)
print_char('=');
print_scaled(eqtb[n].cint);
tprint("pt");
-
} else {
- print_char('?'); /* this can't happen either */
+ /* this can't happen either */
+ print_char('?');
}
}
@@ -1086,17 +1083,23 @@ void show_eqtb(halfword n)
void show_eqtb_meaning(halfword n)
{
if (n < null_cs) {
- print_char('?'); /* this can't happen */
+ /* this can't happen */
+ print_char('?');
} else if ((n < glue_base) || ((n > eqtb_size) && (n <= eqtb_top))) {
- /* Show equivalent |n|, in region 1 or 2 */
- /* 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.) */
+ /*
+ Show equivalent |n|, in region 1 or 2
+ 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}'. */
+ /*
+ 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);
@@ -1111,16 +1114,19 @@ void show_eqtb_meaning(halfword n)
}
} else if (n < int_base) {
- /* 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. */
+ /*
+ 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);
@@ -1138,7 +1144,6 @@ void show_eqtb_meaning(halfword n)
/* Show the font identifier in |eqtb[n]| */
tprint("current font");
}
-
} else if (n < dimen_base) {
/* Show equivalent |n|, in region 5 */
if (n < dir_base) {
@@ -1152,7 +1157,6 @@ void show_eqtb_meaning(halfword n)
tprint_esc("attribute");
print_int(n - attribute_base);
}
-
} else if (n <= eqtb_size) {
/* Show equivalent |n|, in region 6 */
if (n < scaled_base) {
@@ -1162,6 +1166,7 @@ void show_eqtb_meaning(halfword n)
print_int(n - scaled_base);
}
} else {
- print_char('?'); /* this can't happen either */
+ /* this can't happen either */
+ print_char('?');
}
}
diff --git a/Build/source/texk/web2c/luatexdir/tex/errors.h b/Build/source/texk/web2c/luatexdir/tex/errors.h
index 101e78adb71..3eae1c8a927 100644
--- a/Build/source/texk/web2c/luatexdir/tex/errors.h
+++ b/Build/source/texk/web2c/luatexdir/tex/errors.h
@@ -99,7 +99,9 @@ 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, boolean pr, boolean ap);
+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);
@@ -107,4 +109,6 @@ 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/errors.w b/Build/source/texk/web2c/luatexdir/tex/errors.w
index e11fcd908fe..227095d3f09 100644
--- a/Build/source/texk/web2c/luatexdir/tex/errors.w
+++ b/Build/source/texk/web2c/luatexdir/tex/errors.w
@@ -659,10 +659,41 @@ void char_warning(internal_font_number f, int c)
}
@ @c
+
+void wrapup_backend(void) {
+ ensure_output_state(static_pdf, ST_OMODE_FIX);
+ switch (output_mode_used) {
+ case OMODE_NONE:
+ print_err(" ==> Fatal error occurred, no FMT file produced!");
+ break;
+ case OMODE_PDF:
+ if (history == fatal_error_stop) {
+ remove_pdffile(static_pdf); /* will become remove_output_file */
+ print_err(" ==> Fatal error occurred, no output PDF file produced!");
+ } else {
+ finish_pdf_file(static_pdf, luatex_version, get_luatexrevision());
+ }
+ break;
+ case OMODE_DVI:
+ if (history == fatal_error_stop) {
+ print_err(" ==> Fatal error occurred, bad output DVI file produced!");
+ finish_dvi_file(static_pdf, luatex_version, get_luatexrevision());
+ } else {
+ finish_dvi_file(static_pdf, luatex_version, get_luatexrevision());
+ }
+ break;
+ }
+}
+
void normal_error(const char *t, const char *p)
{
normalize_selector();
print_err("error ");
+ if (cur_file_name) {
+ tprint(" (file ");
+ tprint(cur_file_name);
+ tprint(")");
+ }
if (t != NULL) {
tprint(" (");
tprint(t);
@@ -671,11 +702,14 @@ void normal_error(const char *t, const char *p)
tprint(": ");
if (p != NULL)
tprint(p);
- succumb();
+ /* quit */
+ history = fatal_error_stop;
+ wrapup_backend();
+ exit(EXIT_FAILURE);
}
@ @c
-void normal_warning(const char *t, const char *p, boolean prepend_nl, boolean append_nl)
+void normal_warning(const char *t, const char *p)
{
int report_id ;
if (strcmp(t,"lua") == 0) {
@@ -704,9 +738,13 @@ void normal_warning(const char *t, const char *p, boolean prepend_nl, boolean ap
strcpy(last_warning_tag,t);
run_callback(report_id, "->");
} else {
- if (prepend_nl)
- print_ln();
+ print_ln();
tprint("warning ");
+ if (cur_file_name) {
+ tprint(" (file ");
+ tprint(cur_file_name);
+ tprint(")");
+ }
if (t != NULL) {
tprint(" (");
tprint(t);
@@ -715,10 +753,30 @@ void normal_warning(const char *t, const char *p, boolean prepend_nl, boolean ap
tprint(": ");
if (p != NULL)
tprint(p);
- if (append_nl)
- print_ln();
+ print_ln();
}
if (history == spotless)
history = warning_issued;
}
}
+
+@ @c
+static char print_buf[PRINTF_BUF_SIZE];
+
+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);
+}
+
+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/expand.h b/Build/source/texk/web2c/luatexdir/tex/expand.h
index 713901986a3..18c0514e317 100644
--- a/Build/source/texk/web2c/luatexdir/tex/expand.h
+++ b/Build/source/texk/web2c/luatexdir/tex/expand.h
@@ -1,5 +1,5 @@
/* expand.h
-
+
Copyright 2009 Taco Hoekwater <taco@luatex.org>
This file is part of LuaTeX.
@@ -24,7 +24,8 @@
extern boolean is_in_csname;
extern void expand(void);
extern void complain_missing_csname(void);
-extern void manufacture_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);
diff --git a/Build/source/texk/web2c/luatexdir/tex/expand.w b/Build/source/texk/web2c/luatexdir/tex/expand.w
index 098b6808373..46c8622b491 100644
--- a/Build/source/texk/web2c/luatexdir/tex/expand.w
+++ b/Build/source/texk/web2c/luatexdir/tex/expand.w
@@ -221,7 +221,13 @@ void expand(void)
break;
case cs_name_cmd:
/* Manufacture a control sequence name; */
- manufacture_csname();
+ 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(); /* this procedure is discussed in Part 27 below */
@@ -229,6 +235,9 @@ void expand(void)
case the_cmd:
ins_the_toks(); /* this procedure is discussed in Part 27 below */
break;
+ case combine_toks_cmd:
+ combine_the_toks(cur_chr);
+ break;
case if_test_cmd:
conditional(); /* this procedure is discussed in Part 28 below */
break;
@@ -320,7 +329,7 @@ void complain_missing_csname(void)
}
@ @c
-void manufacture_csname(void)
+void manufacture_csname(boolean use)
{
halfword p, q, r;
lstring *ss;
@@ -339,22 +348,50 @@ void manufacture_csname(void)
/* 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 (ss->l > 0) {
- no_new_control_sequence = false;
- cur_cs = string_lookup((char *) ss->s, ss->l);
- no_new_control_sequence = true;
+ 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) {
+ /* skip */
+ } else if (eq_type(cur_cs) == undefined_cs_cmd) {
+ /* skip */
+ } else {
+ cur_tok = cur_cs + cs_token_flag;
+ back_input();
+ }
} else {
- cur_cs = null_cs; /* the list is empty */
+ if (ss->l > 0) {
+ no_new_control_sequence = false;
+ cur_cs = string_lookup((char *) ss->s, ss->l);
+ no_new_control_sequence = true;
+ } else {
+ cur_cs = null_cs; /* the list is empty */
+ }
+ last_cs_name = cur_cs ;
+ free_lstring(ss);
+ flush_list(r);
+ if (eq_type(cur_cs) == undefined_cs_cmd) {
+ eq_define(cur_cs, relax_cmd, too_big_char); /* N.B.: The |save_stack| might change */
+ }; /* the control sequence will now match `\.{\\relax}' */
+ cur_tok = cur_cs + cs_token_flag;
+ back_input();
}
- free_lstring(ss);
- flush_list(r);
- if (eq_type(cur_cs) == undefined_cs_cmd) {
- eq_define(cur_cs, relax_cmd, too_big_char); /* N.B.: The |save_stack| might change */
- }; /* 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();
+ }
+}
@ Sometimes the expansion looks too far ahead, so we want to insert
a harmless \.{\\relax} into the user's input.
@@ -378,7 +415,7 @@ common cases.
void get_x_token(void)
{ /* sets |cur_cmd|, |cur_chr|, |cur_tok|, and expands macros */
RESTART:
- get_next(); /* get_token_lua(); */
+ get_next();
if (cur_cmd <= max_command_cmd)
goto DONE;
if (cur_cmd >= call_cmd) {
@@ -409,7 +446,7 @@ void x_token(void)
{ /* |get_x_token| without the initial |get_next| */
while (cur_cmd > max_command_cmd) {
expand();
- get_next(); /* get_token_lua(); */
+ get_next();
}
if (cur_cs == 0)
cur_tok = token_val(cur_cmd, cur_chr);
@@ -750,9 +787,10 @@ void macro_call(void)
/* 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))
- end_token_list(); /* conserve stack space */
+ while ((istate == token_list) && (iloc == null) && (token_type != v_template)) {
+ /* conserve stack space */
+ end_token_list();
+ }
begin_token_list(ref_count, macro);
iname = warning_index;
iloc = token_link(r);
diff --git a/Build/source/texk/web2c/luatexdir/tex/extensions.h b/Build/source/texk/web2c/luatexdir/tex/extensions.h
index 4909b9b95f6..01a75b7e387 100644
--- a/Build/source/texk/web2c/luatexdir/tex/extensions.h
+++ b/Build/source/texk/web2c/luatexdir/tex/extensions.h
@@ -44,13 +44,6 @@ extern halfword write_loc;
extern void do_extension(int immediate);
-extern int pdf_last_annot;
-extern int pdf_last_link;
-extern int pdf_last_obj;
-extern int pdf_retval;
-
-/* Three extra node types carry information from |main_control|. */
-
/*
User defined whatsits can be inserted into node lists to pass data
along from one lua call to another without interference from the
@@ -59,7 +52,6 @@ type of the value depends on the |user_node_type| field.
*/
extern void new_whatsit(int s);
-extern void scan_pdf_ext_toks(void);
extern halfword concat_tokens(halfword q, halfword r);
diff --git a/Build/source/texk/web2c/luatexdir/tex/extensions.w b/Build/source/texk/web2c/luatexdir/tex/extensions.w
index 37736cc5a1a..0e178f01516 100644
--- a/Build/source/texk/web2c/luatexdir/tex/extensions.w
+++ b/Build/source/texk/web2c/luatexdir/tex/extensions.w
@@ -152,7 +152,7 @@ static void do_extension_pdf(int immediate)
set_pdf_literal_mode(tail, direct_page);
else
set_pdf_literal_mode(tail, set_origin);
- scan_pdf_ext_toks();
+ scan_toks(false, true);
set_pdf_literal_type(tail, normal);
set_pdf_literal_data(tail, def_ref);
} else if (scan_keyword("dest")) {
@@ -165,7 +165,7 @@ static void do_extension_pdf(int immediate)
new_whatsit(pdf_restore_node);
} else if (scan_keyword("setmatrix")) {
new_whatsit(pdf_setmatrix_node);
- scan_pdf_ext_toks();
+ scan_toks(false, true);
set_pdf_setmatrix_data(tail, def_ref);
} else if (scan_keyword("obj")) {
scan_obj(static_pdf);
@@ -211,7 +211,7 @@ static void do_extension_pdf(int immediate)
set_pdf_colorstack_cmd(tail, i);
set_pdf_colorstack_data(tail, null);
if (i <= colorstack_data) {
- scan_pdf_ext_toks();
+ scan_toks(false, true);
set_pdf_colorstack_data(tail, def_ref);
}
} else {
@@ -251,30 +251,30 @@ static void do_extension_pdf(int immediate)
i = cur_val;
if (i == null_font)
normal_error("pdf backend", "invalid font identifier");
- scan_pdf_ext_toks();
+ scan_toks(false, true);
set_pdf_font_attr(i, tokens_to_string(def_ref));
if (str_length(pdf_font_attr(i)) == 0) {
flush_str((str_ptr - 1)); /* from |tokens_to_string| */
set_pdf_font_attr(i, 0);
}
} else if (scan_keyword("mapfile")) {
- scan_pdf_ext_toks();
+ scan_toks(false, true);
pdfmapfile(def_ref);
delete_token_ref(def_ref);
} else if (scan_keyword("mapline")) {
- scan_pdf_ext_toks();
+ 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_pdf_ext_toks();
+ scan_toks(false, true);
pdf_info_toks = concat_tokens(pdf_info_toks, def_ref);
} else if (scan_keyword("names")) {
- scan_pdf_ext_toks();
+ scan_toks(false, true);
pdf_names_toks = concat_tokens(pdf_names_toks, def_ref);
} else if (scan_keyword("trailer")) {
- scan_pdf_ext_toks();
+ scan_toks(false, true);
pdf_trailer_toks = concat_tokens(pdf_trailer_toks, def_ref);
} else {
tex_error("unexpected use of \\pdfextension",null);
@@ -463,8 +463,7 @@ and appends it to the current list.
@c
void new_whatsit(int s)
{
- halfword p; /* the new node */
- p = new_node(whatsit_node, s);
+ halfword p = new_node(whatsit_node, s);
couple_nodes(tail, p);
tail = p;
}
@@ -482,11 +481,10 @@ single page, the stack would overflow.
void expand_macros_in_tokenlist(halfword p)
{
- int old_mode; /* saved |mode| */
- pointer q, r; /* temporary variables for list manipulation */
- q = get_avail();
+ int old_mode;
+ pointer q = get_avail();
+ pointer r = get_avail();
token_info(q) = right_brace_token + '}';
- r = get_avail();
token_link(q) = r;
token_info(r) = end_write_token;
begin_token_list(q, inserted);
@@ -588,22 +586,6 @@ boolean open_write_file(int id, char *fn) {
}
}
-@ We have to check whether \.{\\outputmode} is set for using \pdfTeX{}
- extensions.
-
-@c
-void scan_pdf_ext_toks(void)
-{
- (void) scan_toks(false, true); /* like \.{\\special} */
-}
-
-@ the pdflast* need extra global variables
-
-@c
-int pdf_last_annot;
-int pdf_last_link;
-int pdf_last_obj;
-int pdf_retval; /* global multi-purpose return value */
@ To implement primitives as \.{\\pdfextension info}, \.{\\pdfextension catalog} or
\.{\\pdfextension names} we need to concatenate tokens lists.
@@ -644,58 +626,58 @@ 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;
+ 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;
} /* there are no other cases */
tprint(" group (level ");
print_int(cur_level);
@@ -751,12 +733,10 @@ synchronized with the |in_open| variable indexing |grp_stack|.
@c
void group_warning(void)
{
- int i; /* index into |grp_stack| */
- boolean w; /* do we need a warning? */
+ boolean w = false; /* do we need a warning? */
+ int i = in_open; /* index into |grp_stack| */
base_ptr = input_ptr;
input_stack[base_ptr] = cur_input; /* store current state */
- i = in_open;
- w = false;
while ((grp_stack[i] == cur_boundary) && (i > 0)) {
/* 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
@@ -792,12 +772,10 @@ give a warning message (with the same complications as above).
@c
void if_warning(void)
{
- int i; /* index into |if_stack| */
- boolean w; /* do we need a warning? */
+ boolean w = false; /* do we need a warning? */
+ int i = in_open;
base_ptr = input_ptr;
input_stack[base_ptr] = cur_input; /* store current state */
- i = in_open;
- w = false;
while (if_stack[i] == cond_ptr) {
/* Set variable |w| to... */
if (tracing_nesting > 0) {
@@ -832,13 +810,10 @@ file are still incomplete.
@c
void file_warning(void)
{
- halfword p; /* saved value of |save_ptr| or |cond_ptr| */
- int l; /* saved value of |cur_level| or |if_limit| */
- int c; /* saved value of |cur_group| or |cur_if| */
- int i; /* saved value of |if_line| */
- p = save_ptr;
- l = cur_level;
- c = cur_group;
+ halfword p = save_ptr; /* saved value of |save_ptr| or |cond_ptr| */
+ int l = cur_level; /* saved value of |cur_level| or |if_limit| */
+ int c = cur_group; /* saved value of |cur_group| or |cur_if| */
+ int i; /* saved value of |if_line| */
save_ptr = cur_boundary;
while (grp_stack[in_open] != save_ptr) {
decr(cur_level);
@@ -999,8 +974,7 @@ int set_tex_attribute_register(int j, scaled v)
int get_tex_toks_register(int j)
{
- str_number s;
- s = get_nullstr();
+ str_number s = get_nullstr();
if (toks(j) != null) {
s = tokens_to_string(toks(j));
}
@@ -1009,9 +983,8 @@ int get_tex_toks_register(int j)
int set_tex_toks_register(int j, lstring s)
{
- halfword ref;
int a;
- ref = get_avail();
+ halfword ref = get_avail();
(void) str_toks(s);
set_token_ref_count(ref, 0);
set_token_link(ref, token_link(temp_token_head));
@@ -1025,9 +998,8 @@ int set_tex_toks_register(int j, lstring s)
int scan_tex_toks_register(int j, int c, lstring s)
{
- halfword ref;
int a;
- ref = get_avail();
+ 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));
diff --git a/Build/source/texk/web2c/luatexdir/tex/inputstack.h b/Build/source/texk/web2c/luatexdir/tex/inputstack.h
index 390fb169198..378fabe24b8 100644
--- a/Build/source/texk/web2c/luatexdir/tex/inputstack.h
+++ b/Build/source/texk/web2c/luatexdir/tex/inputstack.h
@@ -1,5 +1,5 @@
/* inputstack.h
-
+
Copyright 2009 Taco Hoekwater <taco@luatex.org>
This file is part of LuaTeX.
@@ -24,7 +24,7 @@
/*
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|.
+ |limit|, and |name|.
*/
typedef struct in_state_record {
@@ -273,7 +273,7 @@ the text expansion of a \.{\\count} or similar variable;
\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.
+|every_par_loc|, etc.
The token list begins with a reference count if and
only if |token_type>=macro|.
@@ -319,18 +319,13 @@ extern int base_ptr;
extern void show_context(void);
extern void set_trick_count(void);
-/* leave an input level, re-enter the old */
-# define pop_input() cur_input=input_stack[--input_ptr]
-
-extern void push_input(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 int reinsert_token(boolean a, halfword pp);
+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);
diff --git a/Build/source/texk/web2c/luatexdir/tex/inputstack.w b/Build/source/texk/web2c/luatexdir/tex/inputstack.w
index aaeec71e65f..273863d2042 100644
--- a/Build/source/texk/web2c/luatexdir/tex/inputstack.w
+++ b/Build/source/texk/web2c/luatexdir/tex/inputstack.w
@@ -19,14 +19,12 @@
@ @c
-
#include "ptexlib.h"
@ @c
#define end_line_char int_par(end_line_char_code)
#define error_context_lines int_par(error_context_lines_code)
-
in_state_record *input_stack = NULL;
int input_ptr = 0; /* first unused location of |input_stack| */
int max_in_stack = 0; /* largest value of |input_ptr| when pushing */
@@ -46,15 +44,13 @@ int scanner_status = 0; /* can a subfile end now? */
pointer warning_index = null; /* identifier relevant to non-|normal| scanner status */
pointer def_ref = null; /* reference count of token list being defined */
-
-
@ Here is a procedure that uses |scanner_status| to print a warning message
when a subfile has ended, and at certain other crucial times:
@c
void runaway(void)
{
- pointer p = null; /* head of runaway list */
+ pointer p = null; /* head of runaway list */
if (scanner_status > skipping) {
switch (scanner_status) {
case defining:
@@ -73,7 +69,8 @@ void runaway(void)
tprint_nl("Runaway text");
p = def_ref;
break;
- default: /* there are no other cases */
+ default:
+ /* there are no other cases */
break;
}
print_char('?');
@@ -82,7 +79,6 @@ void runaway(void)
}
}
-
@ 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
@@ -106,7 +102,6 @@ $v_j$ template begins when a tab mark or \.{\\cr} occurs at a time that
@c
int align_state = 0; /* group level with respect to current alignment */
-
@ 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
@@ -118,7 +113,6 @@ displayed by this procedure.
@c
int base_ptr = 0; /* shallowest level shown by |show_context| */
-
@ 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
@@ -130,66 +124,66 @@ at most |error_line|. Non-current input levels whose |token_type| is
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;
- default:
- tprint_nl("?");
- break; /* this should never happen */
+ 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;
+ default:
+ tprint_nl("?");
+ /* this should never happen */
+ break;
}
}
-
@ 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
@@ -220,8 +214,6 @@ 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.
@@ -259,7 +251,7 @@ void set_trick_count(void)
/*
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 on can set the length larger.
+ any length is. After all one can set the length larger.
*/
#define print_valid_utf8(q) do { \
@@ -287,44 +279,40 @@ void set_trick_count(void)
@ @c
void show_context(void)
-{ /* prints where the scanner is */
- int old_setting; /* saved |selector| setting */
- int nn; /* number of contexts shown so far, less one */
- boolean bottom_line; /* have we reached the final context to be shown? */
- int i; /* index into |buffer| */
- int j; /* end of current line in |buffer| */
- int l; /* length of descriptive information on line 1 */
- int m; /* context information gathered for line 2 */
- int n; /* length of line 1 */
- int p; /* starting or ending place in |trick_buf| */
- int q; /* temporary index */
- int c; /* used in sanitizer */
-
+{ /* prints where the scanner is */
+ int old_setting; /* saved |selector| setting */
+ int nn = -1; /* number of contexts shown so far, less one */
+ boolean bottom_line = false; /* have we reached the final context to be shown? */
+ int i; /* index into |buffer| */
+ int j; /* end of current line in |buffer| */
+ int l; /* length of descriptive information on line 1 */
+ int m; /* context information gathered for line 2 */
+ int n; /* length of line 1 */
+ int p; /* starting or ending place in |trick_buf| */
+ int q; /* temporary index */
+ int c; /* used in sanitizer */
base_ptr = input_ptr;
input_stack[base_ptr] = cur_input;
/* store current state */
- nn = -1;
- bottom_line = false;
while (true) {
cur_input = input_stack[base_ptr]; /* enter into the context */
if (istate != token_list) {
if ((iname > 21) || (base_ptr == 0))
bottom_line = true;
}
- if ((base_ptr == input_ptr) || bottom_line
- || (nn < error_context_lines)) {
+ if ((base_ptr == input_ptr) || bottom_line || (nn < error_context_lines)) {
/* Display the current context */
- if ((base_ptr == input_ptr) || (istate != token_list) ||
- (token_type != backed_up) || (iloc != null)) {
+ if ((base_ptr == input_ptr) || (istate != token_list) || (token_type != backed_up) || (iloc != null)) {
/* we omit backed-up token lists that have already been read */
tally = 0; /* get ready to count characters */
old_setting = selector;
if (istate != token_list) {
- /* Print location of 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.
+ Print location of 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) {
@@ -359,7 +347,8 @@ void show_context(void)
else
show_token_list(token_link(istart), iloc, 100000); /* avoid reference count */
}
- selector = old_setting; /* stop pseudoprinting */
+ /* stop pseudoprinting */
+ selector = old_setting;
/* Print two lines using the tricky pseudoprinted information */
if (trick_count == 1000000)
set_trick_count();
@@ -379,8 +368,9 @@ void show_context(void)
for (q = p; q <= first_count - 1; q++)
print_valid_utf8(q);
print_ln();
+ /* print |n| spaces to begin line~2 */
for (q = 1; q <= n; q++)
- print_char(' '); /* print |n| spaces to begin line~2 */
+ print_char(' ');
if (m + n <= error_line)
p = first_count + m;
else
@@ -389,40 +379,42 @@ void show_context(void)
print_valid_utf8(q);
if (m + n > error_line)
tprint("...");
-
incr(nn);
}
} else if (nn == error_context_lines) {
tprint_nl("...");
- incr(nn); /* omitted if |error_context_lines<0| */
+ incr(nn);
+ /* omitted if |error_context_lines<0| */
}
if (bottom_line)
break;
decr(base_ptr);
}
- cur_input = input_stack[input_ptr]; /* restore original state */
+ /* restore original state */
+ cur_input = input_stack[input_ptr];
}
-
@ 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).
@c
+
/* enter a new input level, save the old */
-void push_input(void)
-{
- 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; /* stack the record */
- nofilter = false;
+# 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);
-}
@
Here is a procedure that starts a new level of token-list input, given
@@ -436,7 +428,8 @@ void begin_token_list(halfword p, quarterword t)
istate = token_list;
istart = p;
token_type = (unsigned char) t;
- if (t >= macro) { /* the token list starts with a reference count */
+ if (t >= macro) {
+ /* the token list starts with a reference count */
add_token_ref(p);
if (t == macro) {
param_start = param_ptr;
@@ -462,7 +455,6 @@ void begin_token_list(halfword p, quarterword t)
}
}
-
@ 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.
@@ -470,13 +462,17 @@ to be equal to either |backed_up| or |inserted| about 2/3 of the time.
@c
void end_token_list(void)
-{ /* leave a token-list input level */
- if (token_type >= backed_up) { /* token list to be deleted */
+{
+ /* leave a token-list input level */
+ if (token_type >= backed_up) {
+ /* token list to be deleted */
if (token_type <= inserted) {
flush_list(istart);
} else {
- delete_token_ref(istart); /* update reference count */
- if (token_type == macro) { /* parameters must be flushed */
+ /* update reference count */
+ delete_token_ref(istart);
+ if (token_type == macro) {
+ /* parameters must be flushed */
while (param_ptr > param_start) {
decr(param_ptr);
flush_list(param_stack[param_ptr]);
@@ -493,7 +489,6 @@ void end_token_list(void)
check_interrupt();
}
-
@ 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
@@ -503,12 +498,16 @@ so it has been slightly optimized for speed.
@^inner loop@>
@c
+
+/* undoes one token of input */
+
void back_input(void)
-{ /* undoes one token of input */
- halfword p; /* a token list of length one */
- while ((istate == token_list) && (iloc == null)
- && (token_type != v_template))
- end_token_list(); /* conserve stack space */
+{
+ halfword p; /* a token list of length one */
+ while ((istate == token_list) && (iloc == null) && (token_type != v_template)) {
+ /* conserve stack space */
+ end_token_list();
+ }
p = get_avail();
set_token_info(p, cur_tok);
if (cur_tok < right_brace_limit) {
@@ -526,7 +525,8 @@ void back_input(void)
@ Insert token |p| into \TeX's input
@c
-int reinsert_token(boolean a, halfword pp)
+
+void reinsert_token(boolean a, halfword pp)
{
halfword t;
t = cur_tok;
@@ -546,13 +546,10 @@ int reinsert_token(boolean a, halfword pp)
}
} else {
back_input();
- a = true; /* etex is always on */
}
cur_tok = t;
- return a;
}
-
@ 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|
@@ -584,7 +581,6 @@ void begin_file_reading(void)
synctex_tag = 0;
}
-
@ Conversely, the variables must be downdated when such a level of input
is finished:
@@ -603,7 +599,6 @@ void end_file_reading(void)
decr(in_open);
}
-
@ 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.
@@ -618,8 +613,7 @@ void clear_for_error_prompt(void)
clear_terminal();
}
-@ To get \TeX's whole input mechanism going, we perform the following
- actions.
+@ To get \TeX's whole input mechanism going, we perform the following actions.
@c
void initialize_inputstack(void)
@@ -662,9 +656,6 @@ void initialize_inputstack(void)
first = last + 1; /* |init_terminal| has set |loc| and |last| */
}
-
-
-
@ 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
@@ -672,7 +663,7 @@ processed: the |subtype| field contains the size of this node,
all the following words contain ASCII codes.
@c
-halfword pseudo_files; /* stack of pseudo files */
+halfword pseudo_files; /* stack of pseudo files */
static halfword string_to_pseudo(str_number str, int nl)
{
@@ -685,7 +676,7 @@ static halfword string_to_pseudo(str_number str, int nl)
len = (unsigned) str_length(str);
l = 0;
while (l < len) {
- unsigned m = l; /* start of current line */
+ unsigned m = l; /* start of current line */
while ((l < len) && (s[l] != nl))
l++;
sz = (int) (l - m + 7) / 4;
@@ -718,14 +709,13 @@ static halfword string_to_pseudo(str_number str, int nl)
return h;
}
-
@ The |pseudo_start| procedure initiates reading from a pseudo file.
@c
void pseudo_from_string(void)
{
- str_number s; /* string to be converted into a pseudo file */
- halfword p; /* for list construction */
+ str_number s; /* string to be converted into a pseudo file */
+ halfword p; /* for list construction */
s = make_string();
/* Convert string |s| into a new pseudo file */
p = string_to_pseudo(s, int_par(new_line_char_code));
@@ -733,10 +723,10 @@ void pseudo_from_string(void)
pseudo_files = p;
flush_str(s);
/* Initiate input from new pseudo file */
- begin_file_reading(); /* set up |cur_file| and new level of input */
+ begin_file_reading(); /* set up |cur_file| and new level of input */
line = 0;
ilimit = istart;
- iloc = ilimit + 1; /* force line read */
+ iloc = ilimit + 1; /* force line read */
if (int_par(tracing_scan_tokens_code) > 0) {
if (term_offset > max_print_line - 3)
print_ln();
@@ -755,7 +745,7 @@ void pseudo_from_string(void)
void pseudo_start(void)
{
- int old_setting; /* holds |selector| setting */
+ int old_setting;
scan_general_text();
old_setting = selector;
selector = new_string;
@@ -769,10 +759,10 @@ void pseudo_start(void)
@ @c
void lua_string_start(void)
{
- begin_file_reading(); /* set up |cur_file| and new level of input */
+ begin_file_reading(); /* set up |cur_file| and new level of input */
line = 0;
ilimit = istart;
- iloc = ilimit + 1; /* force line read */
+ iloc = ilimit + 1; /* force line read */
iname = 21;
luacstring_start(iindex);
}
@@ -780,13 +770,15 @@ void lua_string_start(void)
@ Here we read a line from the current pseudo file into |buffer|.
@c
+/* inputs the next line or returns |false| */
+
boolean pseudo_input(void)
-{ /* inputs the next line or returns |false| */
- halfword p; /* current line from pseudo file */
- int sz; /* size of node |p| */
- four_quarters w; /* four ASCII codes */
- halfword r; /* loop index */
- last = first; /* cf.\ Matthew 19\thinspace:\thinspace30 */
+{
+ halfword p; /* current line from pseudo file */
+ int sz; /* size of node |p| */
+ four_quarters w; /* four ASCII codes */
+ halfword r; /* loop index */
+ last = first; /* cf.\ Matthew 19\thinspace:\thinspace30 */
p = pseudo_lines(pseudo_files);
if (p == null) {
return false;
@@ -798,7 +790,7 @@ boolean pseudo_input(void)
last = first;
for (r = p + 1; r <= p + sz - 1; r++) {
w = varmem[r].qqqq;
- buffer[last] = (packed_ASCII_code) w.b0;
+ 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;
@@ -816,8 +808,10 @@ boolean pseudo_input(void)
@ When we are done with a pseudo file we `close' it.
@c
+/* close the top level pseudo file */
+
void pseudo_close(void)
-{ /* close the top level pseudo file */
+{
halfword p;
p = vlink(pseudo_files);
flush_node(pseudo_files);
diff --git a/Build/source/texk/web2c/luatexdir/tex/linebreak.h b/Build/source/texk/web2c/luatexdir/tex/linebreak.h
index 9ac444b7a37..1b5d1da96ca 100644
--- a/Build/source/texk/web2c/luatexdir/tex/linebreak.h
+++ b/Build/source/texk/web2c/luatexdir/tex/linebreak.h
@@ -17,7 +17,6 @@
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
@@ -83,21 +82,20 @@ extern halfword find_protchar_right(halfword l, halfword r);
)
# define cp_skipable(a) ( (! is_char_node((a))) && ( \
- (type((a)) == ins_node) \
+ ((type((a)) == glue_node) && (glue_ptr((a)) == zero_glue)) \
+ || (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)) \
+ || (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)) == penalty_node) \
|| (type((a)) == boundary_node) \
|| (type((a)) == whatsit_node) \
- || (type((a)) == dir_node) \
- || (type((a)) == local_par_node) \
- || ((type((a)) == rule_node) && zero_dimensions(a)) \
- || ((type((a)) == disc_node) && empty_disc(a)) \
- || ((type((a)) == math_node) && (surround((a)) == 0)) \
- || ((type((a)) == kern_node) && ((width((a)) == 0) || (subtype((a)) == normal))) \
- || ((type((a)) == glue_node) && (glue_ptr((a)) == zero_glue)) \
- || ((type((a)) == hlist_node) && (list_ptr((a)) == null) && zero_dimensions(a)) \
) )
-
#endif
diff --git a/Build/source/texk/web2c/luatexdir/tex/linebreak.w b/Build/source/texk/web2c/luatexdir/tex/linebreak.w
index 90167e43938..3947abfa6cd 100644
--- a/Build/source/texk/web2c/luatexdir/tex/linebreak.w
+++ b/Build/source/texk/web2c/luatexdir/tex/linebreak.w
@@ -19,10 +19,8 @@
@ @c
-
#include "ptexlib.h"
-
@ 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
@@ -75,7 +73,6 @@ line can be ascertained when it is necessary to decide whether to use
@c
halfword just_box; /* the |hlist_node| for the last line of the new paragraph */
-
@ 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.
@@ -120,39 +117,16 @@ void line_break(boolean d, int line_break_context)
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);
-#ifdef DEBUG
- {
- int n = temp_head;
- fprintf(stdout, "pre_linebreak_filter status:\n");
- while (n) {
- fprintf(stdout, " %s node %d\n",
- get_node_name(type(n), subtype(n)), (int) n);
- n = vlink(n);
- }
- }
-#endif
lua_node_filter(pre_linebreak_filter_callback,
- line_break_context, temp_head,
+ 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;
-#ifdef DEBUG
- {
- int n = temp_head;
- fprintf(stdout, "pre_linebreak_filter returned:\n");
- while (n) {
- fprintf(stdout, " %s node %d\n",
- get_node_name(type(n), subtype(n)), (int) n);
- n = vlink(n);
- }
- }
-#endif
callback_id = callback_defined(linebreak_filter_callback);
if (callback_id > 0) {
- callback_id =
- lua_linebreak_callback(d, temp_head,
- addressof(cur_list.tail_field));
+ callback_id = lua_linebreak_callback(d, temp_head, addressof(cur_list.tail_field));
if (callback_id > 0) {
/* find the correct value for the |just_box| */
halfword box_search = cur_list.tail_field;
@@ -182,10 +156,11 @@ void line_break(boolean d, int line_break_context)
}
}
if (callback_id == 0) {
- if ((!is_char_node(vlink(temp_head))) && ((type(vlink(temp_head)) == local_par_node)))
+ if ((!is_char_node(vlink(temp_head))) && ((type(vlink(temp_head)) == local_par_node))) {
paragraph_dir = local_par_dir(vlink(temp_head));
- else
- assert(0); /* |paragraph_dir = 0|; */
+ } else {
+ confusion("weird par dir"); /* assert(0); */ /* |paragraph_dir = 0|; */
+ }
ext_do_line_break(paragraph_dir,
int_par(pretolerance_code),
int_par(tracing_paragraphs_code),
@@ -220,7 +195,6 @@ void line_break(boolean d, int line_break_context)
pack_begin_line = 0;
}
-
@ 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
@@ -229,9 +203,9 @@ void line_break(boolean d, int line_break_context)
prevents this error message from appearing more than once per paragraph.
@c
-#define check_shrinkage(a) \
- if ((shrink_order((a))!=normal)&&(shrink((a))!=0)) \
- a=finite_shrink((a))
+#define check_shrinkage(a) \
+ if ((shrink_order((a))!=normal)&&(shrink((a))!=0)) \
+ a=finite_shrink((a))
static boolean no_shrink_error_yet; /*have we complained about infinite shrinkage? */
@@ -314,7 +288,6 @@ static int max_stretch_ratio = 0; /*maximal stretch ratio of expanded font
static int max_shrink_ratio = 0; /*maximal shrink ratio of expanded fonts */
static int cur_font_step = 0; /*the current step of expanded fonts */
-
static boolean check_expand_pars(internal_font_number f)
{
int m;
@@ -391,18 +364,16 @@ static boolean check_expand_pars(internal_font_number f)
return l;
}
-
@ searches right to left from list tail |r| to head |l|, returns 1st non-skipable item
@c
/*public*/ halfword find_protchar_right(halfword l, halfword r)
{
halfword t;
- boolean run;
+ boolean run = true;
if (r == null)
return null;
hlist_stack_level = 0;
- run = true;
do {
t = r;
while (run && (type(r) == hlist_node) && (list_ptr(r) != null)) {
@@ -538,7 +509,6 @@ static halfword passive; /* most recent node on passive list */
static halfword printed_node; /*most recent node that has been printed */
static halfword pass_number; /*the number of passive nodes allocated on this pass */
-
@ 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
@@ -557,7 +527,6 @@ 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
@@ -618,7 +587,6 @@ static boolean auto_breaking; /*make |auto_breaking| accessible out of |line_b
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
@@ -635,7 +603,6 @@ static boolean auto_breaking; /*make |auto_breaking| accessible out of |line_b
end of a paragraph is also regarded as `|hyphenated_node|'; this case is
distinguishable by the condition |cur_p=null|.
-
@c
static int internal_pen_inter; /* running \.{\\localinterlinepenalty} */
static int internal_pen_broken; /* running \.{\\localbrokenpenalty} */
@@ -668,8 +635,6 @@ static int minimum_demerits; /* best total demerits known for current line cl
static halfword best_place[4]; /* how to achieve |minimal_demerits| */
static halfword best_pl_line[4]; /*corresponding line number */
-
-
@ 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
@@ -687,23 +652,21 @@ Note that if |hang_indent=0|, the value of |hang_after| is irrelevant.
@^length of lines@> @^hanging indentation@>
@c
-static halfword easy_line; /*line numbers |>easy_line| are equivalent in break nodes */
-static halfword last_special_line; /*line numbers |>last_special_line| all have the same width */
-static scaled first_width; /*the width of all lines |<=last_special_line|, if
- no \.{\\parshape} has been specified */
-static scaled second_width; /*the width of all lines |>last_special_line| */
-static scaled first_indent; /*left margin to go with |first_width| */
-static scaled second_indent; /*left margin to go with |second_width| */
-
-static halfword best_bet; /*use this passive node and its predecessors */
-static int fewest_demerits; /*the demerits associated with |best_bet| */
-static halfword best_line; /*line number following the last line of the new paragraph */
-static int actual_looseness; /*the difference between |line_number(best_bet)|
- and the optimum |best_line| */
-static int line_diff; /*the difference between the current line number and
- the optimum |best_line| */
-
-
+static halfword easy_line; /*line numbers |>easy_line| are equivalent in break nodes */
+static halfword last_special_line; /*line numbers |>last_special_line| all have the same width */
+static scaled first_width; /*the width of all lines |<=last_special_line|, if
+ no \.{\\parshape} has been specified */
+static scaled second_width; /*the width of all lines |>last_special_line| */
+static scaled first_indent; /*left margin to go with |first_width| */
+static scaled second_indent; /*left margin to go with |second_width| */
+
+static halfword best_bet; /*use this passive node and its predecessors */
+static int fewest_demerits; /*the demerits associated with |best_bet| */
+static halfword best_line; /*line number following the last line of the new paragraph */
+static int actual_looseness; /*the difference between |line_number(best_bet)|
+ and the optimum |best_line| */
+static int line_diff; /*the difference between the current line number and
+ the optimum |best_line| */
@ \TeX\ makes use of the fact that |hlist_node|, |vlist_node|,
|rule_node|, |ins_node|, |mark_node|, |adjust_node|,
@@ -720,33 +683,46 @@ static int line_diff; /*the difference between the current line number
#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; \
- } \
- }
+#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; \
+ } \
+}
static boolean do_last_line_fit; /* special algorithm for last line of paragraph? */
static scaled fill_width[4]; /* infinite stretch components of |par_fill_skip| */
@@ -768,11 +744,9 @@ static scaled best_pl_glue[4]; /*corresponding glue stretch or shrink */
#define sub_kern_shrink(a,b) a -= kern_shrink((b))
#define sub_kern_stretch(a,b) a -= kern_stretch((b))
-
@ 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.
@@ -789,23 +763,23 @@ static void add_to_widths(halfword s, int line_break_dir, int adjust_spacing, sc
};
} 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);
- }
- /* fall through */
- case rule_node:
- widths[1] += width(s);
- break;
- case disc_node: /* TH temp */
- break;
- default:
- confusion("invalid node found in discretionary"); /* todo: report type */
+ 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);
+ }
+ /* fall through */
+ case rule_node:
+ widths[1] += width(s);
+ break;
+ case disc_node: /* TH temp */
+ break;
+ default:
+ confusion("invalid node found in discretionary"); /* todo: report type */
}
}
s = vlink(s);
@@ -831,31 +805,30 @@ static void sub_from_widths(halfword s, int line_break_dir, int adjust_spacing,
}
} 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);
- }
- /* fall through */
- case rule_node:
- widths[1] -= width(s);
- break;
- case disc_node: /* TH temp */
- break;
- default:
- confusion("invalid node found in discretionary"); /* todo: report type */
- break;
+ 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);
+ }
+ /* fall through */
+ case rule_node:
+ widths[1] -= width(s);
+ break;
+ case disc_node: /* TH temp */
+ break;
+ default:
+ confusion("invalid node found in discretionary"); /* todo: report type */
+ break;
}
}
s = vlink(s);
}
}
-
@ 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
@@ -876,12 +849,10 @@ static void sub_from_widths(halfword s, int line_break_dir, int adjust_spacing,
Kern nodes do not disappear at a line break unless they are |explicit|.
@c
-static void
-compute_break_width(int break_type, int line_break_dir, int adjust_spacing, halfword p)
+static void compute_break_width(int break_type, int line_break_dir, int adjust_spacing, halfword p)
{
- halfword s; /* glue and other 'whitespace' to be skipped after a break
- * used if unhyphenated, or |post_break==empty| */
- s = p;
+ halfword s = p; /* glue and other 'whitespace' to be skipped after a break;
+ used if unhyphenated, or |post_break==empty| */
if (break_type > unhyphenated_node && p != null) {
/*Compute the discretionary |break_width| values; */
/* When |p| is a discretionary break, the length of a line
@@ -921,43 +892,42 @@ compute_break_width(int break_type, int line_break_dir, int adjust_spacing, half
}
while (s != null) {
switch (type(s)) {
- case math_node:
- /* begin mathskip code */
- if (math_skip == zero_glue) {
- break_width[1] -= surround(s);
+ case math_node:
+ /* begin mathskip code */
+ if (math_skip == zero_glue) {
+ break_width[1] -= surround(s);
+ break;
+ } else {
+ /* fall through */
+ }
+ /* end mathskip code */
+ case glue_node:
+ /*Subtract glue from |break_width|; */
+ {
+ halfword v = glue_ptr(s);
+ break_width[1] -= width(v);
+ break_width[2 + stretch_order(v)] -= stretch(v);
+ break_width[7] -= shrink(v);
+ }
break;
- } else {
- /* fall through */
- }
- /* end mathskip code */
- case glue_node:
- /*Subtract glue from |break_width|; */
- {
- halfword v = glue_ptr(s);
- break_width[1] -= width(v);
- break_width[2 + stretch_order(v)] -= stretch(v);
- break_width[7] -= shrink(v);
- }
- break;
- case penalty_node:
- break;
- case kern_node:
- if (subtype(s) != explicit)
+ case penalty_node:
+ break;
+ case kern_node:
+ if (subtype(s) != explicit)
+ return;
+ else
+ break_width[1] -= width(s);
+ break;
+ default:
return;
- else
- break_width[1] -= width(s);
- break;
- default:
- return;
};
s = vlink(s);
}
}
@ @c
-static void
-print_break_node(halfword q, fitness_value fit_class,
- quarterword break_type, halfword cur_p)
+static void print_break_node(halfword q, fitness_value fit_class,
+ quarterword break_type, halfword cur_p)
{
/* Print a symbolic description of the new break node */
tprint_nl("@@@@");
@@ -988,9 +958,8 @@ print_break_node(halfword q, fitness_value fit_class,
}
@ @c
-static void
-print_feasible_break(halfword cur_p, pointer r, halfword b, int pi,
- int d, boolean artificial_demerits)
+static void print_feasible_break(halfword cur_p, pointer r, halfword b, int pi,
+ int d, boolean artificial_demerits)
{
/* Print a symbolic description of this feasible break; */
if (printed_node != cur_p) {
@@ -1046,15 +1015,15 @@ print_feasible_break(halfword cur_p, pointer r, halfword b, int pi,
#define set_break_width_to_background(a) break_width[a]=background[(a)]
-#define convert_to_break_width(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 store_break_width(a) active_width[(a)]=break_width[(a)]
-#define new_delta_to_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) \
+#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)]
@@ -1066,57 +1035,53 @@ print_feasible_break(halfword cur_p, pointer r, halfword b, int pi,
#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)
+#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)
{
/* labels: |CONTINUE,DEACTIVATE,FOUND,NOT_FOUND|; */
pointer r; /* runs through the active list */
scaled margin_kern_stretch;
scaled margin_kern_shrink;
halfword lp, rp, cp;
- halfword prev_r; /* stays a step behind |r| */
- halfword prev_prev_r; /*a step behind |prev_r|, if |type(prev_r)=delta_node| */
- halfword old_l; /* maximum line number in current equivalence class of lines */
- boolean no_break_yet; /* have we found a feasible break at |cur_p|? */
- halfword q; /*points to a new node being created */
- halfword l; /*line number of current active node */
- boolean node_r_stays_active; /*should node |r| remain in the active list? */
- scaled line_width; /*the current line will be justified to this width */
- fitness_value fit_class; /*possible fitness class of test line */
- halfword b; /*badness of test line */
- int d; /*demerits of test line */
- boolean artificial_demerits; /*has |d| been forced to zero? */
+ halfword prev_r = active; /* stays a step behind |r| */
+ halfword prev_prev_r = null; /*a step behind |prev_r|, if |type(prev_r)=delta_node| */
+ halfword old_l = 0; /* maximum line number in current equivalence class of lines */
+ boolean no_break_yet = true; /* have we found a feasible break at |cur_p|? */
+ halfword q; /*points to a new node being created */
+ halfword l; /*line number of current active node */
+ boolean node_r_stays_active; /*should node |r| remain in the active list? */
+ scaled line_width = 0; /*the current line will be justified to this width */
+ fitness_value fit_class; /*possible fitness class of test line */
+ halfword b; /*badness of test line */
+ int d; /*demerits of test line */
+ boolean artificial_demerits; /*has |d| been forced to zero? */
scaled shortfall; /*used in badness calculations */
- scaled g; /*glue stretch or shrink of test line, adjustment for last line */
- scaled cur_active_width[10] = { 0 }; /*distance from current active node */
+ scaled g = 0; /*glue stretch or shrink of test line, adjustment for last line */
+ scaled cur_active_width[10] = { 0 }; /*distance from current active node */
- line_width = 0;
- g = 0;
- prev_prev_r = null;
/*Make sure that |pi| is in the proper range; */
if (pi >= inf_penalty) {
return; /* this breakpoint is inhibited by infinite penalty */
@@ -1124,9 +1089,6 @@ ext_try_break(int pi,
pi = eject_penalty; /*this breakpoint will be forced */
}
- no_break_yet = true;
- prev_r = active;
- old_l = 0;
do_all_eight(copy_to_cur_active);
while (1) {
@@ -1619,34 +1581,33 @@ ext_try_break(int pi,
}
@ @c
-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)
+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)
{
/* DONE,DONE1,DONE2,DONE3,DONE4,DONE5,CONTINUE; */
halfword cur_p, q, r, s; /* miscellaneous nodes of temporary interest */
@@ -1749,7 +1710,7 @@ ext_do_line_break(int paragraph_dir,
dir_ptr = null;
}
#if 0
- push_dir(paragraph_dir,dir_ptr); /* TODO what was the point of this? */
+ push_dir(dir_ptr,paragraph_dir); /* TODO what was the point of this? */
#endif
/* Find optimal breakpoints; */
@@ -1768,7 +1729,6 @@ ext_do_line_break(int paragraph_dir,
if (tracing_paragraphs > 0)
begin_diagnostic();
}
-
while (1) {
halfword first_p;
halfword nest_stack[10];
@@ -1828,8 +1788,7 @@ ext_do_line_break(int paragraph_dir,
`\.{\\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);
+ 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);
@@ -1838,9 +1797,6 @@ ext_do_line_break(int paragraph_dir,
cur_p = vlink(cur_p);
while (cur_p == null && nest_index > 0) {
cur_p = nest_stack[--nest_index];
-#ifdef DEBUG
- fprintf(stderr,"Node Pop %d [%d]\n",nest_index,(int)cur_p);
-#endif
}
}
if (cur_p == null) {
@@ -1853,218 +1809,211 @@ ext_do_line_break(int paragraph_dir,
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: /* DIR: Adjust the dir stack for the |line_break| routine; */
- if (dir_dir(cur_p) >= 0) {
- line_break_dir = dir_dir(cur_p);
- push_dir_node(cur_p,dir_ptr); /* adds to |dir_ptr| */
- } else {
- pop_dir_node(dir_ptr);
- if (dir_ptr != null)
- line_break_dir = dir_dir(dir_ptr);
- }
- break;
- case local_par_node: /* LOCAL: 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);
- /* begin mathskip code */
- if (math_skip == zero_glue) {
- kern_break();
+ case hlist_node:
+ case vlist_node:
+ active_width[1] += pack_width(line_break_dir, box_dir(cur_p), cur_p, false);
break;
- } else {
- /* fall through */
- }
- /* end mathskip code */
- case glue_node:
- /* 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. */
- /* *INDENT-OFF* */
- if (auto_breaking) {
- halfword prev_p = alink(cur_p);
- if (prev_p != temp_head &&
- (is_char_node(prev_p) ||
- precedes_break(prev_p) ||
- ((type(prev_p) == kern_node)
- && (subtype(prev_p) != explicit)))) {
- 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);
- }
- }
- /* *INDENT-ON* */
- check_shrinkage(glue_ptr(cur_p));
- q = glue_ptr(cur_p);
- active_width[1] += width(q);
- active_width[2 + stretch_order(q)] += stretch(q);
- active_width[7] += shrink(q);
- /* begin mathskip code */
- if (type(cur_p)==math_node) {
- active_width[1]+=surround(cur_p);
- }
- /* end mathskip code */
- break;
- case kern_node:
- if (subtype(cur_p) == explicit) {
- kern_break();
- } else {
+ case rule_node:
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 dir_node: /* DIR: Adjust the dir stack for the |line_break| routine; */
+ if (dir_dir(cur_p) >= 0) {
+ line_break_dir = dir_dir(cur_p);
+ push_dir_node(dir_ptr,cur_p); /* adds to |dir_ptr| */
+ } else {
+ pop_dir_node(dir_ptr);
+ if (dir_ptr != null) {
+ line_break_dir = dir_dir(dir_ptr);
+ }
}
- }
- break;
- case disc_node:
- /* |select_disc|s are handled by the leading |init_disc| */
- if (subtype(cur_p) == select_disc)
break;
- /* 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 (HH). */
- if (second_pass || subtype(cur_p) <= automatic_disc) {
- /*
- int actual_penalty = hyphen_penalty;
- if (disc_penalty(cur_p) != 0) {
- actual_penalty = (int) disc_penalty(cur_p);
- } else if (subtype(cur_p) == automatic_disc) {
- actual_penalty = ex_hyphen_penalty;
+ case local_par_node: /* LOCAL: 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);
+ /* begin mathskip code */
+ if (math_skip == zero_glue) {
+ kern_break();
+ break;
+ } else {
+ /* fall through */
}
- */
- int actual_penalty = (int) disc_penalty(cur_p);
- s = vlink_pre_break(cur_p);
- do_one_seven_eight(reset_disc_width);
- if (s == null) { /* 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);
+ /* end mathskip code */
+ case glue_node:
+ /* 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. */
+ /* *INDENT-OFF* */
+ if (auto_breaking) {
+ halfword prev_p = alink(cur_p);
+ if (prev_p != temp_head &&
+ (is_char_node(prev_p) ||
+ precedes_break(prev_p) ||
+ ((type(prev_p) == kern_node)
+ && (subtype(prev_p) != explicit)))) {
+ 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);
+ }
+ }
+ /* *INDENT-ON* */
+ check_shrinkage(glue_ptr(cur_p));
+ q = glue_ptr(cur_p);
+ active_width[1] += width(q);
+ active_width[2 + stretch_order(q)] += stretch(q);
+ active_width[7] += shrink(q);
+ /* begin mathskip code */
+ if (type(cur_p)==math_node) {
+ active_width[1]+=surround(cur_p);
+ }
+ /* end mathskip code */
+ break;
+ case kern_node:
+ if (subtype(cur_p) == explicit) {
+ kern_break();
} 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) {
- /* we should at two break points after the one we
- added above:
- \item1 which does a possible break in INIT's |post_break|
- \item2 which means the |no_break| actually was broken
- just a character later */
- /* do the select-0 case 'f-f-i' */
- assert(type(vlink(cur_p)) == disc_node &&
- subtype(vlink(cur_p)) == select_disc);
- s = vlink_pre_break(vlink(cur_p));
- add_to_widths(s, line_break_dir, adjust_spacing, disc_width);
+ 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:
+ /* |select_disc|s are handled by the leading |init_disc| */
+ if (subtype(cur_p) == select_disc)
+ break;
+ /* 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 (HH). */
+ if (second_pass || subtype(cur_p) <= automatic_disc) {
+ /*
+ int actual_penalty = hyphen_penalty;
+ if (disc_penalty(cur_p) != 0) {
+ actual_penalty = (int) disc_penalty(cur_p);
+ } else if (subtype(cur_p) == automatic_disc) {
+ actual_penalty = ex_hyphen_penalty;
+ }
+ */
+ int actual_penalty = (int) disc_penalty(cur_p);
+ s = vlink_pre_break(cur_p);
+ do_one_seven_eight(reset_disc_width);
+ if (s == null) { /* 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,
- vlink(cur_p));
-#if 0
- /* TODO this does not work */
- /* go back to the starting situation */
- do_one_seven_eight
- (sub_disc_width_from_active_width);
- do_one_seven_eight(reset_disc_width);
- /* add select |no_break| to |active_width| */
- s = vlink_no_break(vlink(cur_p));
+ 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,
- vlink(cur_p));
+ 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) {
+ /* we should at two break points after the one we
+ added above:
+ \item1 which does a possible break in INIT's |post_break|
+ \item2 which means the |no_break| actually was broken
+ just a character later */
+ /* 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));
+#if 0
+ /* TODO this does not work */
+ /* go back to the starting situation */
+ do_one_seven_eight(sub_disc_width_from_active_width);
+ do_one_seven_eight(reset_disc_width);
+ /* 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);
}
- 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:
- /* / Advance past a whatsit node in the |line_break| loop/; */
- case mark_node:
- case ins_node:
- case adjust_node:
- break;
- case glue_spec_node:
- fprintf(stdout, "\nfound a glue_spec in a paragraph!");
- break;
- default:
- fprintf(stdout, "\ntype=%d", type(cur_p));
- confusion("paragraph");
+ 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:
+ /* / 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];
-#ifdef DEBUG
- fprintf(stderr,"Node Pop %d [%d]\n",nest_index,(int)cur_p);
-#endif
}
}
if (cur_p == null) {
- /* 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.
- */
-
+ /*
+ 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,
@@ -2084,16 +2033,18 @@ ext_do_line_break(int paragraph_dir,
r = vlink(r);
} while (r != active);
best_line = line_number(best_bet);
-
- /* /Find an active node with fewest demerits; */
+ /*
+ Find an active node with fewest demerits;
+ */
if (looseness == 0)
goto DONE;
- /*Find the best active node for the desired looseness; */
+ /*
+ 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.
+ 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;
@@ -2116,24 +2067,24 @@ ext_do_line_break(int paragraph_dir,
r = vlink(r);
} while (r != active);
best_line = line_number(best_bet);
-
- /* /Find the best active node for the desired looseness; */
+ /*
+ Find the best active node for the desired looseness;
+ */
if ((actual_looseness == looseness) || final_pass)
goto DONE;
}
}
-
/* Clean up the memory by removing the break nodes; */
clean_up_the_memory();
/* /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 { /* if at first you do not succeed, \dots */
+ } else {
+ /* if at first you do not succeed, \dots */
if (tracing_paragraphs > 0)
tprint_nl("@@emergencypass");
background[2] += emergency_stretch;
@@ -2147,9 +2098,10 @@ ext_do_line_break(int paragraph_dir,
normalize_selector();
}
if (do_last_line_fit) {
- /* Adjust the final line of the paragraph; */
- /* Here we either reset |do_last_line_fit| or adjust the |par_fill_skip| glue.
- */
+ /*
+ 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 {
@@ -2161,12 +2113,12 @@ ext_do_line_break(int paragraph_dir,
}
}
- /* 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.)
- */
+ /*
+ 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.
+ */
/* first thing |ext_post_line_break| does is reset |dir_ptr| */
flush_node_list(dir_ptr);
@@ -2189,8 +2141,10 @@ ext_do_line_break(int paragraph_dir,
last_special_line,
second_width,
second_indent, first_width, first_indent, best_line);
- /* /Break the paragraph at the chosen... */
- /* Clean up the memory by removing the break nodes; */
+ /*
+ Break the paragraph at the chosen ...Clean up the memory by removing
+ the break nodes.
+ */
clean_up_the_memory();
}
diff --git a/Build/source/texk/web2c/luatexdir/tex/mainbody.h b/Build/source/texk/web2c/luatexdir/tex/mainbody.h
index 1cbd214e016..046dd212152 100644
--- a/Build/source/texk/web2c/luatexdir/tex/mainbody.h
+++ b/Build/source/texk/web2c/luatexdir/tex/mainbody.h
@@ -21,7 +21,6 @@
#ifndef MAINBODY_H
# define MAINBODY_H
-extern int luatex_svn;
extern int luatex_version;
extern int luatex_revision;
extern int luatex_date_info;
@@ -218,7 +217,6 @@ is conditionally compiled in the C code.
# define fix_date_and_time() dateandtime(int_par(time_code),int_par(day_code),int_par(month_code),int_par(year_code))
-extern int get_luatexsvn(void);
extern int get_luatexversion(void);
extern str_number get_luatexrevision(void);
extern int get_luatex_date_info(void);
diff --git a/Build/source/texk/web2c/luatexdir/tex/mainbody.w b/Build/source/texk/web2c/luatexdir/tex/mainbody.w
index 745a1531019..5936def5b9f 100644
--- a/Build/source/texk/web2c/luatexdir/tex/mainbody.w
+++ b/Build/source/texk/web2c/luatexdir/tex/mainbody.w
@@ -225,11 +225,6 @@ int get_luatexversion(void)
return luatex_version;
}
-int get_luatexsvn(void)
-{
- return luatex_svn;
-}
-
str_number get_luatexrevision(void)
{
return luatex_revision;
@@ -409,7 +404,7 @@ void main_body(void)
if (bad > 0) {
goto FINAL_END;
}
- print_banner(luatex_version_string, luatex_svn);
+ print_banner(luatex_version_string);
/* Get the first line of input and prepare to start */
/* When we begin the following code, \TeX's tables may still contain garbage;
@@ -441,10 +436,7 @@ void main_body(void)
if (draft_mode_option != 0) {
int_par(draft_mode_code) = draft_mode_value;
}
- /* this is specific for the pdf backend */
- if (int_par(draft_mode_code) != 0) { /* should move */
- static_pdf->draftmode = int_par(draft_mode_code);
- }
+ /* can this be moved? */
pdf_init_map_file((char *) pdftex_map);
/* */
if (end_line_char_inactive)
@@ -493,7 +485,6 @@ This program doesn't bother to close the input files that may still be open.
void close_files_and_terminate(void)
{
int callback_id;
- PDF pdf = static_pdf;
callback_id = callback_defined(stop_run_callback);
finalize_write_files();
if (int_par(tracing_stats_code) > 0) {
@@ -532,26 +523,9 @@ void close_files_and_terminate(void)
}
wake_up_terminal();
/* rubish, these pdf arguments, passed, needs to be fixed, e.g. with a dummy in dvi */
- ensure_output_state(pdf, ST_OMODE_FIX);
- switch (output_mode_used) {
- case OMODE_NONE: /* during initex run */
- break;
- case OMODE_PDF:
- if (history == fatal_error_stop) {
- remove_pdffile(pdf);
- print_err(" ==> Fatal error occurred, no output PDF file produced!");
- } else
- finish_pdf_file(pdf, luatex_version, get_luatexrevision());
- break;
- case OMODE_DVI:
- finish_dvi_file(pdf, luatex_version, get_luatexrevision());
- break;
- default:
- assert(0);
- }
+ wrapup_backend();
/* Close {\sl Sync\TeX} file and write status */
synctexterminate(log_opened_global); /* Let the {\sl Sync\TeX} controller close its files. */
-
free_text_codes();
free_math_codes();
if (log_opened_global) {
diff --git a/Build/source/texk/web2c/luatexdir/tex/maincontrol.w b/Build/source/texk/web2c/luatexdir/tex/maincontrol.w
index 0219320ec41..c6b30b09921 100644
--- a/Build/source/texk/web2c/luatexdir/tex/maincontrol.w
+++ b/Build/source/texk/web2c/luatexdir/tex/maincontrol.w
@@ -19,7 +19,6 @@
@ @c
-
#include "ptexlib.h"
#include "lua/luatex-api.h"
@@ -49,9 +48,7 @@
#define no_local_whatsits int_par(no_local_whatsits_code)
#define no_local_dirs int_par(no_local_dirs_code)
#define err_help equiv(err_help_loc)
-#define text_direction int_par(text_direction_code)
#define every_par equiv(every_par_loc)
-#define par_direction int_par(par_direction_code)
#define page_left_offset dimen_par(page_left_offset_code)
#define page_top_offset dimen_par(page_top_offset_code)
@@ -142,7 +139,6 @@ with particular care.
static halfword main_p; /* temporary register for list manipulation */
static halfword main_s; /* space factor value */
-
@ 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
@@ -164,7 +160,6 @@ void adjust_space_factor(void)
}
}
-
@ From Knuth: ``Having |font_glue| allocated for each text font saves
both time and memory.'' That may be true, but it also punches through
the API wall for fonts, so I removed that -- Taco. But a bit of caching
@@ -185,7 +180,6 @@ its values.
static int main_control_state;
-
@* Main control helpers.
Here are all the functions that are called from |main_control| that
@@ -217,11 +211,16 @@ see to it later that the corresponding glue specification is precisely
to be full of zeroes. Therefore it is simple to test whether a glue parameter
is zero or~not.
-
@c
static void run_app_space (void) {
- if ((abs(mode) + cur_cmd == hmode + spacer_cmd)
- && (!(space_factor == 1000))) {
+ int method = int_par(disable_space_code) ;
+ if (method == 1) {
+ /* don't inject anything, not even zero skip */
+ } else if (method == 2) {
+ temp_ptr = new_glue(zero_glue);
+ couple_nodes(tail,temp_ptr);
+ tail = temp_ptr;
+ } else if ((abs(mode) + cur_cmd == hmode + spacer_cmd) && (!(space_factor == 1000))) {
app_space();
} else {
/* Append a normal inter-word space to the current list */
@@ -238,14 +237,12 @@ static void run_app_space (void) {
space_spec_font = cur_font;
}
main_p = space_spec_cache;
-
temp_ptr = new_glue(main_p);
} else {
temp_ptr = new_param_glue(space_skip_code);
}
couple_nodes(tail,temp_ptr);
tail = temp_ptr;
-
}
}
@@ -266,7 +263,6 @@ static void run_boundary (void) {
tail = n;
}
-
@ @c
static void run_char_ghost (void) {
int t;
@@ -300,12 +296,11 @@ static void run_ignore_spaces (void) {
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(); /* get_token_lua(); */
+ get_next();
scanner_status = t;
cur_cs = prim_lookup(cs_text(cur_cs));
if (cur_cs != undefined_primitive) {
@@ -729,7 +724,7 @@ static void run_option(void) {
scan_int();
word_define(int_base+math_use_old_fraction_scaling_code, cur_val);
} else {
- normal_warning("mathoption","unknown key",false,false);
+ normal_warning("mathoption","unknown key");
}
break;
default:
@@ -1026,7 +1021,6 @@ void app_space(void)
width(main_p) = width(main_p) + extra_space(cur_font);
stretch(main_p) = xn_over_d(stretch(main_p), space_factor, 1000);
shrink(main_p) = xn_over_d(shrink(main_p), 1000, space_factor);
-
q = new_glue(main_p);
glue_ref_count(main_p) = null;
}
@@ -1055,10 +1049,6 @@ void insert_dollar_sign_par_end(void)
}
}
-
-
-
-
@ The `|you_cant|' procedure prints a line saying that the current command
is illegal in the current mode; it identifies these things symbolically.
@@ -1092,7 +1082,6 @@ void report_illegal_case(void)
error();
}
-
@ 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
@@ -1109,7 +1098,6 @@ boolean privileged(void)
}
}
-
@ 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
@@ -1151,24 +1139,24 @@ void append_glue(void)
int s; /* modifier of skip command */
s = cur_chr;
switch (s) {
- case fil_code:
- cur_val = fil_glue;
- break;
- case fill_code:
- cur_val = fill_glue;
- break;
- case ss_code:
- cur_val = ss_glue;
- break;
- case fil_neg_code:
- cur_val = fil_neg_glue;
- break;
- case skip_code:
- scan_glue(glue_val_level);
- break;
- case mskip_code:
- scan_glue(mu_val_level);
- break;
+ case fil_code:
+ cur_val = fil_glue;
+ break;
+ case fill_code:
+ cur_val = fill_glue;
+ break;
+ case ss_code:
+ cur_val = ss_glue;
+ break;
+ case fil_neg_code:
+ cur_val = 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));
if (s >= skip_code) {
@@ -1188,7 +1176,6 @@ void append_kern(void)
subtype(tail) = (quarterword) s;
}
-
@ 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.
@@ -1218,28 +1205,27 @@ void off_save(void)
/* 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;
+ 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.",
@@ -1251,7 +1237,6 @@ void off_save(void)
}
}
-
@ 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
@@ -1267,112 +1252,112 @@ void handle_right_brace(void)
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;
- case hbox_group:
- /* 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. */
- 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 = split_top_skip;
- add_glue_ref(q);
- d = split_max_depth;
- f = floating_penalty;
- unsave();
- save_ptr--;
- /* 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);
- delete_glue_ref(q);
- } else {
- confusion("insert_group");
- }
- list_ptr(p) = null;
- flush_node(p);
- if (nest_ptr == 0) {
- check_filter(insert);
- build_page();
- }
- break;
- case output_group:
- /* this is needed in case the \.{\\output} executes a \.{\\textdir} command. */
- if (dir_level(text_dir_ptr) == cur_level) {
- /* DIR: 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;
+ 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;
+ case hbox_group:
+ /* 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. */
+ 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 = split_top_skip;
+ add_glue_ref(q);
+ d = split_max_depth;
+ f = floating_penalty;
+ unsave();
+ save_ptr--;
+ /* 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);
+ delete_glue_ref(q);
+ } else {
+ confusion("insert_group");
+ }
+ list_ptr(p) = null;
+ flush_node(p);
+ if (nest_ptr == 0) {
+ check_filter(insert);
+ build_page();
+ }
+ break;
+ case output_group:
+ /* this is needed in case the \.{\\output} executes a \.{\\textdir} command. */
+ if (dir_level(text_dir_ptr) == cur_level) {
+ /* DIR: 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;
}
}
@@ -1381,15 +1366,15 @@ 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;
+ 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",
@@ -1400,7 +1385,6 @@ void extra_right_brace(void)
incr(align_state);
}
-
@ 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.
@@ -1419,7 +1403,6 @@ void normal_paragraph(void)
eq_define(inter_line_penalties_loc, shape_ref_cmd, null);
}
-
@ 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|
@@ -1428,7 +1411,6 @@ case can occur only with leaders.
@c
halfword cur_box; /* box to be placed into its context */
-
@ The |box_end| procedure does the right thing with |cur_box|, if
|box_context| represents the context as explained above.
@@ -1456,7 +1438,7 @@ void box_end(int box_context)
append_list(adjust_head, adjust_tail);
adjust_tail = null;
}
- if (mode > 0) {
+ if (mode > 0) {
check_filter(box);
build_page();
}
@@ -1469,15 +1451,12 @@ void box_end(int box_context)
tail = cur_box;
}
}
-
} else if (box_context < ship_out_flag) {
/* 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);
-
+ geq_define(box_base + box_context - global_box_flag, box_ref_cmd, cur_box);
} else if (cur_box != null) {
if (box_context > ship_out_flag) {
/* Append a new leader node that uses |cur_box| */
@@ -1485,12 +1464,10 @@ void box_end(int box_context)
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));
+ subtype(tail) = (quarterword) (box_context - (leader_flag - a_leaders));
leader_ptr(tail) = cur_box;
} else {
print_err("Leaders not followed by proper glue");
@@ -1501,9 +1478,9 @@ void box_end(int box_context)
back_error();
flush_node_list(cur_box);
}
-
- } else
+ } else {
ship_out(static_pdf, cur_box, SHIPPING_PAGE);
+ }
}
}
@@ -1516,7 +1493,6 @@ void scan_box(int box_context)
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) &&
@@ -1547,7 +1523,6 @@ void new_graf(boolean indented)
space_factor = 1000;
/* LOCAL: Add local paragraph node */
tail_append(make_local_par_node());
-
if (indented) {
p = new_null_box();
box_dir(p) = par_direction;
@@ -1598,7 +1573,7 @@ void indent_in_hmode(void)
void head_for_vmode(void)
{
if (mode < 0) {
- if (cur_cmd != hrule_cmd) {
+ if ((cur_cmd != hrule_cmd) && (cur_cmd != no_hrule_cmd)) {
off_save();
} else {
print_err("You can't use `\\hrule' here except with leaders");
@@ -1614,7 +1589,6 @@ void head_for_vmode(void)
}
}
-
@ TODO (BUG?): |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 is probably
@@ -1640,7 +1614,6 @@ void end_graf(int line_break_context)
}
}
-
@ @c
void begin_insert_or_adjust(void)
{
@@ -1668,7 +1641,6 @@ void begin_insert_or_adjust(void)
prev_depth = ignore_depth;
}
-
@ 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
@@ -1705,7 +1677,6 @@ void handle_mark(void)
}
}
-
@ @c
void append_penalty(void)
{
@@ -1717,7 +1688,6 @@ void append_penalty(void)
}
}
-
@ When |delete_last| is called, |cur_chr| is the |type| of node that
will be deleted, if present.
@@ -1752,7 +1722,6 @@ void delete_last(void)
}
error();
}
-
} else {
/* todo: clean this up */
if (!is_char_node(tail)) {
@@ -1845,7 +1814,6 @@ void append_italic_correction(void)
}
}
-
@ @c
void append_local_box(int kind)
{
@@ -1858,7 +1826,6 @@ void append_local_box(int kind)
space_factor = 1000;
}
-
@ Discretionary nodes are easy in the common case `\.{\\-}', but in the
general case we must process three braces full of items.
@@ -1930,7 +1897,6 @@ void build_local_box(void)
eq_word_define(int_base + no_local_whatsits_code, no_local_whatsits + 1);
}
-
@ 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.)
@@ -2014,7 +1980,6 @@ void build_discretionary(void)
space_factor = 1000;
}
-
@ 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
@@ -2085,7 +2050,6 @@ void make_accent(void)
}
}
-
@ 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
@@ -2135,7 +2099,6 @@ void align_error(void)
}
}
-
@ The help messages here contain a little white lie, since \.{\\noalign}
and \.{\\omit} are allowed also after `\.{\\noalign\{...\}}'.
@@ -2156,7 +2119,6 @@ void omit_error(void)
error();
}
-
@ 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.
@@ -2199,7 +2161,6 @@ void cs_error(void)
error();
}
-
@
Assignments to values in |eqtb| can be global or local. Furthermore, a
control sequence can be defined to be `\.{\\long}', `\.{\\protected}',
@@ -2215,8 +2176,6 @@ void cs_error(void)
a sequence of prefixes until coming to a non-prefix, then it carries out
the command.
-
-
@ If the user says, e.g., `\.{\\global\\global}', the redundancy is
silently accepted.
@@ -2238,8 +2197,7 @@ following program is careful to check each case properly.
error(); \
cur_val=0; \
} \
- } while (0)
-
+} while (0)
@ @c
void prefixed_command(void)
@@ -2288,7 +2246,6 @@ void prefixed_command(void)
help1("I'll pretend you didn't say \\long or \\outer or \\protected here.");
error();
}
-
/* Adjust for the setting of \.{\\globaldefs} */
if (global_defs != 0) {
if (global_defs < 0) {
@@ -2300,226 +2257,250 @@ void prefixed_command(void)
}
}
switch (cur_cmd) {
- case set_font_cmd:
- /* 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:
- /* 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 >= 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;
- get_r_token();
- p = cur_cs;
- if (n == normal) {
- do {
+ case set_font_cmd:
+ /* 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:
+ /* 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 >= 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;
+ if (n == normal) {
+ 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();
+ }
+ } else if (n == normal + 1) {
+ /* futurelet */
+ get_r_token();
+ p = cur_cs;
get_token();
- } while (cur_cmd == spacer_cmd);
- if (cur_tok == other_token + '=') {
+ q = cur_tok;
get_token();
- if (cur_cmd == spacer_cmd)
- get_token();
+ back_input();
+ cur_tok = q;
+ /* look ahead, then back up */
+ /* note that |back_input| doesn't affect |cur_cmd|, |cur_chr| */
+ back_input();
+ } else {
+ /* letcharcode */
+ scan_int();
+ if (cur_val > 0) {
+ cur_cs = active_to_cs(cur_val, true);
+ set_token_info(cur_cs, cur_cs + cs_token_flag);
+ 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();
+ }
+ } else {
+ p = null;
+ tex_error("invalid number for \\letcharcode",NULL);
+ }
}
- } else {
- get_token();
- q = cur_tok;
- get_token();
- back_input();
- cur_tok = q;
- back_input(); /* look ahead, then back up */
- } /* note that |back_input| doesn't affect |cur_cmd|, |cur_chr| */
- if (cur_cmd >= call_cmd)
- add_token_ref(cur_chr);
- define(p, cur_cmd, cur_chr);
- break;
- case shorthand_def_cmd:
- /* 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);
- 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);
+ if (cur_cmd >= call_cmd)
+ add_token_ref(cur_chr);
+ define(p, cur_cmd, cur_chr);
break;
- default:
- scan_register_num();
+ case shorthand_def_cmd:
+ /* 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 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);
+ case char_def_code:
+ scan_char_num();
+ define(p, char_given_cmd, cur_val);
break;
- case dimen_def_code:
- define(p, assign_dimen_cmd, scaled_base + cur_val);
+ case math_char_def_code:
+ mval = scan_mathchar(tex_mathcode);
+ cur_val =
+ (mval.class_value * 16 + mval.family_value) * 256 +
+ mval.character_value;
+ define(p, math_given_cmd, cur_val);
break;
- case skip_def_code:
- define(p, assign_glue_cmd, skip_base + cur_val);
+ 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 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);
+ 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:
- confusion("shorthand_def");
+ 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;
- }
- 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:
- /* 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 {
- p = cur_chr; /* |p=every_par_loc| or |output_routine_loc| or \dots */
- }
- scan_optional_equals();
- /* 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) {
- /* If the right-hand side is a token parameter
- or token register, finish the assignment and |goto done| */
+ 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:
+ /* 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();
- cur_cmd = assign_toks_cmd;
- cur_chr = toks_base + cur_val;
+ p = toks_base + cur_val;
+ } else {
+ p = cur_chr; /* |p=every_par_loc| or |output_routine_loc| or \dots */
}
- 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);
+ scan_optional_equals();
+ /* 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) {
+ /* 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;
}
- 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);
+ 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);
}
- define(p, call_cmd, def_ref);
- }
- break;
- case assign_int_cmd:
- /* 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_dir_cmd:
- /* DIR: Assign direction codes */
- 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);
+ case assign_int_cmd:
+ /* 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 int_base + math_direction_code:
- eq_word_define(int_base + math_direction_code, cur_val);
+ 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 int_base + text_direction_code:
+ case assign_dir_cmd:
+ /* DIR: Assign direction codes */
+ 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:
#if 0
/* various tests hint that this is unnecessary and
* sometimes even produces weird results, eg
@@ -2528,319 +2509,322 @@ void prefixed_command(void)
* (DEFCBA)
* in the output
*/
- if ((no_local_dirs > 0) && (abs(mode) == hmode)) {
- /* DIR: Add local dir node */
- tail_append(new_dir(text_direction));
- }
+ if ((no_local_dirs > 0) && (abs(mode) == hmode)) {
+ /* DIR: Add local dir node */
+ tail_append(new_dir(text_direction));
+ }
#endif
- update_text_dir_ptr(cur_val);
- if (abs(mode) == hmode) {
- /* DIR: Add local dir node */
- tail_append(new_dir(cur_val));
- dir_level(tail) = cur_level;
+ update_text_dir_ptr(cur_val);
+ if (abs(mode) == hmode) {
+ /* DIR: Add local dir node */
+ tail_append(new_dir(cur_val));
+ dir_level(tail) = cur_level;
+ }
+ eq_word_define(int_base + text_direction_code, cur_val);
+ eq_word_define(int_base + no_local_dirs_code, no_local_dirs + 1);
+ break;
}
- eq_word_define(int_base + text_direction_code, cur_val);
- eq_word_define(int_base + no_local_dirs_code, no_local_dirs + 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);
- trap_zero_glue();
- define(p, glue_ref_cmd, cur_val);
- break;
- case def_char_code_cmd:
- case def_del_code_cmd:
- /* 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;
+ 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);
+ trap_zero_glue();
+ define(p, glue_ref_cmd, cur_val);
+ break;
+ case def_char_code_cmd:
+ case def_del_code_cmd:
+ /* 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) {
+ 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;
- 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;
+ 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_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_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();
- scan_int();
- check_def_code(cat_code_base);
- define_cat_code(p, cur_val);
- } else if (cur_chr == del_code_base) {
+ 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);
+ trap_zero_glue();
+ if (cur_val == glue_par(thin_mu_skip_code))
+ cur_val = thin_mu_skip_code;
+ else if (cur_val == glue_par(med_mu_skip_code))
+ cur_val = med_mu_skip_code;
+ else if (cur_val == glue_par(thick_mu_skip_code))
+ 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:
+ /* 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))
- 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();
+ n = global_box_flag + cur_val;
else
- scan_dimen(false, false, false);
- } else {
- scan_glue(mu_val_level);
- trap_zero_glue();
- if (cur_val == glue_par(thin_mu_skip_code))
- cur_val = thin_mu_skip_code;
- else if (cur_val == glue_par(med_mu_skip_code))
- cur_val = med_mu_skip_code;
- else if (cur_val == glue_par(thick_mu_skip_code))
- 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:
- /* 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");
- help2("Sorry, \\setbox is not allowed after \\halign in a display,",
- "or between \\accent and an accented character.");
- error();
- }
- break;
- case set_aux_cmd:
- /* 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:
- /* 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 */
+ n = box_flag + cur_val;
+ scan_optional_equals();
+ if (set_box_allowed) {
+ scan_box(n);
+ } else {
+ print_err("Improper \\setbox");
+ help2("Sorry, \\setbox is not allowed after \\halign in a display,",
+ "or between \\accent and an accented character.");
+ error();
}
- if (!odd(n))
- varmem[p + n + 3].cint = 0; /* unused */
- }
- define(q, shape_ref_cmd, p);
- break;
- case hyph_data_cmd:
- /* 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();
+ case set_aux_cmd:
+ /* 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 3:
- new_post_hyphen_char();
+ case set_prev_graf_cmd:
+ alter_prev_graf();
break;
- case 4:
- new_pre_exhyphen_char();
+ case set_page_dimen_cmd:
+ alter_page_so_far();
break;
- case 5:
- new_post_exhyphen_char();
+ case set_page_int_cmd:
+ alter_integer();
break;
- case 6:
- new_hyphenation_min();
+ case set_box_dimen_cmd:
+ /* 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;
- }
- 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) {
+ case set_tex_shape_cmd:
+ q = cur_chr;
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;
+ 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();
- 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;
+ 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 */
}
- }
- break;
- case def_font_cmd:
- /* Here is where the information for a new font gets loaded. */
- tex_def_font((small_number) a);
- 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;
+ define(q, shape_ref_cmd, p);
+ break;
+ case hyph_data_cmd:
+ /* 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:
+ /* Here is where the information for a new font gets loaded. */
+ tex_def_font((small_number) a);
+ 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;
} /* end of Assignments cases */
DONE:
/* Insert a token saved by \.{\\afterassignment}, if any */
@@ -2854,36 +2838,29 @@ void prefixed_command(void)
@ @c
void fixup_directions(void)
{
- int temp_no_whatsits;
- int temp_no_dirs;
- int temporary_dir;
- temp_no_whatsits = no_local_whatsits;
- temp_no_dirs = no_local_dirs;
- temporary_dir = text_direction;
+ int temp_no_whatsits = no_local_whatsits;
+ int temp_no_dirs = no_local_dirs;
+ int temporary_dir = text_direction;
if (dir_level(text_dir_ptr) == cur_level) {
/* DIR: 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) {
/* DIR: Add local dir node */
tail_append(new_dir(text_direction));
-
dir_dir(tail) = temporary_dir - dir_swap;
}
if (temp_no_whatsits != 0) {
/* LOCAL: Add local paragraph node */
tail_append(make_local_par_node());
-
}
}
}
-
@ 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.
@@ -2963,7 +2940,7 @@ void assign_internal_value(int a, halfword p, int val)
break;
case language_code:
if (val < 0) {
- word_define(int_base + cur_lang_code, -1);
+ word_define(int_base + cur_lang_code, -1);
word_define(p, -1);
} else if (val > 16383) {
print_err("Invalid \\language");
@@ -2972,7 +2949,7 @@ void assign_internal_value(int a, halfword p, int val)
"Your invalid assignment will be ignored.");
error();
} else {
- word_define(int_base + cur_lang_code, val);
+ word_define(int_base + cur_lang_code, val);
word_define(p, val);
}
break;
@@ -2994,7 +2971,6 @@ void assign_internal_value(int a, halfword p, int val)
eq_word_define(int_base + no_local_whatsits_code,
no_local_whatsits + 1);
}
-
} else if ((p >= dimen_base) && (p <= eqtb_size)) {
if (p == (dimen_base + page_left_offset_code)) {
n = val - one_true_inch;
@@ -3010,7 +2986,6 @@ void assign_internal_value(int a, halfword p, int val)
word_define(dimen_base + page_top_offset_code, n);
}
word_define(p, val);
-
} else if ((p >= local_base) && (p < toks_base)) { /* internal locals */
define(p, call_cmd, val);
} else {
@@ -3018,7 +2993,6 @@ void assign_internal_value(int a, halfword p, int val)
}
}
-
@ When a glue register or parameter becomes zero, it will always point to
|zero_glue| because of the following procedure. (Exception: The tabskip
glue isn't trapped while preambles are being scanned.)
@@ -3036,16 +3010,16 @@ void trap_zero_glue(void)
@ We use the fact that |register<advance<multiply<divide|
+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.
+
@c
void do_register_command(int a)
{
- halfword l, q, r, s; /* for list manipulation */
- int p; /* type of register involved */
- q = cur_cmd;
- /* 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. */
- l = 0;
+ 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)) {
@@ -3075,12 +3049,11 @@ void do_register_command(int a)
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")) {
- ; /* optional `\.{by}' */
+ /* optional `\.{by}' */
}
arith_error = false;
if (q < multiply_cmd) {
@@ -3096,8 +3069,8 @@ void do_register_command(int a)
scan_glue(p);
if (q == advance_cmd) {
/* Compute the sum of two glue specs */
+ halfword r = equiv(l);
q = new_spec(cur_val);
- r = equiv(l);
delete_glue_ref(cur_val);
width(q) = width(q) + width(r);
if (stretch(q) == 0) {
@@ -3123,7 +3096,6 @@ void do_register_command(int a)
cur_val = q;
}
}
-
} else {
/* Compute result of |multiply| or |divide|, put it in |cur_val| */
scan_int();
@@ -3138,8 +3110,8 @@ void do_register_command(int a)
cur_val = x_over_n(eqtb[l].cint, cur_val);
}
} else {
- s = equiv(l);
- r = new_spec(s);
+ 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);
@@ -3151,7 +3123,6 @@ void do_register_command(int a)
}
cur_val = r;
}
-
}
if (arith_error) {
print_err("Arithmetic overflow");
@@ -3178,7 +3149,6 @@ void do_register_command(int a)
}
}
-
@ @c
void alter_aux(void)
{
@@ -3270,7 +3240,6 @@ void alter_box_dimen(void)
varmem[box(b) + c].cint = cur_val;
}
-
@ @c
void new_interaction(void)
{
@@ -3283,7 +3252,6 @@ void new_interaction(void)
fixup_selector(log_opened_global);
}
-
@ The \.{\\afterassignment} command puts a token into the global
variable |after_token|. This global variable is examined just after
every assignment has been performed.
@@ -3291,7 +3259,6 @@ every assignment has been performed.
@c
halfword after_token; /* zero, or a saved token */
-
@ Here is a procedure that might be called `Get the next non-blank non-relax
non-call non-assignment token'.
@@ -3303,7 +3270,6 @@ void do_assignments(void)
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;
@@ -3397,7 +3363,6 @@ void issue_message(void)
flush_str(s);
}
-
@ The |error| routine calls on |give_err_help| if help is requested from
the |err_help| parameter.
@@ -3407,8 +3372,6 @@ void give_err_help(void)
token_show(err_help);
}
-
-
@ The \.{\\uppercase} and \.{\\lowercase} commands are implemented by
building a token list and then changing the cases of the letters in it.
@@ -3453,7 +3416,6 @@ void shift_case(void)
free_avail(def_ref); /* omit reference count */
}
-
@ We come finally to the last pieces missing from |main_control|, namely the
`\.{\\show}' commands that are useful when debugging.
@@ -3534,7 +3496,6 @@ void show_whatever(void)
} while (p != null);
}
break;
-
default:
/* Show the current value of some parameter or register,
then |goto common_ending| */
@@ -3557,7 +3518,6 @@ void show_whatever(void)
selector = term_and_log;
}
}
-
COMMON_ENDING:
if (interaction < error_stop_mode) {
help0();
@@ -3576,7 +3536,6 @@ void show_whatever(void)
error();
}
-
@ @c
void initialize(void)
{ /* this procedure gets things started properly */
@@ -3610,8 +3569,7 @@ void initialize(void)
initialize_marks();
initialize_read();
- assert(static_pdf == NULL);
- static_pdf = init_pdf_struct(static_pdf);
+ static_pdf = init_pdf_struct(static_pdf); /* should be init_backend() */
format_ident = 0;
format_name = get_nullstr();
@@ -3675,11 +3633,10 @@ void initialize(void)
initialize_text_codes();
initex_cat_codes(0);
for (k = '0'; k <= '9'; k++)
- set_math_code(k, tex_mathcode, var_code, 0, k, level_one);
+ set_math_code(k, var_code, 0, k, level_one);
for (k = 'A'; k <= 'Z'; k++) {
- set_math_code(k, tex_mathcode, var_code, 1, k, level_one);
- set_math_code((k + 32), tex_mathcode, var_code, 1, (k + 32),
- level_one);
+ set_math_code(k, var_code, 1, k, level_one);
+ set_math_code((k + 32), var_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);
@@ -3696,7 +3653,7 @@ void initialize(void)
max_dead_cycles = 25;
escape_char = '\\';
end_line_char = carriage_return;
- set_del_code('.', tex_mathcode, 0, 0, 0, 0, level_one); /* this null delimiter is used in error recovery */
+ set_del_code('.', 0, 0, 0, 0, level_one); /* this null delimiter is used in error recovery */
ex_hyphen_char = '-';
output_box = 255;
for (k = dimen_base; k <= eqtb_size; k++)
diff --git a/Build/source/texk/web2c/luatexdir/tex/mathcodes.h b/Build/source/texk/web2c/luatexdir/tex/mathcodes.h
index a2f84eb8411..1742e43cfd5 100644
--- a/Build/source/texk/web2c/luatexdir/tex/mathcodes.h
+++ b/Build/source/texk/web2c/luatexdir/tex/mathcodes.h
@@ -1,5 +1,5 @@
/* mathcodes.h
-
+
Copyright 2009-2012 Taco Hoekwater <taco@luatex.org>
This file is part of LuaTeX.
@@ -15,33 +15,30 @@
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/>. */
+ with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
+*/
#ifndef MATHCODES_H
# define MATHCODES_H
-/* mathcodes.c */
+/* this is a flag for |scan_delimiter| */
-# define no_mathcode 0 /* this is a flag for |scan_delimiter| */
-# define tex_mathcode 8
-# define umath_mathcode 21
+# define no_mathcode 0
+# define tex_mathcode 8
+# define umath_mathcode 21
# define umathnum_mathcode 22
typedef struct mathcodeval {
int class_value;
- int origin_value;
int family_value;
int character_value;
} mathcodeval;
-void set_math_code(int n,
- int commandorigin,
- int mathclass,
- int mathfamily, int mathcharacter, quarterword gl);
+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, boolean compat);
+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);
@@ -51,18 +48,13 @@ void show_mathcode_value(mathcodeval d);
typedef struct delcodeval {
int class_value;
- int origin_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 commandorigin,
- int smathfamily,
- int smathcharacter,
- int lmathfamily, int lmathcharacter, quarterword gl);
+void set_del_code(int n, int smathfamily, int smathcharacter, int lmathfamily, int lmathcharacter, quarterword gl);
delcodeval get_del_code(int n);
diff --git a/Build/source/texk/web2c/luatexdir/tex/mathcodes.w b/Build/source/texk/web2c/luatexdir/tex/mathcodes.w
index ac26fc75d9d..b9ac4905f7d 100644
--- a/Build/source/texk/web2c/luatexdir/tex/mathcodes.w
+++ b/Build/source/texk/web2c/luatexdir/tex/mathcodes.w
@@ -20,19 +20,12 @@
@ @c
-
#include "ptexlib.h"
-@ math codes
+@ math codes
@c
static sa_tree mathcode_head = NULL;
-#define MATHCODEHEAP 8
-
-static mathcodeval *mathcode_heap = NULL;
-static int mathcode_heapsize = MATHCODEHEAP;
-static int mathcode_heapptr = 0;
-
/* the 0xFFFFFFFF is a flag value */
#define MATHCODESTACK 8
#define MATHCODEDEFAULT 0xFFFFFFFF
@@ -41,12 +34,6 @@ static int mathcode_heapptr = 0;
@c
static sa_tree delcode_head = NULL;
-#define DELCODEHEAP 8
-
-static delcodeval *delcode_heap = NULL;
-static int delcode_heapsize = DELCODEHEAP;
-static int delcode_heapptr = 0;
-
#define DELCODESTACK 4
#define DELCODEDEFAULT 0xFFFFFFFF
@@ -75,48 +62,38 @@ static int delcode_heapptr = 0;
} while (0)
@ @c
-void show_mathcode_value(mathcodeval c)
+mathcodeval mathchar_from_integer(int value, int extcode)
{
- if (c.origin_value == umath_mathcode) {
- print_char('"');
- print_hex_digit(c.class_value);
- print_char('"');
- two_hex(c.family_value);
- print_char('"');
- six_hex(c.character_value);
- } else if (c.origin_value == umathnum_mathcode) {
- int m;
- m = (c.class_value + (c.family_value * 8)) * 2097152 +
- c.character_value;
- print_int(m);
- } else {
- print_char('"');
- if (c.class_value) {
- print_hex_digit(c.class_value);
- print_hex_digit(c.family_value);
- two_hex(c.character_value);
- } else if (c.family_value) {
- print_hex_digit(c.family_value);
- two_hex(c.character_value);
- } else if (c.character_value >= 16) {
- two_hex(c.character_value);
- } else {
- print_hex_digit(c.character_value);
- }
+ mathcodeval mval;
+ if (extcode == tex_mathcode) {
+ mval.class_value = (value / 0x1000);
+ mval.family_value = ((value % 0x1000) / 0x100);
+ mval.character_value = (value % 0x100);
+ } else { /* some xetexended xetex thing */
+ int mfam = (value / 0x200000) & 0x7FF;
+ mval.class_value = mfam % 0x08;
+ mval.family_value = mfam / 0x08;
+ mval.character_value = value & 0x1FFFFF;
}
+ return mval;
+}
+
+@ @c
+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);
}
@ @c
static void show_mathcode(int n)
{
mathcodeval c = get_math_code(n);
- if (c.origin_value == umath_mathcode) {
- tprint_esc("Umathcode");
- } else if (c.origin_value == umathnum_mathcode) {
- tprint_esc("Umathcodenum");
- } else {
- tprint_esc("mathcode");
- }
+ tprint_esc("Umathcode");
print_int(n);
print_char('=');
show_mathcode_value(c);
@@ -128,14 +105,11 @@ 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)
- >= (int) gl) {
+ 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);
- /* now do a trace message, if requested */
- if (int_par(tracing_restores_code) > 0) {
+ if (int_par(tracing_restores_code) > 1) {
begin_diagnostic();
print_char('{');
tprint("restoring");
@@ -150,25 +124,14 @@ static void unsavemathcode(quarterword gl)
}
@ @c
-void set_math_code(int n,
- int commandorigin,
- int mathclass,
- int mathfamily, int mathcharacter, quarterword level)
+void set_math_code(int n, int mathclass, int mathfamily, int mathcharacter, quarterword level)
{
- mathcodeval d;
- d.origin_value = commandorigin;
- d.class_value = mathclass;
- d.family_value = mathfamily;
- d.character_value = mathcharacter;
- if (mathcode_heapptr == mathcode_heapsize) {
- mathcode_heapsize += MATHCODEHEAP;
- mathcode_heap =
- Mxrealloc_array(mathcode_heap, mathcodeval, mathcode_heapsize);
- }
- mathcode_heap[mathcode_heapptr] = d;
- set_sa_item(mathcode_head, n, (sa_tree_item) mathcode_heapptr, level);
- mathcode_heapptr++;
- if (int_par(tracing_assigns_code) > 0) {
+ sa_tree_item v;
+ 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 (int_par(tracing_assigns_code) > 1) {
begin_diagnostic();
print_char('{');
tprint("assigning");
@@ -180,95 +143,47 @@ void set_math_code(int n,
}
@ @c
+/* we could use two structs ... tex and umath */
+
mathcodeval get_math_code(int n)
{
- unsigned int ret;
- ret = get_sa_item(mathcode_head, n);
- if (ret == MATHCODEDEFAULT) {
- mathcodeval d;
+ 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.origin_value = (n < 256 ? tex_mathcode : umath_mathcode);
d.character_value = n;
- return d;
} else {
- return mathcode_heap[ret];
+ d.class_value = v.math_code_value.class_value;
+ d.family_value = v.math_code_value.family_value;
+ d.character_value = v.math_code_value.character_value;
}
+ return d;
}
-
@ @c
-int get_math_code_num(int n, boolean compat)
+int get_math_code_num(int n)
{
- mathcodeval mval;
- mval = get_math_code(n);
- if (compat) { /* \.{\\the\\mathcode} */
- if (mval.class_value > 8
- || mval.family_value > 15
- || mval.character_value > 255) {
- print_err("Extended mathchar used as mathchar");
- help2("A mathchar number must be between 0 and \"8000.",
- "I changed this one to zero.");
- int_error(get_math_code_num(n, false));
- return 0;
- } else
- return mval.class_value * 4096 + mval.family_value * 256 + mval.character_value;
- } else { /* \.{\\the\\Umathcodenum} */
- return (mval.class_value + (mval.family_value * 8)) * (65536 * 32) + mval.character_value;
- }
- return 0;
+ mathcodeval d = get_math_code(n);
+ return (d.class_value + (d.family_value * 8)) * (65536 * 32) + d.character_value;
}
@ @c
static void initializemathcode(void)
{
- mathcode_head = new_sa_tree(MATHCODESTACK, MATHCODEDEFAULT);
- mathcode_heap = Mxmalloc_array(mathcodeval, MATHCODEHEAP);
+ sa_tree_item sa_value = { 0 };
+ sa_value.uint_value = MATHCODEDEFAULT;
+ mathcode_head = new_sa_tree(MATHCODESTACK, 1, sa_value);
}
-@ @c
static void dumpmathcode(void)
{
- int k;
- mathcodeval d;
dump_sa_tree(mathcode_head);
- dump_int(mathcode_heapsize);
- dump_int(mathcode_heapptr);
- for (k = 0; k < mathcode_heapptr; k++) {
- d = mathcode_heap[k];
- dump_int(d.origin_value);
- dump_int(d.class_value);
- dump_int(d.family_value);
- dump_int(d.character_value);
- }
}
static void undumpmathcode(void)
{
- int k, x;
- mathcodeval d;
mathcode_head = undump_sa_tree();
- undump_int(mathcode_heapsize);
- undump_int(mathcode_heapptr);
- mathcode_heap = Mxmalloc_array(mathcodeval, mathcode_heapsize);
- for (k = 0; k < mathcode_heapptr; k++) {
- undump_int(x);
- d.origin_value = x;
- undump_int(x);
- d.class_value = x;
- undump_int(x);
- d.family_value = x;
- undump_int(x);
- d.character_value = x;
- mathcode_heap[k] = d;
- }
- d.origin_value = 0;
- d.class_value = 0;
- d.family_value = 0;
- d.character_value = 0;
- for (k = mathcode_heapptr; k < mathcode_heapsize; k++) {
- mathcode_heap[k] = d;
- }
}
@ @c
@@ -276,54 +191,30 @@ static void show_delcode(int n)
{
delcodeval c;
c = get_del_code(n);
- if (c.origin_value == tex_mathcode) {
- tprint_esc("delcode");
- } else if (c.origin_value == umath_mathcode) {
- tprint_esc("Udelcode");
- } else if (c.origin_value == umathnum_mathcode) {
- tprint_esc("Udelcodenum");
- }
+ tprint_esc("Udelcode");
print_int(n);
print_char('=');
if (c.small_family_value < 0) {
print_char('-');
print_char('1');
} else {
- if (c.origin_value == tex_mathcode) {
- print_char('"');
- print_hex_digit(c.small_family_value);
- two_hex(c.small_character_value);
- print_hex_digit(c.large_family_value);
- two_hex(c.large_character_value);
- } else if (c.origin_value == umath_mathcode) {
- print_char('"');
- two_hex(c.small_family_value);
- six_hex(c.small_character_value);
- } else if (c.origin_value == umathnum_mathcode) {
- int m;
- m = c.small_family_value * 2097152 + c.small_character_value;
- print_int(m);
- }
+ print_char('"');
+ two_hex(c.small_family_value);
+ six_hex(c.small_character_value);
}
}
-
-
-@ TODO: clean up the heap
-@c
+@ @c
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)
- >= (int) gl) {
+ 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);
- /* now do a trace message, if requested */
- if (int_par(tracing_restores_code) > 0) {
+ if (int_par(tracing_restores_code) > 1) {
begin_diagnostic();
print_char('{');
tprint("restoring");
@@ -333,33 +224,22 @@ static void unsavedelcode(quarterword gl)
end_diagnostic(false);
}
}
- (delcode_head->stack_ptr)--;
+ (mathcode_head->stack_ptr)--;
}
-
}
@ @c
-void set_del_code(int n,
- int commandorigin,
- int smathfamily,
- int smathcharacter,
- int lmathfamily, int lmathcharacter, quarterword gl)
+void set_del_code(int n, int smathfamily, int smathcharacter, int lmathfamily, int lmathcharacter, quarterword gl)
{
- delcodeval d;
- d.class_value = 0;
- d.origin_value = commandorigin;
- d.small_family_value = smathfamily;
- d.small_character_value = smathcharacter;
- d.large_family_value = lmathfamily;
- d.large_character_value = lmathcharacter;
- if (delcode_heapptr == delcode_heapsize) {
- delcode_heapsize += DELCODEHEAP;
- delcode_heap =
- Mxrealloc_array(delcode_heap, delcodeval, delcode_heapsize);
- }
- delcode_heap[delcode_heapptr] = d;
- set_sa_item(delcode_head, n, (sa_tree_item) delcode_heapptr, gl);
- if (int_par(tracing_assigns_code) > 0) {
+ 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;
+ set_sa_item(delcode_head, n, v, gl); /* always global */
+ if (int_par(tracing_assigns_code) > 1) {
begin_diagnostic();
print_char('{');
tprint("assigning");
@@ -368,26 +248,27 @@ void set_del_code(int n,
print_char('}');
end_diagnostic(false);
}
- delcode_heapptr++;
}
@ @c
delcodeval get_del_code(int n)
{
- unsigned ret;
- ret = get_sa_item(delcode_head, n);
- if (ret == DELCODEDEFAULT) {
- delcodeval d;
+ delcodeval d;
+ sa_tree_item v = get_sa_item(delcode_head, n);
+ if (v.uint_value == DELCODEDEFAULT) {
d.class_value = 0;
- d.origin_value = tex_mathcode;
d.small_family_value = -1;
d.small_character_value = 0;
d.large_family_value = 0;
d.large_character_value = 0;
- return d;
} else {
- return delcode_heap[ret];
+ 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;
}
@ this really only works for old-style delcodes!
@@ -395,74 +276,32 @@ delcodeval get_del_code(int n)
@c
int get_del_code_num(int n)
{
- unsigned ret;
- ret = get_sa_item(delcode_head, n);
- if (ret == DELCODEDEFAULT) {
+ delcodeval d = get_del_code(n);
+ if (d.small_family_value < 0) {
return -1;
} else {
- delcodeval d = delcode_heap[ret];
- if (d.origin_value == tex_mathcode) {
- return ((d.small_family_value * 256 +
- d.small_character_value) * 4096 +
- (d.large_family_value * 256) + d.large_character_value);
- } else {
- return -1;
- }
+ return ((d.small_family_value * 256 + d.small_character_value) * 4096 +
+ (d.large_family_value * 256) + d.large_character_value);
}
}
@ @c
static void initializedelcode(void)
{
- delcode_head = new_sa_tree(DELCODESTACK, DELCODEDEFAULT);
- delcode_heap = Mxmalloc_array(delcodeval, DELCODEHEAP);
+ sa_tree_item sa_value = { 0 };
+ sa_value.uint_value = DELCODEDEFAULT;
+ delcode_head = new_sa_tree(DELCODESTACK, 2, sa_value);
}
@ @c
static void dumpdelcode(void)
{
- int k;
- delcodeval d;
dump_sa_tree(delcode_head);
- dump_int(delcode_heapsize);
- dump_int(delcode_heapptr);
- for (k = 0; k < delcode_heapptr; k++) {
- d = delcode_heap[k];
- dump_int(d.origin_value);
- dump_int(d.class_value);
- dump_int(d.small_family_value);
- dump_int(d.small_character_value);
- dump_int(d.large_family_value);
- dump_int(d.large_character_value);
- }
}
static void undumpdelcode(void)
{
- int k;
- delcodeval d;
delcode_head = undump_sa_tree();
- undump_int(delcode_heapsize);
- undump_int(delcode_heapptr);
- delcode_heap = Mxmalloc_array(delcodeval, delcode_heapsize);
- for (k = 0; k < delcode_heapptr; k++) {
- undump_int(d.origin_value);
- undump_int(d.class_value);
- undump_int(d.small_family_value);
- undump_int(d.small_character_value);
- undump_int(d.large_family_value);
- undump_int(d.large_character_value);
- delcode_heap[k] = d;
- }
- d.origin_value = tex_mathcode;
- d.class_value = 0;
- d.small_family_value = -1;
- d.small_character_value = 0;
- d.large_family_value = 0;
- d.large_character_value = 0;
- for (k = delcode_heapptr; k < delcode_heapsize; k++) {
- delcode_heap[k] = d;
- }
}
@ @c
@@ -483,9 +322,7 @@ void initialize_math_codes(void)
void free_math_codes(void)
{
destroy_sa_tree(mathcode_head);
- xfree(mathcode_heap);
destroy_sa_tree(delcode_head);
- xfree(delcode_heap);
}
@ @c
diff --git a/Build/source/texk/web2c/luatexdir/tex/mlist.h b/Build/source/texk/web2c/luatexdir/tex/mlist.h
index 1f6551cea69..b2600bcff1b 100644
--- a/Build/source/texk/web2c/luatexdir/tex/mlist.h
+++ b/Build/source/texk/web2c/luatexdir/tex/mlist.h
@@ -27,11 +27,11 @@ extern int cur_size;
/* extern int math_no_italic_compensation ; */ /* $$\int\limits_{|}^{|}$$ */
/* extern int math_no_char_italic ; */ /* catcode"1D443=12 $$P( PP$$ \catcode"1D443=11 $$P( PP$$ */
-extern void run_mlist_to_hlist(halfword, int, boolean);
+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(int a);
-extern void mlist_to_hlist_args(halfword, int, boolean);
#endif
diff --git a/Build/source/texk/web2c/luatexdir/tex/mlist.w b/Build/source/texk/web2c/luatexdir/tex/mlist.w
index a948d42b1a1..035ef6340dd 100644
--- a/Build/source/texk/web2c/luatexdir/tex/mlist.w
+++ b/Build/source/texk/web2c/luatexdir/tex/mlist.w
@@ -76,6 +76,7 @@ already apply that shift.
#define script_space dimen_par(script_space_code)
#define disable_lig int_par(disable_lig_code)
#define disable_kern int_par(disable_kern_code)
+#define disable_space int_par(disable_space_code)
#define scripts_mode int_par(math_scripts_mode_code)
#define nDEBUG
@@ -1571,7 +1572,7 @@ static void math_kern(pointer p, scaled m)
}
@ @c
-void run_mlist_to_hlist(halfword p, int mstyle, boolean penalties)
+void run_mlist_to_hlist(halfword p, boolean penalties, int mstyle)
{
int callback_id;
int a, sfix;
@@ -1605,7 +1606,7 @@ void run_mlist_to_hlist(halfword p, int mstyle, boolean penalties)
lua_settop(L, sfix);
vlink(temp_head) = a;
} else if (callback_id == 0) {
- mlist_to_hlist_args(p, mstyle, penalties);
+ mlist_to_hlist(p, penalties, mstyle);
} else {
vlink(temp_head) = null;
}
@@ -1644,7 +1645,7 @@ static pointer clean_box(pointer p, int s, int cur_style)
q = new_null_box();
goto FOUND;
}
- mlist_to_hlist_args(mlist, s, false);
+ mlist_to_hlist(mlist, false, s);
q = vlink(temp_head); /* recursive call */
setup_cur_size(cur_style);
FOUND:
@@ -3758,7 +3759,7 @@ static pointer check_nucleus_complexity(halfword q, scaled * delta, int cur_styl
p = math_list(nucleus(q));
break;
case sub_mlist_node:
- mlist_to_hlist_args(math_list(nucleus(q)), cur_style, false); /* recursive call */
+ mlist_to_hlist(math_list(nucleus(q)), false, cur_style); /* recursive call */
setup_cur_size(cur_style);
p = hpack(vlink(temp_head), 0, additional, -1);
reset_attributes(p, node_attr(nucleus(q)));
@@ -3773,29 +3774,25 @@ static pointer check_nucleus_complexity(halfword q, scaled * delta, int cur_styl
local variables.
@c
-static void mlist_to_hlist(pointer mlist, boolean penalties, int cur_style)
+void mlist_to_hlist(pointer mlist, boolean penalties, int cur_style)
{
- pointer q; /* runs through the mlist */
- pointer r; /* the most recent noad preceding |q| */
- int style;
- int r_type; /* the |type| of noad |r|, or |op_noad| if |r=null| */
- int r_subtype; /* the |subtype| of noad |r| if |r_type| is |fence_noad| */
- int t; /* the effective |type| of noad |q| during the second pass */
- int t_subtype; /* the effective |subtype| of noad |q| during the second pass */
- pointer p, x, y, z; /* temporary registers for list construction */
- int pen; /* a penalty to be inserted */
- scaled max_hl, max_d; /* maximum height and depth of the list translated so far */
- scaled delta; /* italic correction offset for subscript and superscript */
- scaled cur_mu; /* the math unit width corresponding to |cur_size| */
- style = cur_style; /* tuck global parameter away as local variable */
- q = mlist;
- r = null;
- r_type = simple_noad;
+ pointer q = mlist; /* runs through the mlist */
+ pointer r = null; /* the most recent noad preceding |q| */
+ int style = cur_style; /* tuck global parameter away as local variable */
+ int r_type = simple_noad; /* the |type| of noad |r|, or |op_noad| if |r=null| */
+ int r_subtype = op_noad_type_normal; /* the |subtype| of noad |r| if |r_type| is |fence_noad| */
+ int t; /* the effective |type| of noad |q| during the second pass */
+ int t_subtype; /* the effective |subtype| of noad |q| during the second pass */
+ pointer p = null;
+ pointer x = null;
+ pointer y = null;
+ pointer z = null;
+ int pen; /* a penalty to be inserted */
+ scaled max_hl = 0; /* maximum height of the list translated so far */
+ scaled max_d = 0; /* maximum depth of the list translated so far */
+ scaled delta; /* italic correction offset for subscript and superscript */
+ scaled cur_mu; /* the math unit width corresponding to |cur_size| */
r_subtype = op_noad_type_normal;
- max_hl = 0;
- max_d = 0;
- x = null;
- p = null;
setup_cur_size(cur_style);
cur_mu = x_over_n(get_math_quad(cur_size), 18);
while (q != null) {
@@ -4171,12 +4168,3 @@ static void mlist_to_hlist(pointer mlist, boolean penalties, int cur_style)
free_node(r, get_node_size(type(r), subtype(r)));
}
}
-
-@ This used to be needed when |mlist_to_hlist| communicated via global
-variables.
-
-@c
-void mlist_to_hlist_args(pointer n, int w, boolean m)
-{
- mlist_to_hlist(n, m, w);
-}
diff --git a/Build/source/texk/web2c/luatexdir/tex/packaging.h b/Build/source/texk/web2c/luatexdir/tex/packaging.h
index c431ed15396..c3af41a123b 100644
--- a/Build/source/texk/web2c/luatexdir/tex/packaging.h
+++ b/Build/source/texk/web2c/luatexdir/tex/packaging.h
@@ -15,8 +15,8 @@
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/>. */
-
+ with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
+*/
#ifndef PACKAGING_H
# define PACKAGING_H
@@ -24,28 +24,27 @@
/* 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 */
+ 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 */
+# 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);
+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 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 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 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);
@@ -56,95 +55,95 @@ 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); \
+# 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);
+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 halfword filtered_hpack(halfword p, halfword qt, scaled w, int m,
- int grp, int d);
-
-extern scaled_whd natural_sizes(halfword p, halfword pp, glue_ratio g_mult,
- int g_sign, int g_order, int d);
extern int pack_begin_line;
-# define vpack(A,B,C,D) vpackage(A,B,C,max_dimen,D) /* special case of unconstrained depth */
-
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);
+extern halfword filtered_vpackage(halfword p, scaled h, int m, scaled l, int grp, int d, int just_pack);
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| */
+# 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); /* extracts a page of height |h| from box |n| */
+extern halfword vsplit(halfword n, scaled h); /* 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 vtop_code 4 /* |chr_code| for `\.{\\vtop}' */
+# 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} */
+# 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 */
+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
+
+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
+
+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.
+|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 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 leader_flag ship_out_flag+1 /* context code for `\.{\\leaders}' */
+# define ship_out_flag (max_global_box_flag+1) /* context code for `\.{\\shipout}' */
+# define leader_flag ship_out_flag+1 /* context code for `\.{\\leaders}' */
extern void begin_box(int box_context);
diff --git a/Build/source/texk/web2c/luatexdir/tex/packaging.w b/Build/source/texk/web2c/luatexdir/tex/packaging.w
index 173b7894cb2..b1e8c44425e 100644
--- a/Build/source/texk/web2c/luatexdir/tex/packaging.w
+++ b/Build/source/texk/web2c/luatexdir/tex/packaging.w
@@ -1,4 +1,4 @@
-4% packaging.w
+% packaging.w
%
% Copyright 2009-2010 Taco Hoekwater <taco@@luatex.org>
%
@@ -19,7 +19,6 @@
@ @c
-
#include "ptexlib.h"
@ @c
@@ -29,101 +28,210 @@
#define space_factor cur_list.space_factor_field
#define box(A) eqtb[box_base+(A)].hh.rh
-#define text_direction int_par(text_direction_code)
-#define body_direction int_par(body_direction_code)
#define every_hbox equiv(every_hbox_loc)
#define every_vbox equiv(every_vbox_loc)
#define box_max_depth dimen_par(box_max_depth_code)
-
-@ 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}}$$
+@ 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}}$$
@c
+/*
+ void scan_spec(group_code c)
+ {
+ int spec_code;
+ 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);
+ scan_left_brace();
+ }
+*/
+
void scan_spec(group_code c)
{ /* scans a box specification and left brace */
int spec_code;
- if (scan_keyword("to")) {
- spec_code = exactly;
- scan_normal_dimen();
- } else if (scan_keyword("spread")) {
- spec_code = additional;
- scan_normal_dimen();
- } else {
+ 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 {
+ /* 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);
- scan_left_brace();
+ if (!done) {
+ scan_left_brace();
+ }
}
-
@ 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.
+|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}).
+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}).
@c
-void scan_full_spec(group_code c, int spec_direction)
-{ /* scans a box specification and left brace */
- int s; /* temporarily saved value */
+/*
+ void scan_full_spec(group_code c, int spec_direction)
+ {
+ int s;
+ int i;
+ int v;
+ int spec_code;
+ halfword attr_list;
+ if (attr_list_cache == cache_disabled)
+ update_attribute_cache();
+ attr_list = attr_list_cache;
+ s = saved_value(0);
+ CONTINUE:
+ while (cur_cmd == relax_cmd || cur_cmd == spacer_cmd) {
+ get_x_token();
+ if (cur_cmd != relax_cmd && cur_cmd != spacer_cmd)
+ back_input();
+ }
+ if (scan_keyword("attr")) {
+ scan_register_num();
+ i = cur_val;
+ scan_optional_equals();
+ scan_int();
+ v = cur_val;
+ if ((attr_list != null) && (attr_list == attr_list_cache)) {
+ attr_list = copy_attribute_list(attr_list_cache);
+ add_node_attr_ref(attr_list);
+ }
+ attr_list = do_set_attribute(attr_list, i, v);
+ goto CONTINUE;
+ }
+ if (scan_keyword("dir")) {
+ scan_direction();
+ spec_direction = cur_val;
+ goto CONTINUE;
+ }
+ if (attr_list == attr_list_cache) {
+ add_node_attr_ref(attr_list);
+ }
+ 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();
+ FOUND:
+ set_saved_record(0, saved_boxcontext, 0, s);
+ set_saved_record(1, saved_boxspec, spec_code, cur_val);
+ 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);
+ save_ptr += 4;
+ new_save_level(c);
+ scan_left_brace();
+ 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);
+ }
+*/
+
+/* scans a box specification and left brace */
+
+void scan_full_spec(group_code c, int spec_direction, int just_pack)
+{
+ int s;
int i;
int v;
int spec_code;
+ boolean done = false ;
halfword attr_list;
if (attr_list_cache == cache_disabled)
update_attribute_cache();
attr_list = attr_list_cache;
- assert(saved_type(0) == saved_boxcontext);
- s = saved_value(0); /* the box context */
+ s = saved_value(0); /* the box context */
+ 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 != relax_cmd && cur_cmd != spacer_cmd)
+ if (cur_cmd == left_brace_cmd) {
+ goto QUICK;
+ } else if (cur_cmd != relax_cmd && cur_cmd != spacer_cmd) {
back_input();
+ break;
+ }
}
+ KEYWORDS:
if (scan_keyword("attr")) {
scan_register_num();
i = cur_val;
@@ -132,7 +240,7 @@ void scan_full_spec(group_code c, int spec_direction)
v = cur_val;
if ((attr_list != null) && (attr_list == attr_list_cache)) {
attr_list = copy_attribute_list(attr_list_cache);
- add_node_attr_ref(attr_list); /* will be used once */
+ add_node_attr_ref(attr_list); /* will be used once */
}
attr_list = do_set_attribute(attr_list, i, v);
goto CONTINUE;
@@ -155,6 +263,12 @@ void scan_full_spec(group_code c, int spec_direction)
goto FOUND;
}
scan_normal_dimen();
+ goto FOUND;
+ QUICK:
+ spec_code = additional;
+ cur_val = 0;
+ add_node_attr_ref(attr_list);
+ done = true;
FOUND:
set_saved_record(0, saved_boxcontext, 0, s);
set_saved_record(1, saved_boxspec, spec_code, cur_val);
@@ -166,42 +280,43 @@ void scan_full_spec(group_code c, int spec_direction)
set_saved_record(2, saved_boxdir, spec_direction, null);
}
set_saved_record(3, saved_boxattr, 0, attr_list);
- save_ptr += 4;
+ set_saved_record(4, saved_boxpack, 0, just_pack);
+ save_ptr += 5;
new_save_level(c);
- scan_left_brace();
+ if (! done) {
+ scan_left_brace();
+ }
+ /* no gain: if (body_direction != 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);
}
-
@ 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}.
+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}.
@c
scaled total_stretch[5];
scaled total_shrink[5]; /* glue found by |hpack| or |vpack| */
int last_badness; /* badness of the most recently packaged box */
-
-@ 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|.
+@ 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|.
@c
halfword adjust_tail; /* tail of adjustment list */
@@ -213,7 +328,6 @@ halfword adjust_tail; /* tail of adjustment list */
@c
halfword pre_adjust_tail;
-int font_expand_ratio; /* current expansion ratio */
halfword last_leftmost_char;
halfword last_rightmost_char;
@@ -230,18 +344,17 @@ void set_prev_char_p(halfword p)
@ @c
scaled char_stretch(halfword p)
{
- scaled dw;
- int ef;
- internal_font_number f;
- int c, m;
- f = font(p);
- c = character(p);
- m = font_max_stretch(f);
- ef = get_ef_code(f, c);
- if ((m > 0) && (ef > 0)) {
- dw = calc_char_width(f, c, m) - char_width(f, c);
- if (dw > 0)
- return round_xn_over_d(dw, ef, 1000);
+ 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;
}
@@ -249,18 +362,17 @@ scaled char_stretch(halfword p)
@ @c
scaled char_shrink(halfword p)
{
- scaled dw;
- int ef;
- internal_font_number f;
- int c, m;
- f = font(p);
- c = character(p);
- m = font_max_shrink(f);
- ef = get_ef_code(f, c);
- if ((m > 0) && (ef > 0)) {
- dw = char_width(f, c) - calc_char_width(f, c, -m);
- if (dw > 0)
- return round_xn_over_d(dw, ef, 1000);
+ 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;
}
@@ -271,19 +383,23 @@ scaled kern_stretch(halfword p)
halfword l, r;
scaled d;
int m;
- if ((prev_char_p == null) || (vlink(prev_char_p) != p)
- || (vlink(p) == null))
+ if ((prev_char_p == null) || (vlink(prev_char_p) != p) || (vlink(p) == null))
return 0;
l = prev_char_p;
+ /* we need a left char */
+ if (!is_char_node(l))
+ return 0;
r = vlink(p);
- if (!((is_char_node(l) && is_char_node(r) &&
- (font(l) == font(r)) && (font_max_stretch(font(l)) != 0))))
+ /* and a right char */
+ if (!is_char_node(r))
+ return 0;
+ /* and a reason to kern */
+ if ((font(l) != font(r)) || (font_max_stretch(font(l)) == 0))
return 0;
m = font_max_stretch(font(l));
d = get_kern(font(l), character(l), character(r));
d = round_xn_over_d(d, 1000 + m, 1000);
- return round_xn_over_d(d - width(p),
- get_ef_code(font(l), character(l)), 1000);
+ return round_xn_over_d(d - width(p), get_ef_code(font(l), character(l)), 1000);
}
@ @c
@@ -292,29 +408,30 @@ scaled kern_shrink(halfword p)
halfword l, r;
scaled d;
int m;
- if ((prev_char_p == null) || (vlink(prev_char_p) != p)
- || (vlink(p) == null))
+ if ((prev_char_p == null) || (vlink(prev_char_p) != p) || (vlink(p) == null))
return 0;
l = prev_char_p;
+ /* we need a left char */
+ if (!is_char_node(l))
+ return 0;
r = vlink(p);
- if (!((is_char_node(l) && is_char_node(r) &&
- (font(l) == font(r)) && (font_max_shrink(font(l)) != 0))))
+ /* and a right char */
+ if (!is_char_node(r))
+ return 0;
+ /* and a reason to kern */
+ if ((font(l) != font(r)) || (font_max_shrink(font(l)) == 0))
return 0;
m = font_max_stretch(font(l));
d = get_kern(font(l), character(l), character(r));
d = round_xn_over_d(d, 1000 - m, 1000);
- return round_xn_over_d(width(p) - d,
- get_ef_code(font(l), character(l)), 1000);
+ return round_xn_over_d(width(p) - d, get_ef_code(font(l), character(l)), 1000);
}
@ @c
void do_subst_font(halfword p, int ex_ratio)
{
- internal_font_number f;
- halfword r;
- int ef, ex_shrink, ex_stretch;
if (type(p) == disc_node) {
- r = vlink(pre_break(p));
+ halfword r = vlink(pre_break(p));
while (r != null) {
if (is_char_node(r))
do_subst_font(r, ex_ratio);
@@ -334,22 +451,21 @@ void do_subst_font(halfword p, int ex_ratio)
}
return;
}
- if (is_char_node(p)) {
- r = p;
- } else {
+ if (! is_char_node(p)) {
normal_error("font expansion", "invalid node type");
return;
- }
- f = font(r);
- ef = get_ef_code(f, character(r));
- if (ef == 0)
- return;
- if ((font_max_stretch(f) > 0) && (ex_ratio > 0)) {
- 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)) {
- ex_shrink = ext_xn_over_d(ex_ratio * ef, font_max_shrink(f), 1000000);
- ex_glyph(p) = fix_expand_value(f, ex_shrink)*1000;
+ } 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;
+ }
}
}
@@ -393,49 +509,52 @@ halfword new_margin_kern(scaled w, halfword p, int side)
return k;
}
-
-@ Here is |hpack|, which is place where we do font substituting when
-font expansion is being used.
+@ Here is |hpack|, which is place where we do font substituting when font
+expansion is being used.
@c
halfword hpack(halfword p, scaled w, int m, int pack_direction)
{
halfword r; /* the box node that will be returned */
halfword q; /* trails behind |p| */
- scaled h, d, x; /* height, depth, and natural width */
+ scaled h = 0; /* height */
+ scaled d = 0; /* depth */
+ scaled x = 0; /* natural width */
scaled_whd whd;
scaled s; /* shift amount */
halfword g; /* points to a glue specification */
int o; /* order of infinity */
- halfword dir_ptr1; /* for managing the direction stack */
+ halfword dir_ptr1 = null; /* for managing the direction stack */
int hpack_dir; /* the current direction */
- int disc_level;
+ int disc_level = 0;
halfword pack_interrupt[8];
scaled font_stretch = 0;
scaled font_shrink = 0;
+ int font_expand_ratio = 0; /* current expansion ratio */
scaled k = 0;
last_badness = 0;
- r = new_node(hlist_node, min_quarterword);
+ r = new_node(hlist_node, min_quarterword); /* the box node that will be returned */
if (pack_direction == -1) {
- box_dir(r) = text_direction;
+ hpack_dir = text_direction;
} else {
- box_dir(r) = pack_direction;
+ hpack_dir = pack_direction;
}
- hpack_dir = box_dir(r);
- dir_ptr1 = null;
- push_dir(hpack_dir,dir_ptr1);
- q = r + list_offset;
+ box_dir(r) = hpack_dir;
+ /*
+ potential optimimization, save a little but neglectable in practice (not so
+ many empty boxes are used)
+
+ if (p == null) {
+ width(r) = w;
+ return r;
+ }
+ */
+ push_dir(dir_ptr1,hpack_dir); /* push null */
+ q = r + list_offset; /* hm, adding something to a node address? */
vlink(q) = p;
if (m == cal_expand_ratio) {
- prev_char_p = null;
- font_stretch = 0;
- font_shrink = 0;
- font_expand_ratio = 0;
+ prev_char_p = null; /* why not always */
}
- h = 0;
- /* Clear dimensions to zero */
- d = 0;
- x = 0;
total_stretch[normal] = 0;
total_shrink[normal] = 0;
total_stretch[sfi] = 0;
@@ -447,7 +566,6 @@ halfword hpack(halfword p, scaled w, int m, int pack_direction)
total_stretch[filll] = 0;
total_shrink[filll] = 0;
- disc_level = 0;
RESWITCH:
while ((p != null) || (disc_level > 0)) {
if (p == null) {
@@ -455,15 +573,19 @@ halfword hpack(halfword p, scaled w, int m, int pack_direction)
p = pack_interrupt[disc_level];
goto RESWITCH;
}
- /* 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 */
+ /*
+ 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)) {
- /* 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.
+ /*
+ 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;
@@ -484,151 +606,160 @@ halfword hpack(halfword p, scaled w, int m, int pack_direction)
}
if (p != null) {
switch (type(p)) {
- case hlist_node:
- case vlist_node:
- /* 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 (type(p) >= rule_node)
- s = 0;
- else
- s = shift_amount(p);
- if (height(p) - s > h)
- h = height(p) - s;
- if (depth(p) + s > d)
- d = depth(p) + s;
- break;
- case ins_node:
- case mark_node:
- case adjust_node:
- if (adjust_tail != null || pre_adjust_tail != null) {
- /* Transfer node |p| to the adjustment list */
+ case hlist_node:
+ case vlist_node:
/*
- 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.
- */
- 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));
+ 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 (type(p) >= rule_node) // always
+ s = 0;
+ else
+ s = shift_amount(p);
+ if (height(p) - s > h)
+ h = height(p) - s;
+ if (depth(p) + s > d)
+ d = depth(p) + 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 glue_node:
+ /* Incorporate glue into the horizontal totals */
+ g = glue_ptr(p);
+ x += width(g);
+ o = stretch_order(g);
+ total_stretch[o] = total_stretch[o] + stretch(g);
+ o = shrink_order(g);
+ total_shrink[o] = total_shrink[o] + shrink(g);
+ if (subtype(p) >= a_leaders) {
+ g = leader_ptr(p);
+ if (height(g) > h)
+ h = height(g);
+ if (depth(g) > d)
+ d = depth(g);
+ }
+ break;
+ case kern_node:
+ if (subtype(p) == normal) {
+ 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) {
+ if (font_expand_ratio > 0)
+ k = kern_stretch(p);
+ else if (font_expand_ratio < 0)
+ k = kern_shrink(p);
+ if (k != 0)
+ width(p) = get_kern(font(prev_char_p), character(prev_char_p), character(vlink(p)));
+ }
+ }
+ x += width(p);
+ 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:
+ /* Adjust the dir stack for the |hpack| routine */
+ if (dir_dir(p) >= 0) {
+ hpack_dir = dir_dir(p);
+ push_dir_node(dir_ptr1,p);
} else {
- vlink(adjust_tail) = p;
- adjust_tail = p;
- p = vlink(p);
+ pop_dir_node(dir_ptr1);
+ if (dir_ptr1 != null)
+ hpack_dir = dir_dir(dir_ptr1);
}
- vlink(q) = p;
- p = q;
- }
- break;
- case dir_node:
- /* DIR: Adjust the dir stack for the |hpack| routine */
- if (dir_dir(p) >= 0) {
- hpack_dir = dir_dir(p);
- push_dir_node(p,dir_ptr1);
- } else {
- pop_dir_node(dir_ptr1);
- if (dir_ptr1 != null)
- hpack_dir = dir_dir(dir_ptr1);
- }
- break;
- case math_node:
- /* begin mathskip code */
- if (glue_ptr(p) == zero_glue) {
- x += surround(p);
break;
- } else {
- /* fall through: mathskip */
- }
- /* end mathskip code */
- case glue_node:
- /* Incorporate glue into the horizontal totals */
- g = glue_ptr(p);
- x += width(g);
- o = stretch_order(g);
- total_stretch[o] = total_stretch[o] + stretch(g);
- o = shrink_order(g);
- total_shrink[o] = total_shrink[o] + shrink(g);
- if (subtype(p) >= a_leaders) {
- g = leader_ptr(p);
- if (height(g) > h)
- h = height(g);
- if (depth(g) > d)
- d = depth(g);
- }
- 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 kern_node:
- if (subtype(p) == normal) {
+ case math_node:
+ /* begin mathskip code */
+ if (glue_ptr(p) == zero_glue) {
+ x += surround(p);
+ break;
+ } else {
+ /* fall through: mathskip */
+ }
+ /* end mathskip code */
+ case margin_kern_node:
if (m == cal_expand_ratio) {
- font_stretch = font_stretch + kern_stretch(p);
- font_shrink = font_shrink + kern_shrink(p);
+ 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) {
- if (font_expand_ratio > 0)
- k = kern_stretch(p);
- else if (font_expand_ratio < 0)
- k = kern_shrink(p);
- else
- pdfassert(0);
- if (k != 0)
- width(p) = get_kern(font(prev_char_p),
- character(prev_char_p),
- character(vlink(p)));
+ do_subst_font(margin_char(p), font_expand_ratio);
+ width(p) = -char_pw(margin_char(p), subtype(p));
}
- }
- x += width(p);
- 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;
- default:
- break;
+ x += width(p);
+ break;
+ case ins_node:
+ case mark_node:
+ case adjust_node:
+ /*
+ 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);
}
@@ -641,27 +772,32 @@ halfword hpack(halfword p, scaled w, int m, int pack_direction)
vlink(pre_adjust_tail) = null;
height(r) = h;
depth(r) = d;
- /* 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. */
+ /*
+ 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; /* now |x| is the excess to be made up */
+ x = w - x;
+ /* 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) {
- /* Determine horizontal glue stretch setting, then |return|
- or \hbox{|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. */
-
- /* Determine the stretch order */
+ /*
+ Determine horizontal glue stretch setting, then |return|
+ or \hbox{|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)
@@ -682,13 +818,16 @@ halfword hpack(halfword p, scaled w, int m, int pack_direction)
if (total_stretch[o] != 0) {
glue_set(r) = unfloat((double) x / total_stretch[o]);
} else {
+ /* there's nothing to stretch */
glue_sign(r) = normal;
- set_glue_ratio_zero(glue_set(r)); /* there's nothing to stretch */
+ set_glue_ratio_zero(glue_set(r));
}
if (o == normal) {
if (list_ptr(r) != null) {
- /* Report an underfull hbox and |goto common_ending|, if this box
- is sufficiently bad */
+ /*
+ Report an underfull hbox and |goto common_ending|, if this box
+ is sufficiently bad.
+ */
last_badness = badness(x, total_stretch[normal]);
if (last_badness > int_par(hbadness_code)) {
int callback_id = callback_defined(hpack_quality_callback);
@@ -720,9 +859,10 @@ halfword hpack(halfword p, scaled w, int m, int pack_direction)
}
goto EXIT;
} else {
- /* Determine horizontal glue shrink setting, then |return|
- or \hbox{|goto common_ending|} */
- /* Determine the shrink order */
+ /*
+ Determine horizontal glue shrink setting, then |return|
+ or \hbox{|goto common_ending|},
+ */
if (total_shrink[filll] != 0)
o = filll;
else if (total_shrink[fill] != 0)
@@ -743,15 +883,19 @@ halfword hpack(halfword p, scaled w, int m, int pack_direction)
if (total_shrink[o] != 0) {
glue_set(r) = unfloat((double) (-x) / (double) total_shrink[o]);
} else {
+ /* there's nothing to shrink */
glue_sign(r) = normal;
- set_glue_ratio_zero(glue_set(r)); /* there's nothing to shrink */
+ 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;
- set_glue_ratio_one(glue_set(r)); /* use the maximum shrinkage */
- /* Report an overfull hbox and |goto common_ending|, if this box
- is sufficiently bad */
+ /* use the maximum shrinkage */
+ set_glue_ratio_one(glue_set(r));
+ /*
+ Report an overfull hbox and |goto common_ending|, if this box
+ is sufficiently bad.
+ */
if ((overshoot > dimen_par(hfuzz_code)) || (int_par(hbadness_code) < 100)) {
int callback_id = callback_defined(hpack_quality_callback);
halfword rule = null;
@@ -778,7 +922,10 @@ halfword hpack(halfword p, scaled w, int m, int pack_direction)
}
} else if (o == normal) {
if (list_ptr(r) != null) {
- /* Report a tight hbox and |goto common_ending|, if this box is sufficiently bad */
+ /*
+ Report a tight hbox and |goto common_ending|, if this box is
+ sufficiently bad.
+ */
last_badness = badness(-x, total_shrink[normal]);
if (last_badness > int_par(hbadness_code)) {
int callback_id = callback_defined(hpack_quality_callback);
@@ -804,7 +951,10 @@ halfword hpack(halfword p, scaled w, int m, int pack_direction)
}
COMMON_ENDING:
- /* Finish issuing a diagnostic message for an overfull or underfull hbox */
+ /*
+ Finish issuing a diagnostic message for an overfull or underfull
+ hbox.
+ */
if (output_active) {
tprint(") has occurred while \\output is active");
} else {
@@ -829,7 +979,6 @@ halfword hpack(halfword p, scaled w, int m, int pack_direction)
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);
@@ -844,16 +993,40 @@ halfword hpack(halfword p, scaled w, int m, int pack_direction)
}
@ @c
-halfword filtered_hpack(halfword p, halfword qt, scaled w, int m, int grp,
- int pac)
+/*
+halfword filtered_hpack(halfword p, halfword qt, scaled w, int m, int grp, int pac)
{
halfword q;
new_hyphenation(p, qt);
- (void) new_ligkern(p, qt); /* don't care about the tail in this case */
+ (void) new_ligkern(p, qt); // we don't care about the tail in this case
q = vlink(p);
q = lua_hpack_filter(q, w, m, grp, pac);
return hpack(q, w, m, pac);
}
+*/
+
+halfword filtered_hpack(halfword p, halfword qt, scaled w, int m, int grp, int pac, int just_pack)
+{
+ halfword q;
+ if (just_pack) {
+ q = vlink(p);
+ } else if (type(p) == temp_node && vlink(p) == null) {
+ q = vlink(p);
+ /*
+ q = new_node(hlist_node, min_quarterword);
+ box_dir(q) = (pac == -1) ? text_direction : pac;
+ width(q) = w;
+ return q;
+ */
+ } else {
+ new_hyphenation(p, qt);
+ (void) new_ligkern(p, qt); /* we don't care about the tail in this case */
+ q = vlink(p);
+ /* maybe here: alink(p) = null */
+ q = lua_hpack_filter(q, w, m, grp, pac); /* ignores empty anyway */ /* maybe also pass tail */
+ }
+ return hpack(q, w, m, pac);
+}
@ here is a function to calculate the natural whd of a (horizontal) node list
@@ -861,10 +1034,10 @@ halfword filtered_hpack(halfword p, halfword qt, scaled w, int m, int grp,
scaled_whd natural_sizes(halfword p, halfword pp, glue_ratio g_mult,
int g_sign, int g_order, int pack_direction)
{
- scaled s; /* shift amount */
- halfword g; /* points to a glue specification */
+ scaled s; /* shift amount */
+ halfword g; /* points to a glue specification */
int hpack_dir;
- scaled_whd xx; /* for recursion */
+ scaled_whd xx; /* for recursion */
scaled_whd whd, siz = { 0, 0, 0 };
if (pack_direction == -1) {
hpack_dir = text_direction;
@@ -883,76 +1056,82 @@ scaled_whd natural_sizes(halfword p, halfword pp, glue_ratio g_mult,
}
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 (type(p) >= rule_node)
- s = 0;
- else
+ case hlist_node:
+ case vlist_node:
s = shift_amount(p);
- if (height(p) - s > siz.ht)
- siz.ht = height(p) - s;
- if (depth(p) + s > siz.dp)
- siz.dp = depth(p) + s;
- break;
- case math_node:
- /* begin mathskip code */
- if (glue_ptr(p) == zero_glue) {
- siz.wd += surround(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;
- } else {
- /* fall through: mathskip */
- }
- /* end mathskip code */
- case glue_node:
- g = glue_ptr(p);
- siz.wd += width(g);
- if (g_sign != normal) {
- if (g_sign == stretching) {
- if (stretch_order(g) == g_order) {
- siz.wd +=
- float_round(float_cast(g_mult) *
- float_cast(stretch(g)));
+ /*
+ case rule_node:
+ case unset_node:
+ siz.wd += width(p);
+ if (type(p) >= rule_node) // always true
+ s = 0;
+ else
+ s = shift_amount(p);
+ if (height(p) - s > siz.ht)
+ siz.ht = height(p) - s;
+ if (depth(p) + s > siz.dp)
+ siz.dp = depth(p) + 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:
+ /* begin mathskip code */
+ if (glue_ptr(p) == zero_glue) {
+ siz.wd += surround(p);
+ break;
+ } else {
+ /* fall through: mathskip */
+ }
+ /* end mathskip code */
+ case glue_node:
+ g = glue_ptr(p);
+ siz.wd += width(g);
+ if (g_sign != normal) {
+ if (g_sign == stretching) {
+ if (stretch_order(g) == g_order) {
+ siz.wd += float_round(float_cast(g_mult) * float_cast(stretch(g)));
+ }
+ } else if (shrink_order(g) == g_order) {
+ siz.wd -= float_round(float_cast(g_mult) * float_cast(shrink(g)));
}
- } else if (shrink_order(g) == g_order) {
- siz.wd -=
- float_round(float_cast(g_mult) *
- float_cast(shrink(g)));
}
- }
- 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:
- case kern_node:
- siz.wd += width(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;
+ 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:
+ case kern_node:
+ siz.wd += width(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);
}
@@ -961,29 +1140,31 @@ scaled_whd natural_sizes(halfword p, halfword pp, glue_ratio g_mult,
return siz;
}
+@ 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.
-@ 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:
@c
-int pack_begin_line; /* source file line where the current paragraph
- or alignment began; a negative value denotes alignment */
-
+int pack_begin_line;
-@ 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.
+@ 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.
@c
halfword vpackage(halfword p, scaled h, int m, scaled l, int pack_direction)
{
halfword r; /* the box node that will be returned */
- scaled w, d, x; /* width, depth, and natural height */
+ scaled w = 0; /* width */
+ scaled d = 0; /* depth */
+ scaled x = 0; /* natural height */
scaled_whd whd;
scaled s; /* shift amount */
halfword g; /* points to a glue specification */
@@ -998,10 +1179,6 @@ halfword vpackage(halfword p, scaled h, int m, scaled l, int pack_direction)
subtype(r) = min_quarterword;
shift_amount(r) = 0;
list_ptr(r) = p;
- w = 0;
- /* Clear dimensions to zero */
- d = 0;
- x = 0;
total_stretch[normal] = 0;
total_shrink[normal] = 0;
total_stretch[sfi] = 0;
@@ -1014,16 +1191,21 @@ halfword vpackage(halfword p, scaled h, int m, scaled l, int pack_direction)
total_shrink[filll] = 0;
while (p != null) {
- /* 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 */
+ /*
+ 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:
- /* Incorporate box dimensions into the dimensions of
- the vbox that will contain~it */
+ /*
+ 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)
@@ -1031,17 +1213,27 @@ halfword vpackage(halfword p, scaled h, int m, scaled l, int pack_direction)
x += d + whd.ht;
d = whd.dp;
break;
+ /*
case rule_node:
case unset_node:
x += d + height(p);
d = depth(p);
- if (type(p) >= rule_node)
+ if (type(p) >= rule_node) // always
s = 0;
else
s = shift_amount(p);
if (width(p) + s > w)
w = width(p) + s;
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:
/* Incorporate glue into the vertical totals */
x += d;
@@ -1075,23 +1267,28 @@ halfword vpackage(halfword p, scaled h, int m, scaled l, int pack_direction)
} else {
depth(r) = d;
}
- /* 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. */
+ /*
+ 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; /* now |x| is the excess to be made up */
+ x = h - x;
+ /* 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) {
- /* Determine vertical glue stretch setting, then |return|
- or \hbox{|goto common_ending|} */
- /* Determine the stretch order */
+ /*
+ Determine vertical glue stretch setting, then |return|
+ or \hbox{|goto common_ending|}.
+ */
if (total_stretch[filll] != 0)
o = filll;
else if (total_stretch[fill] != 0)
@@ -1113,8 +1310,10 @@ halfword vpackage(halfword p, scaled h, int m, scaled l, int pack_direction)
}
if (o == normal) {
if (list_ptr(r) != null) {
- /* Report an underfull vbox and |goto common_ending|, if this box
- is sufficiently bad */
+ /*
+ Report an underfull vbox and |goto common_ending|, if this box
+ is sufficiently bad.
+ */
last_badness = badness(x, total_stretch[normal]);
if (last_badness > int_par(vbadness_code)) {
int callback_id = callback_defined(vpack_quality_callback);
@@ -1141,9 +1340,10 @@ halfword vpackage(halfword p, scaled h, int m, scaled l, int pack_direction)
return r;
} else {
- /* Determine vertical glue shrink setting, then |return|
- or \hbox{|goto common_ending|} */
- /* Determine the shrink order */
+ /*
+ Determine vertical glue shrink setting, then |return|
+ or \hbox{|goto common_ending|}.
+ */
if (total_shrink[filll] != 0)
o = filll;
else if (total_shrink[fill] != 0)
@@ -1160,14 +1360,19 @@ halfword vpackage(halfword p, scaled h, int m, scaled l, int pack_direction)
if (total_shrink[o] != 0) {
glue_set(r) = unfloat((double) (-x) / total_shrink[o]);
} else {
+ /* there's nothing to shrink */
glue_sign(r) = normal;
- set_glue_ratio_zero(glue_set(r)); /* there's nothing to shrink */
+ 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;
- set_glue_ratio_one(glue_set(r)); /* use the maximum shrinkage */
- /* Report an overfull vbox and |goto common_ending|, if this box is sufficiently bad */
+ /* use the maximum shrinkage */
+ set_glue_ratio_one(glue_set(r));
+ /*
+ Report an overfull vbox and |goto common_ending|, if this box
+ is sufficiently bad.
+ */
if ((overshoot > dimen_par(vfuzz_code)) || (int_par(vbadness_code) < 100)) {
int callback_id = callback_defined(vpack_quality_callback);
if (callback_id > 0) {
@@ -1183,7 +1388,10 @@ halfword vpackage(halfword p, scaled h, int m, scaled l, int pack_direction)
}
} else if (o == normal) {
if (list_ptr(r) != null) {
- /* Report a tight vbox and |goto common_ending|, if this box is sufficiently bad */
+ /*
+ Report a tight vbox and |goto common_ending|, if this box is
+ sufficiently bad.
+ */
last_badness = badness(-x, total_shrink[normal]);
if (last_badness > int_par(vbadness_code)) {
int callback_id = callback_defined(vpack_quality_callback);
@@ -1207,7 +1415,8 @@ halfword vpackage(halfword p, scaled h, int m, scaled l, int pack_direction)
if (output_active) {
tprint(") has occurred while \\output is active");
} else {
- if (pack_begin_line != 0) { /* it's actually negative */
+ if (pack_begin_line != 0) {
+ /* it's actually negative */
tprint(") in alignment at lines ");
print_int(abs(pack_begin_line));
tprint("--");
@@ -1225,12 +1434,12 @@ halfword vpackage(halfword p, scaled h, int m, scaled l, int pack_direction)
}
@ @c
-halfword filtered_vpackage(halfword p, scaled h, int m, scaled l, int grp,
- int pack_direction)
+halfword filtered_vpackage(halfword p, scaled h, int m, scaled l, int grp, int pack_direction, int just_pack)
{
- halfword q;
- q = p;
- q = lua_vpack_filter(q, h, m, l, grp, pack_direction);
+ halfword q = p;
+ if (!just_pack)
+ /* if (q != null) */
+ q = lua_vpack_filter(q, h, m, l, grp, pack_direction);
return vpackage(q, h, m, l, pack_direction);
}
@@ -1249,42 +1458,37 @@ void finish_vcenter(void)
@ @c
void package(int c)
{
- scaled h; /* height of box */
- halfword p; /* first node in a box */
- scaled d; /* max depth */
- int grp;
- halfword saved0, saved2, saved3;
- grp = cur_group;
- d = box_max_depth;
+ halfword saved0, saved2, saved3, saved4;
+ int grp = cur_group;
+ scaled d = box_max_depth; /* max depth */
unsave();
- save_ptr -= 4;
+ 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));
+ cur_box = filtered_hpack(cur_list.head_field, cur_list.tail_field,
+ saved_value(1), saved_level(1), grp, saved_level(2), saved4);
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));
+ saved_value(1), saved_level(1), d, grp, saved_level(2), saved4);
if (c == vtop_code) {
- /* Readjust 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.
- */
-
- h = 0;
- p = list_ptr(cur_box);
- if (p != null)
- if (type(p) <= rule_node)
- h = height(p);
+ /*
+ 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) {
@@ -1298,10 +1502,8 @@ void package(int c)
box_end(saved0);
}
-
-
-@ When a box is being appended to the current vertical list, the
-baselineskip calculation is handled by the |append_to_vlist| routine.
+@ When a box is being appended to the current vertical list, the baselineskip
+calculation is handled by the |append_to_vlist| routine.
@c
void append_to_vlist(halfword b, int location)
@@ -1332,7 +1534,8 @@ void append_to_vlist(halfword b, int location)
p = new_param_glue(line_skip_code);
} else {
p = new_skip_param(baseline_skip_code);
- width(temp_ptr) = d; /* |temp_ptr=glue_ptr(p)| */
+ /* |temp_ptr=glue_ptr(p)| */
+ width(temp_ptr) = d;
}
couple_nodes(cur_list.tail_field, p);
cur_list.tail_field = p;
@@ -1347,31 +1550,29 @@ void append_to_vlist(halfword b, int location)
}
}
-
-@ 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.
+@ 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.
@c
-#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} */
+#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} */
-halfword disc_ptr[(vsplit_code + 1)]; /* list pointers */
+halfword disc_ptr[(vsplit_code + 1)]; /* list pointers */
+@ 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.
-@ 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.
+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|.
@@ -1379,11 +1580,10 @@ otherwise they are collected in a list starting at |split_disc|.
@c
halfword prune_page_top(halfword p, boolean s)
{
- halfword prev_p; /* lags one step behind |p| */
- halfword q, r; /* temporary variables for list manipulation */
- prev_p = temp_head;
+ halfword q;
+ halfword prev_p = temp_head; /* lags one step behind |p| */
+ halfword r = null;
vlink(temp_head) = p;
- r = null;
while (p != null) {
switch (type(p)) {
case hlist_node:
@@ -1392,7 +1592,8 @@ halfword prune_page_top(halfword p, boolean s)
/* 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; /* now |temp_ptr=glue_ptr(q)| */
+ vlink(q) = p;
+ /* now |temp_ptr=glue_ptr(q)| */
if (width(temp_ptr) > height(p))
width(temp_ptr) = width(temp_ptr) - height(p);
else
@@ -1431,52 +1632,49 @@ halfword prune_page_top(halfword p, boolean s)
return vlink(temp_head);
}
-
-@ 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.
+@ 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.
@c
-scaled active_height[10]; /* distance from first active node to~|cur_p| */
-
+scaled active_height[10]; /* distance from first active node to~|cur_p| */
-@ 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.
+@ 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.
@c
#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 */
+@ 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.)
-@ 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.)
+@ height of the best box, without stretching or shrinking
@c
-scaled best_height_plus_depth; /* height of the best box, without stretching or shrinking */
+scaled best_height_plus_depth;
+
+/* finds optimum page break */
halfword vert_break(halfword p, scaled h, scaled d)
-{ /* finds optimum page break */
- halfword prev_p; /* if |p| is a glue node, |type(prev_p)| determines
- whether |p| is a legal breakpoint */
+{
+ halfword prev_p = p; /* 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 q, r; /* glue specifications */
- int pi; /* penalty value */
+ int pi = 0; /* penalty value */
int b; /* badness at a trial breakpoint */
- int least_cost; /* the smallest badness plus penalties found so far */
- halfword best_place; /* the most recent break that leads to |least_cost| */
- scaled prev_dp; /* depth of previous box in the list */
int t; /* |type| of the node following a kern */
- prev_p = p; /* an initial glue node is not a legal breakpoint */
+ int least_cost; /* the smallest badness plus penalties found so far */
+ halfword best_place = null; /* the most recent break that leads to |least_cost| */
+ scaled prev_dp = 0; /* depth of previous box in the list */
least_cost = awful_bad;
do_all_six(set_height_zero);
- prev_dp = 0;
- best_place = null;
- pi = 0;
while (1) {
/* If node |p| is a legal breakpoint, check if this break is
the best known, and |goto done| if |p| is null or
@@ -1596,13 +1794,11 @@ halfword vert_break(halfword p, scaled h, scaled d)
}
cur_height = cur_height + prev_dp + width(q);
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);
}
@@ -1610,30 +1806,31 @@ halfword vert_break(halfword p, scaled h, scaled d)
return best_place;
}
+@ Now we are ready to consider |vsplit| itself. Most of its work is accomplished
+by the two subroutines that we have just considered.
-@ 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|.
-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).
+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).
@c
+/* extracts a page of height |h| from box |n| */
+
halfword vsplit(halfword n, scaled h)
-{ /* extracts a page of height |h| from box |n| */
- halfword v; /* the box to be split */
- int vdir; /* the direction of the box to be split */
- halfword p; /* runs through the vlist */
- halfword q; /* points to where the break occurs */
- halfword i; /* for traversing marks lists */
+{
+ halfword v; /* the box to be split */
+ int vdir; /* the direction of the box to be split */
+ halfword p; /* runs through the vlist */
+ halfword q; /* points to where the break occurs */
+ halfword i; /* for traversing marks lists */
v = box(n);
vdir = box_dir(v);
flush_node_list(split_disc);
@@ -1653,13 +1850,13 @@ halfword vsplit(halfword n, scaled h)
error();
return null;
}
-
q = vert_break(list_ptr(v), h, dimen_par(split_max_depth_code));
- /* 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. */
-
+ /*
+ 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;
@@ -1668,11 +1865,9 @@ halfword vsplit(halfword n, scaled h)
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_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);
+ 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));
@@ -1686,137 +1881,161 @@ halfword vsplit(halfword n, scaled h)
p = vlink(p);
}
}
-
q = prune_page_top(q, int_par(saving_vdiscards_code) > 0);
p = list_ptr(v);
list_ptr(v) = null;
flush_node(v);
- if (q == null)
- box(n) = null; /* the |eq_level| of the box stays the same */
- else
+ if (q == null) {
+ /* the |eq_level| of the box stays the same */
+ box(n) = null;
+ } else {
box(n) =
- filtered_vpackage(q, 0, additional, dimen_par(max_depth_code),
- split_keep_group, vdir);
- return filtered_vpackage(p, h, exactly,
- dimen_par(split_max_depth_code), split_off_group,
- vdir);
+ filtered_vpackage(q, 0, additional, dimen_par(max_depth_code), split_keep_group, vdir, 0);
+ }
+ return filtered_vpackage(p, h, exactly, dimen_par(split_max_depth_code), split_off_group, vdir, 0);
}
-
-@ 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|.
+@ 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|.
@c
void begin_box(int box_context)
{
- halfword q; /* run through the current list */
- halfword k; /* 0 or |vmode| or |hmode| */
- int n; /* a box number */
+ halfword q; /* run through the current list */
+ halfword k; /* 0 or |vmode| or |hmode| */
+ int n; /* a box number */
int spec_direction = -1;
+ int just_pack = 0;
switch (cur_chr) {
- case box_code:
- scan_register_num();
- cur_box = box(cur_val);
- box(cur_val) = null; /* the box becomes void, at the same level */
- break;
- case copy_code:
- scan_register_num();
- cur_box = copy_node_list(box(cur_val));
- break;
- case last_box_code:
- /* 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) { /* todo: new code, needs testing */
- if ((type(cur_list.tail_field) == hlist_node)
- || (type(cur_list.tail_field) == vlist_node)) {
- /* 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);
+ case box_code:
+ scan_register_num();
+ cur_box = box(cur_val);
+ /* 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:
+ /*
+ 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) {
+ /* todo: new code, needs testing */
+
+ /* maybe: ((type(cur_list.tail_field) == hlist_node) < rule_node) */
+
+ if ((type(cur_list.tail_field) == hlist_node) || (type(cur_list.tail_field) == vlist_node)) {
+ /* 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;
}
- 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:
- /* 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("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);
- break;
- default:
- /* 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. */
- 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;
- break;
- case hmode:
- spec_direction = text_direction;
break;
- case mmode:
- spec_direction = math_direction;
+ case vsplit_code:
+ /*
+ 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("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);
break;
- }
- if (k == hmode) {
- if ((box_context < box_flag) && (abs(cur_list.mode_field) == vmode))
- scan_full_spec(adjusted_hbox_group, spec_direction);
- else
- scan_full_spec(hbox_group, spec_direction);
- } else {
+ default:
+ /*
+ 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;
+ break;
+ case hmode:
+ spec_direction = text_direction;
+ break;
+ case mmode:
+ spec_direction = math_direction;
+ 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();
+ cur_list.mode_field = -k;
if (k == vmode) {
- scan_full_spec(vbox_group, spec_direction);
+ prev_depth = ignore_depth;
+ if (every_vbox != null)
+ begin_token_list(every_vbox, every_vbox_text);
} else {
- scan_full_spec(vtop_group, spec_direction);
- k = vmode;
+ space_factor = 1000;
+ if (every_hbox != null)
+ begin_token_list(every_hbox, every_hbox_text);
}
- normal_paragraph();
- }
- push_nest();
- cur_list.mode_field = -k;
- if (k == vmode) {
- prev_depth = ignore_depth;
- if (every_vbox != null)
- begin_token_list(every_vbox, every_vbox_text);
- } else {
- space_factor = 1000;
- if (every_hbox != null)
- begin_token_list(every_hbox, every_hbox_text);
- }
- return;
- break;
+ return;
+ break;
}
- box_end(box_context); /* in simple cases, we use the box immediately */
+ /* in simple cases, we use the box immediately */
+ box_end(box_context);
}
diff --git a/Build/source/texk/web2c/luatexdir/tex/printing.h b/Build/source/texk/web2c/luatexdir/tex/printing.h
index 838e87e5bde..1619c6072de 100644
--- a/Build/source/texk/web2c/luatexdir/tex/printing.h
+++ b/Build/source/texk/web2c/luatexdir/tex/printing.h
@@ -36,6 +36,7 @@ typedef enum {
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
@@ -69,8 +70,8 @@ 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 *, int);
-extern void log_banner(const char *, int);
+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);
@@ -84,6 +85,7 @@ extern void print_current_string(void);
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);
diff --git a/Build/source/texk/web2c/luatexdir/tex/printing.w b/Build/source/texk/web2c/luatexdir/tex/printing.w
index 2f11e7836dd..baafa24a8af 100644
--- a/Build/source/texk/web2c/luatexdir/tex/printing.w
+++ b/Build/source/texk/web2c/luatexdir/tex/printing.w
@@ -18,18 +18,17 @@
% with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
@ @c
-
-
#include "ptexlib.h"
-#include "lua/luatex-api.h" /* for luatex_banner */
+#include "lua/luatex-api.h" /* for luatex_banner */
@ @c
#define font_id_text(A) cs_text(font_id_base+(A))
-#define wlog(A) fputc(A,log_file)
-#define wterm(A) fputc(A,term_out)
+#define wlog(A) fputc(A,log_file)
+#define wterm(A) fputc(A,term_out)
int new_string_line = 0;
+int escape_controls = 1;
@ Messages that are sent to a user's terminal and to the transcript-log file
are produced by several `|print|' procedures. These procedures will
@@ -71,89 +70,118 @@ have appeared so far on the current line that has been output to the
terminal or to the transcript file, respectively.
@c
-alpha_file log_file; /* transcript of \TeX\ session */
-int selector = term_only; /* where to print a message */
-int dig[23]; /* digits in a number being output */
-int tally = 0; /* the number of characters recently printed */
-int term_offset = 0; /* the number of characters on the current terminal line */
-int file_offset = 0; /* the number of characters on the current file line */
-packed_ASCII_code trick_buf[(ssup_error_line + 1)]; /* circular buffer for pseudoprinting */
-int trick_count; /* threshold for pseudoprinting, explained later */
-int first_count; /* another variable for pseudoprinting */
-boolean inhibit_par_tokens = false; /* for minor adjustments to |show_token_list| */
+alpha_file log_file; /* transcript of \TeX\ session */
+int selector = term_only; /* where to print a message */
+int dig[23]; /* digits in a number being output */
+int tally = 0; /* the number of characters recently printed */
+int term_offset = 0; /* the number of characters on the current terminal line */
+int file_offset = 0; /* the number of characters on the current file line */
+packed_ASCII_code trick_buf[(ssup_error_line + 1)]; /* circular buffer for pseudoprinting */
+int trick_count; /* threshold for pseudoprinting, explained later */
+int first_count; /* another variable for pseudoprinting */
+boolean inhibit_par_tokens = false; /* for minor adjustments to |show_token_list| */
@ To end a line of text output, we call |print_ln|
+
@c
void print_ln(void)
-{ /* prints an end-of-line */
+{
switch (selector) {
- case term_and_log:
- wterm_cr();
- wlog_cr();
- term_offset = 0;
- file_offset = 0;
- break;
- case log_only:
- wlog_cr();
- file_offset = 0;
- break;
- case term_only:
- wterm_cr();
- term_offset = 0;
- break;
- case no_print:
- 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;
+ 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;
}
-} /* |tally| is not affected */
-
+ /* |tally| is not affected */
+}
@ 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).
+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.
@c
-#define wterm_char(A) do { \
- if ((A>=0x20)||(A==0x0A)||(A==0x0D)||(A==0x09)) { \
- wterm(A); \
- } else { \
- if (term_offset+2>=max_print_line) { \
- wterm_cr(); term_offset=0; \
- } \
- incr(term_offset); wterm('^'); \
- incr(term_offset); wterm('^'); \
- wterm(A+64); \
- } \
- } while (0)
-
-#define needs_wrapping(A,B) \
- (((A>=0xF0)&&(B+4>=max_print_line))|| \
- ((A>=0xE0)&&(B+3>=max_print_line))|| \
+#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>=0xF0)&&(B+4>=max_print_line)) || \
+ ((A>=0xE0)&&(B+3>=max_print_line)) || \
((A>=0xC0)&&(B+2>=max_print_line)))
-#define fix_term_offset(A) do { \
- if (needs_wrapping(A,term_offset)){ \
- wterm_cr(); term_offset=0; \
- } \
- } while (0)
+we have mostly ascii in logs, so ...
+
+*/
-#define fix_log_offset(A) do { \
- if (needs_wrapping(A,file_offset)){ \
- wlog_cr(); file_offset=0; \
- } \
- } while (0)
+#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)
-{ /* prints a single byte */
- assert(s >= 0 && s < 256);
+{
+ if (s < 0 || s > 255) {
+ formatted_warning("print","weird character %i",s);
+ return;
+ }
if (s == int_par(new_line_char_code)) {
if (selector < pseudo) {
print_ln();
@@ -161,62 +189,62 @@ void print_char(int s)
}
}
switch (selector) {
- 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 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_only:
- fix_term_offset(s);
- wterm_char(s);
- incr(term_offset);
- if (term_offset == max_print_line) {
- wterm_cr();
- term_offset = 0;
- }
- break;
- case no_print:
- break;
- case pseudo:
- if (tally < trick_count)
- trick_buf[tally % error_line] = (packed_ASCII_code) s;
- break;
- case new_string:
- append_char(s);
- break; /* we drop characters if the string space is full */
- default:
- fprintf(write_file[selector], "%c", s);
+ 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);
}
-
@ 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.)
+
@^system dependencies@>
The first 256 entries above the 17th unicode plane are used for a
@@ -228,24 +256,19 @@ to do the same substraction while typesetting.
@c
void print(int s)
-{ /* prints string |s| */
+{
if (s >= str_ptr) {
- /* this can't happen */
- print_char('?');
- print_char('?');
- print_char('?');
+ normal_warning("print","bad string pointer");
return;
} else if (s < STRING_OFFSET) {
if (s < 0) {
- /* can't happen */
- print_char('?');
- print_char('?');
- print_char('?');
+ normal_warning("print","bad string offset");
} else {
/* TH not sure about this, disabled for now! */
if ((false) && (selector > pseudo)) {
+ /* internal strings are not expanded */
print_char(s);
- return; /* internal strings are not expanded */
+ return;
}
if (s == int_par(new_line_char_code)) {
if (selector < pseudo) {
@@ -265,10 +288,7 @@ void print(int s)
} else if (s >= 0x110000) {
int c = s - 0x110000;
if (c >= 256) {
- normal_warning("print", "bad raw byte to print (c=", true, false);
- print_int(c);
- tprint("), skipped.");
- print_ln();
+ formatted_warning("print", "bad raw byte to print (c=%d), skipped",c);
} else {
print_char(c);
}
@@ -332,6 +352,14 @@ different because it uses buffering, which works well because
most of the output actually comes through |tprint|.
@c
+#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;
@@ -340,115 +368,101 @@ void tprint(const char *sss)
int dolog = 0;
int doterm = 0;
switch (selector) {
- case new_string:
- append_string((const unsigned char *)sss, (unsigned) strlen(sss));
- return;
- break;
- case pseudo:
- while (*sss) {
- if (tally < trick_count) {
- trick_buf[tally % error_line] = (packed_ASCII_code) *sss++;
- tally++;
- } else {
- return;
- }
- }
- return;
- break;
- case no_print:
- return;
- break;
- case term_and_log:
- dolog = 1;
- doterm = 1;
- break;
- case log_only:
- dolog = 1;
- break;
- case term_only:
- doterm = 1;
- break;
- default:
- {
- char *newstr = xstrdup(sss);
- char *s;
- for (s=newstr;*s;s++) {
- if (*s == newlinechar) {
- *s = '\n';
- }
+ 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;
+ }
}
- fputs(newstr, write_file[selector]);
- free(newstr);
return;
- }
- break;
+ 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;
}
/* what is left is the 3 term/log settings */
- buffer = xmalloc(strlen(sss)*3);
- if (dolog) {
- const unsigned char *ss = (const unsigned char *) sss;
- while (*ss) {
- int s = *ss++;
- if (needs_wrapping(s,file_offset) || s == newlinechar) {
- buffer[i++] = '\n';
+ if (dolog || doterm) {
+ buffer = xmalloc(strlen(sss)*3);
+ if (dolog) {
+ 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);
- i = 0; buffer[0] = '\0';
- file_offset=0;
+ buffer[0] = '\0';
}
- if (s != newlinechar) {
- buffer[i++] = s;
- if (file_offset++ == max_print_line) {
- buffer[i++] = '\n';
- buffer[i++] = '\0';
- fputs(buffer, log_file);
- i = 0; buffer[0] = '\0';
- file_offset = 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, 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) {
- buffer[i++] = '\n';
+ if (*buffer) {
buffer[i++] = '\0';
fputs(buffer, term_out);
- i = 0; buffer[0] = '\0';
- term_offset=0;
- }
- if (s != newlinechar) {
- if ((s>=0x20)||(s==0x0A)||(s==0x0D)||(s==0x09)) {
- buffer[i++] = s;
- } else {
- buffer[i++] = '^';
- buffer[i++] = '^';
- buffer[i++] = s+64;
- term_offset += 2;
- }
- if (++term_offset == max_print_line) {
- buffer[i++] = '\n';
- buffer[i++] = '\0';
- fputs(buffer, term_out);
- i = 0; buffer[0] = '\0';
- term_offset = 0;
- }
}
}
- if (*buffer) {
- buffer[i++] = '\0';
- fputs(buffer, term_out);
- }
+ free(buffer);
}
- free(buffer);
}
void tprint_nl(const char *s)
@@ -464,16 +478,11 @@ and format identifier together will occupy at most |max_print_line|
character positions.
@c
-void print_banner(const char *v, int ver)
+void print_banner(const char *v)
{
- int callback_id;
- callback_id = callback_defined(start_run_callback);
+ int callback_id = callback_defined(start_run_callback);
if (callback_id == 0) {
- if (ver < 0)
- fprintf(term_out, "This is " MyName ", Version %s ", v);
- else
- fprintf(term_out, "This is " MyName ", Version %s%s (rev %d) ", v,
- WEB2CVERSION, ver);
+ fprintf(term_out, "This is " MyName ", Version %s%s ", v, WEB2CVERSION);
if (format_ident > 0)
print(format_ident);
print_ln();
@@ -494,7 +503,7 @@ void print_banner(const char *v, int ver)
}
@ @c
-void log_banner(const char *v, int ver)
+void log_banner(const char *v)
{
const char *months[] = { " ",
"JAN", "FEB", "MAR", "APR", "MAY", "JUN",
@@ -503,11 +512,7 @@ void log_banner(const char *v, int ver)
unsigned month = (unsigned) int_par(month_code);
if (month > 12)
month = 0;
- if (ver < 0)
- fprintf(log_file, "This is " MyName ", Version %s ", v);
- else
- fprintf(log_file, "This is " MyName ", Version %s%s (rev %d) ", v,
- WEB2CVERSION, ver);
+ fprintf(log_file, "This is " MyName ", Version %s%s ", v, WEB2CVERSION);
print(format_ident);
print_char(' ');
print_char(' ');
@@ -544,21 +549,19 @@ the user's escape character (which is usually a backslash).
@c
void print_esc(str_number s)
-{ /* prints escape character, then |s| */
- int c; /* the escape character code */
- /* Set variable |c| to the current escape character */
- c = int_par(escape_char_code);
+{
+ int c = int_par(escape_char_code); /* Set variable |c| to the current escape character */
if (c >= 0 && c < STRING_OFFSET)
print(c);
print(s);
}
-@ @c
+@ This prints escape character, then |s|.
+
+@c
void tprint_esc(const char *s)
-{ /* prints escape character, then |s| */
- int c; /* the escape character code */
- /* Set variable |c| to the current escape character */
- c = int_par(escape_char_code);
+{
+ int c = int_par(escape_char_code); /* Set variable |c| to the current escape character */
if (c >= 0 && c < STRING_OFFSET)
print(c);
tprint(s);
@@ -586,10 +589,9 @@ by all PASCAL compilers.
@c
void print_int(longinteger n)
-{ /* prints an integer in decimal form */
- int k; /* index to current digit; we assume that $|n|<10^{23}$ */
- longinteger m; /* used to negate |n| in possibly dangerous cases */
- k = 0;
+{
+ int k = 0; /* index to current digit; we assume that $|n|<10^{23}$ */
+ longinteger m; /* used to negate |n| in possibly dangerous cases */
if (n < 0) {
print_char('-');
if (n > -100000000) {
@@ -621,20 +623,18 @@ a parameter in the range |0<=n<=99|.
@c
void print_two(int n)
-{ /* prints two least significant digits */
+{
n = abs(n) % 100;
print_char('0' + (n / 10));
print_char('0' + (n % 10));
}
-
@ Hexadecimal printing of nonnegative integers is accomplished by |print_hex|.
@c
void print_hex(int n)
-{ /* prints a positive integer in hexadecimal form */
- int k; /* index to current digit; we assume that $0\L n<16^{22}$ */
- k = 0;
+{
+ int k = 0 ; /* index to current digit; we assume that $0\L n<16^{22}$ */
print_char('"');
do {
dig[k] = n % 16;
@@ -644,7 +644,6 @@ void print_hex(int n)
print_the_digs((eight_bits) k);
}
-
@ 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
@@ -653,8 +652,8 @@ works; therefore no explanation will be given. Notice that 1990 yields
@c
void print_roman_int(int n)
{
- char *j, *k; /* mysterious indices */
- int u, v; /* mysterious numbers */
+ char *j, *k; /* mysterious indices */
+ int u, v; /* mysterious numbers */
char mystery[] = "m2d5c2l5x2v5i";
j = (char *) mystery;
v = 1000;
@@ -663,8 +662,10 @@ void print_roman_int(int n)
print_char(*j);
n = n - v;
}
- if (n <= 0)
- return; /* nonpositive input produces no output */
+ if (n <= 0) {
+ /* nonpositive input produces no output */
+ return;
+ }
k = j + 2;
u = v / (*(k - 1) - '0');
if (*(k - 1) == '2') {
@@ -681,14 +682,13 @@ void print_roman_int(int n)
}
}
-
@ The |print| subroutine will not print a string that is still being
created. The following procedure will.
@c
void print_current_string(void)
-{ /* prints a yet-unmade string */
- unsigned j = 0; /* points to current character code */
+{
+ unsigned j = 0; /* points to current character code */
while (j < cur_length)
print_char(cur_string[j++]);
}
@@ -702,9 +702,10 @@ they may be unprintable.
@c
void print_cs(int p)
-{ /* prints a purported control sequence */
+{
str_number t = cs_text(p);
- if (p < hash_base) { /* nullcs */
+ if (p < hash_base) {
+ /* nullcs */
if (p == null_cs) {
tprint_esc("csname");
tprint_esc("endcsname");
@@ -733,13 +734,12 @@ void print_cs(int p)
}
}
-
@ Here is a similar procedure; it avoids the error checks, and it never
prints a space after the control sequence.
@c
void sprint_cs(pointer p)
-{ /* prints a control sequence */
+{
str_number t;
if (p == null_cs) {
tprint_esc("csname");
@@ -753,8 +753,20 @@ void sprint_cs(pointer p)
}
}
+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);
+ }
+}
@ This procedure is never called when |interaction<scroll_mode|.
+
@c
void prompt_input(const char *s)
{
@@ -763,13 +775,12 @@ void prompt_input(const char *s)
term_input();
}
-
@ Then there is a subroutine that prints glue stretch and shrink, possibly
followed by the name of finite units:
@c
void print_glue(scaled d, int order, const char *s)
-{ /* prints a glue component */
+{
print_scaled(d);
if ((order < normal) || (order > filll)) {
tprint("foul");
@@ -785,9 +796,10 @@ void print_glue(scaled d, int order, const char *s)
}
@ The next subroutine prints a whole glue specification
+
@c
void print_spec(int p, const char *s)
-{ /* prints a glue specification */
+{
if (p < 0) {
print_char('*');
} else {
@@ -805,7 +817,6 @@ void print_spec(int p, const char *s)
}
}
-
@ 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''
@@ -824,8 +835,7 @@ is assumed to be present when |short_display| begins; deviations from this
font will be printed.
@c
-int font_in_short_display; /* an internal font number */
-
+int font_in_short_display; /* an internal font number */
@ Boxes, rules, inserts, whatsits, marks, and things in general that are
sort of ``complicated'' are indicated only by printing `\.{[]}'.
@@ -853,9 +863,11 @@ void print_font_identifier(internal_font_number f)
}
}
-@ @c
+@ This prints highlights of list |p|.
+
+@c
void short_display(int p)
-{ /* prints highlights of list |p| */
+{
while (p != null) {
if (is_char_node(p)) {
if (lig_ptr(p) != null) {
@@ -879,14 +891,15 @@ void short_display(int p)
}
}
-
@ 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.
+@ This prints |char_node| data.
+
@c
void print_font_and_char(int p)
-{ /* prints |char_node| data */
+{
if (!is_valid_font(font(p)))
print_char('*');
else
@@ -895,9 +908,11 @@ void print_font_and_char(int p)
print(character(p));
}
-@ @c
+@ This prints token list data in braces
+
+@c
void print_mark(int p)
-{ /* prints token list data in braces */
+{
print_char('{');
if ((p < (int) fix_mem_min) || (p > (int) fix_mem_end))
tprint_esc("CLOBBERED.");
@@ -906,16 +921,17 @@ void print_mark(int p)
print_char('}');
}
-@ @c
+@ This prints dimensions of a rule node.
+
+@c
void print_rule_dimen(scaled d)
-{ /* prints dimension in rule node */
+{
if (is_running(d))
print_char('*');
else
print_scaled(d);
}
-
@ 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
@@ -930,32 +946,29 @@ be given and no sublists will be traversed. Another global variable, called
|breadth_max| had better be positive, or you won't see anything.
@c
-int depth_threshold; /* maximum nesting depth in box displays */
-int breadth_max; /* maximum number of items shown at the same list level */
-
+int depth_threshold; /* maximum nesting depth in box displays */
+int breadth_max; /* maximum number of items shown at the same list level */
-@ The recursive machinery is started by calling |show_box|.
+@ The recursive machinery is started by calling |show_box|. Assign the values
+|depth_threshold:=show_box_depth| and |breadth_max:=show_box_breadth|
@c
void show_box(halfword p)
{
- /* Assign the values |depth_threshold:=show_box_depth| and
- |breadth_max:=show_box_breadth| */
depth_threshold = int_par(show_box_depth_code);
breadth_max = int_par(show_box_breadth_code);
-
if (breadth_max <= 0)
breadth_max = 5;
- show_node_list(p); /* the show starts at |p| */
+ /* the show starts at |p| */
+ show_node_list(p);
print_ln();
}
-
-@ Helper for debugging purposes
+@ Helper for debugging purposes. It prints highlights of list |p|
@c
void short_display_n(int p, int m)
-{ /* prints highlights of list |p| */
+{
int i = 0;
font_in_short_display = null_font;
if (p == null)
@@ -999,7 +1012,6 @@ void short_display_n(int p, int m)
update_terminal();
}
-
@ 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
@@ -1011,21 +1023,21 @@ 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);
+ fprintf(stderr, "fmtdebug:csnames from %d to %d:", (int) hstart, (int) hfinish);
for (h = hstart; h <= hfinish; h++) {
- if (cs_text(h) > 0) { /* if have anything at this position */
+ if (cs_text(h) > 0) {
+ /* we have anything at this position */
c = str_string(cs_text(h));
l = c + str_length(cs_text(h));
while (c < l) {
- fputc(*c++, stderr); /* print the characters */
+ /* print the characters */
+ fputc(*c++, stderr);
}
fprintf(stderr, "|");
}
}
}
-
@ 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.
@@ -1033,8 +1045,7 @@ one fall back on the non-file:line:error style.
@c
void print_file_line(void)
{
- int level;
- level = in_open;
+ int level = in_open;
while ((level > 0) && (full_source_filename_stack[level] == 0))
decr(level);
if (level == 0) {
@@ -1051,14 +1062,13 @@ void print_file_line(void)
}
}
-
@ \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:
@c
void begin_diagnostic(void)
-{ /* prepare to do some tracing */
+{
global_old_setting = selector;
if ((int_par(tracing_online_code) <= 0) && (selector == term_and_log)) {
decr(selector);
@@ -1067,16 +1077,17 @@ void begin_diagnostic(void)
}
}
-@ @c
+@ Restore proper conditions after tracing.
+
+@c
void end_diagnostic(boolean blank_line)
-{ /* restore proper conditions after tracing */
+{
tprint_nl("");
if (blank_line)
print_ln();
selector = global_old_setting;
}
-
@ Of course we had better declare another global variable, if the previous
routines are going to work.
diff --git a/Build/source/texk/web2c/luatexdir/tex/scanning.h b/Build/source/texk/web2c/luatexdir/tex/scanning.h
index 8831901c303..729fcda20ef 100644
--- a/Build/source/texk/web2c/luatexdir/tex/scanning.h
+++ b/Build/source/texk/web2c/luatexdir/tex/scanning.h
@@ -15,8 +15,9 @@
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/>. */
+ with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
+*/
#ifndef SCANNING_H
# define SCANNING_H
@@ -42,7 +43,6 @@ 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);
# define scan_register_num() scan_limited_int(65535,"register code")
@@ -57,17 +57,15 @@ extern void scan_limited_int(int max, const char *name);
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 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 A_token (letter_token+'A') /* the smallest special hex digit */
-# define other_A_token (other_token+'A')
- /* special hex digit of type |other_char| */
-
+# 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 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 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);
@@ -94,15 +92,13 @@ 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 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);
-
+/* extern void scan_expr(void); */
#endif
diff --git a/Build/source/texk/web2c/luatexdir/tex/scanning.w b/Build/source/texk/web2c/luatexdir/tex/scanning.w
index 120d361922e..635ea03e2e2 100644
--- a/Build/source/texk/web2c/luatexdir/tex/scanning.w
+++ b/Build/source/texk/web2c/luatexdir/tex/scanning.w
@@ -35,8 +35,7 @@
#define count(A) eqtb[count_base+(A)].hh.rh
#define box(A) equiv(box_base+(A))
-#define text_direction int_par(text_direction_code)
-#define body_direction int_par(body_direction_code)
+static void scan_expr(void);
@ 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;
@@ -602,7 +601,7 @@ void scan_something_internal(int level, boolean negative)
/* Fetch a character code from some table */
scan_char_num();
if (m == math_code_base) {
- cur_val1 = get_math_code_num(cur_val, true);
+ 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);
@@ -621,6 +620,7 @@ void scan_something_internal(int level, boolean negative)
}
break;
case def_del_code_cmd:
+ case extdef_del_code_cmd: /* bonus */
/* Fetch a character code from some table */
scan_char_num();
cur_val1 = get_del_code_num(cur_val);
@@ -629,7 +629,7 @@ void scan_something_internal(int level, boolean negative)
case extdef_math_code_cmd:
/* Fetch an extended math code table value */
scan_char_num();
- cur_val1 = get_math_code_num(cur_val, false);
+ cur_val1 = get_math_code_num(cur_val);
scanned_result(cur_val1, int_val_level);
break;
case toks_register_cmd:
@@ -1102,26 +1102,73 @@ $|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.
+
@c
+
+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)
+
+/*
+ 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)
-/* sets |cur_val| to a dimension */
{
- boolean negative; /* should the answer be negated? */
- int f; /* numerator of a fraction whose denominator is $2^{16}$ */
- /* Local variables for dimension calculations */
- int num, denom; /* conversion ratio for the scanned units */
- int k, kk; /* number of digits in a decimal fraction */
- halfword p, q; /* top of decimal digit stack */
- scaled v; /* an internal dimension */
- int save_cur_val; /* temporary storage of |cur_val| */
-
- f = 0;
+ boolean negative; /* should the answer be negated? */
+ int f = 0; /* numerator of a fraction whose denominator is $2^{16}$ */
+ int num, denom; /* conversion ratio for the scanned units */
+ halfword q; /* top of decimal digit stack */
+ scaled v; /* an internal dimension */
+ int save_cur_val; /* temporary storage of |cur_val| */
arith_error = false;
cur_order = normal;
negative = false;
if (!shortcut) {
/* Get the next non-blank non-sign... */
- negative = false;
do {
/* Get the next non-blank non-call token */
do {
@@ -1132,23 +1179,22 @@ void scan_dimen(boolean mu, boolean inf, boolean shortcut)
cur_tok = other_token + '+';
}
} while (cur_tok == other_token + '+');
-
if ((cur_cmd >= min_internal_cmd) && (cur_cmd <= max_internal_cmd)) {
- /* Fetch an internal dimension and |goto attach_sign|,
- or fetch an internal integer */
+ /* 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)
+ if (cur_val_level == mu_val_level) {
goto ATTACH_SIGN;
- if (cur_val_level != int_val_level)
+ } 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)
+ if (cur_val_level == dimen_val_level) {
goto ATTACH_SIGN;
+ }
}
-
} else {
back_input();
if (cur_tok == continental_point_token) {
@@ -1160,24 +1206,26 @@ void scan_dimen(boolean mu, boolean inf, boolean shortcut)
radix = 10;
cur_val = 0;
}
- if (cur_tok == continental_point_token)
+ if (cur_tok == continental_point_token) {
cur_tok = point_token;
+ }
if ((radix == 10) && (cur_tok == point_token)) {
- /* 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. */
-
- k = 0;
- p = null;
- get_token(); /* |point_token| is being re-scanned */
+ /*
+ 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;
+ get_token(); /* |point_token| is being re-scanned */
while (1) {
get_x_token();
if ((cur_tok > zero_token + 9) || (cur_tok < zero_token))
break;
- if (k < 17) { /* digits for |k>=17| cannot affect the result */
+ if (k < 17) {
+ /* digits for |k>=17| cannot affect the result */
q = get_avail();
set_token_link(q, p);
set_token_info(q, cur_tok - zero_token);
@@ -1192,31 +1240,33 @@ void scan_dimen(boolean mu, boolean inf, boolean shortcut)
free_avail(q);
}
f = round_decimals(k);
- if (cur_cmd != spacer_cmd)
+ if (cur_cmd != spacer_cmd) {
back_input();
+ }
}
}
}
- if (cur_val < 0) { /* in this case |f=0| */
+ if (cur_val < 0) {
+ /* in this case |f=0| */
negative = !negative;
negate(cur_val);
}
- /* 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.
- */
-
+ /*
+ 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) {
- /* Scan for (f)\.{fil} units; |goto attach_fraction| if found */
- /* In traditional TeX, a specification like `\.{filllll}' or `\.{fill L L
- L}' will lead to two error messages (one for each additional keyword
- \.{"l"}).
- Not so for luatex, it just parses the construct in reverse. */
+ /*
+ Scan for (f)\.{fil} units; |goto attach_fraction| if found. In traditional
+ \TeX, a specification like `\.{filllll}' or `\.{fill L L L}' will lead to
+ two error messages (one for each additional keyword \.{"l"}). Not so for
+ \LuaTeX, it just parses the construct in reverse.
+ */
if (scan_keyword("filll")) {
cur_order = filll;
goto ATTACH_FRACTION;
@@ -1230,12 +1280,13 @@ void scan_dimen(boolean mu, boolean inf, boolean shortcut)
cur_order = sfi;
goto ATTACH_FRACTION;
}
-
}
- /* Scan for (u)units that are internal dimensions;
- |goto attach_sign| with |cur_val| set if found */
+ /*
+ Scan for (u)units that are internal dimensions; |goto attach_sign| with
+ |cur_val| set if found
+ */
save_cur_val = cur_val;
- /* Get the next non-blank non-call... */
+ /* Get the next non-blank non-call... a pitty if just backed up the input */
do {
get_x_token();
} while (cur_cmd == spacer_cmd);
@@ -1243,146 +1294,124 @@ void scan_dimen(boolean mu, boolean inf, boolean shortcut)
if ((cur_cmd < min_internal_cmd) || (cur_cmd > max_internal_cmd)) {
back_input();
} else {
+ /* math_given_cmd xmath_given_cmd last_item_cmd */
if (mu) {
scan_something_internal(mu_val_level, false);
coerce_glue();
- if (cur_val_level != mu_val_level)
+ if (cur_val_level != mu_val_level) {
mu_error();
+ }
} else {
scan_something_internal(dimen_val_level, false);
}
v = cur_val;
goto FOUND;
}
- if (mu)
- goto NOT_FOUND;
- if (scan_keyword("em")) {
- v = (quad(get_cur_font()));
+ /* bah ... true forces to split the unit scanner */
+ if (mu) {
+ /* 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()));
+ v = x_height(get_cur_font());
} else if (scan_keyword("px")) {
v = dimen_par(px_dimen_code);
} else {
- goto NOT_FOUND;
+ goto PICKUP_UNIT;
}
- /* Scan an optional space */
+ /* Scan an optional space (after em, ex or px) */
get_x_token();
- if (cur_cmd != spacer_cmd)
+ 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;
- NOT_FOUND:
-
- if (mu) {
- /* Scan for (m)\.{mu} units and |goto attach_fraction| */
- if (scan_keyword("mu")) {
- goto ATTACH_FRACTION;
- } else {
- 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();
- goto ATTACH_FRACTION;
- }
- }
- if (scan_keyword("true")) {
- /* Adjust (f)for the magnification ratio */
- prepare_mag();
- if (int_par(mag_code) != 1000) {
- cur_val = xn_over_d(cur_val, 1000, int_par(mag_code));
- f = (1000 * f + 0200000 * tex_remainder) / int_par(mag_code);
- cur_val = cur_val + (f / 0200000);
- f = f % 0200000;
- }
- }
- if (scan_keyword("pt"))
+ /*
+ 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")) {
goto ATTACH_FRACTION; /* the easy case */
- /* Scan for (a)all other units and adjust |cur_val| and |f| accordingly;
- |goto done| in the case of scaled points */
-
- /* 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.
- */
-
-#define set_conversion(A,B) do { num=(A); denom=(B); } while(0)
-
- if (scan_keyword("mm")) {
+ } 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);
- } else if (scan_keyword("pc")) {
- set_conversion(12, 1);
+ goto SCALE_VALUE;
+ } else if (scan_keyword("true")) {
+ /* Adjust (f)for the magnification ratio */
+ if (output_mode_used == OMODE_DVI) {
+ prepare_mag();
+ if (int_par(mag_code) != 1000) {
+ cur_val = xn_over_d(cur_val, 1000, int_par(mag_code));
+ f = (1000 * f + 0200000 * tex_remainder) / int_par(mag_code);
+ cur_val = cur_val + (f / 0200000);
+ f = f % 0200000;
+ }
+ }
+ goto PICKUP_UNIT;
} else {
/* Complain about unknown unit and |goto done2| */
- 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();
- goto DONE2;
+ scan_dimen_unknown_unit_error();
+ goto BAD_NEWS;
}
+ SCALE_VALUE:
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;
- DONE2:
+ BAD_NEWS:
ATTACH_FRACTION:
- if (cur_val >= 040000)
+ if (cur_val >= 040000) {
arith_error = true;
- else
+ } else {
cur_val = cur_val * unity + f;
+ }
DONE:
- /* Scan an optional space */
+ /* Scan an optional space */ /* happens too often */
get_x_token();
- if (cur_cmd != spacer_cmd)
+ if (cur_cmd != spacer_cmd) {
back_input();
+ }
ATTACH_SIGN:
if (arith_error || (abs(cur_val) >= 010000000000)) {
/* Report that this dimension is out of range */
- 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();
+ scan_dimen_out_of_range_error();
cur_val = max_dimen;
arith_error = false;
}
- if (negative)
+ if (negative) {
negate(cur_val);
+ }
}
@ The final member of \TeX's value-scanning trio is |scan_glue|, which
@@ -1991,7 +2020,7 @@ halfword scan_toks(boolean macro_def, boolean xpand)
/* Here we insert an entire token list created by |the_toks| without
expanding it further. */
while (1) {
- get_next(); /* get_token_lua(); */
+ get_next();
if (cur_cmd >= call_cmd) {
if (token_info(token_link(cur_chr)) == protected_token) {
cur_cmd = relax_cmd;
@@ -2096,25 +2125,24 @@ typedef enum {
@ clear a number or dimension and set |arith_error|
@c
-#define num_error(A) do { \
- arith_error=true; \
- A=0; \
- } while (0)
-
+#define num_error(A) do { \
+ arith_error=true; \
+ A=0; \
+} while (0)
@ clear a glue spec and set |arith_error|
@c
-#define glue_error(A) do { \
- arith_error=true; \
- delete_glue_ref(A); \
- A=new_spec(zero_glue); \
- } while (0)
+#define glue_error(A) do { \
+ arith_error=true; \
+ delete_glue_ref(A); \
+ A=new_spec(zero_glue); \
+} 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)
+#define normalize_glue(A) do { \
+ if (stretch(A)==0) stretch_order(A)=normal; \
+ if (shrink(A)==0) shrink_order(A)=normal; \
+} while (0)
@ Parenthesized subexpressions can be inside expressions, and this
nesting has a stack. Seven local variables represent the top of the
@@ -2141,7 +2169,7 @@ numerator for a combined multiplication and division, if any.
|max_answer|.
@c
-int add_or_sub(int x, int y, int max_answer, boolean negative)
+inline static int add_or_sub(int x, int y, int max_answer, boolean negative)
{
int a; /* the answer */
if (negative)
@@ -2166,7 +2194,7 @@ int add_or_sub(int x, int y, int max_answer, boolean negative)
$q=\lfloor n/d+{1\over2}\rfloor$, when $n$ and $d$ are positive.
@c
-int quotient(int n, int d)
+inline static int quotient(int n, int d)
{
boolean negative; /* should the answer be negated? */
int a; /* the answer */
@@ -2252,8 +2280,6 @@ int fract(int x, int n, int d, int max_answer)
x = n;
n = t;
}
-
-
/* now |0<n<=x<d| */
/* Compute $f=\lfloor xn/d+{1\over2}\rfloor$; */
/* The loop here preserves the following invariant relations
@@ -2307,7 +2333,7 @@ int fract(int x, int n, int d, int max_answer)
}
@ @c
-void scan_expr(void)
+static void scan_expr(void)
{ /* scans and evaluates an expression */
boolean a, b; /* saved values of |arith_error| */
int l; /* type of expression */
@@ -2402,8 +2428,7 @@ void scan_expr(void)
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))
+ if ((abs(width(f)) > max_dimen) || (abs(stretch(f)) > max_dimen) || (abs(shrink(f)) > max_dimen))
glue_error(f);
}
@@ -2464,7 +2489,6 @@ void scan_expr(void)
expr_s(shrink(t));
}
break;
-
} /* there are no other cases */
if (o > expr_sub) {
s = o;
@@ -2486,8 +2510,7 @@ void scan_expr(void)
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)) {
+ } else if ((stretch_order(e) < stretch_order(t)) && (stretch(t) != 0)) {
stretch(e) = stretch(t);
stretch_order(e) = stretch_order(t);
}
diff --git a/Build/source/texk/web2c/luatexdir/tex/texfileio.w b/Build/source/texk/web2c/luatexdir/tex/texfileio.w
index 76ae365f735..d274f6d3439 100644
--- a/Build/source/texk/web2c/luatexdir/tex/texfileio.w
+++ b/Build/source/texk/web2c/luatexdir/tex/texfileio.w
@@ -138,7 +138,7 @@ 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->S", s, &ftemp);
+ (void) run_callback(callback_id, "S->R", s, &ftemp);
} else {
/* use kpathsea here */
@@ -839,7 +839,7 @@ void open_log_file(void)
log_opened_global = true;
if (callback_defined(start_run_callback) == 0) {
/* Print the banner line, including current date and time */
- log_banner(luatex_version_string, luatex_svn);
+ log_banner(luatex_version_string);
input_stack[input_ptr] = cur_input; /* make sure bottom level is in memory */
tprint_nl("**");
diff --git a/Build/source/texk/web2c/luatexdir/tex/texmath.w b/Build/source/texk/web2c/luatexdir/tex/texmath.w
index 77c6161f475..676f4262b21 100644
--- a/Build/source/texk/web2c/luatexdir/tex/texmath.w
+++ b/Build/source/texk/web2c/luatexdir/tex/texmath.w
@@ -33,7 +33,6 @@
#define incompleat_noad cur_list.incompleat_noad_field
#define cur_fam int_par(cur_fam_code)
-#define text_direction int_par(text_direction_code)
/*
@@ -194,15 +193,17 @@ 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);
+ 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);
- set_sa_item(math_fam_head, n, (sa_tree_item) f, lvl);
+ 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 (int_par(tracing_assigns_code) > 0) {
+ if (int_par(tracing_assigns_code) > 1) {
begin_diagnostic();
tprint("{assigning");
print_char(' ');
@@ -228,7 +229,7 @@ static void unsave_math_fam_data(int gl)
if (st.level > 0) {
rawset_sa_item(math_fam_head, st.code, st.value);
/* now do a trace message, if requested */
- if (int_par(tracing_restores_code) > 0) {
+ if (int_par(tracing_restores_code) > 1) {
int size_id = st.code / 256;
int fam_id = st.code % 256;
begin_diagnostic();
@@ -258,8 +259,10 @@ 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);
- set_sa_item(math_param_head, n, (sa_tree_item) value, lvl);
- if (int_par(tracing_assigns_code) > 0) {
+ sa_tree_item sa_value = { 0 };
+ sa_value.int_value = (int) value;
+ set_sa_item(math_param_head, n, sa_value, lvl);
+ if (int_par(tracing_assigns_code) > 1) {
begin_diagnostic();
tprint("{assigning");
print_char(' ');
@@ -275,7 +278,7 @@ void def_math_param(int param_id, int style_id, scaled value, int lvl)
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);
+ return (scaled) get_sa_item(math_param_head, n).int_value;
}
@ @c
@@ -291,7 +294,7 @@ static void unsave_math_param_data(int gl)
if (st.level > 0) {
rawset_sa_item(math_param_head, st.code, st.value);
/* now do a trace message, if requested */
- if (int_par(tracing_restores_code) > 0) {
+ if (int_par(tracing_restores_code) > 1) {
int param_id = st.code % 256;
int style_id = st.code / 256;
begin_diagnostic();
@@ -322,11 +325,16 @@ void unsave_math_data(int gl)
@c
void dump_math_data(void)
{
- if (math_fam_head == NULL)
- math_fam_head = new_sa_tree(MATHFONTSTACK, MATHFONTDEFAULT);
+ 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);
- if (math_param_head == NULL)
- math_param_head = new_sa_tree(MATHPARAMSTACK, MATHPARAMDEFAULT);
+ 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);
}
@@ -339,10 +347,14 @@ void undump_math_data(void)
@ @c
void initialize_math(void)
{
- if (math_fam_head == NULL)
- math_fam_head = new_sa_tree(MATHFONTSTACK, MATHFONTDEFAULT);
+ 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) {
- math_param_head = new_sa_tree(MATHPARAMSTACK, MATHPARAMDEFAULT);
+ sa_value.int_value = MATHPARAMDEFAULT;
+ math_param_head = new_sa_tree(MATHPARAMSTACK, 1, sa_value);
initialize_math_spacing();
}
return;
@@ -1144,7 +1156,6 @@ static delcodeval do_scan_extdef_del_code(int extcode, boolean doclass)
/* something's gone wrong */
confusion("unknown_extcode");
}
- d.origin_value = extcode;
d.class_value = mcls;
d.small_family_value = msfam;
d.small_character_value = mschr;
@@ -1162,7 +1173,7 @@ void scan_extdef_del_code(int level, int extcode)
p = cur_val;
scan_optional_equals();
d = do_scan_extdef_del_code(extcode, false);
- set_del_code(p, extcode, d.small_family_value, d.small_character_value,
+ set_del_code(p, d.small_family_value, d.small_character_value,
d.large_family_value, d.large_character_value,
(quarterword) (level));
}
@@ -1229,7 +1240,6 @@ mathcodeval scan_mathchar(int extcode)
}
d.class_value = mcls;
d.family_value = mfam;
- d.origin_value = extcode;
d.character_value = mchr;
return d;
}
@@ -1243,7 +1253,7 @@ void scan_extdef_math_code(int level, int extcode)
p = cur_val;
scan_optional_equals();
d = scan_mathchar(extcode);
- set_math_code(p, extcode, d.class_value,
+ set_math_code(p, d.class_value,
d.family_value, d.character_value, (quarterword) (level));
}
@@ -1254,34 +1264,12 @@ mathcodeval scan_delimiter_as_mathchar(int extcode)
delcodeval dval;
mathcodeval mval;
dval = do_scan_extdef_del_code(extcode, true);
- mval.origin_value = 0;
mval.class_value = dval.class_value;
mval.family_value = dval.small_family_value;
mval.character_value = dval.small_character_value;
return mval;
}
-@ this has to match the inverse routine in the pascal code
- where the \.{\\Umathchardef} is executed
-
-@c
-mathcodeval mathchar_from_integer(int value, int extcode)
-{
- mathcodeval mval;
- mval.origin_value = extcode;
- if (extcode == tex_mathcode) {
- mval.class_value = (value / 0x1000);
- mval.family_value = ((value % 0x1000) / 0x100);
- mval.character_value = (value % 0x100);
- } else { /* some xetexended xetex thing */
- int mfam = (value / 0x200000) & 0x7FF;
- mval.class_value = mfam % 0x08;
- mval.family_value = mfam / 0x08;
- mval.character_value = value & 0x1FFFFF;
- }
- return mval;
-}
-
@ 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
@@ -1306,7 +1294,7 @@ int scan_math_style(pointer p, int mstyle)
int scan_math(pointer p, int mstyle)
{
/* label restart,reswitch,exit; */
- mathcodeval mval = { 0, 0, 0, 0 };
+ mathcodeval mval = { 0, 0, 0 };
assert(p != null);
RESTART:
get_next_nb_nr();
@@ -1404,15 +1392,15 @@ void set_math_char(mathcodeval mval)
subtype(p) = ord_noad_type;
} else {
switch (mval.class_value) {
- /* *INDENT-OFF* */
- case 0: subtype(p) = ord_noad_type; break;
- case 1: subtype(p) = op_noad_type_normal; break;
- case 2: subtype(p) = bin_noad_type; break;
- case 3: subtype(p) = rel_noad_type; break;
- case 4: subtype(p) = open_noad_type; break;
- case 5: subtype(p) = close_noad_type; break;
- case 6: subtype(p) = punct_noad_type; break;
- /* *INDENT-ON* */
+ /* *INDENT-OFF* */
+ case 0: subtype(p) = ord_noad_type; break;
+ case 1: subtype(p) = op_noad_type_normal; break;
+ case 2: subtype(p) = bin_noad_type; break;
+ case 3: subtype(p) = rel_noad_type; break;
+ case 4: subtype(p) = open_noad_type; break;
+ case 5: subtype(p) = close_noad_type; break;
+ case 6: subtype(p) = punct_noad_type; break;
+ /* *INDENT-ON* */
}
}
vlink(tail) = p;
@@ -1484,7 +1472,7 @@ delimiter is to be placed; the second tells if this delimiter follows
@c
static void scan_delimiter(pointer p, int r)
{
- delcodeval dval = { 0, 0, 0, 0, 0, 0 };
+ delcodeval dval = { 0, 0, 0, 0, 0 };
if (r == tex_mathcode) { /* \.{\\radical} */
dval = do_scan_extdef_del_code(tex_mathcode, true);
} else if (r == umath_mathcode) { /* \.{\\Uradical} */
@@ -1606,9 +1594,9 @@ void math_radical(void)
void math_ac(void)
{
halfword q;
- mathcodeval t = { 0, 0, 0, 0 };
- mathcodeval b = { 0, 0, 0, 0 };
- mathcodeval o = { 0, 0, 0, 0 };
+ 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.",
@@ -2430,7 +2418,7 @@ void after_math(void)
} else {
check_display_math_end();
}
- run_mlist_to_hlist(p, text_style, false);
+ run_mlist_to_hlist(p, false, text_style);
a = hpack(vlink(temp_head), 0, additional, -1);
build_attribute_list(a);
unsave_math();
@@ -2462,7 +2450,7 @@ void after_math(void)
if (dir_math_save) {
tail_append(new_dir(math_direction));
}
- run_mlist_to_hlist(p, text_style, (mode > 0));
+ run_mlist_to_hlist(p, (mode > 0), text_style);
vlink(tail) = vlink(temp_head);
while (vlink(tail) != null)
tail = vlink(tail);
@@ -2487,7 +2475,7 @@ void after_math(void)
check_display_math_end();
}
}
- run_mlist_to_hlist(p, display_style, false);
+ run_mlist_to_hlist(p, false, display_style);
finish_displayed_math(l, a, vlink(temp_head));
}
}
diff --git a/Build/source/texk/web2c/luatexdir/tex/texnodes.h b/Build/source/texk/web2c/luatexdir/tex/texnodes.h
index ae6a38929c9..618902b58fd 100644
--- a/Build/source/texk/web2c/luatexdir/tex/texnodes.h
+++ b/Build/source/texk/web2c/luatexdir/tex/texnodes.h
@@ -222,6 +222,7 @@ typedef enum {
box_rule,
image_rule,
empty_rule,
+ user_rule,
} rule_subtypes;
# define rule_node_size 8
@@ -301,6 +302,10 @@ typedef enum {
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,
@@ -340,11 +345,32 @@ typedef enum {
delta_node,
passive_node,
shape_node,
- dir_node,
- local_par_node,
} node_types;
-# define MAX_NODE_TYPE 60
+# 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 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 */
@@ -527,6 +553,8 @@ typedef enum {
pdf_restore_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
@@ -534,7 +562,13 @@ typedef enum {
# define MAX_WHATSIT_TYPE 32
-# define get_node_size(i,j) (i!=whatsit_node ? node_data[i].size : whatsit_node_data[j].size)
+# 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)
@@ -781,26 +815,6 @@ 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);
-/*
- TH: these two defines still need checking. The node ordering in luatex is not
- quite the same as in tex82
-*/
-
-/*
-
-# define precedes_break(a) \
-# (type((a))<math_node && (type(a)!=whatsit_node || (subtype(a)!=dir_node && subtype(a)!=local_par_node)))
-
-*/
-
-/*
- so what comes before math (as we have put dir_node and local_par_node to the end)
-*/
-
-# define precedes_break(a) (type((a))<math_node)
-
-# define non_discardable(a) (type((a))<math_node)
-
/* from luanode.c */
typedef struct _node_info {
@@ -840,7 +854,6 @@ 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 void check_node_mem(void);
extern void fix_node_list(halfword);
extern int fix_node_lists;
extern char *sprint_node_mem_usage(void);
@@ -852,8 +865,8 @@ 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);
-extern void check_node_wrapup_pdf(halfword);
+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);
@@ -926,7 +939,6 @@ extern int lua_properties_use_metatable ;
#define local_broken_penalty int_par(local_broken_penalty_code)
#define local_left_box equiv(local_left_box_base)
#define local_right_box equiv(local_right_box_base)
-#define par_direction int_par(par_direction_code)
extern halfword make_local_par_node(void);
diff --git a/Build/source/texk/web2c/luatexdir/tex/texnodes.w b/Build/source/texk/web2c/luatexdir/tex/texnodes.w
index 5dac909c7b9..931b43b8d10 100644
--- a/Build/source/texk/web2c/luatexdir/tex/texnodes.w
+++ b/Build/source/texk/web2c/luatexdir/tex/texnodes.w
@@ -17,21 +17,22 @@
% You should have received a copy of the GNU General Public License along
% with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
-% hh: Here the backend nodes are still interwoven .. when I'm in the mood...
-
@ @c
-
#include "ptexlib.h"
#include "lua/luatex-api.h"
-@ @c
-#undef name
+/* we can consider less mode sizes: 2 4 6 8 */
-#define noDEBUG
-#define DEBUG_OUT stdout
+@
+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 adjust_pre subtype
+@c
#define attribute(A) eqtb[attribute_base+(A)].cint
#define uc_hyph int_par(uc_hyph_code)
@@ -39,14 +40,14 @@
#define left_hyphen_min int_par(left_hyphen_min_code)
#define right_hyphen_min int_par(right_hyphen_min_code)
-#define text_direction int_par(text_direction_code)
+#define MAX_CHAIN_SIZE 13 /* why not a bit larger */
-#define MAX_CHAIN_SIZE 13
+#define CHECK_NODE_USAGE 1 /* this triggers checking */
memory_word *volatile varmem = NULL;
-#ifndef NDEBUG
-char *varmem_sizes = NULL;
+#ifdef CHECK_NODE_USAGE
+ char *varmem_sizes = NULL;
#endif
halfword var_mem_max = 0;
@@ -56,13 +57,9 @@ halfword free_chain[MAX_CHAIN_SIZE] = { null };
static int my_prealloc = 0;
-int fix_node_lists = 1;
-
-int free_error_seen = 0;
-int copy_error_seen = 0;
+int fix_node_lists = 1; /* used in font and lang */
halfword slow_get_node(int s); /* defined below */
-int copy_error(halfword p); /* define below */
#define fake_node 100
#define fake_node_size 2
@@ -286,7 +283,7 @@ const char *node_subtypes_kern[] = {
"fontkern", "userkern", "accentkern", NULL
};
const char *node_subtypes_rule[] = {
- "normal", "box", "image", "empty", NULL
+ "normal", "box", "image", "empty", "user", NULL
};
const char *node_subtypes_glyph[] = {
"character", "glyph", "ligature", "ghost", "left", "right", NULL
@@ -328,6 +325,8 @@ node_info node_data[] = { /* the last entry in a row is the etex number */
{ boundary_node, boundary_size, node_fields_boundary, "boundary", -1 },
{ disc_node, disc_node_size, node_fields_disc, "disc", 8 },
{ whatsit_node, -1, NULL, "whatsit", 9 },
+ { local_par_node, local_par_size, node_fields_local_par, "local_par", -1 },
+ { dir_node, dir_node_size, node_fields_dir, "dir", -1 },
{ math_node, math_node_size, node_fields_math, "math", 10 },
{ glue_node, glue_node_size, node_fields_glue, "glue", 11 },
{ kern_node, kern_node_size, node_fields_kern, "kern", 12 },
@@ -367,8 +366,6 @@ node_info node_data[] = { /* the last entry in a row is the etex number */
{ delta_node, delta_node_size, NULL, "delta", -1 },
{ passive_node, passive_node_size, NULL, "passive", -1 },
{ shape_node, variable_node_size, NULL, "shape", -1 },
- { dir_node, dir_node_size, node_fields_dir, "dir", -1 },
- { local_par_node, local_par_size, node_fields_local_par, "local_par", -1 },
{ -1, -1, NULL, NULL, -1 },
};
@@ -423,8 +420,7 @@ node_info whatsit_node_data[] = {
#define last_whatsit_node pdf_restore_node
-/*
-
+@
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.
@@ -446,9 +442,10 @@ only small lists.
So, in the end this is what we ended up with. For the record, I also experimented with the
following:
-- copy attributes to the properties so that we hav efast access at the lua end: in the end
+- 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
+
- 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,
@@ -462,15 +459,16 @@ alternative is to store a reference in the node itself but that is complicated b
that the register has some limitations (no numeric keys) and we also don't want to mess with
it too much.
-*/
-
+@c
int lua_properties_level = 0 ; /* can be private */
int lua_properties_enabled = 0 ;
int lua_properties_use_metatable = 0 ;
-/* 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. */
+@
+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.
+@c
#define lua_properties_push do { \
if (lua_properties_enabled) { \
lua_properties_level = lua_properties_level + 1 ; \
@@ -511,37 +509,38 @@ don't keep resolving the registry index. */
} \
} while(0)
-/* 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:
-
-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);
+/*
+ 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:
+
+ 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);
}
- lua_pop(L,1);
-}
-#define lua_properties_copy(target, source) do { \
- if (lua_properties_enabled) { \
- lua_pushnumber(Luas,source); \
- lua_rawget(Luas,-2); \
- if (lua_type(Luas,-1)==LUA_TTABLE) { \
- copy_lua_table(Luas,-1); \
- lua_pushnumber(Luas,target); \
- lua_insert(Luas,-2); \
- lua_rawset(Luas,-3); \
- } else { \
- lua_pop(Luas,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)
+ } while(0)
*/
@@ -589,97 +588,297 @@ static void copy_lua_table(lua_State* L, int index) {
/* Here end the property handlers. */
@ @c
-halfword new_node(int i, int j)
+int valid_node(halfword p)
{
- int s;
- halfword n;
- s = get_node_size(i, j);
- n = get_node(s);
- /* it should be possible to do this memset at |free_node()| */
- /* 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 whatsit_node:
- if (j == open_node) {
- open_name(n) = get_nullstr();
- open_area(n) = open_name(n);
- open_ext(n) = open_name(n);
+ 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;
+}
+
+@ @c
+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_glue_ref(a) { dorangetest(p,a,var_mem_max); }
+#define check_attribute_ref(a) { dorangetest(p,a,var_mem_max); }
+#define check_token_ref(a) { confusion("fuzzy token cleanup in node"); }
+
+#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);
+ }
+ }
+ }
+ }
}
- 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;
- rule_dir(n) = -1;
- rule_index(n) = 0;
- rule_transform(n) = 0;
- /* fall through */
- case unset_node:
- width(n) = null_flag;
- break;
- case pseudo_line_node:
- case shape_node:
- /* 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)));
+ }
+}
+
+#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;
}
- break;
- default:
- break;
+#endif
+ } else {
+ formatted_error("nodes", "attempt to free an impossible node %d", (int) p);
+ return 1;
}
- if (int_par(synctex_code)) {
- /* handle synctex extension */
- switch (i) {
- case math_node:
- synctex_tag_math(n) = cur_input.synctex_tag_field;
- synctex_line_math(n) = line;
- break;
- 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;
+ return 0;
+}
+
+@ @c
+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;
+}
+
+@ @c
+halfword new_node(int i, int j)
+{
+ int s = get_node_size(i, j);
+ halfword n = get_node(s);
+ /*
+ 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:
- case unset_node:
- synctex_tag_box(n) = cur_input.synctex_tag_field;
- synctex_line_box(n) = line;
+ 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:
- synctex_tag_rule(n) = cur_input.synctex_tag_field;
- synctex_line_rule(n) = line;
+ 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:
+ /* 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;
+ default:
+ break;
+ }
+ if (int_par(synctex_code)) {
+ /* handle synctex extension */
+ switch (i) {
+ case math_node:
+ synctex_tag_math(n) = cur_input.synctex_tag_field;
+ synctex_line_math(n) = line;
+ break;
+ 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;
}
}
/* take care of attributes */
@@ -689,19 +888,13 @@ halfword new_node(int i, int j)
}
type(n) = (quarterword) i;
subtype(n) = (quarterword) j;
-#ifdef DEBUG
- fprintf(DEBUG_OUT, "Alloc-ing %s node %d\n",
- get_node_name(type(n), subtype(n)), (int) n);
-#endif
return n;
}
halfword raw_glyph_node(void)
{
- register halfword n;
- n = get_node(glyph_node_size);
- (void) memset((void *) (varmem + n + 1), 0,
- (sizeof(memory_word) * (glyph_node_size - 1)));
+ register halfword n = get_node(glyph_node_size);
+ (void) memset((void *) (varmem + n + 1), 0, (sizeof(memory_word) * (glyph_node_size - 1)));
type(n) = glyph_node;
subtype(n) = 0;
return n;
@@ -709,10 +902,8 @@ halfword raw_glyph_node(void)
halfword new_glyph_node(void)
{
- register halfword n;
- n = get_node(glyph_node_size);
- (void) memset((void *) (varmem + n + 1), 0,
- (sizeof(memory_word) * (glyph_node_size - 1)));
+ register halfword n = get_node(glyph_node_size);
+ (void) memset((void *) (varmem + n + 1), 0, (sizeof(memory_word) * (glyph_node_size - 1)));
type(n) = glyph_node;
subtype(n) = 0;
build_attribute_list(n);
@@ -720,16 +911,15 @@ halfword new_glyph_node(void)
return n;
}
-
@ makes a duplicate of the node list that starts at |p| and returns a
- pointer to the new list
+pointer to the new list
+
@c
halfword do_copy_node_list(halfword p, halfword end)
{
- halfword q = null; /* previous position in new list */
- halfword h = null; /* head of the list */
+ halfword q = null; /* previous position in new list */
+ halfword h = null; /* head of the list */
register halfword s ;
- copy_error_seen = 0;
lua_properties_push; /* saves stack and time */
while (p != end) {
s = copy_node(p);
@@ -750,31 +940,6 @@ halfword copy_node_list(halfword p)
return do_copy_node_list(p, null);
}
-/* There is no gain in using a temp var:
-
- #define copy_sub_list(target,source) do { \
- l = source; \
- if (l != null) { \
- s = copy_node_list(l); \
- target = s; \
- } else { \
- target = null; \
- } \
- } while (0)
-
- #define copy_sub_node(target,source) do { \
- l = source; \
- if (l != null) { \
- s = copy_node(l); \
- target = s ; \
- } else { \
- target = null; \
- } \
- } while (0)
-
- So we use:
-*/
-
#define copy_sub_list(target,source) do { \
if (source != null) { \
s = do_copy_node_list(source, null); \
@@ -796,15 +961,6 @@ halfword copy_node_list(halfword p)
@ make a dupe of a single node
@c
-
-/*
- at some point we can use function pointers as in the backend itself:
-
- typedef void (*copy_function) ();
- copy_function *copy_functions;
- xmalloc((MAX_WHATSIT_TYPE + 1) * sizeof(copy_function));
-*/
-
static void copy_node_wrapup_core(halfword p, halfword r)
{
halfword s ;
@@ -829,7 +985,7 @@ static void copy_node_wrapup_core(halfword p, halfword r)
user_node_value(r) = s;
break;
case 's':
- /* |add_string_ref(user_node_value(p));| *//* if this was mpost .. */
+ /* |add_string_ref(user_node_value(p));| */
break;
case 't':
add_token_ref(user_node_value(p));
@@ -895,20 +1051,19 @@ halfword copy_node(const halfword p)
i = get_node_size(type(p), subtype(p));
r = get_node(i);
- (void) memcpy((void *) (varmem + r), (void *) (varmem + p),
- (sizeof(memory_word) * (unsigned) i));
+ (void) memcpy((void *) (varmem + r), (void *) (varmem + p), (sizeof(memory_word) * (unsigned) i));
if (int_par(synctex_code)) {
/* handle synctex extension */
switch (type(p)) {
- 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;
+ 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(type(p))) {
@@ -919,319 +1074,129 @@ halfword copy_node(const halfword p)
vlink(r) = null;
switch (type(p)) {
- case glyph_node:
- copy_sub_list(lig_ptr(r),lig_ptr(p)) ;
- break;
- case glue_node:
- add_glue_ref(glue_ptr(p));
- 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:
- if (glue_ptr(p) != zero_glue) {
+ case glyph_node:
+ copy_sub_list(lig_ptr(r),lig_ptr(p)) ;
+ break;
+ case glue_node:
add_glue_ref(glue_ptr(p));
- }
- break;
- case ins_node:
- add_glue_ref(split_top_ptr(p));
- 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:
- glue_ref_count(r) = null;
- break;
- case dir_node:
- case local_par_node:
- 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;
- }
-#ifdef DEBUG
- fprintf(DEBUG_OUT, "Alloc-ing %s node %d (copy of %d)\n",
- get_node_name(type(r), subtype(r)), (int) r, (int) p);
-#endif
- return r;
-}
-
-@ @c
-int valid_node(halfword p)
-{
- if (p > my_prealloc) {
- if (p < var_mem_max) {
-#ifndef NDEBUG
- if (varmem_sizes[p] > 0)
-#endif
- return 1;
- }
- } else {
- return 0;
- }
- return 0;
-}
-
-@ @c
-static void do_free_error(halfword p)
-{
- halfword r;
- char errstr[255] = { 0 };
- const char *errhlp[] = {
- "When I tried to free the node mentioned in the error message, it turned",
- "out it was not (or no longer) actually in use.",
- "Errors such as these are often caused by Lua node list alteration,",
- "but could also point to a bug in the executable. It should be safe to continue.",
- NULL
- };
-
- check_node_mem();
- if (free_error_seen)
- return;
-
- r = null;
- free_error_seen = 1;
- if (type(p) == glyph_node) {
- snprintf(errstr, 255,
- "Attempt to double-free glyph (%c) node %d, ignored",
- (int) character(p), (int) p);
- } else {
- snprintf(errstr, 255, "Attempt to double-free %s node %d, ignored",
- get_node_name(type(p), subtype(p)), (int) p);
- }
- tex_error(errstr, errhlp);
-#ifndef NDEBUG
- 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);
- }
- }
- }
+ 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:
+ if (glue_ptr(p) != zero_glue) {
+ add_glue_ref(glue_ptr(p));
+ }
+ break;
+ case ins_node:
+ add_glue_ref(split_top_ptr(p));
+ 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:
+ glue_ref_count(r) = null;
+ break;
+ case dir_node:
+ case local_par_node:
+ 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;
}
-#endif
+ return r;
}
-static int free_error(halfword p)
-{
- assert(p > my_prealloc);
- assert(p < var_mem_max);
-#ifndef NDEBUG
- if (varmem_sizes[p] == 0) {
- do_free_error(p);
- return 1; /* double free */
- }
-#endif
- return 0;
-}
+/* x */
-
-@ @c
-static void do_copy_error(halfword p)
-{
- char errstr[255] = { 0 };
- const char *errhlp[] = {
- "When I tried to copy the node mentioned in the error message, it turned",
- "out it was not (or no longer) actually in use.",
- "Errors such as these are often caused by Lua node list alteration,",
- "but could also point to a bug in the executable. It should be safe to continue.",
- NULL
- };
-
- if (copy_error_seen)
- return;
-
- copy_error_seen = 1;
- if (type(p) == glyph_node) {
- snprintf(errstr, 255,
- "Attempt to copy free glyph (%c) node %d, ignored",
- (int) character(p), (int) p);
- } else {
- snprintf(errstr, 255, "Attempt to copy free %s node %d, ignored",
- get_node_name(type(p), subtype(p)), (int) p);
- }
- tex_error(errstr, errhlp);
-}
-
-
-int copy_error(halfword p)
-{
- assert(p >= 0);
- assert(p < var_mem_max);
-#ifndef NDEBUG
- if (p > my_prealloc && varmem_sizes[p] == 0) {
- do_copy_error(p);
- return 1; /* copy free node */
- }
-#endif
- return 0;
-}
-
-/* No gain in a helper:
-
- #define free_sub_list(source) do { \
- l = source; \
- if (l != null) \
- flush_node_list(l); \
- } while (0)
-
- #define free_sub_node(source) do { \
- l = source; \
- if (l != null) \
- flush_node(l); \
- } while (0)
-
- So:
-
-*/
-
-#define free_sub_list(source) do { \
- if (source != null) \
- flush_node_list(source); \
-} while (0)
-
-#define free_sub_node(source) do { \
- if (source != null) \
- flush_node(source); \
-} while (0)
+#define free_sub_list(source) if (source != null) flush_node_list(source);
+#define free_sub_node(source) if (source != null) flush_node(source);
@ @c
@@ -1348,155 +1313,148 @@ void flush_node(halfword p)
halfword w;
if (p == null) /* legal, but no-op */
return;
-
-#ifdef DEBUG
- fprintf(DEBUG_OUT, "Free-ing %s node %d\n",
- get_node_name(type(p), subtype(p)), (int) p);
-#endif
if (free_error(p))
return;
-
switch (type(p)) {
- case glyph_node:
- free_sub_list(lig_ptr(p));
- break;
- case glue_node:
- delete_glue_ref(glue_ptr(p));
- 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:
- /* 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:
- break;
- case math_node:
- /* begin mathskip code */
- if (glue_ptr(p) != zero_glue) {
+ case glyph_node:
+ free_sub_list(lig_ptr(p));
+ break;
+ case glue_node:
delete_glue_ref(glue_ptr(p));
- }
- /* end mathskip code */
- break;
- case glue_spec_node:
- /* this allows free-ing of lua-allocated glue specs */
- if (valid_node(p)) {
- if (glue_ref_count(p)!=null) {
- decr(glue_ref_count(p));
+ 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:
+ /* 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:
+ break;
+ case math_node:
+ /* begin mathskip code */
+ if (glue_ptr(p) != zero_glue) {
+ delete_glue_ref(glue_ptr(p));
+ }
+ /* end mathskip code */
+ break;
+ case glue_spec_node:
+ /* this allows free-ing of lua-allocated glue specs */
+ if (valid_node(p)) {
+ if (glue_ref_count(p)!=null) {
+ decr(glue_ref_count(p));
+ } else {
+ free_node(p, get_node_size(type(p), subtype(p)));
+ }
+ }
+ return ;
+ break ;
+ case dir_node:
+ case local_par_node:
+ 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 {
- free_node(p, get_node_size(type(p), subtype(p)));
+ flush_node_wrapup_core(p);
}
- }
- return ;
- break ;
- case dir_node:
- case local_par_node:
- 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));
- delete_glue_ref(split_top_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: /* 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: /* nothing to do */
- case math_char_node:
- case math_text_char_node:
- 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:
- fprintf(stdout, "flush_node: type is %d\n", type(p));
- return;
-
+ break;
+ case ins_node:
+ flush_node_list(ins_ptr(p));
+ delete_glue_ref(split_top_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: /* 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: /* nothing to do */
+ case math_char_node:
+ case math_text_char_node:
+ 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));
@@ -1510,7 +1468,6 @@ void flush_node(halfword p)
void flush_node_list(halfword pp)
{ /* erase list of nodes starting at |p| */
register halfword p = pp;
- free_error_seen = 0;
if (p == null) /* legal, but no-op */
return;
if (free_error(p))
@@ -1525,27 +1482,6 @@ void flush_node_list(halfword pp)
}
@ @c
-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("dorangetest"); \
- } } 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("dotest"); \
- } } while (0)
-
-#define check_action_ref(a) { dorangetest(p,a,var_mem_max); }
-#define check_glue_ref(a) { dorangetest(p,a,var_mem_max); }
-#define check_attribute_ref(a) { dorangetest(p,a,var_mem_max); }
-#define check_token_ref(a) assert(1)
-
static void check_node_wrapup_core(halfword p)
{
switch (subtype(p)) {
@@ -1555,28 +1491,27 @@ static void check_node_wrapup_core(halfword 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(user_node_value(p));
- break;
- case 'n':
- dorangetest(p, user_node_value(p), var_mem_max);
- break;
- case 's':
- case 'd':
- break;
- default:
- confusion("extuser");
- break;
+ case 'a':
+ check_attribute_ref(user_node_value(p));
+ break;
+ case 't':
+ check_token_ref(user_node_value(p));
+ break;
+ case 'n':
+ dorangetest(p, user_node_value(p), var_mem_max);
+ break;
+ case 's':
+ case 'd':
+ break;
+ default:
+ confusion("unknown user node type");
+ break;
}
break;
case open_node:
case write_node:
case close_node:
case save_pos_node:
- confusion("ext3"); /* why */
break;
}
}
@@ -1631,7 +1566,7 @@ void check_node_wrapup_pdf(halfword p)
case pdf_end_thread_node:
break;
default:
- confusion("ext3");
+ confusion("wrapup pdf nodes");
break;
}
}
@@ -1640,185 +1575,120 @@ 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:
- check_glue_ref(glue_ptr(p));
- 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);
- check_glue_ref(split_top_ptr(p));
- 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:
- /* begin mathskip code */
- if (glue_ptr(p) != zero_glue) {
+ case glyph_node:
+ dorangetest(p, lig_ptr(p), var_mem_max);
+ break;
+ case glue_node:
check_glue_ref(glue_ptr(p));
- }
- /* end mathskip code */
- 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 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:
- case local_par_node:
- break;
- default:
- fprintf(stdout, "check_node: type is %d\n", type(p));
- }
-}
-
-@ @c
-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);
-}
-
-@ @c
-void check_node_mem(void)
-{
- int i;
- check_static_node_mem();
-#ifndef NDEBUG
- for (i = (my_prealloc + 1); i < var_mem_max; i++) {
- if (varmem_sizes[i] > 0) {
- check_node(i);
- }
+ 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);
+ check_glue_ref(split_top_ptr(p));
+ 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:
+ /* begin mathskip code */
+ if (glue_ptr(p) != zero_glue) {
+ check_glue_ref(glue_ptr(p));
+ }
+ /* end mathskip code */
+ 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 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:
+ case local_par_node:
+ break;
+ default:
+ fprintf(stdout, "check_node: type is %d\n", type(p));
+ */
}
-#endif
- test_count++;
}
@ @c
@@ -1840,49 +1710,34 @@ void fix_node_list(halfword head)
halfword get_node(int s)
{
register halfword r;
-#if 0
- check_static_node_mem();
-#endif
- assert(s < MAX_CHAIN_SIZE);
- r = free_chain[s];
- if (r != null) {
- free_chain[s] = vlink(r);
-#ifndef NDEBUG
- varmem_sizes[r] = (char) s;
+ 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;
- var_used += s; /* maintain usage statistics */
- return r;
- }
- /* this is the end of the 'inner loop' */
- return slow_get_node(s);
-}
-
-@ @c
-#ifdef DEBUG
-static void print_free_chain(int c)
-{
- halfword p = free_chain[c];
- fprintf(stdout, "\nfree chain[%d] =\n ", c);
- while (p != null) {
- fprintf(stdout, "%d,", (int) p);
- p = vlink(p);
+ vlink(r) = null;
+ var_used += s; /* maintain usage statistics */
+ return r;
+ }
+ /* this is the end of the 'inner loop' */
+ return slow_get_node(s);
+ } else {
+ normal_error("nodes","there is a problem in getting a node, case 1");
+ return null;
}
- fprintf(stdout, "null;\n");
}
-#endif
@ @c
void free_node(halfword p, int s)
{
-
if (p <= my_prealloc) {
- fprintf(stdout, "node %d (type %d) should not be freed!\n", (int) p,
- type(p));
+ formatted_error("nodes", "node number %d of type %d should not be freed", (int) p, type(p));
return;
}
-#ifndef NDEBUG
+#ifdef CHECK_NODE_USAGE
varmem_sizes[p] = 0;
#endif
if (s < MAX_CHAIN_SIZE) {
@@ -1897,7 +1752,8 @@ void free_node(halfword p, int s)
}
vlink(rover) = p;
}
- var_used -= s; /* maintain statistics */
+ /* maintain statistics */
+ var_used -= s;
}
@ @c
@@ -1905,37 +1761,37 @@ static void free_node_chain(halfword q, int s)
{
register halfword p = q;
while (vlink(p) != null) {
-#ifndef NDEBUG
+#ifdef CHECK_NODE_USAGE
varmem_sizes[p] = 0;
#endif
var_used -= s;
p = vlink(p);
}
var_used -= s;
-#ifndef NDEBUG
+#ifdef CHECK_NODE_USAGE
varmem_sizes[p] = 0;
#endif
vlink(p) = free_chain[s];
free_chain[s] = q;
}
-
@ @c
void init_node_mem(int t)
{
my_prealloc = var_mem_stat_max;
- assert(whatsit_node_data[user_defined_node].id == user_defined_node);
- assert(node_data[passive_node].id == passive_node);
- varmem =
- (memory_word *) realloc((void *) varmem,
- sizeof(memory_word) * (unsigned) t);
+ /* message ?
+
+ assert(whatsit_node_data[user_defined_node].id == user_defined_node);
+ assert(node_data[passive_node].id == passive_node);
+ */
+
+ 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));
-
-#ifndef NDEBUG
+#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);
@@ -2067,7 +1923,7 @@ void dump_node_mem(void)
dump_int(var_mem_max);
dump_int(rover);
dump_things(varmem[0], var_mem_max);
-#ifndef NDEBUG
+#ifdef CHECK_NODE_USAGE
dump_things(varmem_sizes[0], var_mem_max);
#endif
dump_things(free_chain[0], MAX_CHAIN_SIZE);
@@ -2077,6 +1933,7 @@ void dump_node_mem(void)
@ it makes sense to enlarge the varmem array immediately
@c
+
void undump_node_mem(void)
{
int x;
@@ -2084,11 +1941,8 @@ void undump_node_mem(void)
undump_int(rover);
var_mem_max = (x < 100000 ? 100000 : x);
varmem = xmallocarray(memory_word, (unsigned) var_mem_max);
-#if 0
- memset ((void *)varmem,0,x*sizeof(memory_word));
-#endif
undump_things(varmem[0], x);
-#ifndef NDEBUG
+#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);
@@ -2107,24 +1961,6 @@ void undump_node_mem(void)
}
}
-#if 0
-void test_rovers(char *s)
-{
- int q = rover;
- int r = q;
- fprintf(stdout, "%s: {rover=%d,size=%d,link=%d}", s, r, node_size(r),
- vlink(r));
- while (vlink(r) != q) {
- r = vlink(r);
- fprintf(stdout, ",{rover=%d,size=%d,link=%d}", r, node_size(r),
- vlink(r));
- }
- fprintf(stdout, "\n");
-}
-#else
-# define test_rovers(a)
-#endif
-
@ @c
halfword slow_get_node(int s)
{
@@ -2132,105 +1968,99 @@ halfword slow_get_node(int s)
RETRY:
t = node_size(rover);
- assert(vlink(rover) < var_mem_max);
- assert(vlink(rover) != 0);
- test_rovers("entry");
- if (t > s) {
- register halfword r;
- /* allocating from the bottom helps decrease page faults */
- r = rover;
- rover += s;
- vlink(rover) = vlink(r);
- node_size(rover) = node_size(r) - s;
- if (vlink(rover) != r) { /* list is longer than one */
- halfword q = r;
- while (vlink(q) != r) {
- q = vlink(q);
+ if (vlink(rover) < var_mem_max && vlink(rover) != 0) {
+ if (t > s) {
+ /* 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) { /* list is longer than one */
+ halfword q = r;
+ while (vlink(q) != r) {
+ q = vlink(q);
+ }
+ vlink(q) += s;
+ } else {
+ vlink(rover) += s;
}
- vlink(q) += s;
- } else {
- vlink(rover) += s;
- }
- test_rovers("taken");
- assert(vlink(rover) < var_mem_max);
-#ifndef NDEBUG
- varmem_sizes[r] = (char) (s > 127 ? 127 : s);
+ if (vlink(rover) < var_mem_max) {
+#ifdef CHECK_NODE_USAGE
+ varmem_sizes[r] = (char) (s > 127 ? 127 : s);
#endif
- vlink(r) = null;
- var_used += s; /* maintain usage statistics */
- return r; /* this is the only exit */
- } else {
- int x;
- /* attempt to keep the free list small */
- 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;
- test_rovers("outtake");
- goto RETRY;
+ vlink(r) = null;
+ var_used += s; /* maintain usage statistics */
+ return r; /* this is the only exit */
} else {
- halfword l = rover;
- while (vlink(rover) != l) {
- if (node_size(rover) > s) {
- goto RETRY;
+ normal_error("nodes","there is a problem in getting a node, case 2");
+ return null;
+ }
+ } else {
+ /* 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);
}
- rover = vlink(rover);
}
}
- }
- /* 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));
-
-#ifndef NDEBUG
- 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));
+ /* 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
-
- /* todo ? it is 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);
+ /* todo ? it is 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;
}
- vlink(rover) = var_mem_max;
- rover = var_mem_max;
- test_rovers("realloc");
- var_mem_max += x;
- goto RETRY;
+ } else {
+ normal_error("nodes","there is a problem in getting a node, case 3");
+ return null;
}
}
@ @c
char *sprint_node_mem_usage(void)
{
- int i, b;
-
- char *s, *ss;
-#ifndef NDEBUG
+ 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) {
@@ -2242,15 +2072,12 @@ char *sprint_node_mem_usage(void)
}
}
}
- s = strdup("");
- b = 0;
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));
+ 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);
@@ -2268,9 +2095,10 @@ char *sprint_node_mem_usage(void)
@ @c
halfword list_node_mem_usage(void)
{
+ halfword q = null;
+#ifdef CHECK_NODE_USAGE
+ halfword p = null;
halfword i, j;
- halfword p = null, q = null;
-#ifndef NDEBUG
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++) {
@@ -2297,8 +2125,7 @@ void print_node_mem_stats(void)
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));
+ 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(" ");
@@ -2311,13 +2138,13 @@ void print_node_mem_stats(void)
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]);
+ snprintf(msg, 255, "%s%d:%d", (b ? "," : ""), i, (int) free_chain_counts[i]);
tprint(msg);
b = 1;
}
}
- print_nlp(); /* newline, if needed */
+ /* newline, if needed */
+ print_nlp();
}
/* this belongs in the web but i couldn't find the correct syntactic place */
@@ -2400,14 +2227,9 @@ void build_attribute_list(halfword b)
}
attr_list_ref(attr_list_cache)++;
node_attr(b) = attr_list_cache;
-#ifdef DEBUG
- fprintf(DEBUG_OUT, "Added attrlist (%d) to node %d (count=%d)\n",
- node_attr(b), b, attr_list_ref(attr_list_cache));
-#endif
}
}
-
@ @c
halfword current_attribute_list(void)
{
@@ -2442,26 +2264,24 @@ void reassign_attribute(halfword n, halfword new)
node_attr(n) = new ;
}
-
-
@ @c
void delete_attribute_ref(halfword b)
{
if (b != null) {
- assert(type(b) == attribute_list_node);
- attr_list_ref(b)--;
-#ifdef DEBUG
- fprintf(DEBUG_OUT, "Removed attrlistref (%d) (count=%d)\n", b,
- attr_list_ref(b));
-#endif
- if (attr_list_ref(b) == 0) {
- if (b == attr_list_cache)
- attr_list_cache = cache_disabled;
- free_node_chain(b, attribute_node_size);
+ 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);
+ }
+ /* 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");
}
- /* maintain sanity */
- if (attr_list_ref(b) < 0)
- attr_list_ref(b) = 0;
}
}
@@ -2487,28 +2307,32 @@ halfword do_set_attribute(halfword p, int i, int val)
return q;
}
q = p;
- assert(vlink(p) != null);
- while (vlink(p) != null) {
- int t = attribute_id(vlink(p));
- if (t == i && attribute_value(vlink(p)) == val)
- return q; /* no need to do anything */
- if (t >= i)
- break;
- j++;
- p = vlink(p);
- }
+ if (vlink(p) != null) {
+ while (vlink(p) != null) {
+ int t = attribute_id(vlink(p));
+ if (t == i && attribute_value(vlink(p)) == val)
+ return q; /* no need to do anything */
+ 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 { /* add a new node */
- halfword r = new_attribute_node((unsigned) i, val);
- vlink(r) = vlink(p);
- vlink(p) = r;
+ p = q;
+ while (j-- > 0)
+ p = vlink(p);
+ if (attribute_id(vlink(p)) == i) {
+ attribute_value(vlink(p)) = val;
+ } else { /* 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 ;
}
- return q;
}
@ @c
@@ -2531,61 +2355,62 @@ void set_attribute(halfword n, int i, int val)
return;
}
/* we check if we have this attribute already and quit if the value stays the same */
- assert(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);
- }
- /* j has now the position (if found) .. we assume a sorted list ! */
- p = node_attr(n);
+ 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);
+ }
+ /* j has now the position (if found) .. we assume a sorted list ! */
+ p = node_attr(n);
- if (attr_list_ref(p) == 0 ) {
- /* the list is invalid i.e. freed already */
- fprintf(stdout,"Node %d has an attribute list that is free already\n",(int) n);
- /* the still dangling list gets ref count 1 */
- attr_list_ref(p) = 1;
- } else if (attr_list_ref(p) == 1) {
- /* this can really happen HH-LS */
- if (p == attr_list_cache) {
- /* we can invalidate the cache setting */
- /* attr_list_cache = cache_disabled */
- /* or save the list, as done below */
+ if (attr_list_ref(p) == 0 ) {
+ /* 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);
+ /* the still dangling list gets ref count 1 */
+ attr_list_ref(p) = 1;
+ } else if (attr_list_ref(p) == 1) {
+ /* this can really happen HH-LS */
+ if (p == attr_list_cache) {
+ /* we can invalidate the cache setting */
+ /* attr_list_cache = cache_disabled */
+ /* or save the list, as done below */
+ p = copy_attribute_list(p);
+ node_attr(n) = p;
+ /* the copied list gets ref count 1 */
+ attr_list_ref(p) = 1;
+ }
+ } else {
+ /* the list is used multiple times so we make a copy */
p = copy_attribute_list(p);
+ /* we decrement the ref count or the original */
+ delete_attribute_ref(node_attr(n));
node_attr(n) = p;
/* the copied list gets ref count 1 */
attr_list_ref(p) = 1;
}
- } else {
- /* the list is used multiple times so we make a copy */
- p = copy_attribute_list(p);
- /* we decrement the ref count or the original */
- delete_attribute_ref(node_attr(n));
- node_attr(n) = p;
- /* the copied list gets ref count 1 */
- attr_list_ref(p) = 1;
- }
- /* we go to position j in the list */
- while (j-- > 0)
- p = vlink(p);
- /* 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 { /* add a new node */
- halfword r = new_attribute_node((unsigned) i, val);
- vlink(r) = vlink(p);
- vlink(p) = r;
+ /* we go to position j in the list */
+ while (j-- > 0)
+ p = vlink(p);
+ /* 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 { /* 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");
}
- return;
}
-
@ @c
int unset_attribute(halfword n, int i, int val)
{
@@ -2599,43 +2424,45 @@ int unset_attribute(halfword n, int i, int val)
if (p == null)
return UNUSED_ATTRIBUTE;
if (attr_list_ref(p) == 0) {
- fprintf(stdout,
- "Node %d has an attribute list that is free already\n",
- (int) n);
+ formatted_warning("nodes","node %d has an attribute list that is free already, case 2", (int) n);
return UNUSED_ATTRIBUTE;
}
- assert(vlink(p) != null);
- while (vlink(p) != null) {
- t = attribute_id(vlink(p));
- if (t > i)
- return UNUSED_ATTRIBUTE;
- if (t == i) {
+ 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);
- break;
}
- j++;
- p = vlink(p);
- }
- if (attribute_id(p) != i)
- return UNUSED_ATTRIBUTE;
- /* 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));
+ if (attribute_id(p) != i)
+ return UNUSED_ATTRIBUTE;
+ /* 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;
}
- 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;
+ 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;
}
- return t;
}
@ @c
@@ -2666,37 +2493,33 @@ int has_attribute(halfword n, int i, int val)
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_ptr(p) != zero_glue)
- 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;
- default:
- assert(1);
- break;
+ 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_ptr(p) != zero_glue)
+ 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;
}
}
-
@ @c
static void show_pdftex_whatsit_rule_spec(int p)
{
@@ -2708,8 +2531,6 @@ static void show_pdftex_whatsit_rule_spec(int p)
print_rule_dimen(width(p));
}
-
-
@ 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;
@@ -2727,9 +2548,7 @@ static void print_write_whatsit(const char *s, pointer p)
print_char('-');
}
-
@ @c
-
static void show_node_wrapup_core(int p)
{
switch (subtype(p)) {
@@ -2811,7 +2630,7 @@ void show_node_wrapup_pdf(int p)
tprint(" current");
break;
default:
- confusion("pdfcolorstack");
+ confusion("colorstack");
break;
}
if (pdf_colorstack_cmd(p) <= colorstack_data)
@@ -2997,15 +2816,17 @@ void show_node_wrapup_pdf(int p)
@ Recursive calls on |show_node_list| therefore use the following pattern:
@c
-#define node_list_display(A) do { \
- append_char('.'); \
- show_node_list(A); \
- flush_char(); \
+#define node_list_display(A) do { \
+ append_char('.'); \
+ show_node_list(A); \
+ flush_char(); \
} while (0)
+/* prints a node list symbolically */
+
void show_node_list(int p)
-{ /* prints a node list symbolically */
- int n; /* the number of items already printed at this level */
+{
+ int n = 0; /* the number of items already printed at this level */
halfword w;
real g; /* a glue ratio, as a floating point number */
if ((int) cur_length > depth_threshold) {
@@ -3013,7 +2834,6 @@ void show_node_list(int p)
tprint(" []"); /* indicate that there's been some truncation */
return;
}
- n = 0;
while (p != null) {
print_ln();
print_current_string(); /* display the nesting history */
@@ -3111,6 +2931,10 @@ void show_node_list(int p)
/* 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) {
@@ -3221,7 +3045,7 @@ void show_node_list(int p)
print_char('g');
break;
default:
- assert(0);
+ normal_warning("nodes","weird glue leader subtype ignored");
}
tprint("leaders ");
print_spec(glue_ptr(p), NULL);
@@ -3321,7 +3145,7 @@ void show_node_list(int p)
case adjust_node:
/* Display adjustment |p|; */
tprint_esc("vadjust");
- if (adjust_pre(p) != 0)
+ if (subtype(p) != 0)
tprint(" pre ");
node_list_display(adjust_ptr(p)); /* recursive call */
break;
@@ -3345,70 +3169,67 @@ void show_node_list(int p)
@c
pointer actual_box_width(pointer r, scaled base_width)
{
- scaled w; /* calculated |size| */
- pointer p; /* current node when calculating |pre_display_size| */
- pointer q; /* glue specification when calculating |pre_display_size| */
- scaled d; /* increment to |v| */
- scaled v; /* |w| plus possible glue amount */
- w = -max_dimen;
- v = shift_amount(r) + base_width;
- p = list_ptr(r);
+ pointer q; /* glue specification when calculating |pre_display_size| */
+ scaled d; /* increment to |v| */
+ scaled w = -max_dimen; /* calculated |size| */
+ scaled v = shift_amount(r) + base_width; /* |w| plus possible glue amount */
+ pointer p = list_ptr(r); /* current node when calculating |pre_display_size| */
while (p != null) {
if (is_char_node(p)) {
d = glyph_width(p);
- goto found;
+ 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 math_node:
- /* begin mathskip code */
- if (glue_ptr(p) == zero_glue) {
- d = surround(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 math_node:
+ /* begin mathskip code */
+ if (glue_ptr(p) == zero_glue) {
+ d = surround(p);
+ break;
+ } else {
+ /* fall through */
+ }
+ /* end mathskip code */
+ case glue_node:
+ /* 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.
+ */
+ q = glue_ptr(p);
+ d = width(q);
+ if (glue_sign(r) == stretching) {
+ if ((glue_order(r) == stretch_order(q))
+ && (stretch(q) != 0))
+ v = max_dimen;
+ } else if (glue_sign(r) == shrinking) {
+ if ((glue_order(r) == shrink_order(q))
+ && (shrink(q) != 0))
+ v = max_dimen;
+ }
+ if (subtype(p) >= a_leaders)
+ goto FOUND;
+ break;
+ default:
+ d = 0;
break;
- } else {
- /* fall through */
- }
- /* end mathskip code */
- case glue_node:
- /* 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.
- */
- q = glue_ptr(p);
- d = width(q);
- if (glue_sign(r) == stretching) {
- if ((glue_order(r) == stretch_order(q))
- && (stretch(q) != 0))
- v = max_dimen;
- } else if (glue_sign(r) == shrinking) {
- if ((glue_order(r) == shrink_order(q))
- && (shrink(q) != 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:
+ goto NOT_FOUND;
+ FOUND:
if (v < max_dimen) {
v = v + d;
w = v;
@@ -3416,13 +3237,12 @@ pointer actual_box_width(pointer r, scaled base_width)
w = max_dimen;
break;
}
- not_found:
+ NOT_FOUND:
p = vlink(p);
}
return w;
}
-
@ @c
halfword tail_of_list(halfword p)
{
@@ -3432,29 +3252,26 @@ halfword tail_of_list(halfword p)
return q;
}
-
@ |delete_glue_ref| is called when a pointer to a glue
specification is being withdrawn.
@c
-#define fast_delete_glue_ref(A) do { \
- if (glue_ref_count(A)==null) { \
- flush_node(A); \
- } else { \
- decr(glue_ref_count(A)); \
- } \
- } while (0)
-
void delete_glue_ref(halfword p)
-{ /* |p| points to a glue specification */
- assert(type(p) == glue_spec_node);
- fast_delete_glue_ref(p);
+{ /* |p| points to a glue specification */
+ if (type(p) == glue_spec_node) {
+ if (glue_ref_count(p) == null) {
+ flush_node(p);
+ } else {
+ decr(glue_ref_count(p));
+ }
+ } else {
+ normal_error("nodes","invalid glue spec node");
+ }
}
@ @c
int var_used;
-halfword temp_ptr; /* a pointer variable for occasional emergency use */
-
+halfword temp_ptr; /* a pointer variable for occasional emergency use */
@ Attribute lists need two extra globals to increase processing efficiency.
|max_used_attr| limits the test loop that checks for set attributes, and
@@ -3464,7 +3281,7 @@ trusted: after an assignment to an attribute register, and after a group has
ended.
@c
-int max_used_attr; /* maximum assigned attribute id */
+int max_used_attr; /* maximum assigned attribute id */
halfword attr_list_cache;
@ From the computer's standpoint, \TeX's chief mission is to create
@@ -3478,7 +3295,6 @@ 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.
@@ -3507,17 +3323,14 @@ The |subtype| field is set to |min_quarterword|, since that's the desired
@c
halfword new_null_box(void)
{ /* creates a new box node */
- halfword p; /* the new node */
- p = new_node(hlist_node, min_quarterword);
+ halfword p = new_node(hlist_node, min_quarterword);
box_dir(p) = text_direction;
return p;
}
-
@ 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
@@ -3532,12 +3345,10 @@ ones that are not allowed to run.
@c
halfword new_rule(int s)
{
- halfword p; /* the new node */
- p = new_node(rule_node,s);
+ halfword p = new_node(rule_node,s);
return p;
}
-
@ 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|.
@@ -3593,7 +3404,6 @@ halfword new_glyph(int f, int c)
return p;
}
-
@ 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
@@ -3631,12 +3441,10 @@ halfword new_char(int f, int c)
set_to_character(p);
font(p) = f;
character(p) = c;
- lang_data(p) =
- make_lang_data(uc_hyph, cur_lang, left_hyphen_min, right_hyphen_min);
+ lang_data(p) = make_lang_data(uc_hyph, cur_lang, left_hyphen_min, right_hyphen_min);
return p;
}
-
@ 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.
@@ -3646,15 +3454,13 @@ and \.{\\rightghost}, respectively. They are going to be removed by
@c
scaled glyph_width(halfword p)
{
- scaled w;
- w = char_width(font(p), character(p));
+ scaled w = char_width(font(p), character(p));
return w;
}
scaled glyph_height(halfword p)
{
- scaled w;
- w = char_height(font(p), character(p)) + y_displace(p);
+ scaled w = char_height(font(p), character(p)) + y_displace(p);
if (w < 0)
w = 0;
return w;
@@ -3662,8 +3468,7 @@ scaled glyph_height(halfword p)
scaled glyph_depth(halfword p)
{
- scaled w;
- w = char_depth(font(p), character(p));
+ scaled w = char_depth(font(p), character(p));
if (y_displace(p) > 0)
w = w - y_displace(p);
if (w < 0)
@@ -3671,7 +3476,6 @@ scaled glyph_depth(halfword p)
return w;
}
-
@ 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
@@ -3694,8 +3498,7 @@ not chosen.
@c
halfword new_disc(void)
{ /* creates an empty |disc_node| */
- halfword p; /* the new node */
- p = new_node(disc_node, 0);
+ halfword p = new_node(disc_node, 0);
disc_penalty(p) = int_par(hyphen_penalty_code);
return p;
}
@@ -3724,8 +3527,7 @@ the amount of surrounding space inserted by \.{\\mathsurround}.
@c
halfword new_math(scaled w, int s)
{
- halfword p; /* the new node */
- p = new_node(math_node, s);
+ halfword p = new_node(math_node, s);
surround(p) = w;
return p;
}
@@ -3784,8 +3586,7 @@ to be exactly one reference to the new specification.
@c
halfword new_spec(halfword p)
{ /* duplicates a glue specification */
- halfword q; /* the new spec */
- q = copy_node(p);
+ halfword q = copy_node(p);
glue_ref_count(q) = null;
return q;
}
@@ -3798,10 +3599,8 @@ current \.{\\lineskip}.
@c
halfword new_param_glue(int n)
{
- halfword p; /* the new node */
- halfword q; /* the glue specification */
- p = new_node(glue_node, n + 1);
- q = glue_par(n);
+ halfword p = new_node(glue_node, n + 1);
+ halfword q = glue_par(n);
glue_ptr(p) = q;
incr(glue_ref_count(q));
return p;
@@ -3813,8 +3612,7 @@ whose argument points to a glue specification.
@c
halfword new_glue(halfword q)
{
- halfword p; /* the new node */
- p = new_node(glue_node, normal);
+ halfword p = new_node(glue_node, normal);
glue_ptr(p) = q;
incr(glue_ref_count(q));
return p;
@@ -3854,8 +3652,7 @@ inserted from \.{\\mkern} specifications in math formulas).
@c
halfword new_kern(scaled w)
{
- halfword p; /* the new node */
- p = new_node(kern_node, normal);
+ halfword p = new_node(kern_node, normal);
width(p) = w;
return p;
}
@@ -3873,8 +3670,7 @@ be able to guess what comes next.
@c
halfword new_penalty(int m)
{
- halfword p; /* the new node */
- p = new_node(penalty_node, 0); /* the |subtype| is not used */
+ halfword p = new_node(penalty_node, 0); /* the |subtype| is not used */
penalty(p) = m;
return p;
}
@@ -3908,12 +3704,14 @@ the \.{WEB} macro definitions above, so that format changes will leave
\TeX's other algorithms intact.
@^system dependencies@>
-@ @c
+@ This function creates a |local_paragraph| node
+
+@c
+
halfword make_local_par_node(void)
-/* This function creates a |local_paragraph| node */
{
- halfword p, q;
- p = new_node(local_par_node,0);
+ halfword q;
+ halfword p = new_node(local_par_node,0);
local_pen_inter(p) = local_inter_line_penalty;
local_pen_broken(p) = local_broken_penalty;
if (local_left_box != null) {
@@ -3929,5 +3727,3 @@ halfword make_local_par_node(void)
local_par_dir(p) = par_direction;
return p;
}
-
-
diff --git a/Build/source/texk/web2c/luatexdir/tex/textcodes.h b/Build/source/texk/web2c/luatexdir/tex/textcodes.h
index 4249ce631b1..759d9ee740e 100644
--- a/Build/source/texk/web2c/luatexdir/tex/textcodes.h
+++ b/Build/source/texk/web2c/luatexdir/tex/textcodes.h
@@ -1,5 +1,5 @@
/* textcodes.h
-
+
Copyright 2009 Taco Hoekwater <taco@luatex.org>
This file is part of LuaTeX.
@@ -15,31 +15,40 @@
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/>. */
+ 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_cat_code(int h, int n, halfword v, quarterword gl);
-halfword get_cat_code(int h, int n);
-void unsave_cat_codes(int h, quarterword gl);
-int valid_catcode_table(int h);
-void initex_cat_codes(int h);
-void unsave_text_codes(quarterword grouplevel);
+
+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 copy_cat_codes(int from, int to);
+
void free_math_codes(void);
void free_text_codes(void);
-
#endif
diff --git a/Build/source/texk/web2c/luatexdir/tex/textcodes.w b/Build/source/texk/web2c/luatexdir/tex/textcodes.w
index 6487e821c70..8a4fbb949c5 100644
--- a/Build/source/texk/web2c/luatexdir/tex/textcodes.w
+++ b/Build/source/texk/web2c/luatexdir/tex/textcodes.w
@@ -19,37 +19,178 @@
@ @c
-
#include "ptexlib.h"
-@ @c
-#define LCCODESTACK 8
-#define LCCODEDEFAULT 0
+@ catcodes @c
-static sa_tree lccode_head = NULL;
+#define CATCODESTACK 8
+#define CATCODEDEFAULT 12
+#define CATCODE_MAX 32767
-#define UCCODESTACK 8
-#define UCCODEDEFAULT 0
+static sa_tree *catcode_heads = NULL;
+static int catcode_max = 0;
+static unsigned char *catcode_valid = NULL;
-static sa_tree uccode_head = 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);
+}
-#define SFCODESTACK 8
-#define SFCODEDEFAULT 1000
+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;
+}
-static sa_tree sfcode_head = NULL;
+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);
+ }
+}
-#define CATCODESTACK 8
-#define CATCODEDEFAULT 12
+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]);
+ }
+ }
+}
+
+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();
+ 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);
+}
+
+@ lccodes @c
+
+#define LCCODESTACK 8
+#define LCCODEDEFAULT 0
+
+static sa_tree lccode_head = NULL;
void set_lc_code(int n, halfword v, quarterword gl)
{
- set_sa_item(lccode_head, n, (sa_tree_item) v, 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);
+ return (halfword) get_sa_item(lccode_head, n).int_value;
}
static void unsavelccodes(quarterword gl)
@@ -59,7 +200,9 @@ static void unsavelccodes(quarterword gl)
static void initializelccodes(void)
{
- lccode_head = new_sa_tree(LCCODESTACK, LCCODEDEFAULT);
+ sa_tree_item sa_value = { 0 };
+ sa_value.int_value = LCCODEDEFAULT;
+ lccode_head = new_sa_tree(LCCODESTACK, 1, sa_value);
}
static void dumplccodes(void)
@@ -72,14 +215,28 @@ static void undumplccodes(void)
lccode_head = undump_sa_tree();
}
+static void freelccodes(void)
+{
+ destroy_sa_tree(lccode_head);
+}
+
+@ uccodes @c
+
+#define UCCODESTACK 8
+#define UCCODEDEFAULT 0
+
+static sa_tree uccode_head = NULL;
+
void set_uc_code(int n, halfword v, quarterword gl)
{
- set_sa_item(uccode_head, n, (sa_tree_item) v, 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);
+ return (halfword) get_sa_item(uccode_head, n).int_value;
}
static void unsaveuccodes(quarterword gl)
@@ -89,7 +246,9 @@ static void unsaveuccodes(quarterword gl)
static void initializeuccodes(void)
{
- uccode_head = new_sa_tree(UCCODESTACK, UCCODEDEFAULT);
+ sa_tree_item sa_value = { 0 };
+ sa_value.int_value = UCCODEDEFAULT;
+ uccode_head = new_sa_tree(UCCODESTACK, 1, sa_value);
}
static void dumpuccodes(void)
@@ -102,14 +261,28 @@ static void undumpuccodes(void)
uccode_head = undump_sa_tree();
}
+static void freeuccodes(void)
+{
+ destroy_sa_tree(uccode_head);
+}
+
+@ sfcodes @c
+
+#define SFCODESTACK 8
+#define SFCODEDEFAULT 1000
+
+static sa_tree sfcode_head = NULL;
+
void set_sf_code(int n, halfword v, quarterword gl)
{
- set_sa_item(sfcode_head, n, (sa_tree_item) v, 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);
+ return (halfword) get_sa_item(sfcode_head, n).int_value;
}
static void unsavesfcodes(quarterword gl)
@@ -119,7 +292,9 @@ static void unsavesfcodes(quarterword gl)
static void initializesfcodes(void)
{
- sfcode_head = new_sa_tree(SFCODESTACK, SFCODEDEFAULT);
+ sa_tree_item sa_value = { 0 };
+ sa_value.int_value = SFCODEDEFAULT;
+ sfcode_head = new_sa_tree(SFCODESTACK, 1, sa_value);
}
static void dumpsfcodes(void)
@@ -132,188 +307,180 @@ static void undumpsfcodes(void)
sfcode_head = undump_sa_tree();
}
+static void freesfcodes(void)
+{
+ destroy_sa_tree(sfcode_head);
+}
-static sa_tree *catcode_heads = NULL;
-static int catcode_max = 0;
-static unsigned char *catcode_valid = NULL;
+@ hjcodes @c
-#define CATCODE_MAX 32767
+#define HJCODESTACK 8
+#define HJCODEDEFAULT 0
+#define HJCODE_MAX 16383 /* number of languages */
-#define update_catcode_max(h) if (h > catcode_max) catcode_max = h
+static sa_tree *hjcode_heads = NULL;
+static int hjcode_max = 0;
+static unsigned char *hjcode_valid = NULL;
-void set_cat_code(int h, int n, halfword v, quarterword gl)
+@ Here we set codes but we don't initialize from lccodes.
+
+@c void set_hj_code(int h, int n, halfword v, quarterword gl)
{
- sa_tree s = catcode_heads[h];
- update_catcode_max(h);
+ sa_tree_item sa_value = { 0 };
+ sa_tree s = hjcode_heads[h];
+ if (h > hjcode_max)
+ hjcode_max = h;
if (s == NULL) {
- s = new_sa_tree(CATCODESTACK, CATCODEDEFAULT);
- catcode_heads[h] = s;
+ sa_value.int_value = HJCODEDEFAULT;
+ s = new_sa_tree(HJCODESTACK, 1, sa_value);
+ hjcode_heads[h] = s;
}
- set_sa_item(s, n, (sa_tree_item) v, gl);
+ sa_value.int_value = (int) v;
+ set_sa_item(s, n, sa_value, gl);
}
-halfword get_cat_code(int h, int n)
+@ We just return the lccodes when nothing is set.
+
+@c halfword get_hj_code(int h, int n)
{
- sa_tree s = catcode_heads[h];
- update_catcode_max(h);
+ sa_tree s = hjcode_heads[h];
if (s == NULL) {
- s = new_sa_tree(CATCODESTACK, CATCODEDEFAULT);
- catcode_heads[h] = s;
+ s = lccode_head;
}
- return (halfword) get_sa_item(s, n);
+ return (halfword) get_sa_item(s, n).int_value;
}
-void unsave_cat_codes(int h, quarterword gl)
-{
- int k;
- update_catcode_max(h);
- for (k = 0; k <= catcode_max; k++) {
- if (catcode_heads[k] != NULL)
- restore_sa_stack(catcode_heads[k], gl);
- }
-}
+@ 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:
+
+@c
+/*
+ static void unsavehjcodes(quarterword gl) { }
+*/
-#if 0
-static void clearcatcodestack(int h)
+static void initializehjcodes(void)
{
- clear_sa_stack(catcode_heads[h]);
+ 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);
}
-#endif
-static void initializecatcodes(void)
+void hj_codes_from_lc_codes(int h)
{
- catcode_max = 0;
-#if 0
- xfree(catcode_heads); /* not needed */
- xfree(catcode_valid);
-#endif
- 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;
- catcode_heads[0] = new_sa_tree(CATCODESTACK, CATCODEDEFAULT);
+ 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 dumpcatcodes(void)
+static void dumphjcodes(void)
{
- int k, total;
- dump_int(catcode_max);
- total = 0;
- for (k = 0; k <= catcode_max; k++) {
- if (catcode_valid[k]) {
+ 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 <= catcode_max; k++) {
- if (catcode_valid[k]) {
+ for (k = 0; k <= hjcode_max; k++) {
+ if (hjcode_valid[k]) {
dump_int(k);
- dump_sa_tree(catcode_heads[k]);
+ dump_sa_tree(hjcode_heads[k]);
}
}
}
-static void undumpcatcodes(void)
+static void undumphjcodes(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);
+ 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);
- catcode_heads[x] = undump_sa_tree();
- catcode_valid[x] = 1;
+ hjcode_heads[x] = undump_sa_tree();
+ hjcode_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);
- }
- update_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)
+static void freehjcodes(void)
{
int k;
- update_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);
+ for (k = 0; k <= hjcode_max; k++) {
+ if (hjcode_valid[k]) {
+ destroy_sa_tree(hjcode_heads[k]);
+ }
}
- catcode_valid[h] = 1;
+ xfree(hjcode_heads);
+ xfree(hjcode_valid);
}
+/* management */
+
void unsave_text_codes(quarterword grouplevel)
{
- unsavesfcodes(grouplevel);
- unsaveuccodes(grouplevel);
unsavelccodes(grouplevel);
+ unsaveuccodes(grouplevel);
+ unsavesfcodes(grouplevel);
}
void initialize_text_codes(void)
{
- initializesfcodes();
- initializeuccodes();
initializecatcodes();
initializelccodes();
+ initializeuccodes();
+ initializesfcodes();
+ initializehjcodes();
}
void free_text_codes(void)
{
- int k;
- destroy_sa_tree(lccode_head);
- destroy_sa_tree(uccode_head);
- destroy_sa_tree(sfcode_head);
- for (k = 0; k <= catcode_max; k++) {
- if (catcode_valid[k]) {
- destroy_sa_tree(catcode_heads[k]);
- }
- }
- xfree(catcode_heads);
- xfree(catcode_valid);
+ freecatcodes();
+ freelccodes();
+ freeuccodes();
+ freesfcodes();
+ freehjcodes();
}
-
void dump_text_codes(void)
{
- dumpsfcodes();
- dumpuccodes();
- dumplccodes();
dumpcatcodes();
+ dumplccodes();
+ dumpuccodes();
+ dumpsfcodes();
+ dumphjcodes();
}
void undump_text_codes(void)
{
- undumpsfcodes();
- undumpuccodes();
- undumplccodes();
undumpcatcodes();
+ undumplccodes();
+ undumpuccodes();
+ undumpsfcodes();
+ undumphjcodes();
}
diff --git a/Build/source/texk/web2c/luatexdir/tex/textoken.h b/Build/source/texk/web2c/luatexdir/tex/textoken.h
index 241d672264f..71c5777e1dc 100644
--- a/Build/source/texk/web2c/luatexdir/tex/textoken.h
+++ b/Build/source/texk/web2c/luatexdir/tex/textoken.h
@@ -151,6 +151,7 @@ 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(int how);
extern int scan_lua_state(void);
diff --git a/Build/source/texk/web2c/luatexdir/tex/textoken.w b/Build/source/texk/web2c/luatexdir/tex/textoken.w
index 43445721435..0c11bb0f290 100644
--- a/Build/source/texk/web2c/luatexdir/tex/textoken.w
+++ b/Build/source/texk/web2c/luatexdir/tex/textoken.w
@@ -31,6 +31,7 @@
#define every_eof equiv(every_eof_loc)
#define box(A) equiv(box_base+(A))
+#define toks(A) equiv(toks_base+(A))
#define detokenized_line() (line_catcode_table==NO_CAT_TABLE)
@@ -42,19 +43,18 @@
} while (0)
-@ 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.
+@ 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.
+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.
@@ -64,11 +64,11 @@ smemory_word *fixmem; /* the big dynamic storage area */
unsigned fix_mem_min; /* the smallest location of one-word memory in use */
unsigned fix_mem_max; /* the largest location of one-word memory in use */
-@ 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.
+@ 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.
@c
int var_used, dyn_used; /* how much memory is in use */
@@ -110,14 +110,14 @@ void initialize_tokens(void)
dyn_used = 0; /* initialize statistics */
}
-@ 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.
+@ 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.
@^inner loop@>
-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.
+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.
@c
halfword get_avail(void)
@@ -151,8 +151,8 @@ halfword get_avail(void)
return (halfword) p;
}
-@ The procedure |flush_list(p)| frees an entire linked list of
-one-word nodes that starts at position |p|.
+@ The procedure |flush_list(p)| frees an entire linked list of one-word nodes
+that starts at position |p|.
@^inner loop@>
@c
@@ -171,46 +171,45 @@ void flush_list(halfword p)
}
}
-@ A \TeX\ token is either a character or a control sequence, and it is
-@^token@>
-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 \TeX\ token is either a character or a control sequence, and it is @^token@>
+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
+|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
+
$$\.{\\def\\mac a\#1\#2 \\b \{\#1\\-a \#\#1\#2 \#2\}}$$
+
the definition of \.{\\mac} is represented as a token list containing
+
$$\def\,{\hskip2pt}
\vbox{\halign{\hfil#\hfil\cr
(reference count), |letter|\,\.a, |match|\,\#, |match|\,\#, |spacer|\,\.\ ,
@@ -218,25 +217,23 @@ $$\def\,{\hskip2pt}
|out_param|\,1, \.{\\-}, |letter|\,\.a, |spacer|\,\.\ , |mac_param|\,\#,
|other_char|\,\.1,\cr
|out_param|\,2, |spacer|\,\.\ , |out_param|\,2.\cr}}$$
-The procedure |scan_toks| builds such token lists, and |macro_call|
-does the parameter matching.
-@^reference counts@>
-Examples such as
-$$\.{\\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.
+The procedure |scan_toks| builds such token lists, and |macro_call| does the
+parameter matching. @^reference counts@>
+
+Examples such as $$\.{\\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.
+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.
+The |print_meaning| subroutine displays |cur_cmd| and |cur_chr| in symbolic form,
+including the expansion of a macro or mark.
@c
void print_meaning(void)
@@ -272,31 +269,29 @@ void print_meaning(void)
}
}
-@ 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\ }'.
+@ 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\ }'.
@c
#define not_so_bad(p) \
@@ -320,11 +315,9 @@ a real control sequence named \.{BAD} would come out `\.{\\BAD\ }'.
void show_token_list(int p, int q, int l)
{
- int m, c; /* pieces of a token */
- ASCII_code match_chr; /* character used in a `|match|' */
- ASCII_code n; /* the highest parameter number, as an ASCII digit */
- match_chr = '#';
- n = '0';
+ int m, c; /* pieces of a token */
+ ASCII_code match_chr = '#'; /* character used in a `|match|' */
+ ASCII_code n = '0'; /* the highest parameter number, as an ASCII digit */
tally = 0;
if (l < 0)
l = 0x3FFFFFFF;
@@ -347,51 +340,54 @@ void show_token_list(int p, int q, int l)
if (token_info(p) < 0) {
tprint_esc("BAD");
} else {
- /* Display the token $(|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. */
+ /*
+ Display the token $(|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))
+ 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);
- 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;
+ 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;
}
}
}
@@ -402,14 +398,13 @@ void show_token_list(int p, int q, int l)
}
@ @c
-#define do_buffer_to_unichar(a,b) do { \
- a = (halfword)str2uni(buffer+b); \
- b += utf8_size(a); \
- } while (0)
-
+#define do_buffer_to_unichar(a,b) do { \
+ a = (halfword)str2uni(buffer+b); \
+ b += utf8_size(a); \
+} while (0)
-@ Here's the way we sometimes want to display a token list, given a pointer
-to its reference count; the pointer may be null.
+@ Here's the way we sometimes want to display a token list, given a pointer to
+its reference count; the pointer may be null.
@c
void token_show(halfword p)
@@ -418,17 +413,17 @@ void token_show(halfword p)
show_token_list(token_link(p), null, 10000000);
}
-@ |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.
+@ |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.
@^reference counts@>
+@ |p| points to the reference count of a token list that is losing one
+reference.
+
@c
void delete_token_ref(halfword p)
-{ /* |p| points to the reference count
- of a token list that is losing one reference */
- assert(token_ref_count(p) >= 0);
+{
if (token_ref_count(p) == 0)
flush_list(p);
else
@@ -446,8 +441,8 @@ int get_char_cat_code(int curchr)
@ @c
static void invalid_character_error(void)
{
- const char *hlp[] =
- { "A funny symbol that I can't read has just been input.",
+ 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
};
@@ -461,26 +456,26 @@ static boolean process_sup_mark(void); /* below */
static int scan_control_sequence(void); /* below */
-typedef enum { next_line_ok, next_line_return,
+typedef enum {
+ next_line_ok,
+ next_line_return,
next_line_restart
} next_line_retval;
-static next_line_retval next_line(void); /* below */
+static next_line_retval next_line(void); /* below */
-@ 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.
+@ 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.).
- @^inner loop@>
+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.). @^inner loop@>
@c
boolean scan_keyword(const char *s)
@@ -509,7 +504,7 @@ boolean scan_keyword(const char *s)
token_link(p) = q;
begin_token_list(token_link(backup_head), backed_up);
if (cur_cmd != endv_cmd)
- align_state = saved_align_state;
+ align_state = saved_align_state;
} else {
back_input();
}
@@ -517,7 +512,8 @@ boolean scan_keyword(const char *s)
return false;
}
}
- flush_list(token_link(backup_head));
+ if (token_link(backup_head) != null)
+ flush_list(token_link(backup_head));
cur_cs = save_cur_cs;
if (cur_cmd != endv_cmd)
align_state = saved_align_state;
@@ -528,36 +524,119 @@ boolean scan_keyword(const char *s)
(inside |shift_case|, for example). This needs thinking.
@c
+
+/*
+ halfword active_to_cs(int curchr, int force)
+ {
+ halfword curcs;
+ char *a, *b;
+ char *utfbytes = xmalloc(8);
+ int nncs = no_new_control_sequence;
+ a = (char *) uni2str(0xFFFF);
+ utfbytes = strcpy(utfbytes, a);
+ if (force)
+ no_new_control_sequence = false;
+ if (curchr > 0) {
+ b = (char *) uni2str((unsigned) curchr);
+ utfbytes = strcat(utfbytes, b);
+ free(b);
+ curcs = string_lookup(utfbytes, strlen(utfbytes));
+ } else {
+ utfbytes[3] = '\0';
+ curcs = string_lookup(utfbytes, 4);
+ }
+ no_new_control_sequence = nncs;
+ free(a);
+ free(utfbytes);
+ return curcs;
+ }
+*/
+
+/*static char * FFFF = "\xEF\xBF\xBF";*/ /* 0xFFFF */
+
halfword active_to_cs(int curchr, int force)
{
halfword curcs;
- char *a, *b;
- char *utfbytes = xmalloc(10);
int nncs = no_new_control_sequence;
- a = (char *) uni2str(0xFFFF);
- utfbytes = strcpy(utfbytes, a);
- if (force)
+ if (force) {
no_new_control_sequence = false;
+ }
if (curchr > 0) {
- b = (char *) uni2str((unsigned) curchr);
+ 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, strlen(utfbytes));
+ curcs = string_lookup(utfbytes, utf8_size(curchr)+3);
+ free(utfbytes);
} else {
- utfbytes[3] = '\0';
- curcs = string_lookup(utfbytes, 4);
+ curcs = string_lookup("\xEF\xBF\xBF", 4); /* 0xFFFF ... why not 3 ? */
}
no_new_control_sequence = nncs;
- free(a);
- free(utfbytes);
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;
+ }
+
+*/
+
@ TODO this function should listen to \.{\\escapechar}
+@ prints a control sequence
+
@c
static char *cs_to_string(halfword p)
-{ /* prints a control sequence */
+{
const char *s;
char *sh;
int k = 0;
@@ -614,57 +693,51 @@ static char *cmd_chr_to_string(int cmd, int chr)
return s;
}
-@ 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.
-@^eyes and mouth@>
+@ 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. @^eyes and mouth@>
-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.
+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.
+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.
+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.
@c
-halfword par_loc; /* location of `\.{\\par}' in |eqtb| */
-halfword par_token; /* token representing `\.{\\par}' */
-
+halfword par_loc; /* location of `\.{\\par}' in |eqtb| */
+halfword par_token; /* token representing `\.{\\par}' */
@ Parts |get_next| are executed more often than any other instructions of \TeX.
@^mastication@>@^inner loop@>
-
-
-@ 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|.
+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|.
@c
-boolean force_eof; /* should the next \.{\\input} be aborted early? */
-int luacstrings; /* how many lua strings are waiting to be input? */
+boolean force_eof; /* should the next \.{\\input} be aborted early? */
+int luacstrings; /* how many lua strings are waiting to be input? */
-@ 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.
+@ 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.
@c
void firm_up_the_line(void)
@@ -690,10 +763,10 @@ void firm_up_the_line(void)
}
}
-@ 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.
+@ 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.
@c
void check_outer_validity(void)
@@ -717,8 +790,8 @@ void check_outer_validity(void)
cur_chr = ' '; /* replace it by a space */
}
if (scanner_status > skipping) {
- const char *errhlp[] =
- { "I suspect you have forgotten a `}', causing me",
+ 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.",
@@ -777,14 +850,14 @@ void check_outer_validity(void)
tex_error(errmsg, errhlp);
} else {
char errmsg[256];
- const char *errhlp_no[] =
- { "The file ended while I was skipping conditional text.",
+ 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.",
+ 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
@@ -796,9 +869,8 @@ void check_outer_validity(void)
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);
+ snprintf(errmsg, 255, "Incomplete %s; all text was ignored after line %d",
+ ss, (int) skip_line);
free(ss);
/* Incomplete \\if... */
cur_tok = cs_token_flag + frozen_fi;
@@ -816,10 +888,19 @@ void check_outer_validity(void)
}
@ @c
+
+#if 0
+
+/*
+ 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) { /* current line not yet finished */
+ if (iloc <= ilimit) {
+ /* current line not yet finished */
do_buffer_to_unichar(cur_chr, iloc);
RESWITCH:
@@ -829,127 +910,160 @@ static boolean get_next_file(void)
do_get_cat_code(cur_cmd, cur_chr);
}
/*
- 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.
- */
+ 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:
+
+ 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;
+ }
+
+ 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: /* Cases where character is ignored */
- goto SWITCH;
- break;
- case mid_line + escape_cmd:
- case new_line + escape_cmd:
- case skip_blanks + escape_cmd: /* Scan a control sequence ...; */
- istate = (unsigned char) scan_control_sequence();
- if (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: /* 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 (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: /* If this |sup_mark| starts */
- if (process_sup_mark())
- goto RESWITCH;
- else
+ 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:
+ /* Cases where character is ignored */
+ goto SWITCH;
+ break;
+ case mid_line + escape_cmd:
+ case new_line + escape_cmd:
+ case skip_blanks + escape_cmd:
+ /* Scan a control sequence ...; */
+ istate = (unsigned char) scan_control_sequence();
+ if (! suppress_outer_error && 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:
+ /* 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;
- break;
- case mid_line + invalid_char_cmd:
- case new_line + invalid_char_cmd:
- case skip_blanks + invalid_char_cmd: /* Decry the invalid character and |goto restart|; */
- invalid_character_error();
- return false; /* because state may be |token_list| now */
- break;
- case mid_line + spacer_cmd: /* Enter |skip_blanks| state, emit a space; */
- istate = skip_blanks;
- cur_chr = ' ';
- break;
- case mid_line + car_ret_cmd: /* 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: /* Finish line, |goto switch|; */
- iloc = ilimit + 1;
- goto SWITCH;
- break;
- case new_line + car_ret_cmd: /* Finish line, emit a \.{\\par}; */
- iloc = ilimit + 1;
- cur_cs = par_loc;
- cur_cmd = eq_type(cur_cs);
- cur_chr = equiv(cur_cs);
- if (cur_cmd >= outer_call_cmd)
- check_outer_validity();
- break;
- case skip_blanks + left_brace_cmd:
- case new_line + left_brace_cmd:
- istate = mid_line; /* 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; /* 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;
-#if 0
- 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:
-#else
- default:
-#endif
- istate = mid_line;
- break;
+ if (! suppress_outer_error && 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:
+ /* 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:
+ /* Decry the invalid character and |goto restart|; */
+ invalid_character_error();
+ return false; /* because state may be |token_list| now */
+ break;
+ case mid_line + spacer_cmd:
+ /* Enter |skip_blanks| state, emit a space; */
+ istate = skip_blanks;
+ cur_chr = ' ';
+ break;
+ case mid_line + car_ret_cmd:
+ /*
+ 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:
+ /* Finish line, |goto switch|; */
+ iloc = ilimit + 1;
+ goto SWITCH;
+ break;
+ case new_line + car_ret_cmd:
+ /* 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 && cur_cmd >= outer_call_cmd)
+ check_outer_validity();
+ break;
+ case skip_blanks + left_brace_cmd:
+ case new_line + left_brace_cmd:
+ istate = mid_line;
+ /* 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;
+ /* 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;
-
/*
Move to next line of file,
or |goto restart| if there is no next line,
@@ -969,108 +1083,389 @@ static boolean get_next_file(void)
return true;
}
-@ @c
-#define is_hex(a) ((a>='0'&&a<='9')||(a>='a'&&a<='f'))
-
-#define add_nybble(a) do { \
- if (a<='9') cur_chr=(cur_chr<<4)+a-'0'; \
- else cur_chr=(cur_chr<<4)+a-'a'+10; \
- } while (0)
-
-#define hex_to_cur_chr do { \
- if (c<='9') cur_chr=c-'0'; \
- else cur_chr=c-'a'+10; \
- add_nybble(cc); \
- } while (0)
+#else
-#define four_hex_to_cur_chr do { \
- hex_to_cur_chr; \
- add_nybble(ccc); add_nybble(cccc); \
- } while (0)
+/* 10 times less Bim in callgrind */
-#define five_hex_to_cur_chr do { \
- four_hex_to_cur_chr; \
- add_nybble(ccccc); \
- } while (0)
+/*
+ escape_cmd left_brace_cmd right_brace_cmd math_shift_cmd
+ tab_mark_cmd car_ret_cmd mac_param_cmd sup_mark_cmd
+ sub_mark_cmd ignore_cmd spacer_cmd letter_cmd
+ other_char_cmd active_char_cmd comment_cmd invalid_char_cmd
+*/
-#define six_hex_to_cur_chr do { \
- five_hex_to_cur_chr; \
- add_nybble(cccccc); \
- } while (0)
+static boolean get_next_file(void)
+{
+ int c = 0;
+ SWITCH:
+ if (iloc <= ilimit) {
+ /* 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);
+ }
+ /*
+ 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 && 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:
+ /* 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 && 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:
+ /* 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 && cur_cmd >= outer_call_cmd)
+ check_outer_validity();
+ return true;
+ case comment_cmd:
+ iloc = ilimit + 1;
+ goto SWITCH;
+ case invalid_char_cmd:
+ invalid_character_error();
+ return false; /* because state may be |token_list| now */
+ default:
+ istate = mid_line;
+ return true;
+ }
+ } else if (c >= skip_blanks) {
+ switch (c-skip_blanks) {
+ case escape_cmd:
+ /* Scan a control sequence ...; */
+ istate = (unsigned char) scan_control_sequence();
+ if (! suppress_outer_error && 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 this |sup_mark| starts */
+ 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 && cur_cmd >= outer_call_cmd)
+ check_outer_validity();
+ return true;
+ case comment_cmd:
+ /* Finish line, |goto switch|; */
+ iloc = ilimit + 1;
+ goto SWITCH;
+ case invalid_char_cmd:
+ /* Decry the invalid character and |goto restart|; */
+ invalid_character_error();
+ return false; /* because state may be |token_list| now */
+ 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 && 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:
+ /*
+ 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:
+ /* 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 && cur_cmd >= outer_call_cmd)
+ check_outer_validity();
+ return true;
+ case comment_cmd:
+ iloc = ilimit + 1;
+ goto SWITCH;
+ case invalid_char_cmd:
+ invalid_character_error();
+ return false; /* because state may be |token_list| now */
+ default:
+ istate = mid_line;
+ return true;
+ }
+ } else {
+ istate = mid_line;
+ return true;
+ }
+ } else {
+ if (iname != 21) {
+ istate = new_line;
+ }
+ /*
+ 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
@ Notice that a code like \.{\^\^8} becomes \.x if not followed by a hex digit.
+We only support a limited set:
+
+^^^^^^XXXXXX
+^^^^XXXXXX
+^^XX ^^<char>
@c
+
+#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]) {
- int c, cc;
if (iloc < ilimit) {
- if ( (cur_chr == buffer[iloc + 1])
- && (cur_chr == buffer[iloc + 2])
- && (cur_chr == buffer[iloc + 3])
- && (cur_chr == buffer[iloc + 4])
- && ((iloc + 10) <= ilimit)) {
- int ccc, cccc, ccccc, cccccc; /* constituents of a possible expanded code */
- c = buffer[iloc + 5];
- cc = buffer[iloc + 6];
- ccc = buffer[iloc + 7];
- cccc = buffer[iloc + 8];
- ccccc = buffer[iloc + 9];
- cccccc = buffer[iloc + 10];
- if ((is_hex(c)) && (is_hex(cc)) && (is_hex(ccc))
- && (is_hex(cccc))
- && (is_hex(ccccc)) && (is_hex(cccccc))) {
- iloc = iloc + 11;
- six_hex_to_cur_chr;
- return true;
- }
- }
- if ( (cur_chr == buffer[iloc + 1])
- && (cur_chr == buffer[iloc + 2])
- && (cur_chr == buffer[iloc + 3])
- && ((iloc + 8) <= ilimit)) {
- int ccc, cccc, ccccc; /* constituents of a possible expanded code */
- c = buffer[iloc + 4];
- cc = buffer[iloc + 5];
- ccc = buffer[iloc + 6];
- cccc = buffer[iloc + 7];
- ccccc = buffer[iloc + 8];
- if ((is_hex(c)) && (is_hex(cc)) && (is_hex(ccc))
- && (is_hex(cccc)) && (is_hex(ccccc))) {
- iloc = iloc + 9;
- five_hex_to_cur_chr;
- return true;
+ if ((cur_chr == buffer[iloc + 1]) && (cur_chr == buffer[iloc + 2])) {
+ if ((cur_chr == buffer[iloc + 3]) && (cur_chr == buffer[iloc + 4])) {
+ /* ^^^^^^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 {
+ /* ^^^^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);
+ }
}
- }
- if ( (cur_chr == buffer[iloc + 1])
- && (cur_chr == buffer[iloc + 2])
- && ((iloc + 6) <= ilimit)) {
- int ccc, cccc; /* constituents of a possible expanded code */
- c = buffer[iloc + 3];
- cc = buffer[iloc + 4];
- ccc = buffer[iloc + 5];
- cccc = buffer[iloc + 6];
- if ((is_hex(c)) && (is_hex(cc)) && (is_hex(ccc))
- && (is_hex(cccc))) {
- iloc = iloc + 7;
- four_hex_to_cur_chr;
- return true;
+ } else {
+ /* ^^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;
+ }
}
+ /* go on, no error, good old tex */
}
- c = buffer[iloc + 1];
- if (c < 0200) { /* yes we have an expanded char */
+ }
+ /* the rest */
+ {
+ int c1 = buffer[iloc + 1];
+ if (c1 < 0200) {
iloc = iloc + 2;
- if (is_hex(c) && iloc <= ilimit) {
- cc = buffer[iloc];
- if (is_hex(cc)) {
+ if (is_hex(c1) && (iloc <= ilimit)) {
+ int c2 = buffer[iloc];
+ if (is_hex(c2)) {
incr(iloc);
- hex_to_cur_chr;
+ two_hex_to_cur_chr(c1,c2);
return true;
}
}
- cur_chr = (c < 0100 ? c + 0100 : c - 0100);
+ cur_chr = (c1 < 0100 ? c1 + 0100 : c1 - 0100);
return true;
}
}
@@ -1078,20 +1473,19 @@ static boolean process_sup_mark(void)
return false;
}
-@ 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.
+@ 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]|.
+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.
+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.
@c
static boolean check_expanded_code(int *kk); /* below */
@@ -1121,6 +1515,8 @@ static int scan_control_sequence(void)
if (cat == sup_mark_cmd && check_expanded_code(&k)) /* If an expanded...; */
continue;
if (cat != letter_cmd) {
+ /* backtrack one character which can be utf */
+ /*
decr(k);
if (cur_chr > 0xFFFF)
decr(k);
@@ -1128,7 +1524,18 @@ static int scan_control_sequence(void)
decr(k);
if (cur_chr > 0x7F)
decr(k);
- } /* now |k| points to first nonletter */
+ */
+ 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;
+ }
+ /* now |k| points to first nonletter */
+ }
}
cur_cs = id_lookup(iloc, k - iloc);
iloc = k;
@@ -1141,60 +1548,67 @@ static int scan_control_sequence(void)
}
@ 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.
+|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.
@c
static boolean check_expanded_code(int *kk)
{
int l;
int k = *kk;
- int d = 1; /* number of excess characters in an expanded code */
- int c, cc, ccc, cccc, ccccc, cccccc; /* constituents of a possible expanded code */
+ int d = 1;
if (buffer[k] == cur_chr && k < ilimit) {
- if ((cur_chr == buffer[k + 1]) && (cur_chr == buffer[k + 2])
- && ((k + 6) <= ilimit)) {
- d = 4;
- if ((cur_chr == buffer[k + 3]) && ((k + 8) <= ilimit))
- d = 5;
- if ((cur_chr == buffer[k + 4]) && ((k + 10) <= ilimit))
- d = 6;
- c = buffer[k + d - 1];
- cc = buffer[k + d];
- ccc = buffer[k + d + 1];
- cccc = buffer[k + d + 2];
- if (d == 6) {
- ccccc = buffer[k + d + 3];
- cccccc = buffer[k + d + 4];
- if (is_hex(c) && is_hex(cc) && is_hex(ccc) && is_hex(cccc)
- && is_hex(ccccc) && is_hex(cccccc))
- six_hex_to_cur_chr;
- } else if (d == 5) {
- ccccc = buffer[k + d + 3];
- if (is_hex(c) && is_hex(cc) && is_hex(ccc) && is_hex(cccc)
- && is_hex(ccccc))
- five_hex_to_cur_chr;
+ 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 (is_hex(c) && is_hex(cc) && is_hex(ccc) && is_hex(cccc))
- four_hex_to_cur_chr;
+ 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 {
- c = buffer[k + 1];
- if (c < 0200) {
+ int c1 = buffer[k + 1];
+ if (c1 < 0200) {
d = 1;
- if (is_hex(c) && (k + 2) <= ilimit) {
- cc = buffer[k + 2];
- if (is_hex(c) && is_hex(cc)) {
+ if (is_hex(c1) && (k + 2) <= ilimit) {
+ int c2 = buffer[k + 2];
+ if (is_hex(c2)) {
d = 2;
- hex_to_cur_chr;
+ two_hex_to_cur_chr(c1,c2);
+ } else {
+ cur_chr = (c1 < 0100 ? c1 + 0100 : c1 - 0100);
}
- } else if (c < 0100) {
- cur_chr = c + 0100;
} else {
- cur_chr = c - 0100;
+ cur_chr = (c1 < 0100 ? c1 + 0100 : c1 - 0100);
}
}
}
@@ -1213,28 +1627,21 @@ static boolean check_expanded_code(int *kk)
buffer[k - 1] = (packed_ASCII_code) (0xE0 + cur_chr / 0x1000);
k++;
d--;
- buffer[k - 1] =
- (packed_ASCII_code) (0x80 + (cur_chr % 0x1000) / 0x40);
+ buffer[k - 1] = (packed_ASCII_code) (0x80 + (cur_chr % 0x1000) / 0x40);
k++;
d--;
- buffer[k - 1] =
- (packed_ASCII_code) (0x80 + (cur_chr % 0x1000) % 0x40);
+ 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);
+ 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);
+ 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);
+ buffer[k - 1] = (packed_ASCII_code) (0x80 + ((cur_chr % 0x40000) % 0x1000) % 0x40);
}
l = k;
ilimit = ilimit - d;
@@ -1248,13 +1655,12 @@ static boolean check_expanded_code(int *kk)
return false;
}
-@ All of the easy branches of |get_next| have now been taken care of.
- There is one more branch.
+@ All of the easy branches of |get_next| have now been taken care of. There is
+one more branch.
-@c
-static next_line_retval next_line(void)
+@c static next_line_retval next_line(void)
{
- boolean inhibit_eol = false; /* a way to end a pseudo file without trailing space */
+ boolean inhibit_eol = false; /* a way to end a pseudo file without trailing space */
if (iname > 17) {
/* Read next line of file into |buffer|, or |goto restart| if the file has ended */
incr(line);
@@ -1268,7 +1674,7 @@ static next_line_retval next_line(void)
inhibit_eol = true;
} else if ((every_eof != null) && !eof_seen[iindex]) {
ilimit = first - 1;
- eof_seen[iindex] = true; /* fake one empty line */
+ eof_seen[iindex] = true; /* fake one empty line */
if (iname != 19)
begin_token_list(every_eof, every_eof_text);
return next_line_restart;
@@ -1277,7 +1683,7 @@ static next_line_retval next_line(void)
}
} else {
if (iname == 21) {
- if (luacstring_input()) { /* not end of strings */
+ if (luacstring_input()) { /* not end of strings */
firm_up_the_line();
line_catcode_table = (short) luacstring_cattable();
line_partial = (signed char) luacstring_partial();
@@ -1290,12 +1696,12 @@ static next_line_retval next_line(void)
force_eof = true;
}
} else {
- if (lua_input_ln(cur_file, 0, true)) { /* not end of file */
- firm_up_the_line(); /* this sets |ilimit| */
+ if (lua_input_ln(cur_file, 0, true)) { /* not end of file */
+ firm_up_the_line(); /* this sets |ilimit| */
line_catcode_table = DEFAULT_CAT_TABLE;
} else if ((every_eof != null) && (!eof_seen[iindex])) {
ilimit = first - 1;
- eof_seen[iindex] = true; /* fake one empty line */
+ eof_seen[iindex] = true; /* fake one empty line */
begin_token_list(every_eof, every_eof_text);
return next_line_restart;
} else {
@@ -1306,24 +1712,23 @@ static next_line_retval next_line(void)
}
if (force_eof) {
if (tracing_nesting > 0)
- if ((grp_stack[in_open] != cur_boundary)
- || (if_stack[in_open] != cond_ptr))
- if (!((iname == 19) || (iname == 21)))
- file_warning(); /* give warning for some unfinished groups and/or conditionals */
+ if ((grp_stack[in_open] != cur_boundary) || (if_stack[in_open] != cond_ptr))
+ if (!((iname == 19) || (iname == 21))) {
+ /* give warning for some unfinished groups and/or conditionals */
+ file_warning();
+ }
if ((iname > 21) || (iname == 20)) {
report_stop_file(filetype_tex);
decr(open_parens);
-#if 0
- update_terminal(); /* show user that file has been read */
-#endif
}
force_eof = false;
- if (iname == 21 || /* lua input */
- iname == 19) { /* \.{\\scantextokens} */
+ /* lua input or \.{\\scantextokens} */
+ if (iname == 21 || iname == 19) {
end_file_reading();
} else {
end_file_reading();
- check_outer_validity();
+ if (! suppress_outer_error)
+ check_outer_validity();
}
return next_line_restart;
}
@@ -1332,28 +1737,31 @@ static next_line_retval next_line(void)
else
buffer[ilimit] = (packed_ASCII_code) end_line_char;
first = ilimit + 1;
- iloc = istart; /* ready to read */
+ iloc = istart; /* ready to read */
} else {
- if (!terminal_input) { /* \.{\\read} line has ended */
+ if (!terminal_input) {
+ /* \.{\\read} line has ended */
cur_cmd = 0;
cur_chr = 0;
return next_line_return; /* OUTER */
}
- if (input_ptr > 0) { /* text was inserted during error recovery */
+ if (input_ptr > 0) {
+ /* text was inserted during error recovery */
end_file_reading();
- return next_line_restart; /* resume previous level */
+ return next_line_restart; /* resume previous level */
}
if (selector < log_only)
open_log_file();
if (interaction > nonstop_mode) {
if (end_line_char_inactive)
ilimit++;
- if (ilimit == istart) { /* previous line was empty */
+ if (ilimit == istart) {
+ /* previous line was empty */
tprint_nl("(Please type a command or say `\\end')");
}
print_ln();
first = istart;
- prompt_input("*"); /* input on-line into |buffer| */
+ prompt_input("*"); /* input on-line into |buffer| */
ilimit = last;
if (end_line_char_inactive)
ilimit--;
@@ -1362,9 +1770,11 @@ static next_line_retval next_line(void)
first = ilimit + 1;
iloc = istart;
} else {
+ /*
+ Nonstop mode, which is intended for overnight batch processing,
+ never waits for on-line input.
+ */
fatal_error("*** (job aborted, no legal \\end found)");
- /* nonstop mode, which is intended for overnight batch processing,
- never waits for on-line input */
}
}
return next_line_ok;
@@ -1375,18 +1785,20 @@ static next_line_retval next_line(void)
@c
static boolean get_next_tokenlist(void)
{
- register halfword t; /* a token */
- t = token_info(iloc);
- iloc = token_link(iloc); /* move to next */
- if (t >= cs_token_flag) { /* a control sequence token */
+ register halfword t = token_info(iloc);
+ iloc = token_link(iloc); /* move to next */
+ if (t >= cs_token_flag) {
+ /* 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) { /* 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|.
- */
+ if (cur_cmd == dont_expand_cmd) {
+ /*
+ 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);
@@ -1395,7 +1807,7 @@ static boolean get_next_tokenlist(void)
cur_chr = no_expand_flag;
return true;
}
- } else {
+ } else if (! suppress_outer_error) {
check_outer_validity();
}
}
@@ -1404,24 +1816,25 @@ static boolean get_next_tokenlist(void)
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: /* Insert macro parameter and |goto restart|; */
- begin_token_list(param_stack[param_start + cur_chr - 1], parameter);
- return false;
- break;
+ case left_brace_cmd:
+ align_state++;
+ break;
+ case right_brace_cmd:
+ align_state--;
+ break;
+ case out_param_cmd:
+ /* Insert macro parameter and |goto restart|; */
+ begin_token_list(param_stack[param_start + cur_chr - 1], parameter);
+ return false;
+ break;
}
}
return true;
}
-@ 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.
- @^mastication@>@^inner loop@>
+@ 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.
+@^mastication@>@^inner loop@>
@ sets |cur_cmd|, |cur_chr|, |cur_cs| to next token
@@ -1449,34 +1862,35 @@ void get_next(void)
}
}
-@ Since |get_next| is used so frequently in \TeX, it is convenient
-to define three related procedures that do a little more:
+@ Since |get_next| is used so frequently in \TeX, it is convenient to define
+three related procedures that do a little more:
+
+\yskip\hang|get_token| not only sets |cur_cmd| and |cur_chr|, it also sets
+|cur_tok|, a packed halfword version of the current token.
-\yskip\hang|get_token| not only sets |cur_cmd| and |cur_chr|, it
-also sets |cur_tok|, a packed halfword version of the current token.
+\yskip\hang|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.
-\yskip\hang|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.
+\yskip\hang|x_token| is like |get_x_token| except that it assumes that |get_next|
+has already been called.
-\yskip\hang|x_token| is like |get_x_token| except that it assumes that
-|get_next| has already been called.
+\yskip\noindent In fact, these three procedures account for almost every use of
+|get_next|.
-\yskip\noindent
-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.
-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.
+@ sets |cur_cmd|, |cur_chr|, |cur_tok|
@c
void get_token(void)
-{ /* sets |cur_cmd|, |cur_chr|, |cur_tok| */
+{
no_new_control_sequence = false;
- get_next(); /* get_token_lua(); */
+ get_next();
no_new_control_sequence = true;
if (cur_cs == 0)
cur_tok = token_val(cur_cmd, cur_chr);
@@ -1484,32 +1898,14 @@ void get_token(void)
cur_tok = cs_token_flag + cur_cs;
}
-@ @c
-void get_token_lua(void)
-{
- register int callback_id;
- callback_id = callback_defined(token_filter_callback);
- if (callback_id > 0) {
- while (istate == token_list && iloc == null && iindex != v_template)
- end_token_list();
- /* there is some stuff we don't want to see inside the callback */
- if (!(istate == token_list &&
- ((nofilter == true) || (iindex == backed_up && iloc != null)))) {
- do_get_token_lua(callback_id);
- return;
- }
- }
- get_next();
-}
-
-
@ changes the string |s| to a token list
+
@c
halfword string_to_toks(const char *ss)
{
- halfword p; /* tail of the token list */
- halfword q; /* new node being added to the token list via |store_new_token| */
- halfword t; /* token being appended */
+ halfword p; /* tail of the token list */
+ halfword q; /* new node being added to the token list via |store_new_token| */
+ halfword t; /* token being appended */
const char *s = ss;
const char *se = ss + strlen(s);
p = temp_token_head;
@@ -1526,27 +1922,29 @@ halfword string_to_toks(const char *ss)
return token_link(temp_token_head);
}
-@ The token lists for macros and for other things like \.{\\mark} and \.{\\output}
-and \.{\\write} are produced by a procedure called |scan_toks|.
+@ 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|.
+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
+|lua_str_toks| is almost identical, but it also escapes the three symbols that
+|lua| considers special while scanning a literal string
+
+@ changes the string |str_pool[b..pool_ptr]| to a token list
@c
halfword lua_str_toks(lstring b)
-{ /* changes the string |str_pool[b..pool_ptr]| to a token list */
- halfword p; /* tail of the token list */
- halfword q; /* new node being added to the token list via |store_new_token| */
- halfword t; /* token being appended */
- unsigned char *k; /* index into string */
+{
+ halfword p; /* tail of the token list */
+ halfword q; /* new node being added to the token list via |store_new_token| */
+ halfword t; /* token being appended */
+ unsigned char *k; /* index into string */
p = temp_token_head;
set_token_link(p, null);
k = (unsigned char *) b.s;
@@ -1569,16 +1967,18 @@ halfword lua_str_toks(lstring b)
return p;
}
-@ Incidentally, the main reason for wanting |str_toks| is the function |the_toks|,
-which has similar input/output characteristics.
+@ Incidentally, the main reason for wanting |str_toks| is the function
+|the_toks|, which has similar input/output characteristics.
+
+@ changes the string |str_pool[b..pool_ptr]| to a token list
@c
halfword str_toks(lstring s)
-{ /* changes the string |str_pool[b..pool_ptr]| to a token list */
- halfword p; /* tail of the token list */
- halfword q; /* new node being added to the token list via |store_new_token| */
- halfword t; /* token being appended */
- unsigned char *k, *l; /* index into string */
+{
+ halfword p; /* tail of the token list */
+ halfword q; /* new node being added to the token list via |store_new_token| */
+ halfword t; /* token being appended */
+ unsigned char *k, *l; /* index into string */
p = temp_token_head;
set_token_link(p, null);
k = s.s;
@@ -1602,11 +2002,11 @@ halfword str_toks(lstring s)
*/
halfword str_scan_toks(int ct, lstring s)
-{ /* changes the string |str_pool[b..pool_ptr]| to a token list */
- halfword p; /* tail of the token list */
- halfword q; /* new node being added to the token list via |store_new_token| */
- halfword t; /* token being appended */
- unsigned char *k, *l; /* index into string */
+{ /* changes the string |str_pool[b..pool_ptr]| to a token list */
+ halfword p; /* tail of the token list */
+ halfword q; /* new node being added to the token list via |store_new_token| */
+ halfword t; /* token being appended */
+ unsigned char *k, *l; /* index into string */
int cc;
p = temp_token_head;
set_token_link(p, null);
@@ -1667,6 +2067,7 @@ halfword str_scan_toks(int ct, lstring s)
}
@ Here's part of the |expand| subroutine that we are now ready to complete:
+
@c
void ins_the_toks(void)
{
@@ -1674,8 +2075,133 @@ void ins_the_toks(void)
ins_list(token_link(temp_token_head));
}
-@ This routine, used in the next one, prints the job name, possibly
-modified by the |process_jobname| callback.
+#define set_toks_register(n,t,g) { \
+ 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); \
+}
+
+void combine_the_toks(int how)
+{
+ halfword nt;
+ get_x_token();
+ /* target */
+ if (cur_cmd == assign_toks_cmd) {
+ nt = equiv(cur_cs) - toks_base;
+ /* check range */
+ } else {
+ back_input();
+ scan_int();
+ nt = cur_val;
+ }
+ /* source */
+ do {
+ get_x_token();
+ } while (cur_cmd == spacer_cmd);
+ if (cur_cmd == left_brace_cmd) {
+ halfword x, source;
+ back_input();
+ x = scan_toks(false,how > 1); /* expanded or not */
+ source = def_ref;
+ /* action */
+ if (source != null) {
+ halfword target = toks(nt);
+ if (target == null) {
+ set_toks_register(nt,source,0);
+ } else {
+ halfword s = token_link(source);
+ if (s != null) {
+ halfword t = token_link(target);
+ if (t == null) {
+ /* can this happen ? */
+ set_token_link(target, s);
+ } else if (odd(how)) {
+ /* prepend */
+ if (cur_level != eq_level_field(eqtb[toks_base+nt])) {
+ halfword p = temp_token_head;
+ halfword q;
+ set_token_link(p, s); /* s = head, x = tail */
+ p = x;
+ while (t != null) {
+ fast_store_new_token(token_info(t));
+ t = token_link(t);
+ }
+ set_toks_register(nt,temp_token_head,0);
+ } else {
+ set_token_link(x,t);
+ set_token_link(target,s);
+ }
+ } else {
+ /* append */
+ if (cur_level != eq_level_field(eqtb[toks_base+nt])) {
+ halfword p = temp_token_head;
+ halfword q;
+ set_token_link(p, null);
+ while (t != null) {
+ fast_store_new_token(token_info(t));
+ t = token_link(t);
+ }
+ set_token_link(p,s);
+ set_toks_register(nt,temp_token_head,0);
+ } else {
+ while (token_link(t) != null) {
+ t = token_link(t);
+ }
+ set_token_link(t,s);
+ }
+ }
+ }
+ }
+ }
+ } else {
+ halfword source, ns;
+ if (cur_cmd == assign_toks_cmd) {
+ ns = equiv(cur_cs) - toks_base;
+ /* check range */
+ } else {
+ back_input();
+ scan_int();
+ ns = cur_val;
+ }
+ /* action */
+ source = toks(ns);
+ if (source != null) {
+ halfword target = toks(nt);
+ if (target == null) {
+ equiv(toks_base+nt) = source;
+ equiv(toks_base+ns) = null;
+ } else {
+ halfword s = token_link(source);
+ if (s != null) {
+ halfword t = token_link(target);
+ if (t == null) {
+ set_token_link(target, s);
+ } else if (odd(how)) {
+ /* prepend */
+ halfword x = s;
+ while (token_link(x) != null) {
+ x = token_link(x);
+ }
+ set_token_link(x,t);
+ set_token_link(target,s);
+ } else {
+ /* append */
+ while (token_link(t) != null) {
+ t = token_link(t);
+ }
+ set_token_link(t,s);
+ }
+ equiv(toks_base+ns) = null;
+ }
+ }
+ }
+ }
+}
+
+@ This routine, used in the next one, prints the job name, possibly modified by
+the |process_jobname| callback.
@c
static void print_job_name(void)
@@ -1696,21 +2222,23 @@ static void print_job_name(void)
}
}
-@ 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.
+@ 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.
-@ @c
-int scan_lua_state(void) /* hh-ls: optional name or number (not optional name optional number) */
+@ 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.
+
+@c
+
+int scan_lua_state(void)
{
- /* Parse optional lua state integer, or an instance name to be stored in |sn| */
- /* Get the next non-blank non-relax non-call token */
int sn = 0;
do {
get_x_token();
} while ((cur_cmd == spacer_cmd) || (cur_cmd == relax_cmd));
- back_input(); /* have to push it back, whatever it is */
+ back_input();
if (cur_cmd != left_brace_cmd) {
if (scan_keyword("name")) {
(void) scan_toks(false, true);
@@ -1724,13 +2252,13 @@ int scan_lua_state(void) /* hh-ls: optional name or number (not optional name op
return sn;
}
-@ 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 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.
+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.
@c
#define push_selector { \
@@ -1783,7 +2311,6 @@ static int do_variable_pdf(halfword c)
else if (scan_keyword("objcompresslevel")) { do_variable_backend_int(c_pdf_objcompresslevel); }
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("replacefont")) { do_variable_backend_int(c_pdf_replace_font); }
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); }
@@ -1900,7 +2427,7 @@ static int do_feedback_pdf(halfword c)
save_warning_index = warning_index;
save_def_ref = def_ref;
u = save_cur_string();
- scan_toks(false, true); /*hh-ls was scan_pdf_ext_toks();*/
+ scan_toks(false, true);
s = tokens_to_string(def_ref);
delete_token_ref(def_ref);
def_ref = save_def_ref;
@@ -1951,313 +2478,306 @@ void conv_toks(void)
int i = 0;
/* Scan the argument for command |c| */
switch (c) {
- case uchar_code:
- scan_char_num();
- push_selector;
- print(cur_val);
- pop_selector;
- break;
- case number_code:
- scan_int();
- push_selector;
- print_int(cur_val);
- pop_selector;
- break;
- case roman_numeral_code:
- scan_int();
- push_selector;
- print_roman_int(cur_val);
- 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 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 etex_code:
- push_selector;
- tprint(eTeX_version_string);
- 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 font_id_code:
- scan_font_ident();
- push_selector;
- print_int(cur_val);
- pop_selector;
- break;
- case luatex_revision_code:
- push_selector;
- print(get_luatexrevision());
- pop_selector;
- break;
- case luatex_date_code:
- push_selector;
- print_int(get_luatex_date_info());
- pop_selector;
- break;
- case luatex_banner_code:
- push_selector;
- tprint(luatex_banner);
- 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);
- /*
- 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 {
- /*
- 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
- */
- }
- }
+ 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();
}
- }
- 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 format_name_code:
- if (job_name == 0)
- open_log_file();
- push_selector;
- print(format_name);
- pop_selector;
- break;
- case job_name_code:
- if (job_name == 0)
- open_log_file();
- push_selector;
- print_job_name();
- pop_selector;
- break;
- case uniform_deviate_code:
- scan_int();
- push_selector;
- print_int(unif_rand(cur_val));
- pop_selector;
- break;
- case normal_deviate_code:
- scan_int();
- push_selector;
- print_int(norm_rand());
- pop_selector;
- break;
- case lua_escape_string_code:
- {
- lstring escstr;
- int l = 0;
+ /* no further action */
+ return;
+ break;
+ case lua_code:
+ u = save_cur_string();
save_scanner_status = scanner_status;
save_def_ref = def_ref;
save_warning_index = warning_index;
- scan_toks(false, true); /*hh-ls was scan_pdf_ext_toks();*/
- 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);
+ 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); /* TODO: check this, was different */
+ if (luacstrings > 0)
+ lua_string_start();
+ /* 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;
- (void) lua_str_toks(escstr);
- ins_list(token_link(temp_token_head));
- free(escstr.s);
+ ins_list(token_link(def_ref));
+ def_ref = save_def_ref;
+ restore_cur_string(u);
+ /* no further action */
return;
- }
- /* no further action */
- break;
- case math_style_code:
- push_selector;
- print_math_style();
- pop_selector;
- break;
- case math_char_class_code:
- {
- mathcodeval mval;
+ 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();
- mval = get_math_code(cur_val);
push_selector;
- print_int(mval.class_value);
+ print_roman_int(cur_val);
pop_selector;
- }
- break;
- case math_char_fam_code:
- {
- mathcodeval mval;
+ 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;
+ }
+ /* 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();
- mval = get_math_code(cur_val);
+ if ((box(cur_val) == null) || (type(box(cur_val)) != hlist_node))
+ normal_error("marginkern", "a non-empty hbox expected");
push_selector;
- print_int(mval.family_value);
+ 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 math_char_slot_code:
- {
- mathcodeval mval;
+ break;
+ case right_margin_kern_code:
scan_int();
- mval = get_math_code(cur_val);
+ if ((box(cur_val) == null) || (type(box(cur_val)) != hlist_node))
+ normal_error("marginkern", "a non-empty hbox expected");
push_selector;
- print_int(mval.character_value);
+ p = list_ptr(box(cur_val));
+ if (p != null) {
+ p = tail_of_list(p);
+ /*
+ 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 {
+ /*
+ 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 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); /*hh-ls was scan_pdf_ext_toks();*/
- warning_index = save_warning_index;
- scanner_status = save_scanner_status;
- ins_list(token_link(def_ref));
- def_ref = save_def_ref;
- restore_cur_string(u);
- /* no further action */
- 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); /*hh-ls was scan_pdf_ext_toks();*/
- 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); /* TODO: check this, was different */
- if (luacstrings > 0)
- lua_string_start();
- /* no further action */
- return;
- 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();
- }
- /* no further action */
- return;
- break;
- case eTeX_revision_code:
- push_selector;
- tprint(eTeX_revision);
- 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 dvi_feedback_code:
- if (get_o_mode() == OMODE_DVI)
- done = do_feedback_dvi(c);
- else
- done = 0;
- if (done==0)
- tex_error("unexpected use of \\dvifeedback",null);
- else if (done==2)
- return;
- break;
- case pdf_feedback_code:
- if (get_o_mode() == OMODE_PDF)
- done = conv_toks_pdf(c);
- else
- done = 0;
- if (done==0)
- tex_error("unexpected use of \\pdffeedback",null);
- else if (done==2)
- return;
- break;
- */
- default:
- confusion("convert");
- break;
+ break;
+ case uniform_deviate_code:
+ scan_int();
+ push_selector;
+ print_int(unif_rand(cur_val));
+ pop_selector;
+ break;
+ case normal_deviate_code:
+ scan_int();
+ 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 luatex_date_code:
+ push_selector;
+ print_int(get_luatex_date_info());
+ 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));
@@ -2380,49 +2900,62 @@ str_number the_convert_string(halfword c, int i)
case number_code:
print_int(i);
break;
- case uchar_code:
- print(i);
+ /* 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 etex_code:
- tprint(eTeX_version_string);
- break;
- case luatex_revision_code:
- print(get_luatexrevision());
+ /* case meaning_code: */
+ case uchar_code:
+ print(i);
break;
- case luatex_date_code:
- print_int(get_luatex_date_info());
+ /* lua_escape_string_code: */
+ case font_id_code:
+ print_int(i);
break;
- case luatex_banner_code:
- tprint(luatex_banner);
+ 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 job_name_code:
- print_job_name();
+ case luatex_banner_code:
+ tprint(luatex_banner);
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");
- }
+ case luatex_revision_code:
+ print(get_luatexrevision());
break;
- case font_id_code:
- print_int(i);
+ case luatex_date_code:
+ print_int(get_luatex_date_info());
break;
- case math_style_code:
- print_math_style();
+ case etex_code:
+ tprint(eTeX_version_string);
break;
case eTeX_revision_code:
tprint(eTeX_revision);
@@ -2449,16 +2982,16 @@ str_number the_convert_string(halfword c, int i)
return ret;
}
-@ 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.
+@ 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.
@c
-FILE *read_file[16]; /* used for \.{\\read} */
-int read_open[17]; /* state of |read_file[n]| */
+FILE *read_file[16]; /* used for \.{\\read} */
+int read_open[17]; /* state of |read_file[n]| */
void initialize_read(void)
{
@@ -2467,17 +3000,17 @@ void initialize_read(void)
read_open[k] = closed;
}
-@ 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.
+@ 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.
@c
void read_toks(int n, halfword r, halfword j)
{
- halfword p; /* tail of the token list */
- halfword q; /* new node being added to the token list via |store_new_token| */
- int s; /* saved value of |align_state| */
- int m; /* stream number */
+ halfword p; /* tail of the token list */
+ halfword q; /* new node being added to the token list via |store_new_token| */
+ int s; /* saved value of |align_state| */
+ int m; /* stream number */
scanner_status = defining;
warning_index = r;
p = get_avail();
@@ -2496,10 +3029,13 @@ void read_toks(int n, halfword r, halfword j)
begin_file_reading();
iname = m + 1;
if (read_open[m] == closed) {
- /* Input for \.{\\read} from the terminal */
- /* Here 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. */
+ /*
+ Input for \.{\\read} from the terminal
+
+ Here 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("");
@@ -2516,9 +3052,12 @@ void read_toks(int n, halfword r, halfword j)
}
} else if (read_open[m] == just_open) {
- /* 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|. */
+ /*
+ 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 {
@@ -2527,8 +3066,11 @@ void read_toks(int n, halfword r, halfword j)
}
} else {
- /* Input the next line of |read_file[m]| */
- /* An empty line is appended at the end of a |read_file|. */
+ /*
+ 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;
@@ -2552,8 +3094,9 @@ void read_toks(int n, halfword r, halfword j)
istate = new_line;
/* Handle \.{\\readline} and |goto done|; */
if (j == 1) {
- while (iloc <= ilimit) { /* current line not yet finished */
- do_buffer_to_unichar(cur_chr, iloc);
+ while (iloc <= ilimit) {
+ /* current line not yet finished */
+ do_buffer_to_unichar(cur_chr, iloc);
if (cur_chr == ' ')
cur_tok = space_token;
else
@@ -2563,9 +3106,12 @@ void read_toks(int n, halfword r, halfword j)
} else {
while (1) {
get_token();
- if (cur_tok == 0)
- break; /* |cur_cmd=cur_chr=0| will occur at the end of the line */
- if (align_state < 1000000) { /* unmatched `\.\}' aborts the line */
+ if (cur_tok == 0) {
+ /* |cur_cmd=cur_chr=0| will occur at the end of the line */
+ break;
+ }
+ if (align_state < 1000000) {
+ /* unmatched `\.\}' aborts the line */
do {
get_token();
} while (cur_tok != 0);
@@ -2583,9 +3129,11 @@ void read_toks(int n, halfword r, halfword j)
align_state = s;
}
-@ @c
+@ return a string from tokens list
+
+@c
str_number tokens_to_string(halfword p)
-{ /* return a string from tokens list */
+{
int old_setting;
if (selector == new_string)
normal_error("tokens","tokens_to_string() called while selector = new_string");
@@ -2627,7 +3175,6 @@ str_number tokens_to_string(halfword p)
append_i_byte(0x80 + (((s % 0x40000) % 0x1000) % 0x40)); \
} }
-
#define Print_esc(b) { \
const char *v = b; \
if (e>0 && e<STRING_OFFSET) { \
@@ -2646,10 +3193,9 @@ str_number tokens_to_string(halfword p)
#define is_cat_letter(a) \
(get_char_cat_code(pool_to_unichar(str_string((a)))) == 11)
-@ 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.
+@ 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.
@c
char *tokenlist_to_cstring(int pp, int inhibit_par, int *siz)
@@ -2691,9 +3237,7 @@ char *tokenlist_to_cstring(int pp, int inhibit_par, int *siz)
} else {
Print_esc("IMPOSSIBLE.");
}
- } else if ((q >= undefined_control_sequence)
- && ((q <= eqtb_size)
- || (q > eqtb_size + hash_extra))) {
+ } 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.");
@@ -2727,48 +3271,48 @@ char *tokenlist_to_cstring(int pp, int inhibit_par, int *siz)
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))
+ 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);
- 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;
+ 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;
}
}
}