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

Annotation of /stack/stack.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.26 - (hide annotations)
Sat Feb 2 20:49:34 2002 UTC (22 years, 2 months ago) by masse
Branch: MAIN
Changes since 1.25: +41 -22 lines
File MIME type: text/plain
Now it's possible to store and access variables.

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

root@recompile.se
ViewVC Help
Powered by ViewVC 1.1.26