3
% Copyright 2009-2010 Taco Hoekwater <taco@@luatex.org>
5
% This file is part of LuaTeX.
7
% LuaTeX is free software; you can redistribute it and/or modify it under
8
% the terms of the GNU General Public License as published by the Free
9
% Software Foundation; either version 2 of the License, or (at your
10
% option) any later version.
12
% LuaTeX is distributed in the hope that it will be useful, but WITHOUT
13
% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15
% License for more details.
17
% You should have received a copy of the GNU General Public License along
18
% with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
23
static const char _svn_version[] =
24
"$Id: inputstack.w 3612 2010-04-13 09:29:42Z taco $ "
25
"$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.60.1/source/texk/web2c/luatexdir/tex/inputstack.w $";
28
#define end_line_char int_par(end_line_char_code)
29
#define error_context_lines int_par(error_context_lines_code)
32
in_state_record *input_stack = NULL;
33
int input_ptr = 0; /* first unused location of |input_stack| */
34
int max_in_stack = 0; /* largest value of |input_ptr| when pushing */
35
in_state_record cur_input; /* the ``top'' input state */
38
int in_open = 0; /* the number of lines in the buffer, less one */
39
int open_parens = 0; /* the number of open text files */
40
alpha_file *input_file = NULL;
41
int line = 0; /* current line number in the current source file */
42
int *line_stack = NULL;
43
str_number *source_filename_stack = NULL;
44
char **full_source_filename_stack = NULL;
47
int scanner_status = 0; /* can a subfile end now? */
48
pointer warning_index = null; /* identifier relevant to non-|normal| scanner status */
49
pointer def_ref = null; /* reference count of token list being defined */
53
@ Here is a procedure that uses |scanner_status| to print a warning message
54
when a subfile has ended, and at certain other crucial times:
59
pointer p = null; /* head of runaway list */
60
if (scanner_status > skipping) {
61
switch (scanner_status) {
63
tprint_nl("Runaway definition");
67
tprint_nl("Runaway argument");
71
tprint_nl("Runaway preamble");
75
tprint_nl("Runaway text");
78
default: /* there are no other cases */
83
show_token_list(token_link(p), null, error_line - 10);
88
@ The |param_stack| is an auxiliary array used to hold pointers to the token
89
lists for parameters at the current level and subsidiary levels of input.
90
This stack is maintained with convention (2), and it grows at a different
94
pointer *param_stack = NULL; /* token list pointers for parameters */
95
int param_ptr = 0; /* first unused entry in |param_stack| */
96
int max_param_stack = 0; /* largest value of |param_ptr|, will be |<=param_size+9| */
98
@ The input routines must also interact with the processing of
99
\.{\\halign} and \.{\\valign}, since the appearance of tab marks and
100
\.{\\cr} in certain places is supposed to trigger the beginning of special
101
$v_j$ template text in the scanner. This magic is accomplished by an
102
|align_state| variable that is increased by~1 when a `\.{\char'173}' is
103
scanned and decreased by~1 when a `\.{\char'175}' is scanned. The |align_state|
104
is nonzero during the $u_j$ template, after which it is set to zero; the
105
$v_j$ template begins when a tab mark or \.{\\cr} occurs at a time that
109
int align_state = 0; /* group level with respect to current alignment */
112
@ Thus, the ``current input state'' can be very complicated indeed; there
113
can be many levels and each level can arise in a variety of ways. The
114
|show_context| procedure, which is used by \TeX's error-reporting routine to
115
print out the current input state on all levels down to the most recent
116
line of characters from an input file, illustrates most of these conventions.
117
The global variable |base_ptr| contains the lowest level that was
118
displayed by this procedure.
121
int base_ptr = 0; /* shallowest level shown by |show_context| */
124
@ The status at each level is indicated by printing two lines, where the first
125
line indicates what was read so far and the second line shows what remains
126
to be read. The context is cropped, if necessary, so that the first line
127
contains at most |half_error_line| characters, and the second contains
128
at most |error_line|. Non-current input levels whose |token_type| is
129
`|backed_up|' are shown only if they have not been fully read.
132
static void print_token_list_type(int t)
136
tprint_nl("<argument> ");
140
tprint_nl("<template> ");
144
tprint_nl("<recently read> ");
146
tprint_nl("<to be read again> ");
149
tprint_nl("<inserted text> ");
156
tprint_nl("<output> ");
159
tprint_nl("<everypar> ");
161
case every_math_text:
162
tprint_nl("<everymath> ");
164
case every_display_text:
165
tprint_nl("<everydisplay> ");
167
case every_hbox_text:
168
tprint_nl("<everyhbox> ");
170
case every_vbox_text:
171
tprint_nl("<everyvbox> ");
174
tprint_nl("<everyjob> ");
177
tprint_nl("<everycr> ");
180
tprint_nl("<mark> ");
183
tprint_nl("<everyeof> ");
186
tprint_nl("<write> ");
190
break; /* this should never happen */
195
@ Here it is necessary to explain a little trick. We don't want to store a long
196
string that corresponds to a token list, because that string might take up
197
lots of memory; and we are printing during a time when an error message is
198
being given, so we dare not do anything that might overflow one of \TeX's
199
tables. So `pseudoprinting' is the answer: We enter a mode of printing
200
that stores characters into a buffer of length |error_line|, where character
201
$k+1$ is placed into \hbox{|trick_buf[k mod error_line]|} if
202
|k<trick_count|, otherwise character |k| is dropped. Initially we set
203
|tally:=0| and |trick_count:=1000000|; then when we reach the
204
point where transition from line 1 to line 2 should occur, we
205
set |first_count:=tally| and |trick_count:=@tmax@>(error_line,
206
tally+1+error_line-half_error_line)|. At the end of the
207
pseudoprinting, the values of |first_count|, |tally|, and
208
|trick_count| give us all the information we need to print the two lines,
209
and all of the necessary text is in |trick_buf|.
211
Namely, let |l| be the length of the descriptive information that appears
212
on the first line. The length of the context information gathered for that
213
line is |k=first_count|, and the length of the context information
214
gathered for line~2 is $m=\min(|tally|, |trick_count|)-k$. If |l+k<=h|,
215
where |h=half_error_line|, we print |trick_buf[0..k-1]| after the
216
descriptive information on line~1, and set |n:=l+k|; here |n| is the
217
length of line~1. If $l+k>h$, some cropping is necessary, so we set |n:=h|
218
and print `\.{...}' followed by
219
$$\hbox{|trick_buf[(l+k-h+3)..k-1]|,}$$
220
where subscripts of |trick_buf| are circular modulo |error_line|. The
221
second line consists of |n|~spaces followed by |trick_buf[k..(k+m-1)]|,
222
unless |n+m>error_line|; in the latter case, further cropping is done.
223
This is easier to program than to explain.
227
@ The following code sets up the print routines so that they will gather
228
the desired information.
231
void set_trick_count(void)
234
trick_count = tally + 1 + error_line - half_error_line;
235
if (trick_count < error_line)
236
trick_count = error_line;
239
#define begin_pseudoprint() do { \
240
l=tally; tally=0; selector=pseudo; \
241
trick_count=1000000; \
244
#define PSEUDO_PRINT_THE_LINE() do { \
245
begin_pseudoprint(); \
246
if (buffer[ilimit]==end_line_char) j=ilimit; \
247
else j=ilimit+1; /* determine the effective end of the line */ \
249
for (i=istart;i<=j-1;i++) { \
250
if (i==iloc) set_trick_count(); \
251
print_char(buffer[i]); \
257
void show_context(void)
258
{ /* prints where the scanner is */
259
int old_setting; /* saved |selector| setting */
260
int nn; /* number of contexts shown so far, less one */
261
boolean bottom_line; /* have we reached the final context to be shown? */
262
int i; /* index into |buffer| */
263
int j; /* end of current line in |buffer| */
264
int l; /* length of descriptive information on line 1 */
265
int m; /* context information gathered for line 2 */
266
int n; /* length of line 1 */
267
int p; /* starting or ending place in |trick_buf| */
268
int q; /* temporary index */
270
base_ptr = input_ptr;
271
input_stack[base_ptr] = cur_input;
272
/* store current state */
276
cur_input = input_stack[base_ptr]; /* enter into the context */
277
if (istate != token_list) {
278
if ((iname > 21) || (base_ptr == 0))
281
if ((base_ptr == input_ptr) || bottom_line
282
|| (nn < error_context_lines)) {
283
/* Display the current context */
284
if ((base_ptr == input_ptr) || (istate != token_list) ||
285
(token_type != backed_up) || (iloc != null)) {
286
/* we omit backed-up token lists that have already been read */
287
tally = 0; /* get ready to count characters */
288
old_setting = selector;
289
if (current_ocp_lstack > 0) {
290
tprint_nl("OCP stack ");
291
print_scaled(current_ocp_lstack);
293
print_int(current_ocp_no);
295
PSEUDO_PRINT_THE_LINE();
296
} else if (istate != token_list) {
297
/* Print location of current line */
299
This routine should be changed, if necessary, to give the best possible
300
indication of where the current line resides in the input file.
301
For example, on some systems it is best to print both a page and line number.
304
if (terminal_input) {
308
tprint_nl("<insert> ");
314
print_int(iname - 1);
317
} else if (iindex != in_open) { /* input from a pseudo file */
319
print_int(line_stack[iindex + 1]);
325
PSEUDO_PRINT_THE_LINE();
327
print_token_list_type(token_type);
330
if (token_type < macro)
331
show_token_list(istart, iloc, 100000);
333
show_token_list(token_link(istart), iloc, 100000); /* avoid reference count */
335
selector = old_setting; /* stop pseudoprinting */
336
/* Print two lines using the tricky pseudoprinted information */
337
if (trick_count == 1000000)
339
/* |set_trick_count| must be performed */
340
if (tally < trick_count)
341
m = tally - first_count;
343
m = trick_count - first_count; /* context on line 2 */
344
if (l + first_count <= half_error_line) {
349
p = l + first_count - half_error_line + 3;
352
for (q = p; q <= first_count - 1; q++)
353
print_char(trick_buf[(q % error_line)]);
355
for (q = 1; q <= n; q++)
356
print_char(' '); /* print |n| spaces to begin line~2 */
357
if (m + n <= error_line)
360
p = first_count + (error_line - n - 3);
361
for (q = first_count; q <= p - 1; q++)
362
print_char(trick_buf[(q % error_line)]);
363
if (m + n > error_line)
368
} else if (nn == error_context_lines) {
370
incr(nn); /* omitted if |error_context_lines<0| */
376
cur_input = input_stack[input_ptr]; /* restore original state */
380
@ The following subroutines change the input status in commonly needed ways.
382
First comes |push_input|, which stores the current state and creates a
383
new level (having, initially, the same properties as the old).
386
/* enter a new input level, save the old */
388
void push_input(void)
390
if (input_ptr > max_in_stack) {
391
max_in_stack = input_ptr;
392
if (input_ptr == stack_size)
393
overflow("input stack size", (unsigned) stack_size);
395
input_stack[input_ptr] = cur_input; /* stack the record */
401
Here is a procedure that starts a new level of token-list input, given
402
a token list |p| and its type |t|. If |t=macro|, the calling routine should
403
set |name| and |loc|.
406
void begin_token_list(halfword p, quarterword t)
411
token_type = (unsigned char) t;
412
if (t >= macro) { /* the token list starts with a reference count */
415
param_start = param_ptr;
417
iloc = token_link(p);
418
if (int_par(tracing_macros_code) > 1) {
423
else if (t == write_text)
426
print_cmd_chr(assign_toks_cmd,
427
t - output_text + output_routine_loc);
430
end_diagnostic(false);
439
@ When a token list has been fully scanned, the following computations
440
should be done as we leave that level of input. The |token_type| tends
441
to be equal to either |backed_up| or |inserted| about 2/3 of the time.
445
void end_token_list(void)
446
{ /* leave a token-list input level */
447
if (token_type >= backed_up) { /* token list to be deleted */
448
if (token_type <= inserted) {
451
delete_token_ref(istart); /* update reference count */
452
if (token_type == macro) { /* parameters must be flushed */
453
while (param_ptr > param_start) {
455
flush_list(param_stack[param_ptr]);
459
} else if (token_type == u_template) {
460
if (align_state > 500000)
463
fatal_error("(interwoven alignment preambles are not allowed)");
470
@ Sometimes \TeX\ has read too far and wants to ``unscan'' what it has
471
seen. The |back_input| procedure takes care of this by putting the token
472
just scanned back into the input stream, ready to be read again. This
473
procedure can be used only if |cur_tok| represents the token to be
474
replaced. Some applications of \TeX\ use this procedure a lot,
475
so it has been slightly optimized for speed.
479
void back_input(void)
480
{ /* undoes one token of input */
481
halfword p; /* a token list of length one */
482
while ((istate == token_list) && (iloc == null)
483
&& (token_type != v_template))
484
end_token_list(); /* conserve stack space */
486
set_token_info(p, cur_tok);
487
if (cur_tok < right_brace_limit) {
488
if (cur_tok < left_brace_limit)
496
token_type = backed_up;
497
iloc = p; /* that was |back_list(p)|, without procedure overhead */
500
@ Insert token |p| into \TeX's input
502
int reinsert_token(boolean a, halfword pp)
510
set_token_info(p, cur_tok);
511
set_token_link(p, iloc);
514
if (cur_tok < right_brace_limit) {
515
if (cur_tok < left_brace_limit)
522
a = true; /* etex is always on */
529
@ The |begin_file_reading| procedure starts a new level of input for lines
530
of characters to be read from a file, or as an insertion from the
531
terminal. It does not take care of opening the file, nor does it set |loc|
532
or |limit| or |line|.
533
@^system dependencies@>
536
void begin_file_reading(void)
538
if (in_open == max_in_open)
539
overflow("text input levels", (unsigned) max_in_open);
540
if (first == buf_size)
541
check_buffer_overflow(first);
544
iindex = (unsigned char) in_open;
545
source_filename_stack[iindex] = 0;
546
full_source_filename_stack[iindex] = NULL;
547
eof_seen[iindex] = false;
548
grp_stack[iindex] = cur_boundary;
549
if_stack[iindex] = cond_ptr;
550
line_stack[iindex] = line;
553
iname = 0; /* |terminal_input| is now |true| */
554
line_catcode_table = DEFAULT_CAT_TABLE;
555
line_partial = false;
556
/* Prepare terminal input {\sl Sync\TeX} information */
561
@ Conversely, the variables must be downdated when such a level of input
565
void end_file_reading(void)
568
line = line_stack[iindex];
569
if ((iname >= 18) && (iname <= 20))
571
else if (iname == 21)
572
luacstring_close(iindex);
574
lua_a_close_in(cur_file, 0); /* forget it */
580
@ In order to keep the stack from overflowing during a long sequence of
581
inserted `\.{\\show}' commands, the following routine removes completed
582
error-inserted lines from memory.
585
void clear_for_error_prompt(void)
587
while ((istate != token_list) && terminal_input
588
&& (input_ptr > 0) && (iloc > ilimit))
594
@ To get \TeX's whole input mechanism going, we perform the following
598
void initialize_inputstack(void)
602
source_filename_stack[0] = 0;
604
full_source_filename_stack[0] = NULL;
617
} while (first != 0);
618
scanner_status = normal;
619
warning_index = null;
626
current_ocp_lstack = 0;
631
line_catcode_table = DEFAULT_CAT_TABLE;
632
line_partial = false;
633
align_state = 1000000;
634
if (!init_terminal())
635
exit(EXIT_FAILURE); /* |goto final_end|; */
637
first = last + 1; /* |init_terminal| has set |loc| and |last| */
643
@ The global variable |pseudo_files| is used to maintain a stack of
644
pseudo files. The |pseudo_lines| field of each pseudo file points to
645
a linked list of variable size nodes representing lines not yet
646
processed: the |subtype| field contains the size of this node,
647
all the following words contain ASCII codes.
650
halfword pseudo_files; /* stack of pseudo files */
652
static halfword string_to_pseudo(str_number str, int nl)
654
halfword i, r, q = null;
658
halfword h = new_node(pseudo_file_node, 0);
659
unsigned char *s = str_string(str);
660
len = (unsigned) str_length(str);
663
unsigned m = l; /* start of current line */
664
while ((l < len) && (s[l] != nl))
666
sz = (int) (l - m + 7) / 4;
669
r = new_node(pseudo_line_node, sz);
676
varmem[++i].qqqq = w;
678
w.b0 = (quarterword) (l > m ? s[m++] : ' ');
679
w.b1 = (quarterword) (l > m ? s[m++] : ' ');
680
w.b2 = (quarterword) (l > m ? s[m++] : ' ');
681
w.b3 = (quarterword) (l > m ? s[m] : ' ');
682
varmem[++i].qqqq = w;
683
if (pseudo_lines(h) == null) {
697
@ The |pseudo_start| procedure initiates reading from a pseudo file.
700
void pseudo_from_string(void)
702
str_number s; /* string to be converted into a pseudo file */
703
halfword p; /* for list construction */
705
/* Convert string |s| into a new pseudo file */
706
p = string_to_pseudo(s, int_par(new_line_char_code));
707
vlink(p) = pseudo_files;
710
/* Initiate input from new pseudo file */
711
begin_file_reading(); /* set up |cur_file| and new level of input */
714
iloc = ilimit + 1; /* force line read */
715
if (int_par(tracing_scan_tokens_code) > 0) {
716
if (term_offset > max_print_line - 3)
718
else if ((term_offset > 0) || (file_offset > 0))
727
/* Prepare pseudo file {\sl Sync\TeX} information */
731
void pseudo_start(void)
733
int old_setting; /* holds |selector| setting */
735
old_setting = selector;
736
selector = new_string;
737
token_show(temp_token_head);
738
selector = old_setting;
739
flush_list(token_link(temp_token_head));
741
pseudo_from_string();
745
void lua_string_start(void)
747
begin_file_reading(); /* set up |cur_file| and new level of input */
750
iloc = ilimit + 1; /* force line read */
752
luacstring_start(iindex);
755
@ Here we read a line from the current pseudo file into |buffer|.
758
boolean pseudo_input(void)
759
{ /* inputs the next line or returns |false| */
760
halfword p; /* current line from pseudo file */
761
int sz; /* size of node |p| */
762
four_quarters w; /* four ASCII codes */
763
halfword r; /* loop index */
764
last = first; /* cf.\ Matthew 19\thinspace:\thinspace30 */
765
p = pseudo_lines(pseudo_files);
769
pseudo_lines(pseudo_files) = vlink(p);
771
if (4 * sz - 3 >= buf_size - last)
772
check_buffer_overflow(last + 4 * sz);
774
for (r = p + 1; r <= p + sz - 1; r++) {
776
buffer[last] = (packed_ASCII_code) w.b0;
777
buffer[last + 1] = (packed_ASCII_code) w.b1;
778
buffer[last + 2] = (packed_ASCII_code) w.b2;
779
buffer[last + 3] = (packed_ASCII_code) w.b3;
782
if (last >= max_buf_stack)
783
max_buf_stack = last + 1;
784
while ((last > first) && (buffer[last - 1] == ' '))
791
@ When we are done with a pseudo file we `close' it
794
void pseudo_close(void)
795
{ /* close the top level pseudo file */
797
p = vlink(pseudo_files);
798
flush_node(pseudo_files);