1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#!/usr/bin/python
2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgimport sys
4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgif len (sys.argv) != 4:
6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org	print >>sys.stderr, "usage: ./gen-indic-table.py IndicSyllabicCategory.txt IndicMatraCategory.txt Blocks.txt"
7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org	sys.exit (1)
8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgBLACKLISTED_BLOCKS = ["Thai", "Lao", "Tibetan"]
10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
11471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.orgfiles = [file (x) for x in sys.argv[1:]]
12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
13471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.orgheaders = [[f.readline () for i in range (2)] for f in files]
14471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.org
15471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.orgdata = [{} for f in files]
16471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.orgvalues = [{} for f in files]
17471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.orgfor i, f in enumerate (files):
18471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.org	for line in f:
19471ae72f18e7b23a96b245dbd508386fe139449cpbos@webrtc.org
20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org		j = line.find ('#')
21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org		if j >= 0:
22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org			line = line[:j]
23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org		fields = [x.strip () for x in line.split (';')]
25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org		if len (fields) == 1:
26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org			continue
27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org		uu = fields[0].split ('..')
29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org		start = int (uu[0], 16)
30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org		if len (uu) == 1:
31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org			end = start
32b9e5a3d589349ee55e41cb54eca4ec822018f5c5tommi@webrtc.org		else:
33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org			end = int (uu[1], 16)
34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org		t = fields[1]
36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org		for u in range (start, end + 1):
38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org			data[i][u] = t
39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org		values[i][t] = values[i].get (t, 0) + end - start + 1
40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
417b1e78d5a3ffef0815e2d3a8cb082a6ec0766708wjia@webrtc.org# Merge data into one dict:
427b1e78d5a3ffef0815e2d3a8cb082a6ec0766708wjia@webrtc.orgdefaults = ('Other', 'Not_Applicable', 'No_Block')
437b1e78d5a3ffef0815e2d3a8cb082a6ec0766708wjia@webrtc.orgfor i,v in enumerate (defaults):
447b1e78d5a3ffef0815e2d3a8cb082a6ec0766708wjia@webrtc.org	values[i][v] = values[i].get (v, 0) + 1
457b1e78d5a3ffef0815e2d3a8cb082a6ec0766708wjia@webrtc.orgcombined = {}
46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgfor i,d in enumerate (data):
47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org	for u,v in d.items ():
48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org		if i == 2 and not u in combined:
49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org			continue
50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org		if not u in combined:
51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org			combined[u] = list (defaults)
52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org		combined[u][i] = v
53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgcombined = {k:v for k,v in combined.items() if v[2] not in BLACKLISTED_BLOCKS}
54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgdata = combined
55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgdel combined
56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnum = len (data)
57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgfor u in [0x17CD, 0x17CE, 0x17CF, 0x17D0, 0x17D3]:
59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org	if data[u][0] == 'Other':
60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org		data[u][0] = "Vowel_Dependent"
61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org# Move the outliers NO-BREAK SPACE and DOTTED CIRCLE out
63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgsingles = {}
64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgfor u in [0x00A0, 0x25CC]:
65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org	singles[u] = data[u]
66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org	del data[u]
67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgprint "/* == Start of generated table == */"
69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgprint "/*"
70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgprint " * The following table is generated by running:"
71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgprint " *"
72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgprint " *   ./gen-indic-table.py IndicSyllabicCategory.txt IndicMatraCategory.txt Blocks.txt"
73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgprint " *"
74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgprint " * on files with these headers:"
75b3ada1540827c60a63058570a94a57dfd260ad11pbos@webrtc.orgprint " *"
76b3ada1540827c60a63058570a94a57dfd260ad11pbos@webrtc.orgfor h in headers:
77b3ada1540827c60a63058570a94a57dfd260ad11pbos@webrtc.org	for l in h:
78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org		print " * %s" % (l.strip())
79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgprint " */"
80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgprint
81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgprint '#include "hb-ot-shape-complex-indic-private.hh"'
82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgprint
83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org# Shorten values
85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgshort = [{
86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org	"Bindu":		'Bi',
87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org	"Cantillation_Mark":	'Ca',
88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org	"Joiner":		'ZWJ',
89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org	"Non_Joiner":		'ZWNJ',
90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org	"Number":		'Nd',
91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org	"Visarga":		'Vs',
92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org	"Vowel":		'Vo',
93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org	"Vowel_Dependent":	'M',
94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org	"Other":		'x',
95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org},{
96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org	"Not_Applicable":	'x',
97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}]
98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgall_shorts = [{},{}]
99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org# Add some of the values, to make them more readable, and to avoid duplicates
101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgfor i in range (2):
104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org	for v,s in short[i].items ():
105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org		all_shorts[i][s] = v
106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgwhat = ["INDIC_SYLLABIC_CATEGORY", "INDIC_MATRA_CATEGORY"]
108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgwhat_short = ["ISC", "IMC"]
109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgfor i in range (2):
110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org	print
111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org	vv = values[i].keys ()
112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org	vv.sort ()
113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org	for v in vv:
114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org		v_no_and = v.replace ('_And_', '_')
115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org		if v in short[i]:
116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org			s = short[i][v]
117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org		else:
118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org			s = ''.join ([c for c in v_no_and if ord ('A') <= ord (c) <= ord ('Z')])
119b3ada1540827c60a63058570a94a57dfd260ad11pbos@webrtc.org			if s in all_shorts[i]:
120b3ada1540827c60a63058570a94a57dfd260ad11pbos@webrtc.org				raise Exception ("Duplicate short value alias", v, all_shorts[i][s])
121b3ada1540827c60a63058570a94a57dfd260ad11pbos@webrtc.org			all_shorts[i][s] = v
122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org			short[i][v] = s
123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org		print "#define %s_%s	%s_%s	%s/* %3d chars; %s */" % \
124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org			(what_short[i], s, what[i], v.upper (), \
125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org			'	'* ((48-1 - len (what[i]) - 1 - len (v)) / 8), \
126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org			values[i][v], v)
127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgprint
128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgprint "#define _(S,M) INDIC_COMBINE_CATEGORIES (ISC_##S, IMC_##M)"
129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgprint
130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgprint
131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgtotal = 0
133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgused = 0
134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orglast_block = None
135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgdef print_block (block, start, end, data):
136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org	global total, used, last_block
137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org	if block and block != last_block:
138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org		print
139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org		print
140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org		print "  /* %s */" % block
141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org	num = 0
142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org	assert start % 8 == 0
143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org	assert (end+1) % 8 == 0
144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org	for u in range (start, end+1):
145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org		if u % 8 == 0:
146b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com			print
147b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com			print "  /* %04X */" % u,
148b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com		if u in data:
149b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com			num += 1
150b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com		d = data.get (u, defaults)
151b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com		sys.stdout.write ("%9s" % ("_(%s,%s)," % (short[0][d[0]], short[1][d[1]])))
152b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com
153b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com	total += end - start + 1
154b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com	used += num
155b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com	if block:
156b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com		last_block = block
157b3ada1540827c60a63058570a94a57dfd260ad11pbos@webrtc.org
158b3ada1540827c60a63058570a94a57dfd260ad11pbos@webrtc.orguu = data.keys ()
159b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.comuu.sort ()
160b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com
161b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.comlast = -100000
162b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.comnum = 0
163b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.comoffset = 0
164b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.comstarts = []
165b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.comends = []
166b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.comprint "static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = {"
167b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.comfor u in uu:
168b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com	if u <= last:
169b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com		continue
170b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com	block = data[u][2]
171b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com
172b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com	start = u//8*8
173b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com	end = start+1
174b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com	while end in uu and block == data[end][2]:
175b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com		end += 1
176b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com	end = (end-1)//8*8 + 7
177b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com
178b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com	if start != last + 1:
179b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com		if start - last <= 1+16*3:
180b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com			print_block (None, last+1, start-1, data)
181b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com			last = start-1
182b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com		else:
183b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com			if last >= 0:
184b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com				ends.append (last + 1)
185b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com				offset += ends[-1] - starts[-1]
186b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com			print
187b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com			print
188b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com			print "#define indic_offset_0x%04xu %d" % (start, offset)
189b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com			starts.append (start)
190b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com
191b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com	print_block (block, start, end, data)
192b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.com	last = end
193b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.comends.append (last + 1)
194b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.comoffset += ends[-1] - starts[-1]
195b3ada1540827c60a63058570a94a57dfd260ad11pbos@webrtc.orgprint
196b3ada1540827c60a63058570a94a57dfd260ad11pbos@webrtc.orgprint
197b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.comoccupancy = used * 100. / total
198b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.compage_bits = 12
199b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.comprint "}; /* Table items: %d; occupancy: %d%% */" % (offset, occupancy)
200b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.comprint
201b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.comprint "INDIC_TABLE_ELEMENT_TYPE"
202b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.comprint "hb_indic_get_categories (hb_codepoint_t u)"
203b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.comprint "{"
204b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.comprint "  switch (u >> %d)" % page_bits
205b9e3afc6503d3454a6fb68b12be46eb7cfb8effdroosa@google.comprint "  {"
206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgpages = set([u>>page_bits for u in starts+ends+singles.keys()])
207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgfor p in sorted(pages):
208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org	print "    case 0x%0Xu:" % p
209	for (start,end) in zip (starts, ends):
210		if p not in [start>>page_bits, end>>page_bits]: continue
211		offset = "indic_offset_0x%04xu" % start
212		print "      if (hb_in_range (u, 0x%04Xu, 0x%04Xu)) return indic_table[u - 0x%04Xu + %s];" % (start, end, start, offset)
213	for u,d in singles.items ():
214		if p != u>>page_bits: continue
215		print "      if (unlikely (u == 0x%04Xu)) return _(%s,%s);" % (u, short[0][d[0]], short[1][d[1]])
216	print "      break;"
217	print ""
218print "    default:"
219print "      break;"
220print "  }"
221print "  return _(x,x);"
222print "}"
223print
224print "#undef _"
225for i in range (2):
226	print
227	vv = values[i].keys ()
228	vv.sort ()
229	for v in vv:
230		print "#undef %s_%s" % \
231			(what_short[i], short[i][v])
232print
233print "/* == End of generated table == */"
234
235# Maintain at least 30% occupancy in the table */
236if occupancy < 30:
237	raise Exception ("Table too sparse, please investigate: ", occupancy)
238