This is sfexpr.c in view mode; [Download] [Up]
/*
* sfexpr - similar to expr() routine from libfrm.a, but optimized for
* parsing command line for csound. No major differences, some
* features left out, such as sin(), ln(), etc. Postoperators added:
* s - seconds, S - samples, K - 1024, ms - milliseconds, m - minutes,
* dB.
*/
#include <stdio.h>
#include <carl/sndio.h>
#include <math.h>
#define LRPN 200
#define UNOPS "{-}"
#define BINOPS "{^,%}{*,/}{+,-}"
#define POSTOPS "{dB,K,k,S,s,m,ms}"
#define TWOPI (8.0 * atan(1.0) )
float sfexpr(string, timefac)
char *string; float timefac;
{
char *polish(), *rpnp, rpn[LRPN], *it, item[40], sym[40];
int nops, n, top = 0;
double stack[LRPN];
rpnp = rpn;
strncpy(rpn,polish(string,UNOPS,BINOPS,POSTOPS),LRPN);
while(strlen(rpnp))
{
sffield(&rpnp, item, "", ",");
it=item;
sffield(&it, sym, "", "$");
nops = atoi(it);
if (!nops) /* it is a constant number */
{
if(!index(sym,'.') && *sym == '0') /* no '.' and '0' prefix */
{
if( *(sym+1) == 'x' || *(sym+1) == 'X' )
sscanf(sym+2, "%x", &n);
else sscanf(sym, "%o", &n);
stack[++top] = n;
}
else
sscanf(sym,"%F",&stack[++top]);
stack[top] *= timefac;
continue;
}
/* from here on, deal with operators only */
if (!strcmp(sym,"-") && nops == 1)
{
stack[top] = -stack[top];
continue;
}
else
if (nops == 2)
{
switch(sym[0])
{
case '-':
stack[top-1] = stack[top-1] - stack[top];
break;
case '+':
stack[top-1] = stack[top-1] + stack[top];
break;
case '*':
stack[top-1] = stack[top-1] * stack[top];
break;
case '/':
stack[top-1] = stack[top-1] / stack[top];
break;
case '^':
stack[top-1] = pow(stack[top-1], stack[top]);
break;
case '%':
stack[top-1] = (int) stack[top-1] % (int) stack[top];
}
top--;
}
else
if (nops == 1)
{
if(!strcmp(sym,"dB")){
stack[top] /= timefac;
stack[top] = pow( (double) 10.0, stack[top]/20.);
continue;
}
if(!strcmp(sym,"K")){
stack[top] *= 1024.0;
continue;
}
if(!strcmp(sym,"k")){
stack[top] *= 1000.0;
continue;
}
if(!strcmp(sym,"S")){
stack[top] /= timefac;
continue;
}
if(!strcmp(sym,"ms")){
stack[top] *= 0.001;
continue;
}
if(!strcmp(sym,"m")){
stack[top] *= 60.0;
continue;
}
if(!strcmp(sym,"s")){
continue;
}
}
}
return( (float) stack[top]);
}
sffield(input, string, iglist, brklist)
char **input, *string, *iglist, *brklist;
{
int leading = 1, c;
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;
}
}
return;
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.