+/** Load a data of type @c charset from the file FD. */
+
+static void *
+load_charset (FILE *fp, MSymbol charset_name)
+{
+ MCharset *charset = MCHARSET (charset_name);
+ int *decoder;
+ MCharTable *encoder;
+ int size;
+ int i, c;
+ int found = 0;
+ MPlist *plist;
+
+ if (! charset)
+ MERROR (MERROR_DB, NULL);
+ size = (charset->code_range[15]
+ - (charset->min_code - charset->code_range_min_code));
+ MTABLE_MALLOC (decoder, size, MERROR_DB);
+ for (i = 0; i < size; i++)
+ decoder[i] = -1;
+ encoder = mchartable (Minteger, (void *) MCHAR_INVALID_CODE);
+
+ while ((c = getc (fp)) != EOF)
+ {
+ unsigned code1, code2, c1, c2;
+ int idx1, idx2;
+ char buf[256];
+
+ ungetc (c, fp);
+ if (! fgets (buf, 256, fp))
+ break;
+ if (c != '#')
+ {
+ if (sscanf (buf, "0x%x-0x%x 0x%x", &code1, &code2, &c1) == 3)
+ {
+ idx1 = CODE_POINT_TO_INDEX (charset, code1);
+ if (idx1 >= size)
+ continue;
+ idx2 = CODE_POINT_TO_INDEX (charset, code2);
+ if (idx2 >= size)
+ idx2 = size - 1;
+ c2 = c1 + (idx2 - idx1);
+ }
+ else if (sscanf (buf, "0x%x 0x%x", &code1, &c1) == 2)
+ {
+ idx1 = idx2 = CODE_POINT_TO_INDEX (charset, code1);
+ if (idx1 >= size)
+ continue;
+ c2 = c1;
+ }
+ else
+ continue;
+ if (idx1 >= 0 && idx2 >= 0)
+ {
+ decoder[idx1] = c1;
+ mchartable_set (encoder, c1, (void *) code1);
+ for (idx1++, c1++; idx1 <= idx2; idx1++, c1++)
+ {
+ code1 = INDEX_TO_CODE_POINT (charset, idx1);
+ decoder[idx1] = c1;
+ mchartable_set (encoder, c1, (void *) code1);
+ }
+ found++;
+ }
+ }
+ }
+
+ if (! found)
+ {
+ free (decoder);
+ M17N_OBJECT_UNREF (encoder);
+ return NULL;
+ }
+ plist = mplist ();
+ mplist_add (plist, Mt, decoder);
+ mplist_add (plist, Mt, encoder);
+ return plist;
+}
+