home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pine / pine3.07 / c-client / misc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-29  |  8.0 KB  |  281 lines

  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:    5 March 1992
  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 1992 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.  
  44.  
  45. #include <ctype.h>
  46. #if unix
  47. #include <sys/types.h>
  48. #endif
  49. #include "osdep.h"
  50. #include "mail.h"
  51. #include "misc.h"
  52.  
  53. /* Convert string to all uppercase
  54.  * Accepts: string pointer
  55.  * Returns: string pointer
  56.  */
  57.  
  58. char *ucase (s)
  59.     char *s;
  60. {
  61.   char c;
  62.   char *ret = s;
  63.                 /* if lowercase covert to upper */
  64.   for (; c = *s; s++) if (islower (c)) *s -= 'a'-'A';
  65.   return (ret);            /* return string */
  66. }
  67.  
  68.  
  69. /* Convert string to all lowercase
  70.  * Accepts: string pointer
  71.  * Returns: string pointer
  72.  */
  73.  
  74. char *lcase (s)
  75.     char *s;
  76. {
  77.   char c;
  78.   char *ret = s;
  79.                 /* if uppercase covert to lower */
  80.   for (; c = *s; s++) if (isupper (c)) *s += 'a'-'A';
  81.   return (ret);            /* return string */
  82. }
  83.  
  84.  
  85. /* Copy string to free storage
  86.  * Accepts: source string
  87.  * Returns: free storage copy of string
  88.  */
  89.  
  90. char *cpystr (string)
  91.     char *string;
  92. {
  93.   if (string) {            /* make sure argument specified */
  94.     char *dst = (char *) fs_get (1+strlen (string));
  95.     strcpy (dst,string);
  96.     return (dst);
  97.   }
  98.   else return NIL;
  99. }
  100.  
  101. /* Returns index of rightmost bit in word
  102.  * Accepts: pointer to a 32 bit value
  103.  * Returns: -1 if word is 0, else index of rightmost bit
  104.  *
  105.  * Bit is cleared in the word
  106.  */
  107.  
  108. long find_rightmost_bit (valptr)
  109.     long *valptr;
  110. {
  111.   register long value= *valptr;
  112.   register long clearbit;    /* bit to clear */
  113.   register bitno;        /* bit number to return */
  114.   if (value == 0) return (-1);    /* no bits are set */
  115.   if (value & 0xFFFF) {        /* low order halfword has a bit? */
  116.     bitno = 0;            /* yes, start with bit 0 */
  117.     clearbit = 1;        /* which has value 1 */
  118.   } else {            /* high order halfword has the bit */
  119.     bitno = 16;            /* start with bit 16 */
  120.     clearbit = 0x10000;        /* which has value 10000h */
  121.     value >>= 16;        /* and slide the halfword down */
  122.   }
  123.   if (!(value & 0xFF)) {    /* low quarterword has a bit? */
  124.     bitno += 8;            /* no, start 8 bits higher */
  125.     clearbit <<= 8;        /* bit to clear is 2^8 higher */
  126.     value >>= 8;        /* and slide the quarterword down */
  127.   }
  128.   while (T) {            /* search for bit in quarterword */
  129.     if (value & 1) break;    /* found it? */
  130.     value >>= 1;        /* now, slide the bit down */
  131.     bitno += 1;            /* count one more bit */
  132.     clearbit <<= 1;        /* bit to clear is 1 bit higher */
  133.   }
  134.   *valptr ^= clearbit;        /* clear the bit in the argument */
  135.   return (bitno);        /* and return the bit number */
  136. }
  137.  
  138. /* Return minimum of two integers
  139.  * Accepts: integer 1
  140.  *        integer 2
  141.  * Returns: minimum
  142.  */
  143.  
  144. long min (i,j)
  145.     long i;
  146.     long j;
  147. {
  148.   return ((i < j) ? i : j);
  149. }
  150.  
  151.  
  152. /* Return maximum of two integers
  153.  * Accepts: integer 1
  154.  *        integer 2
  155.  * Returns: maximum
  156.  */
  157.  
  158. long max (i,j)
  159.     long i;
  160.     long j;
  161. {
  162.   return ((i > j) ? i : j);
  163. }
  164.  
  165. /* Case independent search (machines)
  166.     fast on 32-bit machines;
  167.  * Accepts: base string
  168.  *        length of base string
  169.  *        pattern string
  170.  *        length of pattern string
  171.  * Returns: T if pattern exists inside base, else NIL
  172.  */
  173.  
  174. #define Word unsigned long
  175.  
  176. long search (s,c,pat,patc)
  177.     char *s;
  178.     long c;
  179.     char *pat;
  180.     long patc;
  181. {
  182.   register Word m;
  183.   long cc;
  184.   union {
  185.     unsigned long wd;
  186.     char ch[9];
  187.   } wdtest;
  188.   strcpy (wdtest.ch,"AAAA1234");/* constant for word testing */
  189.                 /* validate arguments, c becomes # of tries */
  190.   if (!(s && c > 0 && pat && patc > 0 && (c -= (patc - 1)) > 0)) return NIL;
  191.                 /* do slow search if long is not 4 chars */
  192.   if (wdtest.wd != 0x41414141) return ssrc (&s,&c,pat,(long) T);
  193.   /*
  194.    * Fast search algorithm XORs the mask with each word from the base string
  195.    * and complements the result. This will give bytes of all ones where there
  196.    * are matches.  We then mask out the high order and case bits in each byte
  197.    * and add 21 (case + overflow) to all the bytes.  If we have a resulting
  198.    * carry, then we have a match.
  199.    */
  200.   if (cc = ((int) s & 3)) {    /* any chars before word boundary? */
  201.     c -= (cc = 4 - cc);        /* yes, calculate how many, account for them */
  202.                 /* search through those */
  203.     if (ssrc (&s,&cc,pat,(long) NIL)) return T;
  204.   }
  205.   m = *pat * 0x01010101;    /* search mask */
  206.   do {                /* interesting word? */
  207.     if (0x80808080&(0x21212121+(0x5F5F5F5F&~(m^*(Word *) s)))) {
  208.                 /* yes, commence a slow search through it */
  209.       if (ssrc (&s,&c,pat,(long) NIL)) return T;
  210.     }
  211.     else s += 4,c -= 4;        /* try next word */
  212.   } while (c > 0);        /* continue until end of string */
  213.   return NIL;            /* string not found */
  214. }
  215.  
  216. /* Case independent slow search within a word
  217.  * Accepts: base string
  218.  *        number of tries left
  219.  *        pattern string
  220.  *        multi-word hunt flag
  221.  * Returns: T if pattern exists inside base, else NIL
  222.  */
  223.  
  224. long ssrc (base,tries,pat,multiword)
  225.     char **base;
  226.     long *tries;
  227.     char *pat;
  228.     long multiword;
  229. {
  230.   register char *s = *base;
  231.   register long c = multiword ? *tries : min (*tries,(long) 4);
  232.   register char *p = pat;
  233.                 /* search character at a time */
  234.   if (c > 0) do if (!((*p ^ *s++) & (char) 0xDF)) {
  235.     char *ss = s;        /* remember were we began */
  236.     do if (!*++p) return T;    /* match case-independent until end */
  237.     while (!((*p ^ *s++) & (char) 0xDF));
  238.     s = ss;            /* try next character */
  239.     p = pat;            /* start at beginning of pattern */
  240.   } while (--c);        /* continue if multiword or not at boundary */
  241.   *tries -= s - *base;        /* update try count */
  242.   *base = s;            /* update base */
  243.   return NIL;            /* string not found */
  244. }
  245.  
  246. /* Wildcard pattern match
  247.  * Accepts: base string
  248.  *        pattern string
  249.  * Returns: T if pattern matches base, else NIL
  250.  */
  251.  
  252. long pmatch (s,pat)
  253.     char *s;
  254.     char *pat;
  255. {
  256.   char tmp[MAILTMPLEN];
  257.   char c;
  258.   char *t = tmp;
  259.   *t++ = '^';            /* convert wildcard to regular expression */
  260.   while (c = *pat++) switch (c) {
  261.   case '*':
  262.     *t++ = '.';            /* wildcard characters */
  263.     *t++ = '*';
  264.     break;
  265.   case '?':
  266.     *t++ = '.';            /* wildcard character */
  267.     break;
  268.   case '.':
  269.   case '[':
  270.   case '\\':
  271.     *t++ = '\\';        /* quote it and fall into default case */
  272.   default:
  273.     *t++ = c;            /* copy character */
  274.     break;
  275.   }
  276.   *t++ = '$';            /* constrained at both ends */
  277.   *t = '\0';            /* tie off regular expression */
  278.                 /* do the match -- some systems lack recmp */
  279.   return (!re_comp (tmp)) && (re_exec (s) > 0);
  280. }
  281.