XTRAN Example — Translate Labeled Structures in HP (Digital, Compaq) VAX MACRO to C

One way to declare a structure in VAX MACRO is in the following form:

	<lbl1>:
	[[<lbl>:]] <opr> ...
	...
	<name>=.-<lbl1>		;OPTIONAL -- LENGTH OF STRUCTURE

where:

        <lbl1>  is any legal symbol in the source language
        <lbl>   is any legal symbol in the source language
        <opr>   is one of:  .ASCII, .BLK{{B|W|L}}, .BYTE,
                            .WORD, .LONG, .ADDRESS

An example of this usage is

STR:
MEMB1:	.BLKB	 3
	.ASCII	 /ABC/
	.ASCII	 ?DEF?
MEMB2:	.LONG	 2,3
	.BLKL	 1
STRSIZ	=	 .-STR

(Note the use of "fillers" — members with no names.)

Normally, XTRAN would try to translate this as a structure of unknown type named memb1 plus a long array named memb2, and it would be unable to translate the = statement because of the Program Counter reference.

We have created a set of XTRAN rules ("meta-code") to translate this kind of structure declaration, which we call a LBLSTR (labeled structure).  These rules, which comprise just over 400 non-comment lines of meta-code, are input to XTRAN after the normal VAX MACRO to C translation rules we provide.  They implement the following strategy:

The following input to, and output from, XTRAN are untouched except for added commentary in the input and paraphrasing of the LBLSTR start and end markers.




Process Flowchart

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

process flowchart

Input to XTRAN:

MB4DIM	=	5				;MB4DIM =      5

ARR:	.ASCII	/XYZ/				;ARR:   .ASCII /XYZ/
ARRSIZ	=	.-ARR				;ARRSIZ = .-ARR

(Note that the following struct is global.  It ends with an equate, so we don't need to mark its end.)

;(LBLSTR start marker)
STRCT1::
	.ASCII	/ABC/<9>/DEF/			;       .ASCII /ABC/<9>/DEF/;
MEMB1:	.ASCII	/GHI/				;MEMB1: .ASCII /GHI/;
MEMB2:	.BLKW	1				;MEMB2: .BLKW  1
	.ASCII	/JKL/				;       .ASCII /JKL/;
MEMB3:	.ASCII	/YY/				;MEMB3: .ASCII /YY/;
	.LONG	2,3				;       .LONG  2,3
S1SIZ	=	.-STRCT1			;S1SIZ	=      .-STRCT1

WS1:	.LONG	3				;WS1:   .LONG  3

(Note that the following struct is local.  It doesn't end with an equate, so we need to mark its end.)

;(LBLSTR start marker)
STRCT2: .LONG	2,5				;STRCT2:.LONG  2,5
	.ASCII	?XYZ?				;       .ASCII ?XYZ?
MEMB4:	.BLKW	MB4DIM				;MEMB4: .BLKW  MB4DIM
						;(LBLSTR end marker)

WS2:	.BLKW	10				;WS2:   .BLKW  10

CODE:	MOVAL	STRCT1,R3			;       MOVAL  STRCT1,R3
	MOVB	MEMB3+1,R4			;       MOVB   MEMB3+1,R4
	MOVW	MEMB4(R1),MEMB2			;       MOVW   MEMB4(R1),MEMB2
	.END



Output from XTRAN:

	extern long *r3;
	extern char r4;
	extern long r1;

#define MB4DIM 5				/*mb4dim =      5*/

	static char arr[4] = "XYZ";		/*arr:   .ascii /xyz/*/
#define ARRSIZ sizeof(arr)			/*arrsiz = .-arr*/

	struct strct1_str
	    {
	    char filler1[7];

						/*       .ascii /abc/<9>/def/;*/
	    char memb1[3];			/*memb1: .ascii /ghi/;*/
	    short memb2;			/*memb2: .blkw	1*/
	    char filler2[3];			/*       .ascii /jkl/;*/
	    char memb3[2];			/*memb3: .ascii /yy/;*/

	    long filler3[2];			/*       .long	2,3*/
	    };
	    
	struct strct1_str strct1 = 
	    {
	    "ABC\tDEF",				/*filler1*/
	    "GHI",				/*memb1*/
	    0,					/*memb2*/
	    "JKL",				/*filler2*/
	    "YY",				/*memb3*/
	    { 2, 3 }				/*filler3*/

	    };
#define S1SIZ sizeof(strct1)			/*s1siz	 =       .-strct1*/

	static long ws1 = 3;			/*ws1:   .long   3*/

	struct strct2_str
	    {
	    long filler1[2];

						/*strct2:.long	2,5*/
	    char filler2[3];			/*       .ascii ?xyz?*/
	    short memb4[MB4DIM];		/*memb4: .blkw  mb4dim*/
	    };



	    
	static struct strct2_str strct2 = 
	    {
	    { 2, 5 },				/*filler1*/
	    "XYZ",				/*filler2*/
	    { 0 }				/*memb4*/

	    };
	static short ws2[10];			/*ws2:   .blkw  10*/


code:
	r3 = (long *) &strct1;			/*       moval  strct1,r3*/
	r4 = strct1.memb3[1];			/*       movb   memb3+1,r4*/
	strct1.memb2 = *((short *) ((char *)
	  strct2.memb4 + r1));			/*       movw   memb4(r1),memb2*/