/*+++* * title: _tcpfind.c * abstract: find a termcap capability * author: T.R.Hageman, Groningen, The Netherlands. * created: march 1990 * modified: 16-Jun-90, fixed typo in SLOWCAP/HASHED code * 24-Jun-92, make FASTCAP table grow downward when compiling. * description: * #if FASTCAP * Do a binary search for the capability in the capabilities-table. * If there is a match, return a NULL pointer if we are compiling * and a pointer to the VALUE of the matching entry if we are not. * If there is no match, insert the new entry in the table and return * a pointer to the ENTRY (cast to char *) if we are compiling, or a NULL * pointer if we are not. * The routine does not make any assumptions on the maximum allowed size * of the table when a new entry is inserted; it faithfully assumes * that this is checked before. * Also note that the table grows DOWNward when compiling. #else * Scan the termcap entry string for a capability name. #endif *---*/ #include "_termcap.h" #ifdef RCS_ID static const char rcsid[] = "$Id: _tcpfind.c,v 1.4 1993/08/19 23:15:40 tom Exp tom $"; #endif #if !FASTCAP # ifdef HASHED /* a very simplistic hash function indeed */ # define HASHSIZE 32 /* power of 2! */ # define HASH(id) ((unsigned)(((id)[0]) + ((id)[1])) & (HASHSIZE-1)) static char * hashtable[HASHSIZE]; # endif #endif char * _tcpfind(cap) const char *cap; { #if FASTCAP # define MAKEKEY(key,cap) {register const char*t=cap; key=(t[0]<<8)|t[1];} register t_entry *p; int key; DPRINTF(("%.2s ", cap)); MAKEKEY(key, cap); { register int top = 0, end = _tcptable.t_size, med; /* * Store capabilities in reverse lexical order, so that copying * is minimized for termcap entries in normal lexical order. * (since we grow downward) */ while (top < end) { p = &_tcptable.t_body[med = (top + end) >> 1]; if (key > p->t_cap) end = med; else if (key < p->t_cap) top = med + 1; else { DPRINTF(("found @%d\n", med)); return (_tcptable.t_compiling) ? NULL : _TCP_VAL(p); } } } DPRINTF(("not found")); if (!_tcptable.t_compiling) { DPRINTF(("\n")); return NULL; } /* if we get here, we are compiling and should insert the entry. */ { # ifndef COPY_T # define COPY_T short /* * This assumes the table is aligned on a short boundary, and * sizeof(t_entry) is an integer multiple of sizeof(short). * (which is the case when not a pointer implementation, * or (sizeof(char *) % sizeof(short)) == 0) * Other reasonable choices are: char, int, or t_entry. */ # endif /* * Make room for a single new entry; shift everything before the * insertion point one position downward and adjust the base pointer. */ register COPY_T *s = (COPY_T *) _tcptable.t_body, *d = (COPY_T *) ((t_entry *) s - 1); _tcptable.t_body = (t_entry *) d; if (_tcptable.t_size == 0) { p = (t_entry *) d; } else { if (key > p->t_cap) --p; while (d < (COPY_T *) p) *d++ = *s++; } } _tcptable.t_size++; p->t_cap = key; DPRINTF(("-- insert @%d\n", (int)(p - _tcptable.t_body))); return (char *) p; #else /* ! FASTCAP */ register char *s; register const char *cp = cap; # ifdef HASHED if (s = hashtable[HASH(s)]) { while (!(*s++ == cp[0] && *s++ == cp[1])) { --s; do { if (*s == '\0') return NULL; } while (*s++ != ':'); } } return s; # else /* ! HASHED */ if (s = _tcpbuf) { while (*s) { if (*s++ == ':') { if (*s++ == cp[0] && *s++ == cp[1]) { return (s); } --s; } } } return NULL; # endif /* HASHED */ #endif /* FASTCAP */ } #if !FASTCAP # ifdef HASHED void _tcphash() { { register char *s = _tcpbuf; register char c; register char **hp; for (hp = hashtable; hp < &hashtable[HASHSIZE]; ) *hp++ = NULL; while (c = *s++) { if (c == '\\') if (*s++) continue; else break; if (c != ':') continue; if ((c = *s) <= ' ' || c == ':' || c >= 0177) continue; hp = &hashtable[HASH(s)]; if (*hp == NULL) *hp = s; } } # ifdef DEBUG { register int n = 0, i; register char *p; for (i = 0; i < HASHSIZE; i++) if (s = hashtable[i]) { n++; printf("hash %3d\t%.2s[%d]", i, s, (int)(s - _tcpbuf)); while (*s) { if (*s++ != ':') continue; if (*s <= ' ' || *s == ':' || *s >= 0177) continue; if (HASH(s) != i) continue; printf("\t%.2s[%d]", s, (int)(s - _tcpbuf)); } printf("\n"); } printf("---- occupied: %d of %d\n\n", n, HASHSIZE); } # endif /* DEBUG */ } # endif /* HASHED */ #endif /* !FASTCAP */ /*======================================================================* * $Log: _tcpfind.c,v $ * Revision 1.4 1993/08/19 23:15:40 tom * comment fix; fix typo in RCS Log. * *======================================================================*/