urbit/g/v.c

532 lines
9.4 KiB
C
Raw Normal View History

2014-09-23 21:11:59 +04:00
/* g/v.c
**
** This file is in the public domain.
*/
#include <stdio.h>
#include "all.h"
2014-11-02 01:13:18 +03:00
int WISH;
2014-09-23 21:11:59 +04:00
/* _cv_nock_wish(): call wish through hardcoded interface.
*/
static u3_noun
_cv_nock_wish(u3_noun txt)
{
2014-11-02 01:13:18 +03:00
u3_noun fun, pro;
2014-09-23 21:11:59 +04:00
2014-11-02 01:13:18 +03:00
WISH = 1;
2014-11-06 03:20:01 +03:00
fun = u3n_nock_on(u3k(u3A->roc), u3k(u3x_at(20, u3A->roc)));
pro = u3n_slam_on(fun, txt);
2014-11-02 01:13:18 +03:00
WISH = 0;
return pro;
2014-09-23 21:11:59 +04:00
}
2014-11-06 03:20:01 +03:00
/* u3v_make(): make a new pier and instantiate pill.
2014-09-23 21:11:59 +04:00
*/
void
2014-11-06 03:20:01 +03:00
u3v_make(c3_c* pas_c)
2014-09-23 21:11:59 +04:00
{
2014-11-06 03:20:01 +03:00
u3_noun sys = u3_cke_cue(u3m_file(pas_c));
2014-09-23 21:11:59 +04:00
2014-11-06 03:20:01 +03:00
printf("cv_make: loaded pill %s, as %x\n", pas_c, u3r_mug(sys));
2014-09-23 21:11:59 +04:00
u3A->ken = u3k(u3h(sys));
2014-09-24 11:38:37 +04:00
u3A->roc = u3k(u3t(sys));
2014-09-23 21:11:59 +04:00
2014-09-24 11:38:37 +04:00
printf("cv_make: kernel %x, core %x\n",
2014-11-06 03:20:01 +03:00
u3r_mug(u3A->ken), u3r_mug(u3A->roc));
2014-10-10 05:27:02 +04:00
u3z(sys);
2014-09-24 11:38:37 +04:00
}
2014-09-23 21:11:59 +04:00
2014-11-02 01:13:18 +03:00
int JACK;
2014-11-06 03:20:01 +03:00
/* u3v_jack(): execute kernel formula to bind jets.
2014-09-24 11:38:37 +04:00
*/
void
2014-11-06 03:20:01 +03:00
u3v_jack(void)
2014-09-24 11:38:37 +04:00
{
u3_noun cor;
2014-11-02 01:13:18 +03:00
JACK = 1;
2014-11-06 03:20:01 +03:00
printf("cv_jack: activating kernel %x\n", u3r_mug(u3A->ken));
cor = u3n_nock_on(0, u3k(u3A->ken));
2014-09-24 11:38:37 +04:00
printf("cv_jack: activated\n");
2014-11-02 01:13:18 +03:00
JACK = 0;
2014-09-23 21:11:59 +04:00
2014-09-24 11:38:37 +04:00
u3z(cor);
}
2014-09-23 21:11:59 +04:00
2014-11-06 03:20:01 +03:00
/* u3v_hose(): clear initial ovum queue.
2014-11-01 01:36:01 +03:00
*/
void
2014-11-06 03:20:01 +03:00
u3v_hose(void)
2014-11-01 01:36:01 +03:00
{
2014-11-06 03:20:01 +03:00
u3p(u3v_cart) egg_p = u3A->ova.egg_p;
2014-11-01 01:36:01 +03:00
2014-11-04 21:39:56 +03:00
while ( egg_p ) {
2014-11-06 03:20:01 +03:00
u3v_cart* egg_u = u3to(u3v_cart, egg_p);
u3p(u3v_cart) nex_p = egg_u->nex_p;
2014-11-01 01:36:01 +03:00
2014-11-06 03:20:01 +03:00
u3a_lose(egg_u->vir);
u3a_free(egg_u);
2014-11-01 01:36:01 +03:00
2014-11-04 21:39:56 +03:00
egg_p = nex_p;
2014-11-01 01:36:01 +03:00
}
2014-11-04 21:39:56 +03:00
u3A->ova.egg_p = u3A->ova.geg_p = 0;
2014-11-01 01:36:01 +03:00
u3z(u3A->roe);
u3A->roe = u3_nul;
}
2014-11-06 03:20:01 +03:00
/* u3v_start(): start time.
2014-09-24 11:38:37 +04:00
*/
void
2014-11-06 03:20:01 +03:00
u3v_start(u3_noun now)
2014-09-24 11:38:37 +04:00
{
2014-11-06 03:20:01 +03:00
u3v_time(now);
u3v_numb();
2014-09-23 21:11:59 +04:00
{
2014-11-06 03:20:01 +03:00
c3_c* wen_c = u3r_string(u3A->wen);
2014-09-23 21:11:59 +04:00
2014-09-24 11:38:37 +04:00
printf("cv_start: time: %s\n", wen_c);
2014-09-23 21:11:59 +04:00
free(wen_c);
}
}
2014-11-06 03:20:01 +03:00
/* u3v_wish(): text expression with cache.
2014-09-23 21:11:59 +04:00
*/
u3_noun
2014-11-06 03:20:01 +03:00
u3v_wish(const c3_c* str_c)
2014-09-23 21:11:59 +04:00
{
2014-10-28 20:36:22 +03:00
u3_noun exp;
2014-09-23 21:11:59 +04:00
2014-10-28 20:36:22 +03:00
if ( u3R == &u3H->rod_u ) {
2014-11-06 03:20:01 +03:00
u3_noun txt = u3i_string(str_c);
2014-10-03 21:44:08 +04:00
2014-10-22 00:53:27 +04:00
exp = u3_ckdb_get(u3k(u3A->yot), u3k(txt));
2014-10-03 21:44:08 +04:00
2014-11-06 02:36:30 +03:00
if ( u3_none == exp ) {
2014-10-22 00:53:27 +04:00
exp = _cv_nock_wish(u3k(txt));
u3A->yot = u3_ckdb_put(u3A->yot, u3k(txt), u3k(exp));
2014-10-03 21:44:08 +04:00
}
u3z(txt);
2014-10-28 20:36:22 +03:00
return exp;
}
else {
2014-11-06 03:20:01 +03:00
// It's probably not a good idea to use u3v_wish()
2014-10-28 20:36:22 +03:00
// outside the top level...
//
2014-11-06 03:20:01 +03:00
return _cv_nock_wish(u3i_string(str_c));
2014-09-23 21:11:59 +04:00
}
}
/* _cv_mung(): formula wrapper with gate and sample.
*/
static u3_noun
_cv_mung_in(u3_noun gam)
{
2014-11-06 03:20:01 +03:00
u3_noun pro = u3n_slam_on(u3k(u3h(gam)), u3k(u3t(gam)));
2014-09-23 21:11:59 +04:00
u3z(gam); return pro;
}
static u3_noun
_cv_mung(c3_w sec_w, u3_noun gat, u3_noun sam)
{
u3_noun gam = u3nc(gat, sam);
2014-11-06 03:20:01 +03:00
return u3m_soft(0, _cv_mung_in, gam);
2014-09-23 21:11:59 +04:00
}
2014-11-06 03:20:01 +03:00
/* u3v_pike(): poke with floating core.
2014-09-23 21:11:59 +04:00
*/
u3_noun
2014-11-06 03:20:01 +03:00
u3v_pike(u3_noun ovo, u3_noun cor)
2014-09-23 21:11:59 +04:00
{
2014-11-06 03:20:01 +03:00
u3_noun fun = u3n_nock_on(cor, u3k(u3x_at(42, cor)));
2014-09-23 21:11:59 +04:00
u3_noun sam = u3nc(u3k(u3A->now), ovo);
return _cv_mung(0, fun, sam);
}
2014-11-06 03:20:01 +03:00
/* u3v_nick(): transform enveloped packets, [vir cor].
2014-09-23 21:11:59 +04:00
*/
u3_noun
2014-11-06 03:20:01 +03:00
u3v_nick(u3_noun vir, u3_noun cor)
2014-09-23 21:11:59 +04:00
{
if ( u3_nul == vir ) {
return u3nt(u3_blip, vir, cor);
}
else {
u3_noun i_vir = u3h(vir);
u3_noun pi_vir, qi_vir;
u3_noun vix;
2014-11-06 03:20:01 +03:00
if ( (c3y == u3r_cell((i_vir=u3h(vir)), &pi_vir, &qi_vir)) &&
2014-11-05 04:18:47 +03:00
(c3y == u3du(qi_vir)) &&
2014-09-23 21:11:59 +04:00
(c3__hear == u3h(qi_vir)) )
{
u3_noun gon;
2014-11-06 03:20:01 +03:00
gon = u3v_pike(u3k(i_vir), cor);
2014-09-23 21:11:59 +04:00
if ( u3_blip != u3h(gon) ) {
u3z(vir);
return gon;
}
else {
u3_noun viz;
vix = u3k(u3h(u3t(gon)));
cor = u3k(u3t(u3t(gon)));
u3z(gon);
viz = u3_ckb_weld(vix, u3k(u3t(vir)));
u3z(vir);
2014-11-06 03:20:01 +03:00
return u3v_nick(viz, cor);
2014-09-23 21:11:59 +04:00
}
}
else {
2014-11-06 03:20:01 +03:00
u3_noun nez = u3v_nick(u3k(u3t(vir)), cor);
2014-09-23 21:11:59 +04:00
if ( u3_blip != u3h(nez) ) {
u3z(vir);
return nez;
} else {
u3_noun viz;
viz = u3nc(u3k(i_vir), u3k(u3h(u3t(nez))));
cor = u3k(u3t(u3t(nez)));
u3z(vir);
u3z(nez);
return u3nt(u3_blip, viz, cor);
}
}
}
}
/* _cv_nock_poke(): call poke through hardcoded interface.
*/
static u3_noun
_cv_nock_poke(u3_noun ovo)
{
2014-11-06 03:20:01 +03:00
u3_noun fun = u3n_nock_on(u3k(u3A->roc), u3k(u3x_at(42, u3A->roc)));
2014-09-23 21:11:59 +04:00
u3_noun sam, pro;
sam = u3nc(u3k(u3A->now), ovo);
2014-09-25 22:32:07 +04:00
#if 0
2014-09-23 21:11:59 +04:00
{
2014-11-06 03:20:01 +03:00
c3_c* ovi_c = u3r_string(u3h(u3t(ovo)));
2014-10-03 21:44:08 +04:00
u3_noun tox = u3_do("spat", u3k(u3h(ovo)));
2014-11-06 03:20:01 +03:00
c3_c* tox_c = u3r_string(tox);
2014-09-23 21:11:59 +04:00
2014-11-06 03:20:01 +03:00
printf("poke: %%%s (%x) on %s\r\n", ovi_c, u3r_mug(ovo), tox_c);
2014-09-23 21:11:59 +04:00
free(tox_c); free(ovi_c); u3z(tox);
}
#endif
2014-10-28 20:36:22 +03:00
// u3_leak_on(1);
2014-11-06 03:20:01 +03:00
pro = u3n_slam_on(fun, sam);
2014-10-28 20:36:22 +03:00
// u3_leak_off;
2014-09-23 22:58:57 +04:00
2014-09-25 22:32:07 +04:00
#if 0
2014-09-23 21:11:59 +04:00
{
2014-11-06 03:20:01 +03:00
c3_c* ovi_c = u3r_string(u3h(u3t(ovo)));
2014-09-23 21:11:59 +04:00
printf("poked: %s\r\n", ovi_c);
free(ovi_c);
}
#endif
return pro;
}
/* _cv_nock_peek(): call peek through hardcoded interface.
*/
static u3_noun
_cv_nock_peek(u3_noun hap)
{
2014-11-06 03:20:01 +03:00
u3_noun fun = u3n_nock_on(u3k(u3A->roc), u3k(u3x_at(87, u3A->roc)));
2014-09-23 21:11:59 +04:00
u3_noun sam = u3nc(u3k(u3A->now), hap);
2014-11-06 03:20:01 +03:00
return u3n_slam_on(fun, sam);
2014-09-23 21:11:59 +04:00
}
/* _cv_nock_keep(): call wait through hardcoded interface.
*/
static u3_noun
_cv_nock_keep(u3_noun hap)
{
2014-11-06 03:20:01 +03:00
u3_noun fun = u3n_nock_on(u3k(u3A->roc), u3k(u3x_at(4, u3A->roc)));
2014-09-23 21:11:59 +04:00
u3_noun sam = u3nc(u3k(u3A->now), hap);
2014-11-06 03:20:01 +03:00
return u3n_slam_on(fun, sam);
2014-09-23 21:11:59 +04:00
}
2014-11-06 03:20:01 +03:00
/* u3v_do(): use a kernel gate.
2014-09-23 21:11:59 +04:00
*/
u3_noun
2014-11-06 03:20:01 +03:00
u3v_do(const c3_c* txt_c, u3_noun sam)
2014-09-23 21:11:59 +04:00
{
2014-11-06 03:20:01 +03:00
u3_noun gat = u3v_wish(txt_c);
2014-11-02 01:13:18 +03:00
u3_noun pro;
#if 0
if ( &u3H->rod_u == u3R ) {
2014-11-06 03:20:01 +03:00
pro = u3m_soft_slam(gat, sam);
2014-11-02 01:13:18 +03:00
}
else {
2014-11-06 03:20:01 +03:00
pro = u3n_slam_on(gat, sam);
2014-11-02 01:13:18 +03:00
}
#else
2014-11-06 03:20:01 +03:00
pro = u3n_slam_on(gat, sam);
2014-11-02 01:13:18 +03:00
#endif
return pro;
2014-09-23 21:11:59 +04:00
}
/* _cv_scot(): print atom.
*/
static u3_noun
_cv_scot(u3_noun dim)
{
return u3_do("scot", dim);
}
2014-11-06 03:20:01 +03:00
/* u3v_time(): set the reck time.
2014-09-23 21:11:59 +04:00
*/
void
2014-11-06 03:20:01 +03:00
u3v_time(u3_noun now)
2014-09-23 21:11:59 +04:00
{
u3z(u3A->now);
u3A->now = now;
u3z(u3A->wen);
u3A->wen = _cv_scot(u3nc(c3__da, u3k(u3A->now)));
}
2014-11-06 03:20:01 +03:00
/* u3v_numb(): set the instance number.
2014-09-23 21:11:59 +04:00
*/
void
2014-11-06 03:20:01 +03:00
u3v_numb()
2014-09-23 21:11:59 +04:00
{
2014-11-06 03:20:01 +03:00
u3A->sev_l = u3r_mug(u3A->now);
2014-09-23 21:11:59 +04:00
u3z(u3A->sen);
u3A->sen = _cv_scot(u3nc(c3__uv, u3A->sev_l));
}
#if 0
/* _cv_time_bump(): advance the reck time by a small increment.
*/
static void
_cv_time_bump(u3_reck* rec_u)
{
c3_d bum_d = (1ULL << 48ULL);
2014-11-06 03:20:01 +03:00
u3A->now = u3_cka_add(u3A->now, u3i_chubs(1, &bum_d));
2014-09-23 21:11:59 +04:00
}
#endif
2014-11-06 03:20:01 +03:00
/* u3v_peek(): query the reck namespace (protected).
2014-09-23 21:11:59 +04:00
*/
u3_noun
2014-11-06 03:20:01 +03:00
u3v_peek(u3_noun hap)
2014-09-23 21:11:59 +04:00
{
2014-11-06 03:20:01 +03:00
return u3m_soft_sure(_cv_nock_peek, hap);
2014-09-23 21:11:59 +04:00
}
2014-11-06 03:20:01 +03:00
/* u3v_keep(): measure timer.
2014-09-23 21:11:59 +04:00
*/
u3_noun
2014-11-06 03:20:01 +03:00
u3v_keep(u3_noun hap)
2014-09-23 21:11:59 +04:00
{
2014-11-06 03:20:01 +03:00
return u3m_soft_sure(_cv_nock_keep, hap);
2014-09-23 21:11:59 +04:00
}
#if 0
/* _cv_mole(): parse simple atomic mole.
*/
static u3_bean
_cv_mole(u3_noun fot,
u3_noun san,
c3_d* ato_d)
{
u3_noun uco = u3_do("slay", san);
u3_noun p_uco, q_uco, r_uco, s_uco;
2014-11-06 03:20:01 +03:00
if ( (c3n == u3r_qual(uco, &p_uco, &q_uco, &r_uco, &s_uco)) ||
2014-09-23 21:11:59 +04:00
(0 != p_uco) ||
(0 != q_uco) ||
2014-11-05 04:18:47 +03:00
(c3n == u3_sing(fot, r_uco)) )
2014-09-23 21:11:59 +04:00
{
2014-11-06 03:20:01 +03:00
uL(fprintf(uH, "strange mole %s\n", u3r_string(san)));
2014-09-23 21:11:59 +04:00
2014-11-05 04:18:47 +03:00
u3z(fot); u3z(uco); return c3n;
2014-09-23 21:11:59 +04:00
}
else {
2014-11-06 03:20:01 +03:00
*ato_d = u3r_chub(0, s_uco);
2014-09-23 21:11:59 +04:00
2014-11-05 04:18:47 +03:00
u3z(fot); u3z(uco); return c3y;
2014-09-23 21:11:59 +04:00
}
}
/* _cv_lily(): parse little atom.
*/
static u3_bean
_cv_lily(u3_noun fot, u3_noun txt, c3_l* tid_l)
{
c3_d ato_d;
2014-11-05 04:18:47 +03:00
if ( c3n == _cv_mole(fot, txt, &ato_d) ) {
return c3n;
2014-09-23 21:11:59 +04:00
} else {
if ( ato_d >= 0x80000000ULL ) {
2014-11-05 04:18:47 +03:00
return c3n;
2014-09-23 21:11:59 +04:00
} else {
*tid_l = (c3_l) ato_d;
2014-11-05 04:18:47 +03:00
return c3y;
2014-09-23 21:11:59 +04:00
}
}
}
#endif
2014-11-06 03:20:01 +03:00
/* u3v_poke(): insert and apply an input ovum (protected).
2014-09-23 21:11:59 +04:00
*/
u3_noun
2014-11-06 03:20:01 +03:00
u3v_poke(u3_noun ovo)
2014-09-23 21:11:59 +04:00
{
return _cv_nock_poke(ovo);
}
2014-11-06 03:20:01 +03:00
/* u3v_http_request(): hear http request on channel (unprotected).
2014-09-23 21:11:59 +04:00
*/
void
2014-11-06 03:20:01 +03:00
u3v_http_request(u3_bean sec, u3_noun pox, u3_noun req)
2014-09-23 21:11:59 +04:00
{
// uL(fprintf(uH, "http: request\n"));
2014-11-06 03:20:01 +03:00
u3v_plan(pox, u3nq(c3__this, sec, 0, req));
2014-09-23 21:11:59 +04:00
}
2014-11-06 03:20:01 +03:00
/* u3v_tank(): dump single tank.
2014-09-23 21:11:59 +04:00
*/
void
2014-11-06 03:20:01 +03:00
u3v_tank(u3_noun blu, c3_l tab_l, u3_noun tac)
2014-09-23 21:11:59 +04:00
{
2014-11-06 03:20:01 +03:00
u3v_punt(blu, tab_l, u3nc(tac, u3_nul));
2014-09-23 21:11:59 +04:00
}
2014-11-06 03:20:01 +03:00
/* u3v_punt(): dump tank list.
2014-09-23 21:11:59 +04:00
*/
void
2014-11-06 03:20:01 +03:00
u3v_punt(u3_noun blu, c3_l tab_l, u3_noun tac)
2014-09-23 21:11:59 +04:00
{
#if 0
u3_noun blu = u3_term_get_blew(0);
#endif
c3_l col_l = u3h(blu);
u3_noun cat = tac;
// We are calling nock here, but hopefully need no protection.
//
2014-11-06 03:20:01 +03:00
while ( c3y == u3r_du(cat) ) {
2014-09-23 21:11:59 +04:00
u3_noun wol = u3_dc("wash", u3nc(tab_l, col_l), u3k(u3h(cat)));
2014-11-06 03:20:01 +03:00
u3m_wall(wol);
2014-09-23 21:11:59 +04:00
cat = u3t(cat);
}
u3z(tac);
u3z(blu);
}
2014-11-06 03:20:01 +03:00
/* u3v_sway(): print trace.
2014-09-23 21:11:59 +04:00
*/
void
2014-11-06 03:20:01 +03:00
u3v_sway(u3_noun blu, c3_l tab_l, u3_noun tax)
2014-09-23 21:11:59 +04:00
{
u3_noun mok = u3_dc("mook", 2, tax);
2014-11-06 03:20:01 +03:00
u3v_punt(blu, tab_l, u3k(u3t(mok)));
2014-09-23 21:11:59 +04:00
u3z(mok);
}
2014-11-06 03:20:01 +03:00
/* u3v_plan(): queue ovum (external).
2014-09-23 21:11:59 +04:00
*/
void
2014-11-06 03:20:01 +03:00
u3v_plan(u3_noun pax, u3_noun fav)
2014-09-23 21:11:59 +04:00
{
2014-10-12 11:17:06 +04:00
u3_noun egg = u3nc(pax, fav);
u3A->roe = u3nc(u3nc(u3_nul, egg), u3A->roe);
2014-09-23 21:11:59 +04:00
}
2014-11-06 03:20:01 +03:00
/* u3v_plow(): queue multiple ova (external).
2014-09-23 21:11:59 +04:00
*/
void
2014-11-06 03:20:01 +03:00
u3v_plow(u3_noun ova)
2014-09-23 21:11:59 +04:00
{
u3_noun ovi = ova;
while ( u3_nul != ovi ) {
u3_noun ovo=u3h(ovi);
2014-11-06 03:20:01 +03:00
u3v_plan(u3k(u3h(ovo)), u3k(u3t(ovo)));
2014-09-23 21:11:59 +04:00
ovi = u3t(ovi);
}
u3z(ova);
}
2014-11-06 03:20:01 +03:00
/* u3v_louse(): last-minute deviltry upon a bail.
2014-09-23 21:11:59 +04:00
*/
void
2014-11-06 03:20:01 +03:00
u3v_louse(c3_m how_m)
2014-09-23 21:11:59 +04:00
{
#if 0
if ( c3__exit == how_m ) {
printf("louse: nocks: %d\n", NOX);
2014-11-06 03:20:01 +03:00
printf("louse: washing kernel %x %d\n", u3A->ken, u3a_is_dog(u3A->ken));
u3m_wash(u3A->ken);
2014-09-23 21:11:59 +04:00
2014-11-06 03:20:01 +03:00
printf("kernel %x; washed mug %x\n", u3A->ken, u3r_mug(u3A->ken));
2014-09-23 21:11:59 +04:00
}
#endif
}
2014-10-09 06:20:57 +04:00
2014-11-01 01:36:01 +03:00
/* _cv_mark_ova(): mark ova queue.
2014-10-09 06:20:57 +04:00
*/
static void
2014-11-06 03:20:01 +03:00
_cv_mark_ova(u3p(u3v_cart) egg_p)
2014-10-09 06:20:57 +04:00
{
2014-11-04 21:39:56 +03:00
while ( egg_p ) {
2014-11-06 03:20:01 +03:00
u3v_cart* egg_u = u3to(u3v_cart, egg_p);
2014-11-01 01:36:01 +03:00
2014-11-06 03:20:01 +03:00
u3a_mark_ptr(egg_u);
u3a_mark_noun(egg_u->vir);
2014-11-04 21:39:56 +03:00
egg_p = egg_u->nex_p;
2014-10-09 06:20:57 +04:00
}
}
2014-11-06 03:20:01 +03:00
/* u3v_mark(): mark arvo kernel.
2014-10-09 06:20:57 +04:00
*/
void
2014-11-06 03:20:01 +03:00
u3v_mark(void)
2014-10-09 06:20:57 +04:00
{
2014-11-06 03:20:01 +03:00
u3v_arvo* arv_u = &(u3H->arv_u);
2014-10-09 06:20:57 +04:00
2014-11-06 03:20:01 +03:00
u3a_mark_noun(arv_u->yot);
u3a_mark_noun(arv_u->now);
u3a_mark_noun(arv_u->wen);
u3a_mark_noun(arv_u->sen);
u3a_mark_noun(arv_u->own);
2014-10-09 06:20:57 +04:00
2014-11-06 03:20:01 +03:00
u3a_mark_noun(arv_u->roe);
u3a_mark_noun(arv_u->key);
2014-10-09 06:20:57 +04:00
2014-11-06 03:20:01 +03:00
u3a_mark_noun(arv_u->ken);
u3a_mark_noun(arv_u->roc);
2014-10-09 06:20:57 +04:00
2014-11-04 21:39:56 +03:00
_cv_mark_ova(arv_u->ova.egg_p);
2014-10-09 06:20:57 +04:00
}