--- stack/stack.c 2002/01/08 18:58:27 1.12 +++ stack/stack.c 2002/01/31 22:32:59 1.16 @@ -11,20 +11,30 @@ 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; /* Tells what kind 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**); /* Function pointer declaration */ + +/* Initiates a newly created hash table. */ void init_hashtbl(hashtbl out_hash) { long i; @@ -33,6 +43,7 @@ out_hash[i]= NULL; } +/* Returns a pointer to an element in the hash table. */ stackitem** hash(hashtbl in_hashtbl, const char* in_string) { long i= 0; @@ -40,7 +51,7 @@ char key= 0; stackitem** position; - while(1){ + while(1){ /* Hash in_string */ key= in_string[i++]; if(key=='\0') break; @@ -50,18 +61,18 @@ out_hash= out_hash%HASHTBLSIZE; position= &(in_hashtbl[out_hash]); - while(1){ + while(1){ /* Return position if empty */ if(*position==NULL) return position; - if(strcmp(in_string, (*position)->id)==0) + if(strcmp(in_string, (*position)->id)==0) /* Return position if match */ return position; - position= &((*position)->next); + position= &((*position)->next); /* Try next */ } } - +/* Generic push function. */ int push(stackitem** stack_head, stackitem* in_item) { in_item->next= *stack_head; @@ -69,6 +80,7 @@ return 1; } +/* Push a value on the stack. */ int push_val(stackitem** stack_head, int in_val) { stackitem* new_item= malloc(sizeof(stackitem)); @@ -79,6 +91,7 @@ return 1; } +/* Copy a string onto the stack. */ int push_cstring(stackitem** stack_head, const char* in_string) { stackitem* new_item= malloc(sizeof(stackitem)); @@ -90,6 +103,7 @@ return 1; } +/* Create a new hash entry. */ int mk_hashentry(hashtbl in_hashtbl, stackitem* in_item, const char* id) { in_item->id= malloc(strlen(id)+1); @@ -100,6 +114,7 @@ return 1; } +/* Define a function a new function in the hash table. */ void def_func(hashtbl in_hashtbl, funcp in_func, const char* id) { stackitem* temp= malloc(sizeof(stackitem)); @@ -110,15 +125,16 @@ mk_hashentry(in_hashtbl, temp, id); } +/* Define a new symbol in the hash table. */ void def_sym(hashtbl in_hashtbl, const char* id) { stackitem* temp= malloc(sizeof(stackitem)); temp->type= symbol; - mk_hashentry(in_hashtbl, temp, id); } +/* Push a reference to an entry in the hash table onto the stack. */ int push_ref(stackitem** stack_head, hashtbl in_hash, const char* in_string) { static void* handle= NULL; @@ -128,17 +144,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; } @@ -146,6 +162,7 @@ return 1; } +/* Discard the top element of the stack. */ extern void toss(stackitem** stack_head) { stackitem* temp= *stack_head; @@ -160,11 +177,13 @@ free(temp); } +/* Print newline. */ extern void nl() { printf("\n"); } +/* Prints the top element of the stack. */ void print_(stackitem** stack_head) { if((*stack_head)==NULL) @@ -187,13 +206,14 @@ } } +/* Prints the top element of the stack and then discards it. */ extern void print(stackitem** stack_head) { print_(stack_head); toss(stack_head); } -/* print_stack(stack); */ +/* Only to be called by function printstack. */ void print_st(stackitem* stack_head, long counter) { if(stack_head->next != NULL) @@ -204,6 +224,7 @@ nl(); } +/* Prints the stack. */ extern void printstack(stackitem** stack_head) { if(*stack_head != NULL) { @@ -212,7 +233,8 @@ } } - +/* If the top element is a reference, determine if it's a reference to a + function, and if it is, toss the reference and execute the function. */ extern void eval(stackitem** stack_head) { funcp in_func; @@ -228,6 +250,7 @@ } } +/* Parse input. */ int stack_read(stackitem** stack_head, hashtbl in_hash, char* in_line) { char *temp, *rest; @@ -238,15 +261,35 @@ 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, "%[^ ;\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); + 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 ';' */ + if((convert= sscanf(in_line, "%c%[^\n\r]", temp, rest)) && *temp==';') { + eval(stack_head); /* Evaluate top element */ + break; + } + } while(0); + free(temp); @@ -261,22 +304,25 @@ return 1; } +/* Make a list. */ extern void pack(stackitem** stack_head) { void* delimiter; stackitem *iterator, *temp, *pack; - if((*stack_head)==NULL) + if((*stack_head)==NULL) /* No delimiter */ 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; @@ -284,6 +330,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; @@ -291,23 +338,29 @@ push(stack_head, pack); } +/* Relocate elements of the list on the stack. */ extern void expand(stackitem** stack_head) { stackitem *temp, *new_head; + /* Is top element a list? */ if((*stack_head)==NULL || (*stack_head)->type!=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. */ extern void swap(stackitem** stack_head) { stackitem* temp= (*stack_head); @@ -320,6 +373,7 @@ (*stack_head)->next= temp; } +/* Compares two elements by reference. */ extern void eq(stackitem** stack_head) { void *left, *right; @@ -337,11 +391,12 @@ push_val(stack_head, (left==right)); } +/* Negates the top element on the stack. */ extern void not(stackitem** stack_head) { int value; - if((*stack_head)==NULL) + if((*stack_head)==NULL || (*stack_head)->type!=value) return; value= (*stack_head)->content.val; @@ -349,12 +404,15 @@ push_val(stack_head, !value); } +/* Compares the two top elements on the stack and return 0 if they're the + same. */ extern void neq(stackitem** stack_head) { eq(stack_head); not(stack_head); } +/* Give a symbol some content. */ extern void def(stackitem** stack_head) { stackitem *temp, *value; @@ -372,6 +430,7 @@ toss(stack_head); toss(stack_head); } +/* Quit stack. */ extern void quit() { exit(EXIT_SUCCESS);