if (time->cat == NULL && !be_quiet)					      \ error (0, 0, _("%s: field `%s' not defined"), "LC_TIME", #cat);	      \
if (time->cat == NULL)						      \ {									      \ if (! be_quiet && ! nothing)					      \ error (0, 0, _("%s: field `%s' not defined"), "LC_TIME", #cat);	      \ }									      \
time_finish (struct localedef_t *locale, struct charmap_t *charmap){  struct locale_time_t *time = locale->categories[LC_TIME].time;  size_t cnt;#define TESTARR_ELEM(cat) \  if (!time->cat##_defined && !be_quiet)				      \    error (0, 0, _("%s: field `%s' not defined"), "LC_TIME", #cat);	      \  else if (time->w##cat != NULL)					      \    {									      \      size_t n;								      \      for (n = 0; n < sizeof (time->w##cat) / sizeof (time->w##cat[0]); ++n)  \	{								      \	  size_t len = wcslen ((wchar_t *) time->w##cat[n]) + 1;	      \	  uint32_t *wstr = (uint32_t *) xmalloc (len * sizeof (uint32_t));    \	  do								      \	    {								      \	      --len;							      \	      wstr[len] = bswap_32 (time->w##cat[n][len]);		      \	    }								      \	  while (len > 0);						      \	  time->w##cat##_ob[n] = wstr;					      \	}								      \    }  TESTARR_ELEM (abday);  TESTARR_ELEM (day);  TESTARR_ELEM (abmon);  TESTARR_ELEM (mon);  TESTARR_ELEM (am_pm);#define TEST_ELEM(cat) \  if (time->cat == NULL && !be_quiet)					      \    error (0, 0, _("%s: field `%s' not defined"), "LC_TIME", #cat);	      \  else if (time->w##cat != NULL)					      \    {									      \      size_t len = wcslen ((wchar_t *) time->w##cat) + 1;		      \      uint32_t *wstr = (uint32_t *) xmalloc (len * sizeof (uint32_t));	      \      do								      \	{								      \	  --len;							      \	  wstr[len] = bswap_32 (time->w##cat[len]);			      \	}								      \      while (len > 0);							      \      time->w##cat##_ob = wstr;						      \    }  TEST_ELEM (d_t_fmt);  TEST_ELEM (d_fmt);  TEST_ELEM (t_fmt);  /* According to C.Y.Alexis Cheng <alexis@vnet.ibm.com> the T_FMT_AMPM     field is optional.  */  if (time->t_fmt_ampm == NULL)    {      /* Use the 24h format as default.  */      time->t_fmt_ampm = time->t_fmt;      time->wt_fmt_ampm = time->wt_fmt;      time->wt_fmt_ampm_ob = time->wt_fmt_ob;    }  else    {      /* Convert the byte order.  */      size_t len = wcslen ((wchar_t *) time->wt_fmt_ampm) + 1;      uint32_t *wstr = (uint32_t *) xmalloc (len * sizeof (uint32_t));      do	{	  --len;	  wstr[len] = bswap_32 (time->wt_fmt_ampm[len]);	}      while (len > 0);      time->wt_fmt_ampm_ob = wstr;    }  /* Now process the era entries.  */  if (time->num_era != 0)    {      const int days_per_month[12] = { 31, 29, 31, 30, 31, 30,				       31, 31, 30, 31 ,30, 31 };      size_t idx;      wchar_t *wstr;      time->era_entries =	(struct era_data *) xmalloc (time->num_era				     * sizeof (struct era_data));      for (idx = 0; idx < time->num_era; ++idx)	{	  size_t era_len = strlen (time->era[idx]);	  char *str = xmalloc ((era_len + 1 + 3) & ~3);	  char *endp;	  memcpy (str, time->era[idx], era_len + 1);	  /* First character must be + or - for the direction.  */	  if (*str != '+' && *str != '-')	    {	      if (!be_quiet)		error (0, 0, _("%s: direction flag in string %d in `era' field"			       " is not '+' nor '-'"),		       "LC_TIME", idx + 1);	      /* Default arbitrarily to '+'.  */	      time->era_entries[idx].direction = '+';	    }	  else	    time->era_entries[idx].direction = *str;	  if (*++str != ':')	    {	      if (!be_quiet)		error (0, 0, _("%s: direction flag in string %d in `era' field"			       " is not a single character"),		       "LC_TIME", idx + 1);	      (void) strsep (&str, ":");	    }	  else	    ++str;	  /* Now the offset year.  */	  time->era_entries[idx].offset = strtol (str, &endp, 10);	  if (endp == str)	    {	      if (!be_quiet)		error (0, 0, _("%s: invalid number for offset in string %d in"			       " `era' field"),		       "LC_TIME", idx + 1);	      (void) strsep (&str, ":");	    }	  else if (*endp != ':')	    {	      if (!be_quiet)		error (0, 0, _("%s: garbage at end of offset value in"			       " string %d in `era' field"),		       "LC_TIME", idx + 1);	      (void) strsep (&str, ":");	    }	  else	    str = endp + 1;	  /* Next is the starting date in ISO format.  */	  if (strncmp (str, "-*", 2) == 0)	    {	      time->era_entries[idx].start_date[0] =		time->era_entries[idx].start_date[1] =		time->era_entries[idx].start_date[2] = 0x80000000;	      if (str[2] != ':')		goto garbage_start_date;	      str += 3;	    }	  else if (strncmp (str, "+*", 2) == 0)	    {	      time->era_entries[idx].start_date[0] =		time->era_entries[idx].start_date[1] =		time->era_entries[idx].start_date[2] = 0x7fffffff;	      if (str[2] != ':')		goto garbage_start_date;	      str += 3;	    }	  else	    {	      time->era_entries[idx].start_date[0] = strtol (str, &endp, 10);	      if (endp == str || *endp != '/')		goto invalid_start_date;	      else		str = endp + 1;	      time->era_entries[idx].start_date[0] -= 1900;	      time->era_entries[idx].start_date[1] = strtol (str, &endp, 10);	      if (endp == str || *endp != '/')		goto invalid_start_date;	      else		str = endp + 1;	      time->era_entries[idx].start_date[1] -= 1;	      time->era_entries[idx].start_date[2] = strtol (str, &endp, 10);	      if (endp == str)		{		invalid_start_date:		  if (!be_quiet)		    error (0, 0, _("%s: invalid starting date in string %d in"				   " `era' field"),			   "LC_TIME", idx + 1);		  (void) strsep (&str, ":");		}	      else if (*endp != ':')		{		garbage_start_date:		  if (!be_quiet)		    error (0, 0, _("%s: garbage at end of starting date "				   "in string %d in `era' field "),			   "LC_TIME", idx + 1);		  (void) strsep (&str, ":");		}	      else		{		  str = endp + 1;		  /* Check for valid value.  */		  if ((time->era_entries[idx].start_date[1] < 0		       || time->era_entries[idx].start_date[1] >= 12		       || time->era_entries[idx].start_date[2] < 0		       || (time->era_entries[idx].start_date[2]			   > days_per_month[time->era_entries[idx].start_date[1]])		       || (time->era_entries[idx].start_date[1] == 2			   && time->era_entries[idx].start_date[2] == 29			   && !__isleap (time->era_entries[idx].start_date[0])))		      && !be_quiet)			  error (0, 0, _("%s: starting date is invalid in"					 " string %d in `era' field"),				 "LC_TIME", idx + 1);		}	    }	  /* Next is the stopping date in ISO format.  */	  if (strncmp (str, "-*", 2) == 0)	    {	      time->era_entries[idx].stop_date[0] =		time->era_entries[idx].stop_date[1] =		time->era_entries[idx].stop_date[2] = 0x80000000;	      if (str[2] != ':')		goto garbage_stop_date;	      str += 3;	    }	  else if (strncmp (str, "+*", 2) == 0)	    {	      time->era_entries[idx].stop_date[0] =		time->era_entries[idx].stop_date[1] =		time->era_entries[idx].stop_date[2] = 0x7fffffff;	      if (str[2] != ':')		goto garbage_stop_date;	      str += 3;	    }	  else	    {	      time->era_entries[idx].stop_date[0] = strtol (str, &endp, 10);	      if (endp == str || *endp != '/')		goto invalid_stop_date;	      else		str = endp + 1;	      time->era_entries[idx].stop_date[0] -= 1900;	      time->era_entries[idx].stop_date[1] = strtol (str, &endp, 10);	      if (endp == str || *endp != '/')		goto invalid_stop_date;	      else		str = endp + 1;	      time->era_entries[idx].stop_date[1] -= 1;	      time->era_entries[idx].stop_date[2] = strtol (str, &endp, 10);	      if (endp == str)		{		invalid_stop_date:		  if (!be_quiet)		    error (0, 0, _("%s: invalid stopping date in string %d in"				   " `era' field"),			   "LC_TIME", idx + 1);		  (void) strsep (&str, ":");		}	      else if (*endp != ':')		{		garbage_stop_date:		  if (!be_quiet)		    error (0, 0, _("%s: garbage at end of stopping date "				   "in string %d in `era' field"),			   "LC_TIME", idx + 1);		  (void) strsep (&str, ":");		}	      else		{		  str = endp + 1;		  /* Check for valid value.  */		  if ((time->era_entries[idx].stop_date[1] < 0		       || time->era_entries[idx].stop_date[1] >= 12		       || time->era_entries[idx].stop_date[2] < 0		       || (time->era_entries[idx].stop_date[2]			   > days_per_month[time->era_entries[idx].stop_date[1]])		       || (time->era_entries[idx].stop_date[1] == 2			   && time->era_entries[idx].stop_date[2] == 29			   && !__isleap (time->era_entries[idx].stop_date[0])))		      && !be_quiet)			  error (0, 0, _("%s: stopping date is invalid in"					 " string %d in `era' field"),				 "LC_TIME", idx + 1);		}	    }	  if (str == NULL || *str == '\0')	    {	      if (!be_quiet)		error (0, 0, _("%s: missing era name in string %d in `era'"			       " field"), "LC_TIME", idx + 1);	      time->era_entries[idx].name =		time->era_entries[idx].format = "";	    }	  else	    {	      time->era_entries[idx].name = strsep (&str, ":");	      if (str == NULL || *str == '\0')		{		  if (!be_quiet)		    error (0, 0, _("%s: missing era format in string %d"				   " in `era' field"),			   "LC_TIME", idx + 1);		  time->era_entries[idx].name =		    time->era_entries[idx].format = "";		}	      else		time->era_entries[idx].format = str;	    }	  /* Now generate the wide character name and format.  */	  wstr = wcschr ((wchar_t *) time->wera, L':');	/* end direction */	  wstr = wstr ? wcschr (wstr, L':') : NULL;	/* end offset */	  wstr = wstr ? wcschr (wstr, L':') : NULL;	/* end start */	  wstr = wstr ? wcschr (wstr, L':') : NULL;	/* end end */	  time->era_entries[idx].wname = (uint32_t *) wstr;	  wstr = wstr ? wcschr (wstr, L':') : NULL;	/* end name */	  time->era_entries[idx].wformat = (uint32_t *) wstr;	}      /* Construct the array for the other byte order.  */      time->era_entries_ob =	(struct era_data *) xmalloc (time->num_era * sizeof (struct era_data));      for (idx = 0; idx < time->num_era; ++idx)	{	  time->era_entries_ob[idx].direction =	    bswap_32 (time->era_entries[idx].direction);	  time->era_entries_ob[idx].offset =	    bswap_32 (time->era_entries[idx].offset);	  time->era_entries_ob[idx].start_date[0] =	    bswap_32 (time->era_entries[idx].start_date[0]);	  time->era_entries_ob[idx].start_date[1] =	    bswap_32 (time->era_entries[idx].start_date[1]);	  time->era_entries_ob[idx].start_date[2] =	    bswap_32 (time->era_entries[idx].stop_date[2]);	  time->era_entries_ob[idx].stop_date[0] =	    bswap_32 (time->era_entries[idx].stop_date[0]);	  time->era_entries_ob[idx].stop_date[1] =	    bswap_32 (time->era_entries[idx].stop_date[1]);	  time->era_entries_ob[idx].stop_date[2] =	    bswap_32 (time->era_entries[idx].stop_date[2]);	  time->era_entries_ob[idx].name =	    time->era_entries[idx].name;	  time->era_entries_ob[idx].format =	    time->era_entries[idx].format;	  if (time->era_entries[idx].wname != NULL)	    {	      size_t inner = (wcslen ((wchar_t *) time->era_entries[idx].wname)			      + 1);	      time->era_entries_ob[idx].wname = xmalloc (inner							 * sizeof (uint32_t));	      do		time->era_entries_ob[idx].wname[inner - 1]		  = bswap_32 (time->era_entries[idx].wname[inner - 1]);	      while (inner-- > 0);	    }	  else	    time->era_entries_ob[idx].wname = NULL;	  if (time->era_entries[idx].wformat != NULL)	    {	      size_t inner		= wcslen ((wchar_t *) time->era_entries[idx].wformat) + 1;	      time->era_entries_ob[idx].wformat = xmalloc (inner							   * sizeof (uint32_t));	      do		time->era_entries_ob[idx].wformat[inner - 1]		  = bswap_32 (time->era_entries[idx].wformat[inner - 1]);	      while (inner-- > 0);	    }	  else	    time->era_entries_ob[idx].wformat = NULL;	}    }  if (time->week_ndays == 0)    time->week_ndays = 7;  if (time->week_1stday == 0)    time->week_1stday = 19971130;  if (time->week_1stweek > time->week_ndays)    error (0, 0, _("\%s: third operand for value of field `%s' must not be larger than %d"),	   "LC_TIME", "week", 7);  if (time->first_weekday == '\0')    /* The definition does not specify this so the default is used.  */    time->first_weekday = 1;  else if (time->first_weekday > time->week_ndays)    error (0, 0, _("\%s: values of field `%s' must not be larger than %d"),	   "LC_TIME", "first_weekday", 7);  if (time->first_workday == '\0')    /* The definition does not specify this so the default is used.  */    time->first_workday = 1;  else if (time->first_workday > time->week_ndays)    error (0, 0, _("\%s: values of field `%s' must not be larger than %d"),	   "LC_TIME", "first_workday", 7);  if (time->cal_direction == '\0')    /* The definition does not specify this so the default is used.  */    time->cal_direction = 1;  else if (time->cal_direction > 3)    error (0, 0, _("\%s: values for field `%s' must not be larger than 3"),	   "LC_TIME", "cal_direction", 3);  /* XXX We don't perform any tests on the timezone value since this is     simply useless, stupid $&$!@...  */  if (time->timezone == NULL)    time->timezone = "";  /* Generate alt digits in other byte order.  */  for (cnt = 0; cnt < 100; ++cnt)    if (time->walt_digits[cnt] != NULL)      {	size_t len = wcslen ((wchar_t *) time->walt_digits[cnt]) + 1;	uint32_t *wstr = xmalloc (len * sizeof (uint32_t));	do	  wstr[len - 1] = bswap_32 (time->walt_digits[cnt][len - 1]);	while (len-- > 0);	time->walt_digits_ob[cnt] = wstr;      }}