353 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			353 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*/
 | 
