magic/utils/lookup.c

227 lines
6.4 KiB
C
Raw Normal View History

/* 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)
const char *str; /* Pointer to a string to be looked up */
const char * const *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 const 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++)
{
const char *tabc = table[pos];
const 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
* {
* const 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_start, size)
const char *str; /* Pointer to a string to be looked up */
const LookupTable *table_start;
/* 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 */
{
const char * const *table = (const char * const *)table_start;
int match = -2; /* result, initialized to -2 = no match */
const char * const *entry;
int pos;
const 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 = (const char **)((pointertype)entry + (pointertype)size);
}
return(match);
}