/* do a binary search for an address returning its aindex number; * if multiple entries exist, return the highest index. */ int cexpSymTblLkAddrIdx(void *addr, int margin, FILE *f, CexpSymTbl t) { int lo,hi,mid; lo=0; hi=t->nentries-1; while (lo < hi) { mid=(lo+hi+1)>>1; /* round up */ if (addr < (void*)t->aindex[mid]->value.ptv) hi = mid-1; else lo = mid; } mid=lo; if (f) { lo=mid-margin; if (lo<0) lo=0; hi=mid+margin; if (hi>=t->nentries) hi=t->nentries-1; while (lo<=hi) cexpSymPrintInfo(t->aindex[lo++],f); } return mid; }
/* currently, we have only very rudimentary support; just enough * for 'HELP' */ static char * symHelp(CexpTypedVal returnVal, CexpSym sym, va_list ap) { CexpTypedVal v; char *newhelp=0; int verbose=0; returnVal->type=TUCharP; returnVal->tv.p=sym->help; if ((v=va_arg(ap,CexpTypedVal))) { switch (v->type) { case TUCharP: newhelp = v->tv.p; break; case TUInt: verbose = v->tv.i; break; case TULong: verbose = v->tv.l; break; default: return "Cexp Help: Warning, invalid argument"; } } if (newhelp) { if (sym->flags & CEXP_SYMFLG_MALLOC_HELP) free(sym->help); #if defined(CONFIG_STRINGS_LIVE_FOREVER) && 0 /* might come from another module; we better make a copy */ /* the help storage is probably an 'eternal' string */ sym->help=newhelp; #else sym->help=strdup(newhelp); sym->flags |= CEXP_SYMFLG_MALLOC_HELP; #endif } else { if (verbose || !sym->help) { CexpSym s; CexpModule m; if ((s=cexpSymLkAddr(sym->value.ptv,0,0,&m)) && s==sym && m) { fprintf(stdout,"In module %s:\n",cexpModuleName(m)); } else if ((s=cexpVarLookup(sym->name,0)) && s==sym) { fprintf(stdout,"User Variable:\n"); } cexpSymPrintInfo(sym,stdout); } if (sym->help) fprintf(stdout,"%s\n",sym->help); else fprintf(stdout,"No help available\n"); } return 0; }
static void * varprint(const char *name, CexpSym s, void *arg) { FILE *f=stdout; cexp_regex *rc=arg; if (cexp_regexec(rc,name)) { cexpSymPrintInfo(s,f); } return 0; }
/* TODO should acquire the module readlock around this ?? */ for (s=0,m=0; !ch ;) { unsigned char ans; #ifdef HAVE_TECLA { GlTerminalSize ts; ts.nline = 24; ts.ncolumn = 80; cexpResizeTerminal(&ts); nl = ts.nline; } #else nl = ioctl(STDIN_FD, TIOCGWINSZ,&win) ? tgetnum("li") : win.ws_row; #endif if (nl<=0) nl=24; nl--; if (!(s=_cexpSymLookupRegex(rc,&nl,s,stdout,&m))) break; if (!tsaved) { tsaved=1; if (tcgetattr(STDIN_FD,&tatts)) { tsaved=-1; } else { rawatts=tatts; rawatts.c_lflag &= ~ICANON; rawatts.c_cc[VMIN] = 1; } } printf("More (Y/n)?:"); fflush(stdout); if (tsaved>0) tcsetattr(STDIN_FD,TCSANOW,&rawatts); ch = (1 == read(STDIN_FD,&ans,1) ? ans : 'Y'); if ('Y'==toupper(ch) || '\n'==ch || '\r'==ch) ch=0; if (tsaved>0) tcsetattr(STDIN_FD,TCSANOW,&tatts); } printf("\nUSER VARIABLES:\n"); cexpVarWalk(varprint,(void*)rc); if (rc) cexp_regfree(rc); return 0; } #if 0 /* obsoleted by 'help' */ int whatis(char *name, FILE *f) { CexpSym s; int rval=-1; CexpModule mod; if (!f) f=stdout; if ((s=cexpSymLookup(name,&mod))) { fprintf(f,"Module '%s' Symbol Table:\n", cexpModuleName(mod)); cexpSymPrintInfo(s,f); rval=0; } if ((s=cexpVarLookup(name,0))) { fprintf(f,"User Variable:\n"); cexpSymPrintInfo(s,f); rval=0; } return rval; }
/* a semi-public routine which takes a precompiled regexp. * The reason this is not public is that we try to keep * the public from having to deal with/know about the regexp * implementation, i.e. which variant, which headers etc. */ CexpSym _cexpSymTblLookupRegex(cexp_regex *rc, int *pmax, CexpSym s, FILE *f, CexpSymTbl t) { CexpSym found=0; int max=24; if (!pmax) pmax=&max; if (!s) s=t->syms; while (s->name && *pmax) { if (cexp_regexec(rc,s->name)) { if (f) cexpSymPrintInfo(s,f); (*pmax)--; found=s; } s++; } return s->name ? found : 0; }