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

Contents of /stack/stack.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.26 - (show 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 /* 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(1){
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 }
77
78 /* Generic push function. */
79 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 /* Push a value on the stack. */
87 int push_val(stackitem** stack_head, int in_val)
88 {
89 stackitem* new_item= malloc(sizeof(stackitem));
90 assert(new_item != NULL);
91 new_item->content.val= in_val;
92 new_item->type= value;
93
94 push(stack_head, new_item);
95 return 1;
96 }
97
98 /* Copy a string onto the stack. */
99 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 /* Create a new hash entry. */
111 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 /* Define a new function in the hash table. */
122 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 /* Define a new symbol in the hash table. */
133 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 /* Push a reference to an entry in the hash table onto the stack. */
142 int push_ref(stackitem** stack_head, hashtbl in_hash, const char* in_string)
143 {
144 static void* handle= NULL;
145 void* symbol;
146
147 stackitem* new_item= malloc(sizeof(stackitem));
148 new_item->content.ptr= *hash(in_hash, in_string);
149 new_item->type= ref;
150
151 if(new_item->content.ptr==NULL) { /* If hash entry empty */
152 if(handle==NULL) /* If no handle */
153 handle= dlopen(NULL, RTLD_LAZY);
154
155 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 else
159 def_sym(in_hash, in_string); /* Make symbol */
160
161 new_item->content.ptr= *hash(in_hash, in_string); /* The new reference
162 shouldn't point at
163 NULL */
164 new_item->type= ref;
165 }
166
167 push(stack_head, new_item);
168 return 1;
169 }
170
171 void printerr(const char* in_string) {
172 fprintf(stderr, "Err: %s\n", in_string);
173 }
174
175 /* Discard the top element of the stack. */
176 extern void toss(stackitem** stack_head)
177 {
178 stackitem* temp= *stack_head;
179
180 if((*stack_head)==NULL) {
181 printerr("Stack empty");
182 return;
183 }
184
185 if((*stack_head)->type==string)
186 free((*stack_head)->content.ptr);
187
188 *stack_head= (*stack_head)->next;
189 free(temp);
190 }
191
192 /* Print newline. */
193 extern void nl()
194 {
195 printf("\n");
196 }
197
198 /* Prints the top element of the stack. */
199 extern void print_(stackitem** stack_head)
200 {
201 stackitem* temp= *stack_head;
202
203 if(temp==NULL) {
204 printerr("Stack empty");
205 return;
206 }
207
208 while(temp->type==ref) {
209 temp= temp->content.ptr;
210
211 if(temp->type!=ref) {
212 printf("ref-> %s", temp->id);
213 return;
214 }
215 }
216
217 switch(temp->type) {
218 case value:
219 printf("%d", temp->content.val);
220 break;
221 case string:
222 printf("\"%s\"", (char*)temp->content.ptr);
223 break;
224 case symbol:
225 case func:
226 printf("%s", temp->id);
227 break;
228 default:
229 printf("%p", temp->content.ptr);
230 break;
231 }
232 }
233
234 /* Prints the top element of the stack and then discards it. */
235 extern void print(stackitem** stack_head)
236 {
237 print_(stack_head);
238 toss(stack_head);
239 }
240
241 /* Only to be called by function printstack. */
242 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 print_(&stack_head);
249 nl();
250 }
251
252 /* Prints the stack. */
253 extern void printstack(stackitem** stack_head)
254 {
255 if(*stack_head != NULL) {
256 print_st(*stack_head, 1);
257 nl();
258 } else {
259 printerr("Stack empty");
260 }
261 }
262
263 /* 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 /* If the top element is a reference, determine if it's a reference to a
293 function, and if it is, toss the reference and execute the function. */
294 extern void eval(stackitem** stack_head)
295 {
296 funcp in_func;
297 stackitem* temp= *stack_head;
298
299 if(temp==NULL) {
300 printerr("Stack empty");
301 return;
302 }
303
304 while(temp->type==ref)
305 temp= temp->content.ptr;
306
307 if(temp->type==func) {
308 in_func= (funcp)(temp->content.ptr);
309 toss(stack_head);
310 (*in_func)(stack_head);
311 return;
312 }
313
314 push(stack_head, copy(temp));
315 swap(stack_head);
316 toss(stack_head);
317 }
318
319 /* 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 if(iterator==NULL || iterator->content.ptr==delimiter) {
331 temp= NULL;
332 toss(stack_head);
333 } 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
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 /* Parse input. */
356 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 static int non_eval_flag= 0;
363
364 temp= malloc(inlength);
365 rest= malloc(inlength);
366
367 do {
368 /* If string */
369 if((convert= sscanf(in_line, "\"%[^\"\n\r]\" %[^\n\r]", temp, rest))) {
370 push_cstring(stack_head, temp);
371 break;
372 }
373 /* If value */
374 if((convert= sscanf(in_line, "%d %[^\n\r]", &itemp, rest))) {
375 push_val(stack_head, itemp);
376 break;
377 }
378 /* Escape ';' with '\' */
379 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 /* If symbol */
385 if((convert= sscanf(in_line, "%[^][ ;\n\r]%[^\n\r]", temp, rest))) {
386 push_ref(stack_head, in_hash, temp);
387 break;
388 }
389 /* If single char */
390 if((convert= sscanf(in_line, "%c%[^\n\r]", temp, rest))) {
391 if(*temp==';') {
392 if(!non_eval_flag) {
393 eval(stack_head); /* Evaluate top element */
394 break;
395 }
396
397 push_ref(stack_head, in_hash, ";");
398 break;
399 }
400
401 if(*temp==']') {
402 push_ref(stack_head, in_hash, "[");
403 pack(stack_head);
404 if(non_eval_flag!=0)
405 non_eval_flag--;
406 break;
407 }
408
409 if(*temp=='[') {
410 push_ref(stack_head, in_hash, "[");
411 non_eval_flag++;
412 break;
413 }
414 }
415 } while(0);
416
417
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 }
430
431 /* Relocate elements of the list on the stack. */
432 extern void expand(stackitem** stack_head)
433 {
434 stackitem *temp, *new_head;
435
436 /* Is top element a list? */
437 if((*stack_head)==NULL || (*stack_head)->type!=list) {
438 printerr("Stack empty or not a list");
439 return;
440 }
441
442 /* The first list element is the new stack head */
443 new_head= temp= (*stack_head)->content.ptr;
444 toss(stack_head);
445
446 if(temp==NULL)
447 return;
448
449 /* Search the end of the list */
450 while(temp->next!=NULL)
451 temp= temp->next;
452
453 /* Connect the the tail of the list with the old stack head */
454 temp->next= *stack_head;
455 *stack_head= new_head; /* ...and voila! */
456 }
457
458 /* Compares two elements by reference. */
459 extern void eq(stackitem** stack_head)
460 {
461 void *left, *right;
462 int result;
463
464 if((*stack_head)==NULL || (*stack_head)->next==NULL) {
465 printerr("Not enough elements to compare");
466 return;
467 }
468
469 left= (*stack_head)->content.ptr;
470 swap(stack_head);
471 right= (*stack_head)->content.ptr;
472 result= (left==right);
473
474 toss(stack_head); toss(stack_head);
475 push_val(stack_head, (left==right));
476 }
477
478 /* Negates the top element on the stack. */
479 extern void not(stackitem** stack_head)
480 {
481 int value;
482
483 if((*stack_head)==NULL || (*stack_head)->type!=value) {
484 printerr("Stack empty or element is not a value");
485 return;
486 }
487
488 value= (*stack_head)->content.val;
489 toss(stack_head);
490 push_val(stack_head, !value);
491 }
492
493 /* Compares the two top elements on the stack and return 0 if they're the
494 same. */
495 extern void neq(stackitem** stack_head)
496 {
497 eq(stack_head);
498 not(stack_head);
499 }
500
501 /* Give a symbol some content. */
502 extern void def(stackitem** stack_head)
503 {
504 stackitem *temp, *value;
505
506 if(*stack_head==NULL || (*stack_head)->next==NULL
507 || (*stack_head)->type!=ref) {
508 printerr("Define what?");
509 return;
510 }
511
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
521 /* Quit stack. */
522 extern void quit()
523 {
524 exit(EXIT_SUCCESS);
525 }
526
527 /* Clear stack */
528 extern void clear(stackitem** stack_head)
529 {
530 while(*stack_head!=NULL)
531 toss(stack_head);
532 }
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 exit(EXIT_SUCCESS);
550 }
551
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