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

📄 vfprintf.c

📁 绝对正真的stdio.h的实现
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Copyright (C) 1991-2002, 2003, 2004 Free Software Foundation, Inc.   This file is part of the GNU C Library.   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 <ctype.h>#include <limits.h>#include <printf.h>#include <stdarg.h>#include <stdint.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <wchar.h>#include <bits/libc-lock.h>#include <sys/param.h>#include "_itoa.h"#include <locale/localeinfo.h>#include <stdio.h>/* This code is shared between the standard stdio implementation found   in GNU C library and the libio implementation originally found in   GNU libg++.   Beside this it is also shared between the normal and wide character   implementation as defined in ISO/IEC 9899:1990/Amendment 1:1995.  */#include <libioP.h>#define FILE		_IO_FILE#undef va_list#define va_list	_IO_va_list#undef BUFSIZ#define BUFSIZ		_IO_BUFSIZ#define ARGCHECK(S, Format) \  do									      \    {									      \      /* Check file argument for consistence.  */			      \      CHECK_FILE (S, -1);						      \      if (S->_flags & _IO_NO_WRITES)					      \	{								      \	  __set_errno (EBADF);						      \	  return -1;							      \	}								      \      if (Format == NULL)						      \	{								      \	  MAYBE_SET_EINVAL;						      \	  return -1;							      \	}								      \    } while (0)#define UNBUFFERED_P(S) ((S)->_IO_file_flags & _IO_UNBUFFERED)#ifndef COMPILE_WPRINTF# define vfprintf	_IO_vfprintf# define CHAR_T		char# define UCHAR_T	unsigned char# define INT_T		int# define L_(Str)	Str# define ISDIGIT(Ch)	((unsigned int) ((Ch) - '0') < 10)# define STR_LEN(Str)	strlen (Str)# define PUT(F, S, N)	_IO_sputn ((F), (S), (N))# define PAD(Padchar) \  if (width > 0)							      \    done += INTUSE(_IO_padn) (s, (Padchar), width)# define PUTC(C, F)	_IO_putc_unlocked (C, F)# define ORIENT		if (_IO_vtable_offset (s) == 0 && _IO_fwide (s, -1) != -1)\			  return -1#else# define vfprintf	_IO_vfwprintf# define CHAR_T		wchar_t/* This is a hack!!!  There should be a type uwchar_t.  */# define UCHAR_T	unsigned int /* uwchar_t */# define INT_T		wint_t# define L_(Str)	L##Str# define ISDIGIT(Ch)	((unsigned int) ((Ch) - L'0') < 10)# define STR_LEN(Str)	__wcslen (Str)# include "_itowa.h"# define PUT(F, S, N)	_IO_sputn ((F), (S), (N))# define PAD(Padchar) \  if (width > 0)							      \    done += _IO_wpadn (s, (Padchar), width)# define PUTC(C, F)	_IO_putwc_unlocked (C, F)# define ORIENT		if (_IO_fwide (s, 1) != 1) return -1# define _itoa(Val, Buf, Base, Case) _itowa (Val, Buf, Base, Case)# define _itoa_word(Val, Buf, Base, Case) _itowa_word (Val, Buf, Base, Case)# undef EOF# define EOF WEOF#endif#include "_i18n_number.h"/* Include the shared code for parsing the format string.  */#include "printf-parse.h"#define	outchar(Ch)							      \  do									      \    {									      \      register const INT_T outc = (Ch);					      \      if (PUTC (outc, s) == EOF)					      \	{								      \	  done = -1;							      \	  goto all_done;						      \	}								      \      else								      \	++done;								      \    }									      \  while (0)#define outstring(String, Len)						      \  do									      \    {									      \      if ((size_t) PUT (s, (String), (Len)) != (size_t) (Len))		      \	{								      \	  done = -1;							      \	  goto all_done;						      \	}								      \      done += (Len);							      \    }									      \  while (0)/* For handling long_double and longlong we use the same flag.  If   `long' and `long long' are effectively the same type define it to   zero.  */#if LONG_MAX == LONG_LONG_MAX# define is_longlong 0#else# define is_longlong is_long_double#endif/* If `long' and `int' is effectively the same type we don't have to   handle `long separately.  */#if INT_MAX == LONG_MAX# define is_long_num	0#else# define is_long_num	is_long#endif/* Global variables.  */static const CHAR_T null[] = L_("(null)");/* Helper function to provide temporary buffering for unbuffered streams.  */static int buffered_vfprintf (FILE *stream, const CHAR_T *fmt, va_list)     __THROW __attribute__ ((noinline)) internal_function;/* Handle unknown format specifier.  */static int printf_unknown (FILE *, const struct printf_info *,			   const void *const *) __THROW;/* Group digits of number string.  */#ifdef COMPILE_WPRINTFstatic CHAR_T *group_number (CHAR_T *, CHAR_T *, const char *, wchar_t)     __THROW internal_function;#elsestatic CHAR_T *group_number (CHAR_T *, CHAR_T *, const char *, const char *)     __THROW internal_function;#endif/* The function itself.  */intvfprintf (FILE *s, const CHAR_T *format, va_list ap){  /* The character used as thousands separator.  */#ifdef COMPILE_WPRINTF  wchar_t thousands_sep = L'\0';#else  const char *thousands_sep = NULL;#endif  /* The string describing the size of groups of digits.  */  const char *grouping;  /* Place to accumulate the result.  */  int done;  /* Current character in format string.  */  const UCHAR_T *f;  /* End of leading constant string.  */  const UCHAR_T *lead_str_end;  /* Points to next format specifier.  */  const UCHAR_T *end_of_spec;  /* Buffer intermediate results.  */  CHAR_T work_buffer[1000];  CHAR_T *workstart = NULL;  CHAR_T *workend;  /* State for restartable multibyte character handling functions.  */#ifndef COMPILE_WPRINTF  mbstate_t mbstate;#endif  /* We have to save the original argument pointer.  */  va_list ap_save;  /* Count number of specifiers we already processed.  */  int nspecs_done;  /* For the %m format we may need the current `errno' value.  */  int save_errno = errno;  /* 1 if format is in read-only memory, -1 if it is in writable memory,     0 if unknown.  */  int readonly_format = 0;  /* This table maps a character into a number representing a     class.  In each step there is a destination label for each     class.  */  static const int jump_table[] =  {    /* ' ' */  1,            0,            0, /* '#' */  4,	       0, /* '%' */ 14,            0, /* '\''*/  6,	       0,            0, /* '*' */  7, /* '+' */  2,	       0, /* '-' */  3, /* '.' */  9,            0,    /* '0' */  5, /* '1' */  8, /* '2' */  8, /* '3' */  8,    /* '4' */  8, /* '5' */  8, /* '6' */  8, /* '7' */  8,    /* '8' */  8, /* '9' */  8,            0,            0,	       0,            0,            0,            0,	       0, /* 'A' */ 26,            0, /* 'C' */ 25,	       0, /* 'E' */ 19, /* F */   19, /* 'G' */ 19,	       0, /* 'I' */ 29,            0,            0,    /* 'L' */ 12,            0,            0,            0,	       0,            0,            0, /* 'S' */ 21,	       0,            0,            0,            0,    /* 'X' */ 18,            0, /* 'Z' */ 13,            0,	       0,            0,            0,            0,	       0, /* 'a' */ 26,            0, /* 'c' */ 20,    /* 'd' */ 15, /* 'e' */ 19, /* 'f' */ 19, /* 'g' */ 19,    /* 'h' */ 10, /* 'i' */ 15, /* 'j' */ 28,            0,    /* 'l' */ 11, /* 'm' */ 24, /* 'n' */ 23, /* 'o' */ 17,    /* 'p' */ 22, /* 'q' */ 12,            0, /* 's' */ 21,    /* 't' */ 27, /* 'u' */ 16,            0,            0,    /* 'x' */ 18,            0, /* 'z' */ 13  };#define NOT_IN_JUMP_RANGE(Ch) ((Ch) < L_(' ') || (Ch) > L_('z'))#define CHAR_CLASS(Ch) (jump_table[(INT_T) (Ch) - L_(' ')])#if defined HAVE_SUBTRACT_LOCAL_LABELS && defined SHARED  /* 'int' is enough and it saves some space on 64 bit systems.  */# define JUMP_TABLE_TYPE const int# define JUMP(ChExpr, table)						      \      do								      \	{								      \	  int offset;							      \	  void *__unbounded ptr;					      \	  spec = (ChExpr);						      \	  offset = NOT_IN_JUMP_RANGE (spec) ? REF (form_unknown)	      \	    : table[CHAR_CLASS (spec)];					      \	  ptr = &&do_form_unknown + offset;				      \	  goto *ptr;							      \	}								      \      while (0)#else# define JUMP_TABLE_TYPE const void *const# define JUMP(ChExpr, table)						      \      do								      \	{								      \	  const void *__unbounded ptr;					      \	  spec = (ChExpr);						      \	  ptr = NOT_IN_JUMP_RANGE (spec) ? REF (form_unknown)		      \	    : table[CHAR_CLASS (spec)];					      \	  goto *ptr;							      \	}								      \      while (0)#endif#define STEP0_3_TABLE							      \    /* Step 0: at the beginning.  */					      \    static JUMP_TABLE_TYPE step0_jumps[30] =				      \    {									      \      REF (form_unknown),						      \      REF (flag_space),		/* for ' ' */				      \      REF (flag_plus),		/* for '+' */				      \      REF (flag_minus),		/* for '-' */				      \      REF (flag_hash),		/* for '<hash>' */			      \      REF (flag_zero),		/* for '0' */				      \      REF (flag_quote),		/* for '\'' */				      \      REF (width_asterics),	/* for '*' */				      \      REF (width),		/* for '1'...'9' */			      \      REF (precision),		/* for '.' */				      \      REF (mod_half),		/* for 'h' */				      \      REF (mod_long),		/* for 'l' */				      \      REF (mod_longlong),	/* for 'L', 'q' */			      \      REF (mod_size_t),		/* for 'z', 'Z' */			      \      REF (form_percent),	/* for '%' */				      \      REF (form_integer),	/* for 'd', 'i' */			      \      REF (form_unsigned),	/* for 'u' */				      \      REF (form_octal),		/* for 'o' */				      \      REF (form_hexa),		/* for 'X', 'x' */			      \      REF (form_float),		/* for 'E', 'e', 'F', 'f', 'G', 'g' */	      \      REF (form_character),	/* for 'c' */				      \      REF (form_string),	/* for 's', 'S' */			      \      REF (form_pointer),	/* for 'p' */				      \      REF (form_number),	/* for 'n' */				      \      REF (form_strerror),	/* for 'm' */				      \      REF (form_wcharacter),	/* for 'C' */				      \      REF (form_floathex),	/* for 'A', 'a' */			      \      REF (mod_ptrdiff_t),      /* for 't' */				      \      REF (mod_intmax_t),       /* for 'j' */				      \      REF (flag_i18n),	        /* for 'I' */				      \    };									      \    /* Step 1: after processing width.  */				      \    static JUMP_TABLE_TYPE step1_jumps[30] =				      \    {									      \      REF (form_unknown),						      \      REF (form_unknown),	/* for ' ' */				      \      REF (form_unknown),	/* for '+' */				      \      REF (form_unknown),	/* for '-' */				      \      REF (form_unknown),	/* for '<hash>' */			      \      REF (form_unknown),	/* for '0' */				      \      REF (form_unknown),	/* for '\'' */				      \      REF (form_unknown),	/* for '*' */				      \      REF (form_unknown),	/* for '1'...'9' */			      \      REF (precision),		/* for '.' */				      \      REF (mod_half),		/* for 'h' */				      \      REF (mod_long),		/* for 'l' */				      \      REF (mod_longlong),	/* for 'L', 'q' */			      \      REF (mod_size_t),		/* for 'z', 'Z' */			      \      REF (form_percent),	/* for '%' */				      \      REF (form_integer),	/* for 'd', 'i' */			      \      REF (form_unsigned),	/* for 'u' */				      \      REF (form_octal),		/* for 'o' */				      \      REF (form_hexa),		/* for 'X', 'x' */			      \      REF (form_float),		/* for 'E', 'e', 'F', 'f', 'G', 'g' */	      \      REF (form_character),	/* for 'c' */				      \      REF (form_string),	/* for 's', 'S' */			      \      REF (form_pointer),	/* for 'p' */				      \      REF (form_number),	/* for 'n' */				      \      REF (form_strerror),	/* for 'm' */				      \      REF (form_wcharacter),	/* for 'C' */				      \      REF (form_floathex),	/* for 'A', 'a' */			      \      REF (mod_ptrdiff_t),      /* for 't' */				      \      REF (mod_intmax_t),       /* for 'j' */				      \      REF (form_unknown)        /* for 'I' */				      \    };									      \    /* Step 2: after processing precision.  */				      \    static JUMP_TABLE_TYPE step2_jumps[30] =				      \    {									      \      REF (form_unknown),						      \      REF (form_unknown),	/* for ' ' */				      \      REF (form_unknown),	/* for '+' */				      \      REF (form_unknown),	/* for '-' */				      \      REF (form_unknown),	/* for '<hash>' */			      \      REF (form_unknown),	/* for '0' */				      \      REF (form_unknown),	/* for '\'' */				      \      REF (form_unknown),	/* for '*' */				      \      REF (form_unknown),	/* for '1'...'9' */			      \      REF (form_unknown),	/* for '.' */				      \      REF (mod_half),		/* for 'h' */				      \      REF (mod_long),		/* for 'l' */				      \      REF (mod_longlong),	/* for 'L', 'q' */			      \      REF (mod_size_t),		/* for 'z', 'Z' */			      \      REF (form_percent),	/* for '%' */				      \      REF (form_integer),	/* for 'd', 'i' */			      \      REF (form_unsigned),	/* for 'u' */				      \      REF (form_octal),		/* for 'o' */				      \      REF (form_hexa),		/* for 'X', 'x' */			      \      REF (form_float),		/* for 'E', 'e', 'F', 'f', 'G', 'g' */	      \      REF (form_character),	/* for 'c' */				      \      REF (form_string),	/* for 's', 'S' */			      \      REF (form_pointer),	/* for 'p' */				      \      REF (form_number),	/* for 'n' */				      \

⌨️ 快捷键说明

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