home *** CD-ROM | disk | FTP | other *** search
- /*
- File: OSLRslv.c (Orignal name: OSLResolve.c)
-
- Contains:
-
- Owned by: Nick Pilch
-
- Copyright: © 1992 - 1996 by Apple Computer, Inc., all rights reserved.
-
- Change History (most recent first):
-
- <2> 1/15/96 TJ Cleaned Up
- <7> 8/29/95 jpa DescPtr --> AEDesc* for Univ Hdrs 2.1.
- [1279173]
- <6> 7/27/95 eeh 1204615: iAEResolve passes 'exmn' not
- 'null'
- <5> 6/27/95 NP 1262792: move stack pop routine into main
- part of iAEResolve
- <4> 6/23/95 NP 1195474: Make Resolve reentrant.
- <3> 2/22/95 eeh 1222904: fix use of SetCurrentContext
- <2> 8/19/94 NP 1181622: Ownership fix.
- <11> 5/2/94 eeh bug #1160654: various PPC native changes
- <10> 12/17/93 eeh fixed bug from port from Pascal
- <9> 11/30/93 NP Added error checking.
- <8> 10/18/93 NP Added OpenDoc GetErrDescProcPtr callback
- support.
- <7> 10/11/93 NP Removed save and restore of context around
- iAEResolve.
- <6> 9/20/93 NP Save and restore context around calls to
- Resolve. Need this?
- <5> 8/18/93 NP Implemented for new context scheme.
- <4> 8/16/93 NP Adjusted for latest OSL proposal.
- <3> 7/28/93 NP Mods for new token type, OSLToken.
- <2> 7/21/93 NP Fixed #includes.
- <1> 7/21/93 NP first checked in
-
- To Do:
- */
-
- #include <Desk.h>
- #include "OSLPriv.h"
-
- #ifndef _CNTXTOSL_
- #include "CntxtOSL.h"
- #endif
-
- #ifndef _OSLTOKEN_
- #include "OSLToken.h"
- #endif
-
- #pragma segment AEObjSuppt
-
- // SetErrDesc:
- // return true if have replaced a null desc with this guy, else false.
- // This so the caller knows to (or not to) dispose of the failedDesc.
- // Also nil out the handle of the original so it won't be disposed.
- // NOTE: the setting of dataHandle needs to be done by the caller,
- // else the callerwill have to lock down any moveable structure the
- // descriptor might be located in lest it move while the pack is being
- // loaded for the callback to GetErrDescAddress.
-
- Boolean SetErrDesc( AEDesc failedDesc )
- {
- AEDesc* appDescPtr;
- OSErr err = false ;
-
- // err := CallGetErrDesc( appDescPtr ) ; }
-
- if ( NewCallGetErrDesc( &appDescPtr ) == noErr )
- if ( (appDescPtr->descriptorType == typeNull) )
- if ( appDescPtr->dataHandle == NULL )
- {
- *appDescPtr = failedDesc ;
- return true ;
- }
-
- return false ;
- } // SetErrDesc
-
-
-
-
- /*———————————————————————— InternalResolve ————————————————————————*/
- /*This is the basic object resolution routine used internally from several locations.
- it Handles two special cases for container objects, expands and resolves 'whose'
- clauses on request, and calls object accessor procs as needed.*/
-
- OSErr
- InternalResolve ( Object thisObj ,
- DescType exmnClass ,
- OSLToken *dObjExamined ,
- Boolean *contIsExmn ,
- OSLToken *value ,
- Boolean *redo)
-
- {
- OSLToken dContainerToken ;
- DescType containerClass ;
- AEDesc dWhoseData ;
- AEDesc dTemp ; /* used for whose coercion */
- Whose whoseToEval ;
-
- DescType wantClass ;
- Object container ;
- DescType form ;
- AEDesc dSelectionData ;
- OSErr err ;
- Boolean callAccessorFirst ;
- Boolean containerIsDuplicate ;
- OSLContext curContext;
- short appDoesFlags;
-
- err = noErr;
- *contIsExmn = false ;
-
- /* Now initialize some *iables that will save us multiple references */
- // WITH thisObj** DO
- {
- ObjRecordPtr op = *thisObj ;
- wantClass = op->objClass ;
- container = op->objContainer ;
- form = op->u.objForm ;
- dSelectionData = op->objSelectionData ;
- }
-
- /* 1. check for recursion termination conditions */
-
- if ( wantClass == typeNull ) /* fixes LLD bug passing 'null', 0 obj spec to AEResolve. */
- {
- /* pAssert( container == NULL, 'NULL object with non-NULL container' ) ; */
- MakeNullToken( value ) ;
- goto exit ;
- }
- else if ( wantClass == typeCurrentContainer ) /* 4/1: in case someone uses range grammar for other than optimizable stuff */
- {
- /* pAssert( container == NULL, 'CCNT object with non-NULL container' ) ; */
- value->descriptorType = typeCurrentContainer ;
- value->dataHandle = NULL ;
- goto exit ;
- }
- else if ( wantClass == typeToken ) /* 4/4 */
- {
- /* pAssert( container == NULL, 'token object with non-NULL container' ) ; */
- *value = (*thisObj)->objValue ;
- *contIsExmn = true ;
- goto exit ;
- }
- /* The following test should never pass except when InternalResolve has been called by
- EvalObj; in any other case the exmn will be a container and so recursion won't happen,
- as per below. */
- else if ( wantClass == typeObjectBeingExamined ) /* 4/5 */
- {
- /* pAssert( container == NULL, 'exmn object with non-NULL container' ) ; */
- *value = *dObjExamined ;
- /* MakeNull( dObjExamined ) ; */
- *contIsExmn = true ;
- (*thisObj)->valIsExmn = true ; /* because it is a duplicate of another token, and we
- don't want to call DisposeToken on BOTH of them */
- goto exit ;
- }
-
- dTemp.dataHandle = NULL ;
-
- SystemTask() ; /* <eeh> added to give time to das, etc. (Is this the right place?) */
-
- MakeNull( &dWhoseData ) ;
- // OSLGetTokenContext(value, &curContext);
- // OSLSetTokenContext(&dContainerToken, curContext);
- MakeNullToken( &dContainerToken ) ; /*make fromobj null token by default, unless
- a real object specif (ier is found, or the 'object
- being examined' special case is found*/
-
- /* pAssert( container !== NULL, 'Found a NULL container' ) ; */
-
- containerClass = (*container)->objClass ;
-
- if ( containerClass == typeObjectBeingExamined )
- {
- containerIsDuplicate = true ;
- containerClass = exmnClass ;
- }
- else if ( containerClass == typeToken )
- {
- containerIsDuplicate = true ;
- containerClass = (*container)->u.tokenClass ;
- }
- else
- containerIsDuplicate = false ;
-
- (*thisObj)->valIsExmn = false ;
- FailErr( iAEDisposeToken( &(*thisObj)->objValue ),
- err, errExit ) ; /* get rid of value about to be replaced */
-
- /* Two major cases: contained in another object specif (ier OR 'object being examined' special case.
- Ok to recurse on others, as stuff above will catch and terminate recursion. */
-
- if ( *redo ) /* we have an unresolved obj, and must recurse */
- {
- HLock( (Handle)container ) ;
- FailErr( InternalResolve( container,
- exmnClass ,
- dObjExamined,
- &containerIsDuplicate,
- &dContainerToken,
- &(*container)->objRedo ),
- err, errExit ) ;
- HUnlock( (Handle)container ) ;
- }
- /* else
- pAssert( false, 'We got a non-redo' )*/ ;
-
- /* We need to call the accessor function first (and possible do only that) if ( the form
- is not any of our special cases (this means any new cases need to be ANDed into the
- first line below) OR if ( it is one of the special cases and the matching bit is set
- in the flags. In all other cases we fall through to the next test, which calls
- library code to deal with the special case. */
-
- // SHOULD FOLD IT INTO THE IF-ELSE
- FailErr (GetCurrentContext(&curContext), err, errExit);
- FailErr (GetAppDoesFlags(&curContext, &appDoesFlags), err, errExit);
- if ( form != formWhose )
- callAccessorFirst = true ;
- // DO WE LOOK AT THE CONTAINER OR THE VALUE HERE?
- else if ( (form == formWhose) && ((appDoesFlags & kAEAppDoesWhose)!=0) )
- callAccessorFirst = true ;
- else
- {
- callAccessorFirst = false ;
- err = errAEEventNotHandled ;
- }
-
- if ( callAccessorFirst )
- {
- if ( form == formWhose )
- {
- dTemp = dSelectionData ;
- // FailErr( AECoerceDesc( &dSelectionData, typeWhoseDescriptor, &dSelectionData ),
- // err, errExit ) ;
- // <eeh> 7/93 direct call replaces the AEM call above
-
- FailErr( MakeExternalWhose( &dSelectionData, &dSelectionData ),
- err, errExit ) ;
- }
- err = iCallAccessor( wantClass, dContainerToken, containerClass,
- form, dSelectionData, value ) ;
- if ( form == formWhose )
- {
- IgnoreOSErr( AEDisposeDesc( &dSelectionData ) ) ; /* get rid of the special whose */
- dSelectionData = dTemp ;
- dTemp.dataHandle = NULL ;
- }
- }
-
- if ( err == errAEEventNotHandled )
- {
- if ( form == formWhose )
- {
- FailErr( CreateWhose( dSelectionData, &whoseToEval ),
- err, errExit ) ;
- err = EvalWhose( whoseToEval, wantClass, containerClass,
- dContainerToken, appDoesFlags) ;
- *value = (*whoseToEval)->whoseValue ;
- DisposeWhose( whoseToEval ) ;
- }
- }
- if ( err!= noErr ) goto errExit ;
-
- /* cleanup: dispose of container token, it is no longer needed:
- don't confuse client with our descriptors, though. Ie. if ( copied from another
- token no need to dispose at all. */
-
- if ( !containerIsDuplicate )
- FailErr( iAEDisposeToken( &dContainerToken ), err, errExit ) ;
-
- exit:
- return err ;
-
- FAIL_ERR_PROC(err,errExit)
- if ( (thisObj != NULL) && ( SetErrDesc( (*thisObj)->theObjInput )) ) /* 4/5. So doesn't dispose later */
- (*thisObj)->theObjInput.dataHandle = NULL ;
-
- IgnoreOSErr( AEDisposeDesc( &dTemp ) );
- IgnoreOSErr( AEDisposeDesc( &dWhoseData ) );
- if ( !containerIsDuplicate )
- IgnoreOSErr( iAEDisposeToken( &dContainerToken ) ) ;
- END_FAIL_ERR_PROC(err)
-
- } /*InternalResolve*/
-
-
- /*———————————————————————— iAEResolve ————————————————————————*/
- pascal OSErr
- iAEResolve( AEDesc dObjectSpecifier, OSLToken *dTheToken,
- OSLContext* startingContext ) // if NULL, use a internal default context
- /*
- Application calls iAEResolve when some parameter is an object specif (ier.
- iAEResolve parses the object specif (ier to a dTheToken making the proper callbacks.
- */
- {
- Object theObject = NULL;
- // OSLToken dNullObject;
- OSLToken examinedObject;
- Boolean ignoredRedo;
- AEDesc* errDescPtr;
- Boolean ignoreBool;
- OSErr err;
-
- // err = SetCurrentContext(startingContext);
- err = AddContextToTopOfStack(startingContext);
- if (err)
- return err;
-
- if ( NewCallGetErrDesc( &errDescPtr ) == noErr ) /* 6/10; fixing LLD bug. Need to ready for error report in case not an 'obj ' */
- MakeNull( errDescPtr ) ;
- else
- errDescPtr = NULL ;
-
- switch( dObjectSpecifier.descriptorType )
- {
- case typeObjectSpecifier:
- err = noErr;
- theObject = NULL;
-
- ignoredRedo = true; /* ignore because we will only eval this obj once */
- // MakeNullToken( &dNullObject );
- examinedObject.descriptorType = typeObjectBeingExamined;
- examinedObject.dataHandle = NULL;
-
- /* make an object record from the object specif (ier. Don't allow it to expand the whose
- clause data at this stage. */
-
- FailErr( CreateObject( &dObjectSpecifier, NULL, false, &theObject ), err, errExit ) ;
-
- MakeNullToken( dTheToken ) ; /* we'll be testing if ( should dispose this value in InternalResolve */
-
- MoveHHi( (Handle) theObject ) ; /* just in case this is gonna take a while */
- HLock( (Handle) theObject );
-
- FailErr( InternalResolve( theObject,
- // typeNull ,
- typeWildCard ,
- // &dNullObject,
- &examinedObject,
- &ignoreBool,
- dTheToken,
- &ignoredRedo),
- err, errExit ) ;
-
- DisposeObj(theObject);
- break ;
-
- case typeObjectBeingExamined :
- FailErr( GetExmn( dTheToken ), err, errExit ) ;
- break ;
-
- default :
- err = errAENotAnObjSpec ;
- if ( errDescPtr != NULL )
- IgnoreOSErr( AEDuplicateDesc( &dObjectSpecifier, errDescPtr ) ) ; /* nothing we can do about error, anyway */
- }
-
- RemoveTopOfContextStack();
-
- FAIL_ERR_PROC(err,errExit)
- DisposeObj( theObject ) ;
- RemoveTopOfContextStack();
- END_FAIL_ERR_PROC(err)
-
- } /* iAEResolve */
-
-