⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iconvconfig.c

📁 Newlib 嵌入式 C库 标准实现代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Generate fastloading iconv module configuration files.   Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.   This file is part of the GNU C Library.   Contributed by Ulrich Drepper <drepper@redhat.com>, 2000.   The GNU C Library is free software; you can redistribute it and/or   modify it under the terms of the GNU Lesser General Public   License as published by the Free Software Foundation; either   version 2.1 of the License, or (at your option) any later version.   The GNU C Library is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   Lesser General Public License for more details.   You should have received a copy of the GNU Lesser General Public   License along with the GNU C Library; if not, write to the Free   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA   02111-1307 USA.  */#include <argp.h>#include <assert.h>#include <error.h>#include <errno.h>#include <fcntl.h>#include <libintl.h>#include <locale.h>#include <mcheck.h>#include <search.h>#include <stdint.h>#include <stdio.h>#include <stdio_ext.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/cdefs.h>#include <sys/uio.h>#include "iconvconfig.h"/* Get libc version number.  */#include "../version.h"#define PACKAGE _libc_intl_domainname/* The hashing function we use.  */#include "../intl/hash-string.h"/* Types used.  */struct module{  char *fromname;  struct Strent *fromname_strent;  char *filename;  struct Strent *filename_strent;  const char *directory;  struct Strent *directory_strent;  struct module *next;  int cost;  struct Strent *toname_strent;  char toname[0];};struct alias{  char *fromname;  struct Strent *froment;  struct module *module;  struct Strent *toent;  char toname[0];};struct name{  const char *name;  struct Strent *strent;  int module_idx;  uint32_t hashval;};struct name_info{  const char *canonical_name;  struct Strent *canonical_strent;  struct module *from_internal;  struct module *to_internal;  struct other_conv_list  {    int dest_idx;    struct other_conv    {      gidx_t module_idx;      struct module *module;      struct other_conv *next;    } other_conv;    struct other_conv_list *next;  } *other_conv_list;};/* Name and version of program.  */static void print_version (FILE *stream, struct argp_state *state);void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;/* Short description of program.  */static const char doc[] = N_("\Create fastloading iconv module configuration file.");/* Strings for arguments in help texts.  */static const char args_doc[] = N_("[DIR...]");/* Function to print some extra text in the help message.  */static char *more_help (int key, const char *text, void *input);/* Data structure to communicate with argp functions.  */static struct argp argp ={  NULL, NULL, args_doc, doc, NULL, more_help};/* The function doing the actual work.  */static int handle_dir (const char *dir);/* Add all known builtin conversions and aliases.  */static void add_builtins (void);/* Create list of all aliases without circular aliases.  */static void get_aliases (void);/* Create list of all modules.  */static void get_modules (void);/* Get list of all the names and thereby indexing them.  */static void generate_name_list (void);/* Collect information about all the names.  */static void generate_name_info (void);/* Write the output file.  */static int write_output (void);/* Search tree of the modules we know.  */static void *modules;/* Search tree of the aliases we know.  */static void *aliases;/* Search tree for name to index mapping.  */static void *names;/* Number of names we know about.  */static int nnames;/* List of all aliases.  */static struct alias **alias_list;static size_t nalias_list;static size_t nalias_list_max;/* List of all modules.  */static struct module **module_list;static size_t nmodule_list;static size_t nmodule_list_max;/* Names and information about them.  */static struct name_info *name_info;static size_t nname_info;/* Number of translations not from or to INTERNAL.  */static size_t nextra_modules;/* Names and aliases for the builtin transformations.  */static struct{  const char *from;  const char *to;} builtin_alias[] =  {#define BUILTIN_ALIAS(alias, real) \    { .from = alias, .to = real },#define BUILTIN_TRANSFORMATION(From, To, Cost, Name, Fct, MinF, MaxF, \			       MinT, MaxT)#include <gconv_builtin.h>  };#undef BUILTIN_ALIAS#undef BUILTIN_TRANSFORMATION#define nbuiltin_alias (sizeof (builtin_alias) / sizeof (builtin_alias[0]))static struct{  const char *from;  const char *to;  const char *module;  int cost;} builtin_trans[] =  {#define BUILTIN_ALIAS(alias, real)#define BUILTIN_TRANSFORMATION(From, To, Cost, Name, Fct, MinF, MaxF, \			       MinT, MaxT) \    { .from = From, .to = To, .module = Name, .cost = Cost },#include <gconv_builtin.h>  };#define nbuiltin_trans (sizeof (builtin_trans) / sizeof (builtin_trans[0]))/* Filename extension for the modules.  */#ifndef MODULE_EXT# define MODULE_EXT ".so"#endifstatic const char gconv_module_ext[] = MODULE_EXT;extern void *xmalloc (size_t n) __attribute_malloc__;extern void *xcalloc (size_t n, size_t m) __attribute_malloc__;extern void *xrealloc (void *p, size_t n);/* C string table handling.  */struct Strtab;struct Strent;/* Create new C string table object in memory.  */extern struct Strtab *strtabinit (void);/* Free resources allocated for C string table ST.  */extern void strtabfree (struct Strtab *st);/* Add string STR (length LEN is != 0) to C string table ST.  */extern struct Strent *strtabadd (struct Strtab *st, const char *str,				 size_t len);/* Finalize string table ST and store size in *SIZE and return a pointer.  */extern void *strtabfinalize (struct Strtab *st, size_t *size);/* Get offset in string table for string associated with SE.  */extern size_t strtaboffset (struct Strent *se);/* String table we construct.  */static struct Strtab *strtab;intmain (int argc, char *argv[]){  int remaining;  int status = 0;  char *path;  char *tp;  const char *old = GCONV_PATH;  size_t len = strlen (old) + 1;  char *new = alloca(len);  /* Enable memory use testing.  */  /* mcheck_pedantic (NULL); */  mtrace ();  /* Set locale via LC_ALL.  */  setlocale (LC_ALL, "");  /* Set the text message domain.  */  textdomain (_libc_intl_domainname);  /* Parse and process arguments.  */  argp_parse (&argp, argc, argv, 0, &remaining, NULL);  /* Initialize the string table.  */  strtab = strtabinit ();  /* Handle all directories mentioned.  */  while (remaining < argc)    status |= handle_dir (argv[remaining++]);  /* In any case also handle the standard directory.  */  path = memcpy (new, old, len);  tp = strtok (path, ":");  while (tp != NULL)    {      status |= handle_dir (tp);      tp = strtok (NULL, ":");    }  /* Add the builtin transformations and aliases without overwriting     anything.  */  add_builtins ();  /* Store aliases in an array.  */  get_aliases ();  /* Get list of all modules.  */  get_modules ();  /* Generate list of all the names we know to handle in some way.  */  generate_name_list ();  /* Now we know all the names we will handle, collect information     about them.  */  generate_name_info ();  /* Write the output file, but only if we haven't seen any error.  */  if (status == 0)    status = write_output ();  else    error (1, 0, _("no output file produced because warning were issued"));  return status;}static char *more_help (int key, const char *text, void *input){  switch (key)    {    case ARGP_KEY_HELP_EXTRA:      /* We print some extra information.  */      return strdup (gettext ("\Report bugs using the `glibcbug' script to <bugs@gnu.org>.\n"));    default:      break;    }  return (char *) text;}/* Print the version information.  */static voidprint_version (FILE *stream, struct argp_state *state){  fprintf (stream, "iconvconfig (GNU %s) %s\n", PACKAGE, VERSION);  fprintf (stream, gettext ("\Copyright (C) %s Free Software Foundation, Inc.\n\This is free software; see the source for copying conditions.  There is NO\n\warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\"), "2002");  fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");}static intalias_compare (const void *p1, const void *p2){  const struct alias *a1 = (const struct alias *) p1;  const struct alias *a2 = (const struct alias *) p2;  return strcmp (a1->fromname, a2->fromname);}static voidnew_alias (const char *fromname, size_t fromlen, const char *toname,	   size_t tolen){  struct alias *newp;  void **inserted;  newp = (struct alias *) xmalloc (sizeof (struct alias) + fromlen + tolen);  newp->fromname = memcpy (newp->toname, toname, tolen);  newp->fromname += tolen;  memcpy (newp->fromname, fromname, fromlen);  newp->module = NULL;  inserted = (void **) tsearch (newp, &aliases, alias_compare);  if (inserted == NULL)    error (EXIT_FAILURE, errno, gettext ("while inserting in search tree"));  if (*inserted != newp)    /* Something went wrong, free this entry.  */    free (newp);  else    {      newp->froment = strtabadd (strtab, newp->fromname, fromlen);      newp->toent = strtabadd (strtab, newp->toname, tolen);    }}/* Add new alias.  */static voidadd_alias (char *rp){  /* We now expect two more string.  The strings are normalized     (converted to UPPER case) and strored in the alias database.  */  char *from;  char *to;  char *wp;  while (isspace (*rp))    ++rp;  from = wp = rp;  while (*rp != '\0' && !isspace (*rp))    *wp++ = toupper (*rp++);  if (*rp == '\0')    /* There is no `to' string on the line.  Ignore it.  */    return;  *wp++ = '\0';  to = ++rp;  while (isspace (*rp))    ++rp;  while (*rp != '\0' && !isspace (*rp))    *wp++ = toupper (*rp++);  if (to == wp)    /* No `to' string, ignore the line.  */    return;  *wp++ = '\0';  assert (strlen (from) + 1 == to - from);  assert (strlen (to) + 1 == wp - to);  new_alias (from, to - from, to, wp - to);}static voidappend_alias (const void *nodep, VISIT value, int level){  if (value != leaf && value != postorder)    return;  if (nalias_list_max == nalias_list)    {      nalias_list_max += 50;      alias_list = (struct alias **) xrealloc (alias_list,					       (nalias_list_max						* sizeof (struct alias *)));    }  alias_list[nalias_list++] = *(struct alias **) nodep;}static voidget_aliases (void){  twalk (aliases, append_alias);}static intmodule_compare (const void *p1, const void *p2){  const struct module *m1 = (const struct module *) p1;  const struct module *m2 = (const struct module *) p2;  int result;  result = strcmp (m1->fromname, m2->fromname);  if (result == 0)    result = strcmp (m1->toname, m2->toname);  return result;}/* Create new module record.  */static voidnew_module (const char *fromname, size_t fromlen, const char *toname,	    size_t tolen, const char *directory,	    const char *filename, size_t filelen, int cost, size_t need_ext){  struct module *new_module;  size_t dirlen = strlen (directory) + 1;  char *tmp;  void **inserted;  new_module = (struct module *) xmalloc (sizeof (struct module)					  + fromlen + tolen + filelen					  + need_ext);  new_module->fromname = memcpy (new_module->toname, toname, tolen);  new_module->fromname += tolen;  new_module->filename = memcpy (new_module->fromname, fromname, fromlen);  new_module->filename += fromlen;  new_module->cost = cost;  new_module->next = NULL;  tmp = memcpy (new_module->filename, filename, filelen);  tmp += filelen;  if (need_ext)    {      memcpy (tmp - 1, gconv_module_ext, need_ext + 1);      filelen += need_ext;    }  new_module->directory = directory;  /* Now insert the new module data structure in our search tree.  */  inserted = (void **) tsearch (new_module, &modules, module_compare);  if (inserted == NULL)    error (EXIT_FAILURE, errno, "while inserting in search tree");  if (*inserted != new_module)    free (new_module);  else    {      new_module->fromname_strent = strtabadd (strtab, new_module->fromname,					       fromlen);      new_module->toname_strent = strtabadd (strtab, new_module->toname,					     tolen);      new_module->filename_strent = strtabadd (strtab, new_module->filename,					       filelen);      new_module->directory_strent = strtabadd (strtab, directory, dirlen);    }}/* Add new module.  */static voidinternal_functionadd_module (char *rp, const char *directory){  /* We expect now     1. `from' name     2. `to' name     3. filename of the module     4. an optional cost value  */  char *from;  char *to;  char *module;  char *wp;  int need_ext;  int cost;  while (isspace (*rp))    ++rp;  from = rp;  while (*rp != '\0' && !isspace (*rp))    {      *rp = toupper (*rp);      ++rp;    }  if (*rp == '\0')    return;  *rp++ = '\0';  to = wp = rp;  while (isspace (*rp))    ++rp;  while (*rp != '\0' && !isspace (*rp))    *wp++ = toupper (*rp++);  if (*rp == '\0')    return;  *wp++ = '\0';  do    ++rp;  while (isspace (*rp));  module = wp;  while (*rp != '\0' && !isspace (*rp))    *wp++ = *rp++;  if (*rp == '\0')    {      /* There is no cost, use one by default.  */      *wp++ = '\0';      cost = 1;    }  else    {      /* There might be a cost value.  */      char *endp;      *wp++ = '\0';      cost = strtol (rp, &endp, 10);      if (rp == endp || cost < 1)	/* No useful information.  */	cost = 1;    }  if (module[0] == '\0')    /* No module name given.  */    return;  /* See whether we must add the ending.  */  need_ext = 0;  if (wp - module < sizeof (gconv_module_ext)      || memcmp (wp - sizeof (gconv_module_ext), gconv_module_ext,		 sizeof (gconv_module_ext)) != 0)    /* We must add the module extension.  */    need_ext = sizeof (gconv_module_ext) - 1;  assert (strlen (from) + 1 == to - from);  assert (strlen (to) + 1 == module - to);  assert (strlen (module) + 1 == wp - module);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -