File:  [Research Unix] / researchv10no / cmd / basic / bas / fns.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:21:35 2018 UTC (8 years, 1 month ago) by root
Branches: belllabs, MAIN
CVS tags: researchv10, HEAD
researchv10 Norman

#include <stdio.h>
#include "ctype.h"
#include "typedef.h"
#include "basic.h"
#include "tokens.h"

#define	MAXRAND		2147483647

double	sqrt(), exp(), log(), atan(), sin(), cos(), fabs();
double	popfloat(), cvtnumber();
static	char str[MAXSTRING];
Stkptr	pop(), pushstring();
char	*allocstr(), *fprint(), *strpop();


/*
 * function --- interpret builtin function calls
 */

function()
{
	switch (*inptr) {
	case LEFT:
		fnarg("si");
		break;
	case RIGHT:
		fnarg("si");
		break;
	case MID:
		fnarg("sii");
		break;
	case UPSHIFT:
	case UNBLANK:
	case SYSTEM:
	case LEN:
	case VAL:
	case ASCII:
		fnarg("s");
		break;
	case RND:
	case ARG:
	case CHR:
	case RAND:
		fnarg("i");
		break;
	case SIN:
	case COS:
	case TAN:
	case ATN:
	case SQR:
	case EXPFN:
	case LOG:
	case INTFN:
	case ABS:
	case STR:
	case SGN:
		fnarg("f");
		break;
	default:
		return(0);
		}
	return(1);
}


/*
 * fnarg --- do type checking and evaluation of builtin functions
 */

fnarg(args)
char	*args;
{
	register int	op, i;
	register Stkptr s;
	register char	*q;
	char		*p;
	double		x, t;
	int		k, nc, n, ch, len;
	
	op = *inptr++;
	for (p = args; *p; ) {
		expr();
		switch (*p++) {

		case 's':
			if (((Stkptr)stkptr)->k_type != STRINGEXPR)
				err("string argument required");
			break;
		case 'i':
		case 'f':
			if (((Stkptr)stkptr)->k_type != FLOATEXPR)
				err("numeric argument required");
			break;
		default:
			badtype();
			}
		if (*p)
			expectc(COMMA);
		}
	expectc(RPAR);
	switch (op) {
	case SYSTEM:
		p = strpop();		/* got a string in UNIX format */
		i = exec("/bin/sh", "sh", "-c", p, 0);
		pushint(i);
		break;
	case LEFT:
		if ((i = popint()) < 0)
			i = 0;
		s = (Stkptr)stkptr;
		if (i > s->k_un.k_str.s_len)
			i = s->k_un.k_str.s_len;
		n = 0;
		goto common;
	case RIGHT:
		if ((i = popint()) < 0)
			i = 0;
		s = (Stkptr)stkptr;
		if (i > s->k_un.k_str.s_len)
			i = s->k_un.k_str.s_len;
		n = s->k_un.k_str.s_len - i;
		goto common;
	case MID:
		if ((i = popint()) < 0)
			i = 0;
		if ((n = popint() - 1) < 0)
			n = 0;
		s = (Stkptr)stkptr;
		if (n > s->k_un.k_str.s_len)
			n = s->k_un.k_str.s_len;
		if (i > s->k_un.k_str.s_len - n)
			i = s->k_un.k_str.s_len - n;
	common:
		if (n > 0 || i < s->k_un.k_str.s_len) {
			if (isstring(s->k_un.k_str.s_ptr)) {
				p = allocstr(NULL, i, 0);
				if (i)
					move(i, s->k_un.k_str.s_ptr+n, p);
				s->k_un.k_str.s_ptr = p;
				}
			else
				s->k_un.k_str.s_ptr += n;
			s->k_un.k_str.s_len = i;
			}
		break;
	case UPSHIFT:
		p = strpop();
		len = strlen(p);
		for (k = 0; k <= len; k++)
			if (!isalpha(*(p+k)) || isupper(*(p+k)))
				str[k] = p[k];
			else
				str[k] = toupper(p[k]);
		s = pushstring(str, len);
		s->k_un.k_str.s_ptr = str;
		s->k_un.k_str.s_len = len;
		break;
	case UNBLANK:
		p = strpop();
		len = strlen(p);
		for (k = nc = 0; k <= len; k++)
			if (*(p+k) != ' ')
				str[nc++] = p[k];
		s = pushstring(str, nc - 1);
		s->k_un.k_str.s_ptr = str;
		s->k_un.k_str.s_len = nc - 1;
		break;
	case LEN:
		s = pop(ANYTYPE);
		pushint(s->k_un.k_str.s_len);
		break;
	case CHR:
		ch = popint();
		s = pushstring(&ch, 1);
		s->k_un.k_str.s_ptr = allocstr(&ch, 1, 1);
		break;
	case STR:
		p = fprint(popfloat());
		len = strlen(p);
		s = pushstring(p, len);
		s->k_un.k_str.s_ptr = allocstr(p, len, len);
		break;
	case ARG:
		len = popint();
		p = (len > argcnt)? "" : argvec[len];
		len = strlen(p);
		s = pushstring(p, len);
		s->k_un.k_str.s_ptr = allocstr(p, len, len);
		break;
	case ASCII:
		s = pop(ANYTYPE);
		pushint(*s->k_un.k_str.s_ptr);
		break;
	case VAL:
		s = pop(ANYTYPE);
		p = q = s->k_un.k_str.s_ptr;
		i = s->k_un.k_str.s_len;
		pushfloat(cvtnumber(&p, i));
		if (p - q != i)
			err("invalid number %.*s", i, q);
		break;
	case SIN:
		pushfloat(sin(popfloat()));
		break;
	case COS:
		pushfloat(cos(popfloat()));
		break;
	case TAN:
		x = popfloat();
		pushfloat(sin(x)/cos(x));
		break;
	case SGN:
		x = popfloat();
		if (x > 0)
			t = 1;
		else
			if (x < 0)
				t = -1;
			else
				t = 0;
		pushfloat(t);
		break;
	case SQR:
		if ((x = popfloat()) >= 0)
			pushfloat(sqrt(x));
		else
			err("sqr of negatives undefined. check");
		break;
	case LOG:
		if ((x = popfloat()) != 0)
			pushfloat(log(fabs(x)));
		else
			err("log of zero is undefined. check");
		break;
	case EXPFN:
		pushfloat(exp(popfloat()));
		break;
	case ATN:
		pushfloat(atan(popfloat()));
		break;
	case ABS:
		pushfloat(fabs(popfloat()));
		break;
	case INTFN:
		pushfloat((double)(int)popfloat());
		break;
	case RND:
		if ((i = popint()) != 0)
			srand(i);
		pushfloat((double)rand() / MAXRAND);
		break;
	case RAND:
		i = popint();
		srand((int)time(0) + i);
		pushfloat(x = ((double)rand() / MAXRAND));
		break;
	default:
		err("function not found");
		}
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.