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

📄 zio.c

📁 Calc Software Package for Number Calc
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * zio - scanf and printf routines for arbitrary precision integers * * Copyright (C) 1999-2006  David I. Bell * * Calc is open software; you can redistribute it and/or modify it under * the terms of the version 2.1 of the GNU Lesser General Public License * as published by the Free Software Foundation. * * Calc 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. * * A copy of version 2.1 of the GNU Lesser General Public License is * distributed with calc under the filename COPYING-LGPL.  You should have * received a copy with calc; if not, write to Free Software Foundation, Inc. * 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA. * * @(#) $Revision: 29.8 $ * @(#) $Id: zio.c,v 29.8 2006/06/01 16:21:37 chongo Exp $ * @(#) $Source: /usr/local/src/cmd/calc/RCS/zio.c,v $ * * Under source code control:	1993/07/30 19:42:48 * File existed as early as:	1993 * * Share and enjoy!  :-)	http://www.isthe.com/chongo/tech/comp/calc/ */#include <stdio.h>#include "config.h"#include "zmath.h"#include "args.h"#define OUTBUFSIZE	200		/* realloc size for output buffers */#define PUTCHAR(ch)		math_chr(ch)#define PUTSTR(str)		math_str(str)#define PRINTF1(fmt, a1)		math_fmt(fmt, a1)#define PRINTF2(fmt, a1, a2)		math_fmt(fmt, a1, a2)#define PRINTF3(fmt, a1, a2, a3)	math_fmt(fmt, a1, a2, a3)#define PRINTF4(fmt, a1, a2, a3, a4)	math_fmt(fmt, a1, a2, a3, a4)/* * Output state that has been saved when diversions are done. */typedef struct iostate IOSTATE;struct iostate {	IOSTATE *oldiostates;		/* previous saved state */	long outdigits;			/* digits for output */	int outmode;			/* output mode */	int outmode2;			/* secondary output mode */	FILE *outfp;			/* file unit for output (if any) */	char *outbuf;			/* output string buffer (if any) */	size_t outbufsize;		/* current size of string buffer */	size_t outbufused;		/* space used in string buffer */	BOOL outputisstring;		/* TRUE if output is to string buffer */};static IOSTATE	*oldiostates = NULL;	/* list of saved output states */static FILE	*outfp = NULL;		/* file unit for output */static char	*outbuf = NULL;		/* current diverted buffer */static BOOL	outputisstring = FALSE;static size_t	outbufsize;static size_t	outbufused;/* * zio_init - perform needed initilization work * * On some systems, one cannot initialize a pointer to a FILE *. * This routine, called once at startup is a work-a-round for * systems with such bogons. */voidzio_init(void){	static int done = 0;	/* 1 => routine already called */	if (!done) {		outfp = stdout;		done = 1;	}}/* * Routine to output a character either to a FILE * handle or into a string. */voidmath_chr(int ch){	char	*cp;	if (!outputisstring) {		fputc(ch, outfp);		return;	}	if (outbufused >= outbufsize) {		cp = (char *)realloc(outbuf, outbufsize + OUTBUFSIZE + 1);		if (cp == NULL) {			math_error("Cannot realloc output string");			/*NOTREACHED*/		}		outbuf = cp;		outbufsize += OUTBUFSIZE;	}	outbuf[outbufused++] = (char)ch;}/* * Routine to output a null-terminated string either * to a FILE handle or into a string. */voidmath_str(char *str){	char	*cp;	size_t	len;	if (!outputisstring) {		fputs(str, outfp);		return;	}	len = strlen(str);	if ((outbufused + len) > outbufsize) {		cp = (char *)realloc(outbuf, outbufsize + len + OUTBUFSIZE + 1);		if (cp == NULL) {			math_error("Cannot realloc output string");			/*NOTREACHED*/		}		outbuf = cp;		outbufsize += (len + OUTBUFSIZE);	}	memcpy(&outbuf[outbufused], str, len);	outbufused += len;}/* * Output a null-terminated string either to a FILE handle or into a string, * padded with spaces as needed so as to fit within the specified width. * If width is positive, the spaces are added at the front of the string. * If width is negative, the spaces are added at the end of the string. * The complete string is always output, even if this overflows the width. * No characters within the string are handled specially. */voidmath_fill(char *str, long width){	if (width > 0) {		width -= (long)strlen(str);		while (width-- > 0)			PUTCHAR(' ');		PUTSTR(str);	} else {		width += (long)strlen(str);		PUTSTR(str);		while (width++ < 0)			PUTCHAR(' ');	}}/* * Routine to output a printf-style formatted string either * to a FILE handle or into a string. */voidmath_fmt(char *fmt, ...){	va_list ap;	char buf[BUFSIZ+1];	va_start(ap, fmt);	vsnprintf(buf, BUFSIZ, fmt, ap);	va_end(ap);	buf[BUFSIZ] = '\0';	math_str(buf);}/* * Flush the current output stream. */voidmath_flush(void){	if (!outputisstring)		fflush(outfp);}/* * Divert further output so that it is saved into a string that will be * returned later when the diversion is completed.  The current state of * output is remembered for later restoration.	Diversions can be nested. * Output diversion is only intended for saving output to "stdout". */voidmath_divertio(void){	register IOSTATE *sp;	sp = (IOSTATE *) malloc(sizeof(IOSTATE));	if (sp == NULL) {		math_error("No memory for diverting output");		/*NOTREACHED*/	}	sp->oldiostates = oldiostates;	sp->outdigits = conf->outdigits;	sp->outmode = conf->outmode;	sp->outmode2 = conf->outmode2;	sp->outfp = outfp;	sp->outbuf = outbuf;	sp->outbufsize = outbufsize;	sp->outbufused = outbufused;	sp->outputisstring = outputisstring;	outbufused = 0;	outbufsize = 0;	outbuf = (char *) malloc(OUTBUFSIZE + 1);	if (outbuf == NULL) {		math_error("Cannot allocate divert string");		/*NOTREACHED*/	}	outbufsize = OUTBUFSIZE;	outputisstring = TRUE;	oldiostates = sp;}/* * Undivert output and return the saved output as a string.  This also * restores the output state to what it was before the diversion began. * The string needs freeing by the caller when it is no longer needed. */char *math_getdivertedio(void){	register IOSTATE *sp;	char *cp;	sp = oldiostates;	if (sp == NULL) {		math_error("No diverted state to restore");		/*NOTREACHED*/	}	cp = outbuf;	cp[outbufused] = '\0';	oldiostates = sp->oldiostates;	conf->outdigits = sp->outdigits;	conf->outmode = sp->outmode;	conf->outmode2 = sp->outmode2;	outfp = sp->outfp;	outbuf = sp->outbuf;	outbufsize = sp->outbufsize;	outbufused = sp->outbufused;	outbuf = sp->outbuf;	outputisstring = sp->outputisstring;	free(sp);	return cp;}/* * Clear all diversions and set output back to the original destination. * This is called when resetting the global state of the program. */voidmath_cleardiversions(void){	while (oldiostates)		free(math_getdivertedio());}/* * Set the output routines to output to the specified FILE stream. * This interacts with output diversion in the following manner. *	STDOUT	diversion	action *	----	---------	------ *	yes	yes		set output to diversion string again. *	yes	no		set output to stdout. *	no	yes		set output to specified file. *	no	no		set output to specified file. */voidmath_setfp(FILE *newfp){	outfp = newfp;	outputisstring = (oldiostates && (newfp == stdout));}/* * Set the output mode for numeric output. * This also returns the previous mode. */intmath_setmode(int newmode){	int oldmode;	if ((newmode <= MODE_DEFAULT) || (newmode > MODE_MAX)) {		math_error("Setting illegal output mode");		/*NOTREACHED*/	}	oldmode = conf->outmode;	conf->outmode = newmode;	return oldmode;}/* * Set the secondary output mode for numeric output. * This also returns the previous mode. */intmath_setmode2(int newmode){	int oldmode;	if (newmode != MODE2_OFF && ((newmode <= MODE_DEFAULT) || (newmode > MODE_MAX))) {		math_error("Setting illegal secondary output mode");		/*NOTREACHED*/	}	oldmode = conf->outmode2;	conf->outmode2 = newmode;	return oldmode;}/* * Set the number of digits for float or exponential output. * This also returns the previous number of digits. */LENmath_setdigits(LEN newdigits){	LEN olddigits;	if (newdigits < 0) {		math_error("Setting illegal number of digits");		/*NOTREACHED*/	}	olddigits = conf->outdigits;	conf->outdigits = newdigits;	return olddigits;}/* * Print an integer value as a hex number. * Width is the number of columns to print the number in, including the * sign if required.  If zero, no extra output is done.	 If positive, * leading spaces are typed if necessary. If negative, trailing spaces are * typed if necessary.	The special characters 0x appear to indicate the * number is hex. *//*ARGSUSED*/voidzprintx(ZVALUE z, long width){	register HALF *hp;	/* current word to print */	int len;		/* number of halfwords to type */	char *str;	if (width) {		math_divertio();		zprintx(z, 0L);		str = math_getdivertedio();		math_fill(str, width);		free(str);		return;	}	len = z.len - 1;	if (zisneg(z))		PUTCHAR('-');	if ((len == 0) && (*z.v <= (HALF) 9)) {		len = '0' + (int)(*z.v);		PUTCHAR(len & 0xff);		return;	}	hp = z.v + len;#if BASEB == 32	PRINTF1("0x%lx", (PRINT) *hp--);	while (--len >= 0) {		PRINTF1("%08lx", (PRINT) *hp--);	}#else /* BASEB == 32 */

⌨️ 快捷键说明

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