XTRAN Example — Translate IBM Series/1 EDL to C
The following example uses the standard set of XTRAN rules ("meta-code") for parsing EDL 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.
We have declared to XTRAN the following C structures prior to translation:
struct str1 { short strmem1; }; typedef struct { char strmem2; } Str2;
We have also told XTRAN, via meta-code, that
a struct str1
allocation exists named str
.
Process Flowchart
Here is a flowchart for this process, in which the elements are color coded:
- BLUE for XTRAN versions (runnable programs)
- ORANGE for XTRAN rules (text files)
- RED for
code - PURPLE for text data files
Input to XTRAN:
* Expression conversion to symbols: on * Register "unioning": on * Address arithmetic: off * Pointer variables: off A1 EQU 5 A1 EQU 5 B1 EQU 6 B1 EQU 6 C1 EQU 7 C1 EQU 7 D1 EQU 8 D1 EQU 8 E1 EQU 9 E1 EQU 9 FOO1 EQU A1+1 FOO1 EQU A1+1 MOVE (STRMEM2,#1),BVAR1,BYTE MOVE (STRMEM2,#1),BVAR1,BYTE MOVE (STRMEM1,#2),#1 MOVE (STRMEM1,#2),#1 MOVE (D1,#1),(WARR1,#1) MOVE (D1,#1),(WARR1,#1) MOVE (E1,#1),(BARR2,#1),BYTE MOVE (E1,#1),(BARR2,#1),BYTE MOVE STR+STRMEM1,#1 MOVE STR+STRMEM1,#1 MOVE (B1+C1-1,#1),#1 MOVE (B1+C1-1,#1),#1 * Expression conversion to symbols: on (ignored) * Register "unioning": on * Address arithmetic: on * Pointer variables: off A2 EQU 5 A2 EQU 5 B2 EQU 6 B2 EQU 6 C2 EQU 7 C2 EQU 7 D2 EQU 8 D2 EQU 8 E2 EQU 9 E2 EQU 9 FOO2 EQU A2+1 FOO2 EQU A2+1 MOVE (STRMEM2,#1),BVAR1,BYTE MOVE (STRMEM2,#1),BVAR1,BYTE MOVE (STRMEM1,#2),#1 MOVE (STRMEM1,#2),#1 MOVE (D2,#1),(WARR1,#1) MOVE (D2,#1),(WARR1,#1) MOVE (E2,#1),(BARR2,#1),BYTE MOVE (E2,#1),(BARR2,#1),BYTE MOVE STR+STRMEM1,#1 MOVE STR+STRMEM1,#1 MOVE (B2+C2-1,#1),#1 MOVE (B2+C2-1,#1),#1 * Finally, at this point we told XTRAN to use pointer variables * in address arithmetic generation. * * Expression conversion to symbols: on (ignored) * Register "unioning": on * Address arithmetic: on * Pointer variables: on A3 EQU 5 A3 EQU 5 B3 EQU 6 B3 EQU 6 C3 EQU 7 C3 EQU 7 D3 EQU 8 D3 EQU 8 E3 EQU 9 E3 EQU 9 FOO3 EQU A3+1 FOO3 EQU A3+1 MOVE (STRMEM2,#1),BVAR1,BYTE MOVE (STRMEM2,#1),BVAR1,BYTE MOVE (STRMEM1,#2),#1 MOVE (STRMEM1,#2),#1 MOVE (D3,#1),(WARR1,#1) MOVE (D3,#1),(WARR1,#1) MOVE (E3,#1),(BARR2,#1),BYTE MOVE (E3,#1),(BARR2,#1),BYTE MOVE STR+STRMEM1,#1 MOVE STR+STRMEM1,#1 MOVE (B3+C3-1,#1),#1 MOVE (B3+C3-1,#1),#1
Output from XTRAN:
extern struct str1 str; extern union /*unionize reg1*/ { Str2 *p__Str2; short s; struct unkn_str *p__unkn_str; char *p_c; } reg1; extern struct str1 *reg2; static short warr1[] = {1, 2, 3, 4}; /*warr1 data f'1',f'2',f'3',f'4'*/ static short warr2[4] = { 0 }; /*warr2 data 4f*/ short wvar1 = 0; /*wvar1 data f*/ static char barr1[] = {4, 3, 2, 1}; /*barr1 data h'4',h'3',h'2',h'1'*/ static char barr2[3] = { 0 }; /*barr2 data 3h*/ char bvar1 = 0; /*bvar1 data h*/ struct unkn_str { short d1; char e1; short b1_pl_c1_mi_1; }; short *p_opnd_a; short *p_opnd_b; /* * Expression conversion to symbols: on * Register "unioning": on * Address arithmetic: off * Pointer variables: off */ #define A1 5 /*a1 equ 5*/ #define B1 6 /*b1 equ 6*/ #define C1 7 /*c1 equ 7*/ /*d1 equ 8*/ /*e1 equ 9*/ #define FOO1 (A1 + 1) /*foo1 equ a1+1*/ reg1.p__Str2->strmem2 = bvar1; /*move (strmem2,#1),bvar1,byte*/ reg2->strmem1 = reg1.s; reg1.p__unkn_str->d1 = warr1[reg1.s / 2]; /*move (d1,#1),(warr1,#1)*/ reg1.p__unkn_str->e1 = barr2[reg1.s]; /*move (e1,#1),(barr2,#1),byte*/ str.strmem1 = reg1.s; /*move str+strmem1,#1*/ reg1.p__unkn_str->b1_pl_c1_mi_1 = reg1.s; /*move (b1+c1-1,#1),#1*/ /* * Expression conversion to symbols: on (ignored) * Register "unioning": on * Address arithmetic: on * Pointer variables: off */ #define A2 5 /*a2 equ 5*/ #define B2 6 /*b2 equ 6*/ #define C2 7 /*c2 equ 7*/ #define D2 8 /*d2 equ 8*/ #define E2 9 /*e2 equ 9*/ #define FOO2 (A2 + 1) /*foo2 equ a2+1*/ reg1.p__Str2->strmem2 = bvar1; /*move (strmem2,#1),bvar1,byte*/ reg2->strmem1 = reg1.s; /*move (strmem1,#2),#1*/ *(short *) (reg1.p_c + D2) = *(short *) ((char *) warr1 + reg1.s); /*move (d2,#1),(warr1,#1)*/ *(reg1.p_c + E2) = *(barr2 + reg1.s); /*move (e2,#1),(barr2,#1),byte*/ str.strmem1 = reg1.s; /*move str+strmem1,#1*/ *(short *) (reg1.p_c + (B2 + C2 - 1)) = reg1.s; /*move (b2+c2-1,#1),#1*/ /* * Finally, at this point we told XTRAN to use pointer variables * in address arithmetic generation. * * Expression conversion to symbols: on (ignored) * Register "unioning": on * Address arithmetic: on * Pointer variables: on */ #define A3 5 /*a3 equ 5*/ #define B3 6 /*b3 equ 6*/ #define C3 7 /*c3 equ 7*/ #define D3 8 /*d3 equ 8*/ #define E3 9 /*e3 equ 9*/ #define FOO3 (A3 + 1) /*foo3 equ a3+1*/ reg1.p__Str2->strmem2 = bvar1; /*move (strmem2,#1),bvar1,byte*/ reg2->strmem1 = reg1.s; /*move (strmem1,#2),#1*/ p_opnd_a = (short *) (reg1.p_c + D3); /*set up operand pointer*/ p_opnd_b = (short *) ((char *) warr1 + reg1.s); /*set up operand pointer*/ *p_opnd_a = *p_opnd_b; /*move (d3,#1),(warr1,#1)*/ p_opnd_a = (short *) (reg1.p_c + E3); /*set up operand pointer*/ p_opnd_b = (short *) (barr2 + reg1.s); /*set up operand pointer*/ *(char *) p_opnd_a = *(char *) p_opnd_b; /*move (e3,#1),(barr2,#1),byte*/ str.strmem1 = reg1.s; /*move str+strmem1,#1*/ p_opnd_a = (short *) (reg1.p_c + (B3 + C3 - 1)); /*set up operand pointer*/ *p_opnd_a = reg1.s; /*move (b3+c3-1,#1),#1*/