📄 output.c
字号:
/*output.c:管理输出缓冲区,并进行格式化输出*/#include "cmm.h"#include <stdarg.h>#include <unistd.h>#include <limits.h>static char *tokstr[] = { /*记号对应的字符串*/#define xx(a,b,c,d,e,f,g) g,#define yy(a,b,c,d,e,f,g) g,#include "token.h"};int outfd = 1; /*输出文件的描述符,默认为标准输出*/int errfd = 2; /*错误输出文件的描述符,默认为标准出错*/static int fd = 1; /*内部缓冲区的索引。为0表示在临时缓冲区,主要用来 *为存储字符串做为临时缓冲区。为1表示在默认的输出缓冲区。 *为2时用于输出出错信息缓冲或其它输出缓冲*/static char buf1[4 * 1024],buf2[512]; /*内部缓冲区*/char *bp = buf1;static struct io { /*文件高速缓冲结构*/ int fd; /*保存使用该缓冲区的文件描述符*/ char *bp; /*缓冲区当前偏移指针*/ char *buffer; /*缓冲区起始地址*/ char *limit; /*缓冲区的结束地址*/}iob[] = { {0,0,0,0}, {1,buf1,buf1,buf1 + sizeof buf1}, {2,buf2,buf2,buf2 + sizeof buf2 }},*io[] = { &iob[0], &iob[1], &iob[2]};static void vprint(char *fmt, va_list ap);/*printtoken:输出当前记号*/void printtoken(void){ fprint(2,"'%s'",(t == ID || t == ICON || t == SCON || t == CCON) ? token: tokstr[t]);}/*outputInit:初始化输出高速缓存,设置默认的输出文件和出错输出文件*/void outputInit(void){ io[1]->fd = outfd; io[2]->fd = errfd;}/*outs:输出字符串s*/void outs(char *s){ char *p; assert(s); for(p = bp; (*p = *s++) != 0;p++) ; bp = p; if(bp > io[fd]->limit) outflush();}/*outflush:清空缓冲区*/void outflush(void){ struct io *iop = io[fd]; assert(fd); if(bp > iop->buffer) write(iop->fd, iop->buffer, bp - iop->buffer); bp = iop->bp = iop->buffer;}/*print:向输出文件输出格式化字符串fmt*/void print(char *fmt,...){ va_list ap; va_start(ap,fmt); vprint(fmt,ap); va_end(ap);}void fprint(int fd, char *fmt, ...){ va_list ap; va_start(ap, fmt); vfprint(fd, fmt, ap); va_end(ap);}/*stringf:存储格式化字符串fmt*/char *stringf(char *fmt, ...){ char buf[_POSIX_ARG_MAX]; va_list ap; va_start(ap, fmt); fd = 0; /*使用0号缓冲区*/ io[1]->bp = bp; /*保存当前输出的偏移*/ bp = io[0]->bp = io[0]->buffer = buf; io[0]->limit = bp + sizeof buf; vprint(fmt,ap); *bp = 0; fd = 1; /*恢复使用1号缓冲区*/ bp = io[1]->bp; return strings(buf);}/*vfprint:向文件f中输出格式化字符串fmt*/void vfprint(int f, char *fmt,va_list ap){ if(f == 1) /*当f为1时及使用标准输出,将使用1号缓冲区*/ vprint(fmt, ap); else { fd = 2; io[2]->fd = 2 == f ? errfd:f; io[1]->bp = bp; bp = io[2]->bp; vprint(fmt,ap); outflush(); bp = io[1]->bp; fd = 1; }}/*vprint:按格式化字符串fmt输出字符*/static void vprint(char *fmt, va_list ap){ char *s; for(; fmt && *fmt; fmt++) { if(*fmt == '%') switch(*++fmt){ case 'd': {int n = va_arg(ap,int); /*将整形数字转换成字符串形式*/ char buf[25]; unsigned m; s = buf + sizeof buf; *--s = 0; if(n == INT_MIN) m = (unsigned)INT_MAX + 1U; else if(n < 0) m = -n; else m = n; do *--s = m % 10 + '0'; while((m = m/10) != 0); if (n < 0) *--s = '-'; outs(s); }break; case 'x': { unsigned n = va_arg(ap, unsigned); char buf[25], *s = buf + sizeof buf; *--s = 0; do *--s = "0123456789abcdef"[n&0xf]; while ((n >>= 4) != 0); outs(s); } break; case 'c': *bp++ = va_arg(ap, int); /*输出字符*/ break; case 'k': /*输出记号*/ {int tok = va_arg(ap, int); outs((tok == ID || tok == ICON || tok == CCON || tok == SCON )? token:tokstr[tok]); }break; case 's': /*输出字符串*/ s = va_arg(ap, char *); if(s) outs(s); break; case 'S':{ /*输出定长度的字符串*/ s = va_arg(ap, char *); int n = va_arg(ap, int); if(s) while(n-- >0) *bp++ = *s++; }break; case 't':{Type ty = va_arg(ap, Type); /*输出类型*/ outtype(ty ? ty:voidtype); }break; case 'w':{Coordinate *p = va_arg(ap, Coordinate *); /*输出文件位置坐标*/ if(p->file && *p->file) print("%s:",p->file); print("%d", p->y); }break; default: *bp++ = *fmt; break; } else if((*bp++ = *fmt) == '\n' && bp > io[fd]->limit) outflush(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -