home *** CD-ROM | disk | FTP | other *** search
/ ftp.uv.es / 2014.11.ftp.uv.es.tar / ftp.uv.es / pub / unix / pine4.10.tar.gz / pine4.10.tar / pine4.10 / imap / src / c-client / misc.c < prev    next >
C/C++ Source or Header  |  1999-01-13  |  11KB  |  323 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:    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.  
  44.  
  45. #include <ctype.h>
  46. #include "mail.h"
  47. #include "osdep.h"
  48. #include "misc.h"
  49.  
  50. /* Convert string to all uppercase
  51.  * Accepts: string pointer
  52.  * Returns: string pointer
  53.  */
  54.  
  55. char *ucase (char *s)
  56. {
  57.   char *t;
  58.                 /* if lowercase covert to upper */
  59.   for (t = s; *t; t++) if (!(*t & 0x80) && islower (*t)) *t = toupper (*t);
  60.   return s;            /* return string */
  61. }
  62.  
  63.  
  64. /* Convert string to all lowercase
  65.  * Accepts: string pointer
  66.  * Returns: string pointer
  67.  */
  68.  
  69. char *lcase (char *s)
  70. {
  71.   char *t;
  72.                 /* if uppercase covert to lower */
  73.   for (t = s; *t; t++) if (!(*t & 0x80) && isupper (*t)) *t = tolower (*t);
  74.   return s;            /* return string */
  75. }
  76.  
  77. /* Copy string to free storage
  78.  * Accepts: source string
  79.  * Returns: free storage copy of string
  80.  */
  81.  
  82. char *cpystr (const char *string)
  83. {
  84.   return string ? strcpy ((char *) fs_get (1 + strlen (string)),string) : NIL;
  85. }
  86.  
  87.  
  88. /* Copy text/size to free storage as sized text
  89.  * Accepts: destination sized text
  90.  *        pointer to source text
  91.  *        size of source text
  92.  * Returns: text as a char *
  93.  */
  94.  
  95. char *cpytxt (SIZEDTEXT *dst,char *text,unsigned long size)
  96. {
  97.                 /* flush old space */
  98.   if (dst->data) fs_give ((void **) &dst->data);
  99.                 /* copy data in sized text */
  100.   memcpy (dst->data = (unsigned char *)
  101.       fs_get ((size_t) (dst->size = size) + 1),text,(size_t) size);
  102.   dst->data[size] = '\0';    /* tie off text */
  103.   return (char *) dst->data;    /* convenience return */
  104. }
  105.  
  106. /* Copy sized text to free storage as sized text
  107.  * Accepts: destination sized text
  108.  *        source sized text
  109.  * Returns: text as a char *
  110.  */
  111.  
  112. char *textcpy (SIZEDTEXT *dst,SIZEDTEXT *src)
  113. {
  114.                 /* flush old space */
  115.   if (dst->data) fs_give ((void **) &dst->data);
  116.                 /* copy data in sized text */
  117.   memcpy (dst->data = (unsigned char *)
  118.       fs_get ((size_t) (dst->size = src->size) + 1),
  119.       src->data,(size_t) src->size);
  120.   dst->data[dst->size] = '\0';    /* tie off text */
  121.   return (char *) dst->data;    /* convenience return */
  122. }
  123.  
  124.  
  125. /* Copy stringstruct to free storage as sized text
  126.  * Accepts: destination sized text
  127.  *        source stringstruct
  128.  * Returns: text as a char *
  129.  */
  130.  
  131. char *textcpystring (SIZEDTEXT *text,STRING *bs)
  132. {
  133.   unsigned long i = 0;
  134.                 /* clear old space */
  135.   if (text->data) fs_give ((void **) &text->data);
  136.                 /* make free storage space in sized text */
  137.   text->data = (unsigned char *) fs_get ((size_t) (text->size = SIZE (bs)) +1);
  138.   while (i < text->size) text->data[i++] = SNX (bs);
  139.   text->data[i] = '\0';        /* tie off text */
  140.   return (char *) text->data;    /* convenience return */
  141. }
  142.  
  143.  
  144. /* Copy stringstruct from offset to free storage as sized text
  145.  * Accepts: destination sized text
  146.  *        source stringstruct
  147.  *        offset into stringstruct
  148.  *        size of source text
  149.  * Returns: text as a char *
  150.  */
  151.  
  152. char *textcpyoffstring (SIZEDTEXT *text,STRING *bs,unsigned long offset,
  153.             unsigned long size)
  154. {
  155.   unsigned long i = 0;
  156.                 /* clear old space */
  157.   if (text->data) fs_give ((void **) &text->data);
  158.   SETPOS (bs,offset);        /* offset the string */
  159.                 /* make free storage space in sized text */
  160.   text->data = (unsigned char *) fs_get ((size_t) (text->size = size) + 1);
  161.   while (i < size) text->data[i++] = SNX (bs);
  162.   text->data[i] = '\0';        /* tie off text */
  163.   return (char *) text->data;    /* convenience return */
  164. }
  165.  
  166. /* Returns index of rightmost bit in word
  167.  * Accepts: pointer to a 32 bit value
  168.  * Returns: -1 if word is 0, else index of rightmost bit
  169.  *
  170.  * Bit is cleared in the word
  171.  */
  172.  
  173. unsigned long find_rightmost_bit (unsigned long *valptr)
  174. {
  175.   unsigned long value = *valptr;
  176.   unsigned long bit = 0;
  177.   if (!(value & 0xffffffff)) return 0xffffffff;
  178.                 /* binary search for rightmost bit */
  179.   if (!(value & 0xffff)) value >>= 16, bit += 16;
  180.   if (!(value & 0xff)) value >>= 8, bit += 8;
  181.   if (!(value & 0xf)) value >>= 4, bit += 4;
  182.   if (!(value & 0x3)) value >>= 2, bit += 2;
  183.   if (!(value & 0x1)) value >>= 1, bit += 1;
  184.   *valptr ^= (1 << bit);    /* clear specified bit */
  185.   return bit;
  186. }
  187.  
  188.  
  189. /* Return minimum of two integers
  190.  * Accepts: integer 1
  191.  *        integer 2
  192.  * Returns: minimum
  193.  */
  194.  
  195. long min (long i,long j)
  196. {
  197.   return ((i < j) ? i : j);
  198. }
  199.  
  200.  
  201. /* Return maximum of two integers
  202.  * Accepts: integer 1
  203.  *        integer 2
  204.  * Returns: maximum
  205.  */
  206.  
  207. long max (long i,long j)
  208. {
  209.   return ((i > j) ? i : j);
  210. }
  211.  
  212. /* Search, case-insensitive for ASCII characters
  213.  * Accepts: base string
  214.  *        length of base string
  215.  *        pattern string
  216.  *        length of pattern string
  217.  * Returns: T if pattern exists inside base, else NIL
  218.  */
  219.  
  220. long search (unsigned char *base,long basec,unsigned char *pat,long patc)
  221. {
  222.   long i,j,k;
  223.   int c;
  224.   unsigned char mask[256];
  225.   static unsigned char alphatab[256] = {
  226.     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  227.     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  228.     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  229.     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  230.     255,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,
  231.     223,223,223,223,223,223,223,223,223,223,223,255,255,255,255,255,
  232.     255,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,
  233.     223,223,223,223,223,223,223,223,223,223,223,255,255,255,255,255,
  234.     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  235.     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  236.     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  237.     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  238.     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  239.     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  240.     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
  241.     255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
  242.     };
  243.                 /* validate arguments */
  244.   if (base && (basec > 0) && pat && (basec >= patc)) {
  245.     if (patc <= 0) return T;    /* empty pattern always succeeds */
  246.     memset (mask,0,256);    /* initialize search validity mask */
  247.     for (i = 0; i < patc; i++) if (!mask[c = pat[i]]) {
  248.                 /* mark single character if non-alphabetic */
  249.       if (alphatab[c] & 0x20) mask[c] = T;
  250.                 /* else mark both cases */
  251.       else mask[c & 0xdf] = mask[c | 0x20] = T;
  252.     }
  253.                 /* Boyer-Moore type search */
  254.     for (i = --patc; i < basec; i += (mask[c] ? 1 : (j + 1)))
  255.       for (j = patc,c = base[k = i]; !((c ^ pat[j]) & alphatab[c]);
  256.        j--,c = base[--k])
  257.     if (!j) return T;    /* found a match! */
  258.   }
  259.   return NIL;            /* pattern not found */
  260. }
  261.  
  262. /* Wildcard pattern match
  263.  * Accepts: base string
  264.  *        pattern string
  265.  *        delimiter character
  266.  * Returns: T if pattern matches base, else NIL
  267.  */
  268.  
  269. long pmatch_full (char *s,char *pat,char delim)
  270. {
  271.   switch (*pat) {
  272.   case '%':            /* non-recursive */
  273.                 /* % at end, OK if no inferiors */
  274.     if (!pat[1]) return (delim && strchr (s,delim)) ? NIL : T;
  275.                                 /* scan remainder of string until delimiter */
  276.     do if (pmatch_full (s,pat+1,delim)) return T;
  277.     while ((*s != delim) && *s++);
  278.     break;
  279.   case '*':            /* match 0 or more characters */
  280.     if (!pat[1]) return T;    /* * at end, unconditional match */
  281.                 /* scan remainder of string */
  282.     do if (pmatch_full (s,pat+1,delim)) return T;
  283.     while (*s++);
  284.     break;
  285.   case '\0':            /* end of pattern */
  286.     return *s ? NIL : T;    /* success if also end of base */
  287.   default:            /* match this character */
  288.     return (*pat == *s) ? pmatch_full (s+1,pat+1,delim) : NIL;
  289.   }
  290.   return NIL;
  291. }
  292.  
  293. /* Directory pattern match
  294.  * Accepts: base string
  295.  *        pattern string
  296.  *        delimiter character
  297.  * Returns: T if base is a matching directory of pattern, else NIL
  298.  */
  299.  
  300. long dmatch (char *s,char *pat,char delim)
  301. {
  302.   switch (*pat) {
  303.   case '%':            /* non-recursive */
  304.     if (!*s) return T;        /* end of base means have a subset match */
  305.     if (!*++pat) return NIL;    /* % at end, no inferiors permitted */
  306.                 /* scan remainder of string until delimiter */
  307.     do if (dmatch (s,pat,delim)) return T;
  308.     while ((*s != delim) && *s++);
  309.     if (*s && !s[1]) return T;    /* ends with delimiter, must be subset */
  310.     return dmatch (s,pat,delim);/* do new scan */
  311.   case '*':            /* match 0 or more characters */
  312.     return T;            /* unconditional match */
  313.   case '\0':            /* end of pattern */
  314.     break;
  315.   default:            /* match this character */
  316.     if (*s) return (*pat == *s) ? dmatch (s+1,pat+1,delim) : NIL;
  317.                 /* end of base, return if at delimiter */
  318.     else if (*pat == delim) return T;
  319.     break;
  320.   }
  321.   return NIL;
  322. }
  323.