📄 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;}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 *//** September 15, 2000 Added facilities to include ranges in brackets, like %[0-9]. Fixed problem of not reading whitespace, when whitespace is on the end of the controlstring. (Disaster when scanning files) Fixed not detecting of EOF for controlstrings containing only whitespace and whitespace-exception related symbols, like "%[^\n]\n". Bernard van Veelen, veelen@home.nl **/ static char field[256], *p; char *carg, sbuf; int type; int wast, width,cwidth, ch, base,cnt; void *vptr; int v; char scansetarray[256]; int ssai; cnt = v = 0; while(*fmt != '\0') { if(isspace(*fmt)) { /* match white space */ while(*fmt && isspace(*fmt)) fmt++; /* read input UPTO next non-whitespace; */ 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; ssai = 0; if(*fmt == '^') {++fmt; type = 0;} else type = 1; if(*fmt == ']') { scansetarray[ssai++] = *fmt; fmt++; } while(*fmt && *fmt != ']') { switch(*fmt) { case '-' : fmt++; if ((*fmt == ']') || (ssai == 0) || (scansetarray[ssai-1] > *fmt)) /*'-' stands for itself, just add '-' */ scansetarray[ssai++] = '-'; else { /* fill in missing components */ while(scansetarray[ssai-1] != *fmt) { scansetarray[ssai] = scansetarray[ssai-1] + 1; ssai++; } /* advance fmt to the next char in fmt*/ fmt++; } break; default : scansetarray[ssai++] = *fmt++; break; } } if(ssai == 0) return EOF; carg = vptr; while((ch = (*input)(arg)) != EOF) if(type) { if(memchr(scansetarray,ch,ssai)) { if(!wast) *carg++ = ch; ++cnt; }else { (*uget)(ch,arg); break; } } else if(!memchr(scansetarray,ch,ssai)) { if(!wast) *carg++ = ch; ++cnt; }else { (*uget)(ch,arg); break; } *carg = '\0'; if (ch == EOF) { if (v) break; else return EOF; } 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -