thitt@yacht.cis.ohio-state.edu (Todd A Hitt) (06/05/89)
Has anybody used a non-standard dialog box with SFPPutFile? I would like to add a check box to the bottom of my PutFile dialog box. In my dlgHook procedure I can toggle this item, but...how does one get the status of whether the check box was checked after SFPPutFile returns? I can't use a global variable in a Desk Accessory. I've tried using the dialog's refCon - which causes Standard File to crash. Any ideas? Thanks. Todd Hitt (614)424-3297 thitt@cis.ohio-state.edu hitt%36.114@ohstpy.mps.ohio-state.edu
siegel@endor.harvard.edu (Rich Siegel) (06/05/89)
In article <50967@tut.cis.ohio-state.edu> Todd A Hitt <thitt@cis.ohio-state.edu> writes: > >I can't use a global variable in a Desk Accessory. I've tried using the >dialog's refCon - which causes Standard File to crash. If you're using LightspeedC 3.0 or later, or Lightspeed Pascal 2.0 or later, then DA's can have globals. Otherwise, you can allocate storage in the dCtlStorage handle field of the DA's DCE. --Rich ~~~~~~~~~~~~~~~ Rich Siegel Staff Software Developer Symantec Corporation, Language Products Group Internet: siegel@endor.harvard.edu UUCP: ..harvard!endor!siegel "She told me to make myself comfortable, so I pulled down my pants and sat in the pudding." -Emo Phillips ~~~~~~~~~~~~~~~
tim@hoptoad.uucp (Tim Maroney) (06/06/89)
In article <50967@tut.cis.ohio-state.edu> Todd A Hitt <thitt@cis.ohio-state.edu> writes: >Has anybody used a non-standard dialog box with SFPPutFile? I would like >to add a check box to the bottom of my PutFile dialog box. In my dlgHook >procedure I can toggle this item, but...how does one get the status of >whether the check box was checked after SFPPutFile returns? > >I can't use a global variable in a Desk Accessory. I've tried using the >dialog's refCon - which causes Standard File to crash. Yes, strangely enough, Standard File sets its dialog's refCon to one and then crashes if it's changed. Maybe someone at Apple could enlighten us as to the reasons. Globals can be used in desk accessories. It's pretty easy with LightSpeed C, but fairly tricky with MPW C. If you really can't do this, then there are some other tricks. One thing would be to save the contents of one byte of ApplScratch or ToolScratch before going into Standard File, then setting it from inside Standard File, then extracting it after leaving and restoring the old value. Another way is to write directly into your DA's code space, using PC-relative instructions. This is pretty easy in assembly. The above approaches also have a decent chance of breaking on future systems.... Probably the best way is to use your DA's dCtlStorage field, or your DA window's refCon. The dCtlStorage field will be a bit tricky to get at inside the Standard File hook, but you should be able to find your dialog window very easily, and so find its refCon -- it's the nextWindow field of the Standard File dialog. (Some sophisticated approaches to DA windows might change that, but for most DAs, you will always be bringing up Standard File right in front of the DA window.) -- Tim Maroney, Consultant, Eclectic Software, sun!hoptoad!tim "Women's wages are 56% of men's -- but that's not necessarily evidence of discrimination in employment." -- Clayton Cramer in news.groups and soc.women
zben@umd5.umd.edu (Ben Cranston) (06/07/89)
Re: Standard File's putting a 1 in the dialog's RefCon and blowing up if it has changed: the version I am looking at puts the local frame (A6) value of Standard File's main routine into the RefCon; the dialog hook routine and other callback routines then use this to access Standard File's globals. I suggested to the original poster (offline, via mail) that one solution would be to extend the item list handle by one word and plant a pointer back to the DA's globals there. Then the dialog hook routine could link from the dialog record to the item list and pick up the pointer. Too bad the dialoghook routine doesn't get the SFReply record as an argument. Then one could just extend that record in a straightforward manner to accomodate this sort of extension... -- Ben Cranston <zben@umd2.UMD.EDU> (Kingdom of Merryland UniSys 1100/92) Copyright 1989 (you may redistribute ONLY if your recipients can).
thitt@schooner.cis.ohio-state.edu (Todd A Hitt) (06/07/89)
Thanks for all your ideas on Desk Accessories & (non)Standard-File. For a few of you who have asked why I can't use globals it's because I have a DA that's mostly in MPW Pascal and somewhat in MPW C. Neither one of these environments provide "official" support for globals in DA's. I'm sure someone from Symantec can enlighten us but I think they get around this problem by using another register (maybe A4?) to "anchor" the global variables. I believe that applications have their globals referenced by A5. But enough of that. Here's the solution or part of it, I used (and it works) that was sent to me by Krzysztof Kozminski: >In article <50967@tut.cis.ohio-state.edu> you write: >>Has anybody used a non-standard dialog box with SFPPutFile? I would like >>to add a check box to the bottom of my PutFile dialog box. In my dlgHook >>procedure I can toggle this item, but...how does one get the status of >>whether the check box was checked after SFPPutFile returns? >> >>I can't use a global variable in a Desk Accessory. I've tried using the >>dialog's refCon - which causes Standard File to crash. > >I am not sure how you are going to use dialog's refCon - I don't think >you can get at your DialogPtr before or after calling CFPPutFile ... > >Anyway, just an idea, based on what I do: > > long **h = NewHandle(4); > int checkBoxValue; > > **h = (long) &checkBoxValue; > AddResource(h,'pvte',0,"\p"); > > /* Now you have a private resource (in whatever is the current > resource file) that stores the address of your result. */ > > SFPPutfFile( ..., myHook, ...); > > /* my Hook calls GetResource(...'pvte',0...) to find out where to > put the value of the check box control. */ > > RmveResource(h); /* Don't want it added to, e.g., System */ > [stuff deleted] I've modified it a little to suit me but it works like a champ. I do feel a little funny using the resource manager like this, but it doesn't look like there is any particularly clean way to do this. Thanks Krzysztof! = = = = = = = = = = Todd Hitt thitt@cis.ohio-state.edu Battelle Columbus/Ohio State University hitt%36.114@ohstpy.mps.ohio-state.edu (614)424-3297 "You were not put on this earth to 'Get It'" - "Lo Pan" in Big Trouble in Little China -=- = = = = = = = = = = Todd Hitt thitt@cis.ohio-state.edu
siegel@endor.harvard.edu (Rich Siegel) (06/07/89)
In article <51276@tut.cis.ohio-state.edu> Todd A Hitt <thitt@cis.ohio-state.edu> writes:
[adding a resource (!!) to a resource file to hold storage]
Yeeeech. I would throw away any program that added resources
to a running application without my explicit command. The idea of adding
a resource in this manner has some big holes in it:
1. The file is modified.
1a. Doing so changes the mod date, which means that
the next time I do an incremental backup,
the file has to get backed up for no particularly
good reason.
1b. Doing so will set of virus detectors left and right.
2. What if the AddResource fails, perhaps because the disk is
write-protected or full? If that happens, you're hosed.
3. As I said, modifying applications without explicit command
is repugnant to me.
An alternate solution involves some assembly language, and works something like
this:
Define a 4-byte spot in your code where you can store a handle.
Then, allocate the handle with NewHandle, and put it there. Whenever
you need your global storage, retrieve the handle from this location
and use the handle. The code looks something like this (I'm writing
off the top of my head, so forgive me if this doesn't assemble).
;this is where the handle goes
HStorage:
dc.l 0
; this routine saves away the handle for you.
;
; procedure SaveAway(h : Handle);
;
SaveAway:
movea.l (a7)+, a0 ; pop the return address
movea.l (a7)+, a1 ; pop the argument
move.l a0, -(a7) ; push the return address back.
; a1 now contains the handle we want to store
lea @HStorage, a0 ; get the address of our storage
move.l a1, (a0) ; put the handle there
; we're done, so return. A more efficient routine might have
;left the return address in a register and done an indirect JMP,
;but this is quickie code.
rts
; this routine returns the handle that was saved away.
; procedure GetBack(var h : Handle);
;
movea.l (a7)+, a0 ; pop the return address
movea.l (a7)+, a1 ; pop the argument
move.l a0, -(a7) ; push the return address back.
; a1 now contains the address of the variable to hold our
; handle
lea @HStorage, a0 ; get the address of our store handle
move.l a0, (a1) ; store it in our variable
; we're done, so return.
rts
You can assemble this into a .O file, and it should
work substantially as written. This scheme is similar to the way that
THINK C and THINK Pascal save away A4, but to do globals from A4 requires
a little assistance from the compiler and linker.
TLSC and TLSP also have jump-table support which allows you to write
multi-segment DA's and drivers, and (in TLSP) to write DA's or drivers in
Object Pascal. (A rather unique capability, if I may say so myself. :-)
--Rich
~~~~~~~~~~~~~~~
Rich Siegel
Staff Software Developer
Symantec Corporation, Language Products Group
Internet: siegel@endor.harvard.edu
UUCP: ..harvard!endor!siegel
"She told me to make myself comfortable, so I pulled down my pants
and sat in the pudding." -Emo Phillips
~~~~~~~~~~~~~~~
zben@umd5.umd.edu (Ben Cranston) (06/08/89)
Re: using one of the development packages that implements local variables for DAs and other data-less code resources by using A4 as an ersatz global pointer. Standard File saves A4 on entry and uses it to point to other things! For much of the routine it points to the SFReply record, however several of the subroutines save it and use it for local purposes! Therefore it would not work to access DA globals from hook routines... I though of these other ways to solve the original poster's problems: 1. Run the device chain looking for DA's entry, link back to device's control data (see Tim's posting). 2. Use the A6 value from the windows RefCon, knowing that the SFReply record pointer can be found at 8(A6). 3. Use the A4 value, expecting Standard File to have it pointing at SFReply. 4. Build, in a small non-relocatable block, a separate A5 world for the DA. (See the init-time-icon display code recently posted here for examples). At a known offset in that block would be the handle to the main DA data. "Work is the drink of the cursing class..." -- Ben Cranston <zben@umd2.UMD.EDU> (Kingdom of Merryland UniSys 1100/92) Copyright 1989 (you may redistribute ONLY if your recipients can).
tim@hoptoad.uucp (Tim Maroney) (06/08/89)
In article <51276@tut.cis.ohio-state.edu> Todd A Hitt <thitt@cis.ohio-state.edu> writes: >But enough of that. Here's the solution or part of it, I used (and it works) >that was sent to me by Krzysztof Kozminski: > >>Anyway, just an idea, based on what I do: >> >> long **h = NewHandle(4); >> int checkBoxValue; >> >> **h = (long) &checkBoxValue; >> AddResource(h,'pvte',0,"\p"); I don't mean to be the bad guy, but this is a horrible solution. Adding resources to someone else's resource file? Can you say massive potential for conflicts? Can you say forget about network compatibility if you write into an application file? Can you say every sense of programming elegance revolts? There are a number of other solutions that work much better. Ben Cranston pointed out that the dialog item list could have a pointer to globals appended to the end of it. I pointed out that you could use the refCon of your main DA window behind the SF dialog; I also pointed out that you could write into your DA's code space. Rich Siegel suggested using the private storage field of your DA's device control entry, which you can find by looping through the unit table as described in a Tech Note. I'm sure you got other reasonable answers as well, answers that don't require writing into other people's files without even knowing what files they are! >> RmveResource(h); /* Don't want it added to, e.g., System */ That's for sure! Not even for a second! >I've modified it a little to suit me but it works like a champ. I do feel >a little funny using the resource manager like this, but it doesn't look like >there is any particularly clean way to do this. There are much cleaner ways that that, believe me.... -- Tim Maroney, Consultant, Eclectic Software, sun!hoptoad!tim "When errors are found in old research, the relevant theories are re-examined. When facts contradict theory, theory gets dumped. Is that why the NLP people are unwilling to research their facts?" -- Jerry Hollombe on sci.psychology
siegel@endor.harvard.edu (Rich Siegel) (06/08/89)
In article <4975@umd5.umd.edu> zben@umd5.umd.edu (Ben Cranston) writes: >Re: using one of the development packages that implements local variables for >DAs and other data-less code resources by using A4 as an ersatz global pointer. > >Standard File saves A4 on entry and uses it to point to other things! For >much of the routine it points to the SFReply record, however several of the >subroutines save it and use it for local purposes! In principle, you're correct. In practice, TLSP and TLSC provide SetupA4() and RestoreA4(), which are to be used in routines which are callbacks from the Toolbox or other places that don't know about the A4 global conventions. This works quite well - a number of DA's have been written using A4 globals in TLSC, and they work, and they do use Standard file. > [outlines other methods, like using the refcon and expecting it > to point to SF's frame pointer] It's best to use the standard callback mechanism, since you never know when the people who wrote Standard File may decide to keep SF's A6 some- where else. As I said above, callbacks written using TLSC and TLSP will work fine, provided you use SetupA4() and RestoreA4(). --Rich ~~~~~~~~~~~~~~~ Rich Siegel Staff Software Developer Symantec Corporation, Language Products Group Internet: siegel@endor.harvard.edu UUCP: ..harvard!endor!siegel "She told me to make myself comfortable, so I pulled down my pants and sat in the pudding." -Emo Phillips ~~~~~~~~~~~~~~~
thitt@hydroplane.cis.ohio-state.edu (Todd A Hitt) (06/08/89)
Just to set the record straight ... I'm not advocating using resources for temporary purposes. I agree whole-heartedly with Rich Siegel and I do think his assembly language based solution is the most bullet-proof. However ... some people out there may not be using Lightspeed products and not have access to an assembler. In these cases, they may be stuck with using resources as temporary holders. -=- Todd Hitt thitt@cis.ohio-state.edu Battelle Columbus/Ohio State hitt%36.114@ohstpy.mps.ohio-state.edu (614)424-3297 "You were not put on this earth to 'Get It'" - "Lo Pan" in Big Trouble in Little China
siegel@endor.harvard.edu (Rich Siegel) (06/08/89)
In article <51402@tut.cis.ohio-state.edu> Todd A Hitt <thitt@cis.ohio-state.edu> writes: > >However ... some people out there may not be using Lightspeed products and not >have access to an assembler. In these cases, they may be stuck with using >resources as temporary holders. My advice to such people is that if they are doing any kind of work that is intended for publication (be it freeware to the net, shareware, or commercial product), they should expend the effort to do the work correctly, and if they expect any kind of return on their efforts, then spending the money ($100 for the MDS system, at last count) for a tool to get the job done is worthwhile. I've found that for some tasks, a macro assembler is absolutely essential. I'm sure that others will agree with me. If you're hacking in the privacy of your own home, far be it from me to tell you what to do. :-) --Rich ~~~~~~~~~~~~~~~ Rich Siegel Staff Software Developer Symantec Corporation, Language Products Group Internet: siegel@endor.harvard.edu UUCP: ..harvard!endor!siegel "She told me to make myself comfortable, so I pulled down my pants and sat in the pudding." -Emo Phillips ~~~~~~~~~~~~~~~
wdh@well.UUCP (Bill Hofmann) (06/08/89)
In article <4975@umd5.umd.edu> zben@umd5.umd.edu (Ben Cranston) writes: >Re: using one of the development packages that implements local variables for >DAs and other data-less code resources by using A4 as an ersatz global pointer. > >Standard File saves A4 on entry and uses it to point to other things! For >much of the routine it points to the SFReply record, however several of the >subroutines save it and use it for local purposes! > >Therefore it would not work to access DA globals from hook routines... Not so. I've been using a4 in standard file hooks and dialog filter procs for years. All one has to do is save a4 first, then restore at completion. Really, folks, it's a solved problem, at least in any environment other than MPW. Lightspeed makes it quite easy, with SetUpA4() and RestoreA4(), and Manx (typically for Manx) requires a bit of hacking, but look at the sample code in the explorer da, and generalize the save and restore routines. Note that the Dialog manager uses A4 when it calls user item routines (another gotcha). -Bill Hofmann Flashpoint
kk@mcnc.org (Krzysztof Kozminski) (06/08/89)
In article <2015@husc6.harvard.edu> siegel@endor.UUCP (Rich Siegel) writes: >In article <51276@tut.cis.ohio-state.edu> Todd A Hitt <thitt@cis.ohio-state.edu> writes: >> [adding a resource (!!) to a resource file to hold storage] > > Yeeeech. [followed by bashing of the idea, admittedly deserved] OK, OK, so I won't suggest any more ideas generated at 3 am ... but it worked perfectly in that at least Todd got some sound suggestions from Ben Cranston. I am not sure if Rich's solution is applicable - remember that Todd has mentioned that for some reasons he cannot use global variables. :-):-):-):-):-):-):-):-) BTW, an idea that I had at 3:15 am was to use the NULL location: *((Handle*) 0L) = HStorage; Why not? All applications should avoid writing into NULL location, so your data should be perfectly safe there (However, standard file dlogs used to dump 0x00FFFFFF into *NULL in older Sysytem versions) :-):-):-):-):-):-):-):-) For the record, my full letter to Todd included an outline of another technique (using refCon in an existing, privately owned CNTL resource that is already in memory - so that it wouldn't cause any problems that AddResource is likely to create) - similar to Ben Cranston's idea of extending the dialog item list. (I use it to pass data to a custom CDEF that is invoked from a CNTL that is appended to the DITL number -3999 after having increased the window size in DLOG number -3999 to show my extra CNTL) Now, modifying a system DITL in memory is also not that great idea (other applications may want to use it) and having a duplicated, modified DITL in the application calls for updates each time Apple changes theirs... so my application compares its DITL with the system DITL upon startup and updates the modified DITL if necessary (and DLOG, too). Any holes or potential problems there? ------------------------------ Now my turn in idea - bashing: >An alternate solution involves some assembly language, and works something like >this: > Define a 4-byte spot in your code where you can store a handle. Yeeechh. A "spot in your code"? Tim Maroney also suggested writing into the code space ... Is self-modifying code OK nowadays? Anyway, I have this impression that a spot in memory, the address of which is known to more than one routine, is called a global variable ... > [Two procedures in assembly] It seems to me that what Rich wrote is essentially equivalent to the following: Handle HStorage; SaveAway(h) Handle h; { HStorage = h; } GetBack(hp) Handle *hp; { *hp = Hstorage; } That's *not* the answer to the original question (no globals, remember?). Perhaps this modification would work: SaveAndGetBack(saveIt, hp) Boolean saveIt; Handle *hp; { static Handle HStorage; if (saveIt) HStorage = *hp; else *hp = HStorage; } but then, if a development system does not allow globals, then why would it allow static variables? KK
svc@well.UUCP (Leonard Rosenthol) (06/08/89)
In article <2015@husc6.harvard.edu>, siegel@endor.harvard.edu (Rich Siegel) writes: > In article <51276@tut.cis.ohio-state.edu> Todd A Hitt <thitt@cis.ohio-state.edu> writes: > > [adding a resource (!!) to a resource file to hold storage] > > Yeeeech. I would throw away any program that added resources > to a running application without my explicit command. The idea of adding > a resource in this manner has some big holes in it: > I agree that adding a resource FOR THIS reason is VERY bad and I agree that it using resources 'freely' for this type of purpose is not always the way to go - BUT there are VERY good reason to add resources to a file WITHOUT user intervention. One of the best reason that I know of, and that both MPW and MicroPhone II v3.0 do, is autosaving of window sizes/positions. Since the user could reposition/resize his windows WITHOUT changing any settings/text you must STILL retain that window change and the best way that I have found to do that is to simply add a resource to the datafile when it is closed which contains the window info. > 1. The file is modified. > 1a. Doing so changes the mod date, which means that > the next time I do an incremental backup, > the file has to get backed up for no particularly > good reason. > I agree that this does change that mod date, but you HAVE changed the file if you HAVE moved windows. If the mod date problem you felt strongly about you COULD get the curModDate, make the resChange, and then reset the date. > 1b. Doing so will set of virus detectors left and right. > Maybe. We have not found any that get upset about it yet... > 2. What if the AddResource fails, perhaps because the disk is > write-protected or full? If that happens, you're hosed. > For the original concept, yes you are - but for saving window pos it just means that user doesn't get his positions saved. You could, of course, alert the user to the situation just like you do when you try to do ANY write. > 3. As I said, modifying applications without explicit command > is repugnant to me. > I, again, ask you to reconsider - though I AGREE that APPLICATION modification is A LOT worse then datafile mods. -- +--------------------------------------------------+ Leonard Rosenthol | GEnie : MACgician Lazerware, inc. | MacNet: MACgician UUCP: svc@well.UUCP | ALink : D0025
zben@umd5.umd.edu (Ben Cranston) (06/09/89)
Actually, of all the ideas presented, I like the store-into-our-code idea the best. Yes, self-modifying code is not a good thing. But, it is the ONLY way to properly manage A5 in the MultiFinder world, given that CurrentA5 may be swapped out by MF. The only problem I have with the technique is that the people who designed the MC680x0 had the same tunnel vision. "Storing into our own code is a *BAD* thing!", they thought, so they omitted any kind of PC relative store instruction! So you gotta do something like this: LEA blappo,A1 Move.L A5,(A1) Oh, well, it's only one extra instruction... My suggestion of using A4 or A6 was not real. Nobody should depend on the structure of another program like that. The point about SetupA4 and RestoreA4 is well taken. I wonder how they are implemented, though. The old SetupA5 and RestoreA5 used a reserved low memory location (CurrentA5) and I wonder if there is some kind of reservation for A4 in low memory (deal between Apple and developers?) and if there is a similar MultiFinder problem with the low-core location. This would show up in background event handling in MF-aware programs, also in handling raw IO interrupts etc... Q. How many computer professionals does it take to change a lightbulb? A. Three One customer engineer to decide the problem is software. One systems programmer to decide the problem is applications software. One applications programmer to reprogram the light switch... -- Ben Cranston <zben@umd2.UMD.EDU> (Kingdom of Merryland UniSys 1100/92) Copyright 1989 (you may redistribute ONLY if your recipients can).
siegel@endor.harvard.edu (Rich Siegel) (06/09/89)
In article <1241@speedy.mcnc.org> kk@mcnc.org.UUCP (Krzysztof Kozminski) writes: >BTW, an idea that I had at 3:15 am was to use the NULL location: > *((Handle*) 0L) = HStorage; > >Why not? All applications should avoid writing into NULL location, so >your data should be perfectly safe there (However, standard file dlogs >used to dump 0x00FFFFFF into *NULL in older Sysytem versions) Some Radius products do (or used to, at least) use location zero for their own purposes. On the memory map, location 0 is noted as being "part of the system heap", and is usually smashed by applications, whether they're supposed to or not. >> Define a 4-byte spot in your code where you can store a handle. > >Yeeechh. A "spot in your code"? Tim Maroney also suggested writing into >the code space ... Is self-modifying code OK nowadays? Anyway, I have this >impression that a spot in memory, the address of which is known to more >than one routine, is called a global variable ... This is not self-modifying code, because the location that's modified is never executed. It's actually storing data in code space; this particular trick WILL fail once an OS comes out that has separate code and data spaces, but it's reasonably far off. >> [Two procedures in assembly] > >It seems to me that what Rich wrote is essentially equivalent to the following: [An incorrect translation of my assembler source into C]. Taken literally, you're correct; the saved-away handle IS known to more than one routine. However, the routines that DO know about the handle are exactly two in number, and any other routine which wants the handle must access it as an argument to a procedure. Furthermore, "true" global variables are accessed as offsets from a globals base register, such as A5. The saved-away handle is not a global in this sense, since it's accessed via PC-relative offsets, which means that it's independent of the value of ANY base register, which provides an easy and reliable to fetch and store the value. Which was the problem in the first place: not that ANY globals weren't allowed; the code just couldn't use "True" globals (ones that would be addressed relative to a base register). --Rich ~~~~~~~~~~~~~~~ Rich Siegel Staff Software Developer Symantec Corporation, Language Products Group Internet: siegel@endor.harvard.edu UUCP: ..harvard!endor!siegel I classify myself as a real developer because my desk is hip-deep in assembly-language listings and I spend more than 50% of my time in TMON. ~~~~~~~~~~~~~~~
tim@hoptoad.uucp (Tim Maroney) (06/09/89)
I agree with Rich; to do serious programming on the Mac, you *need* an assembler. I think it was a terribly foolish decision to stop bundling the excellent MPW Assembler with the MPW Shell. I can't imagine a serious programming project on the Mac that uses absolutely no assembly language. Very little, possibly, but none? No way. And again, I agree with Rich that you need to *not* write resources into other people's files. It's not a solution, period. Don't do it. There are tons of other ways to do what you need without stepping on people's resource files. How often do both Rich and I spontaneously clutch our throats and make loud exaggerrated gagging noises? Not very often? That should tell you something! So what's wrong with using the DCE private storage field or the refCon of the main DA window? You can get at both without globals, and they both have the ability to store whatever you need. Unlike writing into code space, they won't break on future systems. -- Tim Maroney, Consultant, Eclectic Software, sun!hoptoad!tim "Jesus died for somebody's sins, but not mine." -- Patti Smith
tim@hoptoad.uucp (Tim Maroney) (06/09/89)
In article <1241@speedy.mcnc.org> kk@mcnc.org.UUCP (Krzysztof Kozminski) writes: >>An alternate solution involves some assembly language, and works something like >>this: >> Define a 4-byte spot in your code where you can store a handle. > >Yeeechh. A "spot in your code"? Tim Maroney also suggested writing into >the code space ... Is self-modifying code OK nowadays? No, which is fine, since this is not self-modifying code. No instructions are being written. Writing to a DC.L in your code is not in any way self-modifying code unless the PC hits that location at some point. Nothing that's being written is ever executed, that is, no code is modified. (Actually some self-modifying code is OK -- the jump tables used by the Segment Loader are an example. The modification is very simple and well-defined: a LoadSeg trap is replaced by a JMP instruction. The superstition against self-modifying code originates in more complicated self-modifying software, which is like Dijkstra spaghetti after you run it through a blender.) >Anyway, I have this >impression that a spot in memory, the address of which is known to more >than one routine, is called a global variable ... Then you have a mistaken impression. A global variable on the Macintosh is an offset from register A5 or register A4. The kind of storage Rich and I are suggesting is an offset from the PC. >It seems to me that what Rich wrote is essentially equivalent to the following: > > Handle HStorage; > SaveAway(h) Handle h; { HStorage = h; } > GetBack(hp) Handle *hp; { *hp = Hstorage; } > >That's *not* the answer to the original question (no globals, remember?). You're being silly, Krsysztof. They are not equivalent. For your code to run on the Mac, there has to be a properly initialized globals register, which is what Tom can't cope with from MPW C in a DA. For the code Rich gave (similar to code myself and others have frequently used in our trap patches etc.) there is no such requirement. Tom didn't object to globals on metaphysical grounds, but on pragmatic ones. This is a technical programming problem, not a brain teaser from a puzzle book. >Perhaps this modification would work: > > SaveAndGetBack(saveIt, hp) > Boolean saveIt; Handle *hp; > { static Handle HStorage; > if (saveIt) HStorage = *hp; > else *hp = HStorage; > } > >but then, if a development system does not allow globals, then why would it >allow static variables? It won't. This code also requires a globals register, unlike Rich's. I can't see why you think there might be a difference. I should point out that the SetUpA4 (etc.) macros in Lightspeed C actually work by a code-space write. They can be expected to break on a memory-protected OS, as can the code-space write Rich and I proposed. So when there's an alternative, as there is for what Tom is trying to do, it should be taken. (No use enumerating the alternatives once again.) Nonetheless, in situations where nothing else will do, then the code-space write technique is legitimate. -- Tim Maroney, Consultant, Eclectic Software, sun!hoptoad!tim "The pride of the peacock is the glory of God. The lust of the goat is the bounty of God. The wrath of the lion is the wisdom of God. The nakedness of woman is the work of God." - Blake, "The Marriage of Heaven and Hell"
earleh@eleazar.dartmouth.edu (Earle R. Horton) (06/09/89)
This looks like fun! May I throw in my two cents worth? In article <2024@husc6.harvard.edu> siegel@endor.UUCP (Rich Siegel) writes: >In article <1241@speedy.mcnc.org> kk@mcnc.org.UUCP (Krzysztof Kozminski) writes: >>BTW, an idea that I had at 3:15 am was to use the NULL location: >> *((Handle*) 0L) = HStorage; ... > Some Radius products do (or used to, at least) use location zero >for their own purposes. On the memory map, location 0 is noted as being >"part of the system heap", and is usually smashed by applications, whether >they're supposed to or not. The 68000 reference I use says location zero holds the initial supervisor stack pointer when the machine is first powered up. This makes it a theoretically safe location to use for temporary storage from within a desk accessory. Aesthetically, however, it's a real bad idea. It produces the same problem that you get using ToolScratch, ApplScratch, or any other lowmem location--conflicts with other pieces of code. >>> Define a 4-byte spot in your code where you can store a handle. >> >>Yeeechh. A "spot in your code"? Tim Maroney also suggested writing into >>the code space ... Is self-modifying code OK nowadays? Anyway, I have this >>impression that a spot in memory, the address of which is known to more >>than one routine, is called a global variable ... > > This is not self-modifying code, because the location that's modified >is never executed. It's actually storing data in code space; this particular >trick WILL fail once an OS comes out that has separate code and data spaces, >but it's reasonably far off. Aha! So one of you A4-relative types admits that the trick will fail someday! This makes my day. If Apple is real careful about compatibility of OS releases and the Toolbox, then much current software will still be in operational condition when separate code and data spaces are implemented. It would be real sad for any software to fail then, JUST BECAUSE it writes to its own code space. It's just not real nice to write computer software which has a shorter lifetime than it could have, had you coded it differently. Modifying code space to store variables or Handles to variables seems to save a lot of work in writing code for desk accessories and other code resources today, but is the work saved worth the inevitable aggravation that users will experience if and when the OS makes that technique invalid? Will you be around to make sure the software you have written gets re-coded properly at that time, and will you be able to make sure that users receive upgrades in a timely manner? Perhaps not... Please think carefully before using any technique which can be demonstrated to have a high probably of failure under a future operating system, no matter how convenient it might be to use it today. ... > I classify myself as a real developer because my desk is hip-deep in > assembly-language listings and I spend more than 50% of my time in TMON. 84+ hours a week, wow! Earle R. Horton "People forget how fast you did a job, but they remember how well you did it." Salada Tag Lines
siegel@endor.harvard.edu (Rich Siegel) (06/09/89)
In article <13855@dartvax.Dartmouth.EDU> earleh@eleazar.dartmouth.edu (Earle R. Horton) writes: > > This looks like fun! May I throw in my two cents worth? It IS fun. By the way, Tim Maroney and I really ARE two different people, even though our postings have similar content. I guess we just think the same way.... :-) > Aha! So one of you A4-relative types admits that the trick will >fail someday! This makes my day. If Apple is real careful about Hey, I never said it would work forever. It's actually an educated bet, because it's highly possible that when separate code and data spaces are implemented in the OS, the support structure desk accessories may be radically different, and may well support base-register-relative globals for DA's. Who knows? > It's just not real nice to write computer software which has a >shorter lifetime than it could have, had you coded it differently. I challenge you to solve this problem for the PRESENT incarnation of the operating system, given the contstraints of not being allowed to use a base register, and not being allowed to use any low-memory system space. For example, suppose you have an INIT and a cdev that need to share information with one another? How do you propose to have them communicate? Remember, there's no low memory you can use, and there's no place to place a base register. Well, you could put a block in the system heap with your unique signature in it, and crawl the system heap for it, BUT that (a) won't work when the format of heap blocks changes, and (b) won't work when the system heap becomes protected. As I said, this is just an example. Sometimes, expediency is necessary. It's a risk, but it beats the alternatives (bogus solutions, or no solutions at all). > Please think carefully before using any technique which can be >demonstrated to have a high probably of failure under a future >operating system, no matter how convenient it might be to use it >today. And please think carefully for attacking proven techniques, without also providing a workable solution of your own..... --Rich ~~~~~~~~~~~~~~~ Rich Siegel Staff Software Developer Symantec Corporation, Language Products Group Internet: siegel@endor.harvard.edu UUCP: ..harvard!endor!siegel I classify myself as a real developer because my desk is hip-deep in assembly-language listings and I spend more than 50% of my time in TMON. ~~~~~~~~~~~~~~~
earleh@northstar.dartmouth.edu (Earle Horton) (06/09/89)
I had to hack the references line, because either my news reader or my news poster had an "interp buffer overflow." Sorry if this breaks anyone's train of thought. In article <2026@husc6.harvard.edu> siegel@endor.harvard.edu (Rich Siegel) writes >In article <13855@dartvax.Dartmouth.EDU> earleh@eleazar.dartmouth.edu > (Earle R. Horton) writes: ... >> It's just not real nice to write computer software which has a >>shorter lifetime than it could have, had you coded it differently. > > I challenge you to solve this problem for the PRESENT incarnation >of the operating system, given the contstraints of not being allowed >to use a base register, and not being allowed to use any low-memory >system space. > > For example, suppose you have an INIT and a cdev that need to >share information with one another? How do you propose to have them >communicate? Whoa! I thought we were talking about desk accessories here! Desk accessories have an officially sanctioned place where they are allowed to store information. This is the dCtlStorage field of the Device Control Entry. This field is accessible from anywhere in the code of the 'DRVR' resource, even in a filterproc (I know how to find it, anyway). It is, therefore, not necessary to write to the driver's code space in order to implement private storage for a desk accessory or device driver. You are quite right in saying that there do exist applications where writing to code space and low memory seems to be the only solution presently available. I don't believe that a Desk Accessory or Device Driver is one of these. ... >> Please think carefully before using any technique which can be >>demonstrated to have a high probably of failure under a future >>operating system, no matter how convenient it might be to use it >>today. > > And please think carefully for attacking proven techniques, without >also providing a workable solution of your own..... There are existing working solutions for device drivers under the present system, which do not write into the driver's code space. (Device drivers include Desk Accessories.) What I mean to say is that the safe solution should be used for these, even though it is perhaps more cumbersome than the A4-stashed-in-code method. Desk Accessories should not write to code space because they don't really have to, and because the technique may cause them to break someday. In regard to INIT/cdev combinations, well you have to do what you have to do, and I don't suppose I can argue with that. Earle R. Horton "People forget how fast you did a job, but they remember how well you did it." Salada Tag Lines
jmunkki@santra.UUCP (Juri Munkki) (06/09/89)
siegel@endor.harvard.edu (Rich Siegel) writes: > earleh@eleazar.dartmouth.edu (Earle R. Horton) writes: > > This looks like fun! > It IS fun. I have to agree. > For example, suppose you have an INIT and a cdev that need to > share information with one another? How do you propose to have them > communicate? Remember, there's no low memory you can use, and there's > no place to place a base register. Well, you could put a block in the > system heap with your unique signature in it, and crawl the system > heap for it, BUT that (a) won't work when the format of heap blocks > changes, and (b) won't work when the system heap becomes protected. That's the technique that is described in the QuicKeys manual. I've also used it on one occasion, but I know of a better way to do it. There's only one problem with the better way and it's that it isn't always possible (and it doesn't work with old systems). The solution is to use AppleTalk. If you Mac isn't connected to a network, this doesn't work, but in my case I was writing a program that already required an AppleTalk network. My INIT registered itself with name binding protocol and it also had it's own DDP socket listener. My cdev could have set the selfsend flag, found any entity of the correct type on the local node and sent a ddp packet to this socket. After this the two programs can communicate by sharing memory. There are some problems with writing socket listeners under multifinder or using them from INITs. While writing a VBL task to control the sound driver, I came up with a pretty good solution that works just as well for socket listeners. The solution is LSC specific, since it uses the inline assembler. Here are some code fragments to get you started: /* Note: VVars is just any structure you need >> If A5 points to a VVars structure, the following macro will become >> xx(A5), where xx is the offset into that structure element. */ #define VBV(field) ((int) &((VVars *) 0)->field)(A5) VVars Vv; /* Vertical blanking variables */ /* >> Setup vertical blanking variables & >> install vertical blanking task. */ void InstallMyVBL() { long vbltask; asm { lea @myvbltask,A0 ;Get address of vbltask move.l A0,vbltask ;Store in local variable lea @mybase,A0 ;Get addr of variable base storage lea Vv,A1 ;Get addr of Vv record move.l A1,(A0) ;Store base in base storage } Vv.VBL.qType=vType; /* Vertical blanking queue. */ Vv.VBL.vblAddr=(ProcPtr)vbltask;/* Address of task */ Vv.VBL.vblCount=1; /* Every 1/60 seconds */ Vv.VBL.vblPhase=0; /* 0 is ok.. */ VInstall(&Vv.VBL); /* Install task in queue */ if(0) /* Skip the following :-) */ asm { @myvbltask move.l A5,-(SP) ;Save A5 move.l @mybase,A5 ;Get Vv address into A5 move.w #1,VBV(VBL.vblCount) ;Call again in 1/60 seconds [ Some code deleted... Vv structure elements are accessed as: sub.w #1,VBV(CountB) ;Decrement channel B count In C you would have written Vv.CountB ] @endvbl move.l (SP)+,A5 ;Restore A5 rts ;Return from vbl routine @mybase dc.l 0 ;Vv record address stored here. } } To install the VBL task, you call this routine and to control what it does you just change its variables. (Remember that this is "multitasking" so that you have to use some sort of locking to prevent the vbl task from seeing changes that aren't complete.) -- _._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._ | Juri Munkki jmunkki@hut.fi jmunkki@fingate.bitnet I Want Ne | | Helsinki University of Technology Computing Centre My Own XT | ~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~
svc@well.UUCP (Leonard Rosenthol) (06/10/89)
In article <7596@hoptoad.uucp>, tim@hoptoad.uucp (Tim Maroney) writes: > I agree with Rich; to do serious programming on the Mac, you *need* an > assembler. I think it was a terribly foolish decision to stop bundling > the excellent MPW Assembler with the MPW Shell. I can't imagine a > serious programming project on the Mac that uses absolutely no assembly > language. Very little, possibly, but none? No way. > I will agree with both Tim and Rich that an assembler is a VERY useful item and that no programmer should be without one - HOWEVER I disagree that just because a program does not have any assembly in it, means it is not a SERIOUS programming project. I can name a NUMBER of major commericial Macintosh software which does not contain ONE SINGLE ASSEMBLY instruction. (this even includes defprocs!) -- +--------------------------------------------------+ Leonard Rosenthol | GEnie : MACgician Lazerware, inc. | MacNet: MACgician UUCP: svc@well.UUCP | ALink : D0025
tim@hoptoad.uucp (Tim Maroney) (06/10/89)
In article <13855@dartvax.Dartmouth.EDU> earleh@eleazar.dartmouth.edu (Earle R. Horton) writes: >Aesthetically, however, it's a real bad >idea. It produces the same problem that you get using ToolScratch, >ApplScratch, or any other lowmem location--conflicts with other pieces >of code. Unless, as I pointed out when I proposed it, you save the old state and restore it before anyone else gets a chance to use it. If you save the value, call Standard File, extract the value stashed by your filter procs, and restore the old value, there's no way any code that would use the scratch storage will be interfered with. Only system software, interrupt driven code, and trap patches would have a chance to see it, and it's clear that such software is not allowed to use the scratch areas. Like storing the information in the refCon of the DA window, using ApplScratch or ToolScratch with a state save/restore seems to have been a useful and *easy* technique that was dismissed out of hand for some unknown reason. It's stuff like this that makes me wonder why I put so much work into this newsgroup. It's frustrating. -- Tim Maroney, Mac Software Consultant, sun!hoptoad!tim, tim@toad.com Postal: 424 Tehama, SF CA 94103; Phone: (415) 495-2934 "I slept with Faith, and found a corpse in my arms on awaking; I drank and danced all night with Doubt, and found her a virgin in the morning." -- Aleister Crowley, THE BOOK OF LIES
paul@taniwha.UUCP (Paul Campbell) (06/10/89)
In article <22694@santra.UUCP> jmunkki@santra.UUCP (Juri Munkki) writes: >To install the VBL task, you call this routine and to control what it does >you just change its variables. (Remember that this is "multitasking" so that >you have to use some sort of locking to prevent the vbl task from seeing >changes that aren't complete.) This brings up one of my chief beefs about the MacOS, if you are doing something like this involving: VBL's DDP socket listeners IO completion routines Deferred Tasks Device interrupt handlers in short anything asynchronous - there are no primitives short of 'or.w #$0700, sr' that you can use to do synchronization between application code and asynchronous code. I don't think that 'normal' applications should ever have to turn interrupts off, instead I think that the correct solution is to have a trap that defers the delivery of 'Deferred Tasks' untill the trap is called again to turn them on again. Since all the other above asynchronous operations can Q deferred tasks this is a lowest common denominator, and since the queueing of deferred tasks is relatively cheap it is also a relatively inexpensive solution. APPLE ARE YOU LISTENING? This brings up another issue I've never really pursued, I use the deferred task manager to process incoming DDP packets. (My DDP listener Q's a deffered task). IM V really only mentions DTs being delivered on the return from level 1 and 2 interrupts, it doesn't mention Appletalk ... however it does work - my question is: Does it work because Appletalk calls out queued deferred tasks on return from interrupts (to IPL 0) or do my tasks get called out after the next clock tick? I suspect the latter .... Paul -- Paul Campbell Taniwha Systems Design UUCP: ..!mtxinu!taniwha!paul Oakland CA AppleLink: D3213 Achtung! Ve are from ze Interface Police! Ve vant to look und feel!
earleh@eleazar.dartmouth.edu (Earle R. Horton) (06/10/89)
In article <7610@hoptoad.uucp> tim@hoptoad.UUCP (Tim Maroney) writes: >In article <13855@dartvax.Dartmouth.EDU> earleh@eleazar.dartmouth.edu >(Earle R. Horton) writes: [This is in reference to using location zero as a scratch area.] >>Aesthetically, however, it's a real bad >>idea. It produces the same problem that you get using ToolScratch, >>ApplScratch, or any other lowmem location--conflicts with other pieces >>of code. > >Unless, as I pointed out when I proposed it, you save the old state and >restore it before anyone else gets a chance to use it. If you save the >value, call Standard File, extract the value stashed by your filter >procs, and restore the old value, there's no way any code that would >use the scratch storage will be interfered with. Only system software, >interrupt driven code, and trap patches would have a chance to see it, >and it's clear that such software is not allowed to use the scratch >areas. "Scratch20, Scratch8, and ToolScratch will not be preserved across calls to the routines in the Macintosh ROM. ApplScratch will be preserved; it should be used only by application programs and not by desk accessories or other drivers." Phonebook: Assembly Language Programming Chapter Standard File makes a whole bunch of ROM calls. This means that the three scratch areas dedicated to tool use cannot be used. Saving and restoring the value at location zero (an interrupt vector) will not work across Standard File, because background tasks are allowed to run while Standard File is active, and lots of tasks will have a chance to see it. (I'm assuming MultiFinder here.) It's not nice to use ApplScratch, even though you think it extremely unlikely that the application will need it during the Standard File call. What if the call to Standard File causes the application's grow zone function to be called, and the grow zone function uses ApplScratch? Grow zone functions are just an example; my point is that it is possible for the code of the current application to get control in the midst of a call to Standard File. >Like storing the information in the refCon of the DA window, using >ApplScratch or ToolScratch with a state save/restore seems to have been >a useful and *easy* technique that was dismissed out of hand for some >unknown reason. It's stuff like this that makes me wonder why I put so >much work into this newsgroup. It's frustrating. ToolScratch is definitely out, given what IM says about its volatility. ApplScratch is out, too, because it is just barely possible for the application code to need or modify it during the call to Standard File. Murphy's Law equates "just barely possible" with "will happen," as I am sure you know already. There are aesthetic problems with the use of low memory globals for this sort of thing, too. Many people will just not use them if there is another method. Earle R. Horton "People forget how fast you did a job, but they remember how well you did it." Salada Tag Lines
lsr@Apple.COM (Larry Rosenstein) (06/10/89)
In article <1241@speedy.mcnc.org> kk@mcnc.org (Krzysztof Kozminski) writes: > BTW, an idea that I had at 3:15 am was to use the NULL location: > *((Handle*) 0L) = HStorage; > > Why not? All applications should avoid writing into NULL location, so Two reasons why not: (1) Some applications or DAs do write into location 0. Most do this by mistake, but some do it on purpose. I ran across one piece of code that passed NULL as one of the VAR parameters to a Dialog Manager code, which meant that the Dialog Manager would change location 0. (2) Some programs incorrectly dereference a NIL pointer. If location 0 happens to contain an invalid address, the program will crash. Larry Rosenstein, Apple Computer, Inc. Object Specialist Internet: lsr@Apple.com UUCP: {nsc, sun}!apple!lsr AppleLink: Rosenstein1
cep@apple.com (Christopher Pettus) (06/10/89)
In article <1241@speedy.mcnc.org> kk@mcnc.org (Krzysztof Kozminski) writes: > BTW, an idea that I had at 3:15 am was to use the NULL location: > *((Handle*) 0L) = HStorage; > > Why not? All applications should avoid writing into NULL location, so What happens when the _next_ piece of code comes along, assuming that all applications will avoid writing to zero? And, what happens when you can't write to location zero (as under A/UX, I believe)? -- Christopher Pettus | "Ganesha Said: 'Done! The very Network Systems Development | day I was born I made my first Apple Computer, Inc. | mistake, and by that path have cep@apple.com {nsc, sun}!apple!cep | I sought wisdom ever since.'" AppleLink: PETTUS.C | - The Mahabharata (408) 974-0004 | I: A Mine of Jewels and Gems
ech@cbnewsk.ATT.COM (ned.horvath) (06/13/89)
> In article <2024@husc6.harvard.edu> siegel@endor.UUCP (Rich Siegel) writes: > This is not self-modifying code, because the location that's modified >is never executed. It's actually storing data in code space; this particular >trick WILL fail once an OS comes out that has separate code and data spaces, >but it's reasonably far off. From article <13855@dartvax.Dartmouth.EDU>, by earleh@eleazar.dartmouth.edu (Earle R. Horton): > Aha! So one of you A4-relative types admits that the trick will > fail someday! This makes my day... > It's just not real nice to write computer software which has a > shorter lifetime than it could have, had you coded it differently. > Modifying code space to store variables or Handles to variables seems > to save a lot of work in writing code for desk accessories and other > code resources today, but is the work saved worth the inevitable > aggravation that users will experience if and when the OS makes that > technique invalid? Will you be around to make sure the software you > have written gets re-coded properly at that time, and will you be able > to make sure that users receive upgrades in a timely manner? Perhaps > not... Are you having fun, Earle? Smugness ill-becomes you, unless you have a solution to the problem...if you do, please share it. The "A4-relative" bit is a perfectly wonderful technique for a non-app to maintain access to its global variables. All I need now is someplace for A4 to point at -- that's easy, there are two heaps to do NewHandle in -- and some mechanism in the OS to preserve the value of A4 when I'm not executing. Apple provides no such mechanism. For APPLs, there's A5. For DRVRs, there's the Device control block, and the Handle to data storage. For everything else, there's nada. Not even owned resources for most things. What Aztec, and lately Think, have done is to store the handle to the globals in the only place that belongs to a CODE resource: in the resource itself. Someday Apple may want to separate data from code, so the latter can be write-protected. Presumably, at least 90 days prior to that day, Apple will give us the means to tell the OS just where one ends and the other begins. And if there's anybody sane in charge, along with that, will go some way for the code to find the data. Unless you can propose a mechanism that both works with the benevolent neglect the OS provides today, and is also going to work when the OS grows up. =Ned Horvath=
tim@hoptoad.uucp (Tim Maroney) (06/13/89)
In article <13870@dartvax.Dartmouth.EDU> earleh@eleazar.dartmouth.edu (Earle R. Horton) writes: > "Scratch20, Scratch8, and ToolScratch will not be preserved across > calls to the routines in the Macintosh ROM. ApplScratch will be > preserved; it should be used only by application programs and not > by desk accessories or other drivers." > Phonebook: Assembly Language Programming Chapter > > Standard File makes a whole bunch of ROM calls. This means that >the three scratch areas dedicated to tool use cannot be used. Thanks for the correction. (But are you really still using the phone book?) >Saving >and restoring the value at location zero (an interrupt vector) will >not work across Standard File, because background tasks are allowed to >run while Standard File is active, and lots of tasks will have a >chance to see it. (I'm assuming MultiFinder here.) I'm satisfied with saying that you can't use location zero because it's blecchy, but as someone else pointed out, what if other software also wants to use it? Anyway, I think it goes without saying that any location in the first page belongs to the OS and should be used only in explicitly sanctioned ways. (By the way, it's not an interrupt vector, exactly. It's the reset vector, but due to the way the Mac maps memory, it will never be consulted from RAM. I can't find a reference, but during reset, the ROM is mapped in at address 0.) > It's not nice to use ApplScratch, even though you think it >extremely unlikely that the application will need it during the >Standard File call. What if the call to Standard File causes the >application's grow zone function to be called, and the grow zone >function uses ApplScratch? True, but pretty obscure. I think I could live with this level of compatibility. Grow zone routines ought to use globals anyway; they are guaranteed to find the proper A5 in CurrentA5. >Grow zone functions are just an example; >my point is that it is possible for the code of the current >application to get control in the midst of a call to Standard File. Other than the grow zone routine, how? > ToolScratch is definitely out, given what IM says about its >volatility. Yes. >ApplScratch is out, too, because it is just barely >possible for the application code to need or modify it during the call >to Standard File. Murphy's Law equates "just barely possible" with >"will happen," as I am sure you know already. Murphy's Law is a joke. If everything bad that could happen did happen, no one would ever finish a hundred lines of code. I think a realistic assessment shows that the chances that the grow zone routine will need ApplScratch are so small that they can be neglected. I mean, if you want to get absolutely technical, Standard File can't even be called from a desk accessory, because DAs aren't allowed to allocate more than 3K of RAM. If you violate this, it's possible you will crash. But in real life, it's not a problem. >There are aesthetic >problems with the use of low memory globals for this sort of thing, >too. Many people will just not use them if there is another method. Oh sure, I'm not saying this is the best method by any means. The best method is still to use the refCon of the main DA window; the second best, to use the private storage field of the DCE in the unit table; the third, to write into code space. None of these involve low-memory globals, except for walking the unit table, a process described officially in one of the tech notes. >"People forget how fast you did a job, but they remember how well you >did it." Salada Tag Lines Not in my experience.... -- Tim Maroney, Mac Software Consultant, sun!hoptoad!tim, tim@toad.com Postal: 424 Tehama, SF CA 94103; Phone: (415) 495-2934 "Do what you wanna, do what you will; Just don't mess up your neighbor's thrill. And when you pay the bill, kindly leave a little tip To help the next poor sucker on his one-way trip." - Frank Zappa, "You Are What You Is"
kaufman@polya.Stanford.EDU (Marc T. Kaufman) (06/13/89)
From article <13855@dartvax.Dartmouth.EDU>, by earleh@eleazar.dartmouth.edu (Earle R. Horton): . Aha! So one of you A4-relative types admits that the trick will . fail someday! This makes my day... . It's just not real nice to write computer software which has a . shorter lifetime than it could have, had you coded it differently. . Modifying code space to store variables or Handles to variables seems . to save a lot of work in writing code for desk accessories and other . code resources today, but is the work saved worth the inevitable . aggravation that users will experience if and when the OS makes that . technique invalid? Will you be around to make sure the software you . have written gets re-coded properly at that time, and will you be able . to make sure that users receive upgrades in a timely manner? Perhaps . not... It is EXTREMELY unlikely that Apple will try to separate code and data spaces in the Mac OS. The 680x0 paging system is just not well suited to short, variable length segments. It seems likely (to me) that processes will be protected from one another... but we're unlikely to see protection within a process. Marc Kaufman (kaufman@polya.stanford.edu)
tim@hoptoad.uucp (Tim Maroney) (06/14/89)
In article <9983@polya.Stanford.EDU> kaufman@polya.Stanford.EDU (Marc T. Kaufman) writes: >It is EXTREMELY unlikely that Apple will try to separate code and data >spaces in the Mac OS. The 680x0 paging system is just not well suited to >short, variable length segments. It seems likely (to me) that processes will >be protected from one another... but we're unlikely to see protection within >a process. I think this is an oversimplification. It may turn out to be a correct guess, and certainly it is less important that applications be protected from overwriting their own code space than it is that they be protected from writing into system space or other applications. However, it is not neccessary to protect short, variable-length segments to protect code resources from writing. The Resource Manager can readily be hacked so that code resources of various types turn up in a separate, write-protected area, rather than in the main heap as they do at present. This entire code area would be protected against writing by application code; there would be no need to lock individual code segments. -- Tim Maroney, Mac Software Consultant, sun!hoptoad!tim, tim@toad.com Postal: 424 Tehama, SF CA 94103; Phone: (415) 495-2934 "Satanic is merely the name they give to the behavior of those who would disrupt the orderly way in which men want to live." -- Gabrielle, THE VAMPIRE LESTAT, Anne Rice
earleh@eleazar.dartmouth.edu (Earle R. Horton) (06/16/89)
In article <446@cbnewsk.ATT.COM> ech@cbnewsk.ATT.COM (ned.horvath) writes: >> In article <2024@husc6.harvard.edu> siegel@endor.UUCP (Rich Siegel) writes: >> This is not self-modifying code, because the location that's modified >>is never executed. It's actually storing data in code space; this particular >>trick WILL fail once an OS comes out that has separate code and data spaces, >>but it's reasonably far off. > >From article <13855@dartvax.Dartmouth.EDU>, by earleh@eleazar.dartmouth.edu (Earle R. Horton): >> Aha! So one of you A4-relative types admits that the trick will >> fail someday! This makes my day... ... >Are you having fun, Earle? Smugness ill-becomes you, unless you have >a solution to the problem...if you do, please share it. I have been accused of condemning the use of A4-based code resource globals, while providing no alternate solution of my own. This was not my intent. I merely hoped to point out that for any problem, there usually exist multiple solutions. In the case of code resources which are not provided with an external means of keeping global data around, the use of A4-relative data is only one solution. The technique, while seeming to provide a universal solution to the globals problem, has the serious drawback that it sometimes requires the programmer to write the A4 value into a part of her code space. For many code resources, such as desk accessories and cdevs, there already exist mechanisms for saving a Handle to data. My point is that where such a mechanism exists, it should be used in preference to writing to code space. For desk accessories, when it is necessary to reference A4-based globals from within a routine where the DA's A4 is invalid, it is preferable to use the driver's dCtlStorage Handle for this purpose, rather than using Think's SetupA4(). For some applications it may be possible, or even preferable, to forego globals entirely. Rewriting code to accomodate an OS change can be an expensive proposition. If you can find a way to avoid doing so, then you may save yourself or someone else a lot of trouble in the future. Although I propose no universal solution to this problem, I do suggest that anyone who is involved in writing code which writes to code space ("Class II self-modifying code") make sure that this is the only solution which is practical. If you detect a note of sarcasm in my characterization of "A4-relative bozos," then it is there. The reason is that from my experience with Aztec, I find that the A4-relative method is presented as a solution to the code resource globals problem, but that the potential problems which exist are not discussed in the documentation. I am not condemning the technique, because there appear to be cases where it is perfectly safe. It is the one percent or less where it is not that worries me. Code with a time bomb in it can blow up anytime. Earle R. Horton "People forget how fast you did a job, but they remember how well you did it." Salada Tag Lines