📄 misc.c
字号:
/* * 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: 18 September 2000 * * 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 2000 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] = '\0'; /* 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] = '\0'; /* 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] = '\0'; /* 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] = '\0'; /* 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 */}/* Create a hash table * Accepts: size of new table (note: should be a prime) * Returns: hash table */HASHTAB *hash_create (size_t size){ size_t i = sizeof (size_t) + size * sizeof (HASHENT *); HASHTAB *ret = (HASHTAB *) memset (fs_get (i),0,i); ret->size = size; return ret;}/* Destroy hash table * Accepts: hash table */void hash_destroy (HASHTAB **hashtab){ if (*hashtab) { hash_reset (*hashtab); /* reset hash table */ fs_give ((void **) hashtab); }}/* Reset hash table * Accepts: hash table */void hash_reset (HASHTAB *hashtab){ size_t i; HASHENT *ent,*nxt; /* free each hash entry */ for (i = 0; i < hashtab->size; i++) if (ent = hashtab->table[i]) for (hashtab->table[i] = NIL; ent; ent = nxt) { nxt = ent->next; /* get successor */ fs_give ((void **) &ent); /* flush this entry */ }}/* Calculate index into hash table * Accepts: hash table * entry name * Returns: index */size_t hash_index (HASHTAB *hashtab,char *key){ size_t ret = 0; unsigned int i; /* polynomial of letters of the word */ while (i = (unsigned int) *key++) { ret *= HASHMULT; /* multiply by some strange constant */ ret += i; /* add character to result */ } return ret % hashtab->size;}/* Look up name in hash table * Accepts: hash table * key * Returns: associated data */void **hash_lookup (HASHTAB *hashtab,char *key){ HASHENT *ret; for (ret = hashtab->table[hash_index (hashtab,key)]; ret; ret = ret->next) if (!strcmp (key,ret->name)) return ret->data; return NIL;}/* Add entry to hash table * Accepts: hash table * key * associated data * number of extra data slots * Returns: hash entry * Caller is responsible for ensuring that entry isn't already in table */HASHENT *hash_add (HASHTAB *hashtab,char *key,void *data,long extra){ size_t i = hash_index (hashtab,key); size_t j = sizeof (HASHENT) + (extra * sizeof (void *)); HASHENT *ret = (HASHENT *) memset (fs_get (j),0,j); ret->next = hashtab->table[i];/* insert as new head in this index */ ret->name = key; /* set up hash key */ ret->data[0] = data; /* and first data */ return hashtab->table[i] = ret;}/* Look up name in hash table * Accepts: hash table * key * associated data * number of extra data slots * Returns: associated data */void **hash_lookup_and_add (HASHTAB *hashtab,char *key,void *data,long extra){ HASHENT *ret; size_t i = hash_index (hashtab,key); size_t j = sizeof (HASHENT) + (extra * sizeof (void *)); for (ret = hashtab->table[i]; ret; ret = ret->next) if (!strcmp (key,ret->name)) return ret->data; ret = (HASHENT *) memset (fs_get (j),0,j); ret->next = hashtab->table[i];/* insert as new head in this index */ ret->name = key; /* set up hash key */ ret->data[0] = data; /* and first data */ return (hashtab->table[i] = ret)->data;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -