This is stabsearch.c in view mode; [Download] [Up]
/* * Copyright (c) 1990 Carnegie Mellon University * All Rights Reserved. * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * THE SOFTWARE IS PROVIDED "AS IS" AND CARNEGIE MELLON UNIVERSITY * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT * SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Users of this software agree to return to Carnegie Mellon any * improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * * Export of this software is permitted only after complying with the * regulations of the U.S. Deptartment of Commerce relating to the * Export of Technical Data. */ /* stabsearch -- search for best match within string table * * int stabsearch (arg,table,quiet); * char *arg; * char **table; * int quiet; * * Just like stablk(3), but a match score is determined for each * string in the table, and the best match is used. If quiet=0, * the user will be asked if he really meant the best matching * string; if he says "no", a list of several other good matches * will be printed. * If there is exactly one perfect match, then its index will be * returned, and the user will not be asked anything. If there are * several perfect matches, then up to 50 will be listed for the * user to review and among which he can select one. * * HISTORY * $Log: stabsearch.c,v $ * Revision 1.2 90/12/11 17:59:43 mja * Add copyright/disclaimer for distribution. * * 28-Apr-85 Steven Shafer (sas) at Carnegie-Mellon University * Modified for 4.2 BSD. Now puts output on std. error using fprintf * and fprstab. * * 13-Mar-85 Glenn Marcy (gm0w) at Carnegie-Mellon University * Return NOMATCH if arg is zero. * * 26-Oct-83 Leonard Hamey (lgh) at Carnegie-Mellon University * Included code to detect exact matches. * * 06-Feb-81 Steven Shafer (sas) at Carnegie-Mellon University * Fixed bug in previous bug fixes. * * 27-Jan-81 Steven Shafer (sas) at Carnegie-Mellon University * Added SCROLLSIZE, KEEPPERFECT, and associated code for better * handling of long string tables. * * 16-Apr-80 Steven Shafer (sas) at Carnegie-Mellon University * Changed option-printing code to use "prstab"; this will use * multiple columns where appropriate. * * 12-Mar-80 Steven Shafer (sas) at Carnegie-Mellon University * Added check for unique perfect match; will now return appropriate index * without asking "Did you mean X?". * * 23-Jan-80 Steven Shafer (sas) at Carnegie-Mellon University * Created. Almost identical to Dave McKeown's matching routine from * the PDP-11, but the scores are normalized to lie in the range 0 to 100. * */ #include <stdio.h> #define KEEPBEST 6 /* # of matches to keep around */ #define KEEPPERFECT 50 /* # of perfect matches to keep */ #define KEEPEXACT 50 /* # of exact matches to keep */ #define PERFECT 100 /* perfect match score */ #define EXACT 101 /* exact match pseudo-score */ #define THRESHOLD 35 /* minimum acceptable score */ #define NOMATCH -1 /* return value if no match */ #define MAXLENGTH 400 /* max length of arg and table entries */ #define SCROLLSIZE 20 /* size of each screenful for scrolling */ int srchscore(); /* score function */ int stabsearch (arg,table,quiet) char *arg,**table; int quiet; { int bestentry[KEEPPERFECT], bestscore[KEEPPERFECT]; int arglen; int maxscore; /* best possible score */ register int i,j,k; /* temps */ int nperfect; /* # of perfect matches */ int nexact; /* # of exact matches */ int nentries; /* # of entries in table */ char line[MAXLENGTH]; char a[MAXLENGTH],e[MAXLENGTH]; if (arg == 0) return (NOMATCH); if (strcmp (arg,"?") != 0) { for (i=0; i<KEEPPERFECT; i++) { bestentry[i] = -1; bestscore[i] = -1; } arglen = strlen (arg); maxscore = arglen * arglen; folddown (a,arg); nperfect = 0; nexact = 0; for (i=0; table[i]; i++) { folddown (e,table[i]); j = (srchscore (e,a) * PERFECT) / maxscore; if (nperfect == 0 && nexact == 0 && j != PERFECT) { if (j >= bestscore[KEEPBEST-1]) { k = KEEPBEST - 1; while ((k > 0) && (j > bestscore[k-1])) { bestscore[k] = bestscore[k-1]; bestentry[k] = bestentry[k-1]; --k; } bestscore[k] = j; bestentry[k] = i; } } else if (j == PERFECT && arglen == strlen (e)) { bestscore[0] = EXACT; if (nexact < KEEPEXACT) bestentry[nexact++] = i; } else if (j == PERFECT && nperfect < KEEPPERFECT && !nexact) { bestscore[0] = PERFECT; bestentry[nperfect] = i; nperfect++; } } nentries = i; if (bestscore[0] <= THRESHOLD) { if (!quiet) { fprintf (stderr,"Sorry, nothing matches \"%s\" reasonably.\n",arg); if (getbool("Do you want a list?",(nentries<=SCROLLSIZE))) goto makelist; } return (NOMATCH); } if (quiet) return (bestentry[0]); if (nexact > 1) { fprintf (stderr,"There are %d exact matches for \"%s\":\n",nexact,arg); j = getint ("Which one should be used? (0 if none ok)",0,nexact,1); return ((j > 0) ? bestentry[j-1] : NOMATCH); } else if (nexact == 1) return (bestentry[0]); if (nperfect > 1) { /* multiple max matches */ fprintf (stderr,"There are %d perfect matches for \"%s\":\n",nperfect,arg); for (j=0; j<nperfect && ((j%SCROLLSIZE!=SCROLLSIZE-1) || getbool("Continue?",1)); j++) { fprintf (stderr,"(%d)\t%s\n",j+1,table[bestentry[j]]); } j = getint ("Which one should be used? (0 if none ok)",0,nperfect,1); return ((j > 0) ? bestentry[j-1] : NOMATCH); } else if (nperfect == 1) { /* unique perfect match */ return (bestentry[0]); } sprintf (line,"Did you mean \"%s\" [%d] ?", table[bestentry[0]],bestscore[0]); if (getbool(line,1)) return (bestentry[0]); fprintf (stderr,"May I suggest the following?\n"); for (i=0; i<KEEPBEST && bestscore[i] >= THRESHOLD; i++) { fprintf (stderr,"(%d)\t%-15s \t[%d]\n",i+1,table[bestentry[i]],bestscore[i]); } j = getint ("Which one should be used? (0 if none ok)",0,i,1); if (j>0) return (bestentry[j-1]); if (getbool("Do you want a list of all possibilities?",(nentries<=SCROLLSIZE))) goto makelist; } else { makelist: fprintf (stderr,"The choices are as follows:\n"); fprstab (stderr,table); } return (NOMATCH); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.