/* * NAME: extrafuns.c * DESCRIPTION: special LPMOO builtins */ # ifdef FUNCDEF FUNCDEF(0, "toliteral", 1, 2) # else /* * NAME: bfun->toliteral() * DESCRIPTION: convert argument into a literal string */ varargs MOOVAL b_toliteral(mixed *info, MOOVAL arg1, MOOVAL etc...) { return STR(moo2str(arg1, sizeof(etc) ? TRUTHOF(etc[0]) : 1)); } # endif # ifdef FUNCDEF FUNCDEF(0, "fromliteral", 1, 1) # else /* * NAME: bfun->fromliteral() * DESCRIPTION: convert a literal string to a MOO value */ varargs MOOVAL b_fromliteral(mixed *info, MOOVAL arg) { MOOVAL result; ASSERT(arg, STR); return str2moo(STRVAL(arg)); } # endif # ifdef FUNCDEF FUNCDEF(0, "tofloat", 1, 1) # else /* * NAME: bfun->tofloat() * DESCRIPTION: convert argument to a float */ varargs MOOVAL b_tofloat(mixed *info, MOOVAL arg) { switch (TYPEOF(arg)) { case T_NUM: return FLT((float) NUMVAL(arg)); case T_STR: { string str; float flt; int i, sz; /* this is unnecessarily complex, but mocks the behavior of tonum() and toobj() */ sz = strlen(str = STRVAL(arg)); while (i < sz && (str[i] == ' ' || str[i] == '\t')) ++i; sscanf(str[i ..], "%f%s", flt, str); i = 0, sz = strlen(str); while (i < sz && (str[i] == ' ' || str[i] == '\t')) ++i; if (i < sz) return FLT(0.0); else return FLT(flt); } case T_FLT: return arg; case T_OBJ: return FLT((float) OBJVAL(arg)); case T_ERR: return FLT((float) ERRVAL(arg)); default: return RAISE(E_TYPE); } } # endif /* floating point support */ # ifdef FUNCDEF FUNCDEF(0, "floor", 1, 1) # else /* * NAME: bfun->floor() * DESCRIPTION: round to minus infinity */ varargs MOOVAL b_floor(mixed *info, MOOVAL arg) { float x; if (NUMP(arg)) x = (float) NUMVAL(arg); else { ASSERT(arg, FLT); x = FLTVAL(arg); } return FLT(floor(x)); } # endif # ifdef FUNCDEF FUNCDEF(0, "ceil", 1, 1) # else /* * NAME: bfun->ceil() * DESCRIPTION: round to plus infinity */ varargs MOOVAL b_ceil(mixed *info, MOOVAL arg) { float x; if (NUMP(arg)) x = (float) NUMVAL(arg); else { ASSERT(arg, FLT); x = FLTVAL(arg); } return FLT(ceil(x)); } # endif # ifdef FUNCDEF FUNCDEF(0, "frexp", 1, 1) # else /* * NAME: bfun->frexp() * DESCRIPTION: split floating point value */ varargs MOOVAL b_frexp(mixed *info, MOOVAL arg) { float x; if (NUMP(arg)) x = (float) NUMVAL(arg); else { ASSERT(arg, FLT); x = FLTVAL(arg); } /* same representation */ return LST(frexp(x)); } # endif # ifdef FUNCDEF FUNCDEF(0, "ldexp", 2, 2) # else /* * NAME: bfun->ldexp() * DESCRIPTION: rejoin floating point value */ varargs MOOVAL b_ldexp(mixed *info, MOOVAL arg1, MOOVAL arg2) { float flt, x; if (NUMP(arg1)) x = (float) NUMVAL(arg1); else { ASSERT(arg1, FLT); x = FLTVAL(arg1); } ASSERT(arg2, NUM); return catch(flt = ldexp(x, NUMVAL(arg2))) ? RAISE(E_OVERFL) : FLT(flt); } # endif # ifdef FUNCDEF FUNCDEF(0, "modf", 1, 1) # else /* * NAME: bfun->modf() * DESCRIPTION: split floating point value */ varargs MOOVAL b_modf(mixed *info, MOOVAL arg) { float x; if (NUMP(arg)) x = (float) NUMVAL(arg); else { ASSERT(arg, FLT); x = FLTVAL(arg); } /* same representation */ return LST(modf(x)); } # endif # ifdef FUNCDEF FUNCDEF(0, "exp", 1, 1) # else /* * NAME: bfun->exp() * DESCRIPTION: compute exponentiation */ varargs MOOVAL b_exp(mixed *info, MOOVAL arg) { float flt, x; if (NUMP(arg)) x = (float) NUMVAL(arg); else { ASSERT(arg, FLT); x = FLTVAL(arg); } switch (catch(flt = exp(x))) { case 0: return FLT(flt); case "Result too large": return RAISE(E_OVERFL); default: return RAISE(E_INVARG); } } # endif # ifdef FUNCDEF FUNCDEF(0, "log", 1, 1) # else /* * NAME: bfun->log() * DESCRIPTION: compute natural logarithm */ varargs MOOVAL b_log(mixed *info, MOOVAL arg) { float flt, x; if (NUMP(arg)) x = (float) NUMVAL(arg); else { ASSERT(arg, FLT); x = FLTVAL(arg); } switch (catch(flt = log(x))) { case 0: return FLT(flt); case "Result too large": return RAISE(E_OVERFL); default: return RAISE(E_INVARG); } } # endif # ifdef FUNCDEF FUNCDEF(0, "log10", 1, 1) # else /* * NAME: bfun->log10() * DESCRIPTION: computer logarithm base 10 */ varargs MOOVAL b_log10(mixed *info, MOOVAL arg) { float flt, x; if (NUMP(arg)) x = (float) NUMVAL(arg); else { ASSERT(arg, FLT); x = FLTVAL(arg); } switch (catch(flt = log10(x))) { case 0: return FLT(flt); case "Result too large": return RAISE(E_OVERFL); default: return RAISE(E_INVARG); } } # endif # ifdef FUNCDEF FUNCDEF(0, "pow", 2, 2) # else /* * NAME: bfun->pow() * DESCRIPTION: compute exponential power */ varargs MOOVAL b_pow(mixed *info, MOOVAL arg1, MOOVAL arg2) { float x, y, flt; if (NUMP(arg1)) x = (float) NUMVAL(arg1); else { ASSERT(arg1, FLT); x = FLTVAL(arg1); } if (NUMP(arg2)) y = (float) NUMVAL(arg2); else { ASSERT(arg2, FLT); y = FLTVAL(arg2); } if (y == 0.0) return FLT(1.0); if (x == 0.0) return FLT(0.0); switch (catch(flt = exp(log(x) * y))) { case 0: return FLT(flt); case "Result too large": return RAISE(E_OVERFL); default: return RAISE(E_INVARG); } } # endif # ifdef FUNCDEF FUNCDEF(0, "sin", 1, 1) # else /* * NAME: bfun->sin() * DESCRIPTION: compute sine */ varargs MOOVAL b_sin(mixed *info, MOOVAL arg) { float x; if (NUMP(arg)) x = (float) NUMVAL(arg); else { ASSERT(arg, FLT); x = FLTVAL(arg); } return FLT(sin(x)); } # endif # ifdef FUNCDEF FUNCDEF(0, "cos", 1, 1) # else /* * NAME: bfun->cos() * DESCRIPTION: compute cosine */ varargs MOOVAL b_cos(mixed *info, MOOVAL arg) { float x; if (NUMP(arg)) x = (float) NUMVAL(arg); else { ASSERT(arg, FLT); x = FLTVAL(arg); } return FLT(cos(x)); } # endif # ifdef FUNCDEF FUNCDEF(0, "tan", 1, 1) # else /* * NAME: bfun->tan() * DESCRIPTION: compute tangent */ varargs MOOVAL b_tan(mixed *info, MOOVAL arg) { float x; if (NUMP(arg)) x = (float) NUMVAL(arg); else { ASSERT(arg, FLT); x = FLTVAL(arg); } return FLT(tan(x)); } # endif # ifdef FUNCDEF FUNCDEF(0, "atan", 1, 1) # else /* * NAME: bfun->atan() * DESCRIPTION: compute arctangent */ varargs MOOVAL b_atan(mixed *info, MOOVAL arg) { float x; if (NUMP(arg)) x = (float) NUMVAL(arg); else { ASSERT(arg, FLT); x = FLTVAL(arg); } return FLT(atan(x)); } # endif /* table support */ # ifdef FUNCDEF FUNCDEF(0, "tablemap", 2, 2) # else /* * NAME: bfun->tablemap() * DESCRIPTION: create a table */ varargs MOOVAL b_tablemap(mixed *info, MOOVAL arg1, MOOVAL arg2) { mapping map; MOOVAL *list1, *list2; int i; ASSERT(arg1, LST); ASSERT(arg2, LST); list1 = LSTVAL(arg1); list2 = LSTVAL(arg2); if ((i = sizeof(list1)) != sizeof(list2)) return RAISE(E_INVARG); map = TNEW(); while (i--) TINSERT(map, list1[i], list2[i]); return TBL(map); } # endif # ifdef FUNCDEF FUNCDEF(0, "tableinsert", 3, 3) # else /* * NAME: bfun->tableinsert() * DESCRIPTION: insert a new item into a table */ varargs MOOVAL b_tableinsert(mixed *info, MOOVAL arg1, MOOVAL arg2, MOOVAL arg3) { mapping table; ASSERT(arg1, TBL); TINSERT(table = TBLVAL(arg1) + TNEW(), arg2, arg3); return TBL(table); } # endif # ifdef FUNCDEF FUNCDEF(0, "tabledelete", 2, 2) # else /* * NAME: bfun->tabledelete() * DESCRIPTION: delete an item from a table */ varargs MOOVAL b_tabledelete(mixed *info, MOOVAL arg1, MOOVAL arg2) { mapping table; ASSERT(arg1, TBL); TDELETE(table = TBLVAL(arg1) + TNEW(), arg2); return TBL(table); } # endif # ifdef FUNCDEF FUNCDEF(0, "tablekeys", 1, 1) # else /* * NAME: bfun->tablekeys() * DESCRIPTION: return the keys of a table */ varargs MOOVAL b_tablekeys(mixed *info, MOOVAL arg) { ASSERT(arg, TBL); return TKEYS(TBLVAL(arg)); } # endif # ifdef FUNCDEF FUNCDEF(0, "tablevalues", 1, 1) # else /* * NAME: bfun->tablevalues() * DESCRIPTION: return the values of a table */ varargs MOOVAL b_tablevalues(mixed *info, MOOVAL arg) { ASSERT(arg, TBL); return TVALUES(TBLVAL(arg)); } # endif /* buffer support */ # ifdef FUNCDEF FUNCDEF(0, "tobuf", 0, -1) # else /* * NAME: bfun->tobuf() * DESCRIPTION: convert to a buffer value */ varargs MOOVAL b_tobuf(mixed *info, MOOVAL args...) { MOOVAL arg; string buf, c; int i, sz; buf = ""; c = "x"; for (i = 0, sz = sizeof(args); i < sz; ++i) { switch (TYPEOF(arg = args[i])) { case T_NUM: c[0] = NUMVAL(arg); buf += c; break; case T_STR: buf += STRVAL(arg); break; case T_BUF: buf += BUFVAL(arg); break; default: return RAISE(E_TYPE); } } return BUF(buf); } # endif /* multiple-port listening support */ # ifdef FUNCDEF FUNCDEF(0, "listen", 1, 3) # else /* * NAME: bfun->listen() * DESCRIPTION: open a network port */ varargs MOOVAL b_listen(mixed *info, MOOVAL arg, MOOVAL etc...) { MOOVAL obj; object ob; int result; string protocol; if (sizeof(etc)) obj = etc[0]; else obj = OBJ(0); if (OBJP(arg)) /* backwards compatibility */ { MOOVAL tmp; tmp = arg; arg = obj; obj = tmp; } ASSERT(arg, NUM); ASSERT(obj, OBJ); if (sizeof(etc) > 1) { ASSERT(etc[1], STR); switch (tolower(STRVAL(etc[1]))) { case "telnet": protocol = "telnet"; break; case "binary": protocol = "tcp"; break; default: return RAISE(E_INVARG); } } else protocol = "tcp"; if (! WIZARDP(info) || ! DRIVER->query_net() || ! CONFIG->query(CF_MPORT_LISTENING)) return RAISE(E_PERM); GET_VALID_OBJ(ob, OBJVAL(obj)); result = DRIVER->listen(ob, NUMVAL(arg), protocol); return (result == E_NONE) ? NUM(0) : RAISE(result); } # endif # ifdef FUNCDEF FUNCDEF(0, "unlisten", 1, 1) # else /* * NAME: bfun->unlisten() * DESCRIPTION: stop listening on a network port */ varargs MOOVAL b_unlisten(mixed *info, MOOVAL arg) { int result; ASSERT(arg, NUM); if (! WIZARDP(info) || ! DRIVER->query_net() || ! CONFIG->query(CF_MPORT_LISTENING)) return RAISE(E_PERM); result = DRIVER->unlisten(NUMVAL(arg)); return (result == E_NONE) ? NUM(0) : RAISE(result); } # endif /* miscellaneous proprietary functions below */