home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / msysjour / vol05 / 05 / based / list.c < prev    next >
Text File  |  1990-09-01  |  13KB  |  460 lines

  1. // list.c RHS based pointer linked list routines
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. #include<malloc.h>
  5. #include<string.h>
  6. #include<dos.h>
  7. #include<fcntl.h>
  8.  
  9. static _segment _tempseg;
  10.  
  11. typedef struct _list LIST;
  12. typedef struct _litem LISTITEM;
  13.  
  14. struct _list
  15.     {
  16.     _segment seg;
  17.     unsigned num;
  18.     unsigned segsize;
  19.     char _based(_tempseg) *name;
  20.     LISTITEM _based(_tempseg) *item;
  21.     };
  22.  
  23. struct _litem
  24.     {
  25.     void far *object;
  26.     unsigned objectsize;
  27.     char _based(_tempseg) *name;
  28.     LISTITEM _based(_tempseg) *prev;
  29.     LISTITEM _based(_tempseg) *next;
  30.     };
  31.  
  32. typedef struct _listheader          // for Save/Restore only
  33.     {
  34.     unsigned segsize;
  35.     unsigned offset;
  36.     } LISTHEADER;
  37.  
  38. typedef LIST far                    *PLIST;
  39. typedef LIST _based(_tempseg)       *BPLIST;
  40. typedef LISTITEM _based(_tempseg)   *BPLITEM;
  41.  
  42. #define LITEMHDL              BPLITEM
  43. #define _listinit()     (_tempseg = plist->seg)
  44.  
  45. PLIST ListInit(unsigned members, char *name);
  46. BPLITEM ListAdd(PLIST plist, void far *object, unsigned size,
  47.                 char *name);
  48. LITEMHDL ListFind(PLIST plist, char *name);
  49. void far *ListDelete(PLIST plist, char *name);
  50. static void far *_ListDelete(PLIST plist, BPLITEM bplitem);
  51. void ListDestroy(PLIST plist);
  52. void ListSetObject(PLIST plist, void far *object, unsigned size,
  53.                    char *name);
  54. void far *ListGetObject(PLIST plist, char *name);
  55. void ListDeleteObject(PLIST plist, char *name);
  56. void ListSetName(PLIST plist, char *name);
  57. static PLIST _ListInit(unsigned realsize);
  58. unsigned ListGetNumItems(PLIST plist);
  59. LITEMHDL ListGetItem(PLIST plist);
  60. LITEMHDL ListItemGetNextItem(PLIST plist, LITEMHDL bplitem);
  61. void far *ListItemGetObject(PLIST plist, LITEMHDL bplitem);
  62.  
  63. void error_exit(int err, char *msg);
  64. void ListDump(PLIST plist);
  65. void ListDumpItem(BPLITEM temp);
  66.  
  67.  
  68.     // creates a list and returns a handle (void far *) to it
  69. PLIST ListInit(unsigned members, char *name)
  70.     {
  71.     long realsize;
  72.     PLIST plist;
  73.  
  74.     if(!members)              // if no number specified, set high
  75.         members = ((0xffff/2) / sizeof(LISTITEM));
  76.     realsize = sizeof(LISTITEM);
  77.     realsize *= members;
  78.  
  79.     if(realsize > 65535L)     // check size value
  80.         return NULL;
  81.  
  82.     if((plist = _ListInit((unsigned)realsize+sizeof(LIST))) != NULL)
  83.         {
  84.         plist->name = _NULLOFF;
  85.         ListSetName(plist,name);
  86.         plist->num = 0;
  87.         }
  88.     return plist;
  89.     }
  90.  
  91.     // internal function: intializes a list and returns a pointer
  92. static PLIST _ListInit(unsigned realsize)
  93.     {
  94.     BPLIST plist;
  95.                               // allocate segment for entire list
  96.     if((_tempseg = _bheapseg(realsize)) == _NULLSEG)
  97.         return NULL;
  98.                               // allocate space for header
  99.     if((plist = (BPLIST)_bmalloc(_tempseg, sizeof(LIST)))== _NULLOFF)
  100.         {
  101.         _bfreeseg(_tempseg);
  102.         return (PLIST)NULL;
  103.         }
  104.     plist->seg = _tempseg;
  105.     plist->segsize = realsize;
  106.     plist->item = _NULLOFF;
  107.     return (PLIST)plist;
  108.     }
  109.  
  110.     // sets the name of a list; can be used to change the name
  111. void ListSetName(PLIST plist, char *name)
  112.     {
  113.     _listinit();
  114.  
  115.     if(plist->name == _NULLOFF)
  116.         _bfree(plist->seg, plist->name);
  117.     if((plist->name = _bmalloc(plist->seg,strlen(name)+1)) !=
  118.                                                             _NULLOFF)
  119.         _fstrcpy((char far *)plist->name,(char far *)name);
  120.     }
  121.  
  122.     // adds a new item to the list and returns a pointer to it
  123. BPLITEM ListAdd(PLIST plist, void far *object, unsigned size,
  124.                 char *name)
  125.     {
  126.     BPLITEM plistitem;
  127.  
  128.     _listinit();       // set _tempseg for this operation
  129.  
  130.                        // if unable to allocate item
  131.     if((plistitem= _bmalloc(plist->seg,sizeof(LISTITEM)))== _NULLOFF)
  132.         return _NULLOFF;
  133.  
  134.     plistitem->object = object;         // set object pointer
  135.     plistitem->objectsize = size;
  136.                                         // allocate item name and set
  137.     if((plistitem->name = _bmalloc(plist->seg,strlen(name)+1)) !=
  138.                                                             _NULLOFF)
  139.         _fstrcpy((char far *)plistitem->name,(char far *)name);
  140.     if(plist->item == _NULLOFF)    // find next available list member
  141.  
  142.         {
  143.         plist->item = plistitem;   // use list->item if not used
  144.         plistitem->prev = _NULLOFF;
  145.         }
  146.     else
  147.         {
  148.         BPLITEM temp = plist->item; // or find one in list
  149.  
  150.         for( ; temp->next != _NULLOFF; temp = temp->next);
  151.         temp->next = plistitem;
  152.         plistitem->prev = temp;
  153.         }
  154.     plistitem->next = _NULLOFF;
  155.     plist->num++;
  156.  
  157.     return plistitem;
  158.     }
  159.  
  160.     // deletes a named item from a list; returns the object's pointer
  161. void far *ListDelete(PLIST plist, char *name)
  162.     {
  163.     BPLITEM temp;
  164.  
  165.     _listinit();
  166.  
  167.     if((temp = ListFind(plist,name)) != _NULLOFF)
  168.         return _ListDelete(plist, temp);
  169.     plist->num--;
  170.     return (void far *)NULL;
  171.     }
  172.  
  173.     // internal function: deletes item from a list and returns object
  174. static void far *_ListDelete(PLIST plist, BPLITEM bplitem)
  175.     {
  176.     void far *object;
  177.  
  178.     _listinit();
  179.     object = bplitem->object;
  180.  
  181.     if(bplitem->prev != _NULLOFF)       // remove item from list
  182.                                         // set prev's next to next
  183.         bplitem->prev->next = bplitem->next;
  184.     else                                // unless there is no prev
  185.                                    // then set parent's item to next
  186.         plist->item = bplitem->next;
  187.     if(bplitem->next != _NULLOFF)            // if a next
  188.         bplitem->next->prev= bplitem->prev;  // set it's prev to prev
  189.     _bfree(plist->seg,bplitem->name);        // free the name
  190.     _bfree(plist->seg,bplitem);              // free the item
  191.     return object;                           // return object to user
  192.     }
  193.  
  194.     // relates an object to a list item
  195. void ListSetObject(PLIST plist, void far *object, unsigned size,
  196.     char *name)
  197.     {
  198.     BPLITEM temp;
  199.  
  200.     _listinit();
  201.  
  202.     if((temp = ListFind(plist,name)) != _NULLOFF)
  203.         {
  204.         temp->object = object;          // set object ptr
  205.         temp->objectsize = size;        // set object size
  206.         }
  207.     }
  208.  
  209.     // returns the count of items in the list
  210. unsigned ListGetNumItems(PLIST plist)
  211.     {
  212.     _listinit();
  213.  
  214.     return plist->num;                  // return number of items
  215.     }
  216.  
  217.     // frees the object related to the named item
  218. void ListDeleteObject(PLIST plist, char *name)
  219.     {
  220.     BPLITEM temp;
  221.  
  222.     _listinit();
  223.  
  224.     if((temp = ListFind(plist,name)) != _NULLOFF)
  225.         {
  226.         _ffree(temp->object);           // free object
  227.         temp->object = (void far *)NULL;// set ptr to NULL
  228.         }
  229.     }
  230.  
  231.     // frees list and related objects
  232. void ListDestroy(PLIST plist)
  233.     {
  234.     BPLITEM bplitem;
  235.  
  236.     _listinit();
  237.  
  238.     for(bplitem = plist->item; bplitem != _NULLOFF;
  239.         bplitem = bplitem->next)
  240.         _ffree(bplitem->object);        // free each object
  241.  
  242.     _bfreeseg(plist->seg);              // free list segment
  243.     }
  244.  
  245.     // finds an item in the list by name, and returns a handle
  246. LITEMHDL ListFind(PLIST plist, char *name)
  247.     {
  248.     BPLITEM temp;
  249.  
  250.     _listinit();
  251.  
  252.     for( temp = plist->item; temp != _NULLOFF; temp = temp->next)
  253.         if(!_fstrncmp((char far *)temp->name,
  254.             (char far *)name, strlen(name)))
  255.             return (LITEMHDL)temp;
  256.     return 0;
  257.     }
  258.  
  259.     // dumps list contents to the screen
  260. void ListDump(PLIST plist)
  261.     {
  262.     BPLITEM temp;
  263.  
  264.     _listinit();
  265.  
  266.     printf("List Name=%Fs\n", (char far *)plist->name);
  267.  
  268.     printf("Located @ %lp, occupies %u bytes in %04x:0000"
  269.             " and contains:\n",
  270.             (void far *)plist,
  271.             plist->segsize,
  272.             plist->seg);
  273.  
  274.     if(!plist->item)
  275.         {
  276.         printf("No items.\n");
  277.         return;
  278.         }
  279.     for( temp = plist->item; temp != _NULLOFF; temp = temp->next)
  280.         ListDumpItem(temp);
  281.     }
  282.  
  283.     // dumps an individual item to the screen
  284. void ListDumpItem(BPLITEM bplitem)
  285.     {
  286.     char far * name1;
  287.     char far * name2;
  288.     void far * prev;
  289.     void far * next;
  290.  
  291.     if (bplitem->next != _NULLOFF)
  292.         {
  293.         next = (void far *)bplitem->next;
  294.         name1 = (char far *)bplitem->next->name;
  295.         }
  296.     else
  297.         {
  298.         next = NULL;
  299.         name1 = "NULL";
  300.         }
  301.  
  302.     if (bplitem->prev != _NULLOFF)
  303.         {
  304.         prev = (void far *)bplitem->prev;
  305.         name2 = (char far *)bplitem->prev->name;
  306.         }
  307.     else
  308.         {
  309.         prev = NULL;
  310.         name2 = "NULL";
  311.         }
  312.  
  313.     printf("Item: %Fs is located @ %lp, "
  314.             "(stores related object @ %lp)"
  315.             "\n\t(prev=%lp \"%Fs\" next=%lp \"%Fs\")\n",
  316.             (char far *)bplitem->name,
  317.             (void far *)bplitem,
  318.             (void far *)bplitem->object,
  319.             prev,
  320.             name2,
  321.             next,
  322.             name1);
  323.     }
  324.  
  325.     // returns a pointer to the object related to bplitem
  326. void far *ListItemGetObject(PLIST plist, LITEMHDL bplitem)
  327.     {
  328.     _listinit();
  329.  
  330.     return (bplitem)->object;
  331.     }
  332.  
  333.     // returns a pointer to the object related to the named item
  334. void far *ListGetObject(PLIST plist, char *name)
  335.     {
  336.     BPLITEM temp;
  337.  
  338.     _listinit();
  339.  
  340.     if((temp = ListFind(plist,name)) != _NULLOFF)
  341.         return temp->object;
  342.     return (void far *)NULL;
  343.     }
  344.  
  345.     // returns a handle to the first item in the list
  346. LITEMHDL ListGetItem(PLIST plist)
  347.     {
  348.     _listinit();
  349.  
  350.     return (LITEMHDL)plist->item;
  351.     }
  352.  
  353.     // returns a handle to the next item in the list after bplitem
  354. LITEMHDL ListItemGetNextItem(PLIST plist, LITEMHDL bplitem)
  355.     {
  356.     _listinit();
  357.  
  358.     return (LITEMHDL)(bplitem)->next;
  359.     }
  360.  
  361.     // saves LIST to file
  362. unsigned ListSave(PLIST plist, char *filename)
  363.     {
  364.     int fh;
  365.     unsigned doserror, bytes;
  366.     BPLITEM temp;
  367.     LISTHEADER lh;
  368.     void far *buf;
  369.  
  370.     _listinit();
  371.  
  372.     FP_OFF(buf) = 0;
  373.     FP_SEG(buf) = (unsigned)plist->seg;
  374.  
  375.     lh.segsize = plist->segsize;
  376.     lh.offset = FP_OFF(plist);
  377.  
  378.         // create list file
  379.     if(doserror = _dos_creat(filename,_A_NORMAL,&fh))
  380.         error_exit(doserror,"Unable to create list file");
  381.  
  382.         // write file header with segsize and list header offset
  383.     if((doserror = _dos_write(fh,(void far *)&lh,sizeof(lh),&bytes))
  384.             || (bytes != sizeof(lh)))
  385.         error_exit(doserror,"Unable to write list file header");
  386.  
  387.         // write segment
  388.     if((doserror = _dos_write(fh,buf,plist->segsize,&bytes))
  389.             || (bytes != plist->segsize))
  390.         error_exit(doserror,"Unable to write list file segment");
  391.  
  392.         // write each object
  393.     for(temp = plist->item; temp != _NULLOFF; temp = temp->next)
  394.         if(temp->object)                // if node has an object
  395.             if((doserror=_dos_write(fh,temp->object,temp->objectsize,
  396.                     &bytes)) || (bytes != temp->objectsize))
  397.                 error_exit(doserror,
  398.                            "Unable to write list file object");
  399.     _dos_close(fh);
  400.     return 0;
  401.     }
  402.  
  403.     // restores list from file
  404. PLIST ListRestore(char *filename)
  405.     {
  406.     int fh;
  407.     unsigned doserror,bytes;
  408.     PLIST plist;
  409.     LISTHEADER lh;
  410.     void far *buf;
  411.     BPLITEM temp;
  412.  
  413.         // open list file
  414.     if(doserror = _dos_open(filename,O_RDONLY,&fh))
  415.         error_exit(doserror,"Unable to open list file");
  416.  
  417.         // read list file header with segsize and list header offset
  418.     if((doserror = _dos_read(fh,(void far *)&lh,sizeof(lh),&bytes))
  419.             || (bytes != sizeof(lh)))
  420.         error_exit(doserror,"Unable to read list file header");
  421.  
  422.     if(!(plist = _ListInit(lh.segsize)))
  423.         {
  424.         _dos_close(fh);
  425.         return (PLIST)NULL;
  426.         }
  427.  
  428.     FP_OFF(plist) = lh.offset;          // reset to original offset
  429.     FP_SEG(buf) = plist->seg;           // set buf to plist segment
  430.     FP_OFF(buf) = 0;                    // and base of the segment
  431.  
  432.                                         // read entire segment
  433.     if((doserror = _dos_read(fh,buf,lh.segsize,&bytes)) ||
  434.             (bytes != lh.segsize))
  435.         error_exit(doserror,"Unable to read list file segment");
  436.  
  437.     plist->seg = (_segment)FP_SEG(buf); // reset (since overwritten)
  438.  
  439.     for(temp = plist->item; temp != _NULLOFF; temp = temp->next)
  440.         if(temp->object)                // if item had an object
  441.             {
  442.             if(!(temp->object = _fmalloc(temp->objectsize)))
  443.                 error_exit(0,"Unable to allocate space for object");
  444.             if((doserror= _dos_read(fh,temp->object,temp->objectsize,
  445.                     &bytes)) || (bytes != temp->objectsize))
  446.                 error_exit(doserror,"Unable to read list object");
  447.             }
  448.     _dos_close(fh);
  449.     return plist;
  450.     }
  451.  
  452. void error_exit(int err, char *msg)
  453.     {
  454.     printf("%s\n",msg);
  455.     exit(err);
  456.     }
  457.  
  458.  
  459. // end of program
  460.