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

Diff of /stack/stack.c

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

revision 1.1.1.1 by masse, Mon Jan 7 23:09:01 2002 UTC revision 1.16 by masse, Thu Jan 31 22:32:59 2002 UTC
# Line 4  Line 4 
4  #include <stdlib.h>  #include <stdlib.h>
5  /* NULL */  /* NULL */
6  #include <stddef.h>  #include <stddef.h>
7    /* dlopen, dlsym, dlerror */
8  #include <dlfcn.h>  #include <dlfcn.h>
9    
10  #define HASHTBLSIZE 65536  #define HASHTBLSIZE 65536
11    
12  typedef struct stack_item  typedef struct stack_item
13  {  {
14    enum {value, string, ref, func} 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 32  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 39  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 49  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 68  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 78  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 89  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 99  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 109  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)
130    {
131      stackitem* temp= malloc(sizeof(stackitem));
132      
133      temp->type= symbol;
134      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    void* handle;    static void* handle= NULL;
141    void* symbol;    void* symbol;
142      
143    stackitem* new_item= malloc(sizeof(stackitem));    stackitem* new_item= malloc(sizeof(stackitem));
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      handle= dlopen(NULL, RTLD_LAZY);      if(handle==NULL)            /* If no handle */
149      symbol= dlsym(handle, in_string);        handle= dlopen(NULL, RTLD_LAZY);    
150      if(dlerror()==NULL) {  
151        def_func(in_hash, symbol, in_string);      symbol= dlsym(handle, in_string); /* Get function pointer */
152        new_item->content.ptr= *hash(in_hash, in_string);      if(dlerror()==NULL)         /* If existing function pointer */
153        new_item->type= ref;        def_func(in_hash, symbol, in_string); /* Store function pointer */
154      }      else
155          def_sym(in_hash, in_string); /* Make symbol */
156          
157        new_item->content.ptr= *hash(in_hash, in_string); /* XXX */
158        new_item->type= ref;
159    }    }
160    
161    push(stack_head, new_item);    push(stack_head, new_item);
162    return 1;    return 1;
163  }  }
164    
165    /* Discard the top element of the stack. */
166  extern void toss(stackitem** stack_head)  extern void toss(stackitem** stack_head)
167  {  {
168    stackitem* temp= *stack_head;    stackitem* temp= *stack_head;
169    
170      if((*stack_head)==NULL)
171        return;
172      
173      if((*stack_head)->type==string)
174        free((*stack_head)->content.ptr);
175    
176    *stack_head= (*stack_head)->next;    *stack_head= (*stack_head)->next;
177    free(temp);    free(temp);
178  }  }
179    
180    /* Print newline. */
181    extern void nl()
182    {
183      printf("\n");
184    }
185    
186    /* Prints the top element of the stack. */
187    void print_(stackitem** stack_head)
188    {
189      if((*stack_head)==NULL)
190        return;
191    
192  /* print_stack(stack); */    switch((*stack_head)->type) {
193      case value:
194        printf("%d", (*stack_head)->content.val);
195        break;
196      case string:
197        printf("%s", (char*)(*stack_head)->content.ptr);
198        break;
199      case ref:
200        printf("%s", ((stackitem*)(*stack_head)->content.ptr)->id);
201        break;
202      case symbol:
203      default:
204        printf("%p", (*stack_head)->content.ptr);
205        break;
206      }
207    }
208    
209    /* Prints the top element of the stack and then discards it. */
210    extern void print(stackitem** stack_head)
211    {
212      print_(stack_head);
213      toss(stack_head);
214    }
215    
216    /* Only to be called by function printstack. */
217  void print_st(stackitem* stack_head, long counter)  void print_st(stackitem* stack_head, long counter)
218  {  {
219    if(stack_head->next != NULL)    if(stack_head->next != NULL)
220      print_st(stack_head->next, counter+1);      print_st(stack_head->next, counter+1);
221    
222    if(stack_head->type==value)    printf("%ld: ", counter);
223      printf("%ld: %d\n", counter, (int)stack_head->content.val);    print_(&stack_head);
224    else if(stack_head->type==string)    nl();
     printf("%ld: \"%s\"\n", counter, (char*)stack_head->content.ptr);  
   else  
     printf("%ld: %p\n", counter, stack_head->content.ptr);  
225  }  }
226    
227    /* Prints the stack. */
228  extern void printstack(stackitem** stack_head)  extern void printstack(stackitem** stack_head)
229  {  {
230    if(*stack_head != NULL) {    if(*stack_head != NULL) {
# Line 163  extern void printstack(stackitem** stack Line 233  extern void printstack(stackitem** stack
233    }    }
234  }  }
235    
236    /* If the top element is a reference, determine if it's a reference to a
237       function, and if it is, toss the reference and execute the function. */
238  extern void eval(stackitem** stack_head)  extern void eval(stackitem** stack_head)
239  {  {
240    funcp in_func;    funcp in_func;
# Line 179  extern void eval(stackitem** stack_head) Line 250  extern void eval(stackitem** stack_head)
250    }    }
251  }  }
252    
253    /* Parse input. */
254  int stack_read(stackitem** stack_head, hashtbl in_hash, char* in_line)  int stack_read(stackitem** stack_head, hashtbl in_hash, char* in_line)
255  {  {
256    char *temp, *rest;    char *temp, *rest;
# Line 189  int stack_read(stackitem** stack_head, h Line 261  int stack_read(stackitem** stack_head, h
261    temp= malloc(inlength);    temp= malloc(inlength);
262    rest= malloc(inlength);    rest= malloc(inlength);
263    
264    if((convert= sscanf(in_line, "\"%[^\"\n\r]\" %[^\n\r]", temp, rest)) >= 1)    do {
265      push_cstring(stack_head, temp);      /* If string */
266    else if((convert= sscanf(in_line, "%d %[^\n\r]", &itemp, rest)) >= 1)      if((convert= sscanf(in_line, "\"%[^\"\n\r]\" %[^\n\r]", temp, rest))) {
267      push_val(stack_head, itemp);        push_cstring(stack_head, temp);
268    else if((convert= sscanf(in_line, "%[^ ;\n\r]%[^\n\r]", temp, rest)) >= 1)        break;
269      push_ref(stack_head, in_hash, temp);      }
270    else if((convert= sscanf(in_line, "%c%[^\n\r]", temp, rest)) >= 1)      /* If value */
271      if(*temp==';')      if((convert= sscanf(in_line, "%d %[^\n\r]", &itemp, rest))) {
272        eval(stack_head);        push_val(stack_head, itemp);
273          break;
274        }
275        /* Escape ';' with '\' */
276        if((convert= sscanf(in_line, "\\%c%[^\n\r]", temp, rest))) {
277          temp[1]= '\0';
278          push_ref(stack_head, in_hash, temp);
279          break;
280        }
281        /* If symbol */
282        if((convert= sscanf(in_line, "%[^ ;\n\r]%[^\n\r]", temp, rest))) {
283            push_ref(stack_head, in_hash, temp);
284            break;
285        }
286        /* If ';' */
287        if((convert= sscanf(in_line, "%c%[^\n\r]", temp, rest)) && *temp==';') {
288          eval(stack_head);         /* Evaluate top element */
289          break;
290        }
291      } while(0);
292    
293    
294    free(temp);    free(temp);
295    
# Line 212  int stack_read(stackitem** stack_head, h Line 304  int stack_read(stackitem** stack_head, h
304    return 1;    return 1;
305  }  }
306    
307  extern void print(stackitem** stack_head)  /* Make a list. */
308    extern void pack(stackitem** stack_head)
309  {  {
310    if((*stack_head)==NULL)    void* delimiter;
311      stackitem *iterator, *temp, *pack;
312    
313      if((*stack_head)==NULL)       /* No delimiter */
314      return;      return;
315    
316    if((*stack_head)->type==value)    delimiter= (*stack_head)->content.ptr; /* Get delimiter */
317      printf("%d", (*stack_head)->content.val);    toss(stack_head);
318    else if((*stack_head)->type==string)  
319      printf("%s", (char*)(*stack_head)->content.ptr);    iterator= *stack_head;
320    else  
321      printf("%p", (*stack_head)->content.ptr);    /* Search for first delimiter */
322      while(iterator->next!=NULL && iterator->next->content.ptr!=delimiter)
323        iterator= iterator->next;
324    
325      /* Extract list */
326      temp= *stack_head;
327      *stack_head= iterator->next;
328      iterator->next= NULL;
329      
330      if(*stack_head!=NULL && (*stack_head)->content.ptr==delimiter)
331        toss(stack_head);
332    
333      /* Push list */
334      pack= malloc(sizeof(stackitem));
335      pack->type= list;
336      pack->content.ptr= temp;
337    
338      push(stack_head, pack);
339    }
340    
341    /* Relocate elements of the list on the stack. */
342    extern void expand(stackitem** stack_head)
343    {
344      stackitem *temp, *new_head;
345    
346      /* Is top element a list? */
347      if((*stack_head)==NULL || (*stack_head)->type!=list)
348        return;
349    
350      /* The first list element is the new stack head */
351      new_head= temp= (*stack_head)->content.ptr;
352    toss(stack_head);    toss(stack_head);
353    
354      /* Search the end of the list */
355      while(temp->next!=NULL)
356        temp= temp->next;
357    
358      /* Connect the the tail of the list with the old stack head */
359      temp->next= *stack_head;
360      *stack_head= new_head;        /* ...and voila! */
361  }  }
362    
363  extern void nl()  /* Swap the two top elements on the stack. */
364    extern void swap(stackitem** stack_head)
365  {  {
366    printf("\n");    stackitem* temp= (*stack_head);
367      
368      if((*stack_head)==NULL || (*stack_head)->next==NULL)
369        return;
370    
371      *stack_head= (*stack_head)->next;
372      temp->next= (*stack_head)->next;
373      (*stack_head)->next= temp;
374    }
375    
376    /* Compares two elements by reference. */
377    extern void eq(stackitem** stack_head)
378    {
379      void *left, *right;
380      int result;
381    
382      if((*stack_head)==NULL || (*stack_head)->next==NULL)
383        return;
384    
385      left= (*stack_head)->content.ptr;
386      swap(stack_head);
387      right= (*stack_head)->content.ptr;
388      result= (left==right);
389      
390      toss(stack_head); toss(stack_head);
391      push_val(stack_head, (left==right));
392    }
393    
394    /* Negates the top element on the stack. */
395    extern void not(stackitem** stack_head)
396    {
397      int value;
398    
399      if((*stack_head)==NULL || (*stack_head)->type!=value)
400        return;
401    
402      value= (*stack_head)->content.val;
403      toss(stack_head);
404      push_val(stack_head, !value);
405    }
406    
407    /* Compares the two top elements on the stack and return 0 if they're the
408       same. */
409    extern void neq(stackitem** stack_head)
410    {
411      eq(stack_head);
412      not(stack_head);
413    }
414    
415    /* Give a symbol some content. */
416    extern void def(stackitem** stack_head)
417    {
418      stackitem *temp, *value;
419    
420      if(*stack_head==NULL || (*stack_head)->next==NULL
421         || (*stack_head)->type!=ref)
422        return;
423    
424      temp= (*stack_head)->content.ptr;
425      value= (*stack_head)->next;
426      temp->content= value->content;
427      value->content.ptr=NULL;
428      temp->type= value->type;
429    
430      toss(stack_head); toss(stack_head);
431    }
432    
433    /* Quit stack. */
434    extern void quit()
435    {
436      exit(EXIT_SUCCESS);
437  }  }
438    
439  int main()  int main()
# Line 247  int main() Line 451  int main()
451      printf("okidok\n ");      printf("okidok\n ");
452    }    }
453    
454      exit(EXIT_SUCCESS);
   return EXIT_SUCCESS;  
455  }  }
456    
457    /* Local Variables: */
458    /* compile-command:"make CFLAGS=\"-Wall -g -rdynamic -ldl\" stack" */
459    /* End: */

Legend:
Removed from v.1.1.1.1  
changed lines
  Added in v.1.16

root@recompile.se
ViewVC Help
Powered by ViewVC 1.1.26