1 # Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 # All rights reserved. |
|
3 # This component and the accompanying materials are made available |
|
4 # under the terms of "Eclipse Public License v1.0" |
|
5 # which accompanies this distribution, and is available |
|
6 # at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 # |
|
8 # Initial Contributors: |
|
9 # Nokia Corporation - initial contribution. |
|
10 # |
|
11 # Contributors: |
|
12 # |
|
13 # Description: |
|
14 # |
|
15 |
|
16 use strict; |
|
17 |
|
18 ## Used as global variables, probably need to change and pass variables through as parameters. |
|
19 my %globalValues=(); |
|
20 ##initialise filenames |
|
21 $globalValues{'inputFile'} = 'mglyphs.txt'; |
|
22 $globalValues{'outputFileName'} = 'mglyphs.inl'; |
|
23 $globalValues{'htmlFileName'} = 'mglyphs.html'; |
|
24 $globalValues{'lgtablesize'} = 9; # Default tablesize value is 512 |
|
25 $globalValues{'tablesize'} = 1 << $globalValues{'lgtablesize'}; |
|
26 $globalValues{'storeashex'} = 0; |
|
27 $globalValues{'stepOffset'} = 72; |
|
28 $globalValues{'stepShift'} = 0; |
|
29 |
|
30 ## die if the correct number of argumements have not been entered |
|
31 &extractFlags(\@ARGV, \%globalValues); |
|
32 &printDebug("Remainder:$globalValues{'tablesize'}\n"); |
|
33 &printDebug("StoreAsHex:$globalValues{'storeashex'}\n"); |
|
34 |
|
35 if ($globalValues{"information"}) |
|
36 { |
|
37 &dieShowingUsage(); |
|
38 } |
|
39 |
|
40 &printDebug("Creating HashTable....\n"); |
|
41 my %hashTable = &createHashTable($globalValues{'inputFile'}); |
|
42 if (!defined(%hashTable)) |
|
43 { |
|
44 die("ERROR: Hash table was not created\n"); |
|
45 } |
|
46 if ($globalValues{"outputtohtml"}) |
|
47 { |
|
48 my $htmlFileName = $globalValues{'htmlFileName'}; |
|
49 &printDebug("Creating HTML output to file: $htmlFileName\n"); |
|
50 &createHTMLOfMappings($htmlFileName, %hashTable); |
|
51 } |
|
52 my $outputFileName = $globalValues{'outputFileName'}; |
|
53 &printDebug("Writing Hash table to file: $outputFileName\n"); |
|
54 &writeHashTableToFile($outputFileName, %hashTable); |
|
55 &printDebug("$outputFileName created."); |
|
56 |
|
57 ##################### end of main section |
|
58 sub extractFlags |
|
59 { |
|
60 my $aArgumentArray=shift; |
|
61 my $aArguments=shift; |
|
62 my $expectedArg = 'lgtablesize'; |
|
63 my $expectedExtension; |
|
64 foreach my $argument (@$aArgumentArray) |
|
65 { |
|
66 if ($argument =~ m!^[-/]([a-zA-Z].*)$!) |
|
67 { |
|
68 my $switch = $1; |
|
69 $expectedArg = 'lgtablesize'; |
|
70 $expectedExtension = undef; |
|
71 if ($switch=~/^(x|hexoutput)$/i) |
|
72 { |
|
73 $$aArguments{'storeashex'}=1; |
|
74 } |
|
75 elsif ($switch=~/^(\?|help)$/i) |
|
76 { |
|
77 $$aArguments{'information'}=1; |
|
78 } |
|
79 elsif ($switch=~/^(v|verbose)$/i) |
|
80 { |
|
81 $$aArguments{'verbose'}=1; |
|
82 } |
|
83 elsif ($switch=~/^(h|outputtohtml)$/i) |
|
84 { |
|
85 $$aArguments{'outputtohtml'}=1; |
|
86 $expectedArg = 'htmlFileName'; |
|
87 $expectedExtension = '.html'; |
|
88 } |
|
89 elsif ($switch=~/^(i|input)$/i) |
|
90 { |
|
91 $expectedArg = 'inputFile'; |
|
92 } |
|
93 elsif ($switch=~/^(o|output)$/i) |
|
94 { |
|
95 $expectedArg = 'outputFileName'; |
|
96 $expectedExtension = '.inl'; |
|
97 } |
|
98 elsif ($switch=~/^(offset)$/i) |
|
99 { |
|
100 $expectedArg = 'stepOffset'; |
|
101 } |
|
102 elsif ($switch=~/^(shift)$/i) |
|
103 { |
|
104 $expectedArg = 'stepShift'; |
|
105 } |
|
106 } |
|
107 else |
|
108 { |
|
109 if (defined $expectedExtension && $argument !~ m!\.[^/\\]*$!) |
|
110 { |
|
111 $argument .= $expectedExtension; |
|
112 } |
|
113 $$aArguments{$expectedArg} = $argument; |
|
114 $expectedArg = 'lgtablesize'; |
|
115 } |
|
116 } |
|
117 $globalValues{'tablesize'} = 1 << $globalValues{'lgtablesize'}; |
|
118 $globalValues{'stepOffset'} &= 0xFFFFFE; |
|
119 } |
|
120 ##################### |
|
121 sub dieShowingUsage |
|
122 { |
|
123 print <<USAGE_EOF; |
|
124 |
|
125 Usage: |
|
126 |
|
127 perl -w mglyphtool.pl [-?] [<lg-table-size>] [-x] [-i <input-file-name>] |
|
128 [-o <output-file-name>] [-h [<output-html-file-name]] |
|
129 [-offset <value-for-offset>] [-shift <value-for-shift>] |
|
130 |
|
131 <lg-table-size> the default log(base 2) table size is 9. This gives a table |
|
132 size of 512 entries (2 to the power 9). So 7 gives a size of 128, 8 gives |
|
133 256, 9 gives 512, 10 gives 1024 and so on. |
|
134 |
|
135 options: -x -o -i -h |
|
136 |
|
137 -? Shows help |
|
138 |
|
139 The -x flag stores values into the .inl file in hex format: |
|
140 hex(OriginalKeyCodeMirrorGlyphCode), |
|
141 By default the values are stored in string hex format i.e 0x220C2209 |
|
142 |
|
143 The -h flag generates a html file displaying hash table information. |
|
144 This may be followed by the filename to be output. |
|
145 Default is 'mglyphs.html' |
|
146 |
|
147 The -i file specifies input file name. Default is 'mglyphs.txt'. |
|
148 |
|
149 The -o file specifies output file name. Default is 'mglyphs.inl'. |
|
150 |
|
151 -shift and -offset alter the "step" hash algorithm. |
|
152 |
|
153 USAGE_EOF |
|
154 exit 0; |
|
155 } |
|
156 ######### |
|
157 # |
|
158 # Writes a hash table to file. |
|
159 # Current format: |
|
160 # Hex mode: "hex number created" |
|
161 # Hex string mode: "Original keyMapped key" |
|
162 ##################### |
|
163 sub writeHashTableToFile |
|
164 { |
|
165 &printDebug("Writing to .inl file"); |
|
166 my ($aOutputFileName, %aHashTable) = @_; |
|
167 open(OUTPUT_FILE, '> ' . $aOutputFileName) or die('Error: could not open $aOutputFileName to write to\n'); |
|
168 ## Print comments at top of .inl file |
|
169 printf(OUTPUT_FILE "\/\/ mGlyphs.inl\n"); |
|
170 printf(OUTPUT_FILE "\/\/\n"); |
|
171 printf(OUTPUT_FILE "\/\/ Generated by mglyphtool.pl from '$globalValues{'inputFile'}'\n"); |
|
172 printf(OUTPUT_FILE "\/\/\n\n"); |
|
173 ## Declare array and fill in values |
|
174 printf(OUTPUT_FILE "const unsigned long mGlyphArray[] = {\n\t"); |
|
175 for (my $counter = 0; $counter < $globalValues{'tablesize'}; $counter++) |
|
176 { |
|
177 my $storeValue = "00000000"; |
|
178 if (defined($aHashTable{$counter})) |
|
179 { |
|
180 $storeValue = $aHashTable{$counter}; |
|
181 } |
|
182 $storeValue = ($globalValues{'storeashex'}) ? hex($storeValue) : "0x$storeValue"; |
|
183 print OUTPUT_FILE $storeValue; |
|
184 if (($counter+1) < $globalValues{'tablesize'}) |
|
185 { |
|
186 print OUTPUT_FILE (($counter + 1) % 8 == 0? ",\n\t" : ', '); |
|
187 } |
|
188 } |
|
189 print(OUTPUT_FILE "};\n"); |
|
190 print(OUTPUT_FILE "\nconst int KLgMirrorTableSize=$globalValues{'lgtablesize'};\n"); |
|
191 print(OUTPUT_FILE "const int KMirrorTableSize=$globalValues{'tablesize'};\n"); |
|
192 # Inline functions |
|
193 # Get a Hash value from a given key |
|
194 print(OUTPUT_FILE "\n// Returns the first index to probe for character aKey.\n"); |
|
195 print(OUTPUT_FILE "inline long MirrorStart(long aKey)\n"); |
|
196 print(OUTPUT_FILE "\t{ return aKey \& (KMirrorTableSize-1); }\n"); |
|
197 print(OUTPUT_FILE "\n// Returns the offset for further probes for character aKey.\n"); |
|
198 print(OUTPUT_FILE "inline long MirrorStep(long aKey)\n"); |
|
199 my $stepShift = $globalValues{'stepShift'}; |
|
200 print(OUTPUT_FILE "\t{ return ("); |
|
201 if ($stepShift == 0) |
|
202 { |
|
203 print(OUTPUT_FILE "aKey"); |
|
204 } |
|
205 elsif (0 < $stepShift) |
|
206 { |
|
207 print(OUTPUT_FILE "(aKey >> $stepShift)"); |
|
208 } |
|
209 else |
|
210 { |
|
211 $stepShift = -$stepShift; |
|
212 print(OUTPUT_FILE "(aKey << $stepShift)"); |
|
213 } |
|
214 print(OUTPUT_FILE " | 1) + $globalValues{'stepOffset'}; }\n\n"); |
|
215 |
|
216 close(OUTPUT_FILE); |
|
217 } |
|
218 ##################### listing of hash indexes values for original and mirrored glyphs |
|
219 sub createHTMLOfMappings |
|
220 { |
|
221 my ($aOutputFileName, %aHashTable )= @_; |
|
222 open(OUTPUT_FILE, '> ' . $aOutputFileName) or die('Error: could not open $aOutputFileName to create HTML output'); |
|
223 printf(OUTPUT_FILE "<HTML><HEAD><TITLE>MirrorGlyph Hash Output<\/TITLE><\/HEAD><BODY>"); |
|
224 ## print hash table details |
|
225 printf(OUTPUT_FILE "<P>Values in hash Table - <B>(Hash Function: Key mod $globalValues{'tablesize'})<\/B><\/P><TABLE border=1>"); |
|
226 printf(OUTPUT_FILE "<TR><TD><B>---<\/B><\/TD><TD BGCOLOR=\#8888FF><B>Character code:<\/B><\/TD><TD><B>Hash Index:<\/B><\/TD><TD BGCOLOR=\#8888FF><B>Mirror Glyph Value:<\/B><\/TD><TD><b>Search Jump Count<\/b>"); |
|
227 my %keySet; |
|
228 foreach my $value (values %aHashTable) |
|
229 { |
|
230 $keySet{&getLower(hex $value)} = 1; |
|
231 } |
|
232 foreach my $key (32..127) |
|
233 { |
|
234 $keySet{$key} = 1; |
|
235 } |
|
236 my @keys = sort {$a <=> $b} (keys %keySet); |
|
237 foreach my $key (@keys) |
|
238 { |
|
239 my $counter = 0; |
|
240 my $HKey = &findHashTableIndex($key, \$counter, \%aHashTable); |
|
241 my $stored = $aHashTable{$HKey}; |
|
242 my $storedValue = 'no change'; |
|
243 my $storedKey = $key; |
|
244 if (defined $stored) |
|
245 { |
|
246 $storedValue = sprintf('%02x', &getLower(hex $stored)); |
|
247 $storedKey = &getUpper(hex $stored); |
|
248 } |
|
249 if ($storedKey) |
|
250 { |
|
251 die('incorrect key found in hash table') unless ($storedKey == $key); |
|
252 printf(OUTPUT_FILE "<TR><TD>---<\/TD><TD BGCOLOR=\#8888FF><B>%02x<\/B><\/TD><TD>%02x<\/TD><TD BGCOLOR=\#8888FF><B>%s<\/B><\/TD><TD>%d<\/TD><\/TR>", $key, $HKey, $storedValue, $counter); |
|
253 } |
|
254 } |
|
255 printf(OUTPUT_FILE "<\/TABLE>"); |
|
256 printf(OUTPUT_FILE "<\/BODY><\/HTML>"); |
|
257 close(OUTPUT_FILE); |
|
258 } |
|
259 ##################### |
|
260 # Hash Table functions |
|
261 ##################### |
|
262 |
|
263 ##################### |
|
264 #Returns a new Hash Table |
|
265 ##################### |
|
266 sub createHashTable |
|
267 { |
|
268 my $aInputFileName = shift; |
|
269 my $lineNumber = 1; |
|
270 my %newHashTable = (); |
|
271 open(INPUT_FILE, '< ' . $aInputFileName) or die('ERROR: Could not open $aInputFileName to read from'); |
|
272 while (my $line=<INPUT_FILE>) |
|
273 { |
|
274 if ($line=~/^(.*);\s(.*\w)\s\W.*$/) ## Grab Original glyph value and mirrored glyph value |
|
275 { |
|
276 &updateHashTable($1, $2, \%newHashTable); |
|
277 } |
|
278 $lineNumber++; |
|
279 } |
|
280 close(INPUT_FILE); |
|
281 return %newHashTable; |
|
282 } |
|
283 ##################### |
|
284 # |
|
285 # Retrieves a HashKey which is not currently being used in a given HashTable |
|
286 # |
|
287 ##################### |
|
288 sub findHashTableIndex |
|
289 { |
|
290 my ($aHashKey, $aCounter, $aHashTable) = @_; |
|
291 my $current = &hashFunction($aHashKey); |
|
292 my $step = &hashStepFunction($aHashKey); |
|
293 my $tableSize = $globalValues{'tablesize'}; |
|
294 while (defined($$aHashTable{$current}) && &getUpper(hex($$aHashTable{$current})) != $aHashKey) |
|
295 { |
|
296 ++$$aCounter; |
|
297 $current += $step; |
|
298 $current &= $tableSize - 1; |
|
299 } |
|
300 if (2 < $$aCounter) |
|
301 { |
|
302 printf STDERR ("WARNING: Jumped $$aCounter times, inefficient hash for %02x ($current, $step)\n", $aHashKey); |
|
303 } |
|
304 return $current; |
|
305 } |
|
306 |
|
307 ##################### |
|
308 sub updateHashTable |
|
309 { |
|
310 my ($aKey, $aValueToStore, $aHashTable) = @_; |
|
311 my $counter = 0; |
|
312 my $key = hex($aKey); |
|
313 my $hashKey = &findHashTableIndex($key, \$counter, $aHashTable); |
|
314 $$aHashTable{$hashKey} = "$aKey$aValueToStore"; |
|
315 return $hashKey; |
|
316 } |
|
317 ##################### |
|
318 # Returns a hash key for a given key |
|
319 # Currently using a simple hash function |
|
320 ##################### |
|
321 sub hashFunction |
|
322 { |
|
323 my $aKey = shift; |
|
324 return $aKey & ($globalValues{'tablesize'}-1); |
|
325 } |
|
326 |
|
327 # Returns second hash value: used for the step size |
|
328 sub hashStepFunction |
|
329 { |
|
330 my $aKey = shift; |
|
331 my $stepShift = $globalValues{'stepShift'}; |
|
332 if ($stepShift < 0) |
|
333 { |
|
334 $aKey <<= -$stepShift; |
|
335 } |
|
336 elsif (0 < $stepShift) |
|
337 { |
|
338 $aKey >>= $stepShift; |
|
339 } |
|
340 return ($aKey | 1) + $globalValues{'stepOffset'}; |
|
341 } |
|
342 |
|
343 ##################### |
|
344 # Utility functions |
|
345 ##################### |
|
346 sub getLower |
|
347 { |
|
348 my $aValue = shift; |
|
349 return $aValue & hex("0000FFFF"); |
|
350 } |
|
351 sub getUpper |
|
352 { |
|
353 my $aValue = shift; |
|
354 return ($aValue & hex("FFFF0000")) >> 16; |
|
355 } |
|
356 sub printDebug |
|
357 { |
|
358 my $string = shift; |
|
359 if ($globalValues{'verbose'}) |
|
360 { |
|
361 print $string; |
|
362 } |
|
363 } |
|
364 |
|