summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/luatexdir/tex/expand.w
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/tex/expand.w')
-rw-r--r--Build/source/texk/web2c/luatexdir/tex/expand.w829
1 files changed, 0 insertions, 829 deletions
diff --git a/Build/source/texk/web2c/luatexdir/tex/expand.w b/Build/source/texk/web2c/luatexdir/tex/expand.w
deleted file mode 100644
index c912863b2a1..00000000000
--- a/Build/source/texk/web2c/luatexdir/tex/expand.w
+++ /dev/null
@@ -1,829 +0,0 @@
-% expand.w
-%
-% Copyright 2009-2010 Taco Hoekwater <taco@@luatex.org>
-%
-% This file is part of LuaTeX.
-%
-% LuaTeX is free software; you can redistribute it and/or modify it under
-% the terms of the GNU General Public License as published by the Free
-% Software Foundation; either version 2 of the License, or (at your
-% option) any later version.
-%
-% LuaTeX is distributed in the hope that it will be useful, but WITHOUT
-% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
-% License for more details.
-%
-% You should have received a copy of the GNU General Public License along
-% with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
-
-@ @c
-
-
-#include "ptexlib.h"
-
-@ Only a dozen or so command codes |>max_command| can possibly be returned by
-|get_next|; in increasing order, they are |undefined_cs|, |expand_after|,
-|no_expand|, |input|, |if_test|, |fi_or_else|, |cs_name|, |convert|, |the|,
-|top_bot_mark|, |call|, |long_call|, |outer_call|, |long_outer_call|, and
-|end_template|.{\emergencystretch=40pt\par}
-
-Sometimes, recursive calls to the following |expand| routine may
-cause exhaustion of the run-time calling stack, resulting in
-forced execution stops by the operating system. To diminish the chance
-of this happening, a counter is used to keep track of the recursion
-depth, in conjunction with a constant called |expand_depth|.
-
-Note that this does not catch all possible infinite recursion loops,
-just the ones that exhaust the application calling stack. The
-actual maximum value of |expand_depth| is outside of our control, but
-the initial setting of |100| should be enough to prevent problems.
-@^system dependencies@>
-
-@c
-static int expand_depth_count = 0;
-
-
-@ The |expand| subroutine is used when |cur_cmd>max_command|. It removes a
-``call'' or a conditional or one of the other special operations just
-listed. It follows that |expand| might invoke itself recursively. In all
-cases, |expand| destroys the current token, but it sets things up so that
-the next |get_next| will deliver the appropriate next token. The value of
-|cur_tok| need not be known when |expand| is called.
-
-Since several of the basic scanning routines communicate via global variables,
-their values are saved as local variables of |expand| so that
-recursive calls don't invalidate them.
-@^recursion@>
-
-@c
-int is_in_csname = 0;
-
-@ @c
-void expand(void)
-{
- halfword t; /* token that is being ``expanded after'' */
- halfword p; /* for list manipulation */
- halfword cur_ptr; /* for a local token list pointer */
- int cv_backup; /* to save the global quantity |cur_val| */
- int cvl_backup, radix_backup, co_backup; /* to save |cur_val_level|, etc. */
- halfword backup_backup; /* to save |link(backup_head)| */
- int save_scanner_status; /* temporary storage of |scanner_status| */
- incr(expand_depth_count);
- if (expand_depth_count >= expand_depth)
- overflow("expansion depth", (unsigned) expand_depth);
- cv_backup = cur_val;
- cvl_backup = cur_val_level;
- radix_backup = radix;
- co_backup = cur_order;
- backup_backup = token_link(backup_head);
- RESWITCH:
- if (cur_cmd < call_cmd) {
- /* Expand a nonmacro */
- if (tracing_commands_par > 1)
- show_cur_cmd_chr();
- switch (cur_cmd) {
- case top_bot_mark_cmd:
- /* Insert the appropriate mark text into the scanner */
- t = cur_chr % marks_code;
- if (cur_chr >= marks_code)
- scan_mark_num();
- else
- cur_val = 0;
- switch (t) {
- case first_mark_code:
- cur_ptr = first_mark(cur_val);
- break;
- case bot_mark_code:
- cur_ptr = bot_mark(cur_val);
- break;
- case split_first_mark_code:
- cur_ptr = split_first_mark(cur_val);
- break;
- case split_bot_mark_code:
- cur_ptr = split_bot_mark(cur_val);
- break;
- default:
- cur_ptr = top_mark(cur_val);
- break;
- }
- if (cur_ptr != null)
- begin_token_list(cur_ptr, mark_text);
- break;
- case expand_after_cmd:
- if (cur_chr == 0) {
- /* Expand the token after the next token */
- /* It takes only a little shuffling to do what \TeX\ calls \.{\\expandafter}. */
- get_token();
- t = cur_tok;
- get_token();
- if (cur_cmd > max_command_cmd)
- expand();
- else
- back_input();
- cur_tok = t;
- back_input();
-
- } else { /* \\unless */
- /* Negate a boolean conditional and |goto reswitch| */
- /* The result of a boolean condition is reversed when the conditional is
- preceded by \.{\\unless}. */
- get_token();
- if ((cur_cmd == if_test_cmd) && (cur_chr != if_case_code)) {
- cur_chr = cur_chr + unless_code;
- goto RESWITCH;
- }
- print_err("You can't use `\\unless' before `");
- print_cmd_chr((quarterword) cur_cmd, cur_chr);
- print_char('\'');
- help1("Continue, and I'll forget that it ever happened.");
- back_error();
- }
- break;
- case no_expand_cmd:
- if (cur_chr == 0) {
- /* Suppress expansion of the next token */
- /* The implementation of \.{\\noexpand} is a bit trickier, because it is
- necessary to insert a special `|dont_expand|' marker into \TeX's reading
- mechanism. This special marker is processed by |get_next|, but it does
- not slow down the inner loop.
-
- Since \.{\\outer} macros might arise here, we must also
- clear the |scanner_status| temporarily.
- */
-
- save_scanner_status = scanner_status;
- scanner_status = normal;
- get_token();
- scanner_status = save_scanner_status;
- t = cur_tok;
- back_input(); /* now |start| and |loc| point to the backed-up token |t| */
- if (t >= cs_token_flag) {
- p = get_avail();
- set_token_info(p, cs_token_flag + frozen_dont_expand);
- set_token_link(p, iloc);
- istart = p;
- iloc = p;
- }
-
- } else {
- /* Implement \.{\\primitive} */
- /*
- The \.{\\primitive} handling. If the primitive meaning of the next
- token is an expandable command, it suffices to replace the current
- token with the primitive one and restart |expand|.
-
- Otherwise, the token we just read has to be pushed back, as well
- as a token matching the internal form of \.{\\primitive}, that is
- sneaked in as an alternate form of |ignore_spaces|.
-
- An implementation problem surfaces: There really is no |cur_cs|
- attached to the inserted primitive command, so it is safer to set
- |cur_cs| to zero. |cur_tok| has a similar problem. And for the
- non-expanded branch, simply pushing back a token that matches the
- correct internal command does not work, because that approach would
- not survive roundtripping to a temporary file or even a token list.
-
- In a next version, it would be smart to create |frozen_| versions of
- all the primitives. Then, this problem would not happen, at the
- expense of a few hundred extra control sequences.
- */
- save_scanner_status = scanner_status;
- scanner_status = normal;
- get_token();
- scanner_status = save_scanner_status;
- cur_cs = prim_lookup(cs_text(cur_cs));
- if (cur_cs != undefined_primitive) {
- t = get_prim_eq_type(cur_cs);
- if (t > max_command_cmd) {
- cur_cmd = t;
- cur_chr = get_prim_equiv(cur_cs);
- cur_tok = token_val(cur_cmd, cur_chr);
- cur_cs = 0;
- goto RESWITCH;
- } else {
- back_input(); /* now |loc| and |start| point to a one-item list */
- p = get_avail();
- set_token_info(p, cs_token_flag + frozen_primitive);
- set_token_link(p, iloc);
- iloc = p;
- istart = p;
- }
- } else if (suppress_primitive_error_par == 0) {
- print_err("Missing primitive name");
- help2
- ("The control sequence marked <to be read again> does not",
- "represent any known primitive.");
- back_error();
- }
-
- }
- break;
- case cs_name_cmd:
- /* Manufacture a control sequence name; */
- if (cur_chr == 0) {
- manufacture_csname(0);
- } else if (cur_chr == 1) {
- inject_last_tested_cs();
- } else {
- manufacture_csname(1);
- }
- break;
- case convert_cmd:
- conv_toks(); /* this procedure is discussed in Part 27 below */
- break;
- 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;
- case fi_or_else_cmd:
- /* Terminate the current conditional and skip to \.{\\fi} */
- /* The processing of conditionals is complete except for the following
- code, which is actually part of |expand|. It comes into play when
- \.{\\or}, \.{\\else}, or \.{\\fi} is scanned. */
-
- if (tracing_ifs_par > 0)
- if (tracing_commands_par <= 1)
- show_cur_cmd_chr();
- if (cur_chr > if_limit) {
- if (if_limit == if_code) {
- insert_relax(); /* condition not yet evaluated */
- } else {
- print_err("Extra ");
- print_cmd_chr(fi_or_else_cmd, cur_chr);
- help1("I'm ignoring this; it doesn't match any \\if.");
- error();
- }
- } else {
- while (cur_chr != fi_code)
- pass_text(); /* skip to \.{\\fi} */
- pop_condition_stack();
- }
-
- break;
- case input_cmd:
- /* Initiate or terminate input from a file */
- if (cur_chr == 1)
- force_eof = true;
- else if (cur_chr == 2)
- pseudo_start();
- else if (cur_chr == 3) {
- pseudo_start();
- iname = 19;
- } else if (name_in_progress)
- insert_relax();
- else
- start_input();
- break;
- case variable_cmd:
- do_variable();
- break;
- case feedback_cmd:
- do_feedback();
- break;
- default:
- /* Complain about an undefined macro */
- print_err("Undefined control sequence");
- help5("The control sequence at the end of the top line",
- "of your error message was never \\def'ed. If you have",
- "misspelled it (e.g., `\\hobx'), type `I' and the correct",
- "spelling (e.g., `I\\hbox'). Otherwise just continue,",
- "and I'll forget about whatever was undefined.");
- error();
- break;
- }
- } else if (cur_cmd < end_template_cmd) {
- macro_call();
- } else {
- /* Insert a token containing |frozen_endv| */
- /* An |end_template| command is effectively changed to an |endv| command
- by the following code. (The reason for this is discussed below; the
- |frozen_end_template| at the end of the template has passed the
- |check_outer_validity| test, so its mission of error detection has been
- accomplished.)
- */
- cur_tok = cs_token_flag + frozen_endv;
- back_input();
-
- }
- cur_val = cv_backup;
- cur_val_level = cvl_backup;
- radix = radix_backup;
- cur_order = co_backup;
- set_token_link(backup_head, backup_backup);
- decr(expand_depth_count);
-}
-
-@ @c
-void complain_missing_csname(void)
-{
- print_err("Missing \\endcsname inserted");
- help2("The control sequence marked <to be read again> should",
- "not appear between \\csname and \\endcsname.");
- back_error();
-}
-
-@ @c
-void manufacture_csname(boolean use)
-{
- halfword p, q, r;
- lstring *ss;
- r = get_avail();
- p = r; /* head of the list of characters */
- is_in_csname += 1;
- do {
- get_x_token();
- if (cur_cs == 0)
- store_new_token(cur_tok);
- } while (cur_cs == 0);
- if (cur_cmd != end_cs_name_cmd) {
- /* Complain about missing \.{\\endcsname} */
- complain_missing_csname();
- }
- /* Look up the characters of list |r| in the hash table, and set |cur_cs| */
- ss = tokenlist_to_lstring(r, true);
- is_in_csname -= 1;
- if (use) {
- if (ss->l > 0) {
- cur_cs = string_lookup((char *) ss->s, ss->l);
- } else {
- cur_cs = null_cs;
- }
- last_cs_name = cur_cs ;
- free_lstring(ss);
- flush_list(r);
- if (cur_cs == null_cs) {
- /* skip */
- } else if (eq_type(cur_cs) == undefined_cs_cmd) {
- /* skip */
- } else {
- cur_tok = cur_cs + cs_token_flag;
- back_input();
- }
- } else {
- if (ss->l > 0) {
- no_new_control_sequence = false;
- cur_cs = string_lookup((char *) ss->s, ss->l);
- no_new_control_sequence = true;
- } else {
- 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();
- }
-}
-
-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.
-
-@c
-void insert_relax(void)
-{
- cur_tok = cs_token_flag + cur_cs;
- back_input();
- cur_tok = cs_token_flag + frozen_relax;
- back_input();
- token_type = inserted;
-}
-
-
-@ Here is a recursive procedure that is \TeX's usual way to get the
-next token of input. It has been slightly optimized to take account of
-common cases.
-
-@c
-void get_x_token(void)
-{ /* sets |cur_cmd|, |cur_chr|, |cur_tok|, and expands macros */
- RESTART:
- get_next();
- if (cur_cmd <= max_command_cmd)
- goto DONE;
- if (cur_cmd >= call_cmd) {
- if (cur_cmd < end_template_cmd) {
- macro_call();
- } else {
- cur_cs = frozen_endv;
- cur_cmd = endv_cmd;
- goto DONE; /* |cur_chr=null_list| */
- }
- } else {
- expand();
- }
- goto RESTART;
- DONE:
- if (cur_cs == 0)
- cur_tok = token_val(cur_cmd, cur_chr);
- else
- cur_tok = cs_token_flag + cur_cs;
-}
-
-
-@ The |get_x_token| procedure is equivalent to two consecutive
-procedure calls: |get_next; x_token|.
-
-@c
-void x_token(void)
-{ /* |get_x_token| without the initial |get_next| */
- while (cur_cmd > max_command_cmd) {
- expand();
- get_next();
- }
- if (cur_cs == 0)
- cur_tok = token_val(cur_cmd, cur_chr);
- else
- cur_tok = cs_token_flag + cur_cs;
-}
-
-
-@ A control sequence that has been \.{\\def}'ed by the user is expanded by
-\TeX's |macro_call| procedure.
-
-Before we get into the details of |macro_call|, however, let's consider the
-treatment of primitives like \.{\\topmark}, since they are essentially
-macros without parameters. The token lists for such marks are kept in five
-global arrays of pointers; we refer to the individual entries of these
-arrays by symbolic macros |top_mark|, etc. The value of |top_mark(x)|, etc.
-is either |null| or a pointer to the reference count of a token list.
-
-The variable |biggest_used_mark| is an aid to try and keep the code
-somehwat efficient without too much extra work: it registers the
-highest mark class ever instantiated by the user, so the loops
-in |fire_up| and |vsplit| do not have to traverse the full range
-|0..biggest_mark|.
-
-@c
-halfword top_marks_array[(biggest_mark + 1)];
-halfword first_marks_array[(biggest_mark + 1)];
-halfword bot_marks_array[(biggest_mark + 1)];
-halfword split_first_marks_array[(biggest_mark + 1)];
-halfword split_bot_marks_array[(biggest_mark + 1)];
-halfword biggest_used_mark;
-
-@ @c
-void initialize_marks(void)
-{
- int i;
- biggest_used_mark = 0;
- for (i = 0; i <= biggest_mark; i++) {
- top_mark(i) = null;
- first_mark(i) = null;
- bot_mark(i) = null;
- split_first_mark(i) = null;
- split_bot_mark(i) = null;
- }
-}
-
-
-@ Now let's consider |macro_call| itself, which is invoked when \TeX\ is
-scanning a control sequence whose |cur_cmd| is either |call|, |long_call|,
-|outer_call|, or |long_outer_call|. The control sequence definition
-appears in the token list whose reference count is in location |cur_chr|
-of |mem|.
-
-The global variable |long_state| will be set to |call| or to |long_call|,
-depending on whether or not the control sequence disallows \.{\\par}
-in its parameters. The |get_next| routine will set |long_state| to
-|outer_call| and emit \.{\\par}, if a file ends or if an \.{\\outer}
-control sequence occurs in the midst of an argument.
-
-@c
-int long_state; /* governs the acceptance of \.{\\par} */
-
-@ The parameters, if any, must be scanned before the macro is expanded.
-Parameters are token lists without reference counts. They are placed on
-an auxiliary stack called |pstack| while they are being scanned, since
-the |param_stack| may be losing entries during the matching process.
-(Note that |param_stack| can't be gaining entries, since |macro_call| is
-the only routine that puts anything onto |param_stack|, and it
-is not recursive.)
-
-@c
-halfword pstack[9]; /* arguments supplied to a macro */
-
-
-@ After parameter scanning is complete, the parameters are moved to the
-|param_stack|. Then the macro body is fed to the scanner; in other words,
-|macro_call| places the defined text of the control sequence at the
-top of\/ \TeX's input stack, so that |get_next| will proceed to read it
-next.
-
-The global variable |cur_cs| contains the |eqtb| address of the control sequence
-being expanded, when |macro_call| begins. If this control sequence has not been
-declared \.{\\long}, i.e., if its command code in the |eq_type| field is
-not |long_call| or |long_outer_call|, its parameters are not allowed to contain
-the control sequence \.{\\par}. If an illegal \.{\\par} appears, the macro
-call is aborted, and the \.{\\par} will be rescanned.
-
-@c
-void macro_call(void)
-{ /* invokes a user-defined control sequence */
- halfword r; /* current node in the macro's token list */
- halfword p = null; /* current node in parameter token list being built */
- halfword q; /* new node being put into the token list */
- halfword s; /* backup pointer for parameter matching */
- halfword t; /* cycle pointer for backup recovery */
- halfword u, v; /* auxiliary pointers for backup recovery */
- halfword rbrace_ptr = null; /* one step before the last |right_brace| token */
- int n = 0; /* the number of parameters scanned */
- halfword unbalance; /* unmatched left braces in current parameter */
- halfword m = 0; /* the number of tokens or groups (usually) */
- halfword ref_count; /* start of the token list */
- int save_scanner_status = scanner_status; /* |scanner_status| upon entry */
- halfword save_warning_index = warning_index; /* |warning_index| upon entry */
- int match_chr = 0; /* character used in parameter */
- warning_index = cur_cs;
- ref_count = cur_chr;
- r = token_link(ref_count);
- if (tracing_macros_par > 0) {
- /* Show the text of the macro being expanded */
- begin_diagnostic();
- print_ln();
- print_cs(warning_index);
- token_show(ref_count);
- end_diagnostic(false);
- }
- if (token_info(r) == protected_token)
- r = token_link(r);
- if (token_info(r) != end_match_token) {
- /* Scan the parameters and make |link(r)| point to the macro body; but
- |return| if an illegal \.{\\par} is detected */
- /* At this point, the reader will find it advisable to review the explanation
- of token list format that was presented earlier, since many aspects of that
- format are of importance chiefly in the |macro_call| routine.
-
- The token list might begin with a string of compulsory tokens before the
- first |match| or |end_match|. In that case the macro name is supposed to be
- followed by those tokens; the following program will set |s=null| to
- represent this restriction. Otherwise |s| will be set to the first token of
- a string that will delimit the next parameter.
- */
-
- scanner_status = matching;
- unbalance = 0;
- long_state = eq_type(cur_cs);
- if (long_state >= outer_call_cmd)
- long_state = long_state - 2;
- do {
- set_token_link(temp_token_head, null);
- if ((token_info(r) >= end_match_token)
- || (token_info(r) < match_token)) {
- s = null;
- } else {
- match_chr = token_info(r) - match_token;
- s = token_link(r);
- r = s;
- p = temp_token_head;
- m = 0;
- }
- /* Scan a parameter until its delimiter string has been found; or, if |s=null|,
- simply scan the delimiter string; */
-
- /* If |info(r)| is a |match| or |end_match| command, it cannot be equal to
- any token found by |get_token|. Therefore an undelimited parameter---i.e.,
- a |match| that is immediately followed by |match| or |end_match|---will
- always fail the test `|cur_tok=info(r)|' in the following algorithm. */
- CONTINUE:
- get_token(); /* set |cur_tok| to the next token of input */
- if (cur_tok == token_info(r)) {
- /* Advance |r|; |goto found| if the parameter delimiter has been
- fully matched, otherwise |goto continue| */
- /* A slightly subtle point arises here: When the parameter delimiter ends
- with `\.{\#\{}', the token list will have a left brace both before and
- after the |end_match|\kern-.4pt. Only one of these should affect the
- |align_state|, but both will be scanned, so we must make a correction.
- */
- r = token_link(r);
- if ((token_info(r) >= match_token)
- && (token_info(r) <= end_match_token)) {
- if (cur_tok < left_brace_limit)
- decr(align_state);
- goto FOUND;
- } else {
- goto CONTINUE;
- }
-
- }
- /* Contribute the recently matched tokens to the current parameter, and
- |goto continue| if a partial match is still in effect; but abort if |s=null| */
-
- /* When the following code becomes active, we have matched tokens from |s| to
- the predecessor of |r|, and we have found that |cur_tok<>info(r)|. An
- interesting situation now presents itself: If the parameter is to be
- delimited by a string such as `\.{ab}', and if we have scanned `\.{aa}',
- we want to contribute one `\.a' to the current parameter and resume
- looking for a `\.b'. The program must account for such partial matches and
- for others that can be quite complex. But most of the time we have |s=r|
- and nothing needs to be done.
-
- Incidentally, it is possible for \.{\\par} tokens to sneak in to certain
- parameters of non-\.{\\long} macros. For example, consider a case like
- `\.{\\def\\a\#1\\par!\{...\}}' where the first \.{\\par} is not followed
- by an exclamation point. In such situations it does not seem appropriate
- to prohibit the \.{\\par}, so \TeX\ keeps quiet about this bending of
- the rules. */
-
- if (s != r) {
- if (s == null) {
- /* Report an improper use of the macro and abort */
- print_err("Use of ");
- sprint_cs(warning_index);
- tprint(" doesn't match its definition");
- help4
- ("If you say, e.g., `\\def\\a1{...}', then you must always",
- "put `1' after `\\a', since control sequence names are",
- "made up of letters only. The macro here has not been",
- "followed by the required stuff, so I'm ignoring it.");
- error();
- goto EXIT;
-
- } else {
- t = s;
- do {
- store_new_token(token_info(t));
- incr(m);
- u = token_link(t);
- v = s;
- while (1) {
- if (u == r) {
- if (cur_tok != token_info(v)) {
- goto DONE;
- } else {
- r = token_link(v);
- goto CONTINUE;
- }
- }
- if (token_info(u) != token_info(v))
- goto DONE;
- u = token_link(u);
- v = token_link(v);
- }
- DONE:
- t = token_link(t);
- } while (t != r);
- r = s; /* at this point, no tokens are recently matched */
- }
- }
-
- if (cur_tok == par_token)
- if (long_state != long_call_cmd)
- if (!suppress_long_error_par) {
- goto RUNAWAY;
- }
- if (cur_tok < right_brace_limit) {
- if (cur_tok < left_brace_limit) {
- /* Contribute an entire group to the current parameter */
- unbalance = 1;
- while (1) {
- fast_store_new_token(cur_tok);
- get_token();
- if (cur_tok == par_token) {
- if (long_state != long_call_cmd) {
- if (!suppress_long_error_par) {
- goto RUNAWAY;
-
- }
- }
- }
- if (cur_tok < right_brace_limit) {
- if (cur_tok < left_brace_limit) {
- incr(unbalance);
- } else {
- decr(unbalance);
- if (unbalance == 0)
- break;
- }
- }
- }
- rbrace_ptr = p;
- store_new_token(cur_tok);
-
- } else {
- /* Report an extra right brace and |goto continue| */
- back_input();
- print_err("Argument of ");
- sprint_cs(warning_index);
- tprint(" has an extra }");
- help6
- ("I've run across a `}' that doesn't seem to match anything.",
- "For example, `\\def\\a#1{...}' and `\\a}' would produce",
- "this error. If you simply proceed now, the `\\par' that",
- "I've just inserted will cause me to report a runaway",
- "argument that might be the root of the problem. But if",
- "your `}' was spurious, just type `2' and it will go away.");
- incr(align_state);
- long_state = call_cmd;
- cur_tok = par_token;
- ins_error();
- goto CONTINUE;
- /* a white lie; the \.{\\par} won't always trigger a runaway */
- }
- } else {
- /* Store the current token, but |goto continue| if it is
- a blank space that would become an undelimited parameter */
- if (cur_tok == space_token)
- if (token_info(r) <= end_match_token)
- if (token_info(r) >= match_token)
- goto CONTINUE;
- store_new_token(cur_tok);
-
- }
- incr(m);
- if (token_info(r) > end_match_token)
- goto CONTINUE;
- if (token_info(r) < match_token)
- goto CONTINUE;
- FOUND:
- if (s != null) {
- /* Tidy up the parameter just scanned, and tuck it away */
- /* If the parameter consists of a single group enclosed in braces, we must
- strip off the enclosing braces. That's why |rbrace_ptr| was introduced. */
- if ((m == 1) && (token_info(p) < right_brace_limit)
- && (p != temp_token_head)) {
- set_token_link(rbrace_ptr, null);
- free_avail(p);
- p = token_link(temp_token_head);
- pstack[n] = token_link(p);
- free_avail(p);
- } else {
- pstack[n] = token_link(temp_token_head);
- }
- incr(n);
- if (tracing_macros_par > 0) {
- begin_diagnostic();
- print_nl(match_chr);
- print_int(n);
- tprint("<-");
- show_token_list(pstack[n - 1], null, 1000);
- end_diagnostic(false);
- }
-
- }
-
- /* now |info(r)| is a token whose command code is either |match| or |end_match| */
- } while (token_info(r) != end_match_token);
-
- }
- /* Feed the macro body and its parameters to the scanner */
- /* Before we put a new token list on the input stack, it is wise to clean off
- all token lists that have recently been depleted. Then a user macro that ends
- with a call to itself will not require unbounded stack space. */
- while ((istate == token_list) && (iloc == null) && (token_type != v_template)) {
- /* conserve stack space */
- end_token_list();
- }
- begin_token_list(ref_count, macro);
- iname = warning_index;
- iloc = token_link(r);
- if (n > 0) {
- if (param_ptr + n > max_param_stack) {
- max_param_stack = param_ptr + n;
- if (max_param_stack > param_size)
- overflow("parameter stack size", (unsigned) param_size);
- }
- for (m = 0; m <= n - 1; m++)
- param_stack[param_ptr + m] = pstack[m];
- param_ptr = param_ptr + n;
- }
- goto EXIT;
- RUNAWAY:
- /* Report a runaway argument and abort */
- /* If |long_state=outer_call|, a runaway argument has already been reported. */
- if (long_state == call_cmd) {
- runaway();
- print_err("Paragraph ended before ");
- sprint_cs(warning_index);
- tprint(" was complete");
- help3("I suspect you've forgotten a `}', causing me to apply this",
- "control sequence to too much text. How can we recover?",
- "My plan is to forget the whole thing and hope for the best.");
- back_error();
- }
- pstack[n] = token_link(temp_token_head);
- align_state = align_state - unbalance;
- for (m = 0; m <= n; m++)
- flush_list(pstack[m]);
-
- EXIT:
- scanner_status = save_scanner_status;
- warning_index = save_warning_index;
-}