225 lines
6.3 KiB
C
225 lines
6.3 KiB
C
/* lookup.c --
|
||
*
|
||
* *********************************************************************
|
||
* * Copyright (C) 1985, 1990 Regents of the University of California. *
|
||
* * 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 *
|
||
* * notice appear in all copies. The University of California *
|
||
* * makes no representations about the suitability of this *
|
||
* * software for any purpose. It is provided "as is" without *
|
||
* * express or implied warranty. Export of this software outside *
|
||
* * of the United States of America may require an export license. *
|
||
* *********************************************************************
|
||
*
|
||
* This file contains a single routine used to look up a string in
|
||
* a table, allowing unique abbreviations.
|
||
*/
|
||
|
||
#ifndef lint
|
||
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/lookup.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
|
||
#endif /* not lint */
|
||
|
||
#include <stdio.h>
|
||
#include <ctype.h>
|
||
|
||
#include "utils/magic.h"
|
||
#include "utils/utils.h"
|
||
|
||
|
||
/*---------------------------------------------------------
|
||
* Lookup --
|
||
* Searches a table of strings to find one that matches a given
|
||
* string. It's useful mostly for command lookup.
|
||
*
|
||
* Only the portion of a string in the table up to the first
|
||
* blank character is considered significant for matching.
|
||
*
|
||
* Results:
|
||
* If str is the same as
|
||
* or an unambiguous abbreviation for one of the entries
|
||
* in table, then the index of the matching entry is returned.
|
||
* If str is not the same as any entry in the table, but
|
||
* an abbreviation for more than one entry,
|
||
* then -1 is returned. If str doesn't match any entry, then
|
||
* -2 is returned. Case differences are ignored.
|
||
*
|
||
* NOTE:
|
||
* Table entries need no longer be in alphabetical order
|
||
* and they need not be lower case. The irouter command parsing
|
||
* depends on these features.
|
||
*
|
||
* Side Effects:
|
||
* None.
|
||
*---------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
Lookup(str, table)
|
||
char *str; /* Pointer to a string to be looked up */
|
||
char *(table[]); /* Pointer to an array of string pointers
|
||
* which are the valid commands.
|
||
* The end of
|
||
* the table is indicated by a NULL string.
|
||
*/
|
||
{
|
||
int match = -2; /* result, initialized to -2 = no match */
|
||
int pos;
|
||
int ststart = 0;
|
||
|
||
#ifdef MAGIC_WRAPPER
|
||
static char *namespace = "::magic::";
|
||
|
||
/* Skip over prefix of qualified namespaces "::magic::" and "magic::" */
|
||
for (pos = 0; pos < 9; pos++)
|
||
if ((str[pos] != namespace[pos]) || (str[pos] == '\0')) break;
|
||
if (pos == 9) ststart = 9;
|
||
else
|
||
{
|
||
for (pos = 0; pos < 7; pos++)
|
||
if ((str[pos] != namespace[pos + 2]) || (str[pos] == '\0')) break;
|
||
if (pos == 7) ststart = 7;
|
||
}
|
||
#endif
|
||
|
||
/* search for match */
|
||
for(pos=0; table[pos]!=NULL; pos++)
|
||
{
|
||
char *tabc = table[pos];
|
||
char *strc = &(str[ststart]);
|
||
while(*strc!='\0' && *tabc!=' ' &&
|
||
((*tabc==*strc) ||
|
||
(isupper(*tabc) && islower(*strc) && (tolower(*tabc)== *strc))||
|
||
(islower(*tabc) && isupper(*strc) && (toupper(*tabc)== *strc)) ))
|
||
{
|
||
strc++;
|
||
tabc++;
|
||
}
|
||
|
||
|
||
if(*strc=='\0')
|
||
{
|
||
/* entry matches */
|
||
if(*tabc==' ' || *tabc=='\0')
|
||
{
|
||
/* exact match - record it and terminate search */
|
||
match = pos;
|
||
break;
|
||
}
|
||
else if (match == -2)
|
||
{
|
||
/* inexact match and no previous match - record this one
|
||
* and continue search */
|
||
match = pos;
|
||
}
|
||
else
|
||
{
|
||
/* previous match, so string is ambiguous unless exact
|
||
* match exists. Mark ambiguous for now, and continue
|
||
* search.
|
||
*/
|
||
match = -1;
|
||
}
|
||
}
|
||
}
|
||
return(match);
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------
|
||
*
|
||
* LookupStruct --
|
||
*
|
||
* Searches a table of structures, each of which contains a string
|
||
* pointer as its first element, in a manner similar to that of Lookup()
|
||
* above. Each structure in the table has the following form:
|
||
*
|
||
* struct
|
||
* {
|
||
* char *string;
|
||
* ... rest of structure
|
||
* };
|
||
*
|
||
* The 'string' field of each structure is matched against the
|
||
* argument 'str'. The size of a single structure is given by
|
||
* the argument 'size'.
|
||
*
|
||
* Results:
|
||
* If str is the same as
|
||
* or an unambiguous abbreviation for one of the entries
|
||
* in table, then the index of the matching entry is returned.
|
||
* If str is not the same as any entry in the table, but
|
||
* an abbreviation for more than one entry,
|
||
* then -1 is returned. If str doesn't match any entry, then
|
||
* -2 is returned. Case differences are ignored.
|
||
*
|
||
* NOTE: Table entries need no longer be in alphabetical order
|
||
* and they need not be lower case. The irouter command parsing
|
||
* depends on these features.
|
||
*
|
||
* Side Effects:
|
||
* None.
|
||
*
|
||
*---------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
LookupStruct(str, table, size)
|
||
char str[]; /* Pointer to a string to be looked up */
|
||
char **table; /* Pointer to an array of structs containing string
|
||
* pointers to valid commands.
|
||
* The last table entry should have a NULL
|
||
* string pointer.
|
||
*/
|
||
int size; /* The size, in bytes, of each table entry */
|
||
{
|
||
int match = -2; /* result, initialized to -2 = no match */
|
||
char **entry;
|
||
int pos;
|
||
char *tabc , *strc ;
|
||
|
||
/* search for match */
|
||
for (entry = table, pos = 0; *entry != NULL; )
|
||
{
|
||
tabc = *entry;
|
||
strc = str;
|
||
while(*strc!='\0' && *tabc!=' ' &&
|
||
((*tabc== *strc) ||
|
||
(isupper(*tabc) && islower(*strc) && (tolower(*tabc)== *strc))||
|
||
(islower(*tabc) && isupper(*strc) && (toupper(*tabc)== *strc)) ))
|
||
{
|
||
strc++;
|
||
tabc++;
|
||
}
|
||
|
||
if(*strc=='\0')
|
||
{
|
||
/* entry matches */
|
||
if(*tabc==' ' || *tabc=='\0')
|
||
{
|
||
/* exact match - record it and terminate search */
|
||
match = pos;
|
||
break;
|
||
}
|
||
else if (match == -2)
|
||
{
|
||
/* in exact match and no previous match - record this one
|
||
* and continue search */
|
||
match = pos;
|
||
}
|
||
else
|
||
{
|
||
/* previous match, so string is ambiguous unless exact
|
||
* match exists. Mark ambiguous for now, and continue
|
||
* search.
|
||
*/
|
||
match = -1;
|
||
}
|
||
}
|
||
pos++;
|
||
entry = (char **)((long)entry + (long) size);
|
||
}
|
||
return(match);
|
||
}
|
||
|