Toolbox from Ada
Volume Number: 5
Issue Number: 3
Column Tag: Ada Additions
Calling the Mac ToolBox from Ada 
By Jerry N. Sweet, Laguna Hills, CA
[Jerry Sweet is a member of the technical staff at Meridian Software Systems,
Inc. Meridian is located at 23141 Verdugo Drive, Suite 105, Laguna Hills, CA 92653.
Their phone number is (714) 380-9800.]
Abstract
This report gives an overview of the techniques and tricks needed to write
AdaVantage programs that call Macintosh native system facilities, Specifically, how to
build "double-clickable" applications with AdaVantage is discussed
Meridian plans to introduce an Ada binding for the Macintosh Toolbox facilities
later. This report has been written to help those who who have special system
programming needs or who need to create Macintosh Toolbox interfaces immediately.
Readers should possess an understanding of how to use the AdaVantage compiler, a
reading knowledge of 68000 assembly language, MPW C, and Macintosh Pascal, a
familiarity with Inside Macintosh, and an understanding of the whys and wherefores of
object code linkage.
Making Calling Conventions Match
The Macintosh AdaVantage compiler uses C calling conventions. The Macintosh
operating system uses Pascal calling conventions or specialized (assembly language)
calling conventions that are different from the C calling conventions. This means that
to write Ada code that interfaces to the Macintosh system facilities, a combination of C
code interfaces and machine code insertions must be used.
One might assume that a liberal application of pragma interface is all that is
required to gain access to the Toolbox. Unfortunately, that is not the entire story,
because many of the Toolbox routines do not exist in object form such that they can be
linked with an Ada subprogram. This means that the linker will report unresolved
symbols for many or most interface routines, leaving the programmer wondering what
object library was omitted in the linkage or wondering what else might have gone
wrong.
The solution to this problem is to write one’s own “glue” routines that force the
Toolbox routines to become available in a linkable form. Glue routines are so called
because they create a bridge (i.e. “glue”) between two typically very different
collections of software. This is relatively easy to do with very small C subprograms
that may be named in interface pragmas. Alternatively, but not so easily in many
cases, machine code insertions may be used.
The most compelling reason for using glue routines written in C is that MPW C
provides a ready set of object code libraries and a corresponding set of “include” files
( .h files) that permit C programs to use most of the Macintosh system facilities
directly (i.e. a C language Toolbox binding is already defined). However, most of the C
function definitions contained in these include files use a Macintosh-specific extension
to the C language that generates in-line machine code for the Toolbox A-line traps and
at the same time translates the calling conventions automatically from C to Pascal
(“Pascal external” definitions). Because these function definitions are bound directly
at compile time, rather than at link time, they cannot be referenced by Ada programs.
To make these function definitions available to Ada programs via pragma interface ,
small “wrapper” routines can be written in C that simply call the in-line routines.
Another reason for using glue routines written in C wherever possible as opposed
to Ada machine code insertion routines is that one does not then have to figure out the
stack offsets of the various subprogram parameters and function results and then
write 68000 machine code to push and to pop the parameters.
Consider this example of an in-line C function definition, as defined in the MPW
C include file quickdraw.h :
/* 1 */
pascal void InitGraf(globalPtr)
Ptr globalPtr;
extern 0xA86E;
/* This definition causes an in-line machine instruction */
/* to be generated at the point of the call to this */
/* function. This is conceptually similar to applying */
/* Ada’s pragma inline to a machine code insertion */
/* routine. */
and here is an example of the corresponding wrapper routine that one would write in
C to make InitGraf accessible to an Ada program:
/* 2 */
#include
void MSS_InitGraf ( globalPtr )
Ptr globalPtr;
{
InitGraf ( globalPtr );
}
/* This definition causes a subprogram entry to be emitted */
/* to the object file so that MSS InitGraf is accessible */
/* to an Ada program via pragma interface. */