Blame iconvcap.c

Packit Service 366393
/*
Packit Service 366393
 * iconv capability checker by David Necas (Yeti).
Packit Service 366393
 * This program is in the public domain.
Packit Service 366393
 *
Packit Service 366393
 * iconvcap has two modes of operation:
Packit Service 366393
 *
Packit Service 366393
 * 1. No command line argumets are given.
Packit Service 366393
 * Iconvcap tries to find what charsets of interest iconv knows and under
Packit Service 366393
 * what names.  It prints #defines directly includable to C source for
Packit Service 366393
 * any successfully detected charset (and #defines to NULL for the others).
Packit Service 366393
 * It also prints some info to stderr, which then goes to config.log.  It
Packit Service 366393
 * returns success (0) iff following conditions are satified
Packit Service 366393
 * -- iconv is able to convert ISO-8859-1 to some tested variant of Unicode
Packit Service 366393
 *    (see below)---so it's usable at all, and
Packit Service 366393
 * -- iconv is able convert at least two of the other charsets of interest to
Packit Service 366393
 *    the same variant of Unicode (we then hope conversion in the opposite
Packit Service 366393
 *    direction will work too)
Packit Service 366393
 * Otherwise, failure (1) is returned and the output should be ignored, if
Packit Service 366393
 * any.
Packit Service 366393
 *
Packit Service 366393
 * 2. A file name is given on command line.
Packit Service 366393
 * Iconvcap reads given file (should contain the just generated #define list)
Packit Service 366393
 * and chcecks if conversion from any to any encoding is possible.  If it is
Packit Service 366393
 * OK it returns success (0), otherwise, it fails returning 1.
Packit Service 366393
 *
Packit Service 366393
 */
Packit Service 366393
#include <stdlib.h>
Packit Service 366393
#include <stdio.h>
Packit Service 366393
#include <iconv.h>
Packit Service 366393
/* string.h or strings.h?  That's a question!
Packit Service 366393
 * Don't use const, the compiler may not like it. */
Packit Service 366393
int strncmp(char *s1, char *s2, size_t n);
Packit Service 366393
char* strchr(char *s, int c);
Packit Service 366393
char* strrchr(char *s, int c);
Packit Service 366393
char* strncpy(char *dest, char *src, size_t n);
Packit Service 366393
Packit Service 366393
#define DPREFIX "ICONV_NAME_"
Packit Service 366393
Packit Service 366393
#define TEST_ENC_TO_UNICODE(x) \
Packit Service 366393
  fprintf(stderr, "iconvcap: checking for %s -> Unicode... ", #x); \
Packit Service 366393
  if (iconv_check(VARIANT_##x, unicode) == 0) { \
Packit Service 366393
    printf("#define "DPREFIX"%s \"%s\"\n", #x, FROM); \
Packit Service 366393
    ok++; \
Packit Service 366393
  } else printf("#define "DPREFIX"%s NULL\n", #x);
Packit Service 366393
Packit Service 366393
/* ANY variant of unicode is good enough here
Packit Service 366393
   particular surfaces are defined below */
Packit Service 366393
char* VARIANT_UNICODE[] = {
Packit Service 366393
  "UCS2", "UCS-2", "ISO10646/UCS2", "ISO-10646/UCS2", "ISO_10646/UCS2",
Packit Service 366393
  "UNICODE", "ISO-10646", "ISO_10646", "ISO10646",
Packit Service 366393
  "UCS4", "UCS-4", "ISO10646/UCS4", "ISO-10646/UCS4", "ISO_10646/UCS4",
Packit Service 366393
  "UTF8", "UTF-8", "ISO10646/UTF8", "ISO-10646/UTF8", "ISO_10646/UTF8",
Packit Service 366393
  "CSUCS2", "CSUCS4", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_ASCII[] = {
Packit Service 366393
  "ASCII", "CSASCII", "US-ASCII", "ISO646-US", "ISO_646.IRV:1991", "CP367",
Packit Service 366393
  "IBM367", "CP367", "CSPC367", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_ISO88591[] = {
Packit Service 366393
  "ISO-8859-1", "ISO8859-1", "8859_1", "ISO_8859-1", "LATIN1", "ISOLATIN1",
Packit Service 366393
  "CSLATIN1", "CSISOLATIN1", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_ISO88592[] = {
Packit Service 366393
  "ISO-8859-2", "ISO8859-2", "8859_2", "ISO_8859-2", "LATIN2", "ISOLATIN2",
Packit Service 366393
  "CSLATIN2", "CSISOLATIN2", "ISO-IR-101", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_ISO88594[] = {
Packit Service 366393
  "ISO-8859-4", "ISO8859-4", "8859_4", "ISO_8859-4", "LATIN4", "ISOLATIN4",
Packit Service 366393
  "CSLATIN4", "CSISOLATIN4", "ISO-IR-110", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_ISO88595[] = {
Packit Service 366393
  "ISO-8859-5", "ISO8859-5", "8859_5", "ISO_8859-5", "ISOCYRILLIC",
Packit Service 366393
  "CSISOCYRILLIC", "ISO-IR-144", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_ISO885913[] = {
Packit Service 366393
  "ISO-8859-13", "ISO8859-13", "8859_13", "ISO_8859-13", "LATIN7", "ISOLATIN7",
Packit Service 366393
  "CSLATIN7", "CSISOLATIN7", "ISO-IR-179A", "ISOBALTIC", "CSISOBALTIC",
Packit Service 366393
  "CSISOLATINBALTIC", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_ISO885916[] = {
Packit Service 366393
  "ISO-8859-16", "ISO8859-16", "8859_16", "ISO_8859-16", "ISO-IR-226",
Packit Service 366393
  "LATIN10", "ISOLATIN10", "CSLATIN10", "CSISOLATIN10", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_BALTIC[] = {
Packit Service 366393
  "BALTIC", "CSBALTIC", "ISO-IR-179", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_IBM852[] = {
Packit Service 366393
  "IBM852", "CP852", "CP-852", "CP_852", "852", "IBM-852", "IBM_852",
Packit Service 366393
  "PC852", "CSPC852", "CSPCP852", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_IBM855[] = {
Packit Service 366393
  "IBM855", "CP855", "CP-855", "CP_855", "855", "IBM-855", "IBM_855",
Packit Service 366393
  "PC855", "CSPC855", "CSPCP855", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_IBM775[] = {
Packit Service 366393
  "IBM775", "CP775", "CP-775", "CP_775", "775", "IBM-775", "IBM_775",
Packit Service 366393
  "PC775", "CSPC775", "CSPCP775", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_IBM866[] = {
Packit Service 366393
  "IBM866", "CP866", "CP-866", "CP_866", "866", "IBM-866", "IBM_866",
Packit Service 366393
  "PC866", "CSPC866", "CSPCP866", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_CP1125[] = {
Packit Service 366393
  "CP1125", "1125", "CP-1125", "CP_1125", "MS1125", "MS-1125",
Packit Service 366393
  "WINDOWS-1125", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_CP1250[] = {
Packit Service 366393
  "CP1250", "1250", "CP-1250", "CP_1250", "MS-EE", "MS1250", "MS-1250",
Packit Service 366393
  "WINDOWS-1250", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_CP1251[] = {
Packit Service 366393
  "CP1251", "1251", "CP-1251", "CP_1251", "MS-CYRL", "MS1251", "MS-1251",
Packit Service 366393
  "WINDOWS-1251", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_CP1257[] = {
Packit Service 366393
  "CP1257", "1257", "CP-1257", "CP_1257", "MS-BALT", "MS1257", "MS-1257",
Packit Service 366393
  "WINDOWS-1257", "WinBaltRim", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_MACCE[] = {
Packit Service 366393
  "MACCE", "MAC-CE", "MAC_CE", "MACINTOSH-CE", "MACEE", "MAC-EE", "MAC_EE",
Packit Service 366393
  "MACINTOSH-EE", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_MACCYR[] = {
Packit Service 366393
  "MACCYR", "MAC-CYR", "MAC_CYR", "MACINTOSH-CYR", "MACCYRILLIC",
Packit Service 366393
  "MAC-CYRILLIC", "MACINTOSH-CYRILLIC", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_KOI8CS2[] = {
Packit Service 366393
  "KOI8-CS2", "KOI8CS2", "KOI8_CS2", "KOI-8_CS2", "KOI8CS", "KOI8_CS",
Packit Service 366393
  "KOI8-CS", "KOI-8-CS", "KOI_8-CS", "CSKOI8CS2", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_KOI8R[] = {
Packit Service 366393
  "KOI8-R", "KOI8_R", "KOI-8_R", "KOI8R", "KOI8_R", "CSKOI8R", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_KOI8U[] = {
Packit Service 366393
  "KOI8-U", "KOI8_U", "KOI-8_U", "KOI8U", "KOI8_U", "CSKOI8U", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_KOI8UNI[] = {
Packit Service 366393
  "KOI8-UNI", "KOI8_UNI", "KOI-8_UNI", "KOI8UNI", "KOI8_UNI", "CSKOI8UNI",
Packit Service 366393
  NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_ECMA113[] = {
Packit Service 366393
  "ECMA-113", "ECMA-cyrillic", "ECMA-113:1986", "ISO-IR-111", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_KEYBCS2[] = {
Packit Service 366393
  "KEYBCS2", "KEYBCS-2", "KAM", "KAMENICKY", "CP895", "895", "PC895",
Packit Service 366393
  "csPC895", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_LATEX[] = {
Packit Service 366393
  "TEX", "LATEX", "LTEX", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_UCS2[] = {
Packit Service 366393
  "UCS-2", "UCS-2BE", "UCS2", "ISO10646/UCS2", "ISO-10646/UCS2",
Packit Service 366393
  "ISO_10646/UCS2", "CSUCS2", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_UCS4[] = {
Packit Service 366393
  "UCS-4", "UCS-4BE", "UCS4", "ISO10646/UCS4", "ISO-10646/UCS4",
Packit Service 366393
  "ISO_10646/UCS4", "CSUCS4", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_UTF7[] = {
Packit Service 366393
  "UTF-7", "UTF7", "ISO10646/UTF7", "ISO-10646/UTF7", "ISO_10646/UTF7",
Packit Service 366393
  "UNICODE/UTF7", "CSUTF7", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_UTF8[] = {
Packit Service 366393
  "UTF-8", "UTF8", "ISO10646/UTF8", "ISO-10646/UTF8", "ISO_10646/UTF8",
Packit Service 366393
  "UNICODE/UTF8", "CSUTF8", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_CORK[] = {
Packit Service 366393
  "CORK", "T1", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_GBK[] = {
Packit Service 366393
	"GBK", "GB18030", "GB2312", "CP936", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_BIG5[] = {
Packit Service 366393
	"BIG5", "CP950", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
char* VARIANT_HZ[] = {
Packit Service 366393
  "HZ", "HZ-GB-2312", "GB18030", "GB2312", NULL
Packit Service 366393
};
Packit Service 366393
Packit Service 366393
typedef struct S_EncList {
Packit Service 366393
  char *enc;
Packit Service 366393
  struct S_EncList *next;
Packit Service 366393
} T_EncList, *P_EncList;
Packit Service 366393
Packit Service 366393
/* for the case we would be linked with braindead librecode */
Packit Service 366393
char *program_name = "iconvcap";
Packit Service 366393
Packit Service 366393
char *FROM, *TO;
Packit Service 366393
Packit Service 366393
/* Local protoypes. */
Packit Service 366393
static int iconv_check        (char **fromlist,
Packit Service 366393
                               char **tolist);
Packit Service 366393
static int iconv_check_one    (char *from,
Packit Service 366393
                               char *to);
Packit Service 366393
static int check_transitivity (char *fname);
Packit Service 366393
Packit Service 366393
/* main() */
Packit Service 366393
int
Packit Service 366393
main(int argc, char *argv[])
Packit Service 366393
{
Packit Service 366393
  int ok;
Packit Service 366393
  char *unicode[] = { NULL, NULL };
Packit Service 366393
Packit Service 366393
  /* when we are called with some argument, run transitivity test and exit */
Packit Service 366393
  if (argc > 1) return check_transitivity(argv[1]);
Packit Service 366393
Packit Service 366393
  /* check for conversion ISO-8859-1 -> Unicode */
Packit Service 366393
  fprintf(stderr, "iconvcap: checking for ISO8859-1 -> Unicode... ");
Packit Service 366393
  if ((ok = iconv_check(VARIANT_ISO88591, VARIANT_UNICODE)) == 0) {
Packit Service 366393
    unicode[0] = TO;
Packit Service 366393
    printf("#define "DPREFIX"UNICODE \"%s\"\n", unicode[0]);
Packit Service 366393
  } else {
Packit Service 366393
    fprintf(stderr, "iconvcap: iconv seems to be broken. aborting.\n");
Packit Service 366393
    exit(1);
Packit Service 366393
  }
Packit Service 366393
Packit Service 366393
  /* create table of charset names how iconv uses them */
Packit Service 366393
  ok = 0;
Packit Service 366393
  TEST_ENC_TO_UNICODE(ASCII);
Packit Service 366393
  TEST_ENC_TO_UNICODE(BALTIC);
Packit Service 366393
  TEST_ENC_TO_UNICODE(CP1125);
Packit Service 366393
  TEST_ENC_TO_UNICODE(CP1250);
Packit Service 366393
  TEST_ENC_TO_UNICODE(CP1251);
Packit Service 366393
  TEST_ENC_TO_UNICODE(CP1257);
Packit Service 366393
  TEST_ENC_TO_UNICODE(ECMA113);
Packit Service 366393
  TEST_ENC_TO_UNICODE(IBM852);
Packit Service 366393
  TEST_ENC_TO_UNICODE(IBM855);
Packit Service 366393
  TEST_ENC_TO_UNICODE(IBM775);
Packit Service 366393
  TEST_ENC_TO_UNICODE(IBM866);
Packit Service 366393
  TEST_ENC_TO_UNICODE(ISO88592);
Packit Service 366393
  TEST_ENC_TO_UNICODE(ISO88594);
Packit Service 366393
  TEST_ENC_TO_UNICODE(ISO88595);
Packit Service 366393
  TEST_ENC_TO_UNICODE(ISO885913);
Packit Service 366393
  TEST_ENC_TO_UNICODE(ISO885916);
Packit Service 366393
  TEST_ENC_TO_UNICODE(KEYBCS2);
Packit Service 366393
  TEST_ENC_TO_UNICODE(KOI8CS2);
Packit Service 366393
  TEST_ENC_TO_UNICODE(KOI8R);
Packit Service 366393
  TEST_ENC_TO_UNICODE(KOI8U);
Packit Service 366393
  TEST_ENC_TO_UNICODE(KOI8UNI);
Packit Service 366393
  TEST_ENC_TO_UNICODE(MACCE);
Packit Service 366393
  TEST_ENC_TO_UNICODE(MACCYR);
Packit Service 366393
  TEST_ENC_TO_UNICODE(LATEX);
Packit Service 366393
  TEST_ENC_TO_UNICODE(UCS2);
Packit Service 366393
  TEST_ENC_TO_UNICODE(UCS4);
Packit Service 366393
  TEST_ENC_TO_UNICODE(UTF7);
Packit Service 366393
  TEST_ENC_TO_UNICODE(UTF8);
Packit Service 366393
  TEST_ENC_TO_UNICODE(CORK);
Packit Service 366393
  TEST_ENC_TO_UNICODE(GBK);
Packit Service 366393
  TEST_ENC_TO_UNICODE(BIG5);
Packit Service 366393
  TEST_ENC_TO_UNICODE(HZ);
Packit Service 366393
Packit Service 366393
  if (ok >= 2) exit(0);
Packit Service 366393
  else exit(1);
Packit Service 366393
}
Packit Service 366393
Packit Service 366393
/* return 0 if conversion from any charset from fromlist to any charset from
Packit Service 366393
   tolist is possible and set FROM and TO (globals) to appropriate names
Packit Service 366393
   (it's assumed fromlist and tolist are lists of charset aliases) */
Packit Service 366393
static int
Packit Service 366393
iconv_check(char **fromlist, char **tolist)
Packit Service 366393
{
Packit Service 366393
  char **from, **to;
Packit Service 366393
Packit Service 366393
  for (from = fromlist; *from != NULL; from++) {
Packit Service 366393
    for (to = tolist; *to != NULL; to++) {
Packit Service 366393
      if (iconv_check_one(*from, *to) == 0) {
Packit Service 366393
        fprintf(stderr, "found %s -> %s\n", *from, *to);
Packit Service 366393
        FROM = *from;
Packit Service 366393
        TO = *to;
Packit Service 366393
        return 0;
Packit Service 366393
      }
Packit Service 366393
    }
Packit Service 366393
  }
Packit Service 366393
  fprintf(stderr, "failed.\n");
Packit Service 366393
  FROM = NULL;
Packit Service 366393
  TO = NULL;
Packit Service 366393
  return 1;
Packit Service 366393
}
Packit Service 366393
Packit Service 366393
/* check if conversion from any encoding not defined as NULL in file fname
Packit Service 366393
   to any other defined there is possible, in other words check transitivity
Packit Service 366393
   condition for all defined encodings (we then hope this condition holds
Packit Service 366393
   also for encodings we don't know anything about)
Packit Service 366393
   returns 0 on success 1 on failure */
Packit Service 366393
static int
Packit Service 366393
check_transitivity(char *fname)
Packit Service 366393
{
Packit Service 366393
  char *s, *sb, *se;
Packit Service 366393
  FILE *f;
Packit Service 366393
  P_EncList enclist = NULL;
Packit Service 366393
  P_EncList p_e;
Packit Service 366393
Packit Service 366393
Packit Service 366393
  s = (char*)malloc(1024);
Packit Service 366393
  if ((f = fopen(fname, "r")) == NULL) {
Packit Service 366393
    fprintf(stderr, "iconvcap: cannot open %s\n", fname);
Packit Service 366393
    free(s);
Packit Service 366393
    return 1;
Packit Service 366393
  }
Packit Service 366393
Packit Service 366393
  while (fgets(s, 1024, f) != NULL) {
Packit Service 366393
    p_e = (P_EncList)malloc(sizeof(T_EncList));
Packit Service 366393
    if (strncmp(s, "#define", 7) != 0) {
Packit Service 366393
      fprintf(stderr, "iconvcap: malformed input line: %s", s);
Packit Service 366393
      fclose(f);
Packit Service 366393
      free(s);
Packit Service 366393
      free(p_e);
Packit Service 366393
      return 1;
Packit Service 366393
    }
Packit Service 366393
    if ((sb = strchr(s, '"')) != NULL) {
Packit Service 366393
      if ((se = strrchr(s, '"')) == sb) {
Packit Service 366393
        fprintf(stderr, "iconvcap: malformed input line: %s", s);
Packit Service 366393
        fclose(f);
Packit Service 366393
        free(s);
Packit Service 366393
        free(p_e);
Packit Service 366393
        return 1;
Packit Service 366393
      }
Packit Service 366393
Packit Service 366393
      p_e->enc = strncpy((char*)malloc(se-sb), sb+1, se-sb-1);
Packit Service 366393
      p_e->enc[se-sb-1] = '\0';
Packit Service 366393
      p_e->next = enclist;
Packit Service 366393
      enclist = p_e;
Packit Service 366393
    }
Packit Service 366393
  }
Packit Service 366393
  fclose(f);
Packit Service 366393
Packit Service 366393
  if (enclist == NULL) {
Packit Service 366393
    fprintf(stderr, "no valid encodings\n");
Packit Service 366393
    free(s);
Packit Service 366393
    return 1;
Packit Service 366393
  }
Packit Service 366393
Packit Service 366393
  while (enclist != NULL) {
Packit Service 366393
    for (p_e = enclist->next; p_e != NULL; p_e = p_e->next) {
Packit Service 366393
      if (iconv_check_one(enclist->enc, p_e->enc) != 0) {
Packit Service 366393
        fprintf(stderr, "iconvap: iconv_open(%s, %s) failed\n",
Packit Service 366393
                enclist->enc, p_e->enc);
Packit Service 366393
        free(s);
Packit Service 366393
        return 1;
Packit Service 366393
      }
Packit Service 366393
      if (iconv_check_one(p_e->enc, enclist->enc) != 0) {
Packit Service 366393
        fprintf(stderr, "iconvcap: iconv_open(%s, %s) failed\n",
Packit Service 366393
                p_e->enc, enclist->enc);
Packit Service 366393
        free(s);
Packit Service 366393
        return 1;
Packit Service 366393
      }
Packit Service 366393
    }
Packit Service 366393
    enclist = enclist->next;
Packit Service 366393
  }
Packit Service 366393
Packit Service 366393
  fprintf(stderr, "iconvcap: transitivity OK\n");
Packit Service 366393
  free(s);
Packit Service 366393
  return 0;
Packit Service 366393
}
Packit Service 366393
Packit Service 366393
/* check whether conversion from `from' to `to' is possible */
Packit Service 366393
static int
Packit Service 366393
iconv_check_one(char *from, char *to)
Packit Service 366393
{
Packit Service 366393
  iconv_t id;
Packit Service 366393
Packit Service 366393
  id = iconv_open(from, to);
Packit Service 366393
  if (id == (iconv_t)(-1)) return 1;
Packit Service 366393
  iconv_close(id);
Packit Service 366393
  return 0;
Packit Service 366393
}
Packit Service 366393