~ubuntu-branches/ubuntu/saucy/luatex/saucy

« back to all changes in this revision

Viewing changes to source/texk/web2c/luatexdir/ocp/runocp.c

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Preining
  • Date: 2009-12-25 09:47:05 UTC
  • mfrom: (1.1.9 upstream) (4.2.3 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091225094705-y33rpflo8t4u9nag
Tags: 0.50.0-1
* new upstream release
* disable fix-hurd-ftbfs patch, included upstream
* disable upstram-fixes, included upstream
* disable ubuntu_libpoppler-0.11, not needed anymore

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* runocp.c
 
2
   
 
3
   Copyright 2006-2009 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
#include "ptexlib.h"
 
21
 
 
22
 
 
23
 
 
24
 
 
25
static const char _svn_version[] =
 
26
    "$Id: runocp.c 3261 2009-12-18 11:38:21Z taco $ $URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.50.0/source/texk/web2c/luatexdir/ocp/runocp.c $";
 
27
 
 
28
memory_word active_info[(active_mem_size + 1)];
 
29
active_index active_min_ptr = 0;        /* first unused word of |active_info| */
 
30
active_index active_max_ptr = 0;        /* last unused word of |active_info| */
 
31
active_index active_real = 0;
 
32
 
 
33
static ocp_list_index holding[(active_mem_size + 1)] = { 0 };
 
34
 
 
35
/* Here we do the main work required for reading and interpreting
 
36
   $\Omega$ Compiled Translation Processes.*/
 
37
 
 
38
#define ocp_list_id_text(A) cs_text(ocp_list_id_base+(A))
 
39
 
 
40
#define ocp_active_min_ptr_base (ocp_active_number_base+1)
 
41
#define ocp_active_max_ptr_base (ocp_active_min_ptr_base+1)
 
42
#define ocp_active_base (ocp_active_max_ptr_base+1)
 
43
 
 
44
 
 
45
/* Here are all the instructions in our mini-assembler. */
 
46
 
 
47
typedef enum {
 
48
    otp_right_output = 1,
 
49
    otp_right_num = 2,
 
50
    otp_right_char = 3,
 
51
    otp_right_lchar = 4,
 
52
    otp_right_some = 5,
 
53
    otp_pback_output = 6,
 
54
    otp_pback_num = 7,
 
55
    otp_pback_char = 8,
 
56
    otp_pback_lchar = 9,
 
57
    otp_pback_some = 10,
 
58
    otp_add = 11,
 
59
    otp_sub = 12,
 
60
    otp_mult = 13,
 
61
    otp_div = 14,
 
62
    otp_mod = 15,
 
63
    otp_lookup = 16,
 
64
    otp_push_num = 17,
 
65
    otp_push_char = 18,
 
66
    otp_push_lchar = 19,
 
67
    otp_state_change = 20,
 
68
    otp_state_push = 21,
 
69
    otp_state_pop = 22,
 
70
    otp_left_start = 23,
 
71
    otp_left_return = 24,
 
72
    otp_left_backup = 25,
 
73
    otp_goto = 26,
 
74
    otp_goto_ne = 27,
 
75
    otp_goto_eq = 28,
 
76
    otp_goto_lt = 29,
 
77
    otp_goto_le = 30,
 
78
    otp_goto_gt = 31,
 
79
    otp_goto_ge = 32,
 
80
    otp_goto_no_advance = 33,
 
81
    otp_goto_beg = 34,
 
82
    otp_goto_end = 35,
 
83
    otp_stop = 36
 
84
} otp_command_codes;
 
85
 
 
86
#define check_buffer() do {                                             \
 
87
    if (last==buf_size-2) {                                             \
 
88
      check_buffer_overflow(buf_size+4);                                \
 
89
    }                                                                   \
 
90
  } while (0)
 
91
 
 
92
/* 
 
93
Of course we want to define macros that suppress the detail of how ocp
 
94
information is actually packed, so that we don't have to write things like
 
95
$$\hbox{|ocp_info[k+ocp_info[j+ocp_state_base[i]]]|}$$
 
96
too often. The \.{WEB} definitions here make |ocp_state_entry(i)(j)(k)|
 
97
(|ocp_table_entry(i)(j)(k)|) the |k|-th word in the |j|-th state (table)
 
98
of the |i|-th ocp.
 
99
@^inner loop@>
 
100
*/
 
101
 
 
102
#define ocp_state_entry(A,B,C) ocp_tables[(A)][ocp_tables[(A)][ocp_state_base((A))+((B)*2)]+(C)]
 
103
 
 
104
#define ocp_state_no(A,B) ocp_tables[(A)][ocp_state_base(A)+((B)*2)+1]
 
105
 
 
106
#define ocp_table_entry(A,B,C) ocp_tables[(A)][ocp_tables[(A)][ocp_table_base((A))+(B)*2]+(C)]
 
107
 
 
108
#define ocp_table_no(A,B)  ocp_tables[(A)][ocp_table_base((A))+((B)*2)+1]
 
109
 
 
110
#define otp_cur_state otp_states[otp_state_ptr]
 
111
 
 
112
#define tsuccumb pdftex_fail
 
113
 
 
114
halfword otp_init_input_start;
 
115
halfword otp_init_input_last;
 
116
halfword otp_init_input_end;
 
117
quarterword *otp_init_input_buf;
 
118
 
 
119
halfword otp_input_start;
 
120
halfword otp_input_last;
 
121
halfword otp_input_end;
 
122
quarterword *otp_input_buf;
 
123
 
 
124
halfword otp_output_end;
 
125
quarterword *otp_output_buf;
 
126
 
 
127
halfword otp_stack_used;
 
128
halfword otp_stack_last;
 
129
halfword otp_stack_new;
 
130
quarterword *otp_stack_buf;
 
131
 
 
132
halfword otp_pc;
 
133
 
 
134
halfword otp_calc_ptr;
 
135
halfword *otp_calcs;
 
136
halfword otp_state_ptr;
 
137
halfword *otp_states;
 
138
 
 
139
halfword otp_input_char;
 
140
halfword otp_calculated_char;
 
141
halfword otp_no_input_chars;
 
142
 
 
143
halfword otp_instruction;
 
144
halfword otp_instr;
 
145
halfword otp_arg;
 
146
halfword otp_first_arg;
 
147
halfword otp_second_arg;
 
148
 
 
149
halfword otp_input_ocp;
 
150
 
 
151
boolean otp_finished;
 
152
int otp_ext_str;
 
153
int otp_ext_str_arg;
 
154
int otp_ext_i;
 
155
 
 
156
#define otp_set_instruction() do {                                      \
 
157
    if (otp_pc>=ocp_state_no(otp_input_ocp,otp_cur_state)) {            \
 
158
      tsuccumb("bad OCP program -- PC not valid");                      \
 
159
    }                                                                   \
 
160
    otp_instruction=ocp_state_entry(otp_input_ocp,otp_cur_state,otp_pc); \
 
161
    otp_instr=otp_instruction / 0x1000000;                              \
 
162
    otp_arg=otp_instruction % 0x1000000;                                \
 
163
  } while (0)
 
164
 
 
165
 
 
166
#define otp_check_char(A)  do {                                 \
 
167
    if ((1>(A)) || ((A)>otp_no_input_chars)) {                  \
 
168
      tsuccumb("right hand side of OCP expression is bad");     \
 
169
    }                                                           \
 
170
  } while (0)
 
171
 
 
172
 
 
173
#define otp_get_char(A) do {                                            \
 
174
    otp_check_char((A));                                                \
 
175
    if ((A)>otp_stack_last) {                                           \
 
176
      otp_calculated_char=otp_input_buf[otp_input_start+(A)-otp_stack_last]; \
 
177
    } else {                                                            \
 
178
      otp_calculated_char=otp_stack_buf[(A)];                           \
 
179
    }                                                                   \
 
180
  } while (0)
 
181
 
 
182
 
 
183
void overflow_ocp_buf_size(void)
 
184
{
 
185
    overflow("ocp_buf_size", ocp_buf_size);
 
186
}
 
187
 
 
188
void overflow_ocp_stack_size(void)
 
189
{
 
190
    overflow("ocp_stack_size", ocp_stack_size);
 
191
}
 
192
 
 
193
void run_otp(void)
 
194
{
 
195
    halfword otp_counter;
 
196
    otp_set_instruction();
 
197
    switch (otp_instr) {
 
198
        /* Run the |otp_right| instructions */
 
199
    case otp_right_output:
 
200
        incr(otp_output_end);
 
201
        if (otp_output_end > ocp_buf_size)
 
202
            overflow_ocp_buf_size();
 
203
        otp_output_buf[otp_output_end] = otp_calcs[otp_calc_ptr];
 
204
        decr(otp_calc_ptr);
 
205
        incr(otp_pc);
 
206
        break;
 
207
    case otp_right_num:
 
208
        incr(otp_output_end);
 
209
        if (otp_output_end > ocp_buf_size)
 
210
            overflow_ocp_buf_size();
 
211
        otp_output_buf[otp_output_end] = otp_arg;
 
212
        incr(otp_pc);
 
213
        break;
 
214
    case otp_right_char:
 
215
        otp_get_char(otp_arg);
 
216
        incr(otp_output_end);
 
217
        if (otp_output_end > ocp_buf_size)
 
218
            overflow_ocp_buf_size();
 
219
        otp_output_buf[otp_output_end] = otp_calculated_char;
 
220
        incr(otp_pc);
 
221
        break;
 
222
    case otp_right_lchar:
 
223
        otp_get_char(otp_no_input_chars - otp_arg);
 
224
        incr(otp_output_end);
 
225
        if (otp_output_end > ocp_buf_size)
 
226
            overflow_ocp_buf_size();
 
227
        otp_output_buf[otp_output_end] = otp_calculated_char;
 
228
        incr(otp_pc);
 
229
        break;
 
230
    case otp_right_some:
 
231
        otp_first_arg = otp_arg + 1;
 
232
        incr(otp_pc);
 
233
        otp_set_instruction();
 
234
        otp_second_arg = otp_no_input_chars - otp_arg;
 
235
        for (otp_counter = otp_first_arg; otp_counter <= otp_second_arg;
 
236
             otp_counter++) {
 
237
            otp_get_char(otp_counter);
 
238
            incr(otp_output_end);
 
239
            if (otp_output_end > ocp_buf_size)
 
240
                overflow_ocp_buf_size();
 
241
            otp_output_buf[otp_output_end] = otp_calculated_char;
 
242
        }
 
243
        incr(otp_pc);
 
244
        break;
 
245
 
 
246
        /* Run the |otp_pback| instructions */
 
247
    case otp_pback_output:
 
248
        incr(otp_stack_new);
 
249
        if (otp_stack_new >= ocp_stack_size)
 
250
            overflow_ocp_stack_size();
 
251
        otp_stack_buf[otp_stack_new] = otp_calcs[otp_calc_ptr];
 
252
        decr(otp_calc_ptr);
 
253
        incr(otp_pc);
 
254
        break;
 
255
    case otp_pback_num:
 
256
        incr(otp_stack_new);
 
257
        if (otp_stack_new >= ocp_stack_size)
 
258
            overflow_ocp_stack_size();
 
259
        otp_stack_buf[otp_stack_new] = otp_arg;
 
260
        incr(otp_pc);
 
261
        break;
 
262
    case otp_pback_char:
 
263
        otp_get_char(otp_arg);
 
264
        incr(otp_stack_new);
 
265
        if (otp_stack_new >= ocp_stack_size)
 
266
            overflow_ocp_stack_size();
 
267
        otp_stack_buf[otp_stack_new] = otp_calculated_char;
 
268
        incr(otp_pc);
 
269
        break;
 
270
    case otp_pback_lchar:
 
271
        otp_get_char(otp_no_input_chars - otp_arg);
 
272
        incr(otp_stack_new);
 
273
        if (otp_stack_new >= ocp_stack_size)
 
274
            overflow_ocp_stack_size();
 
275
        otp_stack_buf[otp_stack_new] = otp_calculated_char;
 
276
        incr(otp_pc);
 
277
        break;
 
278
    case otp_pback_some:
 
279
        otp_first_arg = otp_arg + 1;
 
280
        incr(otp_pc);
 
281
        otp_set_instruction();
 
282
        otp_second_arg = otp_no_input_chars - otp_arg;
 
283
        for (otp_counter = otp_first_arg; otp_counter <= otp_second_arg;
 
284
             otp_counter++) {
 
285
            otp_get_char(otp_counter);
 
286
            incr(otp_stack_new);
 
287
            if (otp_stack_new >= ocp_stack_size)
 
288
                overflow_ocp_stack_size();
 
289
            otp_stack_buf[otp_stack_new] = otp_calculated_char;
 
290
        }
 
291
        incr(otp_pc);
 
292
        break;
 
293
 
 
294
        /* Run the arithmetic instructions */
 
295
    case otp_add:
 
296
        otp_calcs[otp_calc_ptr - 1] =
 
297
            otp_calcs[otp_calc_ptr - 1] + otp_calcs[otp_calc_ptr];
 
298
        incr(otp_pc);
 
299
        decr(otp_calc_ptr);
 
300
        break;
 
301
    case otp_sub:
 
302
        otp_calcs[otp_calc_ptr - 1] =
 
303
            otp_calcs[otp_calc_ptr - 1] - otp_calcs[otp_calc_ptr];
 
304
        incr(otp_pc);
 
305
        decr(otp_calc_ptr);
 
306
        break;
 
307
    case otp_mult:
 
308
        otp_calcs[otp_calc_ptr - 1] =
 
309
            otp_calcs[otp_calc_ptr - 1] * otp_calcs[otp_calc_ptr];
 
310
        incr(otp_pc);
 
311
        decr(otp_calc_ptr);
 
312
        break;
 
313
    case otp_div:
 
314
        otp_calcs[otp_calc_ptr - 1] =
 
315
            otp_calcs[otp_calc_ptr - 1] / otp_calcs[otp_calc_ptr];
 
316
        incr(otp_pc);
 
317
        decr(otp_calc_ptr);
 
318
        break;
 
319
    case otp_mod:
 
320
        otp_calcs[otp_calc_ptr - 1] =
 
321
            otp_calcs[otp_calc_ptr - 1] % otp_calcs[otp_calc_ptr];
 
322
        incr(otp_pc);
 
323
        decr(otp_calc_ptr);
 
324
        break;
 
325
    case otp_lookup:
 
326
        if (otp_calcs[otp_calc_ptr] >=
 
327
            ocp_table_no(otp_input_ocp, otp_calcs[otp_calc_ptr - 1])) {
 
328
            tsuccumb("bad OCP program -- table index not valid");
 
329
        }
 
330
        otp_calcs[otp_calc_ptr - 1] =
 
331
            ocp_table_entry(otp_input_ocp, otp_calcs[otp_calc_ptr - 1],
 
332
                            otp_calcs[otp_calc_ptr]);
 
333
        incr(otp_pc);
 
334
        decr(otp_calc_ptr);
 
335
        break;
 
336
    case otp_push_num:
 
337
        incr(otp_calc_ptr);
 
338
        if (otp_calc_ptr >= ocp_stack_size)
 
339
            overflow_ocp_stack_size();
 
340
        otp_calcs[otp_calc_ptr] = otp_arg;
 
341
        incr(otp_pc);
 
342
        break;
 
343
    case otp_push_char:
 
344
        otp_get_char(otp_arg);
 
345
        incr(otp_calc_ptr);
 
346
        if (otp_calc_ptr >= ocp_stack_size)
 
347
            overflow_ocp_stack_size();
 
348
        otp_calcs[otp_calc_ptr] = otp_calculated_char;
 
349
        incr(otp_pc);
 
350
        break;
 
351
    case otp_push_lchar:
 
352
        otp_get_char(otp_no_input_chars - otp_arg);
 
353
        incr(otp_calc_ptr);
 
354
        if (otp_calc_ptr >= ocp_stack_size)
 
355
            overflow_ocp_stack_size();
 
356
        otp_calcs[otp_calc_ptr] = otp_calculated_char;
 
357
        incr(otp_pc);
 
358
        break;
 
359
 
 
360
        /* Run the |otp_state| instructions */
 
361
    case otp_state_change:
 
362
        otp_input_start = otp_input_last;
 
363
        for (otp_counter = 1; otp_counter <= (otp_stack_new - otp_stack_used);
 
364
             otp_counter++) {
 
365
            otp_stack_buf[otp_counter] =
 
366
                otp_stack_buf[otp_counter + otp_stack_used];
 
367
        }
 
368
        otp_stack_new = otp_stack_new - otp_stack_used;
 
369
        otp_stack_last = otp_stack_new;
 
370
        otp_stack_used = 0;
 
371
        otp_states[otp_state_ptr] = otp_arg;
 
372
        otp_pc = 0;
 
373
        break;
 
374
    case otp_state_push:
 
375
        otp_input_start = otp_input_last;
 
376
        for (otp_counter = 1; otp_counter <= (otp_stack_new - otp_stack_used);
 
377
             otp_counter++) {
 
378
            otp_stack_buf[otp_counter] =
 
379
                otp_stack_buf[otp_counter + otp_stack_used];
 
380
        };
 
381
        otp_stack_new = otp_stack_new - otp_stack_used;
 
382
        otp_stack_last = otp_stack_new;
 
383
        otp_stack_used = 0;
 
384
        incr(otp_state_ptr);
 
385
        if (otp_state_ptr >= ocp_stack_size)
 
386
            overflow_ocp_stack_size();
 
387
        otp_states[otp_state_ptr] = otp_arg;
 
388
        otp_pc = 0;
 
389
        break;
 
390
    case otp_state_pop:
 
391
        otp_input_start = otp_input_last;
 
392
        for (otp_counter = 1; otp_counter <= (otp_stack_new - otp_stack_used);
 
393
             otp_counter++) {
 
394
            otp_stack_buf[otp_counter] =
 
395
                otp_stack_buf[otp_counter + otp_stack_used];
 
396
        }
 
397
        otp_stack_new = otp_stack_new - otp_stack_used;
 
398
        otp_stack_last = otp_stack_new;
 
399
        otp_stack_used = 0;
 
400
        if (otp_state_ptr > 0)
 
401
            decr(otp_state_ptr);
 
402
        otp_pc = 0;
 
403
        break;
 
404
 
 
405
        /* Run the |otp_left| instructions */
 
406
    case otp_left_start:
 
407
        otp_input_start = otp_input_last;
 
408
        otp_input_last = otp_input_start;
 
409
        otp_stack_used = 0;
 
410
        if ((otp_stack_last == 0) && (otp_input_last >= otp_input_end)) {
 
411
            otp_finished = true;
 
412
        } else if ((otp_stack_used < otp_stack_last)) {
 
413
            incr(otp_stack_used);       /* no overflow problem */
 
414
            otp_input_char = otp_stack_buf[otp_stack_used];
 
415
            otp_no_input_chars = 1;
 
416
            incr(otp_pc);
 
417
        } else {
 
418
            incr(otp_input_last);       /* no overflow problem */
 
419
            otp_input_char = otp_input_buf[otp_input_last];
 
420
            otp_no_input_chars = 1;
 
421
            incr(otp_pc);
 
422
        }
 
423
        break;
 
424
    case otp_left_return:
 
425
        otp_input_last = otp_input_start;
 
426
        otp_stack_used = 0;
 
427
        if ((otp_stack_used < otp_stack_last)) {
 
428
            incr(otp_stack_used);       /* no overflow problem */
 
429
            otp_input_char = otp_stack_buf[otp_stack_used];
 
430
            otp_no_input_chars = 1;
 
431
            incr(otp_pc);
 
432
        } else {
 
433
            incr(otp_input_last);       /* no overflow problem */
 
434
            otp_input_char = otp_input_buf[otp_input_last];
 
435
            otp_no_input_chars = 1;
 
436
            incr(otp_pc);
 
437
        }
 
438
        break;
 
439
    case otp_left_backup:
 
440
        if (otp_input_start < otp_input_last) {
 
441
            decr(otp_input_last);
 
442
            otp_input_char = otp_input_buf[otp_input_last];
 
443
        } else {
 
444
            decr(otp_stack_used);
 
445
            otp_input_char = otp_stack_buf[otp_stack_used];
 
446
        }
 
447
        decr(otp_no_input_chars);
 
448
        incr(otp_pc);
 
449
        break;
 
450
 
 
451
        /* Run the |otp_goto| instructions */
 
452
    case otp_goto:
 
453
        otp_pc = otp_arg;
 
454
        break;
 
455
    case otp_goto_ne:
 
456
        otp_first_arg = otp_arg;
 
457
        incr(otp_pc);
 
458
        otp_set_instruction();
 
459
        if (otp_input_char != otp_first_arg) {
 
460
            otp_pc = otp_arg;
 
461
        } else {
 
462
            incr(otp_pc);
 
463
        }
 
464
        break;
 
465
    case otp_goto_eq:
 
466
        otp_first_arg = otp_arg;
 
467
        incr(otp_pc);
 
468
        otp_set_instruction();
 
469
        if (otp_input_char == otp_first_arg) {
 
470
            otp_pc = otp_arg;
 
471
        } else {
 
472
            incr(otp_pc);
 
473
        }
 
474
        break;
 
475
    case otp_goto_lt:
 
476
        otp_first_arg = otp_arg;
 
477
        incr(otp_pc);
 
478
        otp_set_instruction();
 
479
        if (otp_input_char < otp_first_arg) {
 
480
            otp_pc = otp_arg;
 
481
        } else {
 
482
            incr(otp_pc);
 
483
        }
 
484
        break;
 
485
    case otp_goto_le:
 
486
        otp_first_arg = otp_arg;
 
487
        incr(otp_pc);
 
488
        otp_set_instruction();
 
489
        if (otp_input_char <= otp_first_arg) {
 
490
            otp_pc = otp_arg;
 
491
        } else {
 
492
            incr(otp_pc);
 
493
        }
 
494
        break;
 
495
    case otp_goto_gt:
 
496
        otp_first_arg = otp_arg;
 
497
        incr(otp_pc);
 
498
        otp_set_instruction();
 
499
        if (otp_input_char > otp_first_arg) {
 
500
            otp_pc = otp_arg;
 
501
        } else {
 
502
            incr(otp_pc);
 
503
        }
 
504
        break;
 
505
    case otp_goto_ge:
 
506
        otp_first_arg = otp_arg;
 
507
        incr(otp_pc);
 
508
        otp_set_instruction();
 
509
        if (otp_input_char >= otp_first_arg) {
 
510
            otp_pc = otp_arg;
 
511
        } else {
 
512
            incr(otp_pc);
 
513
        }
 
514
        break;
 
515
    case otp_goto_no_advance:
 
516
        if (otp_stack_used < otp_stack_last) {
 
517
            incr(otp_stack_used);       /* no overflow problem */
 
518
            otp_input_char = otp_stack_buf[otp_stack_used];
 
519
            incr(otp_no_input_chars);   /* no overflow problem */
 
520
            incr(otp_pc);
 
521
        } else if (otp_input_last >= otp_input_end) {
 
522
            otp_pc = otp_arg;
 
523
        } else {
 
524
            incr(otp_input_last);       /* no overflow problem */
 
525
            otp_input_char = otp_input_buf[otp_input_last];
 
526
            incr(otp_no_input_chars);   /* no overflow problem */
 
527
            incr(otp_pc);
 
528
        }
 
529
        break;
 
530
    case otp_goto_beg:
 
531
        if (otp_input_last == 0) {
 
532
            otp_pc = otp_arg;
 
533
        } else {
 
534
            incr(otp_pc);
 
535
        }
 
536
        break;
 
537
    case otp_goto_end:
 
538
        if (otp_input_last >= otp_input_end) {
 
539
            otp_pc = otp_arg;
 
540
        } else {
 
541
            incr(otp_pc);
 
542
        }
 
543
        break;
 
544
 
 
545
        /* Run the |otp_stop| instruction */
 
546
    case otp_stop:
 
547
        otp_input_start = otp_input_last;
 
548
        for (otp_counter = 1; otp_counter <= (otp_stack_new - otp_stack_used);
 
549
             otp_counter++) {
 
550
            otp_stack_buf[otp_counter] =
 
551
                otp_stack_buf[otp_counter + otp_stack_used];
 
552
        }
 
553
        otp_stack_new = otp_stack_new - otp_stack_used;
 
554
        otp_stack_last = otp_stack_new;
 
555
        otp_stack_used = 0;
 
556
        otp_pc = 0;
 
557
        break;
 
558
 
 
559
    default:
 
560
        tsuccumb("bad OCP program -- unknown instruction");
 
561
        break;
 
562
    }
 
563
}
 
564
 
 
565
void run_external_ocp(char *external_ocp_name)
 
566
{
 
567
    char *in_file_name;
 
568
    char *out_file_name;
 
569
    FILE *in_file;
 
570
    FILE *out_file;
 
571
    int in_file_fd;
 
572
    int out_file_fd;
 
573
    char command_line[400];
 
574
    int i;
 
575
    unsigned c;
 
576
    int c_in;
 
577
#ifdef WIN32
 
578
    char *tempenv;
 
579
 
 
580
#  define null_string(s) ((s == NULL) || (*s == '\0'))
 
581
 
 
582
    tempenv = getenv("TMPDIR");
 
583
    if (null_string(tempenv))
 
584
        tempenv = getenv("TEMP");
 
585
    if (null_string(tempenv))
 
586
        tempenv = getenv("TMP");
 
587
    if (null_string(tempenv))
 
588
        tempenv = "c:/tmp";     /* "/tmp" is not good if we are on a CD-ROM */
 
589
    in_file_name = concat(tempenv, "/__aleph__in__XXXXXX");
 
590
    mktemp(in_file_name);
 
591
    in_file = fopen(in_file_name, FOPEN_WBIN_MODE);
 
592
#else
 
593
    in_file_name = strdup("/tmp/__aleph__in__XXXXXX");
 
594
    in_file_fd = mkstemp(in_file_name);
 
595
    in_file = fdopen(in_file_fd, FOPEN_WBIN_MODE);
 
596
#endif                          /* WIN32 */
 
597
 
 
598
 
 
599
    for (i = 1; i <= otp_input_end; i++) {
 
600
        c = otp_input_buf[i];
 
601
        if (c > 0xffff) {
 
602
            fprintf(stderr, "Aleph does not currently support 31-bit chars\n");
 
603
            exit(1);
 
604
        }
 
605
        if (c > 0x4000000) {
 
606
            fputc(0xfc | ((c >> 30) & 0x1), in_file);
 
607
            fputc(0x80 | ((c >> 24) & 0x3f), in_file);
 
608
            fputc(0x80 | ((c >> 18) & 0x3f), in_file);
 
609
            fputc(0x80 | ((c >> 12) & 0x3f), in_file);
 
610
            fputc(0x80 | ((c >> 6) & 0x3f), in_file);
 
611
            fputc(0x80 | (c & 0x3f), in_file);
 
612
        } else if (c > 0x200000) {
 
613
            fputc(0xf8 | ((c >> 24) & 0x3), in_file);
 
614
            fputc(0x80 | ((c >> 18) & 0x3f), in_file);
 
615
            fputc(0x80 | ((c >> 12) & 0x3f), in_file);
 
616
            fputc(0x80 | ((c >> 6) & 0x3f), in_file);
 
617
            fputc(0x80 | (c & 0x3f), in_file);
 
618
        } else if (c > 0x10000) {
 
619
            fputc(0xf0 | ((c >> 18) & 0x7), in_file);
 
620
            fputc(0x80 | ((c >> 12) & 0x3f), in_file);
 
621
            fputc(0x80 | ((c >> 6) & 0x3f), in_file);
 
622
            fputc(0x80 | (c & 0x3f), in_file);
 
623
        } else if (c > 0x800) {
 
624
            fputc(0xe0 | ((c >> 12) & 0xf), in_file);
 
625
            fputc(0x80 | ((c >> 6) & 0x3f), in_file);
 
626
            fputc(0x80 | (c & 0x3f), in_file);
 
627
        } else if (c > 0x80) {
 
628
            fputc(0xc0 | ((c >> 6) & 0x1f), in_file);
 
629
            fputc(0x80 | (c & 0x3f), in_file);
 
630
        } else {
 
631
            fputc(c & 0x7f, in_file);
 
632
        }
 
633
    }
 
634
    fclose(in_file);
 
635
 
 
636
#define advance_cin if ((c_in = fgetc(out_file)) == -1) { \
 
637
                         fprintf(stderr, "File contains bad char\n"); \
 
638
                         goto end_of_while; \
 
639
                    }
 
640
 
 
641
#ifdef WIN32
 
642
    out_file_name = concat(tempenv, "/__aleph__out__XXXXXX");
 
643
    mktemp(out_file_name);
 
644
    out_file = fopen(out_file_name, FOPEN_RBIN_MODE);
 
645
#else
 
646
    out_file_name = strdup("/tmp/__aleph__out__XXXXXX");
 
647
    out_file_fd = mkstemp(out_file_name);
 
648
    out_file = fdopen(out_file_fd, FOPEN_RBIN_MODE);
 
649
#endif
 
650
 
 
651
    sprintf(command_line, "%s <%s >%s\n",
 
652
            external_ocp_name + 1, in_file_name, out_file_name);
 
653
    system(command_line);
 
654
    otp_output_end = 0;
 
655
    otp_output_buf[otp_output_end] = 0;
 
656
    while ((c_in = fgetc(out_file)) != -1) {
 
657
        if (c_in >= 0xfc) {
 
658
            c = (c_in & 0x1) << 30;
 
659
            advance_cin;
 
660
            c |= (c_in & 0x3f) << 24;
 
661
            advance_cin;
 
662
            c |= (c_in & 0x3f) << 18;
 
663
            advance_cin;
 
664
            c |= (c_in & 0x3f) << 12;
 
665
            advance_cin;
 
666
            c |= (c_in & 0x3f) << 6;
 
667
            advance_cin;
 
668
            c |= c_in & 0x3f;
 
669
        } else if (c_in >= 0xf8) {
 
670
            c = (c_in & 0x3) << 24;
 
671
            advance_cin;
 
672
            c |= (c_in & 0x3f) << 18;
 
673
            advance_cin;
 
674
            c |= (c_in & 0x3f) << 12;
 
675
            advance_cin;
 
676
            c |= (c_in & 0x3f) << 6;
 
677
            advance_cin;
 
678
            c |= c_in & 0x3f;
 
679
        } else if (c_in >= 0xf0) {
 
680
            c = (c_in & 0x7) << 18;
 
681
            advance_cin;
 
682
            c |= (c_in & 0x3f) << 12;
 
683
            advance_cin;
 
684
            c |= (c_in & 0x3f) << 6;
 
685
            advance_cin;
 
686
            c |= c_in & 0x3f;
 
687
        } else if (c_in >= 0xe0) {
 
688
            c = (c_in & 0xf) << 12;
 
689
            advance_cin;
 
690
            c |= (c_in & 0x3f) << 6;
 
691
            advance_cin;
 
692
            c |= c_in & 0x3f;
 
693
        } else if (c_in >= 0x80) {
 
694
            c = (c_in & 0x1f) << 6;
 
695
            advance_cin;
 
696
            c |= c_in & 0x3f;
 
697
        } else {
 
698
            c = c_in & 0x7f;
 
699
        }
 
700
        otp_output_buf[++otp_output_end] = c;
 
701
    }
 
702
    fclose(out_file);
 
703
 
 
704
  end_of_while:
 
705
    remove(in_file_name);
 
706
    remove(out_file_name);
 
707
}
 
708
 
 
709
void run_ocp(void)
 
710
{
 
711
    int t = 0;
 
712
    halfword otp_i;
 
713
    halfword otp_counter;
 
714
    /* The OTP input buffer is an array of 16-bit values.
 
715
       The range |0xD800| \dots |0xDFFF| is used for surrogate pairs, 
 
716
       so it cannot be used for simple 16-bit values like it is in 
 
717
       Omega, and incompatibility with Aleph is unavoidable. 
 
718
     */
 
719
 
 
720
    otp_init_input_end = 0;
 
721
    while ((cur_cmd == letter_cmd) || (cur_cmd == other_char_cmd) ||
 
722
           (cur_cmd == char_given_cmd) || (cur_cmd == spacer_cmd)) {
 
723
        incr(otp_init_input_end);
 
724
        if (otp_init_input_end > ocp_buf_size)
 
725
            overflow_ocp_buf_size();
 
726
        /* |cur_chr| can cover the full range |0..0x10FFFF| */
 
727
        if (cur_chr < 0x10000) {
 
728
            otp_init_input_buf[otp_init_input_end] = cur_chr;
 
729
        } else {
 
730
            otp_init_input_buf[otp_init_input_end] =
 
731
                ((cur_chr - 0x10000) / 0x400) + 0xD800;
 
732
            incr(otp_init_input_end);
 
733
            if (otp_init_input_end > ocp_buf_size)
 
734
                overflow_ocp_buf_size();
 
735
            otp_init_input_buf[otp_init_input_end] =
 
736
                ((cur_chr - 0x10000) % 0x400) + 0xDC00;
 
737
        }
 
738
        get_token();
 
739
        if ((cur_cmd != letter_cmd) && (cur_cmd != other_char_cmd) &&
 
740
            (cur_cmd != char_given_cmd)) {
 
741
            x_token();
 
742
            if (cur_cmd == char_num_cmd) {
 
743
                scan_char_num();
 
744
                cur_cmd = other_char_cmd;
 
745
                cur_chr = cur_val;
 
746
            }
 
747
        }
 
748
    }
 
749
    back_input();
 
750
    otp_input_end = otp_init_input_end;
 
751
    for (otp_i = 0; otp_i <= otp_init_input_end; otp_i++) {
 
752
        otp_input_buf[otp_i] = otp_init_input_buf[otp_i];
 
753
    }
 
754
 
 
755
    otp_input_ocp = active_ocp(active_real);
 
756
    if (otp_input_ocp == 0) {
 
757
        tex_error("Null ocp being used: all input lost", NULL);
 
758
        otp_output_end = 0;
 
759
    } else if (ocp_external(otp_input_ocp) == 0) {
 
760
        otp_input_start = 0;
 
761
        otp_input_last = 0;
 
762
        otp_stack_used = 0;
 
763
        otp_stack_last = 0;
 
764
        otp_stack_new = 0;
 
765
        otp_output_end = 0;
 
766
        otp_pc = 0;
 
767
        otp_finished = false;
 
768
        otp_calc_ptr = 0;
 
769
        otp_calcs[otp_calc_ptr] = 0;
 
770
        otp_state_ptr = 0;
 
771
        otp_states[otp_state_ptr] = 0;
 
772
        while (!otp_finished)
 
773
            run_otp();
 
774
    } else {
 
775
        /* k=0;  ? */
 
776
        char *cmd = makecstring(ocp_external(otp_input_ocp));
 
777
        char *arg = makecstring(ocp_external_arg(otp_input_ocp));
 
778
        char *cmdline = xmalloc(strlen(cmd) + strlen(arg) + 3);
 
779
        strcpy(cmdline, cmd);
 
780
        strcat(cmdline, " ");
 
781
        strcat(cmdline, arg);
 
782
        xfree(cmd);
 
783
        xfree(arg);
 
784
        run_external_ocp(cmdline);
 
785
    }
 
786
 
 
787
 
 
788
    /* The OTP output buffer is an array of 16-bit values. To convert back
 
789
       to the |buffer| it has to be re-encoded into UTF-8. 
 
790
     */
 
791
 
 
792
    if ((first + otp_output_end) >= ocp_buf_size)
 
793
        overflow_ocp_buf_size();
 
794
    push_input();
 
795
    current_ocp_lstack = active_lstack_no(active_real);
 
796
    current_ocp_no = active_counter(active_real);
 
797
    istate = mid_line;
 
798
    istart = first;
 
799
    last = istart;
 
800
    iloc = istart;
 
801
    line_catcode_table = DEFAULT_CAT_TABLE;
 
802
    line_partial = false;
 
803
    for (otp_counter = 1; otp_counter <= otp_output_end; otp_counter++) {
 
804
        /* convert back to utf-8  */
 
805
        t = otp_output_buf[otp_counter];
 
806
        if (otp_counter < otp_output_end) {
 
807
            if ((t >= 0xD800) && (t < 0xDC00)) {
 
808
                if ((otp_output_buf[otp_counter + 1] >= 0xDC00)
 
809
                    && (otp_output_buf[otp_counter + 1] < 0xE000)) {
 
810
                    incr(otp_counter);
 
811
                    t = (t - 0xD800) * 0x400 + (otp_output_buf[otp_counter] -
 
812
                                                0xDC00) + 0x10000;
 
813
                }
 
814
            } else if ((t >= 0xDC00) && (t < 0xE000)) {
 
815
                if ((otp_output_buf[otp_counter + 1] >= 0xD800)
 
816
                    && (otp_output_buf[otp_counter + 1] < 0xDC00)) {
 
817
                    incr(otp_counter);
 
818
                    t = (otp_output_buf[otp_counter] - 0xD800) * 0x400 + (t -
 
819
                                                                          0xDC00)
 
820
                        + 0x10000;
 
821
                }
 
822
            }
 
823
        }
 
824
        if (t <= 0x7F) {
 
825
            buffer[last] = t;
 
826
        } else if (t <= 0x7FF) {
 
827
            buffer[last] = 0xC0 + t / 0x40;
 
828
            incr(last);
 
829
            check_buffer();
 
830
            buffer[last] = 0x80 + t % 0x40;
 
831
        } else if (t <= 0xFFFF) {
 
832
            buffer[last] = 0xE0 + t / 0x1000;
 
833
            incr(last);
 
834
            check_buffer();
 
835
            buffer[last] = 0x80 + (t % 0x1000) / 0x40;
 
836
            incr(last);
 
837
            check_buffer();
 
838
            buffer[last] = 0x80 + (t % 0x1000) % 0x40;
 
839
        } else {
 
840
            buffer[last] = 0xF0 + t / 0x40000;
 
841
            incr(last);
 
842
            check_buffer();
 
843
            buffer[last] = 0x80 + (t % 0x40000) / 0x1000;
 
844
            incr(last);
 
845
            check_buffer();
 
846
            buffer[last] = 0x80 + ((t % 0x40000) % 0x1000) / 0x40;
 
847
            incr(last);
 
848
            check_buffer();
 
849
            buffer[last] = 0x80 + ((t % 0x40000) % 0x1000) % 0x40;
 
850
        }
 
851
        incr(last);
 
852
        check_buffer();
 
853
    }
 
854
    ilimit = last - 1;
 
855
    if (t > 0xFFFF)
 
856
        decr(ilimit);
 
857
    if (t > 0x7FF)
 
858
        decr(ilimit);
 
859
    if (t > 0x7F)
 
860
        decr(ilimit);
 
861
    first = last;
 
862
 
 
863
}
 
864
 
 
865
 
 
866
void initialize_ocp_buffers(int ocp_buf_size, int ocp_stack_size)
 
867
{
 
868
    otp_init_input_buf = xmallocarray(quarterword, ocp_buf_size);
 
869
    otp_input_buf = xmallocarray(quarterword, ocp_buf_size);
 
870
    otp_output_buf = xmallocarray(quarterword, ocp_buf_size);
 
871
    otp_stack_buf = xmallocarray(quarterword, ocp_stack_size);
 
872
    otp_calcs = xmallocarray(halfword, ocp_stack_size);
 
873
    otp_states = xmallocarray(halfword, ocp_stack_size);
 
874
}
 
875
 
 
876
boolean is_last_ocp(scaled llstack_no, int counter)
 
877
{
 
878
    active_min_ptr = equiv(ocp_active_min_ptr_base);
 
879
    active_max_ptr = equiv(ocp_active_max_ptr_base);
 
880
    active_real = active_min_ptr;
 
881
    while ((active_real < active_max_ptr) &&
 
882
           (active_lstack_no(active_real) < llstack_no)) {
 
883
        active_real = active_real + 2;
 
884
    }
 
885
    while ((active_real < active_max_ptr) &&
 
886
           (active_lstack_no(active_real) == llstack_no) &&
 
887
           (active_counter(active_real) <= counter)) {
 
888
        active_real = active_real + 2;
 
889
    }
 
890
    return (active_real == active_max_ptr);
 
891
}
 
892
 
 
893
void print_active_ocps(void)
 
894
{
 
895
    int i;
 
896
    tprint_nl("Active ocps: [");
 
897
    i = active_min_ptr;
 
898
    while (i < active_max_ptr) {
 
899
        tprint("(");
 
900
        print_scaled(active_lstack_no(i));
 
901
        tprint(",");
 
902
        print_int(active_counter(i));
 
903
        tprint(",");
 
904
        print_esc(cs_text(ocp_id_base + active_ocp(i)));
 
905
        tprint(")");
 
906
        if (i != (active_max_ptr - 2))
 
907
            tprint(",");
 
908
        i = i + 2;
 
909
    }
 
910
    tprint("]");
 
911
}
 
912
 
 
913
void add_ocp_stack(int min_index, scaled min_value)
 
914
{
 
915
    ocp_lstack_index p;
 
916
    scaled llstack_no;
 
917
    int counter;
 
918
    scaled m;
 
919
    m = min_value;              /* TH: whatever this is .. */
 
920
    p = ocp_list_lstack(holding[min_index]);
 
921
    llstack_no = ocp_list_lstack_no(holding[min_index]);
 
922
    counter = 0;
 
923
    while (!(is_null_ocp_lstack(p))) {
 
924
        active_ocp(active_max_ptr) = ocp_lstack_ocp(p);
 
925
        active_counter(active_max_ptr) = counter;
 
926
        active_lstack_no(active_max_ptr) = llstack_no;
 
927
        p = ocp_lstack_lnext(p);
 
928
        active_max_ptr = active_max_ptr + 2;
 
929
        incr(counter);          /* no overflow problem */
 
930
    }
 
931
}
 
932
 
 
933
void active_compile(void)
 
934
{
 
935
    int i;
 
936
    int min_index;
 
937
    scaled min_stack_ocp;
 
938
    scaled old_min;
 
939
    int max_active;
 
940
    scaled stack_value;
 
941
    active_min_ptr = active_max_ptr;
 
942
    min_stack_ocp = ocp_maxint;
 
943
    max_active = equiv(ocp_active_number_base) - 1;
 
944
    min_index = max_active;     /* TH I hope ...  */
 
945
    for (i = max_active; i >= 0; i--) {
 
946
        holding[i] = ocp_list_list[ocp_active_base + i];
 
947
        stack_value = ocp_list_lstack_no(holding[i]);
 
948
        if (stack_value < min_stack_ocp) {
 
949
            min_index = i;
 
950
            min_stack_ocp = stack_value;
 
951
        }
 
952
    }
 
953
    while (min_stack_ocp < ocp_maxint) {
 
954
        add_ocp_stack(min_index, min_stack_ocp);
 
955
        old_min = min_stack_ocp;
 
956
        min_stack_ocp = ocp_maxint;
 
957
        for (i = max_active; i >= 0; i--) {
 
958
            stack_value = ocp_list_lstack_no(holding[i]);
 
959
            while (old_min == stack_value) {
 
960
                holding[i] = ocp_list_lnext(holding[i]);
 
961
                stack_value = ocp_list_lstack_no(holding[i]);
 
962
            }
 
963
            if (stack_value < min_stack_ocp) {
 
964
                min_index = i;
 
965
                min_stack_ocp = stack_value;
 
966
            }
 
967
        }
 
968
    }
 
969
}
 
970
 
 
971
void do_push_ocp_list(small_number a)
 
972
{
 
973
    halfword ocp_list_no;
 
974
    halfword old_number;
 
975
    int i;
 
976
    scan_ocp_list_ident();
 
977
    ocp_list_no = cur_val;
 
978
    old_number = equiv(ocp_active_number_base);
 
979
    define(ocp_active_base + old_number, data_cmd, ocp_list_no);
 
980
    define(ocp_active_number_base, data_cmd, (old_number + 1));
 
981
    if (ocp_trace_level == 1) {
 
982
        tprint_nl("New active ocp list: {");
 
983
        for (i = old_number; i >= 0; i--) {
 
984
            print_esc(ocp_list_id_text(equiv(ocp_active_base + i)));
 
985
            tprint("=");
 
986
            print_ocp_list(ocp_list_list[equiv(ocp_active_base + i)]);
 
987
            if (i != 0)
 
988
                tprint(",");
 
989
        }
 
990
        tprint("}");
 
991
    }
 
992
    active_compile();
 
993
    define(ocp_active_min_ptr_base, data_cmd, active_min_ptr);
 
994
    define(ocp_active_max_ptr_base, data_cmd, active_max_ptr);
 
995
}
 
996
 
 
997
void do_pop_ocp_list(small_number a)
 
998
{
 
999
    halfword old_number;
 
1000
    int i;
 
1001
    old_number = equiv(ocp_active_number_base);
 
1002
    if (old_number == 0) {
 
1003
        print_err("No active ocp lists to be popped");
 
1004
    } else {
 
1005
        define(ocp_active_number_base, data_cmd, (old_number - 1));
 
1006
        if (ocp_trace_level == 1) {
 
1007
            tprint_nl("New active ocp list: {");
 
1008
            for (i = (old_number - 2); i >= 0; i++) {
 
1009
                print_esc(ocp_list_id_text(equiv(ocp_active_base + i)));
 
1010
                tprint("=");
 
1011
                print_ocp_list(ocp_list_list[equiv(ocp_active_base + i)]);
 
1012
                if (i != 0)
 
1013
                    tprint(",");
 
1014
            }
 
1015
            tprint("}");
 
1016
        }
 
1017
        active_compile();
 
1018
        define(ocp_active_min_ptr_base, data_cmd, active_min_ptr);
 
1019
        define(ocp_active_max_ptr_base, data_cmd, active_max_ptr);
 
1020
    }
 
1021
}
 
1022
 
 
1023
void do_clear_ocp_lists(small_number a)
 
1024
{
 
1025
    define(ocp_active_number_base, data_cmd, 0);
 
1026
    active_compile();
 
1027
    define(ocp_active_min_ptr_base, data_cmd, active_min_ptr);
 
1028
    define(ocp_active_max_ptr_base, data_cmd, active_max_ptr);
 
1029
}
 
1030
 
 
1031
 
 
1032
void dump_active_ocp_info(void)
 
1033
{
 
1034
    int k;
 
1035
    dump_int(active_min_ptr);
 
1036
    dump_int(active_max_ptr);
 
1037
    for (k = 0; k <= active_max_ptr - 1; k++)
 
1038
        dump_wd(active_info[k]);
 
1039
    if (active_max_ptr > 0) {
 
1040
        print_ln();
 
1041
        print_int(active_max_ptr);
 
1042
        tprint(" words of active ocps");
 
1043
    }
 
1044
}
 
1045
 
 
1046
void undump_active_ocp_info(void)
 
1047
{
 
1048
    int k;
 
1049
    undump_int(active_min_ptr);
 
1050
    /* undump_size(0)(active_mem_size)('active start point')(active_min_ptr); */
 
1051
    undump_int(active_max_ptr);
 
1052
    /*  undump_size(0)(active_mem_size)('active mem size')(active_max_ptr); */
 
1053
    for (k = 0; k <= active_max_ptr - 1; k++)
 
1054
        undump_wd(active_info[k]);
 
1055
}