diff options
Diffstat (limited to 'Build/source/texk/web2c/omegafonts/char_routines.c')
-rw-r--r-- | Build/source/texk/web2c/omegafonts/char_routines.c | 1126 |
1 files changed, 1126 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/omegafonts/char_routines.c b/Build/source/texk/web2c/omegafonts/char_routines.c new file mode 100644 index 00000000000..75d370f27d0 --- /dev/null +++ b/Build/source/texk/web2c/omegafonts/char_routines.c @@ -0,0 +1,1126 @@ +/* char_routines.c: Data structures for character information + +This file is part of Omega, +which is based on the web2c distribution of TeX, + +Copyright (c) 1994--2001 John Plaice and Yannis Haralambous + +Omega is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +Omega is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Omega; if not, write to the Free Software Foundation, Inc., +59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "cpascal.h" +#include "manifests.h" +#include "list_routines.h" +#include "char_routines.h" +#include "print_routines.h" +#include "out_routines.h" +#include "error_routines.h" +#include "ligkern_routines.h" +#include "dimen_routines.h" +#include "header_routines.h" +#include "font_routines.h" +#include "out_ofm.h" +#include "omfonts.h" +#include "parse_ofm.h" +#include "dvi.h" + +#define PLANE 0x10000 +#define INDEX_MAX (PLANE-1) +#define HALFPLANE 0x08000 + +#define MAX_START_OFM 65535 +#define MAX_START_TFM 255 + +/* + * Characters can range from 0x0 to 0x7fffffff (31 bits unsigned), + * which is a lot of characters. We would expect characters to either + * be bunched up in a given region, or else sparsely defined throughout + * the range. The data structure to hold them is an array of HALFPLANE + * arrays, each of which holds a full PLANE (0x10000) of characters. + * + * At all times, init_character ensures that planes[0] to planes[plane_max] + * are either NULL or allocated arrays of PLANE characters. + * + * For allocated array p, init_character also ensures that planes[p][0] + * to planes[p][char_max[p]] are either NULL or pointers to allocated + * char_entry values. + * + * init_character can be called when actually reading a CHARACTER definition + * or when the character is referenced in a charlist cycle, an extensible + * piece or in a ligature/kerning table. In the latter case, ensure_existence + * is called, and it sets the defined field of the character to be FALSE; + * + * init_character also sets current_character to the character entry; + * + */ + +unsigned bc=0x7fffffff; +unsigned ec=0x0; +unsigned ne=0; + +char_entry **planes[HALFPLANE]; +unsigned char_max[HALFPLANE]; +unsigned plane_max = 0; + +char_entry *current_character = NULL; +char_entry *current_secondary_character = NULL; + +queue exten_queue; +four_pieces **exten_table = NULL; + +unsigned no_labels = 0; +label_entry *label_table; +int label_ptr, sort_ptr; +int lk_offset; +boolean extra_loc_needed; + +void +init_planes(void) +{ + plane_max = 0; + planes[plane_max] = NULL; +} + +void +init_character(unsigned c, char_entry *ready_made) +{ + register unsigned i, index, plane; + + if ((c<CHAR_MINIMUM) || (c>CHAR_MAXIMUM)) { + warning_1("CHARACTER index (H %X) not 31-bit unsigned integer; " + "ignored", c); + current_character = NULL; + return; + } + plane = c / PLANE; + index = c % PLANE; + for (i=plane_max+1; i<=plane; i++) { + planes[i] = NULL; + } + if (planes[plane]==NULL) { + planes[plane] = (char_entry **)xmalloc(PLANE * sizeof(char_entry *)); + char_max[plane] = 0; + planes[plane][0] = NULL; + } + for (i=char_max[plane]+1; i<=index; i++) { + planes[plane][i] = NULL; + } + if (plane>plane_max) plane_max = plane; + if (index>char_max[plane]) char_max[plane] = index; + + if (planes[plane][index] != NULL) { + if (planes[plane][index]->defined == FALSE) { + current_character = planes[plane][index]; + current_character->defined = TRUE; + return; + } + warning_1("CHARACTER index (H %X) previously defined; " + "old definition ignored", c); + free(current_character); + current_character = NULL; + } + if (ready_made != NULL) { + current_character = ready_made; + planes[plane][index] = current_character; + } else { + current_character = (char_entry *)xmalloc(sizeof(char_entry)); + planes[plane][index] = current_character; + for (i=C_MIN; i<=C_MAX; i++) { + current_character->indices[i] = NULL; + current_character->index_indices[i] = 0; + } + current_character->c = c; + current_character->copies = 0; + current_character->remainder = 0; + current_character->tag = TAG_NONE; + current_character->defined = TRUE; + current_character->accent = ACC_NONE; + current_character->ovf_packet_length = 0; + current_character->ovf_packet = NULL; + cur_packet = NULL; + } +} + +void +copy_characters(unsigned c, unsigned copies) +{ + unsigned i=0; + unsigned plane, index; + char_entry *the_entry; + + if ((c<CHAR_MINIMUM) || (c>CHAR_MAXIMUM)) { + warning_1("CHARACTER index (H %X) not 31-bit unsigned integer; " + "ignored", c); + current_character = NULL; + return; + } + plane = c / PLANE; + index = c % PLANE; + if ((plane>plane_max) || (planes[plane]==NULL)) + internal_error_1("copy_characters (plane %d)", plane); + the_entry = planes[plane][index]; + if (the_entry==NULL) + internal_error_1("copy_characters (index %d)", index); + the_entry->copies = copies; + for (i=(c+1); i<=(c+copies); i++) + init_character(i, the_entry); +} + +void +ensure_existence(unsigned c) +{ + register unsigned index, plane; + plane = c / PLANE; + index = c % PLANE; + + if ((plane>plane_max) || (planes[plane]==NULL) || + (index>char_max[plane]) || (planes[plane][index]==NULL)) { + init_character(c, NULL); + planes[plane][index]->defined = FALSE; + } + current_secondary_character = planes[plane][index]; +} + +#define FOR_ALL_CHARACTERS(FOR_ALL_CHARACTERS_ACTION) \ + for (plane = 0; plane <=plane_max; plane++) { \ + if (planes[plane] != NULL) { \ + for (index = 0; index <=char_max[plane]; index++) { \ + entry = planes[plane][index]; \ + if (entry != NULL) { \ + FOR_ALL_CHARACTERS_ACTION \ + } \ + } \ + } \ + } + +#define FOR_ALL_EXISTING_CHARACTERS(FOR_ALL_EXISTING_CHARACTERS_ACTION) \ + FOR_ALL_CHARACTERS( \ + if (entry->defined == TRUE) { \ + FOR_ALL_EXISTING_CHARACTERS_ACTION \ + } \ + ) + +void +output_ovf_chars(void) +{ + register unsigned index, plane, k; + char_entry *entry; + fix wd; + + FOR_ALL_EXISTING_CHARACTERS( + unsigned c = plane*PLANE + index; + + if ((entry->indices[C_WD] == NULL) || (entry->indices[C_WD]->index == 0)) + continue; + wd = lval(entry->indices[C_WD]); + if (design_units != UNITY) + wd = zround(((double)wd) / ((double)design_units) * 1048576.0); + if ((entry->ovf_packet_length>241) || + (wd < 0) || (wd >= 0x1000000) || + (c < 0) || (c >255)) { + out_ovf(242); out_ovf_4(entry->ovf_packet_length); + out_ovf_4(c); out_ovf_4(wd); + } else { + out_ovf(entry->ovf_packet_length); out_ovf(c); + out_ovf((wd >>16) & 0xff); out_ovf((wd >>8) & 0xff); + out_ovf(wd & 0xff); + } + for (k=0; k<entry->ovf_packet_length; k++) + out_ovf(entry->ovf_packet[k]); + ) +} + + +static void +check_existence_all_character_fields(void) +{ + register unsigned index, plane; + char_entry *entry; + unsigned *exten; + unsigned j; + + FOR_ALL_EXISTING_CHARACTERS( + unsigned c = plane*PLANE + index; + if (entry->indices[C_WD] == NULL) { + current_character = entry; + set_character_measure(C_WD, 0); + } + switch(entry->tag) { + case TAG_NONE: { break; } + case TAG_LIG: { + check_ligature_program(c, entry->remainder); + break; + } + case TAG_LIST:{ + check_existence_and_safety(c, entry->remainder, "", + "%sCharacter (H %X) NEXTLARGER than (H %X) " + "has no CHARACTER spec"); + if (entry->remainder > 0xffff) { + fprintf(stderr, "Character (H %X) NEXTLARGER than (H %X) " + "exceeds ffff\n", entry->remainder, c); + exit(2); + } + break; + } + case TAG_EXT:{ + exten = entry->extens; + for (j=E_MIN; j<=E_MAX; j++) { + if (exten[j]!=0) { + check_existence_and_safety(c, exten[j], + extensible_pieces[j], + "%s piece (H %X) of character (H %X) " + "has no CHARACTER spec"); + if (exten[j] > 0xfff) { + fprintf(stderr, "%s piece (H %X) of character (H %X) " + "exceeds ffff\n", extensible_pieces[j], exten[j], c); + exit(2); + } + } + } + break; + } + } + ) +} + +void +clear_ligature_entries(void) +{ + register unsigned index, plane; + char_entry *entry; + + FOR_ALL_EXISTING_CHARACTERS( + if (entry->tag == TAG_LIG) { + entry->tag = TAG_NONE; + entry->remainder = 0; + } + ) +} + +void +check_existence_and_safety(unsigned c, unsigned g, const_string extra, const_string fmt) +{ + char_entry *gentry; + + if ((g<CHAR_MINIMUM) || (g>CHAR_MAXIMUM)) + internal_error_1("check_existence_and_safety (g=%d)", g); + ensure_existence(g); + gentry = current_secondary_character; + if ((g>=128) && (c<128)) + seven_bit_calculated = 0; + if (gentry->defined == FALSE) { + warning_s_2(fmt, extra, g, c); + current_character = gentry; + set_character_measure(C_WD, 0); + gentry->defined = TRUE; + } +} + +void +doublecheck_existence(unsigned g, const_string extra, const_string fmt) +{ + char_entry *gentry; + + if ((g<CHAR_MINIMUM) || (g>CHAR_MAXIMUM)) + internal_error_1("doublecheck_existence (g=%d)", g); + ensure_existence(g); + gentry = current_secondary_character; + if (gentry->defined == FALSE) { + warning_s_1(fmt, extra, g); + current_character = gentry; +/* + set_character_measure(C_WD, 0); +*/ + } +} + +static void print_packet(unsigned char *, unsigned); + +#define check_range(ndx, mx, name) \ + if (entry->index_indices[ndx] >= mx) { \ + fprintf(stderr, "\n%s index for character \"%x is too large;\n" \ + "so I reset it to zero.\n", name, c); \ + entry->index_indices[ndx] = 0; \ + changed = TRUE; \ + } + +void +print_characters(boolean read_ovf) +{ + register unsigned index, plane; + char_entry *entry; + four_pieces *exten; + four_entries *lentry; + unsigned j,k; + unsigned copies = 0; + + FOR_ALL_CHARACTERS( + unsigned c = plane*PLANE + index; + if (copies > 0) + copies--; + else { + if (entry->index_indices[C_WD] != 0) { + copies = entry->copies; + if (copies > 0) + print_character_repeat(c, copies); + else + print_character(c); + check_range(C_WD, nw, "Width") + check_range(C_HT, nh, "Height") + check_range(C_DP, nd, "Depth") + check_range(C_IC, ni, "Italic correction") + for (k=C_MIN; k<C_MAX; k++) { + if (entry->index_indices[k] != 0) { + print_character_measure(k, + dimen_tables[k][entry->index_indices[k]]); + } + } + fflush(file_output); + switch (entry->tag) { + case TAG_NONE: { break; } + case TAG_LIG: { + if (entry->remainder >= nl) { + fprintf(stderr, "\nLigature/kern starting index for character \"%x is too large;\n" + "so I removed it.\n", c); + entry->tag = 0; + entry->remainder = 0; + changed = TRUE; + break; + } + left(); + out("COMMENT"); out_ln(); + lentry = lig_kern_table + entry->remainder; + if (lentry->entries[0] > STOP_FLAG) { + lentry = lig_kern_table + + (256*lentry->entries[2]+lentry->entries[3]); + } + do { + print_one_lig_kern_entry(lentry, FALSE); + if (lentry->entries[0] >= STOP_FLAG) { + lentry = lig_kern_table + nl; + } else { + lentry = lentry + 1 + lentry->entries[0]; + } + } while (lentry < (lig_kern_table + nl)); + right(); + break; + } + case TAG_LIST: { + print_next_larger(entry->remainder); + break; + } + case TAG_EXT: { + if (entry->remainder >= ne) { + fprintf(stderr, "\nExtensible index for character \"%x is too large;\n" + "so I reset it to zero.\n", c); + entry->tag = 0; + entry->remainder = 0; + changed = TRUE; + break; + } + print_var_character(); + exten = exten_table[entry->remainder]; + for (j=E_MIN; j<=E_MAX; j++) { + if (exten->pieces[j]!=0) + print_extensible_piece(j,exten->pieces[j]); + } + right(); + break; + } + } + if ((read_ovf==TRUE) && (entry->ovf_packet_length>0)) { + print_map(); + print_packet(entry->ovf_packet, entry->ovf_packet_length); + right(); + } + right(); + fflush(file_output); + } + } + ) +} + +unsigned stack_top = 0; +int wstack[1000]; +int xstack[1000]; +int ystack[1000]; +int zstack[1000]; + +static int +string_balance(unsigned char *special, int k) +{ + unsigned paren_level = 0; + + if (k == 0) + return 1; + if (*special == ' ') + return 0; + for (; k > 0; k--, special++) { + if ((*special < ' ') || (*special > '~')) + return 0; + if (*special == '(') + paren_level++; + if (*special == ')') { + if (paren_level-- == 0) + return 0; + } + } + return (paren_level == 0); +} + +static void +print_packet(unsigned char *packet_start, unsigned packet_length) +{ + unsigned cmd, arg; + fix fix_arg, fix_arg1; + unsigned char *packet = packet_start; + unsigned char *max_packet = packet+packet_length; + + stack_top = 0; + wstack[stack_top] = xstack[stack_top] = + ystack[stack_top] = zstack[stack_top] = 0; + while (packet <max_packet) { + if (*packet <= DVI_SET_CHAR_127) { + arg = *packet; packet++; + print_set_char(arg); + } else if ((*packet >= DVI_FNT_NUM_0) && (*packet <= DVI_FNT_NUM_63)) { + arg = *packet - DVI_FNT_NUM_0; packet++; + print_select_font(arg); + } else switch(*packet) { + case DVI_SET_1: case DVI_SET_2: case DVI_SET_3: case DVI_SET_4: + cmd = *packet; packet++; + arg = ovf_get_arg(&packet, cmd - DVI_SET_1 + 1, FALSE); + print_set_char(arg); + break; + case DVI_NOP: + packet++; + break; + case DVI_PUSH: + cmd = DVI_PUSH; packet++; stack_top++; + wstack[stack_top] = wstack[stack_top-1]; + xstack[stack_top] = xstack[stack_top-1]; + ystack[stack_top] = ystack[stack_top-1]; + zstack[stack_top] = zstack[stack_top-1]; + print_push(); + break; + case DVI_POP: + cmd = DVI_PUSH; packet++; stack_top--; + print_pop(); + break; + case DVI_SET_RULE: + cmd = DVI_SET_RULE; packet++; fix_arg = ovf_get_arg(&packet, 4, TRUE); + fix_arg1 = ovf_get_arg(&packet, 4, TRUE); + print_set_rule(fix_arg, fix_arg1); + break; + case DVI_PUT_RULE: + cmd = DVI_PUT_RULE; packet++; fix_arg = ovf_get_arg(&packet, 4, TRUE); + fix_arg1 = ovf_get_arg(&packet, 4, TRUE); + print_put_rule(fix_arg, fix_arg1); + break; + case DVI_RIGHT_1: case DVI_RIGHT_2: case DVI_RIGHT_3: case DVI_RIGHT_4: + cmd = *packet; packet++; + fix_arg = ovf_get_arg(&packet, cmd - DVI_RIGHT_1 + 1, TRUE); + print_move(M_RIGHT, fix_arg); + break; + case DVI_DOWN_1: case DVI_DOWN_2: case DVI_DOWN_3: case DVI_DOWN_4: + cmd = *packet; packet++; + fix_arg = ovf_get_arg(&packet, cmd - DVI_DOWN_1 + 1, TRUE); + print_move(M_DOWN, fix_arg); + break; + case DVI_W_0: + cmd = DVI_W_0; packet++; + print_move(M_RIGHT, wstack[stack_top]); + break; + case DVI_W_1: case DVI_W_2: case DVI_W_3: case DVI_W_4: + cmd = *packet; packet++; + wstack[stack_top] = ovf_get_arg(&packet, cmd - DVI_W_1 + 1, TRUE); + print_move(M_RIGHT, wstack[stack_top]); + break; + case DVI_X_0: + cmd = DVI_X_0; packet++; + print_move(M_RIGHT, xstack[stack_top]); + break; + case DVI_X_1: case DVI_X_2: case DVI_X_3: case DVI_X_4: + cmd = *packet; packet++; + xstack[stack_top] = ovf_get_arg(&packet, cmd - DVI_X_1 + 1, TRUE); + print_move(M_RIGHT, xstack[stack_top]); + break; + case DVI_Y_0: + cmd = DVI_Y_0; packet++; + print_move(M_DOWN, ystack[stack_top]); + break; + case DVI_Y_1: case DVI_Y_2: case DVI_Y_3: case DVI_Y_4: + cmd = *packet; packet++; + ystack[stack_top] = ovf_get_arg(&packet, cmd - DVI_Y_1 + 1, TRUE); + print_move(M_DOWN, ystack[stack_top]); + break; + case DVI_Z_0: + cmd = DVI_Z_0; packet++; + print_move(M_DOWN, zstack[stack_top]); + break; + case DVI_Z_1: case DVI_Z_2: case DVI_Z_3: case DVI_Z_4: + cmd = *packet; packet++; + zstack[stack_top] = ovf_get_arg(&packet, cmd - DVI_Z_1 + 1, TRUE); + print_move(M_DOWN, zstack[stack_top]); + break; + case DVI_PUT_1: case DVI_PUT_2: case DVI_PUT_3: case DVI_PUT_4: + cmd = *packet; packet++; + fix_arg = ovf_get_arg(&packet, cmd - DVI_PUT_1 + 1, FALSE); + print_put_char(fix_arg); + break; + case DVI_XXX_1: case DVI_XXX_2: case DVI_XXX_3: case DVI_XXX_4: + cmd = *packet; packet++; + fix_arg = ovf_get_arg(&packet, cmd - DVI_XXX_1 + 1, FALSE); + if (fix_arg < 0) { + internal_error_1("Special string with negative length (%d)\n", fix_arg); + } + if ((fix_arg <= 64) && string_balance(packet, fix_arg)) { + char *special = (char *) xmalloc(fix_arg+1); + strncpy(special, (const char *)packet, fix_arg); + special[fix_arg] = '\0'; + print_special(special); + free(special); + } else { + print_special_hex(packet, fix_arg); + } + packet += fix_arg; + break; + case DVI_FNT_1: case DVI_FNT_2: case DVI_FNT_3: case DVI_FNT_4: + cmd = *packet; packet++; + fix_arg = ovf_get_arg(&packet, cmd - DVI_FNT_1 + 1, FALSE); + print_select_font(fix_arg); + break; + default: + internal_error_1("Unrecognized DVI packet (%d)\n", *packet); + } + } + fflush(file_output); + fflush(stderr); +} + +void +check_char_tag(unsigned c) +{ + ensure_existence(c); +} + +void +set_char_tag(unsigned c, unsigned tag) +{ + ensure_existence(c); + planes[c/PLANE][c%PLANE]->tag = tag; +} + +void +set_char_remainder(unsigned c, unsigned remainder) +{ + ensure_existence(c); + planes[c/PLANE][c%PLANE]->remainder = remainder; +} + +static int +get_char_remainder(unsigned c) +{ + ensure_existence(c); + return planes[c/PLANE][c%PLANE]->remainder; +} + +void +set_next_larger(unsigned larger) +{ + check_char_tag(current_character->c); + set_char_tag(current_character->c, TAG_LIST); + set_char_remainder(current_character->c, larger); +} + +void +init_var_character(void) +{ + four_pieces *entry = (four_pieces *) xmalloc(sizeof(four_pieces)); + unsigned j; + + check_char_tag(current_character->c); + set_char_tag(current_character->c, TAG_EXT); + append_to_queue(&exten_queue, entry); + for (j=E_MIN; j<=E_MAX; j++) { + entry->pieces[j] = 0; + } + set_char_remainder(current_character->c, ne); + current_character->extens = (unsigned int *)entry->pieces; + ne++; +} + +void +set_extensible_piece(unsigned piece, unsigned val) +{ + unsigned *exten = current_character->extens; + + if ((piece < E_MIN) || (piece > E_MAX)) + internal_error_1("set_extensible_piece (piece=%d)", piece); + if (exten[piece]!=0) + warning_0("value already defined"); + exten[piece] = val; +} + +void +adjust_labels(boolean play_with_starts) +{ + unsigned plane, index; + char_entry *entry; + int max_start = (ofm_level==OFM_TFM) ? MAX_START_TFM : MAX_START_OFM; + + label_table = (label_entry *)xmalloc((no_labels+2)*sizeof(label_entry)); + label_ptr = 0; + label_table[0].rr = -1; /* sentinel */ + + if (!play_with_starts && (bchar_label < nl)) { + label_ptr = 1; + label_table[1].cc = -1; + label_table[1].rr = bchar_label; + } + + FOR_ALL_CHARACTERS( + unsigned c = plane*PLANE + index; + if ((c>=bc) && (c<=ec) && (entry->tag == TAG_LIG)) { + int r = entry->remainder; + if (r < nl) { + unsigned s = lig_kern_table[r].entries[0]; + if ((s < 256) && (s > STOP_FLAG)) { + r = 256 * lig_kern_table[r].entries[2] + lig_kern_table[r].entries[3]; + if (!play_with_starts && (r < nl) && (activity[entry->remainder] == A_UNREACHABLE)) + activity[entry->remainder] = A_PASS_THROUGH; + } + } + sort_ptr = label_ptr; /* hole at position sort_ptr+1 */ + while (label_table[sort_ptr].rr > r) { + label_table[sort_ptr+1] = label_table[sort_ptr]; + sort_ptr--; /* move the hole */ + } + label_table[sort_ptr+1].cc = c; + label_table[sort_ptr+1].rr = r; + label_ptr++; + if (!play_with_starts) + activity[r] = A_ACCESSIBLE; + } + ) + if (play_with_starts) { + if (bchar != CHAR_BOUNDARY) { + extra_loc_needed = TRUE; lk_offset = 1; + } else { + extra_loc_needed = FALSE; lk_offset = 0; + } + sort_ptr = label_ptr; /* the largest unallocated label */ + if ((label_table[sort_ptr].rr + lk_offset) > max_start) { + lk_offset=0; extra_loc_needed=FALSE; + /* location 0 can do double duty */ + do { + set_char_remainder(label_table[sort_ptr].cc, lk_offset); + while (label_table[sort_ptr-1].rr == label_table[sort_ptr].rr) { + sort_ptr--; + set_char_remainder(label_table[sort_ptr].cc, lk_offset); + } + lk_offset++; sort_ptr--; + } while ((lk_offset+label_table[sort_ptr].rr) > max_start); + /* N.B. lk_offset=MAX_START+1 satisfies this when sort_ptr=0 */ + } + if (lk_offset>0) { + while (sort_ptr>0) { + set_char_remainder(label_table[sort_ptr].cc, + get_char_remainder(label_table[sort_ptr].cc) + +lk_offset); + sort_ptr--; + } + } + } + if (bchar_label < nl) { + lig_kern_table[nl-1].entries[2] = (bchar_label + lk_offset) / (max_start + 1); + lig_kern_table[nl-1].entries[3] = (bchar_label + lk_offset) % (max_start + 1); + } +} + +void +print_labels(void) +{ + unsigned i; + + if (label_ptr>0) { + left(); out("COMMENT"); out_ln(); + for (i=1; i<=label_ptr; i++) { + left(); out("LABEL_ENTRY"); out(" "); + out_int(i,10); out(" "); + out_char(label_table[i].cc); out(" "); + out_int(label_table[i].rr, 10); right(); + } + right(); + } +} + +static void check_charlist_infinite_loops(void); +static void doublecheck_extens(void); +static void build_exten_table(void); + +void +check_and_correct(void) +{ + check_existence_all_character_fields(); + build_kern_table(); + build_dimen_tables(); + build_exten_table(); + check_ligature_ends_properly(); + compute_ofm_character_info(); + adjust_labels(TRUE); + calculate_seven_bit_safe_flag(); + check_ligature_infinite_loops(); + check_charlist_infinite_loops(); + doublecheck_ligatures(); + doublecheck_extens(); +} + +static void +check_charlist_infinite_loops(void) +{ + unsigned plane, index; + char_entry *entry; + unsigned g; + + FOR_ALL_CHARACTERS( + unsigned c = plane*PLANE + index; + if (entry->tag == TAG_LIST) { + g = entry->remainder; + while ((g < c) && (planes[g/PLANE][g%PLANE]->tag == TAG_LIST)) { + g = planes[g/PLANE][g%PLANE]->remainder; + } + if (g == c) { + entry->tag = TAG_NONE; + entry->remainder = 0; + warning_1("Cycle of NEXTLARGER characters " + "has been broken at ",c); + } + } + ) +} + +static void +build_exten_table(void) +{ + list L1 = exten_queue.front, L2; + unsigned i = 0; + + exten_table = (four_pieces **) xmalloc(ne*sizeof(four_pieces *)); + while (L1 != NULL) { + exten_table[i] = (four_pieces *)L1->contents; + L2 = L1->ptr; + free(L1); L1 = L2; + i++; + } +} + +void +retrieve_exten_table(unsigned char *table) +{ + unsigned i = 0, j; + four_pieces *entry; + + exten_table = (four_pieces **) xmalloc(ne*sizeof(four_pieces *)); + for (i=0; i<ne; i++) { + exten_table[i] = entry = (four_pieces *) xmalloc(sizeof(four_pieces)); + for (j=E_MIN; j<=E_MAX; j++) { + if (ofm_level==OFM_TFM) { + entry->pieces[j] = table[4*i+j] & 0xff; + } else { + entry->pieces[j] = + ((table[8*i+j*2] & 0xff) << 8) | + (table[8*i+j*2+1] & 0xff); + } + } + } +} + +void +print_extens(void) +{ + unsigned i,j; + + if (ne>0) { + left(); out("COMMENT"); out_ln(); + for (i=0; i<ne; i++) { + left(); out("EXTEN_ENTRY"); + out(" "); out_int(i,10); out_ln(); + for (j=E_MIN; j<=E_MAX; j++) { + if (exten_table[i]->pieces[j] != 0) + print_extensible_piece(j,exten_table[i]->pieces[j]); + } + right(); + } + right(); + } +} + +static void +doublecheck_extens(void) +{ + unsigned i,j; + + if (ne>0) { + for (i=0; i<ne; i++) { + for (j=E_MIN; j<=E_MAX; j++) { + if (exten_table[i]->pieces[j] != 0) + doublecheck_existence( + exten_table[i]->pieces[j], extensible_pieces[j], + "Unused %s piece (H %X) refers to " + "nonexistent character"); + } + } + } +} + +void +compute_ligkern_offset(void) +{ +} + +void +output_ofm_extensible(void) +{ + unsigned i,j; + + for (i=0; i<ne; i++) { + for (j=E_MIN; j<=E_MAX; j++) { + if (exten_table[i]->pieces[j] != 0) + out_ofm_char(exten_table[i]->pieces[j]); + else out_ofm_char(0); + } + } +} + +unsigned num_char_info, words_per_entry; + +#define XX_ENTRY(key) (entry->indices[key] != NULL ? entry->indices[key]->index : 0) +#define WD_ENTRY XX_ENTRY(C_WD) +#define HT_ENTRY XX_ENTRY(C_HT) +#define DP_ENTRY XX_ENTRY(C_DP) +#define IC_ENTRY XX_ENTRY(C_IC) + +#define XX_NEXT(key) ((next != NULL) && (next->indices[key] != NULL) ? next->indices[key]->index : 0) +#define WD_NEXT XX_NEXT(C_WD) +#define HT_NEXT XX_NEXT(C_HT) +#define DP_NEXT XX_NEXT(C_DP) +#define IC_NEXT XX_NEXT(C_IC) +#define YY_NEXT(field) (next != NULL ? next->field : 0) +#define RM_NEXT YY_NEXT(remainder) +#define TG_NEXT YY_NEXT(tag) + +static void +compute_check_sum(void) +{ + unsigned c; + unsigned plane, index; + char_entry *entry; + unsigned c0 = bc, c1 = ec, c2 = bc, c3 = ec; + fix wd; + + for (c = bc; c <= ec; c++) { + plane = c / PLANE; + index = c % PLANE; + entry = planes[plane][index]; + if ((entry == NULL) || (WD_ENTRY == 0)) + continue; + wd = lval(entry->indices[C_WD]); + if (design_units != UNITY) + wd = zround((wd / (double)design_units) * 1048576.0); + wd += (c + 4) * 0x400000; /* this should be positive */ + c0 = (c0 + c0 + wd) % 255; + c1 = (c1 + c1 + wd) % 253; + c2 = (c2 + c2 + wd) % 251; + c3 = (c3 + c3 + wd) % 247; + } + check_sum = (c0 << 24) | (c1 << 16) | (c2 << 8) | c3; +} + +void +compute_ofm_character_info(void) +{ + unsigned c; + unsigned plane, index; + char_entry *entry; + + bc = 0x7fffffff; ec=0; + FOR_ALL_EXISTING_CHARACTERS( + c = plane*PLANE + index; + if (c < bc) bc = c; + if (c > ec) ec = c; + ) + if (bc > ec) bc = 1; + + /* fill gaps */ + for (plane = 0; plane < plane_max; plane++) { + if (planes[plane] == NULL) { + planes[plane] = (char_entry **)xmalloc(PLANE * sizeof(char_entry *)); + char_max[plane] = 0; + planes[plane][0] = NULL; + } + for (index = char_max[plane]+1; index <= INDEX_MAX; index++) { + planes[plane][index] = NULL; + } + char_max[plane] = INDEX_MAX; + } + + switch (ofm_level) { + case OFM_TFM: { + if (ec>0xff) + fatal_error_1( + "Char (%x) too big for TFM (max ff); use OFM file",ec); + break; + } + case OFM_LEVEL0: { + if (ec>0x10ffff) + fatal_error_1( + "Char (%x) too big for OFM level-0 (max 10ffff); use level-2", + ec); + break; + } + case OFM_LEVEL1: { + if (ec>0x10ffff) + fatal_error_1( + "Char (%x) too big for OFM level-1 (max 10ffff); use level-2", + ec); + num_char_info = 0; + for (c = bc; c <= ec; c++) { + unsigned saved_c = c; + char_entry *next; + + plane = c / PLANE; + index = c % PLANE; + entry = planes[plane][index]; + if ((entry != NULL) && (WD_ENTRY != 0)) { + unsigned wd = WD_ENTRY, ht = HT_ENTRY, dp = DP_ENTRY, ic = IC_ENTRY; + + c += entry->copies; + for (; (c < ec) && (c-saved_c < 0xffff); c++) { + plane = (c+1) / PLANE; + index = (c+1) % PLANE; + next = planes[plane][index]; + if ((WD_NEXT != wd) || (HT_NEXT != ht) || + (DP_NEXT != dp) || (IC_NEXT != ic) || + (RM_NEXT != entry->remainder) || (TG_NEXT != entry->tag)) + break; + planes[plane][index] = entry; + } + } else { + plane = c / PLANE; + index = c % PLANE; + planes[plane][index] = NULL; + init_character(c, NULL); + entry = current_character; + for (; (c < ec) && (c-saved_c < 0xffff); c++) { + plane = (c+1) / PLANE; + index = (c+1) % PLANE; + next = planes[plane][index]; + if (WD_NEXT != 0) + break; + planes[plane][index] = entry; + } + } + entry->copies = c - saved_c; + num_char_info++; + } + break; + } + default: { internal_error_0("compute_ofm_character_info"); } + } + + if (check_sum_specified==FALSE) + compute_check_sum(); +} + +void +output_ofm_character_info(void) +{ + unsigned plane, index; + char_entry *entry; + + switch (ofm_level) { + case OFM_TFM: { + plane=0; + for (index = bc; index <= ec; index++) { + entry = planes[plane][index]; + if (entry == NULL) { + out_ofm_4(0); + } else { + out_ofm(WD_ENTRY); + out_ofm(HT_ENTRY*16 + DP_ENTRY); + out_ofm(IC_ENTRY*4 + entry->tag); + out_ofm(entry->remainder); + } + } + break; + } + case OFM_LEVEL0: { + unsigned c; + + for (c = bc; c <= ec; c++) { + plane = c / PLANE; + index = c % PLANE; + entry = planes[plane][index]; + if (entry == NULL) { + out_ofm_4(0); out_ofm_4(0); + } else { + out_ofm_2(WD_ENTRY); + out_ofm(HT_ENTRY); + out_ofm(DP_ENTRY); + out_ofm(IC_ENTRY); + out_ofm(entry->tag); + out_ofm_2(entry->remainder); + } + } + break; + } + case OFM_LEVEL1: { + unsigned i; + unsigned c; + + for (c = bc; c <= ec; c++) { + plane = c / PLANE; + index = c % PLANE; + entry = planes[plane][index]; + if (entry == NULL) { + for (i=0; i<words_per_entry; i++) + out_ofm_4(0); + } else { + unsigned copies = entry->copies; + + out_ofm_2(WD_ENTRY); + out_ofm(HT_ENTRY); + out_ofm(DP_ENTRY); + out_ofm(IC_ENTRY); + /* assume no ctag */ + out_ofm(entry->tag); + out_ofm_2(entry->remainder); + out_ofm_2(copies); + /* assume no character params */ + for (i=0; i<npc; i++) + out_ofm_2(0); + /* padding */ + if (0 == npc % 2) + out_ofm_2(0); + c += copies; + } + } + break; + } + default: { internal_error_0("compute_ofm_character_info"); } + } +} |