Mercurial > repo
view src/ploki/pp.c @ 6707:2dd82f6f2ed9
<zgrep> ` echo \'if not o.path.isfile(a):print u.check_output(["?",a]),;exit()\' >> bin/tomfoolery
author | HackBot |
---|---|
date | Wed, 10 Feb 2016 02:56:49 +0000 |
parents | ac0403686959 |
children |
line wrap: on
line source
#include "IO.h" #include "Str.h" #include "kork.h" #include "list.h" #include "main_io.h" #include "main_opt.h" #include "match.h" #include "pp.h" #include "re.h" #include "run.h" #include "val.h" #include "xmalloc.h" #include <ctype.h> #include <errno.h> #include <float.h> #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> void pp_abs(struct val *v) { V_NUM(v); v_set_n(v, fabs(v->num)); } void pp_acos(struct val *v) { V_NUM(v); v_set_n(v, acos(v->num)); } void pp_asin(struct val *v) { V_NUM(v); v_set_n(v, asin(v->num)); } void pp_atan(struct val *v) { V_NUM(v); v_set_n(v, atan(v->num)); } void pp_atan2(struct val *v) { if (!V_LIST_P(v) || li_length(v->magic.list) != 2) { v_set_undef(v); #ifdef EINVAL errno = EINVAL; #endif return; } else { struct val *const a = li_at(v->magic.list, 0); struct val *const b = li_at(v->magic.list, 1); V_NUM(a); V_NUM(b); v_set_n(v, atan2(a->num, b->num)); } } void pp_chr(struct val *v) { V_NUM(v); V_xxx_OFF(v); ko_cpy_c(v->ko, (unsigned char)(v->num + .5)); v->type = V_STR_K; } void pp_cos(struct val *v) { V_NUM(v); v_set_n(v, cos(v->num)); } void pp_defined(struct val *v) { if (v->type != V_UNDEF) { v_set_n(v, 1.0); } } void pp_eof(struct val *v) { if (!V_EXT_P(v)) { v_set_undef(v); #ifdef EBADF errno = EBADF; #endif return; } if (io_eof(v->magic.ext)) { v_set_n(v, 1.0); } else { v_set_m(v, "", 0); } } void pp_error(struct val *v) { if (!V_EXT_P(v)) { v_set_undef(v); #ifdef EBADF errno = EBADF; #endif return; } if (io_err(v->magic.ext)) { v_set_n(v, 1.0); } else { v_set_m(v, "", 0); } } void pp_escape(struct val *v) { String tmp; size_t i; V_STR(v); V_xxx_OFF(v); St_init(&tmp); St_cpy(&tmp, ko_str(v->ko)); ko_zero(v->ko); for (i = St_len(&tmp); i; ) { --i; if (!(ST_INDEX(&tmp, i) == '_' || isalnum(ST_INDEX(&tmp, i)))) { ko_cat_c(v->ko, '!'); } ko_cat_c(v->ko, ST_INDEX(&tmp, i)); } St_clear(&tmp); ko_reverse(v->ko); v->type = V_STR_K; } void pp_getc(struct val *v) { int c; if (!V_EXT_P(v)) { V_xxx_OFF(v); v->type = V_UNDEF; #ifdef EBADF errno = EBADF; #endif return; } c = io_getc(v->magic.ext); #if EOF != -1 if (c == EOF) { c = -1; } #endif v_set_n(v, c); } void pp_getenv(struct val *v) { const char *const tmp = getenv(v_sptr(v, NULL)); if (tmp) { v_set_m(v, tmp, strlen(tmp)); } else { V_xxx_OFF(v); v->type = V_UNDEF; } } void pp_gets(struct val *v) { if (!V_EXT_P(v)) { V_xxx_OFF(v); v->type = V_UNDEF; #ifdef EBADF errno = EBADF; #endif return; } if (ko_getline(v->magic.ext, v->ko) + 1u) { V_xxx_OFF(v); v->type = V_STR_K; } else { V_xxx_OFF(v); v->type = V_UNDEF; } } void pp_int(struct val *v) { V_NUM(v); v_set_n(v, floor(v->num + .5)); } void pp_io(struct val *v) { if (V_EXT_P(v)) { v_set_n(v, 1.0); } else { v_set_m(v, "", 0); } } void pp_length(struct val *v) { if (V_LIST_P(v)) { v_set_n(v, li_length(v->magic.list)); return; } v_set_n(v, ko_length(v_kork(v))); } void pp_log(struct val *v) { V_NUM(v); v_set_n(v, log(v->num)); } void pp_log10(struct val *v) { V_NUM(v); v_set_n(v, log10(v->num)); } void pp_lower(struct val *v) { V_STR(v); V_xxx_OFF(v); ko_lower(v->ko); } void pp_moend(struct val *v) { size_t n; V_NUM(v); n = RINT(v->num); if (n < Interp.m_end.size) { v_set_n(v, Interp.m_end.index[n]); } else { v_set_undef(v); } } void pp_mostart(struct val *v) { size_t n; V_NUM(v); n = RINT(v->num); if (n < Interp.m_start.size) { v_set_n(v, Interp.m_start.index[n]); } else { v_set_undef(v); } } void pp_neg(struct val *v) { V_NUM(v); V_xxx_OFF(v); v->num = -v->num; v->type = V_NUM_K; } void pp_not(struct val *v) { if (v_true(v)) { v_set_m(v, "", 0); } else { v_set_n(v, 1.0); } } void pp_num(struct val *v) { V_NUM(v); V_xxx_OFF(v); v->type = V_NUM_K; } void pp_open(struct val *v) { IO *fh; struct val *name, *mode; enum io_flags flags; if (!V_LIST_P(v) || li_length(v->magic.list) != 2) { v_set_undef(v); #ifdef ENOENT errno = ENOENT; #endif return; } name = li_at(v->magic.list, 0); V_STR(name); if (ko_chr(name->ko, '\0') + 1u) { v_set_undef(v); #ifdef ENOENT errno = ENOENT; #endif return; } mode = li_at(v->magic.list, 1); flags = 0; V_STR(mode); if (ko_chr(mode->ko, 'A') + 1u) { flags |= IO_APPEND; if (ko_chr(mode->ko, '+') + 1u) { flags |= IO_READ; } } else if (ko_chr(mode->ko, 'W') + 1u) { flags |= IO_WRITE | IO_TRUNCATE; if (ko_chr(mode->ko, '+') + 1u) { flags |= IO_READ; } } else { flags |= IO_READ; if (ko_chr(mode->ko, '+') + 1u) { flags |= IO_WRITE; } else if (ko_chr(mode->ko, 'Z') + 1u) { flags |= IO_BUFFERED; } } if (ko_chr(mode->ko, 'B') + 1u) { flags |= IO_BINARY; } if ((flags & IO_WRITE || flags & IO_APPEND) && ko_chr(mode->ko, 'F') + 1u) { flags |= IO_AUTOFLUSH; } if (!(fh = io_open(ko_szp(name->ko), flags))) { v_set_undef(v); return; } v_set_io(v, fh); } void pp_openr(struct val *v) { V_STR(v); V_xxx_OFF(v); if (ko_chr(v->ko, '\0') + 1u) { v->type = V_UNDEF; #ifdef ENOENT errno = ENOENT; #endif } else if ((v->magic.ext = io_open(ko_szp(v->ko), IO_READ | IO_BINARY))) { v->type = V_EXT_K; } else { v->type = V_UNDEF; } } void pp_openw(struct val *v) { V_STR(v); V_xxx_OFF(v); if (ko_chr(v->ko, '\0') + 1u) { v->type = V_UNDEF; #ifdef ENOENT errno = ENOENT; #endif } else if ((v->magic.ext = io_open(ko_szp(v->ko), IO_WRITE | IO_TRUNCATE | IO_BINARY | IO_AUTOFLUSH))) { v->type = V_EXT_K; } else { v->type = V_UNDEF; } } void pp_ord(struct val *v) { V_STR(v); V_xxx_OFF(v); if (ko_length(v->ko)) { v->num = ko_at(v->ko, 0); v->type = V_NUM_K; } else { v->type = V_UNDEF; } } void pp_quote(struct val *v) { String tmp; size_t i; V_STR(v); V_xxx_OFF(v); St_init(&tmp); St_cpy_m(&tmp, ko_ptr(v->ko), ko_length(v->ko)); ko_zero(v->ko); for (i = 0; i < St_len(&tmp); ++i) { if (!(ST_INDEX(&tmp, i) == '_' || isalnum(ST_INDEX(&tmp, i)))) { ko_cat_c(v->ko, '\\'); } ko_cat_c(v->ko, ST_INDEX(&tmp, i)); } St_clear(&tmp); v->type = V_STR_K; } void pp_remove(struct val *v) { V_STR(v); V_xxx_OFF(v); if (ko_chr(v->ko, '\0') + 1u) { v->type = V_UNDEF; #ifdef ENOENT errno = ENOENT; #endif return; } if (remove(ko_szp(v->ko))) { v_set_m(v, "", 0); } else { v_set_n(v, 1.0); } } void pp_rename(struct val *v) { struct val *from, *to; if (!V_LIST_P(v) || li_length(v->magic.list) != 2) { v_set_undef(v); #ifdef ENOENT errno = ENOENT; #endif return; } from = li_at(v->magic.list, 0); V_STR(from); if (ko_chr(from->ko, '\0') + 1u) { v_set_undef(v); #ifdef ENOENT errno = ENOENT; #endif return; } to = li_at(v->magic.list, 1); V_STR(to); if (ko_chr(to->ko, '\0') + 1u) { v_set_undef(v); #ifdef EINVAL errno = EINVAL; #endif return; } if (rename(ko_szp(from->ko), ko_szp(to->ko))) { v_set_m(v, "", 0); } else { v_set_n(v, 1.0); } } void pp_reverse(struct val *v) { if (V_LIST_P(v)) { li_reverse(v->magic.list); v->type = V_LIST_K; return; } V_STR(v); V_xxx_OFF(v); ko_reverse(v->ko); v->type = V_STR_K; } void pp_seek(struct val *v) { struct val *fh, *tmp; long off; enum io_whence whence = IOS_START; if (!V_LIST_P(v) || li_length(v->magic.list) < 2 || li_length(v->magic.list) > 3) { v_set_undef(v); #ifdef EINVAL errno = EINVAL; #endif return; } fh = li_at(v->magic.list, 0); if (!V_EXT_P(fh)) { v_set_undef(v); #ifdef EBADF errno = EBADF; #endif return; } tmp = li_at(v->magic.list, 1); V_NUM(tmp); off = RINT(tmp->num); if ((tmp = li_at(v->magic.list, 2))) { V_NUM(tmp); switch ((long)RINT(tmp->num)) { case 0: whence = IOS_START; break; case 1: whence = IOS_CUR; break; case 2: whence = IOS_END; break; default: v_set_undef(v); #ifdef EINVAL errno = EINVAL; #endif return; } } v_set_n(v, io_seek(fh->magic.ext, off, whence)); } void pp_sin(struct val *v) { V_NUM(v); v_set_n(v, sin(v->num)); } void pp_sqrt(struct val *v) { V_NUM(v); V_xxx_OFF(v); v->num = sqrt(v->num); v->type = V_NUM_K; } void pp_str(struct val *v) { V_STR(v); V_xxx_OFF(v); v->type |= V_STR_K; } void pp_tan(struct val *v) { V_NUM(v); v_set_n(v, tan(v->num)); } void pp_tell(struct val *v) { if (!V_EXT_P(v)) { v_set_undef(v); #ifdef EBADF errno = EBADF; #endif return; } v_set_n(v, io_tell(v->magic.ext)); } void pp_typeof(struct val *v) { if (V_SUB_P(v)) { v_set_m(v, "stuff", 5); } else if (V_EXT_P(v)) { v_set_m(v, "stream", 6); } else if (V_LIST_P(v)) { v_set_m(v, "list", 4); } else if (V_NUM_P(v)) { v_set_m(v, "number", 6); } else if (V_STR_P(v)) { v_set_m(v, "string", 6); } else { v_set_m(v, "nothing", 7); } } void pp_upper(struct val *v) { V_STR(v); V_xxx_OFF(v); ko_upper(v->ko); } #define NUMB(expr) \ do { \ V_NUM(b); \ V_NUM(v); \ v_set_n(v, expr); \ } while (0) #define ARITH(op) NUMB(v->num op b->num) void pp_add(struct val *v, struct val *b) { ARITH(+); } #define LOGIC(init, cond) \ do { \ init; \ if (cond) { \ v_set_n(v, 1.0); \ } else { \ v_set_m(v, "", 0); \ } \ } while (0) void pp_and(struct val *v, struct val *b) { LOGIC((void)0, v_true(v) && v_true(b)); } void pp_comma(struct val *v, struct val *b) { v_set(v, b); } void pp_concat(struct val *v, struct val *b) { v_cat(v, b); } void pp_div(struct val *v, struct val *b) { ARITH(/); } #define CMP_LS(op) LOGIC((void)0, v_cmp_ls(v, b) op 0) void pp_eq(struct val *v, struct val *b) { CMP_LS(==); } #define CMP_N(op) LOGIC(V_NUM(v); V_NUM(b), v->num op b->num) void pp_eq_n(struct val *v, struct val *b) { if (V_EXT_P(v)) { if (V_EXT_P(b)) { LOGIC((void)0, v->magic.ext == b->magic.ext); } else if (V_SUB_P(b)) { goto false_cmp; } else { goto default_cmp; } } else if (V_SUB_P(v)) { if (V_SUB_P(b)) { LOGIC((void)0, v->magic.sub == b->magic.sub); } else if (V_EXT_P(b)) false_cmp: { LOGIC((void)0, 0); } else { goto default_cmp; } } else default_cmp: { CMP_N(==); } } static const char xdigits[] = "0123456789" "abcdefghijklmnopqrstuvwxyz"; void pp_frombase(struct val *v, struct val *b) { double p; size_t i; int base, sign; const char *tmp; V_NUM(b); V_STR(v); V_xxx_OFF(v); if (floor(b->num + .5) < 2. || floor(b->num + .5) > 36.) { v->type = V_UNDEF; return; } base = floor(b->num + .5); ko_shiftws(v->ko); sign = 0; if (ko_at(v->ko, 0) == '-') { sign = 1; ko_shift(v->ko, 1); } else if (ko_at(v->ko, 0) == '+') { ko_shift(v->ko, 1); } p = 0.0; for (i = 0; i < ko_length(v->ko); ++i) { if ((tmp = strchr(xdigits, tolower(ko_at(v->ko, i)))) && tmp - xdigits < base) { p *= base; p += tmp - xdigits; } else { break; } } if (i < ko_length(v->ko)) { if (ko_at(v->ko, i) == '.') { double shift = 1.0; for (++i; i < ko_length(v->ko); ++i) { if ((tmp = strchr(xdigits, tolower(ko_at(v->ko, i)))) && tmp - xdigits < base) { shift *= base; p *= base; p += tmp - xdigits; } else { break; } } p /= shift; } } if (sign) { p = -p; } v_set_n(v, p); } void pp_gt(struct val *v, struct val *b) { CMP_LS(>); } void pp_gt_n(struct val *v, struct val *b) { CMP_N(>); } void pp_lt(struct val *v, struct val *b) { CMP_LS(<); } void pp_lt_n(struct val *v, struct val *b) { CMP_N(<); } void pp_match(struct val *v, struct val *b) { t_regex *re; V_STR(b); re = re_compile(ko_str(b->ko)); do_match(v, re); re_free(re); } void pp_mod(struct val *v, struct val *b) { NUMB(fmod(v->num, b->num)); } void pp_mult(struct val *v, struct val *b) { ARITH(*); } void pp_ne(struct val *v, struct val *b) { CMP_LS(!=); } void pp_ne_n(struct val *v, struct val *b) { if (V_EXT_P(v)) { if (V_EXT_P(b)) { LOGIC((void)0, v->magic.ext != b->magic.ext); } else if (V_SUB_P(b)) { goto true_cmp; } else { goto default_cmp; } } else if (V_SUB_P(v)) { if (V_SUB_P(b)) { LOGIC((void)0, v->magic.sub != b->magic.sub); } else if (V_EXT_P(b)) true_cmp: { LOGIC((void)0, 1); } else { goto default_cmp; } } else default_cmp: { CMP_N(!=); } } void pp_or(struct val *v, struct val *b) { LOGIC((void)0, v_true(v) || v_true(b)); } void pp_pop(struct val *v, struct val *b) { long p; V_NUM(b); p = RINT(b->num); if (V_LIST_P(v)) { v->type = V_LIST_K; if (p < 0) { p += li_length(v->magic.list); } if (p < 0) { p = 0; } if ((size_t)p >= li_length(v->magic.list)) { return; } li_trunc(v->magic.list, p); return; } V_STR(v); V_xxx_OFF(v); v->type = V_STR_K; if (p < 0) { p += ko_length(v->ko); } if (p < 0) { p = 0; } if ((size_t)p >= ko_length(v->ko)) { return; } ko_trunc(v->ko, p); } void pp_pow(struct val *v, struct val *b) { NUMB(pow(v->num, b->num)); } void pp_read(struct val *v, struct val *b) { long n; if (V_SUB_P(v)) { const size_t curdepth = depth_get(); stack_store(&Interp.arg, b); eval_into(sub_expr(v->magic.sub), v); depth_restore(curdepth); return; } if (V_EXT_P(v)) { V_NUM(b); ko_read(v->magic.ext, v->ko, b->num < 0.0 ? (size_t)-1 : b->num + .5); V_xxx_OFF(v); v->type = V_STR_K; return; } if (V_LIST_P(v)) { struct val *ptr; V_NUM(b); n = RINT(b->num); if (n < 0) { n += li_length(v->magic.list); } if (n >= 0 && (ptr = li_at(v->magic.list, n))) { struct list *tmp = li_dup(v->magic.list); v_set(v, ptr); li_delete(tmp); } else { v_set_undef(v); } return; } V_STR(v); V_xxx_OFF(v); V_NUM(b); n = RINT(b->num); if (n < 0) { n += ko_length(v->ko); } if (n >= 0 && (size_t)n < ko_length(v->ko)) { ko_shift(v->ko, n); ko_trunc(v->ko, 1); v->type = V_STR_K; } else { v->type = V_UNDEF; } } void pp_shift(struct val *v, struct val *b) { long p; V_NUM(b); p = RINT(b->num); if (V_LIST_P(v)) { v->type = V_LIST_K; if (p < 0) { p += li_length(v->magic.list); } if (p <= 0) { return; } if ((size_t)p >= li_length(v->magic.list)) { li_zero(v->magic.list); } else { li_shift(v->magic.list, p); } return; } V_STR(v); V_xxx_OFF(v); v->type = V_STR_K; if (p < 0) { p += ko_length(v->ko); } if (p <= 0) { return; } if ((size_t)p >= ko_length(v->ko)) { ko_zero(v->ko); } else { ko_shift(v->ko, p); } } void pp_sub(struct val *v, struct val *b) { ARITH(-); } void pp_tobase(struct val *v, struct val *b) { double p; int base, sign; size_t i; V_NUM(b); V_NUM(v); V_xxx_OFF(v); if (floor(b->num + .5) < 2. || floor(b->num + .5) > 36.) { v->type = V_UNDEF; return; } base = floor(b->num + .5); sign = 0; if (v->num < 0.) { v->num = -v->num; sign = 1; } p = v->num; ko_zero(v->ko); if (floor(p) < p) { double foo, bar; size_t rounds; foo = 1 + floor(log(pow(10, DBL_DIG)) / log(base)); bar = p > 0. ? 1 + floor(log(p) / log(base)) : 0.; if (bar >= foo) { rounds = 0; } else { rounds = foo - bar; } for (i = 0; i < rounds; ++i) { p *= base; if (floor(p) >= p) { ++i; break; } } p = floor(p); while (i--) { int c; c = fmod(p, base); p = floor(p / base); if (c >= 0) { ko_cat_c(v->ko, xdigits[c]); } } } while (ko_at(v->ko, 0) == '0') { ko_shift(v->ko, 1); } if (ko_length(v->ko)) { ko_cat_c(v->ko, '.'); } while (p > 0.) { int c; c = fmod(p, base); p = floor(p / base); if (c >= 0) { ko_cat_c(v->ko, xdigits[c]); } } if (!ko_length(v->ko) || ko_lastchar(v->ko) == '.') { ko_cat_c(v->ko, '0'); } if (sign) { ko_cat_c(v->ko, '-'); } v->type = V_STR_K; }