~ubuntu-branches/ubuntu/wily/luatex/wily

« back to all changes in this revision

Viewing changes to source/texk/web2c/luatexdir/tex/inputstack.w

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Preining
  • Date: 2010-04-29 00:47:19 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20100429004719-o42etkqe90n97b9e
Tags: 0.60.1-1
* new upstream release, adapt build-script patch
* disable patch: upstream-epstopdf_cc_no_xpdf_patching, included upstream
* disable patch: libpoppler-0.12, not needed anymore

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
% inputstack.w
 
2
 
 
3
% Copyright 2009-2010 Taco Hoekwater <taco@@luatex.org>
 
4
 
 
5
% This file is part of LuaTeX.
 
6
 
 
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.
 
11
 
 
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.
 
16
 
 
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/>. 
 
19
 
 
20
@ @c
 
21
#include "ptexlib.h"
 
22
 
 
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 $";
 
26
 
 
27
@ @c
 
28
#define end_line_char int_par(end_line_char_code)
 
29
#define error_context_lines int_par(error_context_lines_code)
 
30
 
 
31
 
 
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 */
 
36
 
 
37
 
 
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;
 
45
 
 
46
 
 
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 */
 
50
 
 
51
 
 
52
 
 
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:
 
55
 
 
56
@c
 
57
void runaway(void)
 
58
{
 
59
    pointer p = null;           /* head of runaway list */
 
60
    if (scanner_status > skipping) {
 
61
        switch (scanner_status) {
 
62
        case defining:
 
63
            tprint_nl("Runaway definition");
 
64
            p = def_ref;
 
65
            break;
 
66
        case matching:
 
67
            tprint_nl("Runaway argument");
 
68
            p = temp_token_head;
 
69
            break;
 
70
        case aligning:
 
71
            tprint_nl("Runaway preamble");
 
72
            p = hold_token_head;
 
73
            break;
 
74
        case absorbing:
 
75
            tprint_nl("Runaway text");
 
76
            p = def_ref;
 
77
            break;
 
78
        default:               /* there are no other cases */
 
79
            break;
 
80
        }
 
81
        print_char('?');
 
82
        print_ln();
 
83
        show_token_list(token_link(p), null, error_line - 10);
 
84
    }
 
85
}
 
86
 
 
87
 
 
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
 
91
rate from the others.
 
92
 
 
93
@c
 
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| */
 
97
 
 
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
 
106
|align_state=0|.
 
107
 
 
108
@c
 
109
int align_state = 0;            /* group level with respect to current alignment */
 
110
 
 
111
 
 
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.
 
119
 
 
120
@c
 
121
int base_ptr = 0;               /* shallowest level shown by |show_context| */
 
122
 
 
123
 
 
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.
 
130
 
 
131
@c
 
132
static void print_token_list_type(int t)
 
133
{
 
134
    switch (t) {
 
135
    case parameter:
 
136
        tprint_nl("<argument> ");
 
137
        break;
 
138
    case u_template:
 
139
    case v_template:
 
140
        tprint_nl("<template> ");
 
141
        break;
 
142
    case backed_up:
 
143
        if (iloc == null)
 
144
            tprint_nl("<recently read> ");
 
145
        else
 
146
            tprint_nl("<to be read again> ");
 
147
        break;
 
148
    case inserted:
 
149
        tprint_nl("<inserted text> ");
 
150
        break;
 
151
    case macro:
 
152
        print_ln();
 
153
        print_cs(iname);
 
154
        break;
 
155
    case output_text:
 
156
        tprint_nl("<output> ");
 
157
        break;
 
158
    case every_par_text:
 
159
        tprint_nl("<everypar> ");
 
160
        break;
 
161
    case every_math_text:
 
162
        tprint_nl("<everymath> ");
 
163
        break;
 
164
    case every_display_text:
 
165
        tprint_nl("<everydisplay> ");
 
166
        break;
 
167
    case every_hbox_text:
 
168
        tprint_nl("<everyhbox> ");
 
169
        break;
 
170
    case every_vbox_text:
 
171
        tprint_nl("<everyvbox> ");
 
172
        break;
 
173
    case every_job_text:
 
174
        tprint_nl("<everyjob> ");
 
175
        break;
 
176
    case every_cr_text:
 
177
        tprint_nl("<everycr> ");
 
178
        break;
 
179
    case mark_text:
 
180
        tprint_nl("<mark> ");
 
181
        break;
 
182
    case every_eof_text:
 
183
        tprint_nl("<everyeof> ");
 
184
        break;
 
185
    case write_text:
 
186
        tprint_nl("<write> ");
 
187
        break;
 
188
    default:
 
189
        tprint_nl("?");
 
190
        break;                  /* this should never happen */
 
191
    }
 
192
}
 
193
 
 
194
 
 
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|.
 
210
 
 
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.
 
224
 
 
225
 
 
226
 
 
227
@ The following code sets up the print routines so that they will gather
 
228
the desired information.
 
229
 
 
230
@c
 
231
void set_trick_count(void)
 
232
{
 
233
    first_count = tally;
 
234
    trick_count = tally + 1 + error_line - half_error_line;
 
235
    if (trick_count < error_line)
 
236
        trick_count = error_line;
 
237
}
 
238
 
 
239
#define begin_pseudoprint() do {                \
 
240
    l=tally; tally=0; selector=pseudo;          \
 
241
    trick_count=1000000;                        \
 
242
  } while (0)
 
243
 
 
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 */      \
 
248
    if (j>0) {                                                          \
 
249
      for (i=istart;i<=j-1;i++) {                                       \
 
250
        if (i==iloc) set_trick_count();                                 \
 
251
        print_char(buffer[i]);                                          \
 
252
      }                                                                 \
 
253
    }                                                                   \
 
254
  } while (0)
 
255
 
 
256
@ @c
 
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 */
 
269
 
 
270
    base_ptr = input_ptr;
 
271
    input_stack[base_ptr] = cur_input;
 
272
    /* store current state */
 
273
    nn = -1;
 
274
    bottom_line = false;
 
275
    while (true) {
 
276
        cur_input = input_stack[base_ptr];      /* enter into the context */
 
277
        if (istate != token_list) {
 
278
            if ((iname > 21) || (base_ptr == 0))
 
279
                bottom_line = true;
 
280
        }
 
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);
 
292
                    tprint(" entry ");
 
293
                    print_int(current_ocp_no);
 
294
                    tprint(":");
 
295
                    PSEUDO_PRINT_THE_LINE();
 
296
                } else if (istate != token_list) {
 
297
                    /* Print location of current line */
 
298
                    /*
 
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.
 
302
                     */
 
303
                    if (iname <= 17) {
 
304
                        if (terminal_input) {
 
305
                            if (base_ptr == 0)
 
306
                                tprint_nl("<*>");
 
307
                            else
 
308
                                tprint_nl("<insert> ");
 
309
                        } else {
 
310
                            tprint_nl("<read ");
 
311
                            if (iname == 17)
 
312
                                print_char('*');
 
313
                            else
 
314
                                print_int(iname - 1);
 
315
                            print_char('>');
 
316
                        };
 
317
                    } else if (iindex != in_open) {     /* input from a pseudo file */
 
318
                        tprint_nl("l.");
 
319
                        print_int(line_stack[iindex + 1]);
 
320
                    } else {
 
321
                        tprint_nl("l.");
 
322
                        print_int(line);
 
323
                    }
 
324
                    print_char(' ');
 
325
                    PSEUDO_PRINT_THE_LINE();
 
326
                } else {
 
327
                    print_token_list_type(token_type);
 
328
 
 
329
                    begin_pseudoprint();
 
330
                    if (token_type < macro)
 
331
                        show_token_list(istart, iloc, 100000);
 
332
                    else
 
333
                        show_token_list(token_link(istart), iloc, 100000);      /* avoid reference count */
 
334
                }
 
335
                selector = old_setting; /* stop pseudoprinting */
 
336
                /* Print two lines using the tricky pseudoprinted information */
 
337
                if (trick_count == 1000000)
 
338
                    set_trick_count();
 
339
                /* |set_trick_count| must be performed */
 
340
                if (tally < trick_count)
 
341
                    m = tally - first_count;
 
342
                else
 
343
                    m = trick_count - first_count;      /* context on line 2 */
 
344
                if (l + first_count <= half_error_line) {
 
345
                    p = 0;
 
346
                    n = l + first_count;
 
347
                } else {
 
348
                    tprint("...");
 
349
                    p = l + first_count - half_error_line + 3;
 
350
                    n = half_error_line;
 
351
                }
 
352
                for (q = p; q <= first_count - 1; q++)
 
353
                    print_char(trick_buf[(q % error_line)]);
 
354
                print_ln();
 
355
                for (q = 1; q <= n; q++)
 
356
                    print_char(' ');    /* print |n| spaces to begin line~2 */
 
357
                if (m + n <= error_line)
 
358
                    p = first_count + m;
 
359
                else
 
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)
 
364
                    tprint("...");
 
365
 
 
366
                incr(nn);
 
367
            }
 
368
        } else if (nn == error_context_lines) {
 
369
            tprint_nl("...");
 
370
            incr(nn);           /* omitted if |error_context_lines<0| */
 
371
        }
 
372
        if (bottom_line)
 
373
            break;
 
374
        decr(base_ptr);
 
375
    }
 
376
    cur_input = input_stack[input_ptr]; /* restore original state */
 
377
}
 
378
 
 
379
 
 
380
@ The following subroutines change the input status in commonly needed ways.
 
381
 
 
382
First comes |push_input|, which stores the current state and creates a
 
383
new level (having, initially, the same properties as the old).
 
384
 
 
385
@c
 
386
/* enter a new input level, save the old */
 
387
 
 
388
void push_input(void)
 
389
{
 
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);
 
394
    }
 
395
    input_stack[input_ptr] = cur_input; /* stack the record */
 
396
    nofilter = false;
 
397
    incr(input_ptr);
 
398
}
 
399
 
 
400
 
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|.
 
404
 
 
405
@c
 
406
void begin_token_list(halfword p, quarterword t)
 
407
{
 
408
    push_input();
 
409
    istate = token_list;
 
410
    istart = p;
 
411
    token_type = (unsigned char) t;
 
412
    if (t >= macro) {           /* the token list starts with a reference count */
 
413
        add_token_ref(p);
 
414
        if (t == macro) {
 
415
            param_start = param_ptr;
 
416
        } else {
 
417
            iloc = token_link(p);
 
418
            if (int_par(tracing_macros_code) > 1) {
 
419
                begin_diagnostic();
 
420
                tprint_nl("");
 
421
                if (t == mark_text)
 
422
                    tprint_esc("mark");
 
423
                else if (t == write_text)
 
424
                    tprint_esc("write");
 
425
                else
 
426
                    print_cmd_chr(assign_toks_cmd,
 
427
                                  t - output_text + output_routine_loc);
 
428
                tprint("->");
 
429
                token_show(p);
 
430
                end_diagnostic(false);
 
431
            }
 
432
        }
 
433
    } else {
 
434
        iloc = p;
 
435
    }
 
436
}
 
437
 
 
438
 
 
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.
 
442
@^inner loop@>
 
443
 
 
444
@c
 
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) {
 
449
            flush_list(istart);
 
450
        } else {
 
451
            delete_token_ref(istart);   /* update reference count */
 
452
            if (token_type == macro) {  /* parameters must be flushed */
 
453
                while (param_ptr > param_start) {
 
454
                    decr(param_ptr);
 
455
                    flush_list(param_stack[param_ptr]);
 
456
                }
 
457
            }
 
458
        }
 
459
    } else if (token_type == u_template) {
 
460
        if (align_state > 500000)
 
461
            align_state = 0;
 
462
        else
 
463
            fatal_error("(interwoven alignment preambles are not allowed)");
 
464
    }
 
465
    pop_input();
 
466
    check_interrupt();
 
467
}
 
468
 
 
469
 
 
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.
 
476
@^inner loop@>
 
477
 
 
478
@c
 
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 */
 
485
    p = get_avail();
 
486
    set_token_info(p, cur_tok);
 
487
    if (cur_tok < right_brace_limit) {
 
488
        if (cur_tok < left_brace_limit)
 
489
            decr(align_state);
 
490
        else
 
491
            incr(align_state);
 
492
    }
 
493
    push_input();
 
494
    istate = token_list;
 
495
    istart = p;
 
496
    token_type = backed_up;
 
497
    iloc = p;                   /* that was |back_list(p)|, without procedure overhead */
 
498
}
 
499
 
 
500
@ Insert token |p| into \TeX's input 
 
501
@c
 
502
int reinsert_token(boolean a, halfword pp)
 
503
{
 
504
    halfword t;
 
505
    t = cur_tok;
 
506
    cur_tok = pp;
 
507
    if (a) {
 
508
        halfword p;
 
509
        p = get_avail();
 
510
        set_token_info(p, cur_tok);
 
511
        set_token_link(p, iloc);
 
512
        iloc = p;
 
513
        istart = p;
 
514
        if (cur_tok < right_brace_limit) {
 
515
            if (cur_tok < left_brace_limit)
 
516
                decr(align_state);
 
517
            else
 
518
                incr(align_state);
 
519
        }
 
520
    } else {
 
521
        back_input();
 
522
        a = true;               /* etex is always on */
 
523
    }
 
524
    cur_tok = t;
 
525
    return a;
 
526
}
 
527
 
 
528
 
 
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@>
 
534
 
 
535
@c
 
536
void begin_file_reading(void)
 
537
{
 
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);
 
542
    incr(in_open);
 
543
    push_input();
 
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;
 
551
    istart = first;
 
552
    istate = mid_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 */
 
557
    synctex_tag = 0;
 
558
}
 
559
 
 
560
 
 
561
@ Conversely, the variables must be downdated when such a level of input
 
562
is finished:
 
563
 
 
564
@c
 
565
void end_file_reading(void)
 
566
{
 
567
    first = istart;
 
568
    line = line_stack[iindex];
 
569
    if ((iname >= 18) && (iname <= 20))
 
570
        pseudo_close();
 
571
    else if (iname == 21)
 
572
        luacstring_close(iindex);
 
573
    else if (iname > 17)
 
574
        lua_a_close_in(cur_file, 0);    /* forget it */
 
575
    pop_input();
 
576
    decr(in_open);
 
577
}
 
578
 
 
579
 
 
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.
 
583
 
 
584
@c
 
585
void clear_for_error_prompt(void)
 
586
{
 
587
    while ((istate != token_list) && terminal_input
 
588
           && (input_ptr > 0) && (iloc > ilimit))
 
589
        end_file_reading();
 
590
    print_ln();
 
591
    clear_terminal();
 
592
}
 
593
 
 
594
@ To get \TeX's whole input mechanism going, we perform the following
 
595
   actions. 
 
596
 
 
597
@c
 
598
void initialize_inputstack(void)
 
599
{
 
600
    input_ptr = 0;
 
601
    max_in_stack = 0;
 
602
    source_filename_stack[0] = 0;
 
603
 
 
604
    full_source_filename_stack[0] = NULL;
 
605
    in_open = 0;
 
606
    open_parens = 0;
 
607
    max_buf_stack = 0;
 
608
 
 
609
    grp_stack[0] = 0;
 
610
    if_stack[0] = null;
 
611
    param_ptr = 0;
 
612
    max_param_stack = 0;
 
613
    first = buf_size;
 
614
    do {
 
615
        buffer[first] = 0;
 
616
        decr(first);
 
617
    } while (first != 0);
 
618
    scanner_status = normal;
 
619
    warning_index = null;
 
620
    first = 1;
 
621
    istate = new_line;
 
622
    istart = 1;
 
623
    iindex = 0;
 
624
    line = 0;
 
625
    iname = 0;
 
626
    current_ocp_lstack = 0;
 
627
    current_ocp_no = 0;
 
628
    nofilter = false;
 
629
    force_eof = false;
 
630
    luacstrings = 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|; */
 
636
    ilimit = last;
 
637
    first = last + 1;           /* |init_terminal| has set |loc| and |last| */
 
638
}
 
639
 
 
640
 
 
641
 
 
642
 
 
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.
 
648
 
 
649
@c
 
650
halfword pseudo_files;          /* stack of pseudo files */
 
651
 
 
652
static halfword string_to_pseudo(str_number str, int nl)
 
653
{
 
654
    halfword i, r, q = null;
 
655
    unsigned l, len;
 
656
    four_quarters w;
 
657
    int sz;
 
658
    halfword h = new_node(pseudo_file_node, 0);
 
659
    unsigned char *s = str_string(str);
 
660
    len = (unsigned) str_length(str);
 
661
    l = 0;
 
662
    while (l < len) {
 
663
        unsigned m = l;         /* start of current line */
 
664
        while ((l < len) && (s[l] != nl))
 
665
            l++;
 
666
        sz = (int) (l - m + 7) / 4;
 
667
        if (sz == 1)
 
668
            sz = 2;
 
669
        r = new_node(pseudo_line_node, sz);
 
670
        i = r;
 
671
        while (--sz > 1) {
 
672
            w.b0 = s[m++];
 
673
            w.b1 = s[m++];
 
674
            w.b2 = s[m++];
 
675
            w.b3 = s[m++];
 
676
            varmem[++i].qqqq = w;
 
677
        }
 
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) {
 
684
            pseudo_lines(h) = r;
 
685
            q = r;
 
686
        } else {
 
687
            couple_nodes(q, r);
 
688
        }
 
689
        q = vlink(q);
 
690
        if (s[l] == nl)
 
691
            l++;
 
692
    }
 
693
    return h;
 
694
}
 
695
 
 
696
 
 
697
@ The |pseudo_start| procedure initiates reading from a pseudo file. 
 
698
 
 
699
@c
 
700
void pseudo_from_string(void)
 
701
{
 
702
    str_number s;               /* string to be converted into a pseudo file */
 
703
    halfword p;                 /* for list construction */
 
704
    s = make_string();
 
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;
 
708
    pseudo_files = p;
 
709
    flush_str(s);
 
710
    /* Initiate input from new pseudo file */
 
711
    begin_file_reading();       /* set up |cur_file| and new level of input */
 
712
    line = 0;
 
713
    ilimit = istart;
 
714
    iloc = ilimit + 1;          /* force line read */
 
715
    if (int_par(tracing_scan_tokens_code) > 0) {
 
716
        if (term_offset > max_print_line - 3)
 
717
            print_ln();
 
718
        else if ((term_offset > 0) || (file_offset > 0))
 
719
            print_char(' ');
 
720
        iname = 20;
 
721
        tprint("( ");
 
722
        incr(open_parens);
 
723
        update_terminal();
 
724
    } else {
 
725
        iname = 18;
 
726
    }
 
727
    /* Prepare pseudo file {\sl Sync\TeX} information */
 
728
    synctex_tag = 0;
 
729
}
 
730
 
 
731
void pseudo_start(void)
 
732
{
 
733
    int old_setting;            /* holds |selector| setting */
 
734
    scan_general_text();
 
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));
 
740
    str_room(1);
 
741
    pseudo_from_string();
 
742
}
 
743
 
 
744
@ @c
 
745
void lua_string_start(void)
 
746
{
 
747
    begin_file_reading();       /* set up |cur_file| and new level of input */
 
748
    line = 0;
 
749
    ilimit = istart;
 
750
    iloc = ilimit + 1;          /* force line read */
 
751
    iname = 21;
 
752
    luacstring_start(iindex);
 
753
}
 
754
 
 
755
@ Here we read a line from the current pseudo file into |buffer|.
 
756
 
 
757
@c
 
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);
 
766
    if (p == null) {
 
767
        return false;
 
768
    } else {
 
769
        pseudo_lines(pseudo_files) = vlink(p);
 
770
        sz = subtype(p);
 
771
        if (4 * sz - 3 >= buf_size - last)
 
772
            check_buffer_overflow(last + 4 * sz);
 
773
        last = first;
 
774
        for (r = p + 1; r <= p + sz - 1; r++) {
 
775
            w = varmem[r].qqqq;
 
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;
 
780
            last += 4;
 
781
        }
 
782
        if (last >= max_buf_stack)
 
783
            max_buf_stack = last + 1;
 
784
        while ((last > first) && (buffer[last - 1] == ' '))
 
785
            decr(last);
 
786
        flush_node(p);
 
787
    }
 
788
    return true;
 
789
}
 
790
 
 
791
@ When we are done with a pseudo file we `close' it 
 
792
 
 
793
@c
 
794
void pseudo_close(void)
 
795
{                               /* close the top level pseudo file */
 
796
    halfword p;
 
797
    p = vlink(pseudo_files);
 
798
    flush_node(pseudo_files);
 
799
    pseudo_files = p;
 
800
}