3
Copyright 2009 Taco Hoekwater <taco@luatex.org>
5
This file is part of LuaTeX.
7
LuaTeX is free software; you can redistribute it and/or modify it under
8
the terms of the GNU General Public License as published by the Free
9
Software Foundation; either version 2 of the License, or (at your
10
option) any later version.
12
LuaTeX is distributed in the hope that it will be useful, but WITHOUT
13
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15
License for more details.
17
You should have received a copy of the GNU General Public License along
18
with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */
23
static const char _svn_version[] =
24
"$Id: readocp.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/readocp.c $";
26
extern int program_name_set; /* in lkpselib.c */
28
static char *b_test_in(char *nam)
30
if (program_name_set) {
31
return (char *) kpse_find_file(nam, kpse_program_binary_format, true);
39
static unsigned char *ocp_buffer = NULL; /* byte buffer for ocp files */
40
static int ocp_size = 0; /* total size of the ocp file */
41
static int ocp_cur = 0; /* index into |ocp_buffer| */
43
void init_null_ocp(str_number a, str_number n)
46
allocate_ocp_table(null_ocp, 17);
47
ocp_file_size(null_ocp) = 17;
48
ocp_name(null_ocp) = n;
49
ocp_area(null_ocp) = a;
50
ocp_external(null_ocp) = 0;
51
ocp_external_arg(null_ocp) = 0;
52
ocp_input(null_ocp) = 1;
53
ocp_output(null_ocp) = 1;
54
ocp_no_tables(null_ocp) = 0;
55
ocp_no_states(null_ocp) = 1;
56
ocp_table_base(f) = offset_ocp_info;
57
ocp_state_base(f) = offset_ocp_info;
58
ocp_info(null_ocp, offset_ocp_info) = offset_ocp_info + 2; /* number of entries */
59
ocp_info(null_ocp, offset_ocp_info + 1) = offset_ocp_info + 5; /* number of entries */
60
ocp_info(null_ocp, offset_ocp_info + 2) = 23; /* |OTP_LEFT_START| */
61
ocp_info(null_ocp, offset_ocp_info + 3) = 3; /* |OTP_RIGHT_CHAR| */
62
ocp_info(null_ocp, offset_ocp_info + 4) = 36; /* |OTP_STOP| */
67
/* $\Omega$ checks the information of a \.{OCP} file for validity as the
68
file is being read in, so that no further checks will be needed when
69
typesetting is going on. The somewhat tedious subroutine that does this
70
is called |read_ocp_info|. It has three parameters: the user ocp
71
identifier~|u|, and the file name and area strings |nom| and |aire|.
73
The subroutine opens and closes a global file variable called |ocp_file|.
74
It returns the value of the internal ocp number that was just loaded.
75
If an error is detected, an error message is issued and no ocp
76
information is stored; |null_ocp| is returned in this case.
80
/* do this when the \.{OCP} data is wrong */
81
#define ocp_abort(A) do { \
82
tprint("OCP file error ("); \
83
tprint(A); tprint(")"); print_ln(); \
87
/* macros for reading and storing ocp data */
89
#define add_to_ocp_info(A) ocp_tables[f][ocpmem_run_ptr++]=(A)
90
#define ocp_read(A) do { \
91
ocpword=ocp_buffer[ocp_cur++]; \
92
if (ocpword>127) ocp_abort("checking first octet"); \
93
ocpword=ocpword*0400+ocp_buffer[ocp_cur++]; \
94
ocpword=ocpword*0400+ocp_buffer[ocp_cur++]; \
95
ocpword=ocpword*0400+ocp_buffer[ocp_cur++]; \
99
#define ocp_read_all(A) ocp_read(A)
100
#define ocp_read_info do { ocp_read_all(ocpword); add_to_ocp_info(ocpword); } while (0)
104
/* input a \.{OCP} file */
106
read_ocp_info(pointer u, char *nom, char *aire, char *ext, boolean external_ocp)
108
boolean file_opened; /* was |ocp_file| successfully opened? */
111
char *cnam; /* C version of file name */
112
internal_ocp_number f; /* the new ocp's number */
113
internal_ocp_number g; /* the number to return */
115
ocp_index ocpmem_run_ptr;
116
int ocp_length, real_ocp_length; /* length of ocp file */
117
ocp_index previous_address;
120
int temp_ocp_no_tables;
121
int temp_ocp_no_states;
122
int i, new_offset, room_for_tables, room_for_states;
128
/* @<Check |ocp_file| exists@> */
129
cnam = xmalloc(strlen(nom) + strlen(aire) + strlen(ext) + 1);
130
sprintf(cnam, "%s%s%s", aire, nom, ext);
131
cnam = b_test_in(cnam);
133
ocp_abort("opening file");
135
allocate_ocp_table(f, 13);
136
ocp_file_size(f) = 13;
137
ocp_external(f) = maketexstring(cnam);
138
scan_string_argument();
139
ocp_external_arg(f) = cur_val;
140
ocp_name(f) = get_nullstr();
141
ocp_area(f) = get_nullstr();
142
ocp_state_base(f) = 0;
143
ocp_table_base(f) = 0;
146
ocp_info(f, offset_ocp_info) = 0;
152
/* @<Open |ocp_file| for input@>; */
153
char *cname = xmalloc(strlen(nom) + strlen(aire) + strlen(".ocp") + 1);
154
sprintf(cname, "%s%s.ocp", aire, nom);
155
if (ocp_buffer != NULL)
160
cnam = luatex_find_file(cname, find_ocp_file_callback);
161
callback_id = callback_defined(read_ocp_file_callback);
162
if (cnam && callback_id > 0) {
163
res = run_callback(callback_id, "S->bSd", cnam,
164
&file_opened, &ocp_buffer, &ocp_size);
166
ocp_abort("callback error");
168
ocp_abort("opening file");
170
FILE *ocp_file = NULL;
173
if (!luatex_open_input
174
(&ocp_file, cnam, kpse_ocp_format, FOPEN_RBIN_MODE, true))
175
ocp_abort("opening file");
177
res = read_ocp_file(ocp_file, &ocp_buffer, &ocp_size);
178
close_file(ocp_file);
180
ocp_abort("reading file");
183
ocp_abort("checking size");
185
/* @<Read the {\.{OCP}} file@>; */
187
ocpmem_run_ptr = offset_ocp_info;
188
ocp_read(ocp_length);
189
real_ocp_length = ocp_length - 7;
190
ocp_read_all(temp_ocp_input);
191
ocp_read_all(temp_ocp_output);
192
ocp_read_all(temp_ocp_no_tables);
193
ocp_read_all(room_for_tables);
194
ocp_read_all(temp_ocp_no_states);
195
ocp_read_all(room_for_states);
196
if (real_ocp_length !=
197
(temp_ocp_no_tables + room_for_tables +
198
temp_ocp_no_states + room_for_states))
199
ocp_abort("checking size");
200
real_ocp_length = real_ocp_length + 12 +
201
temp_ocp_no_states + temp_ocp_no_tables;
202
allocate_ocp_table(f, real_ocp_length);
204
ocp_external_arg(f) = 0;
205
ocp_file_size(f) = real_ocp_length;
206
ocp_input(f) = temp_ocp_input;
207
ocp_output(f) = temp_ocp_output;
208
ocp_no_tables(f) = temp_ocp_no_tables;
209
ocp_no_states(f) = temp_ocp_no_states;
210
ocp_table_base(f) = ocpmem_run_ptr;
211
if (ocp_no_tables(f) != 0) {
212
previous_address = ocpmem_run_ptr + 2 * (ocp_no_tables(f));
213
for (i = 1; i <= ocp_no_tables(f); i++) {
214
add_to_ocp_info(previous_address);
215
ocp_read_all(new_offset);
216
add_to_ocp_info(new_offset);
217
previous_address = previous_address + new_offset;
220
if (room_for_tables != 0) {
221
for (i = 1; i <= room_for_tables; i++) {
225
ocp_state_base(f) = ocpmem_run_ptr;
226
if (ocp_no_states(f) != 0) {
227
previous_address = ocpmem_run_ptr + 2 * (ocp_no_states(f));
228
for (i = 1; i <= ocp_no_states(f); i++) {
229
add_to_ocp_info(previous_address);
230
ocp_read_all(new_offset);
231
add_to_ocp_info(new_offset);
232
previous_address = previous_address + new_offset;
235
if (room_for_states != 0) {
236
for (i = 1; i <= room_for_states; i++) {
246
/* @<Report that the ocp won't be loaded@>; */
247
/* $\Omega$ does not give precise details about why it
248
rejects a particular \.{OCP} file. */
250
"I wasn't able to read the data for this ocp,",
251
"so I will ignore the ocp specification.",
255
char *c = makecstring(cs_text(u));
257
snprintf(errmsg, 255,
258
"Translation process \\%s=%s not loadable: Bad ocp file",
261
snprintf(errmsg, 255,
262
"Translation process \\%s=%s not loadable: ocp file not found",
266
tex_error(errmsg, hlp);
269
ocp_name(f) = maketexstring(nom);
270
ocp_area(f) = maketexstring(aire);