1 /* parse_ofm.h: Checking an existent OFM file
2 
3 This file is part of Omega,
4 which is based on the web2c distribution of TeX,
5 
6 Copyright (c) 1994--2001 John Plaice and Yannis Haralambous
7 Copyright (C) 2005, 2006 Roozbeh Pournader
8 
9 Omega is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13 
14 Omega is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Omega; if not, write to the Free Software Foundation, Inc.,
21 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
22 
23 */
24 
25 #include "cpascal.h"
26 #include "list_routines.h"
27 #include "header_routines.h"
28 #include "manifests.h"
29 #include "char_routines.h"
30 #include "ligkern_routines.h"
31 #include "out_ofm.h"
32 #include "extra_routines.h"
33 #include "param_routines.h"
34 #include "dimen_routines.h"
35 #include "error_routines.h"
36 #include "print_routines.h"
37 #include "out_routines.h"
38 #include "font_routines.h"
39 #include "parse_ofm.h"
40 #include "omfonts.h"
41 #include "manifests.h"
42 
43 unsigned top_char, top_width, top_height, top_depth, top_italic;
44 unsigned start_ptr, check_sum_pos, design_size_pos, scheme_pos;
45 unsigned seven_bit_flag_pos;
46 unsigned random_word_pos, header_length;
47 
48 unsigned ivalues_start,fvalues_start,mvalues_start,
49     rules_start,glues_start,penalties_start;
50 unsigned ivalues_base,fvalues_base,mvalues_base,
51     rules_base,glues_base,penalties_base;
52 unsigned char_base,width_base,height_base,depth_base,italic_base;
53 unsigned lig_kern_base,kern_base,exten_base,param_base;
54   /* base addresses for the subfiles */
55 unsigned char_start;
56 unsigned bytes_per_entry;
57 
58 unsigned lf;
59 boolean ofm_on;
60 unsigned start_pos;
61 unsigned family_pos;
62 unsigned ofm_ptr;
63 unsigned ncw;
64 unsigned ncl;
65 unsigned nce;
66 unsigned nco;
67 unsigned npc;
68 
69 static void
eval_two_bytes(unsigned * pos)70 eval_two_bytes(unsigned *pos) {
71   if (ofm[ofm_ptr]>127)
72       fatal_error_0("One of the subfile sizes (2) is negative");
73   *pos = ofm[ofm_ptr]*0x100 + ofm[ofm_ptr+1];
74   ofm_ptr += 2;
75 }
76 
77 static void
eval_four_bytes(unsigned * pos)78 eval_four_bytes(unsigned *pos) {
79   if (ofm[ofm_ptr]>127)
80       fatal_error_0("One of the subfile sizes (4) is negative");
81   *pos = ofm[ofm_ptr]*0x1000000 + ofm[ofm_ptr+1]*0x10000 +
82          ofm[ofm_ptr+2]*0x100   + ofm[ofm_ptr+3];
83   ofm_ptr += 4;
84 }
85 
86 static void ofm_organize(void);
87 static void ofm_read_simple(void);
88 static void ofm_read_rest(void);
89 
90 boolean changed = FALSE;
91 
92 void
parse_ofm(boolean read_ovf)93 parse_ofm(boolean read_ovf)
94 {
95     ofm_organize();
96     if (read_ovf == TRUE) input_ovf_file();
97     ofm_read_simple();
98     if (read_ovf == TRUE) input_ovf_fonts();
99     ofm_read_rest();
100     if (read_ovf == TRUE) input_ovf_chars();
101     print_characters(read_ovf);
102     if (changed) {
103         left();
104         out("COMMENT THE OFM FILE WAS BAD, SO THE DATA HAS BEEN CHANGED!");
105         right();
106     }
107 }
108 
109 /* parse_ofm ensures that all of the header entries are consistent.
110    The file is assumed to have been read in already, with the
111    contents in the ofm array (length_ofm bytes).
112 */
113 
114 void
ofm_organize(void)115 ofm_organize(void)
116 {
117     unsigned copies,i;
118 
119     ofm_on = false; ofm_level = OFM_NOLEVEL; lf = 0; lh = 0;
120     nco = 0; ncw = 0; npc = 0;
121     bc = 0; ec = 0; nw = 0; nh = 0; nd = 0; ni = 0;
122     nl = 0; nk = 0; ne = 0; np = 0;
123     nki = 0; nwi = 0; nkf = 0; nwf = 0;
124     nkm = 0; nwm = 0;
125     nkr = 0; nwr = 0; nkg = 0; nwg = 0;
126     nkp = 0; nwp = 0; font_dir = 0;
127 
128     if (length_ofm < 8)
129         fatal_error_0("File too short");
130     lf = ofm[0]*256 + ofm[1];
131     if (lf==0) { /* This is not a TFM file, it is an OFM-file */
132         ofm_on = TRUE;
133 
134         /* next line edited by Thomas Esser, based on a patch sent
135          * by Hossein Movahhedian. The old code had " + 1"
136          * instead of "+ OFM_LEVEL0" and caused lots of segfaults */
137         ofm_level = ofm[2]*0x100 + ofm[3] + OFM_LEVEL0;
138         if (ofm[4]>127)
139             fatal_error_0("File length is negative");
140         lf = ofm[4]*0x1000000 + ofm[5]*0x10000 + ofm[6]*0x100 + ofm[7];
141     } else {
142         ofm_on = FALSE;
143         ofm_level  = OFM_TFM;
144     }
145     if ((lf*4)!=length_ofm)
146        fatal_error_2("Stated (%d) and actual (%d) file length do not match",
147                       lf*4, length_ofm);
148 
149     switch(ofm_level) {
150         case OFM_TFM: { start_pos = 2; check_sum_pos = 24;  break; }
151         case OFM_LEVEL0: { start_pos = 8; check_sum_pos = 56;  break; }
152         case OFM_LEVEL1: { start_pos = 8; check_sum_pos = 116; break; }
153         default: { fatal_error_1("OFMLEVEL %d not supported", ofm_level-OFM_LEVEL0);
154                    break; }
155     }
156     design_size_pos = check_sum_pos+4;
157     scheme_pos = design_size_pos+4;
158     family_pos = scheme_pos+40;
159     random_word_pos = family_pos+20;
160 
161     ofm_ptr = start_pos;
162 
163     if (ofm_on==FALSE) {
164         eval_two_bytes(&lh);
165         eval_two_bytes(&bc);
166         eval_two_bytes(&ec);
167         eval_two_bytes(&nw);
168         eval_two_bytes(&nh);
169         eval_two_bytes(&nd);
170         eval_two_bytes(&ni);
171         eval_two_bytes(&nl);
172         eval_two_bytes(&nk);
173         eval_two_bytes(&ne);
174         eval_two_bytes(&np);
175         ncw = (ec-bc+1);
176         ncl = nl;
177         nce = ne;
178         header_length = 6;
179         top_char = 255;
180         top_width = 255;
181         top_height = 15;
182         top_depth = 15;
183         top_italic = 63;
184     } else {
185         eval_four_bytes(&lh);
186         eval_four_bytes(&bc);
187         eval_four_bytes(&ec);
188         eval_four_bytes(&nw);
189         eval_four_bytes(&nh);
190         eval_four_bytes(&nd);
191         eval_four_bytes(&ni);
192         eval_four_bytes(&nl);
193         eval_four_bytes(&nk);
194         eval_four_bytes(&ne);
195         eval_four_bytes(&np);
196         eval_four_bytes(&font_dir);
197         top_char = 0x10ffff;
198         top_width = 65535;
199         top_height = 255;
200         top_depth = 255;
201         top_italic = 255;
202         ncl = nl*2;
203         nce = ne*2;
204         if (ofm_level==OFM_LEVEL0) {
205             header_length = 14;
206             ncw = 2*(ec-bc+1);
207         } else {
208             header_length = 29;
209             eval_four_bytes(&nco);
210             eval_four_bytes(&ncw);
211             eval_four_bytes(&npc);
212             eval_four_bytes(&nki); /* Kinds of font ivalues   */
213             eval_four_bytes(&nwi); /* Words of font ivalues   */
214             eval_four_bytes(&nkf); /* Kinds of font fvalues   */
215             eval_four_bytes(&nwf); /* Words of font fvalues   */
216             eval_four_bytes(&nkm); /* Kinds of font mvalues   */
217             eval_four_bytes(&nwm); /* Words of font mvalues   */
218             eval_four_bytes(&nkr); /* Kinds of font rules     */
219             eval_four_bytes(&nwr); /* Words of font rules     */
220             eval_four_bytes(&nkg); /* Kinds of font glues     */
221             eval_four_bytes(&nwg); /* Words of font glues     */
222             eval_four_bytes(&nkp); /* Kinds of font penalties */
223             eval_four_bytes(&nwp); /* Words of font penalties */
224         }
225     }
226     if (lf != (header_length+lh+ncw+nw+nh+nd+ni+ncl+nk+nce+np+
227                nki+nwi+nkf+nwf+nkm+nwm+nkr+nwr+nkg+nwg+nkp+nwp))
228         fatal_error_0("Subfile sizes do not add up to the stated total");
229     if (lh < 2)
230         fatal_error_1("The header length is only %d", lh);
231     if ((bc > (ec+1)) || (ec > top_char))
232         fatal_error_2("The character code range %d .. %d is illegal", bc, ec);
233     if ((nw==0) || (nh==0) || (nd==0) || (ni==0))
234         fatal_error_0("Incomplete subfiles for character dimensions");
235     ivalues_start   = header_length+lh;
236     fvalues_start   = ivalues_start+nki;
237     mvalues_start   = fvalues_start+nkf;
238     rules_start     = mvalues_start+nkm;
239     glues_start     = rules_start+nkr;
240     penalties_start = glues_start+nkg;
241     ivalues_base    = penalties_start+nkp;
242     fvalues_base    = ivalues_base+nwi;
243     mvalues_base    = fvalues_base+nwf;
244     rules_base      = mvalues_base+nwm;
245     glues_base      = rules_base+nwr;
246     penalties_base  = glues_base+nwg;
247     char_base       = penalties_base+nwp;
248     bytes_per_entry = (12 + 2*npc) / 4 * 4;
249     init_planes();
250     no_labels = 0;
251     switch (ofm_level) {
252     case OFM_TFM: {
253       for(i=bc; i<=ec; i++) {
254         init_character(i,NULL);
255         char_start = 4*char_base+4*(i-bc);
256         current_character->index_indices[C_WD] =
257            ofm[char_start] & 0xff;
258         current_character->index_indices[C_HT] =
259            (ofm[char_start+1] & 0xf0) >> 4;
260         current_character->index_indices[C_DP] =
261 	   ofm[char_start+1] & 0xf;
262         current_character->index_indices[C_IC] =
263            (ofm[char_start+2] & 0xfc) >> 2;
264         current_character->tag =
265            ofm[char_start+2] & 0x3;
266         if (current_character->tag == TAG_LIG) no_labels++;
267         current_character->remainder =
268            ofm[char_start+3] & 0xff;
269       }
270       break;
271     }
272     case OFM_LEVEL0: {
273       for(i=bc; i<=ec; i++) {
274         init_character(i,NULL);
275         char_start = 4*char_base+8*(i-bc);
276         current_character->index_indices[C_WD] =
277            ((ofm[char_start] & 0xff) << 8) |
278            (ofm[char_start+1] & 0xff);
279         current_character->index_indices[C_HT] =
280            ofm[char_start+2] & 0xff;
281         current_character->index_indices[C_DP] =
282 	   ofm[char_start+3] & 0xff;
283         current_character->index_indices[C_IC] =
284            ofm[char_start+4] & 0xff;
285         current_character->tag =
286            ofm[char_start+5] & 0x3;
287         if (current_character->tag == TAG_LIG) no_labels++;
288         current_character->remainder =
289            ((ofm[char_start+6] & 0xff) << 8) |
290            (ofm[char_start+7] & 0xff);
291       }
292       break;
293     }
294     case OFM_LEVEL1: {
295       char_start = 4*char_base;
296       i = bc;
297       while (i<=ec) {
298         init_character(i,NULL);
299         current_character->index_indices[C_WD] =
300            ((ofm[char_start] & 0xff) << 8) |
301            (ofm[char_start+1] & 0xff);
302         current_character->index_indices[C_HT] =
303            ofm[char_start+2] & 0xff;
304         current_character->index_indices[C_DP] =
305 	   ofm[char_start+3] & 0xff;
306         current_character->index_indices[C_IC] =
307            ofm[char_start+4] & 0xff;
308         current_character->tag =
309            ofm[char_start+5] & 0x3;
310         if (current_character->tag == TAG_LIG) no_labels++;
311         current_character->remainder =
312            ((ofm[char_start+6] & 0xff) << 8) |
313            (ofm[char_start+7] & 0xff);
314         copies = 256*ofm[char_start+8]+ofm[char_start+9];
315         /* Handle character params */
316         copy_characters(i, copies);
317         i += copies + 1;
318         char_start += bytes_per_entry;
319       }
320       if (char_start != (4*(char_base+ncw)))
321           fatal_error_0("Length of char info table does not "
322                         "correspond to specification");
323       break;
324     }
325     default: {
326       fatal_error_1("Inappropriate font level (%d)", ofm_level-OFM_LEVEL0);
327     }
328     }
329     width_base    = char_base+ncw;
330     height_base   = width_base+nw;
331     depth_base    = height_base+nh;
332     italic_base   = depth_base+nd;
333     lig_kern_base = italic_base+ni;
334     kern_base     = lig_kern_base+ncl;
335     exten_base    = kern_base+nk;
336     param_base    = exten_base+nce-1;
337 }
338 
339 void
ofm_read_simple(void)340 ofm_read_simple(void)
341 {
342 
343     if (ofm_on==TRUE) {
344         print_ofm_level(ofm_level-OFM_LEVEL0);
345         print_font_dir(font_dir);
346     }
347     header = (char *) ofm+check_sum_pos;
348     retrieve_header();
349     print_family();
350     print_face();
351     print_coding_scheme();
352     print_design_size();
353     out("(COMMENT DESIGNSIZE IS IN POINTS)"); out_ln();
354     out("(COMMENT OTHER SIZES ARE MULTIPLES OF DESIGNSIZE)"); out_ln();
355     print_check_sum();
356     if ((seven_bit == TRUE) || (ofm_level != OFM_TFM))
357       print_seven_bit_safe_flag();
358     retrieve_parameters(ofm+(4*param_base));
359     print_parameters();
360 }
361 
362 void
ofm_read_rest(void)363 ofm_read_rest(void)
364 {
365     retrieve_dimen_tables();
366     if (verbose_option==TRUE) print_dimen_tables();
367     retrieve_ligkern_table(ofm+(4*lig_kern_base), ofm+(4*kern_base));
368     adjust_labels(FALSE);
369     if (verbose_option==TRUE) print_labels();
370     print_ligkern_table();
371     retrieve_exten_table(ofm+(4*exten_base));
372     if (verbose_option==TRUE) print_extens();
373 }
374