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

📄 tic.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
字号:
#ifdef lintstatic char *sccsid = "@(#)tic.c	4.1	(ULTRIX)	7/2/90";#endif lint#ifdef pdp11	/* Has to be this small to fit, even split I/D, with several use='s */# define CAPSIZ	2048#else# define CAPSIZ	4096#endif#define MAXHOP	32	/* max number of use= indirections */#define COMMENT	'#'#define SEPARATE	','#define NUMBER	'#'#define STRING	'='#define CANCEL	'@'#include <stdio.h>#include <ctype.h>#include <sys/types.h>#include <sys/stat.h>#include "../local/uparm.h"#ifndef E_TERMINFO#define E_TERMINFO "terminfo.src"#endif#ifndef termpath#define termpath(name) "/usr/lib/terminfo/name"#endif/* * L_ctermid is only defined on USG. * We use it here since we don't include curses.h. */#ifdef L_ctermid#define index strchr#endif/* * compile: program to compile a source terminfo file into object files */static	char *tbuf;static	int hopcount;	/* detect infinite loops in terminfo, init 0 */long	starttime;int	verbose;char	*terminfo;char	*tskip();char	*tgetstr();char	*tdecode();char	*getenv();char *sourcefile = E_TERMINFO;main(argc, argv)char **argv;{	int i;	time(&starttime);	while (argc > 1 && argv[1][0] == '-') {		switch(argv[1][1]) {		case 'v':			if (argv[1][2])				verbose = argv[1][2] - '0';			else				verbose++;			break;		default:			fprintf(stderr, "Usage: compile [-v] [files...]\n");			exit(1);		}		argc--; argv++;	}	terminfo = getenv("TERMINFO");	if (argc == 1) {		compfile(stdin, "stdin");	}	else for (i=1; i<argc; i++) {		compfile(fopen(argv[i], "r"), argv[i]);	}}/* * Compile a file.  This is very similar to the * code in tgetstr but it passes through the whole file. */compfile(tf, fname)	FILE *tf;	char *fname;{	register char *cp;	register int c;	register int i = 0, cnt = 0;	char bp[CAPSIZ];	char ibuf[CAPSIZ];	char *cp2;	if (tf == NULL) {		perror(fname);		return (-1);	}	ibuf[0] = 0;	for (;;) {		tbuf = bp;		strcpy(bp, ibuf);		for (;;) {			if (fgets(ibuf, sizeof ibuf, tf) == NULL) {				fclose(tf);				if (tnchkuse(fname))					store(bp);				return 0;			}			/* comment or blank line */			if (ibuf[0] == COMMENT || ibuf[0] == '\n')				continue;			cp = &ibuf[strlen(ibuf)-3];			/* Allow and ignore old style backslashes */			if (*cp == SEPARATE && cp[1] == '\\')				cp[1] = 0;			cp[2] = 0;	/* get rid of newline */			/* lines with leading white space are continuation */			if (!isspace(ibuf[0]) && *bp)				break;			if (strlen(bp) + strlen(ibuf) >= CAPSIZ) {				fprintf(stdout, "Terminfo entry too long:\n");				fprintf(stdout, "%s", bp);			}			else {				cp = ibuf;				while (isspace(*cp))					cp++;				strcat(bp, cp);			}		}		/*		 * We have it, now do something with it.		 */		if (tnchkuse(fname))			store(bp);	}}/* * Get an entry for terminal name in buffer bp, * from the terminfo file.  Parse is very rudimentary; * we just notice escaped newlines. */tgetent(bp, name, fname)	char *bp, *name, *fname;{	register char *cp;	register int c;	register int i = 0, cnt = 0;	char ibuf[CAPSIZ];	char *cp2;	FILE *tf;	ibuf[0] = 0;	tf = fopen(fname, "r");	if (tf == NULL)		return (-1);	tbuf = bp;	for (;;) {		strcpy(bp, ibuf);		for (;;) {			if (fgets(ibuf, sizeof ibuf, tf) == NULL) {				fclose(tf);				if (tnamatch(name))					return(tnchkuse(fname));				return 0;			}			if (ibuf[0] == COMMENT) /* comment */				continue;			cp = &ibuf[strlen(ibuf)-3];			/* Allow and ignore old style backslashes */			if (*cp == SEPARATE && cp[1] == '\\')				cp[1] = 0;			cp[2] = 0;	/* get rid of newline */			/* lines with leading white space are continuation */			if (!isspace(ibuf[0]) && *bp)				break;			if (strlen(bp) + strlen(ibuf) >= CAPSIZ) {				fprintf(stdout, "Terminfo entry too long:\n");				fprintf(stdout, "%s", bp);			}			else {				cp = ibuf;				while (isspace(*cp))					cp++;				strcat(bp, cp);			}		}		/*		 * The real work for the match.		 */		if (tnamatch(name)) {			fclose(tf);			return(tnchkuse(fname));		}	}}/* * tnchkuse: check the last entry, see if it's use=xxx. If so, * recursively find xxx and append that entry (minus the names) * to take the place of the use=xxx entry. This allows terminfo * entries to say "like an HP2621 but doesn't turn on the labels". * Note that this works because of the left to right scan. */tnchkuse(fname)char *fname;{	register char *p, *q;	char tcname[16];	/* name of similar terminal */	char tcbuf[CAPSIZ];	char restbuf[CAPSIZ];	char *holdtbuf = tbuf;	char *beg_use, *beg_next;	char *index();	int l;	p = tbuf;	if (++hopcount > MAXHOP) {		fprintf(stdout, "Infinite use= loop '%s'\n", tbuf);		return (0);	}	for (;;) {		p = index(p, 'u');		if (p == NULL) {			tbuf = holdtbuf;			return 1;		}		beg_use = p;		if (*++p != 's' || *++p != 'e' || *++p != '=')			continue;		strncpy(tcname, ++p, sizeof tcname);		q = index(tcname, SEPARATE);		if (q)			*q = 0;		/* try local file ... */		if (tgetent(tcbuf, tcname, fname) != 1)	{			/* ... and master */			if (tgetent(tcbuf, tcname, E_TERMINFO) != 1) {				printf("Cannot find term %s\n", tcname);				return(0);			}		}		/* Find the end of the use= spec */		for(beg_next=beg_use;		    *beg_next && *beg_next!=SEPARATE;		    beg_next++)			;		beg_next++;		while (isspace(*beg_next++))			;		beg_next--;				/* Now shuffle string around. */		strcpy(restbuf, beg_next);		p = index(tcbuf, SEPARATE);		if (p == NULL)			p = tcbuf;		else			p++;		strcpy(beg_use, p);		p = index(beg_use, '\0');		strcpy(p, restbuf);	}}/* * Tnamatch deals with name matching.  The first field of the terminfo * entry is a sequence of names separated by |'s, so we compare * against each such name.  The normal : terminator after the last * name (before the first field) stops us. */tnamatch(np)	char *np;{	register char *Np, *Bp;/* printf("tnamatch, np '%s', tbuf '%s'\n", np, tbuf); */	Bp = tbuf;	if (*Bp == COMMENT)		return(0);	for (;;) {		for (Np = np; *Np && *Bp == *Np; Bp++, Np++)			;		if (*Np == 0 && (*Bp == '|' || *Bp == SEPARATE || *Bp == 0))			return (1);		while (*Bp && *Bp != SEPARATE && *Bp != '|')			Bp++;		if (*Bp == 0 || *Bp == SEPARATE)			return (0);		Bp++;	}}/* * Skip to the next SEPARATE delimited field. */static char *tskip(bp)	register char *bp;{	while (*bp && *bp != SEPARATE)		bp++;	if (*bp == 0)		return bp;	bp++;	while (isspace(*bp) || *bp == SEPARATE)		bp++;	return (bp);}/* * Return the (numeric) option id. * Numeric options look like *	li#80 * i.e. the option string is separated from the numeric value by * a # character.  If the option is not found we return -1. * Note that we handle octal numbers beginning with 0. */tgetnum(id)	char *id;{	register int i, base;	register char *bp = tbuf;	int idl = strlen(id);	int sign = 1;	for (;;) {		bp = tskip(bp);		if (*bp == 0)			return (-1);		if (strncmp(id, bp, idl))			continue;		bp += idl;		if (*bp == CANCEL)			return(-1);		if (*bp != NUMBER && *bp != STRING)			continue;		bp++;		if (*bp == '-') {			sign = -1;			bp++;		}		base = 10;		if (*bp == '0')			base = 8;		i = 0;		while (isdigit(*bp))			i *= base, i += *bp++ - '0';		i *= sign;		return (i);	}}/* * Handle a flag option. * Flag options are given "naked", i.e. followed by a : or the end * of the buffer.  Return 1 if we find the option, or 0 if it is * not given. */tgetflag(id)	char *id;{	register char *bp = tbuf;	int idl = strlen(id);	for (;;) {		bp = tskip(bp);		if (!*bp)			return (0);		if (strncmp(bp, id, idl) == 0) {			bp += idl;			if (!*bp || *bp == SEPARATE)				return (1);			else if (*bp == CANCEL)				return(0);		}	}}/* * Get a string valued option. * These are given as *	cl=^Z * Much decoding is done on the strings, and the strings are * placed in area, which is a ref parameter which is updated. * No checking on area overflow. */char *tgetstr(id, area)	char *id, **area;{	register char *bp = tbuf;	int idl = strlen(id);	for (;;) {		bp = tskip(bp);		if (!*bp)			return (0);		if (strncmp(id, bp, idl))			continue;		bp += idl;		if (*bp == CANCEL)			return(0);		if (*bp != STRING)			continue;		bp++;		return (tdecode(bp, area));	}}/* * Tdecode does the grung work to decode the * string capability escapes. */static char *tdecode(str, area)	register char *str;	char **area;{	register char *cp;	register int c;	register char *dp;	int i;	cp = *area;	while ((c = *str++) && c != SEPARATE) {		switch (c) {		case '^':			c = *str++ & 037;			break;		case '\\':			/*			 * \x escapes understood:			 *	\e	escape			 *	\E	escape			 *	\^	^			 *	\\	\			 *	\,	,			 *	\:	:			 *	\l	linefeed			 *	\n	newline (=linefeed)			 *	\r	return			 *	\t	tab			 *	\b	backspace			 *	\f	formfeed			 *	\s	space			 *	\0	null			 *	\###	octal ###			 */			dp = "e\033E\033^^\\\\,,::l\012n\nr\rt\tb\bf\fs ";			c = *str++;nextc:			if (*dp++ == c) {				c = *dp++;				break;			}			dp++;			if (*dp)				goto nextc;			if (isdigit(c)) {				c -= '0', i = 2;				do {					if (!isdigit(*str))						break;					c <<= 3;					c |= *str++ - '0';				} while (--i);				if (c == 0)					c = 0200;	/* don't term. str. */			}			break;		}		*cp++ = c;	}	*cp++ = 0;	str = *area;	*area = cp;	return (str);}extern char *boolnames[], *numnames[], *strnames[];extern char *boolcodes[], *numcodes[], *strcodes[];char *malloc();char *tgetstr();#define TIMAGNUM 0432store(cap)char *cap;{	register char *cp;	register int i;	register char **pp, **np;	char tcpbuf[1024];	char *tcp = tcpbuf;	char *tname = cap;	char *tnp;	char tnbuf[256], names[256];	char fnbuf[64], lnbuf[64];	char strtab[4096];	register char *strtabptr;	FILE *fd;	int sname, sbool;	while (*cap != SEPARATE)	/* skip over names */		cap++;	*cap = 0;	strcpy(tnbuf, tname);	strcpy(names, tname);	*cap = SEPARATE;	for (tnp=tnbuf; *tnp && *tnp != '|' && *tnp != SEPARATE; tnp++)		;	if (*tnp)		*tnp++ = 0;	if (terminfo) {		strcpy(fnbuf, terminfo);		strcat(fnbuf, "/");	} else {		strcpy(fnbuf, termpath(/));	}	strcat(fnbuf, tnbuf);	checkon(fnbuf);	if (verbose)		printf("create '%s'\n", fnbuf);	fd = fopen(fnbuf, "w");	if (fd == NULL) {		perror(fnbuf);		return;	}	putsh(TIMAGNUM, fd);	sname = strlen(names)+1;	putsh(sname, fd);	sbool = listlen(boolcodes);	putsh(sbool, fd);	putsh(listlen(numcodes), fd);	putsh(listlen(strcodes), fd);	putsh(0, fd);			/* length of string table */	/* Write out various terminal names to file, null terminated. */	for (cp=names; *cp; cp++)		putc(*cp, fd);	putc(0, fd);	/* Write out the booleans: flag */	for (pp=boolnames, np=boolcodes; *np; pp++,np++) {		i = tgetflag(*pp);		putc(i, fd);		if (verbose > 2)			printf("bool cap %s code %s val %d\n", *pp, *np, i);	}	if ((sname + sbool) & 1)		putc(0, fd);	/* Numbers: highbyte, lowbyte.  0377,0377 means -1 (missing) */	for (pp=numnames, np=numcodes;   *np; pp++,np++) {		i = tgetnum(*pp);		putsh(i, fd);		if (verbose > 1)			printf("num cap %s code %s val %d\n", *pp, *np, i);	}	/* Strings: offset into string table.  If cap is missing, -1 is used */	strtabptr = strtab;	for (pp=strnames, np=strcodes;   *np; pp++,np++) {		cp = tgetstr(*pp, &tcp);		if (verbose > 3)			if (cp)				printf("str %s code %s val %s\n", *pp, *np, cp);			else				printf("str %s code %s val NULL\n", *pp, *np);		if (cp) {			putsh(strtabptr-strtab, fd);			while (*strtabptr++ = *cp++)				;		} else {			putsh(-1, fd);		}	}	fwrite(strtab, 1, strtabptr-strtab, fd);	fseek(fd, 10L, 0);	/* Back to string table size in header */	putsh(strtabptr-strtab, fd);	fclose(fd);	hopcount = 0;	while (*tnp) {		i = 0;		for (tname=tnp; *tnp && *tnp != '|' && *tnp != SEPARATE; tnp++)			if (isspace(*tnp))				i = 1;		if (*tnp)			*tnp++ = 0;		if (i)			continue;		if (terminfo) {			strcpy(lnbuf, terminfo);			strcat(lnbuf, "/");		} else {			strcpy(lnbuf, termpath(/));		}		strcat(lnbuf, tname);		checkon(lnbuf);		link(fnbuf, lnbuf);		if (verbose)			printf("link '%s' '%s'\n", fnbuf, lnbuf);	}}/* * Write a short out to the file in machine-independent format. */putsh(val, fd)register val;FILE *fd;{	if (val != -1) {		putc(val&0377, fd);		putc((val>>8)&0377, fd);	} else {		/* Write -1 as two 0377's. */		putc(0377, fd);		putc(0377, fd);	}}listlen(list)register char **list;{	register int rv = 0;	while (*list) {		list++;		rv++;	}	return rv;}/* * Do various processing on a file name we are about to create. * If it already exists, and it's older than we started, unlink it. * Also insert a / after the 2nd char of the tail, and make sure * that directory exists. */checkon(fn)char *fn;{	struct stat stbuf;	char *fp, *cp;	char nbuf[64];	char cmdbuf[64];	/* Find last / */	for (cp=fn; *cp; cp++)		if (*cp == '/')			fp = cp;	if (cp-fp > 2) {		cp = fp+2;		strcpy(nbuf, fp+1);		*cp = 0;		if (stat(fn, &stbuf) < 0) {			sprintf(cmdbuf, "mkdir %s", fn);			if (verbose)				printf("%s\n", cmdbuf);			system(cmdbuf);		}		*cp++ = '/';		strcpy(cp, nbuf);	}	else		printf("%s: terminal name too short\n", fp+1);	if (stat(fn, &stbuf) < 0)		return;	if (stbuf.st_mtime < starttime) {		if (verbose > 1)			printf("unlink %s\n", fn);		unlink(fn);	}}

⌨️ 快捷键说明

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