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

📄 iconvconfig.c

📁 Newlib 嵌入式 C库 标准实现代码
💻 C
📖 第 1 页 / 共 2 页
字号:
  new_module (from, to - from, to, module - to, directory, module, wp - module,	      cost, need_ext);}/* Read the config file and add the data for this directory to that.  */static inthandle_dir (const char *dir){  char *infile;  FILE *fp;  char *line = NULL;  size_t linelen = 0;  size_t dirlen = strlen (dir);  char *tmp;  if (dir[dirlen - 1] != '/')    {      char *newp = (char *) xmalloc (dirlen + 2);      dir = memcpy (newp, dir, dirlen);      newp[dirlen++] = '/';      newp[dirlen] = '\0';    }  infile = (char *) alloca (dirlen + sizeof "gconv-modules");  tmp = mempcpy (infile, dir, dirlen);  tmp += dirlen;  strcpy (tmp, "gconv-modules");  fp = fopen (infile, "r");  if (fp == NULL)    {      error (0, errno, "cannot open `%s'", infile);      return 1;    }  /* No threads present.  */  __fsetlocking (fp, FSETLOCKING_BYCALLER);  while (!feof_unlocked (fp))    {      char *rp, *endp, *word;      ssize_t n = __getdelim (&line, &linelen, '\n', fp);      if (n < 0)	/* An error occurred.  */	break;      rp = line;      /* Terminate the line (excluding comments or newline) with a NUL	 byte to simplify the following code.  */      endp = strchr (rp, '#');      if (endp != NULL)	*endp = '\0';      else	if (rp[n - 1] == '\n')	  rp[n - 1] = '\0';      while (isspace (*rp))	++rp;      /* If this is an empty line go on with the next one.  */      if (rp == endp)	continue;      word = rp;      while (*rp != '\0' && !isspace (*rp))	++rp;      if (rp - word == sizeof ("alias") - 1	  && memcmp (word, "alias", sizeof ("alias") - 1) == 0)	add_alias (rp);      else if (rp - word == sizeof ("module") - 1	       && memcmp (word, "module", sizeof ("module") - 1) == 0)	add_module (rp, dir);      /* else */	/* Otherwise ignore the line.  */    }  free (line);  fclose (fp);  return 0;}static voidappend_module (const void *nodep, VISIT value, int level){  struct module *mo;  if (value != leaf && value != postorder)    return;  mo = *(struct module **) nodep;  if (nmodule_list > 0      && strcmp (module_list[nmodule_list - 1]->fromname, mo->fromname) == 0)    {      /* Same name.  */      mo->next = module_list[nmodule_list - 1];      module_list[nmodule_list - 1] = mo;      return;    }  if (nmodule_list_max == nmodule_list)    {      nmodule_list_max += 50;      module_list = (struct module **) xrealloc (module_list,						 (nmodule_list_max						  * sizeof (struct module *)));    }  module_list[nmodule_list++] = mo;}static voidget_modules (void){  twalk (modules, append_module);}static voidadd_builtins (void){  size_t cnt;  /* Add all aliases.  */  for (cnt = 0; cnt < nbuiltin_alias; ++cnt)    new_alias (builtin_alias[cnt].from,	       strlen (builtin_alias[cnt].from) + 1,	       builtin_alias[cnt].to,	       strlen (builtin_alias[cnt].to) + 1);  /* add the builtin transformations.  */  for (cnt = 0; cnt < nbuiltin_trans; ++cnt)    new_module (builtin_trans[cnt].from,		strlen (builtin_trans[cnt].from) + 1,		builtin_trans[cnt].to,		strlen (builtin_trans[cnt].to) + 1,		"", builtin_trans[cnt].module,		strlen (builtin_trans[cnt].module) + 1,		builtin_trans[cnt].cost, 0);}static intname_compare (const void *p1, const void *p2){  const struct name *n1 = (const struct name *) p1;  const struct name *n2 = (const struct name *) p2;  return strcmp (n1->name, n2->name);}static struct name *new_name (const char *str, struct Strent *strent){  struct name *newp = (struct name *) xmalloc (sizeof (struct name));  newp->name = str;  newp->strent = strent;  newp->module_idx = -1;  newp->hashval = hash_string (str);  ++nnames;  return newp;}static voidgenerate_name_list (void){  size_t i;  /* A name we always need.  */  tsearch (new_name ("INTERNAL", strtabadd (strtab, "INTERNAL",					    sizeof ("INTERNAL"))),	   &names, name_compare);  for (i = 0; i < nmodule_list; ++i)    {      struct module *runp;      if (strcmp (module_list[i]->fromname, "INTERNAL") != 0)	tsearch (new_name (module_list[i]->fromname,			   module_list[i]->fromname_strent),		 &names, name_compare);      for (runp = module_list[i]; runp != NULL; runp = runp->next)	if (strcmp (runp->toname, "INTERNAL") != 0)	  tsearch (new_name (runp->toname, runp->toname_strent),		   &names, name_compare);    }}static intname_to_module_idx (const char *name, int add){  struct name **res;  struct name fake_name = { .name = name };  int idx;  res = (struct name **) tfind (&fake_name, &names, name_compare);  if (res == NULL)    abort ();  idx = (*res)->module_idx;  if (idx == -1 && add)    /* No module index assigned yet.  */    idx = (*res)->module_idx = nname_info++;  return idx;}static voidgenerate_name_info (void){  size_t i;  int idx;  name_info = (struct name_info *) xcalloc (nmodule_list + 1,					    sizeof (struct name_info));  /* First add a special entry for the INTERNAL name.  This must have     index zero.  */  idx = name_to_module_idx ("INTERNAL", 1);  name_info[0].canonical_name = "INTERNAL";  name_info[0].canonical_strent = strtabadd (strtab, "INTERNAL",					     sizeof ("INTERNAL"));  assert (nname_info == 1);  for (i = 0; i < nmodule_list; ++i)    {      struct module *runp;      for (runp = module_list[i]; runp != NULL; runp = runp->next)	if (strcmp (runp->fromname, "INTERNAL") == 0)	  {	    idx = name_to_module_idx (runp->toname, 1);	    name_info[idx].from_internal = runp;	    assert (name_info[idx].canonical_name == NULL		    || strcmp (name_info[idx].canonical_name,			       runp->toname) == 0);	    name_info[idx].canonical_name = runp->toname;	    name_info[idx].canonical_strent = runp->toname_strent;	  }	else if (strcmp (runp->toname, "INTERNAL") == 0)	  {	    idx = name_to_module_idx (runp->fromname, 1);	    name_info[idx].to_internal = runp;	    assert (name_info[idx].canonical_name == NULL		    || strcmp (name_info[idx].canonical_name,			       runp->fromname) == 0);	    name_info[idx].canonical_name = runp->fromname;	    name_info[idx].canonical_strent = runp->fromname_strent;	  }	else	  {	    /* This is a transformation not to or from the INTERNAL	       encoding.  */	    int from_idx = name_to_module_idx (runp->fromname, 1);	    int to_idx = name_to_module_idx (runp->toname, 1);	    struct other_conv_list *newp;	    newp = (struct other_conv_list *)	      xmalloc (sizeof (struct other_conv_list));	    newp->other_conv.module_idx = to_idx;	    newp->other_conv.module = runp;	    newp->other_conv.next = NULL; /* XXX Allow multiple module sequence */	    newp->dest_idx = to_idx;	    newp->next = name_info[from_idx].other_conv_list;	    name_info[from_idx].other_conv_list = newp;	    assert (name_info[from_idx].canonical_name == NULL		    || strcmp (name_info[from_idx].canonical_name,			       runp->fromname) == 0);	    name_info[from_idx].canonical_name = runp->fromname;	    name_info[from_idx].canonical_strent = runp->fromname_strent;	    ++nextra_modules;	  }    }  /* Now add the module index information for all the aliases.  */  for (i = 0; i < nalias_list; ++i)    {      struct name fake_name = { .name = alias_list[i]->toname };      struct name **tonamep;      tonamep = (struct name **) tfind (&fake_name, &names, name_compare);      if (tonamep != NULL)	{	  struct name *newp = new_name (alias_list[i]->fromname,					alias_list[i]->froment);	  newp->module_idx = (*tonamep)->module_idx;	  tsearch (newp, &names, name_compare);	}    }}static intis_prime (unsigned long int candidate){  /* No even number and none less than 10 will be passed here.  */  unsigned long int divn = 3;  unsigned long int sq = divn * divn;  while (sq < candidate && candidate % divn != 0)    {      ++divn;      sq += 4 * divn;      ++divn;    }  return candidate % divn != 0;}static uint32_tnext_prime (uint32_t seed){  /* Make it definitely odd.  */  seed |= 1;  while (!is_prime (seed))    seed += 2;  return seed;}/* Format of the output file.   Offset   Length       Description   0000     4            Magic header bytes   0004     4            Offset of string table (stoff)   0008     4            Offset of name hashing table (hoff)   000C     4            Hashing table size (hsize)   0010     4            Offset of module table (moff)   0014     4            Offset of other conversion module table (ooff)   stoff    ???          String table   hoff     8*hsize      Array of tuples                            string table offset                            module index   moff     ???          Array of tuples                            canonical name offset                            from-internal module dir name offset                            from-internal module name off                            to-internal module dir name offset                            to-internal module name offset                            offset into other conversion table   ooff     ???          One or more of                            number of steps/modules                            one or more of tuple                              canonical name offset for output                              module dir name offset                              module name offset                         (following last entry with step count 0)*/static intwrite_output (void){  int fd;  char *string_table;  size_t string_table_size;  struct gconvcache_header header;  struct hash_entry *hash_table;  size_t hash_size;  struct module_entry *module_table;  char *extra_table;  char *cur_extra_table;  size_t n;  int idx;  struct iovec iov[6];  static const gidx_t null_word;  size_t total;  char tmpfname[sizeof (GCONV_MODULES_CACHE) + strlen (".XXXXXX")];  /* Function to insert the names.  */  static void name_insert (const void *nodep, VISIT value, int level)    {      struct name *name;      unsigned int idx;      unsigned int hval2;      if (value != leaf && value != postorder)	return;      name = *(struct name **) nodep;      idx = name->hashval % hash_size;      hval2 = 1 + name->hashval % (hash_size - 2);      while (hash_table[idx].string_offset != 0)	if ((idx += hval2) >= hash_size)	  idx -= hash_size;      hash_table[idx].string_offset = strtaboffset (name->strent);      assert (name->module_idx != -1);      hash_table[idx].module_idx = name->module_idx;    }  /* Open the output file.  */  strcpy (stpcpy (tmpfname, GCONV_MODULES_CACHE), ".XXXXXX");  fd = mkstemp (tmpfname);  if (fd == -1)    return 1;  /* Create the string table.  */  string_table = strtabfinalize (strtab, &string_table_size);  /* Create the hashing table.  We know how many strings we have.     Creating a perfect hash table is not reasonable here.  Therefore     we use open hashing and a table size which is the next prime 40%     larger than the number of strings.  */  hash_size = next_prime (nnames * 1.4);  hash_table = (struct hash_entry *) xcalloc (hash_size,					      sizeof (struct hash_entry));  /* Fill the hash table.  */  twalk (names, name_insert);  /* Create the section for the module list.  */  module_table = (struct module_entry *) xcalloc (sizeof (struct module_entry),						  nname_info);  /* Allocate memory for the non-INTERNAL conversions.  The allocated     memory can be more than is actually needed.  */  extra_table = (char *) xcalloc (sizeof (struct extra_entry)				  + sizeof (gidx_t)				  + sizeof (struct extra_entry_module),				  nextra_modules);  cur_extra_table = extra_table;  /* Fill in the module information.  */  for (n = 0; n < nname_info; ++n)    {      module_table[n].canonname_offset =	strtaboffset (name_info[n].canonical_strent);      if (name_info[n].from_internal == NULL)	{	  module_table[n].fromdir_offset = 0;	  module_table[n].fromname_offset = 0;	}      else	{	  module_table[n].fromdir_offset =	    strtaboffset (name_info[n].from_internal->directory_strent);	  module_table[n].fromname_offset =	    strtaboffset (name_info[n].from_internal->filename_strent);	}      if (name_info[n].to_internal == NULL)	{	  module_table[n].todir_offset = 0;	  module_table[n].toname_offset = 0;	}      else	{	  module_table[n].todir_offset =	    strtaboffset (name_info[n].to_internal->directory_strent);	  module_table[n].toname_offset =	    strtaboffset (name_info[n].to_internal->filename_strent);	}      if (name_info[n].other_conv_list != NULL)	{	  struct other_conv_list *other = name_info[n].other_conv_list;	  /* Store the reference.  We add 1 to distinguish the entry	     at offset zero from the case where no extra modules are	     available.  The file reader has to account for the	     offset.  */	  module_table[n].extra_offset = 1 + cur_extra_table - extra_table;	  do	    {	      struct other_conv *runp;	      struct extra_entry *extra;	      /* Allocate new entry.  */	      extra = (struct extra_entry *) cur_extra_table;	      cur_extra_table += sizeof (struct extra_entry);	      extra->module_cnt = 0;	      runp = &other->other_conv;	      do		{		  cur_extra_table += sizeof (struct extra_entry_module);		  extra->module[extra->module_cnt].outname_offset =		    runp->next == NULL		    ? other->dest_idx : runp->next->module_idx;		  extra->module[extra->module_cnt].dir_offset =		    strtaboffset (runp->module->directory_strent);		  extra->module[extra->module_cnt].name_offset =		    strtaboffset (runp->module->filename_strent);		  ++extra->module_cnt;		  runp = runp->next;		}	      while (runp != NULL);	      other = other->next;	    }	  while (other != NULL);	  /* Final module_cnt is zero.  */	  *((gidx_t *) cur_extra_table) = 0;	  cur_extra_table += sizeof (gidx_t);	}    }  header.magic = GCONVCACHE_MAGIC;  iov[0].iov_base = &header;  iov[0].iov_len = sizeof (struct gconvcache_header);  total = iov[0].iov_len;  header.string_offset = total;  iov[1].iov_base = string_table;  iov[1].iov_len = string_table_size;  total += iov[1].iov_len;  idx = 2;  if ((string_table_size & (sizeof (gidx_t) - 1)) != 0)    {      iov[2].iov_base = (void *) &null_word;      iov[2].iov_len = (sizeof (gidx_t)			- (string_table_size & (sizeof (gidx_t) - 1)));      total += iov[2].iov_len;      ++idx;    }  header.hash_offset = total;  header.hash_size = hash_size;  iov[idx].iov_base = hash_table;  iov[idx].iov_len = hash_size * sizeof (struct hash_entry);  total += iov[idx].iov_len;  ++idx;  header.module_offset = total;  iov[idx].iov_base = module_table;  iov[idx].iov_len = nname_info * sizeof (struct module_entry);  total += iov[idx].iov_len;  ++idx;  assert (cur_extra_table - extra_table	  <= ((sizeof (struct extra_entry) + sizeof (gidx_t)	       + sizeof (struct extra_entry_module))	      * nextra_modules));  header.otherconv_offset = total;  iov[idx].iov_base = extra_table;  iov[idx].iov_len = cur_extra_table - extra_table;  total += iov[idx].iov_len;  ++idx;  if (TEMP_FAILURE_RETRY (writev (fd, iov, idx)) != total      /* The file was created with mode 0600.  Make it world-readable.  */      || fchmod (fd, 0644) != 0      /* Rename the file, possibly replacing an old one.  */      || rename (tmpfname, GCONV_MODULES_CACHE) != 0)    {      int save_errno = errno;      close (fd);      unlink (tmpfname);      error (EXIT_FAILURE, save_errno,	     gettext ("cannot generate output file"));    }  close (fd);  return 0;}

⌨️ 快捷键说明

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