home *** CD-ROM | disk | FTP | other *** search
/ Internet Publisher's Toolbox 2.0 / Internet Publisher's Toolbox.iso / internet / ntserver / wtsource / cutil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-05  |  29.5 KB  |  1,157 lines

  1.  
  2. /* Copyright (c) CNIDR (Work in progress) */
  3.  
  4. /* Wide AREA INFORMATION SERVER SOFTWARE        
  5.    No guarantees or restrictions.  See the readme file for the full standard
  6.    disclaimer.  
  7.   
  8.    3.26.90      Harry Morris, morris@think.com
  9.    4.11.90  HWM - generalized conditional includes (see c-dialect.h)
  10.    7/19/91  speed up substrcmp by ses@ccgr.technion.ac.il (Simon E Spero)
  11.  *
  12.  * $Log: cutil.c,v $
  13.  * Revision 1.9  1993/09/22  16:07:52  pfeifer
  14.  * Fixed word breaking for german ISO Umlaute and sz
  15.  *
  16.  * Revision 1.8  1993/07/16  12:10:19  huynh1
  17.  * Function generate_newline_for_boolean deleted!
  18.  *
  19.  * Revision 1.7  1993/07/14  09:52:38  huynh1
  20.  * keine "Anderung!
  21.  *
  22.  * Revision 1.6  1993/07/14  07:30:24  huynh1
  23.  * "Anderung in der Funktion generate_newline_for_boolean: Variable umbenannt: brackets = parentheses!
  24.  *
  25.  * Revision 1.5  1993/07/13  19:14:43  huynh1
  26.  * printf(".....") gel"oscht!
  27.  *
  28.  * Revision 1.4  1993/07/13  18:44:04  huynh1
  29.  * Keine "Anderung!
  30.  *
  31.  * Revision 1.3  1993/07/13  18:40:31  huynh1
  32.  * funktion generate_newline_for_boolean eingef"ugt!
  33.  *
  34.  * Revision 1.2  1993/02/16  14:59:21  freewais
  35.  * include stdargs.h or varargs.h based on whether compiler
  36.  * is ansi or non-ansi
  37.  *
  38.  * Revision 1.1  1993/02/16  14:53:14  freewais
  39.  * Initial revision
  40.  *
  41.  * Revision 1.24  92/03/28  19:53:39  jonathan
  42.  * Removed useless ifdef BSD in cprintf
  43.  * 
  44.  * Revision 1.23  92/03/07  19:44:39  jonathan
  45.  * ANSIfied arguments.
  46.  * 
  47.  * Revision 1.22  92/03/04  16:14:23  jonathan
  48.  * Added include <ctype.h> for isalnum.
  49.  * 
  50.  * Revision 1.21  92/02/21  11:03:15  jonathan
  51.  * Fixed $Log.
  52.  * 
  53.  * Revision 1.20  92/02/21  11:02:02  jonathan
  54.  * Added wais_log_level, RCSIdent
  55.  * 
  56.  * Revision 1.19  92/02/16  21:24:54  jonathan
  57.  * Added code for vprintf, if needed (like for old BSD).
  58.  * 
  59.  * Revision 1.18  92/02/12  14:33:26  morris
  60.  * made string_downcase not die when passed NULL
  61.  * 
  62.  * Revision 1.17  92/02/12  13:16:21  jonathan
  63.  * Added $Log so RCS will put the log message in the header
  64.  * 
  65.  *
  66. */
  67.  
  68. #ifndef lint
  69. static char *RCSid = "$Header: /usr/local/ls63/pfeifer/freeWAIS-0.1-s/ir/RCS/cutil.c,v 1.9 1993/09/22 16:07:52 pfeifer Exp $";
  70. #endif
  71.  
  72. #define _C_C_util_
  73.  
  74. #include "cutil.h"
  75. #include "panic.h"
  76.  
  77. #include <ctype.h>
  78. #include <string.h>
  79.  
  80. #if defined (ANSI_LIKE) || defined(PROTO_ANSI)
  81. #include <stdarg.h>
  82. #else
  83. #include <varargs.h>
  84. #endif
  85.  
  86. #ifdef USE_SYSLOG
  87. #include <syslog.h>
  88. #endif
  89.  
  90. #ifdef M_XENIX /* perhaps this should be in ustubs.h */
  91. #include <malloc.h>
  92. char* calloc();
  93. #endif /* def M_XENIX */
  94.  
  95. #ifdef sgi
  96. #include <sys/types.h>
  97. #include <malloc.h>
  98. #endif /* sgi */
  99.  
  100. /*----------------------------------------------------------------------*/
  101.  
  102. /* #define MEMORY_ACCOUNTING */
  103.  
  104. #ifdef MEMORY_ACCOUNTING
  105. #include "futil.h"
  106. #undef s_checkPtr
  107. #define s_checkPtr(ptr) fs_checkPtr(ptr)
  108. static FILE* memRecord = NULL;
  109. static void prepMemAcct _AP((void));
  110. static void 
  111. prepMemAcct()
  112. {
  113.   if (memRecord == NULL)
  114.     memRecord = s_fopen("MemoryAccounting","w");
  115. }
  116. static void flushMemAcct _AP((void));
  117. static void 
  118. flushMemAcct()
  119. {
  120.   fflush(memRecord);
  121. }
  122. #define tickles 0
  123. static char*    badPtr  = (char*)-1;
  124. static size_t   badSize = -1;
  125. #endif /* def MEMORY_ACCOUNTING */
  126.  
  127. /*----------------------------------------------------------------------*/
  128.  
  129. void
  130. fs_checkPtr(ptr)
  131. void* ptr;
  132. /* If the ptr is NULL, give an error */
  133. #ifdef MEMORY_ACCOUNTING
  134. static char** ptrs = NULL;
  135. long i;
  136. static Boolean  doneSetup = false;
  137. if (doneSetup == false)
  138. {
  139. #ifdef THINK_C
  140. Debugger();
  141. #endif /* def THINK_C */
  142. doneSetup = true;
  143. }
  144. #endif /* def MEMORY_ACCOUNTING */
  145.  
  146.   if (ptr == NULL)
  147.     panic("checkPtr found a NULL pointer");
  148.  
  149. #ifdef MEMORY_ACCOUNTING
  150. /* look for specific ptr (useful when tracking un-freed memory) */
  151. if (ptr == badPtr) warn("checking found bad ptr"); 
  152. /* tickle a memory bug */
  153. if (ptrs == NULL && tickles > 0)
  154.   ptrs = (char**)malloc((size_t)tickles * sizeof(char*));
  155. for (i = 0; i < tickles; i++)
  156. { ptrs[i] = malloc((size_t)5);
  157. }
  158. for (i = 0; i < tickles; i++)
  159. { free(ptrs[i]);
  160. }
  161. #endif /* def MEMORY_ACCOUNTING */
  162.  
  163. }
  164.  
  165. /*----------------------------------------------------------------------*/
  166.  
  167. void*
  168. fs_malloc(size)
  169. size_t size;
  170. /* does safety checks and optional accounting */
  171.   register void* ptr = NULL;
  172.  
  173.   if(!size) return(NULL);
  174.  
  175. #ifdef THINK_C
  176.   ptr = (void*)NewPtr((long)size);
  177.   s_checkPtr(ptr);
  178.   memset(ptr,0,(size_t)size);   /* zero it */
  179. #else  
  180.   ptr = NULL;
  181.   ptr = (void*)calloc((size_t)size,(size_t)1);
  182.   s_checkPtr(ptr);
  183. #endif
  184.   
  185. #ifdef MEMORY_ACCOUNTING
  186.   /* look for specific size (useful when tracking un-freed memory) */
  187.   if (size == badSize)
  188.     warn("bad size in malloc");
  189.   
  190.   prepMemAcct();
  191.   fprintf(memRecord,"malloced %lu bytes at %lu\n",size,ptr);
  192.   flushMemAcct();
  193. #endif
  194.  
  195.   return(ptr);
  196. }
  197.  
  198. /*----------------------------------------------------------------------*/
  199.  
  200. void*
  201. fs_realloc(ptr,size)
  202. void* ptr;
  203. size_t size;
  204. /* does safety checks and optional accounting 
  205.    note - we don't know how big ptr's memory is, so we can't ensure
  206.    that any new memory allocated is NULLed!
  207.  */
  208.   register void* nptr = NULL;
  209.   
  210.   if (ptr == NULL)              /* this is really a malloc */
  211.     return(s_malloc(size));
  212.     
  213. #ifdef THINK_C
  214.   nptr = NewPtr(size);          /* need to make a copy */ 
  215.   s_checkPtr(nptr);
  216.   BlockMove(ptr,nptr,size);     /* move the old contents into it */
  217.   DisposPtr(ptr);                   /* get rid of the old ones */
  218. #else
  219.   nptr = (void*)realloc(ptr,size);
  220.   s_checkPtr(ptr);
  221. #endif  
  222.    
  223. #ifdef MEMORY_ACCOUNTING
  224.   /* look for specific size (useful when tracking un-freed memory) */
  225.   if (size == badSize) 
  226.     warn("bad size in realloc");
  227.   
  228.   prepMemAcct();
  229.   fprintf(memRecord,"realloced %lu bytes at %lu from %lu\n",size,nptr,ptr);
  230.   flushMemAcct();
  231. #endif
  232.  
  233.   return(nptr);
  234. }
  235.  
  236. /*----------------------------------------------------------------------*/
  237.  
  238. void
  239. fs_free(ptr)
  240. void* ptr;
  241. /* does safety checks and optional accounting */
  242. {
  243. #ifdef MEMORY_ACCOUNTING
  244.   prepMemAcct();
  245.   /* note that the sizeof a pointer is always 4.  If only we could find out
  246.      how much space that pointer was pointing to.  Oh well, this is a place
  247.      holder for now
  248.    */
  249.   fprintf(memRecord,"freed %lu bytes at %lu\n",(size_t)sizeof(ptr),ptr);
  250.   flushMemAcct();
  251.  
  252.   /* look for specific ptr (useful when tracking un-freed memory) */
  253.   if (ptr == badPtr) warn("bad ptr in free");
  254. #endif
  255.  
  256.   if (ptr != NULL)              /* some non-ansi compilers/os's cant handle freeing null */
  257.     {                           /* if we knew the size of this block of memory, we could clear it - oh well */
  258. #ifdef THINK_C
  259.       DisposPtr(ptr);
  260. #else
  261.       free(ptr);
  262. #endif
  263.     }
  264. }
  265.  
  266. /*----------------------------------------------------------------------*/
  267.  
  268. char*
  269. s_strdup(s)
  270. char* s;
  271.  
  272. /* return a copy of s.  This is identical to the standard library routine
  273.    strdup(), except that it is safe.  If s == NULL or malloc fails, 
  274.    appropriate action is taken.
  275.  */
  276. {
  277.   unsigned long len;
  278.   char* copy = NULL;
  279.   
  280.   if (s == NULL)                /* saftey check to postpone stupid errors */
  281.     return(NULL);
  282.     
  283.   len = strlen(s);              /* length of string - terminator */
  284.   copy = (char*)s_malloc((size_t)(sizeof(char)*(len + 1)));
  285.   strncpy(copy,s,len + 1);
  286.   return(copy);
  287. }
  288.  
  289. /*----------------------------------------------------------------------*/
  290.  
  291. char*
  292. fs_strncat(dst,src,maxToAdd,maxTotal)
  293. char* dst;
  294.    char* src;
  295.    size_t maxToAdd;
  296.    size_t maxTotal;
  297.  
  298. /* like strncat, except the fourth argument limits the maximum total 
  299.    length of the resulting string
  300.  */
  301. {
  302.   size_t dstSize = strlen(dst);
  303.   size_t srcSize = strlen(src);
  304.   
  305.   if (dstSize + srcSize < maxTotal) /* use regular old strncat */
  306.     return(strncat(dst,src,maxToAdd));
  307.   else
  308.     { size_t truncateTo = maxTotal - dstSize - 1;
  309.       char   saveChar;
  310.       char*  result = NULL;
  311.  
  312.       saveChar = src[truncateTo];
  313.       src[truncateTo] = '\0';
  314.       result = strncat(dst,src,maxToAdd);
  315.       src[truncateTo] = saveChar;
  316.       return(result);
  317.     }
  318. }
  319.  
  320. /*----------------------------------------------------------------------*/
  321.  
  322. char*
  323. fs_strncpy(s1, s2, n)
  324.      char* s1;
  325.      char* s2;
  326.      long n;
  327. /* like strncpy except that it guarentees that the destination string ends with a NULL at position n.
  328.  */
  329. {
  330.   s1[n-1] = '\0';
  331.   return(strncpy(s1, s2, n - 1));
  332. }
  333.  
  334. /*----------------------------------------------------------------------*/
  335.  
  336. boolean 
  337.  
  338. wordbreak_isiso(c)              /* dgg */
  339. long   c;
  340. {   
  341.   c &= 0xFF;
  342.   return((c == 0304) || (c == 0344) || (c == 0334) ||
  343.          (c == 0366) || (c == 0326) || (c == 0374) || (c == 0337));
  344. }
  345.  
  346. boolean 
  347. wordbreak_notalnum(ch)          /* dgg */
  348. long   ch;
  349. {   
  350.     return( !isalnum(ch) && !wordbreak_isiso(ch));
  351. }
  352.  
  353. boolean 
  354. wordbreak_notgraph(ch)          /* dgg */
  355. long   ch;
  356. {   
  357.     return( !isgraph(ch) && !wordbreak_isiso(ch));
  358. }
  359.  
  360. boolean wordbreak_user(c)
  361. long c;
  362. {
  363.   if ( (gDelimiters[0] != '\0') && (strchr(gDelimiters, (char) c) != NULL) )
  364.     return(IS_DELIMITER);  
  365.   else if (isgraph(c)||wordbreak_isiso(c))
  366.     return(NOT_DELIMITER);
  367.   else
  368.     return(IS_DELIMITER);
  369. }
  370.  
  371. typedef boolean (boolfunc) _AP((long c));
  372.  
  373. char*
  374. strtokf(s1,isDelimiter)
  375. char* s1;
  376. boolfunc *isDelimiter; /* really *isDelimiter() */
  377.  
  378. /* This function is exactly like strtok, except that instead of passing a 
  379.    delimiter string, you pass a function that decides if a character is 
  380.    a delimiter or not, returning IS_DELIMITER or NOT_DELIMITER respecively.
  381.    Note that passing a NULL delimiter function will cause the last delimiter
  382.    to be used.
  383.  */
  384. {
  385.   static char* searchStr = NULL;
  386.   static boolfunc *delimiterFunc;
  387.   long i;
  388.   char* startTok = NULL;
  389.  
  390.   if (s1 != NULL)               /* passing s1 = NULL says use the last pos */
  391.     searchStr = s1;
  392.     
  393.   if (isDelimiter != NULL)
  394.     delimiterFunc = isDelimiter;
  395.    
  396.   if (searchStr == NULL || searchStr[0] == '\0')
  397.     return(NULL);               /* nothing left to search */
  398.     
  399.   if (delimiterFunc == NULL)
  400.     return(NULL);               /* no delimiter to search with */
  401.     
  402.   /* find the start of the next token */
  403.   for (i = 0; searchStr[i] != '\0'; i++)
  404.     { if ((*delimiterFunc)((long)searchStr[i]) == NOT_DELIMITER)
  405.         break;
  406.     }
  407.   
  408.   if (searchStr[i] == '\0') 
  409.     return(NULL);               /* read to end of search string */
  410.   else
  411.     startTok = searchStr + i;   /* remember the starting point for this token*/
  412.     
  413.   /* find the end of the next token */
  414.   for (; searchStr[i] != '\0'; i++)
  415.     { if ((*delimiterFunc)((long)searchStr[i]) == IS_DELIMITER)
  416.         break;
  417.     }
  418.    
  419.   /* if the end is a delimiter (and not just the end of the search string)
  420.      replace it with '\0', and put searchStr just beyond it, otherwise
  421.      put searchStr at the terminator. */
  422.   if (searchStr[i] != '\0')
  423.     { searchStr[i] = '\0';
  424.       searchStr = searchStr + i + 1;
  425.     }
  426.   else
  427.     searchStr = searchStr + i;
  428.    
  429.   return(startTok);
  430. }
  431.  
  432. /*----------------------------------------------------------------------*/
  433.  
  434. char*
  435. strtokf_isalnum(s1)
  436. char* s1;
  437.  
  438. /* 
  439.   This is a partially evaluated version of strtok_f
  440.  */
  441. {
  442.   static char* searchStr = NULL;
  443.   long i;
  444.   char* startTok = NULL;
  445.  
  446.   if (s1 != NULL)               /* passing s1 = NULL says use the last pos */
  447.     searchStr = s1;
  448.     
  449.    
  450.   if (searchStr == NULL || searchStr[0] == '\0')
  451.     return(NULL);               /* nothing left to search */
  452.     
  453.     
  454.   /* find the start of the next token */
  455.   for (i = 0; searchStr[i] != '\0'; i++)
  456.     { if (isalnum(searchStr[i])||wordbreak_isiso(searchStr[i]))
  457.         break;
  458.     }
  459.   
  460.   if (searchStr[i] == '\0') 
  461.     return(NULL);               /* read to end of search string */
  462.   else
  463.     startTok = searchStr + i;   /* remember the starting point for this token*/
  464.     
  465.   /* find the end of the next token */
  466.   for (; searchStr[i] != '\0'; i++)
  467.     { if (!isalnum(searchStr[i])&&!wordbreak_isiso(searchStr[i]))
  468.         break;
  469.     }
  470.    
  471.   /* if the end is a delimiter (and not just the end of the search string)
  472.      replace it with '\0', and put searchStr just beyond it, otherwise
  473.      put searchStr at the terminator. */
  474.   if (searchStr[i] != '\0')
  475.     { searchStr[i] = '\0';
  476.       searchStr = searchStr + i + 1;
  477.     }
  478.   else
  479.     searchStr = searchStr + i;
  480.    
  481.   return(startTok);
  482. }
  483.  
  484. /*----------------------------------------------------------------------*/
  485.  
  486. #ifdef ANSI_LIKE /* use ansi varargs */
  487.  
  488. long
  489. cprintf(boolean print, char* format, ...)
  490. /* just like printf, but only prints if the first argument = 1 */
  491. {
  492.   va_list ap;                   /* the variable arguments */
  493.   if (print == 1)
  494.     { long res;
  495.       va_start(ap,format);      /* init ap */
  496.       res = vprintf(format,ap); /* print the contents */
  497.       va_end(ap);               /* free ap */
  498.       return(res);
  499.     }
  500.   else
  501.     return(0);
  502. }
  503.  
  504. #else /* use k&r varargs */
  505.  
  506. long
  507. cprintf(va_alist)
  508. va_dcl
  509. /* just like printf, but only prints if the first argument = 1 */
  510. {
  511.   va_list ap;                   /* the variable arguments */
  512.   boolean print;
  513.   long res;
  514.  
  515.   va_start(ap);                 /* init ap */
  516.  
  517.   print = va_arg(ap,boolean);   /* get the condition */
  518.  
  519.   if (print == 1)
  520.     { char* format = va_arg(ap,char*); /* get the format */
  521.       res = vprintf(format,ap); /* print the contents */
  522.     }
  523.   else
  524.     res = 0;
  525.  
  526.   va_end(ap);                   /* free ap */
  527.  
  528.   return(res);
  529. }
  530.  
  531.   
  532. #endif
  533.  
  534. extern FILE* logfile;
  535.  
  536. /* waislog - a new and improved logging facility.
  537.    first two arguments are important, the rest is text.
  538.  
  539.    arg1: priority.  If priority > log_level (some global), output this
  540.    message
  541.  
  542.    arg2: message code.  This is the kind of message (search, retrieval, etc).
  543. */
  544.  
  545. char *syslog_name = 0;
  546.   
  547. void
  548. #ifdef ANSI_LIKE
  549. waislog(long priority, long message, char *format, ...)
  550. #else
  551. waislog(va_alist)
  552. va_dcl
  553. #endif
  554.   {
  555.   va_list ap;
  556. #ifndef ANSI_LIKE
  557.   int priority, message;
  558.   char *format;
  559.   
  560.   va_start(ap);
  561.   priority = va_arg(ap, int);
  562.   message = va_arg(ap, int);
  563.   format = va_arg(ap, char *);
  564.   vwaislog(priority, message, format, ap);
  565.   va_end(ap);
  566. #else
  567.   va_start(ap, format);
  568.   vwaislog(priority, message, format, ap);
  569.   va_end(ap);
  570. #endif
  571.   }
  572.   
  573.   void
  574. #ifdef ANSI_LIKE /* use ansi varargs */
  575. vwaislog(long priority, long message, char* format, va_list ap)
  576. #else
  577. vwaislog(priority, message, format, ap)
  578. long priority, message;
  579. char *format;   
  580. va_list ap;
  581. #endif /* ANSI_LIKE */
  582.   /* just like printf, but prints to the logfile, with PID and time. */
  583.   {
  584.   static boolean in_vwaislog; /* to avoid reentrancy problems if */
  585.                               /* s_malloc fails and calls panic() */
  586.   
  587. #ifdef USE_SYSLOG
  588.   static boolean opened = 0;
  589. #endif
  590.   
  591.   in_vwaislog++;
  592.   
  593. #ifdef USE_SYSLOG
  594.   if (syslog_name && !opened) {
  595.     openlog(syslog_name, LOG_PID, LOG_WAIS);
  596.     opened = 1;
  597.   }
  598. #endif
  599.   
  600.   if(priority <= wais_log_level) {
  601.   
  602. #ifdef USE_SYSLOG
  603.     if (! opened) {
  604. #endif
  605.       if(logfile == NULL && log_file_name != NULL)
  606.         logfile = fopen(log_file_name, "a");
  607.   
  608.       if(logfile) {
  609.   
  610.         fprintf(logfile, "%d: %d: %s: %d: ", wais_pid, log_line++,
  611.                 printable_time(), message);
  612.   
  613.         vfprintf(logfile, format,ap); /* print the contents */
  614.         fprintf(logfile, "\n");
  615.         fflush(logfile);
  616.       }
  617.  
  618.       if(logfile != NULL && logfile != stderr) {
  619.         fclose(logfile);
  620.         logfile = NULL;
  621.       }
  622. #ifdef USE_SYSLOG
  623.     }
  624.     else {
  625.       int log_priority;
  626.       char log_buf[512];
  627.       static int buffer_size;
  628.       static char *buffer;
  629.       char *use_buffer;
  630.       int format_size = strlen(format);
  631.  
  632.       /*
  633.        * All of this grungy code is to allow us to use s_malloc or
  634.        * s_realloc to allocate enough space for the message buffers,
  635.        * while at the same time not getting into an infinite loop if
  636.        * s_malloc or s_realloc fails and calls panic.
  637.        */
  638.   
  639.       if ((in_vwaislog > 1) || (format_size <= sizeof(log_buf) - 20)) {
  640.         use_buffer = log_buf;
  641.       }
  642.       else {
  643.         if (format_size + 20 > buffer_size) {
  644.           buffer_size = format_size + 20;
  645.           if (! buffer) {
  646.             buffer = s_malloc(buffer_size);
  647.           }
  648.           else {
  649.             buffer = s_realloc(buffer, buffer_size);
  650.           }
  651.         }
  652.         use_buffer = buffer;
  653.       }
  654.  
  655.       if (message < 0) {
  656.            /* Error message or warning */
  657.            if (priority >= 9) {
  658.                 log_priority = LOG_NOTICE;
  659.            }
  660.            else if (priority >= 5) {
  661.                 log_priority = LOG_WARNING;
  662.            }
  663.            else {
  664.                 priority = LOG_ERR;
  665.            }
  666.       }
  667.       else {
  668.            switch (priority) {
  669.            case 1:
  670.            case 2:
  671.            case 3:
  672.                 log_priority = LOG_NOTICE;
  673.                 break;
  674.            case 4:
  675.            case 5:
  676.            case 6:
  677.                 log_priority = LOG_INFO;
  678.                 break;
  679.            default:
  680.                 log_priority = LOG_DEBUG;
  681.                 break;
  682.            }
  683.       }
  684.       
  685.       sprintf(use_buffer, "%d: %s", message, format);
  686.       vsyslog(log_priority, use_buffer, ap);
  687.       }
  688. #endif /* USE_SYSLOG */
  689.     }
  690.   
  691.   in_vwaislog--;
  692. }
  693.     
  694.   /*----------------------------------------------------------------------*/
  695.  
  696. void
  697. warn(message)
  698. char* message;
  699.  
  700. {
  701. #ifdef THINK_C
  702.   Debugger();
  703. #else
  704.   printf("%s\n<press return to continue>\n",message);
  705.   getchar();
  706. #endif
  707. }
  708.  
  709. /*----------------------------------------------------------------------*/
  710. boolean substrcmp(string1,string2)
  711. char *string1, *string2;
  712. {
  713.   /* compares the strings up until one of then ends.
  714.    * returns true if they are the same, false if not.
  715.    */
  716.   register char *a, *b;
  717.   
  718.   a = string1;
  719.   b = string2;
  720.   
  721.   while (*a && *b) 
  722.     if(*a++ != *b++) 
  723.       return false;
  724.   return true;
  725. }
  726.  
  727. /*----------------------------------------------------------------------*/
  728.  
  729. char *printable_time()
  730.   static char *string;
  731.   time_t tptr;
  732.   time(&tptr);
  733.   string = ctime(&tptr);
  734.   if(string){
  735.     if(string[strlen(string)-1] == '\n')
  736.       string[strlen(string)-1] = '\0';   
  737.     return(string+4);
  738.   }
  739.   else
  740.     return("Time Unknown");
  741. }
  742.  
  743. /*----------------------------------------------------------------------*/
  744.  
  745. char char_downcase(long_ch)
  746. unsigned long long_ch;
  747. {
  748. #ifdef WIN32
  749.   unsigned char ch = (char)(long_ch & 0xFF); /* just want one byte */
  750. #else
  751.   unsigned char ch = long_ch & 0xFF; /* just want one byte */
  752. #endif
  753.   /* when ansi is the way of the world, this can be tolower */
  754.   return (((ch >= 'A') && (ch <= 'Z')) ? (ch + 'a' -'A') : ch);
  755. }
  756.  
  757. char *string_downcase(word)
  758. char *word;
  759. {
  760.   long i = 0;
  761.  
  762.   if (word == NULL)
  763.     return(NULL);
  764.  
  765.   while(word[i] != '\0')
  766.    { word[i] = char_downcase((unsigned long)word[i]);
  767.      i++;
  768.    }
  769.  
  770.   return(word);
  771. }
  772.  
  773. /*----------------------------------------------------------------------*/
  774.  
  775.  
  776. /* parsing arguments functions */
  777.  
  778. char *next_arg(argc,argv)
  779. int *argc;
  780. char ***argv;
  781.  
  782.      /* Returns NULL when it is out of arguments,
  783.         This side effects both argc and argv.  argc always contains the number
  784.         of arguments left.
  785.         The first returned is the command name. 
  786.         */
  787. {
  788.   if((*argc)-- > 0)
  789.     return(*((*argv)++));
  790.   else
  791.     return(NULL);
  792. }
  793.  
  794. /*----------------------------------------------------------------------*/
  795.  
  796. char *peek_arg(argc,argv)
  797. int *argc;
  798.     char ***argv;
  799.  
  800.      /* Returns the next argument without popping it.
  801.        Returns NULL when it is out of arguments.
  802.        */
  803. {
  804.   if((*argc) > 0)
  805.     return(**argv);
  806.   else
  807.     return(NULL);
  808. }
  809.  
  810. /*----------------------------------------------------------------------*/
  811.  
  812.  
  813. #ifdef THINK_C
  814. #include <EventMgr.h>
  815. #undef MAX_FILE_NAME_LEN 
  816. #ifdef WAIStation
  817. #include "CRetrievalApp.h"
  818. #endif /* def WAIStation */
  819. #endif /* def THINK_C */
  820.  
  821. void
  822. beFriendly()
  823. /* this routine is called during time intensive operations
  824.    on single processing machines (macs and DOS).  It gives
  825.    time to other processes
  826.  */
  827. #ifdef never
  828. #ifdef THINK_C
  829.    EventRecord          macEvent;       /* an event */
  830.  
  831.    static RgnHandle     mouseRgn = NULL; /* region for mouse moved events */
  832.    long                 sleepTime;      /* max time between events */
  833.    
  834. #ifdef WAIStation
  835.    gApplication->FrobWaitCursor();
  836. #endif /* def WAIStation */
  837.    
  838.    if (mouseRgn == NULL)
  839.      mouseRgn = NewRgn(); /* do we need to set its value? */
  840.      
  841.    sleepTime = 5; /* arbitrary - a tech note recommends < 50 */
  842.    
  843.    WaitNextEvent(everyEvent,&macEvent,sleepTime,mouseRgn); 
  844. #endif /* def THINK_C */
  845. #endif
  846. }
  847.  
  848.  
  849. #if defined(BSD) || defined(BSD43)
  850. #define NEED_VPRINTF
  851. #endif
  852.  
  853. #ifdef NEED_VPRINTF
  854. /* Portable vsprintf  by Robert A. Larson <blarson@skat.usc.edu> */
  855.  
  856. /* Copyright 1989 Robert A. Larson.
  857.  * Distribution in any form is allowed as long as the author
  858.  * retains credit, changes are noted by their author and the
  859.  * copyright message remains intact.  This program comes as-is
  860.  * with no warentee of fitness for any purpouse.
  861.  *
  862.  * Thanks to Doug Gwen, Chris Torek, and others who helped clarify
  863.  * the ansi printf specs.
  864.  *
  865.  * Please send any bug fixes and improvments to blarson@skat.usc.edu .
  866.  * The use of goto is NOT a bug.
  867.  */
  868.  
  869. /* Feb  7, 1989         blarson         First usenet release */
  870.  
  871. /* This code implements the vsprintf function, without relying on
  872.  * the existance of _doprint or other system specific code.
  873.  *
  874.  * Define NOVOID if void * is not a supported type.
  875.  *
  876.  * Two compile options are available for efficency:
  877.  *      INTSPRINTF      should be defined if sprintf is int and returns
  878.  *                      the number of chacters formated.
  879.  *      LONGINT         should be defined if sizeof(long) == sizeof(int)
  880.  *
  881.  *      They only make the code smaller and faster, they need not be
  882.  *      defined.
  883.  *
  884.  * UNSIGNEDSPECIAL should be defined if unsigned is treated differently
  885.  * than int in argument passing.  If this is definded, and LONGINT is not,
  886.  * the compiler must support the type unsingned long.
  887.  *
  888.  * Most quirks and bugs of the available sprintf fuction are duplicated,
  889.  * however * in the width and precision fields will work correctly
  890.  * even if sprintf does not support this, as will the n format.
  891.  *
  892.  * Bad format strings, or those with very long width and precision
  893.  * fields (including expanded * fields) will cause undesired results.
  894.  */
  895.  
  896. #ifdef OSK              /* os9/68k can take advantage of both */
  897. #define LONGINT
  898. #define INTSPRINTF
  899. #endif
  900.  
  901. /* This must be a typedef not a #define! */
  902. #ifdef NOVOID
  903. typedef char *pointer;
  904. #else
  905. typedef void *pointer;
  906. #endif
  907.  
  908. #ifdef  INTSPRINTF
  909. #define Sprintf(string,format,arg)      (sprintf((string),(format),(arg)))
  910. #else
  911. #define Sprintf(string,format,arg)      (\
  912.         sprintf((string),(format),(arg)),\
  913.         strlen(string)\
  914. )
  915. #endif
  916.  
  917. typedef int *intp;
  918.  
  919. int vsprintf(dest, format, args)
  920. char *dest;
  921. register char *format;
  922. va_list args;
  923. {
  924.     register char *dp = dest;
  925.     register char c;
  926.     register char *tp;
  927.     char tempfmt[64];
  928. #ifndef LONGINT
  929.     int longflag;
  930. #endif
  931.  
  932.     tempfmt[0] = '%';
  933.     while( (c = *format++) != 0) {
  934.         if(c=='%') {
  935.             tp = &tempfmt[1];
  936. #ifndef LONGINT
  937.             longflag = 0;
  938. #endif
  939. continue_format:
  940.             switch(c = *format++) {
  941.                 case 's':
  942.                     *tp++ = c;
  943.                     *tp = '\0';
  944.                     dp += Sprintf(dp, tempfmt, va_arg(args, char *));
  945.                     break;
  946.                 case 'u':
  947.                 case 'x':
  948.                 case 'o':
  949.                 case 'X':
  950. #ifdef UNSIGNEDSPECIAL
  951.                     *tp++ = c;
  952.                     *tp = '\0';
  953. #ifndef LONGINT
  954.                     if(longflag)
  955.                         dp += Sprintf(dp, tempfmt, va_arg(args, unsigned long));
  956.                     else
  957. #endif
  958.                         dp += Sprintf(dp, tempfmt, va_arg(args, unsigned));
  959.                     break;
  960. #endif
  961.                 case 'd':
  962.                 case 'c':
  963.                 case 'i':
  964.                     *tp++ = c;
  965.                     *tp = '\0';
  966. #ifndef LONGINT
  967.                     if(longflag)
  968.                         dp += Sprintf(dp, tempfmt, va_arg(args, long));
  969.                     else
  970. #endif
  971.                         dp += Sprintf(dp, tempfmt, va_arg(args, int));
  972.                     break;
  973.                 case 'f':
  974.                 case 'e':
  975.                 case 'E':
  976.                 case 'g':
  977.                 case 'G':
  978.                     *tp++ = c;
  979.                     *tp = '\0';
  980.                     dp += Sprintf(dp, tempfmt, va_arg(args, double));
  981.                     break;
  982.                 case 'p':
  983.                     *tp++ = c;
  984.                     *tp = '\0';
  985.                     dp += Sprintf(dp, tempfmt, va_arg(args, pointer));
  986.                     break;
  987.                 case '-':
  988.                 case '+':
  989.                 case '0':
  990.                 case '1':
  991.                 case '2':
  992.                 case '3':
  993.                 case '4':
  994.                 case '5':
  995.                 case '6':
  996.                 case '7':
  997.                 case '8':
  998.                 case '9':
  999.                 case '.':
  1000.                 case ' ':
  1001.                 case '#':
  1002.                 case 'h':
  1003.                     *tp++ = c;
  1004.                     goto continue_format;
  1005.                 case 'l':
  1006. #ifndef LONGINT
  1007.                     longflag = 1;
  1008.                     *tp++ = c;
  1009. #endif
  1010.                     goto continue_format;
  1011.                 case '*':
  1012.                     tp += Sprintf(tp, "%d", va_arg(args, int));
  1013.                     goto continue_format;
  1014.                 case 'n':
  1015.                     *va_arg(args, intp) = dp - dest;
  1016.                     break;
  1017.                 case '%':
  1018.                 default:
  1019.                     *dp++ = c;
  1020.                     break;
  1021.             }
  1022.         } else *dp++ = c;
  1023.     }
  1024.     *dp = '\0';
  1025.     return dp - dest;
  1026. }
  1027.  
  1028.  
  1029. int vfprintf(dest, format, args)
  1030. FILE *dest;
  1031. register char *format;
  1032. va_list args;
  1033. {
  1034.     register char c;
  1035.     register char *tp;
  1036.     register int count = 0;
  1037.     char tempfmt[64];
  1038. #ifndef LONGINT
  1039.     int longflag;
  1040. #endif
  1041.  
  1042.     tempfmt[0] = '%';
  1043.     while(c = *format++) {
  1044.         if(c=='%') {
  1045.             tp = &tempfmt[1];
  1046. #ifndef LONGINT
  1047.             longflag = 0;
  1048. #endif
  1049. continue_format:
  1050.             switch(c = *format++) {
  1051.                 case 's':
  1052.                     *tp++ = c;
  1053.                     *tp = '\0';
  1054.                     count += fprintf(dest, tempfmt, va_arg(args, char *));
  1055.                     break;
  1056.                 case 'u':
  1057.                 case 'x':
  1058.                 case 'o':
  1059.                 case 'X':
  1060. #ifdef UNSIGNEDSPECIAL
  1061.                     *tp++ = c;
  1062.                     *tp = '\0';
  1063. #ifndef LONGINT
  1064.                     if(longflag)
  1065.                         count += fprintf(dest, tempfmt, va_arg(args, unsigned long));
  1066.                     else
  1067. #endif
  1068.                         count += fprintf(dest, tempfmt, va_arg(args, unsigned));
  1069.                     break;
  1070. #endif
  1071.                 case 'd':
  1072.                 case 'c':
  1073.                 case 'i':
  1074.                     *tp++ = c;
  1075.                     *tp = '\0';
  1076. #ifndef LONGINT
  1077.                     if(longflag)
  1078.                         count += fprintf(dest, tempfmt, va_arg(args, long));
  1079.                     else
  1080. #endif
  1081.                         count += fprintf(dest, tempfmt, va_arg(args, int));
  1082.                     break;
  1083.                 case 'f':
  1084.                 case 'e':
  1085.                 case 'E':
  1086.                 case 'g':
  1087.                 case 'G':
  1088.                     *tp++ = c;
  1089.                     *tp = '\0';
  1090.                     count += fprintf(dest, tempfmt, va_arg(args, double));
  1091.                     break;
  1092.                 case 'p':
  1093.                     *tp++ = c;
  1094.                     *tp = '\0';
  1095.                     count += fprintf(dest, tempfmt, va_arg(args, pointer));
  1096.                     break;
  1097.                 case '-':
  1098.                 case '+':
  1099.                 case '0':
  1100.                 case '1':
  1101.                 case '2':
  1102.                 case '3':
  1103.                 case '4':
  1104.                 case '5':
  1105.                 case '6':
  1106.                 case '7':
  1107.                 case '8':
  1108.                 case '9':
  1109.                 case '.':
  1110.                 case ' ':
  1111.                 case '#':
  1112.                 case 'h':
  1113.                     *tp++ = c;
  1114.                     goto continue_format;
  1115.                 case 'l':
  1116. #ifndef LONGINT
  1117.                     longflag = 1;
  1118.                     *tp++ = c;
  1119. #endif
  1120.                     goto continue_format;
  1121.                 case '*':
  1122.                     tp += Sprintf(tp, "%d", va_arg(args, int));
  1123.                     goto continue_format;
  1124.                 case 'n':
  1125.                     *va_arg(args, intp) = count;
  1126.                     break;
  1127.                 case '%':
  1128.                 default:
  1129.                     putc(c, dest);
  1130.                     count++;
  1131.                     break;
  1132.             }
  1133.         } else {
  1134.             putc(c, dest);
  1135.             count++;
  1136.         }
  1137.     }
  1138.     return count;
  1139. }
  1140.  
  1141. vprintf(format, args)
  1142. char *format;
  1143. va_list args;
  1144. {
  1145.     return vfprintf(stdout, format, args);
  1146. }
  1147.  
  1148. #endif
  1149.  
  1150.  
  1151. /*----------------------------------------------------------------------*/
  1152.