macintosh@felix.UUCP (09/06/87)
---
/*
* LightspeedC source for a program to create and install a debugger
* FKEY, number 8, in the current system file.
* Earle R. Horton, August 30, 1987.
* (Inspired by Apple Technical Note # 145.)
* The above-mentioned technical note requires the MPW assembler, the
* MPW linker, RMaker, and a resource editor in order to create it. It
* also requires MacWrite in order to decode the technical note.
* This example requires only LightspeedC, version 2.01 or greater, and
* requires no special program to decode it, other than a text editor.
*
* This example is superior to the example provided in Technical Note 145
* for the following reasons.
*
* a) A data structure is used to insure our FKEY has the correct
* format.
* b) The program creates the FKEY, installs it in the current
* system file, and then tests it, all without leaving
* LightspeedC.
* c) This example is more elaborate than the example in the
* technical note, but yet is more simple in execution.
* i) It uses the C preprocessor.
* ii) It uses structure assignment.
* iii) It uses the "application" mode of
* LightspeedC to produce stand-alone code.
* iv) It uses Inline assembly.
*
* I know I will get bad karma for ridiculing Apple and their writers like
* this, but I just couldn't stop myself. I have just spent three days
* trying to decipher the specifications for a Printing Manager, and I am
* on the verge of "losing it". To the moderator of comp.sources.mac:
* Please, oh, please post this. Make my day.
*
* Tabstops are 8.
* Instructions:
* Make a new LightspeedC application project. Add this source
* file to it and select Run from the Project menu. For a really
* bloated project file, set the macro USING_MACTRAPS equal to 1
* and link the project with MacTraps.
*/
#define FBRANCH(a) (0x6000 | a) /* Assemble a short branch. */
#define Version 0x0000 /* Version number of zero. */
#define IDnum 0x0008 /* Use cmd-shift-8. */
#define Flags 0x0000 /* No flags. */
#define Type 'FKEY' /* It's an FKEY. */
#define INSTRUCTIONS 2 /* How many instructions will you need? */
#define nil 0L
/* Set the following to 1 if loading MacTraps into the project, 0 if not. */
#define USING_MACTRAPS 0
typedef struct{
short thebranch; /* Standard header, branch to start. */
short flags; /* You know, flags! */
long thename; /* Resource type. */
short theid; /* Number of resource. */
short theversion; /* Two byte version for your FKEY. */
short instructions[INSTRUCTIONS];
/* As many instructions as you need. */
}FKEY,*PFKEY,**HFKEY;
typedef void (*TESTFKEY)(); /* ProcPtr for testing FKEYs. */
short *makefkeycode(); /* Function to produce code. */
static FKEY myfkey = {
FBRANCH(10), /* Branch to +10, start of our code. */
Flags, /* Whatever you want. */
Type, /* Define the type. */
IDnum, /* Define the ID. */
Version, /* Version number of this resource. */
{0,0}, /* The actual code, to be filled in */
/* later. */
};
main(){
HFKEY newfkey,oldfkey; /* Handle to FKEY resource. */
int resultcode; /* Abort on error. */
TESTFKEY testing; /* ProcPtr to test it. */
short *stream; /* Array to hold machine code. */
int i; /* Loop counter. */
UseResFile(0); /* Use system file. */
oldfkey = (HFKEY)GetResource('FKEY',8);
/* Get the old FKEY. */
RmveResource(oldfkey); /* Pluck it out, discard. */
/* (Ignore errors, might not have been an old one present.) */
/*
* Get a handle to a block of memory big enough to hold our new FKEY.
* Check for memory error.
*/
#if USING_MACTRAPS
newfkey = (HFKEY)NewHandle((long)sizeof(FKEY));
resultcode = MemError();
#else
/*
* LightspeedC doesn't do inline register-based calls, so if you don't
* use MacTraps, you have to do this.
*/
asm{
move.l #((long)sizeof(FKEY)),d0 ;; Same thing as
NewHandle ;; above.
move.l a0,newfkey
move.w d0,resultcode
}
#endif
if((resultcode == 0) && (newfkey != nil)){
/* If new handle is assumed valid. */
stream = makefkeycode(); /* Get actual code. */
for(i= 0;INSTRUCTIONS - i;i++){
myfkey.instructions[i] = stream[i]; /* Copy it. */
}
**newfkey = myfkey;
/* Do the structure assignment, Ooh, Ahh! */
AddResource(newfkey,'FKEY',8,"\pDebugger FKEY");
/* Make it an FKEY resource. */
WriteResource(newfkey);
/* Save it. */
/* Let's try it out, right now! */
testing = (TESTFKEY)(*newfkey);
(*testing)();
}
}
/* This function is in two parts. The first part returns a pointer to
* the second part, then returns. The second part contains the actual
* FKEY code.
*/
short *makefkeycode()
{
asm{
dc.l 0x41FA0006 ;; lea 8(pc),a0
move.l a0,d0 ;; d0 = return value
rts
Debugger ;; FKEY code here
rts ;; don't forget to return
}
}
---