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

📄 mprintf.c

📁 harvest是一个下载html网页得机器人
💻 C
📖 第 1 页 / 共 2 页
字号:
/**************************************************************************** * * $Id: mprintf.c,v 1.27 2003/10/26 15:37:45 bagder Exp $ * ************************************************************************* * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. * * Purpose: *  A merge of Bjorn Reese's format() function and Daniel's dsprintf() *  1.0. A full blooded printf() clone with full support for <num>$ *  everywhere (parameters, widths and precisions) including variabled *  sized parameters (like doubles, long longs, long doubles and even *  void * in 64-bit architectures). * * Current restrictions: * - Max 128 parameters * - No 'long double' support. * * If you ever want truly portable and good *printf() clones, the project that * took on from here is named 'Trio' and you find more details on the trio web * page at http://daniel.haxx.se/trio/ */#include "setup.h"#include <sys/types.h>#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <ctype.h>#include <string.h>#ifndef SIZEOF_LONG_DOUBLE#define SIZEOF_LONG_DOUBLE 0#endif/* The last #include file should be: */#ifdef CURLDEBUG#include "memdebug.h"#endif#define BUFFSIZE 256 /* buffer for long-to-str and float-to-str calcs */#define MAX_PARAMETERS 128 /* lame static limit */#undef TRUE#undef FALSE#undef BOOL#ifdef __cplusplus# define TRUE true# define FALSE false# define BOOL bool#else# define TRUE  ((char)(1 == 1))# define FALSE ((char)(0 == 1))# define BOOL char#endif/* Lower-case digits.  */static const char lower_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";/* Upper-case digits.  */static const char upper_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";#define	OUTCHAR(x) done+=(stream(x, (FILE *)data)==-1?0:1)/* Data type to read from the arglist */typedef enum  {  FORMAT_UNKNOWN = 0,  FORMAT_STRING,  FORMAT_PTR,  FORMAT_INT,  FORMAT_INTPTR,  FORMAT_LONG,  FORMAT_LONGLONG,  FORMAT_DOUBLE,  FORMAT_LONGDOUBLE,  FORMAT_WIDTH /* For internal use */} FormatType;/* convertion and display flags */enum {  FLAGS_NEW        = 0,  FLAGS_SPACE      = 1<<0,  FLAGS_SHOWSIGN   = 1<<1,  FLAGS_LEFT       = 1<<2,  FLAGS_ALT        = 1<<3,  FLAGS_SHORT      = 1<<4,  FLAGS_LONG       = 1<<5,  FLAGS_LONGLONG   = 1<<6,  FLAGS_LONGDOUBLE = 1<<7,  FLAGS_PAD_NIL    = 1<<8,  FLAGS_UNSIGNED   = 1<<9,  FLAGS_OCTAL      = 1<<10,  FLAGS_HEX        = 1<<11,  FLAGS_UPPER      = 1<<12,  FLAGS_WIDTH      = 1<<13, /* '*' or '*<num>$' used */  FLAGS_WIDTHPARAM = 1<<14, /* width PARAMETER was specified */  FLAGS_PREC       = 1<<15, /* precision was specified */  FLAGS_PRECPARAM  = 1<<16, /* precision PARAMETER was specified */  FLAGS_CHAR       = 1<<17, /* %c story */  FLAGS_FLOATE     = 1<<18, /* %e or %E */  FLAGS_FLOATG     = 1<<19  /* %g or %G */};typedef struct {  FormatType type;  int flags;  int width;     /* width OR width parameter number */  int precision; /* precision OR precision parameter number */  union {    char *str;    void *ptr;    long num;#ifdef HAVE_LONGLONG    long long lnum;#endif    double dnum;#if SIZEOF_LONG_DOUBLE    long double ldnum;#endif  } data;} va_stack_t;struct nsprintf {  char *buffer;  size_t length;  size_t max;};struct asprintf {  char *buffer; /* allocated buffer */  size_t len;   /* length of string */  size_t alloc; /* length of alloc */};int curl_msprintf(char *buffer, const char *format, ...);static int dprintf_DollarString(char *input, char **end){  int number=0;  while(isdigit((int)*input)) {    number *= 10;    number += *input-'0';    input++;  }  if(number && ('$'==*input++)) {    *end = input;    return number;  }  return 0;}static BOOL dprintf_IsQualifierNoDollar(char c){  switch (c) {  case '-': case '+': case ' ': case '#': case '.':  case '0': case '1': case '2': case '3': case '4':  case '5': case '6': case '7': case '8': case '9':  case 'h': case 'l': case 'L': case 'Z': case 'q':  case '*':    return TRUE;  default:    return FALSE;  }}#ifdef DPRINTF_DEBUG2int dprintf_Pass1Report(va_stack_t *vto, int max){  int i;  char buffer[128];  int bit;  int flags;  for(i=0; i<max; i++) {    char *type;    switch(vto[i].type) {    case FORMAT_UNKNOWN:      type = "unknown";      break;    case FORMAT_STRING:      type ="string";      break;    case FORMAT_PTR:      type ="pointer";      break;    case FORMAT_INT:      type = "int";      break;    case FORMAT_LONG:      type = "long";      break;    case FORMAT_LONGLONG:      type = "long long";      break;    case FORMAT_DOUBLE:      type = "double";      break;    case FORMAT_LONGDOUBLE:      type = "long double";      break;          }    buffer[0]=0;    for(bit=0; bit<31; bit++) {      flags = vto[i].flags & (1<<bit);      if(flags & FLAGS_SPACE)	strcat(buffer, "space ");      else if(flags & FLAGS_SHOWSIGN)	strcat(buffer, "plus ");      else if(flags & FLAGS_LEFT)	strcat(buffer, "left ");      else if(flags & FLAGS_ALT)	strcat(buffer, "alt ");      else if(flags & FLAGS_SHORT)	strcat(buffer, "short ");      else if(flags & FLAGS_LONG)	strcat(buffer, "long ");      else if(flags & FLAGS_LONGLONG)	strcat(buffer, "longlong ");      else if(flags & FLAGS_LONGDOUBLE)	strcat(buffer, "longdouble ");      else if(flags & FLAGS_PAD_NIL)	strcat(buffer, "padnil ");      else if(flags & FLAGS_UNSIGNED)	strcat(buffer, "unsigned ");      else if(flags & FLAGS_OCTAL)	strcat(buffer, "octal ");      else if(flags & FLAGS_HEX)	strcat(buffer, "hex ");      else if(flags & FLAGS_UPPER)	strcat(buffer, "upper ");      else if(flags & FLAGS_WIDTH)	strcat(buffer, "width ");      else if(flags & FLAGS_WIDTHPARAM)	strcat(buffer, "widthparam ");      else if(flags & FLAGS_PREC)	strcat(buffer, "precision ");      else if(flags & FLAGS_PRECPARAM)	strcat(buffer, "precparam ");      else if(flags & FLAGS_CHAR)	strcat(buffer, "char ");      else if(flags & FLAGS_FLOATE)	strcat(buffer, "floate ");      else if(flags & FLAGS_FLOATG)	strcat(buffer, "floatg ");    }    printf("REPORT: %d. %s [%s]\n", i, type, buffer);  }}#endif/****************************************************************** * * Pass 1: * Create an index with the type of each parameter entry and its * value (may vary in size) * ******************************************************************/static int dprintf_Pass1(char *format, va_stack_t *vto, char **endpos, va_list arglist){  char *fmt = format;  int param_num = 0;  int this_param;  int width;  int precision;  int flags;  int max_param=0;  int i;  while (*fmt) {    if (*fmt++ == '%') {      if (*fmt == '%') {	fmt++;	continue; /* while */      }      flags = FLAGS_NEW;      /* Handle the positional case (N$) */      param_num++;            this_param = dprintf_DollarString(fmt, &fmt);      if (0 == this_param)	/* we got no positional, get the next counter */	this_param = param_num;      if (this_param > max_param)	max_param = this_param;      /*       * The parameter with number 'i' should be used. Next, we need       * to get SIZE and TYPE of the parameter. Add the information       * to our array.       */      width = 0;      precision = 0;      /* Handle the flags */      while (dprintf_IsQualifierNoDollar(*fmt)) {	switch (*fmt++) {	case ' ':	  flags |= FLAGS_SPACE;	  break;	case '+':	  flags |= FLAGS_SHOWSIGN;	  break;	case '-':	  flags |= FLAGS_LEFT;	  flags &= ~FLAGS_PAD_NIL;	  break;	case '#':	  flags |= FLAGS_ALT;	  break;	case '.':	  flags |= FLAGS_PREC;	  if ('*' == *fmt) {	    /* The precision is picked from a specified parameter */	    flags |= FLAGS_PRECPARAM;	    fmt++;	    param_num++;	    i = dprintf_DollarString(fmt, &fmt);	    if (i)	      precision = i;	    else	      precision = param_num;	    if (precision > max_param)	      max_param = precision;       	  }	  else {	    flags |= FLAGS_PREC;	    precision = strtol(fmt, &fmt, 10);	  }	  break;	case 'h':	  flags |= FLAGS_SHORT;	  break;	case 'l':	  if (flags & FLAGS_LONG)	    flags |= FLAGS_LONGLONG;	  else	    flags |= FLAGS_LONG;	  break;	case 'L':	  flags |= FLAGS_LONGDOUBLE;	  break;	case 'q':	  flags |= FLAGS_LONGLONG;	  break;	case 'Z':	  if (sizeof(size_t) > sizeof(unsigned long int))	    flags |= FLAGS_LONGLONG;	  if (sizeof(size_t) > sizeof(unsigned int))	    flags |= FLAGS_LONG;	  break;	case '0':	  if (!(flags & FLAGS_LEFT))	    flags |= FLAGS_PAD_NIL;	  /* FALLTHROUGH */	case '1': case '2': case '3': case '4':	case '5': case '6': case '7': case '8': case '9':	  flags |= FLAGS_WIDTH;	  width = strtol(fmt-1, &fmt, 10);	  break;	case '*':  /* Special case */	  flags |= FLAGS_WIDTHPARAM;	  param_num++;	  	  i = dprintf_DollarString(fmt, &fmt);	  if(i)	    width = i;	  else	    width = param_num;	  if(width > max_param)	    max_param=width;	  break;	default:	  break;	}      } /* switch */      /* Handle the specifier */      i = this_param - 1;      switch (*fmt) {      case 'S':	flags |= FLAGS_ALT;	/* FALLTHROUGH */      case 's':	vto[i].type = FORMAT_STRING;	break;      case 'n':	vto[i].type = FORMAT_INTPTR;	break;      case 'p':	vto[i].type = FORMAT_PTR;	break;      case 'd': case 'i':	vto[i].type = FORMAT_INT;	break;      case 'u':	vto[i].type = FORMAT_INT;	flags |= FLAGS_UNSIGNED;	break;      case 'o':	vto[i].type = FORMAT_INT;	flags |= FLAGS_OCTAL;	break;      case 'x':	vto[i].type = FORMAT_INT;	flags |= FLAGS_HEX;	break;      case 'X':	vto[i].type = FORMAT_INT;	flags |= FLAGS_HEX|FLAGS_UPPER;	break;      case 'c':	vto[i].type = FORMAT_INT;	flags |= FLAGS_CHAR;	break;	      case 'f':	vto[i].type = FORMAT_DOUBLE;	break;      case 'e': case 'E':	vto[i].type = FORMAT_DOUBLE;	flags |= FLAGS_FLOATE| (('E' == *fmt)?FLAGS_UPPER:0);	break;      case 'g': case 'G':	vto[i].type = FORMAT_DOUBLE;	flags |= FLAGS_FLOATG| (('G' == *fmt)?FLAGS_UPPER:0);	break;	      default:	vto[i].type = FORMAT_UNKNOWN;	break;      } /* switch */      vto[i].flags = flags;      vto[i].width = width;      vto[i].precision = precision;            if (flags & FLAGS_WIDTHPARAM) {	/* we have the width specified from a parameter, so we make that	   parameter's info setup properly */	vto[i].width = width - 1;	i = width - 1;	vto[i].type = FORMAT_WIDTH;	vto[i].flags = FLAGS_NEW;	vto[i].precision = vto[i].width = 0; /* can't use width or precision						of width! */	      }      if (flags & FLAGS_PRECPARAM) {	/* we have the precision specified from a parameter, so we make that	   parameter's info setup properly */	vto[i].precision = precision - 1;	i = precision - 1;	vto[i].type = FORMAT_WIDTH;	vto[i].flags = FLAGS_NEW;	vto[i].precision = vto[i].width = 0; /* can't use width or precision						of width! */      }      *endpos++ = fmt + 1; /* end of this sequence */    }  }#ifdef DPRINTF_DEBUG2  dprintf_Pass1Report(vto, max_param);#endif  /* Read the arg list parameters into our data list */  for (i=0; i<max_param; i++) {    if ((i + 1 < max_param) && (vto[i + 1].type == FORMAT_WIDTH))      {	/* Width/precision arguments must be read before the main argument	 * they are attached to	 */	vto[i + 1].data.num = va_arg(arglist, int);      }    switch (vto[i].type)      {      case FORMAT_STRING:	vto[i].data.str = va_arg(arglist, char *);	break;	      case FORMAT_INTPTR:      case FORMAT_UNKNOWN:      case FORMAT_PTR:	vto[i].data.ptr = va_arg(arglist, void *);	break;	      case FORMAT_INT:#ifdef HAVE_LONGLONG	if(vto[i].flags & FLAGS_LONGLONG)	  vto[i].data.lnum = va_arg(arglist, long long);	else#endif	  if(vto[i].flags & FLAGS_LONG)	    vto[i].data.num = va_arg(arglist, long);	else	  vto[i].data.num = va_arg(arglist, int);	break;	      case FORMAT_DOUBLE:#if SIZEOF_LONG_DOUBLE	if(vto[i].flags & FLAGS_LONG)	  vto[i].data.ldnum = va_arg(arglist, long double);	else#endif	  vto[i].data.dnum = va_arg(arglist, double);	break;	      case FORMAT_WIDTH:	/* Argument has been read. Silently convert it into an integer	 * for later use	 */	vto[i].type = FORMAT_INT;	break;	      default:	break;      }  }  return max_param;}static int dprintf_formatf(             void *data, /* untouched by format(), just sent to the                            stream() function in the first argument */	     int (*stream)(int, FILE *), /* function pointer called for each					    output character */	     const char *format,    /* %-formatted string */	     va_list ap_save) /* list of parameters */{  /* Base-36 digits for numbers.  */  const char *digits = lower_digits;  /* Pointer into the format string.  */  char *f;  /* Number of characters written.  */  register size_t done = 0;  long param; /* current parameter to read */  long param_num=0; /* parameter counter */  va_stack_t vto[MAX_PARAMETERS];  char *endpos[MAX_PARAMETERS];  char **end;  char work[BUFFSIZE];  va_stack_t *p;  /* Do the actual %-code parsing */  dprintf_Pass1((char *)format, vto, endpos, ap_save);  end = &endpos[0]; /* the initial end-position from the list dprintf_Pass1()                       created for us */    f = (char *)format;  while (*f != '\0') {    /* Format spec modifiers.  */    char alt;

⌨️ 快捷键说明

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