Packed char symbol table

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int symbol_error(char * s) {
printf("%s\n",s);
exit(9);
}
enum { NOTFOUND=0,CONTINUE,EXIT,QUIT,SUCCESS,ERROR};
enum {more_tag,less_tag,equal_tag,pop_tag,error_tag,done_tag};
typedef int EntryType(int *, void**);
// Set up entry points on the Bus
EntryType * ExecCommand;
typedef char Packed[8];
enum { entry_type,namespace_type};
typedef union {
unsigned long l;
void * vp;
char * s;
EntryType *entry;
struct Sym * sym;
char txt[8];
} Val;

typedef struct Sym {
unsigned long key;
Val def;
int type;
struct Sym * less;
struct Sym * more;
struct Sym * parent;
Val symlink; // arbitrary use
} Sym;
typedef Sym* PSym;

PSym start;
int sym_count;
Sym * put_key(unsigned long v);
Sym * get_key(unsigned long v);
typedef int SymFun(PSym ,int );
// One table op at a time and we keep the search termhere
unsigned long key_search; 
PSym key_sym;
PSym namespace=0;
PSym add_key(unsigned long key,PSym parent) {
PSym new =  calloc(1,sizeof(Sym));
key_sym=new;
new->key=key;
new->parent=parent;
sym_count++;
return(new);
}
void link_key(PSym link) {
PSym parent=link->parent;
PSym new;
new= add_key(key_search,parent);
link->parent=new;
if(parent->less == link) {
new->less=link;
parent->less=new;
}
else if(parent->more ==  link )  {
new->more=link;
parent->more=new;
}
else symbol_error("Link error\n");
}
void unlink_key(PSym link) {
PSym parent = link->parent;
if(parent->less == link)
parent->less = link->less;
else if(parent->more == link)
parent->more = link->more;
else symbol_error("Unlink bad");
sym_count--;
free(link);
}
int new_fun(PSym p, int tag) {
//signed long temp;
if(tag == done_tag) return(tag); // already found
if(!p)  { // first symbol check
start = add_key(key_search,0);
return(done_tag);
} else if(key_search < p->key) {// less branch?
if(!p->less) {
p->less = add_key(key_search,p);
return(done_tag);
} else if(key_search > p->less->key) {
if(p->less->parent != p) symbol_error("Par l");
link_key(p->less);
return(done_tag);
}
return(less_tag);
} else if(key_search > p->key) { // Same as less branch
if(!p->more) {
p->more = add_key(key_search,p);
return(done_tag);
} else if(key_search < p->more->key) {
//temp = key_search - p->more->key;
if(p->more->parent != p) symbol_error("Par m");
link_key(p->more);
return(done_tag);
}
return(more_tag);
} else {
printf("Dup\n");
key_sym=p;
return(done_tag);
}
return(symbol_error("error exit\n"));
}

int find_fun(PSym p, int tag) {
if(tag == done_tag) return(tag); // already found
if(!p) 
return(done_tag);
else if(key_search < p->key) {// less branch?
if(!p->less || (key_search > p->less->key))
return(done_tag);
else
return(less_tag);
} else if(key_search > p->key) { // Same as less branch
if(!p->more || (key_search < p->more->key))
return(done_tag);
else
return(more_tag);
} else {
key_sym=p;  //printf("Find %s %s\n",p->key.txt, key_search.txt);
return(done_tag);
}
return(symbol_error("error exit\n"));
}
void print_sym(PSym);
int list_fun(PSym p, int tag) {
print_sym(p);
if(p->less) return(less_tag);
if(p->more) return(more_tag);
return(done_tag);
}
// Traverse symbol table, execute action
int  act_on_syms(PSym s, int tag,SymFun *fun) {             
if(!fun) symbol_error("No action");
tag = fun(s,tag);  // Take action on each node
if(tag == more_tag)
tag = act_on_syms(s->more,tag,fun);
if(tag == less_tag )
tag = act_on_syms(s->less,tag,fun);
return(tag);
}
Sym *put_key(unsigned long v) {
int status= pop_tag;
key_search=v;
act_on_syms(start,status,new_fun);
return(key_sym);
}

Sym * get_key(unsigned long v) {
int status=pop_tag;
key_search=v;
key_sym=0;
act_on_syms(start,status,find_fun);
return(key_sym);
}
void del_key(unsigned long v) {
int status=pop_tag;
key_search=v;
act_on_syms(start,status,find_fun);
}
unsigned long pack_text(char* arg) {
Val v;
v.l=0;
int i = strlen(arg);
if(i > 8) i=8;
// backwards ord, needs fixing
strncpy(v.txt,arg, i);
return(v.l);
}

void print_tag(int tag){
char * str = ( (more_tag==tag ) ? "More " :
( (less_tag == tag) ? "Less " : "None ") );
printf("%s",str);
}
void print8(unsigned long l) {
int i,j;
Val v;
v.l=l;
i= strlen(v.txt);
if(i > 8) i=8;
printf(":");
for(j=0;j < i;j++)
printf("%c",v.txt[j]);
while(i < 8) {
printf(".");i++;
}
}
void print_sym(PSym p) {
print8(p->key);
print8(p->def.l);
printf("\n");
}

int list_keys(PSym p) {
print_sym(p);
if(p->less) list_keys(p->less);
if(p->more) list_keys(p->more);
return(SUCCESS);
}

int GetKey(int * argc, void * args[]){
PSym p = get_key((unsigned long) args[*argc+1]);
args[*argc+2]= p->def.vp;
*argc +=3; // Include space for return value 
return(SUCCESS);
}
int PutKey(int * argc, void * args[]){
PSym p = put_key( (unsigned long) args[*argc+1]);
p->def.vp = args[*argc+2];
*argc +=3; // Include space for return value 
return(SUCCESS);
}

int ListKeys(int * argc, void * args[]){
return(list_keys(start));
}
// linuc string commandis tokenized
int ExecStr(int * argc, void * args[]) {
char src[40];
int base = *argc;
strcpy(src,args[base+1]);  // make local copy
args[base]="Tokenize";
args[base+1]=src;
ExecCommand(argc,args);
*argc=base;
return(ExecCommand(argc,args));
}
#ifdef LINKED
#define Entry _Entry
#endif
int Init(int * argc, void * args[]);
#define m(a) {#a,a}
struct {
char * str;
EntryType * entry;
} key_terms[] =
{
m(ListKeys),m(GetKey),m(PutKey),m(ExecStr)
//m(GetNamed),m(PutNamed),m(Using)
};
const int Nterms = sizeof( key_terms)/(sizeof(long)*2);
int init_key_terms() {
int i=0;
Val v;
PSym s;
while(i < Nterms) {
v.l= pack_text(key_terms[i].str);
s = put_key(v.l);
s->def.entry=  key_terms[i].entry;
s->type=entry_type;
i++;
}
return(SUCCESS);
}


int Entry(int *argc, void * args[]) {
if(strcmp("Init",args[*argc])) {
ExecCommand = (EntryType * ) args[*argc+1];
return(init_key_terms());
}
PSym p = get_key((unsigned long) args[*argc+1]);
if(!p) return(NOTFOUND);
if(p->type != entry_type) return(NOTFOUND);
*argc+=1;
return(p->def.entry(argc,args));
}

#ifdef TEST
char * tc = "auavwxayzfghiajklmnopqarstuvwopqaryzbcdbcdestuvwxyzfghijklmnopqrstuopqarxyzbcdes";
int main(void) {
int i,k;
PSym p;
PSym q;
Val  key;
Val def;
key.l= pack_text("Hello");
init_key_terms();
print_tag(more_tag);
print_tag(less_tag);
print_tag(pop_tag);
printf("\n");
sym_count=0;
for (i=0;i < 18;i++) {
k = rand() % 50;
key.l=0;def.l=0;
sprintf(key.txt,"%d%c%c%c",k,tc[k],tc[k+3],tc[k+2]);
sprintf(def.txt,"%c%d",tc[i],i);
p=put_key(key.l);
p->def=def;
q= get_key(key.l);
if(q !=p)
printf("Err %s %s \n",(char *) &q->key,(char *) &p->key);
p=q;
//if(p) print_sym(p); else printf("Not found\n");
}
printf("\nList %d\n",sym_count);
list_keys(start);
return(0);
}
/*
* under test, may be removed
int Using(int * argc, void * args[]) {
PSym p = get_key((Val) args[*argc]);
if(!p || (p->type != namespace_type)) return(NOTFOUND);
namespace=p->def.sym;
*argc +=1;
return(SUCCESS);
}
int GetNamed(int * argc, void * args[]){
if(Using(argc,args) != SUCCESS)
return(NOTFOUND);
return(GetKey(argc,args));
};
int PutNamed(int * argc, void * args[]){
if(Using(argc,args) != SUCCESS)
return(NOTFOUND);
return(PutKey(argc,args));
}
* */
#endif


No comments: