Basics of a semantic processor

//
//
// The official interface between Json grammar and underlying data
// base engine.   No other header files needed for c based embedded database
//
// Introduction:
// Nested or serialized formats are really expression trees, this model treats
// data as nested expression machs.
//
// The atom is the Element, a node on a mach obeying nested format grammar.
// Every Element is the first in a sequence of one or more Elements, and the 
// sequence obey's nested format grammar.  A Mach is simly a cursor set defined 
// over a sequence of Elements.  The Element contains a Key, which is the 
// unit of informaton, and the Elements points to the next Element in a set 
// with the Total field.  The Element comes with a link field containing an operator
// ID, exactly similar to an expresson tree within a compiler.
//
// **************************
// The nested store record format. 
//
// ****   Key: The actual data bytes ****
//  Passing the actual key bytes, the form is |int size|char bytes[size]|
// Implementations will implement a get_key/put_key private function 
// and accept or return the proper form
typedef int (*Handler)();
#define MAXNAME 40
typedef struct {int len; char * bytes;} Key;
typedef struct {int len; char * bytes; char buff[MAXNAME];} NameKey;

//typedef union {Key key;FlatKey flat;} NameKey;
//****  Element: The format of a mach node *****
// The actual mach node, as passed between layers
// actual internal form obviously up to the data base engine
typedef struct {
  int link;  // contains at least one byte from a Json parse
  int pointer;  // size of enclosed object, in element count
  Key key;   
} Element;
void elementPrint(Element *t);
// Link space. 128 available values can fill the link integer in a node
//
//  Sixteen are reserved for local system
#define SystemNone 15

// ****  A RowSequence: Defines the actual valid row pointers
//  The db can count out elements using the row sequence in a mach
typedef struct {
  int row;  //  current relative row
  int total; // total elements n the mach
  int offset; // offset to obtain absolute indexed row
} RowSequence;

// Machs contexts are nested cursors.  The row sequence is
// the nested cursor struct.
typedef struct Mach Mach;
typedef struct Cursor Cursor;
typedef struct Cursor  {
  RowSequence rdx;
  Cursor * parent;
  Mach * mach;  // Points back to the controlling object
} Cursor;
typedef Cursor *PCursor;
typedef PCursor *Glist;
// This is the structure that guides the general
// left_join() uses this
typedef struct JoinSet JoinSet;

typedef struct  JoinSet {
  Glist left;
  Glist right;
  Glist result;
  Element N;
}  JoinSet;
// 
// Databases must look like machs.
//
// It needs to implement the mach methods it consider important
//
// In the default grammar, uses fetch,step and read on table it is not writing to.
//
enum MachMethods{ 
  Select=0,
  Reset,
  Exec,
  Fetch,
  Step,
  StepFetch,
  FetchRow,
  Index,
  Update,
  Append,
  Eval,
  Script,
  None};
// Possible return status
#define EV_Error 0x0100
#define EV_Done 0x0200
#define EV_Data 0x0400
#define MachError 0x0100
#define MachDone 0x0200
#define MachData 0x0400

// The actual object between  Json execution unit and
// the D base engine
//
  // Preinstalled sub classes of Mach
  enum {Mach_Base,Mach_Mem,Mach_Flat,Mach_Parse,
    Mach_Json,Mach_Console,Mach_Net,Mach_File,Mach_None
  } MachTypes;

  // **************  Mach  *******************
  typedef struct Mach { 
    int subclass;
    Cursor *cursors;  // Single Linked  cursor list open on the object
// This is the main method selector and all DBs must have
    int (*exec)(Mach *obj,int method,Element *argument);
// object variables
    NameKey key;  // Everything has a name somewhere
    Mach *schema;  // Json schema available in a mem mach 
    Mach *parent;  // stacked
    int attributes;  // Square? Fixed size set elements? Has a parsed index? Empty? No data? Data ready? 
    void * variables[8]; // Available for local db
  } Mach;
  typedef Mach * (*MachInit)(Mach *);
  Mach * machInit(Mach *);
  int machAddName(char *,Mach * (*h)(Mach *)); 
// Each implementation exports the mach init function.  
// The execution unit will make a Mach and install defaults.
// Mach Init needs to modifiy and put in its one exec_operator and binds
// Mach *Init(Mach *obj,Key name);

extern JoinSet join;  // This is static, but often copies are pushed and popped
extern  Mach matchMach; // A permanent '*' D Base

#define ELSIZE 200
#define STRSIZE 8192


#define LG  ((Mach * )((*join.left)->mach))
#define RSLG ((Mach * )((*join.result)->mach))
#define RG  ((Mach * )((*join.right)->mach))
#define LC ((Cursor *) *join.left)
#define RSLC ((Cursor *) *join.result)
#define RC ((Cursor *) *join.right)
int left_join();

void MakeName(NameKey *namekey,Key *key);

extern JoinSet matchJoin;
Key  read_file(char * name);
int fdSendKey(int,Key);
// and the Json left join
#include "./include/config.h"
#include 
#include
#include
#include "./include/mach.h"
#include "./include/g_types.h"
#include "./include/names.h"
#include "./include/cursors.h"
#include "./include/items.h"

#ifndef DBG_ENGINE
#endif
// Will be shared Protected
OP operators[128];

JoinSet join;
// Using  cursor list grammar, a join becomes 
//  two program counters marching sequentially over two 
// different graphs. in a descent
// the handle argument will manipulate the
// cursor stack when skipping elements in a set.
// handle is expected to recursively call join
int left_join() {
  do {
    while(RC->rdx.row < RC->rdx.total) {
      LG->exec(LG,Fetch,&join.N);
      //Open a new expression tree
      if(join.N.pointer >  1) {
        new_cursor(join.left);  // a push
        LC->rdx.total=join.N.pointer;
      }
      operators[join.N.link & EV_Opcode].handler(); }
  }  while(LC->rdx.row < LC->rdx.total);
  if( LC->rdx.total > 1)
      delete_cursor(join.left);  
  return EV_Done;
}
int joinSwap() {
  PCursor *c;
  c = join.left; join.left= join.right; join.right = c; // parenthesis mean right join
  return 0;
}
int keycmp(Key k1,Key k2) {
  while(k1.len && k2.len && (k1.bytes[k1.len] == k2.bytes[k2.len]))
  { k1.len--;k2.len--;}
  if(k1.len || k2.len)
    return 0;
  return 1;
}
//
//  This is the one 'Arithmetic' method of the 'ALU' 
// Key out = match_pass_collect(Key left Key right
#define PROPERTY(a) operators[a.link & EV_Opcode].properties
int DotHandler(){
  Element left,right;
  RG->exec(RG,Fetch,&right);
  LG->exec(LG,Fetch,&left);
  // Operator precadence.
  if((right.pointer > 1) || (PROPERTY(right) & EV_Left))
    return joinSwap();
  if( (PROPERTY(right) & EV_Matched)) {
    (*join.left)->rdx.row++;
    // if(!(RSLG->attributes & EV_Not))
    RSLG->exec(RSLG,Append,&left);
    if(!(PROPERTY(right) & EV_NoInc)  || keycmp(left.key,right.key)) {
      (*join.right)->rdx.row++;
    }
  } else if( !(PROPERTY(left) & EV_Not) || left.link == '?') {
    (*join.right)->rdx.row++;
     // if(!(RSLG->attributes & EV_Not))
    RSLG->exec(RSLG,Append,&right);
    if(!(PROPERTY(left) & EV_NoInc)  ||  keycmp(left.key,right.key)) {
      (*join.left)->rdx.row++;
    }
  } else if( PROPERTY(left) & PROPERTY(right) & EV_Matcheable ) {
      (*join.right)->rdx.row++;
      (*join.left)->rdx.row++;
      if( // if(!(RSLG->attributes & EV_Not)) &&
        keycmp(left.key,right.key))
        RSLG->exec(RSLG,Append,&right);
      else {
        // skipping to the next left element
         delete_cursor(join.left); // this sequence fails
         LG->exec(LG,Fetch,&right);
         (*join.left)->rdx.row = right.pointer; 
         if((*join.left)->rdx.row < (*join.left)->rdx.total)
            (*join.right)->rdx.row=0;  // and restart the right
         else if((*join.left)->rdx.row > (*join.left)->rdx.total)
           printf("Sytax error\n");
      }
    } else  if(left.key.bytes[0] == '$') {// by relative row number of rightside arguments
      RG->exec(RG,FetchRow,&right); 
      // if(!(RSLG->attributes & EV_Not))
      RSLG->exec(RSLG,Append,&right);
      (*join.left)->rdx.row++;
      (*join.right)->rdx.row++;
    }  else return joinSwap(); // Dunno
    return EV_Done;
  }
  void MakeName(NameKey *namekey,Key *key) {
    namekey->len=  key->len > MAXNAME ? MAXNAME-1  : key->len; 
    strncpy(namekey->buff,key->bytes,namekey->len);
    namekey->bytes=  namekey->buff;namekey->buff[namekey->len]=0;
  }
  // sql:name@parse:,console:
  int ColonHandler() {
    Element n; Symbol *s;
    LG->exec(LG,StepFetch,&n);  // fetch the key of the next element
    //if(!key_compare())
    s=find_key(n.key); //look it up
    if(s && s->type == G_TYPE_HANDLER)
      ((Handler) s->value)();
    else if(s && s->type == G_TYPE_GRAPH) {  
      Mach g;
      LG->exec(LG,StepFetch,&n);  // fetch anyname
      MakeName(&g.key,&n.key);
      ((MachInit) s->value)(&g);
      return EV_Done;
    }
    else if(s && s->type == G_TYPE_OPID) 
      operators[(int) s->value].handler();
    LC->rdx.row=LC->rdx.total; //Clear
    return EV_Done;
  }
  int UnderHandler(){
    if(RG->attributes & EV_Matcheable){
      (*join.left)->rdx.row = (*join.left)->rdx.total;
      return 0;
    }
    else return joinSwap();
  }
  //
  int CommaHandler(){
    return DotHandler();
  }
   int NotHandler(){
     LG->attributes |= EV_Not;
    if(join.N.pointer == 1){
       DotHandler();
       LG->attributes &= ~EV_Not;
  } else 
    LC->rdx.row++;
  return 0;
   }

  int AsteriskHandler(){
    if(RG->attributes & EV_Matched){
      DotHandler();
    }  else{
      joinSwap();
      RG->attributes |= EV_Matched;
    }
    return 0;
  }
  int ParenthHandler(){
    joinSwap();
    return ColonHandler();
  }
  // Three At operators, one is visible
  int PreambleHandler(){
    LG->attributes |= EV_Preamble;
    return DotHandler();
  }
  // restart the join and place the result on the left
  int AtHandler(){
    //  set up right cursor
    Element N;
    Mach mach;
    Mach mem={Mach_Mem};
    Glist g=join.result;
    LG->attributes &= ~EV_Result;  // Clear any preamble condition
    mach = *(*join.left)->mach;
    mach.attributes &= ~EV_Left;
    mach.attributes |= EV_Right;
    mach.cursors= new_mach_cursor(&mach);
    LG->exec(LG,StepFetch,&N);
    // making the split
    mach.cursors->rdx.offset = (*join.left)->rdx.offset+N.pointer+1;
    mach.cursors->rdx.total = (*join.left)->rdx.total-N.pointer-1;
    (*join.left)->rdx.row++;
    machStart(&mach);
    mem.attributes |= EV_Result;
    machInit(&mem);
    machStart(&mem);
    left_join();
    machEnd(&mem);
    mem.attributes &= ~EV_Result;
    mem.attributes |= EV_Left;
    machStart(&mem);
    return 0;
  }
  enum { SystemNull,SystemCall,SystemConfig,SystemJson,SystemFile,SystemNet,SystemParse};
  int console_handler();
  //#define KEY(a) {strlen("a"),"a"}
#define KEY(a) {sizeof(#a)-1,0,#a}
#define OPCODE(a,h)   {a,KEY(a),h,0, EV_Installed}
#define UGLYCODE(a,h,p) {a,{1,0,a,0},h,0,p | EV_Ugly | EV_Matcheable}
  int opcode_initialize(OP *map);
  // install key at installed operand position pointer
  int  config_handler() {
    int opid;Element var;
    OP op=OPCODE(SystemNull,UnderHandler);
    Key name = {sizeof("Installed"),"installed"};
    MakeName(&op.key,&name); 
    LG->exec(LG,StepFetch,&var);
    opid = atoi(var.key.bytes);  // key value is opid
    op.opid=opid;
    if(SystemNone > opid ) 
      return(EV_Error);
    LG->exec(LG,StepFetch,&var);
    LG->exec(LG,Eval,&var);
    op.stmt=var.key.bytes;
    opcode_initialize(&op);
    LC->rdx.row=LC->rdx.total;
    return 0;
  }
  OP pre_installed[] = {
    OPCODE(SystemNull,UnderHandler),
    OPCODE(SystemConfig,config_handler),
    UGLYCODE('*',AsteriskHandler,EV_Matched|EV_NoInc),
    UGLYCODE('(',ParenthHandler,EV_Right),
    UGLYCODE(':',ColonHandler,EV_Left),
    UGLYCODE('_',UnderHandler,0),
    UGLYCODE(',',CommaHandler,0),
    UGLYCODE('.',DotHandler,0),
    UGLYCODE('!',NotHandler,0),
    UGLYCODE('@',AtHandler,EV_Left),
    UGLYCODE('?',UnderHandler,EV_Matched),
    OPCODE(128,0)
  };
  int opcode_initialize(OP *map) {
    Symbol s;
    if( map->opid > 127) 
      return EV_Error;
    if(operators[map->opid].properties) //not empty? 
      return EV_Error;
    map->key.bytes=map->key.buff;
    map->key.len = 
      strlen(map->key.bytes); //Key integrety
    if(map->key.len >20)
      return EV_Error;
    operators[map->opid]= *map;

    //if(!(operators[map->opid].properties & EV_Ugly)) {
    s.key=  *((Key *) &operators[map->opid].key);
    s.type = G_TYPE_OPID;
    s.value = (void *) map->handler;
    new_symbol(&s);
    // }
    return EV_Done;
  }
int handlerName(char * name,void * handler) {
Key k;
k.len=strlen(name);k.bytes = name;
add_key( k,G_TYPE_HANDLER, handler);
return 0;
}
  int init_handlers() {
    int i;
    for(i=0;pre_installed[i].opid!=128;i++)
      opcode_initialize(&pre_installed[i]);
    machInitInstalled();
    return EV_Done;
  }
#include 
#include 
#include "./include/mach.h"
#include "./include/g_types.h"
#include "./include/cursors.h"

#define DBP ((Element *) obj->variables[0])
char MemoryStrings[STRSIZE ];
char * MemoryStrptr;
// This is a null data base
#undef ATTRIBUTES
#define ATTRIBUTES (EV_Position | EV_Matched | EV_Matcheable)
int match_operator(Mach *obj,int opid,Element * data) {return '*';}
const Element matchElement={'*',1,{1,"*"}};
const RowSequence matchRdx={0,1,0}; 
Mach matchMach;
Cursor matchCursor;
JoinSet matchJoin= {&matchMach.cursors,&matchMach.cursors,&matchMach.cursors};
int matchExec(Mach * obj,int method, Element * arg) {
  matchMach.cursors=&matchCursor;
  if(arg) {
    if(method== Append) 
      elementPrint(arg);
    else 
      *arg = matchElement;
  }
  return 0;
}

int initmatchMach(){
  matchMach.attributes = ATTRIBUTES;
  new_mach_cursor(&matchMach);
  matchCursor.rdx=matchRdx;
  matchCursor.mach=&matchMach;
  matchMach.key.bytes = matchMach.key.buff;
  matchMach.cursors=&matchCursor;
  matchMach.exec = matchExec;
  return 0;
}

#define ORDX obj->cursors->rdx
#define memcpy( to,from,n){while(n--) to[n-1]=from[n=1];}

int memUpdate(Mach *obj,Element * e){ 
  DBP[ORDX.offset].pointer= ORDX.row;
  return EV_Done;
}
#define  keyCopy( to, from) \
  for(to.len=0;to.len < from.len;to.len++) to.bytes[to.len]=from.bytes[to.len];

int memAppend(Mach *obj,Element * from) {
  Element * to = &DBP[ORDX.row+ORDX.offset];
  if(!(obj->attributes &  EV_Result)) {
    printf("Syntax Error");
    return EV_Done;
  }
  to->key.bytes=MemoryStrptr;
  keyCopy(to->key,from->key);
  MemoryStrptr+=to->key.len;
  ORDX.row++;
  return EV_Done;
}
int memFetch(Mach *mach,Element * e) {
  if(mach->cursors->rdx.row >= (int) mach->variables[1])
    return EV_Done;
  *e = ((Element *) mach->variables[0])[mach->cursors->rdx.row+mach->cursors->rdx.offset];
  return EV_Data;
}
int memReset(Mach *obj,Element * e) {
  ORDX.row=0;
  ORDX.total=DBP[ORDX.row+ORDX.offset].pointer;
  return EV_Done;
}
int memStep(Mach *obj,Element * e) {
  ORDX.row++;
  return EV_Done;
}

int memStepFetch(Mach *obj,Element * e) {
  ORDX.row++;
  *e = DBP[ORDX.row+ORDX.offset];
  return EV_Done;
}
int memFetchRow(Mach *obj,Element *e) {
  int row;
  row = atoi(e->key.bytes+1);
  *e = DBP[row+ORDX.offset];
  return EV_Data;
}

int memDefault(Mach *obj,Element * e) {
  return EV_Done;
}
typedef int (*Handler)(Mach *,Element *);
Handler mem_methods[None-Select];
Handler flat_methods[None-Select];
#undef INSERT
#define INSERT(M,H) mem_methods[M]=H;flat_methods[M]=H;
#undef FLAT
#define FLAT(M,H) flat_methods[M]=H;
int mem_exec(Mach *mach,int method,Element * data) {
 return(method < None ? mem_methods[method-Select](mach,data) : memDefault(mach,data) );
}
int flat_exec(Mach *mach,int method,Element * data) {
   return(method < None ? flat_methods[method-Select](mach,data) : memDefault(mach,data) );
}
Mach *  MemInit(Mach * obj) {
  int size=0;
  Key *k = (Key *) (&obj->key);
    if(obj->attributes & EV_Flat){
    obj->exec =flat_exec;
    return 0;
    }
   obj->exec =mem_exec;
  if(!obj->attributes) 
    obj->attributes = LG->attributes;
  new_mach_cursor(obj);
  if(!obj->variables[0]) {  // caller supplied no memory
    size= (k->bytes && k->len && k->bytes[0]=='$')  ?
      atoi(obj->key.bytes+1) : ELSIZE;
      obj->variables[0] = (void *) malloc(size * sizeof(Element));
      obj->variables[1]= (void *) size;
  }
  if(!obj->variables[1])
    obj->variables[1]= (void *) size;
  obj->cursors->rdx.offset=0;
  return obj;
} 
void  MemDel(Mach * obj) {
  free(obj->variables[0]);
}

int memClose(Mach * obj,Element *t) {
  return EV_Done;
}
// this method steps through a flat file of the form:
// link1,pointer1,key1.len,key1.bytes,bytes[key1.len],link2,pointer2,key2....
int flatStep(Mach * mach,Element *e) {
  Element *cur;
  cur = (Element *) (int *) mach->variables[0];
  mach->variables[1] = cur + (cur->key.len/sizeof(int));
  mach->cursors->rdx.row++;
  return EV_Done;
}
int flatStepFetch(Mach * mach,Element *e) {
  flatStep(mach,e);
  return memFetch(mach,e);
}
int flatAppend(Mach * mach,Element *e) {
  Element *cur;int * I;
  I = (int *) mach->variables[0];
  cur = (Element *) I;
  cur->key.bytes = (char *)  &I[4];
  memcpy(cur->key.bytes,e->key.bytes,cur->key.len);
  mach->variables[1] = &I[(cur->key.len+3)/sizeof(int)];
  mach->cursors->rdx.row++;
  return EV_Done;
}

int initMemMach(){
  MemoryStrptr=MemoryStrings;
  initmatchMach();
  INSERT(Select,memReset);
  INSERT(Reset,memReset);
  INSERT(Append,memAppend);
  FLAT(Append,flatAppend);
  INSERT(Update,memUpdate);
  INSERT(Fetch,memFetch);
  INSERT(Step,memStep);
  FLAT(Step,flatStep);
  INSERT(FetchRow,memFetchRow);
  INSERT(StepFetch,memStepFetch);
  FLAT(StepFetch,flatStepFetch);
  machStart(&matchMach);
  return 0;
}

#include 
#include 
#include 
#include 
#include "./include/mach.h"
#include "./include/g_types.h"
#include "./include/cursors.h"
#include "./include/names.h"
#define DISCARD 0xff
const char  *uglies = "\"._,{}$!:@()";
int isin(char c,const char * str);// {while(*str && (*str) != c) str++; return *str;}
#define isugly(a) isin(a,uglies)

// Front end key word from text and json operators
#define trim(tmp) while((tmp != (*key)) && isspace(*(tmp-1))) tmp--;
#define white(v)while(isspace(*v)) v++;
int keyop(char * *Json,char **key,int *link) {
  char * ptr = *Json;
  char * end;
  int i=0;
  int events=0;
  *key = "_"; // Initial condition
  *link = '_';
  // Key
  white(ptr);
  if(*ptr == 0)
    return -1;
  end = ptr;
  if(isdigit(*ptr) ) {
    int one=0;
    while(isdigit(*ptr) || *ptr == '.') {
      if(*ptr == '.') one++;
      if(one > 1) return -1;
      ptr++; 
    }
    end = ptr;
  }
  else if(*ptr == '"') {// Quote char?
    ptr++;  *key=ptr;
    while(*ptr  != '"')  ptr++;
    end = ptr;  ptr++;    
  } else {
    *key=ptr;
    while(!isugly(*ptr) && !isspace(*ptr) && (*ptr != 0) ) ptr++;
    end = ptr;
  }
  i =   (int) end;
  i -= (int) (*key) ; // char count

  if(i==0)
    *key = "_";  // valid null key

  white(ptr);
  if((*ptr == 0) || !isugly(*ptr) ){ // End of string
    *link = '_';
    return -1;
  }
  // next operator
  *link = *ptr;
  *end = 0;
  ptr++;
  *Json = ptr;
  return i;
}

int json_rules(PCursor *inner);
// builds a submach on inner from user text
Element current,next;
#define LIST &obj->parent->cursors;
int parseAppend(Mach *obj,Element *e) {
  int nchars;
  char *Json;
  Json=e->key.bytes;
  nchars=0;
  // points to first child
  printf("\nparse start %s\n",Json);
  while(nchars >= 0) {
    nchars = keyop(&Json,&next.key.bytes,&next.link);
    next.pointer=1;
    json_rules(&obj->cursors);
  }  
  // finish up
  while(obj->cursors) 
    if(count_cursor(obj->cursors))
      close_update_cursor(&obj->cursors);
    else delete_cursor(&obj->cursors);

    printf("\nparse done\n");
    return(EV_Ok);
}
//  The Json parser chews through the text left to right as
// sequences of name/ops with the free pointer to be assigned
//

int json_rules(PCursor *inner) {
  // Some combinations can be ignored
  printf("%c %d %s\n",next.link,next.pointer,next.key.bytes);
  // Using $ to mean local relative pointer
  // forms like $ $1 $4 are special names
  if(next.key.bytes[0] == '$') {
    next.pointer = atoi(next.key.bytes+1);
    next.link = '$';
  }

  if(current.link == '{' ) { // value{ illegal
       new_cursor(inner);  
 }
  else
  // One append through this series
  if( current.link  == ':') {
    new_cursor(inner);
    append_cursor(inner,¤t);}
  else if(current.link == ',') {
    append_cursor(inner,¤t);
    close_update_cursor(inner);
    new_cursor(inner);
   } 
  else if(current.link == '.' ){
    if(next.link != '{')  
      append_cursor(inner,¤t);
    else {
      new_cursor(inner);
      (*inner)->rdx.offset--; // this is a prepend
    }
  }
  else if (current.link == '$')
    append_cursor(inner,¤t);
  else if (current.link == '('){
    new_cursor(inner);
    append_cursor(inner,¤t);
    
  }
  else if ((current.link == '}') || (current.link == ')')) {
    append_cursor(inner,¤t);
    close_update_cursor(inner);
  }
  current = next; 
  return 0;
}

// Json and parse are each result graphs
#undef ATTRIBUTES
#define ATTRIBUTES (EV_Result)
// fill a flat memory buffer with json
#define RDX(a) a->cursors->rdx
int jsonAppend(Mach * obj, Element *e) {
  Key *out = (Key *) obj->variables;
   if(e->pointer > 1) {
     new_cursor(join.result);
     LC->rdx.total=e->pointer;
    out->bytes[out->len]='{';out->len++;
  }
   (*join.result)->rdx.row++;
  sprintf(out->bytes+out->len,"%4s%4s%4s",e->link,e->pointer,e->key.len);
  out->len+= 12;
  strncpy(out->bytes+out->len,e->key.bytes,e->key.len); 
  if(LC->rdx.row == LC->rdx.total) {
    delete_cursor(join.result);
    out->len +=e->key.len;
    out->bytes[out->len]='}';out->len++;
    }
  return EV_Done;
}

int execParse(Mach *obj,int method,Element *t){
  if(method== Append)
    return parseAppend(obj,t);
  else
    return EV_Done;
}
Mach * ParseInit(Mach *mach){
    mach->attributes =  ATTRIBUTES;
    new_mach_cursor(mach);
    mach->exec=execParse;
  return mach;}

int execJson(Mach *obj,int method,Element *t){
  if(method== Append)
    return jsonAppend(obj,t);
  else
    return EV_Done;
}
static Key JsonKey;
Mach * JsonInit(Mach *mach){
 mach->attributes =  ATTRIBUTES;
   new_mach_cursor(mach);
   mach->cursors->rdx.total=1;
  mach->variables[0] = (void *) &JsonKey;
  JsonKey.bytes = (char *) malloc(8000);
  mach->variables[0] = (void *) (*join.result)->mach;
  JsonKey.len=0;
  mach->exec=execJson;

  return mach;
}
Symbol json_names[] = { 
   {{4,"json"},G_TYPE_GRAPH,JsonInit},
    {{5,"parse"},G_TYPE_GRAPH,ParseInit},
   {0}
};
int initJsonMach(){
add_symbols(json_names);
return EV_Done;
}
#include 
#include
#include
#include "./include/config.h"
#include "./include/mach.h"
#include "./include/g_types.h"
#include "./include/names.h"
#include "./include/cursors.h"

#undef DBG_CursorS
#ifndef DBG_CursorS
#define G_printf printf
#endif
//#define RDX(a) (*a)->rdx
#define MX(a,b,c) (*a)->mach->exec( (*a)->mach,b,c)
void list_cursors(PCursor  *list,char*);
// every cursor is an open subraph of its parent. 
// cursor map sqlson sub cursors in the database
int machEnd(Mach * mach);
int machStart(Mach * mach) ;
PCursor new_cursor_context() {
  PCursor p;
  //BC.new_cursor_count++;
  p= (PCursor) malloc(sizeof(Cursor));
  memset(p,0,sizeof(Cursor));
  return p;
}
PCursor free_cursor_context(PCursor  child) {
  PCursor parent=child->parent;
  //if(BC.del_cursor_count >= BC.new_cursor_count)
   // printf("Bad cursor",EV_Error);
  free((void *) child);
  //BC.del_cursor_count++;
  return parent;
} 

int count_cursor(PCursor cursor) {
  return(cursor->rdx.row );
}

PCursor dup_cursor(PCursor l1,PCursor l2) {
  memset(&l1->rdx,0,sizeof(RowSequence));
  l1->rdx.total = l2->rdx.total- l2->rdx.row;
  l1->rdx.offset = l2->rdx.offset + l2->rdx.row;
  l1->parent = l2;
  l1->rdx.row=0;
  l1->mach =  l2->mach;
  return l1;
}

Element node = {'_',0,{4,"Qson"}};
PCursor new_cursor(PCursor *list) {
  PCursor child,parent;
  if(!(*list)) {
    printf("First Parent \n");
    exit(1);
  } 
  parent = *list;
  child = new_cursor_context();
  dup_cursor(child,parent);
  *list=child;
  return child;
}
PCursor delete_cursor(PCursor *list) {
  PCursor child,parent;
  child = *list;
  if(!child) {
    printf("del no child\n");
    return 0;
  }
  parent = child->parent;
  (*list) = child->parent;
  if(child->parent) {
    child->parent->rdx.row += child->rdx.row;
  } else 
    machEnd(child->mach);
  free_cursor_context(child);
  return *list;
}


void close_update_cursor(PCursor *list) { 
  int status;
  Mach *mach =  (*list)->mach;
  status = mach->exec(mach,Update,0);
  delete_cursor(list);
}
int release_cursor_list(PCursor * inner) {
  if( inner) {
    while(*inner)
      *inner = delete_cursor(inner);
  }
  return 0;
}

int append_cursor(PCursor *list,Element *node) {
  int status=0;
  Mach *obj = (*list)->mach;
  status = obj->exec(obj,Append,node);
  return(status);
}


void list_cursors(PCursor  *list,char * arg){
  PCursor g;
  int i=0;
  g = *list;
  while(g) {
    G_printf("%s %d %x %x ",arg,i,g->parent); 
    G_printf(" %d %d %d\n",g->rdx.row,g->rdx.total,g->rdx.offset); 
    g=g->parent;i++;
  }
}

// Mach methods
int machName(char * name,void * init) {
Key k;
k.len=strlen(name);k.bytes = name;
add_key( k,G_TYPE_GRAPH, init);
return 0;
}

Cursor * new_mach_cursor(Mach *mach) {
  Cursor *cursor =  new_cursor_context();
  mach->cursors=cursor;
  cursor->mach = mach;
  return cursor;
}

int machEnd(Mach * mach) {
  if(mach->attributes & EV_Result)
    join.result= &mach->parent->cursors->mach->cursors;
  if(mach->attributes & EV_Left)
    join.left= &mach->parent->cursors->mach->cursors;
  if(mach->attributes & EV_Right)
    join.right= &mach->parent->cursors->mach->cursors;
  return EV_Done;
}
int machStart(Mach * mach) {
  if(mach->attributes & EV_Result ){
    if(join.result)
    mach->parent= (*join.result)->mach->cursors->mach;
    join.result= &mach->cursors;}
  if(mach->attributes & EV_Left){
      if(join.left)
    mach->parent= (*join.left)->mach->cursors->mach;
    join.left= &mach->cursors;}
  if(mach->attributes & EV_Right){
      if(join.right)
    mach->parent= (*join.right)->mach->cursors->mach;
    join.right= &mach->cursors;}
  return EV_Done;
}
//Buit in machs

#define NUMINSTALLED 8
static MachInit MachInitTable[NUMINSTALLED];
extern MachInit  SqlInit;
extern Mach * MemInit(Mach *);
extern MachInit ParseInit;
extern MachInit ConsoleInit;
extern MachInit NetInit;
extern MachInit JsonInit;
extern MachInit FileInit;
#undef ENTRY
#define ENTRY(a,b)  MachInitTable[a]=b
int initMemMach();
int initSqlMach();
int initJsonMach();
int initConsoleMach();
int machInitInstalled() {
  //ENTRY(Mach_Base,SqlInit); machName("base",SqlInit);initSqlMach();
  MachInitTable[Mach_Mem]=MemInit; 
  machName("mem",MemInit);
  initMemMach();
  //ENTRY(Mach_Parse,ParseInit); machName("parse",ParseInit);
 // ENTRY(Mach_Json,JsonInit); machName("json",JsonInit);initJsonMach();
 // ENTRY(Mach_Console,ConsoleInit); machName("console",ConsoleInit);initConsoleMach();
  //ENTRY(Mach_Net,NetInit); machName("net",NetInit);
  //ENTRY(Mach_File,FileInit); machName("file",FileInit);
  return 0;
}

Mach * machInit(Mach * mach) {
  if(mach)
    if(mach->subclass < NUMINSTALLED)
       return MachInitTable[mach->subclass](mach);
  return 0;
}
Cursors
#include 
#include
#include
#include "./include/config.h"
#include "./include/mach.h"
#include "./include/g_types.h"
#include "./include/names.h"
#include "./include/cursors.h"

#undef DBG_CursorS
#ifndef DBG_CursorS
#define G_printf printf
#endif
//#define RDX(a) (*a)->rdx
#define MX(a,b,c) (*a)->mach->exec( (*a)->mach,b,c)
void list_cursors(PCursor  *list,char*);
// every cursor is an open subraph of its parent. 
// cursor map sqlson sub cursors in the database
int machEnd(Mach * mach);
int machStart(Mach * mach) ;
PCursor new_cursor_context() {
  PCursor p;
  //BC.new_cursor_count++;
  p= (PCursor) malloc(sizeof(Cursor));
  memset(p,0,sizeof(Cursor));
  return p;
}
PCursor free_cursor_context(PCursor  child) {
  PCursor parent=child->parent;
  //if(BC.del_cursor_count >= BC.new_cursor_count)
   // printf("Bad cursor",EV_Error);
  free((void *) child);
  //BC.del_cursor_count++;
  return parent;
} 

int count_cursor(PCursor cursor) {
  return(cursor->rdx.row );
}

PCursor dup_cursor(PCursor l1,PCursor l2) {
  memset(&l1->rdx,0,sizeof(RowSequence));
  l1->rdx.total = l2->rdx.total- l2->rdx.row;
  l1->rdx.offset = l2->rdx.offset + l2->rdx.row;
  l1->parent = l2;
  l1->rdx.row=0;
  l1->mach =  l2->mach;
  return l1;
}

Element node = {'_',0,{4,"Qson"}};
PCursor new_cursor(PCursor *list) {
  PCursor child,parent;
  if(!(*list)) {
    printf("First Parent \n");
    exit(1);
  } 
  parent = *list;
  child = new_cursor_context();
  dup_cursor(child,parent);
  *list=child;
  return child;
}
PCursor delete_cursor(PCursor *list) {
  PCursor child,parent;
  child = *list;
  if(!child) {
    printf("del no child\n");
    return 0;
  }
  parent = child->parent;
  (*list) = child->parent;
  if(child->parent) {
    child->parent->rdx.row += child->rdx.row;
  } else 
    machEnd(child->mach);
  free_cursor_context(child);
  return *list;
}


void close_update_cursor(PCursor *list) { 
  int status;
  Mach *mach =  (*list)->mach;
  status = mach->exec(mach,Update,0);
  delete_cursor(list);
}
int release_cursor_list(PCursor * inner) {
  if( inner) {
    while(*inner)
      *inner = delete_cursor(inner);
  }
  return 0;
}

int append_cursor(PCursor *list,Element *node) {
  int status=0;
  Mach *obj = (*list)->mach;
  status = obj->exec(obj,Append,node);
  return(status);
}


void list_cursors(PCursor  *list,char * arg){
  PCursor g;
  int i=0;
  g = *list;
  while(g) {
    G_printf("%s %d %x %x ",arg,i,g->parent); 
    G_printf(" %d %d %d\n",g->rdx.row,g->rdx.total,g->rdx.offset); 
    g=g->parent;i++;
  }
}

// Mach methods
int machName(char * name,void * init) {
Key k;
k.len=strlen(name);k.bytes = name;
add_key( k,G_TYPE_GRAPH, init);
return 0;
}

Cursor * new_mach_cursor(Mach *mach) {
  Cursor *cursor =  new_cursor_context();
  mach->cursors=cursor;
  cursor->mach = mach;
  return cursor;
}

int machEnd(Mach * mach) {
  if(mach->attributes & EV_Result)
    join.result= &mach->parent->cursors->mach->cursors;
  if(mach->attributes & EV_Left)
    join.left= &mach->parent->cursors->mach->cursors;
  if(mach->attributes & EV_Right)
    join.right= &mach->parent->cursors->mach->cursors;
  return EV_Done;
}
int machStart(Mach * mach) {
  if(mach->attributes & EV_Result ){
    if(join.result)
    mach->parent= (*join.result)->mach->cursors->mach;
    join.result= &mach->cursors;}
  if(mach->attributes & EV_Left){
      if(join.left)
    mach->parent= (*join.left)->mach->cursors->mach;
    join.left= &mach->cursors;}
  if(mach->attributes & EV_Right){
      if(join.right)
    mach->parent= (*join.right)->mach->cursors->mach;
    join.right= &mach->cursors;}
  return EV_Done;
}
//Buit in machs

#define NUMINSTALLED 8
static MachInit MachInitTable[NUMINSTALLED];
extern MachInit  SqlInit;
extern Mach * MemInit(Mach *);
extern MachInit ParseInit;
extern MachInit ConsoleInit;
extern MachInit NetInit;
extern MachInit JsonInit;
extern MachInit FileInit;
#undef ENTRY
#define ENTRY(a,b)  MachInitTable[a]=b
int initMemMach();
int initSqlMach();
int initJsonMach();
int initConsoleMach();
int machInitInstalled() {
  //ENTRY(Mach_Base,SqlInit); machName("base",SqlInit);initSqlMach();
  MachInitTable[Mach_Mem]=MemInit; 
  machName("mem",MemInit);
  initMemMach();
  //ENTRY(Mach_Parse,ParseInit); machName("parse",ParseInit);
 // ENTRY(Mach_Json,JsonInit); machName("json",JsonInit);initJsonMach();
 // ENTRY(Mach_Console,ConsoleInit); machName("console",ConsoleInit);initConsoleMach();
  //ENTRY(Mach_Net,NetInit); machName("net",NetInit);
  //ENTRY(Mach_File,FileInit); machName("file",FileInit);
  return 0;
}

Mach * machInit(Mach * mach) {
  if(mach)
    if(mach->subclass < NUMINSTALLED)
       return MachInitTable[mach->subclass](mach);
  return 0;
}
Chrsors.h
/*! \ingroup  Cursor
 * New sub cursor within the curren cursor context.
 */
PCursor new_cursor(PCursor *);
PCursor delete_cursor(PCursor *);
/*! \ingroup  Cursor
 * Close and delete cursor, write the pointer value back into the table..
 */
void close_update_cursor(PCursor *);
/*! \ingroup  Cursor
 * Write the actualy key bytes,link and pointer to the table.
 */
int append_cursor(PCursor *,Element * );
int count_cursor(PCursor );
Cursor * new_mach_cursor(Mach *obj);




No comments: