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

📄 join.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
/*	join F1 F2 on stuff */#include <u.h>#include <libc.h>#include <stdio.h>#include <ctype.h>#define F1 0#define F2 1#define F0 3#define	NFLD	100	/* max field per line */#define comp() runecmp(ppi[F1][j1],ppi[F2][j2])FILE *f[2];Rune buf[2][BUFSIZ];	/*input lines */Rune *ppi[2][NFLD+1];	/* pointers to fields in lines */Rune *s1,*s2;int	j1	= 1;	/* join of this field of file 1 */int	j2	= 1;	/* join of this field of file 2 */int	olist[2*NFLD];	/* output these fields */int	olistf[2*NFLD];	/* from these files */int	no;		/* number of entries in olist */Rune	sep1	= ' ';	/* default field separator */Rune	sep2	= '\t';char *sepstr=" ";int	discard;	/* count of truncated lines */Rune	null[BUFSIZ]	= L"";int	a1;int 	a2;char *getoptarg(int*, char***);void output(int, int);int input(int);void oparse(char*);void error(char*, char*);void seek1(void), seek2(void);Rune *strtorune(Rune *, char *);voidmain(int argc, char **argv){	int i;	while (argc > 1 && argv[1][0] == '-') {		if (argv[1][1] == '\0')			break;		switch (argv[1][1]) {		case '-':			argc--;			argv++;			goto proceed;		case 'a':			switch(*getoptarg(&argc, &argv)) {			case '1':				a1++;				break;			case '2':				a2++;				break;			default:				error("incomplete option -a","");			}			break;		case 'e':			strtorune(null, getoptarg(&argc, &argv));			break;		case 't':			sepstr=getoptarg(&argc, &argv);			chartorune(&sep1, sepstr);			sep2 = sep1;			break;		case 'o':			if(argv[1][2]!=0 ||			   argc>2 && strchr(argv[2],',')!=0)				oparse(getoptarg(&argc, &argv));			else for (no = 0; no<2*NFLD && argc>2; no++){				if (argv[2][0] == '1' && argv[2][1] == '.') {					olistf[no] = F1;					olist[no] = atoi(&argv[2][2]);				} else if (argv[2][0] == '2' && argv[2][1] == '.') {					olist[no] = atoi(&argv[2][2]);					olistf[no] = F2;				} else if (argv[2][0] == '0')					olistf[no] = F0;				else					break;				argc--;				argv++;			}			break;		case 'j':			if(argc <= 2)				break;			if (argv[1][2] == '1')				j1 = atoi(argv[2]);			else if (argv[1][2] == '2')				j2 = atoi(argv[2]);			else				j1 = j2 = atoi(argv[2]);			argc--;			argv++;			break;		case '1':			j1 = atoi(getoptarg(&argc, &argv));			break;		case '2':			j2 = atoi(getoptarg(&argc, &argv));			break;		}		argc--;		argv++;	}proceed:	for (i = 0; i < no; i++)		if (olist[i]-- > NFLD)	/* 0 origin */			error("field number too big in -o","");	if (argc != 3)		error("usage: join [-1 x -2 y] [-o list] file1 file2","");	if (j1 < 1  || j2 < 1)		error("invalid field indices", "");	j1--;	j2--;	/* everyone else believes in 0 origin */	s1 = ppi[F1][j1];	s2 = ppi[F2][j2];	if (strcmp(argv[1], "-") == 0)		f[F1] = stdin;	else if ((f[F1] = fopen(argv[1], "r")) == 0)		error("can't open %s", argv[1]);	if(strcmp(argv[2], "-") == 0) {		f[F2] = stdin;	} else if ((f[F2] = fopen(argv[2], "r")) == 0)		error("can't open %s", argv[2]);	if(ftell(f[F2]) >= 0)		seek2();	else if(ftell(f[F1]) >= 0)		seek1();	else		error("neither file is randomly accessible","");	if (discard)		error("some input line was truncated", "");	exits("");}int runecmp(Rune *a, Rune *b){	while(*a==*b){		if(*a=='\0') return 0;		a++;		b++;	}	if(*a<*b) return -1;	return 1;}char *runetostr(char *buf, Rune *r){	char *s;	for(s=buf;*r;r++) s+=runetochar(s, r);	*s='\0';	return buf;}Rune *strtorune(Rune *buf, char *s){	Rune *r;	for(r=buf;*s;r++) s+=chartorune(r, s);	*r='\0';	return buf;}/* lazy.  there ought to be a clean way to combine seek1 & seek2 */#define get1() n1=input(F1)#define get2() n2=input(F2)voidseek2(){	int n1, n2;	int top2=0;	int bot2 = ftell(f[F2]);	get1();	get2();	while(n1>0 && n2>0 || (a1||a2) && n1+n2>0) {		if(n1>0 && n2>0 && comp()>0 || n1==0) {			if(a2) output(0, n2);			bot2 = ftell(f[F2]);			get2();		} else if(n1>0 && n2>0 && comp()<0 || n2==0) {			if(a1) output(n1, 0);			get1();		} else /*(n1>0 && n2>0 && comp()==0)*/ {			while(n2>0 && comp()==0) {				output(n1, n2);				top2 = ftell(f[F2]);				get2();			}			fseek(f[F2], bot2, 0);			get2();			get1();			for(;;) {				if(n1>0 && n2>0 && comp()==0) {					output(n1, n2);					get2();				} else if(n1>0 && n2>0 && comp()<0 || n2==0) {					fseek(f[F2], bot2, 0);					get2();					get1();				} else /*(n1>0 && n2>0 && comp()>0 || n1==0)*/{					fseek(f[F2], top2, 0);					bot2 = top2;					get2();					break;				}			}		}	}}voidseek1(){	int n1, n2;	int top1=0;	int bot1 = ftell(f[F1]);	get1();	get2();	while(n1>0 && n2>0 || (a1||a2) && n1+n2>0) {		if(n1>0 && n2>0 && comp()>0 || n1==0) {			if(a2) output(0, n2);			get2();		} else if(n1>0 && n2>0 && comp()<0 || n2==0) {			if(a1) output(n1, 0);			bot1 = ftell(f[F1]);			get1();		} else /*(n1>0 && n2>0 && comp()==0)*/ {			while(n2>0 && comp()==0) {				output(n1, n2);				top1 = ftell(f[F1]);				get1();			}			fseek(f[F1], bot1, 0);			get2();			get1();			for(;;) {				if(n1>0 && n2>0 && comp()==0) {					output(n1, n2);					get1();				} else if(n1>0 && n2>0 && comp()>0 || n1==0) {					fseek(f[F1], bot1, 0);					get2();					get1();				} else /*(n1>0 && n2>0 && comp()<0 || n2==0)*/{					fseek(f[F1], top1, 0);					bot1 = top1;					get1();					break;				}			}		}	}}intinput(int n)		/* get input line and split into fields */{	register int i, c;	Rune *bp;	Rune **pp;	char line[BUFSIZ];	bp = buf[n];	pp = ppi[n];	if (fgets(line, BUFSIZ, f[n]) == 0)		return(0);	strtorune(bp, line);	i = 0;	do {		i++;		if (sep1 == ' ')	/* strip multiples */			while ((c = *bp) == sep1 || c == sep2)				bp++;	/* skip blanks */		*pp++ = bp;	/* record beginning */		while ((c = *bp) != sep1 && c != '\n' && c != sep2 && c != '\0')			bp++;		*bp++ = '\0';	/* mark end by overwriting blank */	} while (c != '\n' && c != '\0' && i < NFLD-1);	if (c != '\n')		discard++;	*pp = 0;	return(i);}voidoutput(int on1, int on2)	/* print items from olist */{	int i;	Rune *temp;	char buf[BUFSIZ];	if (no <= 0) {	/* default case */		printf("%s", runetostr(buf, on1? ppi[F1][j1]: ppi[F2][j2]));		for (i = 0; i < on1; i++)			if (i != j1)				printf("%s%s", sepstr, runetostr(buf, ppi[F1][i]));		for (i = 0; i < on2; i++)			if (i != j2)				printf("%s%s", sepstr, runetostr(buf, ppi[F2][i]));		printf("\n");	} else {		for (i = 0; i < no; i++) {			if (olistf[i]==F0 && on1>j1)				temp = ppi[F1][j1];			else if (olistf[i]==F0 && on2>j2)				temp = ppi[F2][j2];			else {				temp = ppi[olistf[i]][olist[i]];				if(olistf[i]==F1 && on1<=olist[i] ||				   olistf[i]==F2 && on2<=olist[i] ||				   *temp==0)					temp = null;			}			printf("%s", runetostr(buf, temp));			if (i == no - 1)				printf("\n");			else				printf("%s", sepstr);		}	}}voiderror(char *s1, char *s2){	fprintf(stderr, "join: ");	fprintf(stderr, s1, s2);	fprintf(stderr, "\n");	exits(s1);}char *getoptarg(int *argcp, char ***argvp){	int argc = *argcp;	char **argv = *argvp;	if(argv[1][2] != 0)		return &argv[1][2];	if(argc<=2 || argv[2][0]=='-')		error("incomplete option %s", argv[1]);	*argcp = argc-1;	*argvp = ++argv;	return argv[1];}voidoparse(char *s){	for (no = 0; no<2*NFLD && *s; no++, s++) {		switch(*s) {		case 0:			return;		case '0':			olistf[no] = F0;			break;		case '1':		case '2':			if(s[1] == '.' && isdigit(s[2])) {				olistf[no] = *s=='1'? F1: F2;				olist[no] = atoi(s += 2);				break;			} /* fall thru */		default:			error("invalid -o list", "");		}		if(s[1] == ',')			s++;	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -