XTRAN Example — PL/M $INCLUDE Implies Typedef'd Data Type
The PL/M language doesn't have a mechanism like C's
typedef
. In order to share STRUCTURE
declarations across modules, some PL/M programmers use an $INCLUDE
statement to fill in the body of a STRUCTURE
. Furthermore,
PL/M programmers sometimes combine many such STRUCTURE
bodies in
one $INCLUDE
file; the desired body is then selected using a
$SET
variable prior to the $INCLUDE
statement.
When we translate such code to C, what we want is to use a
typedef
to establish each structure, and put those
typedef
declarations into %include
files.
To facilitate this, XTRAN provides a mechanism, via
a primitive in XTRAN's rules language
("meta-code"), called "include implies typedef".
Using this mechanism, we can tell XTRAN that when it
sees a given combination of (optional) $SET
statement and
$INCLUDE
statement, it is to parse a named $INCLUDE
file for the corresponding TYPEDEF
declaration, and is to ensure
an appropriate #include
statement in the resulting C code.
XTRAN also provides TYPEDEF
as an
extension to the PL/M language, for use with this feature.
The following example uses the standard set of XTRAN rules for parsing PL/M and translating it to C. The input and output are untouched except for the parenthetical remarks added to the input.
NOTE that the translation shown below was done with default conditions. XTRAN provides many options for controlling the way it translates.
Rules:
Rules that tell XTRAN to infer TYPEDEF
declared structures from combinations of $INCLUDE
files and
$SET
variables, using XTRAN's built-in
primitive:
$INCLUDE file inoriginal source |
TYPEDEF name to infer
|
File to $INCLUDE todeclare TYPEDEF
|
$SET name
|
foo:str1.plm
|
str1_t
|
demitd1.plm
|
|
foo:str23.plm
|
str2_t
|
demitd2.plm
|
setv2
|
foo:str23.plm
|
str3_t
|
demitd2.plm
|
setv3
|
foo:str4.plm
|
str4_t
|
demitd4.plm
|
setv4
|
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
Input to XTRAN: demitd.plm
(The following $INCLUDE
statement will be translated as is, and
will create an #include
of demitd4.h
in this module's
C translation.)
$INCLUDE (foo:demitd0.plm) DECLARE ptr POINTER;
(The following DECLARE
statements should turn into
typedef
declared declarations.)
DECLARE extstr1 STRUCTURE $INCLUDE (foo:str1.plm) EXTERNAL; DECLARE str1 STRUCTURE $INCLUDE (foo:str1.plm) ; DECLARE str2 $NOLIST $SET(setv2) INCLUDE (foo:str23.plm) $LIST EXTERNAL; DECLARE str3 $NOLIST $SET(setv3) INCLUDE (foo:str23.plm) $LIST ; DECLARE str4 STRUCTURE ( $INCLUDE (foo:str1.plm) ); DECLARE str5 BASED ptr $NOLIST $SET(setv3) INCLUDE (foo:str23.plm) ; $LIST $SET(setv2) DECLARE str6 $NOLIST $INCLUDE (foo:str23.plm) ; $LIST
(The following DECLARE
statements are not in a legal form for
"include implies type" processing, and therefore should not turn into
typedef
declared declarations.
XTRAN will parse the include files (issuing messages
that it is doing so) and discard the
$SET
and $INCLUDE
statements.)
DECLARE str7 STRUCTURE ( $SET(setv4) $INCLUDE(foo:demitd5.plm) , $SET(setv5) $INCLUDE(foo:demitd6.plm) ); DECLARE str8 STRUCTURE ( $SET(setv4) $INCLUDE(foo:demitd5.plm) , str_memb3 DWORD, $SET(setv5) $INCLUDE(foo:demitd6.plm) ); $SET (setv5) DECLARE str8a STRUCTURE ( $INCLUDE(foo:demitd6.plm) );
(The following case is a legal "include implies type" construction but hasn't been so described. XTRAN will issue a warning and parse the include file.)
DECLARE str9 $NOLIST $SET(setv4) INCLUDE (foo:demitd3.plm) $LIST EXTERNAL;
(Now some references to the declared STRUCTURE
members, to show
that they parse correctly.)
str0.s4_memb2 = 0; str1.s1_memb1 = 1; extstr1.s1_memb2 = 2; str2.s2_memb1 = 3; str3.s3_memb1 = 4; str4.s1_memb1 = 5; str5.s3_memb1 = 6; str6.s2_memb1 = 7; str7.str_memb1 = 8; str7.str_memb5 = 9; str8.str_memb1 = 10; str8.str_memb3 = 11; str8.str_memb5 = 12; str9.str9_memb2 = 13;
Input to XTRAN: demitd0.plm
(This file is unconditionally included by demitd.plm
.)
DECLARE str0 $NOLIST
(The following $INCLUDE
contains spaces before and after the
file name. This is yet another undocumented PL/M
"feature".)
$SET(setv4) INCLUDE ( foo:str4.plm ) $LIST ;
Input to XTRAN: demitd1.plm
(This file is used by demitd.plm
to declare a
TYPEDEF
data type.)
DECLARE str1_t TYPEDEF STRUCTURE ( s1_memb1 WORD, s1_memb2 DWORD );
Input to XTRAN: demitd2.plm
(This file is used by demitd.plm
to declare
TYPEDEF
data types.)
$IF (setv2) DECLARE str2_t TYPEDEF STRUCTURE ( s2_memb1 WORD, s2_memb2 DWORD ); $RESET(setv2) $ENDIF $IF (setv3) DECLARE str3_t TYPEDEF STRUCTURE ( s3_memb1 WORD, s3_memb2 DWORD ); $RESET(setv3) $ENDIF
Input to XTRAN: demitd3.plm
(This file will be parsed by XTRAN, because it hasn't been described via XTRAN's "include implies typedef" mechanism.)
$IF (setv4) STRUCTURE ( str9_memb1 WORD, str9_memb2 DWORD ) $RESET(setv4) $ENDIF
Input to XTRAN: demitd4.plm
(This file is used by demitd.plm
to declare a
TYPEDEF
data type.)
DECLARE str4_t TYPEDEF STRUCTURE ( s4_memb1 WORD, s4_memb2 DWORD );
Input to XTRAN: demitd5.plm
(This file will be parsed by XTRAN, because it is
used in DECLARE
statements in a way that doesn't
allow TYPEDEF
inference via XTRAN's
"include implies typedef" mechanism.)
str_memb1 WORD, str_memb2 DWORD
Input to XTRAN: demitd6.plm
(This file will be parsed by XTRAN, because it is
used in DECLARE
statements in a way that doesn't
allow TYPEDEF
inference via XTRAN's
"include implies typedef" mechanism.)
$IF setv5 $LIST str_memb5 BYTE, str_memb6 WORD $NOLIST $RESET (setv5) $ENDIF
Output from XTRAN:
#undef PP_SETV4 #define PP_SETV4 0xFF #include "demitd4.h" #include "demitd1.h" #undef PP_SETV2 #define PP_SETV2 0xFF #include "demitd2.h" #undef PP_SETV3 #define PP_SETV3 0xFF #include "demitd2.h" #include "demitd0.h" static void *ptr; extern Str1_t extstr1; static Str1_t str1; extern Str2_t str2; static Str3_t str3; static Str1_t str4; static Str2_t str6; static struct { unsigned short str_memb1; unsigned long str_memb2; unsigned char str_memb5; unsigned short str_memb6; } str7; static struct { unsigned short str_memb1; unsigned long str_memb2; unsigned long str_memb3; unsigned char str_memb5; unsigned short str_memb6; } str8; #undef PP_SETV5 #define PP_SETV5 0xFF static struct { unsigned char str_memb5; unsigned short str_memb6; } str8a; extern struct { unsigned short str9_memb1; unsigned long str9_memb2; } str9; str0.s4_memb2 = 0; str1.s1_memb1 = 1; extstr1.s1_memb2 = 2; str2.s2_memb1 = 3; str3.s3_memb1 = 4; str4.s1_memb1 = 5; ((Str3_t *) ptr)->s3_memb1 = 6; str6.s2_memb1 = 7; str7.str_memb1 = 8; str7.str_memb5 = 9; str8.str_memb1 = 10; str8.str_memb3 = 11; str8.str_memb5 = 12; str9.str9_memb2 = 13;
Messages from the run:
demitd.plm(92): XTRAN -- Substituting INCLUDE file demitd5.plm demitd.plm(94): XTRAN -- Substituting INCLUDE file demitd6.plm demitd.plm(98): XTRAN -- Substituting INCLUDE file demitd5.plm demitd.plm(101): XTRAN -- Substituting INCLUDE file demitd6.plm demitd.plm(106): ?XTRAN nonfatal error; status = -162: ); ^ %No typedef rule for this [[$SET and]] $INCLUDE in a DECLARE; will substitute! demitd.plm(104): XTRAN -- Substituting INCLUDE file demitd6.plm demitd.plm(116): ?XTRAN nonfatal error; status = -162: EXTERNAL; ^ %No typedef rule for this [[$SET and]] $INCLUDE in a DECLARE; will substitute! demitd.plm(112): XTRAN -- Substituting INCLUDE file demitd3.plm