XTRAN Example — Translate PL/M to C

The following example uses the standard set of XTRAN rules for parsing PL/M and translating it to C.

NOTE that the translation shown below was done with default conditions.  XTRAN provides many options for controlling the way it translates.

The input to, and output from, XTRAN are untouched.



Process Flowchart

Here is a flowchart for this process, in which the elements are color coded:

data flowchart

PL/M code to translate:


func1:  PROCEDURE EXTERNAL;             /*func1: PROCEDURE EXTERNAL;*/
        END func1;
func2:  PROCEDURE EXTERNAL;             /*func2: PROCEDURE EXTERNAL;*/
        END func2;
func3:  PROCEDURE EXTERNAL;             /*func3: PROCEDURE EXTERNAL;*/
        END func3;

        DECLARE outidx WORD;            /*DECLARE outidx WORD;*/

proc1:  PROCEDURE(arg);                 /*proc1: PROCEDURE(arg);*/
        DECLARE arg WORD;               /*DECLARE arg WORD;*/
        DECLARE (byt1, byt2) BYTE;      /*DECLARE (byt1, byt2) BYTE;*/
        DECLARE (wrd1, wrd2, wrd3) WORD; /*DECLARE (wrd1, wrd2, wrd3) WORD;*/
        DECLARE (int1, int2) INTEGER;   /*DECLARE (int1, int2) INTEGER;*/

lbl3:   DO CASE arg;                    /*lbl3: DO CASE arg;*/
            wrd2 = 1;                   /*wrd2 = 1;*/
            DO;                         /*DO;*/
                IF wrd1 < wrd2 THEN     /*IF wrd1 < wrd2 THEN*/
                    wrd2 = 1;           /*wrd2 = 1;*/
                ELSE                    /*ELSE*/
                    DO WHILE wrd1 < 1;  /*DO WHILE wrd1 < 1;*/
                        wrd2 = 2;       /*wrd2 = 2;*/
                        wrd3 = 1 + wrd3; /*wrd3 = 1 + wrd3;*/
                    END;
                wrd1 = wrd2;            /*wrd1 = wrd2;*/
            END;
            wrd2 = wrd2 + 3;            /*wrd2 = wrd2 + 3;*/
            IF wrd2 < 3 THEN            /*IF wrd2 < 3 THEN*/
                wrd2 = 4 + wrd2;        /*wrd2 = 4 + wrd2;*/
            ELSE                        /*ELSE*/
                DO;                     /*DO;*/
                wrd2 = 5 * wrd2;        /*wrd2 = 5 * wrd2;*/
                wrd3 = wrd3 / 6;        /*wrd3 = wrd3 / 6;*/
                END;
        END lbl3;                       /*END lbl3;*/
        DO byt1 = 1 to byt2 BY 2;       /*DO byt1 = 1 to byt2 BY 2;*/
            wrd3 = wrd1 + 2;            /*wrd3 = wrd1 + 2;*/
        END;
        DO WHILE wrd2 < 3;              /*DO WHILE wrd2 < 3;*/
            wrd1 = 1;                   /*wrd1 = 1;*/
            wrd1 = wrd1 - 1;            /*wrd1 = wrd1 - 1;*/
            DO wrd1 = 1 to wrd2 by 2;   /*DO wrd1 = 1 to wrd2 by 2;*/
                wrd3 = 2 - wrd3;        /*wrd3 = 2 - wrd3;*/
            END;
            DO int1 = int2 to 1 by -1;  /*DO int1 = int2 to 1 by -1;*/
                wrd3 = wrd1;            /*wrd3 = wrd1;*/
            END;
        END;
        RETURN (wrd1);                  /*RETURN (wrd1);*/
        END proc1;

proc2:  PROCEDURE(arg);                 /*proc2: PROCEDURE(arg);*/
        DECLARE arg WORD;               /*DECLARE arg WORD;*/
        DECLARE (byt1, byt2) BYTE;      /*DECLARE (byt1, byt2) BYTE;*/
        DECLARE (wrd1, wrd2, wrd3) WORD; /*DECLARE (wrd1, wrd2, wrd3) WORD;*/
        DECLARE fnam POINTER;           /*DECLARE fnam POINTER;*/
        DECLARE fnarr (3) POINTER       /*DECLARE fnarr (3) POINTER..*/
          DATA(.func1, .func2, .func3); /*..DATA(.func1, .func2, .func3);*/
        DECLARE str1 STRUCTURE          /*DECLARE str1 STRUCTURE..*/
          (m1 WORD, m2 BYTE)            /*..(m1 WORD, m2 BYTE)..*/
          DATA (1, 2);                  /*..DATA (1, 2);*/

        DO byt2 = 1 to byt1;            /*DO byt2 = 1 to byt1;*/
            wrd3 = wrd1;                /*wrd3 = wrd1;*/
        END;
        DO outidx = 1 to 3;             /*DO outidx = 1 to 3;*/
            wrd1 = wrd3;                /*wrd1 = wrd3;*/
        END;
        wrd1 = (wrd2 := wrd3 + 1) + 2;  /*wrd1 = (wrd2 := wrd3 + 1) + 2;*/
        fnam = @func1;                  /*fnam = @func1;*/
        CALL fnam;                      /*CALL fnam;*/
        CALL func1;                     /*CALL func1;*/ 
        fnam = fnarr(1);                /*fnam = fnarr(1);*/
        CALL fnam;                      /*CALL fnam;*/
        END proc2;



Translation as C code:


        extern void func1(void);        /*func1: PROCEDURE EXTERNAL;*/
        extern void func2(void);        /*func2: PROCEDURE EXTERNAL;*/
        extern void func3(void);        /*func3: PROCEDURE EXTERNAL;*/

        static unsigned short outidx;   /*DECLARE outidx WORD;*/

static void proc1(unsigned short arg)   /*proc1: PROCEDURE(arg);*/
{
        static unsigned char byt1, byt2; /*DECLARE (byt1, byt2) BYTE;*/
                                        /*DECLARE arg WORD;*/
        static unsigned short wrd1,
          wrd2, wrd3;                   /*DECLARE (wrd1, wrd2, wrd3) WORD;*/
        static short int1, int2;        /*DECLARE (int1, int2) INTEGER;*/

        static unsigned char prev_byt1;
        static unsigned short prev_wrd1;
        switch (arg)                    /*lbl3: DO CASE arg;*/
            {
            case 0 :
                wrd2 = 1;               /*wrd2 = 1;*/
                break;

            case 1 :
                                        /*do;*/
                if (wrd1 < wrd2)        /*IF wrd1 < wrd2 THEN*/
                    wrd2 = 1;           /*wrd2 = 1;*/
                else                    /*else*/
                    {
                    while (wrd1 < 1)    /*DO WHILE wrd1 < 1;*/
                        {
                        wrd2 = 2;       /*wrd2 = 2;*/
                        ++wrd3;         /*wrd3 = 1 + wrd3;*/
                        }
                    }
                wrd1 = wrd2;            /*wrd1 = wrd2;*/
                break;

            case 2 :
                wrd2 += 3;              /*wrd2 = wrd2 + 3;*/
                break;

            case 3 :
                if (wrd2 < 3)           /*IF wrd2 < 3 THEN*/
                    wrd2 += 4;          /*wrd2 = 4 + wrd2;*/
                else                    /*else*/
                                        /*do;*/
                                        /*END lbl3;*/
                    {
                    wrd2 *= 5;          /*wrd2 = 5 * wrd2;*/
                    wrd3 /= 6;          /*wrd3 = wrd3 / 6;*/
                    }
                break;
            }
        for (byt1 = prev_byt1 = 1; byt1
          <= byt2 && prev_byt1 <= byt1;
          prev_byt1 = byt1, byt1 += 2)  /*DO byt1 = 1 to byt2 BY 2;*/
            wrd3 = (unsigned short)
              (wrd1 + 2);               /*wrd3 = wrd1 + 2;*/
        while (wrd2 < 3)                /*DO WHILE wrd2 < 3;*/
            {
            wrd1 = 1;                   /*wrd1 = 1;*/
            --wrd1;                     /*wrd1 = wrd1 - 1;*/
            for (wrd1 = prev_wrd1 = 1;
              wrd1 <= wrd2 && prev_wrd1
              <= wrd1; prev_wrd1 = wrd1,
              wrd1 += 2)                /*DO wrd1 = 1 to wrd2 by 2;*/
                wrd3 = (unsigned short)
                  (2 - wrd3);           /*wrd3 = 2 - wrd3;*/
            for (int1 = int2; int1 >= 1;
              --int1)                   /*DO int1 = int2 to 1 by -1;*/
                wrd3 = wrd1;            /*wrd3 = wrd1;*/
            }
        return (wrd1);                  /*RETURN (wrd1);*/
}

static void proc2(unsigned short arg)   /*proc2: PROCEDURE(arg);*/
{
        static unsigned char byt1, byt2; /*DECLARE (byt1, byt2) BYTE;*/
                                        /*DECLARE arg WORD;*/
        static unsigned short wrd1,
          wrd2, wrd3;                   /*DECLARE (wrd1, wrd2, wrd3) WORD;*/
        static void (*fnam)(void);      /*DECLARE fnam POINTER;*/
        static const void *fnarr[3] = 
            { func1, func2, func3
            };                          /*DECLARE fnarr (3) POINTER..*/
                                        /*..DATA(.func1, .func2, .func3);*/
        static unsigned char prev_byt2;
        static const struct             /*DECLARE str1 STRUCTURE..*/
                                        /*..data (1, 2);*/
            {
            unsigned short m1;
            unsigned char m2;           /*..(m1 WORD, m2 BYTE)..*/
            }
            str1 = 
                { 1, 2
                };

        static unsigned short prev_outidx;
        for (byt2 = prev_byt2 = 1; byt2
          <= byt1 && prev_byt2 <= byt2;
          prev_byt2 = byt2++)           /*DO byt2 = 1 to byt1;*/
            wrd3 = wrd1;                /*wrd3 = wrd1;*/
        for (outidx = prev_outidx = 1;
          outidx <= 3 && prev_outidx <=
          outidx; prev_outidx = outidx++) /*DO outidx = 1 to 3;*/
            wrd1 = wrd3;                /*wrd1 = wrd3;*/
        wrd1 = (wrd2 = (unsigned short)
          (wrd3 + 1)) + 2;              /*wrd1 = (wrd2 := wrd3 + 1) + 2;*/
        fnam = func1;                   /*fnam = @func1;*/
        (*fnam)();                      /*CALL fnam;*/
        func1();                        /*CALL func1;*/
        fnam = fnarr[1];                /*fnam = fnarr(1);*/
        (*fnam)();                      /*CALL fnam;*/
}