/************************************************************************ * This program is Copyright (C) 1986 by Jonathan Payne. JOVE is * * provided to you without charge, and with no warranty. You may give * * away copies of JOVE, including sources, provided that this notice is * * included in all the files. * ************************************************************************/ #define NO_PROCDECL /* kludge to get this file through small v7 compiler */ #include "jove.h" RCS("$Id: funcdefs.c,v 14.30 1993/02/09 17:44:07 tom Exp tom $") #include "ctype.h" #include "maps.h" #ifdef IPROCS # include #endif /* * First we redefine the DEF_XXX macros and include the command list * to declare the routines. */ #undef DEF_CMD #undef DEF_MAJ #undef DEF_MIN #undef DEF_MAP #define DEF_CMD(name,f,opt) extern void f __((void)); #define DEF_MAJ(name,n,desc) #define DEF_MIN(name,n,desc) #define DEF_MAP(name,map,n) #include "funcs.inc" /* * Now we redefine the macros to make valid command table entries, and * include the command list again. */ #undef DEF_CMD #undef DEF_MAJ #undef DEF_MIN #undef DEF_MAP #define DEF_CMD(name,f,opt) {FUNCTION|opt,name,f}, #define DEF_MAJ(name,n,desc) {FUNCTION|MAJOR_MODE|ARG(n),name}, #define DEF_MIN(name,n,desc) {FUNCTION|MINOR_MODE|ARG(n),name}, #define DEF_MAP(name,map,n) {FUNCTION|PREFIX|ARG(n),name,(void(*)__((void)))&Maps[n]}, const Command commands[] = { # include "funcs.inc" FUNCTION, 0, 0 }; data_obj * findcom(prompt) const char *prompt; { static struct FIND_CACHE(sizeof commands/sizeof commands[0]) cache ZERO; return find_builtin((data_obj *) commands, (struct find_cache *) &cache, prompt); } /* * Support routine to find a builtin Command or Variable. */ data_obj * find_builtin(objtab, cache, prompt) const data_obj *objtab; struct find_cache *cache; const char *prompt; { register const data_obj *dp = objtab; #define objsize sizeof(Command) #ifdef objsize /* ...this assumes: */ ASSERT(sizeof(Command) == sizeof(Variable)); #else size_t objsize = sizeof(Command); if ((sizeof(Variable) != sizeof(Command)) /* optimization */&& (dp->Type & VARIABLE)) objsize = sizeof(Variable); #endif ASSERT((dp->Type & REALTYPEMASK) == FUNCTION || (dp->Type & REALTYPEMASK) == VARIABLE); /* do the address calculation ``by hand''. */ #define address(p, n) ((data_obj *)((char *) p + (n) * objsize)) #define hash(c) (islower(c) ? (c) - 'a' + 1 : 0) { register const char **names = cache->nametab; if (!names[0]) { /* initialize name- and hash table */ while (*names = dp->Name) { register int c = *(*names++); c = hash(c); if (!cache->hashtab[c]) cache->hashtab[c] = dp; dp = address(dp, 1); } dp = objtab; } if (!InJoverc) return address(dp, complete(names, (dp->Type & FUNCTION) ? CASEIND : NOTHING, prompt)); /* complete() now always returns a valid index (i.e. >= 0) */ } /* This is for faster startup. This just reads until a space or a tab or a newline character is reached, and then does a semi-hashed lookup on that string. This should be much faster than initializing the minibuffer for each line. The command list must be maintained in alphabetical order for this to work. */ { register char *cp = Minibuf; /* yes it is idle now */ register int c; register int len, found = 0; const data_obj *which; /* we "know" since we're in a .joverc that the command is supplied via Inputp. This avoids some overhead. */ if (Inputp) { while ((c = *Inputp) != '\0') { Inputp++; if (isspace(c)) { if (cp > Minibuf) break; continue; } if (c == '\n' || c == '\r') { break; } if (dp->Type & FUNCTION) c = tolower(c); *cp++ = c; } *cp = '\0'; } if ((len = cp - Minibuf) == 0) complain("[Premature end of line]"); /* look it up (in the reduced search space) */ if (c = Minibuf[0], dp = cache->hashtab[hash(c)]) { while ((cp = (char *)dp->Name) && (cp[0] <= c)) { if (numcomp(cp, Minibuf) == len) { if (cp[len] == '\0') /* exact match */ return (data_obj *) dp; found++; which = dp; } dp = address(dp, 1); } } if (--found) complain((found > 0) ? "[\"%s\" ambiguous]" : "[\"%s\" unknown]", Minibuf); #undef hash #undef address #undef objsize return (data_obj *) which; } } /* this is a dummy function for the poor man's version of JOVE */ void NonExisting() { s_mess("Sorry, \"%f\" is not available..."); } /*====================================================================== * $Log: funcdefs.c,v $ * Revision 14.30 1993/02/09 17:44:07 tom * cleanup whitespace; factor out joverc optimization to find_builtin() so * that findvar() can use it too; change DEF_MAP() to contain pointer to Keymap. * * Revision 14.28 1992/10/23 17:57:27 tom * change cast in DEF_MAP to full ANSI-prototype. * * Revision 14.26 1992/08/26 23:56:49 tom * add RCS directives. * */