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.