tw.spell.c revision 59243
159243Sobrien/* $Header: /src/pub/tcsh/tw.spell.c,v 3.14 1996/04/26 19:23:27 christos Exp $ */ 259243Sobrien/* 359243Sobrien * tw.spell.c: Spell check words 459243Sobrien */ 559243Sobrien/*- 659243Sobrien * Copyright (c) 1980, 1991 The Regents of the University of California. 759243Sobrien * All rights reserved. 859243Sobrien * 959243Sobrien * Redistribution and use in source and binary forms, with or without 1059243Sobrien * modification, are permitted provided that the following conditions 1159243Sobrien * are met: 1259243Sobrien * 1. Redistributions of source code must retain the above copyright 1359243Sobrien * notice, this list of conditions and the following disclaimer. 1459243Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1559243Sobrien * notice, this list of conditions and the following disclaimer in the 1659243Sobrien * documentation and/or other materials provided with the distribution. 1759243Sobrien * 3. All advertising materials mentioning features or use of this software 1859243Sobrien * must display the following acknowledgement: 1959243Sobrien * This product includes software developed by the University of 2059243Sobrien * California, Berkeley and its contributors. 2159243Sobrien * 4. Neither the name of the University nor the names of its contributors 2259243Sobrien * may be used to endorse or promote products derived from this software 2359243Sobrien * without specific prior written permission. 2459243Sobrien * 2559243Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2659243Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2759243Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2859243Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2959243Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3059243Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3159243Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3259243Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3359243Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3459243Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3559243Sobrien * SUCH DAMAGE. 3659243Sobrien */ 3759243Sobrien#include "sh.h" 3859243Sobrien 3959243SobrienRCSID("$Id: tw.spell.c,v 3.14 1996/04/26 19:23:27 christos Exp $") 4059243Sobrien 4159243Sobrien#include "tw.h" 4259243Sobrien 4359243Sobrien/* spell_me : return corrrectly spelled filename. From K&P spname */ 4459243Sobrienint 4559243Sobrienspell_me(oldname, oldsize, looking, pat, suf) 4659243Sobrien Char *oldname; 4759243Sobrien int oldsize, looking; 4859243Sobrien Char *pat; 4959243Sobrien int suf; 5059243Sobrien{ 5159243Sobrien /* The +1 is to fool hp's optimizer */ 5259243Sobrien Char guess[FILSIZ + 1], newname[FILSIZ + 1]; 5359243Sobrien register Char *new = newname, *old = oldname; 5459243Sobrien register Char *p, *cp, *ws; 5559243Sobrien bool foundslash = 0; 5659243Sobrien int retval; 5759243Sobrien 5859243Sobrien for (;;) { 5959243Sobrien while (*old == '/') { /* skip '/' */ 6059243Sobrien *new++ = *old++; 6159243Sobrien foundslash = 1; 6259243Sobrien } 6359243Sobrien /* do not try to correct spelling of single letter words */ 6459243Sobrien if (*old != '\0' && old[1] == '\0') 6559243Sobrien *new++ = *old++; 6659243Sobrien *new = '\0'; 6759243Sobrien if (*old == '\0') { 6859243Sobrien retval = (StrQcmp(oldname, newname) != 0); 6959243Sobrien copyn(oldname, newname, oldsize); /* shove it back. */ 7059243Sobrien return retval; 7159243Sobrien } 7259243Sobrien p = guess; /* start at beginning of buf */ 7359243Sobrien if (newname[0]) /* add current dir if any */ 7459243Sobrien for (cp = newname; *cp; cp++) 7559243Sobrien if (p < guess + FILSIZ) 7659243Sobrien *p++ = *cp; 7759243Sobrien ws = p; 7859243Sobrien for (; *old != '/' && *old != '\0'; old++)/* add current file name */ 7959243Sobrien if (p < guess + FILSIZ) 8059243Sobrien *p++ = *old; 8159243Sobrien *p = '\0'; /* terminate it */ 8259243Sobrien 8359243Sobrien /* 8459243Sobrien * Don't tell t_search we're looking for cmd if no '/' in the name so 8559243Sobrien * far but there are later - or it will look for *all* commands 8659243Sobrien */ 8759243Sobrien /* (*should* say "looking for directory" whenever '/' is next...) */ 8859243Sobrien retval = t_search(guess, p, SPELL, FILSIZ, 8959243Sobrien looking == TW_COMMAND && (foundslash || *old != '/') ? 9059243Sobrien TW_COMMAND : looking, 1, pat, suf); 9159243Sobrien if (retval >= 4 || retval < 0) 9259243Sobrien return -1; /* hopeless */ 9359243Sobrien for (p = ws; (*new = *p++) != '\0'; new++) 9459243Sobrien continue; 9559243Sobrien } 9659243Sobrien/*NOTREACHED*/ 9759243Sobrien#ifdef notdef 9859243Sobrien return (0); /* lint on the vax under mtXinu complains! */ 9959243Sobrien#endif 10059243Sobrien} 10159243Sobrien 10259243Sobrien#define EQ(s,t) (StrQcmp(s,t) == 0) 10359243Sobrien 10459243Sobrien/* 10559243Sobrien * spdist() is taken from Kernighan & Pike, 10659243Sobrien * _The_UNIX_Programming_Environment_ 10759243Sobrien * and adapted somewhat to correspond better to psychological reality. 10859243Sobrien * (Note the changes to the return values) 10959243Sobrien * 11059243Sobrien * According to Pollock and Zamora, CACM April 1984 (V. 27, No. 4), 11159243Sobrien * page 363, the correct order for this is: 11259243Sobrien * OMISSION = TRANSPOSITION > INSERTION > SUBSTITUTION 11359243Sobrien * thus, it was exactly backwards in the old version. -- PWP 11459243Sobrien */ 11559243Sobrien 11659243Sobrienint 11759243Sobrienspdist(s, t) 11859243Sobrien register Char *s, *t; 11959243Sobrien{ 12059243Sobrien for (; (*s & TRIM) == (*t & TRIM); t++, s++) 12159243Sobrien if (*t == '\0') 12259243Sobrien return 0; /* exact match */ 12359243Sobrien if (*s) { 12459243Sobrien if (*t) { 12559243Sobrien if (s[1] && t[1] && (*s & TRIM) == (t[1] & TRIM) && 12659243Sobrien (*t & TRIM) == (s[1] & TRIM) && EQ(s + 2, t + 2)) 12759243Sobrien return 1; /* transposition */ 12859243Sobrien if (EQ(s + 1, t + 1)) 12959243Sobrien return 3; /* 1 char mismatch */ 13059243Sobrien } 13159243Sobrien if (EQ(s + 1, t)) 13259243Sobrien return 2; /* extra character */ 13359243Sobrien } 13459243Sobrien if (*t && EQ(s, t + 1)) 13559243Sobrien return 1; /* missing character */ 13659243Sobrien return 4; 13759243Sobrien} 13859243Sobrien 13959243Sobrienint 14059243Sobrienspdir(extended_name, tilded_dir, item, name) 14159243Sobrien Char *extended_name; 14259243Sobrien Char *tilded_dir; 14359243Sobrien Char *item; 14459243Sobrien Char *name; 14559243Sobrien{ 14659243Sobrien Char path[MAXPATHLEN + 1]; 14759243Sobrien Char *s; 14859243Sobrien Char oldch; 14959243Sobrien 15059243Sobrien if (ISDOT(item) || ISDOTDOT(item)) 15159243Sobrien return 0; 15259243Sobrien 15359243Sobrien for (s = name; *s != 0 && (*s & TRIM) == (*item & TRIM); s++, item++) 15459243Sobrien continue; 15559243Sobrien if (*s == 0 || s[1] == 0 || *item != 0) 15659243Sobrien return 0; 15759243Sobrien 15859243Sobrien (void) Strcpy(path, tilded_dir); 15959243Sobrien oldch = *s; 16059243Sobrien *s = '/'; 16159243Sobrien catn(path, name, (int) (sizeof(path) / sizeof(Char))); 16259243Sobrien if (access(short2str(path), F_OK) == 0) { 16359243Sobrien (void) Strcpy(extended_name, name); 16459243Sobrien return 1; 16559243Sobrien } 16659243Sobrien *s = oldch; 16759243Sobrien return 0; 16859243Sobrien} 169