home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / DCLAP 6d / dclap6d / network / apple / DNR.c_copy < prev    next >
Encoding:
Text File  |  1996-07-05  |  14.7 KB  |  540 lines  |  [TEXT/R*ch]

  1. /*
  2.     DNR.c - DNR library for MPW
  3.  
  4.     © Copyright 1988 by Apple Computer.  All rights reserved
  5.     
  6. */
  7.  
  8. #define MPW3.0
  9.  
  10. #include <OSUtils.h>
  11. #include <Errors.h>
  12. #include <Files.h>
  13. #include <Resources.h>
  14. #include <Memory.h>
  15. #include <Traps.h>
  16. #include <GestaltEqu.h>
  17. #include <Folders.h>
  18. #include <MixedMode.h>                                        
  19.  
  20.  
  21.  
  22.  
  23. #define OPENRESOLVER    1
  24. #define CLOSERESOLVER    2
  25. #define STRTOADDR        3
  26. #define    ADDRTOSTR        4
  27. #define    ENUMCACHE        5
  28. #define ADDRTONAME        6
  29. #define    HINFO            7
  30. #define MXINFO            8
  31.  
  32. Handle                 codeHndl = nil;
  33. UniversalProcPtr    dnr = nil;
  34.  
  35.  
  36. TrapType GetTrapType(theTrap)
  37. unsigned long theTrap;
  38. {
  39.     if (BitAnd(theTrap, 0x0800) > 0)
  40.         return(ToolTrap);
  41.     else
  42.         return(OSTrap);
  43.     }
  44.     
  45. Boolean TrapAvailable(trap)
  46. unsigned long trap;
  47. {
  48. TrapType trapType = ToolTrap;
  49. unsigned long numToolBoxTraps;
  50.  
  51.     if (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap))
  52.         numToolBoxTraps = 0x200;
  53.     else
  54.         numToolBoxTraps = 0x400;
  55.  
  56.     trapType = GetTrapType(trap);
  57.     if (trapType == ToolTrap) {
  58.         trap = BitAnd(trap, 0x07FF);
  59.         if (trap >= numToolBoxTraps)
  60.             trap = _Unimplemented;
  61.         }
  62.     return(NGetTrapAddress(trap, trapType) != NGetTrapAddress(_Unimplemented, ToolTrap));
  63.  
  64. }
  65.  
  66. void GetSystemFolder(short *vRefNumP, long *dirIDP)
  67. {
  68.     SysEnvRec info;
  69.     long wdProcID;
  70.     
  71.     SysEnvirons(1, &info);
  72.     if (GetWDInfo(info.sysVRefNum, vRefNumP, dirIDP, &wdProcID) != noErr) {
  73.         *vRefNumP = 0;
  74.         *dirIDP = 0;
  75.         }
  76.     }
  77.  
  78. void GetCPanelFolder(short *vRefNumP, long *dirIDP)
  79. {
  80.     Boolean hasFolderMgr = false;
  81.     long feature;
  82.     
  83.     if (Gestalt(gestaltFindFolderAttr, &feature) == noErr) 
  84.         hasFolderMgr = true;
  85.     if (!hasFolderMgr) {
  86.         GetSystemFolder(vRefNumP, dirIDP);
  87.         return;
  88.         }
  89.     else {
  90.         if (FindFolder(kOnSystemDisk, kControlPanelFolderType, kDontCreateFolder, vRefNumP, dirIDP) != noErr) {
  91.             *vRefNumP = 0;
  92.             *dirIDP = 0;
  93.             }
  94.         }
  95.     }
  96.     
  97. /* SearchFolderForDNRP is called to search a folder for files that might 
  98.     contain the 'dnrp' resource */
  99. short SearchFolderForDNRP(long targetType, long targetCreator, short vRefNum, long dirID)
  100. {
  101.     HParamBlockRec fi;
  102.     Str255 filename;
  103.     short refnum;
  104.     
  105.     fi.fileParam.ioCompletion = nil;
  106.     fi.fileParam.ioNamePtr = filename;
  107.     fi.fileParam.ioVRefNum = vRefNum;
  108.     fi.fileParam.ioDirID = dirID;
  109.     fi.fileParam.ioFDirIndex = 1;
  110.     
  111.     while (PBHGetFInfo(&fi, false) == noErr) {
  112.         /* scan system folder for driver resource files of specific type & creator */
  113.         if (fi.fileParam.ioFlFndrInfo.fdType == targetType &&
  114.             fi.fileParam.ioFlFndrInfo.fdCreator == targetCreator) {
  115.             /* found the MacTCP driver file? */
  116.             refnum = HOpenResFile(vRefNum, dirID, filename, fsRdPerm);
  117.             if (GetIndResource('dnrp', 1) == NULL)
  118.                 CloseResFile(refnum);
  119.             else
  120.                 return refnum;
  121.             }
  122.         /* check next file in system folder */
  123.         fi.fileParam.ioFDirIndex++;
  124.         fi.fileParam.ioDirID = dirID;    /* PBHGetFInfo() clobbers ioDirID */
  125.         }
  126.     return(-1);
  127.     }    
  128.  
  129.  
  130.  
  131. /* OpenOurRF is called to open the MacTCP driver resources */
  132.  
  133. short OpenOurRF()
  134. {
  135.     short refnum;
  136.     short vRefNum;
  137.     long dirID;
  138.     
  139.     /* first search Control Panels for MacTCP 1.1 */
  140.     GetCPanelFolder(&vRefNum, &dirID);
  141.     refnum = SearchFolderForDNRP('cdev', 'ztcp', vRefNum, dirID);
  142.     if (refnum != -1) return(refnum);
  143.         
  144.     /* next search System Folder for MacTCP 1.0.x */
  145.     GetSystemFolder(&vRefNum, &dirID);
  146.     refnum = SearchFolderForDNRP('cdev', 'mtcp', vRefNum, dirID);
  147.     if (refnum != -1) return(refnum);
  148.         
  149.     /* finally, search Control Panels for MacTCP 1.0.x */
  150.     GetCPanelFolder(&vRefNum, &dirID);
  151.     refnum = SearchFolderForDNRP('cdev', 'mtcp', vRefNum, dirID);
  152.     if (refnum != -1) return(refnum);
  153.         
  154.     return -1;
  155.     }    
  156.  
  157.  
  158.  
  159.  
  160. typedef OSErr (*OpenResolverProcPtr)(short selector, char* fileName);
  161.  
  162. enum {
  163.     uppOpenResolverProcInfo = kCStackBased
  164.          | RESULT_SIZE(SIZE_CODE(sizeof(short)))
  165.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short)))
  166.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(char *)))
  167. };
  168.  
  169. #if USESROUTINEDESCRIPTORS
  170. typedef UniversalProcPtr OpenResolverUPP;
  171.  
  172. #define    NewOpenResolverProc(userRoutine)                        \
  173.         (OpenResolverUPP) NewRoutineDescriptor(userRoutine, uppOpenResolverProcInfo, GetCurrentISA())
  174. #define    CallOpenResolverProc(userRoutine, selector, filename)    \
  175.         CallUniversalProc(userRoutine, uppOpenResolverProcInfo, selector, filename)
  176. #else
  177. typedef OpenResolverProcPtr OpenResolverUPP;
  178.  
  179. #define    NewOpenResolverProc(userRoutine)                    \
  180.         (OpenResolverUPP)(userRoutine)
  181. #define    CallOpenResolverProc(userRoutine, selector, filename)    \
  182.         (*userRoutine)(selector, filename)
  183. #endif
  184.  
  185.  
  186.  
  187. OSErr OpenResolver(fileName)
  188. char *fileName;
  189. {
  190.     short             refnum;
  191.     OSErr             rc;
  192.     
  193.     if (dnr != nil)
  194.         /* resolver already loaded in */
  195.         return(noErr);
  196.         
  197.     /* open the MacTCP driver to get DNR resources. Search for it based on
  198.        creator & type rather than simply file name */    
  199.     refnum = OpenOurRF();
  200.  
  201.     /* ignore failures since the resource may have been installed in the 
  202.        System file if running on a Mac 512Ke */
  203.        
  204.     /* load in the DNR resource package */
  205.     codeHndl = GetIndResource('dnrp', 1);
  206.     if (codeHndl == nil) {
  207.         /* can't open DNR */
  208.         return(ResError());
  209.     }
  210.     
  211.     DetachResource(codeHndl);
  212.     if (refnum != -1) {
  213.         CloseWD(refnum);
  214.         CloseResFile(refnum);
  215.     }
  216.         
  217.     /* lock the DNR resource since it cannot be reloated while opened */
  218.     HLock(codeHndl);
  219.     dnr = (UniversalProcPtr) *codeHndl;
  220.     
  221.     /* call open resolver */
  222.     rc = CallOpenResolverProc(dnr, OPENRESOLVER, fileName);
  223.     if (rc != noErr) {
  224.         /* problem with open resolver, flush it */
  225.         HUnlock(codeHndl);
  226.         DisposHandle(codeHndl);
  227.         dnr = nil;
  228.     }
  229.     return(rc);
  230. }
  231.  
  232.  
  233.  
  234. typedef OSErr (*CloseResolverProcPtr)(short selector);
  235.  
  236. enum {
  237.     uppCloseResolverProcInfo = kCStackBased
  238.          | RESULT_SIZE(SIZE_CODE(sizeof(short)))
  239.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short)))
  240. };
  241.  
  242. #if USESROUTINEDESCRIPTORS
  243. typedef UniversalProcPtr CloseResolverUPP;
  244.  
  245. #define    NewCloseResolverProc(userRoutine)                        \
  246.         (CloseResolverUPP) NewRoutineDescriptor(userRoutine, uppCloseResolverProcInfo, GetCurrentISA())
  247. #define    CallCloseResolverProc(userRoutine, selector)    \
  248.         CallUniversalProc(userRoutine, uppCloseResolverProcInfo, selector)
  249. #else
  250. typedef CloseResolverProcPtr CloseResolverUPP;
  251.  
  252. #define    NewCloseResolverProc(userRoutine)                         \
  253.         (CloseResolverUPP)(userRoutine)
  254. #define    CallCloseResolverProc(userRoutine, selector)    \
  255.         (*userRoutine)(selector)
  256. #endif
  257.  
  258.  
  259.  
  260. OSErr CloseResolver()
  261. {
  262.     if (dnr == nil)
  263.         /* resolver not loaded error */
  264.         return(notOpenErr);
  265.         
  266.     /* call close resolver */
  267.     CallCloseResolverProc(dnr, CLOSERESOLVER);
  268.  
  269.     /* release the DNR resource package */
  270.     HUnlock(codeHndl);
  271.     DisposHandle(codeHndl);
  272.     dnr = nil;
  273.     return(noErr);
  274. }
  275.  
  276.  
  277.  
  278.  
  279. typedef OSErr (*StrToAddrProcPtr)(short selector, char* hostName, struct hostInfo* rtnStruct,
  280.                                     long resultProc, char* userData);
  281.                                     
  282. enum {
  283.     uppStrToAddrProcInfo = kCStackBased
  284.          | RESULT_SIZE(SIZE_CODE(sizeof(short)))
  285.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short)))
  286.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(char *)))
  287.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(struct hostInfo *)))
  288.          | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(long)))
  289.          | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(char *)))
  290. };
  291.  
  292. #if USESROUTINEDESCRIPTORS
  293. typedef UniversalProcPtr StrToAddrUPP;
  294.  
  295. #define    NewStrToAddrProc(userRoutine)                        \
  296.         (StrToAddrUPP) NewRoutineDescriptor(userRoutine, uppStrToAddrProcInfo, GetCurrentISA())
  297. #define    CallStrToAddrProc(userRoutine, selector, hostName, rtnStruct, resultProc, userData)    \
  298.         CallUniversalProc(userRoutine, uppStrToAddrProcInfo, selector, hostName, rtnStruct, resultProc, userData)
  299. #else
  300. typedef StrToAddrProcPtr StrToAddrUPP;
  301.  
  302. #define    NewStrToAddrProc(userRoutine)                        \
  303.         (StrToAddrUPP)(userRoutine)
  304. #define    CallStrToAddrProc(userRoutine, selector, hostName, rtnStruct, resultProc, userData)    \
  305.         (*userRoutine)(selector, hostName, rtnStruct, resultProc, userData)
  306. #endif
  307.  
  308.  
  309.  
  310. OSErr StrToAddr(hostName, rtnStruct, resultproc, userDataPtr)
  311. char *hostName;
  312. struct hostInfo *rtnStruct;
  313. long resultproc;
  314. char *userDataPtr;
  315. {
  316.     if (dnr == nil)
  317.         /* resolver not loaded error */
  318.         return(notOpenErr);
  319.         
  320.     return(CallStrToAddrProc(dnr, STRTOADDR, hostName, rtnStruct, resultproc, userDataPtr));
  321. }
  322.  
  323.  
  324. typedef OSErr (*AddrToStrProcPtr)(short selector, long address, char* hostName);
  325.  
  326. enum {
  327.     uppAddrToStrProcInfo = kCStackBased
  328.          | RESULT_SIZE(SIZE_CODE(sizeof(short)))
  329.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short)))
  330.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(unsigned long)))
  331.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(char *)))
  332. };
  333.  
  334. #if USESROUTINEDESCRIPTORS
  335. typedef UniversalProcPtr AddrToStrUPP;
  336.  
  337. #define    NewAddrToStrProc(userRoutine)                        \
  338.         (AddrToStrUPP) NewRoutineDescriptor(userRoutine, uppAddrToStrProcInfo, GetCurrentISA())
  339. #define    CallAddrToStrProc(userRoutine, selector, address, hostName)    \
  340.         CallUniversalProc(userRoutine, uppAddrToStrProcInfo, selector, address, hostName)
  341. #else
  342. typedef AddrToStrProcPtr AddrToStrUPP;
  343.  
  344. #define    NewAddrToStrProc(userRoutine)                        \
  345.         (AddrToStrUPP)(userRoutine)
  346. #define    CallAddrToStrProc(userRoutine, selector, address, hostName)    \
  347.         (*userRoutine)(selector, address, hostName)
  348. #endif
  349.  
  350.     
  351. OSErr AddrToStr(addr, addrStr)
  352. unsigned long addr;
  353. char *addrStr;                                    
  354. {
  355.     if (dnr == nil)
  356.         /* resolver not loaded error */
  357.         return(notOpenErr);
  358.         
  359.     CallAddrToStrProc(dnr, ADDRTOSTR, addr, addrStr);
  360.  
  361.     return(noErr);
  362. }
  363.  
  364.  
  365.  
  366. typedef OSErr (*EnumCacheProcPtr)(short selector, long result, char* userData);
  367.  
  368. enum {
  369.     uppEnumCacheProcInfo = kCStackBased
  370.          | RESULT_SIZE(SIZE_CODE(sizeof(short)))
  371.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short)))
  372.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(long)))
  373.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(char *)))
  374. };
  375.  
  376. #if USESROUTINEDESCRIPTORS
  377. typedef UniversalProcPtr EnumCacheUPP;
  378.  
  379. #define    NewEnumCacheProc(userRoutine)                        \
  380.         (EnumCacheUPP) NewRoutineDescriptor(userRoutine, uppEnumCacheProcInfo, GetCurrentISA())
  381. #define    CallEnumCacheProc(userRoutine, selector, result, userData)    \
  382.         CallUniversalProc(userRoutine, uppEnumCacheProcInfo, selector, result, userData)
  383. #else
  384. typedef EnumCacheProcPtr EnumCacheUPP;
  385.  
  386. #define    NewEnumCacheProc(userRoutine)                        \
  387.         (EnumCacheUPP)(userRoutine)
  388. #define    CallEnumCacheProc(userRoutine, selector, result, userData)    \
  389.         (*userRoutine)(selector, result, userData)
  390. #endif
  391.  
  392.  
  393.     
  394. OSErr EnumCache(resultproc, userDataPtr)
  395. long resultproc;
  396. char *userDataPtr;
  397. {
  398.     if (dnr == nil)
  399.         /* resolver not loaded error */
  400.         return(notOpenErr);
  401.         
  402.     return(CallEnumCacheProc(dnr, ENUMCACHE, resultproc, userDataPtr));
  403. }
  404.  
  405.  
  406.  
  407. typedef OSErr (*AddrToNameProcPtr)(short selector, unsigned long addr, struct hostInfo* rtnStruct,
  408.                                     long resultProc, char* userData);
  409.  
  410. enum {
  411.     uppAddrToNameProcInfo = kCStackBased
  412.          | RESULT_SIZE(SIZE_CODE(sizeof(short)))
  413.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short)))
  414.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(unsigned long)))
  415.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(struct hostInfo *)))
  416.          | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(long)))
  417.          | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(char *)))
  418.  
  419. };
  420.  
  421. #if USESROUTINEDESCRIPTORS
  422. typedef UniversalProcPtr AddrToNameUPP;
  423.  
  424. #define    NewAddrToNameProc(userRoutine)                        \
  425.         (AddrToNameUPP) NewRoutineDescriptor(userRoutine, uppAddrToNameProcInfo, GetCurrentISA())
  426. #define    CallAddrToNameProc(userRoutine, selector, addr, rtnStruct, resultProc, userData)    \
  427.         CallUniversalProc(userRoutine, uppAddrToNameProcInfo, selector, addr, rtnStruct, resultProc, userData)
  428. #else
  429. typedef AddrToNameProcPtr AddrToNameUPP;
  430.  
  431. #define    NewAddrToNameProc(userRoutine)                        \
  432.         (AddrToNameUPP)(userRoutine)
  433. #define    CallAddrToNameProc(userRoutine, selector, addr, rtnStruct, resultProc, userData)    \
  434.         (*userRoutine)(selector, addr, rtnStruct, resultProc, userData)
  435. #endif
  436.  
  437.     
  438.     
  439. OSErr AddrToName(addr, rtnStruct, resultproc, userDataPtr)
  440. unsigned long addr;
  441. struct hostInfo *rtnStruct;
  442. long resultproc;
  443. char *userDataPtr;                                    
  444. {
  445.     if (dnr == nil)
  446.         /* resolver not loaded error */
  447.         return(notOpenErr);
  448.         
  449.     return(CallAddrToNameProc(dnr, ADDRTONAME, addr, rtnStruct, resultproc, userDataPtr));
  450. }
  451.  
  452.  
  453. typedef OSErr (*HInfoProcPtr)(short selector, char* hostName, struct returnRec* returnRecPtr,
  454.                                 long resultProc, char* userData);
  455.  
  456. enum {
  457.     uppHInfoProcInfo = kCStackBased
  458.          | RESULT_SIZE(SIZE_CODE(sizeof(short)))
  459.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short)))
  460.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(char *)))
  461.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(struct returnRec *)))
  462.          | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(long)))
  463.          | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(char *)))
  464.  
  465. };
  466.  
  467. #if USESROUTINEDESCRIPTORS
  468. typedef UniversalProcPtr HInfoUPP;
  469.  
  470. #define    NewHInfoProc(userRoutine)                        \
  471.         (HInfoUPP) NewRoutineDescriptor(userRoutine, uppHInfoProcInfo, GetCurrentISA())
  472. #define    CallHInfoProc(userRoutine, selector, hostName, returnRecPtr, resultProc, userData)    \
  473.         CallUniversalProc(userRoutine, uppHInfoProcInfo, selector, hostName, returnRecPtr, resultProc, userData)
  474. #else
  475. typedef HInfoProcPtr HInfoUPP;
  476.  
  477. #define    NewHInfoProc(userRoutine)                        \
  478.         (HInfoUPP)(userRoutine)
  479. #define    CallHInfoProc(userRoutine, selector, hostName, returnRecPtr, resultProc, userData)    \
  480.         CallUniversalProc(userRoutine, uppHInfoProcInfo, selector, hostName, returnRecPtr, resultProc, userData)
  481. #endif
  482.  
  483. extern OSErr HInfo(hostName, returnRecPtr, resultProc, userDataPtr)
  484. char *hostName;
  485. struct returnRec *returnRecPtr;
  486. long resultProc;
  487. char *userDataPtr;
  488. {
  489.     if (dnr == nil)
  490.         /* resolver not loaded error */
  491.         return(notOpenErr);
  492.         
  493.     return(CallHInfoProc(dnr, HINFO, hostName, returnRecPtr, resultProc, userDataPtr));
  494. }
  495.  
  496.  
  497.  
  498. typedef OSErr (*MXInfoProcPtr)(short selector, char* hostName, struct returnRec* returnRecPtr,
  499.                                 long resultProc, char* userData);
  500.  
  501. enum {
  502.     uppMXInfoProcInfo = kCStackBased
  503.          | RESULT_SIZE(SIZE_CODE(sizeof(short)))
  504.          | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short)))
  505.          | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(char *)))
  506.          | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(struct returnRec *)))
  507.          | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(long)))
  508.          | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(char *)))
  509.  
  510. };
  511.  
  512. #if USESROUTINEDESCRIPTORS
  513. typedef UniversalProcPtr MXInfoUPP;
  514.  
  515. #define    NewMXInfoProc(userRoutine)                        \
  516.         (MXInfoUPP) NewRoutineDescriptor(userRoutine, uppMXInfoProcInfo, GetCurrentISA())
  517. #define    CallMXInfoProc(userRoutine, selector, hostName, returnRecPtr, resultProc, userData)    \
  518.         CallUniversalProc(userRoutine, selector, hostName, returnRecPtr, resultProc, userData)
  519. #else
  520. typedef MXInfoProcPtr MXInfoUPP;
  521.  
  522. #define    NewMXInfoProc(userRoutine)                        \
  523.         (MXInfoUPP)(userRoutine)
  524. #define    CallMXInfoProc(userRoutine, selector, hostName, returnRecPtr, resultProc, userData)    \
  525.         (*userRoutine)(selector, hostName, returnRecPtr, resultProc, userData)
  526. #endif
  527.     
  528.     
  529. extern OSErr MXInfo(hostName, returnRecPtr, resultProc, userDataPtr)
  530. char *hostName;
  531. struct returnRec *returnRecPtr;
  532. long resultProc;
  533. char *userDataPtr;
  534. {
  535.     if (dnr == nil)
  536.         /* resolver not loaded error */
  537.         return(notOpenErr);
  538.         
  539.     return(CallMXInfoProc(dnr, MXINFO, hostName, returnRecPtr, resultProc, userDataPtr));
  540. };