MOVING FROM ASSEMBLER TO "C"
with C Application Builder and FalconTPF
By Jeff Robinson

If you've been following this column the past few issues, then you know that we've been exploring a "fast track" approach to learning "C" programming from a TPF Assembler programmers point of view. "That's all well and good", you may say, "but what do we do about new C development or about all of the existing Assembler code currently in production?". Answer: consider acquiring products like the two I'll be reviewing in this issue. One, Starpush Inc.'s "C Application Builder" helps take the pain out developing new edit and validation programs in TPF/C; the other, Sapien's FalconTPF, does the job of converting your existing legacy TPF Assembler code to "C" language.

You can find more information about both products at their web-sites. Starpush, Inc. can be found at "http://www.starpush.com"; Sapien's International is located is "http://www.sapiens.com".

The C Application Builder
Targeting the ubiquitous Windows workstation platform, the "C Application Builder" or CAB is a stand-alone product which builds framework modules for the TPF/C programmer. In short, CAB is a code generator or second-generation CASE tool for the TPF platform. Similar tools have existed on other platforms for years (Unix, Windows, Web) and have played a great role in the application development success of those environments. Now, with "C Application Builder", TPF finally has a worthwhile product that can also be used to quickly generate code for those redundant programming tasks such as entry message edits and validations.

Because the CAB employs an intuitive, graphical user interface, its users do not need to know 'C' programming. This means that the 'C' programming novice, expert or even a business analyst can use the tool to construct 'C' programs. Furthermore, with its familiar MicroSoft Windows Explorer style look and feel, learning to use this product should be a cinch for anyone familiar with the Windows environment.

The target output of the CAB is the creation of 'C' programs and headers based on an old, current or new project. The results will be fully functional, source programs that can be compiled and tested right away. Although the CAB's strong point is the generation of TPF edit and validation entry programs, the product can be easily augmented with another tool supplied by Starpush to generate TPFDF 'C' components.

What would be the advantages of your shop acquiring CAB? Using CAB could shield your developers from over-exposure to complicated 'C' code; allow high-level edit and validation information to be entered by business analysts working along-side customers; allow high-level analysis to be started by a programmer-analyst and low-level design to be completed by a programmer. The best premium of all is that because CAB uses a visual, step-by-step presentation format, information can be easily understood at a glance and readily changed in an instant.

So, if you're looking for a friendly, innovative TPF/C tool, give the "C Application Builder" consideration. You can even download a demo version of the product from the Starpush web-site. (NOTE: A live demonstration of CAB's code generation capabilities was not available at the time of this writing.)

FALCONTPF Background
FalconTPF stands for "Fast Assembly Language CONverter for TPF" and its purpose is to do exactly what the name implies: Convert TPF Assembly Language programs to "C" (Currently 'C' the only supported targeted language). The unique aspect of this conversion process is that, with little or no manual intervention, it is mostly automatic. For financially-strapped TPF shops, that point could mean a huge savings in maintenance costs.

As discussed in the last issue of ACP· TPF Today, FalconTPF uses a process called "Plan Calculus" developed at the MIT Artificial Intelligence Laboratory in the late eighties. This approach uses a "canonical, mathematical abstraction used to describe imperative programs. It is based on the insight that programs can be seen as the combination of their control-flow and data-flow.". The FalconTPF workbench uses Plan Calculus in its program translation algorithm

by employing a three-stage process consisting of 1)parsing the source program and generating the abstract representation 2)Further analysis and transformations of the abstract representation and 3)Final code generation of the algorithm into the target language (C in this case).

A FALCONTPF Translation Example
I wanted to know just how good FalconTPF's conversion process was. So, I supplied the exercises from the third installment of "Moving from Assembler to C" in the July 1999 issue of ACP· TPF Today to the team at Sapiens and asked them to translate it using the FalconTPF conversion process. The program exercises are included here also for your reference. My own answers can be found at "http://www.robisoft.com/answers.html".

BEGIN NAME=XYZ1,VERSION=A0

**********************************************************************

*THE PURPOSE OF THIS PROGRAM IS TO CHECK THE CHARACTER IN THE 7TH *
*POSITION OF THE INPUT MESSAGE. IF ITS A 'Y' FOR YES, THEN WIPE OUT *
*THE PASSENGER NAME CURRENTLY BEING WORKED UPON. OTHERWISE, *
*JUST EXIT AND RETURN. *

***********************************************************************

MI0MI REG=R1
PN0NR REG=R3
*
CRUSA S0=4 RELEASE LEVEL 4 BLOCK IF ANY
*
L R1,CE1CR0 BASE THE INPUT BLOCK
L R3,CE1CR2 BASE THE PASSENGER NAME BLOCK
XR R4,R4 ZERO OUT THIS REGISTER
AH R4,MI0CCT GET THE NUMBER OF BYTES PASSED
LTR R4,R4 IS R4 ZERO?
BE SETERROR YES, THEN GO EXIT
CLI MI0ACC,C'Y' ZERO OUT THE CURRENT PASSENGER NAME ?
BE ZAPNAME IF 'Y', THEN GO TO ZAP NAME
*
ENTRC ABCD INVOKE ABCD TO DO THE COPY
*
B EXITHERE GO TO EXIT
*
ZAPNAME DS 0H
XC PN0NM(L'256),PN0NM ZERO OUT THE CURRENT NAME RECORD
B EXITHERE
*
SETERROR DS 0H
MVI EBSW01,C'E' INDICATE AN ERROR OCCURRED
*
EXITHERE DS 0H
BACKC ,
*
LTORG ,
FINIS XYZ1
END ,

 

BEGIN NAME=ABCD,VERSION=A0

**********************************************************************

*THIS PROGRAM IS CALLED FROM XYZ1 TO COPY ITEMS FROM EBW WORK AREA. *

**********************************************************************
MI0MI REG=R1
PN0NR REG=R3
*
MVC PN0LST,EBW000 COPY IN LAST NAME (20 Bytes)
MVC PN0FST,EBW020 COPY FIRST NAME (15 Bytes)
MVC PN0PHN,EBW035 COPY PHONE NUMBER (12 Bytes)
MVC PN0FLT,EBW047 COPY FLIGHT NUMBER (4 Bytes)
*--------------------------------------------------------------------*
*Now, clear out the EBW work area. *
*--------------------------------------------------------------------*
XC EBW000(L'PN0LST),EBW000
XC EBW020(L'PN0FST),EBW020
XC EBW035(L'PN0PHN),EBW035
XC EBW047(L'PN0FLT),EBW047
*
BACKC ,
LTORG
FINIS ABCD
END

---------------------------------------------------------------------

Now, lets take a look at the generated results from the FalconTPF process supplied to me by the product team at Sapiens:

/********************************************************************/

/* File GACPTPF.C */
/* Generated by FALCON-TPF(c) */
/* The file was generated at 11.13.54 Thursday,19/08/99. */

/********************************************************************/

#define _GACPTPF_MAIN
#define TPF
#include "gacptpf.h"
void GACPTPF(struct TPF_regs *reg)
{
struct mi0mi * pMIM;
struct pn0nr * pPNR;
crusa(1,D4);
pMIM = ecbptr()->ce1cr0; /* BASE THE INPUT BLOCK */
pPNR = ecbptr()->ce1cr2; /* BASE THE PASSENGER NAME BLOCK */
reg->r4 = pMIM->mi0cct; /* GET THE NUMBER OF BYTES PASSED */
if (reg->r4!= 0) /* YES, THEN GOTO EXIT */
{
if (pMIM->mi0acc[0] != 'Y') /* IF 'Y', THEN GO TO ZAP NAME */
{
ABCD(pPNR); /* INVOKE ABCD TO DO THE COPY */
}
else
memset(pPNR->pn0nm, '\0', 256); /* ZERO OUT THE CURRENT- */
/* NAME RECORD */
}
else
{
ecbptr()->ebsw01 = 'E'; /* INDICATE AN ERROR OCCURRED */
}
reg->r1 = (sWord)(pMIM);
reg->r3 = (sWord)(pPNR);
}
/********************************************************************/
/* THIS PROGRAM IS CALLED FROM XYZ1 TO COPY ITEMS FROM EBW WORK AREA*/
/********************************************************************/
void ABCD( struct pn0nr * pPNR )
{
memcpy(pPNR->pn0lst, &ecbptr()->ebw000, sizeof(pPNR->pn0lst));
/* COPY IN LAST NAME (20 BYTES) */
memcpy(pPNR->pn0fst, &ecbptr()->ebw020, sizeof(pPNR->pn0fst));
/* COPY FIRST NAME (15 BYTES) */
memcpy(pPNR->pn0phn, &ecbptr()->ebw035, sizeof(pPNR->pn0phn));
/* COPY PHONE NUMBER (12 BYTES) */
memcpy(pPNR->pn0flt, &ecbptr()->ebw047, sizeof(pPNR->pn0flt));
/* COPY FLIGHT NUMBER (4 BYTES) */
/*------------------------------------------------------------------ */
/* NOW, CLEAR OUT THE EBW WORK AREA. */
/*------------------------------------------------------------------ */
memset(&ecbptr()->ebw000, '\0', sizeof(pPNR->pn0lst)); memset(&ecbptr()->ebw020, '\0', sizeof(pPNR->pn0fst)); memset(&ecbptr()->ebw035, '\0', sizeof(pPNR->pn0phn)); memset(&ecbptr()->ebw047, '\0', sizeof(pPNR->pn0flt));
}
---------------------------------------------------------------------

If you study the above translation and know anything about "C" programming, you'll see that the FALCONTPF results are nearly flawless. Most notably, the FALCONTPF translation process accomplished 4 major hurdles that are tantamount in any reliable translation tool:

Also of note on an advanced level is the way FALCONTPF correctly set up pointers to the level blocks instead of just using the "ecbptr()" macro. Including those steps helps to eliminate the complexity of understanding statements that follow and will help to reduce the overall size of the generated "C" modules.

My overall grade for this FalconTPF demonstration is definitely an "A". So, if you're looking for an easier and less painful way of moving your existing Assembler code to "C", you should give FalconTPF serious consideration.