/** * Create a wrap from a value. * @ret: Ref. The returned value. * @value: The value. * @env: The environment. * &returns: Error. */ char *amp_wrap_make(struct ml_value_t **ret, struct ml_value_t *value, struct ml_env_t *env) { #define onexit struct amp_param_t *limit; chkfail(amp_match_unpack(value, "P", &limit)); *ret = amp_pack_effect((struct amp_effect_t){ amp_wrap_new(limit), &_wrap_iface });
/** * Create an ADSR from a value. * @value: The value. * @env: The environment. * @err: The error. * &returns: The value or null. */ char *amp_adsr_make(struct ml_value_t **ret, struct ml_value_t *value, struct ml_env_t *env) { #define onexit double min, max, atk, decay, sus, rel; chkfail(amp_match_unpack(value, "((f,f),(f,f,f,f))", &min, &max, &atk, &decay, &sus, &rel)); *ret = amp_pack_module((struct amp_module_t){ amp_adsr_new(min, max, atk, decay, sus, rel, amp_core_rate(env)), &_adsr_iface });
/** * Create a sine oscillator from a value. * @ret: Ref. The return value. * @value: The value. * @env: The environment. * &returns: Error */ char *amp_sine_make(struct ml_value_t **ret, struct ml_value_t *value, struct ml_env_t *env) { #define onexit struct amp_module_t phase; chkfail(amp_match_unpack(value, "M", &phase)); *ret = amp_pack_module((struct amp_module_t){ amp_osc_new(amp_osc_sine_v, phase), &_osc_iface });
/** * Create a gain from a value. * @ret: Ref. The returned value. * @value: The value. * @env: The environment. * &returns: Error. */ char *amp_inject_make(struct ml_value_t **ret, struct ml_value_t *value, struct ml_env_t *env) { #define onexit struct amp_seq_t seq; struct amp_box_t *box; chkfail(amp_match_unpack(value, "(S,*)", &seq, &box)); *ret = amp_poly_make(box, amp_inject_new(seq), &_inject_iface); return NULL; #undef onexit }
int main(void) { long pgsz = sysconf(_SC_PAGESIZE); plan_tests(17); #define chkfail(x, y, z, c1, c2) (call1 = 0, call2 = 0, errno = 0, ok1((fail = x) && (y) && errno == (z) && call1 == (c1) && call2 == (c2))); #define chkok( y, z, c1, c2) (call1 = 0, call2 = 0, errno = 0, fail = 0, ok1((y) && errno == (z) && call1 == (c1) && call2 == (c2))); chkfail(getrlimit_, altstack(8*MiB, wrap, 0, 0) == -1, e(getrlimit_), 0, 0); chkfail(setrlimit_, altstack(8*MiB, wrap, 0, 0) == -1, e(setrlimit_), getrlimit_, 0); chkfail(mmap_, altstack(8*MiB, wrap, 0, 0) == -1, e(mmap_), getrlimit_|setrlimit_, setrlimit_); chkfail(sigaltstack_, altstack(8*MiB, wrap, 0, 0) == -1, e(sigaltstack_), getrlimit_|setrlimit_|mmap_, setrlimit_|munmap_); chkfail(sigaction_, altstack(8*MiB, wrap, 0, 0) == -1, e(sigaction_), getrlimit_|setrlimit_|mmap_|sigaltstack_, setrlimit_|munmap_|sigaltstack_); chkfail(munmap_, altstack(8*MiB, wrap, 0, 0) == 1, e(munmap_), getrlimit_|setrlimit_|mmap_|sigaltstack_|sigaction_, setrlimit_|sigaltstack_|sigaction_); if (fail = 0, munmap(m_, msz_) == -1) err(1, "munmap"); chkok( altstack(1*MiB, wrap, (void *) 1000000, 0) == -1, EOVERFLOW, getrlimit_|setrlimit_|mmap_|sigaltstack_|sigaction_, setrlimit_|munmap_|sigaltstack_|sigaction_); // be sure segv catch is repeatable (SA_NODEFER) chkok( altstack(1*MiB, wrap, (void *) 1000000, 0) == -1, EOVERFLOW, getrlimit_|setrlimit_|mmap_|sigaltstack_|sigaction_, setrlimit_|munmap_|sigaltstack_|sigaction_); used = 1; chkfail(munmap_, altstack(1*MiB, wrap, (void *) 1000000, 0) == -1, EOVERFLOW, getrlimit_|setrlimit_|mmap_|sigaltstack_|sigaction_, setrlimit_|sigaltstack_|sigaction_); if (fail = 0, munmap(m_, msz_) == -1) err(1, "munmap"); ok1(altstack_max() == 1*MiB); diag("used: %lu", used); ok1(used >= 1*MiB - pgsz && used <= 1*MiB + pgsz); char *p; for(p = altstack_geterr(); *p; p++) if (*p >= '0' && *p <= '9') *p = '~'; #define estr "(altstack@~~~) SIGSEGV caught; (altstack@~~~) munmap(m, max): Unknown error ~~~" ok1(strcmp(altstack_geterr(), estr) == 0); char buf[ALTSTACK_ERR_MAXLEN*2] = {0}; if ((mystderr = fmemopen(buf, sizeof(buf), "w")) == NULL) err(1, "fmemopen"); altstack_perror(); fflush(mystderr); ok1(strcmp(buf, estr "\n") == 0); used = 1; chkok( altstack(8*MiB, wrap, (void *) 1000000, 0) == -1, EOVERFLOW, getrlimit_|setrlimit_|mmap_|sigaltstack_|sigaction_, setrlimit_|munmap_|sigaltstack_|sigaction_); diag("used: %lu", used); ok1(used >= 8*MiB - pgsz && used <= 8*MiB + pgsz); used = 0; chkok( altstack(8*MiB, wrap, (void *) 100000, 0) == 0, 0, getrlimit_|setrlimit_|mmap_|sigaltstack_|sigaction_|munmap_, setrlimit_|munmap_|sigaltstack_|sigaction_); used = 1; altstack_rsp_save(); dn(0); diag("used: %lu", used); ok1(used == 32 || used == 40); return exit_status(); }