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

📄 shf.c

📁 一个开放源代码的 AT&T 的 Korn Shell 的复制品, 支持大多数 ksh89 的特性。
💻 C
📖 第 1 页 / 共 2 页
字号:
		return EOF;	if (shf->flags & SHF_UNBUF) {		char cc = c;		int n;		if (shf->fd < 0)			internal_errorf(1, "shf_putchar: no fd");		if (shf->flags & SHF_ERROR) {			errno = shf->errno_;			return EOF;		}		while ((n = write(shf->fd, &cc, 1)) != 1)			if (n < 0) {				if (errno == EINTR				    && !(shf->flags & SHF_INTERRUPT))					continue;				shf->flags |= SHF_ERROR;				shf->errno_ = errno;				return EOF;			}	} else {		/* Flush deals with strings and sticky errors */		if (shf->wnleft == 0 && shf_emptybuf(shf, EB_GROW) == EOF)			return EOF;		shf->wnleft--;		*shf->wp++ = c;	}	return c;}/* Write a string.  Returns the length of the string if successful, EOF if * the string could not be written. */intshf_puts(s, shf)	const char *s;	struct shf *shf;{	if (!s)		return EOF;	return shf_write(s, strlen(s), shf);}/* Write a buffer.  Returns nbytes if successful, EOF if there is an error. */intshf_write(buf, nbytes, shf)	const char *buf;	int nbytes;	struct shf *shf;{	int orig_nbytes = nbytes;	int n;	int ncopy;	if (!(shf->flags & SHF_WR))		internal_errorf(1, "shf_write: flags %x", shf->flags);	if (nbytes < 0)		internal_errorf(1, "shf_write: nbytes %d", nbytes);	/* Don't buffer if buffer is empty and we're writting a large amount. */	if ((ncopy = shf->wnleft)	    && (shf->wp != shf->buf || nbytes < shf->wnleft))	{		if (ncopy > nbytes)			ncopy = nbytes;		memcpy(shf->wp, buf, ncopy);		nbytes -= ncopy;		buf += ncopy;		shf->wp += ncopy;		shf->wnleft -= ncopy;	}	if (nbytes > 0) {		/* Flush deals with strings and sticky errors */		if (shf_emptybuf(shf, EB_GROW) == EOF)			return EOF;		if (nbytes > shf->wbsize) {			ncopy = nbytes;			if (shf->wbsize)				ncopy -= nbytes % shf->wbsize;			nbytes -= ncopy;			while (ncopy > 0) {				n = write(shf->fd, buf, ncopy);				if (n < 0) {					if (errno == EINTR					    && !(shf->flags & SHF_INTERRUPT))						continue;					shf->flags |= SHF_ERROR;					shf->errno_ = errno;					shf->wnleft = 0;					/* Note: fwrite(3S) returns 0 for					 * errors - this doesn't */					return EOF;				}				buf += n;				ncopy -= n;			}		}		if (nbytes > 0) {			memcpy(shf->wp, buf, nbytes);			shf->wp += nbytes;			shf->wnleft -= nbytes;		}	}	return orig_nbytes;}int#ifdef HAVE_PROTOTYPESshf_fprintf(struct shf *shf, const char *fmt, ...)#elseshf_fprintf(shf, fmt, va_alist)	struct shf *shf;	const char *fmt;	va_dcl#endif{	va_list args;	int n;	SH_VA_START(args, fmt);	n = shf_vfprintf(shf, fmt, args);	va_end(args);	return n;}int#ifdef HAVE_PROTOTYPESshf_snprintf(char *buf, int bsize, const char *fmt, ...)#elseshf_snprintf(buf, bsize, fmt, va_alist)	char *buf;	int bsize;	const char *fmt;	va_dcl#endif{	struct shf shf;	va_list args;	int n;	if (!buf || bsize <= 0)		internal_errorf(1, "shf_snprintf: buf %lx, bsize %d",			(long) buf, bsize);	shf_sopen(buf, bsize, SHF_WR, &shf);	SH_VA_START(args, fmt);	n = shf_vfprintf(&shf, fmt, args);	va_end(args);	shf_sclose(&shf); /* null terminates */	return n;}char *#ifdef HAVE_PROTOTYPESshf_smprintf(const char *fmt, ...)#elseshf_smprintf(fmt, va_alist)	char *fmt;	va_dcl#endif{	struct shf shf;	va_list args;	shf_sopen((char *) 0, 0, SHF_WR|SHF_DYNAMIC, &shf);	SH_VA_START(args, fmt);	shf_vfprintf(&shf, fmt, args);	va_end(args);	return shf_sclose(&shf); /* null terminates */}#undef FP  			/* if you want floating point stuff */#define BUF_SIZE	128#define FPBUF_SIZE	(DMAXEXP+16)/* this must be >				 *	MAX(DMAXEXP, log10(pow(2, DSIGNIF)))				 *    + ceil(log10(DMAXEXP)) + 8 (I think).				 * Since this is hard to express as a				 * constant, just use a large buffer.				 *//* *	What kinda of machine we on?  Hopefully the C compiler will optimize *  this out... * *	For shorts, we want sign extend for %d but not for %[oxu] - on 16 bit *  machines it don't matter.  Assmumes C compiler has converted shorts to *  ints before pushing them. */#define POP_INT(f, s, a) (((f) & FL_LONG) ?				\				va_arg((a), unsigned long)		\			    :						\				(sizeof(int) < sizeof(long) ?		\					((s) ?				\						(long) va_arg((a), int)	\					    :				\						va_arg((a), unsigned))	\				    :					\					va_arg((a), unsigned)))#define ABIGNUM		32000	/* big numer that will fit in a short */#define LOG2_10		3.321928094887362347870319429	/* log base 2 of 10 */#define	FL_HASH		0x001	/* `#' seen */#define FL_PLUS		0x002	/* `+' seen */#define FL_RIGHT	0x004	/* `-' seen */#define FL_BLANK	0x008	/* ` ' seen */#define FL_SHORT	0x010	/* `h' seen */#define FL_LONG		0x020	/* `l' seen */#define FL_ZERO		0x040	/* `0' seen */#define FL_DOT		0x080	/* '.' seen */#define FL_UPPER	0x100	/* format character was uppercase */#define FL_NUMBER	0x200	/* a number was formated %[douxefg] */#ifdef FP#include <math.h>static doublemy_ceil(d)	double	d;{	double		i;	return d - modf(d, &i) + (d < 0 ? -1 : 1);}#endif /* FP */intshf_vfprintf(shf, fmt, args)	struct shf *shf;	const char *fmt;	va_list args;{	char		c, *s;	int		UNINITIALIZED(tmp);	int		field, precision;	int		len;	int		flags;	unsigned long	lnum;					/* %#o produces the longest output */	char		numbuf[(BITS(long) + 2) / 3 + 1];	/* this stuff for dealing with the buffer */	int		nwritten = 0;#ifdef FP	/* should be in <math.h>	 *  extern double frexp();	 */	extern char *ecvt();	double		fpnum;	int		expo, decpt;	char		style;	char		fpbuf[FPBUF_SIZE];#endif /* FP */	if (!fmt)		return 0;	while ((c = *fmt++)) {		if (c != '%') {			shf_putc(c, shf);			nwritten++;			continue;		}		/*		 *	This will accept flags/fields in any order - not		 *  just the order specified in printf(3), but this is		 *  the way _doprnt() seems to work (on bsd and sysV).		 *  The only resriction is that the format character must		 *  come last :-).		 */		flags = field = precision = 0;		for ( ; (c = *fmt++) ; ) {			switch (c) {			case '#':				flags |= FL_HASH;				continue;			case '+':				flags |= FL_PLUS;				continue;			case '-':				flags |= FL_RIGHT;				continue;			case ' ':				flags |= FL_BLANK;				continue;			case '0':				if (!(flags & FL_DOT))					flags |= FL_ZERO;				continue;			case '.':				flags |= FL_DOT;				precision = 0;				continue;			case '*':				tmp = va_arg(args, int);				if (flags & FL_DOT)					precision = tmp;				else if ((field = tmp) < 0) {					field = -field;					flags |= FL_RIGHT;				}				continue;			case 'l':				flags |= FL_LONG;				continue;			case 'h':				flags |= FL_SHORT;				continue;			}			if (digit(c)) {				tmp = c - '0';				while (c = *fmt++, digit(c))					tmp = tmp * 10 + c - '0';				--fmt;				if (tmp < 0)		/* overflow? */					tmp = 0;				if (flags & FL_DOT)					precision = tmp;				else					field = tmp;				continue;			}			break;		}		if (precision < 0)			precision = 0;		if (!c)		/* nasty format */			break;		if (c >= 'A' && c <= 'Z') {			flags |= FL_UPPER;			c = c - 'A' + 'a';		}		switch (c) {		case 'p': /* pointer */			flags &= ~(FL_LONG | FL_SHORT);			if (sizeof(char *) > sizeof(int))				flags |= FL_LONG; /* hope it fits.. */			/* aaahhh... */		case 'd':		case 'i':		case 'o':		case 'u':		case 'x':			flags |= FL_NUMBER;			s = &numbuf[sizeof(numbuf)];			lnum = POP_INT(flags, c == 'd', args);			switch (c) {			case 'd':			case 'i':				if (0 > (long) lnum)					lnum = - (long) lnum, tmp = 1;				else					tmp = 0;				/* aaahhhh..... */			case 'u':				do {					*--s = lnum % 10 + '0';					lnum /= 10;				} while (lnum);				if (c != 'u') {					if (tmp)						*--s = '-';					else if (flags & FL_PLUS)						*--s = '+';					else if (flags & FL_BLANK)						*--s = ' ';				}				break;			case 'o':				do {					*--s = (lnum & 0x7) + '0';					lnum >>= 3;				} while (lnum);				if ((flags & FL_HASH) && *s != '0')					*--s = '0';				break;			case 'p':			case 'x':			    {				const char *digits = (flags & FL_UPPER) ?						  "0123456789ABCDEF"						: "0123456789abcdef";				do {					*--s = digits[lnum & 0xf];					lnum >>= 4;				} while (lnum);				if (flags & FL_HASH) {					*--s = (flags & FL_UPPER) ? 'X' : 'x';					*--s = '0';				}			    }			}			len = &numbuf[sizeof(numbuf)] - s;			if (flags & FL_DOT) {				if (precision > len) {					field = precision;					flags |= FL_ZERO;				} else					precision = len; /* no loss */			}			break;#ifdef FP		case 'e':		case 'g':		case 'f':		    {			char *p;			/*			 *	This could proabably be done better,			 *  but it seems to work.  Note that gcvt()			 *  is not used, as you cannot tell it to			 *  not strip the zeros.			 */			flags |= FL_NUMBER;			if (!(flags & FL_DOT))				precision = 6;	/* default */			/*			 *	Assumes doubles are pushed on			 *  the stack.  If this is not so, then			 *  FL_LONG/FL_SHORT should be checked.			 */			fpnum = va_arg(args, double);			s = fpbuf;			style = c;			/*			 *  This is the same as			 *	expo = ceil(log10(fpnum))			 *  but doesn't need -lm.  This is an			 *  aproximation as expo is rounded up.			 */			(void) frexp(fpnum, &expo);			expo = my_ceil(expo / LOG2_10);			if (expo < 0)				expo = 0;			p = ecvt(fpnum, precision + 1 + expo,				 &decpt, &tmp);			if (c == 'g') {				if (decpt < -4 || decpt > precision)					style = 'e';				else					style = 'f';				if (decpt > 0 && (precision -= decpt) < 0)					precision = 0;			}			if (tmp)				*s++ = '-';			else if (flags & FL_PLUS)				*s++ = '+';			else if (flags & FL_BLANK)				*s++ = ' ';			if (style == 'e')				*s++ = *p++;			else {				if (decpt > 0) {					/* Overflow check - should					 * never have this problem.					 */					if (decpt >						&fpbuf[sizeof(fpbuf)]							- s - 8)						decpt =						 &fpbuf[sizeof(fpbuf)]							- s - 8;					(void) memcpy(s, p, decpt);					s += decpt;					p += decpt;				} else					*s++ = '0';			}			/* print the fraction? */			if (precision > 0) {				*s++ = '.';				/* Overflow check - should				 * never have this problem.				 */				if (precision > &fpbuf[sizeof(fpbuf)]							- s - 7)					precision =						&fpbuf[sizeof(fpbuf)]						- s - 7;				for (tmp = decpt;  tmp++ < 0 &&					    precision > 0 ; precision--)					*s++ = '0';				tmp = strlen(p);				if (precision > tmp)					precision = tmp;				/* Overflow check - should				 * never have this problem.				 */				if (precision > &fpbuf[sizeof(fpbuf)]							- s - 7)					precision =						&fpbuf[sizeof(fpbuf)]						- s - 7;				(void) memcpy(s, p, precision);				s += precision;				/*				 *	`g' format strips trailing				 *  zeros after the decimal.				 */				if (c == 'g' && !(flags & FL_HASH)) {					while (*--s == '0')						;					if (*s != '.')						s++;				}			} else if (flags & FL_HASH)				*s++ = '.';			if (style == 'e') {				*s++ = (flags & FL_UPPER) ? 'E' : 'e';				if (--decpt >= 0)					*s++ = '+';				else {					*s++ = '-';					decpt = -decpt;				}				p = &numbuf[sizeof(numbuf)];				for (tmp = 0; tmp < 2 || decpt ; tmp++) {					*--p = '0' + decpt % 10;					decpt /= 10;				}				tmp = &numbuf[sizeof(numbuf)] - p;				(void) memcpy(s, p, tmp);				s += tmp;			}			len = s - fpbuf;			s = fpbuf;			precision = len;			break;		    }#endif /* FP */		case 's':			if (!(s = va_arg(args, char *)))				s = "(null %s)";			len = strlen(s);			break;		case 'c':			flags &= ~FL_DOT;			numbuf[0] = va_arg(args, int);			s = numbuf;			len = 1;			break;		case '%':		default:			numbuf[0] = c;			s = numbuf;			len = 1;			break;		}		/*		 *	At this point s should point to a string that is		 *  to be formatted, and len should be the length of the		 *  string.		 */		if (!(flags & FL_DOT) || len < precision)			precision = len;		if (field > precision) {			field -= precision;			if (!(flags & FL_RIGHT)) {				field = -field;				/* skip past sign or 0x when padding with 0 */				if ((flags & FL_ZERO) && (flags & FL_NUMBER)) {					if (*s == '+' || *s == '-' || *s ==' ')					{						shf_putc(*s, shf);						s++;						precision--;						nwritten++;					} else if (*s == '0') {						shf_putc(*s, shf);						s++;						nwritten++;						if (--precision > 0 &&							(*s | 0x20) == 'x')						{							shf_putc(*s, shf);							s++;							precision--;							nwritten++;						}					}					c = '0';				} else					c = flags & FL_ZERO ? '0' : ' ';				if (field < 0) {					nwritten += -field;					for ( ; field < 0 ; field++)						shf_putc(c, shf);				}			} else				c = ' ';		} else			field = 0;		if (precision > 0) {			nwritten += precision;			for ( ; precision-- > 0 ; s++)				shf_putc(*s, shf);		}		if (field > 0) {			nwritten += field;			for ( ; field > 0 ; --field)				shf_putc(c, shf);		}	}	return shf_error(shf) ? EOF : nwritten;}

⌨️ 快捷键说明

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