--- stack/stack.c 2002/01/31 19:51:12 1.14 +++ stack/stack.c 2002/02/02 14:50:44 1.19 @@ -6,27 +6,38 @@ #include /* dlopen, dlsym, dlerror */ #include +/* assert */ +#include #define HASHTBLSIZE 65536 typedef struct stack_item { - enum {value, string, ref, func, symbol, list} type; + enum { + value, /* Integer */ + string, + ref, /* Reference (to an element in the + hash table) */ + func, /* Function pointer */ + symbol, + list + } type; /* Type of stack element */ + union { - void* ptr; - int val; - } content; + void* ptr; /* Pointer to the content */ + int val; /* ...or an integer */ + } content; /* Stores a pointer or an integer */ - char* id; - struct stack_item* next; + char* id; /* Symbol name */ + struct stack_item* next; /* Next element */ } stackitem; -typedef stackitem* hashtbl[HASHTBLSIZE]; -typedef void (*funcp)(stackitem**); - +typedef stackitem* hashtbl[HASHTBLSIZE]; /* Hash table declaration */ +typedef void (*funcp)(stackitem**); /* funcp is a pointer to a + void function (stackitem **) */ -/* Initiates a newly created hash table. */ +/* Initialize a newly created hash table. */ void init_hashtbl(hashtbl out_hash) { long i; @@ -40,10 +51,10 @@ { long i= 0; unsigned long out_hash= 0; - char key= 0; + char key= '\0'; stackitem** position; - while(1){ + while(1){ /* Hash in_string */ key= in_string[i++]; if(key=='\0') break; @@ -53,15 +64,17 @@ out_hash= out_hash%HASHTBLSIZE; position= &(in_hashtbl[out_hash]); - while(1){ - if(*position==NULL) + while(position != NULL){ + if(*position==NULL) /* If empty */ return position; - if(strcmp(in_string, (*position)->id)==0) + if(strcmp(in_string, (*position)->id)==0) /* If match */ return position; - position= &((*position)->next); + position= &((*position)->next); /* Try next */ } + return NULL; /* end of list reached without finding + an empty position */ } /* Generic push function. */ @@ -76,6 +89,7 @@ int push_val(stackitem** stack_head, int in_val) { stackitem* new_item= malloc(sizeof(stackitem)); + assert(new_item != NULL); new_item->content.val= in_val; new_item->type= value; @@ -106,7 +120,7 @@ return 1; } -/* Define a function a new function in the hash table. */ +/* Define a new function in the hash table. */ void def_func(hashtbl in_hashtbl, funcp in_func, const char* id) { stackitem* temp= malloc(sizeof(stackitem)); @@ -123,7 +137,6 @@ stackitem* temp= malloc(sizeof(stackitem)); temp->type= symbol; - mk_hashentry(in_hashtbl, temp, id); } @@ -137,17 +150,17 @@ new_item->content.ptr= *hash(in_hash, in_string); new_item->type= ref; - if(new_item->content.ptr==NULL) { - if(handle==NULL) + if(new_item->content.ptr==NULL) { /* If hash entry empty */ + if(handle==NULL) /* If no handle */ handle= dlopen(NULL, RTLD_LAZY); - symbol= dlsym(handle, in_string); - if(dlerror()==NULL) - def_func(in_hash, symbol, in_string); + symbol= dlsym(handle, in_string); /* Get function pointer */ + if(dlerror()==NULL) /* If existing function pointer */ + def_func(in_hash, symbol, in_string); /* Store function pointer */ else - def_sym(in_hash, in_string); + def_sym(in_hash, in_string); /* Make symbol */ - new_item->content.ptr= *hash(in_hash, in_string); + new_item->content.ptr= *hash(in_hash, in_string); /* XXX */ new_item->type= ref; } @@ -155,13 +168,19 @@ return 1; } +void printerr(const char* in_string) { + fprintf(stderr, "Err: %s\n", in_string); +} + /* Discard the top element of the stack. */ extern void toss(stackitem** stack_head) { stackitem* temp= *stack_head; - if((*stack_head)==NULL) + if((*stack_head)==NULL) { + printerr("Stack empty"); return; + } if((*stack_head)->type==string) free((*stack_head)->content.ptr); @@ -179,8 +198,10 @@ /* Prints the top element of the stack. */ void print_(stackitem** stack_head) { - if((*stack_head)==NULL) + if((*stack_head)==NULL) { + printerr("Stack empty"); return; + } switch((*stack_head)->type) { case value: @@ -223,61 +244,29 @@ if(*stack_head != NULL) { print_st(*stack_head, 1); printf("\n"); + } else { + printerr("Stack empty"); } } /* If the top element is a reference, determine if it's a reference to a - function, and if it is execute and pop the reference and execute the - function. */ + function, and if it is, toss the reference and execute the function. */ extern void eval(stackitem** stack_head) { funcp in_func; - if((*stack_head)==NULL || (*stack_head)->type!=ref) + if((*stack_head)==NULL || (*stack_head)->type!=ref) { + printerr("Stack empty or not a reference"); return; + } if(((stackitem*)(*stack_head)->content.ptr)->type==func) { in_func= (funcp)((stackitem*)(*stack_head)->content.ptr)->content.ptr; toss(stack_head); (*in_func)(stack_head); return; - } -} - -/* Parse input. */ -int stack_read(stackitem** stack_head, hashtbl in_hash, char* in_line) -{ - char *temp, *rest; - int itemp; - size_t inlength= strlen(in_line)+1; - int convert= 0; - - temp= malloc(inlength); - rest= malloc(inlength); - - if((convert= sscanf(in_line, "\"%[^\"\n\r]\" %[^\n\r]", temp, rest)) >= 1) - push_cstring(stack_head, temp); - else if((convert= sscanf(in_line, "%d %[^\n\r]", &itemp, rest)) >= 1) - push_val(stack_head, itemp); - else if((convert= sscanf(in_line, "\\%c%[^\n\r]", temp, rest)) >= 1) { - temp[1]= '\0'; push_ref(stack_head, in_hash, temp); - } else if((convert= sscanf(in_line, "%[^ ;\n\r]%[^\n\r]", temp, rest)) >= 1) - push_ref(stack_head, in_hash, temp); - else if((convert= sscanf(in_line, "%c%[^\n\r]", temp, rest)) >= 1) - if(*temp==';') - eval(stack_head); - - free(temp); - - if(convert<2) { - free(rest); - return 0; - } - - stack_read(stack_head, in_hash, rest); - - free(rest); - return 1; + } else + printerr("Not a function"); } /* Make a list. */ @@ -286,17 +275,21 @@ void* delimiter; stackitem *iterator, *temp, *pack; - if((*stack_head)==NULL) + if((*stack_head)==NULL) { + printerr("Stack empty"); return; + } - delimiter= (*stack_head)->content.ptr; + delimiter= (*stack_head)->content.ptr; /* Get delimiter */ toss(stack_head); iterator= *stack_head; + /* Search for first delimiter */ while(iterator->next!=NULL && iterator->next->content.ptr!=delimiter) iterator= iterator->next; + /* Extract list */ temp= *stack_head; *stack_head= iterator->next; iterator->next= NULL; @@ -304,6 +297,7 @@ if(*stack_head!=NULL && (*stack_head)->content.ptr==delimiter) toss(stack_head); + /* Push list */ pack= malloc(sizeof(stackitem)); pack->type= list; pack->content.ptr= temp; @@ -311,22 +305,90 @@ push(stack_head, pack); } -/* Push elements of the list on the stack. */ +/* Parse input. */ +int stack_read(stackitem** stack_head, hashtbl in_hash, char* in_line) +{ + char *temp, *rest; + int itemp; + size_t inlength= strlen(in_line)+1; + int convert= 0; + + temp= malloc(inlength); + rest= malloc(inlength); + + do { + /* If string */ + if((convert= sscanf(in_line, "\"%[^\"\n\r]\" %[^\n\r]", temp, rest))) { + push_cstring(stack_head, temp); + break; + } + /* If value */ + if((convert= sscanf(in_line, "%d %[^\n\r]", &itemp, rest))) { + push_val(stack_head, itemp); + break; + } + /* Escape ';' with '\' */ + if((convert= sscanf(in_line, "\\%c%[^\n\r]", temp, rest))) { + temp[1]= '\0'; + push_ref(stack_head, in_hash, temp); + break; + } + /* If symbol */ + if((convert= sscanf(in_line, "%[^] ;\n\r]%[^\n\r]", temp, rest))) { + push_ref(stack_head, in_hash, temp); + break; + } + /* If single char */ + if((convert= sscanf(in_line, "%c%[^\n\r]", temp, rest))) { + if(*temp==';') { + eval(stack_head); /* Evaluate top element */ + break; + } + + if(*temp==']') { + push_ref(stack_head, in_hash, "["); + pack(stack_head); + break; + } + } + } while(0); + + + free(temp); + + if(convert<2) { + free(rest); + return 0; + } + + stack_read(stack_head, in_hash, rest); + + free(rest); + return 1; +} + +/* Relocate elements of the list on the stack. */ extern void expand(stackitem** stack_head) { stackitem *temp, *new_head; - if((*stack_head)==NULL || (*stack_head)->type!=list) + /* Is top element a list? */ + if((*stack_head)==NULL || (*stack_head)->type!=list) { + printerr("Stack empty or not a list"); return; + } + /* The first list element is the new stack head */ new_head= temp= (*stack_head)->content.ptr; toss(stack_head); + /* Search the end of the list */ while(temp->next!=NULL) temp= temp->next; + /* Connect the the tail of the list with the old stack head */ temp->next= *stack_head; - *stack_head= new_head; + *stack_head= new_head; /* ...and voila! */ } /* Swap the two top elements on the stack. */ @@ -334,7 +396,12 @@ { stackitem* temp= (*stack_head); - if((*stack_head)==NULL || (*stack_head)->next==NULL) + if((*stack_head)==NULL) { + printerr("Stack empty"); + return; + } + + if((*stack_head)->next==NULL) return; *stack_head= (*stack_head)->next; @@ -348,8 +415,10 @@ void *left, *right; int result; - if((*stack_head)==NULL || (*stack_head)->next==NULL) + if((*stack_head)==NULL || (*stack_head)->next==NULL) { + printerr("Not enough elements to compare"); return; + } left= (*stack_head)->content.ptr; swap(stack_head); @@ -365,8 +434,10 @@ { int value; - if((*stack_head)==NULL) + if((*stack_head)==NULL || (*stack_head)->type!=value) { + printerr("Stack empty or element is not a value"); return; + } value= (*stack_head)->content.val; toss(stack_head); @@ -387,8 +458,10 @@ stackitem *temp, *value; if(*stack_head==NULL || (*stack_head)->next==NULL - || (*stack_head)->type!=ref) + || (*stack_head)->type!=ref) { + printerr("Define what?"); return; + } temp= (*stack_head)->content.ptr; value= (*stack_head)->next;