| 1 | /* ELLE - Copyright 1982, 1985, 1987 by Ken Harrenstien, SRI International
 | 
|---|
| 2 |  *      This software is quasi-public; it may be used freely with
 | 
|---|
| 3 |  *      like software, but may NOT be sold or made part of licensed
 | 
|---|
| 4 |  *      products without permission of the author.
 | 
|---|
| 5 |  */
 | 
|---|
| 6 | /*      EEDIAG - Error diagnostics and testing routines
 | 
|---|
| 7 |  */
 | 
|---|
| 8 | 
 | 
|---|
| 9 | #include "elle.h"
 | 
|---|
| 10 | 
 | 
|---|
| 11 | #if FX_DEBUG
 | 
|---|
| 12 | 
 | 
|---|
| 13 | /* EFUN: "Debug Mode" */
 | 
|---|
| 14 | /*      With no arg, toggles self-checking on and off.
 | 
|---|
| 15 |  *      With arg of 4 (^U), enters special debug/diagnostics mode.
 | 
|---|
| 16 |  */
 | 
|---|
| 17 | 
 | 
|---|
| 18 | f_debug(ch)
 | 
|---|
| 19 | int ch;
 | 
|---|
| 20 | {       extern int (*vfy_vec)();        /* In E_MAIN.C */
 | 
|---|
| 21 |         char *vfy_data();
 | 
|---|
| 22 | 
 | 
|---|
| 23 |         if(ch < 0)              /* Internal call? */
 | 
|---|
| 24 |           {     dbg_diag();
 | 
|---|
| 25 |                 return;
 | 
|---|
| 26 |           }
 | 
|---|
| 27 |         if(exp == 4)
 | 
|---|
| 28 |           {     askerr();
 | 
|---|
| 29 |                 return;
 | 
|---|
| 30 |           }
 | 
|---|
| 31 |         if(vfy_vec) vfy_vec = 0;                /* Toggle current value */
 | 
|---|
| 32 |         else vfy_vec = (int (*)())vfy_data;
 | 
|---|
| 33 |         say(vfy_vec ? "Self-checking on" : "Self-checking off");
 | 
|---|
| 34 | }
 | 
|---|
| 35 |  | 
|---|
| 36 | 
 | 
|---|
| 37 | char *
 | 
|---|
| 38 | vfy_data(flag)          /* Flag = 0 for quiet check */
 | 
|---|
| 39 | int flag;
 | 
|---|
| 40 | {
 | 
|---|
| 41 |         register char *res, *mess;
 | 
|---|
| 42 |         char *sbe_mvfy(), *sbe_sbvfy(), *sbe_svfy();
 | 
|---|
| 43 | 
 | 
|---|
| 44 |         if(res = sbe_mvfy(0)) mess = "Mem mgt";
 | 
|---|
| 45 |         else if(res = sbe_sbvfy(cur_buf,0)) mess = "SBBUF";
 | 
|---|
| 46 |         else if(res = sbe_svfy(0)) mess = "SD list";
 | 
|---|
| 47 |         else return(0);         /* Success */
 | 
|---|
| 48 | 
 | 
|---|
| 49 |         if(flag)
 | 
|---|
| 50 |           {     int ostate = clean_exit();
 | 
|---|
| 51 |                 printf("\n%s error: %s !!!\n",mess,res);
 | 
|---|
| 52 |                 askerr();
 | 
|---|
| 53 |                 if(ostate > 0) set_tty();
 | 
|---|
| 54 |           }
 | 
|---|
| 55 |         return(res);    /* Error seen */
 | 
|---|
| 56 | }
 | 
|---|
| 57 |  | 
|---|
| 58 | 
 | 
|---|
| 59 | extern char *asklin();
 | 
|---|
| 60 | extern int sbx_nfl,sbm_nfl;
 | 
|---|
| 61 | 
 | 
|---|
| 62 | char diaghelp[] = "\
 | 
|---|
| 63 | Q - Quit diag mode\n\
 | 
|---|
| 64 | ! - Goto subshell\n\
 | 
|---|
| 65 | V - Verify Mem & SD lists\n\
 | 
|---|
| 66 | MF - Mem Freelist\n\
 | 
|---|
| 67 | M  - Mem list\n\
 | 
|---|
| 68 | B  - Current buffer SB\n\
 | 
|---|
| 69 | DF - SD Freelist\n\
 | 
|---|
| 70 | D  - SDs in use\n\
 | 
|---|
| 71 | DL - SD Logical lists\n\
 | 
|---|
| 72 | DP - SD Physical lists\n\
 | 
|---|
| 73 | C n - Compact; 0-7=sbx_comp(n), 8=SM freelist, 9=SD freelist.\n\
 | 
|---|
| 74 | W  - Window printout\n\
 | 
|---|
| 75 | X n - Xercise randomly (GC every n)\n\
 | 
|---|
| 76 | Z n - like X but with notes\n";
 | 
|---|
| 77 | 
 | 
|---|
| 78 | dbg_diag()
 | 
|---|
| 79 | {       register char *cp;
 | 
|---|
| 80 |         register int c;
 | 
|---|
| 81 |         char linbuf[100];
 | 
|---|
| 82 |         char *sbe_mfl();
 | 
|---|
| 83 |         char *sbe_sfl();
 | 
|---|
| 84 |         char *sbe_sbs();
 | 
|---|
| 85 |         char *sbe_sdlist();
 | 
|---|
| 86 | 
 | 
|---|
| 87 |     for(;;)
 | 
|---|
| 88 |     {   printf("D>");
 | 
|---|
| 89 |         asklin(cp = linbuf);                    /* Read a line of input */
 | 
|---|
| 90 |         switch(upcase(*cp++))
 | 
|---|
| 91 |           {
 | 
|---|
| 92 |         case '?':
 | 
|---|
| 93 |                 writez(1,diaghelp);     /* Too long for printf */
 | 
|---|
| 94 |                 continue;
 | 
|---|
| 95 |         case '!':
 | 
|---|
| 96 |                 f_pshinf();             /* Invoke inferior subshell */
 | 
|---|
| 97 |                 clean_exit();           /* Restore normal modes */
 | 
|---|
| 98 |                 continue;
 | 
|---|
| 99 |         case 'Q':               /* Quit */
 | 
|---|
| 100 |                 return;
 | 
|---|
| 101 | 
 | 
|---|
| 102 |         case 'B':               /* Print current SBBUF */
 | 
|---|
| 103 |                 sbe_sbs(cur_buf,1);
 | 
|---|
| 104 |                 continue;
 | 
|---|
| 105 | 
 | 
|---|
| 106 |         case 'C':               /* C n - Compact */
 | 
|---|
| 107 |                 c = atoi(&linbuf[1]);
 | 
|---|
| 108 |                 if(c == 8)
 | 
|---|
| 109 |                         sbm_ngc();      /* GC the SM nodes */
 | 
|---|
| 110 | #if 0 /* This doesn't work, dangerous to invoke. */
 | 
|---|
| 111 |                 else if(c == 9)
 | 
|---|
| 112 |                         sbm_xngc(&sbx_nfl,sizeof(struct sdblk),
 | 
|---|
| 113 |                                 SM_DNODS);
 | 
|---|
| 114 | #endif
 | 
|---|
| 115 |                 else
 | 
|---|
| 116 |                         sbx_comp(512,c);
 | 
|---|
| 117 |                 continue;
 | 
|---|
| 118 | 
 | 
|---|
| 119 |         case 'D':               /* Print all SD blocks in mem order */
 | 
|---|
| 120 |                 switch(upcase(*cp))
 | 
|---|
| 121 |                   {
 | 
|---|
| 122 |                 case 0:         /* D - all SDs in mem order */
 | 
|---|
| 123 |                         sbe_sds();
 | 
|---|
| 124 |                         continue;
 | 
|---|
| 125 |                 case 'F':       /* DF - SD freelist */
 | 
|---|
| 126 |                         sbe_sfl(1);
 | 
|---|
| 127 |                         continue;
 | 
|---|
| 128 |                 case 'L':       /* DL - SD logical list */
 | 
|---|
| 129 |                         sbe_sdlist(1,0);
 | 
|---|
| 130 |                         continue;
 | 
|---|
| 131 |                 case 'P':       /* DP - SD physical list */
 | 
|---|
| 132 |                         sbe_sdlist(1,1);
 | 
|---|
| 133 |                         continue;
 | 
|---|
| 134 |                   }
 | 
|---|
| 135 |                 break;          /* failure */
 | 
|---|
| 136 | 
 | 
|---|
| 137 |         case 'M':       
 | 
|---|
| 138 |                 switch(upcase(*cp))
 | 
|---|
| 139 |                   {
 | 
|---|
| 140 |                 case 0:         /* M - all mem alloc info */
 | 
|---|
| 141 |                         sbe_mem();
 | 
|---|
| 142 |                         continue;
 | 
|---|
| 143 |                 case 'F':       /* MF - mem freelist */
 | 
|---|
| 144 |                         sbe_mfl(1);
 | 
|---|
| 145 |                         continue;
 | 
|---|
| 146 |                   }
 | 
|---|
| 147 |                 break;          /* failure */
 | 
|---|
| 148 | 
 | 
|---|
| 149 |         case 'V':               /* Verify */
 | 
|---|
| 150 |                 if(cp = vfy_data(0))
 | 
|---|
| 151 |                         printf("  Failed: %s\n",cp);
 | 
|---|
| 152 |                 else printf("  OK\n");
 | 
|---|
| 153 |                 continue;
 | 
|---|
| 154 |         case 'W':               /* Print out current window */
 | 
|---|
| 155 |                 db_prwind(cur_win);
 | 
|---|
| 156 |                 continue;
 | 
|---|
| 157 |         case 'X':               /* Xercise */
 | 
|---|
| 158 |                 c = atoi(&linbuf[1]);
 | 
|---|
| 159 |                 vfy_exer(0, c ? c : 100);
 | 
|---|
| 160 |                 continue;
 | 
|---|
| 161 |         case 'Z':               /* Zercise */
 | 
|---|
| 162 |                 c = atoi(&linbuf[1]);
 | 
|---|
| 163 |                 vfy_exer(1, c ? c : 100);
 | 
|---|
| 164 |                 continue;
 | 
|---|
| 165 | 
 | 
|---|
| 166 |           }     /* End of switch */
 | 
|---|
| 167 | 
 | 
|---|
| 168 |         printf("?? Type ? for help\n");
 | 
|---|
| 169 |     }   /* Loop forever */
 | 
|---|
| 170 | }
 | 
|---|
| 171 |  | 
|---|
| 172 | 
 | 
|---|
| 173 | 
 | 
|---|
| 174 | /* VFY_EXER - a "random" editor exerciser.  It creates a buffer,
 | 
|---|
| 175 |  *      fills it with some patterned stuff, and then edits it
 | 
|---|
| 176 |  *      pseudo-randomly in ways which retain the basic pattern.
 | 
|---|
| 177 |  *      Frequent GC's and self-checks are done, and execution
 | 
|---|
| 178 |  *      halted either when an error is seen or when typein is detected.
 | 
|---|
| 179 |  */
 | 
|---|
| 180 | char *xer_strs [] = {
 | 
|---|
| 181 |         "throne", "too", "sky", "fore", "fingers", "sex", "stone",
 | 
|---|
| 182 |         "010", "nazgul", "base"
 | 
|---|
| 183 | };
 | 
|---|
| 184 | 
 | 
|---|
| 185 | 
 | 
|---|
| 186 | vfy_exer(pf, gcfrq)
 | 
|---|
| 187 | int pf;                 /* Nonzero to print notes as we go */
 | 
|---|
| 188 | int gcfrq;              /* Frequency of GC invocation (# passes per GC) */
 | 
|---|
| 189 | {       register int i, k, c;
 | 
|---|
| 190 |         long npass;
 | 
|---|
| 191 |         char *res, linbuf[100];
 | 
|---|
| 192 |         chroff lbeg, lend;
 | 
|---|
| 193 |         struct buffer *bfp, *make_buf();
 | 
|---|
| 194 | 
 | 
|---|
| 195 |         /* Clean out kill buffer first */
 | 
|---|
| 196 |         for(i = 0; i < KILL_LEN; ++i)
 | 
|---|
| 197 |                 kill_push((SBSTR *)0);
 | 
|---|
| 198 | 
 | 
|---|
| 199 |         bfp = make_buf("**EXORCISE**");
 | 
|---|
| 200 |         chg_buf(bfp);
 | 
|---|
| 201 |         i = 2000;
 | 
|---|
| 202 |         e_gobol();
 | 
|---|
| 203 |         do {
 | 
|---|
| 204 |                 ed_sins("Line ");
 | 
|---|
| 205 |                 ed_sins(xer_strs[i%10]);
 | 
|---|
| 206 |                 e_putc(LF);
 | 
|---|
| 207 |           } while(--i);
 | 
|---|
| 208 |         if(pf) printf("Bufflen: %ld\n", e_blen());
 | 
|---|
| 209 | 
 | 
|---|
| 210 |         /* Buffer now has stuff in it, start hacking. */
 | 
|---|
| 211 |         npass = 0;
 | 
|---|
| 212 |         srand(1);       /* Start random seed */
 | 
|---|
| 213 |         for(;;)
 | 
|---|
| 214 |           {     if(tinwait() && (*asklin(linbuf)))
 | 
|---|
| 215 |                   {     printf("Typein stop.\n");
 | 
|---|
| 216 |                         break;
 | 
|---|
| 217 |                   }
 | 
|---|
| 218 |                 ++npass;
 | 
|---|
| 219 |                 printf(" Pass %ld",npass);
 | 
|---|
| 220 |                 if(npass%gcfrq == 0)            /* Time to do a GC? */
 | 
|---|
| 221 |                   {
 | 
|---|
| 222 |                         i = rand();             /* Level between 0-4 */
 | 
|---|
| 223 |                         i = (i < 0 ? -i : i) % 5;
 | 
|---|
| 224 |                         printf(" - GC lev %d\n", i);
 | 
|---|
| 225 |                         sbx_comp(512,i);
 | 
|---|
| 226 |                         goto xerchk;
 | 
|---|
| 227 |                   }
 | 
|---|
| 228 | 
 | 
|---|
| 229 |                 k = (i = rand())%1024;
 | 
|---|
| 230 |                 if (i&020000) k = -k;
 | 
|---|
| 231 |                 e_igoff(k);             /* Move randomly */
 | 
|---|
| 232 |                 e_gobol();              /* Get stuff to flush */
 | 
|---|
| 233 |                 lbeg = e_dot();
 | 
|---|
| 234 |                 k = (i = rand())%64;
 | 
|---|
| 235 |                 if(i&010000) k = -k;
 | 
|---|
| 236 |                 e_igoff(k);
 | 
|---|
| 237 |                 lend = e_nldot();
 | 
|---|
| 238 |                 if(pf) printf(" Kill %ld/ %d;", lbeg, k);
 | 
|---|
| 239 |                 ed_kill(lbeg, lend);
 | 
|---|
| 240 |                 if(res = vfy_data(0))
 | 
|---|
| 241 |                   {     printf("XERR after kill: %s\n",res);
 | 
|---|
| 242 |                         break;
 | 
|---|
| 243 |                   }
 | 
|---|
| 244 |                 k = (i = rand())%2048;
 | 
|---|
| 245 |                 if(i&04000) k = -k;
 | 
|---|
| 246 |                 e_igoff(k);
 | 
|---|
| 247 |                 e_gobol();
 | 
|---|
| 248 |                 e_setcur();
 | 
|---|
| 249 |                 if(pf) printf(" Yank %ld;", e_dot());
 | 
|---|
| 250 |                 f_unkill();             /* Yank back */
 | 
|---|
| 251 |                 if(res = vfy_data(0))
 | 
|---|
| 252 |                   {     printf("XERR after yank: %s\n",res);
 | 
|---|
| 253 |                         break;
 | 
|---|
| 254 |                   }
 | 
|---|
| 255 |                 last_cmd = YANKCMD;
 | 
|---|
| 256 |                 for(i = rand()%4; i >= 0; --i)
 | 
|---|
| 257 |                   {     if(pf) printf(" Pop;");
 | 
|---|
| 258 |                         f_unkpop();     /* Do meta-Y */
 | 
|---|
| 259 |                         if(res = vfy_data(0))
 | 
|---|
| 260 |                           {     printf("XERR after pop: %s\n",res);
 | 
|---|
| 261 |                                 goto out;
 | 
|---|
| 262 |                           }
 | 
|---|
| 263 |                   }
 | 
|---|
| 264 |                 if(rand()&07)   /* Slowly add stuff */
 | 
|---|
| 265 |                   {     if(pf) printf(" Add");
 | 
|---|
| 266 |                         ed_sins("Line ");
 | 
|---|
| 267 |                         ed_sins(xer_strs[rand()%10]);
 | 
|---|
| 268 |                         e_putc(LF);
 | 
|---|
| 269 |                         if(res = vfy_data(0))
 | 
|---|
| 270 |                           {     printf("XERR after ins: %s\n",res);
 | 
|---|
| 271 |                                 break;
 | 
|---|
| 272 |                           }
 | 
|---|
| 273 |                   }
 | 
|---|
| 274 |                 printf("\n");
 | 
|---|
| 275 | 
 | 
|---|
| 276 |                 /* Okay, done with this pass edits, run through the
 | 
|---|
| 277 |                  * file to ensure pattern is still there
 | 
|---|
| 278 |                  */
 | 
|---|
| 279 |         xerchk: e_gobob();
 | 
|---|
| 280 |                 while((c = e_getc()) != EOF)
 | 
|---|
| 281 |                         if(c == LF && (c = e_getc()) != EOF)
 | 
|---|
| 282 |                           {     if(         c != 'L'
 | 
|---|
| 283 |                                   || e_getc() != 'i'
 | 
|---|
| 284 |                                   || e_getc() != 'n'
 | 
|---|
| 285 |                                   || e_getc() != 'e'
 | 
|---|
| 286 |                                   || e_getc() != ' ')
 | 
|---|
| 287 |                                   {     printf("XERR in pattern!\n");
 | 
|---|
| 288 |                                         goto out;
 | 
|---|
| 289 |                                   }
 | 
|---|
| 290 |                           }
 | 
|---|
| 291 |           }
 | 
|---|
| 292 |         /* User typein or error, stop. */
 | 
|---|
| 293 | out:    e_setcur();
 | 
|---|
| 294 |         redp(RD_SCREEN);
 | 
|---|
| 295 |         printf("Loop count = %ld\n",npass);
 | 
|---|
| 296 | }
 | 
|---|
| 297 |  | 
|---|
| 298 | 
 | 
|---|
| 299 | /* DB_PRWIND(win) - Print out stuff about given window
 | 
|---|
| 300 |  */
 | 
|---|
| 301 | db_prwind(w)
 | 
|---|
| 302 | register struct window *w;
 | 
|---|
| 303 | {       register struct scr_line *s;
 | 
|---|
| 304 |         register int i;
 | 
|---|
| 305 |         char tstr[MAXLINE+MAXCHAR];
 | 
|---|
| 306 |         char *db_scflgs();
 | 
|---|
| 307 | 
 | 
|---|
| 308 |         printf("cur_dot/ %ld  cur_buf/ %o cur_win/ %o\n",
 | 
|---|
| 309 |                 cur_dot, cur_buf, cur_win);
 | 
|---|
| 310 | 
 | 
|---|
| 311 |         printf("Window %o:\n", w);
 | 
|---|
| 312 |         printf("  next/ %o\n", w->w_next);
 | 
|---|
| 313 |         printf("  buf / %o\n", w->w_buf);
 | 
|---|
| 314 |         printf("  redp/ %o\n", w->w_redp);
 | 
|---|
| 315 | 
 | 
|---|
| 316 |         printf("  topldot/ %ld\n", w->w_topldot);
 | 
|---|
| 317 |         printf("  dot / %ld\n", w->w_dot);
 | 
|---|
| 318 |         printf("  bmod/ %ld\n", w->w_bmod);
 | 
|---|
| 319 |         printf("  emod/ %ld\n", w->w_emod);
 | 
|---|
| 320 |         printf("  oldz/ %ld\n", w->w_oldz);
 | 
|---|
| 321 | 
 | 
|---|
| 322 |         printf("  pos / %d\n", w->w_pos);
 | 
|---|
| 323 |         printf("  ht  / %d\n", w->w_ht);
 | 
|---|
| 324 |         printf("\
 | 
|---|
| 325 | #  Flags   Boff Len ! Cols Line\n");
 | 
|---|
| 326 |         for(i = w->w_pos; i < w->w_pos + w->w_ht; ++i)
 | 
|---|
| 327 |           {     s = scr[i];
 | 
|---|
| 328 |                 printf("%2d %-5.5s %6ld %3d %1d %4d ",
 | 
|---|
| 329 |                         i, db_scflgs(s->sl_flg), s->sl_boff, s->sl_len,
 | 
|---|
| 330 |                         s->sl_cont, s->sl_col);
 | 
|---|
| 331 |                 strncpy(tstr, s->sl_line, MAXLINE);
 | 
|---|
| 332 |                 tstr[s->sl_col] = 0;
 | 
|---|
| 333 |                 printf("%-40.40s\n", tstr);
 | 
|---|
| 334 |                 if(s->sl_flg&SL_MOD)
 | 
|---|
| 335 |                   {     printf("%26d ", s->sl_ncol);
 | 
|---|
| 336 |                         strncpy(tstr, s->sl_nlin, MAXLINE);
 | 
|---|
| 337 |                         tstr[s->sl_ncol] = 0;
 | 
|---|
| 338 |                         printf("%-40.40s\n", tstr);
 | 
|---|
| 339 |                   }
 | 
|---|
| 340 |           }
 | 
|---|
| 341 | }
 | 
|---|
| 342 | 
 | 
|---|
| 343 | char *
 | 
|---|
| 344 | db_scflgs(flags)
 | 
|---|
| 345 | int flags;
 | 
|---|
| 346 | {       static char retstr[10];
 | 
|---|
| 347 |         register char *cp;
 | 
|---|
| 348 |         
 | 
|---|
| 349 |         cp = retstr;
 | 
|---|
| 350 |         if(flags&SL_MOD) *cp++ = 'M';
 | 
|---|
| 351 |         if(flags&SL_EOL) *cp++ = 'E';
 | 
|---|
| 352 |         *cp = 0;
 | 
|---|
| 353 |         return(retstr);
 | 
|---|
| 354 | }
 | 
|---|
| 355 | 
 | 
|---|
| 356 | #endif /*FX_DEBUG*/
 | 
|---|