Executive cursor manager

/////////////////////
///  Command executive and slot code
//////////////////////////////


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "cursor.h"


//
//
// definitions:
// the stack is a linear array of cursor pointers with a status
//  an Instance is a group of three adjacent cursors engaged in join
// devices are the attachments and their call back
//
//
#define SELF ((PCursor) self)
enum {SUCCESS=0,QUIT,CONTINUE,STEP,DEBUG,Bad};
// Manage set of  cursor triplets waiting join service
//
// join cycles through the cursor stack  working in round robin fashion
// convolutions that oush repolace their entry into the stack 
// until they break
//
#define MAX 9    //Maximum number of pending join instances
struct Stack { PCursor cursor; int status;} stack[MAX];
int InitJoin(void) {
 memset(stack,0,sizeof(stack));
 return(0);
}
void ReplaceCursor(PCursor m) {
 stack[m->index].cursor = m;
}

void InsertCursor(PCursor l,int index){
 l->index = index;
 ReplaceCursor(l);
 }
int AddInstance(PCursor l,PCursor r,PCursor o)
{ int i;

char *p;
 i=0;
 while(( (i+2) < MAX) && stack[i].cursor) {i=i+3;}
 if( !stack[i].cursor) {
  if(l) InsertCursor( l,i);
     i++;
  if(r) InsertCursor(r,i);
  i++;
  if(o)  InsertCursor(o,i);
    } else
         printf("\nStack is full!!");
 return(i);
}

// remove an Instance

void RemoveInstance(PCursor self) {
 int index= SELF->index;
    index = index - (index % 3);
 stack[index].cursor = 0;
 stack[index+1].cursor = 0;
 stack[index+2].cursor = 0;
    }

// round robin access
//
int index_stack=0;

int NextInstance(PCursor *l, PCursor *r,PCursor *o)
{
 // There will be a master process
 // that can mnipulate the stack
  *l = stack[index_stack].cursor;
  *r = stack[index_stack+1].cursor;
  *o = stack[index_stack+2].cursor;
  index_stack= index_stack+3;
  if(index_stack == MAX) 
   index_stack = 0;
 return(Null);
}

int CurrentInstance(PCursor *l, PCursor *r,PCursor *o){
 int i = index_stack-3;
 if(i < 0) i = MAX-3;
 *l = stack[i].cursor;
 *r = stack[+1].cursor;
 *o = stack[+2].cursor;
 return(0);
}
typedef int Entry(int*,char **);
typedef struct{
 Entry *entry;
 char  name[8];
}CallBack;
int callback_index=0;
// alow for 16 attachments
CallBack devices[16];

int id_from_name(char* name) {
 int i=0;
 while((i < callback_index) && strcmp(devices[i].name,name)) 
  i++;
 if(i == callback_index) return (-1);
 else return(i);
}

char* name_from_id(int id) {
 if(id < callback_index) return(devices[id].name); 
 else  return (0);
}
// Microsoft stole GetCursor
PCursor FetchCursor(int index) {
  if(index < MAX)
   return(stack[index].cursor);
  else
   return(0);
} 

void ListCursor(int i) {
 PCursor self= stack[i].cursor;
 printf("Name: %s Status: %d Slot %d\n",
 devices[self->type].name,stack[i].status,i);
}
void ListDevices(void) {
 int i;
 for(i=0;i < callback_index; i++) 
  printf("Name %s Entry%x\n",
  devices[i].name,devices[i].entry);

}
void ListStack(void) {
 int i,type;
 PCursor p;
 printf("Index Name    Mode Current Typeid\n");
 for(i=0;i < MAX;i++) ListCursor(i);
}
void StartJoin(void) {
 PCursor l,r,o;
 int i =0;
 do {NextInstance(&l,&r,&o);i++;
  } while((l==0) && (i < MAX/3));
 join_cursor(l,r,o);
 l->mode = Pause;
 printf("Join complete\n");
}


//  Handle match modes
static struct { int mode; char* name;} Modifier[]=  {
 {Match_All,"all"},{Match_Once,"once"}, 
 {Match_Some,"some"}, {Debug,"debug"} };


void SetMode(int index, int mode){
 if((index < MAX) && stack[index].cursor)
  stack[index].cursor->mode=mode; 
}
int mode_from_name(char* mode) {
  int i=0;
  while((i < 4) && 
   strcmp(Modifier[i].name,mode) ) i++; 
  if(i < 4) return(Modifier[i].mode);
  else return(0);
}
char* name_from_mode(int mode) {
  int i=0;
  while((i < 4) && 
   Modifier[i].mode !=mode ) i++; 
  if(i < 4) return(Modifier[i].name);
  else return("None");
}
int dup_slot(int src,int dest) {
 
 if(src < MAX && dest < MAX) {
  stack[dest].cursor = dup_cursor(stack[src].cursor);
  return(0);
 } else return(1);
}


// set up a new graph
// The device will createandinitialize the cursor
int SetCurse(int* argc,char* args[]) {
 char *name;
 int slot;
 int id;
 PCursor self;
 FILE * f;
 name=args[1];
 slot=atoi(args[2]);
 if((id = id_from_name(name)) >= 0) {
  devices[id].entry(argc,args);
  self = (PCursor) args[3];
  if(!self) return(Bad);
  self->type = id;
  InsertCursor(self,slot);
  printf("New Cursor %s ID: %d Slot: %d\n",name,self->type,slot);
 }
 return(0);
}


void PrintBuffer(int  * argc,char * args[]);
void SaveMem(char * filename);
void PrintHelp(void);
int ExecShellCommand(int* argc,char * args[]){
 char *filename;
 char *cmd;
 int cursor_index;
 char ch;
 int i,j;
 printf("Exec\n");
 if(*args[0] == '#')  return(1);// skip comment
 cmd=args[1];
 if( !strcmp(cmd,"quit")) 
  return(QUIT);
 if( !strcmp(cmd,"continue")) 
  return(CONTINUE);
 if( !strcmp(cmd,"debug")) 
  return(DEBUG);
 else if(!strcmp(cmd,"StartJoin")) 
  StartJoin();
 else if(!strcmp(cmd,"InitJoin")) 
  InitJoin();

 else if(!strcmp(cmd, "SetCurse")) 
  return(SetCurse(argc,args));
 else if(!strcmp(cmd, "DupSlot")) {
  i= atoi(args[2]);
  j = atoi(args[3]);
  dup_slot(i,j);
 }
 else  if(!strcmp(cmd,"ListDevices"))
  ListDevices();
 else if( !strcmp(cmd, "ListStack"))
  ListStack();
 else if(!strcmp(cmd,"ListCursor")){
  i = atoi(args[2]); 
  ListCursor(i);
  }
 else if(!strcmp(cmd,"SetMode")) {
  i=atoi(args[2]);
  SetMode(i,mode_from_name(args[2]));
  }
 else if(!strcmp(cmd,"help"))
  PrintHelp(); 
 else { // go through the attachment list
  i=0;
  while(devices[i].entry) {
   if(devices[i].entry(argc,args) == SUCCESS) 
    break;
   }
  }
 return(SUCCESS);
} 

char * ops[] = {"Null","End","Done","Pause","Break","Match","Push","Singleton"};
char *status_str(int s){
 return(ops[s]);
}

void print_status(int l, int r){
 printf("%s %s  ",status_str(l),status_str(r));}
void PrintKeys(void) {
  int i;
 char *p;
 PCursor l,r,o;
 CurrentInstance(&l,&r,&o);
 if(!l) return;
 p = l->element.key;
 printf("[%s%c]",l->element.key,l->element.op);
 printf(" %d ",r->mode);
 printf("[%s%c]",r->element.key,r->element.op);
 printf(" %d ",r->mode);
 printf("[%s%c]",o->element.key,o->element.op);
 printf(" %d ",o->mode);
 printf("\n");
 }

// Device specific print slot buffer
void PrintBuffer(int * argc,char * args[]) {
 int index;
 char * buf;
 char mode[10];
 int id;
 PCursor self;
 self= (void *)  FetchCursor(atoi(args[1]));
 if(self) {
  id = self->type;
  devices[id].entry(argc,args);  // just pass it on
  }
 }

#define MAXBUF 10000
// Generic routine to fill a text base
// upon which join operates. 
// The text base  is attached to a cursor
// Identified by slot
// both plain text, lazyj and someimes html scraper use this
int GetCursorFile(int *argc, char* args[]) {

 PCursor self;
 FILE *fin;
 int size,i;
 char *p;
 if(!*args) return(1);
 self= (void *)  FetchCursor(atoi(args[1]));
 char * file = args[1];
 if(!args[2]) size = MAXBUF;
 else size = atoi(args[2]); 
 if(size==0) size = MAXBUF;
 self->current=malloc(size);
 p=self->current;
 fin = fopen(file,"rb");
 if(!fin) {
  printf("No file\n");
  return(1);
 }
 i = fread(self->current,1,size-1,fin);
 p[i]=0; //terminate
 printf("Read %d from file %s type %d index %d\n",i,file,self->type,self->index);
 //printf("First 20 read %20s\n",self->current);
 return(0);
}
// Help string
char * helpstr = 
 "ListStack - List cursor stack\n" 
 "types - List cursor types\n"
 "set TYPE index arguments - Make cursor of type TYPE\n"
 "for the index.  Arguments are:\n"
 "    set MEM index keysize nodecount\n"
 "    set CONSOLE index\n" // stdio
 "    set CONSOLE index filename\n"  
 "    set LAZYJ index filename maxsize\n"
 "    set TEXT index filename maxsize\n"
 "cursor index - List cursor by index\n\n"
 "dup src dest = Duplicate one slot with copy from another\n"
 "join - Start join\n"
 "init - Initialize tee stack\n"
 "mode index mode - Set match modifier for slot index\n"
 "file filename - Execute commnds from file\n"
 "mem index - Print contents of MEM for index\n"
 "Three console exits:\n" 
 "   quit - Exit the system \n"
 "   debug - Run debugger loop\n"
 "   continue - Run console loop\n"
  " save filename - Save the MEM to disk\n";
void PrintHelp(void) {
   printf("%s",helpstr);
  }


void InitJson(void);
void InitText(void);
void InitMem(void);
void InitConsole(void);
// the order of initialization on built in 
//   devices  sets device id
void InitSystem(void) {
 InitJson();
 InitMem(); // includes 2 indexing devices on memory
 InitConsole();
 InitText(); 
}

int LoadDll(int * argc, char * args[]) {  
 if(!args[1]) 
  InitSystem(); // Initial set up
 else {
  int i= callback_index;
  devices[i].entry=(Entry *) args[1];
  devices[i].entry(argc,args); // pass it on
  strcpy(devices[i].name,args[2]);
  callback_index++;
 }
  return(0);
}

No comments: