strpsearch.c revision 3e14f97f673e8a630f076077de35afdd43dc1587
/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1985-2010 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* http://www.opensource.org/licenses/cpl1.0.txt *
* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <gsf@research.att.com> *
* David Korn <dgk@research.att.com> *
* Phong Vo <kpv@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
/*
* Glenn Fowler
* AT&T Research
*/
#include <ast.h>
#include <ccode.h>
#include <ctype.h>
#if CC_NATIVE == CC_ASCII
#define MAP(m,c) (c)
#else
#define MAP(m,c) m[c]
#endif
/*
* return a pointer to the isalpha() identifier matching
* name in the CC_ASCII sorted tab of num elements of
* size siz where the first member of each
* element is a char*
*
* [xxx] brackets optional identifier characters
* * starts optional identifier characters
*
* 0 returned if name not found
* otherwise if next!=0 then it points to the next
* unmatched char in name
*/
void*
strpsearch(const void* tab, size_t num, size_t siz, const char* name, char** next)
{
register char* lo = (char*)tab;
register char* hi = lo + (num - 1) * siz;
register char* mid;
#if CC_NATIVE != CC_ASCII
register unsigned char* m;
#endif
register unsigned char* s;
register unsigned char* t;
register int c;
register int v;
int sequential = 0;
#if CC_NATIVE != CC_ASCII
m = ccmap(CC_NATIVE, CC_ASCII);
#endif
c = MAP(m, *((unsigned char*)name));
while (lo <= hi)
{
mid = lo + (sequential ? 0 : (((hi - lo) / siz) / 2) * siz);
if (!(v = c - MAP(m, *(s = *((unsigned char**)mid)))) || *s == '[' && !(v = c - MAP(m, *++s)) && (v = 1))
{
t = (unsigned char*)name;
for (;;)
{
if (!v && (*s == '[' || *s == '*'))
{
v = 1;
s++;
}
else if (v && *s == ']')
{
v = 0;
s++;
}
else if (!isalpha(*t))
{
if (v || !*s)
{
if (next)
*next = (char*)t;
return (void*)mid;
}
if (!sequential)
{
while ((mid -= siz) >= lo && (s = *((unsigned char**)mid)) && ((c == MAP(m, *s)) || *s == '[' && c == MAP(m, *(s + 1))));
sequential = 1;
}
v = 1;
break;
}
else if (*t != *s)
{
v = MAP(m, *t) - MAP(m, *s);
break;
}
else
{
t++;
s++;
}
}
}
else if (sequential)
break;
if (v > 0)
lo = mid + siz;
else
hi = mid - siz;
}
return 0;
}