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

Contents of /stack/stack.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.24 - (show annotations)
Sat Feb 2 19:30:07 2002 UTC (22 years, 3 months ago) by masse
Branch: MAIN
Changes since 1.23: +25 -15 lines
File MIME type: text/plain
Added possibility to make empty lists.

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

root@recompile.se
ViewVC Help
Powered by ViewVC 1.1.26