The Relogix translation

Note: This is a 100% automatic translation, with no human intervention or cleaning-up of the code. Relogix has automatically chosen the function prototype, has detected the use of structures and pointers, has chosen the variable names itself, and has placed the assembler comments in the translated source allowing for the re-arrangement of the code flow.

In a real translation project, the translation could be further improved by providing user-defined header files to tune the names and types of variables, and the function prototypes. If you download the full sample translation you can see examples of this and read about the translation in detail.



/*
*************************************************************************
* ParseExpression                                                       *
*************************************************************************
*
*
*       ParseExpression() - Build expression tree                       
*
* NOTES:
* 1.    This routine builds an expression tree using standard operator
*       precedence analysis. It is lifted from Bornat, "Understanding and
*       Writing Compilers" Chpt 17 with various modifications.
*       The structure of the tree is different from Bornat; to cater for
*       multiple arguments, they are held in the form of a linked list of
*       nodes; nodep->child points to the first argument (if any), with the
*       arguments held in the linked list sibling->.
*                               node
*                                |
*                        +-------+
*                        |
*                        +-->node----->node----->node...
*                             |          |
*                   +---------+     +----+
*                   |               |
*                   +-->node...     +-->node...
* 2. On entry:
*       EDI -> environment
*       EAX = priority
*    On exit:
*       ESI -> root node
*
* Parameters:
*
*    long priority                                  [Originally in eax; In]
*    struct env *environment                        [Originally in edi; In]
*
* Result:
*
*    struct node *                                  [Originally in esi]
*/
struct node * ParseExpression (long priority, struct env *environment)
{
    struct node *result;                         /* [Originally in esi] */
    char buffer [MAX_TOKENLEN];                  /* [Originally on stack at offset -528] */
    unsigned char e;                             /* [Originally in cl] */
    struct node *node_ptr;                       /* [Originally in esi] */
    char *p;                                     /* [Originally in edx] */
    char *ptr_env_tokstr;                        /* [Originally in esi] */
    long the_op_priority;                        /* [Originally in ebx] */

    result = ParsePrimary (environment);         /* Get ESI -> left node */

    while (result != NULL) {
        /* Get CL = token value, e.g. TOK_TIMES */
        e = environment->env_tokval [0];

        /* Get EBX priority if operator (-1 if other token, e.g TOK_IDENT) */
        the_op_priority = (signed char) ((struct op *) ((signed char *) op_table + e * sizeof(struct op)))->op_priority;

        if (the_op_priority == -1) {
            /* Not an operator. TOK_END and TOK_COMMA are ok, else error */
            if (e != TOK_END && e != TOK_COMMA) {
                /* Oops, not an operator */
                errmsg ("Operator expected");    /* Error: "Operator expected" */
                result = NULL;
            }

            /* Arrive here with ESI -> left hand node (result) */
            return result;                       /* Clean up stack */
        }

        /* Have:
                 CL = token value
                 EBX = operator priority 
                 [ESP] = arg priority 
                 ESI -> left node 
                 EDI -> env */
        if (e == TOK_RPAREN)
            the_op_priority = 0;                 /* Adjust left priority of ) */

        /* op_priority <= priority ? */
        if (the_op_priority <= priority) {
            /* Arrive here with ESI -> left hand node (result) */
            return result;                       /* Clean up stack */
        }

        /* Copy token string to stack */
        p = buffer;
        ptr_env_tokstr = environment->env_tokstr;

        while (True) {
            *p = *ptr_env_tokstr;
            if (*p == 0)
                break;
            ptr_env_tokstr++;
            p++;
        }

        LexAnalyse (environment);
        if (e == TOK_LPAREN)
            the_op_priority = 0;                 /* Adjust right priority of ( */

        /* Have:
                 CL = token value 
                 EBX = operator priority 
                 [ESP] = arg priority
                 [ESP+4] = token string 
                 ESI -> left node 
                 EDI -> env */
        node_ptr = ParseExpression (the_op_priority, environment);
                                                 /* EAX = op priority
                                                    Get ESI -> right node */
        if (node_ptr == NULL)
            break;

        /* Call newnode with:
                 EDI -> env
                 CL = token value
                 EDX -> token string
                 EBX -> left node
                 ESI -> right node
           Returns ESI -> new node */
        result = newnode (e, buffer, result, node_ptr);
                                                 /*     EBX -> left node */
    }

    /* Arrive here with ESI -> left hand node (result) */
    return NULL;                                 /* Clean up stack */
}


/*
*************************************************************************
* ParsePrimary                                                          *
*************************************************************************
*
*
*       ParsePrimary() - Mutually recursive routine of ParseExpression()
*
* NOTES:
* 1.    This routine performs top down analysis of expression primaries.
*       See ParseExpression() above.
* 2. On entry:
*       EDI -> environment
*    On exit:
*       ESI -> root node
*
* Parameters:
*
*    struct env *environment                        [Originally in edi; In]
*
* Result:
*
*    struct node *                                  [Originally in esi]
*/
struct node * ParsePrimary (struct env *environment)
{
    struct node *result;                         /* [Originally in esi] */
    char buffer [MAX_TOKENLEN];                  /* [Originally on stack at offset -528] */
    char *expression;                            /* [Originally in esi] */
    struct node *node_ptr;                       /* [Originally in esi] */
    char *p;                                     /* [Originally in edx] */
    char *ptr_env_tokstr;                        /* [Originally in esi] */
    char *q;                                     /* [Originally in edx] */
    char **the_env_expptr;                       /* [Originally in ebx] */
    unsigned long the_node_idx;                  /* [Originally in eax] */
    unsigned char the_tok_int;                   /* [Originally in cl] */

    expression = NULL;

    /* Get CL = token value */
    the_tok_int = environment->env_tokval [0];

    /* A % operator occuring where an operand is expected is probably the result
       of misinterpreting a binary operand like %10101. Try to correct ourselves now */
    if (the_tok_int == TOK_MOD) {
        the_env_expptr = environment->env_expptr;
                                                 /* EBX -> pointer to expression */
        expression = *the_env_expptr;            /* ESI -> expression */

        /* AL = next char. Is it 0 or 1 ? */
        if (*expression >= '0' && *expression <= '1') {
            the_tok_int = TOK_INT;               /* Aha, change to TOK_INT */
            environment->env_tokval [0] = TOK_INT;
            environment->env_tokstr [0] = '%';   /* Copy %10101 string */
            p = &environment->env_tokstr [1];
            while (*expression >= '0' && *expression <= '1')
                *p++ = *expression++;

            *the_env_expptr = expression;        /* Update expression pointer */
            *p = 0;
        }
    }

    /* Identifier or integer ? */
    switch (the_tok_int) {
    case TOK_IDENT:
    case TOK_INT:
        result = endnode (the_tok_int, environment->env_tokstr);
                                                 /* EDI -> env, EDX -> token string, CL = token value */
        if (result == NULL)
            return NULL;
        break;

    case TOK_LPAREN:
        LexAnalyse (environment);                /* Get next token */
        result = ParseExpression (0, environment);
                                                 /* Parse expression in () */

        /* Parsed ok? */
        if (result == NULL)
            return NULL;

        /* Got right ) ? */
        if (environment->env_tokval [0] == TOK_RPAREN)
            break;
        errmsg ("Right parenthesis missing");    /* Error "Right parenthesis missing" */
        return NULL;

    default:
        switch (the_tok_int) {
        case TOK_BIT_NOT:
        case TOK_LOGICAL_NOT:
            break;
        case TOK_PLUS:
            the_tok_int = TOK_UNIPLUS;
            environment->env_tokval [0] = TOK_UNIPLUS;
            break;
        case TOK_MINUS:
            the_tok_int = TOK_NEGATE;
            environment->env_tokval [0] = TOK_NEGATE;
            break;
        default:
            /* Oops, expected an operand */
            errmsg ("Operand expected");         /* Error : "Operand expected" */
            return NULL;
        }

        /* Get here if we have unary operator, + - ! or ~ */
        q = buffer;                              /* Copy token string to stack. LexAnalyse will kill it */
        ptr_env_tokstr = environment->env_tokstr;

        while (True) {
            *q = *ptr_env_tokstr;
            if (*q == 0)
                break;
            ptr_env_tokstr++;
            q++;
        }

        LexAnalyse (environment);                /* Consume token */
        node_ptr = ParsePrimary (environment);   /* Get ESI -> node tree for argument of unary operator */

        if (node_ptr == NULL)
            result = NULL;
        else {
            /* Call newnode with:
                     EDI -> env
                     CL = token value
                     EDX -> token string
                     EBX -> left node
                     ESI -> right node
               Returns ESI -> new node */
            result = newnode (the_tok_int, buffer, node_ptr, NULL);
        }

        return result;
    }

    LexAnalyse (environment);

    /* Is this a function invocation ? */
    if (result == NULL)
        result = NULL;
    else if (result->node_tokval [0] == TOK_IDENT) {
        the_node_idx = check_function (result->node_tokstr);
                                                 /* EAX -> function name
                                                    EAX = function index, or -1 */
        if (environment->env_tokval [0] == TOK_LPAREN) {
            /* Have (, hopefully following function */
            LexAnalyse (environment);
            if ((long) the_node_idx == -1) {
                errmsg ("Invalid function name");
                                                 /* Error : "Invalid function name" */
                result = NULL;
            } else {
                result->node_tokval [0] = TOK_FUNC;
                                                 /* Change type to TOK_FUNC */
                result->node_idx = the_node_idx; /* Store index into function table */
                result = ParseArguments (result, environment);
                                                 /* Parse arguments in () */
            }
        } else if ((long) the_node_idx != -1) {
            result->node_tokval [0] = TOK_FUNC;  /* Yes, so just change type to TOK_FUNC */
            result->node_idx = the_node_idx;     /* and store index into function table */
        }
    }

    return result;
}