iov[1 + cnt].iov_base = (char *) "";
iov[1 + cnt].iov_base = "";
categories_write (void){  struct locale_file  {      int magic;      int n;      int idx[0];  } *data;  struct obstack obstk;  int cat_no;#define obstack_chunk_alloc xmalloc#define obstack_chunk_free free  obstack_init (&obstk);  for (cat_no = 0; cat_no < NCATEGORIES; ++cat_no)    {      int result = 0;      if (category[cat_no].copy_locale != NULL)	/* Simply copy the addressed locale file of the specified	   category.  Please note that this is tried before the distinction	   between categories which need special handling is made.  */	{	  int source;	  /* Open source file.  */	  source = open (category[cat_no].copy_locale, O_RDONLY);	  if (source < 0)	    error (0, 0, gettext ("cannot copy locale definition file `%s'"),		   category[cat_no].copy_locale);	  else	    {	      /* Construct file name of output file and open for writing.  */	      char path[strlen (output_path)                        + strlen(category[cat_no].name) + 1];	      int dest;	      char *t;	      t = stpcpy (path, output_path);	      strcpy (t, category[cat_no].name);	      dest = creat (path, 0666);	      if (dest == -1)		error (0, 0, gettext ("cannot open output file `%s': %m"),		       path);	      else		{		  char buffer[BUFSIZ];		  int size;		  		  /* Copy the files.  */		  do		    {		      size = read (source, buffer, BUFSIZ);		      write (dest, buffer, size);		    }		  while (size > 0);		  close (dest);		  /* Show success.  */		  puts (category[cat_no].name);		}	      close (source);	    }	  /* Next category.   */	  continue;	}      if (category[cat_no].outfct)	result = category[cat_no].outfct();      else	{	  char *path, *t;	  int fd;	  struct iovec *iov;	  int item_no, len, slen, cnt;	  int elems = 0;	  /* Count number of elements.  */	  for (item_no = 0; item_no < category[cat_no].number; ++item_no)	    {	      switch (category[cat_no].item_desc[item_no].value_type)		{		case string:		case byte:		case bytearray:		  ++elems;		  break;		case stringarray:		  elems += category[cat_no].item_desc[item_no].max;		  break;		default:		  error (5, 0, gettext ("internal error in %s, line %u"),			 __FUNCTION__, __LINE__);		  /* NOTREACHED */		}	    }	  /* We now have the number of elements.  We build the structure	     and a helper structure for writing all out.  */	  len = sizeof (struct locale_file) + elems * sizeof (int);	  data = obstack_alloc (&obstk, len);	  iov = obstack_alloc (&obstk, (elems + 1) * sizeof (struct iovec));	  data->magic = LIMAGIC (cat_no);	  data->n = elems;	  iov[0].iov_base = data;	  iov[0].iov_len = len;	  cnt = 0;	  for (item_no = 0; item_no < category[cat_no].number; ++item_no)	    if (category[cat_no].item_value[item_no] == NULL)	      {		switch (category[cat_no].item_desc[item_no].value_type)		  {		  case string:		  case byte:		  case bytearray:		    data->idx[cnt] = len;		    ++len;  /* We reserve one single byte for this entry.  */		    iov[1 + cnt].iov_base = (char *) "";		    iov[1 + cnt].iov_len = 1;		    ++cnt;		    break;		  case stringarray:		    {		      int max;		      int nstr;		      max = category[cat_no].item_desc[item_no].max;		      for (nstr = 0; nstr < max; ++nstr)			{			  data->idx[cnt] = len;			  ++len;			  iov[1 + cnt].iov_base = (char *) "";			  iov[1 + cnt].iov_len = 1;			  ++cnt;			}		    }		  }	      }	    else	      switch (category[cat_no].item_desc[item_no].value_type)		{		case string:		case bytearray:		  data->idx[cnt] = len;		  slen = strlen (category[cat_no].item_value[item_no]) + 1;		  len += slen;		  iov[1 + cnt].iov_base = category[cat_no].item_value[item_no];		  iov[1 + cnt].iov_len = slen;		  ++cnt;		  break;		case byte:		  data->idx[cnt] = len;		  slen = 1;		  len += slen;		  iov[1 + cnt].iov_base = category[cat_no].item_value[item_no];		  iov[1 + cnt].iov_len = slen;		  ++cnt;		  break;		case stringarray:		  {		    int nstr, nact;		    char **first;		  		    if (category[cat_no].item_desc[item_no].min			== category[cat_no].item_desc[item_no].max)		      {			nstr = category[cat_no].item_desc[item_no].min;			first = (char **) category[cat_no].item_value[item_no];		      }		    else		      {			nstr = *(int *) category[cat_no].item_value[item_no];			first =			  ((char **) category[cat_no].item_value[item_no]) + 1;		      }		    nact = nstr;		    while (nstr > 0)		      {			data->idx[cnt] = len;			if (*first != NULL)			  {			    slen = strlen (*first) + 1;			    iov[1 + cnt].iov_base = first;			  }			else			  {			    slen = 1;			    iov[1 + cnt].iov_base = (char *) "";			  }			len += slen;			iov[1 + cnt].iov_len = slen;			++cnt;			++first;			--nstr;		      }		    while (nact < category[cat_no].item_desc[item_no].max)		      {			data->idx[cnt] = len;			len += 1;			iov[1 + cnt].iov_base = (char *) "";			iov[1 + cnt].iov_len = 1;			++cnt;			++nact;		      }		  }		  break;		default:		  /* Cannot happen.  */		  break;		}	  assert (cnt <= elems);	  /* Construct the output filename from the argument given to	     localedef on the command line.  */	  path = (char *) obstack_alloc (&obstk, strlen (output_path) +					 strlen (category[cat_no].name) + 1);	  t = stpcpy (path, output_path);	  strcpy (t, category[cat_no].name);	  fd = creat (path, 0666);	  if (fd == -1)	    {	      error (0, 0, gettext ("cannot open output file `%s': %m"), path);	      result = 1;	    }	  else	    {	      if (writev (fd, iov, cnt + 1) == -1)		{		  error (0, 0, gettext ("cannot write output file `%s': %m"),			 path);		  result = 1;		}if (elems==0) write(fd, &elems, 1);	      close (fd);	    }	  /* The old data is not needed anymore, but keep the obstack	     intact.  */	  obstack_free (&obstk, data);	}      if (result == 0)	puts (category[cat_no].name);    }  /* Now the whole obstack can be removed.  */  obstack_free (&obstk, NULL);}