11

Using a union

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. #include <assert.h>
  5.  
  6. typedef enum { INTEGER, STRING, REAL, POINTER } type;
  7.  
  8. typedef struct {
  9.     type type;
  10.     union {
  11.         int integer;
  12.         char *string;
  13.         float real;
  14.         void *pointer;
  15.     } x;
  16. } value;
  17.  
  18. typedef struct _stack {
  19.     int top;
  20.     int size;
  21.     value *data;
  22. } *stack;
  23.  
  24. stack stack_create(unsigned siz) {
  25.     stack sk = (stack)malloc(sizeof (struct _stack));
  26.     if (!sk)
  27.         return 0;
  28.  
  29.     sk->data = (value *)malloc(sizeof (value) * siz);
  30.     if (!sk->data)
  31.         return 0;
  32.  
  33.     sk->size = siz;
  34.     sk->top = 0;
  35.  
  36.     return sk;
  37. }
  38.  
  39. void stack_delete(stack sk) {
  40.     free(sk->data);
  41.     free(sk);
  42. }
  43.  
  44. void stack_push(stack sk, value v) {
  45.     assert(sk->top < sk->size);
  46.  
  47.     sk->data[sk->top++] = v;
  48. }
  49.  
  50. value stack_pop(stack sk) {
  51.     assert(sk->top > 0);
  52.  
  53.     return sk->data[--sk->top];
  54. }
  55.  
  56. void stack_add(stack sk) {
  57.     value v1 = stack_pop(sk), v2 = stack_pop(sk);
  58.  
  59.     assert((v1.type == INTEGER || v1.type == REAL) && v1.type == v2.type);
  60.  
  61.     if (v1.type == INTEGER)
  62.         v1.x.integer += v2.x.integer;
  63.     else
  64.         v1.x.real += v2.x.real;
  65.  
  66.     stack_push(sk, v1);
  67. }
  68.  
  69. void stack_exec(stack sk) {
  70.     value v = stack_pop(sk);
  71.  
  72.     assert(v.type == POINTER);
  73.  
  74.     ((void (*)(stack))(v.x.pointer))(sk);
  75. }
  76.  
  77. void stack_dot(stack sk) {
  78.     value v = stack_pop(sk);
  79.  
  80.     switch (v.type) {
  81.     case INTEGER:
  82.         fprintf(stdout, "%d", v.x.integer);
  83.         break;
  84.     case REAL:
  85.         fprintf(stdout, "%f", v.x.real);
  86.         break;
  87.     case STRING:
  88.         fputs(v.x.string, stdout);
  89.         break;
  90.     case POINTER:
  91.         fprintf(stdout, "0x%x", (unsigned)v.x.pointer);
  92.         break;
  93.     default:
  94.         break;
  95.     }
  96. }
  97.  
  98. #define STACKSIZE 100
  99.  
  100. main() {
  101.     stack sk;
  102.     value op1, op2, s, nl, pf;
  103.  
  104.     sk = stack_create(STACKSIZE);
  105.  
  106.     nl.type = STRING;
  107.     nl.x.string = "\n";
  108.     s.type = STRING;
  109.     s.x.string = " = ";
  110.  
  111.     op1.type = INTEGER;
  112.     op1.x.integer = 1;
  113.     op2.type = INTEGER;
  114.     op2.x.integer = 2;
  115.  
  116.     stack_push(sk, nl);
  117.     stack_push(sk, op1);
  118.     stack_push(sk, op2);
  119.     stack_add(sk);
  120.     stack_push(sk, s);
  121.     stack_dot(sk);
  122.     stack_dot(sk);
  123.     stack_dot(sk);
  124.  
  125.     op1.type = REAL;
  126.     op1.x.real = 1.0;
  127.     op2.type = REAL;
  128.     op2.x.real = -1;
  129.     pf.type = POINTER;
  130.     pf.x.pointer = stack_add;
  131.  
  132.     stack_push(sk, nl);
  133.     stack_push(sk, op1);
  134.     stack_push(sk, op2);
  135.     stack_push(sk, pf);
  136.     stack_exec(sk);
  137.     stack_push(sk, s);
  138.     stack_dot(sk);
  139.     stack_dot(sk);
  140.     stack_dot(sk);
  141.  
  142.     stack_delete(sk);
  143. }
$ gcc -o stack stack.c
$ ./stack
 = 3
 = 0.000000

Comments

Your comment:
[p] [b] [i] [u] [s] [quote] [pre] [br] [code] [url] [email] strip help 2000

Enter a maximum of 2000 characters.
Improve the presentation of your text with the following formatting tags:
[p]paragraph[/p], [b]bold[/b], [i]italics[/i], [u]underline[/u], [s]strike[/s], [quote]citation[/quote], [pre]as is[/pre], [br]line break,
[url]http://www.izend.org[/url], [url=http://www.izend.org]site[/url], [email]izend@izend.org[/email], [email=izend@izend.org]izend[/email],
[code]command[/code], [code=language]source code in c, java, php, html, javascript, xml, css, sql, bash, dos, make, etc.[/code].