home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD v1.2 / amidev_cd_12.iso / reference / amiga_mail_vol1 / program / portability < prev    next >
Text File  |  1990-01-26  |  21KB  |  404 lines

  1. (c)  Copyright 1989 Commodore-Amiga, Inc.   All rights reserved.
  2. The information contained herein is subject to change without notice, and 
  3. is provided "as is" without warranty of any kind, either expressed or implied.  
  4. The entire risk as to the use of this information is assumed by the user.
  5.  
  6.  
  7.  
  8.        Programming For Portability and Compatibility
  9.  
  10.                   By Bill Koester
  11.  
  12. In this article I will provide some guidelines for making programs
  13. portable between the current Amiga  models, and hopefully any
  14. future models.  The first rule of compatability is: assume nothing.
  15. There can be many variations among models and particular user setups.
  16.  
  17.  
  18. MEMORY
  19.  
  20. This one should be obvious; the amount of memory varies from one
  21. Amiga to another.  Always check for success when allocating memory.
  22. If you need to know beforehand, the Exec AvailMem() function can be
  23. used to provide a  means  of  checking  CHIP,  FAST,  and LARGEST
  24. memory available during program execution.
  25.  
  26. FONTS
  27.  
  28. On floppy based systems, the fonts directory is often deleted by
  29. the user to get extra disk space.  The only fonts you can be
  30. guaranteed to have are Topaz60 and Topaz80 which reside in ROM.
  31. If your program can use other fonts, always check for availability first.
  32. Offer access only to those fonts found in the FONTS directory at run time.
  33.  
  34.  
  35. DEVICES
  36.  
  37. Two other files that frequently get deleted are the clipboard.device
  38. and narrator.device.  Check the value returned when you open these devices.
  39. Of course, you should ALWAYS check for errors when calling any system
  40. function!  If you want to be really friendly,  an error message or
  41. requester is a good idea.  Many speech programs won't run because
  42. the narrator.device or translator.library is not present. This is less
  43. mysterious if you inform the user of the problem.
  44.  
  45.  
  46. LIBRARIES
  47.  
  48. As with devices, never assume the availability of a library.  Check 
  49. the value returned by OpenLibrary() calls and notify the user if there
  50. is a problem.  If your program doesn't run and the user doesn't know why,
  51. you will get the blame (even if the user is at fault).
  52.  
  53.  
  54. DRIVE UNITS
  55.  
  56. With the release of the A2000, many disk drive configurations are
  57. now possible.  One configuration often found on the 2000 is one
  58. internal and one external 3.5" drive.  This  configuration  results
  59. in drive names of df0: and df2:,  NOT  df0:  and  df1: as you might
  60. expect.  With the 2000, there will be many more hard drives, too.
  61. Remember  that additional hard disk partitions or drives have their
  62. own entry in the mountlist.  This means the user has free  reign
  63. over choosing the name.  Lots of file requestors allow the user
  64. to pick df0: or df1: (and possibly ram: or dh0:).  Unfortunately,
  65. very few configure themselves dynamically so that the user can
  66. pick ANY drive in the run-time system.
  67.  
  68. So what's the  solution?  With  this  article  I  have included a
  69. program called getdisks which  searches  the system for the names
  70. of all mounted disk  devices.  The  program  builds a simple Exec
  71. List with named nodes.  The node names correspond to the names of
  72. the mounted disk devices.  Use this program as a subroutine in
  73. your application so you can find out what drive units are available.
  74. For your old applications that can't be changed, try the public domain
  75. program AssignDev on Fish disk #79.
  76.  
  77.  
  78.  
  79.  
  80.  
  81.  
  82. /*********************************************************************/
  83. /*                                                                   */
  84. /*  Program name:  GetDisks (c) 1987 Commodore-Amiga Inc.            */
  85. /*                                                                   */
  86. /*  Function: To find the names of all available disk devices and    */
  87. /*            return them to the user in a simple exec list. The     */
  88. /*            list is made up of named nodes, the "names" being the  */
  89. /*            device name.                                           */
  90. /*                                                                   */
  91. /*  Purpose:  To provide a way to find out the number of drives      */
  92. /*            installed and their names. Provides a method for       */
  93. /*            programs to change themselves dynamically according    */
  94. /*            to a users particular configuration.                   */
  95. /*                                                                   */
  96. /*  Arguments:  None.                                                */
  97. /*                                                                   */
  98. /*  Programer:  Phillip Lindsay                                      */
  99. /*                                                                   */
  100. /*  Revised 24-Aug-87 for Lattice-C Compiler 3.10 (Bill Koester)     */
  101. /*********************************************************************/
  102. #include <exec/types.h>
  103. #include <exec/nodes.h>
  104. #include <exec/lists.h>
  105. #include <exec/memory.h>
  106. #include <libraries/dos.h>
  107. #include <libraries/dosextens.h>
  108. #include <libraries/filehandler.h>
  109.  
  110. #ifdef MANX                                  /* Manx includes        */
  111. #include <functions.h>
  112. #include <stdio.h>
  113. #else
  114. #include <lattice/stdio.h>
  115. #endif
  116.  
  117. extern struct DosLibrary *DOSBase;
  118.  
  119. /************************************************************************/
  120. /*                                                                      */
  121. /* NAME                                                                 */
  122. /*                                                                      */
  123. /*    btoc                                                              */
  124. /*                                                                      */
  125. /* SYNOPSIS                                                             */
  126. /*                                                                      */
  127. /*    void btoc(bstring);                                               */
  128. /*    char *bstring;                                                    */
  129. /*                                                                      */
  130. /* PURPOSE                                                              */
  131. /*                                                                      */
  132. /*    To convert the BCPL format string pointed to by bstring, to a     */
  133. /*    NULL terminated C string.                                         */
  134. /*                                                                      */
  135. /* INPUTS                                                               */
  136. /*                                                                      */
  137. /*    char *bstring - Pointer to a string in BCPL format with the       */
  138. /*                    length in the first byte.                         */
  139. /*                                                                      */
  140. /* OUTPUTS                                                              */
  141. /*                                                                      */
  142. /*    None.                                                             */
  143. /*                                                                      */
  144. /* RESULTS                                                              */
  145. /*                                                                      */
  146. /*    The BCPL string (pointed to by bstring) is shifted left one byte  */
  147. /*    and the last character is replaced with the NULL terminator       */
  148. /*    according to C string format.                                     */
  149. /*                                                                      */
  150. /************************************************************************/
  151. void btoc(bstring)
  152. char *bstring;
  153. {
  154.  register UBYTE len,count,*cstring; 
  155.  
  156.  cstring = (UBYTE *) bstring;          /* Get pointer to BSTRING     */
  157.  len = cstring[0];                     /* Length is in first byte    */
  158.  
  159.  for(count=0;count < len;count++)      /* Shift entire string 1 byte */
  160.   cstring[count] = cstring[count+1];   /* to the left                */
  161.  
  162.  cstring[count] = '\0';                /* Replace last byte of BSTR  */
  163.                                        /* with required NULL byte    */
  164. }
  165.  
  166. /************************************************************************/
  167. /*                                                                      */
  168. /* NAME                                                                 */
  169. /*                                                                      */
  170. /*    GetNode                                                           */
  171. /*                                                                      */
  172. /* SYNOPSIS                                                             */
  173. /*                                                                      */
  174. /*    struct Node *GetNode(name,type,pri)                               */
  175. /*    char *name;                                                       */
  176. /*    UBYTE type,pri;                                                   */
  177. /*                                                                      */
  178. /* PURPOSE                                                              */
  179. /*                                                                      */
  180. /*    GetNode() will build a node structure for you. It will append     */
  181. /*    memory to the node structure for the node name passed.            */
  182. /*                                                                      */
  183. /*                                                                      */
  184. /* INPUTS                                                               */
  185. /*                                                                      */
  186. /*    char *name  -  Pointer to C string containg node name.            */
  187. /*    UBYTE type  -  Node type.                                         */
  188. /*    UBYTE pri   -  Node priority.                                     */
  189. /*                                                                      */
  190. /* OUTPUTS                                                              */
  191. /*                                                                      */
  192. /*    struct Node *  -  Pointer to allocated and initialized node.      */
  193. /*                      Returns NULL on memory allocation error.        */
  194. /*                                                                      */
  195. /* RESULTS                                                              */
  196. /*                                                                      */
  197. /*    Allocates a block of memory big enough for the Node structure     */
  198. /*    plus the name string. Copies the name string to the end of the    */
  199. /*    block and adjusts ln_Name to point there. Then set ln_Type and    */
  200. /*    ln_Pri. Finally returns a pointer to the start of the memory      */
  201. /*    block which contains the initialized Node structure with the      */
  202. /*    name appended.                                                    */
  203. /*                                                                      */
  204. /************************************************************************/
  205. struct Node *GetNode(name,type,pri)
  206. char *name;
  207. UBYTE type,pri;
  208. {
  209.  register struct Node   *mynode;
  210.  register char          *myname;
  211.  register UBYTE         *mymemory;
  212.  register ULONG         mynamesize;
  213.  
  214.  /* Size is 0 if no name else length of string plus NULL terminator  */
  215.  
  216.  mynamesize =( ((ULONG)strlen(name)) ? (ULONG)strlen(name)+1 : 0L );   
  217.  
  218.  mynode=0; /* make compiler happy about unitialized auto variable */
  219.  
  220.  mymemory = (UBYTE *) 
  221.   AllocMem((ULONG)sizeof(*mynode)+mynamesize,MEMF_PUBLIC | MEMF_CLEAR); 
  222.  
  223.  if(!mymemory) return((struct Node *)NULL);
  224.  
  225.  mynode = (struct Node *) mymemory; 
  226.  if(mynamesize)
  227.   {
  228.    myname = (char *) mymemory+(ULONG)sizeof(*mynode);
  229.    strcpy(myname,name);
  230.    mynode->ln_Name = myname;
  231.   }
  232.  mynode->ln_Type = type;
  233.  mynode->ln_Pri  = pri;
  234.  
  235.  return(mynode);
  236. }
  237.  
  238. /************************************************************************/
  239. /*                                                                      */
  240. /* NAME                                                                 */
  241. /*                                                                      */
  242. /*    FreeNode                                                          */
  243. /*                                                                      */
  244. /* SYNOPSIS                                                             */
  245. /*                                                                      */
  246. /*    void FreeNode(mynode);                                            */
  247. /*    struct Node *mynode;                                              */
  248. /*                                                                      */
  249. /* PURPOSE                                                              */
  250. /*                                                                      */
  251. /*    This function assumes you used GetNode() for node initialization. */
  252. /*    Will free all memory used by node. Make sure you remove node from */
  253. /*    any list.                                                         */
  254. /*                                                                      */
  255. /* INPUTS                                                               */
  256. /*                                                                      */
  257. /*    struct Node *mynode  -  Pointer to a node initialized by GetNode. */
  258. /*                                                                      */
  259. /* OUTPUTS                                                              */
  260. /*                                                                      */
  261. /*    None.                                                             */
  262. /*                                                                      */
  263. /* RESULTS                                                              */
  264. /*                                                                      */
  265. /*    All memory associated with the node is freed.                     */
  266. /*                                                                      */
  267. /************************************************************************/
  268. void FreeNode(mynode)
  269. struct Node *mynode;
  270. {
  271.  register ULONG mymemsize;
  272.  
  273.  mymemsize = (ULONG) sizeof(*mynode);
  274.  mymemsize+= ((mynode->ln_Name) ? (ULONG)strlen(mynode->ln_Name)+1 : 0L);
  275.  
  276.  FreeMem(mynode,mymemsize);
  277. }
  278.  
  279. /************************************************************************/
  280. /*                                                                      */
  281. /* NAME                                                                 */
  282. /*                                                                      */
  283. /*    getdisks                                                          */
  284. /*                                                                      */
  285. /* SYNOPSIS                                                             */
  286. /*                                                                      */
  287. /*    void getdisks(dlist)                                              */
  288. /*    struct List *dlist;                                               */
  289. /*                                                                      */
  290. /* PURPOSE                                                              */
  291. /*                                                                      */
  292. /*    This routine searches the system device list for all the disk     */
  293. /*    device names. For each disk device found it appends a named node  */
  294. /*    to the list pointed to by dlist. The appended node contains the   */
  295. /*    name of the disk device as its name.                              */
  296. /*                                                                      */
  297. /* GLOBALS NEEDED                                                       */
  298. /*                                                                      */
  299. /*    extern struct DosLibrary *DOSBase;                                */
  300. /*                                                                      */
  301. /* INPUTS                                                               */
  302. /*                                                                      */
  303. /*    struct List *dlist;  -  Pointer to your list to be filled.        */
  304. /*                                                                      */
  305. /* OUTPUTS                                                              */
  306. /*                                                                      */
  307. /*    None.                                                             */
  308. /*                                                                      */
  309. /* RESULTS                                                              */
  310. /*                                                                      */
  311. /*    Named nodes are added to your list where the node names           */
  312. /*    correspond to the disk device names currently mounted.            */
  313. /*                                                                      */
  314. /************************************************************************/
  315. void getdisks(dlist)
  316. struct List *dlist;     /* passed a pointer to an initialized exec list */ 
  317. {
  318.  extern struct DosLibrary     *DOSBase;
  319.  struct RootNode              *rnode; 
  320.  struct DosInfo               *dinfo;
  321.  register struct DeviceNode   *dnode;
  322.  register struct Node         *adisk;
  323.  char                         *bname,name[32];
  324.  
  325.  rnode   = (struct RootNode *)  DOSBase->dl_Root;
  326.  dinfo   = (struct DosInfo  *)  BADDR(rnode->rn_Info);
  327.  
  328.  Forbid();
  329.  for(dnode = (struct DeviceNode *) BADDR(dinfo->di_DevInfo);BADDR(dnode);
  330.     dnode = (struct DeviceNode *) BADDR(dnode->dn_Next))
  331.   {
  332.    if(!dnode->dn_Type && dnode->dn_Task && BADDR(dnode->dn_Name)) 
  333.     {
  334.      bname = (char *) BADDR(dnode->dn_Name);    
  335.      movmem(bname,name,(ULONG)bname[0]+1L);
  336.      btoc(name);
  337.      if((adisk=GetNode(name,0,0))) AddTail(dlist,adisk);    
  338.     }
  339.   }
  340.  Permit(); 
  341. }
  342.  
  343. /************************************************************************/
  344. /*                                                                      */
  345. /* NAME                                                                 */
  346. /*                                                                      */
  347. /*    freedisks                                                         */
  348. /*                                                                      */
  349. /* SYNOPSIS                                                             */
  350. /*                                                                      */
  351. /*    void freedisks(dlist)                                             */
  352. /*    struct List *dlist;                                               */
  353. /*                                                                      */
  354. /* PURPOSE                                                              */
  355. /*                                                                      */
  356. /*    Will free all nodes in the list pointed to by dlist. Assumes the  */
  357. /*    nodes where initialized with GetNode().                           */
  358. /*                                                                      */
  359. /* INPUTS                                                               */
  360. /*                                                                      */
  361. /*    struct List *dlist;  -  Pointer to list with the nodes you want   */
  362. /*                            freed.                                    */
  363. /*                                                                      */
  364. /* OUTPUTS                                                              */
  365. /*                                                                      */
  366. /*    None.                                                             */
  367. /*                                                                      */
  368. /* RESULTS                                                              */
  369. /*                                                                      */
  370. /*    All nodes in the list pointed to by dlist are returned to the     */
  371. /*    system free memory list.                                          */
  372. /*                                                                      */
  373. /************************************************************************/
  374. void freedisks(dlist)
  375. struct List *dlist;
  376. {
  377.  register struct Node *disk;
  378.  
  379.  while((disk= (struct Node *)RemTail(dlist)))
  380.   FreeNode(disk);
  381. }
  382.  
  383. /************************************************************************/
  384. /*                                                                      */
  385. /*                              M A I N                                 */
  386. /*                                                                      */
  387. /************************************************************************/
  388. main()
  389. {
  390.  struct List disks;
  391.  struct Node *disk;
  392.   
  393.  NewList(&disks);   /* Initialize list header */
  394.  getdisks(&disks);   /* Fill list */
  395.  
  396. /* print any devices in list.... if any */
  397.  if((struct List *)disks.lh_TailPred != (struct List *)&disks)
  398.    for(disk = disks.lh_Head;disk->ln_Succ;disk=disk->ln_Succ)
  399.      puts(disk->ln_Name);
  400.  
  401.  freedisks(&disks);
  402.  return(0);
  403. }  
  404.