/* xlthrow - throw to a catch */ void xlthrow(LVAL tag, LVAL val) { XLCONTEXT *cptr; /* find a catch context */ for (cptr = xlcontext; cptr; cptr = cptr->c_xlcontext) if ((cptr->c_flags & CF_THROW) && cptr->c_expr == tag) xljump(cptr,CF_THROW,val); xlfail("no target for THROW"); }
/* xlreturn - return from a block */ void xlreturn(LVAL name, LVAL val) { XLCONTEXT *cptr; /* find a block context */ for (cptr = xlcontext; cptr; cptr = cptr->c_xlcontext) if (cptr->c_flags & CF_RETURN && cptr->c_expr == name) xljump(cptr,CF_RETURN,val); xlfail("no target for RETURN"); }
/* findandjump - find a target context frame and jump to it */ LOCAL void findandjump(int mask, const char *error) { XLCONTEXT *cptr; /* find a block context */ for (cptr = xlcontext; cptr; cptr = cptr->c_xlcontext) if (cptr->c_flags & mask) xljump(cptr,mask,NIL); xlabort(error); }
/* xlsignal - signal an error */ void xlsignal(const char *emsg, LVAL arg) { XLCONTEXT *cptr; /* find an error catcher */ for (cptr = xlcontext; cptr; cptr = cptr->c_xlcontext) if (cptr->c_flags & CF_ERROR) { if (cptr->c_expr && emsg) xlerrprint("error",NULL,emsg,arg); xljump(cptr,CF_ERROR,NIL); } }
/* xlgo - go to a label */ void xlgo(LVAL label) { XLCONTEXT *cptr; LVAL *argv; int argc; /* find a tagbody context */ for (cptr = xlcontext; cptr; cptr = cptr->c_xlcontext) if (cptr->c_flags & CF_GO) { argc = cptr->c_xlargc; argv = cptr->c_xlargv; while (--argc >= 0) if (*argv++ == label) { cptr->c_xlargc = argc; cptr->c_xlargv = argv; xljump(cptr,CF_GO,NIL); } } xlfail("no target for GO"); }
int nyx_get_audio(nyx_audio_callback callback, void *userdata) { float *buffer = NULL; sound_type *snds = NULL; long *totals = NULL; long *lens = NULL; sound_type snd; int result = 0; int num_channels; int ch; // Any variable whose value is set between the setjmp() and the "finish" label // and that is used after the "finish" label, must be marked volatile since // any routine outside of the current one that calls longjmp() will cause values // cached in registers to be lost. volatile int success = FALSE; if (nyx_get_type(nyx_result) != nyx_audio) { return FALSE; } #if defined(NYX_MEMORY_STATS) && NYX_MEMORY_STATS printf("\nnyx_get_audio before\n"); xmem(); #endif num_channels = nyx_get_audio_num_channels(); buffer = (sample_type *) malloc(max_sample_block_len * sizeof(sample_type)); if (buffer == NULL) { goto finish; } snds = (sound_type *) malloc(num_channels * sizeof(sound_type)); if (snds == NULL) { goto finish; } totals = (long *) malloc(num_channels * sizeof(long)); if (totals == NULL) { goto finish; } lens = (long *) malloc(num_channels * sizeof(long)); if (lens == NULL) { goto finish; } // Setup a new context xlbegin(&nyx_cntxt, CF_TOPLEVEL|CF_CLEANUP|CF_BRKLEVEL|CF_ERROR, s_true); // Set the context jump destination if (setjmp(nyx_cntxt.c_jmpbuf)) { // If the script is cancelled or some other condition occurs that causes // the script to exit and return to this level, then we don't need to // restore the previous context. goto finish; } for (ch = 0; ch < num_channels; ch++) { if (num_channels == 1) { snd = getsound(nyx_result); } else { snd = getsound(getelement(nyx_result, ch)); } snds[ch] = snd; totals[ch] = 0; lens[ch] = snd_length(snd, snd->stop); } while (result == 0) { for (ch =0 ; ch < num_channels; ch++) { sample_block_type block; long cnt; int i; snd = snds[ch]; cnt = 0; block = sound_get_next(snd, &cnt); if (block == zero_block || cnt == 0) { success = TRUE; result = -1; break; } // Copy and scale the samples for (i = 0; i < cnt; i++) { buffer[i] = block->samples[i] * snd->scale; } result = callback((float *)buffer, ch, totals[ch], cnt, lens[ch], userdata); if (result != 0) { result = -1; break; } totals[ch] += cnt; } } // This will unwind the xlisp context and restore internals to a point just // before we issued our xlbegin() above. This is important since the internal // xlisp stacks will contain pointers to invalid objects otherwise. // // Also note that execution will jump back up to the statement following the // setjmp() above. xljump(&nyx_cntxt, CF_TOPLEVEL, NIL); // Never reached finish: if (buffer) { free(buffer); } if (lens) { free(lens); } if (totals) { free(totals); } if (snds) { free(snds); } gc(); #if defined(NYX_MEMORY_STATS) && NYX_MEMORY_STATS printf("\nnyx_get_audio after\n"); xmem(); #endif return success; }
nyx_rval nyx_eval_expression(const char *expr_string) { LVAL expr = NULL; #if defined(NYX_MEMORY_STATS) && NYX_MEMORY_STATS printf("\nnyx_eval_expression before\n"); xmem(); #endif nyx_result = NULL; nyx_result_type = nyx_error; // Check argument if (!expr_string || !strlen(expr_string)) { return nyx_get_type(nyx_result); } nyx_expr_string = expr_string; nyx_expr_len = strlen(nyx_expr_string); nyx_expr_pos = 0; // Protect the expression from being garbage collected xlprot1(expr); // Setup a new context xlbegin(&nyx_cntxt, CF_TOPLEVEL|CF_CLEANUP|CF_BRKLEVEL|CF_ERROR, s_true); // Set the context jump destination if (setjmp(nyx_cntxt.c_jmpbuf)) { // If the script is cancelled or some other condition occurs that causes // the script to exit and return to this level, then we don't need to // restore the previous context. goto finish; } while (nyx_expr_pos < nyx_expr_len) { expr = NULL; // Read an expression if (!xlread(getvalue(s_stdin), &expr, FALSE)) { break; } #if 0 /* save the input expression (so the user can refer to it as +, ++, or +++) */ xlrdsave(expr); #endif // Evaluate the expression nyx_result = xleval(expr); } // This will unwind the xlisp context and restore internals to a point just // before we issued our xlbegin() above. This is important since the internal // xlisp stacks will contain pointers to invalid objects otherwise. // // Also note that execution will jump back up to the statement following the // setjmp() above. xljump(&nyx_cntxt, CF_TOPLEVEL, NIL); // Never reached finish: xlflush(); xlpop(); // unprotect expr gc(); #if defined(NYX_MEMORY_STATS) && NYX_MEMORY_STATS printf("\nnyx_eval_expression after\n"); xmem(); #endif return nyx_get_type(nyx_result); }