home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Programming / ICU / src / icu / source / tools / makeconv / makeconv.c next >
Encoding:
C/C++ Source or Header  |  1999-11-08  |  23.3 KB  |  755 lines

  1. /*
  2.  ********************************************************************************
  3.  *                                                                              *
  4.  * COPYRIGHT:                                                                   *
  5.  *   (C) Copyright International Business Machines Corporation, 1998            *
  6.  *   Licensed Material - Program-Property of IBM - All Rights Reserved.         *
  7.  *   US Government Users Restricted Rights - Use, duplication, or disclosure    *
  8.  *   restricted by GSA ADP Schedule Contract with IBM Corp.                     *
  9.  *                                                                              *
  10.  ********************************************************************************
  11.  *
  12.  *
  13.  *  makeconv.c:
  14.  *  tool creating a binary (compressed) representation of the conversion mapping
  15.  *  table (IBM NLTC ucmap format).
  16.  */
  17.    
  18. #include <stdio.h>
  19. #include "ucmp16.h"
  20. #include "ucmp8.h"
  21. #include "ucnv_io.h"
  22. #include "ucnv_bld.h"
  23. #include "ucnv_err.h"
  24. #include "ucnv_imp.h"
  25. #include "cstring.h"
  26. #include "cmemory.h"
  27. #include "filestrm.h"
  28.  
  29.  
  30. /*Reads the header of the table file and fills in basic knowledge about the converter
  31.  *in "converter"
  32.  */
  33. static void readHeaderFromFile(UConverter* myConverter, FileStream* convFile, UErrorCode* err);
  34.  
  35. /*Reads the rest of the file, and fills up the shared objects if necessary*/
  36. static void loadMBCSTableFromFile(FileStream* convFile, UConverter* converter, UErrorCode* err);
  37.  
  38. /*Reads the rest of the file, and fills up the shared objects if necessary*/
  39. static void loadEBCDIC_STATEFULTableFromFile(FileStream* convFile, UConverter* converter, UErrorCode* err);
  40.  
  41. /*Reads the rest of the file, and fills up the shared objects if necessary*/
  42. static void loadSBCSTableFromFile(FileStream* convFile, UConverter* converter, UErrorCode* err);
  43.  
  44. /*Reads the rest of the file, and fills up the shared objects if necessary*/
  45. static void loadDBCSTableFromFile(FileStream* convFile, UConverter* converter, UErrorCode* err);
  46.  
  47. /* creates a UConverterSharedData from a mapping file, fills in necessary links to it the 
  48.  * appropriate function pointers
  49.  * if the data tables are already in memory
  50.  */
  51. static UConverterSharedData* createConverterFromTableFile(const char* realName, UErrorCode* err);
  52.  
  53.  
  54. /*writes a CompactShortArray to a file*/
  55. static void writeCompactShortArrayToFile(FileStream* outfile, const CompactShortArray* myArray);
  56.  
  57. /*writes a CompactByteArray to a file*/
  58. static void writeCompactByteArrayToFile(FileStream* outfile, const CompactByteArray* myArray);
  59.  
  60. /*writes a binary to a file*/
  61. static void writeUConverterSharedDataToFile(const char* filename, 
  62.                           UConverterSharedData* mySharedData, 
  63.                           UErrorCode* err);
  64.  
  65. static UConverterPlatform getPlatformFromName(char* name);
  66. static int32_t getCodepageNumberFromName(char* name);
  67.  
  68.  
  69. static const char NLTC_SEPARATORS[9] = { '\r', '\n', '\t', ' ', '<', '>' ,'"' , 'U', '\0' };
  70. static const char PLAIN_SEPARATORS[9] = { '\r', '\n', '\t', ' ', '<', '>' ,'"' ,  '\0' };
  71. static const char CODEPOINT_SEPARATORS[8] = {  '\r', '>', '\\', 'x', '\n', ' ', '\t', '\0' };
  72. static const char UNICODE_CODEPOINT_SEPARATORS[6] = {  '<', '>', 'U', ' ', '\t', '\0' };
  73.  
  74.  
  75.  
  76. int main(int argc, char** argv)
  77. {
  78.   UConverterSharedData* mySharedData = NULL; 
  79.   UErrorCode err = U_ZERO_ERROR;
  80.   char outFileName[UCNV_MAX_FULL_FILE_NAME_LENGTH];
  81.   char* dot = NULL;
  82.  
  83.   
  84.   if (argc == 1)
  85.     {
  86.       /*prints out a usage message*/
  87.       printf("usage: %s file1 file2 file3 ...\n", argv[0]);
  88.     }
  89.   while (--argc)
  90.     {
  91.       /*removes the extension if any is found*/
  92.       icu_strcpy(outFileName, argv[argc]);
  93.       if (dot = icu_strchr(outFileName +   icu_strlen(outFileName) - 4, '.')) 
  94.     {
  95.       *dot = '\0';
  96.     }
  97.       /*Adds the target extension*/
  98.       icu_strcat(outFileName, CONVERTER_FILE_EXTENSION);
  99.       
  100.       mySharedData = createConverterFromTableFile(argv[argc], &err);
  101.       if (U_FAILURE(err) || (mySharedData == NULL))
  102.     {
  103.       /* in an error is found, print out a error msg and keep going*/
  104.       printf("Error creating \"%s\" file for \"%s\" (error code %d)\n", outFileName, argv[argc], err);
  105.       err = U_ZERO_ERROR;
  106.     }
  107.       else
  108.     {
  109.       writeUConverterSharedDataToFile(outFileName, mySharedData, &err);
  110.       deleteSharedConverterData(mySharedData);
  111.       puts(outFileName);
  112.     }
  113.       
  114.     }
  115.  
  116.   return err;
  117.       
  118. }
  119.  
  120.  
  121. /*Streams out to a file a compact short array*/
  122. void writeCompactShortArrayToFile(FileStream* outfile, const CompactShortArray* myArray)
  123. {
  124.   int32_t i = 0;
  125.   const int16_t* myShortArray = NULL;
  126.   const uint16_t* myIndexArray = NULL;
  127.   int32_t myValuesCount = 0;
  128.   int32_t myIndexCount = ucmp16_getkUnicodeCount() / ucmp16_getkBlockCount();
  129.   int32_t myBlockShift = myArray->kBlockShift;
  130.   
  131.   /*streams out the length of the arrays to come*/
  132.   myValuesCount = myArray->fCount;
  133.   T_FileStream_write(outfile, &myValuesCount, sizeof(int32_t));
  134.   T_FileStream_write(outfile, &myIndexCount, sizeof(int32_t));
  135.   T_FileStream_write(outfile, &myBlockShift, sizeof(int32_t));
  136.  
  137.   /*Gets pointers to the internal arrays*/
  138.   myShortArray = myArray->fArray;
  139.   myIndexArray = myArray->fIndex;
  140.  
  141.   /*streams out the 2 arrays*/
  142.   T_FileStream_write(outfile, myShortArray, myValuesCount*sizeof(int16_t));
  143.   T_FileStream_write(outfile, myIndexArray, myIndexCount*sizeof(uint16_t));
  144.   
  145.   
  146.   return ;
  147. }
  148.  
  149. void writeCompactByteArrayToFile(FileStream* outfile, const CompactByteArray* myArray)
  150. {
  151.   int32_t i = 0;
  152.   const int8_t* myByteArray = NULL;
  153.   const uint16_t* myIndexArray = NULL;
  154.   int32_t myValuesCount = 0;
  155.   int32_t myIndexCount = ucmp8_getkUnicodeCount() / ucmp8_getkBlockCount();
  156.   
  157.   /*streams out the length of the arrays to come*/
  158.   myValuesCount = ucmp8_getCount(myArray);
  159.   T_FileStream_write(outfile, &myValuesCount, sizeof(int32_t));
  160.   T_FileStream_write(outfile, &myIndexCount, sizeof(int32_t));
  161.  
  162.   /*Gets pointers to the internal arrays*/
  163.   myByteArray =  myArray->fArray;
  164.   myIndexArray =  myArray->fIndex;
  165.  
  166.   /*streams out the 2 arrays*/
  167.   T_FileStream_write(outfile, myByteArray, myValuesCount*sizeof(int8_t));
  168.   T_FileStream_write(outfile, myIndexArray, myIndexCount*sizeof(uint16_t));
  169.   
  170.   return ;
  171. }
  172.  
  173. void writeUConverterSharedDataToFile(const char* filename,
  174.                      UConverterSharedData* mySharedData,
  175.                      UErrorCode* err)
  176. {
  177.   int32_t i = 0;
  178.   const int8_t* myByteArray = NULL;
  179.   const uint16_t* myIndexArray = NULL;
  180.   int32_t myValuesCount = 0;
  181.   int32_t myIndexCount = 0;
  182.   int32_t myCheck = UCNV_FILE_CHECK_MARKER;
  183.   FileStream* outfile = NULL;
  184.   UConverterTable* myTableAlias = NULL;
  185.   
  186.   if (U_FAILURE(*err)) return;
  187.   
  188.   outfile = T_FileStream_open(filename, "wb");
  189.   if (outfile == NULL) 
  190.     {
  191.       *err = U_FILE_ACCESS_ERROR;
  192.       return;
  193.     }
  194.  
  195.   /*Writes a Sentinel value*/
  196.   T_FileStream_write(outfile, &myCheck, sizeof(int32_t));
  197.   T_FileStream_write(outfile, UCNV_COPYRIGHT_STRING, UCNV_COPYRIGHT_STRING_LENGTH);
  198.   
  199.   /*Writes NULL in places where there is a pointer in order
  200.    *to enable bitwise equivalence of binary files
  201.    */
  202.   myTableAlias = mySharedData->table;
  203.   mySharedData->table = NULL;
  204.   T_FileStream_write(outfile, mySharedData, sizeof(UConverterSharedData));
  205.   mySharedData->table = myTableAlias;
  206.   
  207.   switch (mySharedData->conversionType)
  208.     {
  209.     case UCNV_SBCS :
  210.       {
  211.     T_FileStream_write(outfile, mySharedData->table->sbcs.toUnicode, 256*sizeof(UChar));
  212.     writeCompactByteArrayToFile(outfile, mySharedData->table->sbcs.fromUnicode);
  213.       }break;
  214.     case UCNV_DBCS : case UCNV_EBCDIC_STATEFUL:
  215.       {
  216.     writeCompactShortArrayToFile(outfile, mySharedData->table->dbcs.toUnicode);
  217.     writeCompactShortArrayToFile(outfile, mySharedData->table->dbcs.fromUnicode);
  218.       }break;
  219.     case UCNV_MBCS : 
  220.       {
  221.     T_FileStream_write(outfile, mySharedData->table->mbcs.starters, 256*sizeof(bool_t));
  222.     writeCompactShortArrayToFile(outfile, mySharedData->table->mbcs.toUnicode);
  223.     writeCompactShortArrayToFile(outfile, mySharedData->table->mbcs.fromUnicode);
  224.       }break;
  225.       
  226.     };
  227.  
  228.   if (T_FileStream_error(outfile)) 
  229.     {
  230.       *err = U_FILE_ACCESS_ERROR;
  231.     }
  232.   T_FileStream_close(outfile);
  233. }
  234.  
  235.  
  236. #ifndef __amigaos__
  237. void copyPlatformString(char* platformString, UConverterPlatform pltfrm)
  238. {
  239.   switch (pltfrm)
  240.     {
  241.     case UCNV_IBM: {icu_strcpy(platformString, "ibm");break;}
  242.     default: {icu_strcpy(platformString, "");break;}
  243.     };
  244.  
  245.   return;
  246. }
  247. #endif
  248.  
  249. UConverterPlatform getPlatformFromName(char* name)
  250. {
  251.   char myPlatform[10];
  252.   char mySeparators[2] = { '-', '\0' };
  253.   
  254.   getToken(myPlatform, name, mySeparators);
  255.   strtoupper(myPlatform);
  256.  
  257.   if (icu_strcmp(myPlatform, "IBM") == 0) return UCNV_IBM;
  258.   else return UCNV_UNKNOWN;
  259. }
  260.  
  261. int32_t getCodepageNumberFromName(char* name)
  262. {
  263.   char myNumber[10];
  264.   char mySeparators[2] = { '-', '\0' };
  265.   char* line = NULL;
  266.  
  267.   line = getToken(myNumber, name, mySeparators);
  268.   getToken(myNumber, line, mySeparators);
  269.  
  270.   return T_CString_stringToInteger(myNumber, 10);
  271. }
  272.  
  273. /*Reads the header of the table file and fills in basic knowledge about the converter in "converter"*/
  274. void readHeaderFromFile(UConverter* myConverter,
  275.             FileStream* convFile,
  276.             UErrorCode* err)
  277. {
  278.   char storeLine[UCNV_MAX_LINE_TEXT];
  279.   char key[15];
  280.   char value[30];
  281.   char* line = storeLine;
  282.   bool_t endOfHeader = FALSE;
  283.   bool_t hasConvClass = FALSE;
  284.   bool_t hasSubChar = FALSE;
  285.   char codepointByte[3];
  286.  
  287.   if (U_FAILURE(*err)) return;
  288.   while (!endOfHeader && T_FileStream_readLine(convFile, line, UCNV_MAX_LINE_TEXT)) 
  289.     {
  290.       removeComments(line);
  291.       
  292.       /*skip blank lines*/
  293.       if (*(line + nextTokenOffset(line, NLTC_SEPARATORS)) != '\0') 
  294.     {      
  295.       /*gets the key that will qualify adjacent information*/
  296.       /*gets the adjacent value*/
  297.       line = getToken(key, line, NLTC_SEPARATORS);
  298.       if (icu_strcmp(key, "uconv_class"))
  299.         line = getToken(value, line, NLTC_SEPARATORS);          
  300.       else
  301.         line = getToken(value, line, PLAIN_SEPARATORS);          
  302.  
  303.       
  304.       /*
  305.          Figure out what key was found and fills in myConverter with the appropriate values
  306.          a switch statement for strings...
  307.          */
  308.       
  309.       /*Checks for end of header marker*/
  310.       if (icu_strcmp(key, "CHARMAP") == 0) endOfHeader = TRUE;
  311.  
  312.       /*get name tag*/
  313.       else if (icu_strcmp(key, "code_set_name") == 0) 
  314.         {
  315.           icu_strcpy(myConverter->sharedData->name, value);
  316.           myConverter->sharedData->platform = getPlatformFromName(value);
  317.           myConverter->sharedData->codepage = getCodepageNumberFromName(value);
  318.           
  319.         }
  320.  
  321.       /*get conversion type*/
  322.       else if (icu_strcmp(key, "uconv_class") == 0)
  323.         {
  324.  
  325.           hasConvClass = TRUE;
  326.           if (icu_strcmp(value, "DBCS") == 0) 
  327.         {
  328.           myConverter->sharedData->conversionType = UCNV_DBCS;
  329.         }
  330.           else if (icu_strcmp(value, "SBCS") == 0) 
  331.         {
  332.           myConverter->sharedData->conversionType = UCNV_SBCS;
  333.         }
  334.           else if (icu_strcmp(value, "MBCS") == 0) 
  335.         {
  336.           myConverter->sharedData->conversionType = UCNV_MBCS;
  337.         }
  338.           else if (icu_strcmp(value, "EBCDIC_STATEFUL") == 0) 
  339.         {
  340.           myConverter->sharedData->conversionType = UCNV_EBCDIC_STATEFUL;
  341.         }
  342.           else 
  343.         {
  344.           *err = U_INVALID_TABLE_FORMAT;
  345.           return;
  346.         }
  347.  
  348.         }
  349.       
  350.       /*get mb_cur_max amount*/
  351.       else if (icu_strcmp(key, "mb_cur_max") == 0) 
  352.         myConverter->sharedData->maxBytesPerChar = (int8_t)T_CString_stringToInteger(value, 10);
  353.       
  354.       /*get mb_cur_max amount*/
  355.       else if (icu_strcmp(key, "mb_cur_min") == 0)
  356.         myConverter->sharedData->minBytesPerChar = (int8_t)T_CString_stringToInteger(value, 10);
  357.      
  358.       
  359.       else if (icu_strcmp(key, "subchar") == 0) 
  360.         {
  361.           hasSubChar = TRUE;
  362.           myConverter->sharedData->defaultConverterValues.subCharLen = 0;
  363.           
  364.           /*readies value for tokenizing, we want to break each byte of the codepoint into single tokens*/
  365.           line = value;
  366.           while (*line)
  367.         {
  368.           line = getToken(codepointByte, line, CODEPOINT_SEPARATORS);
  369.           myConverter->sharedData->defaultConverterValues.subChar[(myConverter->sharedData->defaultConverterValues.subCharLen++)] =
  370.             (unsigned char)T_CString_stringToInteger(codepointByte, 16);
  371.         }
  372.           
  373.           /*Initializes data from the mutable area to that found in the immutable area*/
  374.           
  375.         }      
  376.     }
  377.       /*make line point to the beginning of the storage buffer again*/
  378.       line = storeLine;
  379.     }
  380.  
  381.   if (!hasSubChar)   {myConverter->subCharLen = myConverter->sharedData->defaultConverterValues.subCharLen = 0;}
  382.   else 
  383.     {
  384.       myConverter->subCharLen = myConverter->sharedData->defaultConverterValues.subCharLen;
  385.       icu_memcpy(myConverter->subChar,
  386.          myConverter->sharedData->defaultConverterValues.subChar, 
  387.          myConverter->subCharLen);
  388.     }
  389.   
  390.   
  391.   if (!endOfHeader || !hasConvClass)     *err = U_INVALID_TABLE_FORMAT;
  392.   return;
  393. }
  394.   
  395.   
  396.  
  397. void loadSBCSTableFromFile(FileStream* convFile, UConverter* myConverter, UErrorCode* err)
  398. {
  399.   char storageLine[UCNV_MAX_LINE_TEXT];
  400.   char* line = NULL;
  401.   UConverterTable* myUConverterTable = NULL;
  402.   UChar unicodeValue = 0xFFFF;
  403.   int32_t sbcsCodepageValue = 0;
  404.   char codepointBytes[5];
  405.   unsigned char replacementChar = '\0';
  406.   int32_t i = 0;
  407.   CompactByteArray* myFromUnicode = NULL;
  408.  
  409.   
  410.   if (U_FAILURE(*err)) return;
  411.   replacementChar = myConverter->subChar[0];
  412.   myUConverterTable = (UConverterTable*)icu_malloc(sizeof(UConverterSBCSTable));
  413.   if (myUConverterTable == NULL) 
  414.     {
  415.       *err = U_MEMORY_ALLOCATION_ERROR;
  416.       return;
  417.     }
  418.  
  419.   /*create a compact array with replacement chars as default chars*/
  420.   myFromUnicode = ucmp8_open(0);  
  421.   if (myFromUnicode == NULL) 
  422.     {
  423.       icu_free(myUConverterTable);
  424.       *err = U_MEMORY_ALLOCATION_ERROR;
  425.       return;
  426.     } 
  427.   
  428.   /*fills in the toUnicode array with the Unicode Replacement Char*/
  429.   for (i=0;i<255;i++) myUConverterTable->sbcs.toUnicode[i] = unicodeValue;
  430.  
  431.   
  432.   while (T_FileStream_readLine(convFile, storageLine, UCNV_MAX_LINE_TEXT))
  433.     {
  434.       /*removes comments*/
  435.       removeComments(storageLine);
  436.  
  437.       /*set alias pointer back to the beginning of the buffer*/
  438.       line = storageLine;
  439.       
  440.       /*skips empty lines*/
  441.       if (line[nextTokenOffset(line, NLTC_SEPARATORS)] != '\0')
  442.     {
  443.       line = getToken(codepointBytes, line, UNICODE_CODEPOINT_SEPARATORS);
  444.       if (!icu_strcmp(codepointBytes, "END")) break;
  445.       unicodeValue = (UChar)T_CString_stringToInteger(codepointBytes, 16);
  446.       line = getToken(codepointBytes, line, CODEPOINT_SEPARATORS);
  447.       sbcsCodepageValue = T_CString_stringToInteger(codepointBytes, 16);
  448.       /*Store in the toUnicode array*/
  449.       myUConverterTable->sbcs.toUnicode[sbcsCodepageValue] = unicodeValue;
  450.       /*Store in the fromUnicode compact array*/
  451.       ucmp8_set(myFromUnicode, unicodeValue, (int8_t)sbcsCodepageValue);
  452.     }
  453.     }
  454.   ucmp8_compact(myFromUnicode, 1);
  455.   myUConverterTable->sbcs.fromUnicode = myFromUnicode;
  456.   /*Initially sets the referenceCounter to 1*/
  457.   myConverter->sharedData->referenceCounter = 1;
  458.   myConverter->sharedData->table = myUConverterTable;
  459.   
  460.   return;
  461. }
  462.  
  463. void loadMBCSTableFromFile(FileStream* convFile, UConverter* myConverter, UErrorCode* err)
  464. {
  465.   char storageLine[UCNV_MAX_LINE_TEXT];
  466.   char* line = NULL;
  467.   UConverterTable* myUConverterTable = NULL;
  468.   UChar unicodeValue = 0xFFFF;
  469.   int32_t mbcsCodepageValue = '\0';
  470.   char codepointBytes[6];
  471.   int32_t replacementChar = 0x0000;
  472.   uint16_t i = 0;
  473.   CompactShortArray* myFromUnicode = NULL;
  474.   CompactShortArray* myToUnicode = NULL;
  475.  
  476.   /*Evaluates the replacement codepoint*/
  477.   replacementChar = 0xFFFF;
  478.  
  479.   myUConverterTable = (UConverterTable*)icu_malloc(sizeof(UConverterMBCSTable));
  480.   if (myUConverterTable == NULL) 
  481.     {
  482.       *err = U_MEMORY_ALLOCATION_ERROR;
  483.       return;
  484.     }
  485.  
  486.   /*Initializes the mbcs.starters to FALSE*/
  487.  
  488.   for (i=0; i<=255; i++) 
  489.     {
  490.       myUConverterTable->mbcs.starters[i] = FALSE;
  491.     } 
  492.  
  493.   myFromUnicode = ucmp16_open((uint16_t)replacementChar);
  494.   myToUnicode = ucmp16_open((int16_t)0xFFFD);  
  495.   
  496.   while (T_FileStream_readLine(convFile, storageLine, UCNV_MAX_LINE_TEXT))
  497.     {
  498.       removeComments(storageLine);
  499.       line = storageLine;
  500.       if (line[nextTokenOffset(line, NLTC_SEPARATORS)] != '\0')
  501.     {
  502.       line = getToken(codepointBytes, line, UNICODE_CODEPOINT_SEPARATORS);
  503.       if (!icu_strcmp(codepointBytes, "END")) break;
  504.       unicodeValue = (UChar)T_CString_stringToInteger(codepointBytes, 16);
  505.       line = getToken(codepointBytes, line, CODEPOINT_SEPARATORS);
  506.       if (line[nextTokenOffset(line, CODEPOINT_SEPARATORS)] != '\0') 
  507.         {
  508.           /*When there is a second byte*/
  509.           myUConverterTable->mbcs.starters[T_CString_stringToInteger(codepointBytes, 16)] = TRUE;
  510.           line = getToken(codepointBytes+2, line, CODEPOINT_SEPARATORS);
  511.         }
  512.  
  513.       mbcsCodepageValue = T_CString_stringToInteger(codepointBytes, 16);
  514.       
  515.       ucmp16_set(myToUnicode, (int16_t)mbcsCodepageValue, unicodeValue);
  516.       ucmp16_set(myFromUnicode, unicodeValue, (int16_t)mbcsCodepageValue);
  517.     }
  518.     }
  519.  
  520.   ucmp16_compact(myFromUnicode);
  521.   ucmp16_compact(myToUnicode);
  522.   myUConverterTable->mbcs.fromUnicode = myFromUnicode;
  523.   myUConverterTable->mbcs.toUnicode = myToUnicode;
  524.   myConverter->sharedData->referenceCounter = 1;
  525.   myConverter->sharedData->table = myUConverterTable;
  526.  
  527.   /* if the default subCharLen is > 1 we need to insert it in the data structure
  528.      so that we know how to transition */
  529.   if (myConverter->subCharLen > 1)
  530.     {
  531.       myConverter->sharedData->table->mbcs.starters[myConverter->subChar[0]] = TRUE;
  532.     }
  533.   return;
  534. }
  535.  
  536. void loadEBCDIC_STATEFULTableFromFile(FileStream* convFile, UConverter* myConverter, UErrorCode* err)
  537. {
  538.   char storageLine[UCNV_MAX_LINE_TEXT];
  539.   char* line = NULL;
  540.   UConverterTable* myUConverterTable = NULL;
  541.   UChar unicodeValue = 0xFFFF;
  542.   int32_t mbcsCodepageValue = '\0';
  543.   char codepointBytes[6];
  544.   int32_t replacementChar = 0x0000;
  545.   uint8_t i = 0;
  546.   CompactShortArray* myFromUnicode = NULL;
  547.   CompactShortArray* myToUnicode = NULL;
  548.  
  549.   /*Evaluates the replacement codepoint*/
  550.   replacementChar = 0xFFFF;
  551.  
  552.   myUConverterTable = (UConverterTable*)icu_malloc(sizeof(UConverterMBCSTable));
  553.   if (myUConverterTable == NULL) 
  554.     {
  555.       *err = U_MEMORY_ALLOCATION_ERROR;
  556.       return;
  557.     }
  558.   
  559.   
  560.   myFromUnicode = ucmp16_open((uint16_t)replacementChar);
  561.   myToUnicode = ucmp16_open((int16_t)0xFFFD);  
  562.   
  563.   while (T_FileStream_readLine(convFile, storageLine, UCNV_MAX_LINE_TEXT))
  564.     {
  565.       removeComments(storageLine);
  566.       line = storageLine;
  567.       if (line[nextTokenOffset(line, NLTC_SEPARATORS)] != '\0')
  568.     {
  569.       line = getToken(codepointBytes, line, UNICODE_CODEPOINT_SEPARATORS);
  570.       if (!icu_strcmp(codepointBytes, "END")) break;
  571.       unicodeValue = (UChar)T_CString_stringToInteger(codepointBytes, 16);
  572.       line = getToken(codepointBytes, line, CODEPOINT_SEPARATORS);
  573.       if (line[nextTokenOffset(line, CODEPOINT_SEPARATORS)] != '\0') 
  574.         {
  575.           /*two-byter!*/
  576.           line = getToken(codepointBytes+2, line, CODEPOINT_SEPARATORS);
  577.         }
  578.       
  579.       mbcsCodepageValue = T_CString_stringToInteger(codepointBytes, 16);
  580.       
  581.       ucmp16_set(myToUnicode, (int16_t)mbcsCodepageValue, unicodeValue);
  582.       ucmp16_set(myFromUnicode, unicodeValue, (int16_t)mbcsCodepageValue);
  583.     }
  584.     }
  585.  
  586.   ucmp16_compact(myFromUnicode);
  587.   ucmp16_compact(myToUnicode);
  588.   myUConverterTable->dbcs.fromUnicode = myFromUnicode;
  589.   myUConverterTable->dbcs.toUnicode = myToUnicode;
  590.   myConverter->sharedData->referenceCounter = 1;
  591.   myConverter->sharedData->table = myUConverterTable;
  592.  
  593.   /* if the default subCharLen is > 1 we need to insert it in the data structure
  594.      so that we know how to transition */
  595.   if (myConverter->subCharLen > 1)
  596.     {
  597.       myConverter->sharedData->table->mbcs.starters[myConverter->subChar[0]] = TRUE;
  598.     }
  599.   return;
  600. }
  601.  
  602.  
  603. void loadDBCSTableFromFile(FileStream* convFile, UConverter* myConverter, UErrorCode* err)
  604. {
  605.   char storageLine[UCNV_MAX_LINE_TEXT];
  606.   char* line = NULL;
  607.   UConverterTable* myUConverterTable = NULL;
  608.   UChar unicodeValue = 0xFFFD;
  609.   int32_t dbcsCodepageValue = '\0';
  610.   char codepointBytes[6];
  611.   int32_t replacementChar = 0x0000;
  612.   uint8_t i = 0;
  613.   CompactShortArray* myFromUnicode = NULL;
  614.   CompactShortArray* myToUnicode = NULL;
  615.   
  616.   /*Evaluates the replacement codepoint*/
  617.   replacementChar = 0xFFFF;
  618.  
  619.   myUConverterTable = (UConverterTable*)icu_malloc(sizeof(UConverterDBCSTable));
  620.   if (myUConverterTable == NULL) 
  621.     {
  622.       *err = U_MEMORY_ALLOCATION_ERROR;
  623.       return;
  624.     }
  625.   
  626.   myFromUnicode = ucmp16_open((int16_t)replacementChar);
  627.   myToUnicode = ucmp16_open((int16_t)0xFFFD);  
  628.   
  629.   while (T_FileStream_readLine(convFile, storageLine, UCNV_MAX_LINE_TEXT))
  630.     {
  631.       removeComments(storageLine);
  632.       line = storageLine;
  633.       if (line[nextTokenOffset(line, NLTC_SEPARATORS)] != '\0')
  634.     {
  635.       line = getToken(codepointBytes, line, UNICODE_CODEPOINT_SEPARATORS);
  636.       if (!icu_strcmp(codepointBytes, "END")) break;
  637.       unicodeValue = (UChar)T_CString_stringToInteger(codepointBytes, 16);
  638.       
  639.       /*first byte*/
  640.       line = getToken(codepointBytes, line, CODEPOINT_SEPARATORS);
  641.       
  642.       /*second byte*/
  643.       line = getToken(codepointBytes+2, line, CODEPOINT_SEPARATORS);
  644.     }
  645.       
  646.       dbcsCodepageValue = T_CString_stringToInteger(codepointBytes, 16);
  647.       ucmp16_set(myToUnicode, (int16_t)dbcsCodepageValue, unicodeValue);
  648.       ucmp16_set(myFromUnicode, unicodeValue, (int16_t)dbcsCodepageValue);
  649.     }
  650.   
  651.   ucmp16_compact(myFromUnicode);
  652.   ucmp16_compact(myToUnicode);
  653.   myUConverterTable->dbcs.fromUnicode = myFromUnicode;
  654.   myUConverterTable->dbcs.toUnicode = myToUnicode;
  655.   myConverter->sharedData->referenceCounter = 1;
  656.   myConverter->sharedData->table = myUConverterTable;
  657.   
  658.   return;
  659. }
  660.  
  661. #ifndef __amigaos__
  662. /*deletes the "shared" type object*/
  663. bool_t deleteSharedConverterData(UConverterSharedData* deadSharedData)
  664. {
  665.   if (deadSharedData->conversionType == UCNV_SBCS)
  666.     {
  667.       ucmp8_close(deadSharedData->table->sbcs.fromUnicode);
  668.       icu_free(deadSharedData->table);
  669.       icu_free(deadSharedData);
  670.     }
  671.   else if (deadSharedData->conversionType == UCNV_MBCS)
  672.     {
  673.       ucmp16_close(deadSharedData->table->mbcs.fromUnicode);
  674.       ucmp16_close(deadSharedData->table->mbcs.toUnicode);
  675.       icu_free(deadSharedData->table);
  676.       icu_free(deadSharedData);
  677.     }
  678.   else if ((deadSharedData->conversionType == UCNV_DBCS) || (deadSharedData->conversionType == UCNV_EBCDIC_STATEFUL))
  679.     {
  680.       ucmp16_close(deadSharedData->table->dbcs.fromUnicode);
  681.       ucmp16_close(deadSharedData->table->dbcs.toUnicode);
  682.       icu_free(deadSharedData->table);
  683.       icu_free(deadSharedData);
  684.     }
  685.   else
  686.     {
  687.       icu_free(deadSharedData);
  688.     }
  689.   return TRUE;
  690. }
  691. #endif
  692.  
  693.  
  694.  
  695. /*creates a UConverter, fills in necessary links to it the appropriate function pointers*/
  696. UConverterSharedData* createConverterFromTableFile(const char* converterName, UErrorCode* err)
  697. {
  698.   FileStream* convFile = NULL;
  699.   int32_t i = 0;
  700.   UConverterSharedData* mySharedData = NULL;
  701.   UConverter myConverter;
  702.  
  703.  
  704.   if (U_FAILURE(*err)) return NULL;
  705.   
  706.   convFile = T_FileStream_open(converterName, "r");
  707.   if (convFile == NULL) 
  708.     {
  709.       *err = U_FILE_ACCESS_ERROR;
  710.       return NULL;
  711.     }
  712.   
  713.   
  714.   mySharedData = (UConverterSharedData*) icu_malloc(sizeof(UConverterSharedData));
  715.   if (mySharedData == NULL)
  716.     {
  717.       *err = U_MEMORY_ALLOCATION_ERROR;
  718.       T_FileStream_close(convFile);
  719.     }
  720.   
  721.   myConverter.sharedData = mySharedData;
  722.   readHeaderFromFile(&myConverter, convFile, err);
  723.  
  724.   if (U_FAILURE(*err)) return NULL;
  725.   
  726.   switch (mySharedData->conversionType)
  727.     {
  728.     case UCNV_SBCS: 
  729.       {
  730.       loadSBCSTableFromFile(convFile, &myConverter, err);
  731.     break;
  732.       }
  733.     case UCNV_MBCS: 
  734.       {
  735.     loadMBCSTableFromFile(convFile, &myConverter, err);
  736.     break;
  737.       }
  738.     case UCNV_EBCDIC_STATEFUL: 
  739.       {
  740.     loadEBCDIC_STATEFULTableFromFile(convFile, &myConverter, err);
  741.     break;
  742.       }
  743.     case UCNV_DBCS: 
  744.       {
  745.     loadDBCSTableFromFile(convFile, &myConverter, err);
  746.     break;
  747.       }
  748.  
  749.     default : break;
  750.     };
  751.  
  752.   T_FileStream_close(convFile);
  753.   return mySharedData;
  754. }
  755.