% inputstack.w % Copyright 2009-2010 Taco Hoekwater % 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 . @ @c #include "ptexlib.h" static const char _svn_version[] = "$Id: inputstack.w 3849 2010-09-01 09:10:48Z taco $ " "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.70.1/source/texk/web2c/luatexdir/tex/inputstack.w $"; @ @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 */ in_state_record cur_input; /* the ``top'' input state */ int in_open = 0; /* the number of lines in the buffer, less one */ int open_parens = 0; /* the number of open text files */ alpha_file *input_file = NULL; int line = 0; /* current line number in the current source file */ int *line_stack = NULL; str_number *source_filename_stack = NULL; char **full_source_filename_stack = NULL; 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 */ if (scanner_status > skipping) { switch (scanner_status) { case defining: tprint_nl("Runaway definition"); p = def_ref; break; case matching: tprint_nl("Runaway argument"); p = temp_token_head; break; case aligning: tprint_nl("Runaway preamble"); p = hold_token_head; break; case absorbing: tprint_nl("Runaway text"); p = def_ref; break; default: /* there are no other cases */ break; } print_char('?'); print_ln(); show_token_list(token_link(p), null, error_line - 10); } } @ The |param_stack| is an auxiliary array used to hold pointers to the token lists for parameters at the current level and subsidiary levels of input. This stack is maintained with convention (2), and it grows at a different rate from the others. @c pointer *param_stack = NULL; /* token list pointers for parameters */ int param_ptr = 0; /* first unused entry in |param_stack| */ int max_param_stack = 0; /* largest value of |param_ptr|, will be |<=param_size+9| */ @ The input routines must also interact with the processing of \.{\\halign} and \.{\\valign}, since the appearance of tab marks and \.{\\cr} in certain places is supposed to trigger the beginning of special $v_j$ template text in the scanner. This magic is accomplished by an |align_state| variable that is increased by~1 when a `\.{\char'173}' is scanned and decreased by~1 when a `\.{\char'175}' is scanned. The |align_state| is nonzero during the $u_j$ template, after which it is set to zero; the $v_j$ template begins when a tab mark or \.{\\cr} occurs at a time that |align_state=0|. @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 print out the current input state on all levels down to the most recent line of characters from an input file, illustrates most of these conventions. The global variable |base_ptr| contains the lowest level that was displayed by this procedure. @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 contains at most |half_error_line| characters, and the second contains at most |error_line|. Non-current input levels whose |token_type| is `|backed_up|' are shown only if they have not been fully read. @c static void print_token_list_type(int t) { switch (t) { case parameter: tprint_nl(" "); break; case u_template: case v_template: tprint_nl("