/* @(#)run.c 1.9 89/12/11 * * Run time interpreter used by the popi program. * * Popi was originally written by Gerard J. Holzmann - AT&T Bell Labs. * This version is based on the code in his Prentice Hall book, * "Beyond Photography - the digital darkroom," ISBN 0-13-074410-7, * which is copyright (c) 1988 by Bell Telephone Laboratories, Inc. * * Permission is given to distribute these extensions, as long as these * introductory messages are not removed, and no monies are exchanged. * * No responsibility is taken for any errors or inaccuracies inherent * either to the comments or the code of this program, but if reported * (see README file) then an attempt will be made to fix them. */ #include #include "popi.h" #if SEQPAR #include #endif /* SEQPAR */ #define STACKSIZE 128 #define dop(OP) a = *--sp ; tp = sp-1 ; *tp = (*tp OP (stack_t) a) /* local function prototypes */ void prun P((void)); void SwapOldNew() { CUROLD = CURNEW; CURNEW = 1 - CUROLD; } static void prun() { long *ParseEnd; /* after end of parse string */ int x, y; /* coordinates */ int nrange = 0; /* no. range errors */ ParseEnd = &parsed[prs]; if (Debug) { register long *CurrParse; /* pointer to current item in parse string */ FPRINTF(Debug, "Parse string\n"); for (CurrParse = parsed; CurrParse != ParseEnd; ++CurrParse) FPRINTF(Debug, "'%c' (%ld)\n", (char) *CurrParse, *CurrParse); FPRINTF(Debug, "---\n"); } /* * Warning: Microsoft Quick C generates incorrect code * for the following loop when optimisation is turned on. */ #ifndef SEQPAR for (y = 0; y < Ysize; ++y) #else /* ! SEQPAR */ for (y = m_myid; y < Ysize; y += m_numprocs) #endif /* ! SEQPAR */ { short *ap, /* precalculated polar angles */ *rp; /* precalculated polar radius */ register pixel_t *p; /* default destination */ ap = &avals[y * Xsize]; rp = &rvals[y * Xsize]; p = src[CURNEW].pix[y]; DEBUG((Debug, "y = %d\n", y)); for (x = 0; x < Xsize; ++x, ++p) { stack_t Stack[STACKSIZE]; /* the stack */ register stack_t *sp, /* stack pointer (top of stack) */ *tp; /* temp stack pointer */ stack_t a, b; int c; /* scratch */ register pixel_t *u; /* explicit destination */ register long *CurrParse; /* pointer to current item in parse string */ for (CurrParse = parsed, sp = Stack; CurrParse != ParseEnd; ++CurrParse) { if (*CurrParse == VALUE) { *sp++ = (stack_t) *++CurrParse; continue; } if (*CurrParse == '@') { --sp; if (Truncate) { if (*sp > Zmax) *sp = Zmax; else if (*sp < 0) *sp = 0; } *p = (pixel_t) *sp; continue; } switch ((int) *CurrParse) { case '+': dop(+); break; case '-': dop(-); break; case '*': dop(*); break; case '/': a = *--sp; tp = sp-1; if (a == 0) *tp = Zmax; else *tp = (*tp / (stack_t) a); break; case '%': a = *--sp; tp = sp-1; if (a == 0) *tp = 0; else *tp = (*tp % (stack_t) a); break; case '>': dop(>); break; case '<': dop(<); break; case GE: dop(>=); break; case LE: dop(<=); break; case EQ: dop(==); break; case NE: dop(!=); break; case AND: dop(&&); break; case OR: dop(||); break; case '^': dop(^); break; case '|': dop(|); break; case '&': dop(&); break; case 'x': *sp++ = (stack_t) x; break; case 'y': *sp++ = (stack_t) y; break; case UMIN: tp = sp-1; *tp = -(*tp); break; case '!': tp = sp-1; *tp = !(*tp); break; case '=': a = *--sp; u = (pixel_t *) *--sp; if (Truncate) { if (a > Zmax) a = Zmax; else if (a < 0) a = 0; } *u = (pixel_t) a; break; case CRVAL: a = *--sp; /* y */ b = *--sp; /* x */ tp = sp-1; c = (int) *tp; if ( RangeCheck && ( a > Xsize - 1 || a < 0 || b > Ysize - 1 || b < 0 ) ) { if (nrange++ == 0) FPRINTF(stderr, "Range err at (%d,%d) => %s[%d, %d]\n", x, y, src[c].str, b, a); } if (a >= Ysize) a = Ysize - 1; if (a < 0) a = 0; if (b >= Xsize) b = Xsize - 1; if (b < 0) b = 0; *tp = (stack_t) src[c].pix[a][b]; break; case CLVAL: a = *--sp; /* y */ b = *--sp; /* x */ tp = sp-1; c = (int) *tp; if ( RangeCheck && ( a > Xsize - 1 || a < 0 || b > Ysize - 1 || b < 0 ) ) { if (nrange++ == 0) FPRINTF(stderr, "Range err at (%d,%d) => %s[%d, %d]\n", x, y, src[c].str, b, a); } if (a >= Ysize) a = Ysize - 1; if (a < 0) a = 0; if (b >= Xsize) b = Xsize - 1; if (b < 0) b = 0; *tp = (stack_t) &(src[c].pix[a][b]); break; case PRVAL: { int xval, yval; a = *--sp; /* angle */ b = *--sp; /* radius */ xval = (int) (b * cos((double) DtoR(a)) + Xsize / 2.0); yval = (int) (- b * sin((double) DtoR(a)) + Ysize / 2.0); tp = sp - 1; c = (int) *tp; if (RangeCheck && (xval < 0 || xval >= Xsize || yval < 0 || yval >= Ysize)) { if (nrange++ == 0) FPRINTF(stderr, "Range err at (%d,%d) => %s{%d,%d} [%d,%d]\n", x, y, src[c].str, b, a, xval, yval); } if (xval < 0) xval = 0; if (xval >= Xsize) xval = Xsize - 1; if (yval < 0) yval = 0; if (yval >= Ysize) yval = Ysize - 1; *tp = (stack_t) src[c].pix[yval][xval]; } break; case PLVAL: { int xval, yval; a = *--sp; /* angle */ b = *--sp; /* radius */ xval = (int) (b * cos((double) DtoR(a)) + Xsize / 2.0); yval = (int) (- b * sin((double) DtoR(a)) + Ysize / 2.0); tp = sp - 1; c = (int) *tp; if (RangeCheck && (xval < 0 || xval >= Xsize || yval < 0 || yval >= Ysize)) { if (nrange++ == 0) FPRINTF(stderr, "Range err at (%d,%d) => %s{%d,%d} [%d,%d]\n", x, y, src[c].str, b, a, xval, yval); } if (xval < 0) xval = 0; if (xval >= Xsize) xval = Xsize - 1; if (yval < 0) yval = 0; if (yval >= Ysize) yval = Ysize - 1; *tp = (stack_t) &(src[c].pix[yval][xval]); } break; case POW: a = *--sp; /* exponent */ tp = sp-1; *tp = (stack_t) pow((double) *tp, (double) a); break; case 'a': #if NOMEM *sp++ = (stack_t) RtoD(atan2((double) y, (double) x)) + 0.5; #else /* !NOMEM */ *sp++ = (stack_t) *ap; #endif /* !NOMEM */ break; case 'r': *sp++ = (stack_t) *rp; break; case SIN: tp = sp-1; *tp = (stack_t) (sin((double) DtoR(*tp)) * (double)Zmax); break; case COS: tp = sp-1; *tp = (stack_t) (cos((double) DtoR(*tp)) * (double)Zmax); break; case ATAN: a = *--sp; tp = sp-1; *tp = (stack_t) RtoD(atan2((double) *tp, (double) a)); break; case HYPOT: a = *--sp; tp = sp - 1; *tp = (stack_t) hypot((double) *tp, (double) a); break; case ABS: tp = sp-1; *tp = *tp < 0 ? - *tp : *tp; break; case LOG: tp = sp-1; *tp = (stack_t) log((double) *tp); break; case SQRT: tp = sp-1; *tp = (stack_t) sqrt((double) *tp); break; case RAND: #if 0 tp = sp -1; *tp = (stack_t) RANDOM % *tp; #else *sp++ = (stack_t) RANDOM; #endif break; case LSHIFT: dop(<<); break; case RSHIFT: dop(>>); break; case '?': a = *--sp; CurrParse++; if (!a) CurrParse = &parsed[*CurrParse]; break; case ':': CurrParse = &parsed[CurrParse[1]]; break; default: if (*CurrParse < 127 && isprint(*CurrParse)) SPRINTF(ErrBuf, "run: unknown operator '%c' (%d)", *CurrParse, *CurrParse); else SPRINTF(ErrBuf, "run: unknown operator %d", *CurrParse); error(ERR_SNARK); return; } } ++ap; ++rp; } #if SEQPAR if (m_myid == 0) #endif /* SEQPAR */ disp_percentdone(y * 100 / (Ysize-1)); } #if 0 if (nrange != 0) FPRINTF(stderr, "Total of %d range errors corrected\n", nrange); #endif } void run() { int y; #if SEQPAR static int parked = 0; if (parked) m_rele_procs(); m_fork(prun); m_kill_procs(); /* For some reason, parking doesn't work properly ... m_park_procs(); parked = 1; /* so it can be released above */ #else /* ! SEQPAR */ prun(); #endif /* ! SEQPAR */ disp_percentdone(100); /* Can rely on '100' to terminate */ if (disp_active) { disp_imgstart(); for (y = 0; y < Ysize; ++y) disp_putline(src[CURNEW].pix[y], y); disp_imgend(); } SwapOldNew(); }