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

📄 output.c

📁 unix环境下实现的cmm语言编译器
💻 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 + -