/media/sda-magnetic/david/Dok-15-2023-11-27/informatik/src-codes-20240203/asmparser15.c


#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>


#define NO      0
#define WEST    1
#define EAST    2

#define MAX_NODES                   64
#define STACKS_MAX                  4

#define STACKS_COND_MAX                 3

char *op_names [] = {"==", \
    "!=", \
    ">", \
    ">=", \
    "<", \
    "<=", \
    "+", \
    "++", \
    "-", \
    "--", \
    "<<", \
    ">>", \
    "<|", \
    "|>", \
    "and", \
    "not", \
    "or", \
    "xor", \
    "+", \
    "++", \
    "-", \
    "--", \
    "<<", \
    ">>", \
    "<|", \
    "|>", \
    "and", \
    "not", \
    "or", \
    "xor", \
    "<-"
};

#define OP_CMP_EQ_REG_CONST         0
#define OP_CMP_NE_REG_CONST         1
#define OP_CMP_GR_REG_CONST         2
#define OP_CMP_GE_REG_CONST         3
#define OP_CMP_LT_REG_CONST         4
#define OP_CMP_LE_REG_CONST         5
#define OP_ADD_REG_REG_CONST        6
#define OP_INC_REG_REG_CONST        7
#define OP_SUB_REG_REG_CONST        8
#define OP_DEC_REG_REG_CONST        9
#define OP_SLL_REG_REG_CONST        10
#define OP_SLR_REG_REG_CONST        11
#define OP_RL_REG_REG_CONST       12
#define OP_RR_REG_REG_CONST       13
#define OP_AND_REG_REG_CONST      14
#define OP_NOT_REG_REG_CONST      15
#define OP_OR_REG_REG_CONST       16
#define OP_EXOR_REG_REG_CONST     17
#define OP_ADD_REG_REG_REG        18
#define OP_INC_REG_REG_REG        19
#define OP_SUB_REG_REG_REG        20
#define OP_DEC_REG_REG_REG        21
#define OP_SLL_REG_REG_REG        22
#define OP_SLR_REG_REG_REG        23
#define OP_RL_REG_REG_REG         24
#define OP_RR_REG_REG_REG         25
#define OP_AND_REG_REG_REG        26
#define OP_NOT_REG_REG_REG        27
#define OP_OR_REG_REG_REG         28
#define OP_EXOR_REG_REG_REG       29
#define OP_ASSIGNMENT_REG_CONST   30
#define NA                        -1
#define EMPTY                       -2
#define STACK_UNDERFLOW             -3

#define STACK_OPCODE                0
#define STACK_OP1                   1
#define STACK_OP2                   2
#define STACK_OP3                   3

#define MAX_COND                    3
#define CONST_MAX                   32

#define STACK_CONDITION_Z           0
#define STACK_CONDITION_LEFT_END    1
#define STACK_CONDITION_RIGHT_END   2

int stack [STACKS_MAX][MAX_NODES];
int stack_cond [STACKS_COND_MAX][MAX_NODES];
int stack_ptr [STACKS_MAX];
int queue_ptr [STACKS_MAX];
int queue_cond_ptr [STACKS_COND_MAX];
int stack_cond_ptr [STACKS_COND_MAX];


void init_stack (void) {
    int i;
    for (i = 0;  i < STACKS_MAX;  i++) {
        stack_ptr [i] = 0;
    }
    for (i = 0;  i < STACKS_COND_MAX;  i++)
        stack_cond_ptr [i] = 0;
return;
}

void queue_init (void) {
    int i;
    for (i = 0;  i < STACKS_MAX;  i++) {
        queue_ptr [i] = 0;
    }
    for (i = 0;  i < STACKS_COND_MAX;  i++) {
        queue_cond_ptr [i] = 0;
    }

return;
}

void push (int stck, int v) {
    if (stack_ptr[stck] < (MAX_NODES-1)) {
        stack [stck][stack_ptr [stck]] = v;
        stack_ptr [stck]++;
    }
return;
}

int pop (int stck) {
    if (stack_ptr [stck] > 0) {
        stack_ptr [stck]--;
        return stack [stck][stack_ptr [stck]];
    }
    else
        return STACK_UNDERFLOW;
}

int getstckptr (int stck) {
    return stack_ptr [stck];
}

int get (int stck) {
    if (queue_ptr [stck] < stack_ptr [stck]) {
        return stack [stck][queue_ptr [stck]++];
    }
    else return EMPTY;
}
void unget (int stck) {
    if (queue_ptr [stck] > 0)
        queue_ptr [stck]--;
}


void push_cond (int stck_cond, int v) {
    if (stack_cond_ptr [stck_cond] < (MAX_NODES-1)) {
        stack_cond [stck_cond][stack_cond_ptr[stck_cond]] = v;
        stack_cond_ptr [stck_cond]++;
    }
}

int pop_cond (int stck_cond) {
    if (stack_cond_ptr [stck_cond] > 0) {
        stack_cond_ptr [stck_cond]--;
        return stack_cond [stck_cond][stack_cond_ptr [stck_cond]];
    }
    else
        return -1;
}

int get_cond (int stck_cond) {
    if (queue_cond_ptr [stck_cond] < stack_cond_ptr [stck_cond]) {
        return stack_cond [stck_cond][queue_cond_ptr [stck_cond]++];
    }
    else return EMPTY;
}


int regmax = 0;


/*
 * reg ::= op reg reg reg | op reg reg const | op const
 * cond ::= op_cmp reg const addr1 addr2
 */

void init () {
    int i = 0;
    int cond_count = MAX_COND;
    int cond_least = 0;
    int op;
    int imax = (rand () % 6) + 5;
    int lastreg;
    int r;

    push (STACK_OPCODE, OP_ASSIGNMENT_REG_CONST);           // Assignment at begin
    push (STACK_OP1, 0);                                    // Register R0 ()
    push (STACK_OP2, rand () % CONST_MAX);                  // Const
    push (STACK_OP3, NA);                                   // Operand 3, assignment, not given

    for (i = 1;  i < imax;  i++) {
        op = rand () % (OP_EXOR_REG_REG_REG+1);
        if ((op <= OP_CMP_LE_REG_CONST) && (cond_least == 0)) {
            if (cond_count > 0) {
                cond_count--;
                lastreg = pop (STACK_OP1);
                push (STACK_OP1, lastreg);
                push (STACK_OPCODE, op);
                push (STACK_OP1, lastreg);
                push (STACK_OP2, rand () % CONST_MAX);
                push (STACK_OP3, NA );
                cond_least = 2;
                if ((i + cond_least) > imax) {
                    imax += cond_least;
                }
            }
            else {
                i--;
            }
        }
        else if (op > OP_CMP_LE_REG_CONST){
                if (cond_least != 0)
                    cond_least--;
                lastreg = pop (STACK_OP1);
                push (STACK_OP1, lastreg);
                push (STACK_OPCODE, op);
                push (STACK_OP1, lastreg+1);
                push (STACK_OP2, lastreg);
                if ((op >= OP_ADD_REG_REG_REG) && (op <= OP_EXOR_REG_REG_REG)) {
                    r = (rand () % (lastreg+1))-1;
                    if (r < 0)
                        r = 0;
                    push (STACK_OP3, r);
                }
                else
                    push (STACK_OP3, rand () % CONST_MAX);
        }
        else
            i--;
    }
    push (STACK_OPCODE, EMPTY);
    push (STACK_OP1, EMPTY);
    push (STACK_OP2, EMPTY);
    push (STACK_OP3, EMPTY);
}

void test_output (void) {
    int p, o1, o2, o3;

    while ((p = get (STACK_OPCODE)) != EMPTY) {
        if ((p >= OP_CMP_EQ_REG_CONST) && (p <= OP_CMP_LE_REG_CONST)) {
            printf ("R%i %s %i\n", get (STACK_OP1), op_names [p], get(STACK_OP2));
            get (STACK_OP3);
        }
        else if (p == OP_ASSIGNMENT_REG_CONST) {
            printf ("R%i %s %i\n", get (STACK_OP1), op_names [p], get(STACK_OP2));
            get (STACK_OP3);
        }
        else {
            if ((p == OP_INC_REG_REG_CONST) || (p == OP_INC_REG_REG_REG) || (p == OP_DEC_REG_REG_CONST) || (p == OP_DEC_REG_REG_REG)) {
                printf ("R%i %s R%i %s\n", get (STACK_OP1), op_names [OP_ASSIGNMENT_REG_CONST], get (STACK_OP2), op_names [p]);
                get (STACK_OP3);
            }
            else if ((p >= OP_ADD_REG_REG_CONST) && (p <= OP_EXOR_REG_REG_CONST))
                printf ("R%i %s R%i %s %i\n", get (STACK_OP1), op_names [OP_ASSIGNMENT_REG_CONST], get (STACK_OP2), op_names [p],  get (STACK_OP3));
            else
                printf ("R%i %s R%i %s R%i\n", get (STACK_OP1), op_names [OP_ASSIGNMENT_REG_CONST], get (STACK_OP2), op_names [p],  get (STACK_OP3));
        }
    }
}


int expr (int z, int zs, int dir) {
    int p = get (STACK_OPCODE);
    if (dir == NO) {
        printf ("\\node [zbox] (z%i) {\\verb\"", z);
    }
    else if (dir == WEST) {
        printf ("\\node [zbox, below=of z%i.west, yshift=-4em] (z%i) {\\verb\"", zs, z);
    }
    else if (dir == EAST) {
        printf ("\\node [zbox, below=of z%i.east, yshift=-4em] (z%i) {\\verb\"",zs, z);
    }
    if (p == OP_ASSIGNMENT_REG_CONST) {
            printf ("R%i %s %i", get (STACK_OP1), op_names [p], get(STACK_OP2));
            get (STACK_OP3);
    }
    else if ((p == OP_INC_REG_REG_CONST) || (p == OP_INC_REG_REG_REG) || (p == OP_DEC_REG_REG_CONST) || (p == OP_DEC_REG_REG_REG)) {
        printf ("R%i %s R%i %s", get (STACK_OP1), op_names [OP_ASSIGNMENT_REG_CONST], get (STACK_OP2), op_names [p]);
        get (STACK_OP3);
    }
    else if ((p >= OP_ADD_REG_REG_CONST) && (p <= OP_EXOR_REG_REG_CONST))
        printf ("R%i %s R%i %s %i", get (STACK_OP1), op_names [OP_ASSIGNMENT_REG_CONST], get (STACK_OP2), op_names [p],  get (STACK_OP3));
    else {
        printf ("R%i %s R%i %s R%i", get (STACK_OP1), op_names [OP_ASSIGNMENT_REG_CONST], get (STACK_OP2), op_names [p],  get (STACK_OP3));
    }

   printf ("\"};\n");
   printf ("\\node [above=0mm of z%i, text width=8em] {$Z_{%i}$};\n", z, z);
   if (z != 1) {
        if (dir == NO) {
            printf ("\\draw [->] (z%i) -- (z%i);\n\n", zs, z);
        }
        else if (dir == WEST) {
            printf ("\\draw [->] (z%i.west) -- (z%i);\n\n", zs, z);
        }
        else if (dir == EAST) {
            printf ("\\draw [->] (z%i.east) -- (z%i);\n\n", zs, z);
        }
   }

return z;
}

int cond (int z, int zs, int dir) {
    int p = get (STACK_OPCODE);
    if (dir == NO) {
        printf ("\\node [ebox] (z%i) {\\verb\"", z);
    }
    else if (dir == WEST) {
        printf ("\\node [ebox, below=of z%i.west, yshift=-4em] (z%i) {\\verb\"", zs, z);
    }
    else if (dir == EAST) {
        printf ("\\node [ebox, below=of z%i.east, yshift=-4em] (z%i) {\\verb\"",zs, z);
    }
    printf ("R%i %s %i", get (STACK_OP1), op_names [p], get(STACK_OP2));
    get (STACK_OP3);
    printf ("\"};\n");
    printf ("\\node [above=0mm of z%i, text width=8em] {$Z_{%i}$};\n", z, z);
    if (z != 1) {
        if (dir == NO) {
            printf ("\\draw [->] (z%i) -- (z%i);\n\n", zs, z);
        }
        else if (dir == WEST) {
            printf ("\\draw [->] (z%i.west) -- (z%i);\n\n", zs, z);
        }
        else if (dir == EAST) {
            printf ("\\draw [->] (z%i.east) -- (z%i);\n\n", zs, z);
        }
    }
    push_cond (STACK_CONDITION_Z, z);
    return z;
}


int as (int z, int zs, int dir, int steps) {
    int ztmp;
    int r, rtmp;
    int stepsr;
    int stepss;


    if (steps > 0) {
        r = get (STACK_OPCODE);
        if ((r >= OP_CMP_EQ_REG_CONST) && (r <= OP_CMP_LE_REG_CONST)){
            unget (STACK_OPCODE);
            z = ztmp = cond (z+1, z, dir);
            stepsr = (rand () % 2) * steps;
            stepss = steps - stepsr;
            z = as (z, z, WEST, stepsr);
            push_cond (STACK_CONDITION_LEFT_END, z);
            z = as (z, ztmp, EAST, stepss);
            push_cond (STACK_CONDITION_RIGHT_END, z);
        }
        else if (r != EMPTY) {
            unget (STACK_OPCODE);
            z = expr (z+1, zs, dir);
            z = as (z, z, NO, steps-1);
        }
    }
return z;
}

void make_condition_connections () {
    int c1, c2;
    int r, l;
    //int c;
    /*while ((c = pop_cond (STACK_CONDITION_Z)) != -1) {
        r = pop_cond (STACK_CONDITION_RIGHT_END);
        l = pop_cond (STACK_CONDITION_LEFT_END);
        if ((r - c) >= (l - c)) {
            printf ("\\draw [->] (z%i) -- (z%i);\n\n", l, c-1);
            //printf ("\\draw [->] (z%i.west) |- (z%i);\n\n", r, 1);
        }
        else {
            printf ("\\draw [->] (z%i) -- (z%i);\n\n", r, c-1);
            //printf ("\\draw [->] (z%i.west) |- (z%i);\n\n", l, 1);
        }
    }*/
    c1 = 0;
    while ((c2 = get_cond (STACK_CONDITION_Z)) != EMPTY) {
        r = get_cond (STACK_CONDITION_RIGHT_END);
        l = get_cond (STACK_CONDITION_LEFT_END);

        if (r > l) {
            printf ("\\draw [->] (z%i.west) |- (z%i);\n\n", c2, c1+1);
        }
        else {
            printf ("\\draw [->] (z%i.east) |- (z%i);\n\n", c2, c1+1);
        }
        c1 = c2;
    }
}


int main (void) {
    time_t t;
    int j;
    srand (t = time(NULL));

    init_stack ();
    queue_init ();
    init ();
    //test_output ();

    printf("\\documentclass{article}\n");
    printf("\\usepackage[utf8]{inputenc}\n");
    printf("\\usepackage{pgf, tikz}\n");
    printf("\\usetikzlibrary{shapes, chains, calc, arrows, positioning}\n\n");
    printf("\\begin{document}\n\n");

    queue_init ();

    printf("\\begin{center}\n");
    printf("\\begin{tikzpicture}[%\n");
    printf("\t>=triangle 60,              \n");
    printf("\tstart chain=going below,    \n");
    printf("\tnode distance=6mm and 60mm, \n");
    printf("\tevery join/.style={norm},\n");
    printf("]\n");
    printf("\\tikzset{\n");
    printf("base/.style={draw, on chain, on grid, align=center, minimum height=4ex},\n");
    printf("zbox/.style={base, rectangle, text width=8em},\n");
    printf("ebox/.style={base, diamond, aspect=1.5, text width=10em},\n");
    printf("term/.style={zbox, rounded corners},\n");
    printf("norm/.style={->, draw},\n");
    printf("coord/.style={coordinate, on chain, on grid, node distance=6mm and 25mm}}\n\n");


    as (0, 0, NO, getstckptr (STACK_OPCODE));
    make_condition_connections ();

    printf ("\\end{tikzpicture}\n\n");
    printf ("\\end{center}\n\n");

    printf("\\end{document}\n");
return 0;
}