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

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

/* cmusic's private version of expr (knows about symbols, such as p5,
   and knows the current values of sampling rate, function length, etc. */
#include "mm.head.h"

#define LRPN 1024
#define UNOPS "{sin,cos,atan,ln,exp,floor,abs,rand,sqrt}{-}"
#define BINOPS "{^,%}{*,/}{+,-}"
#define POSTOPS "{S,Hz,dB,K,ms,Deg,sec,MM,IS}"

float expr(string) char *string;{
    char *polish(), *rpnp, rpn[LRPN], *it, item[1024], sym[1024];
    char *substr[LRPN];
    char *lb, *rb, *index(), ssstr[LRPN];
    int i, blev, nops, n, top = 0;
    float x,y,z;
    int subscriptval;
    double stack[LRPN];

    rpnp = rpn;
/* Strip out subscript expressions */
    while(lb = rb = index(string,'[')){
	blev = 0;
	while(*(++rb)){
	    if(*rb == '[')blev++; 
	    if(*rb == ']' && blev == 0)break;
	    if(*rb == ']')blev--;
	    if(blev < 0){
		Error++;
		PROUT("Unbalanced []'s\n",blev);
		return(0.0);
	    }
	}
	substr[0] = '\0';
	strncat(substr,lb+1,rb-lb-1);
	subscriptval = expr(substr);
	sprintf(ssstr,"%d",subscriptval);
	ssinsert(string,lb,rb,ssstr);
    }
    rpn[0] = '\0';
    strncat(rpn,polish(string,UNOPS,BINOPS,POSTOPS),LRPN);

    while(strlen(rpnp)){
	sfield(&rpnp, item, "", ",");
	it=item;
	sfield(&it, sym, "", "$");
	nops = atoi(it);
	if(!nops){
	    if(sym[0]=='p'){
		if(sym[1] != '[')n = atoi(&sym[1]);
		 else{
		    sym[strlen(sym)-1] = '\0';
		    n = expr(&sym[2]);
		 }
		if(n > Pmax){
		    Pmax = n;
		    EXTEND(Pp, Params, Pmax+1, float);
		    PROUT("%d note parameters (due to expression reference).\n",
			Pmax+1);
		}
		stack[++top] = *(Params + n);
		continue;
	    }
	    if(sym[0]=='v'){
		n = atoi(&sym[1]);
		if(n > Vmax){
		    Vmax = n;
		    EXTEND(Vp, Vars, Vmax+1, float);
		   PROUT("%d static variables (due to expression reference).\n",
			Vmax+1);
		}
		stack[++top] = *(Vars + n);
		continue;
	    }
	    for (i = strlen(sym)-1; i >=0; i--)
	     if(isdigit( *(sym+i)) || *(sym+i) == '.' || *(sym+i) == 'x'
	      || *(sym+i) == 'X') continue;
	       else{
		    Error++;
		    PROUT("\nEXPR: Illegal symbol: '%s'\n",sym);
		    return( (float) 0.0 );
	       }
	    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])){
		Error++;
		PROUT("\nEXPR: Illegal expression: '%s'\n",string);
		return( (float) 0.0 );
	    }
	}
	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) random()/(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] = (long) stack[top-1] % (long) stack[top];
		top--;
		continue;
	    }
	    if(!strcmp(sym,"Hz") && nops == 1){
		stack[top] = stack[top] * Lfuncs / Srate;
		continue;
	    }
	    if(!strcmp(sym,"sec") && nops == 1){
		stack[top] = Lfuncs / (stack[top] * Srate);
		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,"ms") && nops == 1){
		stack[top] = ceil(stack[top] * Srate / 1000.0);
		continue;
	    }
	    if(!strcmp(sym,"S") && nops == 1){
		stack[top] /= (double) Srate;
		continue;
	    }
	    if(!strcmp(sym,"MM") && nops == 1){
		stack[top] = 60.0 / stack[top];
		continue;
	    }
	    if(!strcmp(sym,"Deg") && nops == 1){
		stack[top] = stack[top] / 360.0 * TWOPI;
		continue;
	    }
	    if(!strcmp(sym,"IS") && nops == 1){
		if(stack[top]<1.0){stack[top] = 0.0; continue;}
		n = stack[top];
		stack[top] = 0;
		for(i = 1; i <= n; i++)stack[top] += 1.0/i;
		continue;
	    }
	}
	if(top != 1){
	    Error++;
	    PROUT("\nEXPR: Illegal expression: '%s'\n",string);
	    return( (float) 0.0 );
	}
	if(Verbose || Listfile || Barefile){ float v = (float) stack[top];
	    sprintf(item,"%f",v);
	    sqz0s(item);	/* Squeeze trailing fractional zeros */
	    if(Verbose)fprintf(stderr," {=%s} ", item);
	    if(Listfile)fprintf(Listfile," {=%s} ", item);
	    if(Barefile)fprintf(Barefile," {=%s} ", item);
	}
	return( (float) stack[top]);
}
ssinsert(s,a,b,new) char *s, *a, *b, *new;{
 char stemp[LRPN];
    stemp[0] = '\0';
    strncat(stemp,s,a-s);
    strcat(stemp,new);
    strcat(stemp,(b+1));
    strcpy(s,stemp);
    return;
}

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