misc.c
上传用户:ycwykj01
上传日期:2007-01-04
资源大小:1819k
文件大小:10k
源码类别:

网络编程

开发平台:

Unix_Linux

  1. /*
  2.  * Program: Miscellaneous utility routines
  3.  *
  4.  * Author: Mark Crispin
  5.  * Networks and Distributed Computing
  6.  * Computing & Communications
  7.  * University of Washington
  8.  * Administration Building, AG-44
  9.  * Seattle, WA  98195
  10.  * Internet: MRC@CAC.Washington.EDU
  11.  *
  12.  * Date: 5 July 1988
  13.  * Last Edited: 13 January 1999
  14.  *
  15.  * Sponsorship: The original version of this work was developed in the
  16.  * Symbolic Systems Resources Group of the Knowledge Systems
  17.  * Laboratory at Stanford University in 1987-88, and was funded
  18.  * by the Biomedical Research Technology Program of the National
  19.  * Institutes of Health under grant number RR-00785.
  20.  *
  21.  * Original version Copyright 1988 by The Leland Stanford Junior University
  22.  * Copyright 1999 by the University of Washington
  23.  *
  24.  *  Permission to use, copy, modify, and distribute this software and its
  25.  * documentation for any purpose and without fee is hereby granted, provided
  26.  * that the above copyright notices appear in all copies and that both the
  27.  * above copyright notices and this permission notice appear in supporting
  28.  * documentation, and that the name of the University of Washington or The
  29.  * Leland Stanford Junior University not be used in advertising or publicity
  30.  * pertaining to distribution of the software without specific, written prior
  31.  * permission.  This software is made available "as is", and
  32.  * THE UNIVERSITY OF WASHINGTON AND THE LELAND STANFORD JUNIOR UNIVERSITY
  33.  * DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE,
  34.  * INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  35.  * FITNESS FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE UNIVERSITY OF
  36.  * WASHINGTON OR THE LELAND STANFORD JUNIOR UNIVERSITY BE LIABLE FOR ANY
  37.  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
  38.  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
  39.  * CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF
  40.  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  41.  *
  42.  */
  43. #include <ctype.h>
  44. #include "mail.h"
  45. #include "osdep.h"
  46. #include "misc.h"
  47. /* Convert string to all uppercase
  48.  * Accepts: string pointer
  49.  * Returns: string pointer
  50.  */
  51. char *ucase (char *s)
  52. {
  53.   char *t;
  54. /* if lowercase covert to upper */
  55.   for (t = s; *t; t++) if (!(*t & 0x80) && islower (*t)) *t = toupper (*t);
  56.   return s; /* return string */
  57. }
  58. /* Convert string to all lowercase
  59.  * Accepts: string pointer
  60.  * Returns: string pointer
  61.  */
  62. char *lcase (char *s)
  63. {
  64.   char *t;
  65. /* if uppercase covert to lower */
  66.   for (t = s; *t; t++) if (!(*t & 0x80) && isupper (*t)) *t = tolower (*t);
  67.   return s; /* return string */
  68. }
  69. /* Copy string to free storage
  70.  * Accepts: source string
  71.  * Returns: free storage copy of string
  72.  */
  73. char *cpystr (const char *string)
  74. {
  75.   return string ? strcpy ((char *) fs_get (1 + strlen (string)),string) : NIL;
  76. }
  77. /* Copy text/size to free storage as sized text
  78.  * Accepts: destination sized text
  79.  *     pointer to source text
  80.  *     size of source text
  81.  * Returns: text as a char *
  82.  */
  83. char *cpytxt (SIZEDTEXT *dst,char *text,unsigned long size)
  84. {
  85. /* flush old space */
  86.   if (dst->data) fs_give ((void **) &dst->data);
  87. /* copy data in sized text */
  88.   memcpy (dst->data = (unsigned char *)
  89.   fs_get ((size_t) (dst->size = size) + 1),text,(size_t) size);
  90.   dst->data[size] = ''; /* tie off text */
  91.   return (char *) dst->data; /* convenience return */
  92. }
  93. /* Copy sized text to free storage as sized text
  94.  * Accepts: destination sized text
  95.  *     source sized text
  96.  * Returns: text as a char *
  97.  */
  98. char *textcpy (SIZEDTEXT *dst,SIZEDTEXT *src)
  99. {
  100. /* flush old space */
  101.   if (dst->data) fs_give ((void **) &dst->data);
  102. /* copy data in sized text */
  103.   memcpy (dst->data = (unsigned char *)
  104.   fs_get ((size_t) (dst->size = src->size) + 1),
  105.   src->data,(size_t) src->size);
  106.   dst->data[dst->size] = ''; /* tie off text */
  107.   return (char *) dst->data; /* convenience return */
  108. }
  109. /* Copy stringstruct to free storage as sized text
  110.  * Accepts: destination sized text
  111.  *     source stringstruct
  112.  * Returns: text as a char *
  113.  */
  114. char *textcpystring (SIZEDTEXT *text,STRING *bs)
  115. {
  116.   unsigned long i = 0;
  117. /* clear old space */
  118.   if (text->data) fs_give ((void **) &text->data);
  119. /* make free storage space in sized text */
  120.   text->data = (unsigned char *) fs_get ((size_t) (text->size = SIZE (bs)) +1);
  121.   while (i < text->size) text->data[i++] = SNX (bs);
  122.   text->data[i] = ''; /* tie off text */
  123.   return (char *) text->data; /* convenience return */
  124. }
  125. /* Copy stringstruct from offset to free storage as sized text
  126.  * Accepts: destination sized text
  127.  *     source stringstruct
  128.  *     offset into stringstruct
  129.  *     size of source text
  130.  * Returns: text as a char *
  131.  */
  132. char *textcpyoffstring (SIZEDTEXT *text,STRING *bs,unsigned long offset,
  133. unsigned long size)
  134. {
  135.   unsigned long i = 0;
  136. /* clear old space */
  137.   if (text->data) fs_give ((void **) &text->data);
  138.   SETPOS (bs,offset); /* offset the string */
  139. /* make free storage space in sized text */
  140.   text->data = (unsigned char *) fs_get ((size_t) (text->size = size) + 1);
  141.   while (i < size) text->data[i++] = SNX (bs);
  142.   text->data[i] = ''; /* tie off text */
  143.   return (char *) text->data; /* convenience return */
  144. }
  145. /* Returns index of rightmost bit in word
  146.  * Accepts: pointer to a 32 bit value
  147.  * Returns: -1 if word is 0, else index of rightmost bit
  148.  *
  149.  * Bit is cleared in the word
  150.  */
  151. unsigned long find_rightmost_bit (unsigned long *valptr)
  152. {
  153.   unsigned long value = *valptr;
  154.   unsigned long bit = 0;
  155.   if (!(value & 0xffffffff)) return 0xffffffff;
  156. /* binary search for rightmost bit */
  157.   if (!(value & 0xffff)) value >>= 16, bit += 16;
  158.   if (!(value & 0xff)) value >>= 8, bit += 8;
  159.   if (!(value & 0xf)) value >>= 4, bit += 4;
  160.   if (!(value & 0x3)) value >>= 2, bit += 2;
  161.   if (!(value & 0x1)) value >>= 1, bit += 1;
  162.   *valptr ^= (1 << bit); /* clear specified bit */
  163.   return bit;
  164. }
  165. /* Return minimum of two integers
  166.  * Accepts: integer 1
  167.  *     integer 2
  168.  * Returns: minimum
  169.  */
  170. long min (long i,long j)
  171. {
  172.   return ((i < j) ? i : j);
  173. }
  174. /* Return maximum of two integers
  175.  * Accepts: integer 1
  176.  *     integer 2
  177.  * Returns: maximum
  178.  */
  179. long max (long i,long j)
  180. {
  181.   return ((i > j) ? i : j);
  182. }
  183. /* Search, case-insensitive for ASCII characters
  184.  * Accepts: base string
  185.  *     length of base string
  186.  *     pattern string
  187.  *     length of pattern string
  188.  * Returns: T if pattern exists inside base, else NIL
  189.  */
  190. long search (unsigned char *base,long basec,unsigned char *pat,long patc)
  191. {
  192.   long i,j,k;
  193.   int c;
  194.   unsigned char mask[256];
  195.   static unsigned char alphatab[256] = {
  196.     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  197.     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  198.     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  199.     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  200.     255,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,
  201.     223,223,223,223,223,223,223,223,223,223,223,255,255,255,255,255,
  202.     255,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,
  203.     223,223,223,223,223,223,223,223,223,223,223,255,255,255,255,255,
  204.     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  205.     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  206.     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  207.     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  208.     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  209.     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  210.     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  211.     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
  212.     };
  213. /* validate arguments */
  214.   if (base && (basec > 0) && pat && (basec >= patc)) {
  215.     if (patc <= 0) return T; /* empty pattern always succeeds */
  216.     memset (mask,0,256); /* initialize search validity mask */
  217.     for (i = 0; i < patc; i++) if (!mask[c = pat[i]]) {
  218. /* mark single character if non-alphabetic */
  219.       if (alphatab[c] & 0x20) mask[c] = T;
  220. /* else mark both cases */
  221.       else mask[c & 0xdf] = mask[c | 0x20] = T;
  222.     }
  223. /* Boyer-Moore type search */
  224.     for (i = --patc; i < basec; i += (mask[c] ? 1 : (j + 1)))
  225.       for (j = patc,c = base[k = i]; !((c ^ pat[j]) & alphatab[c]);
  226.    j--,c = base[--k])
  227. if (!j) return T; /* found a match! */
  228.   }
  229.   return NIL; /* pattern not found */
  230. }
  231. /* Wildcard pattern match
  232.  * Accepts: base string
  233.  *     pattern string
  234.  *     delimiter character
  235.  * Returns: T if pattern matches base, else NIL
  236.  */
  237. long pmatch_full (char *s,char *pat,char delim)
  238. {
  239.   switch (*pat) {
  240.   case '%': /* non-recursive */
  241. /* % at end, OK if no inferiors */
  242.     if (!pat[1]) return (delim && strchr (s,delim)) ? NIL : T;
  243.                                 /* scan remainder of string until delimiter */
  244.     do if (pmatch_full (s,pat+1,delim)) return T;
  245.     while ((*s != delim) && *s++);
  246.     break;
  247.   case '*': /* match 0 or more characters */
  248.     if (!pat[1]) return T; /* * at end, unconditional match */
  249. /* scan remainder of string */
  250.     do if (pmatch_full (s,pat+1,delim)) return T;
  251.     while (*s++);
  252.     break;
  253.   case '': /* end of pattern */
  254.     return *s ? NIL : T; /* success if also end of base */
  255.   default: /* match this character */
  256.     return (*pat == *s) ? pmatch_full (s+1,pat+1,delim) : NIL;
  257.   }
  258.   return NIL;
  259. }
  260. /* Directory pattern match
  261.  * Accepts: base string
  262.  *     pattern string
  263.  *     delimiter character
  264.  * Returns: T if base is a matching directory of pattern, else NIL
  265.  */
  266. long dmatch (char *s,char *pat,char delim)
  267. {
  268.   switch (*pat) {
  269.   case '%': /* non-recursive */
  270.     if (!*s) return T; /* end of base means have a subset match */
  271.     if (!*++pat) return NIL; /* % at end, no inferiors permitted */
  272. /* scan remainder of string until delimiter */
  273.     do if (dmatch (s,pat,delim)) return T;
  274.     while ((*s != delim) && *s++);
  275.     if (*s && !s[1]) return T; /* ends with delimiter, must be subset */
  276.     return dmatch (s,pat,delim);/* do new scan */
  277.   case '*': /* match 0 or more characters */
  278.     return T; /* unconditional match */
  279.   case '': /* end of pattern */
  280.     break;
  281.   default: /* match this character */
  282.     if (*s) return (*pat == *s) ? dmatch (s+1,pat+1,delim) : NIL;
  283. /* end of base, return if at delimiter */
  284.     else if (*pat == delim) return T;
  285.     break;
  286.   }
  287.   return NIL;
  288. }