--- stack/stack.c 2002/02/01 23:30:55 1.18 +++ stack/stack.c 2002/02/02 22:22:04 1.27 @@ -46,7 +46,7 @@ out_hash[i]= NULL; } -/* Returns a pointer to an element in the hash table. */ +/* Returns a pointer to a pointer to an element in the hash table. */ stackitem** hash(hashtbl in_hashtbl, const char* in_string) { long i= 0; @@ -64,7 +64,7 @@ out_hash= out_hash%HASHTBLSIZE; position= &(in_hashtbl[out_hash]); - while(position != NULL){ + while(1){ if(*position==NULL) /* If empty */ return position; @@ -73,8 +73,6 @@ position= &((*position)->next); /* Try next */ } - return NULL; /* end of list reached without finding - an empty position */ } /* Generic push function. */ @@ -160,7 +158,9 @@ else def_sym(in_hash, in_string); /* Make symbol */ - new_item->content.ptr= *hash(in_hash, in_string); /* XXX */ + new_item->content.ptr= *hash(in_hash, in_string); /* The new reference + shouldn't point at + NULL */ new_item->type= ref; } @@ -196,26 +196,37 @@ } /* Prints the top element of the stack. */ -void print_(stackitem** stack_head) +extern void print_(stackitem** stack_head) { - if((*stack_head)==NULL) { + stackitem* temp= *stack_head; + + if(temp==NULL) { printerr("Stack empty"); return; } - switch((*stack_head)->type) { + while(temp->type==ref) { + temp= temp->content.ptr; + + if(temp->type!=ref) { + printf("ref-> %s", temp->id); + return; + } + } + + switch(temp->type) { case value: - printf("%d", (*stack_head)->content.val); + printf("%d", temp->content.val); break; case string: - printf("%s", (char*)(*stack_head)->content.ptr); - break; - case ref: - printf("%s", ((stackitem*)(*stack_head)->content.ptr)->id); + printf("\"%s\"", (char*)temp->content.ptr); break; case symbol: + case func: + printf("%s", temp->id); + break; default: - printf("%p", (*stack_head)->content.ptr); + printf("%p", temp->content.ptr); break; } } @@ -243,30 +254,102 @@ { if(*stack_head != NULL) { print_st(*stack_head, 1); - printf("\n"); + nl(); } else { printerr("Stack empty"); } } +/* Swap the two top elements on the stack. */ +extern void swap(stackitem** stack_head) +{ + stackitem* temp= (*stack_head); + + if((*stack_head)==NULL) { + printerr("Stack empty"); + return; + } + + if((*stack_head)->next==NULL) + return; + + *stack_head= (*stack_head)->next; + temp->next= (*stack_head)->next; + (*stack_head)->next= temp; +} + +stackitem* copy(stackitem* in_item) +{ + stackitem* out_item= malloc(sizeof(stackitem)); + + memcpy(out_item, in_item, sizeof(stackitem)); + out_item->next= NULL; + + return out_item; +} + + /* 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; + stackitem* temp= *stack_head; - if((*stack_head)==NULL || (*stack_head)->type!=ref) { - printerr("Stack empty or not a reference"); + if(temp==NULL) { + printerr("Stack empty"); return; } - if(((stackitem*)(*stack_head)->content.ptr)->type==func) { - in_func= (funcp)((stackitem*)(*stack_head)->content.ptr)->content.ptr; + while(temp->type==ref) + temp= temp->content.ptr; + + if(temp->type==func) { + in_func= (funcp)(temp->content.ptr); toss(stack_head); (*in_func)(stack_head); return; - } else - printerr("Not a function"); + } + + push(stack_head, copy(temp)); + swap(stack_head); + toss(stack_head); +} + +/* Make a list. */ +extern void pack(stackitem** stack_head) +{ + void* delimiter; + stackitem *iterator, *temp, *pack; + + delimiter= (*stack_head)->content.ptr; /* Get delimiter */ + toss(stack_head); + + iterator= *stack_head; + + if(iterator==NULL || iterator->content.ptr==delimiter) { + temp= NULL; + toss(stack_head); + } else { + /* 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; + + 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; + + push(stack_head, pack); } /* Parse input. */ @@ -276,6 +359,7 @@ int itemp; size_t inlength= strlen(in_line)+1; int convert= 0; + static int non_eval_flag= 0; temp= malloc(inlength); rest= malloc(inlength); @@ -298,14 +382,35 @@ break; } /* If symbol */ - if((convert= sscanf(in_line, "%[^ ;\n\r]%[^\n\r]", temp, rest))) { + 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; + /* If single char */ + if((convert= sscanf(in_line, "%c%[^\n\r]", temp, rest))) { + if(*temp==';') { + if(!non_eval_flag) { + eval(stack_head); /* Evaluate top element */ + break; + } + + push_ref(stack_head, in_hash, ";"); + break; + } + + if(*temp==']') { + push_ref(stack_head, in_hash, "["); + pack(stack_head); + if(non_eval_flag!=0) + non_eval_flag--; + break; + } + + if(*temp=='[') { + push_ref(stack_head, in_hash, "["); + non_eval_flag++; + break; + } } } while(0); @@ -323,42 +428,6 @@ return 1; } -/* Make a list. */ -extern void pack(stackitem** stack_head) -{ - void* delimiter; - stackitem *iterator, *temp, *pack; - - if((*stack_head)==NULL) { - printerr("Stack empty"); - return; - } - - 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; - - 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; - - push(stack_head, pack); -} - /* Relocate elements of the list on the stack. */ extern void expand(stackitem** stack_head) { @@ -374,6 +443,9 @@ new_head= temp= (*stack_head)->content.ptr; toss(stack_head); + if(temp==NULL) + return; + /* Search the end of the list */ while(temp->next!=NULL) temp= temp->next; @@ -383,24 +455,6 @@ *stack_head= new_head; /* ...and voila! */ } -/* Swap the two top elements on the stack. */ -extern void swap(stackitem** stack_head) -{ - stackitem* temp= (*stack_head); - - if((*stack_head)==NULL) { - printerr("Stack empty"); - return; - } - - if((*stack_head)->next==NULL) - return; - - *stack_head= (*stack_head)->next; - temp->next= (*stack_head)->next; - (*stack_head)->next= temp; -} - /* Compares two elements by reference. */ extern void eq(stackitem** stack_head) { @@ -470,6 +524,13 @@ exit(EXIT_SUCCESS); } +/* Clear stack */ +extern void clear(stackitem** stack_head) +{ + while(*stack_head!=NULL) + toss(stack_head); +} + int main() { stackitem* s= NULL; @@ -487,7 +548,3 @@ exit(EXIT_SUCCESS); } - -/* Local Variables: */ -/* compile-command:"make CFLAGS=\"-Wall -g -rdynamic -ldl\" stack" */ -/* End: */