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

📄 vfprintf.c

📁 绝对正真的stdio.h的实现
💻 C
📖 第 1 页 / 共 5 页
字号:
	LABEL (form_unknown):	  if (spec == L_('\0'))	    {	      /* The format string ended before the specifier is complete.  */	      done = -1;	      goto all_done;	    }	  /* If we are in the fast loop force entering the complicated	     one.  */	  goto do_positional;	}      /* The format is correctly handled.  */      ++nspecs_done;      if (__builtin_expect (workstart != NULL, 0))	free (workstart);      workstart = NULL;      /* Look for next format specifier.  */#ifdef COMPILE_WPRINTF      f = __find_specwc ((end_of_spec = ++f));#else      f = __find_specmb ((end_of_spec = ++f), &mbstate);#endif      /* Write the following constant string.  */      outstring (end_of_spec, f - end_of_spec);    }  while (*f != L_('\0'));  /* Unlock stream and return.  */  goto all_done;  /* Here starts the more complex loop to handle positional parameters.  */do_positional:  {    /* Array with information about the needed arguments.  This has to       be dynamically extensible.  */    size_t nspecs = 0;    size_t nspecs_max = 32;	/* A more or less arbitrary start value.  */    struct printf_spec *specs      = alloca (nspecs_max * sizeof (struct printf_spec));    /* The number of arguments the format string requests.  This will       determine the size of the array needed to store the argument       attributes.  */    size_t nargs = 0;    int *args_type;    union printf_arg *args_value = NULL;    /* Positional parameters refer to arguments directly.  This could       also determine the maximum number of arguments.  Track the       maximum number.  */    size_t max_ref_arg = 0;    /* Just a counter.  */    size_t cnt;    if (grouping == (const char *) -1)      {#ifdef COMPILE_WPRINTF	thousands_sep = _NL_CURRENT_WORD (LC_NUMERIC,					  _NL_NUMERIC_THOUSANDS_SEP_WC);#else	thousands_sep = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);#endif	grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);	if (*grouping == '\0' || *grouping == CHAR_MAX)	  grouping = NULL;      }    for (f = lead_str_end; *f != L_('\0'); f = specs[nspecs++].next_fmt)      {	if (nspecs >= nspecs_max)	  {	    /* Extend the array of format specifiers.  */	    struct printf_spec *old = specs;	    nspecs_max *= 2;	    specs = alloca (nspecs_max * sizeof (struct printf_spec));	    if (specs == &old[nspecs])	      /* Stack grows up, OLD was the last thing allocated;		 extend it.  */	      nspecs_max += nspecs_max / 2;	    else	      {		/* Copy the old array's elements to the new space.  */		memcpy (specs, old, nspecs * sizeof (struct printf_spec));		if (old == &specs[nspecs])		  /* Stack grows down, OLD was just below the new		     SPECS.  We can use that space when the new space		     runs out.  */		  nspecs_max += nspecs_max / 2;	      }	  }	/* Parse the format specifier.  */#ifdef COMPILE_WPRINTF	nargs += __parse_one_specwc (f, nargs, &specs[nspecs], &max_ref_arg);#else	nargs += __parse_one_specmb (f, nargs, &specs[nspecs], &max_ref_arg,				     &mbstate);#endif      }    /* Determine the number of arguments the format string consumes.  */    nargs = MAX (nargs, max_ref_arg);    /* Allocate memory for the argument descriptions.  */    args_type = alloca (nargs * sizeof (int));    memset (args_type, s->_flags2 & _IO_FLAGS2_FORTIFY ? '\xff' : '\0',	    nargs * sizeof (int));    args_value = alloca (nargs * sizeof (union printf_arg));    /* XXX Could do sanity check here: If any element in ARGS_TYPE is       still zero after this loop, format is invalid.  For now we       simply use 0 as the value.  */    /* Fill in the types of all the arguments.  */    for (cnt = 0; cnt < nspecs; ++cnt)      {	/* If the width is determined by an argument this is an int.  */	if (specs[cnt].width_arg != -1)	  args_type[specs[cnt].width_arg] = PA_INT;	/* If the precision is determined by an argument this is an int.  */	if (specs[cnt].prec_arg != -1)	  args_type[specs[cnt].prec_arg] = PA_INT;	switch (specs[cnt].ndata_args)	  {	  case 0:		/* No arguments.  */	    break;	  case 1:		/* One argument; we already have the type.  */	    args_type[specs[cnt].data_arg] = specs[cnt].data_arg_type;	    break;	  default:	    /* We have more than one argument for this format spec.	       We must call the arginfo function again to determine	       all the types.  */	    (void) (*__printf_arginfo_table[specs[cnt].info.spec])	      (&specs[cnt].info,	       specs[cnt].ndata_args, &args_type[specs[cnt].data_arg]);	    break;	  }      }    /* Now we know all the types and the order.  Fill in the argument       values.  */    for (cnt = 0; cnt < nargs; ++cnt)      switch (args_type[cnt])	{#define T(tag, mem, type)						      \	case tag:							      \	  args_value[cnt].mem = va_arg (ap_save, type);			      \	  break	T (PA_CHAR, pa_int, int); /* Promoted.  */	T (PA_WCHAR, pa_wchar, wint_t);	T (PA_INT|PA_FLAG_SHORT, pa_int, int); /* Promoted.  */	T (PA_INT, pa_int, int);	T (PA_INT|PA_FLAG_LONG, pa_long_int, long int);	T (PA_INT|PA_FLAG_LONG_LONG, pa_long_long_int, long long int);	T (PA_FLOAT, pa_double, double);	/* Promoted.  */	T (PA_DOUBLE, pa_double, double);	T (PA_DOUBLE|PA_FLAG_LONG_DOUBLE, pa_long_double, long double);	T (PA_STRING, pa_string, const char *);	T (PA_WSTRING, pa_wstring, const wchar_t *);	T (PA_POINTER, pa_pointer, void *);#undef T	default:	  if ((args_type[cnt] & PA_FLAG_PTR) != 0)	    args_value[cnt].pa_pointer = va_arg (ap_save, void *);	  else	    args_value[cnt].pa_long_double = 0.0;	  break;	case -1:	  /* Error case.  Not all parameters appear in N$ format	     strings.  We have no way to determine their type.  */	  assert (s->_flags2 & _IO_FLAGS2_FORTIFY);	  __libc_fatal ("*** invalid %N$ use detected ***\n");	}    /* Now walk through all format specifiers and process them.  */    for (; (size_t) nspecs_done < nspecs; ++nspecs_done)      {#undef REF#if defined HAVE_SUBTRACT_LOCAL_LABELS && defined SHARED# define REF(Name) &&do2_##Name - &&do_form_unknown#else# define REF(Name) &&do2_##Name#endif#undef LABEL#define LABEL(Name) do2_##Name	STEP4_TABLE;	int is_negative;	union	{	  unsigned long long int longlong;	  unsigned long int word;	} number;	int base;	union printf_arg the_arg;	CHAR_T *string;		/* Pointer to argument string.  */	/* Fill variables from values in struct.  */	int alt = specs[nspecs_done].info.alt;	int space = specs[nspecs_done].info.space;	int left = specs[nspecs_done].info.left;	int showsign = specs[nspecs_done].info.showsign;	int group = specs[nspecs_done].info.group;	int is_long_double = specs[nspecs_done].info.is_long_double;	int is_short = specs[nspecs_done].info.is_short;	int is_char = specs[nspecs_done].info.is_char;	int is_long = specs[nspecs_done].info.is_long;	int width = specs[nspecs_done].info.width;	int prec = specs[nspecs_done].info.prec;	int use_outdigits = specs[nspecs_done].info.i18n;	char pad = specs[nspecs_done].info.pad;	CHAR_T spec = specs[nspecs_done].info.spec;	CHAR_T *workstart = NULL;	/* Fill in last information.  */	if (specs[nspecs_done].width_arg != -1)	  {	    /* Extract the field width from an argument.  */	    specs[nspecs_done].info.width =	      args_value[specs[nspecs_done].width_arg].pa_int;	    if (specs[nspecs_done].info.width < 0)	      /* If the width value is negative left justification is		 selected and the value is taken as being positive.  */	      {		specs[nspecs_done].info.width *= -1;		left = specs[nspecs_done].info.left = 1;	      }	    width = specs[nspecs_done].info.width;	  }	if (specs[nspecs_done].prec_arg != -1)	  {	    /* Extract the precision from an argument.  */	    specs[nspecs_done].info.prec =	      args_value[specs[nspecs_done].prec_arg].pa_int;	    if (specs[nspecs_done].info.prec < 0)	      /* If the precision is negative the precision is		 omitted.  */	      specs[nspecs_done].info.prec = -1;	    prec = specs[nspecs_done].info.prec;	  }	/* Maybe the buffer is too small.  */	if (MAX (prec, width) + 32 > (int) (sizeof (work_buffer)					    / sizeof (CHAR_T)))	  {	    if (__libc_use_alloca ((MAX (prec, width) + 32)				   * sizeof (CHAR_T)))	      workend = ((CHAR_T *) alloca ((MAX (prec, width) + 32)					    * sizeof (CHAR_T))			 + (MAX (prec, width) + 32));	    else	      {		workstart = (CHAR_T *) malloc ((MAX (prec, width) + 32)					       * sizeof (CHAR_T));		workend = workstart + (MAX (prec, width) + 32);	      }	  }	/* Process format specifiers.  */	while (1)	  {	    JUMP (spec, step4_jumps);	    process_arg ((&specs[nspecs_done]));	    process_string_arg ((&specs[nspecs_done]));	  LABEL (form_unknown):	    {	      extern printf_function **__printf_function_table;	      int function_done;	      printf_function *function;	      unsigned int i;	      const void **ptr;	      function =		(__printf_function_table == NULL ? NULL :		 __printf_function_table[specs[nspecs_done].info.spec]);	      if (function == NULL)		function = &printf_unknown;	      ptr = alloca (specs[nspecs_done].ndata_args			    * sizeof (const void *));	      /* Fill in an array of pointers to the argument values.  */	      for (i = 0; i < specs[nspecs_done].ndata_args; ++i)		ptr[i] = &args_value[specs[nspecs_done].data_arg + i];	      /* Call the function.  */	      function_done = (*function) (s, &specs[nspecs_done].info, ptr);	      /* If an error occurred we don't have information about #		 of chars.  */	      if (function_done < 0)		{		  done = -1;		  goto all_done;		}	      done += function_done;	    }	    break;	  }	if (__builtin_expect (workstart != NULL, 0))	  free (workstart);	workstart = NULL;	/* Write the following constant string.  */	outstring (specs[nspecs_done].end_of_fmt,		   specs[nspecs_done].next_fmt		   - specs[nspecs_done].end_of_fmt);      }  }all_done:  if (__builtin_expect (workstart != NULL, 0))    free (workstart);  /* Unlock the stream.  */  _IO_funlockfile (s);  _IO_cleanup_region_end (0);  return done;}/* Handle an unknown format specifier.  This prints out a canonicalized   representation of the format spec itself.  */static intprintf_unknown (FILE *s, const struct printf_info *info,		const void *const *args){  int done = 0;  CHAR_T work_buffer[MAX (info->width, info->spec) + 32];  CHAR_T *const workend    = &work_buffer[sizeof (work_buffer) / sizeof (CHAR_T)];  register CHAR_T *w;  outchar (L_('%'));  if (info->alt)    outchar (L_('#'));  if (info->group)    outchar (L_('\''));  if (info->showsign)    outchar (L_('+'));  else if (info->space)    outchar (L_(' '));  if (info->left)    outchar (L_('-'));  if (info->pad == L_('0'))    outchar (L_('0'));  if (info->i18n)    outchar (L_('I'));  if (info->width != 0)    {      w = _itoa_word (info->width, workend, 10, 0);      while (w < workend)	outchar (*w++);    }  if (info->prec != -1)

⌨️ 快捷键说明

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