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 } } ---