summaryrefslogtreecommitdiff
path: root/language/hyph-utf8/source/generic/hyph-utf8/generate-converters.rb
blob: d76aa29657ec343ff3feffa3889c1b0bbc49013b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#!/usr/bin/env ruby

require_relative 'hyph-utf8'

$path_root=File.expand_path("../../../..", __FILE__)
$encoding_data_dir = File.expand_path("../data/encodings", __FILE__)
$output_data_dir = "#{$path_root}/tex/generic/hyph-utf8/conversions"

def output_file_name(encoding)
	File.join($output_data_dir, sprintf('conv-utf8-%s.tex', encoding))
end

$header = <<__EOHEADER__
%% conv-utf8-%s.tex
%%
%% Conversion from UTF-8 to %s,
%% used before loading hyphenation patterns for 8-bit TeX engines.
%%
%% This file is part of hyph-utf8 package and autogenerated.
%% See http://tug.org/tex-hyphen
%%
%% Copyright 2008-%d TeX Users Group.
%% You may freely use, modify and/or distribute this file.
%% (But consider adapting the scripts if you need modifications.)
__EOHEADER__

def output_copyright_notice(outfile, encoding)
	outfile.printf $header, encoding, encoding.upcase, Time.new.year
end

$uniconvmacro1 = <<__EOUNIMAC1__
% macros adapted from ConTeXt MKII; see unic-ini.mkii
\\def\\unicodechar#1{%
	\\ifcsname unichar@\\number#1\\endcsname
	  \\csname unichar@\\number#1\\endcsname
	\\else
	  \\errmessage{Unicode character [#1] not in encoding.}%
	\\fi}
__EOUNIMAC1__

$uniconvmacros = [nil, nil]

$uniconvmacros << <<__EOTWOBYTES__
\\def\\utftwouniglyph#1#2%
	{\\expandafter\\unicodechar\\expandafter
		{\\the\\numexpr64*(#1-192)+`#2-128\\relax}}
__EOTWOBYTES__

$uniconvmacros << <<__EOTHREEBYTES__
\\def\\utfthreeuniglyph#1#2#3%
	{\\expandafter\\unicodechar\\expandafter
		{\\the\\numexpr4096*(#1-224)+64*(`#2-128)+`#3-128\\relax}}
__EOTHREEBYTES__

$uniconvmacros << <<__EOFOURBYTES__
\\def\\utffouruniglyph#1#2#3#4%
	{\\expandafter\\unicodechar\\expandafter
		{\\the\\numexpr262144*(#1-240)+4096*(`#2-128)+64*(`#3-128)+`#4-128\\relax}}
__EOFOURBYTES__

$uniconvmacro2 = <<__EOUNIMAC2__

\\def\\addunichar #1 #2 {\\expandafter\\def\\csname unichar@\\number#1\\endcsname{#2}}

% \\addunichar "unicode_code - ^^font_encoding_code
__EOUNIMAC2__

["t8m", "lth"].each do |encoding|
	# load encoding
	e = HyphEncoding.new(encoding)

	# open file
	File.open(output_file_name(encoding), "w") do |file_out|

		# copyright notice
		output_copyright_notice(file_out, encoding)
		file_out.puts

		# macro to get mapping unicode -> font encoding & error message if screwed up
		file_out.puts $uniconvmacro1

		# minimal and maximal length of characters in the encoding (until now just 2 & 3)
		unicode_characters_array = e.unicode_characters.sort
		length_min = unicode_characters_array.first[1].bytes.size
		length_max = unicode_characters_array.last[1].bytes.size

		# only output the necessary macros for transforming UTF-8 -> Unicode number
		(length_min..length_max).each do |nbytes|
			file_out.puts $uniconvmacros[nbytes]
		end

		# macro to store mapping unicode -> font encoding
		file_out.puts $uniconvmacro2

		# all unicode characters in the encoding
		e.unicode_characters.sort.each do |code,c|
			file_out.printf("\\addunichar \"%04X ^^%02x \\lccode\"%02X=\"%02X %% %s - %s\n",
				c.code_uni, c.code_enc, c.code_enc, c.code_enc, [c.code_uni].pack('U'), c.name)
		end
		file_out.puts

		# make all the possible first characters active
		# output the definition into file
		e.unicode_characters_first_byte.sort.each do |first_byte_code,chars|
			byte = first_byte_code.hex
			size = chars[0].bytes.size
			# 2-byte: 0b11000000 <= byte < 0b11100000
			str = case size
			when 2 then
				"two"
			# 3-byte: 0b11100000 <= byte < 0b11110000
			when 3 then
				"three"
			# 4-byte: 0b11110000 <= byte < 0b11111000
			when 4 then
				"four"
			end
			file_out.printf("\\catcode\"%02X=\\active \\def^^%02x{\\utf%suniglyph{\"%02X}}\n", byte, byte, str, byte)
		end
	end
end

["ec", "qx", "t2a", "lmc", "il2", "il3", "l7x"].each do |encoding|
	# load encoding
	e = HyphEncoding.new(encoding)

	# open file
	File.open(output_file_name(encoding), "w") do |file_out|

		# copyright notice
		output_copyright_notice(file_out, encoding)
		file_out.puts '%'

		e.unicode_characters_first_byte.sort.each do |first_byte_code,chars|
			# sorting all the second characters alphabetically
			chars.sort!{|x,y| x.code_uni <=> y.code_uni }
			# make all the possible first characters active
			# output the definition into file
			file_out.printf("\\catcode\"%02X=\\active\n", first_byte_code.hex)
		end
		file_out.puts "%"
		e.unicode_characters_first_byte.sort.each do |first_byte_code,chars|
			first_byte_code = first_byte_code.hex
			size = chars[0].bytes.size
			if size != 2 then
				throw "The encoding #{encoding} uses more than two bytes to encode characters"
			else

				file_out.printf("\\def^^%02x#1{%%\n", first_byte_code)
				string_fi = ""
				for i in 1..(chars.size)
					uni_character = chars[i-1]
					enc_byte    = uni_character.code_enc
					enc_byte    = [ uni_character.code_enc ].pack('c').unpack('H2')
					file_out.printf("\t\\ifx#1^^%02x^^%02x\\else %% %s - U+%04X - %s\n", uni_character.bytes[1], uni_character.code_enc, [uni_character.code_uni].pack('U'), uni_character.code_uni, uni_character.name)
					string_fi = string_fi + "\\fi"
				end

			# at least three bytes
			end
			file_out.puts "\t\\errmessage{Hyphenation pattern file corrupted or #{encoding} encoding not supported!}"
			file_out.puts string_fi + "}"
		end
		file_out.puts '%'
		file_out.puts '% ensure all the chars above have valid \lccode values'
		file_out.puts '%'
		e.lowercase_characters.each do |character|
			code = [ character.code_enc ].pack("c").unpack("H2").first.upcase
			# \lccode"FF="FF
			file_out.printf "\\lccode\"%s=\"%s %% %s - U+%04X - %s\n", code, code, [character.code_uni].pack('U'), character.code_uni, character.name
		end

		file_out.puts
	end
end