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

Contents of /stack/stack.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.15 - (show annotations)
Thu Jan 31 21:47:20 2002 UTC (22 years, 3 months ago) by masse
Branch: MAIN
Changes since 1.14: +27 -10 lines
File MIME type: text/plain
Made stack_read readable.

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 {value, string, ref, func, symbol, list} type;
15 union {
16 void* ptr;
17 int val;
18 } content;
19
20 char* id;
21 struct stack_item* next;
22 } stackitem;
23
24
25 typedef stackitem* hashtbl[HASHTBLSIZE];
26 typedef void (*funcp)(stackitem**);
27
28
29 /* Initiates a newly created hash table. */
30 void init_hashtbl(hashtbl out_hash)
31 {
32 long i;
33
34 for(i= 0; i<HASHTBLSIZE; i++)
35 out_hash[i]= NULL;
36 }
37
38 /* Returns a pointer to an element in the hash table. */
39 stackitem** hash(hashtbl in_hashtbl, const char* in_string)
40 {
41 long i= 0;
42 unsigned long out_hash= 0;
43 char key= 0;
44 stackitem** position;
45
46 while(1){
47 key= in_string[i++];
48 if(key=='\0')
49 break;
50 out_hash= out_hash*32+key;
51 }
52
53 out_hash= out_hash%HASHTBLSIZE;
54 position= &(in_hashtbl[out_hash]);
55
56 while(1){
57 if(*position==NULL)
58 return position;
59
60 if(strcmp(in_string, (*position)->id)==0)
61 return position;
62
63 position= &((*position)->next);
64 }
65 }
66
67 /* Generic push function. */
68 int push(stackitem** stack_head, stackitem* in_item)
69 {
70 in_item->next= *stack_head;
71 *stack_head= in_item;
72 return 1;
73 }
74
75 /* Push a value on the stack. */
76 int push_val(stackitem** stack_head, int in_val)
77 {
78 stackitem* new_item= malloc(sizeof(stackitem));
79 new_item->content.val= in_val;
80 new_item->type= value;
81
82 push(stack_head, new_item);
83 return 1;
84 }
85
86 /* Copy a string onto the stack. */
87 int push_cstring(stackitem** stack_head, const char* in_string)
88 {
89 stackitem* new_item= malloc(sizeof(stackitem));
90 new_item->content.ptr= malloc(strlen(in_string)+1);
91 strcpy(new_item->content.ptr, in_string);
92 new_item->type= string;
93
94 push(stack_head, new_item);
95 return 1;
96 }
97
98 /* Create a new hash entry. */
99 int mk_hashentry(hashtbl in_hashtbl, stackitem* in_item, const char* id)
100 {
101 in_item->id= malloc(strlen(id)+1);
102
103 strcpy(in_item->id, id);
104 push(hash(in_hashtbl, id), in_item);
105
106 return 1;
107 }
108
109 /* Define a function a new function in the hash table. */
110 void def_func(hashtbl in_hashtbl, funcp in_func, const char* id)
111 {
112 stackitem* temp= malloc(sizeof(stackitem));
113
114 temp->type= func;
115 temp->content.ptr= in_func;
116
117 mk_hashentry(in_hashtbl, temp, id);
118 }
119
120 /* Define a new symbol in the hash table. */
121 void def_sym(hashtbl in_hashtbl, const char* id)
122 {
123 stackitem* temp= malloc(sizeof(stackitem));
124
125 temp->type= symbol;
126
127 mk_hashentry(in_hashtbl, temp, id);
128 }
129
130 /* Push a reference to an entry in the hash table onto the stack. */
131 int push_ref(stackitem** stack_head, hashtbl in_hash, const char* in_string)
132 {
133 static void* handle= NULL;
134 void* symbol;
135
136 stackitem* new_item= malloc(sizeof(stackitem));
137 new_item->content.ptr= *hash(in_hash, in_string);
138 new_item->type= ref;
139
140 if(new_item->content.ptr==NULL) {
141 if(handle==NULL)
142 handle= dlopen(NULL, RTLD_LAZY);
143
144 symbol= dlsym(handle, in_string);
145 if(dlerror()==NULL)
146 def_func(in_hash, symbol, in_string);
147 else
148 def_sym(in_hash, in_string);
149
150 new_item->content.ptr= *hash(in_hash, in_string);
151 new_item->type= ref;
152 }
153
154 push(stack_head, new_item);
155 return 1;
156 }
157
158 /* Discard the top element of the stack. */
159 extern void toss(stackitem** stack_head)
160 {
161 stackitem* temp= *stack_head;
162
163 if((*stack_head)==NULL)
164 return;
165
166 if((*stack_head)->type==string)
167 free((*stack_head)->content.ptr);
168
169 *stack_head= (*stack_head)->next;
170 free(temp);
171 }
172
173 /* Print newline. */
174 extern void nl()
175 {
176 printf("\n");
177 }
178
179 /* Prints the top element of the stack. */
180 void print_(stackitem** stack_head)
181 {
182 if((*stack_head)==NULL)
183 return;
184
185 switch((*stack_head)->type) {
186 case value:
187 printf("%d", (*stack_head)->content.val);
188 break;
189 case string:
190 printf("%s", (char*)(*stack_head)->content.ptr);
191 break;
192 case ref:
193 printf("%s", ((stackitem*)(*stack_head)->content.ptr)->id);
194 break;
195 case symbol:
196 default:
197 printf("%p", (*stack_head)->content.ptr);
198 break;
199 }
200 }
201
202 /* Prints the top element of the stack and then discards it. */
203 extern void print(stackitem** stack_head)
204 {
205 print_(stack_head);
206 toss(stack_head);
207 }
208
209 /* Only to be called by function printstack. */
210 void print_st(stackitem* stack_head, long counter)
211 {
212 if(stack_head->next != NULL)
213 print_st(stack_head->next, counter+1);
214
215 printf("%ld: ", counter);
216 print_(&stack_head);
217 nl();
218 }
219
220 /* Prints the stack. */
221 extern void printstack(stackitem** stack_head)
222 {
223 if(*stack_head != NULL) {
224 print_st(*stack_head, 1);
225 printf("\n");
226 }
227 }
228
229 /* If the top element is a reference, determine if it's a reference to a
230 function, and if it is execute and pop the reference and execute the
231 function. */
232 extern void eval(stackitem** stack_head)
233 {
234 funcp in_func;
235
236 if((*stack_head)==NULL || (*stack_head)->type!=ref)
237 return;
238
239 if(((stackitem*)(*stack_head)->content.ptr)->type==func) {
240 in_func= (funcp)((stackitem*)(*stack_head)->content.ptr)->content.ptr;
241 toss(stack_head);
242 (*in_func)(stack_head);
243 return;
244 }
245 }
246
247 /* Parse input. */
248 int stack_read(stackitem** stack_head, hashtbl in_hash, char* in_line)
249 {
250 char *temp, *rest;
251 int itemp;
252 size_t inlength= strlen(in_line)+1;
253 int convert= 0;
254
255 temp= malloc(inlength);
256 rest= malloc(inlength);
257
258 do {
259 if((convert= sscanf(in_line, "\"%[^\"\n\r]\" %[^\n\r]", temp, rest))) {
260 push_cstring(stack_head, temp);
261 break;
262 }
263
264 if((convert= sscanf(in_line, "%d %[^\n\r]", &itemp, rest))) {
265 push_val(stack_head, itemp);
266 break;
267 }
268
269 if((convert= sscanf(in_line, "\\%c%[^\n\r]", temp, rest))) {
270 temp[1]= '\0';
271 push_ref(stack_head, in_hash, temp);
272 break;
273 }
274
275 if((convert= sscanf(in_line, "%[^ ;\n\r]%[^\n\r]", temp, rest))) {
276 push_ref(stack_head, in_hash, temp);
277 break;
278 }
279
280 if((convert= sscanf(in_line, "%c%[^\n\r]", temp, rest)) && *temp==';') {
281 eval(stack_head);
282 break;
283 }
284 } while(0);
285
286
287 free(temp);
288
289 if(convert<2) {
290 free(rest);
291 return 0;
292 }
293
294 stack_read(stack_head, in_hash, rest);
295
296 free(rest);
297 return 1;
298 }
299
300 /* Make a list. */
301 extern void pack(stackitem** stack_head)
302 {
303 void* delimiter;
304 stackitem *iterator, *temp, *pack;
305
306 if((*stack_head)==NULL)
307 return;
308
309 delimiter= (*stack_head)->content.ptr;
310 toss(stack_head);
311
312 iterator= *stack_head;
313
314 while(iterator->next!=NULL && iterator->next->content.ptr!=delimiter)
315 iterator= iterator->next;
316
317 temp= *stack_head;
318 *stack_head= iterator->next;
319 iterator->next= NULL;
320
321 if(*stack_head!=NULL && (*stack_head)->content.ptr==delimiter)
322 toss(stack_head);
323
324 pack= malloc(sizeof(stackitem));
325 pack->type= list;
326 pack->content.ptr= temp;
327
328 push(stack_head, pack);
329 }
330
331 /* Push elements of the list on the stack. */
332 extern void expand(stackitem** stack_head)
333 {
334 stackitem *temp, *new_head;
335
336 if((*stack_head)==NULL || (*stack_head)->type!=list)
337 return;
338
339 new_head= temp= (*stack_head)->content.ptr;
340 toss(stack_head);
341
342 while(temp->next!=NULL)
343 temp= temp->next;
344
345 temp->next= *stack_head;
346 *stack_head= new_head;
347 }
348
349 /* Swap the two top elements on the stack. */
350 extern void swap(stackitem** stack_head)
351 {
352 stackitem* temp= (*stack_head);
353
354 if((*stack_head)==NULL || (*stack_head)->next==NULL)
355 return;
356
357 *stack_head= (*stack_head)->next;
358 temp->next= (*stack_head)->next;
359 (*stack_head)->next= temp;
360 }
361
362 /* Compares two elements by reference. */
363 extern void eq(stackitem** stack_head)
364 {
365 void *left, *right;
366 int result;
367
368 if((*stack_head)==NULL || (*stack_head)->next==NULL)
369 return;
370
371 left= (*stack_head)->content.ptr;
372 swap(stack_head);
373 right= (*stack_head)->content.ptr;
374 result= (left==right);
375
376 toss(stack_head); toss(stack_head);
377 push_val(stack_head, (left==right));
378 }
379
380 /* Negates the top element on the stack. */
381 extern void not(stackitem** stack_head)
382 {
383 int value;
384
385 if((*stack_head)==NULL)
386 return;
387
388 value= (*stack_head)->content.val;
389 toss(stack_head);
390 push_val(stack_head, !value);
391 }
392
393 /* Compares the two top elements on the stack and return 0 if they're the
394 same. */
395 extern void neq(stackitem** stack_head)
396 {
397 eq(stack_head);
398 not(stack_head);
399 }
400
401 /* Give a symbol some content. */
402 extern void def(stackitem** stack_head)
403 {
404 stackitem *temp, *value;
405
406 if(*stack_head==NULL || (*stack_head)->next==NULL
407 || (*stack_head)->type!=ref)
408 return;
409
410 temp= (*stack_head)->content.ptr;
411 value= (*stack_head)->next;
412 temp->content= value->content;
413 value->content.ptr=NULL;
414 temp->type= value->type;
415
416 toss(stack_head); toss(stack_head);
417 }
418
419 /* Quit stack. */
420 extern void quit()
421 {
422 exit(EXIT_SUCCESS);
423 }
424
425 int main()
426 {
427 stackitem* s= NULL;
428 hashtbl myhash;
429 char in_string[100];
430
431 init_hashtbl(myhash);
432
433 printf("okidok\n ");
434
435 while(fgets(in_string, 100, stdin) != NULL) {
436 stack_read(&s, myhash, in_string);
437 printf("okidok\n ");
438 }
439
440 exit(EXIT_SUCCESS);
441 }
442
443 /* Local Variables: */
444 /* compile-command:"make CFLAGS=\"-Wall -g -rdynamic -ldl\" stack" */
445 /* End: */

root@recompile.se
ViewVC Help
Powered by ViewVC 1.1.26