misc.c
上传用户:ycwykj01
上传日期:2007-01-04
资源大小:1819k
文件大小:10k
- /*
- * Program: Miscellaneous utility routines
- *
- * Author: Mark Crispin
- * Networks and Distributed Computing
- * Computing & Communications
- * University of Washington
- * Administration Building, AG-44
- * Seattle, WA 98195
- * Internet: MRC@CAC.Washington.EDU
- *
- * Date: 5 July 1988
- * Last Edited: 13 January 1999
- *
- * Sponsorship: The original version of this work was developed in the
- * Symbolic Systems Resources Group of the Knowledge Systems
- * Laboratory at Stanford University in 1987-88, and was funded
- * by the Biomedical Research Technology Program of the National
- * Institutes of Health under grant number RR-00785.
- *
- * Original version Copyright 1988 by The Leland Stanford Junior University
- * Copyright 1999 by the University of Washington
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted, provided
- * that the above copyright notices appear in all copies and that both the
- * above copyright notices and this permission notice appear in supporting
- * documentation, and that the name of the University of Washington or The
- * Leland Stanford Junior University not be used in advertising or publicity
- * pertaining to distribution of the software without specific, written prior
- * permission. This software is made available "as is", and
- * THE UNIVERSITY OF WASHINGTON AND THE LELAND STANFORD JUNIOR UNIVERSITY
- * DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE,
- * INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE UNIVERSITY OF
- * WASHINGTON OR THE LELAND STANFORD JUNIOR UNIVERSITY BE LIABLE FOR ANY
- * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
- * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
- * CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
- #include <ctype.h>
- #include "mail.h"
- #include "osdep.h"
- #include "misc.h"
- /* Convert string to all uppercase
- * Accepts: string pointer
- * Returns: string pointer
- */
- char *ucase (char *s)
- {
- char *t;
- /* if lowercase covert to upper */
- for (t = s; *t; t++) if (!(*t & 0x80) && islower (*t)) *t = toupper (*t);
- return s; /* return string */
- }
- /* Convert string to all lowercase
- * Accepts: string pointer
- * Returns: string pointer
- */
- char *lcase (char *s)
- {
- char *t;
- /* if uppercase covert to lower */
- for (t = s; *t; t++) if (!(*t & 0x80) && isupper (*t)) *t = tolower (*t);
- return s; /* return string */
- }
- /* Copy string to free storage
- * Accepts: source string
- * Returns: free storage copy of string
- */
- char *cpystr (const char *string)
- {
- return string ? strcpy ((char *) fs_get (1 + strlen (string)),string) : NIL;
- }
- /* Copy text/size to free storage as sized text
- * Accepts: destination sized text
- * pointer to source text
- * size of source text
- * Returns: text as a char *
- */
- char *cpytxt (SIZEDTEXT *dst,char *text,unsigned long size)
- {
- /* flush old space */
- if (dst->data) fs_give ((void **) &dst->data);
- /* copy data in sized text */
- memcpy (dst->data = (unsigned char *)
- fs_get ((size_t) (dst->size = size) + 1),text,(size_t) size);
- dst->data[size] = ' '; /* tie off text */
- return (char *) dst->data; /* convenience return */
- }
- /* Copy sized text to free storage as sized text
- * Accepts: destination sized text
- * source sized text
- * Returns: text as a char *
- */
- char *textcpy (SIZEDTEXT *dst,SIZEDTEXT *src)
- {
- /* flush old space */
- if (dst->data) fs_give ((void **) &dst->data);
- /* copy data in sized text */
- memcpy (dst->data = (unsigned char *)
- fs_get ((size_t) (dst->size = src->size) + 1),
- src->data,(size_t) src->size);
- dst->data[dst->size] = ' '; /* tie off text */
- return (char *) dst->data; /* convenience return */
- }
- /* Copy stringstruct to free storage as sized text
- * Accepts: destination sized text
- * source stringstruct
- * Returns: text as a char *
- */
- char *textcpystring (SIZEDTEXT *text,STRING *bs)
- {
- unsigned long i = 0;
- /* clear old space */
- if (text->data) fs_give ((void **) &text->data);
- /* make free storage space in sized text */
- text->data = (unsigned char *) fs_get ((size_t) (text->size = SIZE (bs)) +1);
- while (i < text->size) text->data[i++] = SNX (bs);
- text->data[i] = ' '; /* tie off text */
- return (char *) text->data; /* convenience return */
- }
- /* Copy stringstruct from offset to free storage as sized text
- * Accepts: destination sized text
- * source stringstruct
- * offset into stringstruct
- * size of source text
- * Returns: text as a char *
- */
- char *textcpyoffstring (SIZEDTEXT *text,STRING *bs,unsigned long offset,
- unsigned long size)
- {
- unsigned long i = 0;
- /* clear old space */
- if (text->data) fs_give ((void **) &text->data);
- SETPOS (bs,offset); /* offset the string */
- /* make free storage space in sized text */
- text->data = (unsigned char *) fs_get ((size_t) (text->size = size) + 1);
- while (i < size) text->data[i++] = SNX (bs);
- text->data[i] = ' '; /* tie off text */
- return (char *) text->data; /* convenience return */
- }
- /* Returns index of rightmost bit in word
- * Accepts: pointer to a 32 bit value
- * Returns: -1 if word is 0, else index of rightmost bit
- *
- * Bit is cleared in the word
- */
- unsigned long find_rightmost_bit (unsigned long *valptr)
- {
- unsigned long value = *valptr;
- unsigned long bit = 0;
- if (!(value & 0xffffffff)) return 0xffffffff;
- /* binary search for rightmost bit */
- if (!(value & 0xffff)) value >>= 16, bit += 16;
- if (!(value & 0xff)) value >>= 8, bit += 8;
- if (!(value & 0xf)) value >>= 4, bit += 4;
- if (!(value & 0x3)) value >>= 2, bit += 2;
- if (!(value & 0x1)) value >>= 1, bit += 1;
- *valptr ^= (1 << bit); /* clear specified bit */
- return bit;
- }
- /* Return minimum of two integers
- * Accepts: integer 1
- * integer 2
- * Returns: minimum
- */
- long min (long i,long j)
- {
- return ((i < j) ? i : j);
- }
- /* Return maximum of two integers
- * Accepts: integer 1
- * integer 2
- * Returns: maximum
- */
- long max (long i,long j)
- {
- return ((i > j) ? i : j);
- }
- /* Search, case-insensitive for ASCII characters
- * Accepts: base string
- * length of base string
- * pattern string
- * length of pattern string
- * Returns: T if pattern exists inside base, else NIL
- */
- long search (unsigned char *base,long basec,unsigned char *pat,long patc)
- {
- long i,j,k;
- int c;
- unsigned char mask[256];
- static unsigned char alphatab[256] = {
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,
- 223,223,223,223,223,223,223,223,223,223,223,255,255,255,255,255,
- 255,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,
- 223,223,223,223,223,223,223,223,223,223,223,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
- };
- /* validate arguments */
- if (base && (basec > 0) && pat && (basec >= patc)) {
- if (patc <= 0) return T; /* empty pattern always succeeds */
- memset (mask,0,256); /* initialize search validity mask */
- for (i = 0; i < patc; i++) if (!mask[c = pat[i]]) {
- /* mark single character if non-alphabetic */
- if (alphatab[c] & 0x20) mask[c] = T;
- /* else mark both cases */
- else mask[c & 0xdf] = mask[c | 0x20] = T;
- }
- /* Boyer-Moore type search */
- for (i = --patc; i < basec; i += (mask[c] ? 1 : (j + 1)))
- for (j = patc,c = base[k = i]; !((c ^ pat[j]) & alphatab[c]);
- j--,c = base[--k])
- if (!j) return T; /* found a match! */
- }
- return NIL; /* pattern not found */
- }
- /* Wildcard pattern match
- * Accepts: base string
- * pattern string
- * delimiter character
- * Returns: T if pattern matches base, else NIL
- */
- long pmatch_full (char *s,char *pat,char delim)
- {
- switch (*pat) {
- case '%': /* non-recursive */
- /* % at end, OK if no inferiors */
- if (!pat[1]) return (delim && strchr (s,delim)) ? NIL : T;
- /* scan remainder of string until delimiter */
- do if (pmatch_full (s,pat+1,delim)) return T;
- while ((*s != delim) && *s++);
- break;
- case '*': /* match 0 or more characters */
- if (!pat[1]) return T; /* * at end, unconditional match */
- /* scan remainder of string */
- do if (pmatch_full (s,pat+1,delim)) return T;
- while (*s++);
- break;
- case ' ': /* end of pattern */
- return *s ? NIL : T; /* success if also end of base */
- default: /* match this character */
- return (*pat == *s) ? pmatch_full (s+1,pat+1,delim) : NIL;
- }
- return NIL;
- }
- /* Directory pattern match
- * Accepts: base string
- * pattern string
- * delimiter character
- * Returns: T if base is a matching directory of pattern, else NIL
- */
- long dmatch (char *s,char *pat,char delim)
- {
- switch (*pat) {
- case '%': /* non-recursive */
- if (!*s) return T; /* end of base means have a subset match */
- if (!*++pat) return NIL; /* % at end, no inferiors permitted */
- /* scan remainder of string until delimiter */
- do if (dmatch (s,pat,delim)) return T;
- while ((*s != delim) && *s++);
- if (*s && !s[1]) return T; /* ends with delimiter, must be subset */
- return dmatch (s,pat,delim);/* do new scan */
- case '*': /* match 0 or more characters */
- return T; /* unconditional match */
- case ' ': /* end of pattern */
- break;
- default: /* match this character */
- if (*s) return (*pat == *s) ? dmatch (s+1,pat+1,delim) : NIL;
- /* end of base, return if at delimiter */
- else if (*pat == delim) return T;
- break;
- }
- return NIL;
- }