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

Annotation of /stack/stack.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.17 - (hide annotations)
Thu Jan 31 23:09:07 2002 UTC (22 years, 3 months ago) by masse
Branch: MAIN
Changes since 1.16: +38 -10 lines
File MIME type: text/plain
Added error messages.

1 masse 1.1 /* printf */
2     #include <stdio.h>
3     /* EXIT_SUCCESS */
4     #include <stdlib.h>
5     /* NULL */
6     #include <stddef.h>
7 teddy 1.3 /* dlopen, dlsym, dlerror */
8 masse 1.1 #include <dlfcn.h>
9    
10     #define HASHTBLSIZE 65536
11    
12     typedef struct stack_item
13     {
14 masse 1.16 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 masse 1.1 union {
24 masse 1.16 void* ptr; /* Pointer to the content */
25     int val; /* ...or an integer */
26     } content; /* Stores a pointer or an integer */
27 masse 1.1
28 masse 1.16 char* id; /* Symbol name */
29     struct stack_item* next; /* Next element */
30 masse 1.1 } stackitem;
31    
32    
33 masse 1.16 typedef stackitem* hashtbl[HASHTBLSIZE]; /* Hash table declaration */
34     typedef void (*funcp)(stackitem**); /* Function pointer declaration */
35 masse 1.1
36 masse 1.14
37     /* Initiates a newly created hash table. */
38 masse 1.1 void init_hashtbl(hashtbl out_hash)
39     {
40     long i;
41    
42     for(i= 0; i<HASHTBLSIZE; i++)
43     out_hash[i]= NULL;
44     }
45    
46 masse 1.14 /* Returns a pointer to an element in the hash table. */
47 masse 1.1 stackitem** hash(hashtbl in_hashtbl, const char* in_string)
48     {
49     long i= 0;
50     unsigned long out_hash= 0;
51     char key= 0;
52     stackitem** position;
53    
54 masse 1.16 while(1){ /* Hash in_string */
55 masse 1.1 key= in_string[i++];
56     if(key=='\0')
57     break;
58     out_hash= out_hash*32+key;
59     }
60    
61     out_hash= out_hash%HASHTBLSIZE;
62     position= &(in_hashtbl[out_hash]);
63    
64 masse 1.16 while(1){ /* Return position if empty */
65 masse 1.1 if(*position==NULL)
66     return position;
67    
68 masse 1.16 if(strcmp(in_string, (*position)->id)==0) /* Return position if match */
69 masse 1.1 return position;
70    
71 masse 1.16 position= &((*position)->next); /* Try next */
72 masse 1.1 }
73     }
74    
75 masse 1.14 /* Generic push function. */
76 masse 1.1 int push(stackitem** stack_head, stackitem* in_item)
77     {
78     in_item->next= *stack_head;
79     *stack_head= in_item;
80     return 1;
81     }
82    
83 masse 1.14 /* Push a value on the stack. */
84 masse 1.1 int push_val(stackitem** stack_head, int in_val)
85     {
86     stackitem* new_item= malloc(sizeof(stackitem));
87     new_item->content.val= in_val;
88     new_item->type= value;
89    
90     push(stack_head, new_item);
91     return 1;
92     }
93    
94 masse 1.14 /* Copy a string onto the stack. */
95 masse 1.1 int push_cstring(stackitem** stack_head, const char* in_string)
96     {
97     stackitem* new_item= malloc(sizeof(stackitem));
98     new_item->content.ptr= malloc(strlen(in_string)+1);
99     strcpy(new_item->content.ptr, in_string);
100     new_item->type= string;
101    
102     push(stack_head, new_item);
103     return 1;
104     }
105    
106 masse 1.14 /* Create a new hash entry. */
107 masse 1.1 int mk_hashentry(hashtbl in_hashtbl, stackitem* in_item, const char* id)
108     {
109     in_item->id= malloc(strlen(id)+1);
110    
111     strcpy(in_item->id, id);
112     push(hash(in_hashtbl, id), in_item);
113    
114     return 1;
115     }
116    
117 masse 1.14 /* Define a function a new function in the hash table. */
118 masse 1.1 void def_func(hashtbl in_hashtbl, funcp in_func, const char* id)
119     {
120     stackitem* temp= malloc(sizeof(stackitem));
121    
122     temp->type= func;
123     temp->content.ptr= in_func;
124    
125     mk_hashentry(in_hashtbl, temp, id);
126     }
127    
128 masse 1.14 /* Define a new symbol in the hash table. */
129 masse 1.4 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 masse 1.14 /* Push a reference to an entry in the hash table onto the stack. */
138 masse 1.1 int push_ref(stackitem** stack_head, hashtbl in_hash, const char* in_string)
139     {
140 masse 1.6 static void* handle= NULL;
141 masse 1.1 void* symbol;
142 masse 1.6
143 masse 1.1 stackitem* new_item= malloc(sizeof(stackitem));
144     new_item->content.ptr= *hash(in_hash, in_string);
145     new_item->type= ref;
146    
147 masse 1.16 if(new_item->content.ptr==NULL) { /* If hash entry empty */
148     if(handle==NULL) /* If no handle */
149 masse 1.9 handle= dlopen(NULL, RTLD_LAZY);
150 masse 1.6
151 masse 1.16 symbol= dlsym(handle, in_string); /* Get function pointer */
152     if(dlerror()==NULL) /* If existing function pointer */
153     def_func(in_hash, symbol, in_string); /* Store function pointer */
154 masse 1.4 else
155 masse 1.16 def_sym(in_hash, in_string); /* Make symbol */
156 masse 1.4
157 masse 1.16 new_item->content.ptr= *hash(in_hash, in_string); /* XXX */
158 masse 1.4 new_item->type= ref;
159 masse 1.1 }
160    
161     push(stack_head, new_item);
162     return 1;
163     }
164    
165 masse 1.17 void printerr(const char* in_string) {
166     fprintf(stderr, "Err: %s\n", in_string);
167     }
168    
169 masse 1.14 /* Discard the top element of the stack. */
170 masse 1.1 extern void toss(stackitem** stack_head)
171     {
172     stackitem* temp= *stack_head;
173    
174 masse 1.17 if((*stack_head)==NULL) {
175     printerr("Stack empty");
176 masse 1.7 return;
177 masse 1.17 }
178 masse 1.7
179     if((*stack_head)->type==string)
180     free((*stack_head)->content.ptr);
181    
182 masse 1.1 *stack_head= (*stack_head)->next;
183     free(temp);
184     }
185    
186 masse 1.14 /* Print newline. */
187 masse 1.8 extern void nl()
188     {
189     printf("\n");
190     }
191 masse 1.1
192 masse 1.14 /* Prints the top element of the stack. */
193 masse 1.11 void print_(stackitem** stack_head)
194 masse 1.8 {
195 masse 1.17 if((*stack_head)==NULL) {
196     printerr("Stack empty");
197 masse 1.8 return;
198 masse 1.17 }
199 masse 1.1
200 masse 1.8 switch((*stack_head)->type) {
201 teddy 1.2 case value:
202 masse 1.8 printf("%d", (*stack_head)->content.val);
203 teddy 1.2 break;
204     case string:
205 masse 1.8 printf("%s", (char*)(*stack_head)->content.ptr);
206 teddy 1.2 break;
207     case ref:
208 masse 1.8 printf("%s", ((stackitem*)(*stack_head)->content.ptr)->id);
209 masse 1.6 break;
210 masse 1.4 case symbol:
211 masse 1.7 default:
212 masse 1.8 printf("%p", (*stack_head)->content.ptr);
213 teddy 1.2 break;
214     }
215 masse 1.1 }
216    
217 masse 1.14 /* Prints the top element of the stack and then discards it. */
218 masse 1.8 extern void print(stackitem** stack_head)
219     {
220 masse 1.11 print_(stack_head);
221 masse 1.8 toss(stack_head);
222     }
223    
224 masse 1.14 /* Only to be called by function printstack. */
225 masse 1.8 void print_st(stackitem* stack_head, long counter)
226     {
227     if(stack_head->next != NULL)
228     print_st(stack_head->next, counter+1);
229    
230     printf("%ld: ", counter);
231 masse 1.11 print_(&stack_head);
232 masse 1.8 nl();
233     }
234    
235 masse 1.14 /* Prints the stack. */
236 masse 1.1 extern void printstack(stackitem** stack_head)
237     {
238     if(*stack_head != NULL) {
239     print_st(*stack_head, 1);
240     printf("\n");
241 masse 1.17 } else {
242     printerr("Stack empty");
243 masse 1.1 }
244     }
245    
246 masse 1.14 /* If the top element is a reference, determine if it's a reference to a
247 masse 1.16 function, and if it is, toss the reference and execute the function. */
248 masse 1.1 extern void eval(stackitem** stack_head)
249     {
250     funcp in_func;
251    
252 masse 1.17 if((*stack_head)==NULL || (*stack_head)->type!=ref) {
253     printerr("Stack empty or not a reference");
254 masse 1.1 return;
255 masse 1.17 }
256 masse 1.1
257     if(((stackitem*)(*stack_head)->content.ptr)->type==func) {
258     in_func= (funcp)((stackitem*)(*stack_head)->content.ptr)->content.ptr;
259     toss(stack_head);
260     (*in_func)(stack_head);
261     return;
262 masse 1.17 } else
263     printerr("Not a function");
264 masse 1.1 }
265    
266 masse 1.14 /* Parse input. */
267 masse 1.1 int stack_read(stackitem** stack_head, hashtbl in_hash, char* in_line)
268     {
269     char *temp, *rest;
270     int itemp;
271     size_t inlength= strlen(in_line)+1;
272     int convert= 0;
273    
274     temp= malloc(inlength);
275     rest= malloc(inlength);
276    
277 masse 1.15 do {
278 masse 1.16 /* If string */
279 masse 1.15 if((convert= sscanf(in_line, "\"%[^\"\n\r]\" %[^\n\r]", temp, rest))) {
280     push_cstring(stack_head, temp);
281     break;
282     }
283 masse 1.16 /* If value */
284 masse 1.15 if((convert= sscanf(in_line, "%d %[^\n\r]", &itemp, rest))) {
285     push_val(stack_head, itemp);
286     break;
287     }
288 masse 1.16 /* Escape ';' with '\' */
289 masse 1.15 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 masse 1.16 /* If symbol */
295 masse 1.15 if((convert= sscanf(in_line, "%[^ ;\n\r]%[^\n\r]", temp, rest))) {
296     push_ref(stack_head, in_hash, temp);
297     break;
298     }
299 masse 1.16 /* If ';' */
300 masse 1.15 if((convert= sscanf(in_line, "%c%[^\n\r]", temp, rest)) && *temp==';') {
301 masse 1.16 eval(stack_head); /* Evaluate top element */
302 masse 1.15 break;
303     }
304     } while(0);
305    
306 masse 1.1
307     free(temp);
308    
309     if(convert<2) {
310     free(rest);
311     return 0;
312     }
313    
314     stack_read(stack_head, in_hash, rest);
315    
316     free(rest);
317     return 1;
318     }
319    
320 masse 1.14 /* Make a list. */
321 masse 1.7 extern void pack(stackitem** stack_head)
322     {
323     void* delimiter;
324     stackitem *iterator, *temp, *pack;
325    
326 masse 1.17 if((*stack_head)==NULL) {
327     printerr("Stack empty");
328 masse 1.7 return;
329 masse 1.17 }
330 masse 1.7
331 masse 1.16 delimiter= (*stack_head)->content.ptr; /* Get delimiter */
332 masse 1.7 toss(stack_head);
333    
334     iterator= *stack_head;
335    
336 masse 1.16 /* Search for first delimiter */
337 masse 1.7 while(iterator->next!=NULL && iterator->next->content.ptr!=delimiter)
338     iterator= iterator->next;
339    
340 masse 1.16 /* Extract list */
341 masse 1.7 temp= *stack_head;
342     *stack_head= iterator->next;
343     iterator->next= NULL;
344    
345     if(*stack_head!=NULL && (*stack_head)->content.ptr==delimiter)
346     toss(stack_head);
347    
348 masse 1.16 /* Push list */
349 masse 1.7 pack= malloc(sizeof(stackitem));
350     pack->type= list;
351     pack->content.ptr= temp;
352    
353     push(stack_head, pack);
354     }
355 masse 1.1
356 masse 1.16 /* Relocate elements of the list on the stack. */
357 masse 1.8 extern void expand(stackitem** stack_head)
358 masse 1.1 {
359 masse 1.8 stackitem *temp, *new_head;
360    
361 masse 1.16 /* Is top element a list? */
362 masse 1.17 if((*stack_head)==NULL || (*stack_head)->type!=list) {
363     printerr("Stack empty or not a list");
364 masse 1.8 return;
365 masse 1.17 }
366 masse 1.8
367 masse 1.16 /* The first list element is the new stack head */
368 masse 1.8 new_head= temp= (*stack_head)->content.ptr;
369     toss(stack_head);
370    
371 masse 1.16 /* Search the end of the list */
372 masse 1.8 while(temp->next!=NULL)
373     temp= temp->next;
374    
375 masse 1.16 /* Connect the the tail of the list with the old stack head */
376 masse 1.8 temp->next= *stack_head;
377 masse 1.16 *stack_head= new_head; /* ...and voila! */
378 teddy 1.5 }
379    
380 masse 1.14 /* Swap the two top elements on the stack. */
381 masse 1.10 extern void swap(stackitem** stack_head)
382     {
383     stackitem* temp= (*stack_head);
384    
385 masse 1.17 if((*stack_head)==NULL) {
386     printerr("Stack empty");
387     return;
388     }
389    
390     if((*stack_head)->next==NULL)
391 masse 1.10 return;
392    
393     *stack_head= (*stack_head)->next;
394     temp->next= (*stack_head)->next;
395     (*stack_head)->next= temp;
396     }
397 masse 1.11
398 masse 1.14 /* Compares two elements by reference. */
399 masse 1.11 extern void eq(stackitem** stack_head)
400     {
401     void *left, *right;
402     int result;
403    
404 masse 1.17 if((*stack_head)==NULL || (*stack_head)->next==NULL) {
405     printerr("Not enough elements to compare");
406 masse 1.11 return;
407 masse 1.17 }
408 masse 1.11
409     left= (*stack_head)->content.ptr;
410 masse 1.12 swap(stack_head);
411     right= (*stack_head)->content.ptr;
412 masse 1.11 result= (left==right);
413    
414     toss(stack_head); toss(stack_head);
415     push_val(stack_head, (left==right));
416     }
417    
418 masse 1.14 /* Negates the top element on the stack. */
419 masse 1.11 extern void not(stackitem** stack_head)
420     {
421     int value;
422    
423 masse 1.17 if((*stack_head)==NULL || (*stack_head)->type!=value) {
424     printerr("Stack empty or element is not a value");
425 masse 1.11 return;
426 masse 1.17 }
427 masse 1.11
428     value= (*stack_head)->content.val;
429     toss(stack_head);
430     push_val(stack_head, !value);
431     }
432    
433 masse 1.14 /* Compares the two top elements on the stack and return 0 if they're the
434     same. */
435 masse 1.11 extern void neq(stackitem** stack_head)
436     {
437     eq(stack_head);
438     not(stack_head);
439     }
440 masse 1.12
441 masse 1.14 /* Give a symbol some content. */
442 masse 1.12 extern void def(stackitem** stack_head)
443     {
444     stackitem *temp, *value;
445    
446     if(*stack_head==NULL || (*stack_head)->next==NULL
447 masse 1.17 || (*stack_head)->type!=ref) {
448     printerr("Define what?");
449 masse 1.12 return;
450 masse 1.17 }
451 masse 1.12
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 masse 1.10
461 masse 1.14 /* Quit stack. */
462 teddy 1.5 extern void quit()
463     {
464     exit(EXIT_SUCCESS);
465 masse 1.1 }
466    
467     int main()
468     {
469     stackitem* s= NULL;
470     hashtbl myhash;
471     char in_string[100];
472    
473     init_hashtbl(myhash);
474    
475     printf("okidok\n ");
476    
477     while(fgets(in_string, 100, stdin) != NULL) {
478     stack_read(&s, myhash, in_string);
479     printf("okidok\n ");
480     }
481    
482 masse 1.10 exit(EXIT_SUCCESS);
483 masse 1.1 }
484 teddy 1.3
485     /* Local Variables: */
486     /* compile-command:"make CFLAGS=\"-Wall -g -rdynamic -ldl\" stack" */
487     /* End: */

root@recompile.se
ViewVC Help
Powered by ViewVC 1.1.26