ftp.nice.ch/pub/next/unix/audio/cmusic.bs.N.tar.gz#/src/lib/libfrm/expr.c

This is expr.c in view mode; [Download] [Up]

/* General-purpose expr (NOT used by cmusic, but can be used by any
   program for command line expression arguments, for example
   (see man 3X expr or help expr)
*/

#include <stdio.h>
#include <math.h>

#define LRPN 1000
#define UNOPS "{sin,cos,atan,ln,exp,floor,abs,rand,sqrt}{-}"
#define BINOPS "{^,%}{*,/}{+,-}"
#define POSTOPS "{dB,K,k,Deg,invs,MM}"
#define TWOPI (8.0 * atan(1.0) )

int exprerr = 0;	/* error flag */

float expr(string) char *string;{
    char *polish(), *rpnp, rpn[LRPN], *it, item[40], sym[40];
    int nops, i, n, top = 0;
    double stack[LRPN];

    exprerr = 0;
    rpnp = rpn;
    strncpy(rpn,polish(string,UNOPS,BINOPS,POSTOPS),LRPN);

    while(strlen(rpnp)){
	sfield(&rpnp, item, "", ",");
	it=item;
	sfield(&it, sym, "", "$");
	nops = atoi(it);
	if(!nops){
	    if(!index(sym,'.') && *sym == '0'){
		if( *(sym+1) == 'x' || *(sym+1) == 'X' ){
		    sscanf(sym+2, "%x", &n);
		} else {
		    sscanf(sym, "%o", &n);
		}
		    stack[++top] = n;
	    } else {
		if(!sscanf(sym,"%F",&stack[++top]))exprerr++;
	    }
	    continue;
	}
	if(nops){
	    if(!strcmp(sym,"sin")){stack[top] = sin(stack[top]); continue;}
	    if(!strcmp(sym,"cos")){stack[top] = cos(stack[top]); continue;}
	    if(!strcmp(sym,"atan")){stack[top] = atan(stack[top]); continue;}
	    if(!strcmp(sym,"ln")){stack[top] = log(stack[top]); continue;}
	    if(!strcmp(sym,"exp")){stack[top] = exp(stack[top]); continue;}
	    if(!strcmp(sym,"floor")){stack[top] = floor(stack[top]); continue;}
	    if(!strcmp(sym,"abs")){stack[top] = fabs(stack[top]); continue;}
	    if(!strcmp(sym,"sqrt")){stack[top] = sqrt(stack[top]); continue;}
	    if(!strcmp(sym,"rand")){
		stack[top] = (double) rand()/(double) 0x7fffffff * stack[top]; 
		continue;}
	    if(!strcmp(sym,"-") && nops == 1){
		stack[top] = -stack[top];
		continue;
	    }
	    if(!strcmp(sym,"-") && nops == 2){
		stack[top-1] = stack[top-1] - stack[top];
		top--;
		continue;
	    }
	    if(!strcmp(sym,"+") && nops == 2){
		stack[top-1] = stack[top-1] + stack[top];
		top--;
		continue;
	    }
	    if(!strcmp(sym,"*") && nops == 2){
		stack[top-1] = stack[top-1] * stack[top];
		top--;
		continue;
	    }
	    if(!strcmp(sym,"/") && nops == 2){
		stack[top-1] = stack[top-1] / stack[top];
		top--;
		continue;
	    }
	    if(!strcmp(sym,"^") && nops == 2){
		stack[top-1] = pow( stack[top-1], stack[top]);
		top--;
		continue;
	    }
	    if(!strcmp(sym,"%") && nops == 2){
		stack[top-1] = (int) stack[top-1] % (int) stack[top];
		top--;
		continue;
	    }
	    if(!strcmp(sym,"dB") && nops == 1){
		stack[top] = pow( (double) 10.0, stack[top]/20.);
		continue;
	    }
	    if(!strcmp(sym,"K") && nops == 1){
		stack[top] = stack[top] * 1024.0;
		continue;
	    }
	    if(!strcmp(sym,"k") && nops == 1){
		stack[top] = stack[top] * 1000.0;
		continue;
	    }
	    if(!strcmp(sym,"Deg") && nops == 1){
		stack[top] = stack[top] / 360.0 * TWOPI;
		continue;
	    }
	    if(!strcmp(sym,"invs") && nops == 1){
		if(stack[top]<1.0){stack[top] = 1.0; continue;}
		n = stack[top];
		stack[top] = 0;
		for(i = 1; i <= n; i++)stack[top] += 1.0/i;
		continue;
	    }
	    if(!strcmp(sym,"MM") && nops == 1){
		stack[top] = 60.0 / stack[top];
		continue;
	    }
	    }
	    exprerr++;
	}
	if(top != 1)exprerr++;
	return( (float) stack[top]);
}

sfield(input,string,iglist,brklist) char **input, *string, *iglist, *brklist;{
    int leading, c;
    leading = 1;
    while( (c = *(*input)++) != NULL){
	if(leading && c==' ')continue;
	if(index(iglist,c))continue;
	if(!index(brklist,c)){*string++ = c; leading = 0; continue;}
	    else {*string = NULL; return(c);}
    }
    return(NULL);
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.