os/textandloc/charconvfw/charconvplugins/tools/cnvtool.pl
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/textandloc/charconvfw/charconvplugins/tools/cnvtool.pl	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1533 @@
     1.4 +#
     1.5 +# Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.6 +# All rights reserved.
     1.7 +# This component and the accompanying materials are made available
     1.8 +# under the terms of "Eclipse Public License v1.0"
     1.9 +# which accompanies this distribution, and is available
    1.10 +# at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.11 +#
    1.12 +# Initial Contributors:
    1.13 +# Nokia Corporation - initial contribution.
    1.14 +#
    1.15 +# Contributors:
    1.16 +#
    1.17 +# Description: 
    1.18 +#
    1.19 +
    1.20 +use strict;
    1.21 +use integer;
    1.22 +
    1.23 +BEGIN
    1.24 +	{
    1.25 +	my $perlScriptPath=$0;
    1.26 +	my $os = $^O; #get the OS type
    1.27 +	#check OS type
    1.28 +  if($os=~/MSWin32/) #Windows OS
    1.29 +    {
    1.30 +    $perlScriptPath=~s/\//\\/g; # replace any forward-slashes with back-slashes
    1.31 +    $perlScriptPath=~s/(\\?)[^\\]+$/$1/; # get rid of this Perl-script's file-name
    1.32 +    }
    1.33 +  else #Unix OS
    1.34 +    {
    1.35 +    $perlScriptPath=~s/\\/\//g; # replace any back-slashes with forward-slashes
    1.36 +    $perlScriptPath=~s/(\/?)[^\/]+$/$1/; # get rid of this Perl-script's file-name
    1.37 +    }
    1.38 +	unshift(@INC, $perlScriptPath); # can't do "use lib $perlScriptPath" here as "use lib" only seems to work with *hard-coded* directory names
    1.39 +	}
    1.40 +use PARSER;
    1.41 +use WRITER;
    1.42 +
    1.43 +$|=1; # ensures that any progress information sent to the screen is displayed immediately and not buffered
    1.44 +if ((@ARGV==0) || ($ARGV[0]=~/\?/i) || ($ARGV[0]=~/-h/i) || ($ARGV[0]=~/help/i))
    1.45 +	{
    1.46 +	die("\nVersion 021\n\nCharacter-set conversion-table generating tool\nCopyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).\n\nUsage:\n\n\tcnvtool <control-file> <source-file> <output-file> [options]\n\nwhere the following options are available (each has a short form and a long form which are shown below separated by a '|'):\n\n\t-s | -generateSourceCode\n\t-c | -columns(<a>: <b>, <c>)\n\t-r | -omitReplacementForUnconvertibleUnicodeCharacters\n\t-p | -cutOutAnyPrivateUseUnicodeCharacterSlotsBeingUsed\n\t-u | -sourceFilesToSubtract(<a>, <b>, ...)\n\n");
    1.47 +	}
    1.48 +my $generateSourceCode=0;
    1.49 +my @columns=(2, 1, 2);
    1.50 +my $omitReplacementForUnconvertibleUnicodeCharacters=0;
    1.51 +my $cutOutAnyPrivateUseUnicodeCharacterSlotsBeingUsed=0;
    1.52 +my @sourceFilesToSubtract=();
    1.53 +my $flattenHashAndSave=0; # this flag is not published for use outside of the CHARCONV component
    1.54 +&extractCommandLineFlags(\$generateSourceCode, \@columns, \$omitReplacementForUnconvertibleUnicodeCharacters, \$cutOutAnyPrivateUseUnicodeCharacterSlotsBeingUsed, \@sourceFilesToSubtract, \$flattenHashAndSave);
    1.55 +(!$omitReplacementForUnconvertibleUnicodeCharacters || $generateSourceCode) or die("Error: bad combination of flags\n");
    1.56 +my $controlFile=shift;
    1.57 +my $sourceFile=shift;
    1.58 +my $outputFile=shift;
    1.59 +print("Generating $outputFile...\n");
    1.60 +my $uid=0;
    1.61 +my $endiannessAsText='';
    1.62 +my $endianness=0;
    1.63 +my $replacementForUnconvertibleUnicodeCharacters='';
    1.64 +my @foreignVariableByteData=();
    1.65 +my @foreignToUnicodeData=();
    1.66 +my @unicodeToForeignData=();
    1.67 +my %foreignCharacterCodes=();
    1.68 +my %unicodeCharacterCodes=();
    1.69 +my %preferredForeignCharacterCodesForConflictResolution=();
    1.70 +my %preferredUnicodeCharacterCodesForConflictResolution=();
    1.71 +my %additionalSubsetTables=();
    1.72 +my %privateUseUnicodeCharacterSlotsUsed=();
    1.73 +
    1.74 +print("    reading $controlFile...\n");
    1.75 +open(CONTROL_FILE, "< $controlFile") or die("Error: could not open \"$controlFile\" for reading\n");
    1.76 +&readHeaderFromControlFile(\*CONTROL_FILE, $controlFile, $generateSourceCode, \$uid, \$endiannessAsText, \$endianness, \$replacementForUnconvertibleUnicodeCharacters, $flattenHashAndSave);
    1.77 +&readForeignVariableByteDataFromControlFile(\*CONTROL_FILE, $controlFile, \@foreignVariableByteData);
    1.78 +&readOneDirectionDataFromControlFile(\*CONTROL_FILE, $controlFile, \@foreignToUnicodeData, \%preferredUnicodeCharacterCodesForConflictResolution, \%additionalSubsetTables, 1);
    1.79 +&readOneDirectionDataFromControlFile(\*CONTROL_FILE, $controlFile, \@unicodeToForeignData, \%preferredForeignCharacterCodesForConflictResolution, \%additionalSubsetTables, 0);
    1.80 +close(CONTROL_FILE) or die("Error: could not close \"$controlFile\"\n");
    1.81 +
    1.82 +print("    reading $sourceFile...\n");
    1.83 +open(SOURCE_FILE, "< $sourceFile") or die("Error: could not open \"$sourceFile\" for reading\n");
    1.84 +&readSourceFile(\*SOURCE_FILE, $sourceFile, \%foreignCharacterCodes, \%unicodeCharacterCodes, \@columns, $cutOutAnyPrivateUseUnicodeCharacterSlotsBeingUsed, \%privateUseUnicodeCharacterSlotsUsed, 0);
    1.85 +close(SOURCE_FILE) or die("Error: could not close \"$sourceFile\"\n");
    1.86 +
    1.87 +my $sourceFileToSubtract;
    1.88 +foreach $sourceFileToSubtract (@sourceFilesToSubtract)
    1.89 +	{
    1.90 +	print("    subtracting from $sourceFileToSubtract...\n");
    1.91 +	open(SOURCE_FILE_TO_SUBTRACT, "< $sourceFileToSubtract") or die("Error: could not open \"$sourceFileToSubtract\" for reading\n");
    1.92 +	&readSourceFile(\*SOURCE_FILE_TO_SUBTRACT, $sourceFileToSubtract, \%foreignCharacterCodes, \%unicodeCharacterCodes, \@columns, $cutOutAnyPrivateUseUnicodeCharacterSlotsBeingUsed, \%privateUseUnicodeCharacterSlotsUsed, 1);
    1.93 +	close(SOURCE_FILE_TO_SUBTRACT) or die("Error: could not close \"$sourceFileToSubtract\"\n");
    1.94 +	}
    1.95 +
    1.96 +&warnIfAnyPrivateUseUnicodeCharacterSlotsBeingUsed(\%privateUseUnicodeCharacterSlotsUsed);
    1.97 +&resolveConflictsAndFlattenArraysToScalars(\%foreignCharacterCodes, \%preferredForeignCharacterCodesForConflictResolution, 'Unicode', 'foreign');
    1.98 +&resolveConflictsAndFlattenArraysToScalars(\%unicodeCharacterCodes, \%preferredUnicodeCharacterCodesForConflictResolution, 'foreign', 'Unicode');
    1.99 +&checkForeignVariableByteData($endianness, \@foreignVariableByteData, \@foreignToUnicodeData);
   1.100 +
   1.101 +print("    writing $outputFile...\n");
   1.102 +open(OUTPUT_FILE, "> $outputFile") or die("Error: could not open \"$outputFile\" for writing\n");
   1.103 +if ($generateSourceCode)
   1.104 +	{
   1.105 +	my @sourceCodeOfForeignToUnicodeIndexedTables16=();
   1.106 +	my @sourceCodeOfForeignToUnicodeKeyedTables1616=();
   1.107 +	my @sourceCodeOfForeignToUnicodeKeyedTables16OfIndexedTables16_indexedEntries=();
   1.108 +	my @sourceCodeOfForeignToUnicodeKeyedTables16OfIndexedTables16_keyedEntries=();
   1.109 +
   1.110 +	my @sourceCodeOfUnicodeToForeignIndexedTables16=();
   1.111 +	my @sourceCodeOfUnicodeToForeignKeyedTables1616=();
   1.112 +	my @sourceCodeOfUnicodeToForeignKeyedTables16OfIndexedTables16_indexedEntries=();
   1.113 +	my @sourceCodeOfUnicodeToForeignKeyedTables16OfIndexedTables16_keyedEntries=();
   1.114 +
   1.115 +	# new for 32 bit encoding begin
   1.116 +	my @sourceCodeOfForeignToUnicodeIndexedTables32=();
   1.117 +	my @sourceCodeOfForeignToUnicodeKeyedTables3232=();
   1.118 +	my @sourceCodeOfForeignToUnicodeKeyedTables32OfIndexedTables32_indexedEntries=();
   1.119 +	my @sourceCodeOfForeignToUnicodeKeyedTables32OfIndexedTables32_keyedEntries=();
   1.120 +
   1.121 +	my @sourceCodeOfUnicodeToForeignIndexedTables32=();
   1.122 +	my @sourceCodeOfUnicodeToForeignKeyedTables3232=();
   1.123 +	my @sourceCodeOfUnicodeToForeignKeyedTables32OfIndexedTables32_indexedEntries=();
   1.124 +	my @sourceCodeOfUnicodeToForeignKeyedTables32OfIndexedTables32_keyedEntries=();
   1.125 +	# new for 32 bit endcoding end
   1.126 +
   1.127 +	my @sourceCodeOfTopLevelStructures=();
   1.128 +
   1.129 +	&writeSourceCodeHeader(\*OUTPUT_FILE, $outputFile, $replacementForUnconvertibleUnicodeCharacters);
   1.130 +	&writeSourceCodeForeignVariableByteData(\@sourceCodeOfTopLevelStructures, \@foreignVariableByteData);
   1.131 +	&writeSourceCodeOneDirectionData(\@sourceCodeOfTopLevelStructures,
   1.132 +		\@sourceCodeOfForeignToUnicodeIndexedTables16, \@sourceCodeOfForeignToUnicodeKeyedTables1616, \@sourceCodeOfForeignToUnicodeKeyedTables16OfIndexedTables16_indexedEntries, \@sourceCodeOfForeignToUnicodeKeyedTables16OfIndexedTables16_keyedEntries,
   1.133 +		\@sourceCodeOfForeignToUnicodeIndexedTables32, \@sourceCodeOfForeignToUnicodeKeyedTables3232, \@sourceCodeOfForeignToUnicodeKeyedTables32OfIndexedTables32_indexedEntries, \@sourceCodeOfForeignToUnicodeKeyedTables32OfIndexedTables32_keyedEntries,
   1.134 +		\@foreignToUnicodeData, \%unicodeCharacterCodes, 1);
   1.135 +	&writeSourceCodeOneDirectionData(\@sourceCodeOfTopLevelStructures,
   1.136 +		\@sourceCodeOfUnicodeToForeignIndexedTables16, \@sourceCodeOfUnicodeToForeignKeyedTables1616, \@sourceCodeOfUnicodeToForeignKeyedTables16OfIndexedTables16_indexedEntries, \@sourceCodeOfUnicodeToForeignKeyedTables16OfIndexedTables16_keyedEntries,
   1.137 +		\@sourceCodeOfUnicodeToForeignIndexedTables32, \@sourceCodeOfUnicodeToForeignKeyedTables3232, \@sourceCodeOfUnicodeToForeignKeyedTables32OfIndexedTables32_indexedEntries, \@sourceCodeOfUnicodeToForeignKeyedTables32OfIndexedTables32_keyedEntries,
   1.138 +		\@unicodeToForeignData, \%foreignCharacterCodes, 0);
   1.139 +	&writeSourceCodeFinalStuff(\*OUTPUT_FILE,
   1.140 +		\@sourceCodeOfForeignToUnicodeIndexedTables16, \@sourceCodeOfForeignToUnicodeKeyedTables1616, \@sourceCodeOfForeignToUnicodeKeyedTables16OfIndexedTables16_indexedEntries, \@sourceCodeOfForeignToUnicodeKeyedTables16OfIndexedTables16_keyedEntries,
   1.141 +		\@sourceCodeOfUnicodeToForeignIndexedTables16, \@sourceCodeOfUnicodeToForeignKeyedTables1616, \@sourceCodeOfUnicodeToForeignKeyedTables16OfIndexedTables16_indexedEntries, \@sourceCodeOfUnicodeToForeignKeyedTables16OfIndexedTables16_keyedEntries,
   1.142 +		\@sourceCodeOfForeignToUnicodeIndexedTables32, \@sourceCodeOfForeignToUnicodeKeyedTables3232, \@sourceCodeOfForeignToUnicodeKeyedTables32OfIndexedTables32_indexedEntries, \@sourceCodeOfForeignToUnicodeKeyedTables32OfIndexedTables32_keyedEntries,
   1.143 +		\@sourceCodeOfUnicodeToForeignIndexedTables32, \@sourceCodeOfUnicodeToForeignKeyedTables3232, \@sourceCodeOfUnicodeToForeignKeyedTables32OfIndexedTables32_indexedEntries, \@sourceCodeOfUnicodeToForeignKeyedTables32OfIndexedTables32_keyedEntries,
   1.144 +		\@sourceCodeOfTopLevelStructures, $endiannessAsText, \%additionalSubsetTables);
   1.145 +	}
   1.146 +elsif ($flattenHashAndSave)
   1.147 +	{
   1.148 +	binmode OUTPUT_FILE;
   1.149 +	#instead of calling the writeBinaryHeader, just write the data I need followed by 
   1.150 +	# writeBinaryForeignVariableByteData...
   1.151 +	&write8(\*OUTPUT_FILE, $endianness);
   1.152 +	&write8(\*OUTPUT_FILE, length($replacementForUnconvertibleUnicodeCharacters));
   1.153 +	&writeString(\*OUTPUT_FILE, $replacementForUnconvertibleUnicodeCharacters);
   1.154 +	&writeBinaryForeignVariableByteData(\*OUTPUT_FILE, \@foreignVariableByteData);
   1.155 +	#choose %unicodeCharacterCodes and write the data as keypair
   1.156 +	my $key;
   1.157 +	my $rangekey;
   1.158 +	my $limit;
   1.159 +	foreach $key (keys(%unicodeCharacterCodes))
   1.160 +		{
   1.161 +		&write16(\*OUTPUT_FILE,$key);
   1.162 +		&write16(\*OUTPUT_FILE,$unicodeCharacterCodes{$key});
   1.163 +		}
   1.164 +	}
   1.165 +else
   1.166 +	{
   1.167 +	binmode OUTPUT_FILE;
   1.168 +	&writeBinaryHeader(\*OUTPUT_FILE, $uid, $endianness, $replacementForUnconvertibleUnicodeCharacters);
   1.169 +	&writeBinaryForeignVariableByteData(\*OUTPUT_FILE, \@foreignVariableByteData);
   1.170 +	&writeBinaryOneDirectionData(\*OUTPUT_FILE, \@foreignToUnicodeData, \%unicodeCharacterCodes, 1);
   1.171 +	&writeBinaryOneDirectionData(\*OUTPUT_FILE, \@unicodeToForeignData, \%foreignCharacterCodes, 0);
   1.172 +	}
   1.173 +close(OUTPUT_FILE) or die("Error: could not close \"$outputFile\"\n");
   1.174 +print("complete\n\n");
   1.175 +
   1.176 +sub extractCommandLineFlags()
   1.177 +	{
   1.178 +	my $generateSourceCode=shift;
   1.179 +	my $columns=shift;
   1.180 +	my $omitReplacementForUnconvertibleUnicodeCharacters=shift;
   1.181 +	my $cutOutAnyPrivateUseUnicodeCharacterSlotsBeingUsed=shift;
   1.182 +	my $sourceFilesToSubtract=shift;
   1.183 +	my $flattenHashAndSave=shift;
   1.184 +	my $i;
   1.185 +	for ($i=0; $i<=$#ARGV;) # (i) not cache-ing $#ARGV into a variable as @ARGV may change length in this loop (ii) iterate forwards as some parameters may occupy more than one element in @ARGV
   1.186 +		{
   1.187 +		if (($ARGV[$i]=~/^-s$/i) || ($ARGV[$i]=~/^-generateSourceCode$/i))
   1.188 +			{
   1.189 +			if ($$flattenHashAndSave==1)
   1.190 +				{
   1.191 +				die ("Error: Cannot have -s and -b flags set at the same time");
   1.192 +				}
   1.193 +			else
   1.194 +				{
   1.195 +				splice(@ARGV, $i, 1);
   1.196 +				$$generateSourceCode=1;
   1.197 +				}
   1.198 +			}
   1.199 +		elsif (($ARGV[$i]=~/^-c\b(.*)$/i) || ($ARGV[$i]=~/^-columns\b(.*)$/i))
   1.200 +			{
   1.201 +			my $columnsData=$1;
   1.202 +			splice(@ARGV, $i, 1);
   1.203 +			for (;;)
   1.204 +				{
   1.205 +				if ($columnsData=~/^\s*\(\s*(\d+)\s*:\s*(\d+)\s*\,?\s*(\d+)\s*\)\s*$/)
   1.206 +					{
   1.207 +					@$columns=($1, $2, $3);
   1.208 +					last;
   1.209 +					}
   1.210 +				($#ARGV>=$i) or die("Error: bad \"-columns\" format\n");
   1.211 +				$columnsData.=(splice(@ARGV, $i, 1))[0];
   1.212 +				}
   1.213 +			}
   1.214 +		elsif (($ARGV[$i]=~/^-r$/i) || ($ARGV[$i]=~/^-omitReplacementForUnconvertibleUnicodeCharacters$/i))
   1.215 +			{
   1.216 +			splice(@ARGV, $i, 1);
   1.217 +			$$omitReplacementForUnconvertibleUnicodeCharacters=1;
   1.218 +			}
   1.219 +		elsif (($ARGV[$i]=~/^-p$/i) || ($ARGV[$i]=~/^-cutOutAnyPrivateUseUnicodeCharacterSlotsBeingUsed$/i))
   1.220 +			{
   1.221 +			splice(@ARGV, $i, 1);
   1.222 +			$$cutOutAnyPrivateUseUnicodeCharacterSlotsBeingUsed=1;
   1.223 +			}
   1.224 +		elsif (($ARGV[$i]=~/^-u\b(.*)$/i) || ($ARGV[$i]=~/^-sourceFilesToSubtract\b(.*)$/i))
   1.225 +			{
   1.226 +			my $sourceFilesData=$1;
   1.227 +			splice(@ARGV, $i, 1);
   1.228 +			for (;;)
   1.229 +				{
   1.230 +				if ($sourceFilesData=~/^\s*\(\s*(.+)\)\s*$/)
   1.231 +					{
   1.232 +					my $sourceFilesData=$1;
   1.233 +					@$sourceFilesToSubtract=split(/,/, $sourceFilesData, -1);
   1.234 +					my $j;
   1.235 +					for ($j=$#$sourceFilesToSubtract; $j>=0; --$j)
   1.236 +						{
   1.237 +						$sourceFilesToSubtract->[$j]=~s/^\s+//;
   1.238 +						$sourceFilesToSubtract->[$j]=~s/\s+$//;
   1.239 +						($sourceFilesToSubtract->[$j] ne '') or die("Error: bad \"-sourceFilesToSubtract\" format (1)\n");
   1.240 +						}
   1.241 +					last;
   1.242 +					}
   1.243 +				($#ARGV>=$i) or die("Error: bad \"-sourceFilesToSubtract\" format (2)\n");
   1.244 +				$sourceFilesData.=(splice(@ARGV, $i, 1))[0];
   1.245 +				}
   1.246 +			}
   1.247 +		elsif (($ARGV[$i]=~/^-f$/i) || ($ARGV[$i]=~/^-flattenHashAndSave$/i))
   1.248 +			{
   1.249 +			if ($$generateSourceCode==1)
   1.250 +				{
   1.251 +				die ("Error: Cannot have -s and -b flags set at the same time");
   1.252 +				}
   1.253 +			else
   1.254 +				{
   1.255 +				splice(@ARGV, $i, 1);
   1.256 +				$$flattenHashAndSave=1;
   1.257 +				}
   1.258 +			}
   1.259 +		else
   1.260 +			{
   1.261 +			++$i;
   1.262 +			}
   1.263 +		}
   1.264 +	}
   1.265 +
   1.266 +sub algorithm
   1.267 +	{
   1.268 +	my $algorithmAsText=shift;
   1.269 +	if ($algorithmAsText=~/^Direct$/i)
   1.270 +		{
   1.271 +		return 0;
   1.272 +		}
   1.273 +	elsif ($algorithmAsText=~/^Offset$/i)
   1.274 +		{
   1.275 +		return 1;
   1.276 +		}
   1.277 +	elsif ($algorithmAsText=~/^IndexedTable16$/i)
   1.278 +		{
   1.279 +		return 2;
   1.280 +		}
   1.281 +	elsif ($algorithmAsText=~/^KeyedTable1616$/i)
   1.282 +		{
   1.283 +		return 3;
   1.284 +		}
   1.285 +	elsif ($algorithmAsText=~/^KeyedTable16OfIndexedTables16$/i)
   1.286 +		{
   1.287 +		return 4;
   1.288 +		}
   1.289 +	elsif ($algorithmAsText=~/^IndexedTable32$/i)
   1.290 +		{
   1.291 +		return 5;
   1.292 +		}
   1.293 +	elsif ($algorithmAsText=~/^KeyedTable3232$/i)
   1.294 +		{
   1.295 +		return 6;
   1.296 +		}
   1.297 +	elsif ($algorithmAsText=~/^KeyedTable32OfIndexedTables32$/i)
   1.298 +		{
   1.299 +		return 7;
   1.300 +		}
   1.301 +	else
   1.302 +		{
   1.303 +		return -1;
   1.304 +		}
   1.305 +	}
   1.306 +
   1.307 +sub hexadecimalify
   1.308 +	{
   1.309 +	my $string=shift;
   1.310 +	my $result='';
   1.311 +	my $lengthOfString=length($string);
   1.312 +	my $i;
   1.313 +	for ($i=0; $i<$lengthOfString; ++$i)
   1.314 +		{
   1.315 +		$result.=sprintf("\\x%02x", (unpack('C', substr($string, $i, 1)))[0]);
   1.316 +		}
   1.317 +	return $result;
   1.318 +	}
   1.319 +
   1.320 +sub readSourceFile
   1.321 +	{
   1.322 +	my $fileHandle=shift;
   1.323 +	my $fileName=shift;
   1.324 +	my $foreignCharacterCodes=shift;
   1.325 +	my $unicodeCharacterCodes=shift;
   1.326 +	my $columns=shift;
   1.327 +	my $cutOutAnyPrivateUseUnicodeCharacterSlotsBeingUsed=shift;
   1.328 +	my $privateUseUnicodeCharacterSlotsUsed=shift;
   1.329 +	my $subtract=shift;
   1.330 +	my $foreignCharacterCodeProcessingCode='';
   1.331 +	if (!(($columns->[0]>0) && ($columns->[1]>0) && ($columns->[2]>0) && ($columns->[1]<=$columns->[0]) && ($columns->[2]<=$columns->[0]) && ($columns->[1]!=$columns->[2])))
   1.332 +		{
   1.333 +		close($fileHandle);
   1.334 +		die("Error: bad \"-columns\" data\n");
   1.335 +		}
   1.336 +	my $patternOfLineContainingCharacterCodes=join('\s+', ('0x([0-9a-f]+)') x $columns->[0]);
   1.337 +	my $line;
   1.338 +	my $strippedDownLine;
   1.339 +	for (;;)
   1.340 +		{
   1.341 +		($line, $strippedDownLine)=&nextNonEmptyStrippedDownLine($fileHandle);
   1.342 +		if (($strippedDownLine eq '')||(substr($strippedDownLine,0,1) eq chr(26)))  # if there are no more lines in the file or if we encountered EOF character
   1.343 +			{
   1.344 +			last;
   1.345 +			}
   1.346 +		if ($strippedDownLine=~/^SET_FOREIGN_CHARACTER_CODE_PROCESSING_CODE\s+(.*)$/i)
   1.347 +			{
   1.348 +			$foreignCharacterCodeProcessingCode=$1;
   1.349 +			}
   1.350 +		elsif ($strippedDownLine=~/^$patternOfLineContainingCharacterCodes$/i)
   1.351 +			{
   1.352 +			no strict 'refs'; # so that we can use symbolic references for $1, $2, etc
   1.353 +			my $foreignCharacterCode=hex(${$columns->[1]});
   1.354 +			my $unicodeCharacterCode=hex(${$columns->[2]});
   1.355 +			use strict 'refs';
   1.356 +			if ($foreignCharacterCodeProcessingCode ne '')
   1.357 +				{
   1.358 +				$foreignCharacterCode=eval($foreignCharacterCodeProcessingCode);
   1.359 +				}
   1.360 +			my $handleConversionPair=1;
   1.361 +			if ((($unicodeCharacterCode>=0xe000) && ($unicodeCharacterCode<=0xf8ff)) || (($unicodeCharacterCode>=0xf0000) && ($unicodeCharacterCode<=0x10ffff)))
   1.362 +				{
   1.363 +				if ($cutOutAnyPrivateUseUnicodeCharacterSlotsBeingUsed)
   1.364 +					{
   1.365 +					$handleConversionPair=0;
   1.366 +					}
   1.367 +				else
   1.368 +					{
   1.369 +					if ($subtract)
   1.370 +						{
   1.371 +						delete $privateUseUnicodeCharacterSlotsUsed->{$unicodeCharacterCode};
   1.372 +						}
   1.373 +					else
   1.374 +						{
   1.375 +						$privateUseUnicodeCharacterSlotsUsed->{$unicodeCharacterCode}=1;
   1.376 +						}
   1.377 +					}
   1.378 +				}
   1.379 +			if ($handleConversionPair)
   1.380 +				{
   1.381 +				if ($subtract)
   1.382 +					{
   1.383 +					if (!defined($foreignCharacterCodes->{$unicodeCharacterCode}->{$foreignCharacterCode}))
   1.384 +						{
   1.385 +						close($fileHandle);
   1.386 +						die('Error: cannot subtract conversion pair ['.sprintf('foreign 0x%x, Unicode 0x%04x', $foreignCharacterCode, $unicodeCharacterCode)."] as it does not occur in \"$fileName\"\n");
   1.387 +						}
   1.388 +					if (!defined($unicodeCharacterCodes->{$foreignCharacterCode}->{$unicodeCharacterCode}))
   1.389 +						{
   1.390 +						close($fileHandle);
   1.391 +						die('Error: cannot subtract conversion pair ['.sprintf('Unicode 0x%04x, foreign 0x%x', $unicodeCharacterCode, $foreignCharacterCode)."] as it does not occur in \"$fileName\"\n");
   1.392 +						}
   1.393 +					delete $foreignCharacterCodes->{$unicodeCharacterCode}->{$foreignCharacterCode};
   1.394 +					if (keys(%{$foreignCharacterCodes->{$unicodeCharacterCode}})==0)
   1.395 +						{
   1.396 +						delete $foreignCharacterCodes->{$unicodeCharacterCode};
   1.397 +						}
   1.398 +					delete $unicodeCharacterCodes->{$foreignCharacterCode}->{$unicodeCharacterCode};
   1.399 +					if (keys(%{$unicodeCharacterCodes->{$foreignCharacterCode}})==0)
   1.400 +						{
   1.401 +						delete $unicodeCharacterCodes->{$foreignCharacterCode};
   1.402 +						}
   1.403 +					}
   1.404 +				else
   1.405 +					{
   1.406 +					if (defined($foreignCharacterCodes->{$unicodeCharacterCode}->{$foreignCharacterCode}))
   1.407 +						{
   1.408 +						close($fileHandle);
   1.409 +						die('Error: same conversion pair ['.sprintf('foreign 0x%x, Unicode 0x%04x', $foreignCharacterCode, $unicodeCharacterCode)."] occurs more than once in \"$fileName\"\n");
   1.410 +						}
   1.411 +					if (defined($unicodeCharacterCodes->{$foreignCharacterCode}->{$unicodeCharacterCode}))
   1.412 +						{
   1.413 +						close($fileHandle);
   1.414 +						die('Error: same conversion pair ['.sprintf('Unicode 0x%04x, foreign 0x%x', $unicodeCharacterCode, $foreignCharacterCode)."] occurs more than once in \"$fileName\"\n");
   1.415 +						}
   1.416 +					$foreignCharacterCodes->{$unicodeCharacterCode}->{$foreignCharacterCode}=1;
   1.417 +					$unicodeCharacterCodes->{$foreignCharacterCode}->{$unicodeCharacterCode}=1;
   1.418 +					}
   1.419 +				}
   1.420 +			}
   1.421 +		elsif ($line!~/^\s*0x([0-9a-f]+)\s*#\s*undefined.*$/i)
   1.422 +			{
   1.423 +			close($fileHandle);
   1.424 +			die("Error: unexpected line in \"$fileName\":\n    $line\n");
   1.425 +			}
   1.426 +		}
   1.427 +	}
   1.428 +
   1.429 +sub readHeaderFromControlFile
   1.430 +	{
   1.431 +	my $fileHandle=shift;
   1.432 +	my $fileName=shift;
   1.433 +	my $generateSourceCode=shift;
   1.434 +	my $uid=shift;
   1.435 +	my $endiannessAsText=shift;
   1.436 +	my $endianness=shift;
   1.437 +	my $replacementForUnconvertibleUnicodeCharacters=shift;
   1.438 +	my $flattenHashAndSave=shift;
   1.439 +	my $line;
   1.440 +	my $strippedDownLine;
   1.441 +	($line, $strippedDownLine)=&nextNonEmptyStrippedDownLine($fileHandle);
   1.442 +	if ($strippedDownLine=~/^UID\s+0x([0-9a-f]+)$/i)
   1.443 +		{
   1.444 +		if ($generateSourceCode)
   1.445 +			{
   1.446 +			print(STDERR "Warning: \"UID\" keyword should not be used with \"-generateSourceCode\" flag - specify the UID in the MMP file\n");
   1.447 +			}
   1.448 +		$$uid=hex($1);
   1.449 +		($line, $strippedDownLine)=&nextNonEmptyStrippedDownLine($fileHandle);
   1.450 +		}
   1.451 +	else
   1.452 +		{
   1.453 +		if (!$generateSourceCode && !$flattenHashAndSave)
   1.454 +			{
   1.455 +			close($fileHandle);
   1.456 +			die("Error: unexpected line in \"$fileName\" (\"UID\" keyword expected):\n    $line\n");
   1.457 +			}
   1.458 +		}
   1.459 +	if ($strippedDownLine=~/^Name\s+"(.+?)"$/i)
   1.460 +		{
   1.461 +		print(STDERR "Warning: obsolete keyword \"Name\" used\n");
   1.462 +		($line, $strippedDownLine)=&nextNonEmptyStrippedDownLine($fileHandle);
   1.463 +		}
   1.464 +	if ($strippedDownLine!~/^Endianness\s+(\w+)$/i)
   1.465 +		{
   1.466 +		close($fileHandle);
   1.467 +		die("Error: unexpected line in \"$fileName\" (\"Endianness\" keyword expected):\n    $line\n");
   1.468 +		}
   1.469 +	$$endiannessAsText=$1;
   1.470 +	if ($$endiannessAsText=~/Unspecified/i)
   1.471 +		{
   1.472 +		$$endianness=0; # SCnvConversionData::EUnspecified
   1.473 +		}
   1.474 +	elsif ($$endiannessAsText=~/FixedLittleEndian/i)
   1.475 +		{
   1.476 +		$$endianness=1; # SCnvConversionData::EFixedLittleEndian
   1.477 +		}
   1.478 +	elsif ($$endiannessAsText=~/FixedBigEndian/i)
   1.479 +		{
   1.480 +		$$endianness=2; # SCnvConversionData::EFixedBigEndian
   1.481 +		}
   1.482 +	else
   1.483 +		{
   1.484 +		close($fileHandle);
   1.485 +		die("Error: \"$$endiannessAsText\" is not a legal value for \"Endianness\"\n");
   1.486 +		}
   1.487 +	($line, $strippedDownLine)=&nextNonEmptyStrippedDownLine($fileHandle);
   1.488 +	if ($strippedDownLine!~/^ReplacementForUnconvertibleUnicodeCharacters\s+(.*?)$/i)
   1.489 +		{
   1.490 +		close($fileHandle);
   1.491 +		die("Error: unexpected line in \"$fileName\" (\"ReplacementForUnconvertibleUnicodeCharacters\" keyword expected):\n    $line\n");
   1.492 +		}
   1.493 +	$$replacementForUnconvertibleUnicodeCharacters='';
   1.494 +	my $remainderOfXxx=$1;
   1.495 +	while ($remainderOfXxx ne '')
   1.496 +		{
   1.497 +		if ($remainderOfXxx!~/^0x([0-9a-f]{1,2})\s*(.*)$/i)
   1.498 +			{
   1.499 +			close($fileHandle);
   1.500 +			die("Error: unexpected line in \"$fileName\":\n    $line\n");
   1.501 +			}
   1.502 +		$$replacementForUnconvertibleUnicodeCharacters.=pack("C", hex($1));
   1.503 +		$remainderOfXxx=$2;
   1.504 +		}
   1.505 +	my @temp=&nextNonEmptyStrippedDownLine($fileHandle);
   1.506 +	if ($temp[1]=~/^ForeignCharacterCodeProcessingCode/i)
   1.507 +		{
   1.508 +		print(STDERR "Warning: obsolete keyword \"ForeignCharacterCodeProcessingCode\" used\n");
   1.509 +		}
   1.510 +	else
   1.511 +		{
   1.512 +		ungetNonEmptyStrippedDownLine(@temp)
   1.513 +		}
   1.514 +	}
   1.515 +
   1.516 +sub readForeignVariableByteDataFromControlFile
   1.517 +	{
   1.518 +	my $fileHandle=shift;
   1.519 +	my $fileName=shift;
   1.520 +	my $foreignVariableByteData=shift;
   1.521 +	my $line;
   1.522 +	my $strippedDownLine;
   1.523 +	($line, $strippedDownLine)=&nextNonEmptyStrippedDownLine($fileHandle);
   1.524 +	if ($strippedDownLine!~/^StartForeignVariableByteData$/i)
   1.525 +		{
   1.526 +		close($fileHandle);
   1.527 +		die("Error: unexpected line in \"$fileName\":\n    $line\n");
   1.528 +		}
   1.529 +
   1.530 +	for (;;)
   1.531 +		{
   1.532 +		($line, $strippedDownLine)=&nextNonEmptyStrippedDownLine($fileHandle);
   1.533 +		if ($strippedDownLine=~/^EndForeignVariableByteData$/i)
   1.534 +			{
   1.535 +			last;
   1.536 +			}
   1.537 +		if ($strippedDownLine!~/^0x([0-9a-f]+)\s+0x([0-9a-f]+)\s+(\d+)$/i)
   1.538 +			{
   1.539 +			close($fileHandle);
   1.540 +			die("Error: unexpected line in \"$fileName\":\n    $line\n");
   1.541 +			}
   1.542 +		my $firstInitialByteValueInRange=hex($1);
   1.543 +		my $lastInitialByteValueInRange=hex($2);
   1.544 +		my $numberOfSubsequentBytes=$3;
   1.545 +		if ($firstInitialByteValueInRange>0xff)
   1.546 +			{
   1.547 +			close($fileHandle);
   1.548 +			die("Error: firstInitialByteValueInRange ".sprintf("0x%02x", $firstInitialByteValueInRange)." does not fit in a single byte\n");
   1.549 +			}
   1.550 +		if ($lastInitialByteValueInRange>0xff)
   1.551 +			{
   1.552 +			close($fileHandle);
   1.553 +			die("Error: lastInitialByteValueInRange ".sprintf("0x%02x", $lastInitialByteValueInRange)." does not fit in a single byte\n");
   1.554 +			}
   1.555 +		if ($lastInitialByteValueInRange<$firstInitialByteValueInRange)
   1.556 +			{
   1.557 +			close($fileHandle);
   1.558 +			die("Error: lastInitialByteValueInRange ".sprintf("0x%02x", $lastInitialByteValueInRange)." is less than firstInitialByteValueInRange ".sprintf("0x%02x", $firstInitialByteValueInRange)."\n");
   1.559 +			}
   1.560 +		push(@$foreignVariableByteData, [$firstInitialByteValueInRange, $lastInitialByteValueInRange, $numberOfSubsequentBytes]);
   1.561 +		}
   1.562 +	}
   1.563 +
   1.564 +sub readOneDirectionDataFromControlFile
   1.565 +	{
   1.566 +	my $fileHandle=shift;
   1.567 +	my $fileName=shift;
   1.568 +	my $oneDirectionData=shift;
   1.569 +	my $preferredCharacterCodesForConflictResolution=shift;
   1.570 +	my $additionalSubsetTables=shift;
   1.571 +	my $outputIsUnicode=shift;
   1.572 +	my $source=$outputIsUnicode? 'foreign': 'Unicode';
   1.573 +	my $target=$outputIsUnicode? 'Unicode': 'foreign';
   1.574 +	my $middlePortionOfKeyWords=$outputIsUnicode? "ForeignToUnicode": "UnicodeToForeign";
   1.575 +	my $extraPatternToMatch=$outputIsUnicode? '()': '\s+(\d+)';
   1.576 +	my $line;
   1.577 +	my $strippedDownLine;
   1.578 +	($line, $strippedDownLine)=&nextNonEmptyStrippedDownLine($fileHandle);
   1.579 +	if ($strippedDownLine!~/^Start${middlePortionOfKeyWords}Data$/i)
   1.580 +		{
   1.581 +		close($fileHandle);
   1.582 +		die("Error: unexpected line in \"$fileName\":\n    $line\n");
   1.583 +		}
   1.584 +	my $doingConflictResolution=0;
   1.585 +	for (;;)
   1.586 +		{
   1.587 +		($line, $strippedDownLine)=&nextNonEmptyStrippedDownLine($fileHandle);
   1.588 +		if ($strippedDownLine=~/^End${middlePortionOfKeyWords}Data$/i)
   1.589 +			{
   1.590 +			last;
   1.591 +			}
   1.592 +		if ($strippedDownLine=~/^ConflictResolution$/i)
   1.593 +			{
   1.594 +			$doingConflictResolution=1;
   1.595 +			}
   1.596 +		elsif ($doingConflictResolution)
   1.597 +			{
   1.598 +			if ($strippedDownLine!~/^0x([0-9a-f]+)\s+0x([0-9a-f]+)$/i)
   1.599 +				{
   1.600 +				close($fileHandle);
   1.601 +				die("Error: unexpected line in \"$fileName\":\n    $line\n");
   1.602 +				}
   1.603 +			my $sourceCharacterCodeToResolve=hex($1);
   1.604 +			my $targetCharacterCodePreferred=hex($2);
   1.605 +			$preferredCharacterCodesForConflictResolution->{$sourceCharacterCodeToResolve}=$targetCharacterCodePreferred;
   1.606 +			}
   1.607 +		elsif ($strippedDownLine=~/^(Start|End)AdditionalSubsetTable\s+(.*)$/i)
   1.608 +			{
   1.609 +			my $prefix=$1;
   1.610 +			my $nameOfAdditionalSubsetTable=$2;
   1.611 +			my $index=$prefix=~(/^Start$/i)? 0: 1;
   1.612 +			if (!$outputIsUnicode)
   1.613 +				{
   1.614 +				$index+=2;
   1.615 +				}
   1.616 +			if (defined($additionalSubsetTables{$nameOfAdditionalSubsetTable}->[$index]))
   1.617 +				{
   1.618 +				close($fileHandle);
   1.619 +				die("Error: multiple redefinition of \"${prefix}AdditionalSubsetTable $nameOfAdditionalSubsetTable\"\n");
   1.620 +				}
   1.621 +			$additionalSubsetTables{$nameOfAdditionalSubsetTable}->[$index]=@$oneDirectionData;
   1.622 +			}
   1.623 +		else
   1.624 +			{
   1.625 +			if ($strippedDownLine!~/^(\d+)\s+(\d+)\s+0x([0-9a-f]+)\s+0x([0-9a-f]+)\s+(\w+)$extraPatternToMatch\s+\{(.*?)\}$/i)
   1.626 +				{
   1.627 +				close($fileHandle);
   1.628 +				die("Error: unexpected line in \"$fileName\":\n    $line\n");
   1.629 +				}
   1.630 +			my $includePriority=$1;
   1.631 +			my $searchPriority=$2;
   1.632 +			my $firstInputCharacterCodeInRange=hex($3);
   1.633 +			my $lastInputCharacterCodeInRange=hex($4);
   1.634 +			my $algorithmAsText=$5;
   1.635 +			my $sizeOfOutputCharacterCodeInBytes=$6;
   1.636 +			my $parameters=$7;
   1.637 +			if ($lastInputCharacterCodeInRange<$firstInputCharacterCodeInRange)
   1.638 +				{
   1.639 +				close($fileHandle);
   1.640 +				die("Error: lastInputCharacterCodeInRange ".sprintf("0x%02x", $lastInputCharacterCodeInRange)." is less than firstInputCharacterCodeInRange ".sprintf("0x%02x", $firstInputCharacterCodeInRange)."\n");
   1.641 +				}
   1.642 +			my $algorithm=&algorithm($algorithmAsText);
   1.643 +			if ($algorithm<0)
   1.644 +				{
   1.645 +				close($fileHandle);
   1.646 +				die("Error: unexpected algorithm \"$algorithmAsText\"\n");
   1.647 +				}
   1.648 +			my $rangeData=[$includePriority, $searchPriority, $firstInputCharacterCodeInRange, $lastInputCharacterCodeInRange, $algorithm];
   1.649 +			if (!$outputIsUnicode)
   1.650 +				{
   1.651 +				push(@$rangeData, $sizeOfOutputCharacterCodeInBytes);
   1.652 +				}
   1.653 +			push(@$rangeData, $parameters);
   1.654 +			push(@$oneDirectionData, $rangeData);
   1.655 +			}
   1.656 +		}
   1.657 +	}
   1.658 +
   1.659 +sub warnIfAnyPrivateUseUnicodeCharacterSlotsBeingUsed
   1.660 +	{
   1.661 +	my $privateUseUnicodeCharacterSlotsUsed=shift;
   1.662 +	my @sortedPrivateUseUnicodeCharacterSlotsUsed=sort({$a<=>$b} keys(%$privateUseUnicodeCharacterSlotsUsed));
   1.663 +	if (@sortedPrivateUseUnicodeCharacterSlotsUsed>0)
   1.664 +		{
   1.665 +		my $lastPrivateUseUnicodeCharacterSlotUsed=$sortedPrivateUseUnicodeCharacterSlotsUsed[0];
   1.666 +		my $asText=sprintf('0x%04x', $lastPrivateUseUnicodeCharacterSlotUsed);
   1.667 +		my @asText=($asText);
   1.668 +		my $i;
   1.669 +		for ($i=1; $i<@sortedPrivateUseUnicodeCharacterSlotsUsed; ++$i) # this loop starts from 1 not 0 as we have already dealt with $sortedPrivateUseUnicodeCharacterSlotsUsed[0]
   1.670 +			{
   1.671 +			($sortedPrivateUseUnicodeCharacterSlotsUsed[$i]>$lastPrivateUseUnicodeCharacterSlotUsed) or die("Error: internal error 1\n");
   1.672 +			if ($sortedPrivateUseUnicodeCharacterSlotsUsed[$i]>$lastPrivateUseUnicodeCharacterSlotUsed+1)
   1.673 +				{
   1.674 +				$asText=sprintf('0x%04x', $lastPrivateUseUnicodeCharacterSlotUsed);
   1.675 +				if ($asText[-1] ne $asText)
   1.676 +					{
   1.677 +					$asText[-1].='-'.$asText;
   1.678 +					}
   1.679 +				push(@asText, sprintf('0x%04x', $sortedPrivateUseUnicodeCharacterSlotsUsed[$i]));
   1.680 +				}
   1.681 +			$lastPrivateUseUnicodeCharacterSlotUsed=$sortedPrivateUseUnicodeCharacterSlotsUsed[$i];
   1.682 +			}
   1.683 +		$asText=sprintf('0x%04x', $lastPrivateUseUnicodeCharacterSlotUsed);
   1.684 +		if ($asText[-1] ne $asText)
   1.685 +			{
   1.686 +			$asText[-1].='-'.$asText;
   1.687 +			}
   1.688 +		print(STDERR 'Warning: the following private-use Unicode character slots were used: ['.join(', ', @asText)."]\n");
   1.689 +		}
   1.690 +	}
   1.691 +
   1.692 +sub resolveConflictsAndFlattenArraysToScalars
   1.693 +	{
   1.694 +	my $characterCodes=shift;
   1.695 +	my $preferredCharacterCodesForConflictResolution=shift;
   1.696 +	my $source=shift;
   1.697 +	my $target=shift;
   1.698 +	my $sourceCharacterCode;
   1.699 +	my $candidateTargetCharacterCodes;
   1.700 +	while (($sourceCharacterCode, $candidateTargetCharacterCodes)=each(%$characterCodes))
   1.701 +		{
   1.702 +		my @candidateTargetCharacterCodes=keys(%$candidateTargetCharacterCodes);
   1.703 +		if (@candidateTargetCharacterCodes<1)
   1.704 +			{
   1.705 +			die("Error: internal error 2\n");
   1.706 +			}
   1.707 +		if (@candidateTargetCharacterCodes==1)
   1.708 +			{
   1.709 +			$characterCodes->{$sourceCharacterCode}=$candidateTargetCharacterCodes[0];
   1.710 +			}
   1.711 +		else
   1.712 +			{
   1.713 +			if (!defined($preferredCharacterCodesForConflictResolution->{$sourceCharacterCode}))
   1.714 +				{
   1.715 +				die("Error: no preferred $target character code is specified for conflict resolution for the $source character code ".sprintf("0x%08x", $sourceCharacterCode)."\n");
   1.716 +				}
   1.717 +			my $preferredCharacterCodeIsNotACandidateForConflictResolution=1;
   1.718 +			my $candidateTargetCharacterCode;
   1.719 +			foreach $candidateTargetCharacterCode (@candidateTargetCharacterCodes)
   1.720 +				{
   1.721 +				if ($preferredCharacterCodesForConflictResolution->{$sourceCharacterCode}==$candidateTargetCharacterCode)
   1.722 +					{
   1.723 +					$preferredCharacterCodeIsNotACandidateForConflictResolution=0;
   1.724 +					last;
   1.725 +					}
   1.726 +				}
   1.727 +			if ($preferredCharacterCodeIsNotACandidateForConflictResolution)
   1.728 +				{
   1.729 +				die("Error: the preferred $target character code ".sprintf("0x%08x", $preferredCharacterCodesForConflictResolution->{$sourceCharacterCode})." is not a candidate for conflict resolution for the $source character code ".sprintf("0x%08x", $sourceCharacterCode)."\n");
   1.730 +				}
   1.731 +			$characterCodes->{$sourceCharacterCode}=$preferredCharacterCodesForConflictResolution->{$sourceCharacterCode};
   1.732 +			delete $preferredCharacterCodesForConflictResolution->{$sourceCharacterCode};
   1.733 +			}
   1.734 +		}
   1.735 +	my $numberOfPreferredCharacterCodesForConflictResolution=keys(%$preferredCharacterCodesForConflictResolution);
   1.736 +	if ($numberOfPreferredCharacterCodesForConflictResolution!=0)
   1.737 +		{
   1.738 +		print(STDERR "Warning: there are $numberOfPreferredCharacterCodesForConflictResolution $target preferred character codes specified for which there are no conflicts to resolve\n");
   1.739 +		}
   1.740 +	}
   1.741 +
   1.742 +sub checkForeignVariableByteData
   1.743 +	{
   1.744 +	my $endianness=shift;
   1.745 +	my $foreignVariableByteData=shift;
   1.746 +	my $foreignToUnicodeData=shift;
   1.747 +	my $rangeData;
   1.748 +	my %initialForeignBytes=();
   1.749 +	foreach $rangeData (@$foreignVariableByteData)
   1.750 +		{
   1.751 +		my $initialByte;
   1.752 +		for ($initialByte=$rangeData->[0]; $initialByte<=$rangeData->[1]; ++$initialByte)
   1.753 +			{
   1.754 +			if (defined($initialForeignBytes{$initialByte}))
   1.755 +				{
   1.756 +				die("Error: the number of bytes subsequent to the initial foreign-byte $initialForeignBytes{$initialByte} is defined more than once\n");
   1.757 +				}
   1.758 +			$initialForeignBytes{$initialByte}=1;
   1.759 +			}
   1.760 +		}
   1.761 +#	if ($endianness!=0) # unfortunately, nothing can be checked if the $endianness is 0 (SCnvConversionData::EUnspecified)
   1.762 +#		{
   1.763 +#		foreach $rangeData (@$foreignToUnicodeData)
   1.764 +#			{
   1.765 +#			my $inputCharacterCode;
   1.766 +#			for ($inputCharacterCode=$rangeData->[2]; $inputCharacterCode<=$rangeData->[3]; ++$inputCharacterCode)
   1.767 +#				{
   1.768 +#				my $initialByte;
   1.769 +#				if ($endianness==1) # SCnvConversionData::EFixedLittleEndian
   1.770 +#					{
   1.771 +#					$initialByte=($inputCharacterCode&0xff);
   1.772 +#					}
   1.773 +#				elsif ($endianness==2) # SCnvConversionData::EFixedBigEndian
   1.774 +#					{
   1.775 +#					$initialByte=($inputCharacterCode&0xff00)>>8; ## this is hard-coded and needs to be done properly!
   1.776 +#					}
   1.777 +#				else
   1.778 +#					{
   1.779 +#					die("Error: internal error ??\n");
   1.780 +#					}
   1.781 +#				if (!defined($initialForeignBytes{$initialByte}))
   1.782 +#					{
   1.783 +#					die("Error: no number-of-subsequent-bytes is specified for the initial byte $initialByte\n");
   1.784 +#					}
   1.785 +#				}
   1.786 +#			}
   1.787 +#		}
   1.788 +	}
   1.789 +
   1.790 +sub writeSourceCodeHeader
   1.791 +	{
   1.792 +	my $fileHandle=shift;
   1.793 +	my $fileName=shift;
   1.794 +	my $replacementForUnconvertibleUnicodeCharacters=shift;
   1.795 +	while ($fileName=~/^.*\\(.*)$/i)
   1.796 +		{
   1.797 +		$fileName=$1;
   1.798 +		}
   1.799 +	print($fileHandle "// $fileName\n//\n// Copyright (c) Nokia Corporation and/or its subsidiary(-ies) ".(1900+(gmtime(time))[5]).". All rights reserved.\n//\n\n");
   1.800 +	print($fileHandle "#include <e32std.h>\n#include <convdata.h>\n#include <convgeneratedcpp.h>\n\n#define ARRAY_LENGTH(aArray) (sizeof(aArray)/sizeof((aArray)\[0\]))\n\n#pragma warning (disable: 4049) // compiler limit : terminating line number emission\n\n");
   1.801 +	if (!$omitReplacementForUnconvertibleUnicodeCharacters)
   1.802 +		{
   1.803 +		print($fileHandle "_LIT8(KLit8ReplacementForUnconvertibleUnicodeCharacters, \"".&hexadecimalify($replacementForUnconvertibleUnicodeCharacters)."\");\n\n");
   1.804 +		print($fileHandle "GLDEF_C const TDesC8& ReplacementForUnconvertibleUnicodeCharacters_internal()\n\t{\n\treturn KLit8ReplacementForUnconvertibleUnicodeCharacters;\n\t}\n\n");
   1.805 +		}
   1.806 +	}
   1.807 +
   1.808 +sub writeSourceCodeForeignVariableByteData
   1.809 +	{
   1.810 +	my $sourceCodeOfTopLevelStructures=shift;
   1.811 +	my $foreignVariableByteData=shift;
   1.812 +	push(@$sourceCodeOfTopLevelStructures, "LOCAL_D const SCnvConversionData::SVariableByteData::SRange foreignVariableByteDataRanges[]=\n\t\{\n");
   1.813 +	my $indexOfLastRange=$#$foreignVariableByteData;
   1.814 +	my $i;
   1.815 +	for ($i=0; $i<=$indexOfLastRange; ++$i)
   1.816 +		{
   1.817 +		my $rangeData=$foreignVariableByteData->[$i];
   1.818 +		if (@$rangeData!=3)
   1.819 +			{
   1.820 +			die("Error: internal error 3\n");
   1.821 +			}
   1.822 +		my $firstInitialByteValueInRange=$rangeData->[0];
   1.823 +		my $lastInitialByteValueInRange=$rangeData->[1];
   1.824 +		if ($lastInitialByteValueInRange<$firstInitialByteValueInRange)
   1.825 +			{
   1.826 +			die("Error: internal error 4\n");
   1.827 +			}
   1.828 +		my $numberOfSubsequentBytes=$rangeData->[2];
   1.829 +		push(@$sourceCodeOfTopLevelStructures, "\t\t\{\n\t\t".sprintf("0x%02x", $firstInitialByteValueInRange).",\n\t\t".sprintf("0x%02x", $lastInitialByteValueInRange).",\n\t\t$numberOfSubsequentBytes,\n\t\t0\n\t\t\}");
   1.830 +		if ($i<$indexOfLastRange)
   1.831 +			{
   1.832 +			push(@$sourceCodeOfTopLevelStructures, ',');
   1.833 +			}
   1.834 +		push(@$sourceCodeOfTopLevelStructures, "\n");
   1.835 +		}
   1.836 +	push(@$sourceCodeOfTopLevelStructures, "\t\};\n\n");
   1.837 +	}
   1.838 +
   1.839 +sub writeSourceCodeOneDirectionData
   1.840 +	{
   1.841 +	my $sourceCodeOfTopLevelStructures=shift;
   1.842 +	my $sourceCodeOfOneDirectionIndexedTables16=shift;
   1.843 +	my $sourceCodeOfOneDirectionKeyedTables1616=shift;
   1.844 +	my $sourceCodeOfOneDirectionKeyedTables16OfIndexedTables16_indexedEntries=shift;
   1.845 +	my $sourceCodeOfOneDirectionKeyedTables16OfIndexedTables16_keyedEntries=shift;
   1.846 +	# new for 32 bit encoding begin
   1.847 +	my $sourceCodeOfOneDirectionIndexedTables32=shift;
   1.848 +	my $sourceCodeOfOneDirectionKeyedTables3232=shift;
   1.849 +	my $sourceCodeOfOneDirectionKeyedTables32OfIndexedTables32_indexedEntries=shift;
   1.850 +	my $sourceCodeOfOneDirectionKeyedTables32OfIndexedTables32_keyedEntries=shift;
   1.851 +	# new for 32 bit encoding end
   1.852 +	
   1.853 +	my $oneDirectionData=shift;
   1.854 +	my $characterCodes=shift;
   1.855 +	my $outputIsUnicode=shift;
   1.856 +	push(@$sourceCodeOfTopLevelStructures, 'LOCAL_D const SCnvConversionData::SOneDirectionData::SRange '.($outputIsUnicode? 'foreignToUnicodeDataRanges': 'unicodeToForeignDataRanges')."[]=\n\t\{\n");
   1.857 +	my $formatForInputCharacters=$outputIsUnicode? '0x%02x': '0x%04x';
   1.858 +	my $formatForOutputCharacters=$outputIsUnicode? '0x%04x': '0x%02x';
   1.859 +	my $indexOfLastRange=$#$oneDirectionData;
   1.860 +	my $i;
   1.861 +	for ($i=0; $i<=$indexOfLastRange; ++$i)
   1.862 +		{
   1.863 +		my $rangeData=$oneDirectionData->[$i];
   1.864 +		# $rangeData is $includePriority, $searchPriority, $firstInputCharacterCodeInRange, $lastInputCharacterCodeInRange, $algorithm[, $sizeOfOutputCharacterCodeInBytes], $parameters
   1.865 +		if (scalar(@$rangeData)!=($outputIsUnicode? 6: 7))
   1.866 +			{
   1.867 +			die("Error: internal error 5\n");
   1.868 +			}
   1.869 +		my $firstInputCharacterCodeInRange=$rangeData->[2];
   1.870 +		my $lastInputCharacterCodeInRange=$rangeData->[3];
   1.871 +		if ($lastInputCharacterCodeInRange<$firstInputCharacterCodeInRange)
   1.872 +			{
   1.873 +			die("Error: internal error 6\n");
   1.874 +			}
   1.875 +		my $algorithmAsText=''; # set by the if-elsif stuff below
   1.876 +		my $sizeOfOutputCharacterCodeInBytesIfForeign=$outputIsUnicode? 0: $rangeData->[5];
   1.877 +		my $parameters=$rangeData->[$outputIsUnicode? 5: 6];
   1.878 +		my $word1=0; # set by the if-elsif stuff below
   1.879 +		my $algorithm=$rangeData->[4];
   1.880 +		if ($algorithm==0) # Direct
   1.881 +			{
   1.882 +			$algorithmAsText='Direct';
   1.883 +			my $characterCode;
   1.884 +			for ($characterCode=$firstInputCharacterCodeInRange; $characterCode<=$lastInputCharacterCodeInRange; ++$characterCode)
   1.885 +				{
   1.886 +				if (!defined($characterCodes->{$characterCode}))
   1.887 +					{
   1.888 +					die("Error: There is no conversion defined for ".($outputIsUnicode? 'foreign': 'Unicode')." character code ".sprintf("0x%08x", $characterCode)."\n");
   1.889 +					}
   1.890 +				if ($characterCodes->{$characterCode}!=$characterCode)
   1.891 +					{
   1.892 +					die("Error: the conversion from ".($outputIsUnicode? 'foreign': 'Unicode')." character code ".sprintf("0x%08x", $characterCode)." to ".($outputIsUnicode? 'Unicode': 'foreign')." character code ".sprintf("0x%08x", $characterCodes->{$characterCode})." is not a direct conversion\n");
   1.893 +					}
   1.894 +				delete $characterCodes->{$characterCode};
   1.895 +				}
   1.896 +			}
   1.897 +		elsif ($algorithm==1) # Offset
   1.898 +			{
   1.899 +			$algorithmAsText='Offset';
   1.900 +			my $offset=$characterCodes->{$firstInputCharacterCodeInRange}-$firstInputCharacterCodeInRange;
   1.901 +			delete $characterCodes->{$firstInputCharacterCodeInRange};
   1.902 +			my $characterCode;
   1.903 +			for ($characterCode=$firstInputCharacterCodeInRange+1; $characterCode<=$lastInputCharacterCodeInRange; ++$characterCode)
   1.904 +				{
   1.905 +				if (!defined($characterCodes->{$characterCode}))
   1.906 +					{
   1.907 +					die("Error: There is no conversion defined for ".($outputIsUnicode? 'foreign': 'Unicode')." character code ".sprintf("0x%08x (0x%08x-0x%08x)", $characterCode, $firstInputCharacterCodeInRange, $lastInputCharacterCodeInRange)."\n");
   1.908 +					}
   1.909 +				if ($characterCodes->{$characterCode}-$characterCode!=$offset)
   1.910 +					{
   1.911 +					die("Error: the conversion from ".($outputIsUnicode? 'foreign': 'Unicode')." character code ".sprintf("0x%08x", $characterCode)." to ".($outputIsUnicode? 'Unicode': 'foreign')." character code ".sprintf("0x%08x", $characterCodes->{$characterCode})." has a different offset from the previous one in the range\n");
   1.912 +					}
   1.913 +				delete $characterCodes->{$characterCode};
   1.914 +				}
   1.915 +			$word1="STATIC_CAST(TUint, $offset)";
   1.916 +			}
   1.917 +		elsif ($algorithm==2) # IndexedTable16
   1.918 +			{
   1.919 +			$algorithmAsText='IndexedTable16';
   1.920 +			my $nameOfNextOneDirectionIndexedTable16='indexedTable16_'.($outputIsUnicode? 'foreignToUnicode': 'unicodeToForeign').'_'.($#$sourceCodeOfOneDirectionIndexedTables16+2);
   1.921 +			my $sourceCodeOfNextOneDirectionIndexedTable16=[];
   1.922 +			push(@$sourceCodeOfNextOneDirectionIndexedTable16, "LOCAL_D const SCnvConversionData::SOneDirectionData::SRange::UData::SIndexedTable16::SEntry $nameOfNextOneDirectionIndexedTable16\[\]=\n\t\{\n");
   1.923 +			my $characterCode;
   1.924 +			for ($characterCode=$firstInputCharacterCodeInRange; $characterCode<=$lastInputCharacterCodeInRange; ++$characterCode)
   1.925 +				{
   1.926 +				if (!defined($characterCodes->{$characterCode}))
   1.927 +					{
   1.928 +					die("Error: There is no conversion defined for ".($outputIsUnicode? 'foreign': 'Unicode')." character code ".sprintf("0x%08x", $characterCode)."\n");
   1.929 +					}
   1.930 +				push(@$sourceCodeOfNextOneDirectionIndexedTable16, "\t\t\{\n\t\t".sprintf($formatForOutputCharacters, $characterCodes->{$characterCode})."\n\t\t\}");
   1.931 +				if ($characterCode<$lastInputCharacterCodeInRange)
   1.932 +					{
   1.933 +					push(@$sourceCodeOfNextOneDirectionIndexedTable16, ',');
   1.934 +					}
   1.935 +				push(@$sourceCodeOfNextOneDirectionIndexedTable16, "\n");
   1.936 +				delete $characterCodes->{$characterCode};
   1.937 +				}
   1.938 +			push(@$sourceCodeOfNextOneDirectionIndexedTable16, "\t\};\n\n");
   1.939 +			push(@$sourceCodeOfOneDirectionIndexedTables16, $sourceCodeOfNextOneDirectionIndexedTable16);
   1.940 +			$word1="UData_S$algorithmAsText($nameOfNextOneDirectionIndexedTable16)";
   1.941 +			}
   1.942 +		elsif ($algorithm==3) # KeyedTable1616
   1.943 +			{
   1.944 +			$algorithmAsText='KeyedTable1616';
   1.945 +			my $nameOfNextOneDirectionKeyedTable1616='keyedTable1616_'.($outputIsUnicode? 'foreignToUnicode': 'unicodeToForeign').'_'.($#$sourceCodeOfOneDirectionKeyedTables1616+2);
   1.946 +			my $sourceCodeOfNextOneDirectionKeyedTable1616=[];
   1.947 +			push(@$sourceCodeOfNextOneDirectionKeyedTable1616, "LOCAL_D const SCnvConversionData::SOneDirectionData::SRange::UData::SKeyedTable1616::SEntry $nameOfNextOneDirectionKeyedTable1616\[\]=\n\t\{\n");
   1.948 +			my @characterCodes=grep(($_>=$firstInputCharacterCodeInRange) && ($_<=$lastInputCharacterCodeInRange), sort({$a<=>$b} keys(%$characterCodes)));
   1.949 +			if (@characterCodes==0)
   1.950 +				{
   1.951 +				die("Error: There are no ".($outputIsUnicode? 'foreign': 'Unicode').'-to-'.($outputIsUnicode? 'Unicode': 'foreign')." characters to convert using KeyedTable1616 (range ".sprintf("$formatForInputCharacters-$formatForInputCharacters", $firstInputCharacterCodeInRange, $lastInputCharacterCodeInRange).").\n");
   1.952 +				}
   1.953 +			if ($characterCodes[0]!=$firstInputCharacterCodeInRange)
   1.954 +				{
   1.955 +				print(STDERR 'Warning: the specified start of the '.($outputIsUnicode? 'foreign': 'Unicode').' range '.sprintf("$formatForInputCharacters-$formatForInputCharacters", $firstInputCharacterCodeInRange, $lastInputCharacterCodeInRange).' could actually be '.sprintf("$formatForInputCharacters", $characterCodes[0])."\n");
   1.956 +				}
   1.957 +			if ($characterCodes[-1]!=$lastInputCharacterCodeInRange)
   1.958 +				{
   1.959 +				print(STDERR 'Warning: the specified end of the '.($outputIsUnicode? 'foreign': 'Unicode').' range '.sprintf("$formatForInputCharacters-$formatForInputCharacters", $firstInputCharacterCodeInRange, $lastInputCharacterCodeInRange).' could actually be '.sprintf("$formatForInputCharacters", $characterCodes[-1])."\n");
   1.960 +				}
   1.961 +			my $characterCode;
   1.962 +			foreach $characterCode (@characterCodes)
   1.963 +				{
   1.964 +				if (defined($characterCodes->{$characterCode}))
   1.965 +					{
   1.966 +					push(@$sourceCodeOfNextOneDirectionKeyedTable1616, "\t\t\{\n\t\t".sprintf($formatForInputCharacters, $characterCode).",\n\t\t".sprintf($formatForOutputCharacters, $characterCodes->{$characterCode})."\n\t\t\}");
   1.967 +					if ($characterCode<$characterCodes[-1])
   1.968 +						{
   1.969 +						push(@$sourceCodeOfNextOneDirectionKeyedTable1616, ',');
   1.970 +						}
   1.971 +					push(@$sourceCodeOfNextOneDirectionKeyedTable1616, "\n");
   1.972 +					delete $characterCodes->{$characterCode};
   1.973 +					}
   1.974 +				}
   1.975 +			push(@$sourceCodeOfNextOneDirectionKeyedTable1616, "\t\};\n\n");
   1.976 +			push(@$sourceCodeOfOneDirectionKeyedTables1616, $sourceCodeOfNextOneDirectionKeyedTable1616);
   1.977 +			$word1="UData_S$algorithmAsText($nameOfNextOneDirectionKeyedTable1616)";
   1.978 +			}
   1.979 +		elsif ($algorithm==4) # KeyedTable16OfIndexedTables16
   1.980 +			{
   1.981 +			$algorithmAsText='KeyedTable16OfIndexedTables16';
   1.982 +			my $nameOfNextOneDirectionKeyedTables16OfIndexedTables16_keyedEntries='keyedTables16OfIndexedTables16_keyedEntries_'.($outputIsUnicode? 'foreignToUnicode': 'unicodeToForeign').'_'.($#$sourceCodeOfOneDirectionKeyedTables16OfIndexedTables16_keyedEntries+2);
   1.983 +			my $sourceCodeOfNextOneDirectionKeyedTables16OfIndexedTables16_keyedEntries=[];
   1.984 +			push(@$sourceCodeOfNextOneDirectionKeyedTables16OfIndexedTables16_keyedEntries, "LOCAL_D const SCnvConversionData::SOneDirectionData::SRange::UData::SKeyedTable16OfIndexedTables16::SKeyedEntry $nameOfNextOneDirectionKeyedTables16OfIndexedTables16_keyedEntries\[\]=\n\t\{\n");
   1.985 +			my @characterCodes=grep(($_>=$firstInputCharacterCodeInRange) && ($_<=$lastInputCharacterCodeInRange), sort({$a<=>$b} keys(%$characterCodes)));
   1.986 +			if (@characterCodes==0)
   1.987 +				{
   1.988 +				die("Error: There are no ".($outputIsUnicode? 'foreign': 'Unicode').'-to-'.($outputIsUnicode? 'Unicode': 'foreign')." characters to convert using KeyedTable16OfIndexedTables16 (range ".sprintf("$formatForInputCharacters-$formatForInputCharacters", $firstInputCharacterCodeInRange, $lastInputCharacterCodeInRange).").\n");
   1.989 +				}
   1.990 +			if ($characterCodes[0]!=$firstInputCharacterCodeInRange)
   1.991 +				{
   1.992 +				print(STDERR 'Warning: the specified start of the '.($outputIsUnicode? 'foreign': 'Unicode').' range '.sprintf("$formatForInputCharacters-$formatForInputCharacters", $firstInputCharacterCodeInRange, $lastInputCharacterCodeInRange).' could actually be '.sprintf("$formatForInputCharacters", $characterCodes[0])."\n");
   1.993 +				}
   1.994 +			if ($characterCodes[-1]!=$lastInputCharacterCodeInRange)
   1.995 +				{
   1.996 +				print(STDERR 'Warning: the specified end of the '.($outputIsUnicode? 'foreign': 'Unicode').' range '.sprintf("$formatForInputCharacters-$formatForInputCharacters", $firstInputCharacterCodeInRange, $lastInputCharacterCodeInRange).' could actually be '.sprintf("$formatForInputCharacters", $characterCodes[-1])."\n");
   1.997 +				}
   1.998 +			my @characterCodeRanges=();
   1.999 +			my $minimumNumberOfEntriesPerIndexedTable=($parameters ne '')? $parameters: 0;
  1.1000 +			my $firstInputCharacterCodeInIndexedTable=$characterCodes[0];
  1.1001 +			my $previousCharacterCode=$firstInputCharacterCodeInIndexedTable;
  1.1002 +			my $characterCode;
  1.1003 +			foreach $characterCode (@characterCodes)
  1.1004 +				{
  1.1005 +				($characterCode>=$previousCharacterCode) or die("Error: internal error 7\n");
  1.1006 +				if ($characterCode>$previousCharacterCode+1)
  1.1007 +					{
  1.1008 +					if (($previousCharacterCode-$firstInputCharacterCodeInIndexedTable)+1>=$minimumNumberOfEntriesPerIndexedTable)
  1.1009 +						{
  1.1010 +						push(@characterCodeRanges, [$firstInputCharacterCodeInIndexedTable, $previousCharacterCode]);
  1.1011 +						}
  1.1012 +					$firstInputCharacterCodeInIndexedTable=$characterCode;
  1.1013 +					}
  1.1014 +				$previousCharacterCode=$characterCode;
  1.1015 +				}
  1.1016 +			push(@characterCodeRanges, [$firstInputCharacterCodeInIndexedTable, $previousCharacterCode]);
  1.1017 +			@characterCodes=();
  1.1018 +			my $characterCodeRange;
  1.1019 +			foreach $characterCodeRange (@characterCodeRanges)
  1.1020 +				{
  1.1021 +				my $nameOfNextOneDirectionKeyedTables16OfIndexedTables16_indexedEntries='keyedTables16OfIndexedTables16_indexedEntries_'.($outputIsUnicode? 'foreignToUnicode': 'unicodeToForeign').'_'.($#$sourceCodeOfOneDirectionKeyedTables16OfIndexedTables16_indexedEntries+2);
  1.1022 +				my $sourceCodeOfNextOneDirectionKeyedTables16OfIndexedTables16_indexedEntries=[];
  1.1023 +				push(@$sourceCodeOfNextOneDirectionKeyedTables16OfIndexedTables16_indexedEntries, "LOCAL_D const TUint16 $nameOfNextOneDirectionKeyedTables16OfIndexedTables16_indexedEntries\[\]=\n\t\{\n");
  1.1024 +				my $characterCode;
  1.1025 +				my $lastInputCharacterCodeInIndexedTable=$characterCodeRange->[1];
  1.1026 +				for ($characterCode=$characterCodeRange->[0]; $characterCode<=$lastInputCharacterCodeInIndexedTable; ++$characterCode)
  1.1027 +					{
  1.1028 +					if (!defined($characterCodes->{$characterCode}))
  1.1029 +						{
  1.1030 +						die("Error: internal error 8\n");
  1.1031 +						}
  1.1032 +					push(@$sourceCodeOfNextOneDirectionKeyedTables16OfIndexedTables16_indexedEntries, "\t".sprintf($formatForOutputCharacters, $characterCodes->{$characterCode}));
  1.1033 +					if ($characterCode<$lastInputCharacterCodeInIndexedTable)
  1.1034 +						{
  1.1035 +						push(@$sourceCodeOfNextOneDirectionKeyedTables16OfIndexedTables16_indexedEntries, ',');
  1.1036 +						}
  1.1037 +					push(@$sourceCodeOfNextOneDirectionKeyedTables16OfIndexedTables16_indexedEntries, "\n");
  1.1038 +					delete $characterCodes->{$characterCode};
  1.1039 +					}
  1.1040 +				push(@$sourceCodeOfNextOneDirectionKeyedTables16OfIndexedTables16_indexedEntries, "\t\};\n\n");
  1.1041 +				push(@$sourceCodeOfOneDirectionKeyedTables16OfIndexedTables16_indexedEntries, $sourceCodeOfNextOneDirectionKeyedTables16OfIndexedTables16_indexedEntries);
  1.1042 +				push(@$sourceCodeOfNextOneDirectionKeyedTables16OfIndexedTables16_keyedEntries, "\t\t\{\n\t\t".sprintf($formatForInputCharacters, $characterCodeRange->[0]).",\n\t\t".sprintf($formatForInputCharacters, $characterCodeRange->[1]).",\n\t\t$nameOfNextOneDirectionKeyedTables16OfIndexedTables16_indexedEntries\n\t\t\}");
  1.1043 +				if ($characterCodeRange->[1]<$characterCodeRanges[-1]->[1])
  1.1044 +					{
  1.1045 +					push(@$sourceCodeOfNextOneDirectionKeyedTables16OfIndexedTables16_keyedEntries, ',');
  1.1046 +					}
  1.1047 +				push(@$sourceCodeOfNextOneDirectionKeyedTables16OfIndexedTables16_keyedEntries, "\n");
  1.1048 +				}
  1.1049 +			push(@$sourceCodeOfNextOneDirectionKeyedTables16OfIndexedTables16_keyedEntries, "\t\};\n\n");
  1.1050 +			push(@$sourceCodeOfOneDirectionKeyedTables16OfIndexedTables16_keyedEntries, $sourceCodeOfNextOneDirectionKeyedTables16OfIndexedTables16_keyedEntries);
  1.1051 +			$word1="UData_S$algorithmAsText($nameOfNextOneDirectionKeyedTables16OfIndexedTables16_keyedEntries)";
  1.1052 +			}
  1.1053 +		elsif ($algorithm==5) # IndexedTable32
  1.1054 +			{
  1.1055 +			$algorithmAsText='IndexedTable32';
  1.1056 +			my $nameOfNextOneDirectionIndexedTable32='indexedTable32_'.($outputIsUnicode? 'foreignToUnicode': 'unicodeToForeign').'_'.($#$sourceCodeOfOneDirectionIndexedTables32+2);
  1.1057 +			my $sourceCodeOfNextOneDirectionIndexedTable32=[];
  1.1058 +			push(@$sourceCodeOfNextOneDirectionIndexedTable32, "LOCAL_D const SCnvConversionData::SOneDirectionData::SRange::UData::SIndexedTable32::SEntry $nameOfNextOneDirectionIndexedTable32\[\]=\n\t\{\n");
  1.1059 +			my $characterCode;
  1.1060 +			for ($characterCode=$firstInputCharacterCodeInRange; $characterCode<=$lastInputCharacterCodeInRange; ++$characterCode)
  1.1061 +				{
  1.1062 +				if (!defined($characterCodes->{$characterCode}))
  1.1063 +					{
  1.1064 +					die("Error: There is no conversion defined for ".($outputIsUnicode? 'foreign': 'Unicode')." character code ".sprintf("0x%08x", $characterCode)."\n");
  1.1065 +					}
  1.1066 +				push(@$sourceCodeOfNextOneDirectionIndexedTable32, "\t\t\{\n\t\t".sprintf($formatForOutputCharacters, $characterCodes->{$characterCode})."\n\t\t\}");
  1.1067 +				if ($characterCode<$lastInputCharacterCodeInRange)
  1.1068 +					{
  1.1069 +					push(@$sourceCodeOfNextOneDirectionIndexedTable32, ',');
  1.1070 +					}
  1.1071 +				push(@$sourceCodeOfNextOneDirectionIndexedTable32, "\n");
  1.1072 +				delete $characterCodes->{$characterCode};
  1.1073 +				}
  1.1074 +			push(@$sourceCodeOfNextOneDirectionIndexedTable32, "\t\};\n\n");
  1.1075 +			push(@$sourceCodeOfOneDirectionIndexedTables32, $sourceCodeOfNextOneDirectionIndexedTable32);
  1.1076 +			$word1="UData_S$algorithmAsText($nameOfNextOneDirectionIndexedTable32)";
  1.1077 +			}
  1.1078 +		elsif ($algorithm==6) # KeyedTable3232
  1.1079 +			{
  1.1080 +			$algorithmAsText='KeyedTable3232';
  1.1081 +			my $nameOfNextOneDirectionKeyedTable3232='keyedTable3232_'.($outputIsUnicode? 'foreignToUnicode': 'unicodeToForeign').'_'.($#$sourceCodeOfOneDirectionKeyedTables3232+2);
  1.1082 +			my $sourceCodeOfNextOneDirectionKeyedTable3232=[];
  1.1083 +			push(@$sourceCodeOfNextOneDirectionKeyedTable3232, "LOCAL_D const SCnvConversionData::SOneDirectionData::SRange::UData::SKeyedTable3232::SEntry $nameOfNextOneDirectionKeyedTable3232\[\]=\n\t\{\n");
  1.1084 +			my @characterCodes=grep(($_>=$firstInputCharacterCodeInRange) && ($_<=$lastInputCharacterCodeInRange), sort({$a<=>$b} keys(%$characterCodes)));
  1.1085 +			if (@characterCodes==0)
  1.1086 +				{
  1.1087 +				die("Error: There are no ".($outputIsUnicode? 'foreign': 'Unicode').'-to-'.($outputIsUnicode? 'Unicode': 'foreign')." characters to convert using KeyedTable3232 (range ".sprintf("$formatForInputCharacters-$formatForInputCharacters", $firstInputCharacterCodeInRange, $lastInputCharacterCodeInRange).").\n");
  1.1088 +				}
  1.1089 +			if ($characterCodes[0]!=$firstInputCharacterCodeInRange)
  1.1090 +				{
  1.1091 +				print(STDERR 'Warning: the specified start of the '.($outputIsUnicode? 'foreign': 'Unicode').' range '.sprintf("$formatForInputCharacters-$formatForInputCharacters", $firstInputCharacterCodeInRange, $lastInputCharacterCodeInRange).' could actually be '.sprintf($formatForInputCharacters, $characterCodes[0])."\n");
  1.1092 +				}
  1.1093 +			if ($characterCodes[-1]!=$lastInputCharacterCodeInRange)
  1.1094 +				{
  1.1095 +				print(STDERR 'Warning: the specified end of the '.($outputIsUnicode? 'foreign': 'Unicode').' range '.sprintf("$formatForInputCharacters-$formatForInputCharacters", $firstInputCharacterCodeInRange, $lastInputCharacterCodeInRange).' could actually be '.sprintf($formatForInputCharacters, $characterCodes[-1])."\n");
  1.1096 +				}
  1.1097 +			my $characterCode;
  1.1098 +			foreach $characterCode (@characterCodes)
  1.1099 +				{
  1.1100 +				if (defined($characterCodes->{$characterCode}))
  1.1101 +					{
  1.1102 +					push(@$sourceCodeOfNextOneDirectionKeyedTable3232, "\t\t\{\n\t\t".sprintf($formatForInputCharacters, $characterCode).",\n\t\t".sprintf($formatForOutputCharacters, $characterCodes->{$characterCode})."\n\t\t\}");
  1.1103 +					if ($characterCode<$characterCodes[-1])
  1.1104 +						{
  1.1105 +						push(@$sourceCodeOfNextOneDirectionKeyedTable3232, ',');
  1.1106 +						}
  1.1107 +					push(@$sourceCodeOfNextOneDirectionKeyedTable3232, "\n");
  1.1108 +					delete $characterCodes->{$characterCode};
  1.1109 +					}
  1.1110 +				}
  1.1111 +			push(@$sourceCodeOfNextOneDirectionKeyedTable3232, "\t\};\n\n");
  1.1112 +			push(@$sourceCodeOfOneDirectionKeyedTables3232, $sourceCodeOfNextOneDirectionKeyedTable3232);
  1.1113 +			$word1="UData_S$algorithmAsText($nameOfNextOneDirectionKeyedTable3232)";
  1.1114 +			}
  1.1115 +		elsif ($algorithm==7) # KeyedTable32OfIndexedTables32
  1.1116 +			{
  1.1117 +			$algorithmAsText='KeyedTable32OfIndexedTables32';
  1.1118 +			my $nameOfNextOneDirectionKeyedTables32OfIndexedTables32_keyedEntries='keyedTables32OfIndexedTables32_keyedEntries_'.($outputIsUnicode? 'foreignToUnicode': 'unicodeToForeign').'_'.($#$sourceCodeOfOneDirectionKeyedTables32OfIndexedTables32_keyedEntries+2);
  1.1119 +			my $sourceCodeOfNextOneDirectionKeyedTables32OfIndexedTables32_keyedEntries=[];
  1.1120 +			push(@$sourceCodeOfNextOneDirectionKeyedTables32OfIndexedTables32_keyedEntries, "LOCAL_D const SCnvConversionData::SOneDirectionData::SRange::UData::SKeyedTable32OfIndexedTables32::SKeyedEntry $nameOfNextOneDirectionKeyedTables32OfIndexedTables32_keyedEntries\[\]=\n\t\{\n");
  1.1121 +			my @characterCodes=grep(($_>=$firstInputCharacterCodeInRange) && ($_<=$lastInputCharacterCodeInRange), sort({$a<=>$b} keys(%$characterCodes)));
  1.1122 +			if (@characterCodes==0)
  1.1123 +				{
  1.1124 +				die("Error: There are no ".($outputIsUnicode? 'foreign': 'Unicode').'-to-'.($outputIsUnicode? 'Unicode': 'foreign')." characters to convert using KeyedTable32OfIndexedTables32 (range ".sprintf("$formatForInputCharacters-$formatForInputCharacters", $firstInputCharacterCodeInRange, $lastInputCharacterCodeInRange).").\n");
  1.1125 +				}
  1.1126 +			if ($characterCodes[0]!=$firstInputCharacterCodeInRange)
  1.1127 +				{
  1.1128 +				print(STDERR 'Warning: the specified start of the '.($outputIsUnicode? 'foreign': 'Unicode').' range '.sprintf("$formatForInputCharacters-$formatForInputCharacters", $firstInputCharacterCodeInRange, $lastInputCharacterCodeInRange).' could actually be '.sprintf("$formatForInputCharacters", $characterCodes[0])."\n");
  1.1129 +				}
  1.1130 +			if ($characterCodes[-1]!=$lastInputCharacterCodeInRange)
  1.1131 +				{
  1.1132 +				print(STDERR 'Warning: the specified end of the '.($outputIsUnicode? 'foreign': 'Unicode').' range '.sprintf("$formatForInputCharacters-$formatForInputCharacters", $firstInputCharacterCodeInRange, $lastInputCharacterCodeInRange).' could actually be '.sprintf("$formatForInputCharacters", $characterCodes[-1])."\n");
  1.1133 +				}
  1.1134 +			my @characterCodeRanges=();
  1.1135 +			my $minimumNumberOfEntriesPerIndexedTable=($parameters ne '')? $parameters: 0;
  1.1136 +			my $firstInputCharacterCodeInIndexedTable=$characterCodes[0];
  1.1137 +			my $previousCharacterCode=$firstInputCharacterCodeInIndexedTable;
  1.1138 +			my $characterCode;
  1.1139 +			foreach $characterCode (@characterCodes)
  1.1140 +				{
  1.1141 +				($characterCode>=$previousCharacterCode) or die("Error: internal error 7\n");
  1.1142 +				if ($characterCode>$previousCharacterCode+1)
  1.1143 +					{
  1.1144 +					if (($previousCharacterCode-$firstInputCharacterCodeInIndexedTable)+1>=$minimumNumberOfEntriesPerIndexedTable)
  1.1145 +						{
  1.1146 +						push(@characterCodeRanges, [$firstInputCharacterCodeInIndexedTable, $previousCharacterCode]);
  1.1147 +						}
  1.1148 +					$firstInputCharacterCodeInIndexedTable=$characterCode;
  1.1149 +					}
  1.1150 +				$previousCharacterCode=$characterCode;
  1.1151 +				}
  1.1152 +			push(@characterCodeRanges, [$firstInputCharacterCodeInIndexedTable, $previousCharacterCode]);
  1.1153 +			@characterCodes=();
  1.1154 +			my $characterCodeRange;
  1.1155 +			foreach $characterCodeRange (@characterCodeRanges)
  1.1156 +				{
  1.1157 +				my $nameOfNextOneDirectionKeyedTables32OfIndexedTables32_indexedEntries='keyedTables32OfIndexedTables32_indexedEntries_'.($outputIsUnicode? 'foreignToUnicode': 'unicodeToForeign').'_'.($#$sourceCodeOfOneDirectionKeyedTables32OfIndexedTables32_indexedEntries+2);
  1.1158 +				my $sourceCodeOfNextOneDirectionKeyedTables32OfIndexedTables32_indexedEntries=[];
  1.1159 +				push(@$sourceCodeOfNextOneDirectionKeyedTables32OfIndexedTables32_indexedEntries, "LOCAL_D const TUint32 $nameOfNextOneDirectionKeyedTables32OfIndexedTables32_indexedEntries\[\]=\n\t\{\n");
  1.1160 +				my $characterCode;
  1.1161 +				my $lastInputCharacterCodeInIndexedTable=$characterCodeRange->[1];
  1.1162 +				for ($characterCode=$characterCodeRange->[0]; $characterCode<=$lastInputCharacterCodeInIndexedTable; ++$characterCode)
  1.1163 +					{
  1.1164 +					if (!defined($characterCodes->{$characterCode}))
  1.1165 +						{
  1.1166 +						die("Error: internal error 8\n");
  1.1167 +						}
  1.1168 +					push(@$sourceCodeOfNextOneDirectionKeyedTables32OfIndexedTables32_indexedEntries, "\t".sprintf($formatForOutputCharacters, $characterCodes->{$characterCode}));
  1.1169 +					if ($characterCode<$lastInputCharacterCodeInIndexedTable)
  1.1170 +						{
  1.1171 +						push(@$sourceCodeOfNextOneDirectionKeyedTables32OfIndexedTables32_indexedEntries, ',');
  1.1172 +						}
  1.1173 +					push(@$sourceCodeOfNextOneDirectionKeyedTables32OfIndexedTables32_indexedEntries, "\n");
  1.1174 +					delete $characterCodes->{$characterCode};
  1.1175 +					}
  1.1176 +				push(@$sourceCodeOfNextOneDirectionKeyedTables32OfIndexedTables32_indexedEntries, "\t\};\n\n");
  1.1177 +				push(@$sourceCodeOfOneDirectionKeyedTables32OfIndexedTables32_indexedEntries, $sourceCodeOfNextOneDirectionKeyedTables32OfIndexedTables32_indexedEntries);
  1.1178 +				push(@$sourceCodeOfNextOneDirectionKeyedTables32OfIndexedTables32_keyedEntries, "\t\t\{\n\t\t".sprintf($formatForInputCharacters, $characterCodeRange->[0]).",\n\t\t".sprintf($formatForInputCharacters, $characterCodeRange->[1]).",\n\t\t$nameOfNextOneDirectionKeyedTables32OfIndexedTables32_indexedEntries\n\t\t\}");
  1.1179 +				if ($characterCodeRange->[1]<$characterCodeRanges[-1]->[1])
  1.1180 +					{
  1.1181 +					push(@$sourceCodeOfNextOneDirectionKeyedTables32OfIndexedTables32_keyedEntries, ',');
  1.1182 +					}
  1.1183 +				push(@$sourceCodeOfNextOneDirectionKeyedTables32OfIndexedTables32_keyedEntries, "\n");
  1.1184 +				}
  1.1185 +			push(@$sourceCodeOfNextOneDirectionKeyedTables32OfIndexedTables32_keyedEntries, "\t\};\n\n");
  1.1186 +			push(@$sourceCodeOfOneDirectionKeyedTables32OfIndexedTables32_keyedEntries, $sourceCodeOfNextOneDirectionKeyedTables32OfIndexedTables32_keyedEntries);
  1.1187 +			$word1="UData_S$algorithmAsText($nameOfNextOneDirectionKeyedTables32OfIndexedTables32_keyedEntries)";
  1.1188 +			}
  1.1189 +		else
  1.1190 +			{
  1.1191 +			die("Error: internal error 9\n");
  1.1192 +			}
  1.1193 +		push(@$sourceCodeOfTopLevelStructures, "\t\t\{\n\t\t".sprintf($formatForInputCharacters, $firstInputCharacterCodeInRange).",\n\t\t".sprintf($formatForInputCharacters, $lastInputCharacterCodeInRange).",\n\t\tSCnvConversionData::SOneDirectionData::SRange::E$algorithmAsText,\n\t\t".$sizeOfOutputCharacterCodeInBytesIfForeign.",\n\t\t0,\n\t\t\t\{\n\t\t\t".$word1."\n\t\t\t\}\n\t\t\}");
  1.1194 +		if ($i<$indexOfLastRange)
  1.1195 +			{
  1.1196 +			push(@$sourceCodeOfTopLevelStructures, ',');
  1.1197 +			}
  1.1198 +		push(@$sourceCodeOfTopLevelStructures, "\n");
  1.1199 +		}
  1.1200 +	my @characterCodes=sort({$a<=>$b} keys(%$characterCodes));
  1.1201 +	if (@characterCodes>0)
  1.1202 +		{
  1.1203 +		die('The following '.($outputIsUnicode? 'foreign': 'Unicode').' characters have no conversion algorithm specified: ['.join(', ', map(sprintf($formatForInputCharacters, $_), @characterCodes))."\]\n");
  1.1204 +		}
  1.1205 +	push(@$sourceCodeOfTopLevelStructures, "\t\};\n\n");
  1.1206 +	}
  1.1207 +
  1.1208 +sub writeSourceCodeFinalStuff
  1.1209 +	{
  1.1210 +	my $fileHandle=shift;
  1.1211 +	my $sourceCodeOfForeignToUnicodeIndexedTables16=shift;
  1.1212 +	my $sourceCodeOfForeignToUnicodeKeyedTables1616=shift;
  1.1213 +	my $sourceCodeOfForeignToUnicodeKeyedTables16OfIndexedTables16_indexedEntries=shift;
  1.1214 +	my $sourceCodeOfForeignToUnicodeKeyedTables16OfIndexedTables16_keyedEntries=shift;
  1.1215 +	my $sourceCodeOfUnicodeToForeignIndexedTables16=shift;
  1.1216 +	my $sourceCodeOfUnicodeToForeignKeyedTables1616=shift;
  1.1217 +	my $sourceCodeOfUnicodeToForeignKeyedTables16OfIndexedTables16_indexedEntries=shift;
  1.1218 +	my $sourceCodeOfUnicodeToForeignKeyedTables16OfIndexedTables16_keyedEntries=shift;
  1.1219 +
  1.1220 +	my $sourceCodeOfForeignToUnicodeIndexedTables32=shift;
  1.1221 +	my $sourceCodeOfForeignToUnicodeKeyedTables3232=shift;
  1.1222 +	my $sourceCodeOfForeignToUnicodeKeyedTables32OfIndexedTables32_indexedEntries=shift;
  1.1223 +	my $sourceCodeOfForeignToUnicodeKeyedTables32OfIndexedTables32_keyedEntries=shift;
  1.1224 +	my $sourceCodeOfUnicodeToForeignIndexedTables32=shift;
  1.1225 +	my $sourceCodeOfUnicodeToForeignKeyedTables3232=shift;
  1.1226 +	my $sourceCodeOfUnicodeToForeignKeyedTables32OfIndexedTables32_indexedEntries=shift;
  1.1227 +	my $sourceCodeOfUnicodeToForeignKeyedTables32OfIndexedTables32_keyedEntries=shift;
  1.1228 +
  1.1229 +	my $sourceCodeOfTopLevelStructures=shift;
  1.1230 +	my $endiannessAsText=shift;
  1.1231 +	my $additionalSubsetTables=shift;
  1.1232 +	my $sourceCodeChunk;
  1.1233 +	my $arrayOfSourceCodeChunks;
  1.1234 +
  1.1235 +	foreach $arrayOfSourceCodeChunks (@$sourceCodeOfForeignToUnicodeIndexedTables16)
  1.1236 +		{
  1.1237 +		foreach $sourceCodeChunk (@$arrayOfSourceCodeChunks)
  1.1238 +			{
  1.1239 +			print($fileHandle $sourceCodeChunk);
  1.1240 +			}
  1.1241 +		}
  1.1242 +	foreach $arrayOfSourceCodeChunks (@$sourceCodeOfForeignToUnicodeKeyedTables1616)
  1.1243 +		{
  1.1244 +		foreach $sourceCodeChunk (@$arrayOfSourceCodeChunks)
  1.1245 +			{
  1.1246 +			print($fileHandle $sourceCodeChunk);
  1.1247 +			}
  1.1248 +		}
  1.1249 +	foreach $arrayOfSourceCodeChunks (@$sourceCodeOfForeignToUnicodeKeyedTables16OfIndexedTables16_indexedEntries)
  1.1250 +		{
  1.1251 +		foreach $sourceCodeChunk (@$arrayOfSourceCodeChunks)
  1.1252 +			{
  1.1253 +			print($fileHandle $sourceCodeChunk);
  1.1254 +			}
  1.1255 +		}
  1.1256 +	foreach $arrayOfSourceCodeChunks (@$sourceCodeOfForeignToUnicodeKeyedTables16OfIndexedTables16_keyedEntries)
  1.1257 +		{
  1.1258 +		foreach $sourceCodeChunk (@$arrayOfSourceCodeChunks)
  1.1259 +			{
  1.1260 +			print($fileHandle $sourceCodeChunk);
  1.1261 +			}
  1.1262 +		}
  1.1263 +	foreach $arrayOfSourceCodeChunks (@$sourceCodeOfUnicodeToForeignIndexedTables16)
  1.1264 +		{
  1.1265 +		foreach $sourceCodeChunk (@$arrayOfSourceCodeChunks)
  1.1266 +			{
  1.1267 +			print($fileHandle $sourceCodeChunk);
  1.1268 +			}
  1.1269 +		}
  1.1270 +	foreach $arrayOfSourceCodeChunks (@$sourceCodeOfUnicodeToForeignKeyedTables1616)
  1.1271 +		{
  1.1272 +		foreach $sourceCodeChunk (@$arrayOfSourceCodeChunks)
  1.1273 +			{
  1.1274 +			print($fileHandle $sourceCodeChunk);
  1.1275 +			}
  1.1276 +		}
  1.1277 +	foreach $arrayOfSourceCodeChunks (@$sourceCodeOfUnicodeToForeignKeyedTables16OfIndexedTables16_indexedEntries)
  1.1278 +		{
  1.1279 +		foreach $sourceCodeChunk (@$arrayOfSourceCodeChunks)
  1.1280 +			{
  1.1281 +			print($fileHandle $sourceCodeChunk);
  1.1282 +			}
  1.1283 +		}
  1.1284 +	foreach $arrayOfSourceCodeChunks (@$sourceCodeOfUnicodeToForeignKeyedTables16OfIndexedTables16_keyedEntries)
  1.1285 +		{
  1.1286 +		foreach $sourceCodeChunk (@$arrayOfSourceCodeChunks)
  1.1287 +			{
  1.1288 +			print($fileHandle $sourceCodeChunk);
  1.1289 +			}
  1.1290 +		}
  1.1291 +	# for 32 bit encoding begin
  1.1292 +	foreach $arrayOfSourceCodeChunks (@$sourceCodeOfForeignToUnicodeIndexedTables32)
  1.1293 +		{
  1.1294 +		foreach $sourceCodeChunk (@$arrayOfSourceCodeChunks)
  1.1295 +			{
  1.1296 +			print($fileHandle $sourceCodeChunk);
  1.1297 +			}
  1.1298 +		}
  1.1299 +	foreach $arrayOfSourceCodeChunks (@$sourceCodeOfForeignToUnicodeKeyedTables3232)
  1.1300 +		{
  1.1301 +		foreach $sourceCodeChunk (@$arrayOfSourceCodeChunks)
  1.1302 +			{
  1.1303 +			print($fileHandle $sourceCodeChunk);
  1.1304 +			}
  1.1305 +		}
  1.1306 +	foreach $arrayOfSourceCodeChunks (@$sourceCodeOfForeignToUnicodeKeyedTables32OfIndexedTables32_indexedEntries)
  1.1307 +		{
  1.1308 +		foreach $sourceCodeChunk (@$arrayOfSourceCodeChunks)
  1.1309 +			{
  1.1310 +			print($fileHandle $sourceCodeChunk);
  1.1311 +			}
  1.1312 +		}
  1.1313 +	foreach $arrayOfSourceCodeChunks (@$sourceCodeOfForeignToUnicodeKeyedTables32OfIndexedTables32_keyedEntries)
  1.1314 +		{
  1.1315 +		foreach $sourceCodeChunk (@$arrayOfSourceCodeChunks)
  1.1316 +			{
  1.1317 +			print($fileHandle $sourceCodeChunk);
  1.1318 +			}
  1.1319 +		}
  1.1320 +	foreach $arrayOfSourceCodeChunks (@$sourceCodeOfUnicodeToForeignIndexedTables32)
  1.1321 +		{
  1.1322 +		foreach $sourceCodeChunk (@$arrayOfSourceCodeChunks)
  1.1323 +			{
  1.1324 +			print($fileHandle $sourceCodeChunk);
  1.1325 +			}
  1.1326 +		}
  1.1327 +	foreach $arrayOfSourceCodeChunks (@$sourceCodeOfUnicodeToForeignKeyedTables3232)
  1.1328 +		{
  1.1329 +		foreach $sourceCodeChunk (@$arrayOfSourceCodeChunks)
  1.1330 +			{
  1.1331 +			print($fileHandle $sourceCodeChunk);
  1.1332 +			}
  1.1333 +		}
  1.1334 +	foreach $arrayOfSourceCodeChunks (@$sourceCodeOfUnicodeToForeignKeyedTables32OfIndexedTables32_indexedEntries)
  1.1335 +		{
  1.1336 +		foreach $sourceCodeChunk (@$arrayOfSourceCodeChunks)
  1.1337 +			{
  1.1338 +			print($fileHandle $sourceCodeChunk);
  1.1339 +			}
  1.1340 +		}
  1.1341 +	foreach $arrayOfSourceCodeChunks (@$sourceCodeOfUnicodeToForeignKeyedTables32OfIndexedTables32_keyedEntries)
  1.1342 +		{
  1.1343 +		foreach $sourceCodeChunk (@$arrayOfSourceCodeChunks)
  1.1344 +			{
  1.1345 +			print($fileHandle $sourceCodeChunk);
  1.1346 +			}
  1.1347 +		}
  1.1348 +	# for 32 bit encoding end
  1.1349 +	foreach $sourceCodeChunk (@$sourceCodeOfTopLevelStructures)
  1.1350 +		{
  1.1351 +		print($fileHandle $sourceCodeChunk);
  1.1352 +		}
  1.1353 +
  1.1354 +	print($fileHandle "GLDEF_D const SCnvConversionData conversionData=\n\t\{\n\tSCnvConversionData::E$endiannessAsText,\n\t\t\{\n\t\tARRAY_LENGTH(foreignVariableByteDataRanges),\n\t\tforeignVariableByteDataRanges\n\t\t\},\n\t\t\{\n\t\tARRAY_LENGTH(foreignToUnicodeDataRanges),\n\t\tforeignToUnicodeDataRanges\n\t\t\},\n\t\t\{\n\t\tARRAY_LENGTH(unicodeToForeignDataRanges),\n\t\tunicodeToForeignDataRanges\n\t\t\},\n\tNULL,\n\tNULL\n\t\};\n\n");
  1.1355 +
  1.1356 +	my $additionalSubsetTableName;
  1.1357 +	my $additionalSubsetTableData;
  1.1358 +	while (($additionalSubsetTableName, $additionalSubsetTableData)=each(%$additionalSubsetTables))
  1.1359 +		{
  1.1360 +		(defined($additionalSubsetTableData->[0]) && defined($additionalSubsetTableData->[1]) && defined($additionalSubsetTableData->[2]) && defined($additionalSubsetTableData->[3])) or die("Error: incomplete definition of \"$additionalSubsetTableName\"\n");
  1.1361 +		print($fileHandle "GLREF_D const SCnvConversionData $additionalSubsetTableName;\n");
  1.1362 +		print($fileHandle "GLDEF_D const SCnvConversionData $additionalSubsetTableName=\n\t\{\n\tSCnvConversionData::E$endiannessAsText,\n\t\t\{\n\t\tARRAY_LENGTH(foreignVariableByteDataRanges),\n\t\tforeignVariableByteDataRanges\n\t\t\},\n\t\t\{\n\t\t$additionalSubsetTableData->[1]-$additionalSubsetTableData->[0],\n\t\tforeignToUnicodeDataRanges+$additionalSubsetTableData->[0]\n\t\t\},\n\t\t\{\n\t\t$additionalSubsetTableData->[3]-$additionalSubsetTableData->[2],\n\t\tunicodeToForeignDataRanges+$additionalSubsetTableData->[2]\n\t\t\}\n\t\};\n\n");
  1.1363 +		}
  1.1364 +	}
  1.1365 +
  1.1366 +sub writeBinaryHeader
  1.1367 +	{
  1.1368 +	my $fileHandle=shift;
  1.1369 +	my $uid=shift;
  1.1370 +	my $endianness=shift;
  1.1371 +	my $replacementForUnconvertibleUnicodeCharacters=shift;
  1.1372 +	&writeUids($fileHandle, 0x100011bd, $uid, 0);
  1.1373 +	&write32($fileHandle, 1); # version number of the file format
  1.1374 +	&write32($fileHandle, 0); # not currently used
  1.1375 +	&write8($fileHandle, 0); # number of Unicode characters in the name (which is now derived from the file-name, hence why this is zero)
  1.1376 +	&write8($fileHandle, $endianness);
  1.1377 +	&write8($fileHandle, length($replacementForUnconvertibleUnicodeCharacters));
  1.1378 +	&writeString($fileHandle, $replacementForUnconvertibleUnicodeCharacters);
  1.1379 +	}
  1.1380 +
  1.1381 +sub writeBinaryForeignVariableByteData
  1.1382 +	{
  1.1383 +	my $fileHandle=shift;
  1.1384 +	my $foreignVariableByteData=shift;
  1.1385 +	&writePositiveIntegerCompacted30($fileHandle, scalar(@$foreignVariableByteData));
  1.1386 +	my $rangeData;
  1.1387 +	foreach $rangeData (@$foreignVariableByteData)
  1.1388 +		{
  1.1389 +		if (@$rangeData!=3)
  1.1390 +			{
  1.1391 +			die("Error: internal error 10\n");
  1.1392 +			}
  1.1393 +		my $firstInitialByteValueInRange=$rangeData->[0];
  1.1394 +		my $lastInitialByteValueInRange=$rangeData->[1];
  1.1395 +		if ($lastInitialByteValueInRange<$firstInitialByteValueInRange)
  1.1396 +			{
  1.1397 +			die("Error: internal error 11\n");
  1.1398 +			}
  1.1399 +		&write8($fileHandle, $firstInitialByteValueInRange);
  1.1400 +		&write8($fileHandle, $lastInitialByteValueInRange);
  1.1401 +		&write8($fileHandle, $rangeData->[2]); # numberOfSubsequentBytes
  1.1402 +		}
  1.1403 +	}
  1.1404 +
  1.1405 +sub writeBinaryOneDirectionData
  1.1406 +	{
  1.1407 +	my $fileHandle=shift;
  1.1408 +	my $oneDirectionData=shift;
  1.1409 +	my $characterCodes=shift;
  1.1410 +	my $outputIsUnicode=shift;
  1.1411 +	&writePositiveIntegerCompacted30($fileHandle, scalar(@$oneDirectionData));
  1.1412 +	my $rangeData;
  1.1413 +	foreach $rangeData (@$oneDirectionData)
  1.1414 +		{
  1.1415 +##		$rangeData is $includePriority, $searchPriority, $firstInputCharacterCodeInRange, $lastInputCharacterCodeInRange, $algorithm[, $sizeOfOutputCharacterCodeInBytes], $parameters
  1.1416 +		if (scalar(@$rangeData)!=($outputIsUnicode? 6: 7))
  1.1417 +			{
  1.1418 +			die("Error: internal error 12\n");
  1.1419 +			}
  1.1420 +		my $firstInputCharacterCodeInRange=$rangeData->[2];
  1.1421 +		my $lastInputCharacterCodeInRange=$rangeData->[3];
  1.1422 +		if ($lastInputCharacterCodeInRange<$firstInputCharacterCodeInRange)
  1.1423 +			{
  1.1424 +			die("Error: internal error 13\n");
  1.1425 +			}
  1.1426 +		&writePositiveIntegerCompacted30($fileHandle, $firstInputCharacterCodeInRange);
  1.1427 +		&writePositiveIntegerCompacted30($fileHandle, $lastInputCharacterCodeInRange);
  1.1428 +		my $algorithm=$rangeData->[4];
  1.1429 +		&write8($fileHandle, $algorithm);
  1.1430 +		if (!$outputIsUnicode)
  1.1431 +			{
  1.1432 +			&write8($fileHandle, $rangeData->[5]); # sizeOfOutputCharacterCodeInBytesIfForeign
  1.1433 +			}
  1.1434 +		if ($algorithm==0) # Direct
  1.1435 +			{
  1.1436 +			my $characterCode;
  1.1437 +			for ($characterCode=$firstInputCharacterCodeInRange; $characterCode<=$lastInputCharacterCodeInRange; ++$characterCode)
  1.1438 +				{
  1.1439 +				if (!defined($characterCodes->{$characterCode}))
  1.1440 +					{
  1.1441 +					die("Error: There is no conversion defined for ".($outputIsUnicode? 'foreign': 'Unicode')." character code ".sprintf("0x%08x", $characterCode)."\n");
  1.1442 +					}
  1.1443 +				if ($characterCodes->{$characterCode}!=$characterCode)
  1.1444 +					{
  1.1445 +					die("Error: the conversion from ".($outputIsUnicode? 'foreign': 'Unicode')." character code ".sprintf("0x%08x", $characterCode)." to ".($outputIsUnicode? 'Unicode': 'foreign')." character code ".sprintf("0x%08x", $characterCodes->{$characterCode})." is not a direct conversion\n");
  1.1446 +					}
  1.1447 +				delete $characterCodes->{$characterCode};
  1.1448 +				}
  1.1449 +			}
  1.1450 +		elsif ($algorithm==1) # Offset
  1.1451 +			{
  1.1452 +			my $offset=$characterCodes->{$firstInputCharacterCodeInRange}-$firstInputCharacterCodeInRange;
  1.1453 +			delete $characterCodes->{$firstInputCharacterCodeInRange};
  1.1454 +			my $characterCode;
  1.1455 +			for ($characterCode=$firstInputCharacterCodeInRange+1; $characterCode<=$lastInputCharacterCodeInRange; ++$characterCode)
  1.1456 +				{
  1.1457 +				if (!defined($characterCodes->{$characterCode}))
  1.1458 +					{
  1.1459 +					die("Error: There is no conversion defined for ".($outputIsUnicode? 'foreign': 'Unicode')." character code ".sprintf("0x%08x (0x%08x-0x%08x)", $characterCode, $firstInputCharacterCodeInRange, $lastInputCharacterCodeInRange)."\n");
  1.1460 +					}
  1.1461 +				if ($characterCodes->{$characterCode}-$characterCode!=$offset)
  1.1462 +					{
  1.1463 +					die("Error: the conversion from ".($outputIsUnicode? 'foreign': 'Unicode')." character code ".sprintf("0x%08x", $characterCode)." to ".($outputIsUnicode? 'Unicode': 'foreign')." character code ".sprintf("0x%08x", $characterCodes->{$characterCode})." has a different offset from the previous one in the range\n");
  1.1464 +					}
  1.1465 +				delete $characterCodes->{$characterCode};
  1.1466 +				}
  1.1467 +			&writeSignedIntegerCompacted29($fileHandle, $offset);
  1.1468 +			}
  1.1469 +		elsif ($algorithm==2) # IndexedTable16
  1.1470 +			{
  1.1471 +			my $characterCode;
  1.1472 +			for ($characterCode=$firstInputCharacterCodeInRange; $characterCode<=$lastInputCharacterCodeInRange; ++$characterCode)
  1.1473 +				{
  1.1474 +				if (!defined($characterCodes->{$characterCode}))
  1.1475 +					{
  1.1476 +					die("Error: There is no conversion defined for ".($outputIsUnicode? 'foreign': 'Unicode')." character code ".sprintf("0x%08x", $characterCode)."\n");
  1.1477 +					}
  1.1478 +				&write16($fileHandle, $characterCodes->{$characterCode});
  1.1479 +				delete $characterCodes->{$characterCode};
  1.1480 +				}
  1.1481 +			}
  1.1482 +		elsif ($algorithm==3) # KeyedTable1616
  1.1483 +			{
  1.1484 +			my $characterCode;
  1.1485 +			my @table=();
  1.1486 +			for ($characterCode=$firstInputCharacterCodeInRange; $characterCode<=$lastInputCharacterCodeInRange; ++$characterCode)
  1.1487 +				{
  1.1488 +				if (defined($characterCodes->{$characterCode}))
  1.1489 +					{
  1.1490 +					push(@table, [$characterCode, $characterCodes->{$characterCode}]);
  1.1491 +					delete $characterCodes->{$characterCode};
  1.1492 +					}
  1.1493 +				}
  1.1494 +			my $firstIteration=1;
  1.1495 +			my $lastKey;
  1.1496 +			&writePositiveIntegerCompacted30($fileHandle, scalar(@table));
  1.1497 +			if ($table[0][0]!=$firstInputCharacterCodeInRange)
  1.1498 +				{
  1.1499 +				die("Error: no conversion is specified for the first ".($outputIsUnicode? 'foreign': 'Unicode')." character code in the KeyedTable1616 range ".sprintf("0x%08x to 0x%08x", $firstInputCharacterCodeInRange, $lastInputCharacterCodeInRange)."\n");
  1.1500 +				}
  1.1501 +			my $pair;
  1.1502 +			foreach $pair (@table)
  1.1503 +				{
  1.1504 +				my $key=$pair->[0];
  1.1505 +				if ($firstIteration)
  1.1506 +					{
  1.1507 +					$firstIteration=0;
  1.1508 +					}
  1.1509 +				else
  1.1510 +					{
  1.1511 +					if ($key<=$lastKey)
  1.1512 +						{
  1.1513 +						die("Error: internal error 14\n");
  1.1514 +						}
  1.1515 +					&writePositiveIntegerCompacted15($fileHandle, $key-$lastKey);
  1.1516 +					}
  1.1517 +				&write16($fileHandle, $pair->[1]);
  1.1518 +				$lastKey=$key;
  1.1519 +				}
  1.1520 +			}
  1.1521 +		elsif ($algorithm==4) # KeyedTable16OfIndexedTables16
  1.1522 +			{
  1.1523 +			die("Error: \"KeyedTable16OfIndexedTables16\" is only supported if generating source code\n");
  1.1524 +			}
  1.1525 +		else
  1.1526 +			{
  1.1527 +			die("Error: internal error 15\n");
  1.1528 +			}
  1.1529 +		}
  1.1530 +	my @characterCodes=sort({$a<=>$b} keys(%$characterCodes));
  1.1531 +	if (@characterCodes>0)
  1.1532 +		{
  1.1533 +		die('The following '.($outputIsUnicode? 'foreign': 'Unicode').'characters have no conversion algorithm specified: ['.join(', ', map({sprintf('0x%x', $_)} @characterCodes))."\]\n");
  1.1534 +		}
  1.1535 +	}
  1.1536 +