/[cvs]/stack/stack.c
ViewVC logotype

Diff of /stack/stack.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.10 by masse, Tue Jan 8 17:31:27 2002 UTC revision 1.17 by masse, Thu Jan 31 23:09:07 2002 UTC
# Line 11  Line 11 
11    
12  typedef struct stack_item  typedef struct stack_item
13  {  {
14    enum {value, string, ref, func, symbol, list} type;    enum {
15        value,                      /* Integer */
16        string,
17        ref,            /* Reference (to an element in the hash table) */
18        func,                       /* Function pointer */
19        symbol,
20        list
21      } type;                       /* Tells what kind of stack element */
22      
23    union {    union {
24      void* ptr;      void* ptr;                  /* Pointer to the content */
25      int val;      int val;                    /* ...or an integer */
26    } content;    } content;                    /* Stores a pointer or an integer */
27    
28    char* id;    char* id;                     /* Symbol name */
29    struct stack_item* next;    struct stack_item* next;      /* Next element */
30  } stackitem;  } stackitem;
31    
32    
33  typedef stackitem* hashtbl[HASHTBLSIZE];  typedef stackitem* hashtbl[HASHTBLSIZE]; /* Hash table declaration */
34  typedef void (*funcp)(stackitem**);  typedef void (*funcp)(stackitem**); /* Function pointer declaration */
35    
36    
37    /* Initiates a newly created hash table. */
38  void init_hashtbl(hashtbl out_hash)  void init_hashtbl(hashtbl out_hash)
39  {  {
40    long i;    long i;
# Line 33  void init_hashtbl(hashtbl out_hash) Line 43  void init_hashtbl(hashtbl out_hash)
43      out_hash[i]= NULL;      out_hash[i]= NULL;
44  }  }
45    
46    /* Returns a pointer to an element in the hash table. */
47  stackitem** hash(hashtbl in_hashtbl, const char* in_string)  stackitem** hash(hashtbl in_hashtbl, const char* in_string)
48  {  {
49    long i= 0;    long i= 0;
# Line 40  stackitem** hash(hashtbl in_hashtbl, con Line 51  stackitem** hash(hashtbl in_hashtbl, con
51    char key= 0;    char key= 0;
52    stackitem** position;    stackitem** position;
53        
54    while(1){    while(1){                     /* Hash in_string */
55      key= in_string[i++];      key= in_string[i++];
56      if(key=='\0')      if(key=='\0')
57        break;        break;
# Line 50  stackitem** hash(hashtbl in_hashtbl, con Line 61  stackitem** hash(hashtbl in_hashtbl, con
61    out_hash= out_hash%HASHTBLSIZE;    out_hash= out_hash%HASHTBLSIZE;
62    position= &(in_hashtbl[out_hash]);    position= &(in_hashtbl[out_hash]);
63    
64    while(1){    while(1){                     /* Return position if empty */
65      if(*position==NULL)      if(*position==NULL)
66        return position;        return position;
67            
68      if(strcmp(in_string, (*position)->id)==0)      if(strcmp(in_string, (*position)->id)==0) /* Return position if match */
69        return position;        return position;
70    
71      position= &((*position)->next);      position= &((*position)->next); /* Try next */
72    }    }
73  }  }
74    
75    /* Generic push function. */
76  int push(stackitem** stack_head, stackitem* in_item)  int push(stackitem** stack_head, stackitem* in_item)
77  {  {
78    in_item->next= *stack_head;    in_item->next= *stack_head;
# Line 69  int push(stackitem** stack_head, stackit Line 80  int push(stackitem** stack_head, stackit
80    return 1;    return 1;
81  }  }
82    
83    /* Push a value on the stack. */
84  int push_val(stackitem** stack_head, int in_val)  int push_val(stackitem** stack_head, int in_val)
85  {  {
86    stackitem* new_item= malloc(sizeof(stackitem));    stackitem* new_item= malloc(sizeof(stackitem));
# Line 79  int push_val(stackitem** stack_head, int Line 91  int push_val(stackitem** stack_head, int
91    return 1;    return 1;
92  }  }
93    
94    /* Copy a string onto the stack. */
95  int push_cstring(stackitem** stack_head, const char* in_string)  int push_cstring(stackitem** stack_head, const char* in_string)
96  {  {
97    stackitem* new_item= malloc(sizeof(stackitem));    stackitem* new_item= malloc(sizeof(stackitem));
# Line 90  int push_cstring(stackitem** stack_head, Line 103  int push_cstring(stackitem** stack_head,
103    return 1;    return 1;
104  }  }
105    
106    /* Create a new hash entry. */
107  int mk_hashentry(hashtbl in_hashtbl, stackitem* in_item, const char* id)  int mk_hashentry(hashtbl in_hashtbl, stackitem* in_item, const char* id)
108  {  {
109    in_item->id= malloc(strlen(id)+1);    in_item->id= malloc(strlen(id)+1);
# Line 100  int mk_hashentry(hashtbl in_hashtbl, sta Line 114  int mk_hashentry(hashtbl in_hashtbl, sta
114    return 1;    return 1;
115  }  }
116    
117    /* Define a function a new function in the hash table. */
118  void def_func(hashtbl in_hashtbl, funcp in_func, const char* id)  void def_func(hashtbl in_hashtbl, funcp in_func, const char* id)
119  {  {
120    stackitem* temp= malloc(sizeof(stackitem));    stackitem* temp= malloc(sizeof(stackitem));
# Line 110  void def_func(hashtbl in_hashtbl, funcp Line 125  void def_func(hashtbl in_hashtbl, funcp
125    mk_hashentry(in_hashtbl, temp, id);    mk_hashentry(in_hashtbl, temp, id);
126  }  }
127    
128    /* Define a new symbol in the hash table. */
129  void def_sym(hashtbl in_hashtbl, const char* id)  void def_sym(hashtbl in_hashtbl, const char* id)
130  {  {
131    stackitem* temp= malloc(sizeof(stackitem));    stackitem* temp= malloc(sizeof(stackitem));
132        
133    temp->type= symbol;    temp->type= symbol;
   
134    mk_hashentry(in_hashtbl, temp, id);    mk_hashentry(in_hashtbl, temp, id);
135  }  }
136    
137    /* Push a reference to an entry in the hash table onto the stack. */
138  int push_ref(stackitem** stack_head, hashtbl in_hash, const char* in_string)  int push_ref(stackitem** stack_head, hashtbl in_hash, const char* in_string)
139  {  {
140    static void* handle= NULL;    static void* handle= NULL;
# Line 128  int push_ref(stackitem** stack_head, has Line 144  int push_ref(stackitem** stack_head, has
144    new_item->content.ptr= *hash(in_hash, in_string);    new_item->content.ptr= *hash(in_hash, in_string);
145    new_item->type= ref;    new_item->type= ref;
146    
147    if(new_item->content.ptr==NULL) {    if(new_item->content.ptr==NULL) { /* If hash entry empty */
148      if(handle==NULL)      if(handle==NULL)            /* If no handle */
149        handle= dlopen(NULL, RTLD_LAZY);            handle= dlopen(NULL, RTLD_LAZY);    
150    
151      symbol= dlsym(handle, in_string);      symbol= dlsym(handle, in_string); /* Get function pointer */
152      if(dlerror()==NULL)      if(dlerror()==NULL)         /* If existing function pointer */
153        def_func(in_hash, symbol, in_string);        def_func(in_hash, symbol, in_string); /* Store function pointer */
154      else      else
155        def_sym(in_hash, in_string);        def_sym(in_hash, in_string); /* Make symbol */
156                
157      new_item->content.ptr= *hash(in_hash, in_string);      new_item->content.ptr= *hash(in_hash, in_string); /* XXX */
158      new_item->type= ref;      new_item->type= ref;
159    }    }
160    
# Line 146  int push_ref(stackitem** stack_head, has Line 162  int push_ref(stackitem** stack_head, has
162    return 1;    return 1;
163  }  }
164    
165    void printerr(const char* in_string) {
166      fprintf(stderr, "Err: %s\n", in_string);
167    }
168    
169    /* Discard the top element of the stack. */
170  extern void toss(stackitem** stack_head)  extern void toss(stackitem** stack_head)
171  {  {
172    stackitem* temp= *stack_head;    stackitem* temp= *stack_head;
173    
174    if((*stack_head)==NULL)    if((*stack_head)==NULL) {
175        printerr("Stack empty");
176      return;      return;
177      }
178        
179    if((*stack_head)->type==string)    if((*stack_head)->type==string)
180      free((*stack_head)->content.ptr);      free((*stack_head)->content.ptr);
# Line 160  extern void toss(stackitem** stack_head) Line 183  extern void toss(stackitem** stack_head)
183    free(temp);    free(temp);
184  }  }
185    
186    /* Print newline. */
187  extern void nl()  extern void nl()
188  {  {
189    printf("\n");    printf("\n");
190  }  }
191    
192  void prin(stackitem** stack_head)  /* Prints the top element of the stack. */
193    void print_(stackitem** stack_head)
194  {  {
195    if((*stack_head)==NULL)    if((*stack_head)==NULL) {
196        printerr("Stack empty");
197      return;      return;
198      }
199    
200    switch((*stack_head)->type) {    switch((*stack_head)->type) {
201    case value:    case value:
# Line 187  void prin(stackitem** stack_head) Line 214  void prin(stackitem** stack_head)
214    }    }
215  }  }
216    
217    /* Prints the top element of the stack and then discards it. */
218  extern void print(stackitem** stack_head)  extern void print(stackitem** stack_head)
219  {  {
220    prin(stack_head);    print_(stack_head);
221    toss(stack_head);    toss(stack_head);
222  }  }
223    
224  /* print_stack(stack); */  /* Only to be called by function printstack. */
225  void print_st(stackitem* stack_head, long counter)  void print_st(stackitem* stack_head, long counter)
226  {  {
227    if(stack_head->next != NULL)    if(stack_head->next != NULL)
228      print_st(stack_head->next, counter+1);      print_st(stack_head->next, counter+1);
229    
230    printf("%ld: ", counter);    printf("%ld: ", counter);
231    prin(&stack_head);    print_(&stack_head);
232    nl();    nl();
233  }  }
234    
235    /* Prints the stack. */
236  extern void printstack(stackitem** stack_head)  extern void printstack(stackitem** stack_head)
237  {  {
238    if(*stack_head != NULL) {    if(*stack_head != NULL) {
239      print_st(*stack_head, 1);      print_st(*stack_head, 1);
240      printf("\n");      printf("\n");
241      } else {
242        printerr("Stack empty");
243    }    }
244  }  }
245    
246    /* If the top element is a reference, determine if it's a reference to a
247       function, and if it is, toss the reference and execute the function. */
248  extern void eval(stackitem** stack_head)  extern void eval(stackitem** stack_head)
249  {  {
250    funcp in_func;    funcp in_func;
251    
252    if((*stack_head)==NULL || (*stack_head)->type!=ref)    if((*stack_head)==NULL || (*stack_head)->type!=ref) {
253        printerr("Stack empty or not a reference");
254      return;      return;
255      }
256    
257    if(((stackitem*)(*stack_head)->content.ptr)->type==func) {    if(((stackitem*)(*stack_head)->content.ptr)->type==func) {
258      in_func= (funcp)((stackitem*)(*stack_head)->content.ptr)->content.ptr;      in_func= (funcp)((stackitem*)(*stack_head)->content.ptr)->content.ptr;
259      toss(stack_head);      toss(stack_head);
260      (*in_func)(stack_head);      (*in_func)(stack_head);
261      return;      return;
262    }    } else
263        printerr("Not a function");
264  }  }
265    
266    /* Parse input. */
267  int stack_read(stackitem** stack_head, hashtbl in_hash, char* in_line)  int stack_read(stackitem** stack_head, hashtbl in_hash, char* in_line)
268  {  {
269    char *temp, *rest;    char *temp, *rest;
# Line 238  int stack_read(stackitem** stack_head, h Line 274  int stack_read(stackitem** stack_head, h
274    temp= malloc(inlength);    temp= malloc(inlength);
275    rest= malloc(inlength);    rest= malloc(inlength);
276    
277    if((convert= sscanf(in_line, "\"%[^\"\n\r]\" %[^\n\r]", temp, rest)) >= 1)    do {
278      push_cstring(stack_head, temp);      /* If string */
279    else if((convert= sscanf(in_line, "%d %[^\n\r]", &itemp, rest)) >= 1)      if((convert= sscanf(in_line, "\"%[^\"\n\r]\" %[^\n\r]", temp, rest))) {
280      push_val(stack_head, itemp);        push_cstring(stack_head, temp);
281    else if((convert= sscanf(in_line, "%[^ ;\n\r]%[^\n\r]", temp, rest)) >= 1)        break;
282      push_ref(stack_head, in_hash, temp);      }
283    else if((convert= sscanf(in_line, "%c%[^\n\r]", temp, rest)) >= 1)      /* If value */
284      if(*temp==';')      if((convert= sscanf(in_line, "%d %[^\n\r]", &itemp, rest))) {
285        eval(stack_head);        push_val(stack_head, itemp);
286          break;
287        }
288        /* Escape ';' with '\' */
289        if((convert= sscanf(in_line, "\\%c%[^\n\r]", temp, rest))) {
290          temp[1]= '\0';
291          push_ref(stack_head, in_hash, temp);
292          break;
293        }
294        /* If symbol */
295        if((convert= sscanf(in_line, "%[^ ;\n\r]%[^\n\r]", temp, rest))) {
296            push_ref(stack_head, in_hash, temp);
297            break;
298        }
299        /* If ';' */
300        if((convert= sscanf(in_line, "%c%[^\n\r]", temp, rest)) && *temp==';') {
301          eval(stack_head);         /* Evaluate top element */
302          break;
303        }
304      } while(0);
305    
306    
307    free(temp);    free(temp);
308    
# Line 261  int stack_read(stackitem** stack_head, h Line 317  int stack_read(stackitem** stack_head, h
317    return 1;    return 1;
318  }  }
319    
320    /* Make a list. */
321  extern void pack(stackitem** stack_head)  extern void pack(stackitem** stack_head)
322  {  {
323    void* delimiter;    void* delimiter;
324    stackitem *iterator, *temp, *pack;    stackitem *iterator, *temp, *pack;
325    
326    if((*stack_head)==NULL)    if((*stack_head)==NULL) {
327        printerr("Stack empty");
328      return;      return;
329      }
330    
331    delimiter= (*stack_head)->content.ptr;    delimiter= (*stack_head)->content.ptr; /* Get delimiter */
332    toss(stack_head);    toss(stack_head);
333    
334    iterator= *stack_head;    iterator= *stack_head;
335    
336      /* Search for first delimiter */
337    while(iterator->next!=NULL && iterator->next->content.ptr!=delimiter)    while(iterator->next!=NULL && iterator->next->content.ptr!=delimiter)
338      iterator= iterator->next;      iterator= iterator->next;
339    
340      /* Extract list */
341    temp= *stack_head;    temp= *stack_head;
342    *stack_head= iterator->next;    *stack_head= iterator->next;
343    iterator->next= NULL;    iterator->next= NULL;
# Line 284  extern void pack(stackitem** stack_head) Line 345  extern void pack(stackitem** stack_head)
345    if(*stack_head!=NULL && (*stack_head)->content.ptr==delimiter)    if(*stack_head!=NULL && (*stack_head)->content.ptr==delimiter)
346      toss(stack_head);      toss(stack_head);
347    
348      /* Push list */
349    pack= malloc(sizeof(stackitem));    pack= malloc(sizeof(stackitem));
350    pack->type= list;    pack->type= list;
351    pack->content.ptr= temp;    pack->content.ptr= temp;
# Line 291  extern void pack(stackitem** stack_head) Line 353  extern void pack(stackitem** stack_head)
353    push(stack_head, pack);    push(stack_head, pack);
354  }  }
355    
356    /* Relocate elements of the list on the stack. */
357  extern void expand(stackitem** stack_head)  extern void expand(stackitem** stack_head)
358  {  {
359    stackitem *temp, *new_head;    stackitem *temp, *new_head;
360    
361    if((*stack_head)==NULL || (*stack_head)->type!=list)    /* Is top element a list? */
362      if((*stack_head)==NULL || (*stack_head)->type!=list) {
363        printerr("Stack empty or not a list");
364      return;      return;
365      }
366    
367      /* The first list element is the new stack head */
368    new_head= temp= (*stack_head)->content.ptr;    new_head= temp= (*stack_head)->content.ptr;
369    toss(stack_head);    toss(stack_head);
370    
371      /* Search the end of the list */
372    while(temp->next!=NULL)    while(temp->next!=NULL)
373      temp= temp->next;      temp= temp->next;
374    
375      /* Connect the the tail of the list with the old stack head */
376    temp->next= *stack_head;    temp->next= *stack_head;
377    *stack_head= new_head;    *stack_head= new_head;        /* ...and voila! */
378  }  }
379    
380    /* Swap the two top elements on the stack. */
381  extern void swap(stackitem** stack_head)  extern void swap(stackitem** stack_head)
382  {  {
383    stackitem* temp= (*stack_head);    stackitem* temp= (*stack_head);
384        
385    if((*stack_head)==NULL || (*stack_head)->next==NULL)    if((*stack_head)==NULL) {
386        printerr("Stack empty");
387        return;
388      }
389    
390      if((*stack_head)->next==NULL)
391      return;      return;
392    
393    *stack_head= (*stack_head)->next;    *stack_head= (*stack_head)->next;
# Line 320  extern void swap(stackitem** stack_head) Line 395  extern void swap(stackitem** stack_head)
395    (*stack_head)->next= temp;    (*stack_head)->next= temp;
396  }  }
397    
398    /* Compares two elements by reference. */
399    extern void eq(stackitem** stack_head)
400    {
401      void *left, *right;
402      int result;
403    
404      if((*stack_head)==NULL || (*stack_head)->next==NULL) {
405        printerr("Not enough elements to compare");
406        return;
407      }
408    
409      left= (*stack_head)->content.ptr;
410      swap(stack_head);
411      right= (*stack_head)->content.ptr;
412      result= (left==right);
413      
414      toss(stack_head); toss(stack_head);
415      push_val(stack_head, (left==right));
416    }
417    
418    /* Negates the top element on the stack. */
419    extern void not(stackitem** stack_head)
420    {
421      int value;
422    
423      if((*stack_head)==NULL || (*stack_head)->type!=value) {
424        printerr("Stack empty or element is not a value");
425        return;
426      }
427    
428      value= (*stack_head)->content.val;
429      toss(stack_head);
430      push_val(stack_head, !value);
431    }
432    
433    /* Compares the two top elements on the stack and return 0 if they're the
434       same. */
435    extern void neq(stackitem** stack_head)
436    {
437      eq(stack_head);
438      not(stack_head);
439    }
440    
441    /* Give a symbol some content. */
442    extern void def(stackitem** stack_head)
443    {
444      stackitem *temp, *value;
445    
446      if(*stack_head==NULL || (*stack_head)->next==NULL
447         || (*stack_head)->type!=ref) {
448        printerr("Define what?");
449        return;
450      }
451    
452      temp= (*stack_head)->content.ptr;
453      value= (*stack_head)->next;
454      temp->content= value->content;
455      value->content.ptr=NULL;
456      temp->type= value->type;
457    
458      toss(stack_head); toss(stack_head);
459    }
460    
461    /* Quit stack. */
462  extern void quit()  extern void quit()
463  {  {
464    exit(EXIT_SUCCESS);    exit(EXIT_SUCCESS);

Legend:
Removed from v.1.10  
changed lines
  Added in v.1.17

root@recompile.se
ViewVC Help
Powered by ViewVC 1.1.26