/** * set window */ void dev_window(int x1, int y1, int x2, int y2) { if (x1 == x2 || y1 == y2) { // reset dev_Wx1 = dev_Vx1; dev_Wy1 = dev_Vy1; dev_Wx2 = dev_Vx2; dev_Wy2 = dev_Vy2; dev_Wdx = dev_Vdx; dev_Wdy = dev_Vdy; } else { dev_Wx1 = x1; dev_Wy1 = y1; dev_Wx2 = x2; dev_Wy2 = y2; dev_Wdx = x2 - x1; dev_Wdy = y2 - y1; if (dev_Wdx == 0 || dev_Wdy == 0) { rt_raise(ERR_WIN_ZERO); } } }
void err_evargerr(void) { rt_raise(EVAL_PARAM); }
void cmd_play() { char *p; var_t var; int n = 0; int calc_time_f = 1; char *str, *s; double TmpL; par_getstr(&var); if (prog_error) { return; } if (strncmp("file://", var.v.p.ptr, FILE_PREFIX_LEN) == 0) { const char *path = var.v.p.ptr + FILE_PREFIX_LEN; if (dev_fexists(path)) { dev_audio(path); } else { err_file_not_found(); } v_free(&var); return; } str = (char *) malloc(var.v.p.length + 1); // copy without spaces p = (char *) var.v.p.ptr; s = str; while (*p) { if (*p > 32) { *s++ = to_upper(*p); } p++; } *s = '\0'; v_free(&var); // run p = str; while (*p) { if (dev_events(0) < 0) { break; } if (calc_time_f) { period = (4.0 / L) * (60000 / T) * TM; duration = M * period; calc_time_f = 0; } switch (*p) { // Volume case 'V': n = 0; while (is_digit(*(p + 1))) { p++; n = (n * 10) + (*p - '0'); } CPLERR((n < 0 || n > 100), "PLAY: V0-100"); vol = n; break; // clear queue case 'Q': dev_clear_sound_queue(); break; // Octaves case '<': if (O > 0) O--; break; case '>': if (O < 6) O++; break; case 'O': O = -1; if (is_digit(*(p + 1))) { p++; O = *p - '0'; } CPLERR((O < 0 || O > 6), "PLAY: O0-6"); break; // Time case 'L': n = 0; while (is_digit(*(p + 1))) { p++; n = (n * 10) + (*p - '0'); } CPLERR((n < 1 || n > 64), "PLAY: L1-64"); L = n; calc_time_f = 1; break; case 'T': n = 0; while (is_digit(*(p + 1))) { p++; n = (n * 10) + (*p - '0'); } CPLERR((n < 45 || n > 255), "PLAY: T32-255"); T = n; calc_time_f = 1; break; case 'M': p++; switch (*p) { case 'S': M = 0.5; break; case 'N': M = 3.0 / 4.0; break; case 'L': M = 1.0; break; case 'F': bg = 0; break; case 'B': bg = 1; break; default: rt_raise("PLAY: M%c UNSUPPORTED", *p); v_free(&var); } calc_time_f = 1; break; // Pause case 'P': n = 0; while (is_digit(*(p + 1))) { p++; n = (n * 10) + (*p - '0'); } if (*(p + 1) == '.') { p++; TM = 1.5; } else { TM = 1.0; } CPLERR((n < 1 || n > 64), "PLAY: P1-64"); period = (4.0 / n) * (60000 / T) * TM; dev_sound(0, period, vol, bg); calc_time_f = 1; break; // Play N case 'N': n = 0; while (is_digit(*(p + 1))) { p++; n = (n * 10) + (*p - '0'); } CPLERR((n < 0 || n > 84), "PLAY: N0-84"); if (n) { // oct = n / 12; // pitch = tones[n - oct * 12] * (1 << oct); pitch = tones[n]; } if (n == 0) dev_sound(0, period, vol, bg); else { dev_sound(pitch, duration, vol, bg); if (duration < period) dev_sound(0, period - duration, vol, bg); } calc_time_f = 1; break; // Play note case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': switch (*p) { case 'A': n = 13; break; case 'B': n = 15; break; case 'C': n = 4; break; case 'D': n = 6; break; case 'E': n = 8; break; case 'F': n = 9; break; case 'G': n = 11; break; } if (*(p + 1) == '-' || *(p + 1) == '+' || *(p + 1) == '#') { p++; if (*p == '-') n--; else n++; } if (is_digit(*(p + 1))) { TmpL = 0; while (is_digit(*(p + 1))) { p++; TmpL = (TmpL * 10) + (*p - '0'); } calc_time_f = 1; } else { TmpL = L; } if (*(p + 1) == '.') { p++; TM = 1.5; } else { TM = 1.0; } period = (4.0 / TmpL) * (60000 / T) * TM; duration = M * period; // pitch = tones[n] * (1 << O); pitch = tones[(n - 4) + O * 12]; dev_sound(pitch, duration, vol, bg); if (duration < period) { dev_sound(0, period - duration, vol, bg); } break; default: rt_raise("PLAY: '%c' UNSUPPORTED", *p); free(str); return; } // next if (*p) { p++; } } free(str); }
void err_run_err(const char *file) { rt_raise(ERR_RUN_FILE, file); }
void err_ref_circ_var() { rt_raise(ERR_REF_CIRC_VAR); }
void err_parsepoly(int idx, int mark) { rt_raise(ERR_POLY, idx, mark); }
void err_pcode_err(long pcode) { rt_raise(ERR_CRITICAL_MISSING_PROC, pcode); }
void err_missing_sep(void) { rt_raise(ERR_MISSING_SEP_OR_PAR); }
void err_division_by_zero(void) { rt_raise(ERR_DIVZERO); }
void err_notarray(void) { rt_raise(ERR_NOT_ARR_OR_FUNC); }
void err_out_of_range(void) { rt_raise(ERR_RANGE); }
void err_notavar(void) { rt_raise(ERR_NOT_A_VAR); }
void err_const(void) { rt_raise(ERR_CONST); }
void err_unsup(void) { rt_raise(ERR_UNSUPPORTED); }
// no separator found void err_syntaxsep(const char *seps) { rt_raise(ERR_SEP_FMT, seps); }
void err_matop(void) { rt_raise(ERR_OPERATOR); }
void err_missing_comma(void) { rt_raise(ERR_SEP_FMT, ","); }
void err_matsig(void) { rt_raise(ERR_MATSIG); }
void err_bfn_err(long code) { rt_raise(ERR_CRITICAL_MISSING_FUNC, code); }
void err_missing_lp(void) { rt_raise(ERR_MISSING_LP); }
void err_chain_err(const char *file) { rt_raise(ERR_CHAIN_FILE, file); }
void err_parfmt(const char *fmt) { rt_raise(ERR_PARFMT, fmt); }
void err_ref_var() { rt_raise(ERR_REF_VAR); }
// UDP/F: parameter is 'by reference' so const not allowed void err_parm_byref(int n) { rt_raise(ERR_BYREF, n); }
void err_array() { rt_raise(MSG_ARRAY_SE); }
void err_stridx(int n) { rt_raise(ERR_STR_RANGE, n); }
/** * @ingroup clib * * call a C-function * * @param handle the lib-handle * @param name the function name * @return depented on function */ void *clib_call_func(int handle, const char *name, ...) { // NDC information // // It is valid for C to call a function with parameters // even if it is declared without parameters. // // the ... operator works like all others, but there is // a problem because compiler requires one parameters to be // declared // // The compiler pushes the arguments on the stack with reverse order // and after the call it is removes the allocated size from the stack // // Example: // // f(a,b,c) produces // // push c // push b // push a // call f // add sp, size(a)+size(b)+size(c) // ; that means substract from stack pointer the correct size // // now, the push statement (at least on compilers output that I have // study) uses default CPU's words (1 CPU word = 1 int). // Real numbers or any bigest value uses 2 or more words. Smallest // values (like 1 byte) are also uses 1 word. That is depented on // CPU architecture, and it is correct. Unfortunately I don't know // if there is a different way. // // The problem is the returned value. The default is to returned on // accumulator, but that is not the rule (in any case there are no // rules). For example the linux's gcc returns a 'int' the value on // the stack. Turbo C uses AX (DX:AX for long ints). // // I had to found a cross-compiled code to call a C function, so, // that is the idea. // // a) we will convert the parameters to CPU words (ptable, pcount) // b) we will use the C function-pointer (f) without declaring the parameters // c) we will call that function based on number of the parameters that we // have // d) we got the return value as int. // // Problems: // We can't get a 'double' return value #if USE_CLIB void *(f) (); void *proc_ptr; int ptable[256]; int pcount; if (handle > 0 && handle < clib_count) { if (table[handle].handle) { #if defined(_UnixOS) proc_ptr = dlsym(table[handle].handle, name); #elif defined(_Win32) proc_ptr = GetProcAddress((HMODULE) table[handle].handle, name); #endif if (proc_ptr == NULL) rt_raise("CALL: FUNCTION '%s' DOES NOT EXISTS", name); else { f = proc_ptr; } } } #else rt_raise("SUBSYSTEM NOT SUPPORTED"); return NULL; #endif }
void err_fopen(void) { rt_raise(ERR_BAD_FILE_HANDLE); }
// open a web server connection int http_open(dev_file_t *f) { char host[250]; char txbuf[1024]; f->port = 0; // check for http:// if (0 != strncasecmp(f->name, "http://", 7)) { rt_raise("HTTP: INVALID URL"); return 0; } // check for end of host delimeter char *colon = strchr(f->name + 7, ':'); char *slash = strchr(f->name + 7, '/'); char *lastSlash; // saves the length of the path component in f->drv_dw[1] if (colon) { // http://host:port/resource or http://host:port if (slash) { *slash = 0; f->port = xstrtol(colon + 1); *slash = '/'; lastSlash = strrchr(slash, '/'); f->drv_dw[1] = lastSlash ? lastSlash - f->name : slash - f->name; } else { f->port = xstrtol(colon + 1); f->drv_dw[1] = strlen(f->name); } *colon = 0; strcpy(host, f->name + 7); *colon = ':'; } else if (slash) { // http://host/resource or http://host/ *slash = 0; strcpy(host, f->name + 7); *slash = '/'; lastSlash = strrchr(slash, '/'); f->drv_dw[1] = lastSlash ? lastSlash - f->name : slash - f->name; } else { // http://host strcpy(host, f->name + 7); f->drv_dw[1] = strlen(f->name); } f->drv_dw[0] = 1; if (f->port == 0) { f->port = 80; } socket_t s = net_connect(host, f->port); f->handle = (socket_t) s; if (f->handle <= 0) { f->handle = -1; f->drv_dw[0] = 0; f->port = 0; return 0; } sprintf(txbuf, "GET %s HTTP/1.0\r\n" "Host: %s\r\n" "Accept: */*\r\n" "Accept-Language: en-au\r\n" "User-Agent: SmallBASIC\r\n", slash ? slash : "/", host); if (f->drv_dw[2]) { // If-Modified-Since: Sun, 03 Apr 2005 04:45:47 GMT strcat(txbuf, "If-Modified-Since: "); strftime(txbuf + strlen(txbuf), 60, "%a, %d %b %Y %H:%M:%S %Z\r\n", localtime((time_t *) &f->drv_dw[2])); } strcat(txbuf, "\r\n"); net_print(s, txbuf); return 1; }
void err_evtype(void) { rt_raise(EVAL_TYPE); }