1% omtrans.ch: Characters sets for input and output
2%
3% This file is part of the Omega project, which
4% is based on the web2c distribution of TeX.
5%
6% Copyright (c) 1994--2000 John Plaice and Yannis Haralambous
7%
8% This library is free software; you can redistribute it and/or
9% modify it under the terms of the GNU Library General Public
10% License as published by the Free Software Foundation; either
11% version 2 of the License, or (at your option) any later version.
12%
13% This library is distributed in the hope that it will be useful,
14% but WITHOUT ANY WARRANTY; without even the implied warranty of
15% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16% Library General Public License for more details.
17%
18% You should have received a copy of the GNU Library General Public
19% License along with this library; if not, write to the Free Software
20% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21%
22%---------------------------------------
23@x [3] m.25 l.767 - Omega Translation
24initialization.  We shall define a word file later; but it will be possible
25for us to specify simple operations on word files before they are defined.
26@y
27initialization.  We shall define a word file later; but it will be possible
28for us to specify simple operations on word files before they are defined.
29
30@d no_mode=0
31@d onebyte_mode=1
32@d ebcdic_mode=2
33@d twobyte_mode=3
34@d twobyteLE_mode=4
35
36@d trans_input=0
37@d trans_output=1
38@d trans_default_input=2
39@d trans_default_output=3
40@d trans_no_input=4
41@d trans_no_output=5
42@d trans_no_default_input=6
43@d trans_no_default_output=7
44
45@d mode_input=0
46@d mode_output=1
47@d mode_default_input=2
48@d mode_default_output=3
49@d mode_no_input=4
50@d mode_no_output=5
51@d mode_no_default_input=6
52@d mode_no_default_output=7
53@z
54%---------------------------------------
55@x [3] m.30 l.890 - Omega Translation
56@!max_buf_stack:0..buf_size; {largest index used in |buffer|}
57@y
58@!max_buf_stack:0..buf_size; {largest index used in |buffer|}
59@!term_in_mode:halfword;
60@!term_in_translation:halfword;
61@z
62%---------------------------------------
63@x [3] m.37 l.1065 - Omega Translation
64  if not input_ln(term_in,true) then {this shouldn't happen}
65@y
66  if not new_input_ln(term_in,term_in_mode,term_in_translation,true)
67then {this shouldn't happen}
68@z
69%---------------------------------------
70@x [5] m.54 l. - Omega Translation
71@!log_file : alpha_file; {transcript of \TeX\ session}
72@y
73@!log_file : alpha_file; {transcript of \TeX\ session}
74@!term_out_mode:halfword;
75@!term_out_translation:halfword;
76@z
77%---------------------------------------
78@x [5] m.59 l. - Omega Translation
79@<Basic printing...@>=
80procedure print_char(@!s:ASCII_code); {prints a single character}
81label exit;
82begin if @<Character |s| is the current new-line character@> then
83 if selector<pseudo then
84  begin print_ln; return;
85  end;
86case selector of
87term_and_log: begin wterm(xchr[s]); wlog(xchr[s]);
88  incr(term_offset); incr(file_offset);
89  if term_offset=max_print_line then
90    begin wterm_cr; term_offset:=0;
91    end;
92  if file_offset=max_print_line then
93    begin wlog_cr; file_offset:=0;
94    end;
95  end;
96log_only: begin wlog(xchr[s]); incr(file_offset);
97  if file_offset=max_print_line then print_ln;
98  end;
99term_only: begin wterm(xchr[s]); incr(term_offset);
100  if term_offset=max_print_line then print_ln;
101  end;
102no_print: do_nothing;
103pseudo: if tally<trick_count then trick_buf[tally mod error_line]:=s;
104new_string: begin if pool_ptr<pool_size then append_char(s);
105  end; {we drop characters if the string space is full}
106othercases write(write_file[selector],xchr[s])
107endcases;@/
108incr(tally);
109exit:end;
110@y
111@d omega_write(#)==case term_out_mode of
112                   no_mode: write(#,xchr[s]);
113                   onebyte_mode,ebcdic_mode: write(#,xchr[s]);
114                   twobyte_mode: begin write(#,xchr[s div @"100]);
115                     write(#,xchr[s mod @"100]);
116                     end;
117                   twobyteLE_mode: begin write(#,xchr[s mod @"100]);
118                     write(#,xchr[s div @"100]);
119                     end;
120                   end
121
122@d omega_file_write(#)==case write_file_mode[#] of
123                   no_mode: write(write_file[#],xchr[s]);
124                   onebyte_mode,ebcdic_mode: write(write_file[#],xchr[s]);
125                   twobyte_mode: begin write(write_file[#],xchr[s div @"100]);
126                     write(write_file[#],xchr[s mod @"100]);
127                     end;
128                   twobyteLE_mode: begin write(write_file[#],xchr[s mod @"100]);
129                     write(write_file[#],xchr[s div @"100]);
130                     end;
131                   end
132
133@<Basic printing...@>=
134procedure print_char(@!s:ASCII_code); {prints a single character}
135label exit;
136begin if @<Character |s| is the current new-line character@> then
137 if selector<pseudo then
138  begin print_ln; return;
139  end;
140case selector of
141term_and_log: begin omega_write(term_out); omega_write(log_file);
142  incr(term_offset); incr(file_offset);
143  if term_offset=max_print_line then
144    begin wterm_cr; term_offset:=0;
145    end;
146  if file_offset=max_print_line then
147    begin wlog_cr; file_offset:=0;
148    end;
149  end;
150log_only: begin omega_write(log_file); incr(file_offset);
151  if file_offset=max_print_line then print_ln;
152  end;
153term_only: begin omega_write(term_out); incr(term_offset);
154  if term_offset=max_print_line then print_ln;
155  end;
156no_print: do_nothing;
157pseudo: if tally<trick_count then trick_buf[tally mod error_line]:=s;
158new_string: begin if pool_ptr<pool_size then append_char(s);
159  end; {we drop characters if the string space is full}
160othercases omega_file_write(selector)
161endcases;@/
162incr(tally);
163exit:end;
164@z
165%---------------------------------------
166@x [5] m.59 l. - Omega Translation
167procedure print(@!s:integer); {prints string |s|}
168label exit;
169var j:pool_pointer; {current character code position}
170@!nl:integer; {new-line character to restore}
171@!l:integer; {for printing 16-bit characters}
172begin if s>=str_ptr then s:="???" {this can't happen}
173@.???@>
174else if s<biggest_char then
175  if s<0 then s:="???" {can't happen}
176  else begin if selector>pseudo then
177      begin print_char(s); return; {internal strings are not expanded}
178      end;
179    if (@<Character |s| is the current new-line character@>) then
180      if selector<pseudo then
181        begin print_ln; return;
182        end;
183    nl:=new_line_char;
184    @<Set newline character to -1@>;
185    if s<@"20 then begin
186      print_char(@"5E); print_char(@"5E); print_char(s+@'100);
187      end
188    else if s<@"7F then
189      print_char(s)
190    else if s=@"7F then begin
191      print_char(@"5E); print_char(@"5E); print_char(s-@'100);
192      end
193    else if s<@"100 then begin
194      print_char(@"5E); print_char(@"5E);
195      print_lc_hex((s mod @"100) div @"10); print_lc_hex(s mod @"10);
196      end
197    else begin {Here is where we generate the strings on the fly.}
198      print_char(@"5E); print_char(@"5E);
199      print_char(@"5E); print_char(@"5E);
200      print_lc_hex(s div @"1000); print_lc_hex((s mod @"1000) div @"100);
201      print_lc_hex((s mod @"100) div @"10); print_lc_hex(s mod @"10);
202      end;
203    @<Set newline character to nl@>;
204    return;
205    end;
206j:=str_start(s);
207while j<str_start(s+1) do
208  begin print_char(so(str_pool[j])); incr(j);
209  end;
210exit:end;
211
212@ Control sequence names, file names, and strings constructed with
213\.{\\string} might contain |ASCII_code| values that can't
214be printed using |print_char|. Therefore we use |slow_print| for them:
215
216@<Basic print...@>=
217procedure slow_print(@!s:integer); {prints string |s|}
218var j:pool_pointer; {current character code position}
219begin if (s>=str_ptr) or (s<=biggest_char) then print(s)
220else begin j:=str_start(s);
221  while j<str_start(s+1) do
222    begin print(so(str_pool[j])); incr(j);
223    end;
224  end;
225end;
226@y
227procedure print(@!s:integer); {prints string |s|}
228label exit;
229var j:pool_pointer; {current character code position}
230@!nl:integer; {new-line character to restore}
231@!l:integer; {for printing 16-bit characters}
232begin if s>=str_ptr then s:="???" {this can't happen}
233@.???@>
234else if s<biggest_char then
235  if s<0 then s:="???" {can't happen}
236  else begin if selector>pseudo then
237      begin print_char(s); return; {internal strings are not expanded}
238      end;
239    if (@<Character |s| is the current new-line character@>) then
240      if selector<pseudo then
241        begin print_ln; return;
242        end;
243    nl:=new_line_char;
244    @<Set newline character to -1@>;
245    if s<@"20 then begin
246      print_char(@"5E); print_char(@"5E); print_char(s+@'100);
247      end
248    else if s<@"7F then
249      print_char(s)
250    else if s=@"7F then begin
251      print_char(@"5E); print_char(@"5E); print_char(s-@'100);
252      end
253    else if s<@"100 then begin
254      print_char(@"5E); print_char(@"5E);
255      print_lc_hex((s mod @"100) div @"10); print_lc_hex(s mod @"10);
256      end
257    else begin {Here is where we generate the strings on the fly.}
258      print_char(@"5E); print_char(@"5E);
259      print_char(@"5E); print_char(@"5E);
260      print_lc_hex(s div @"1000); print_lc_hex((s mod @"1000) div @"100);
261      print_lc_hex((s mod @"100) div @"10); print_lc_hex(s mod @"10);
262      end;
263    @<Set newline character to nl@>;
264    return;
265    end;
266j:=str_start(s);
267while j<str_start(s+1) do
268  begin print_char(so(str_pool[j])); incr(j);
269  end;
270exit:end;
271
272procedure print_nl(@!s:str_number); {prints string |s| at beginning of line}
273begin if ((term_offset>0)and(odd(selector)))or@|
274  ((file_offset>0)and(selector>=log_only)) then print_ln;
275print(s);
276end;
277
278procedure overflow_ocp_buf_size; forward;
279procedure overflow_ocp_stack_size; forward;
280
281procedure omega_print(s:str_number);
282var new_s:str_number;
283    om_mode,om_translation:integer;
284    j:integer;
285begin
286om_mode:=no_mode;
287om_translation:=0;
288case selector of
289term_and_log,log_only,term_only: begin
290  om_mode:=term_out_mode;
291  if om_mode<>no_mode then om_translation:=term_out_translation;
292  end;
293no_print,pseudo,new_string: do_nothing;
294othercases begin
295  om_mode:=write_file_mode[selector];
296  if om_mode<>no_mode then om_translation:=write_file_translation[selector];
297  end
298endcases;
299
300if (om_mode=no_mode) or
301   ((om_mode=onebyte_mode) and (om_translation=0)) then
302  begin
303  j:=str_start(s);
304  while j<str_start(s+1) do begin
305    new_s:=so(str_pool[j]);
306    if new_s<@"20 then begin
307      print_char(@"5E); print_char(@"5E); print_char(new_s+@'100);
308      end
309    else if new_s<@"7F then
310      print_char(new_s)
311    else if new_s=@"7F then begin
312      print_char(@"5E); print_char(@"5E); print_char(new_s-@'100);
313      end
314    else if new_s<@"100 then begin
315      print_char(@"5E); print_char(@"5E);
316      print_lc_hex((new_s mod @"100) div @"10); print_lc_hex(new_s mod @"10);
317      end
318    else begin {Here is where we generate the strings on the fly.}
319      print_char(@"5E); print_char(@"5E);
320      print_char(@"5E); print_char(@"5E);
321      print_lc_hex(new_s div @"1000);
322      print_lc_hex((new_s mod @"1000) div @"100);
323      print_lc_hex((new_s mod @"100) div @"10);
324      print_lc_hex(new_s mod @"10);
325      end;
326    incr(j);
327    end;
328  end
329else begin
330  if om_translation=0 then begin
331    j:=str_start(s);
332    otp_counter:=1;
333    while j<str_start(s+1) do begin
334      otp_output_buf[otp_counter]:=so(str_pool[j]);
335      incr(otp_counter);
336      incr(j);
337      end;
338    otp_output_end:=otp_counter;
339    end
340  else begin
341    otp_input_start:=0;
342    otp_input_last:=0;
343    otp_stack_used:=0;
344    otp_stack_last:=0;
345    otp_stack_new:=0;
346    otp_output_end:=0;
347    otp_pc:=0;
348    otp_finished:=false;
349    otp_calc_ptr:=0;
350    otp_calcs[otp_calc_ptr]:=0;
351    otp_state_ptr:=0;
352    otp_states[otp_state_ptr]:=0;
353    otp_input_ocp:=om_translation;
354    j:=str_start(s);
355    otp_counter:=1;
356    while j<str_start(s+1) do begin
357      otp_input_buf[otp_counter]:=so(str_pool[j]);
358      incr(otp_counter);
359      incr(j);
360      end;
361    otp_input_end:=otp_counter;
362    while not otp_finished do
363      @<Run the OTP program@>;
364    end;
365  for otp_counter:=1 to (otp_output_end-1) do begin
366    new_s:=otp_output_buf[otp_counter];
367    if (om_mode<twobyte_mode) and (new_s>255) then
368      begin
369      print_char(@"5E); print_char(@"5E);
370      print_char(@"5E); print_char(@"5E);
371      print_lc_hex(new_s div @"1000);
372      print_lc_hex((new_s mod @"1000) div @"100);
373      print_lc_hex((new_s mod @"100) div @"10);
374      print_lc_hex(new_s mod @"10);
375      end
376    else
377      print_char(new_s);
378    end;
379  end;
380end;
381
382@ Control sequence names, file names, and strings constructed with
383\.{\\string} might contain |ASCII_code| values that can't
384be printed using |print_char|. Therefore we use |slow_print| for them:
385
386@<Basic print...@>=
387procedure slow_print(@!s:integer); {prints string |s|}
388begin if (s>=str_ptr) or (s<=biggest_char) then print(s)
389else omega_print(s);
390end;
391@z
392%---------------------------------------
393@x [5] - Omega Translation
394procedure print_nl(@!s:str_number); {prints string |s| at beginning of line}
395begin if ((term_offset>0)and(odd(selector)))or@|
396  ((file_offset>0)and(selector>=log_only)) then print_ln;
397print(s);
398end;
399@y
400@z
401%---------------------------------------
402@x [5] m.71 l.1694 - Omega Translation
403if not input_ln(term_in,true) then fatal_error("End of file on the terminal!");
404@y
405if not new_input_ln(term_in,term_in_mode,term_in_translation,true)
406then fatal_error("End of file on the terminal!");
407@z
408%---------------------------------------
409@x [15] m.209 l.4170 - Omega Translation
410@d max_command=ocp_trace_level
411   {the largest command code seen at |big_switch|}
412@y
413@d char_trans=ocp_trace_level+1
414@d char_mode=char_trans+1
415@d max_command=char_mode
416   {the largest command code seen at |big_switch|}
417@z
418%---------------------------------------
419@x [17] m.230 l.4722 - Omega Translation
420@d toks_base=ocp_active_base+max_active_ocp_lists
421   {table of |number_regs| token list registers}
422@y
423@d ocp_input_mode_base=ocp_active_base+max_active_ocp_lists
424@d ocp_input_onebyte_translation_base    =ocp_input_mode_base+ 1
425@d ocp_input_ebcdic_translation_base     =ocp_input_mode_base+ 2
426@d ocp_input_twobyte_translation_base    =ocp_input_mode_base+ 3
427@d ocp_input_twobyteLE_translation_base  =ocp_input_mode_base+ 4
428
429@d ocp_output_mode_base                  =ocp_input_mode_base+ 5
430@d ocp_output_onebyte_translation_base   =ocp_input_mode_base+ 6
431@d ocp_output_ebcdic_translation_base    =ocp_input_mode_base+ 7
432@d ocp_output_twobyte_translation_base   =ocp_input_mode_base+ 8
433@d ocp_output_twobyteLE_translation_base =ocp_input_mode_base+ 9
434
435@d toks_base                             =ocp_input_mode_base+10
436@z
437%---------------------------------------
438@x [22] m.304 l.6535 - Omega Translation
439@!input_file : array[1..max_in_open] of alpha_file;
440@y
441@!input_file : array[1..max_in_open] of alpha_file;
442@!input_file_mode : array[1..max_in_open] of halfword;
443@!input_file_translation : array[1..max_in_open] of halfword;
444@z
445%---------------------------------------
446@x [23] m.331 l.7066 - Omega Translation
447param_ptr:=0; max_param_stack:=0;
448@y
449param_ptr:=0; max_param_stack:=0;
450geq_define(ocp_input_mode_base,data,1);
451term_in_mode:=equiv(ocp_input_mode_base);
452term_out_mode:=equiv(ocp_input_mode_base);
453if term_in_mode>0
454then term_in_translation:=
455     equiv(ocp_input_onebyte_translation_base+term_in_mode-1);
456if term_out_mode>0
457then term_out_translation:=
458     equiv(ocp_output_onebyte_translation_base+term_in_mode-1);
459@z
460%---------------------------------------
461@x [24] m.362 l.7066 - Omega Translation
462  begin if input_ln(cur_file,true) then {not end of file}
463@y
464  begin if new_input_ln(cur_file,input_file_mode[index],
465           input_file_translation[index],true) then {not end of file}
466@z
467%---------------------------------------
468@x [27] m.480 l.9411 - Omega Translation
469@!read_file:array[0..15] of alpha_file; {used for \.{\\read}}
470@y
471@!read_file:array[0..15] of alpha_file; {used for \.{\\read}}
472@!read_file_mode:array[0..15] of halfword;
473@!read_file_translation:array[0..15] of halfword;
474@z
475%---------------------------------------
476@x [27] m.485 l.9475 - Omega Translation
477@<Input the first line of |read_file[m]|@>=
478if input_ln(read_file[m],false) then read_open[m]:=normal
479else  begin a_close(read_file[m]); read_open[m]:=closed;
480  end
481@y
482@<Input the first line of |read_file[m]|@>=
483begin read_file_mode[m]:=
484  get_file_mode(read_file[m], equiv(ocp_input_mode_base));
485if read_file_mode[m]>0
486then read_file_translation[m]:=
487     equiv(ocp_input_onebyte_translation_base+read_file_mode[m]-1);
488if new_input_ln(read_file[m],read_file_mode[m],
489   read_file_translation[m],false) then read_open[m]:=normal
490else  begin a_close(read_file[m]); read_open[m]:=closed;
491  end
492end
493@z
494%---------------------------------------
495@x [27] m.486 l.9484 - Omega Translation
496begin if not input_ln(read_file[m],true) then
497  begin a_close(read_file[m]); read_open[m]:=closed;
498@y
499begin if not new_input_ln(read_file[m],
500read_file_mode[m],read_file_translation[m],true) then
501  begin a_close(read_file[m]); read_open[m]:=closed;
502@z
503%---------------------------------------
504@x [29] m.538 l.10371 - Omega Translation
505begin line:=1;
506if input_ln(cur_file,false) then do_nothing;
507@y
508begin line:=1;
509input_file_mode[index]:=
510  get_file_mode(cur_file, equiv(ocp_input_mode_base));
511if input_file_mode[index]>0
512then input_file_translation[index]:=
513     equiv(ocp_input_onebyte_translation_base+input_file_mode[index]-1);
514if new_input_ln(cur_file,input_file_mode[index],
515   input_file_translation[index],false) then do_nothing;
516@z
517%---------------------------------------
518@x [49] m.1210 l.22629 - Omega Translation
519any_mode(ocp_trace_level) : prefixed_command;
520@y
521any_mode(ocp_trace_level) : prefixed_command;
522any_mode(char_mode) : do_char_mode;
523any_mode(char_trans) : do_char_translation;
524@z
525%---------------------------------------
526@x [49] m.1343 l.24928 - Omega Translation
527@!write_file:array[0..15] of alpha_file;
528@y
529@!write_file:array[0..15] of alpha_file;
530@!write_file_mode:array[0..15] of halfword;
531@!write_file_translation:array[0..15] of halfword;
532@z
533%---------------------------------------
534@x
535@* \[54] $\Omega$ changes.
536
537@y
538@* \[54] $\Omega$ changes.
539
540@ Here we do the main work required for reading and interpreting
541  $\Omega$ Input Translation Processes.
542
543@ @<Put each...@>=
544primitive("InputTranslation",           char_trans, trans_input);
545primitive("OutputTranslation",          char_trans, trans_output);
546primitive("DefaultInputTranslation",    char_trans, trans_default_input);
547primitive("DefaultOutputTranslation",   char_trans, trans_default_output);
548primitive("noInputTranslation",         char_trans, trans_no_input);
549primitive("noOutputTranslation",        char_trans, trans_no_output);
550primitive("noDefaultInputTranslation",  char_trans, trans_no_default_input);
551primitive("noDefaultOutputTranslation", char_trans, trans_no_default_output);
552primitive("InputMode",                  char_mode,  mode_input);
553primitive("OutputMode",                 char_mode,  mode_output);
554primitive("DefaultInputMode",           char_mode,  mode_default_input);
555primitive("DefaultOutputMode",          char_mode,  mode_default_output);
556primitive("noInputMode",                char_mode,  mode_no_input);
557primitive("noOutputMode",               char_mode,  mode_no_output);
558primitive("noDefaultInputMode",         char_mode,  mode_no_default_input);
559primitive("noDefaultOutputMode",        char_mode,  mode_no_default_output);
560
561geq_define(ocp_input_onebyte_translation_base, data, 0);
562geq_define(ocp_input_ebcdic_translation_base, data, 0);
563geq_define(ocp_input_twobyte_translation_base, data, 0);
564geq_define(ocp_input_twobyteLE_translation_base, data, 0);
565geq_define(ocp_input_mode_base, data, 0);
566
567geq_define(ocp_output_onebyte_translation_base, data, 0);
568geq_define(ocp_output_ebcdic_translation_base, data, 0);
569geq_define(ocp_output_twobyte_translation_base, data, 0);
570geq_define(ocp_output_twobyteLE_translation_base, data, 0);
571geq_define(ocp_output_mode_base, data, 0);
572
573@ @<Cases of |print_cmd_chr|...@>=
574char_trans:
575  case chr_code of
576  trans_input:             print_esc("InputTranslation");
577  trans_output:            print_esc("OutputTranslation");
578  trans_default_input:     print_esc("DefaultInputTranslation");
579  trans_default_output:    print_esc("DefaultOutputTranslation");
580  trans_no_input:          print_esc("noInputTranslation");
581  trans_no_output:         print_esc("noOutputTranslation");
582  trans_no_default_input:  print_esc("noDefaultInputTranslation");
583  trans_no_default_output: print_esc("noDefaultOutputTranslation");
584  end;
585char_mode:
586  case chr_code of
587  mode_input:              print_esc("InputMode");
588  mode_output:             print_esc("OutputMode");
589  mode_default_input:      print_esc("DefaultInputMode");
590  mode_default_output:     print_esc("DefaultOutputMode");
591  mode_no_input:           print_esc("noInputMode");
592  mode_no_output:          print_esc("noOutputMode");
593  mode_no_default_input:   print_esc("noDefaultInputMode");
594  mode_no_default_output:  print_esc("noDefaultOutputMode");
595  end;
596
597@ @<Declare subprocedures for |prefixed_command|@>=
598procedure scan_file_referrent;
599begin
600if scan_keyword("currentfile") then cur_val:=max_halfword
601else scan_int;
602end;
603
604procedure scan_mode;
605begin
606if scan_keyword("onebyte") then cur_val:=onebyte_mode
607else if scan_keyword("ebcdic") then cur_val:=ebcdic_mode
608else if scan_keyword("twobyte") then cur_val:=twobyte_mode
609else if scan_keyword("twobyteLE") then cur_val:=twobyteLE_mode
610else begin print_err("Invalid input mode"); cur_val:=0; end;
611end;
612
613procedure do_char_translation;
614var kind:halfword;
615    fileref:halfword;
616    moderef:halfword;
617    ocpref:halfword;
618begin
619fileref:=0;
620moderef:=0;
621ocpref:=0;
622kind:=cur_chr;
623if (kind mod 4) <= 1 then begin
624  scan_file_referrent;
625  fileref:=cur_val;
626  end
627else begin
628  scan_mode;
629  moderef:=cur_val;
630  end;
631if kind < 4 then begin
632  scan_ocp_ident;
633  ocpref:=cur_val;
634  end;
635case (kind mod 4) of
636  trans_input: begin
637    if (fileref>=0) and (fileref<=15) then begin
638      read_file_translation[fileref]:=ocpref;
639      end
640    else if fileref<>max_halfword then begin
641      term_in_translation:=ocpref;
642      end
643    else begin
644      base_ptr:=input_ptr; input_stack[base_ptr]:=cur_input;
645      while state = token_list do
646        begin
647        decr(base_ptr);
648        cur_input:=input_stack[base_ptr];
649        end;
650      if name>17 then input_file_translation[index]:=ocpref;
651      cur_input:=input_stack[input_ptr];
652      end;
653    end;
654  trans_output: begin
655    if (fileref>=0) and (fileref<=15) then begin
656      write_file_translation[fileref]:=ocpref;
657      end
658    else begin
659      term_out_translation:=ocpref;
660      end;
661    end;
662  trans_default_input: begin
663    geq_define(ocp_input_mode_base+moderef,data,ocpref);
664    end;
665  trans_default_output: begin
666    geq_define(ocp_output_mode_base+moderef,data,ocpref);
667    end;
668  end;
669end;
670
671procedure do_char_mode;
672var kind:halfword;
673    fileref:halfword;
674    moderef:halfword;
675begin
676fileref:=0;
677moderef:=0;
678kind:=cur_chr;
679if (kind mod 4) <= 1 then begin
680  scan_file_referrent;
681  fileref:=cur_val;
682  end;
683if kind < 4 then begin
684  scan_mode;
685  moderef:=cur_val;
686  end;
687case (kind mod 4) of
688  trans_input: begin
689    if (fileref>=0) and (fileref<=15) then begin
690      read_file_mode[fileref]:=moderef;
691      end
692    else if fileref<>max_halfword then begin
693      term_in_mode:=moderef;
694      end
695    else begin
696      base_ptr:=input_ptr; input_stack[base_ptr]:=cur_input;
697      while state = token_list do
698        begin
699        decr(base_ptr);
700        cur_input:=input_stack[base_ptr];
701        end;
702      if name>17 then input_file_mode[index]:=moderef;
703      cur_input:=input_stack[input_ptr];
704      end;
705    end;
706  trans_output: begin
707    if (fileref>=0) and (fileref<=15) then begin
708      write_file_mode[fileref]:=moderef;
709      end
710    else begin
711      term_out_mode:=moderef;
712      end;
713    end;
714  trans_default_input: begin
715    geq_define(ocp_input_mode_base,data,moderef);
716    end;
717  trans_default_output: begin
718    geq_define(ocp_output_mode_base,data,moderef);
719    end;
720  end;
721end;
722
723function p_new_input_ln(f:alpha_file;
724the_mode,translation:halfword;
725bypass_eoln:boolean):boolean;
726begin
727if (the_mode=no_mode) or ((the_mode=onebyte_mode) and (translation=0))
728then p_new_input_ln:=input_ln(f,bypass_eoln)
729else if not newinputline(f,the_mode,bypass_eoln)
730then p_new_input_ln:=false
731else if translation=0 then
732begin
733   if (first+otp_input_end)>=buf_size then overflow("buffer size", buf_size);
734   state:=new_line;
735   start:=first;
736   last:=start;
737   loc:=start;
738   for otp_counter:=1 to otp_input_end do
739   begin
740      buffer[last]:=otp_input_buf[otp_counter];
741      incr(last);
742   end;
743   while buffer[last-1]=' ' do decr(last);
744   limit:=last-1;
745   p_new_input_ln:=true
746end
747else
748begin
749   otp_input_start:=0;
750   otp_input_last:=0;
751   otp_stack_used:=0;
752   otp_stack_last:=0;
753   otp_stack_new:=0;
754   otp_output_end:=0;
755   otp_pc:=0;
756   otp_finished:=false;
757   otp_calc_ptr:=0;
758   otp_calcs[otp_calc_ptr]:=0;
759   otp_state_ptr:=0;
760   otp_states[otp_state_ptr]:=0;
761   otp_input_ocp:=translation;
762   while not otp_finished do
763      @<Run the OTP program@>;
764   if (first+otp_output_end)>=buf_size then overflow("buffer size", buf_size);
765   state:=new_line;
766   start:=first;
767   last:=start;
768   loc:=start;
769   for otp_counter:=1 to otp_output_end do
770   begin
771      buffer[last]:=otp_output_buf[otp_counter];
772      incr(last);
773   end;
774   while buffer[last-1]=' ' do decr(last);
775   limit:=last-1;
776   p_new_input_ln:=true
777end
778end;
779
780
781@z
782%---------------------------------------
783