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

Contents of /stack/stack.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.16 - (show annotations)
Thu Jan 31 22:32:59 2002 UTC (22 years, 3 months ago) by masse
Branch: MAIN
Changes since 1.15: +46 -32 lines
File MIME type: text/plain
Minor changes. Added some more comments.

1 /* printf */
2 #include <stdio.h>
3 /* EXIT_SUCCESS */
4 #include <stdlib.h>
5 /* NULL */
6 #include <stddef.h>
7 /* dlopen, dlsym, dlerror */
8 #include <dlfcn.h>
9
10 #define HASHTBLSIZE 65536
11
12 typedef struct stack_item
13 {
14 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 {
24 void* ptr; /* Pointer to the content */
25 int val; /* ...or an integer */
26 } content; /* Stores a pointer or an integer */
27
28 char* id; /* Symbol name */
29 struct stack_item* next; /* Next element */
30 } stackitem;
31
32
33 typedef stackitem* hashtbl[HASHTBLSIZE]; /* Hash table declaration */
34 typedef void (*funcp)(stackitem**); /* Function pointer declaration */
35
36
37 /* Initiates a newly created hash table. */
38 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 /* Returns a pointer to an element in the hash table. */
47 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 while(1){ /* Hash in_string */
55 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 while(1){ /* Return position if empty */
65 if(*position==NULL)
66 return position;
67
68 if(strcmp(in_string, (*position)->id)==0) /* Return position if match */
69 return position;
70
71 position= &((*position)->next); /* Try next */
72 }
73 }
74
75 /* Generic push function. */
76 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 /* Push a value on the stack. */
84 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 /* Copy a string onto the stack. */
95 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 /* Create a new hash entry. */
107 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 /* Define a function a new function in the hash table. */
118 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 /* 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)
139 {
140 static void* handle= NULL;
141 void* symbol;
142
143 stackitem* new_item= malloc(sizeof(stackitem));
144 new_item->content.ptr= *hash(in_hash, in_string);
145 new_item->type= ref;
146
147 if(new_item->content.ptr==NULL) { /* If hash entry empty */
148 if(handle==NULL) /* If no handle */
149 handle= dlopen(NULL, RTLD_LAZY);
150
151 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 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);
162 return 1;
163 }
164
165 /* Discard the top element of the stack. */
166 extern void toss(stackitem** stack_head)
167 {
168 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;
177 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 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)
218 {
219 if(stack_head->next != NULL)
220 print_st(stack_head->next, counter+1);
221
222 printf("%ld: ", counter);
223 print_(&stack_head);
224 nl();
225 }
226
227 /* Prints the stack. */
228 extern void printstack(stackitem** stack_head)
229 {
230 if(*stack_head != NULL) {
231 print_st(*stack_head, 1);
232 printf("\n");
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)
239 {
240 funcp in_func;
241
242 if((*stack_head)==NULL || (*stack_head)->type!=ref)
243 return;
244
245 if(((stackitem*)(*stack_head)->content.ptr)->type==func) {
246 in_func= (funcp)((stackitem*)(*stack_head)->content.ptr)->content.ptr;
247 toss(stack_head);
248 (*in_func)(stack_head);
249 return;
250 }
251 }
252
253 /* Parse input. */
254 int stack_read(stackitem** stack_head, hashtbl in_hash, char* in_line)
255 {
256 char *temp, *rest;
257 int itemp;
258 size_t inlength= strlen(in_line)+1;
259 int convert= 0;
260
261 temp= malloc(inlength);
262 rest= malloc(inlength);
263
264 do {
265 /* If string */
266 if((convert= sscanf(in_line, "\"%[^\"\n\r]\" %[^\n\r]", temp, rest))) {
267 push_cstring(stack_head, temp);
268 break;
269 }
270 /* If value */
271 if((convert= sscanf(in_line, "%d %[^\n\r]", &itemp, rest))) {
272 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);
295
296 if(convert<2) {
297 free(rest);
298 return 0;
299 }
300
301 stack_read(stack_head, in_hash, rest);
302
303 free(rest);
304 return 1;
305 }
306
307 /* Make a list. */
308 extern void pack(stackitem** stack_head)
309 {
310 void* delimiter;
311 stackitem *iterator, *temp, *pack;
312
313 if((*stack_head)==NULL) /* No delimiter */
314 return;
315
316 delimiter= (*stack_head)->content.ptr; /* Get delimiter */
317 toss(stack_head);
318
319 iterator= *stack_head;
320
321 /* 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);
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 /* Swap the two top elements on the stack. */
364 extern void swap(stackitem** stack_head)
365 {
366 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()
440 {
441 stackitem* s= NULL;
442 hashtbl myhash;
443 char in_string[100];
444
445 init_hashtbl(myhash);
446
447 printf("okidok\n ");
448
449 while(fgets(in_string, 100, stdin) != NULL) {
450 stack_read(&s, myhash, in_string);
451 printf("okidok\n ");
452 }
453
454 exit(EXIT_SUCCESS);
455 }
456
457 /* Local Variables: */
458 /* compile-command:"make CFLAGS=\"-Wall -g -rdynamic -ldl\" stack" */
459 /* End: */

root@recompile.se
ViewVC Help
Powered by ViewVC 1.1.26