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

Contents of /stack/stack.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.14 - (show annotations)
Thu Jan 31 19:51:12 2002 UTC (22 years, 3 months ago) by masse
Branch: MAIN
Changes since 1.13: +29 -3 lines
File MIME type: text/plain
Added comments to the code.

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 if((convert= sscanf(in_line, "\"%[^\"\n\r]\" %[^\n\r]", temp, rest)) >= 1)
259 push_cstring(stack_head, temp);
260 else if((convert= sscanf(in_line, "%d %[^\n\r]", &itemp, rest)) >= 1)
261 push_val(stack_head, itemp);
262 else if((convert= sscanf(in_line, "\\%c%[^\n\r]", temp, rest)) >= 1) {
263 temp[1]= '\0'; push_ref(stack_head, in_hash, temp);
264 } else if((convert= sscanf(in_line, "%[^ ;\n\r]%[^\n\r]", temp, rest)) >= 1)
265 push_ref(stack_head, in_hash, temp);
266 else if((convert= sscanf(in_line, "%c%[^\n\r]", temp, rest)) >= 1)
267 if(*temp==';')
268 eval(stack_head);
269
270 free(temp);
271
272 if(convert<2) {
273 free(rest);
274 return 0;
275 }
276
277 stack_read(stack_head, in_hash, rest);
278
279 free(rest);
280 return 1;
281 }
282
283 /* Make a list. */
284 extern void pack(stackitem** stack_head)
285 {
286 void* delimiter;
287 stackitem *iterator, *temp, *pack;
288
289 if((*stack_head)==NULL)
290 return;
291
292 delimiter= (*stack_head)->content.ptr;
293 toss(stack_head);
294
295 iterator= *stack_head;
296
297 while(iterator->next!=NULL && iterator->next->content.ptr!=delimiter)
298 iterator= iterator->next;
299
300 temp= *stack_head;
301 *stack_head= iterator->next;
302 iterator->next= NULL;
303
304 if(*stack_head!=NULL && (*stack_head)->content.ptr==delimiter)
305 toss(stack_head);
306
307 pack= malloc(sizeof(stackitem));
308 pack->type= list;
309 pack->content.ptr= temp;
310
311 push(stack_head, pack);
312 }
313
314 /* Push elements of the list on the stack. */
315 extern void expand(stackitem** stack_head)
316 {
317 stackitem *temp, *new_head;
318
319 if((*stack_head)==NULL || (*stack_head)->type!=list)
320 return;
321
322 new_head= temp= (*stack_head)->content.ptr;
323 toss(stack_head);
324
325 while(temp->next!=NULL)
326 temp= temp->next;
327
328 temp->next= *stack_head;
329 *stack_head= new_head;
330 }
331
332 /* Swap the two top elements on the stack. */
333 extern void swap(stackitem** stack_head)
334 {
335 stackitem* temp= (*stack_head);
336
337 if((*stack_head)==NULL || (*stack_head)->next==NULL)
338 return;
339
340 *stack_head= (*stack_head)->next;
341 temp->next= (*stack_head)->next;
342 (*stack_head)->next= temp;
343 }
344
345 /* Compares two elements by reference. */
346 extern void eq(stackitem** stack_head)
347 {
348 void *left, *right;
349 int result;
350
351 if((*stack_head)==NULL || (*stack_head)->next==NULL)
352 return;
353
354 left= (*stack_head)->content.ptr;
355 swap(stack_head);
356 right= (*stack_head)->content.ptr;
357 result= (left==right);
358
359 toss(stack_head); toss(stack_head);
360 push_val(stack_head, (left==right));
361 }
362
363 /* Negates the top element on the stack. */
364 extern void not(stackitem** stack_head)
365 {
366 int value;
367
368 if((*stack_head)==NULL)
369 return;
370
371 value= (*stack_head)->content.val;
372 toss(stack_head);
373 push_val(stack_head, !value);
374 }
375
376 /* Compares the two top elements on the stack and return 0 if they're the
377 same. */
378 extern void neq(stackitem** stack_head)
379 {
380 eq(stack_head);
381 not(stack_head);
382 }
383
384 /* Give a symbol some content. */
385 extern void def(stackitem** stack_head)
386 {
387 stackitem *temp, *value;
388
389 if(*stack_head==NULL || (*stack_head)->next==NULL
390 || (*stack_head)->type!=ref)
391 return;
392
393 temp= (*stack_head)->content.ptr;
394 value= (*stack_head)->next;
395 temp->content= value->content;
396 value->content.ptr=NULL;
397 temp->type= value->type;
398
399 toss(stack_head); toss(stack_head);
400 }
401
402 /* Quit stack. */
403 extern void quit()
404 {
405 exit(EXIT_SUCCESS);
406 }
407
408 int main()
409 {
410 stackitem* s= NULL;
411 hashtbl myhash;
412 char in_string[100];
413
414 init_hashtbl(myhash);
415
416 printf("okidok\n ");
417
418 while(fgets(in_string, 100, stdin) != NULL) {
419 stack_read(&s, myhash, in_string);
420 printf("okidok\n ");
421 }
422
423 exit(EXIT_SUCCESS);
424 }
425
426 /* Local Variables: */
427 /* compile-command:"make CFLAGS=\"-Wall -g -rdynamic -ldl\" stack" */
428 /* End: */

root@recompile.se
ViewVC Help
Powered by ViewVC 1.1.26