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

« 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: 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
 
/* 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
 
}