// Description   : NANO OS Core $Revision: 37 $

// Copyright     : Proxima Centauri Romania SRL, ALL RIGHTS RESERVED. (http://www.ProximaCentauri.org)

// Author        : Alexander Ioan Mihail

 

#include "nano.h"

#include <io.h>

#include <memory.h>

#include <malloc.h>

#include <stdio.h>

#include <process.h>

#include <setjmp.h>

 

extern const struct SBitmapData

{

  const unsigned char*ptr;

  int size;

};

const SBitmapData*GetBitmapData();

char*GetCurrentUserName();

int GetCurrentPID();

 

START_NAMESPACE(NANO_CORE)

PACKAGE void BreakPoint() {}

void PACKAGE debug_trace(int flags,int level,const char*format,...)

{

  va_list marker;

  va_start(marker,format);

  char buf[10000];

 #ifdef _MSC_VER

  _vsnprintf_s_l (buf,sizeof(buf),sizeof(buf),format,0,marker);

 #else

  vsprintf(buf,format,marker);

 #endif

  va_end(marker);

  ELEMENT::Trace((ETraceFlags)flags,level,buf);

}

 

extern "C" int PACKAGE core_debug_trace(void*app,ETraceFlags,int,PSTRING msg)

{

  printf(msg);

  return 0;

}

__declspec(thread) ELEMENT*CurrentThread=0;

char CoreVersion[]="$Revision: 37 $";

#define LOCK Lock();

#define UNLOCK Unlock();

void ourmemcpy(void*dst,void*src,size_t sz) {memcpy(dst,src,sz);}

#ifndef _M_X64

struct SFork

{

  void*retaddr;

  void*frame;

  char*name;

  int stacksize;

  int wait;

  ELEMENT*thmeta;

};

#else

struct SFork

{

  const char*name;

  _JUMP_BUFFER*pjb;

  ELEMENT*thmeta;

  size_t  flen;

  size_t extra;

};

#define FORK_LOCALS (0x118 + sizeof(SFork))

int DoContext(_JUMP_BUFFER*pjb,void*&context)

{

  if (setjmp(*(jmp_buf*)pjb))

    return 0;

  if (context)

  {

    SFork*pargs=(SFork*)context;

   #ifdef _M_X64

    *(void**)(pjb->Rsp+0x180+sizeof(SFork))=*(void**)(pargs->pjb->Rsp+0x180+sizeof(SFork));

    char*frame_bottom=((char*)pjb->Rbp+FORK_LOCALS);

    *(char**)frame_bottom-=0x2E0;

   #else

    *(void**)(pjb->Esp+0x180+sizeof(SFork))=*(void**)(pargs->pjb->Esp+0x180+sizeof(SFork));

    char*frame_bottom=((char*)pjb->Ebp+FORK_LOCALS);

    *(char**)frame_bottom-=0x2E0;

   #endif

    pargs->name=0;

    longjmp(*(jmp_buf*)pjb,1);

  }

  context=pjb;

  return 1;

}

#endif

ELEMENT* DoFork (void* context)

{

  SFork*args=(SFork*)context;

  ELEMENT*th=ELEMENT::INIT(nullptr,nullptr,args->name,nullptr,args->thmeta,nullptr,0);

  args->thmeta=th;

#ifndef _M_X64

  __asm {

  // Create a return path for exiting the thread

   PUSH __JumpPoint;

   PUSH EBP;

   MOV EAX,context;

   MOV EBP,ESP;

   MOV ECX,EAX;

   MOV EDX,[EAX]SFork.retaddr;

   SUB ECX,EDX;

   NEG ECX;

   MOV EDX,ESP;

   SUB EDX,ECX;

   MOV ESP,EDX;

   PUSH ECX;

   PUSH EAX;

   PUSH EDX;

   CALL ourmemcpy;

   ADD  ESP,3*4;

   MOV EAX,[ESP-2*4]; // go up to the original BP this function set upon entry

   MOV [ESP],EBP;

   MOV EBP,ESP;

   MOV [EAX]SFork.name,0; // reset local wait spinlock in Fork

  }

  return 0; // the result of fork is 0 for the child thread.

__JumpPoint:

  delete CurrentThread;

  _endthread();

#else

  char*frame_bottom=((char*)args->pjb->Rbp);

  char*frame_top=*((char**)(frame_bottom+FORK_LOCALS));

  frame_bottom+=FORK_LOCALS+0x20;

  frame_top+=FORK_LOCALS+0x20;

  size_t frame_len=frame_top-frame_bottom;

  frame_len+=FORK_LOCALS+2*0x20;

  char*frame_new=(char*)alloca(frame_len);

  BreakPoint();

  for (int i=0;i<frame_len;i++)

    frame_new[i]=frame_bottom[i];

  return th->ELEMENT::Fork(0,0,0,context,nullptr);

#endif

}

 

BOND::BOND ()

{

  if (!(POYC[1]&&POYC[2]))

    POYC[1]=POYC[2]=this;

  Object=nullptr;

}

BOND::~BOND ()

{

  Remove();

}

BOND* BOND::INIT (ELEMENT* container, BOND* parent, BOND* self)

{

  self->Object=container;

  self->POYC[0]=nullptr;

  self->POYC[1]=self;

  self->POYC[2]=self;

  self->POYC[3]=nullptr;

  self->Flags=0;

  self->Extra=0;

  self->LVR[0]=0;

  self->LVR[1]=0;

  self->LVR[2]=0;

  if (parent)

   self->Insert(parent);

  return self;

}

void BOND::DONE (bool release)

{

  Remove();

  LOCK

  while (POYC[3])

  {

   BOND* t=POYC[3];

   t->Remove();

   if (release&&t->Object)

   {

    PELEMENT obj=t->Object;

    t->Object=nullptr;

    delete obj;

   }

  }

  UNLOCK

}

void BOND::Insert (BOND* parent, BOND* before)

{

  LOCK

  if (before)

    parent=before->POYC[0];

  if (parent==nullptr||parent!=POYC[0])

  {

    UNLOCK

    Remove();

    if (!parent)

     return;

    LOCK

  }

  if (!before)

  {

    POYC[0]=parent;

    if (parent->POYC[3])

    {

      BOND* Tail=parent->POYC[3];

      POYC[2]=Tail; // Last

      if (POYC[1])

      {

        POYC[1]=Tail->POYC[1]; // First

        POYC[1]->POYC[2]=this;

        POYC[2]->POYC[1]=this;

      }

    }

    parent->POYC[3]=this;

  }

  else

  {

    POYC[2]=before;

    if (POYC[1])

    {

      POYC[1]=before->POYC[1];

      before->POYC[1]->POYC[2]=this;

      before->POYC[1]=this;

    }

    POYC[0]=before->POYC[0];

  }

  UNLOCK

}

void BOND::Remove ()

{

  LOCK

  if (POYC[0])

  {

   if (POYC[0]->POYC[3]==this)

    if (POYC[2]==this)

     POYC[0]->POYC[3]=nullptr;

    else

     POYC[0]->POYC[3]=POYC[2];

   POYC[0]=nullptr;

  }

  if (POYC[1])

  {

   POYC[1]->POYC[2]=POYC[2];

   POYC[2]->POYC[1]=POYC[1];

   POYC[2]=this;

   POYC[1]=this;

  }

  else

   POYC[2]=nullptr;

  UNLOCK

}

int BOND::Count ()

{

  LOCK

  int retval=0;

  BOND*sb=POYC[3];

  if (sb)

  do

    retval++;

  while ((sb=sb->POYC[2])!=POYC[3]);

  UNLOCK

  return retval;

}

BOND* BOND::get_First ()

{

  BOND* retval=nullptr;

  BOND*c;

  if (c=POYC[3])

   retval=c->POYC[1];

  return retval;

}

int BOND::IsEndpoint ()

{

  int id=this-Object->TSLPIO;

  if (id<2)

    return 0;

  return id;

}

void BOND::Lock ()

{

  while (Flags&(1<<flLocked));

  Flags|=(1<<flLocked);

}

void BOND::Unlock ()

{

  Flags&=~(1<<flLocked);

}

 

int_XXX_XvoidXXenum_ETraceFlagsX_intX_charXX ELEMENT::fTrace=core_debug_trace;

int_XXX_XvoidXX_class_ELEMENTXX_intX_class_BONDXX ELEMENT::fEdit;

 

ELEMENT::~ELEMENT ()

{

  ELEMENT*type=TypeOf();

  ELEMENT*parent=GetParent();

  TSLPIO[1].Remove();

  TSLPIO[1].Lock();

__L:

  BOND*sb=TSLPIO[1].POYC[3];

  if (sb)

    while (true)

    {

      BOND*n=sb->POYC[2];

      ELEMENT*e=sb->Object;

      sb->Remove();

      if (!e->TSLPIO[0].Object)

      {

        if (e!=this)

        {

          e->TSLPIO[0].Object=nullptr;

          delete e;

        }

        goto __L;

      }

      sb=n;

    }

  TSLPIO[1].Unlock();

  if (Name)

  {

    BOND*amorphous=(BOND*)((char*)Name-sizeof(BOND));

    ELEMENT*allocator=amorphous->Object;

    if (amorphous->POYC[0]==&TSLPIO[0])

      allocator=this;

    Name=(char*)allocator->ReAlloc(Name,0,nullptr);

  }

  if (type==&GetKernel()->Types[CAT_CORE::em_THREAD])

    if (!parent->TSLPIO[1].POYC[3])

      delete parent;

    else

     _endthread();

  if (type)

    if (this==type->GetKernel())

      CurrentThread=nullptr;

}

void ELEMENT::operator delete (void* ptr)

{

  our_free(ptr);

}

ELEMENT* ELEMENT::INIT (ELEMENT* container, ELEMENT* parent, const char* name, ELEMENT* target, ELEMENT* type, ELEMENT* self, int value)

{

  if (!self)

  {

    if (!CurrentThread)

      CurrentThread=type->GetKernel();

    int size=type->GetSize(0,0);

    self=(ELEMENT*)our_calloc(size,1);

    BOND::INIT(nullptr,&type->TSLPIO[0],&self->TSLPIO[0]);

  }

  *(void**)self=(void*)type->TSLPIO[0].LVR[1];

  self->TSLPIO[1].LVR[0]=(char*)MAX_DATE;

  self->TSLPIO[1].LVR[2]=(char*)MIN_DATE;

  if (!self->TSLPIO[0].POYC[0])

  {

    self->TSLPIO[0].Object=nullptr;

    self->TSLPIO[0].POYC[1]=&self->TSLPIO[0];

    self->TSLPIO[0].POYC[2]=&self->TSLPIO[0];

  }

  for (int i=1;i<6;i++)

  {

    self->TSLPIO[i].Object=self;

    if (i!=4)

    {

     self->TSLPIO[i].POYC[0]=nullptr;

     self->TSLPIO[i].POYC[1]=&self->TSLPIO[i];

     self->TSLPIO[i].POYC[2]=&self->TSLPIO[i];

    }

    self->TSLPIO[i].POYC[3]=nullptr;

  }

  if (type&&(type!=self->TypeOf()))

    self->TSLPIO[0].Insert(&type->TSLPIO[0]);

 

  self->TSLPIO[5].INIT(self,target?&target->TSLPIO[4]:nullptr,&self->TSLPIO[5]);

  if (container)

  {

    self->Touch((size_t)container->TSLPIO[1].LVR[0],1);

    self->Touch((size_t)container->TSLPIO[1].LVR[2],1);

    ELEMENT*To=self->TSLPIO[5].Object;

    if (To)

    {

      To->Touch((size_t)container->TSLPIO[1].LVR[0],1);

      To->Touch((size_t)container->TSLPIO[1].LVR[2],1);

    }

  }

  self->TSLPIO[0].Object=container;

  if (parent)

    self->TSLPIO[1].Insert(&parent->TSLPIO[1]);

  if (name)

    self->Translate(+1,0,(char*)name,strlen(name)+1,0);

  if (type==&self->GetKernel()->Types[CAT_CORE::em_THREAD])

  {

    CurrentThread=self;

    self->Insert(self->GetProcess());

  }

  self->TSLPIO[5].LVR[1]=(char*)value;

  return self;

}

ELEMENT* ELEMENT::TypeOf ()

{

  #define TYPEINFO(ti) ((ELEMENT*)ti?((char*)ti-(char*)&(*((ELEMENT*)0)).TSLPIO[0]):0)

  #define TYPEOF(obj) ((ELEMENT*)TYPEINFO((obj->TSLPIO[0].POYC[0])))

  return TYPEOF(this);

  #undef TYPEOF

  #undef TYPEINFO

}

bool ELEMENT::IsOfType (ELEMENT* type)

{

  ELEMENT*meta=TypeOf();

  CAT_CORE*core=GetKernel();

  BOND*b;

  while

    (

      meta!=type&&

      meta!=&core->Types[CAT_CORE::em_VOID]&&

      (b=meta->TSLPIO[5].POYC[0])

    )

    meta=b->Object;

  return (meta==type);

}

bool ELEMENT::IsSelector ()

{

  return (TypeOf()&&IsOfType(&GetKernel()->Types[CAT_CORE::em_HAS]));

}

void ELEMENT::Insert (ELEMENT* parent)

{

  TSLPIO[1].Insert(&parent->TSLPIO[1]);

}

void ELEMENT::Remove ()

{

  TSLPIO[1].Remove();

}

void ELEMENT::Touch (size_t value, int aspect)

{

  if (value<=MIN_DATE||value>=MAX_DATE)

    return;

  if (value<(size_t)TSLPIO[aspect].LVR[0])

    TSLPIO[aspect].LVR[0]=(char*)value;

  if (value>(size_t)TSLPIO[aspect].LVR[2])

    TSLPIO[aspect].LVR[2]=(char*)value;

  if (GetParent())

    GetParent()->Touch(value,aspect);

}

int ELEMENT::Evaluate (int phase, int param1)

{

  int retval=1;

  ELEMENT*var=nullptr;

  FOR_CHILDREN_OF(this)

    if (!var->IsOfType(&GetKernel()->Types[CAT_CORE::em_PROCESS]))

      retval+=var->Evaluate(phase,param1);

  FOREND

  return retval;

}

ELEMENT* ELEMENT::Find (const char* name, int flags)

{

  ELEMENT*var=nullptr;

  ELEMENT*retval=nullptr;

  FOR_CHILDREN_OF(this)

    if (var->Name)

    {

      if ((flags&(1<<PARTIAL)))

        if (strstr(var->Name,name))

        {

          retval=var;

          break;

        }

      if (!(flags&(1<<INSENSITIVE)))

      {

        if (!stricmp(var->Name,name))

        {

          retval=var;

          break;

        }

      }

      else

      {

        if (!strcmp(var->Name,name))

        {

          retval=var;

          break;

        }

      }

    }

  FOREND

  if (retval)

    return retval;

  if ((flags&(1<<FLAT)))

    return nullptr;

  FOR_CHILDREN_OF(this)

    if (var=var->Find(name,flags))

    {

      retval=var;

      break;

    }

  FOREND

  return retval;

}

void ELEMENT::Expand (BOND* aspect, bool on)

{

}

void* ELEMENT::SetEditor (void* editor)

{

  // returns

  //    1. null if a foreign editor is locked onto the element

  //    2. previous editor so that the caller may delete it

  //    3. the current editor so that the caller knows to do nothing.

  ELEMENT*Editor=nullptr;

  if (TSLPIO[3].POYC[3])

  {

    Editor=TSLPIO[3].POYC[3]->Object;

    ELEMENT*p=Editor;

    if ((p=p->GetParent()) && (p=p->GetParent())!=GetProcess())

      return nullptr;

  }

  void*old_edit=Editor;

  if (Editor&&!editor)

    Editor->TSLPIO[3].Remove();

  Editor=(ELEMENT*)editor;

  if (Editor)

    Editor->TSLPIO[3].Insert(&TSLPIO[3],nullptr);

  if (Editor&&!old_edit)

    return Editor;

  return old_edit;

}

CAT_CORE* ELEMENT::GetKernel ()

{

  ELEMENT*type=TypeOf();

  if (!type)

    return 0;

  if (type==this)

    if (!TSLPIO[0].Object)

      return (CAT_CORE*)this;

  type=type->TypeOf();

  CAT_CORE*core=(CAT_CORE*)((char*)type-(size_t)&((CAT_CORE*)0)->Types[CAT_CORE::em_META]);

  return core;

}

ELEMENT* ELEMENT::GetParent ()

{

  return (PELEMENT )(TSLPIO[1].POYC[0]?TSLPIO[1].POYC[0]->Object:nullptr);

}

int ELEMENT::GetTypeID ()

{

  return GetKernel()->Types[CAT_CORE::em_ELEMENT].GetId();

}

void ELEMENT::GetPath (char* path)

{

  ((ELEMENT*)GetParent())->GetPath(path);

  path+=strlen(path);

  strcpy(path,Name);

}

ELEMENT* ELEMENT::GetEndpoint ()

{

  return (ELEMENT*)TSLPIO[5].POYC[0]->Object;

}

int ELEMENT::GetId ()

{

  CAT_CORE*core=(CAT_CORE*)GetKernel();

  ELEMENT*metas=(ELEMENT*)core;

  int id=((char*)this-(char*)metas)/sizeof(ELEMENT);

  return id;

}

void ELEMENT::GetBitmapData (void*& ptr, int& size)

{

  int id=GetId();

  ptr=(void*)::GetBitmapData()[id].ptr;

  size=::GetBitmapData()[id].size;

}

ELEMENT* ELEMENT::GetActor ()

{

  ELEMENT*user;

  char*uname=GetCurrentUserName();

  CAT_CORE*core=GetKernel();

  user=(ELEMENT*)core->Types[CAT_CORE::em_Actors].Find(uname,0);

  if (!user)

  {

    user=ELEMENT::INIT(nullptr,&core->Types[CAT_CORE::em_Actors],uname,nullptr,&core->Types[CAT_CORE::em_ACTOR],nullptr,0);

    ELEMENT*home=ELEMENT::INIT(nullptr,user,"Home",nullptr,&core->Types[CAT_CORE::em_ELEMENT],nullptr,0);

    user->TSLPIO[5].Insert(&home->TSLPIO[4]);

  }

  return user;

}

ELEMENT* ELEMENT::GetProcess ()

{

  ELEMENT*process=nullptr;

  if (CurrentThread)

    if (process=CurrentThread->GetParent())

      return process;

  CAT_CORE*core=CurrentThread->GetKernel();

  ELEMENT*actor=core->GetActor();

  int pid=GetCurrentPID();

  // PID is a value associated with the input of a process

  ELEMENT*sessions=&core->Types[CAT_CORE::em_PROCESS];

  ELEMENT*var=nullptr;

  FOR_CHILDREN_OF(actor)

    if (sessions==var->TypeOf())

      if (pid==(int)var->TSLPIO[4].LVR[1])

        break;

  FOREND

  process=var;

  if (!process)

  {

    char buf[1000];

    sprintf(buf,"PROCESS (%d)",pid);

    process=ELEMENT::INIT(nullptr,actor,buf,nullptr,sessions,nullptr,0);

    process->TSLPIO[4].LVR[1]=(char*)pid;

  }

  return process;

}

ELEMENT* ELEMENT::GetThread ()

{

  return CurrentThread;

}

bool ELEMENT::IsAdmin ()

{

  ELEMENT*user=CurrentThread->GetActor();

  if (user->TSLPIO[5].POYC[0]->Object==user->GetKernel())

    return true;

  return false;

}

char* ELEMENT::GetVersion ()

{

  static char buf[100]="";

  if (!buf[0])

  {

    char*b=buf;

    strcpy(b,"uOS 2.");

    b+=strlen(b);

    char*l=CoreVersion+11;

    char*r=strchr(l,'$');

    strncpy(b,l,(r-l));

    b+strlen(b);

  #ifdef _M_X64

    strcat(b,"64 bit");

  #else

    strcat(b,"32 bit");

  #endif

  #ifdef _DEBUG

    strcat(b," Debug");

  #endif

  }

  return buf;

}

int ELEMENT::Trace (enum ETraceFlags flags, int level, char* msg)

{

  if (!fTrace)

    return 0;

  ELEMENT*var=nullptr;

  ELEMENT*ct=CurrentThread;

  if (ct&&ct!=ct->TypeOf())

  {

    CAT_CORE*core=ct->GetKernel();

    if (core)

    {

      ELEMENT*process=ct->GetProcess();

      FOR_CHILDREN_OF(process)

        if (var->TypeOf()==&core->Types[CAT_CORE::em_PROXY])

          break;

      FOREND

    }

  }

  return fTrace(var,flags,level,msg);

}

void* ELEMENT::ReAlloc (void* ptr, size_t size, void* pref)

{

  ELEMENT*allocator=this;

  BOND*heap=&allocator->TSLPIO[0];

  while (heap->LVR[0]==heap->LVR[2])

  {

    allocator=heap->Object;

    heap=&allocator->TSLPIO[0];

  }

  size_t cpysz=0;

  if (ptr!=nullptr && size==0)

  {

    heap->Lock();

    BOND*block=(BOND*)((char*)ptr-sizeof(BOND));

    cpysz=(size_t)block->LVR[1];

    BOND*left=(BOND*)block->POYC[2];

    BOND*right=(BOND*)block->POYC[1];

    if (left->LVR[1]>0&&left<block)

    {

      left->LVR[1]-=(size_t)block->LVR[1];

      block->Remove();

      block=left;

      right=(BOND*)block->POYC[1];

    }

    if (right->LVR[1]>0&&block<right)

    {

      block->LVR[1]-=(size_t)right->LVR[1];

      right->Remove();

      if (heap->POYC[3]==right)

        heap->POYC[3]=block;

      left=(BOND*)block->POYC[2];

    }

    block->LVR[1]=(char*)-(size_t)block->LVR[1];

    heap->Unlock();

    // heap->ballance--;

    return nullptr;

  }

  if (!ptr && size!=0)

  {

    heap->Lock();

    size+=sizeof(BOND);

    BOND*rover=(BOND*)heap->POYC[3];

    if (heap==rover)

      rover=rover->POYC[2];

    while (true)

    {

      if (!rover->Object)

        BreakPoint();

      if ((size_t)rover->LVR[1]>=size)

      {

        // found a large enough hole

        BOND*block=rover;

        if ((size_t)block->LVR[1]<size+sizeof(BOND))

        {

          if (heap->POYC[3]==block)

          {

            do

            {

              rover=(BOND*)block->POYC[1];

              if (heap->POYC[3]==block)

                goto __fail;

            }

            while ((size_t)rover->LVR[1]<0);

            heap->POYC[3]=rover;

          }

          size=(size_t)block->LVR[1];

        }

        else

        {

          heap->POYC[3]=(BOND*)((char*)block+size);

          BOND::INIT(allocator,nullptr,heap->POYC[3]);

          heap->POYC[3]->LVR[1]=block->LVR[1]-size;

          heap->POYC[3]->Insert(nullptr,block);

        }

        block->LVR[1]=(char*)-size;

        heap->Unlock();

        // heap->ballance++;

        if (!block->Object)

          BreakPoint();

        if (cpysz>size)

          cpysz=size;

        memcpy((char*)block+sizeof(BOND),ptr,cpysz);

        return ((char*)block+sizeof(BOND));

      }

      while ((int)rover->LVR[1]<size)

      {

        rover=(BOND*)rover->POYC[1];

        if (rover==heap->POYC[3])

          goto __fail;

      }

    }

  __fail:

    heap->Unlock();

    return nullptr;

  }

  return nullptr;

}

int ELEMENT::Translate (int direction, int offset, char* buf, int len, int flags)

{

  CAT_CORE*core=CurrentThread?CurrentThread->GetKernel():(CAT_CORE*)this;

  if (direction==+1)

    if (Name=(char*)core->ReAlloc(nullptr,len,nullptr))

      memcpy(Name,buf,len);

  if (direction==-1)

    if (!buf)

      len=Name?strlen(Name):0;

    else

      if (Name)

        strcpy(buf,Name);

  return len;

}

void ELEMENT::Walk ()

{

  BOND*heap=&TSLPIO[0];

  heap->Lock();

  TRACE((NORMAL,0,"Kernel heap %X from %x to %x has the following structure:\r\n",heap,heap->LVR[0],heap->LVR[2]));

  BOND*rover=(BOND*)heap->POYC[3];

  size_t used_space=0;

  size_t free_space=0;

  int used_blocks=0;

  int free_blocks=0;

  do

    if ((int)rover->LVR[1]>0)

    {

      TRACE((NORMAL,0,"%8d Free block %X of size %d\r\n",used_blocks+free_blocks,rover,rover->LVR[1]));

      free_blocks++;

      free_space+=(size_t)rover->LVR[1];

    }

    else

    {

      TRACE((NORMAL,0,"%8d Used block %X of size %d\r\n",used_blocks+free_blocks,rover,-(size_t)rover->LVR[1]));

      used_blocks++;

      used_space-=(size_t)rover->LVR[1];

    }

    while ((rover=(BOND*)rover->POYC[1])!=heap->POYC[3]);

  // TRACE((NORMAL,0,"Ballance is %d\r\n",heap->ballance));

  TRACE((NORMAL,0,"%8d free blocks of total size %d\r\n",free_blocks,free_space));

  TRACE((NORMAL,0,"%8d used blocks of total size %d\r\n",used_blocks,used_space));

  TRACE((NORMAL,0,"%8d total blocks of total size %d\r\n",used_blocks+free_blocks,used_space+free_space));

  heap->Unlock();

}

int ELEMENT::GetSize (char* path, size_t offset)

{

  char*ppath=path;

  if (path)

  {

    ppath+=strlen(ppath);

    strcpy(ppath,Name);

    ppath+=strlen(Name);

  }

  int sz=0;

  if (!TSLPIO[5].POYC[0])

  {

    sz=(int)TSLPIO[5].LVR[1];

    if (path)

      TRACE((ETraceFlags::NORMAL,0,"%d %s\r\n",offset,path));

  }

  else

  {

    if ((int)TSLPIO[5].LVR[1])

    {

      ELEMENT*target=TSLPIO[5].POYC[0]->Object;

      ELEMENT*var=this;

      for (int i=0;i<(int)TSLPIO[5].LVR[1];i++)

      {

        if (ppath)

          if (!i)

            strcpy(ppath+strlen(ppath),"^");

          else

          {

            strcpy(ppath,".");

            strcpy(ppath+1,var->Name);

            strcpy(ppath+strlen(ppath),":");

          }

        size_t field_sz=target->GetSize(path,offset);

        if (ppath)

          *(ppath+strlen(ppath)-1)=0;

        offset+=field_sz;

        sz+=field_sz;

        var++;

      }

    }

    CAT_CORE*core=GetKernel();

    ELEMENT*var=nullptr;

    FOR_CHILDREN_OF(this)

      for (int i=0;i<(int)var->TSLPIO[5].LVR[1];i++)

      if (var->TypeOf()==&core->Types[CAT_CORE::em_HAS])

      {

        ELEMENT*target=var->TSLPIO[5].POYC[0]->Object;

        if (ppath)

        {

          strcpy(ppath,".");

          strcpy(ppath+1,var->Name);

          strcpy(ppath+strlen(ppath),":");

        }

        size_t field_sz=target->GetSize(path,offset);

        sz+=field_sz;

        offset+=field_sz;

        if (ppath)

          *ppath=0;

      }

      else if (var->TypeOf()==&core->Types[CAT_CORE::em_REF])

      {

        ELEMENT*target=var->TSLPIO[5].POYC[0]->Object;

        if (ppath)

        {

          strcpy(ppath,"*");

          strcpy(ppath+1,var->Name);

          strcpy(ppath+strlen(ppath),":");

          strcpy(ppath+strlen(ppath),target->Name);

        }

        sz+=sizeof(void*);

        if (ppath)

        {

          TRACE((ETraceFlags::NORMAL,0,"%d %s\r\n",offset,path));

          *ppath=0;

        }

        offset+=sizeof(void*);

      }

    FOREND

  }

  if (path)

    *(ppath-strlen(Name))=0;

  return sz;

}

 

#pragma optimize( "", off )

ELEMENT* ELEMENT::Fork (const char* name, int stacksize, int is_gui, void* context, ELEMENT* pivot)

{

  SFork*pargs;

#ifndef _M_X64

  __asm mov pargs,EBP;

#else

  STACK_FRAME

  SFork args;

  jmp_buf jb;

  _JUMP_BUFFER*pjb=(_JUMP_BUFFER*)&jb;

  if (!DoContext(pjb,context))

    return 0;

  pargs=&args;

  args.name=name;

  args.pjb=pjb;

#endif

  if (!pivot)

    pargs->thmeta=&CurrentThread->GetKernel()->Types[CAT_CORE::em_THREAD];

  if (_beginthread ((void(*)(void*))DoFork,stacksize,pargs))

  {

    while (pargs->name)

     BreakPoint();

    return pargs->thmeta;

  }

  return nullptr;

}

#pragma optimize( "", on )

 

 

CAT_CORE::CAT_CORE (ELEMENT* container, ELEMENT* parent, char* name, ELEMENT* type, void* start, void* end, int value)

{

  INIT(container,parent,0,&Types[em_META],type,this,1+em_Max+value);

  BOND*heap=&TSLPIO[0];

  BOND*FreeBlock=(BOND*)start;

  heap->POYC[3]=FreeBlock;

  BOND::INIT(this,heap,FreeBlock);

  FreeBlock->LVR[1]=(char*)((char*)end-(char*)start);

  heap->LVR[0]=(char*)start;

  heap->LVR[2]=(char*)end;

  char buf[sizeof(ELEMENT)];

  memset(buf,0,sizeof(buf));

  ELEMENT*el=new(buf) ELEMENT();

  for (int i=0;i<em_Max;i++)

  {

    Types[i].TSLPIO[0].Insert(&Types[em_META].TSLPIO[0]);

    Types[i].TSLPIO[0].LVR[1]=*(char**)el;

  }

  if (name)

    Translate(+1,0,(char*)name,strlen(name)+1,0);

  Types[em_META].TSLPIO[0].POYC[3]=&Types[em_META].TSLPIO[0];

  INIT(this,nullptr,"VOID",nullptr,&Types[em_META],&Types[em_VOID],0);

  INIT(this,nullptr,"INT",nullptr,&Types[em_META],&Types[em_INT],sizeof(int));

  INIT(this,nullptr,"CHAR",nullptr,&Types[em_META],&Types[em_CHAR],sizeof(char));

  INIT(this,nullptr,"BOOL",nullptr,&Types[em_META],&Types[em_BOOL],sizeof(bool));

  INIT(this,nullptr,"BOND",&Types[em_VOID],&Types[em_META],&Types[em_BOND],0);

  INIT(this,nullptr,"ELEMENT",&Types[em_VOID],&Types[em_META],&Types[em_ELEMENT],0);

  INIT(this,nullptr,"HAS",&Types[em_ELEMENT],&Types[em_META],&Types[em_HAS],1);

  INIT(this,nullptr,"REF",&Types[em_HAS],&Types[em_META],&Types[em_REF],1);

  INIT(this,nullptr,"THREAD",&Types[em_ELEMENT],&Types[em_META],&Types[em_THREAD],1);

  INIT(this,nullptr,"PROCESS",&Types[em_ELEMENT],&Types[em_META],&Types[em_PROCESS],1);

  INIT(this,nullptr,"ACTOR",&Types[em_ELEMENT],&Types[em_META],&Types[em_ACTOR],1);

  INIT(this,nullptr,"PROXY",&Types[em_ELEMENT],&Types[em_META],&Types[em_PROXY],1);

  INIT(this,this,"TYPE",&Types[em_ELEMENT],&Types[em_META],&Types[em_META],1);

  // Pieces

  INIT(this,this,"Actors",&Types[em_VOID],&Types[em_META],&Types[CAT_CORE::em_Actors],0);

  Types[CAT_CORE::em_Actors].TSLPIO[0].Insert(&Types[em_ELEMENT].TSLPIO[0]);

  // Rels

  INIT(this,&Types[em_BOND],"Object",&Types[em_ELEMENT],&Types[em_REF],&Types[rel_Object],1);

  INIT(this,&Types[em_BOND],"POYC",&Types[em_BOND],&Types[em_REF],&Types[rel_POYC],4);

  INIT(this,&Types[em_BOND],"Flags",&Types[em_INT],&Types[em_HAS],&Types[rel_Flags],1);

  INIT(this,&Types[em_BOND],"Extra",&Types[em_INT],&Types[em_HAS],&Types[rel_Extra],1);

  INIT(this,&Types[em_BOND],"LVR",&Types[em_CHAR],&Types[em_REF],&Types[rel_LVR],3);

  INIT(this,&Types[em_ELEMENT],"VMT",&Types[em_VOID],&Types[em_REF],&Types[rel_VMT],1);

  INIT(this,&Types[em_ELEMENT],"Name",&Types[em_CHAR],&Types[em_REF],&Types[rel_Name],1);

  INIT(this,&Types[em_ELEMENT],"Info",&Types[em_CHAR],&Types[em_REF],&Types[rel_Info],1);

  INIT(this,&Types[em_ELEMENT],"TSLPIO",&Types[em_BOND],&Types[em_HAS],&Types[rel_TSLPIO],6);

}

bool CAT_CORE::IsUsed ()

{

  return (Types[CAT_CORE::em_THREAD].TSLPIO[0].POYC[3]);

}

 

void*our_malloc(size_t sz)

{

  ELEMENT*th=ELEMENT::GetThread();

  CAT_CORE*core=th->GetKernel();

  return core->ReAlloc(nullptr,sz,nullptr);

}

void our_free(void*ptr)

{

  BOND*amorphous=(BOND*)((char*)ptr-sizeof(BOND));

  ELEMENT*allocator=amorphous->Object;

  allocator->ReAlloc(ptr,0,nullptr);

}

void*our_calloc(size_t sz,size_t element_sz)

{

  void*ptr=our_malloc(sz*element_sz);

  memset(ptr,0,sz*element_sz);

  return ptr;

}

END_NAMESPACE(NANO_CORE)