📄 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 _IRIXextern 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 PPCLIBvoid outbyte(int ch);#endif/* The following code provides for an open FILE cleanupmechanism. EiC will call _ffexit, cleaning up all openFILEs 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 interpretedcode can be closed in compiled code, but such a situation isill 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;}/*Gris comment*//*int _eicUprintf(int (*output)(), void *arg, char *fmt, arg_list ap)*//*Gris begin*/int _eicUprintf(int (*output)(), char**arg, char *fmt, arg_list ap)/*Gris end*/{ /* 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;} } /*Gris begin*/ *arg -= v; /*Gris end*/ return v;}/*Gris comment*//*int _eicUscanf(int (*input)(), int (*uget)(),*//* void *arg, const char *fmt, arg_list ap)*//*Gris begin*/int _eicUscanf(int (*input)(), int (*uget)(), char **arg, const char *fmt, arg_list ap)/*Gris end*/{ /*_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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -