OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [newlib-1.18.0/] [newlib/] [libc/] [iconv/] [ccs/] [mktbl.pl] - Blame information for rev 262

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 207 jeremybenn
#!/usr/bin/perl -w
2
#
3
#  Copyright (c) 2003-2004, Artem B. Bityuckiy, SoftMine Corporation.
4
#
5
#  Redistribution and use in source and binary forms, with or without
6
#  modification, are permitted provided that the following conditions
7
#  are met:
8
#  1. Redistributions of source code must retain the above copyright
9
#     notice, this list of conditions and the following disclaimer.
10
#  2. Redistributions in binary form must reproduce the above copyright
11
#     notice, this list of conditions and the following disclaimer in the
12
#     documentation and/or other materials provided with the distribution.
13
#
14
#  THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15
#  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
#  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18
#  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
#  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
#  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
#  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22
#  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23
#  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
#  SUCH DAMAGE.
25
#
26
use integer;
27
use Getopt::Std;
28
use IO::Seekable;
29
use strict;
30
 
31
 
32
# ##############################################################################
33
#
34
# FUNCTION PROTOTYPES AND GLOBAL DATA DECLARATION SECTION
35
#
36
# ##############################################################################
37
 
38
 
39
# SUPPLEMENTARY FUNCTIONS FORWARD DECLARATIONS
40
sub ProcessOptions();
41
sub Err($;$);
42
sub Generate8bitToUCS();
43
sub GenerateSpeed($);
44
sub Generate16bitSize($);
45
sub Output8bitToUCS(;$);
46
sub Output8bitFromUCS(;$);
47
sub OutputSpeed($;$);
48
sub OutputSize($;$);
49
 
50
# VARIABLES RELATING TO COMMAND-LINE OPTIONS
51
my $Verbose;  # Be verbose if true
52
my $Source;   # Output C source code instead of binary .cct file if true
53
my $Plane;    # Use this plane if defined
54
my $InFile;   # Use this file for input
55
my $OutFile;  # Use this file for output
56
my $CCSName;  # Use this CCS name
57
my $NoSpeed;  # Don't generate speed-optimized tables (binary files only)
58
my $NoSize;   # Don't generate size-optimized tables (binary files only)
59
my $NoBE;     # Don't generate big-endian tables (binary files only)
60
my $NoLE;     # Don't generate big-endian tables (binary files only)
61
my $NoTo;     # Don't generate "to_ucs" table (binary files only)
62
my $NoFrom;   # Don't generate "from_ucs" table (binary files only)
63
my $CCSCol;   # CCS column number in source file
64
my $UCSCol;   # UCS column number in source file
65
 
66
 
67
# DATA STRUCTURES WITH "TO_UCS" AND "FROM_UCS" SPEED/SIZE -OPTIMIZED TABLES
68
my (@FromSpeedTbl, @ToSpeedTbl, @FromSizeTbl, @ToSizeTbl);
69
# "TO_UCS" AND "FROM_UCS" SPEED/SIZE -OPTIMIZED TABLES SIZE IN BYTES
70
my ($FromSpeedBytes, $ToSpeedBytes, $FromSizeBytes, $ToSizeBytes) =
71
   (0, 0, 0, 0);
72
 
73
my (%CCSUCS, %UCSCCS); # CCS->UCS and UCS->CCS mappings
74
my $Bits = 8;          # Table bits (8 or 16);
75
 
76
# SPECIAL MARKER CODES
77
my $InvCode  = 0xFFFF; # FFFF indicates 18 bit invalid codes
78
my $InvBlock = 0xFFFF; # FFFF also mark empty blocks in speed-optimized tables
79
my $LostCode = 0x3F;   # ASCII '?' marks codes lost during CCS->UCS mapping
80
# To mark invalid codes in 8bit encodings 0xFF is used CCS's 0xFF mapping is saved
81
# separately. $FFMap variable stores real 0xFF mapping if defined.
82
my $InvCode8bit = 0xFF;
83
my $FFMap;
84
 
85
# 8 Bit "From UCS" table header size (bytes)
86
my $Hdr8bitFromUCS = 2;
87
# Binary table header size (bytes)
88
my $HdrBinary = 8;
89
 
90
# At first all lost CCS codes are marked by $TmpLost to distinguish between
91
# code which is equivalent to $LostCode and lost codes. This is done in order to
92
# output $MacroLostCode instead of $LostCode in source file.
93
my $TmpLost = 0x1FFFF;
94
 
95
# VARIABLES RELATING TO C SOURCE CODE
96
my $MacroInvCode      = 'INVALC';
97
my $MacroInvBlock     = 'INVBLK';
98
my $MacroLostCode     = 'LOST_C';
99
my $MacroCCSName      = 'ICONV_CCS_%s';
100
my $GuardSize       = 'defined (TABLE_USE_SIZE_OPTIMIZATION)';
101
my $GuardToUCS      = "ICONV_TO_UCS_CCS_%s";
102
my $GuardFromUCS    = "ICONV_FROM_UCS_CCS_%s";
103
my $MacroSpeedTable = 'TABLE_SPEED_OPTIMIZED';
104
my $MacroSizeTable  = 'TABLE_SIZE_OPTIMIZED';
105
my $Macro8bitTable  = 'TABLE_8BIT';
106
my $Macro16bitTable = 'TABLE_16BIT';
107
my $MacroVer1Table  = 'TABLE_VERSION_1';
108
my $TypeBICCS       = 'iconv_ccs_t';
109
my $VarToUCSSize    = "to_ucs_size_%s";
110
my $VarToUCSSpeed   = "to_ucs_speed_%s";
111
my $VarFromUCSSize  = "from_ucs_size_%s";
112
my $VarFromUCSSpeed = "from_ucs_speed_%s";
113
my $VarBICCS             = "_iconv_ccs_%s";
114
# Text block that visually separates tables.
115
my $Separator = '=' x 70;
116
 
117
# ##############################################################################
118
#
119
# SCRIPT ENTRY POINT
120
#
121
# ##############################################################################
122
 
123
 
124
# Parse command-line options, check them and set correspondent global variables
125
ProcessOptions();
126
 
127
# Initialize global variables tat depend on CCS name.
128
$_ = sprintf $_, $CCSName foreach +($VarToUCSSpeed,
129
                                    $VarToUCSSize,
130
                                    $VarToUCSSpeed,
131
                                    $VarFromUCSSpeed,
132
                                    $VarFromUCSSize,
133
                                    $VarBICCS);
134
$_ = sprintf $_, "\U$CCSName" foreach +($GuardToUCS,
135
                                        $GuardFromUCS,
136
                                        $MacroCCSName);
137
 
138
# Open input and output files
139
Err "Can't open \"$InFile\" file for reading: $!.\n", 1
140
unless open(INFILE, '<', $InFile);
141
Err "Can't open \"$OutFile\" file for writing: $!.\n", 1
142
unless open(OUTFILE, '>', $OutFile);
143
 
144
# ==============================================================================
145
# EXTRACT CODES MAP FROM INPUT FILE
146
# ==============================================================================
147
 
148
for (my $ln = 1; my $l = <INFILE>; $ln += 1)
149
{
150
  # Skip comment and empty lines, remove ending CR symbol
151
  next if $l =~ /^#.*$/ or $l =~ /^\s*$/;
152
  $l =~ s/^(.*)\n$/$1/, $l =~ s/^(.*)\r$/$1/;
153
 
154
  # Remove comment and extra spaces
155
  $l =~ s/(.*)\s*#.*/$1/;
156
  $l =~ s/\s+/ /g;
157
  $l =~ s/(.*)\s*$/$1/;
158
 
159
  # Split line into individual codes
160
  my @codes = split / /, $l;
161
 
162
  # Skip line if there is no needed columns
163
  unless (defined $codes[$CCSCol])
164
  {
165
    print("Warning (line $ln): no CCS column, skip.\n") if $Verbose;
166
    next;
167
  }
168
  unless (defined $codes[$UCSCol])
169
  {
170
    print("Warning (line $ln): no UCS column, skip.\n") if $Verbose;
171
    next;
172
  }
173
 
174
  # Extract codes strings from needed columns
175
  my ($ccs, $ucs) = ($codes[$CCSCol], $codes[$UCSCol]);
176
  my $patt = qr/(0[xX])?[0-9a-fA-F]{1,8}/; # HEX digit regexp pattern.
177
 
178
  # Check that CCS and UCS code strings has right format.
179
  unless ($ccs =~ m/^$patt$/)
180
  {
181
    print("Warning (line $ln): $ccs CCS code isn't recognized, skip.\n")
182
    if $Verbose;
183
    next;
184
  }
185
  unless ($ucs =~ m/^($patt(,|\+))*$patt$/)
186
  {
187
    print("Warning (line $ln): $ucs UCS code isn't recognized, skip.\n")
188
    if $Verbose;
189
    next;
190
  }
191
 
192
  # Convert code to numeric format (assume hex).
193
  $ccs = hex $ccs;
194
 
195
  if ($ucs =~ m/,/ or $ucs =~ m/\+/)
196
  {
197
    # Mark CCS codes with "one to many" mappings as lost
198
    printf "Warning (line $ln): only one to one mapping is supported, "
199
         . "mark 0x%.4X CCS code as lost.\n", hex $ccs if $Verbose;
200
    $ucs = $TmpLost;
201
  }
202
  else
203
  {
204
    # Convert code to numeric format
205
    $ucs = hex $ucs;
206
 
207
    # Check that UCS code isn't longer than 16 bits.
208
    if ($ucs > 0xFFFF)
209
    {
210
      printf("Warning (line $ln): UCS code should fit 16 bits, "
211
           . "mark 0x%.4X CCS code as lost.\n", hex $ccs) if $Verbose;
212
      $ucs = $TmpLost;
213
    }
214
  }
215
 
216
  # If CCS value > 0xFFFF user should specify plane number.
217
  if ($ccs > 0xFFFF && !defined $Plane)
218
  {
219
    print("Warning (line $ln): $ccs is > 16 bit, plane number should be specified,"
220
        . " skip this mapping.\n") if $Verbose;
221
    next;
222
  }
223
 
224
  if (defined $Plane)
225
  {
226
    next if (($ccs & 0xFFFF0000) >> 16) != hex $Plane; # Skip alien plane.
227
    $ccs &= 0xFFFF;
228
  }
229
 
230
  # Check that reserved codes aren't used.
231
  if ($ccs == $InvCode or $ucs == $InvCode)
232
  {
233
    print("Warning (line $ln): $InvCode is reserved to mark invalid codes and "
234
       . "shouldn't be used in mappings, skip.\n") if $Verbose;
235
    next;
236
  }
237
 
238
  # Save mapping in UCSCCS and CCSUCS hash arrays.
239
  $UCSCCS{$ucs} = $ccs if $ucs != $TmpLost && !defined $UCSCCS{$ucs};
240
  $CCSUCS{$ccs} = $ucs if !defined $CCSUCS{$ccs};
241
 
242
  $Bits = 16 if $ccs > 0xFF;
243
}
244
 
245
if (not %CCSUCS)
246
{
247
  Err "Error: there is no plane $Plane in \"$0\".\n" if defined $Plane;
248
  Err "Error: mapping wasn't found.\n";
249
}
250
 
251
 
252
# ==============================================================================
253
# GENERATE TABLE DATA
254
# ==============================================================================
255
 
256
if ($Bits == 8)
257
{
258
  $FFMap = $CCSUCS{0xFF};
259
  $FFMap = $InvCode if !defined $FFMap;
260
}
261
 
262
if ($Bits == 8)
263
{
264
  Generate8bitToUCS() unless $NoTo;
265
}
266
else
267
{
268
  GenerateSpeed("to_ucs") unless $NoTo || $NoSpeed;
269
  Generate16bitSize("to_ucs")  unless $NoTo || $NoSize;
270
}
271
 
272
GenerateSpeed("from_ucs") unless $NoFrom || $NoSpeed;
273
Generate16bitSize("from_ucs")  unless $NoFrom || $NoSize;
274
 
275
# ==============================================================================
276
# OUTPUT ARRAYS
277
# ==============================================================================
278
 
279
if ($Source)
280
{
281
  # OUTPUT SOURCE
282
  print OUTFILE
283
"/*
284
 * This file was generated automatically - don't edit it.
285
 * File contains iconv CCS tables for $CCSName encoding.
286
 */
287
 
288
#include \"ccsbi.h\"
289
 
290
#if defined ($GuardToUCS) \\
291
 || defined ($GuardFromUCS)
292
 
293
#include <_ansi.h>
294
#include <sys/types.h>
295
#include <sys/param.h>
296
#include \"ccs.h\"
297
#include \"ccsnames.h\"
298
 
299
";
300
 
301
  if ($Bits == 8)
302
  {
303
    print OUTFILE
304
"#if (BYTE_ORDER == LITTLE_ENDIAN)
305
#  define W(word) (word) & 0xFF, (word) >> 8
306
#elif (BYTE_ORDER == BIG_ENDIAN)
307
#  define W(word) (word) >> 8, (word) & 0xFF
308
#else
309
#  error \"Unknown byte order.\"
310
#endif
311
 
312
";
313
  }
314
 
315
  unless ($NoTo)
316
  {
317
    if ($Bits == 8)
318
    {
319
      Output8bitToUCS();
320
    }
321
    else
322
    {
323
      OutputSpeed("to_ucs") unless $NoSpeed;
324
      OutputSize("to_ucs")  unless $NoSize;
325
    }
326
  }
327
  unless ($NoFrom)
328
  {
329
    if ($Bits == 8)
330
    {
331
      Output8bitFromUCS();
332
    }
333
    else
334
    {
335
      OutputSpeed("from_ucs") unless $NoSpeed;
336
      OutputSize("from_ucs")  unless $NoSize;
337
    }
338
  }
339
 
340
  # OUTPUT TABLE DESCRIPTION STRUCTURE 
341
  print OUTFILE
342
"/*
343
 * $CCSName CCS description table.
344
 * $Separator
345
 */
346
_CONST $TypeBICCS
347
$VarBICCS =
348
{
349
\t$MacroVer1Table, /* Table version */
350
\t$MacroCCSName, /* CCS name */
351
";
352
  if ($Bits == 8)
353
  {
354
    print OUTFILE
355
"\t$Macro8bitTable, /* Table bits */
356
\t0, /* Not Used */
357
#if defined ($GuardFromUCS)
358
\t(__uint16_t *)&$VarFromUCSSpeed, /* UCS -> $CCSName table */
359
#else
360
\t(__uint16_t *)NULL,
361
#endif
362
\t0, /* Not Used */
363
#if defined ($GuardToUCS)
364
\t(__uint16_t *)&$VarToUCSSpeed /* $CCSName -> UCS table */
365
#else
366
\t(__uint16_t *)NULL,
367
#endif
368
};\n";
369
  }
370
  else
371
  {
372
    print OUTFILE
373
"\t$Macro16bitTable, /* Table bits */
374
#if defined ($GuardFromUCS) \\
375
 && ($GuardSize)
376
\t$MacroSizeTable,
377
\t(__uint16_t *)&$VarFromUCSSize, /* UCS -> $CCSName table size-optimized table */
378
#elif defined ($GuardFromUCS) \\
379
 && !($GuardSize)
380
\t$MacroSpeedTable,
381
\t(__uint16_t *)&$VarFromUCSSpeed, /* UCS -> $CCSName table speed-optimized table */
382
#else
383
\t$MacroSpeedTable,
384
\t(__uint16_t *)NULL,
385
#endif
386
#if defined ($GuardToUCS) \\
387
 && ($GuardSize)
388
\t$MacroSizeTable,
389
\t(__uint16_t *)&$VarToUCSSize /* $CCSName -> UCS table speed-optimized table */
390
#elif defined ($GuardToUCS) \\
391
 && !($GuardSize)
392
\t$MacroSpeedTable,
393
\t(__uint16_t *)&$VarToUCSSpeed /* $CCSName -> UCS table speed-optimized table */
394
#else
395
\t$MacroSpeedTable,
396
\t(__uint16_t *)NULL,
397
#endif
398
};\n";
399
  }
400
  print OUTFILE "\n#endif /* $GuardToUCS) || ... */\n\n";
401
}
402
else
403
{
404
  # OUTPUT BINARY TABLES DESCRIPTION STRUCTURE (ALWAYS BIG ENDIAN)
405
  print OUTFILE pack "n", 1;
406
  print OUTFILE pack "n", $Bits;
407
  my $len = length $CCSName;
408
  print OUTFILE pack "N", $len;
409
  print OUTFILE pack "a$len", $CCSName;
410
 
411
  my $pos = $HdrBinary + $len;
412
  if ($pos & 3)
413
  {
414
    my $l = 4 - ($pos & 3);
415
    print OUTFILE pack "a$l", 'XXX';
416
    $pos += $l;
417
  }
418
 
419
  $pos += 16*4;
420
 
421
  my @tables;
422
  for (my $i = 0; $i < 16; $i++)
423
  {
424
    $tables[$i] = 0;
425
  }
426
 
427
  $tables[0] = $pos, $tables[1] = $FromSpeedBytes, $pos += $FromSpeedBytes
428
  unless $NoFrom || $NoSpeed || $NoBE;
429
  $tables[2] = $pos, $tables[3] = $FromSpeedBytes, $pos += $FromSpeedBytes
430
  unless $NoFrom || $NoSpeed || $NoLE;
431
  if ($Bits == 16)
432
  {
433
    $tables[4] = $pos, $tables[5] = $FromSizeBytes, $pos += $FromSizeBytes
434
    unless $NoFrom || $NoSize || $NoBE;
435
    $tables[6] = $pos, $tables[7] = $FromSizeBytes, $pos += $FromSizeBytes
436
    unless $NoFrom || $NoSize || $NoLE;
437
  }
438
  $tables[8] = $pos, $tables[9] = $ToSpeedBytes, $pos += $ToSpeedBytes
439
  unless $NoTo || $NoSpeed || $NoBE;
440
  $tables[10] = $pos, $tables[11] = $ToSpeedBytes, $pos += $ToSpeedBytes
441
  unless $NoTo || $NoSpeed || $NoLE;
442
  if ($Bits == 16)
443
  {
444
    $tables[12] = $pos, $tables[13] = $ToSizeBytes, $pos += $ToSizeBytes
445
    unless $NoTo || $NoSize || $NoBE;
446
    $tables[14] = $pos, $tables[15] = $ToSizeBytes, $pos += $ToSizeBytes
447
    unless $NoTo || $NoSize || $NoLE;
448
  }
449
 
450
  print OUTFILE pack("N", $_) foreach @tables;
451
 
452
  print "Total bytes for output: $pos.\n" if $Verbose;
453
 
454
  # OUTPUT BINARY TABLES
455
  unless ($NoFrom)
456
  {
457
    if ($Bits == 8)
458
    {
459
      Output8bitFromUCS("n") unless $NoBE;
460
      Output8bitFromUCS("v") unless $NoLE;
461
    }
462
    else
463
    {
464
      unless ($NoSpeed)
465
      {
466
        OutputSpeed("from_ucs", "n") unless $NoBE;
467
        OutputSpeed("from_ucs", "v") unless $NoLE;
468
      }
469
      unless ($NoSize)
470
      {
471
        OutputSize("from_ucs", "n") unless $NoBE;
472
        OutputSize("from_ucs", "v") unless $NoLE;
473
      }
474
    }
475
  }
476
  unless ($NoTo)
477
  {
478
    if ($Bits == 8)
479
    {
480
      Output8bitToUCS("n") unless $NoBE;
481
      Output8bitToUCS("v") unless $NoLE;
482
    }
483
    else
484
    {
485
      unless ($NoSpeed)
486
      {
487
        OutputSpeed("to_ucs", "n") unless $NoBE;
488
        OutputSpeed("to_ucs", "v") unless $NoLE;
489
      }
490
      unless ($NoSize)
491
      {
492
        OutputSize("to_ucs", "n") unless $NoBE;
493
        OutputSize("to_ucs", "v") unless $NoLE;
494
      }
495
    }
496
  }
497
}
498
 
499
close INFILE;
500
close OUTFILE;
501
exit 0;
502
 
503
 
504
# ##############################################################################
505
#
506
# SUPPLEMENTARY FUNCTIONS
507
#
508
# ##############################################################################
509
 
510
 
511
# =============================================================================
512
#
513
# Generate 8bit "to_ucs" table. Store table data in %ToSpeedTbl hash.
514
# Store table size in $ToSpeedBytes scalar.
515
#
516
# =============================================================================
517
sub Generate8bitToUCS()
518
{
519
  for (my $i = 0; $i <= 255; $i++)
520
  {
521
    $ToSpeedTbl[$i] = defined $CCSUCS{$i} ? $CCSUCS{$i} : $InvCode;
522
  }
523
  $ToSpeedBytes = 256*2;
524
}
525
 
526
 
527
# =============================================================================
528
#
529
# Generate speed-optimized table.
530
#
531
# Parameter 1: 
532
#    "to_ucs"   - generate "to_ucs" table, store table data in @ToSpeedTbl
533
#                 array, store table size in $ToSpeedBytes scalar.
534
#    "from_ucs" - generate "from_ucs" table, store table data in @FromSpeedTbl
535
#                 array, store table size in $FromSpeedBytes scalar.
536
#
537
# Data is written to @ToSpeedTbl or @FromSpeedTbl (@map) table and has the
538
# following format:
539
# $table[0] - 256-element array (control block);
540
# $table[1 .. $#table] - 256-element arrays (data blocks).
541
#
542
# =============================================================================
543
sub GenerateSpeed($)
544
{
545
  my $map;
546
  my $tbl;
547
  my $bytes;
548
 
549
  if ($_[0] eq "to_ucs")
550
  {
551
    $map = \%CCSUCS;
552
    $tbl = \@ToSpeedTbl;
553
    $bytes = \$ToSpeedBytes;
554
  }
555
  elsif ($_[0] eq "from_ucs")
556
  {
557
    $map = \%UCSCCS;
558
    $tbl = \@FromSpeedTbl;
559
    $bytes = \$FromSpeedBytes;
560
  }
561
  else
562
  {
563
    Err "Internal script error in GenerateSpeed()\n";
564
  }
565
 
566
  # Identify unused blocks
567
  my @busy_blocks;
568
  $busy_blocks[$_ >> 8] = 1 foreach (keys %$map);
569
 
570
  # GENERATE FIRST 256-ELEMENT CONTROL BLOCK
571
  for (my $i = 0,
572
       my $idx = $Bits == 16 ? 0 : 256 + $Hdr8bitFromUCS;
573
       $i <= 0xFF; $i++)
574
  {
575
    $tbl->[0]->[$i] = $busy_blocks[$i] ? $idx += 256 : undef;
576
  }
577
 
578
  # GENERATE DATA BLOCKS
579
  $$bytes = 0;
580
  for (my $i = 0; $i <= 0xFF; $i++)
581
  {
582
    next unless $busy_blocks[$i];
583
    $$bytes += 256;
584
    for (my $j = 0; $j <= 0xFF; $j++)
585
    {
586
      $tbl->[$i+1]->[$j] = $map->{($i << 8) | $j};
587
    }
588
  }
589
  $$bytes *= 2 if $Bits == 16;
590
  $$bytes += $Hdr8bitFromUCS if $Bits == 8;
591
  $$bytes += 512;
592
}
593
 
594
 
595
# =============================================================================
596
#
597
# Generate 16bit size-optimized table.
598
#
599
# Parameter 1: 
600
#    "to_ucs"   - generate "to_ucs" table, store table data in @ToSizeTbl
601
#                 array, store table size in $ToSizeBytes scalar.
602
#    "from_ucs" - generate "from_ucs" table, store table data in @FromSizeTbl
603
#                 array, store table size in $FromSizeBytes scalar.
604
#
605
# Data is written to @ToSizeTbl or @FromSizeTbl (@map) table and has the
606
# following format:
607
# $table[0] - number of ranges;
608
# $table[1] - number of unranged codes;
609
# $table[2] - unranged codes index in resulting array;
610
# $table[3]->[0 .. $table[0]] - array of arrays of ranges:
611
#     $table[3]->[x]->[0] - first code;
612
#     $table[3]->[x]->[1] - last code;
613
#     $table[3]->[x]->[2] - range index in resulting array;
614
# $table[4]->[0 .. $table[0]] - array of arrays of ranges content;
615
# $table[5]->[0 .. $table[1]] - array of arrays of unranged codes;
616
#     $table[5]->[x]->[0] - CCS code;
617
#     $table[5]->[x]->[0] - UCS code;
618
#
619
# =============================================================================
620
sub Generate16bitSize($)
621
{
622
  my $map;
623
  my $tbl;
624
  my $bytes;
625
 
626
  if ($_[0] eq "to_ucs")
627
  {
628
    $map = \%CCSUCS;
629
    $tbl = \@ToSizeTbl;
630
    $bytes = \$ToSizeBytes;
631
  }
632
  elsif ($_[0] eq "from_ucs")
633
  {
634
    $map = \%UCSCCS;
635
    $tbl = \@FromSizeTbl;
636
    $bytes = \$FromSizeBytes;
637
  }
638
  else
639
  {
640
    Err "Internal script error  Generate16bitSize()\n";
641
  }
642
 
643
  # CREATE LIST OF RANGES.
644
  my @codes = sort {$a <=> $b} keys %$map;
645
  my @ranges;  # Code ranges
646
  my @range;   # Current working range
647
  foreach (@codes)
648
  {
649
    if (not @range or $_ - 1 == $range[$#range])
650
    {
651
      push @range, $_;
652
    }
653
    else
654
    {
655
      my @tmp = @range;
656
      push @ranges, \@tmp;
657
      undef @range;
658
      redo;
659
    }
660
  }
661
  # Add Last range too
662
  if (@range)
663
  {
664
    my @tmp = @range;
665
    push @ranges, \@tmp;
666
  }
667
 
668
  # OPTIMIZE LIST OF RANGES.
669
  my $r = 0; # Working range number
670
  while (1)
671
  {
672
    last if ($r == $#ranges);
673
 
674
    my @r1 = @{$ranges[$r]};
675
    my @r2 = @{$ranges[$r + 1]};
676
 
677
    # Calculate how many array entries two ranges need
678
    my ($s1, $s2);
679
 
680
    if ($#r1 == 0)
681
    { $s1 = 2; }
682
    elsif ($#r1 == 1)
683
    { $s1 = 4; }
684
    else
685
    { $s1 = $#r1 + 1 + 3; }
686
 
687
    if ($#r2 == 0)
688
    { $s2 = 2; }
689
    elsif ($#r2 == 1)
690
    { $s2 = 4; }
691
    else
692
    { $s2 = $#r2 + 1 + 3; }
693
 
694
    my $two = $s1 + $s2;
695
 
696
    # Calculate how many array entries will be needed if we join them
697
    my $one = $r2[$#r2] - $r1[0] + 1 + 3;
698
 
699
    $r += 1, next if ($one > $two);
700
 
701
    # Join ranges
702
    my @r; # New range.
703
    push @r, $_ foreach (@r1);
704
    for (my $i = $r1[$#r1]+1; $i < $r2[0]; $i++)
705
    {
706
      push @r, undef;
707
    }
708
    push @r, $_ foreach (@r2);
709
    $ranges[$r] = \@r;
710
    splice @ranges, $r+1, 1;
711
  }
712
 
713
  # SEPARATE RANGED AND UNRANGED CODES. SPLIT 2-CODES RANGES ON 2 UNRANGED.
714
  my @unranged;
715
  foreach (@ranges)
716
  {
717
    if ($#$_ == 0)
718
    {
719
      push @unranged, $$_[0];
720
      undef $_;
721
    }
722
    elsif ($#$_ == 1)
723
    {
724
      push @unranged, $$_[0];
725
      push @unranged, $$_[1];
726
      undef $_;
727
    }
728
  }
729
 
730
  # DELETE UNUSED ELEMENTS
731
  for (my $i = 0; $i <= $#ranges; $i++)
732
  {
733
    splice @ranges, $i--, 1 unless defined $ranges[$i];
734
  }
735
 
736
  # CALCULATE UNRANGED CODES ARRAY INDEX
737
  my $idx = 3 + ($#ranges + 1)*3;
738
  $idx += $#$_ + 1 foreach @ranges;
739
 
740
  # COMPOSE TABLE
741
  $tbl->[0] = $#ranges + 1;   # Number of ranges
742
  $tbl->[1] = $#unranged + 1; # Number of unranged codes
743
  $tbl->[2] = $idx;           # Array index of unranged codes
744
 
745
  # Generate ranges list
746
  $idx = 3 + ($#ranges + 1)*3; # First range data index
747
  $$bytes = $idx*2;
748
  my $num = 0;
749
  foreach (@ranges)
750
  {
751
    $tbl->[3]->[$num]->[0] = $_->[0];
752
    $tbl->[3]->[$num]->[1] = $_->[$#$_];
753
    $tbl->[3]->[$num]->[2] = $idx;
754
    $idx += $#$_ + 1;
755
    $num += 1;
756
  }
757
 
758
  # Generate ranges content
759
  $num = 0;
760
  foreach (@ranges)
761
  {
762
    for (my $i = 0; $i <= $#$_; $i++)
763
    {
764
      $tbl->[4]->[$num]->[$i] = defined $_->[$i] ? $map->{$_->[$i]} : undef;
765
    }
766
    $num += 1;
767
    $$bytes += ($#$_ + 1)*2;
768
  }
769
 
770
  # Generate unranged codes list
771
  $num = 0;
772
  foreach (@unranged)
773
  {
774
    $tbl->[5]->[$num]->[0] = $_;
775
    $tbl->[5]->[$num]->[1] = $map->{$_};
776
    $num += 1;
777
  }
778
 
779
  $$bytes += ($#unranged + 1)*4;
780
}
781
 
782
 
783
# =============================================================================
784
#
785
# Output 8bit "to UCS" table. Output table's source code if $Source
786
# and table's binary data if !$Source.
787
# 
788
# Parameter 1: Not used when sources are output. Output BE binary if 'n' and
789
#              LE binary if 'v'.
790
#
791
# =============================================================================
792
sub Output8bitToUCS(;$)
793
{
794
  my $endian = $_[0];
795
  my $br = 0;
796
 
797
  printf "Output%s 8-bit UCS -> $CCSName table ($ToSpeedBytes bytes).\n",
798
         defined $endian ? ($endian eq 'n' ?
799
                 " Big Endian" : " Little Endian") : "" if $Verbose;
800
  if ($Source)
801
  {
802
    # Output heading information
803
    printf OUTFILE
804
"/*
805
 * 8-bit $CCSName -> UCS table ($ToSpeedBytes bytes).
806
 * $Separator
807
 */
808
#if defined ($GuardToUCS)
809
 
810
static _CONST __uint16_t
811
${VarToUCSSpeed}\[] =
812
{\n\t";
813
  }
814
 
815
  if ($Source)
816
  {
817
    foreach (@ToSpeedTbl)
818
    {
819
      $br += 1;
820
      if ($_ != $InvCode)
821
      {
822
        if ($_ != $TmpLost)
823
        {
824
          printf OUTFILE "0x%.4X,", $_;
825
        }
826
        else
827
        {
828
          print OUTFILE "$MacroLostCode,";
829
        }
830
      }
831
      else
832
      {
833
        print OUTFILE "$MacroInvCode,";
834
      }
835
      print(OUTFILE "\n\t"), $br = 0 unless $br % 8;
836
    }
837
    print OUTFILE "\n};\n\n#endif /* $GuardToUCS */\n\n";
838
  }
839
  else
840
  {
841
    foreach (@ToSpeedTbl)
842
    {
843
      print OUTFILE pack($endian, $_ == $TmpLost ? $LostCode : $_);
844
    }
845
  }
846
}
847
 
848
 
849
# =============================================================================
850
#
851
# Output 8bit "from UCS" table. Output table's source code if $Source
852
# and table's binary data if !$Source.
853
# 
854
# Parameter 1: Not used when sources are output. Output BE binary if 'n' and
855
#              LE binary if 'v'.
856
#
857
# =============================================================================
858
sub Output8bitFromUCS(;$)
859
{
860
  my $endian = $_[0];
861
 
862
  printf "Output%s 8-bit $CCSName -> UCS table ($FromSpeedBytes bytes).\n",
863
         defined $endian ? ($endian eq 'n' ?
864
                 " Big Endian" : " Little Endian") : "" if $Verbose;
865
  if ($Source)
866
  {
867
    print OUTFILE
868
"/*
869
 * 8-bit UCS -> $CCSName speed-optimized table ($FromSpeedBytes bytes).
870
 * $Separator
871
 */
872
 
873
#if defined ($GuardFromUCS)
874
 
875
static _CONST unsigned char
876
${VarFromUCSSpeed}\[] =
877
{
878
";
879
  }
880
 
881
  # SAVE 0xFF MAPPING.
882
  if ($Source)
883
  {
884
    printf OUTFILE "\tW(0x%.4X), /* Real 0xFF mapping. 0xFF is used "
885
                 . "to mark invalid codes */\n", $FFMap;
886
  }
887
  else
888
  {
889
    print OUTFILE pack($endian, $FFMap);
890
  }
891
 
892
  # OUTPUT HEADING BLOCK (ALWAYS 16 BIT)
893
  if ($Source)
894
  {
895
    my $count = 0;
896
    print OUTFILE "\t/* Heading Block */";
897
    for (my $i = 0, my $br = 0; $i < 256; $br = ++$i % 4)
898
    {
899
      print OUTFILE "\n\t" unless $br;
900
      if (defined $FromSpeedTbl[0]->[$i])
901
      {
902
        printf OUTFILE "W(0x%.4X),", $FromSpeedTbl[0]->[$i];
903
      }
904
      else
905
      {
906
        print OUTFILE "W($MacroInvBlock),";
907
      }
908
    }
909
  }
910
  else
911
  {
912
    print OUTFILE pack($endian, defined $_ ? $_ : $InvBlock)
913
    foreach @{$FromSpeedTbl[0]};
914
  }
915
 
916
  if ($Source)
917
  {
918
    my $index = 512 + $Hdr8bitFromUCS;
919
    for (my $blk = 1; $blk <= $#FromSpeedTbl; $blk++)
920
    {
921
      next unless defined $FromSpeedTbl[$blk];
922
      printf OUTFILE "\n\t/* Block $blk, Array index 0x%.4X */", $index;
923
      $index += 256;
924
      for (my $i = 0, my $br = 0; $i < 256; $i++, $br = $i % 8)
925
      {
926
        print OUTFILE "\n\t" unless $br;
927
        my $code = $FromSpeedTbl[$blk]->[$i];
928
        if (!defined $code)
929
        {
930
          printf OUTFILE "0x%.2X,", $InvCode8bit;
931
        }
932
        else
933
        {
934
          printf OUTFILE "0x%.2X,", $code == $TmpLost ? $LostCode : $code;
935
        }
936
      }
937
    }
938
    print OUTFILE "\n};\n\n#endif /* $GuardFromUCS */\n\n";
939
  }
940
  else
941
  {
942
    for (my $blk = 1; $blk <= $#FromSpeedTbl; $blk++)
943
    {
944
      next unless defined $FromSpeedTbl[$blk];
945
      for (my $i = 0, my $br = 0; $i < 256; $br = ++$i % 8)
946
      {
947
        my $code = $FromSpeedTbl[$blk]->[$i];
948
        if (!defined $code)
949
        {
950
          printf OUTFILE pack 'C', $InvCode8bit;
951
        }
952
        else
953
        {
954
          print OUTFILE $code == $TmpLost ? pack('C', $LostCode)
955
                                          : pack('C', $code);
956
        }
957
      }
958
    }
959
  }
960
}
961
 
962
 
963
# =============================================================================
964
#
965
# Output 16bit Speed-optimized table. Output table's source code if $Source
966
# and table's binary data if !$Source.
967
# 
968
# Parameter 1: 
969
#    "to_ucs"   - Output "to_ucs" table.
970
#    "from_ucs" - Output "from_ucs" table.
971
# Parameter 2:    Not used when sources are output. Output BE binary if 'n' and
972
#                 LE binary if 'v'.
973
#
974
# =============================================================================
975
sub OutputSpeed($;$)
976
{
977
  my $endian = $_[1];
978
  my $tbl;
979
  my ($direction, $optimiz, $e, $bytes);
980
  $optimiz = $Bits == 16 ? " speed-optimized" : "";
981
  $e = $endian ? ($endian eq 'n' ? " Big Endian" : " Little Endian") : "";
982
  if ($_[0] eq "to_ucs")
983
  {
984
    $tbl = \@ToSpeedTbl;
985
    $direction = " $CCSName -> UCS";
986
    $bytes = $ToSpeedBytes;
987
 
988
    if ($Source)
989
    {
990
      print OUTFILE
991
"/*
992
 * 16-bit $CCSName -> UCS speed-optimized table ($ToSpeedBytes bytes).
993
 * $Separator
994
 */
995
#if defined ($GuardToUCS) \\
996
 && !($GuardSize)
997
 
998
static _CONST __uint16_t
999
${VarToUCSSpeed}\[] =
1000
{
1001
";
1002
    }
1003
  }
1004
  elsif ($_[0] eq "from_ucs")
1005
  {
1006
    $tbl = \@FromSpeedTbl;
1007
    $direction = " UCS -> $CCSName";
1008
    $bytes = $FromSpeedBytes;
1009
 
1010
    if ($Source)
1011
    {
1012
      print OUTFILE
1013
"/*
1014
 * 16-bit UCS -> $CCSName speed-optimized table ($FromSpeedBytes bytes).
1015
 * $Separator
1016
 */
1017
 
1018
#if defined ($GuardFromUCS) \\
1019
 && !($GuardSize)
1020
 
1021
static _CONST __uint16_t
1022
${VarFromUCSSpeed}\[] =
1023
{
1024
";
1025
    }
1026
  }
1027
  else
1028
  {
1029
    Err "Internal script error  Output16bitSpeed()\n";
1030
  }
1031
 
1032
  printf "Output%s 16-bit%s%s table (%d bytes).\n",
1033
  $e, $direction, $optimiz, $bytes if $Verbose;
1034
 
1035
  # OUTPUT HEADING BLOCK (ALWAYS 16 BIT)
1036
  if ($Source)
1037
  {
1038
    my $count = 0;
1039
    print OUTFILE "\t/* Heading Block */";
1040
    for (my $i = 0, my $br = 0; $i < 256; $br = ++$i % 8)
1041
    {
1042
      print OUTFILE "\n\t" unless $br;
1043
      if (defined $tbl->[0]->[$i])
1044
      {
1045
        printf OUTFILE "0x%.4X,", $tbl->[0]->[$i];
1046
      }
1047
      else
1048
      {
1049
        print OUTFILE "$MacroInvBlock,";
1050
      }
1051
    }
1052
  }
1053
  else
1054
  {
1055
    print OUTFILE pack($endian, defined $_ ? $_ : $InvBlock)
1056
    foreach @{$tbl->[0]};
1057
  }
1058
 
1059
  # OUTPUT OTHER BLOCKS
1060
  if ($Source)
1061
  {
1062
    my $index = 256;
1063
    for (my $blk = 1; $blk <= $#$tbl; $blk++)
1064
    {
1065
      next unless defined $tbl->[$blk];
1066
      printf OUTFILE "\n\t/* Block $blk, Array index 0x%.4X */", $index;
1067
      $index += 256;
1068
      for (my $i = 0, my $br = 0; $i < 256; $br = ++$i % 8)
1069
      {
1070
        print OUTFILE "\n\t" unless $br;
1071
        my $code = $tbl->[$blk]->[$i];
1072
        print OUTFILE defined $code ?
1073
            ($code == $TmpLost ? $MacroLostCode : sprintf "0x%.4X", $code)
1074
                                     : $MacroInvCode, ",";
1075
      }
1076
    }
1077
  }
1078
  else
1079
  {
1080
    for (my $blk = 1; $blk <= $#$tbl; $blk++)
1081
    {
1082
      next unless defined $tbl->[$blk];
1083
      for (my $i = 0, my $br = 0; $i < 256; $br = ++$i % 8)
1084
      {
1085
        my $code = $tbl->[$blk]->[$i];
1086
        print OUTFILE pack($endian,
1087
          defined $code ? ($code == $TmpLost ? $LostCode : $code) : $InvCode);
1088
      }
1089
    }
1090
  }
1091
 
1092
  if ($Source)
1093
  {
1094
    if ($_[0] eq "to_ucs")
1095
    {
1096
      print OUTFILE
1097
"
1098
};
1099
 
1100
#endif /* $GuardToUCS && !$GuardSize */
1101
 
1102
";
1103
    }
1104
    else
1105
    {
1106
      print OUTFILE
1107
"
1108
};
1109
 
1110
#endif /* $GuardFromUCS && !$GuardSize */
1111
 
1112
";
1113
    }
1114
  }
1115
}
1116
 
1117
# =============================================================================
1118
#
1119
# Output 16bit Size-optimized table. Output table's source code if $Source
1120
# and table's binary data if !$Source.
1121
# 
1122
# Parameter 1: 
1123
#    "to_ucs"   - Output "to_ucs" table.
1124
#    "from_ucs" - Output "from_ucs" table.
1125
# Parameter 2:    Not used when sources are output. Output BE binary if 'n' and
1126
#                 LE binary if 'v'.
1127
#
1128
# =============================================================================
1129
sub OutputSize($;$)
1130
{
1131
  my $endian = $_[1];
1132
  my $tbl;
1133
  my ($direction, $optimiz, $e, $bytes);
1134
  $optimiz = $Bits == 16 ? " size-optimized" : "";
1135
  $e = $endian ? ($endian eq 'n' ? " Big Endian" : " Little Endian") : "";
1136
  if ($_[0] eq "to_ucs")
1137
  {
1138
    $tbl = \@ToSizeTbl;
1139
    $direction = " $CCSName -> UCS";
1140
    $bytes = $ToSizeBytes;
1141
 
1142
    if ($Source)
1143
    {
1144
      print OUTFILE
1145
"/*
1146
 * 16-bit $CCSName -> UCS size-optimized table ($ToSizeBytes bytes).
1147
 * $Separator
1148
 */
1149
#if defined ($GuardToUCS) \\
1150
 && ($GuardSize)
1151
 
1152
static _CONST __uint16_t
1153
${VarToUCSSize}\[] =
1154
{
1155
";
1156
    }
1157
  }
1158
  elsif ($_[0] eq "from_ucs")
1159
  {
1160
    $tbl = \@FromSizeTbl;
1161
    $direction = " UCS -> $CCSName";
1162
    $bytes = $FromSizeBytes;
1163
    if ($Source)
1164
    {
1165
      print OUTFILE
1166
"/*
1167
 * 16-bit UCS -> $CCSName size-optimized table ($FromSizeBytes bytes).
1168
 * $Separator
1169
 */
1170
 
1171
#if defined ($GuardFromUCS) \\
1172
 && ($GuardSize)
1173
 
1174
static _CONST __uint16_t
1175
${VarFromUCSSize}\[] =
1176
{
1177
";
1178
    }
1179
  }
1180
  else
1181
  {
1182
    Err "Internal script error  Output16bitSize()\n";
1183
  }
1184
 
1185
  printf "Output%s 16-bit%s%s table (%d bytes).\n",
1186
  $e, $direction, $optimiz, $bytes if $Verbose;
1187
 
1188
  # OUTPUT FIRST 3 ELEMENTS
1189
  if ($Source)
1190
  {
1191
    printf OUTFILE "\t0x%.4X, /* Ranges number */\n", $tbl->[0];
1192
    printf OUTFILE "\t0x%.4X, /* Unranged codes number */\n", $tbl->[1];
1193
    printf OUTFILE "\t0x%.4X, /* First unranged code index */\n", $tbl->[2];
1194
  }
1195
  else
1196
  {
1197
    printf OUTFILE pack $endian, $tbl->[0];
1198
    printf OUTFILE pack $endian, $tbl->[1];
1199
    printf OUTFILE pack $endian, $tbl->[2];
1200
  }
1201
 
1202
  my $idx = 0;
1203
  # OUTPUT RANGES
1204
  if ($Source)
1205
  {
1206
    print OUTFILE "\t/* Ranges list: first code, last Code, array index. */\n";
1207
    for (my $range = 0; $range <= $#{$tbl->[3]}; $range++)
1208
    {
1209
      printf OUTFILE "\t/* Array index: 0x%.4X */ 0x%.4X, 0x%.4X, 0x%.4X,\n",
1210
             $idx += 3,
1211
             $tbl->[3]->[$range]->[0],
1212
             $tbl->[3]->[$range]->[1],
1213
             $tbl->[3]->[$range]->[2];
1214
    }
1215
  }
1216
  else
1217
  {
1218
    for (my $range = 0; $range <= $#{$tbl->[3]}; $range++)
1219
    {
1220
      print OUTFILE pack($endian, $tbl->[3]->[$range]->[0]),
1221
                    pack($endian, $tbl->[3]->[$range]->[1]),
1222
                    pack($endian, $tbl->[3]->[$range]->[2]);
1223
    }
1224
  }
1225
  $idx += 3;
1226
 
1227
  # OUTPUT RANGES CONTENT
1228
  if ($Source)
1229
  {
1230
    print OUTFILE "\t/* Ranges content */";
1231
    for (my $range = 0; $range <= $#{$tbl->[3]}; $range++)
1232
    {
1233
      printf OUTFILE "\n\t/* Range 0x%.4X - 0x%.4X, array index: 0x%.4X */",
1234
             $tbl->[3]->[$range]->[0], $tbl->[3]->[$range]->[1], $idx;
1235
             $idx += $tbl->[3]->[$range]->[1] - $tbl->[3]->[$range]->[0] + 1;
1236
      for (my $elt = 0, my $br = 0;
1237
           $elt <= $#{$tbl->[4]->[$range]};
1238
           $br = ++$elt % 8)
1239
      {
1240
        print OUTFILE "\n\t" unless $br;
1241
        if (defined $tbl->[4]->[$range]->[$elt])
1242
        {
1243
          if ($tbl->[4]->[$range]->[$elt] != $TmpLost)
1244
          {
1245
            printf OUTFILE "0x%.4X,", $tbl->[4]->[$range]->[$elt];
1246
          }
1247
          else
1248
          {
1249
            print OUTFILE "$MacroLostCode,";
1250
          }
1251
        }
1252
        else
1253
        {
1254
          print OUTFILE "$MacroInvCode,";
1255
        }
1256
      }
1257
    }
1258
  }
1259
  else
1260
  {
1261
    for (my $range = 0; $range <= $#{$tbl->[3]}; $range++)
1262
    {
1263
      for (my $elt = 0; $elt <= $#{$tbl->[4]->[$range]}; $elt++)
1264
      {
1265
        if (defined $tbl->[4]->[$range]->[$elt])
1266
        {
1267
          if ($tbl->[4]->[$range]->[$elt] != $TmpLost)
1268
          {
1269
            print OUTFILE pack $endian, $tbl->[4]->[$range]->[$elt];
1270
          }
1271
          else
1272
          {
1273
            print OUTFILE pack $endian, $LostCode;
1274
          }
1275
        }
1276
        else
1277
        {
1278
          print OUTFILE pack $endian, $InvCode;
1279
        }
1280
      }
1281
    }
1282
  }
1283
 
1284
  # OUTPUT UNRANGED CODES
1285
  if ($Source)
1286
  {
1287
    printf OUTFILE "\n\t/* Unranged codes (%d codes) */", $#{$tbl->[4]} + 1;
1288
    for (my $i = 0; $i <= $#{$tbl->[5]}; $i++)
1289
    {
1290
      printf OUTFILE "\n\t/* Array index: 0x%.4X */ 0x%.4X,0x%.4X,",
1291
             $idx, $tbl->[5]->[$i]->[0], $tbl->[5]->[$i]->[1];
1292
    }
1293
  }
1294
  else
1295
  {
1296
    for (my $i = 0; $i <= $#{$tbl->[5]}; $i++)
1297
    {
1298
      print OUTFILE pack($endian, $tbl->[5]->[$i]->[0]),
1299
                    pack($endian, $tbl->[5]->[$i]->[1]);
1300
    }
1301
  }
1302
 
1303
  if ($Source)
1304
  {
1305
    if ($_[0] eq "to_ucs")
1306
    {
1307
      print OUTFILE
1308
"
1309
};
1310
 
1311
#endif /* $GuardToUCS && $GuardSize */
1312
 
1313
";
1314
    }
1315
    else
1316
    {
1317
      print OUTFILE
1318
"
1319
};
1320
 
1321
#endif /* $GuardFromUCS && $GuardSize */
1322
 
1323
";
1324
    }
1325
  }
1326
}
1327
 
1328
 
1329
# =============================================================================
1330
#
1331
# Parse command line options
1332
#
1333
# =============================================================================
1334
sub ProcessOptions()
1335
{
1336
  my $help_opt    = 'h'; # Print help option
1337
  my $input_opt   = 'i'; # Input file name option
1338
  my $output_opt  = 'o'; # Output file name option
1339
  my $source_opt  = 'S'; # Generate C source file option
1340
  my $enc_opt     = 'N'; # Encoding name
1341
  my $plane_opt   = 'p'; # Plane number
1342
  my $verbose_opt = 'v'; # Verbose output
1343
  my $ccscol_opt  = 'x'; # Encoding's column number
1344
  my $ucscol_opt  = 'y'; # UCS column number
1345
  my $nosize_opt  = 'l'; # Don't generate size-optimized tables
1346
  my $nospeed_opt = 'b'; # Don't generate speed-optimized tables
1347
  my $nobe_opt    = 'B'; # Don't generate big-endian tables
1348
  my $nole_opt    = 'L'; # Don't generate big-endian tables
1349
  my $noto_opt    = 't'; # Don't generate "to_ucs" table
1350
  my $nofrom_opt  = 'f'; # Don't generate "from_ucs" table
1351
 
1352
  my %args;              # Command line arguments found by getopts()
1353
 
1354
  my $getopts_string =
1355
     "$help_opt$source_opt$enc_opt:$verbose_opt$input_opt:$output_opt:$plane_opt:"
1356
   . "$nosize_opt$nospeed_opt$nobe_opt$nole_opt$noto_opt$nofrom_opt$ccscol_opt:"
1357
   . "$ucscol_opt:";
1358
 
1359
  getopts($getopts_string, \%args) || Err "getopts() failed: $!.\n", 1;
1360
 
1361
  # Print usage rules and exit.
1362
  if ($args{$help_opt})
1363
  {
1364
    print<<END
1365
Usage:
1366
     -$help_opt - this help message;
1367
     -$input_opt - input file name (required);
1368
     -$output_opt - output file name;
1369
     -$enc_opt - CCS or encoding name;
1370
     -$plane_opt - plane number (high 16 bits) to use (in hex);
1371
     -$source_opt - generate C source file;
1372
     -$nospeed_opt - don't generate speed-optimized tables (binary files only);
1373
     -$nosize_opt - don't generate size-optimized tables (binary files only);
1374
     -$nobe_opt - don't generate Big Endian tables (binary files only);
1375
     -$nole_opt - don't generate Little Endian tables (binary files only);
1376
     -$noto_opt - don't generate "to_ucs" table;
1377
     -$nofrom_opt - don't generate "from_ucs" table;
1378
     -$ccscol_opt - encoding's column number;
1379
     -$ucscol_opt - UCS column number;
1380
     -$verbose_opt - verbose output.
1381
 
1382
If output file name isn't specified, <infile>.c (for sources) or
1383
<infile>.cct (for binaries) is assumed.
1384
If encoding name isn't specified <infile> is assumed.
1385
<infile> is normalized (small letters, "-" are substituted by "_") input file
1386
name base (no extension). For example, for Koi8-r.txt input file, <infile>
1387
is koi8_r.
1388
END
1389
;
1390
    exit 0;
1391
  }
1392
 
1393
  $Verbose   = $args{$verbose_opt};
1394
  $Source    = $args{$source_opt};
1395
  $NoSpeed   = $args{$nospeed_opt};
1396
  $NoSize    = $args{$nosize_opt};
1397
  $NoBE      = $args{$nobe_opt};
1398
  $NoLE      = $args{$nole_opt};
1399
  $NoFrom    = $args{$nofrom_opt};
1400
  $NoTo      = $args{$noto_opt};
1401
  $CCSCol    = $args{$ccscol_opt};
1402
  $UCSCol    = $args{$ucscol_opt};
1403
  $Plane     = $args{$plane_opt};
1404
  $InFile    = $args{$input_opt};
1405
  $OutFile   = $args{$output_opt};
1406
  $CCSName   = $args{$enc_opt};
1407
 
1408
  Err "Error: input file isn't defined. Use -$help_opt for help.\n", 1
1409
  unless $InFile;
1410
 
1411
  unless ($OutFile)
1412
  {
1413
    # Construct output file name
1414
    $OutFile = $InFile;
1415
    $OutFile =~ s/(.*\/)*([0-9a-zA-Z-_]*)(\..*)$/\L$2/;
1416
    $OutFile =~ tr/-/_/;
1417
    if ($Source)
1418
    {
1419
      $OutFile = "$OutFile.c";
1420
    }
1421
    else
1422
    {
1423
      $OutFile = "$OutFile.cct"
1424
    }
1425
  }
1426
 
1427
  unless ($CCSName)
1428
  {
1429
    # Construct CCS name
1430
    $CCSName = $InFile;
1431
    $CCSName =~ s/(.*\/)*([0-9a-zA-Z-_]*)(\..*)$/\L$2/;
1432
    $CCSName =~ tr/-/_/;
1433
  }
1434
 
1435
  Err "-$nosize_opt option can't be used with -$nospeed_opt option "
1436
    . "simultaniously.\n", 1 if $NoSpeed && $NoSize;
1437
 
1438
  Err "-$nobe_opt option can't be used with -$nole_opt option "
1439
    . "simultaniously.\n", 1 if $NoBE && $NoLE;
1440
 
1441
  Err "-$noto_opt option can't be used with -$nofrom_opt option"
1442
    . "simultaniously.\n", 1 if $NoTo && $NoFrom;
1443
 
1444
  Err "-$nosize_opt, -$nospeed_opt, -$nobe_opt -$nole_opt "
1445
    . "-$noto_opt and -$nofrom_opt "
1446
    . "options can't be used with -$source_opt option.\n"
1447
    . "Source code always contains both speed- and size-optimized "
1448
    . "tables in System Endian. Use -$help_opt for help.\n", 1
1449
  if $Source and $NoSpeed || $NoSize || $NoBE || $NoLE || $NoTo || $NoFrom;
1450
 
1451
  if (!$CCSCol && !$UCSCol)
1452
  {
1453
    $CCSCol = 0;
1454
    $UCSCol = 1;
1455
  }
1456
  elsif ($CCSCol && $UCSCol)
1457
  {
1458
    Err "Column number should be >= 0\n", 1 if ($CCSCol <= 0 or $UCSCol <= 0);
1459
    $CCSCol -= 1;
1460
    $UCSCol -= 1;
1461
  }
1462
  else
1463
  {
1464
    Err "Please, define both CCS and UCS column numbers\n", 1;
1465
  }
1466
 
1467
  if ($Verbose)
1468
  {
1469
    print  "Use $InFile file for input.\n",
1470
           "Use $OutFile file for output.\n",
1471
           "Use $CCSName as CCS name.\n";
1472
    print  "Generate C source file.\n"                if $Source;
1473
    print  "Generate binary file.\n"                  if !$Source;
1474
    printf "Use plane N 0x%.4X.\n", hex $Plane if defined $Plane;
1475
    printf "Use column N $CCSCol for $CCSName.\n";
1476
    printf "Use column N $UCSCol for UCS.\n";
1477
    print  "Don't generate size-optimized tables.\n"  if $NoSize;
1478
    print  "Don't generate speed-optimized tables.\n" if $NoSpeed;
1479
    print  "Don't generate big-endian tables.\n"      if $NoBE;
1480
    print  "Don't generate little-endian tables.\n"   if $NoLE;
1481
    print  "Don't generate \"to_ucs\" table.\n"       if $NoTo;
1482
    print  "Don't generate \"from_ucs\" table.\n"     if $NoFrom;
1483
  }
1484
 
1485
  return;
1486
}
1487
 
1488
 
1489
# =============================================================================
1490
#
1491
# Print error message, close all and exit
1492
#
1493
# Parameter 1: error message
1494
# Parameter 2: don't delete output file if > 1
1495
#
1496
# =============================================================================
1497
sub Err($;$)
1498
{
1499
  print STDERR "$_[0]";
1500
  close INFILE;
1501
  close OUTFILE;
1502
  unlink $OutFile unless $_[1];
1503
 
1504
  exit 1;
1505
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.