diff options
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/tex/maincontrol.w')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/tex/maincontrol.w | 1460 |
1 files changed, 735 insertions, 725 deletions
diff --git a/Build/source/texk/web2c/luatexdir/tex/maincontrol.w b/Build/source/texk/web2c/luatexdir/tex/maincontrol.w index 38b508f31d3..6b17a5bdb8d 100644 --- a/Build/source/texk/web2c/luatexdir/tex/maincontrol.w +++ b/Build/source/texk/web2c/luatexdir/tex/maincontrol.w @@ -19,8 +19,8 @@ @ @c static const char _svn_version[] = - "$Id: maincontrol.w 3659 2010-04-28 15:10:32Z taco $" - "$URL: http://foundry.supelec.fr/svn/luatex/branches/0.60.x/source/texk/web2c/luatexdir/tex/maincontrol.w $"; + "$Id: maincontrol.w 4023 2010-12-05 15:10:06Z taco $" + "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.66.0/source/texk/web2c/luatexdir/tex/maincontrol.w $"; #include "ptexlib.h" @@ -178,716 +178,737 @@ is very welcome, which is why I need to have the next two globals: internal_font_number space_spec_font; halfword space_spec_cache; -@ for mode-independent commands, the following macros is useful: +@ To handle the execution state of |main_control|'s eternal loop, +an extra global variable is used, along with a macro to define +its values. @c -#define any_mode(A) vmode+(A): case hmode+(A): case mmode+(A) +#define goto_next 0 +#define goto_skip_token 1 +#define goto_return 2 +static int main_control_state; -@ There is a list of cases where the user has probably gotten into or out of math -mode by mistake. \TeX\ will insert a dollar sign and rescan the current token. +@* Main control helpers. + +Here are all the functions that are called from |main_control| that +are not already defined elsewhere. For the moment, this list simply +in the order that the appear in |init_main_control|, below. + +@ @c -#define non_math(A) vmode+(A): case hmode+(A) +static void run_char_num (void) { + scan_char_num(); + cur_chr = cur_val; + adjust_space_factor(); + tail_append(new_char(cur_font, cur_chr)); +} + +static void run_char (void) { + adjust_space_factor(); + tail_append(new_char(cur_font, cur_chr)); +} -@ @c -void main_control(void) -{ /* governs \TeX's activities */ - int t; /* general-purpose temporary variable */ - halfword p; /* for whatsit nodes and testing whether an auto kern should be inserted */ - int chr_stack; /* to temporarily save an |cur_chr| to be appended */ - mathcodeval mval; /* to build up an argument to |set_math_char| */ - t = 0; /* for -Wall */ - chr_stack = -1; - if (equiv(every_job_loc) != null) - begin_token_list(equiv(every_job_loc), every_job_text); +@ +The occurrence of blank spaces is almost part of \TeX's inner loop, +since we usually encounter about one space for every five non-blank characters. +Therefore |main_control| gives second-highest priority to ordinary spaces. - BIG_SWITCH: - get_x_token(); +When a glue parameter like \.{\\spaceskip} is set to `\.{0pt}', we will +see to it later that the corresponding glue specification is precisely +|zero_glue|, not merely a pointer to some specification that happens +to be full of zeroes. Therefore it is simple to test whether a glue parameter +is zero or~not. - RESWITCH: - /* Give diagnostic information, if requested */ - /* When a new token has just been fetched at |big_switch|, we have an - ideal place to monitor \TeX's activity. */ - if (interrupt != 0) { - if (OK_to_interrupt) { - back_input(); - check_interrupt(); - goto BIG_SWITCH; - } - } - if (int_par(tracing_commands_code) > 0) - show_cur_cmd_chr(); - switch (abs(mode) + cur_cmd) { - case hmode + letter_cmd: - case hmode + other_char_cmd: - case hmode + char_given_cmd: - case hmode + char_num_cmd: - if (abs(mode) + cur_cmd == hmode + char_num_cmd) { - scan_char_num(); - cur_chr = cur_val; - } - if (is_last_ocp(current_ocp_lstack, current_ocp_no)) { - /* Append character |cur_chr| and the following characters (if~any) - to the current hlist in the current font; |goto reswitch| when - a non-character has been fetched */ - CONTINUE: - adjust_space_factor(); - chr_stack = cur_chr; - tail_append(new_char(cur_font, chr_stack)); - get_x_token(); - if ((cur_cmd == letter_cmd) || (cur_cmd == other_char_cmd) || - (cur_cmd == char_given_cmd) || (cur_cmd == char_num_cmd)) { - if (cur_cmd == char_num_cmd) { - scan_char_num(); - cur_chr = cur_val; - } - if ((chr_stack == ex_hyphen_char) && (cur_chr != ex_hyphen_char) - && (mode > 0)) { - tail = compound_word_break(tail, cur_lang); - subtype(tail) = automatic_disc; - } - goto CONTINUE; - } else { - if ((chr_stack == ex_hyphen_char) && (mode > 0)) { - tail = compound_word_break(tail, cur_lang); - subtype(tail) = automatic_disc; - } - chr_stack = -1; - goto RESWITCH; +@c +static void run_app_space (void) { + if ((abs(mode) + cur_cmd == hmode + spacer_cmd) + && (!(space_factor == 1000))) { + app_space(); + } else { + /* Append a normal inter-word space to the current list */ + if (space_skip == zero_glue) { + /* Find the glue specification, |main_p|, for + text spaces in the current font */ + if (cur_font != space_spec_font) { + if (space_spec_cache != zero_glue) + delete_glue_ref(space_spec_cache); + space_spec_cache = new_spec(zero_glue); + width(space_spec_cache) = space(cur_font); + stretch(space_spec_cache) = space_stretch(cur_font); + shrink(space_spec_cache) = space_shrink(cur_font); + space_spec_font = cur_font; } + main_p = space_spec_cache; + temp_ptr = new_glue(main_p); } else { - /* Create a buffer with character |cur_chr| and the following - characters (if~any) and then apply the current active OCP filter - to this buffer */ - run_ocp(); - goto BIG_SWITCH; - + temp_ptr = new_param_glue(space_skip_code); } - break; - case hmode + spacer_cmd: - case hmode + ex_space_cmd: - case mmode + ex_space_cmd: - if ((abs(mode) + cur_cmd == hmode + spacer_cmd) - && (!(space_factor == 1000))) { - app_space(); - } else { - /* Append a normal inter-word space to the current list */ - /* The occurrence of blank spaces is almost part of \TeX's inner loop, - since we usually encounter about one space for every five non-blank characters. - Therefore |main_control| gives second-highest priority to ordinary spaces. - - When a glue parameter like \.{\\spaceskip} is set to `\.{0pt}', we will - see to it later that the corresponding glue specification is precisely - |zero_glue|, not merely a pointer to some specification that happens - to be full of zeroes. Therefore it is simple to test whether a glue parameter - is zero or~not. - */ - if (space_skip == zero_glue) { - /* Find the glue specification, |main_p|, for - text spaces in the current font */ - if (cur_font != space_spec_font) { - if (space_spec_cache != zero_glue) - delete_glue_ref(space_spec_cache); - space_spec_cache = new_spec(zero_glue); - width(space_spec_cache) = space(cur_font); - stretch(space_spec_cache) = space_stretch(cur_font); - shrink(space_spec_cache) = space_shrink(cur_font); - space_spec_font = cur_font; - } - main_p = space_spec_cache; + couple_nodes(tail,temp_ptr); + tail = temp_ptr; - temp_ptr = new_glue(main_p); - } else { - temp_ptr = new_param_glue(space_skip_code); - } - vlink(tail) = temp_ptr; - tail = temp_ptr; - - } - break; + } +} - case hmode + no_boundary_cmd: - /* Append a |cancel_boundary_node| */ - new_whatsit(cancel_boundary_node); - break; - case hmode + char_ghost_cmd: - t = cur_chr; - get_x_token(); - if ((cur_cmd == letter_cmd) || (cur_cmd == other_char_cmd) - || (cur_cmd == char_given_cmd) || (cur_cmd == char_num_cmd)) { - p = new_glyph(get_cur_font(), cur_chr); - if (t == 0) { - set_is_leftghost(p); - } else { - set_is_rightghost(p); - } - tail_append(p); - } - break; - /* Cases of |main_control| that are not part of the inner loop */ - case any_mode(relax_cmd): - case vmode + spacer_cmd: - case mmode + spacer_cmd: - case mmode + no_boundary_cmd: - break; - case any_mode(ignore_spaces_cmd): - if (cur_chr == 0) { - /* Get the next non-blank non-call... */ - do { - get_x_token(); - } while (cur_cmd == spacer_cmd); +@ Append a |cancel_boundary_node| +@c +static void run_no_boundary (void) { + new_whatsit(cancel_boundary_node); +} - goto RESWITCH; +@ @c +static void run_char_ghost (void) { + int t; + t = cur_chr; + get_x_token(); + if ((cur_cmd == letter_cmd) || (cur_cmd == other_char_cmd) + || (cur_cmd == char_given_cmd) || (cur_cmd == char_num_cmd)) { + halfword p = new_glyph(get_cur_font(), cur_chr); + if (t == 0) { + set_is_leftghost(p); } else { - t = scanner_status; - scanner_status = normal; - get_token_lua(); - scanner_status = t; - cur_cs = prim_lookup(cs_text(cur_cs)); - if (cur_cs != undefined_primitive) { - cur_cmd = get_prim_eq_type(cur_cs); - cur_chr = get_prim_equiv(cur_cs); - cur_tok = (cur_cmd * STRING_OFFSET) + cur_chr; - goto RESWITCH; - } + set_is_rightghost(p); } - break; - case vmode + stop_cmd: - if (its_all_over()) - return; /* this is the only way out */ - break; - /* Math cases in non-math modes */ - case vmode + math_char_num_cmd: - case vmode + math_given_cmd: - case vmode + omath_given_cmd: - case vmode + xmath_given_cmd: - back_input(); - new_graf(true); - break; - case hmode + math_char_num_cmd: - if (cur_chr == 0) - mval = scan_mathchar(tex_mathcode); - else if (cur_chr == 1) - mval = scan_mathchar(aleph_mathcode); - else if (cur_chr == 2) - mval = scan_mathchar(xetex_mathcode); - else - mval = scan_mathchar(xetexnum_mathcode); - math_char_in_text(mval); - break; - case hmode + math_given_cmd: - mval = mathchar_from_integer(cur_chr, tex_mathcode); - math_char_in_text(mval); - break; - case hmode + omath_given_cmd: - mval = mathchar_from_integer(cur_chr, aleph_mathcode); - math_char_in_text(mval); - break; - case hmode + xmath_given_cmd: - mval = mathchar_from_integer(cur_chr, xetex_mathcode); - math_char_in_text(mval); - break; - - /* Forbidden cases detected in |main_control| */ - case vmode + vmove_cmd: - case hmode + hmove_cmd: - case mmode + hmove_cmd: - case any_mode(last_item_cmd): - case vmode + vadjust_cmd: - case vmode + ital_corr_cmd: - case non_math(eq_no_cmd): - case any_mode(mac_param_cmd): - /* When erroneous situations arise, \TeX\ usually issues an error message - specific to the particular error. For example, `\.{\\noalign}' should - not appear in any mode, since it is recognized by the |align_peek| routine - in all of its legitimate appearances; a special error message is given - when `\.{\\noalign}' occurs elsewhere. But sometimes the most appropriate - error message is simply that the user is not allowed to do what he or she - has attempted. For example, `\.{\\moveleft}' is allowed only in vertical mode, - and `\.{\\lower}' only in non-vertical modes. Such cases are enumerated - here and in the other sections referred to under `See also \dots.' - */ - report_illegal_case(); - break; + tail_append(p); + } +} - /* Math-only cases in non-math modes, or vice versa */ - case non_math(sup_mark_cmd): - case non_math(sub_mark_cmd): - case non_math(super_sub_script_cmd): - case non_math(math_comp_cmd): - case non_math(delim_num_cmd): - case non_math(left_right_cmd): - case non_math(above_cmd): - case non_math(radical_cmd): - case non_math(math_style_cmd): - case non_math(math_choice_cmd): - case non_math(vcenter_cmd): - case non_math(non_script_cmd): - case non_math(mkern_cmd): - case non_math(limit_switch_cmd): - case non_math(mskip_cmd): - case non_math(math_accent_cmd): - case mmode + endv_cmd: - case mmode + par_end_cmd: - case mmode + stop_cmd: - case mmode + vskip_cmd: - case mmode + un_vbox_cmd: - case mmode + valign_cmd: - case mmode + hrule_cmd: - insert_dollar_sign(); - break; - /* Cases of |main_control| that build boxes and lists */ - case vmode + hrule_cmd: - case hmode + vrule_cmd: - case mmode + vrule_cmd: - /* The most important parts of |main_control| are concerned with \TeX's - chief mission of box-making. We need to control the activities that put - entries on vlists and hlists, as well as the activities that convert - those lists into boxes. All of the necessary machinery has already been - developed; it remains for us to ``push the buttons'' at the right times. - - As an introduction to these routines, let's consider one of the simplest - cases: What happens when `\.{\\hrule}' occurs in vertical mode, or - `\.{\\vrule}' in horizontal mode or math mode? The code in |main_control| - is short, since the |scan_rule_spec| routine already does most of what is - required; thus, there is no need for a special action procedure. - - Note that baselineskip calculations are disabled after a rule in vertical - mode, by setting |prev_depth:=pdf_ignored_dimen|. - */ - tail_append(scan_rule_spec()); - if (abs(mode) == vmode) - prev_depth = pdf_ignored_dimen; - else if (abs(mode) == hmode) - space_factor = 1000; - break; +@ @c +static void run_relax (void) { + return; +} - case vmode + vskip_cmd: - case hmode + hskip_cmd: - case mmode + hskip_cmd: - case mmode + mskip_cmd: - /* The processing of things like \.{\\hskip} and \.{\\vskip} is slightly - more complicated. But the code in |main_control| is very short, since - it simply calls on the action routine |append_glue|. Similarly, \.{\\kern} - activates |append_kern|. */ - append_glue(); - break; - case any_mode(kern_cmd): - case mmode + mkern_cmd: - append_kern(); - break; - - case non_math(left_brace_cmd): - /* Many of the actions related to box-making are triggered by the appearance - of braces in the input. For example, when the user says `\.{\\hbox} - \.{to} \.{100pt\{$\langle\,\hbox{hlist}\,\rangle$\}}' in vertical mode, - the information about the box size (100pt, |exactly|) is put onto |save_stack| - with a level boundary word just above it, and |cur_group:=adjusted_hbox_group|; - \TeX\ enters restricted horizontal mode to process the hlist. The right - brace eventually causes |save_stack| to be restored to its former state, - at which time the information about the box size (100pt, |exactly|) is - available once again; a box is packaged and we leave restricted horizontal - mode, appending the new box to the current list of the enclosing mode - (in this case to the current list of vertical mode), followed by any - vertical adjustments that were removed from the box by |hpack|. - - The next few sections of the program are therefore concerned with the - treatment of left and right curly braces. - - If a left brace occurs in the middle of a page or paragraph, it simply - introduces a new level of grouping, and the matching right brace will not have - such a drastic effect. Such grouping affects neither the mode nor the - current list. */ - new_save_level(simple_group); - eq_word_define(int_base + no_local_whatsits_code, 0); - eq_word_define(int_base + no_local_dirs_code, 0); - break; - case any_mode(begin_group_cmd): - new_save_level(semi_simple_group); - eq_word_define(int_base + no_local_whatsits_code, 0); - eq_word_define(int_base + no_local_dirs_code, 0); - break; - case any_mode(end_group_cmd): - if (cur_group == semi_simple_group) { - fixup_directions(); - } else { - off_save(); +@ |ignore_spaces| is a special case: after it has acted, |get_x_token| has already +fetched the next token from the input, so that operation in |main_control| +should be skipped. + +@c +static void run_ignore_spaces (void) { + if (cur_chr == 0) { + /* Get the next non-blank non-call... */ + do { + get_x_token(); + } while (cur_cmd == spacer_cmd); + + main_control_state = goto_skip_token; + } else { + int t = scanner_status; + scanner_status = normal; + get_token_lua(); + scanner_status = t; + cur_cs = prim_lookup(cs_text(cur_cs)); + if (cur_cs != undefined_primitive) { + cur_cmd = get_prim_eq_type(cur_cs); + cur_chr = get_prim_equiv(cur_cs); + cur_tok = (cur_cmd * STRING_OFFSET) + cur_chr; + main_control_state = goto_skip_token; } - break; - case any_mode(right_brace_cmd): - handle_right_brace(); - break; + } +} - case vmode + hmove_cmd: - case hmode + vmove_cmd: - case mmode + vmove_cmd: - /* Constructions that require a box are started by calling |scan_box| with - a specified context code. The |scan_box| routine verifies - that a |make_box| command comes next and then it calls |begin_box|. - */ - t = cur_chr; - scan_normal_dimen(); - if (t == 0) - scan_box(cur_val); - else - scan_box(-cur_val); - break; - case any_mode(leader_ship_cmd): - scan_box(leader_flag - a_leaders + cur_chr); - break; - case any_mode(make_box_cmd): - begin_box(0); - break; - case any_mode(assign_box_dir_cmd): - scan_register_num(); - cur_box = box(cur_val); - scan_optional_equals(); - scan_direction(); - if (cur_box != null) - box_dir(cur_box) = cur_val; - break; +@ |stop| is the second special case. We want |main_control| to return to its caller +if there is nothing left to do. - case vmode + start_par_cmd: - /* There is a really small patch to add a new primitive called - \.{\\quitvmode}. In vertical modes, it is identical to \.{\\indent}, - but in horizontal and math modes it is really a no-op (as opposed to - \.{\\indent}, which executes the |indent_in_hmode| procedure). - */ - /* A paragraph begins when horizontal-mode material occurs in vertical mode, - or when the paragraph is explicitly started by `\.{\\quitvmode}', - `\.{\\indent}' or `\.{\\noindent}'. - */ - new_graf((cur_chr > 0)); - break; - case hmode + start_par_cmd: - case mmode + start_par_cmd: - if (cur_chr != 2) - indent_in_hmode(); - break; - case vmode + letter_cmd: - case vmode + other_char_cmd: - case vmode + char_num_cmd: - case vmode + char_given_cmd: - case vmode + char_ghost_cmd: - case vmode + math_shift_cmd: - case vmode + math_shift_cs_cmd: - case vmode + un_hbox_cmd: - case vmode + vrule_cmd: - case vmode + accent_cmd: - case vmode + discretionary_cmd: - case vmode + hskip_cmd: - case vmode + valign_cmd: - case vmode + ex_space_cmd: - case vmode + no_boundary_cmd: - back_input(); - new_graf(true); - break; +@c +static void run_stop (void) { + if (its_all_over()) + main_control_state= goto_return; /* this is the only way out */ +} - case vmode + par_end_cmd: - /* A paragraph ends when a |par_end| command is sensed, or when we are in - horizontal mode when reaching the right brace of vertical-mode routines - like \.{\\vbox}, \.{\\insert}, or \.{\\output}. */ - normal_paragraph(); - if (mode > 0) { - check_filter("vmode_par"); - build_page(); - } - break; - case hmode + par_end_cmd: - if (align_state < 0) - off_save(); /* this tries to recover from an alignment that didn't end properly */ - end_graf(bottom_level); /* this takes us to the enclosing mode, if |mode>0| */ - if (mode == vmode) { - check_filter("hmode_par"); - build_page(); - } - break; - case hmode + stop_cmd: - case hmode + vskip_cmd: - case hmode + hrule_cmd: - case hmode + un_vbox_cmd: - case hmode + halign_cmd: - head_for_vmode(); - break; - case any_mode(insert_cmd): - case hmode + vadjust_cmd: - case mmode + vadjust_cmd: - /* Insertion and adjustment and mark nodes are constructed by the following - pieces of the program. */ - begin_insert_or_adjust(); - break; - case any_mode(mark_cmd): - handle_mark(); - break; - case any_mode(break_penalty_cmd): - /* Penalty nodes get into a list via the |break_penalty| command. */ - append_penalty(); - break; - case any_mode(remove_item_cmd): - /* The |remove_item| command removes a penalty, kern, or glue node if it - appears at the tail of the current list, using a brute-force linear scan. - Like \.{\\lastbox}, this command is not allowed in vertical mode (except - internal vertical mode), since the current list in vertical mode is sent - to the page builder. But if we happen to be able to implement it in - vertical mode, we do. */ - delete_last(); - break; - case vmode + un_vbox_cmd: - case hmode + un_hbox_cmd: - case mmode + un_hbox_cmd: - /* The |un_hbox| and |un_vbox| commands unwrap one of the |number_regs| - current boxes. */ - unpackage(); - break; - case hmode + ital_corr_cmd: - /* Italic corrections are converted to kern nodes when the |ital_corr| command - follows a character. In math mode the same effect is achieved by appending - a kern of zero here, since italic corrections are supplied later. */ - append_italic_correction(); - break; - case mmode + ital_corr_cmd: - tail_append(new_kern(0)); - break; - case hmode + discretionary_cmd: - case mmode + discretionary_cmd: - append_discretionary(); - break; - case any_mode(assign_local_box_cmd): - append_local_box(cur_chr); - break; - case hmode + accent_cmd: - /* We need only one more thing to complete the horizontal mode routines, namely - the \.{\\accent} primitive. */ - make_accent(); - break; - case any_mode(car_ret_cmd): - case any_mode(tab_mark_cmd): - align_error(); - break; - case any_mode(no_align_cmd): - no_align_error(); - break; - case any_mode(omit_cmd): - omit_error(); - break; - case vmode + halign_cmd: - case hmode + valign_cmd: - init_align(); - break; - case mmode + halign_cmd: - if (privileged()) { - if (cur_group == math_shift_group) - init_align(); - else - off_save(); - } - break; - case vmode + endv_cmd: - case hmode + endv_cmd: - do_endv(); - break; - case any_mode(end_cs_name_cmd): - cs_error(); - break; - case hmode + math_shift_cmd: - case hmode + math_shift_cs_cmd: - init_math(); - break; - case mmode + eq_no_cmd: - if (privileged()) { - if (cur_group == math_shift_group) - start_eq_no(); - else - off_save(); - } - break; - case mmode + left_brace_cmd: - math_left_brace(); - break; - case mmode + letter_cmd: - case mmode + other_char_cmd: - case mmode + char_given_cmd: - set_math_char(get_math_code(cur_chr)); - break; - case mmode + char_num_cmd: - scan_char_num(); - cur_chr = cur_val; - set_math_char(get_math_code(cur_chr)); - break; - case mmode + math_char_num_cmd: - if (cur_chr == 0) - mval = scan_mathchar(tex_mathcode); - else if (cur_chr == 1) - mval = scan_mathchar(aleph_mathcode); - else if (cur_chr == 2) - mval = scan_mathchar(xetex_mathcode); - else - mval = scan_mathchar(xetexnum_mathcode); - set_math_char(mval); - break; - case mmode + math_given_cmd: - mval = mathchar_from_integer(cur_chr, tex_mathcode); - set_math_char(mval); - break; - case mmode + omath_given_cmd: - mval = mathchar_from_integer(cur_chr, aleph_mathcode); - set_math_char(mval); - break; - case mmode + xmath_given_cmd: - mval = mathchar_from_integer(cur_chr, xetex_mathcode); - set_math_char(mval); - break; - case mmode + delim_num_cmd: - if (cur_chr == 0) - mval = scan_delimiter_as_mathchar(tex_mathcode); - else if (cur_chr == 1) - mval = scan_delimiter_as_mathchar(aleph_mathcode); - else - mval = scan_delimiter_as_mathchar(xetex_mathcode); - set_math_char(mval); - break; - case mmode + math_comp_cmd: - math_math_comp(); - break; - case mmode + limit_switch_cmd: - math_limit_switch(); - break; - case mmode + radical_cmd: - math_radical(); - break; - case mmode + accent_cmd: - case mmode + math_accent_cmd: - math_ac(); - break; - case mmode + vcenter_cmd: - scan_spec(vcenter_group); - normal_paragraph(); - push_nest(); - mode = -vmode; +@ @c +static void run_non_math_math (void) { + back_input(); + new_graf(true); +} + +@ @c +static void run_math_char_num (void) { + mathcodeval mval; /* to build up an argument to |set_math_char| */ + if (cur_chr == 0) + mval = scan_mathchar(tex_mathcode); + else if (cur_chr == 1) + mval = scan_mathchar(aleph_mathcode); + else if (cur_chr == 2) + mval = scan_mathchar(xetex_mathcode); + else + mval = scan_mathchar(xetexnum_mathcode); + math_char_in_text(mval); +} + +@ @c +static void run_math_given (void) { + mathcodeval mval; /* to build up an argument to |set_math_char| */ + mval = mathchar_from_integer(cur_chr, tex_mathcode); + math_char_in_text(mval); +} + +static void run_omath_given (void) { + mathcodeval mval; /* to build up an argument to |set_math_char| */ + mval = mathchar_from_integer(cur_chr, aleph_mathcode); + math_char_in_text(mval); +} + +static void run_xmath_given (void) { + mathcodeval mval; /* to build up an argument to |set_math_char| */ + mval = mathchar_from_integer(cur_chr, xetex_mathcode); + math_char_in_text(mval); +} + +@ The most important parts of |main_control| are concerned with \TeX's +chief mission of box-making. We need to control the activities that put +entries on vlists and hlists, as well as the activities that convert +those lists into boxes. All of the necessary machinery has already been +developed; it remains for us to ``push the buttons'' at the right times. + +As an introduction to these routines, let's consider one of the simplest +cases: What happens when `\.{\\hrule}' occurs in vertical mode, or +`\.{\\vrule}' in horizontal mode or math mode? The code in |main_control| +is short, since the |scan_rule_spec| routine already does most of what is +required; thus, there is no need for a special action procedure. + +Note that baselineskip calculations are disabled after a rule in vertical +mode, by setting |prev_depth:=pdf_ignored_dimen|. + +@c +static void run_rule (void) { + tail_append(scan_rule_spec()); + if (abs(mode) == vmode) prev_depth = pdf_ignored_dimen; - if (every_vbox != null) - begin_token_list(every_vbox, every_vbox_text); - break; - case mmode + math_style_cmd: - tail_append(new_style((small_number) cur_chr)); - break; - case mmode + non_script_cmd: - tail_append(new_glue(zero_glue)); - subtype(tail) = cond_math_glue; - break; - case mmode + math_choice_cmd: - if (cur_chr == 0) - append_choices(); + else if (abs(mode) == hmode) + space_factor = 1000; +} + +@ +Many of the actions related to box-making are triggered by the appearance +of braces in the input. For example, when the user says `\.{\\hbox} +\.{to} \.{100pt\{$\langle\,\hbox{hlist}\,\rangle$\}}' in vertical mode, +the information about the box size (100pt, |exactly|) is put onto |save_stack| +with a level boundary word just above it, and |cur_group:=adjusted_hbox_group|; +\TeX\ enters restricted horizontal mode to process the hlist. The right +brace eventually causes |save_stack| to be restored to its former state, +at which time the information about the box size (100pt, |exactly|) is +available once again; a box is packaged and we leave restricted horizontal +mode, appending the new box to the current list of the enclosing mode +(in this case to the current list of vertical mode), followed by any +vertical adjustments that were removed from the box by |hpack|. + +The next few sections of the program are therefore concerned with the +treatment of left and right curly braces. + +If a left brace occurs in the middle of a page or paragraph, it simply +introduces a new level of grouping, and the matching right brace will not have +such a drastic effect. Such grouping affects neither the mode nor the +current list. + +@c +static void run_left_brace (void) { + new_save_level(simple_group); + eq_word_define(int_base + no_local_whatsits_code, 0); + eq_word_define(int_base + no_local_dirs_code, 0); +} + +static void run_begin_group (void) { + new_save_level(semi_simple_group); + eq_word_define(int_base + no_local_whatsits_code, 0); + eq_word_define(int_base + no_local_dirs_code, 0); +} + +static void run_end_group (void) { + if (cur_group == semi_simple_group) { + fixup_directions(); + } else { + off_save(); + } +} + +@ Constructions that require a box are started by calling |scan_box| with +a specified context code. The |scan_box| routine verifies +that a |make_box| command comes next and then it calls |begin_box|. + +@c +static void run_move (void) { + int t = cur_chr; + scan_normal_dimen(); + if (t == 0) + scan_box(cur_val); + else + scan_box(-cur_val); +} + +@ @c +static void run_leader_ship (void) { + scan_box(leader_flag - a_leaders + cur_chr); +} + +@ @c +static void run_make_box (void) { + begin_box(0); +} + +@ @c +static void run_box_dir (void) { + scan_register_num(); + cur_box = box(cur_val); + scan_optional_equals(); + scan_direction(); + if (cur_box != null) + box_dir(cur_box) = cur_val; +} + +@ There is a really small patch to add a new primitive called +\.{\\quitvmode}. In vertical modes, it is identical to \.{\\indent}, +but in horizontal and math modes it is really a no-op (as opposed to +\.{\\indent}, which executes the |indent_in_hmode| procedure). + +A paragraph begins when horizontal-mode material occurs in vertical mode, +or when the paragraph is explicitly started by `\.{\\quitvmode}', +`\.{\\indent}' or `\.{\\noindent}'. + +@c +static void run_start_par_vmode (void) { + new_graf((cur_chr > 0)); +} + +@ @c +static void run_start_par (void) { + if (cur_chr != 2) + indent_in_hmode(); +} + +@ @c +static void run_new_graf (void) { + back_input(); + new_graf(true); +} + +@ A paragraph ends when a |par_end| command is sensed, or when we are in +horizontal mode when reaching the right brace of vertical-mode routines +like \.{\\vbox}, \.{\\insert}, or \.{\\output}. + +@c +static void run_par_end_vmode (void) { + normal_paragraph(); + if (mode > 0) { + check_filter("vmode_par"); + build_page(); + } +} + +@ @c +static void run_par_end_hmode (void) { + if (align_state < 0) + off_save(); /* this tries to recover from an alignment that didn't end properly */ + end_graf(bottom_level); /* this takes us to the enclosing mode, if |mode>0| */ + if (mode == vmode) { + check_filter("hmode_par"); + build_page(); + } +} + +@ @c +static void append_italic_correction_mmode (void) { + tail_append(new_kern(0)); +} + +@ @c +static void run_local_box (void) { + append_local_box(cur_chr); +} + +@ @c +static void run_halign_mmode (void) { + if (privileged()) { + if (cur_group == math_shift_group) + init_align(); else - setup_math_style(); - break; - case mmode + above_cmd: - math_fraction(); - break; - case mmode + sub_mark_cmd: - case mmode + sup_mark_cmd: - case mmode + super_sub_script_cmd: - sub_sup(); - break; - case mmode + left_right_cmd: - math_left_right(); - break; - case mmode + math_shift_cmd: - case mmode + math_shift_cs_cmd: + off_save(); + } +} + +@ @c +static void run_eq_no (void) { + if (privileged()) { if (cur_group == math_shift_group) - after_math(); + start_eq_no(); else off_save(); - break; + } +} - /* Cases of |main_control| that do not depend on |mode| */ - /* - The long |main_control| procedure has now been fully specified, except for - certain activities that are independent of the current mode. These activities - do not change the current vlist or hlist or mlist; if they change anything, - it is the value of a parameter or the meaning of a control sequence. - */ - case any_mode(toks_register_cmd): - case any_mode(assign_toks_cmd): - case any_mode(assign_int_cmd): - case any_mode(assign_attr_cmd): - case any_mode(assign_dir_cmd): - case any_mode(assign_dimen_cmd): - case any_mode(assign_glue_cmd): - case any_mode(assign_mu_glue_cmd): - case any_mode(assign_font_dimen_cmd): - case any_mode(assign_font_int_cmd): - case any_mode(set_aux_cmd): - case any_mode(set_prev_graf_cmd): - case any_mode(set_page_dimen_cmd): - case any_mode(set_page_int_cmd): - case any_mode(set_box_dimen_cmd): - case any_mode(set_tex_shape_cmd): - case any_mode(set_etex_shape_cmd): - case any_mode(def_char_code_cmd): - case any_mode(def_del_code_cmd): - case any_mode(extdef_math_code_cmd): - case any_mode(extdef_del_code_cmd): - case any_mode(def_family_cmd): - case any_mode(set_math_param_cmd): - case any_mode(set_font_cmd): - case any_mode(def_font_cmd): - case any_mode(letterspace_font_cmd): - case any_mode(pdf_copy_font_cmd): - case any_mode(register_cmd): - case any_mode(advance_cmd): - case any_mode(multiply_cmd): - case any_mode(divide_cmd): - case any_mode(prefix_cmd): - case any_mode(let_cmd): - case any_mode(shorthand_def_cmd): - case any_mode(read_to_cs_cmd): - case any_mode(def_cmd): - case any_mode(set_box_cmd): - case any_mode(hyph_data_cmd): - case any_mode(set_interaction_cmd): - case any_mode(set_ocp_cmd): - case any_mode(def_ocp_cmd): - case any_mode(set_ocp_list_cmd): - case any_mode(def_ocp_list_cmd): - case any_mode(clear_ocp_lists_cmd): - case any_mode(push_ocp_list_cmd): - case any_mode(pop_ocp_list_cmd): - case any_mode(ocp_list_op_cmd): - case any_mode(ocp_trace_level_cmd): - prefixed_command(); - break; - case any_mode(after_assignment_cmd): - get_token(); - after_token = cur_tok; - break; - case any_mode(after_group_cmd): - get_token(); - save_for_after(cur_tok); - break; - case any_mode(in_stream_cmd): - open_or_close_in(); - break; - case any_mode(message_cmd): - issue_message(); - break; - case any_mode(case_shift_cmd): - shift_case(); - break; - case any_mode(xray_cmd): - show_whatever(); - break; +@ @c +static void run_letter_mmode (void) { + set_math_char(get_math_code(cur_chr)); +} - /* Cases of |main_control| that are for extensions to \TeX */ - case any_mode(extension_cmd): - do_extension(static_pdf); - break; - } /* end of the big |switch| statement */ +@ @c +static void run_char_num_mmode (void) { + scan_char_num(); + cur_chr = cur_val; + set_math_char(get_math_code(cur_chr)); +} + +@ @c +static void run_math_char_num_mmode (void) { + mathcodeval mval; /* to build up an argument to |set_math_char| */ + if (cur_chr == 0) + mval = scan_mathchar(tex_mathcode); + else if (cur_chr == 1) + mval = scan_mathchar(aleph_mathcode); + else if (cur_chr == 2) + mval = scan_mathchar(xetex_mathcode); + else + mval = scan_mathchar(xetexnum_mathcode); + set_math_char(mval); +} + +@ @c +static void run_math_given_mmode (void) { + mathcodeval mval; /* to build up an argument to |set_math_char| */ + mval = mathchar_from_integer(cur_chr, tex_mathcode); + set_math_char(mval); +} + +static void run_omath_given_mmode (void) { + mathcodeval mval; /* to build up an argument to |set_math_char| */ + mval = mathchar_from_integer(cur_chr, aleph_mathcode); + set_math_char(mval); +} + +static void run_xmath_given_mmode (void) { + mathcodeval mval; /* to build up an argument to |set_math_char| */ + mval = mathchar_from_integer(cur_chr, xetex_mathcode); + set_math_char(mval); +} + +@ @c +static void run_delim_num (void) { + mathcodeval mval; /* to build up an argument to |set_math_char| */ + if (cur_chr == 0) + mval = scan_delimiter_as_mathchar(tex_mathcode); + else if (cur_chr == 1) + mval = scan_delimiter_as_mathchar(aleph_mathcode); + else + mval = scan_delimiter_as_mathchar(xetex_mathcode); + set_math_char(mval); + +} + +@ @c +static void run_vcenter (void) { + scan_spec(vcenter_group); + normal_paragraph(); + push_nest(); + mode = -vmode; + prev_depth = pdf_ignored_dimen; + if (every_vbox != null) + begin_token_list(every_vbox, every_vbox_text); +} + +@ @c +static void run_math_style (void) { + tail_append(new_style((small_number) cur_chr)); +} + +@ @c +static void run_non_script (void) { + tail_append(new_glue(zero_glue)); + subtype(tail) = cond_math_glue; +} + +@ @c +static void run_math_choice (void) { + if (cur_chr == 0) + append_choices(); + else + setup_math_style(); +} + +@ @c +static void run_math_shift (void) { + if (cur_group == math_shift_group) + after_math(); + else + off_save(); +} + +@ @c +static void run_after_assignment (void) { + get_token(); + after_token = cur_tok; +} + +@ @c +static void run_after_group (void) { + get_token(); + save_for_after(cur_tok); +} + +@ @c +static void run_extension (void) { + do_extension(static_pdf); +} + + +@ For mode-independent commands, the following macro is useful. + +Also, there is a list of cases where the user has probably gotten into or out of math +mode by mistake. \TeX\ will insert a dollar sign and rescan the current token, and +it makes sense ot have a macro for that as well. - goto BIG_SWITCH; /* restart */ +@c +#define any_mode(A,B) jump_table[vmode+(A)]=B; jump_table[hmode+(A)]=B; jump_table[mmode+(A)]=B +#define non_math(A,B) jump_table[vmode+(A)]=B; jump_table[hmode+(A)]=B; + + +@ The |main_control| uses a jump table, and |init_main_control| sets that table up. +@c +typedef void (*main_control_function) (void); +main_control_function *jump_table; + +static void init_main_control (void) { + jump_table = xmalloc((mmode+max_command_cmd+1) * sizeof(main_control_function)) ; + + jump_table[hmode + char_num_cmd] = run_char_num; + jump_table[hmode + letter_cmd] = run_char; + jump_table[hmode + other_char_cmd] = run_char; + jump_table[hmode + char_given_cmd] = run_char; + jump_table[hmode + spacer_cmd] = run_app_space; + jump_table[hmode + ex_space_cmd] = run_app_space; + jump_table[mmode + ex_space_cmd] = run_app_space; + jump_table[hmode + no_boundary_cmd] = run_no_boundary; + jump_table[hmode + char_ghost_cmd] = run_char_ghost; + jump_table[mmode + char_ghost_cmd] = run_char_ghost; + any_mode(relax_cmd, run_relax); + jump_table[vmode + spacer_cmd] = run_relax; + jump_table[mmode + spacer_cmd] = run_relax; + jump_table[mmode + no_boundary_cmd] = run_relax; + any_mode(ignore_spaces_cmd,run_ignore_spaces); + jump_table[vmode + stop_cmd] = run_stop; + jump_table[vmode + math_char_num_cmd] = run_non_math_math; + jump_table[vmode + math_given_cmd] = run_non_math_math; + jump_table[vmode + omath_given_cmd] = run_non_math_math; + jump_table[vmode + xmath_given_cmd] = run_non_math_math; + jump_table[hmode + math_char_num_cmd] = run_math_char_num; + jump_table[hmode + math_given_cmd] = run_math_given; + jump_table[hmode + omath_given_cmd] = run_omath_given; + jump_table[hmode + xmath_given_cmd] = run_xmath_given; + + jump_table[vmode + vmove_cmd] = report_illegal_case; + jump_table[hmode + hmove_cmd] = report_illegal_case; + jump_table[mmode + hmove_cmd] = report_illegal_case; + any_mode(last_item_cmd, report_illegal_case); + jump_table[vmode + vadjust_cmd] = report_illegal_case; + jump_table[vmode + ital_corr_cmd] = report_illegal_case; + non_math(eq_no_cmd,report_illegal_case); + any_mode(mac_param_cmd,report_illegal_case); + + non_math(sup_mark_cmd, insert_dollar_sign); + non_math(sub_mark_cmd, insert_dollar_sign); + non_math(super_sub_script_cmd, insert_dollar_sign); + non_math(math_comp_cmd, insert_dollar_sign); + non_math(delim_num_cmd, insert_dollar_sign); + non_math(left_right_cmd, insert_dollar_sign); + non_math(above_cmd, insert_dollar_sign); + non_math(radical_cmd, insert_dollar_sign); + non_math(math_style_cmd, insert_dollar_sign); + non_math(math_choice_cmd, insert_dollar_sign); + non_math(vcenter_cmd, insert_dollar_sign); + non_math(non_script_cmd, insert_dollar_sign); + non_math(mkern_cmd, insert_dollar_sign); + non_math(limit_switch_cmd, insert_dollar_sign); + non_math(mskip_cmd, insert_dollar_sign); + non_math(math_accent_cmd, insert_dollar_sign); + jump_table[mmode + endv_cmd] = insert_dollar_sign; + jump_table[mmode + par_end_cmd] = insert_dollar_sign; + jump_table[mmode + stop_cmd] = insert_dollar_sign; + jump_table[mmode + vskip_cmd] = insert_dollar_sign; + jump_table[mmode + un_vbox_cmd] = insert_dollar_sign; + jump_table[mmode + valign_cmd] = insert_dollar_sign; + jump_table[mmode + hrule_cmd] = insert_dollar_sign; + jump_table[vmode + hrule_cmd] = run_rule; + jump_table[hmode + vrule_cmd] = run_rule; + jump_table[mmode + vrule_cmd] = run_rule; + jump_table[vmode + vskip_cmd] = append_glue; + jump_table[hmode + hskip_cmd] = append_glue; + jump_table[mmode + hskip_cmd] = append_glue; + jump_table[mmode + mskip_cmd] = append_glue; + any_mode(kern_cmd, append_kern); + jump_table[mmode + mkern_cmd] = append_kern; + non_math(left_brace_cmd, run_left_brace); + any_mode(begin_group_cmd,run_begin_group); + any_mode(end_group_cmd, run_end_group); + any_mode(right_brace_cmd, handle_right_brace); + jump_table[vmode + hmove_cmd] = run_move; + jump_table[hmode + vmove_cmd] = run_move; + jump_table[mmode + vmove_cmd] = run_move; + any_mode(leader_ship_cmd, run_leader_ship); + any_mode(make_box_cmd, run_make_box); + any_mode(assign_box_dir_cmd, run_box_dir); + jump_table[vmode + start_par_cmd] = run_start_par_vmode; + jump_table[hmode + start_par_cmd] = run_start_par; + jump_table[mmode + start_par_cmd] = run_start_par; + jump_table[vmode + letter_cmd] = run_new_graf; + jump_table[vmode + other_char_cmd] = run_new_graf; + jump_table[vmode + char_num_cmd] = run_new_graf; + jump_table[vmode + char_given_cmd] = run_new_graf; + jump_table[vmode + char_ghost_cmd] = run_new_graf; + jump_table[vmode + math_shift_cmd] = run_new_graf; + jump_table[vmode + math_shift_cs_cmd] = run_new_graf; + jump_table[vmode + un_hbox_cmd] = run_new_graf; + jump_table[vmode + vrule_cmd] = run_new_graf; + jump_table[vmode + accent_cmd] = run_new_graf; + jump_table[vmode + discretionary_cmd] = run_new_graf; + jump_table[vmode + hskip_cmd] = run_new_graf; + jump_table[vmode + valign_cmd] = run_new_graf; + jump_table[vmode + ex_space_cmd] = run_new_graf; + jump_table[vmode + no_boundary_cmd] = run_new_graf; + jump_table[vmode + par_end_cmd] = run_par_end_vmode; + jump_table[hmode + par_end_cmd] = run_par_end_hmode; + jump_table[hmode + stop_cmd] = head_for_vmode; + jump_table[hmode + vskip_cmd] = head_for_vmode; + jump_table[hmode + hrule_cmd] = head_for_vmode; + jump_table[hmode + un_vbox_cmd] = head_for_vmode; + jump_table[hmode + halign_cmd] = head_for_vmode; + any_mode(insert_cmd,begin_insert_or_adjust); + jump_table[hmode + vadjust_cmd] = begin_insert_or_adjust; + jump_table[mmode + vadjust_cmd] = begin_insert_or_adjust; + any_mode(mark_cmd, handle_mark); + any_mode(break_penalty_cmd, append_penalty); + any_mode(remove_item_cmd, delete_last); + jump_table[vmode + un_vbox_cmd] = unpackage; + jump_table[hmode + un_hbox_cmd] = unpackage; + jump_table[mmode + un_hbox_cmd] = unpackage; + jump_table[hmode + ital_corr_cmd] = append_italic_correction; + jump_table[mmode + ital_corr_cmd] = append_italic_correction_mmode; + jump_table[hmode + discretionary_cmd] = append_discretionary; + jump_table[mmode + discretionary_cmd] = append_discretionary; + any_mode(assign_local_box_cmd, run_local_box); + jump_table[hmode + accent_cmd] = make_accent; + any_mode(car_ret_cmd,align_error); + any_mode(tab_mark_cmd,align_error); + any_mode(no_align_cmd,no_align_error); + any_mode(omit_cmd, omit_error); + jump_table[vmode + halign_cmd] = init_align; + jump_table[hmode + valign_cmd] = init_align; + jump_table[mmode + halign_cmd] = run_halign_mmode; + jump_table[vmode + endv_cmd] = do_endv; + jump_table[hmode + endv_cmd] = do_endv; + any_mode(end_cs_name_cmd, cs_error); + jump_table[hmode + math_shift_cmd] = init_math; + jump_table[hmode + math_shift_cs_cmd] = init_math; + jump_table[mmode + eq_no_cmd] = run_eq_no; + jump_table[mmode + left_brace_cmd] = math_left_brace; + jump_table[mmode + letter_cmd] = run_letter_mmode; + jump_table[mmode + other_char_cmd] = run_letter_mmode; + jump_table[mmode + char_given_cmd] = run_letter_mmode; + jump_table[mmode + char_num_cmd] = run_char_num_mmode; + jump_table[mmode + math_char_num_cmd] = run_math_char_num_mmode; + jump_table[mmode + math_given_cmd] = run_math_given_mmode; + jump_table[mmode + omath_given_cmd] = run_omath_given_mmode; + jump_table[mmode + xmath_given_cmd] = run_xmath_given_mmode; + jump_table[mmode + delim_num_cmd] = run_delim_num; + jump_table[mmode + math_comp_cmd] = math_math_comp; + jump_table[mmode + limit_switch_cmd] = math_limit_switch; + jump_table[mmode + radical_cmd] = math_radical; + jump_table[mmode + accent_cmd] = math_ac; + jump_table[mmode + math_accent_cmd] = math_ac; + jump_table[mmode + vcenter_cmd] = run_vcenter; + jump_table[mmode + math_style_cmd] = run_math_style; + jump_table[mmode + non_script_cmd] = run_non_script; + jump_table[mmode + math_choice_cmd] = run_math_choice; + jump_table[mmode + above_cmd] = math_fraction; + jump_table[mmode + sub_mark_cmd] = sub_sup; + jump_table[mmode + sup_mark_cmd] = sub_sup; + jump_table[mmode + super_sub_script_cmd] = sub_sup; + jump_table[mmode + left_right_cmd] = math_left_right; + jump_table[mmode + math_shift_cmd] = run_math_shift; + jump_table[mmode + math_shift_cs_cmd] = run_math_shift; + any_mode(toks_register_cmd, prefixed_command); + any_mode(assign_toks_cmd, prefixed_command); + any_mode(assign_int_cmd, prefixed_command); + any_mode(assign_attr_cmd, prefixed_command); + any_mode(assign_dir_cmd, prefixed_command); + any_mode(assign_dimen_cmd, prefixed_command); + any_mode(assign_glue_cmd, prefixed_command); + any_mode(assign_mu_glue_cmd, prefixed_command); + any_mode(assign_font_dimen_cmd, prefixed_command); + any_mode(assign_font_int_cmd, prefixed_command); + any_mode(set_aux_cmd, prefixed_command); + any_mode(set_prev_graf_cmd, prefixed_command); + any_mode(set_page_dimen_cmd, prefixed_command); + any_mode(set_page_int_cmd, prefixed_command); + any_mode(set_box_dimen_cmd, prefixed_command); + any_mode(set_tex_shape_cmd, prefixed_command); + any_mode(set_etex_shape_cmd, prefixed_command); + any_mode(def_char_code_cmd, prefixed_command); + any_mode(def_del_code_cmd, prefixed_command); + any_mode(extdef_math_code_cmd, prefixed_command); + any_mode(extdef_del_code_cmd, prefixed_command); + any_mode(def_family_cmd, prefixed_command); + any_mode(set_math_param_cmd, prefixed_command); + any_mode(set_font_cmd, prefixed_command); + any_mode(def_font_cmd, prefixed_command); + any_mode(letterspace_font_cmd, prefixed_command); + any_mode(pdf_copy_font_cmd, prefixed_command); + any_mode(register_cmd, prefixed_command); + any_mode(advance_cmd, prefixed_command); + any_mode(multiply_cmd, prefixed_command); + any_mode(divide_cmd, prefixed_command); + any_mode(prefix_cmd, prefixed_command); + any_mode(let_cmd, prefixed_command); + any_mode(shorthand_def_cmd, prefixed_command); + any_mode(read_to_cs_cmd, prefixed_command); + any_mode(def_cmd, prefixed_command); + any_mode(set_box_cmd, prefixed_command); + any_mode(hyph_data_cmd, prefixed_command); + any_mode(set_interaction_cmd, prefixed_command); + any_mode(after_assignment_cmd,run_after_assignment); + any_mode(after_group_cmd,run_after_group); + any_mode(in_stream_cmd,open_or_close_in); + any_mode(message_cmd,issue_message); + any_mode(case_shift_cmd, shift_case); + any_mode(xray_cmd, show_whatever); + any_mode(extension_cmd, run_extension); +} + +@ And here is |main_control| itself. It is quite short nowadays. + +@c +void main_control(void) +{ + main_control_state = goto_next; + init_main_control () ; + + if (equiv(every_job_loc) != null) + begin_token_list(equiv(every_job_loc), every_job_text); + + while (1) { + if (main_control_state == goto_skip_token) + main_control_state = goto_next; /* reset */ + else + get_x_token(); + + /* Give diagnostic information, if requested */ + /* When a new token has just been fetched at |big_switch|, we have an + ideal place to monitor \TeX's activity. */ + if (interrupt != 0 && OK_to_interrupt) { + back_input(); + check_interrupt(); + continue; + } + if (int_par(tracing_commands_code) > 0) + show_cur_cmd_chr(); + + (jump_table[(abs(mode) + cur_cmd)])(); /* run the command */ + + if (main_control_state == goto_return) { + return; + } + } + return; /* not reached */ } @ @c @@ -941,6 +962,18 @@ void you_cant(void) print_in_mode(mode); } +@ +When erroneous situations arise, \TeX\ usually issues an error message +specific to the particular error. For example, `\.{\\noalign}' should +not appear in any mode, since it is recognized by the |align_peek| routine +in all of its legitimate appearances; a special error message is given +when `\.{\\noalign}' occurs elsewhere. But sometimes the most appropriate +error message is simply that the user is not allowed to do what he or she +has attempted. For example, `\.{\\moveleft}' is allowed only in vertical mode, +and `\.{\\lower}' only in non-vertical modes. Such cases are enumerated +here and in the other sections referred to under `See also \dots.' + +@c void report_illegal_case(void) { you_cant(); @@ -1324,7 +1357,7 @@ void box_end(int box_context) space_factor = 1000; else cur_box = new_sub_box(cur_box); - vlink(tail) = cur_box; + couple_nodes(tail, cur_box); tail = cur_box; } } @@ -1362,7 +1395,7 @@ void box_end(int box_context) } } else - ship_out(static_pdf, cur_box, true); + ship_out(static_pdf, cur_box, SHIPPING_PAGE); } } @@ -1410,6 +1443,7 @@ void new_graf(boolean indented) p = new_null_box(); box_dir(p) = par_direction; width(p) = par_indent; + subtype(p) = HLIST_SUBTYPE_INDENT; q = tail; tail_append(p); } else { @@ -1419,8 +1453,8 @@ void new_graf(boolean indented) while (dir_rover != null) { if ((vlink(dir_rover) != null) || (dir_dir(dir_rover) != par_direction)) { dir_graf_tmp = new_dir(dir_dir(dir_rover)); - vlink(dir_graf_tmp) = vlink(q); - vlink(q) = dir_graf_tmp; + try_couple_nodes(dir_graf_tmp,vlink(q)); + couple_nodes(q,dir_graf_tmp); } dir_rover = vlink(dir_rover); } @@ -1578,6 +1612,13 @@ void append_penalty(void) @ When |delete_last| is called, |cur_chr| is the |type| of node that will be deleted, if present. +The |remove_item| command removes a penalty, kern, or glue node if it +appears at the tail of the current list, using a brute-force linear scan. +Like \.{\\lastbox}, this command is not allowed in vertical mode (except +internal vertical mode), since the current list in vertical mode is sent +to the page builder. But if we happen to be able to implement it in +vertical mode, we do. + @c void delete_last(void) { @@ -1635,7 +1676,7 @@ void unpackage(void) halfword s; /* for varmem assignment */ if (cur_chr > copy_code) { /* Handle saved items and |goto done| */ - vlink(tail) = disc_ptr[cur_chr]; + try_couple_nodes(tail, disc_ptr[cur_chr]); disc_ptr[cur_chr] = null; goto DONE; } @@ -1656,9 +1697,9 @@ void unpackage(void) } if (c == copy_code) { s = copy_node_list(list_ptr(p)); - vlink(tail) = s; + try_couple_nodes(tail,s); } else { - vlink(tail) = list_ptr(p); + try_couple_nodes(tail,list_ptr(p)); box(cur_val) = null; list_ptr(p) = null; flush_node(p); @@ -1667,14 +1708,19 @@ void unpackage(void) while (vlink(tail) != null) { r = vlink(tail); if (!is_char_node(r) && (type(r) == margin_kern_node)) { - vlink(tail) = vlink(r); + try_couple_nodes(tail,vlink(r)); flush_node(r); } tail = vlink(tail); } } -@ @c +@ +Italic corrections are converted to kern nodes when the |ital_corr| command +follows a character. In math mode the same effect is achieved by appending +a kern of zero here, since italic corrections are supplied later. + +@c void append_italic_correction(void) { halfword p; /* |char_node| at the tail of the current list */ @@ -2662,40 +2708,6 @@ void prefixed_command(void) case set_interaction_cmd: new_interaction(); break; - case set_ocp_cmd: - print_err("To use ocps, use the \\pushocplist primitive"); - print_ln(); - break; - case def_ocp_cmd: - new_ocp((small_number) a); - break; - case set_ocp_list_cmd: - print_err("To use ocp lists, use the \\pushocplist primitive"); - print_ln(); - break; - case def_ocp_list_cmd: - new_ocp_list((small_number) a); - break; - case push_ocp_list_cmd: - do_push_ocp_list((small_number) a); - break; - case pop_ocp_list_cmd: - do_pop_ocp_list((small_number) a); - break; - case clear_ocp_lists_cmd: - do_clear_ocp_lists((small_number) a); - break; - case ocp_list_op_cmd: - print_err("To build ocp lists, use the \\ocplist primitive"); - print_ln(); - break; - case ocp_trace_level_cmd: - scan_optional_equals(); - scan_int(); - if (cur_val != 0) - cur_val = 1; - define(ocp_trace_level_base, data_cmd, cur_val); - break; default: confusion("prefix"); break; @@ -2854,7 +2866,7 @@ void assign_internal_value(int a, halfword p, int cur_val) no_local_whatsits + 1); } - } else if ((p >= dimen_base) && (p < eqtb_size)) { + } else if ((p >= dimen_base) && (p <= eqtb_size)) { if (p == (dimen_base + page_left_offset_code)) { n = cur_val - one_true_inch; word_define(dimen_base + h_offset_code, n); @@ -3582,8 +3594,6 @@ void initialize(void) cs_text(frozen_primitive) = maketexstring("primitive"); create_null_font(); font_bytes = 0; - init_null_ocp(get_nullstr(), maketexstring("nullocp")); - initialize_init_ocplists(); pdf_h_origin = one_inch; pdf_v_origin = one_inch; pdf_compress_level = 9; |