home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc / OpenDoc Development / Debugging Support / OpenDoc™ Source Code / Messaging / OSL / OSLRslv.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-28  |  11.1 KB  |  371 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        OSLRslv.c (Orignal name: OSLResolve.c)
  3.  
  4.     Contains:    
  5.  
  6.     Owned by:    Nick Pilch
  7.  
  8.     Copyright:    © 1992 - 1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <2>     1/15/96    TJ        Cleaned Up
  13.          <7>     8/29/95    jpa        DescPtr --> AEDesc* for Univ Hdrs 2.1.
  14.                                     [1279173]
  15.          <6>     7/27/95    eeh        1204615: iAEResolve passes 'exmn' not
  16.                                     'null'
  17.          <5>     6/27/95    NP        1262792: move stack pop routine into main
  18.                                     part of iAEResolve
  19.          <4>     6/23/95    NP        1195474: Make Resolve reentrant.
  20.          <3>     2/22/95    eeh        1222904: fix use of SetCurrentContext
  21.          <2>     8/19/94    NP        1181622: Ownership fix.
  22.         <11>      5/2/94    eeh        bug #1160654: various PPC native changes
  23.         <10>    12/17/93    eeh        fixed bug from port from Pascal
  24.          <9>    11/30/93    NP        Added error checking.
  25.          <8>    10/18/93    NP        Added OpenDoc GetErrDescProcPtr callback
  26.                                     support.
  27.          <7>    10/11/93    NP        Removed save and restore of context around
  28.                                     iAEResolve.
  29.          <6>     9/20/93    NP        Save and restore context around calls to
  30.                                     Resolve. Need this?
  31.          <5>     8/18/93    NP        Implemented for new context scheme.
  32.          <4>     8/16/93    NP        Adjusted for latest OSL proposal.
  33.          <3>     7/28/93    NP        Mods for new token type, OSLToken.
  34.          <2>     7/21/93    NP        Fixed #includes.
  35.          <1>     7/21/93    NP        first checked in
  36.  
  37.     To Do:
  38. */
  39.  
  40. #include <Desk.h>
  41. #include "OSLPriv.h"
  42.  
  43. #ifndef _CNTXTOSL_
  44. #include "CntxtOSL.h"
  45. #endif
  46.  
  47. #ifndef _OSLTOKEN_
  48. #include "OSLToken.h"
  49. #endif
  50.  
  51. #pragma segment AEObjSuppt
  52.  
  53. // SetErrDesc:
  54. // return true if have replaced a null desc with this guy, else false.
  55. // This so the  caller knows to (or not to) dispose of the failedDesc.
  56. // Also nil out the handle of the original so it won't be disposed.
  57. // NOTE: the setting of dataHandle needs to be done by the caller,
  58. // else the callerwill have to lock down any moveable structure the
  59. // descriptor might be located in lest it move while the pack is being
  60. // loaded for the callback to GetErrDescAddress.
  61.  
  62. Boolean SetErrDesc( AEDesc failedDesc )
  63. {
  64.     AEDesc* appDescPtr;
  65.     OSErr err = false ;
  66.  
  67. //        err := CallGetErrDesc( appDescPtr ) ;        }
  68.  
  69.     if ( NewCallGetErrDesc( &appDescPtr ) == noErr )
  70.         if ( (appDescPtr->descriptorType == typeNull) )
  71.             if ( appDescPtr->dataHandle == NULL )
  72.             {
  73.                 *appDescPtr = failedDesc ;
  74.                 return true ;
  75.             }
  76.  
  77.     return false ;
  78. } // SetErrDesc
  79.  
  80.  
  81.  
  82.  
  83. /*———————————————————————— InternalResolve ————————————————————————*/
  84.         /*This is the basic object resolution routine used internally from several locations.
  85.         it Handles two special cases for container objects, expands and resolves 'whose'
  86.         clauses on request, and calls object accessor procs as needed.*/
  87.  
  88. OSErr
  89. InternalResolve    (    Object         thisObj ,    
  90.                      DescType    exmnClass ,
  91.                     OSLToken    *dObjExamined ,
  92.                     Boolean        *contIsExmn ,
  93.                     OSLToken    *value ,
  94.                     Boolean        *redo)
  95.  
  96. {
  97.     OSLToken          dContainerToken ;
  98.     DescType          containerClass ;
  99.     AEDesc          dWhoseData ;
  100.     AEDesc          dTemp ;                /* used for whose coercion */
  101.     Whose          whoseToEval ;
  102.     
  103.     DescType         wantClass ;
  104.     Object         container ;
  105.     DescType         form ;
  106.     AEDesc         dSelectionData ;
  107.     OSErr          err ;
  108.     Boolean          callAccessorFirst ;
  109.     Boolean          containerIsDuplicate ;
  110.     OSLContext    curContext;
  111.     short        appDoesFlags;
  112.  
  113.     err = noErr;
  114.     *contIsExmn = false ;
  115.  
  116.     /* Now initialize some *iables that will save us multiple references */
  117. //    WITH thisObj** DO
  118.     {
  119.         ObjRecordPtr op = *thisObj ;
  120.         wantClass = op->objClass ;
  121.         container = op->objContainer ;
  122.         form =    op->u.objForm ;
  123.         dSelectionData = op->objSelectionData ;
  124.     }
  125.  
  126.     /* 1. check for recursion termination conditions */
  127.  
  128.     if ( wantClass == typeNull )            /* fixes LLD bug passing 'null', 0 obj spec to AEResolve. */
  129.     {
  130. /*                pAssert( container == NULL, 'NULL object with non-NULL container' ) ;        */
  131.         MakeNullToken( value ) ;
  132.         goto exit ;
  133.     }
  134.     else if ( wantClass == typeCurrentContainer )        /* 4/1: in case someone uses range grammar for other than optimizable stuff */
  135.     {
  136. /*                pAssert( container == NULL, 'CCNT object with non-NULL container' ) ;        */
  137.         value->descriptorType = typeCurrentContainer ;
  138.         value->dataHandle = NULL ;
  139.         goto exit ;
  140.     }
  141.     else if ( wantClass == typeToken )        /* 4/4 */
  142.     {
  143. /*                pAssert( container == NULL, 'token object with non-NULL container' ) ;        */
  144.         *value = (*thisObj)->objValue ;
  145.         *contIsExmn = true ;
  146.         goto exit ;
  147.     }
  148.     /* The following test should never pass except when InternalResolve has been called by
  149.       EvalObj; in any other case the exmn will be a container and so recursion won't happen, 
  150.         as per below. */
  151.     else if ( wantClass == typeObjectBeingExamined )        /* 4/5 */
  152.     {
  153. /*                pAssert( container == NULL, 'exmn object with non-NULL container' ) ;        */
  154.         *value = *dObjExamined ;
  155.     /*    MakeNull( dObjExamined ) ;            */
  156.         *contIsExmn = true ;
  157.         (*thisObj)->valIsExmn = true ;                        /* because it is a duplicate of another token, and we
  158.                                                                                                 don't want to call DisposeToken on BOTH of them */
  159.         goto exit ;
  160.     }
  161.  
  162.     dTemp.dataHandle = NULL ;
  163.     
  164.     SystemTask() ;                /* <eeh> added to give time to das, etc.  (Is this the right place?) */
  165.  
  166.     MakeNull( &dWhoseData ) ;
  167. //    OSLGetTokenContext(value, &curContext);
  168. //    OSLSetTokenContext(&dContainerToken, curContext);
  169.     MakeNullToken( &dContainerToken ) ;        /*make fromobj null token by default, unless
  170.                                             a real object specif (ier is found, or the 'object
  171.                                             being examined' special case is found*/
  172.  
  173. /*        pAssert( container !== NULL, 'Found a NULL container' ) ;        */
  174.  
  175.     containerClass = (*container)->objClass ;
  176.  
  177.     if ( containerClass == typeObjectBeingExamined )
  178.     {
  179.         containerIsDuplicate = true ;
  180.         containerClass = exmnClass ;
  181.     }
  182.     else if ( containerClass == typeToken )
  183.     {
  184.         containerIsDuplicate = true ;
  185.         containerClass = (*container)->u.tokenClass ;
  186.     }
  187.     else
  188.         containerIsDuplicate = false ;
  189.  
  190.     (*thisObj)->valIsExmn = false ;
  191.     FailErr( iAEDisposeToken( &(*thisObj)->objValue ),
  192.             err, errExit ) ;        /* get rid of value about to be replaced */
  193.  
  194.     /* Two major cases: contained in another object specif (ier OR 'object being examined' special case.
  195.       Ok to recurse on others, as stuff above will catch and terminate recursion. */
  196.  
  197.         if ( *redo )                            /* we have an unresolved obj, and must recurse */
  198.         {
  199.             HLock( (Handle)container ) ;
  200.             FailErr( InternalResolve(    container,
  201.                                         exmnClass ,
  202.                                         dObjExamined,
  203.                                         &containerIsDuplicate,
  204.                                         &dContainerToken,
  205.                                         &(*container)->objRedo ),
  206.                 err, errExit ) ;
  207.             HUnlock( (Handle)container ) ;
  208.         }
  209. /*            else
  210.             pAssert( false, 'We got a non-redo' )*/ ;
  211.  
  212.     /* We need to call the accessor function first (and possible do only that) if ( the form
  213.       is not any of our special cases (this means any new cases need to be ANDed into the
  214.       first line below) OR if ( it is one of the special cases and the matching bit is set
  215.       in the flags.  In all other cases we fall through to the next test, which calls
  216.       library code to deal with the special case. */
  217.  
  218.     // SHOULD FOLD IT INTO THE IF-ELSE
  219.     FailErr (GetCurrentContext(&curContext), err, errExit);
  220.     FailErr (GetAppDoesFlags(&curContext, &appDoesFlags), err, errExit);
  221.     if ( form != formWhose )
  222.         callAccessorFirst = true ;
  223.     // DO WE LOOK AT THE CONTAINER OR THE VALUE HERE?
  224.     else if ( (form == formWhose) && ((appDoesFlags & kAEAppDoesWhose)!=0) ) 
  225.         callAccessorFirst = true ;
  226.     else
  227.     {
  228.         callAccessorFirst = false ;
  229.         err = errAEEventNotHandled ;
  230.     }
  231.  
  232.     if ( callAccessorFirst )
  233.     {
  234.         if ( form == formWhose )
  235.         {
  236.             dTemp = dSelectionData ;
  237.         //    FailErr( AECoerceDesc( &dSelectionData, typeWhoseDescriptor, &dSelectionData ),
  238.         //        err, errExit ) ;
  239.         // <eeh> 7/93 direct call replaces the AEM call above
  240.  
  241.             FailErr( MakeExternalWhose( &dSelectionData, &dSelectionData ),
  242.                     err, errExit ) ;
  243.         }
  244.         err = iCallAccessor( wantClass, dContainerToken, containerClass,
  245.                 form, dSelectionData, value ) ;
  246.         if ( form == formWhose )
  247.         {
  248.             IgnoreOSErr( AEDisposeDesc( &dSelectionData ) ) ;                /* get rid of the special whose */
  249.             dSelectionData = dTemp ;
  250.             dTemp.dataHandle = NULL ;
  251.         }
  252.     }
  253.  
  254.     if ( err == errAEEventNotHandled )
  255.     {
  256.         if ( form == formWhose ) 
  257.         {
  258.             FailErr( CreateWhose( dSelectionData, &whoseToEval ),
  259.                     err, errExit ) ;
  260.             err = EvalWhose( whoseToEval, wantClass, containerClass,
  261.                     dContainerToken, appDoesFlags) ;
  262.             *value = (*whoseToEval)->whoseValue ;
  263.             DisposeWhose( whoseToEval ) ;
  264.         }
  265.     }
  266.     if ( err!= noErr ) goto errExit ;
  267.     
  268.     /* cleanup: dispose of container token, it is no longer needed:
  269.         don't confuse client with our descriptors, though.  Ie. if ( copied from another
  270.         token no need to dispose at all. */
  271.  
  272.     if ( !containerIsDuplicate )
  273.         FailErr( iAEDisposeToken( &dContainerToken ), err, errExit ) ;
  274.  
  275. exit:
  276.     return err ;
  277.  
  278. FAIL_ERR_PROC(err,errExit)
  279.     if ( (thisObj != NULL) && ( SetErrDesc( (*thisObj)->theObjInput )) )                /* 4/5. So doesn't dispose later */
  280.         (*thisObj)->theObjInput.dataHandle = NULL ;
  281.  
  282.     IgnoreOSErr( AEDisposeDesc( &dTemp ) );
  283.     IgnoreOSErr( AEDisposeDesc( &dWhoseData ) );
  284.     if ( !containerIsDuplicate )
  285.         IgnoreOSErr( iAEDisposeToken( &dContainerToken ) ) ;
  286. END_FAIL_ERR_PROC(err)
  287.  
  288. } /*InternalResolve*/
  289.  
  290.  
  291. /*———————————————————————— iAEResolve ————————————————————————*/
  292. pascal OSErr
  293. iAEResolve(    AEDesc dObjectSpecifier, OSLToken *dTheToken,
  294.             OSLContext* startingContext ) // if NULL, use a internal default context
  295.     /*
  296.         Application calls iAEResolve when some parameter is an object specif (ier.
  297.         iAEResolve parses the object specif (ier to a dTheToken making the proper callbacks. 
  298.     */
  299. {
  300.     Object         theObject = NULL;
  301. //    OSLToken     dNullObject;
  302.     OSLToken examinedObject;
  303.     Boolean     ignoredRedo;
  304.     AEDesc*      errDescPtr;
  305.     Boolean      ignoreBool;
  306.     OSErr        err;
  307.  
  308. //    err = SetCurrentContext(startingContext);
  309.     err = AddContextToTopOfStack(startingContext);
  310.     if (err)
  311.         return err;
  312.  
  313.     if ( NewCallGetErrDesc( &errDescPtr ) == noErr )                            /* 6/10; fixing LLD bug.  Need to ready for error report in case not an 'obj ' */
  314.         MakeNull( errDescPtr ) ;
  315.     else
  316.         errDescPtr = NULL ;
  317.  
  318.     switch( dObjectSpecifier.descriptorType )
  319.     {
  320.         case typeObjectSpecifier:
  321.             err = noErr;
  322.             theObject = NULL;
  323.         
  324.             ignoredRedo = true;            /* ignore because we will only eval this obj once */
  325. //            MakeNullToken( &dNullObject );
  326.             examinedObject.descriptorType = typeObjectBeingExamined;
  327.             examinedObject.dataHandle = NULL;
  328.         
  329.         /* make an object record from the object specif (ier.  Don't allow it to expand the whose
  330.             clause data at this stage. */
  331.         
  332.             FailErr( CreateObject( &dObjectSpecifier, NULL, false, &theObject ), err, errExit ) ;    
  333.         
  334.             MakeNullToken( dTheToken ) ;            /* we'll be testing if ( should dispose this value in InternalResolve */
  335.         
  336.             MoveHHi( (Handle) theObject ) ;        /* just in case this is gonna take a while */
  337.             HLock( (Handle) theObject );
  338.         
  339.             FailErr( InternalResolve(    theObject,
  340. //                                        typeNull ,
  341.                                         typeWildCard ,
  342. //                                        &dNullObject,
  343.                                         &examinedObject,
  344.                                         &ignoreBool,
  345.                                         dTheToken,
  346.                                         &ignoredRedo),
  347.                 err, errExit ) ;
  348.         
  349.             DisposeObj(theObject);
  350.             break ;
  351.  
  352.         case typeObjectBeingExamined :
  353.             FailErr( GetExmn( dTheToken ), err, errExit ) ;
  354.             break ;
  355.             
  356.         default :
  357.             err = errAENotAnObjSpec ;
  358.             if ( errDescPtr != NULL )
  359.                 IgnoreOSErr( AEDuplicateDesc( &dObjectSpecifier, errDescPtr ) ) ;        /* nothing we can do about error, anyway */
  360.     }
  361.  
  362.     RemoveTopOfContextStack();
  363.  
  364. FAIL_ERR_PROC(err,errExit)
  365.     DisposeObj( theObject ) ;
  366.     RemoveTopOfContextStack();
  367. END_FAIL_ERR_PROC(err)
  368.  
  369. } /* iAEResolve */
  370.  
  371.