Changeset 15429

Show
Ignore:
Timestamp:
14.05.2008 11:14:32 (11 years ago)
Author:
mdewsnip
Message:

(Adding new db support) Moved gdbmclass out of infodbclass into its own file.

Location:
gsdl/trunk/lib
Files:
2 added
4 modified

Legend:

Unmodified
Added
Removed
  • gsdl/trunk/lib/Makefile.in

    r15420 r15429  
    9090HEADERS = \ 
    9191  cfgread.h        cnfgable.h       cnfgator.h       display.h \ 
    92   fileutil.h       gsdlsitecfg.h    gsdltimes.h      gsdltools.h \ 
    93   gsdlunicode.h    infodbclass.h    md5.h            OIDtools.h \ 
    94   phrases.h        text_t.h         $(CORBAHEADERS)  gsdlconf.h 
     92  fileutil.h       gdbmclass.h      gsdlsitecfg.h    gsdltimes.h \ 
     93  gsdltools.h      gsdlunicode.h    infodbclass.h    md5.h \ 
     94  OIDtools.h       phrases.h        text_t.h         $(CORBAHEADERS)  gsdlconf.h 
    9595 
    9696SOURCES = \ 
    9797  cfgread.cpp      cnfgable.cpp     cnfgator.cpp     display.cpp \ 
    98   fileutil.cpp     gsdlsitecfg.cpp  gsdltimes.cpp    gsdltools.cpp \ 
    99   gsdlunicode.cpp  infodbclass.cpp  md5.cpp          OIDtools.cpp \ 
    100   phrases.cpp      text_t.cpp       $(CORBASOURCES) 
     98  fileutil.cpp     gdbmclass.cpp    gsdlsitecfg.cpp  gsdltimes.cpp \ 
     99  gsdltools.cpp    gsdlunicode.cpp  infodbclass.cpp  md5.cpp \ 
     100  OIDtools.cpp     phrases.cpp      text_t.cpp       $(CORBASOURCES) 
    101101 
    102102OBJECTS = \ 
    103103  cfgread.o        cnfgable.o       cnfgator.o       display.o \ 
    104   fileutil.o       gsdlsitecfg.o    gsdltimes.o      gsdltools.o \ 
    105   gsdlunicode.o    infodbclass.o    md5.o            OIDtools.o \ 
    106   phrases.o        text_t.o         $(CORBAOBJECTS) 
     104  fileutil.o       gdbmclass.o      gsdlsitecfg.o    gsdltimes.o \ 
     105  gsdltools.o      gsdlunicode.o    infodbclass.o    md5.o \ 
     106  OIDtools.o       phrases.o        text_t.o         $(CORBAOBJECTS) 
    107107 
    108108 
  • gsdl/trunk/lib/infodbclass.cpp

    r15420 r15429  
    2525 
    2626#include "infodbclass.h" 
    27 #include "unitool.h" 
    28 #include "gsdlunicode.h" 
    29 #include "fileutil.h" 
    30 #include "OIDtools.h" 
    31 #include <stdlib.h> 
    3227 
    3328 
     
    151146  return &((*here).second); 
    152147} 
    153  
    154  
    155  
    156 gdbmclass::~gdbmclass() 
    157 { 
    158   closedatabase(); 
    159 } 
    160  
    161 // returns true if opened 
    162 bool gdbmclass::opendatabase (const text_t &filename, int mode, int num_retrys,  
    163 #ifdef __WIN32__ 
    164                   bool need_filelock 
    165 #else 
    166                               bool 
    167 #endif 
    168                   ) 
    169 { 
    170   text_t data_location; 
    171   int block_size = 512; 
    172    
    173   if (gdbmfile != NULL) { 
    174     if (openfile == filename) return true; 
    175     else closedatabase (); 
    176   } 
    177  
    178   openfile = filename; 
    179    
    180   char *namebuffer = filename.getcstr(); 
    181   do { 
    182 #ifdef __WIN32__ 
    183     gdbmfile = gdbm_open (namebuffer, block_size, mode, 00664, NULL, (need_filelock) ? 1 : 0); 
    184 #else 
    185     gdbmfile = gdbm_open (namebuffer, block_size, mode, 00664, NULL); 
    186 #endif 
    187     --num_retrys; 
    188   } while (num_retrys>0 && gdbmfile==NULL && 
    189        (gdbm_errno==GDBM_CANT_BE_READER || gdbm_errno==GDBM_CANT_BE_WRITER)); 
    190   delete []namebuffer; 
    191    
    192   if (gdbmfile == NULL && logout != NULL) { 
    193     outconvertclass text_t2ascii; 
    194     (*logout) << text_t2ascii << "database open failed on: " << filename << "\n"; 
    195   } 
    196  
    197   return (gdbmfile != NULL); 
    198 } 
    199  
    200  
    201 void gdbmclass::closedatabase () 
    202 { 
    203   if (gdbmfile == NULL) return; 
    204    
    205   gdbm_close (gdbmfile); 
    206   gdbmfile = NULL; 
    207   openfile.clear(); 
    208 } 
    209  
    210  
    211 // returns true on success 
    212 bool gdbmclass::setinfo (const text_t &key, const infodbclass &info) 
    213 { 
    214   if (gdbmfile == NULL) return false; 
    215  
    216   text_t subkey; 
    217   text_t data; 
    218  
    219   // get all the keys and values 
    220   infodbclass::const_iterator info_here = info.begin(); 
    221   infodbclass::const_iterator info_end = info.end(); 
    222   while (info_here != info_end) { 
    223     // add the key 
    224     subkey.clear(); 
    225     subkey.push_back('<'); 
    226     text_t::const_iterator subkey_here = (*info_here).first.begin(); 
    227     text_t::const_iterator subkey_end = (*info_here).first.end(); 
    228     while (subkey_here != subkey_end) { 
    229       if (*subkey_here == '>') { 
    230     subkey.push_back('\\'); subkey.push_back('>'); 
    231       } else if (*subkey_here == '\n') { 
    232     subkey.push_back('\\'); subkey.push_back('n'); 
    233       } else if (*subkey_here == '\r') { 
    234     subkey.push_back('\\'); subkey.push_back('r'); 
    235       } else if (*subkey_here == '\\') { 
    236     subkey.push_back('\\'); subkey.push_back('\\'); 
    237       } else { 
    238     subkey.push_back (*subkey_here); 
    239       } 
    240       ++subkey_here; 
    241     } 
    242     subkey.push_back('>'); 
    243  
    244     // add the values 
    245     text_tarray::const_iterator subvalue_here = (*info_here).second.begin(); 
    246     text_tarray::const_iterator subvalue_end = (*info_here).second.end(); 
    247     while (subvalue_here != subvalue_end) { 
    248       data += subkey; 
    249        
    250       text_t::const_iterator thissubvalue_here = (*subvalue_here).begin(); 
    251       text_t::const_iterator thissubvalue_end = (*subvalue_here).end(); 
    252       while (thissubvalue_here != thissubvalue_end) { 
    253     if (*thissubvalue_here == '>') { 
    254       data.push_back('\\'); data.push_back('>'); 
    255     } else if (*thissubvalue_here == '\n') { 
    256       data.push_back('\\'); data.push_back('n'); 
    257     } else if (*thissubvalue_here == '\r') { 
    258       data.push_back('\\'); data.push_back('r'); 
    259     } else if (*thissubvalue_here == '\\') { 
    260       data.push_back('\\'); data.push_back('\\'); 
    261     } else { 
    262       data.push_back (*thissubvalue_here); 
    263     } 
    264      
    265     ++thissubvalue_here; 
    266       } 
    267        
    268       data.push_back('\n'); 
    269       ++subvalue_here; 
    270     } 
    271  
    272     ++info_here; 
    273   } 
    274  
    275   // store the value 
    276   datum key_data; 
    277   datum data_data; 
    278  
    279   // get a utf-8 encoded c string of the unicode key 
    280   key_data.dptr = (to_utf8(key)).getcstr(); 
    281   if (key_data.dptr == NULL) { 
    282     if (logout != NULL) (*logout) << "gdbmclass: out of memory\n"; 
    283     return false; 
    284   } 
    285   key_data.dsize = strlen (key_data.dptr); 
    286  
    287   data_data.dptr = (to_utf8(data)).getcstr(); 
    288   if (data_data.dptr == NULL) { 
    289     if (logout != NULL) (*logout) << "gdbmclass: out of memory\n"; 
    290     delete []key_data.dptr; 
    291     return false; 
    292   } 
    293   data_data.dsize = strlen (data_data.dptr); 
    294  
    295   int ret = gdbm_store (gdbmfile, key_data, data_data, GDBM_REPLACE); 
    296   delete []key_data.dptr; 
    297   delete []data_data.dptr; 
    298  
    299   return (ret == 0); 
    300 } 
    301  
    302  
    303 //returns true on success 
    304 bool gdbmclass::setinfo (const text_t &key, const text_t &data) 
    305 { 
    306   if (gdbmfile == NULL) return false; 
    307    
    308   // store the value 
    309   datum key_data; 
    310   datum data_data; 
    311  
    312   // get a utf-8 encoded c string of the unicode key 
    313   key_data.dptr = (to_utf8(key)).getcstr(); 
    314   if (key_data.dptr == NULL) { 
    315     if (logout != NULL) (*logout) << "gdbmclass: out of memory\n"; 
    316     return false; 
    317   } 
    318   key_data.dsize = strlen (key_data.dptr); 
    319  
    320   data_data.dptr = (to_utf8(data)).getcstr(); 
    321   if (data_data.dptr == NULL) { 
    322     if (logout != NULL) (*logout) << "gdbmclass: out of memory\n"; 
    323     delete []key_data.dptr; 
    324     return false; 
    325   } 
    326   data_data.dsize = strlen (data_data.dptr); 
    327  
    328   int ret = gdbm_store (gdbmfile, key_data, data_data, GDBM_REPLACE); 
    329   delete []key_data.dptr; 
    330   delete []data_data.dptr; 
    331  
    332   return (ret == 0); 
    333 } 
    334  
    335  
    336 void gdbmclass::deletekey (const text_t &key) 
    337 { 
    338   if (gdbmfile == NULL) return; 
    339  
    340   // get a utf-8 encoded c string of the unicode key 
    341   datum key_data; 
    342   key_data.dptr = (to_utf8(key)).getcstr(); 
    343   if (key_data.dptr == NULL) return; 
    344   key_data.dsize = strlen (key_data.dptr); 
    345  
    346   // delete the key 
    347   gdbm_delete (gdbmfile, key_data); 
    348  
    349   // free up the key memory 
    350   delete []key_data.dptr; 
    351 } 
    352  
    353  
    354 // getfirstkey and getnextkey are used for traversing the database 
    355 // no insertions or deletions should be carried out while traversing 
    356 // the database. when there are no keys left to visit in the database 
    357 // an empty string is returned. 
    358 text_t gdbmclass::getfirstkey () 
    359 { 
    360   if (gdbmfile == NULL) return g_EmptyText; 
    361  
    362   // get the first key 
    363   datum firstkey_data = gdbm_firstkey (gdbmfile); 
    364   if (firstkey_data.dptr == NULL) return g_EmptyText; 
    365  
    366   // convert it to text_t 
    367   text_t firstkey; 
    368   firstkey.setcarr (firstkey_data.dptr, firstkey_data.dsize); 
    369   free (firstkey_data.dptr); 
    370   return to_uni(firstkey);  // convert to unicode 
    371 } 
    372  
    373  
    374 text_t gdbmclass::getnextkey (const text_t &key) 
    375 { 
    376   if (gdbmfile == NULL || key.empty()) return g_EmptyText; 
    377  
    378   // get a utf-8 encoded c string of the unicode key 
    379   datum key_data; 
    380   key_data.dptr = (to_utf8(key)).getcstr(); 
    381   if (key_data.dptr == NULL) return g_EmptyText; 
    382   key_data.dsize = strlen (key_data.dptr); 
    383    
    384   // get the next key 
    385   datum nextkey_data = gdbm_nextkey (gdbmfile, key_data); 
    386   if (nextkey_data.dptr == NULL) { 
    387     delete []key_data.dptr; 
    388     return g_EmptyText; 
    389   } 
    390  
    391   // convert it to text_t 
    392   text_t nextkey; 
    393   nextkey.setcarr (nextkey_data.dptr, nextkey_data.dsize); 
    394   free (nextkey_data.dptr); 
    395   delete []key_data.dptr; 
    396   return to_uni(nextkey);  // convert to unicode 
    397 } 
    398  
    399  
    400 // replaces the .fc, .lc, .pr, .rt, .ns and .ps syntax (first child,  
    401 // last child, parent, root, next sibling, previous sibling)  
    402 // it expects child, parent, etc. to exist if syntax has been used 
    403 // so you should test before using 
    404 text_t gdbmclass::translate_OID (const text_t &inOID, infodbclass &info) 
    405 { 
    406   if (inOID.size() < 4) return inOID; 
    407   if (findchar (inOID.begin(), inOID.end(), '.') == inOID.end()) return inOID; 
    408  
    409   text_t OID = inOID; 
    410   text_tarray tailarray; 
    411   text_t tail = substr (OID.end()-3, OID.end()); 
    412   if (tail == ".rt") { 
    413     get_top (inOID, OID); 
    414     return OID; 
    415   } 
    416   while (tail == ".fc" || tail == ".lc" || tail == ".pr" ||  
    417      tail == ".ns" || tail == ".ps") { 
    418     tailarray.push_back(tail); 
    419     OID.erase (OID.end()-3, OID.end()); 
    420     tail = substr (OID.end()-3, OID.end()); 
    421     if (tail == ".rt") { 
    422       get_top (inOID, OID); 
    423       return OID; 
    424     } 
    425   } 
    426  
    427   if (tailarray.empty()) return inOID; 
    428   text_tarray::const_iterator begin = tailarray.begin(); 
    429   text_tarray::const_iterator here = tailarray.end() - 1; 
    430  
    431   while (here >= begin) { 
    432  
    433     if (*here == ".fc") 
    434       get_first_child (OID, info); 
    435     else if (*here == ".lc") 
    436       get_last_child (OID, info); 
    437     else if (*here == ".pr") 
    438       OID = get_parent (OID); 
    439     else if (*here == ".ns") 
    440       get_next_sibling (OID, info); 
    441     else if (*here == ".ps") 
    442       get_previous_sibling (OID, info); 
    443      
    444     if (here == begin) 
    445       break; 
    446     --here; 
    447   } 
    448  
    449   return OID; 
    450 } 
    451  
    452  
    453 void gdbmclass::get_first_child (text_t &OID, infodbclass &info) 
    454 { 
    455   text_t firstchild; 
    456   if (getinfo (OID, info)) { 
    457     text_t &contains = info["contains"]; 
    458     if (!contains.empty()) { 
    459       text_t parent = OID; 
    460       getdelimitstr (contains.begin(), contains.end(), ';', firstchild); 
    461       if (firstchild.empty()) OID = contains; 
    462       else OID = firstchild; 
    463       if (*(OID.begin()) == '"') translate_parent (OID, parent); 
    464     } 
    465   } 
    466 } 
    467  
    468  
    469 void gdbmclass::get_last_child (text_t &OID, infodbclass &info) 
    470 { 
    471   text_tarray children; 
    472   if (getinfo (OID, info)) { 
    473     text_t &contains = info["contains"]; 
    474     if (!contains.empty()) { 
    475       text_t parent = OID; 
    476       splitchar (contains.begin(), contains.end(), ';', children); 
    477       OID = children.back(); 
    478       if (*(OID.begin()) == '"') translate_parent (OID, parent); 
    479     } 
    480   } 
    481 } 
    482  
    483    
    484 void gdbmclass::get_next_sibling (text_t &OID, infodbclass &info) 
    485 { 
    486   text_tarray siblings; 
    487   text_t parent = get_parent (OID); 
    488           
    489   if (getinfo (parent, info)) { 
    490     text_t &contains = info["contains"]; 
    491     if (!contains.empty()) { 
    492       splitchar (contains.begin(), contains.end(), ';', siblings); 
    493       text_tarray::const_iterator here = siblings.begin(); 
    494       text_tarray::const_iterator end = siblings.end(); 
    495       text_t shrunk_OID = OID; 
    496       shrink_parent (shrunk_OID); 
    497       while (here != end) { 
    498     if (*here == shrunk_OID && (here+1 != end)) { 
    499       OID = *(here+1); 
    500       if (*(OID.begin()) == '"') translate_parent (OID, parent); 
    501       break; 
    502     } 
    503     ++here; 
    504       } 
    505     } 
    506   } 
    507 } 
    508  
    509  
    510 void gdbmclass::get_previous_sibling (text_t &OID, infodbclass &info) 
    511 { 
    512   text_tarray siblings; 
    513   text_t parent = get_parent (OID); 
    514  
    515   if (getinfo (parent, info)) { 
    516     text_t &contains = info["contains"]; 
    517     if (!contains.empty()) { 
    518       splitchar (contains.begin(), contains.end(), ';', siblings); 
    519       text_tarray::const_iterator here = siblings.begin(); 
    520       text_tarray::const_iterator end = siblings.end(); 
    521       text_t shrunk_OID = OID; 
    522       shrink_parent (shrunk_OID); 
    523       while (here != end) { 
    524     if (*here == shrunk_OID && (here != siblings.begin())) { 
    525       OID = *(here-1); 
    526       if (*(OID.begin()) == '"') translate_parent (OID, parent); 
    527       break; 
    528     } 
    529     ++here; 
    530       } 
    531     } 
    532   } 
    533 } 
    534  
    535  
    536 // returns true on success 
    537 bool gdbmclass::getinfo (const text_t& key, infodbclass &info) 
    538 { 
    539   text_t data; 
    540    
    541   if (!getkeydata (key, data)) return false; 
    542   text_t::iterator here = data.begin (); 
    543   text_t::iterator end = data.end (); 
    544    
    545   text_t ikey, ivalue; 
    546   info.clear (); // reset info 
    547    
    548   while (getinfoline (here, end, ikey, ivalue)) { 
    549     info.addinfo (ikey, ivalue); 
    550   } 
    551    
    552   return true; 
    553 } 
    554  
    555  
    556 // returns true if exists 
    557 bool gdbmclass::exists (const text_t& key) 
    558 { 
    559   text_t data; 
    560   return getkeydata (key, data); 
    561 } 
    562  
    563  
    564 // returns true on success 
    565 bool gdbmclass::getkeydata (const text_t& key, text_t &data) 
    566 { 
    567   datum key_data; 
    568   datum return_data; 
    569  
    570   if (gdbmfile == NULL) return false; 
    571    
    572   // get a utf-8 encoded c string of the unicode key 
    573   key_data.dptr = (to_utf8(key)).getcstr(); 
    574   if (key_data.dptr == NULL) { 
    575     if (logout != NULL) (*logout) << "gdbmclass: out of memory\n"; 
    576     return false; 
    577   } 
    578   key_data.dsize = strlen (key_data.dptr); 
    579    
    580   // fetch the result 
    581   return_data = gdbm_fetch (gdbmfile, key_data); 
    582   delete []key_data.dptr; 
    583    
    584   if (return_data.dptr == NULL) return false; 
    585  
    586   data.setcarr (return_data.dptr, return_data.dsize); 
    587   free (return_data.dptr); 
    588   data = to_uni(data);  // convert to unicode 
    589  
    590   return true; 
    591 } 
    592  
    593  
    594 // returns true on success 
    595 bool gdbmclass::getinfoline (text_t::iterator &here, text_t::iterator end,  
    596                  text_t &key, text_t &value) 
    597 { 
    598   key.clear(); 
    599   value.clear(); 
    600  
    601   // ignore white space 
    602   while (here != end && is_unicode_space (*here)) ++here; 
    603  
    604   // get the '<' 
    605   if (here == end || *here != '<') return false; 
    606   ++here; 
    607    
    608   // get the key 
    609   while (here != end && *here != '>') { 
    610     key.push_back(*here); 
    611     ++here; 
    612   } 
    613    
    614   // get the '>' 
    615   if (here == end || *here != '>') return false; 
    616   ++here; 
    617    
    618   // get the value 
    619   while (here != end && *here != '\n') { 
    620     if (*here == '\\') {  
    621       // found escape character 
    622       ++here; 
    623       if (here != end) { 
    624     if (*here == 'n') value.push_back ('\n'); 
    625     else if (*here == 'r') value.push_back ('\r'); 
    626     else value.push_back(*here); 
    627       } 
    628  
    629     } else { 
    630       // a normal character 
    631       value.push_back(*here); 
    632     } 
    633  
    634     ++here; 
    635   } 
    636  
    637   return true; 
    638 } 
  • gsdl/trunk/lib/infodbclass.h

    r15420 r15429  
    4141#  include <iostream> 
    4242#  include <fstream> 
    43 #endif 
    44  
    45 #ifdef __WIN32__ 
    46  
    47 #ifdef __cplusplus 
    48   extern "C" { 
    49 #endif 
    50 #include "autoconf.h" 
    51 #include "systems.h" 
    52 #include "gdbmconst.h" 
    53 #include "gdbm.h" 
    54 #ifdef __cplusplus 
    55   } 
    56 #endif 
    57  
    58 #else 
    59 #include <gdbm.h> 
    6043#endif 
    6144 
     
    138121 
    139122 
    140 class gdbmclass { 
    141 public: 
    142   gdbmclass() {gdbmfile = NULL; logout = &cerr;}; 
    143   ~gdbmclass(); 
    144    
    145   // returns true if opened 
    146   bool opendatabase (const text_t &filename, int mode, int num_retrys,  
    147              bool need_filelock); 
    148   void closedatabase (); 
    149  
    150   // replaces the .c, .p, .n, .l syntax (child, parent, next, previous)  
    151   // it expects child, parent, etc. to exist if syntax has been used 
    152   // so you should test before using 
    153   text_t translate_OID (const text_t &OID, infodbclass &info); 
    154  
    155   // returns true on success 
    156   bool getinfo (const text_t& key, infodbclass &info); 
    157   void setlogout (ostream *thelogout) {logout = thelogout;} 
    158  
    159   // returns true if exists 
    160   bool exists (const text_t& key); 
    161  
    162   // returns true on success 
    163   bool setinfo (const text_t &key, const infodbclass &info); 
    164   // returns true on success 
    165   bool setinfo (const text_t &key, const text_t &data); 
    166  
    167   void deletekey (const text_t &key); 
    168  
    169   // getfirstkey and getnextkey are used for traversing the database 
    170   // no insertions or deletions should be carried out while traversing 
    171   // the database. when there are no keys left to visit in the database 
    172   // an empty string is returned. 
    173   text_t getfirstkey (); 
    174   text_t getnextkey (const text_t &key); 
    175  
    176     // returns true on success 
    177   bool getkeydata (const text_t& key, text_t &data); 
    178  
    179 protected: 
    180   text_t openfile; 
    181   GDBM_FILE gdbmfile; 
    182   ostream *logout; 
    183  
    184   void get_first_child (text_t &OID, infodbclass &info); 
    185   void get_last_child (text_t &OID, infodbclass &info); 
    186   void get_next_sibling (text_t &OID, infodbclass &info); 
    187   void get_previous_sibling (text_t &OID, infodbclass &info); 
    188  
    189  
    190   // returns true on success 
    191   bool getinfoline (text_t::iterator &here, text_t::iterator end,  
    192            text_t &key, text_t &value); 
    193 }; 
    194  
    195  
    196123#endif 
  • gsdl/trunk/lib/win32.mak

    r15420 r15429  
    7373HEADERS = \ 
    7474  cfgread.h        cnfgable.h       cnfgator.h       display.h \ 
    75   fileutil.h       gsdlsitecfg.h    gsdltimes.h      gsdltools.h \ 
    76   gsdlunicode.h    infodbclass.h    md5.h            OIDtools.h \ 
    77   phrases.h        text_t.h         gsdlconf.h 
     75  fileutil.h       gdbmclass.h      gsdlsitecfg.h    gsdltimes.h \ 
     76  gsdltools.h      gsdlunicode.h    infodbclass.h    md5.h \ 
     77  OIDtools.h       phrases.h        text_t.h         gsdlconf.h 
    7878 
    7979SOURCES = \ 
    8080  cfgread.cpp      cnfgable.cpp     cnfgator.cpp     display.cpp \ 
    81   fileutil.cpp     gsdlsitecfg.cpp  gsdltimes.cpp    gsdltools.cpp \ 
    82   gsdlunicode.cpp  infodbclass.cpp  md5.cpp          OIDtools.cpp \ 
    83   phrases.cpp      text_t.cpp 
     81  fileutil.cpp     gdbmclass.cpp    gsdlsitecfg.cpp  gsdltimes.cpp \ 
     82  gsdltools.cpp    gsdlunicode.cpp  infodbclass.cpp  md5.cpp \ 
     83  OIDtools.cpp     phrases.cpp      text_t.cpp 
    8484 
    8585OBJECTS = \ 
    8686  cfgread.o        cnfgable.o       cnfgator.o       display.o \ 
    87   fileutil.o       gsdlsitecfg.o    gsdltimes.o      gsdltools.o \ 
    88   gsdlunicode.o    infodbclass.o    md5.o            OIDtools.o \ 
    89   phrases.o        text_t.o 
     87  fileutil.o       gdbmclass.o      gsdlsitecfg.o    gsdltimes.o \ 
     88  gsdltools.o      gsdlunicode.o    infodbclass.o    md5.o \ 
     89  OIDtools.o       phrases.o        text_t.o 
     90 
    9091 
    9192all: gsdllib.lib