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

Contents of /stack/stack.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.17 - (show 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 /* 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 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)
171 {
172 stackitem* temp= *stack_head;
173
174 if((*stack_head)==NULL) {
175 printerr("Stack empty");
176 return;
177 }
178
179 if((*stack_head)->type==string)
180 free((*stack_head)->content.ptr);
181
182 *stack_head= (*stack_head)->next;
183 free(temp);
184 }
185
186 /* Print newline. */
187 extern void nl()
188 {
189 printf("\n");
190 }
191
192 /* Prints the top element of the stack. */
193 void print_(stackitem** stack_head)
194 {
195 if((*stack_head)==NULL) {
196 printerr("Stack empty");
197 return;
198 }
199
200 switch((*stack_head)->type) {
201 case value:
202 printf("%d", (*stack_head)->content.val);
203 break;
204 case string:
205 printf("%s", (char*)(*stack_head)->content.ptr);
206 break;
207 case ref:
208 printf("%s", ((stackitem*)(*stack_head)->content.ptr)->id);
209 break;
210 case symbol:
211 default:
212 printf("%p", (*stack_head)->content.ptr);
213 break;
214 }
215 }
216
217 /* Prints the top element of the stack and then discards it. */
218 extern void print(stackitem** stack_head)
219 {
220 print_(stack_head);
221 toss(stack_head);
222 }
223
224 /* Only to be called by function printstack. */
225 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 print_(&stack_head);
232 nl();
233 }
234
235 /* Prints the stack. */
236 extern void printstack(stackitem** stack_head)
237 {
238 if(*stack_head != NULL) {
239 print_st(*stack_head, 1);
240 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)
249 {
250 funcp in_func;
251
252 if((*stack_head)==NULL || (*stack_head)->type!=ref) {
253 printerr("Stack empty or not a reference");
254 return;
255 }
256
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 } else
263 printerr("Not a function");
264 }
265
266 /* Parse input. */
267 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 do {
278 /* If string */
279 if((convert= sscanf(in_line, "\"%[^\"\n\r]\" %[^\n\r]", temp, rest))) {
280 push_cstring(stack_head, temp);
281 break;
282 }
283 /* If value */
284 if((convert= sscanf(in_line, "%d %[^\n\r]", &itemp, rest))) {
285 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);
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 /* Make a list. */
321 extern void pack(stackitem** stack_head)
322 {
323 void* delimiter;
324 stackitem *iterator, *temp, *pack;
325
326 if((*stack_head)==NULL) {
327 printerr("Stack empty");
328 return;
329 }
330
331 delimiter= (*stack_head)->content.ptr; /* Get delimiter */
332 toss(stack_head);
333
334 iterator= *stack_head;
335
336 /* Search for first delimiter */
337 while(iterator->next!=NULL && iterator->next->content.ptr!=delimiter)
338 iterator= iterator->next;
339
340 /* Extract list */
341 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 /* Push list */
349 pack= malloc(sizeof(stackitem));
350 pack->type= list;
351 pack->content.ptr= temp;
352
353 push(stack_head, pack);
354 }
355
356 /* Relocate elements of the list on the stack. */
357 extern void expand(stackitem** stack_head)
358 {
359 stackitem *temp, *new_head;
360
361 /* Is top element a list? */
362 if((*stack_head)==NULL || (*stack_head)->type!=list) {
363 printerr("Stack empty or not a list");
364 return;
365 }
366
367 /* The first list element is the new stack head */
368 new_head= temp= (*stack_head)->content.ptr;
369 toss(stack_head);
370
371 /* Search the end of the list */
372 while(temp->next!=NULL)
373 temp= temp->next;
374
375 /* Connect the the tail of the list with the old stack head */
376 temp->next= *stack_head;
377 *stack_head= new_head; /* ...and voila! */
378 }
379
380 /* Swap the two top elements on the stack. */
381 extern void swap(stackitem** stack_head)
382 {
383 stackitem* temp= (*stack_head);
384
385 if((*stack_head)==NULL) {
386 printerr("Stack empty");
387 return;
388 }
389
390 if((*stack_head)->next==NULL)
391 return;
392
393 *stack_head= (*stack_head)->next;
394 temp->next= (*stack_head)->next;
395 (*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()
463 {
464 exit(EXIT_SUCCESS);
465 }
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 exit(EXIT_SUCCESS);
483 }
484
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