📄 stdio.c
字号:
/* stdio.c
*
* (C) Copyright Dec 19 1998, Edmond J. Breen.
* ALL RIGHTS RESERVED.
* This code may be copied for personal, non-profit use only.
*
*/
/* This file is broken into 2 parts
* the first part defines the interface routines
* and the 2nd part adds the interface routine
* to EiC's look up tables.
*/
#ifndef _USE_POSIX
#define _USE_POSIX
#endif
#ifndef _POSIX_SOURCE
#define _POSIX_SOURCE 1
#endif
#ifndef __EXTENSIONS__
#define __EXTENSIONS__
#endif
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE
#endif
#include <stdio.h>
#if 0
#ifdef _IRIX
extern FILE *popen(const char *, const char *);
extern int pclose(FILE *);
#endif
#endif
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include <limits.h>
#include <ctype.h>
#include <math.h>
#include "eic.h"
#include "stdliblocal.h"
#ifdef PPCLIB
void outbyte(int ch);
#endif
/* The following code provides for an open FILE cleanup
mechanism. EiC will call _ffexit, cleaning up all open
FILEs which were opened in the side effects being discarded.
*/
static size_t NextFopenEntry = 4;
static size_t book1[FOPEN_MAX] = {1,2,3};
static FILE * book2[FOPEN_MAX];
size_t fopen_NextEntryNum(void) {
return NextFopenEntry;
}
/* We assume that eic_fopen() is always closed by eic_fclose()
and eic_popen() is aways closed by eic_pclose() so that book[i]
being non-zero implies that the associated FILE is still open.
This ignores the possibility that a file opened in interpreted
code can be closed in compiled code, but such a situation is
ill advised in any event.
*/
void _ffexit(size_t Entry) {
int i;
for(i = 0; i < FOPEN_MAX; i += 1) {
if(book1[i] >= Entry) {
fclose(stdin + i);
book1[i] = 0;
book2[i] = NULL;
}
}
return;
}
/* INTERFACE FUNCTIONS */
int charin_(char **buf)
{
int ch;
ch = **buf;
*buf += 1;
if(!ch)
ch = EOF;
return ch;
}
int charback_(int ch, char **buf)
{
*buf -= 1;
return ch;
}
int charout_(int c, char **buf)
{
char *s;
s = *buf;
*s++ = c;
*s = 0;
*buf = s;
return 1;
}
int _eicUprintf(int (*output)(), void *arg, char *fmt, arg_list ap)
{
/* copy of _UPRINTF that works with EiC's run time stack.
* Orginally developed from James Hendrix's Small C tools.
*
* (c) Edmond J.Breen (March, 1995).
* ALL RIGHTS RESERVED.
*
* Purpose: To perform formatted printing to a function.
* It performs a superset of printf type
* operations.
*
* _UPRINTF RECOGNISES:
* FLAGS:
* -, +, 0 and #.
* plus ! and | (see below).
*
* CONVERSION CHARACTERS:
* d, i, o, x, X, u, c, s,
* f, e, E, g, G, p, n, %
* plus b (see below).
*
* LENGTH MODIFIES:
* l, L, and h.
*
* The WIDTH and or the PRECISION can be set indirectly
* via * as specified by K&R.
*
* _UPRINTF EXTRA FEATURES.
* NEW FLAGS:
* FLAG WHAT IT SPECIFIES
* | Centre justification.
* ! Used with floating point numbers.
* It specifies, if possible, that the
* number will be centred with respect
* to the decimal point.
* If used with non floating point
* numbers or the floating point number
* does not contain a decimal point,
* the ! flag is equivalent to |.
* NEW CONVERSION CHARACTER:
* CHARACTER WHAT IT SPECIFIES
* b int, unsigned binary notation.
*/
int v;
static char str[128];
char *sptr, lseen,Lseen;
int left, right, centre, maxchr,
pad, len, width, sign, dprec,
mod, prec,dot,gotfloat;
v = 0;
while(*fmt) {
if(*fmt != '%') {
(*output)(*fmt,arg);
++fmt;++v;
continue;
} else if(*++fmt =='%') {
(*output)(*fmt++,arg);
++v;
continue;
}
pad = ' ';
centre = len = right = left = 0;
gotfloat = dot = sign = mod = 0;
Lseen = lseen = dprec = 0;
while(*fmt) { /* collect in any order */
if(*fmt == '-') left = 1;
else if(*fmt == '0') pad = '0';
else if(*fmt == '+') sign = 1;
else if(*fmt == '#') mod = 1;
else if(*fmt == '|') centre = 1;
else if(*fmt == '!') centre = 1, dot = 1;
else
break;
++fmt;
}
if(isdigit(*fmt)) {
width = atoi(fmt);
while(isdigit(*fmt)) ++fmt;
} else if(*fmt == '*') {
width = nextarg(ap,int);
fmt++;
} else
width = -1;
if(*fmt == '.') {
if(*++fmt == '*') {
maxchr = nextarg(ap,int);
fmt++;
} else {
maxchr = atoi(fmt);
while(isdigit(*fmt)) ++fmt;
}
} else
maxchr = -1;
switch(*fmt) { /* check for length modifier*/
case 'h': fmt++;break;
case 'l': lseen = 1; fmt++;break;
case 'L': Lseen = 1; fmt++;break;
}
sptr = str;
switch(*fmt++) {
case 'c': sptr[0] = (char)nextarg(ap,int);
sptr[1] = 0;
break;
case 'b':
if(lseen) ultoa(nextarg(ap,long),sptr,2);
else utoa(nextarg(ap,int),sptr,2);
break;
case 'i':
case 'd': if(lseen) ltoa(nextarg(ap,long),sptr,10);
else itoa(nextarg(ap,int),sptr,10);
dprec=1;
break;
case 'u': if(lseen) ultoa(nextarg(ap,unsigned long),sptr,10);
else utoa(nextarg(ap,unsigned),sptr,10);
dprec=1;
break;
case 'o': if(mod) *sptr = '0';
if(lseen)ltoa(nextarg(ap,long),&sptr[mod],8);
else itoa(nextarg(ap,int),&sptr[mod],8);
dprec = 1;
break;
case 's': sptr = nextarg(ap,ptr_t).p; break;
case 'x': case 'X':
if(mod) {
*sptr = '0', sptr[1] = *(fmt-1);
mod++;
}
if(lseen)ultoa(nextarg(ap,long),&sptr[mod],16);
else utoa(nextarg(ap,int),&sptr[mod],16);
if(*(fmt-1) == 'X') {
while(*sptr) {
*sptr = toupper(*sptr);
sptr++;
}
sptr = str;
}
dprec = 1;
break;
case 'e': case 'E': case 'g': case 'G':
case 'f': {
int trunc = 0;
char type = *(fmt-1),c;
double d;
gotfloat = 1;
if(maxchr < 0) prec = 6;
else prec = maxchr,maxchr = -1;
if(Lseen)
d = nextarg(ap,double);
else
d = nextarg(ap,double);
if(type == 'g' || type == 'G') {
double ex;
if(d !=0)
ex = log10(d < 0? -d:d);
else
ex = 1;
if(ex < -4 || ex >= prec)
c = type - 2;
else
c = 'f';
trunc = 1;
} else
c = type;
if(mod) {
if(!prec) prec = 1;
trunc = 0;
}
sptr = fftoa(d,str, prec, c,trunc);
}
break;
case 'n': *(int*)nextarg(ap,ptr_t).p = v; continue;
case 'p':
ultoa((long)nextarg(ap,ptr_t).p,sptr,16);
break;
default: (*output)(*(fmt-1),arg);
while(*fmt) {
(*output)(*fmt++,arg);
++v;
}
return v;
}
if(!len && sptr) len = strlen(sptr);
if(sign) len += (*sptr == '-' ? 0: 1);
if(dprec && maxchr >=0) {
dprec = maxchr;
pad = '0';
}else
dprec = 0;
if(maxchr > -1 && maxchr<len)
len = maxchr;
if(width>len)
width = width -len;
else if(dprec > len)
width = dprec - len;
else
width = 0;
if(centre) {
left = (right = width >> 1) + (width%2);
if(dot && gotfloat) {
int d = 0,c;
while(sptr[d] && sptr[d] != '.')
d++;
if(sptr[d] == '.') {
c = (width + len)/2;
if(sign && sptr[0] != '-')
d++;
if(c-d > 0) right = c-d;
else right = 0;
if(width - right > 0)
left = width - right;
else
left = 0;
}
}
} else
if(!left)
right = width;
else
left = width;
if(sign && !left && pad == '0') {
if(*sptr != '-') {
(*output)('+',arg);
++v;len--;
}
sign = 0;
}
while(right--) {(*output)(pad,arg); ++v;}
if(sign && *sptr != '-') {(*output)('+',arg);len--;++v;}
while(len--) {(*output)(*sptr++,arg);++v;}
while(left--) {(*output)(pad,arg);++v;}
}
return v;
}
int _eicUscanf(int (*input)(), int (*uget)(),
void *arg, const char *fmt, arg_list ap)
{
/*_USCANF
*
* (C) May 10 1995 Edmond J.Breen.
* ALL RIGHTS RESERVED.
*
* Purpose: To perform formatted reading from a function.
* _Uscanf performs a superset of scanf type
* operations.
*
* _USCANF RECOGNISES:
*
* %[*] [width] [h|l|L] [b|d|i|o|x|X|u|c|s|f|e|E|g|G|p|n|%]
* %[*] [width] [scan-set]
*
* CONVERSION CHARACTERS:
* d, i, o, x, X, u, c, s
* f, e, E, g, G, p, n, %
* plus b (see below).
*
* LENGTH MODIFIES:
* l, L, and h.
*
* * optional assignment-suppression character
* WIDTH optional integer width of field specifier
*
* SCAN-SET
* [...] matches the longest non-emtpy string
* of input from the set between the brackects.
* [^...] matches the longest non-emtpy string
* of input NOT from the set between the brackects.
* []...] and [^]...]
* includes ] as part of the scan-set.
*
* NEW CONVERSION CHARACTER:
* CHARACTER WHAT IT SPECIFIES
* b int, unsigned binary notation.
*
* STANDARD C AUXILIARY FUNCTIONS REQUIRED
* strtol, strtod, strtoul
*
* LIMITATIONS:
* (1) long double handled as double
* (2) error checking could be improved
*/
static char field[256], *p;
char *carg, sbuf;
int type;
int wast, width,cwidth, ch, base,cnt;
void *vptr;
int v;
cnt = v = 0;
while(*fmt != '\0') {
if(isspace(*fmt)) { /* match white space */
while(*fmt && isspace(*fmt)) ++fmt;
if(*fmt) {
while(isspace((ch=(*input)(arg))))
++cnt;
(*uget)(ch,arg);
}
continue;
}
if(*fmt != '%') { /* match literal text */
while(*fmt && !isspace(*fmt) && *fmt != '%')
if((ch=(*input)(arg)) == *fmt)
++fmt,++cnt;
else
return v;
continue;
}
if(*++fmt == '*') {
vptr = &sbuf;
wast = 1;
++fmt;
} else if(*fmt == '%') {
cnt++;
fmt++;
continue;
} else {
wast = 0;
vptr = nextarg(ap,ptr_t).p;
}
for(width = 0;isdigit(*fmt);fmt++)
width = *fmt - '0' + width * 10;
if(!width)
width = INT_MAX, cwidth = 1;
else
cwidth = width;
if(*fmt != 'c' && *fmt != '[' && *fmt != 'n') {
/* strip leading white space */
while(isspace(ch = (*input)(arg)))
++cnt;
if(ch == EOF) {
if(v)
break;
else
return EOF;
}
(*uget)(ch,arg);
}
switch(*fmt) {
case 'h': type = 'h'; ++fmt; break;
case 'l': type = 'l'; ++fmt; break;
case 'L': type = 'L'; ++fmt; break;
default: type = 0;
}
switch(*fmt) {
case 'c': carg = vptr;
while(cwidth--) {
*carg = (*input)(arg);
++cnt;
if(carg != &sbuf)
++carg;
}
break;
case 's':
carg = vptr;
while(width--) {
if((*carg = (*input)(arg)) == EOF)
break;
++cnt;
if(isspace(*carg)) {
(*uget)(*carg,arg);
--cnt;
break;
} if(carg != &sbuf)
++carg;
}
*carg = '\0';
break;
case '[':
++fmt;
if(*fmt == '^') {++fmt; type = 0;}
else type = 1;
p = (char*)fmt;
if(*p == ']') ++p;
while(*p && *p != ']') ++p;
cwidth = p - fmt;
if(cwidth == 0) return EOF;
carg = vptr;
while((ch = (*input)(arg)) != EOF)
if(type) {
if(memchr(fmt,ch,cwidth)) {
if(!wast)
*carg++ = ch;
++cnt;
}else {
(*uget)(ch,arg);
break;
}
} else
if(!memchr(fmt,ch,cwidth)) {
if(!wast)
*carg++ = ch;
++cnt;
}else {
(*uget)(ch,arg);
break;
}
*carg = '\0';
fmt += cwidth;
break;
case 'e': case 'f': case 'g':
case 'E': case 'G':
p = field;
ch = (*input)(arg);
if(ch == '-' || ch == '+') {
++cnt;
*p++ = ch;
} else
(*uget)(ch,arg);
while(width-- && isdigit(ch=(*input)(arg))) {
++cnt; *p++ = ch;
}
if(ch == '.' && width-- > 0) {
*p++ = '.';
++cnt;
while(isdigit(ch=(*input)(arg)) && width--) {
++cnt;
*p++ = ch;
}
}
if((ch == 'e' || ch == 'E') && width--) {
*p++ = ch;
ch = (*input)(arg);
if(ch != '+' && ch != '-' && !isdigit(ch) &&
ch != EOF && !isspace(ch)) {
(*uget)(ch,arg);
ch = *--p;
} else
cnt++;
}
if((ch == '+' || ch == '-') && width--) {
*p++ = ch;
++cnt;
ch = (*input)(arg);
}
while(isdigit(ch) && width--) {
*p++ = ch;
++cnt;
ch = (*input)(arg);
}
(*uget)(ch,arg);
if(p == field)
return v;
*p = '\0';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -