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

Annotation of /stack/stack.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.34 - (hide annotations)
Tue Feb 5 23:26:46 2002 UTC (22 years, 2 months ago) by masse
Branch: MAIN
Changes since 1.33: +28 -2 lines
File MIME type: text/plain
Added funtion 'forget'.

1 masse 1.1 /* printf */
2     #include <stdio.h>
3     /* EXIT_SUCCESS */
4     #include <stdlib.h>
5     /* NULL */
6     #include <stddef.h>
7 teddy 1.3 /* dlopen, dlsym, dlerror */
8 masse 1.1 #include <dlfcn.h>
9 teddy 1.18 /* assert */
10     #include <assert.h>
11 masse 1.1
12     #define HASHTBLSIZE 65536
13    
14 teddy 1.28 /* First, define some types. */
15    
16     /* A value of some type */
17     typedef struct {
18 masse 1.16 enum {
19 teddy 1.28 integer,
20 teddy 1.18 string,
21     ref, /* Reference (to an element in the
22     hash table) */
23 masse 1.16 func, /* Function pointer */
24 teddy 1.28 symb,
25 masse 1.16 list
26 teddy 1.18 } type; /* Type of stack element */
27    
28 masse 1.1 union {
29 teddy 1.28 void *ptr; /* Pointer to the content */
30 masse 1.16 int val; /* ...or an integer */
31     } content; /* Stores a pointer or an integer */
32 masse 1.1
33 teddy 1.28 int refcount; /* Reference counter */
34    
35     } value;
36    
37     /* A symbol with a name and possible value */
38     /* (These do not need reference counters, they are kept unique by
39     hashing.) */
40     typedef struct symbol_struct {
41     char *id; /* Symbol name */
42     value *val; /* The value (if any) bound to it */
43     struct symbol_struct *next; /* In case of hashing conflicts, a */
44     } symbol; /* symbol is a kind of stack item. */
45    
46     /* A type for a hash table for symbols */
47     typedef symbol *hashtbl[HASHTBLSIZE]; /* Hash table declaration */
48    
49     /* An item (value) on a stack */
50     typedef struct stackitem_struct
51     {
52     value *item; /* The value on the stack */
53     struct stackitem_struct *next; /* Next item */
54 masse 1.1 } stackitem;
55    
56 teddy 1.28 /* An environment; gives access to the stack and a hash table of
57     defined symbols */
58     typedef struct {
59     stackitem *head; /* Head of the stack */
60     hashtbl symbols; /* Hash table of all variable bindings */
61 teddy 1.33 int err; /* Error flag */
62 teddy 1.28 } environment;
63    
64     /* A type for pointers to external functions */
65     typedef void (*funcp)(environment *); /* funcp is a pointer to a void
66     function (environment *) */
67 masse 1.1
68 teddy 1.28 /* Initialize a newly created environment */
69     void init_env(environment *env)
70 masse 1.1 {
71     long i;
72    
73     for(i= 0; i<HASHTBLSIZE; i++)
74 teddy 1.28 env->symbols[i]= NULL;
75 masse 1.1 }
76    
77 teddy 1.27 /* Returns a pointer to a pointer to an element in the hash table. */
78 teddy 1.28 symbol **hash(hashtbl in_hashtbl, const char *in_string)
79 masse 1.1 {
80     long i= 0;
81     unsigned long out_hash= 0;
82 teddy 1.18 char key= '\0';
83 teddy 1.28 symbol **position;
84 masse 1.1
85 masse 1.16 while(1){ /* Hash in_string */
86 masse 1.1 key= in_string[i++];
87     if(key=='\0')
88     break;
89     out_hash= out_hash*32+key;
90     }
91    
92     out_hash= out_hash%HASHTBLSIZE;
93     position= &(in_hashtbl[out_hash]);
94    
95 masse 1.25 while(1){
96 teddy 1.18 if(*position==NULL) /* If empty */
97 masse 1.1 return position;
98    
99 teddy 1.18 if(strcmp(in_string, (*position)->id)==0) /* If match */
100 masse 1.1 return position;
101    
102 masse 1.16 position= &((*position)->next); /* Try next */
103 masse 1.1 }
104     }
105    
106 masse 1.14 /* Generic push function. */
107 masse 1.1 int push(stackitem** stack_head, stackitem* in_item)
108     {
109     in_item->next= *stack_head;
110     *stack_head= in_item;
111     return 1;
112     }
113    
114 teddy 1.29 /* Push a value onto the stack */
115     void push_val(stackitem **stack_head, value *val)
116     {
117     stackitem *new_item= malloc(sizeof(stackitem));
118     new_item->item= val;
119     val->refcount++;
120     push(stack_head, new_item);
121     }
122    
123 teddy 1.28 /* Push an integer onto the stack. */
124 teddy 1.29 int push_int(stackitem **stack_head, int in_val)
125 masse 1.1 {
126 teddy 1.28 value *new_value= malloc(sizeof(value));
127     stackitem *new_item= malloc(sizeof(stackitem));
128     new_item->item= new_value;
129    
130     new_value->content.val= in_val;
131     new_value->type= integer;
132     new_value->refcount=1;
133 masse 1.1
134     push(stack_head, new_item);
135     return 1;
136     }
137    
138 masse 1.14 /* Copy a string onto the stack. */
139 teddy 1.28 int push_cstring(stackitem **stack_head, const char *in_string)
140 masse 1.1 {
141 teddy 1.28 value *new_value= malloc(sizeof(value));
142     stackitem *new_item= malloc(sizeof(stackitem));
143     new_item->item=new_value;
144    
145     new_value->content.ptr= malloc(strlen(in_string)+1);
146     strcpy(new_value->content.ptr, in_string);
147     new_value->type= string;
148     new_value->refcount=1;
149 masse 1.1
150     push(stack_head, new_item);
151     return 1;
152     }
153    
154 teddy 1.28 /* Push a symbol onto the stack. */
155     int push_sym(environment *env, const char *in_string)
156 masse 1.1 {
157 teddy 1.28 stackitem *new_item; /* The new stack item */
158     /* ...which will contain... */
159     value *new_value; /* A new symbol value */
160     /* ...which might point to... */
161 teddy 1.29 symbol **new_symbol; /* (if needed) A new actual symbol */
162 teddy 1.28 /* ...which, if possible, will be bound to... */
163     value *new_fvalue; /* (if needed) A new function value */
164     /* ...which will point to... */
165     void *funcptr; /* A function pointer */
166    
167     static void *handle= NULL; /* Dynamic linker handle */
168    
169     /* Create a new stack item containing a new value */
170     new_item= malloc(sizeof(stackitem));
171     new_value= malloc(sizeof(value));
172     new_item->item=new_value;
173    
174     /* The new value is a symbol */
175     new_value->type= symb;
176     new_value->refcount= 1;
177    
178     /* Look up the symbol name in the hash table */
179 teddy 1.29 new_symbol= hash(env->symbols, in_string);
180     new_value->content.ptr= *new_symbol;
181 teddy 1.28
182 teddy 1.30 if(*new_symbol==NULL) { /* If symbol was undefined */
183 teddy 1.28
184     /* Create a new symbol */
185 teddy 1.30 (*new_symbol)= malloc(sizeof(symbol));
186 teddy 1.29 (*new_symbol)->val= NULL; /* undefined value */
187     (*new_symbol)->next= NULL;
188     (*new_symbol)->id= malloc(strlen(in_string)+1);
189     strcpy((*new_symbol)->id, in_string);
190 masse 1.1
191 teddy 1.28 /* Intern the new symbol in the hash table */
192 teddy 1.29 new_value->content.ptr= *new_symbol;
193 masse 1.1
194 teddy 1.28 /* Try to load the symbol name as an external function, to see if
195     we should bind the symbol to a new function pointer value */
196 masse 1.16 if(handle==NULL) /* If no handle */
197 teddy 1.28 handle= dlopen(NULL, RTLD_LAZY);
198 masse 1.6
199 teddy 1.28 funcptr= dlsym(handle, in_string); /* Get function pointer */
200     if(dlerror()==NULL) { /* If a function was found */
201     new_fvalue= malloc(sizeof(value)); /* Create a new value */
202     new_fvalue->type=func; /* The new value is a function pointer */
203     new_fvalue->content.ptr=funcptr; /* Store function pointer */
204 teddy 1.29 (*new_symbol)->val= new_fvalue; /* Bind the symbol to the new
205     function value */
206 teddy 1.28 new_fvalue->refcount= 1;
207     }
208 masse 1.1 }
209 teddy 1.28 push(&(env->head), new_item);
210 masse 1.1 return 1;
211     }
212    
213 masse 1.17 void printerr(const char* in_string) {
214     fprintf(stderr, "Err: %s\n", in_string);
215     }
216    
217 teddy 1.28 /* Throw away a value */
218     void free_val(value *val){
219     stackitem *item, *temp;
220    
221     val->refcount--; /* Decrease the reference count */
222     if(val->refcount == 0){
223     switch (val->type){ /* and free the contents if necessary */
224     case string:
225     free(val->content.ptr);
226     case list: /* lists needs to be freed recursively */
227     item=val->content.ptr;
228     while(item != NULL) { /* for all stack items */
229     free_val(item->item); /* free the value */
230     temp=item->next; /* save next ptr */
231     free(item); /* free the stackitem */
232     item=temp; /* go to next stackitem */
233     }
234     free(val); /* Free the actual list value */
235     break;
236     default:
237     break;
238     }
239     }
240     }
241    
242 masse 1.14 /* Discard the top element of the stack. */
243 teddy 1.28 extern void toss(environment *env)
244 masse 1.1 {
245 teddy 1.28 stackitem *temp= env->head;
246 masse 1.1
247 teddy 1.28 if((env->head)==NULL) {
248 masse 1.17 printerr("Stack empty");
249 masse 1.7 return;
250 masse 1.17 }
251 masse 1.7
252 teddy 1.28 free_val(env->head->item); /* Free the value */
253     env->head= env->head->next; /* Remove the top stack item */
254     free(temp); /* Free the old top stack item */
255 masse 1.1 }
256    
257 masse 1.14 /* Print newline. */
258 masse 1.34 extern void nl()
259 masse 1.8 {
260     printf("\n");
261     }
262 masse 1.1
263 masse 1.14 /* Prints the top element of the stack. */
264 teddy 1.28 void print_h(stackitem *stack_head)
265 masse 1.8 {
266 masse 1.23
267 teddy 1.28 if(stack_head==NULL) {
268 masse 1.17 printerr("Stack empty");
269 masse 1.8 return;
270 masse 1.17 }
271 masse 1.1
272 teddy 1.28 switch(stack_head->item->type) {
273     case integer:
274     printf("%d", stack_head->item->content.val);
275 teddy 1.2 break;
276     case string:
277 teddy 1.28 printf("\"%s\"", (char*)stack_head->item->content.ptr);
278 teddy 1.2 break;
279 teddy 1.28 case symb:
280     printf("'%s'", ((symbol *)(stack_head->item->content.ptr))->id);
281 masse 1.6 break;
282 masse 1.7 default:
283 teddy 1.28 printf("%p", (funcp)(stack_head->item->content.ptr));
284 teddy 1.2 break;
285     }
286 masse 1.1 }
287    
288 teddy 1.28 extern void print_(environment *env) {
289     print_h(env->head);
290     }
291    
292 masse 1.14 /* Prints the top element of the stack and then discards it. */
293 teddy 1.28 extern void print(environment *env)
294 masse 1.8 {
295 teddy 1.28 print_(env);
296     toss(env);
297 masse 1.8 }
298    
299 masse 1.14 /* Only to be called by function printstack. */
300 teddy 1.28 void print_st(stackitem *stack_head, long counter)
301 masse 1.8 {
302     if(stack_head->next != NULL)
303     print_st(stack_head->next, counter+1);
304     printf("%ld: ", counter);
305 teddy 1.28 print_h(stack_head);
306 masse 1.8 nl();
307     }
308    
309 teddy 1.28
310    
311 masse 1.14 /* Prints the stack. */
312 teddy 1.28 extern void printstack(environment *env)
313 masse 1.1 {
314 teddy 1.28 if(env->head != NULL) {
315     print_st(env->head, 1);
316 masse 1.21 nl();
317 masse 1.17 } else {
318     printerr("Stack empty");
319 masse 1.1 }
320     }
321    
322 masse 1.26 /* Swap the two top elements on the stack. */
323 teddy 1.28 extern void swap(environment *env)
324 masse 1.26 {
325 teddy 1.28 stackitem *temp= env->head;
326 masse 1.26
327 teddy 1.28 if((env->head)==NULL) {
328 masse 1.26 printerr("Stack empty");
329     return;
330     }
331    
332 teddy 1.28 if(env->head->next==NULL) {
333     printerr("Not enough arguments");
334 masse 1.26 return;
335 teddy 1.28 }
336 masse 1.26
337 teddy 1.28 env->head= env->head->next;
338     temp->next= env->head->next;
339     env->head->next= temp;
340 masse 1.26 }
341    
342     stackitem* copy(stackitem* in_item)
343     {
344 teddy 1.28 stackitem *out_item= malloc(sizeof(stackitem));
345 masse 1.26
346     memcpy(out_item, in_item, sizeof(stackitem));
347     out_item->next= NULL;
348    
349     return out_item;
350     }
351    
352 teddy 1.33 /* Recall a value from a symbol, if bound */
353 teddy 1.31 extern void rcl(environment *env)
354     {
355     value *val;
356    
357     if(env->head == NULL) {
358     printerr("Stack empty");
359     return;
360     }
361    
362     if(env->head->item->type!=symb) {
363     printerr("Not a symbol");
364     return;
365     }
366     val=((symbol *)(env->head->item->content.ptr))->val;
367 teddy 1.33 if(val == NULL){
368     printerr("Unbound variable");
369     return;
370     }
371 teddy 1.31 toss(env); /* toss the symbol */
372     push_val(&(env->head), val); /* Return its bound value */
373     }
374 masse 1.26
375 teddy 1.29 /* If the top element is a symbol, determine if it's bound to a
376     function value, and if it is, toss the symbol and execute the
377     function. */
378 teddy 1.28 extern void eval(environment *env)
379 masse 1.1 {
380     funcp in_func;
381 teddy 1.29 value* val;
382     if(env->head==NULL) {
383 masse 1.22 printerr("Stack empty");
384 masse 1.1 return;
385 masse 1.17 }
386 masse 1.1
387 teddy 1.29 /* if it's a symbol */
388     if(env->head->item->type==symb) {
389    
390     /* If it's not bound to anything */
391     if (((symbol *)(env->head->item->content.ptr))->val == NULL) {
392     printerr("Unbound variable");
393     return;
394     }
395    
396     /* If it contains a function */
397     if (((symbol *)(env->head->item->content.ptr))->val->type == func) {
398     in_func=
399     (funcp)(((symbol *)(env->head->item->content.ptr))->val->content.ptr);
400     toss(env);
401     (*in_func)(env); /* Run the function */
402     return;
403     } else { /* If it's not a function */
404     val=((symbol *)(env->head->item->content.ptr))->val;
405     toss(env); /* toss the symbol */
406     push_val(&(env->head), val); /* Return its bound value */
407     }
408 teddy 1.28 }
409 masse 1.22
410 teddy 1.29 /* If it's a lone function value, run it */
411     if(env->head->item->type==func) {
412     in_func= (funcp)(env->head->item->content.ptr);
413 teddy 1.28 toss(env);
414     (*in_func)(env);
415 masse 1.1 return;
416 masse 1.26 }
417    
418 masse 1.1 }
419    
420 masse 1.19 /* Make a list. */
421 teddy 1.28 extern void pack(environment *env)
422 masse 1.19 {
423     void* delimiter;
424 teddy 1.28 stackitem *iterator, *temp;
425     value *pack;
426 masse 1.19
427 teddy 1.28 delimiter= env->head->item->content.ptr; /* Get delimiter */
428     toss(env);
429 masse 1.19
430 teddy 1.28 iterator= env->head;
431 masse 1.19
432 teddy 1.28 if(iterator==NULL || iterator->item->content.ptr==delimiter) {
433 masse 1.24 temp= NULL;
434 teddy 1.28 toss(env);
435 masse 1.24 } else {
436     /* Search for first delimiter */
437 teddy 1.28 while(iterator->next!=NULL
438     && iterator->next->item->content.ptr!=delimiter)
439 masse 1.24 iterator= iterator->next;
440    
441     /* Extract list */
442 teddy 1.28 temp= env->head;
443     env->head= iterator->next;
444 masse 1.24 iterator->next= NULL;
445    
446 teddy 1.28 if(env->head!=NULL)
447     toss(env);
448 masse 1.24 }
449 masse 1.19
450     /* Push list */
451 teddy 1.28 pack= malloc(sizeof(value));
452 masse 1.19 pack->type= list;
453     pack->content.ptr= temp;
454 teddy 1.28 pack->refcount= 1;
455    
456     temp= malloc(sizeof(stackitem));
457     temp->item= pack;
458 masse 1.19
459 teddy 1.28 push(&(env->head), temp);
460 masse 1.19 }
461    
462 masse 1.14 /* Parse input. */
463 teddy 1.28 int stack_read(environment *env, char *in_line)
464 masse 1.1 {
465     char *temp, *rest;
466     int itemp;
467     size_t inlength= strlen(in_line)+1;
468     int convert= 0;
469 masse 1.20 static int non_eval_flag= 0;
470 masse 1.1
471     temp= malloc(inlength);
472     rest= malloc(inlength);
473    
474 masse 1.15 do {
475 masse 1.16 /* If string */
476 masse 1.15 if((convert= sscanf(in_line, "\"%[^\"\n\r]\" %[^\n\r]", temp, rest))) {
477 teddy 1.28 push_cstring(&(env->head), temp);
478 masse 1.15 break;
479     }
480 teddy 1.28 /* If integer */
481 masse 1.15 if((convert= sscanf(in_line, "%d %[^\n\r]", &itemp, rest))) {
482 teddy 1.29 push_int(&(env->head), itemp);
483 masse 1.15 break;
484     }
485 masse 1.16 /* Escape ';' with '\' */
486 masse 1.15 if((convert= sscanf(in_line, "\\%c%[^\n\r]", temp, rest))) {
487 teddy 1.28 temp[1]= '\0';
488     push_sym(env, temp);
489 masse 1.15 break;
490     }
491 masse 1.16 /* If symbol */
492 masse 1.34 if((convert= sscanf(in_line, "%[^][ ;\n\r]%[^\n\r]", temp, rest))) {
493 teddy 1.28 push_sym(env, temp);
494 masse 1.15 break;
495     }
496 masse 1.19 /* If single char */
497     if((convert= sscanf(in_line, "%c%[^\n\r]", temp, rest))) {
498     if(*temp==';') {
499 masse 1.21 if(!non_eval_flag) {
500 teddy 1.28 eval(env); /* Evaluate top element */
501 masse 1.20 break;
502     }
503    
504 teddy 1.28 push_sym(env, ";");
505 masse 1.19 break;
506     }
507    
508     if(*temp==']') {
509 teddy 1.28 push_sym(env, "[");
510     pack(env);
511 masse 1.21 if(non_eval_flag!=0)
512     non_eval_flag--;
513 masse 1.20 break;
514     }
515    
516     if(*temp=='[') {
517 teddy 1.28 push_sym(env, "[");
518 masse 1.20 non_eval_flag++;
519 masse 1.19 break;
520     }
521 masse 1.15 }
522     } while(0);
523    
524 masse 1.1
525     free(temp);
526    
527     if(convert<2) {
528     free(rest);
529     return 0;
530     }
531    
532 teddy 1.28 stack_read(env, rest);
533 masse 1.1
534     free(rest);
535     return 1;
536 masse 1.7 }
537 masse 1.1
538 masse 1.16 /* Relocate elements of the list on the stack. */
539 teddy 1.28 extern void expand(environment *env)
540 masse 1.1 {
541 masse 1.8 stackitem *temp, *new_head;
542    
543 masse 1.16 /* Is top element a list? */
544 teddy 1.28 if(env->head==NULL || env->head->item->type!=list) {
545 masse 1.17 printerr("Stack empty or not a list");
546 masse 1.8 return;
547 masse 1.17 }
548 masse 1.8
549 masse 1.16 /* The first list element is the new stack head */
550 teddy 1.28 new_head= temp= env->head->item->content.ptr;
551 masse 1.8
552 teddy 1.28 env->head->item->refcount++;
553     toss(env);
554 masse 1.24
555 teddy 1.28 /* Find the end of the list */
556 masse 1.8 while(temp->next!=NULL)
557     temp= temp->next;
558    
559 teddy 1.28 /* Connect the tail of the list with the old stack head */
560     temp->next= env->head;
561     env->head= new_head; /* ...and voila! */
562    
563 teddy 1.5 }
564 masse 1.11
565 masse 1.14 /* Compares two elements by reference. */
566 teddy 1.28 extern void eq(environment *env)
567 masse 1.11 {
568     void *left, *right;
569     int result;
570    
571 teddy 1.28 if((env->head)==NULL || env->head->next==NULL) {
572 masse 1.17 printerr("Not enough elements to compare");
573 masse 1.11 return;
574 masse 1.17 }
575 masse 1.11
576 teddy 1.28 left= env->head->item->content.ptr;
577     swap(env);
578     right= env->head->item->content.ptr;
579 masse 1.11 result= (left==right);
580    
581 teddy 1.28 toss(env); toss(env);
582 teddy 1.29 push_int(&(env->head), result);
583 masse 1.11 }
584    
585 masse 1.14 /* Negates the top element on the stack. */
586 teddy 1.28 extern void not(environment *env)
587 masse 1.11 {
588 teddy 1.28 int val;
589 masse 1.11
590 teddy 1.28 if((env->head)==NULL || env->head->item->type!=integer) {
591     printerr("Stack empty or element is not a integer");
592 masse 1.11 return;
593 masse 1.17 }
594 masse 1.11
595 teddy 1.28 val= env->head->item->content.val;
596     toss(env);
597 teddy 1.29 push_int(&(env->head), !val);
598 masse 1.11 }
599    
600 masse 1.14 /* Compares the two top elements on the stack and return 0 if they're the
601     same. */
602 teddy 1.28 extern void neq(environment *env)
603 masse 1.11 {
604 teddy 1.28 eq(env);
605     not(env);
606 masse 1.11 }
607 masse 1.12
608 masse 1.14 /* Give a symbol some content. */
609 teddy 1.28 extern void def(environment *env)
610 masse 1.12 {
611 teddy 1.28 symbol *sym;
612 masse 1.12
613 teddy 1.28 /* Needs two values on the stack, the top one must be a symbol */
614     if(env->head==NULL || env->head->next==NULL
615     || env->head->item->type!=symb) {
616 masse 1.17 printerr("Define what?");
617 masse 1.12 return;
618 masse 1.17 }
619 masse 1.12
620 teddy 1.28 /* long names are a pain */
621     sym=env->head->item->content.ptr;
622    
623     /* if the symbol was bound to something else, throw it away */
624     if(sym->val != NULL)
625     free_val(sym->val);
626    
627     /* Bind the symbol to the value */
628     sym->val= env->head->next->item;
629     sym->val->refcount++; /* Increase the reference counter */
630 masse 1.12
631 teddy 1.28 toss(env); toss(env);
632 masse 1.12 }
633 masse 1.10
634 masse 1.14 /* Quit stack. */
635 teddy 1.28 extern void quit(environment *env)
636 teddy 1.5 {
637     exit(EXIT_SUCCESS);
638 masse 1.24 }
639    
640     /* Clear stack */
641 teddy 1.28 extern void clear(environment *env)
642 masse 1.24 {
643 teddy 1.28 while(env->head!=NULL)
644     toss(env);
645 masse 1.1 }
646    
647 teddy 1.33 /* List all defined words */
648 masse 1.32 extern void words(environment *env)
649     {
650     symbol *temp;
651     int i;
652    
653     for(i= 0; i<HASHTBLSIZE; i++) {
654     temp= env->symbols[i];
655     while(temp!=NULL) {
656     printf("%s\n", temp->id);
657     temp= temp->next;
658     }
659     }
660     }
661 masse 1.34
662     /* Forgets a symbol (remove it from the hash table) */
663     extern void forget(environment *env)
664     {
665     char* sym_id;
666     stackitem *stack_head= env->head;
667     symbol **hash_entry, *temp;
668    
669     if(stack_head==NULL || stack_head->item->type!=symb) {
670     printerr("Stack empty or not a symbol");
671     return;
672     }
673    
674     sym_id= ((symbol*)(stack_head->item->content.ptr))->id;
675     toss(env);
676    
677     hash_entry= hash(env->symbols, sym_id);
678     temp= *hash_entry;
679     *hash_entry= (*hash_entry)->next;
680    
681     if(temp->val!=NULL) {
682     free_val(temp->val);
683     }
684     free(temp->id);
685     free(temp);
686     }
687 masse 1.32
688 masse 1.1 int main()
689     {
690 teddy 1.28 environment myenv;
691 masse 1.1 char in_string[100];
692    
693 teddy 1.28 init_env(&myenv);
694 masse 1.1
695     printf("okidok\n ");
696    
697     while(fgets(in_string, 100, stdin) != NULL) {
698 teddy 1.28 stack_read(&myenv, in_string);
699 masse 1.1 printf("okidok\n ");
700     }
701    
702 masse 1.10 exit(EXIT_SUCCESS);
703 masse 1.1 }

root@recompile.se
ViewVC Help
Powered by ViewVC 1.1.26