In C
Accessorize Your Programs
BY SAMUEL STREEPER
Write dual-purpose C programs with CINIT.ARC on your START disk.
Have you ever written a useful utility and wished you could access it as a desk accessory? Or the other way around? Perhaps you converted that accessory into an executable program but don't like maintaining two source code files that do the same thing.
The truth is that there's very little difference between desk accessories and programs if they follow some simple guidelines. On this issue's START disk you will find MMINIT.C, LASINIT.C and MWINIT.S, which replace the standard initialization routines for Megamax C, Laser C and Mark Williams C, respectively. They're in the archive file CINIT.ARC. Copy CINIT.ARC and ARCX.TTP onto a blank, formatted disk and unARC CINIT.ARC following the Disk Instructions elsewhere in this issue.
difference between
desk accessories and
programs if they
follow some simple
guidelines.
The compiler-specific instructions for linking these initialization routines with your program are at the end of this article. These startup routines are not always recommended as a replacement for the standard routines; they are intended for programs that you want to be as small as possible. Compiling a very small program with these startup routines will reduce the executable file size from about 4,000 bytes to less than 400 bytes. However, the startup code will not parse the command line into the argv array and dirty, unclosed file streams will not be flushed to disk when the program terminates. I'll assume that since you want your program to run as an accessory (which accepts no command line arguments and never terminates), these issues don't bother you. These routines also use the ST-specific GEMDOS file routines which are smaller and faster than the corresponding Unix-compatible routines. In addition to taking care of startup housekeeping, the startup code sets a variable (_app) which is 0xff if the application is running as a program, 0 if it's a desk accessory.
The Main Event
Let's assume you have source code to an event-driven GEM program and
you'd like to turn it into a dual-purpose desk accessory/program. From
the evnt_multi function call, the application receives keypresses,
button clicks and window redraw messages. Also, programs may receive menu
bar events, and desk accessories may receive accessory open and close events
denoting that they've been activated or deactivated. (One requirement for
a dual-purpose desk accessory/program: the program must not be heavily
dependent upon the menu bar because when it runs as a desk accessory it
won't have one.)
To convert the program to act as a desk accessory, you'll need to add the code necessary to handle desk accessory open and close messages. There's no harm in having your program check to see if it receives accessory open events; it never will. The desk accessory must stay in the evnt_multi loop forever because if it terminates, the computer will reset. See the source to PRGACC.C to find out how to handle a dual-purpose evnt_multi loop.
Registration
If your application is being run as an accessory it should use the
menu_
register() call to put its name in the desk accessory menu bar so the
user can activate it. Make this call right after appl_init() because
if you make too many AES calls before calling menu_ register(),
the name won't be registered until the second time the Desktop is drawn.
Memory Handling
At load time, a desk accessory is given as much memory space as its
code and data require; it should not allocate more memory. On the other
hand, when a program is loaded, it is given the largest chunk of free memory
in the machine. It can keep as much of this memory as it needs, but should
give some of it back to the system. Assembly language programmers are responsible
for taking care of this initialization themselves. For programmers using
C or other high level languages, the compiler will take care of linking
initialization code that does this automatically.
program that you'd
like to use as a desk
accessory?
A desk accessory should not use malloc() to allocate memory,
primarily because this memory may be lost when the user changes resolution.
Also, old versions of GEMDOS allow only a small number of malloc()
calls (between 20 and 40), and the program the desk accessory is called
from may make some malloc() calls as well. An alternative to malloc()
is to reserve space by creating a pointer to a buffer.
The Resource Dumper
I wrote the utility RSCDUMP.TTP to let you merge a resource file with a C program listing. This program (and the source code) is on your START disk in CINIT.ARC. Copy CINIT.ARC and ARCX.TTP onto a blank, formatted disk and un-ARC CINIT.ARC following the Disk Instructions elsewhere in this issue. The following example program has a resource file with one object in it, a simple dialog box with one button. The following code loads the resource from disk and puts up the dialog box: #include "resource h" /* include object offsets */Now let's build that resource file in. Run the program RSCDUMP.TTP and type in the command line: resource. rsc >resource.cThis will give you the C data structures for the resource file in the file RESOURCE C That file will look like this OBJECT obj0[] = {You don't really need to understand this structure, but just by looking at it you can see that it is an array whose first object is a box type, and whose second object is a button type containing the text "A Button" Now look at the RESOURCE.H file created by the resource construction program: #define DIALOGBX 0This tells you that the dialog box is the "zeroth" object array and that the button is the first object in that array. Rewrite the above program fragment to include its resource: #define BUTTON 1If the application is running as a program and you wish to display this menu bar, simply call: convert_resource(menubar); /* only convert it once! */ |
Instead of
char *ptr;
ptr = Malloc((long)(16 * 1024));
use:
char buffer[(16 * 1024)];
char *ptr = buffer;
If you must use malloc(), do so before making any AES calls. If you allocate memory after AES calls, GEMDOS may take the memory away without warning.
A Resource Dumper
Your desk accessory/program should not load a resource file because
in doing so, GEM will allocate space for that file. On this issue's START
disk is the tool RSCDUMP.TTP, which lets you construct dialog boxes and
menu bars using a resource construction program. Then it outputs this file
as an array of C structures which you can incorporate into your program
easily. It works well for most resources that don't contain bitmapped structures.
See the sidebar accompanying this column for a description of how to use
this program.
The program PRGACC.C demonstrates a dual-purpose application. You can run PRGACC.PRG from the Desktop or rename the file PRGACC.ACC to use it as a desk accessory. The accompanying resource file PRGACC.RSC is not necessary; it's already incorporated into the program.
Link Notes for Megamax C
The Megamax linker MMUNK expects to find its initialization code in
the file INIT.O in the SYSLIB library file. Unfortunately, you can't specify
an alternate INIT file, so you'll need to replace this file in your system
library. Make a backup copy of the system library before you replace
1NIT.O! There may be times you'll want to use to the standard library.
Compile MMINIT.C, ignoring the compiler warnings. Change the name of the object file from MMINIT.O to INIT.O and optimize it using MMIMP:
mmimp init.oNow delete INIT.O from the system library and replace it:
mmlib dv syslib init.oYou may now compile your programs normally. I include my stack in a separate object file that lets me customize the amount of memory taken by the stack. Note that this stack, unlike the standard Megamax C stack, is part of the 32K of data space you can use from Megamax. This is only a limiting factor in very large programs. (If it's a problem, consider the upgrade to Laser C.)
mmlib rv syslib init.o
To link your program (and the stack):
mmlink your_prg.o mmstack.o -o your_prg.accLink Notes for Laser C
Compile the files LASINIT.C (the initialization code) and LASSTACK.C (the variable size stack). You don't need to have the initialization code in the system library; the linker assumes that the first file it links is the initialization code. If you use the graphic interface to the linker, remove the default file INIT.O and link with LASINIT.O as the first file. You may also have make call the linker with this as the first file:
prgacc.acc: prgacc.o
$(L1NKER) -v lasinit.o lasstack.o
prgacc.o $(CLIB) -o prgacc.acc
The file MKPRGACC in the CINIT.ARC archive file on your START disk is a sample Laser C makefile.
For what it is worth: the default Laser C init actually works fine as an init for programs or accessories. My init will generate smaller code for those who don't need file stream cleanup or command line arguments. Also, the current Laser init allocates the stack from GEMDOS if it initializes an accessory; this memory is lost when you change resolution.
Link Notes for Mark Williams C 2.0
Compile the file MWINITS as follows:
cc -c mwinit.sMove the resulting file MWINIT.O into your \LIB directory. Now to compile your program/accessory:
cc prgacc.c -Nrmwinit.o -laes -lvdiThe -Nrmwinit.o tells the linker to use the file MWINIT.O as the runtime startup module. The options -laes and -lvdi tell the linker to link your program with the GEM binding libraries.
Assembly Accessories
The file ASMBLY.S is an example of how to write an assembly application
which functions both as an accessory and a program. It was assembled with
HiSoft Devpac, but shouldn't be too difficult to transfer to another macro
assembler. It simply puts up a dialog box when it is run as a program or
selected as an accessory. It doesn't do the fancy window or menu handling
of the C example.
Conclusion
You now have all the tools to write dual-purpose applications. These
techniques will make debugging your desk accessories much easier, because
you can run them as programs until they work perfectly.
Samuel Streeper is currently working on an Atari ST MIDI networking
system. This is his first article in START
Programming in C. . . on your START Disk
The following files are in the archive file CINIT.ARC on your START disk: PRGACC.C
PRGACC.RSC
These files were created using the Megamax resource construction program but are not needed to run PRGACC since they have been incorporated in the program using Resource Dump. RSCDUMP.C
MMINIT.C
LASSTACK.C
MKPRGACC
MWINIT S
ASMBLY. PRO
|