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

📄 tparm.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
字号:
/*	Copyright (c) 1984 AT&T	*//*	  All Rights Reserved  	*//*	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T	*//*	The copyright notice above does not evidence any   	*//*	actual or intended publication of such source code.	*/#ifndef lintstatic	char sccsid[] = "@(#)tparm.c 1.1 92/07/30 SMI"; /* from S5R3.1 1.8 */#endif/* Copyright (c) 1979 Regents of the University of California */#include	"curses_inc.h"#ifndef	_CHCTRL#define	_CHCTRL(c)	('c' & 037)#endif	/* _CHCTRL */char	*_branchto();/* * Routine to perform parameter substitution. * instring is a string containing printf type escapes. * The whole thing uses a stack, much like an HP 35. * The following escapes are defined for substituting row/column: * *	%[:[-+ #0]][0-9][.][0-9][dsoxX] *		print pop() as in printf(3), as defined in the local *		sprintf(3), except that a leading + or - must be preceded *		with a colon (:) to distinguish from the plus/minus operators. * *	%c	print pop() like %c in printf(3) *	%l	pop() a string address and push its length. *	%P[a-z] set dynamic variable a-z *	%g[a-z] get dynamic variable a-z *	%P[A-Z] set static variable A-Z *	%g[A-Z] get static variable A-Z * *	%p[1-0]	push ith parm *	%'c'	char constant c *	%{nn}	integer constant nn * *	%+ %- %* %/ %m		arithmetic (%m is mod): push(pop() op pop()) *	%& %| %^		bit operations:		push(pop() op pop()) *	%= %> %<		logical operations:	push(pop() op pop()) *	%A %O			logical AND, OR		push(pop() op pop()) *	%! %~			unary operations	push(op pop()) *	%%			output % *	%? expr %t thenpart %e elsepart %; *				if-then-else, %e elsepart is optional. *				else-if's are possible ala Algol 68: *				%? c1 %t %e c2 %t %e c3 %t %e c4 %t %e %; *	% followed by anything else *				is not defined, it may output the character, *				and it may not. This is done so that further *				enhancements to the format capabilities may *				be made without worrying about being upwardly *				compatible from buggy code. * * all other characters are ``self-inserting''.  %% gets % output. * * The stack structure used here is based on an idea by Joseph Yao. */#define	_PUSH(i)	(stack[++top] = (i))#define	_POP()		(stack[top--])/* VARARGS */char	*tparm(instring, fp1, fp2, p3, p4, p5, p6, p7, p8, p9)char	*instring;long	fp1, fp2, p3, p4, p5, p6, p7, p8 , p9;{    static	char	result[512];    static	char	added[100];    int		vars[26];    long	stack[10], top = 0;    register	char	*cp = instring;    register	char	*outp = result;    register	int	c;    register	int	op;    int		sign;    int		onrow = 0;    long	p1 = fp1, p2 = fp2;	/* copy in case < 2 actual parms */    char	*xp;    char	formatbuffer[100];    char	*format;    int		looping;    short	*regs = cur_term->_regs;#ifdef	SYSV    int		sprintf();#else	/* SYSV */    char	*sprintf();#endif	/* SYSV */    if (instring == 0)    {#ifdef	DEBUG    if (outf)	fprintf(outf, "TPARM: null arg\n");#endif	/* DEBUG */	return (0);    }    added[0] = 0;    while (c = *cp++)    {	if (c != '%')	{	    *outp++ = c;	    continue;	}	op = stack[top];	switch (c = *cp++)	{	    /* PRINTING CASES */	    case ':':	    case ' ':	    case '#':	    case '0':	    case '1':	    case '2':	    case '3':	    case '4':	    case '5':	    case '6':	    case '7':	    case '8':	    case '9':	    case '.':	    case 'd':	    case 's':	    case 'o':	    case 'x':	    case 'X':		format = formatbuffer;		*format++ = '%';		/* leading ':' to allow +/- in format */		if (c == ':')		    c = *cp++;		/* take care of flags, width and precision */		looping = 1;		while (c && looping)		    switch (c)		    {			case '-':			case '+':			case ' ':			case '#':			case '0':			case '1':			case '2':			case '3':			case '4':			case '5':			case '6':			case '7':			case '8':			case '9':			case '.':			    *format++ = c;			    c = *cp++;			    break;			default:			    looping = 0;		    }		/* add in the conversion type */		switch (c)		{		    case 'd':		    case 's':		    case 'o':		    case 'x':		    case 'X':			*format++ = c;			break;		    default:#ifdef	DEBUG			    if (outf)				fprintf(outf, "TPARM: invalid conversion type\n");#endif	/* DEBUG */			    return (0);		}		*format = '\0';		/*		 * Pass off the dirty work to sprintf.		 * It's debatable whether we should just pull in		 * the appropriate code here. I decided not to for now.		 */		if (c == 's')		    (void) sprintf(outp, formatbuffer, (char *) op);		else		    (void) sprintf(outp, formatbuffer, op);		/*		 * Advance outp past what sprintf just did. 		 * sprintf returns an indication of its length on some		 * systems, others the first char, and there's		 * no easy way to tell which. The Sys V on		 * BSD emulations are particularly confusing.		 */		while (*outp)		    outp++;		(void) _POP();		continue;	    case 'c':		/*		 * This code is worth scratching your head at for a		 * while.  The idea is that various weird things can		 * happen to nulls, EOT's, tabs, and newlines by the		 * tty driver, arpanet, and so on, so we don't send		 * them if we can help it.  So we instead alter the		 * place being addessed and then move the cursor		 * locally using UP or RIGHT.		 *		 * This is a kludge, clearly.  It loses if the		 * parameterized string isn't addressing the cursor		 * (but hopefully that is all that %c terminals do		 * with parms).  Also, since tab and newline happen		 * to be next to each other in ASCII, if tab were		 * included a loop would be needed.  Finally, note		 * that lots of other processing is done here, so		 * this hack won't always work (e.g. the Ann Arbor		 * 4080, which uses %B and then %c.)		 */		switch (op)		{		    /*		     * Null.  Problem is that our 		     * output is, by convention, null terminated.		     */		    case 0:			op = 0200;   /* Parity should be ignored */			break;			/*			 * Control D.  Problem is that certain very ancient			 * hardware hangs up on this, so the current (!)			 * UNIX tty driver doesn't xmit control D's.			 */		    case _CHCTRL(d):			/*			 * Newline.  Problem is that UNIX will expand			 * this to CRLF.			 */		    case '\n':			xp = onrow ? cursor_down : cursor_right;			if (onrow && xp && op < lines-1 && cursor_up)			{			    op += 2;			    xp = cursor_up;			}			if (xp && instring == cursor_address)			{			    (void) strcat(added, xp);			    op--;			}			break;			/*			 * Tab used to be in this group too,			 * because UNIX might expand it to blanks.			 * We now require that this tab mode be turned			 * off by any program using this routine,			 * or using termcap in general, since some			 * terminals use tab for other stuff, like			 * nondestructive space.  (Filters like ul			 * or vcrt will lose, since they can't stty.)			 * Tab was taken out to get the Ann Arbor			 * 4080 to work.			 */		}		*outp++ = op;		(void) _POP();		break;	    case 'l':		xp = (char *) _POP();		_PUSH(strlen(xp));		break;	    case '%':		*outp++ = c;		break;	    /*	     * %i: shorthand for increment first two parms.	     * Useful for terminals that start numbering from	     * one instead of zero (like ANSI terminals).	     */	    case 'i':		p1++;		p2++;		break;	    /* %pi: push the ith parameter */	    case 'p':		switch (c = *cp++)		{		    case '1':			_PUSH(p1);			break;		    case '2':			_PUSH(p2);			break;		    case '3':			_PUSH(p3);			break;		    case '4':			_PUSH(p4);			break;		    case '5':			_PUSH(p5);			break;		    case '6':			_PUSH(p6);			break;		    case '7':			_PUSH(p7);			break;		    case '8':			_PUSH(p8);			break;		    case '9':			_PUSH(p9);			break;		    default:#ifdef	DEBUG			if (outf)			    fprintf(outf, "TPARM: bad parm number\n");#endif	/* DEBUG */			return (0);		}		onrow = (c == '1');		break;	/* %Pi: pop from stack into variable i (a-z) */	    case 'P':		if (*cp >= 'a' && *cp <= 'z')		    vars[*cp++ - 'a'] = _POP();		else		    if (*cp >= 'A' && *cp <= 'Z')			regs[*cp++ - 'a'] = _POP();#ifdef	DEBUG		    else			if (outf)			    fprintf(outf, "TPARM: bad register name\n");#endif	/* DEBUG */		break;	    /* %gi: push variable i (a-z) */	    case 'g':		if (*cp >= 'a' && *cp <= 'z')		    _PUSH(vars[*cp++ - 'a']);		else		    if (*cp >= 'A' && *cp <= 'Z')			_PUSH(regs[*cp++ - 'a']);#ifdef	DEBUG		    else			if (outf)			    fprintf(outf, "TPARM: bad register name\n");#endif	/* DEBUG */		break;	    /* %'c' : character constant */	    case '\'':		_PUSH(*cp++);		if (*cp++ != '\'')		{#ifdef	DEBUG		    if (outf)			fprintf(outf, "TPARM: missing closing quote\n");#endif	/* DEBUG */		    return (0);		}		break;	    /* %{nn} : integer constant.  */	    case '{':		op = 0;		sign = 1;		if (*cp == '-')		{		    sign = -1;		    cp++;		}		else		    if (*cp == '+')			cp++;		while ((c = *cp++) >= '0' && c <= '9')		{			op = 10 * op + c - '0';		}		if (c != '}')		{#ifdef	DEBUG		    if (outf)			fprintf(outf, "TPARM: missing closing brace\n");#endif	/* DEBUG */		    return (0);		}		_PUSH(sign * op);		break;	    /* binary operators */	    case '+':		c = _POP();		op = _POP();		_PUSH(op + c);		break;	    case '-':		c = _POP();		op = _POP();		_PUSH(op - c);		break;	    case '*':		c = _POP();		op = _POP();		_PUSH(op * c);		break;	    case '/':		c = _POP();		op = _POP();		_PUSH(op / c);		break;	    case 'm':		c = _POP();		op = _POP();		_PUSH(op % c);		break; /* %m: mod */	    case '&':		c = _POP();		op = _POP();		_PUSH(op & c);		break;	    case '|':		c = _POP();		op = _POP();		_PUSH(op | c);		break;	    case '^':		c = _POP();		op = _POP();		_PUSH(op ^ c);		break;	    case '=':		c = _POP();		op = _POP();		_PUSH(op == c);		break;	    case '>':		c = _POP();		op = _POP();		_PUSH(op > c);		break;	    case '<':		c = _POP();		op = _POP();		_PUSH(op < c);		break;	    case 'A':		c = _POP();		op = _POP();		_PUSH(op && c);		break; /* AND */	    case 'O':		c = _POP();		op = _POP();		_PUSH(op || c);		break; /* OR */	    /* Unary operators. */	    case '!':		stack[top] = !stack[top];		break;	    case '~':		stack[top] = ~stack[top];		break;	    /* Sorry, no unary minus, because minus is binary. */	    /*	     * If-then-else.  Implemented by a low level hack of	     * skipping forward until the match is found, counting	     * nested if-then-elses.	     */	    case '?':	/* IF - just a marker */		break;	    case 't':	/* THEN - branch if false */		if (!_POP())		    cp = _branchto(cp, 'e');		break;	    case 'e':	/* ELSE - branch to ENDIF */		cp = _branchto(cp, ';');		break;	    case ';':	/* ENDIF - just a marker */		break;	    default:#ifdef	DEBUG		if (outf)		    fprintf(outf, "TPARM: bad % sequence\n");#endif	/* DEBUG */		return (0);	}    }    (void) strcpy(outp, added);    return (result);}char	*_branchto(cp, to)register	char	*cp;char		to;{    register	int	level = 0;    register	char	c;    while (c = *cp++)    {	if (c == '%')	{	    if ((c = *cp++) == to || c == ';')	    {		if (level == 0)		{		    return (cp);		}	    }	    if (c == '?')		level++;	    if (c == ';')		level--;	}    }#ifdef	DEBUG    if (outf)	fprintf(outf, "TPARM: no matching ENDIF");#endif	/* DEBUG */    return (0);}

⌨️ 快捷键说明

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