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

📄 printf.def

📁 android-w.song.android.widget
💻 DEF
📖 第 1 页 / 共 2 页
字号:
This file is printf.def, from which is created printf.c.It implements the builtin "printf" in Bash.Copyright (C) 1997-2010 Free Software Foundation, Inc.This file is part of GNU Bash, the Bourne Again SHell.Bash is free software: you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation, either version 3 of the License, or(at your option) any later version.Bash is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with Bash.  If not, see <http://www.gnu.org/licenses/>.$PRODUCES printf.c$BUILTIN printf$FUNCTION printf_builtin$SHORT_DOC printf [-v var] format [arguments]Formats and prints ARGUMENTS under control of the FORMAT.Options:  -v var	assign the output to shell variable VAR rather than		display it on the standard outputFORMAT is a character string which contains three types of objects: plaincharacters, which are simply copied to standard output; character escapesequences, which are converted and copied to the standard output; andformat specifications, each of which causes printing of the next successiveargument.In addition to the standard format specifications described in printf(1)and printf(3), printf interprets:  %b	expand backslash escape sequences in the corresponding argument  %q	quote the argument in a way that can be reused as shell input  %(fmt)T output the date-time string resulting from using FMT as a format        string for strftime(3)Exit Status:Returns success unless an invalid option is given or a write or assignmenterror occurs.$END#include <config.h>#include "../bashtypes.h"#include <errno.h>#if defined (HAVE_LIMITS_H)#  include <limits.h>#else   /* Assume 32-bit ints. */#  define INT_MAX		2147483647#  define INT_MIN		(-2147483647-1)#endif#if defined (PREFER_STDARG)#  include <stdarg.h>#else#  include <varargs.h>#endif#include <stdio.h>#include <chartypes.h>#ifdef HAVE_INTTYPES_H#  include <inttypes.h>#endif#include "posixtime.h"#include "../bashansi.h"#include "../bashintl.h"#define NEED_STRFTIME_DECL#include "../shell.h"#include "shmbutil.h"#include "stdc.h"#include "bashgetopt.h"#include "common.h"#if defined (PRI_MACROS_BROKEN)#  undef PRIdMAX#endif#if !defined (PRIdMAX)#  if HAVE_LONG_LONG#    define PRIdMAX	"lld"#  else#    define PRIdMAX	"ld"#  endif#endif#if !defined (errno)extern int errno;#endif#define PC(c) \  do { \    char b[2]; \    tw++; \    b[0] = c; b[1] = '\0'; \    if (vflag) \      vbadd (b, 1); \    else \      putchar (c); \  } while (0)#define PF(f, func) \  do { \    int nw; \    clearerr (stdout); \    if (have_fieldwidth && have_precision) \      nw = vflag ? vbprintf (f, fieldwidth, precision, func) : printf (f, fieldwidth, precision, func); \    else if (have_fieldwidth) \      nw = vflag ? vbprintf (f, fieldwidth, func) : printf (f, fieldwidth, func); \    else if (have_precision) \      nw = vflag ? vbprintf (f, precision, func) : printf (f, precision, func); \    else \      nw = vflag ? vbprintf (f, func) : printf (f, func); \    tw += nw; \    if (ferror (stdout)) \      { \	sh_wrerror (); \	clearerr (stdout); \	return (EXECUTION_FAILURE); \      } \  } while (0)/* We free the buffer used by mklong() if it's `too big'. */#define PRETURN(value) \  do \    { \      if (vflag) \	{ \	  bind_printf_variable  (vname, vbuf, 0); \	  stupidly_hack_special_variables (vname); \	} \      if (conv_bufsize > 4096 ) \	{ \	  free (conv_buf); \	  conv_bufsize = 0; \	  conv_buf = 0; \	} \      if (vbsize > 4096) \	{ \	  free (vbuf); \	  vbsize = 0; \	  vbuf = 0; \	} \      else if (vbuf) \	vbuf[0] = 0; \      terminate_immediately--; \      fflush (stdout); \      if (ferror (stdout)) \	{ \	  sh_wrerror (); \	  clearerr (stdout); \	  return (EXECUTION_FAILURE); \	} \      return (value); \    } \  while (0)#define SKIP1 "#'-+ 0"#define LENMODS "hjlLtz"extern time_t shell_start_time;#if !HAVE_ASPRINTFextern int asprintf __P((char **, const char *, ...)) __attribute__((__format__ (printf, 2, 3)));#endif#if !HAVE_VSNPRINTFextern int vsnprintf __P((char *, size_t, const char *, va_list)) __attribute__((__format__ (printf, 3, 0)));#endifstatic void printf_erange __P((char *));static int printstr __P((char *, char *, int, int, int));static int tescape __P((char *, char *, int *, int *));static char *bexpand __P((char *, int, int *, int *));static char *vbadd __P((char *, int));static int vbprintf __P((const char *, ...)) __attribute__((__format__ (printf, 1, 2)));static char *mklong __P((char *, char *, size_t));static int getchr __P((void));static char *getstr __P((void));static int  getint __P((void));static intmax_t getintmax __P((void));static uintmax_t getuintmax __P((void));static SHELL_VAR *bind_printf_variable __P((char *, char *, int));#if defined (HAVE_LONG_DOUBLE) && HAVE_DECL_STRTOLD && !defined(STRTOLD_BROKEN)typedef long double floatmax_t;#  define FLOATMAX_CONV	"L"#  define strtofltmax	strtold#elsetypedef double floatmax_t;#  define FLOATMAX_CONV	""#  define strtofltmax	strtod#endifstatic floatmax_t getfloatmax __P((void));static intmax_t asciicode __P((void));static WORD_LIST *garglist;static int retval;static int conversion_error;/* printf -v var support */static int vflag = 0;static char *vbuf, *vname;static size_t vbsize;static int vblen;static intmax_t tw;static char *conv_buf;static size_t conv_bufsize;intprintf_builtin (list)     WORD_LIST *list;{  int ch, fieldwidth, precision;  int have_fieldwidth, have_precision;  char convch, thisch, nextch, *format, *modstart, *fmt, *start;#if defined (HANDLE_MULTIBYTE)  char mbch[25];		/* 25 > MB_LEN_MAX, plus can handle 4-byte UTF-8 and large Unicode characters*/  int mbind, mblen;#endif  conversion_error = 0;  retval = EXECUTION_SUCCESS;  vflag = 0;  reset_internal_getopt ();  while ((ch = internal_getopt (list, "v:")) != -1)    {      switch (ch)	{	case 'v':	  vname = list_optarg;#if defined (ARRAY_VARS)	  if (legal_identifier (vname) || valid_array_reference (vname))#else	  if (legal_identifier (vname))#endif	    {	      vflag = 1;	      vblen = 0;	      if (vbuf)		vbuf[0] = 0;	    }	  else	    {	      sh_invalidid (vname);	      return (EX_USAGE);	    }	  break;	default:	  builtin_usage ();	  return (EX_USAGE);	}    }  list = loptend;	/* skip over possible `--' */  if (list == 0)    {      builtin_usage ();      return (EX_USAGE);    }  if (list->word->word == 0 || list->word->word[0] == '\0')    return (EXECUTION_SUCCESS);  format = list->word->word;  tw = 0;  garglist = list->next;  /* If the format string is empty after preprocessing, return immediately. */  if (format == 0 || *format == 0)    return (EXECUTION_SUCCESS);  terminate_immediately++;	    /* Basic algorithm is to scan the format string for conversion     specifications -- once one is found, find out if the field     width or precision is a '*'; if it is, gather up value.  Note,     format strings are reused as necessary to use up the provided     arguments, arguments of zero/null string are provided to use     up the format string. */  do    {      tw = 0;      /* find next format specification */      for (fmt = format; *fmt; fmt++)	{	  precision = fieldwidth = 0;	  have_fieldwidth = have_precision = 0;	  if (*fmt == '\\')	    {	      fmt++;	      /* A NULL third argument to tescape means to bypass the		 special processing for arguments to %b. */#if defined (HANDLE_MULTIBYTE)	      /* Accommodate possible use of \u or \U, which can result in		 multibyte characters */	      memset (mbch, '\0', sizeof (mbch));	      fmt += tescape (fmt, mbch, &mblen, (int *)NULL);	      for (mbind = 0; mbind < mblen; mbind++)	        PC (mbch[mbind]);#else	      fmt += tescape (fmt, &nextch, (int *)NULL, (int *)NULL);	      PC (nextch);#endif	      fmt--;	/* for loop will increment it for us again */	      continue;	    }	  if (*fmt != '%')	    {	      PC (*fmt);	      continue;	    }	  /* ASSERT(*fmt == '%') */	  start = fmt++;	  if (*fmt == '%')		/* %% prints a % */	    {	      PC ('%');	      continue;	    }	  /* found format specification, skip to field width */	  for (; *fmt && strchr(SKIP1, *fmt); ++fmt)	    ;	  /* Skip optional field width. */	  if (*fmt == '*')	    {	      fmt++;	      have_fieldwidth = 1;	      fieldwidth = getint ();	    }	  else	    while (DIGIT (*fmt))	      fmt++;	  /* Skip optional '.' and precision */	  if (*fmt == '.')	    {	      ++fmt;	      if (*fmt == '*')		{		  fmt++;		  have_precision = 1;		  precision = getint ();		}	      else		{		  /* Negative precisions are allowed but treated as if the		     precision were missing; I would like to allow a leading		     `+' in the precision number as an extension, but lots		     of asprintf/fprintf implementations get this wrong. */#if 0		  if (*fmt == '-' || *fmt == '+')#else		  if (*fmt == '-')#endif		    fmt++;		  while (DIGIT (*fmt))		    fmt++;		}	    }	  /* skip possible format modifiers */	  modstart = fmt;	  while (*fmt && strchr (LENMODS, *fmt))	    fmt++;	    	  if (*fmt == 0)	    {	      builtin_error (_("`%s': missing format character"), start);	      PRETURN (EXECUTION_FAILURE);	    }	  convch = *fmt;	  thisch = modstart[0];	  nextch = modstart[1];	  modstart[0] = convch;	  modstart[1] = '\0';	  switch(convch)	    {	    case 'c':	      {		char p;		p = getchr ();		PF(start, p);		break;	      }	    case 's':	      {		char *p;		p = getstr ();		PF(start, p);		break;	      }	    case '(':	      {		char *timefmt, timebuf[128], *t;		int n;		intmax_t arg;		time_t secs;		struct tm *tm;		modstart[1] = nextch;	/* restore char after left paren */		timefmt = xmalloc (strlen (fmt) + 3);		fmt++;	/* skip over left paren */		for (t = timefmt, n = 1; *fmt; )		  {		    if (*fmt == '(')		      n++;		    else if (*fmt == ')')		      n--;		    if (n == 0)		      break;		    *t++ = *fmt++;		  }		*t = '\0';		if (*++fmt != 'T')		  {		    builtin_warning (_("`%c': invalid time format specification"), *fmt);		    fmt = start;		    free (timefmt);		    PC (*fmt);		    continue;		  }		if (timefmt[0] == '\0')		  {		    timefmt[0] = '%';		    timefmt[1] = 'X';	/* locale-specific current time - should we use `+'? */		    timefmt[2] = '\0';		  }		/* argument is seconds since the epoch with special -1 and -2 */		arg = getintmax ();		if (arg == -1)		  secs = NOW;		/* roughly date +%s */		else if (arg == -2)		  secs = shell_start_time;	/* roughly $SECONDS */		else		  secs = arg;		tm = localtime (&secs);		n = strftime (timebuf, sizeof (timebuf), timefmt, tm);		free (timefmt);		if (n == 0)		  timebuf[0] = '\0';		else		  timebuf[sizeof(timebuf) - 1] = '\0';		/* convert to %s format that preserves fieldwidth and precision */		modstart[0] = 's';		modstart[1] = '\0';		n = printstr (start, timebuf, strlen (timebuf), fieldwidth, precision);	/* XXX - %s for now */		if (n < 0)		  {		    sh_wrerror ();		    clearerr (stdout);		    PRETURN (EXECUTION_FAILURE);		  }		break;	      }	    case 'n':	      {		char *var;		var = getstr ();		if (var && *var)		  {		    if (legal_identifier (var))		      bind_var_to_int (var, tw);		    else		      {			sh_invalidid (var);			PRETURN (EXECUTION_FAILURE);		      }		  }		break;	      }	    case 'b':		/* expand escapes in argument */	      {		char *p, *xp;		int rlen, r;		p = getstr ();		ch = rlen = r = 0;		xp = bexpand (p, strlen (p), &ch, &rlen);		if (xp)		  {		    /* Have to use printstr because of possible NUL bytes		       in XP -- printf does not handle that well. */		    r = printstr (start, xp, rlen, fieldwidth, precision);		    if (r < 0)		      {		        sh_wrerror ();			clearerr (stdout);		        retval = EXECUTION_FAILURE;		      }		    free (xp);		  }		if (ch || r < 0)		  PRETURN (retval);		break;	      }	    case 'q':		/* print with shell quoting */	      {		char *p, *xp;		int r;		r = 0;		p = getstr ();		if (p && *p == 0)	/* XXX - getstr never returns null */		  xp = savestring ("''");		else if (ansic_shouldquote (p))		  xp = ansic_quote (p, 0, (int *)0);		else		  xp = sh_backslash_quote (p);		if (xp)		  {		    /* Use printstr to get fieldwidth and precision right. */		    r = printstr (start, xp, strlen (xp), fieldwidth, precision);		    if (r < 0)		      {			sh_wrerror ();			clearerr (stdout);		      }		    free (xp);		  }		if (r < 0)		  PRETURN (EXECUTION_FAILURE);		break;	      }	    case 'd':	    case 'i':	      {		char *f;		long p;		intmax_t pp;		p = pp = getintmax ();		if (p != pp)		  {		    f = mklong (start, PRIdMAX, sizeof (PRIdMAX) - 2);		    PF (f, pp);		  }		else		  {		    /* Optimize the common case where the integer fits		       in "long".  This also works around some long		       long and/or intmax_t library bugs in the common		       case, e.g. glibc 2.2 x86.  */		    f = mklong (start, "l", 1);		    PF (f, p);		  }		break;	      }	    case 'o':	    case 'u':	    case 'x':	    case 'X':	      {		char *f;		unsigned long p;		uintmax_t pp;		p = pp = getuintmax ();		if (p != pp)		  {		    f = mklong (start, PRIdMAX, sizeof (PRIdMAX) - 2);		    PF (f, pp);		  }		else		  {		    f = mklong (start, "l", 1);		    PF (f, p);		  }		break;	      }	    case 'e':	    case 'E':	    case 'f':	    case 'F':	    case 'g':	    case 'G':#if defined (HAVE_PRINTF_A_FORMAT)

⌨️ 快捷键说明

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