352 lines
7.8 KiB
C
352 lines
7.8 KiB
C
/* ELLE - Copyright 1982, 1985, 1987 by Ken Harrenstien, SRI International
|
||
* This software is quasi-public; it may be used freely with
|
||
* like software, but may NOT be sold or made part of licensed
|
||
* products without permission of the author.
|
||
*/
|
||
/* EEDIAG - Error diagnostics and testing routines
|
||
*/
|
||
|
||
#include "elle.h"
|
||
|
||
#if FX_DEBUG
|
||
|
||
/* EFUN: "Debug Mode" */
|
||
/* With no arg, toggles self-checking on and off.
|
||
* With arg of 4 (^U), enters special debug/diagnostics mode.
|
||
*/
|
||
|
||
f_debug(ch)
|
||
int ch;
|
||
{ extern int (*vfy_vec)(); /* In E_MAIN.C */
|
||
char *vfy_data();
|
||
|
||
if(ch < 0) /* Internal call? */
|
||
{ dbg_diag();
|
||
return;
|
||
}
|
||
if(exp == 4)
|
||
{ askerr();
|
||
return;
|
||
}
|
||
if(vfy_vec) vfy_vec = 0; /* Toggle current value */
|
||
else vfy_vec = (int (*)())vfy_data;
|
||
say(vfy_vec ? "Self-checking on" : "Self-checking off");
|
||
}
|
||
|
||
char *
|
||
vfy_data(flag) /* Flag = 0 for quiet check */
|
||
int flag;
|
||
{
|
||
register char *res, *mess;
|
||
char *sbe_mvfy(), *sbe_sbvfy(), *sbe_svfy();
|
||
|
||
if(res = sbe_mvfy(0)) mess = "Mem mgt";
|
||
else if(res = sbe_sbvfy(cur_buf,0)) mess = "SBBUF";
|
||
else if(res = sbe_svfy(0)) mess = "SD list";
|
||
else return(0); /* Success */
|
||
|
||
if(flag)
|
||
{ int ostate = clean_exit();
|
||
printf("\n%s error: %s !!!\n",mess,res);
|
||
askerr();
|
||
if(ostate > 0) set_tty();
|
||
}
|
||
return(res); /* Error seen */
|
||
}
|
||
|
||
extern char *asklin();
|
||
extern int sbx_nfl,sbm_nfl;
|
||
|
||
char diaghelp[] = "\
|
||
Q - Quit diag mode\n\
|
||
! - Goto subshell\n\
|
||
V - Verify Mem & SD lists\n\
|
||
MF - Mem Freelist\n\
|
||
M - Mem list\n\
|
||
B - Current buffer SB\n\
|
||
DF - SD Freelist\n\
|
||
D - SDs in use\n\
|
||
DL - SD Logical lists\n\
|
||
DP - SD Physical lists\n\
|
||
C n - Compact; 0-7=sbx_comp(n), 8=SM freelist, 9=SD freelist.\n\
|
||
W - Window printout\n\
|
||
X n - Xercise randomly (GC every n)\n\
|
||
Z n - like X but with notes\n";
|
||
|
||
dbg_diag()
|
||
{ register char *cp;
|
||
register int c;
|
||
char linbuf[100];
|
||
char *sbe_mfl();
|
||
char *sbe_sfl();
|
||
char *sbe_sbs();
|
||
char *sbe_sdlist();
|
||
|
||
for(;;)
|
||
{ printf("D>");
|
||
asklin(cp = linbuf); /* Read a line of input */
|
||
switch(upcase(*cp++))
|
||
{
|
||
case '?':
|
||
writez(1,diaghelp); /* Too long for printf */
|
||
continue;
|
||
case '!':
|
||
f_pshinf(); /* Invoke inferior subshell */
|
||
clean_exit(); /* Restore normal modes */
|
||
continue;
|
||
case 'Q': /* Quit */
|
||
return;
|
||
|
||
case 'B': /* Print current SBBUF */
|
||
sbe_sbs(cur_buf,1);
|
||
continue;
|
||
|
||
case 'C': /* C n - Compact */
|
||
c = atoi(&linbuf[1]);
|
||
if(c == 8)
|
||
sbm_ngc(); /* GC the SM nodes */
|
||
#if 0 /* This doesn't work, dangerous to invoke. */
|
||
else if(c == 9)
|
||
sbm_xngc(&sbx_nfl,sizeof(struct sdblk),
|
||
SM_DNODS);
|
||
#endif
|
||
else
|
||
sbx_comp(512,c);
|
||
continue;
|
||
|
||
case 'D': /* Print all SD blocks in mem order */
|
||
switch(upcase(*cp))
|
||
{
|
||
case 0: /* D - all SDs in mem order */
|
||
sbe_sds();
|
||
continue;
|
||
case 'F': /* DF - SD freelist */
|
||
sbe_sfl(1);
|
||
continue;
|
||
case 'L': /* DL - SD logical list */
|
||
sbe_sdlist(1,0);
|
||
continue;
|
||
case 'P': /* DP - SD physical list */
|
||
sbe_sdlist(1,1);
|
||
continue;
|
||
}
|
||
break; /* failure */
|
||
|
||
case 'M':
|
||
switch(upcase(*cp))
|
||
{
|
||
case 0: /* M - all mem alloc info */
|
||
sbe_mem();
|
||
continue;
|
||
case 'F': /* MF - mem freelist */
|
||
sbe_mfl(1);
|
||
continue;
|
||
}
|
||
break; /* failure */
|
||
|
||
case 'V': /* Verify */
|
||
if(cp = vfy_data(0))
|
||
printf(" Failed: %s\n",cp);
|
||
else printf(" OK\n");
|
||
continue;
|
||
case 'W': /* Print out current window */
|
||
db_prwind(cur_win);
|
||
continue;
|
||
case 'X': /* Xercise */
|
||
c = atoi(&linbuf[1]);
|
||
vfy_exer(0, c ? c : 100);
|
||
continue;
|
||
case 'Z': /* Zercise */
|
||
c = atoi(&linbuf[1]);
|
||
vfy_exer(1, c ? c : 100);
|
||
continue;
|
||
|
||
} /* End of switch */
|
||
|
||
printf("?? Type ? for help\n");
|
||
} /* Loop forever */
|
||
}
|
||
|
||
|
||
/* VFY_EXER - a "random" editor exerciser. It creates a buffer,
|
||
* fills it with some patterned stuff, and then edits it
|
||
* pseudo-randomly in ways which retain the basic pattern.
|
||
* Frequent GC's and self-checks are done, and execution
|
||
* halted either when an error is seen or when typein is detected.
|
||
*/
|
||
char *xer_strs [] = {
|
||
"throne", "too", "sky", "fore", "fingers", "sex", "stone",
|
||
"010", "nazgul", "base"
|
||
};
|
||
|
||
|
||
vfy_exer(pf, gcfrq)
|
||
int pf; /* Nonzero to print notes as we go */
|
||
int gcfrq; /* Frequency of GC invocation (# passes per GC) */
|
||
{ register int i, k, c;
|
||
long npass;
|
||
char *res, linbuf[100];
|
||
chroff lbeg, lend;
|
||
struct buffer *bfp, *make_buf();
|
||
|
||
/* Clean out kill buffer first */
|
||
for(i = 0; i < KILL_LEN; ++i)
|
||
kill_push((SBSTR *)0);
|
||
|
||
bfp = make_buf("**EXORCISE**");
|
||
chg_buf(bfp);
|
||
i = 2000;
|
||
e_gobol();
|
||
do {
|
||
ed_sins("Line ");
|
||
ed_sins(xer_strs[i%10]);
|
||
e_putc(LF);
|
||
} while(--i);
|
||
if(pf) printf("Bufflen: %ld\n", e_blen());
|
||
|
||
/* Buffer now has stuff in it, start hacking. */
|
||
npass = 0;
|
||
srand(1); /* Start random seed */
|
||
for(;;)
|
||
{ if(tinwait() && (*asklin(linbuf)))
|
||
{ printf("Typein stop.\n");
|
||
break;
|
||
}
|
||
++npass;
|
||
printf(" Pass %ld",npass);
|
||
if(npass%gcfrq == 0) /* Time to do a GC? */
|
||
{
|
||
i = rand(); /* Level between 0-4 */
|
||
i = (i < 0 ? -i : i) % 5;
|
||
printf(" - GC lev %d\n", i);
|
||
sbx_comp(512,i);
|
||
goto xerchk;
|
||
}
|
||
|
||
k = (i = rand())%1024;
|
||
if (i&020000) k = -k;
|
||
e_igoff(k); /* Move randomly */
|
||
e_gobol(); /* Get stuff to flush */
|
||
lbeg = e_dot();
|
||
k = (i = rand())%64;
|
||
if(i&010000) k = -k;
|
||
e_igoff(k);
|
||
lend = e_nldot();
|
||
if(pf) printf(" Kill %ld/ %d;", lbeg, k);
|
||
ed_kill(lbeg, lend);
|
||
if(res = vfy_data(0))
|
||
{ printf("XERR after kill: %s\n",res);
|
||
break;
|
||
}
|
||
k = (i = rand())%2048;
|
||
if(i&04000) k = -k;
|
||
e_igoff(k);
|
||
e_gobol();
|
||
e_setcur();
|
||
if(pf) printf(" Yank %ld;", e_dot());
|
||
f_unkill(); /* Yank back */
|
||
if(res = vfy_data(0))
|
||
{ printf("XERR after yank: %s\n",res);
|
||
break;
|
||
}
|
||
last_cmd = YANKCMD;
|
||
for(i = rand()%4; i >= 0; --i)
|
||
{ if(pf) printf(" Pop;");
|
||
f_unkpop(); /* Do meta-Y */
|
||
if(res = vfy_data(0))
|
||
{ printf("XERR after pop: %s\n",res);
|
||
goto out;
|
||
}
|
||
}
|
||
if(rand()&07) /* Slowly add stuff */
|
||
{ if(pf) printf(" Add");
|
||
ed_sins("Line ");
|
||
ed_sins(xer_strs[rand()%10]);
|
||
e_putc(LF);
|
||
if(res = vfy_data(0))
|
||
{ printf("XERR after ins: %s\n",res);
|
||
break;
|
||
}
|
||
}
|
||
printf("\n");
|
||
|
||
/* Okay, done with this pass edits, run through the
|
||
* file to ensure pattern is still there
|
||
*/
|
||
xerchk: e_gobob();
|
||
while((c = e_getc()) != EOF)
|
||
if(c == LF && (c = e_getc()) != EOF)
|
||
{ if( c != 'L'
|
||
|| e_getc() != 'i'
|
||
|| e_getc() != 'n'
|
||
|| e_getc() != 'e'
|
||
|| e_getc() != ' ')
|
||
{ printf("XERR in pattern!\n");
|
||
goto out;
|
||
}
|
||
}
|
||
}
|
||
/* User typein or error, stop. */
|
||
out: e_setcur();
|
||
redp(RD_SCREEN);
|
||
printf("Loop count = %ld\n",npass);
|
||
}
|
||
|
||
/* DB_PRWIND(win) - Print out stuff about given window
|
||
*/
|
||
db_prwind(w)
|
||
register struct window *w;
|
||
{ register struct scr_line *s;
|
||
register int i;
|
||
char tstr[MAXLINE+MAXCHAR];
|
||
char *db_scflgs();
|
||
|
||
printf("cur_dot/ %ld cur_buf/ %o cur_win/ %o\n",
|
||
cur_dot, cur_buf, cur_win);
|
||
|
||
printf("Window %o:\n", w);
|
||
printf(" next/ %o\n", w->w_next);
|
||
printf(" buf / %o\n", w->w_buf);
|
||
printf(" redp/ %o\n", w->w_redp);
|
||
|
||
printf(" topldot/ %ld\n", w->w_topldot);
|
||
printf(" dot / %ld\n", w->w_dot);
|
||
printf(" bmod/ %ld\n", w->w_bmod);
|
||
printf(" emod/ %ld\n", w->w_emod);
|
||
printf(" oldz/ %ld\n", w->w_oldz);
|
||
|
||
printf(" pos / %d\n", w->w_pos);
|
||
printf(" ht / %d\n", w->w_ht);
|
||
printf("\
|
||
# Flags Boff Len ! Cols Line\n");
|
||
for(i = w->w_pos; i < w->w_pos + w->w_ht; ++i)
|
||
{ s = scr[i];
|
||
printf("%2d %-5.5s %6ld %3d %1d %4d ",
|
||
i, db_scflgs(s->sl_flg), s->sl_boff, s->sl_len,
|
||
s->sl_cont, s->sl_col);
|
||
strncpy(tstr, s->sl_line, MAXLINE);
|
||
tstr[s->sl_col] = 0;
|
||
printf("%-40.40s\n", tstr);
|
||
if(s->sl_flg&SL_MOD)
|
||
{ printf("%26d ", s->sl_ncol);
|
||
strncpy(tstr, s->sl_nlin, MAXLINE);
|
||
tstr[s->sl_ncol] = 0;
|
||
printf("%-40.40s\n", tstr);
|
||
}
|
||
}
|
||
}
|
||
|
||
char *
|
||
db_scflgs(flags)
|
||
int flags;
|
||
{ static char retstr[10];
|
||
register char *cp;
|
||
|
||
cp = retstr;
|
||
if(flags&SL_MOD) *cp++ = 'M';
|
||
if(flags&SL_EOL) *cp++ = 'E';
|
||
*cp = 0;
|
||
return(retstr);
|
||
}
|
||
|
||
#endif /*FX_DEBUG*/
|