The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This file extends lang_enc.cc with additional languages and extended routines
// It is current with Unicode 5.1 (beta Jan 2008)
//

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "encodings/compact_lang_det/ext_lang_enc.h"
#include "encodings/compact_lang_det/win/cld_macros.h"
#include "encodings/compact_lang_det/win/cld_strtoint.h"

// Language names above NUM_LANGUAGES
// These are also the C enum declared names
static const char* const kExtLanguageName[] = {
"X_BORK_BORK_BORK", "X_PIG_LATIN", "X_HACKER", "X_KLINGON", "X_ELMER_FUDD",

// Pseudo-languages for Unicode scripts that express a single language
"X_OGHAM", "X_RUNIC", "X_YI", "X_OLD_ITALIC", "X_GOTHIC",
"X_DESERET", "X_HANUNOO", "X_BUHID", "X_TAGBANWA", "X_TAI_LE",
"X_LINEAR_B", "X_UGARITIC", "X_SHAVIAN", "X_OSMANYA", "X_CYPRIOT",
"X_BUGINESE", "X_COPTIC", "X_NEW_TAI_LUE", "X_GLAGOLITIC", "X_TIFINAGH",
"X_SYLOTI_NAGRI", "X_OLD_PERSIAN", "X_KHAROSHTHI", "X_BALINESE", "X_CUNEIFORM",
"X_PHOENICIAN", "X_PHAGS_PA", "X_NKO",

// Unicode 5.1
"X_SUDANESE", "X_LEPCHA", "X_OL_CHIKI", "X_VAI", "X_SAURASHTRA",
"X_KAYAH_LI", "X_REJANG", "X_LYCIAN", "X_CARIAN", "X_LYDIAN",
"X_CHAM",
};


// These are the C enum declared names, for programs creating C code
static const char* const kExtLangDeclaredName[] = {
  "ENGLISH",      /* 0 */
  "DANISH",       /* 1 */
  "DUTCH",        /* 2 */
  "FINNISH",      /* 3 */
  "FRENCH",       /* 4 */
  "GERMAN",       /* 5 */
  "HEBREW",       /* 6 */
  "ITALIAN",      /* 7 */
  "JAPANESE",     /* 8 */
  "KOREAN",       /* 9 */
  "NORWEGIAN",    /* 10 */
  "POLISH",       /* 11 */
  "PORTUGUESE",   /* 12 */
  "RUSSIAN",      /* 13 */
  "SPANISH",      /* 14 */
  "SWEDISH",      /* 15 */
  "CHINESE",      /* 16 */
  "CZECH",        /* 17 */
  "GREEK",        /* 18 */
  "ICELANDIC",    /* 19 */
  "LATVIAN",      /* 20 */
  "LITHUANIAN",   /* 21 */
  "ROMANIAN",     /* 22 */
  "HUNGARIAN",    /* 23 */
  "ESTONIAN",     /* 24 */
  "TG_UNKNOWN_LANGUAGE",  /* 25 */
  "UNKNOWN_LANGUAGE",     /* 26 */
  "BULGARIAN",    /* 27 */
  "CROATIAN",     /* 28 */
  "SERBIAN",      /* 29 */
  "IRISH",        /* 30 */
  "GALICIAN",     /* 31 */
  "TAGALOG",      /* 32 */
  "TURKISH",      /* 33 */
  "UKRAINIAN",    /* 34 */
  "HINDI",        /* 35 */
  "MACEDONIAN",   /* 36 */
  "BENGALI",      /* 37 */
  "INDONESIAN",   /* 38 */
  "LATIN",        /* 39 */
  "MALAY",        /* 40 */
  "MALAYALAM",    /* 41 */
  "WELSH",        /* 42 */
  "NEPALI",       /* 43 */
  "TELUGU",       /* 44 */
  "ALBANIAN",     /* 45 */
  "TAMIL",        /* 46 */
  "BELARUSIAN",   /* 47 */
  "JAVANESE",     /* 48 */
  "OCCITAN",      /* 49 */
  "URDU",         /* 50 */
  "BIHARI",       /* 51 */
  "GUJARATI",     /* 52 */
  "THAI",         /* 53 */
  "ARABIC",       /* 54 */
  "CATALAN",      /* 55 */
  "ESPERANTO",    /* 56 */
  "BASQUE",       /* 57 */
  "INTERLINGUA",  /* 58 */
  "KANNADA",      /* 59 */
  "PUNJABI",      /* 60 */
  "SCOTS_GAELIC", /* 61 */
  "SWAHILI",      /* 62 */
  "SLOVENIAN",    /* 63 */
  "MARATHI",      /* 64 */
  "MALTESE",      /* 65 */
  "VIETNAMESE",   /* 66 */
  "FRISIAN",      /* 67 */
  "SLOVAK",       /* 68 */
  "CHINESE_T",    /* 69 */
  "FAROESE",      /* 70 */
  "SUNDANESE",    /* 71 */
  "UZBEK",        /* 72 */
  "AMHARIC",      /* 73 */
  "AZERBAIJANI",  /* 74 */
  "GEORGIAN",     /* 75 */
  "TIGRINYA",     /* 76 */
  "PERSIAN",      /* 77 */
  "BOSNIAN",      /* 78 */
  "SINHALESE",    /* 79 */
  "NORWEGIAN_N",  /* 80 */
  "PORTUGUESE_P", /* 81 */
  "PORTUGUESE_B", /* 82 */
  "XHOSA",        /* 83 */
  "ZULU",         /* 84 */
  "GUARANI",      /* 85 */
  "SESOTHO",      /* 86 */
  "TURKMEN",      /* 87 */
  "KYRGYZ",       /* 88 */
  "BRETON",       /* 89 */
  "TWI",          /* 90 */
  "YIDDISH",      /* 91 */
  "SERBO_CROATIAN",       /* 92 */
  "SOMALI",       /* 93 */
  "UIGHUR",       /* 94 */
  "KURDISH",      /* 95 */
  "MONGOLIAN",    /* 96 */
  "ARMENIAN",     /* 97 */
  "LAOTHIAN",     /* 98 */
  "SINDHI",       /* 99 */
  "RHAETO_ROMANCE",  /* 100 */
  "AFRIKAANS",    /* 101 */
  "LUXEMBOURGISH", /* 102 */
  "BURMESE",      /* 103 */
  "KHMER",        /* 104 */
  "TIBETAN",      /* 105 */
  "DHIVEHI",      /* 106 */       // sometimes spelled Divehi; lang of Maldives
  "CHEROKEE",     /* 107 */
  "SYRIAC",       /* 108 */
  "LIMBU",        /* 109 */
  "ORIYA",        /* 110 */
  "ASSAMESE",     /* 111 */
  "CORSICAN",     /* 112 */
  "INTERLINGUE",  /* 113 */
  "KAZAKH",       /* 114 */
  "LINGALA",      /* 115 */
  "MOLDAVIAN",    /* 116 */
  "PASHTO",       /* 117 */
  "QUECHUA",      /* 118 */
  "SHONA",        /* 119 */
  "TAJIK",        /* 120 */
  "TATAR",        /* 121 */
  "TONGA",        /* 122 */
  "YORUBA",       /* 123 */
  "CREOLES_AND_PIDGINS_ENGLISH_BASED",      /* 124 */
  "CREOLES_AND_PIDGINS_FRENCH_BASED",       /* 125 */
  "CREOLES_AND_PIDGINS_PORTUGUESE_BASED",   /* 126 */
  "CREOLES_AND_PIDGINS_OTHER",              /* 127 */
  "MAORI",        /* 128 */
  "WOLOF",        /* 129 */
  "ABKHAZIAN",    /* 130 */
  "AFAR",         /* 131 */
  "AYMARA",       /* 132 */
  "BASHKIR",      /* 133 */
  "BISLAMA",      /* 134 */
  "DZONGKHA",     /* 135 */
  "FIJIAN",       /* 136 */
  "GREENLANDIC",  /* 137 */
  "HAUSA",        /* 138 */
  "HAITIAN_CREOLE",  /* 139 */
  "INUPIAK",      /* 140 */
  "INUKTITUT",    /* 141 */
  "KASHMIRI",     /* 142 */
  "KINYARWANDA",  /* 143 */
  "MALAGASY",     /* 144 */
  "NAURU",        /* 145 */
  "OROMO",        /* 146 */
  "RUNDI",        /* 147 */
  "SAMOAN",       /* 148 */
  "SANGO",        /* 149 */
  "SANSKRIT",     /* 150 */
  "SISWANT",      /* 151 */
  "TSONGA",       /* 152 */
  "TSWANA",       /* 153 */
  "VOLAPUK",      /* 154 */
  "ZHUANG",       /* 155 */
  "KHASI",        /* 156 */
  "SCOTS",        /* 157 */
  "GANDA",        /* 158 */
  "MANX",         /* 159 */
  "MONTENEGRIN",  /* 160 */
  // Add new language declared names just before here
};

COMPILE_ASSERT(arraysize(kExtLangDeclaredName) == NUM_LANGUAGES,
       kExtLangDeclaredName_has_incorrect_length);


// Language codes above NUM_LANGUAGES
// I made all these up, except Klingon from ISO-639-2 (dsites)
// NOTE: zza is a standard name
static const char* const kExtLanguageCode[] = {
  // "X_BORK_BORK_BORK", "X_PIG_LATIN", "X_HACKER", "X_KLINGON", "X_ELMER_FUDD",
  // All Latin script
  "zzb", "zzp", "zzh", "tlh", "zze",

  // Pseudo-languages for Unicode scripts that express a single language
  "xx-Ogam", "xx-Runr", "xx-Yiii", "xx-Ital", "xx-Goth",
  "xx-Dsrt", "xx-Hano", "xx-Buhd", "xx-Tagb", "xx-Tale",
  "xx-Linb", "xx-Ugar", "xx-Shaw", "xx-Osma", "xx-Cprt",
  "xx-Bugi", "xx-Copt", "xx-Talu", "xx-Glag", "xx-Tfng",
  "xx-Sylo", "xx-Xpeo", "xx-Khar", "xx-Bali", "xx-Xsux",
  "xx-Phnx", "xx-Phag", "xx-Nkoo",

  // Unicode 5.1
  "xx-Sund", "xx-Lepc", "xx-Olck", "xx-Vaii", "xx-Saur",
  "xx-Kali", "xx-Rjng", "xx-Lyci", "xx-Cari", "xx-Lydi",
  "xx-Cham",
};


// Given the Language, returns its string name used as the output by
// the lang/enc identifier, e.g. "Korean"
// "invalid_language" if the input is invalid.
// TG_UNKNOWN_LANGUAGE is used as a placeholder for the "ignore me" language,
// used to subtract out HTML, link farms, DNA strings, and alittle English porn
const char* ExtLanguageName(const Language lang) {
  if (lang < 0) {
    // No-text-at-all result from a Tote
    return "";
  }
  // CompactLanguageDetect extension
  if (lang == TG_UNKNOWN_LANGUAGE) {
    return "Ignore";
  }
  if ((0 <= lang) && (lang < NUM_LANGUAGES)) {
    return LanguageName(lang);
  }
  if ((EXT_LANGUAGE_BASE <= lang) && (lang < EXT_NUM_LANGUAGES)) {
    return kExtLanguageName[lang - EXT_LANGUAGE_BASE];
  }
  return invalid_language_name();
}


// Given the Language, returns its Language enum spelling, for use by
// programs that create C declarations, e.g. "KOREAN"
// "UNKNOWN_LANGUAGE" if the input is invalid.
const char* ExtLanguageDeclaredName(const Language lang) {
  if ((0 <= lang) && (lang < NUM_LANGUAGES)) {
    return kExtLangDeclaredName[lang];
  }
  if ((EXT_LANGUAGE_BASE <= lang) && (lang < EXT_NUM_LANGUAGES)) {
    return kExtLanguageName[lang - EXT_LANGUAGE_BASE];
  }
  return "UNKNOWN_LANGUAGE";
}

// Given the Language, return the language code, e.g. "ko"
const char* ExtLanguageCode(const Language lang) {
  // Hack for ignore/porn pseudo-language
  if (lang == TG_UNKNOWN_LANGUAGE) {
    return "xxx";
  }
  if ((0 <= lang) && (lang < NUM_LANGUAGES)) {
    return LanguageCode(lang);
  }
  if ((EXT_LANGUAGE_BASE <= lang) && (lang < EXT_NUM_LANGUAGES)) {
    return kExtLanguageCode[lang - EXT_LANGUAGE_BASE];
  }
  return "??";
}


// Convert "en-Latn-GB" to ENGLISH
// Normalize to PORTUGUESE, not PORTUGUESE_B nor PORTUGUESE_P
// Consider for later: NORWEGIAN, NORWEGIAN_N
// Consider for later: SCOTS, SCOTS_GAELIC
// Consider for later: SERBO_CROATIAN, SERBIAN, CROATIAN, BOSNIAN
//
Language GetLanguageFromNumberOrName(const char* src) {
  if (strspn(src, "0123456789") == strlen(src)) {
    // All digits
    return static_cast<Language>(strto32(src, NULL, 10));
  }

  Language retlang = UNKNOWN_LANGUAGE;
  size_t len = strlen(src);

  if (true /*FLAGS_mergepairs*/) {
    // Merge sets of langauges pt-xx en-xx fr-xx, NOT bs/hr/sr
    if (memcmp(src, "pt-", 3) == 0) {return PORTUGUESE;}
    if (memcmp(src, "en-", 3) == 0) {return ENGLISH;}
    if (memcmp(src, "fr-", 3) == 0) {return FRENCH;}
    // Use NormalizeLanguage instead
    if (memcmp(src, "bs-", 3) == 0) {return CROATIAN;}
    if (memcmp(src, "hr-", 3) == 0) {return CROATIAN;}
    if (memcmp(src, "sr-Latn", 7) == 0) {return CROATIAN;}
    if (memcmp(src, "sh-Latn", 7) == 0) {return CROATIAN;}
    if (memcmp(src, "sr-Cyrl", 7) == 0) {return SERBIAN;}
    if (memcmp(src, "sh-Cyrl", 7) == 0) {return SERBIAN;}
  }

  // Extensions
  if (len >= 3) {
    // Standin for ignore/porn "language"
    if (memcmp(src, "xxx", 3) == 0) {return TG_UNKNOWN_LANGUAGE;}

    if (memcmp(src, "zzb", 3) == 0) {return X_BORK_BORK_BORK;}
    if (memcmp(src, "zzp", 3) == 0) {return X_PIG_LATIN;}
    if (memcmp(src, "zzh", 3) == 0) {return X_HACKER;}
    if (memcmp(src, "tlh", 3) == 0) {return X_KLINGON;}
    if (memcmp(src, "zze", 3) == 0) {return X_ELMER_FUDD;}
  }

  // We have a name like en-Latn-GB or pt-BR
  // First, get rid of some special cases
  if (len <= 3) {
    LanguageFromCode(src, &retlang);
  } else if (len == 7) {
    // More Extensions
    if (memcmp(src, "xx-", 3) == 0) {
      if (memcmp(src, "xx-Ogam", 7) == 0) {return X_OGHAM;}
      if (memcmp(src, "xx-Runr", 7) == 0) {return X_RUNIC;}
      if (memcmp(src, "xx-Yiii", 7) == 0) {return X_YI;}
      if (memcmp(src, "xx-Ital", 7) == 0) {return X_OLD_ITALIC;}
      if (memcmp(src, "xx-Goth", 7) == 0) {return X_GOTHIC;}
      if (memcmp(src, "xx-Dsrt", 7) == 0) {return X_DESERET;}
      if (memcmp(src, "xx-Hano", 7) == 0) {return X_HANUNOO;}
      if (memcmp(src, "xx-Buhd", 7) == 0) {return X_BUHID;}
      if (memcmp(src, "xx-Tagb", 7) == 0) {return X_TAGBANWA;}
      if (memcmp(src, "xx-Tale", 7) == 0) {return X_TAI_LE;}
      if (memcmp(src, "xx-Linb", 7) == 0) {return X_LINEAR_B;}
      if (memcmp(src, "xx-Ugar", 7) == 0) {return X_UGARITIC;}
      if (memcmp(src, "xx-Shaw", 7) == 0) {return X_SHAVIAN;}
      if (memcmp(src, "xx-Osma", 7) == 0) {return X_OSMANYA;}
      if (memcmp(src, "xx-Cprt", 7) == 0) {return X_CYPRIOT;}
      if (memcmp(src, "xx-Bugi", 7) == 0) {return X_BUGINESE;}
      if (memcmp(src, "xx-Copt", 7) == 0) {return X_COPTIC;}
      if (memcmp(src, "xx-Talu", 7) == 0) {return X_NEW_TAI_LUE;}
      if (memcmp(src, "xx-Glag", 7) == 0) {return X_GLAGOLITIC;}
      if (memcmp(src, "xx-Tfng", 7) == 0) {return X_TIFINAGH;}
      if (memcmp(src, "xx-Sylo", 7) == 0) {return X_SYLOTI_NAGRI;}
      if (memcmp(src, "xx-Xpeo", 7) == 0) {return X_OLD_PERSIAN;}
      if (memcmp(src, "xx-Khar", 7) == 0) {return X_KHAROSHTHI;}
      if (memcmp(src, "xx-Bali", 7) == 0) {return X_BALINESE;}
      if (memcmp(src, "xx-Xsux", 7) == 0) {return X_CUNEIFORM;}
      if (memcmp(src, "xx-Phnx", 7) == 0) {return X_PHOENICIAN;}
      if (memcmp(src, "xx-Phag", 7) == 0) {return X_PHAGS_PA;}
      if (memcmp(src, "xx-Nkoo", 7) == 0) {return X_NKO;}

      // Unicode 5.1
      if (memcmp(src, "xx-Sund", 7) == 0) {return X_SUDANESE;}
      if (memcmp(src, "xx-Lepc", 7) == 0) {return X_LEPCHA;}
      if (memcmp(src, "xx-Olck", 7) == 0) {return X_OL_CHIKI;}
      if (memcmp(src, "xx-Vaii", 7) == 0) {return X_VAI;}
      if (memcmp(src, "xx-Saur", 7) == 0) {return X_SAURASHTRA;}
      if (memcmp(src, "xx-Kali", 7) == 0) {return X_KAYAH_LI;}
      if (memcmp(src, "xx-Rjng", 7) == 0) {return X_REJANG;}
      if (memcmp(src, "xx-Lyci", 7) == 0) {return X_LYCIAN;}
      if (memcmp(src, "xx-Cari", 7) == 0) {return X_CARIAN;}
      if (memcmp(src, "xx-Lydi", 7) == 0) {return X_LYDIAN;}
      if (memcmp(src, "xx-Cham", 7) == 0) {return X_CHAM;}
    }
  }
  // Some other weird ones
  // Could be Latn or Limb; all our current training data is Latn
  if (strcmp(src, "sit-NP") == 0) {return LIMBU;}
  if (strcmp(src, "un-Latn") == 0) {return UNKNOWN_LANGUAGE;}

  // Multi-country langauges
  if (memcmp(src, "zh", 2) == 0) {
    if (memcmp(&src[len - 2], "TW", 2) == 0) {return CHINESE_T;}
    if (memcmp(&src[len - 2], "HK", 2) == 0) {return CHINESE_T;}
    return CHINESE;
  }
  if (memcmp(src, "pt", 2) == 0) {
    if (memcmp(&src[len - 2], "BR", 2) == 0) {return PORTUGUESE;}
    return PORTUGUESE;
  }
  if (memcmp(src, "fr", 2) == 0) {
    if (memcmp(&src[len -2], "CA", 2) == 0) {return FRENCH;}
    return FRENCH;
  }

  // None of the special cases matched
  if (src[2] == '-') {
    char temp[4];
    memcpy(temp, src, 4);
    temp[2] = '\0';
    LanguageFromCode(temp, &retlang);
  }
  if (src[3] == '-') {
    char temp[4];
    memcpy(temp, src, 4);
    temp[3] = '\0';
    LanguageFromCode(temp, &retlang);
  }
  if (retlang != UNKNOWN_LANGUAGE) {
    return retlang;
  }

  return retlang;
}

typedef struct {
  const char* name;
  UnicodeLScript lscript;
} NameScriptPair;

// In alphabetic order for binary search
static const NameScriptPair kNameScriptPair[] = {
  // Unicode 5.1 additional scripts
  {"Arab", ULScript_Arabic},
  {"Armn", ULScript_Armenian},
  {"Bali", ULScript_Balinese},
  {"Beng", ULScript_Bengali},
  {"Bugi", ULScript_Buginese},
  {"Buhd", ULScript_Buhid},
  {"Cans", ULScript_Canadian_Aboriginal},
  {"Cari", ULScript_Carian},      // Unicode 5.1
  {"Cham", ULScript_Cham},        // Unicode 5.1
  {"Cher", ULScript_Cherokee},
  {"Copt", ULScript_Coptic},
  {"Cprt", ULScript_Cypriot},
  {"Cyrl", ULScript_Cyrillic},
  {"Deva", ULScript_Devanagari},
  {"Dsrt", ULScript_Deseret},
  {"Ethi", ULScript_Ethiopic},
  {"Geor", ULScript_Georgian},
  {"Glag", ULScript_Glagolitic},
  {"Goth", ULScript_Gothic},
  {"Grek", ULScript_Greek},
  {"Gujr", ULScript_Gujarati},
  {"Guru", ULScript_Gurmukhi},
  {"Hani", ULScript_HanCJK},
  {"Hano", ULScript_Hanunoo},
  {"Hebr", ULScript_Hebrew},
  {"Ital", ULScript_Old_Italic},
  {"Kali", ULScript_Kayah_Li},    // Unicode 5.1
  {"Khar", ULScript_Kharoshthi},
  {"Khmr", ULScript_Khmer},
  {"Knda", ULScript_Kannada},
  {"Laoo", ULScript_Lao},
  {"Latn", ULScript_Latin},
  {"Lepc", ULScript_Lepcha},      // Unicode 5.1
  {"Limb", ULScript_Limbu},
  {"Linb", ULScript_Linear_B},
  {"Lyci", ULScript_Lycian},      // Unicode 5.1
  {"Lydi", ULScript_Lydian},      // Unicode 5.1
  {"Mlym", ULScript_Malayalam},
  {"Mong", ULScript_Mongolian},
  {"Mymr", ULScript_Myanmar},
  {"Nkoo", ULScript_Nko},
  {"Ogam", ULScript_Ogham},
  {"Olck", ULScript_Ol_Chiki},    // Unicode 5.1
  {"Orya", ULScript_Oriya},
  {"Osma", ULScript_Osmanya},
  {"Phag", ULScript_Phags_Pa},
  {"Phnx", ULScript_Phoenician},
  {"Rjng", ULScript_Rejang},      // Unicode 5.1
  {"Runr", ULScript_Runic},
  {"Saur", ULScript_Saurashtra},  // Unicode 5.1
  {"Shaw", ULScript_Shavian},
  {"Sinh", ULScript_Sinhala},
  {"Sund", ULScript_Sundanese},   // Unicode 5.1
  {"Sylo", ULScript_Syloti_Nagri},
  {"Syrc", ULScript_Syriac},
  {"Tagb", ULScript_Tagbanwa},
  {"Tale", ULScript_Tai_Le},
  {"Talu", ULScript_New_Tai_Lue},
  {"Taml", ULScript_Tamil},
  {"Telu", ULScript_Telugu},
  {"Tfng", ULScript_Tifinagh},
  {"Tglg", ULScript_Tagalog},
  {"Thaa", ULScript_Thaana},
  {"Thai", ULScript_Thai},
  {"Tibt", ULScript_Tibetan},
  {"Ugar", ULScript_Ugaritic},
  {"Vaii", ULScript_Vai},         // Unicode 5.1 // NOTE: apparently 'Vai '
  {"Xpeo", ULScript_Old_Persian},
  {"Xsux", ULScript_Cuneiform},
  {"Yiii", ULScript_Yi},
  {"Zyyy", ULScript_Common},
  {"Zzzz", ULScript_Inherited},
};

// Convert "en-Latn-GB" to ULScript_Latin
UnicodeLScript GetLScriptFromNumberOrName(const char* src) {
  if (strspn(src, "0123456789") == strlen(src)) {
    // All digits
    return static_cast<UnicodeLScript>(strto32(src, NULL, 10));
  }

  if (strcmp(src, "zh-TW") == 0) {return ULScript_HanCJK;}
  if (strcmp(src, "zh-CN") == 0) {return ULScript_HanCJK;}
  if (strcmp(src, "pt-BR") == 0) {return ULScript_Latin;}
  if (strcmp(src, "pt-PT") == 0) {return ULScript_Latin;}
  // Could be Latn or Limb; all our current training data is Latn
  if (strcmp(src, "sit-NP") == 0) {return ULScript_Latin;}

  // Isolate just the script field
  char temp[5];
  const char* src2 = strchr(src, '-');
  if (src2 == NULL) {return ULScript_Latin;}
  src2 += 1;      // over the -
  memcpy(temp, src2, 4);
  temp[4] = '\0';

  int lo = 0;
  int hi = ULScript_NUM_SCRIPTS;
  while (lo < hi) {
    int mid = (lo + hi) >> 1;
    if (strcmp(temp, kNameScriptPair[mid].name) < 0) {
      hi = mid;
    } else if (strcmp(temp, kNameScriptPair[mid].name) > 0) {
      lo = mid + 1;
    } else {
      return kNameScriptPair[mid].lscript;
    }
  }
  return ULScript_Latin;
}


// Merge together some languages, such as bo/hr/sr
// Croatian Latin and Serbian Cyrillic now.
Language NormalizeLanguage(Language lang) {
  if (lang == BOSNIAN) {return CROATIAN;}
  if (lang == SERBO_CROATIAN) {return SERBIAN;}

  if (lang == PORTUGUESE_P) {return PORTUGUESE;}
  if (lang == PORTUGUESE_B) {return PORTUGUESE;}

  return lang;
}