diff options
Diffstat (limited to 'editors')
-rw-r--r-- | editors/vi.c | 859 |
1 files changed, 450 insertions, 409 deletions
diff --git a/editors/vi.c b/editors/vi.c index 835adb6..8e9ecc9 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -19,7 +19,7 @@ */ static const char vi_Version[] = - "$Id: vi.c,v 1.25 2002/11/28 11:27:23 aaronl Exp $"; + "$Id: vi.c,v 1.26 2002/12/02 21:18:08 bug1 Exp $"; /* * To compile for standalone use: @@ -87,6 +87,12 @@ static const char vi_Version[] = #include "busybox.h" #endif /* STANDALONE */ +#ifdef CONFIG_LOCALE_SUPPORT +#define Isprint(c) isprint((c)) +#else +#define Isprint(c) ( (c) >= ' ' && (c) != 127 && (c) != ((unsigned char)'\233') ) +#endif + #ifndef TRUE #define TRUE ((int)1) #define FALSE ((int)0) @@ -116,6 +122,22 @@ static const char vi_Version[] = #define VI_K_FUN11 147 // Function Key F11 #define VI_K_FUN12 148 // Function Key F12 +/* vt102 typical ESC sequence */ +/* terminal standout start/normal ESC sequence */ +static const char SOs[] = "\033[7m"; +static const char SOn[] = "\033[0m"; +/* terminal bell sequence */ +static const char bell[] = "\007"; +/* Clear-end-of-line and Clear-end-of-screen ESC sequence */ +static const char Ceol[] = "\033[0K"; +static const char Ceos [] = "\033[0J"; +/* Cursor motion arbitrary destination ESC sequence */ +static const char CMrc[] = "\033[%d;%dH"; +/* Cursor motion up and down ESC sequence */ +static const char CMup[] = "\033[A"; +static const char CMdown[] = "\n"; + + static const int YANKONLY = FALSE; static const int YANKDEL = TRUE; static const int FORWARD = 1; // code depends on "1" for array index @@ -131,27 +153,29 @@ static const int S_END_ALNUM = 5; // used in skip_thing() for moving "dot" typedef unsigned char Byte; +static int vi_setops; +#define VI_AUTOINDENT 1 +#define VI_SHOWMATCH 2 +#define VI_IGNORECASE 4 +#define VI_ERR_METHOD 8 +#define autoindent (vi_setops & VI_AUTOINDENT) +#define showmatch (vi_setops & VI_SHOWMATCH ) +#define ignorecase (vi_setops & VI_IGNORECASE) +/* indicate error with beep or flash */ +#define err_method (vi_setops & VI_ERR_METHOD) + static int editing; // >0 while we are editing a file static int cmd_mode; // 0=command 1=insert static int file_modified; // buffer contents changed -static int err_method; // indicate error with beep or flash static int fn_start; // index of first cmd line file name static int save_argc; // how many file names on cmd line static int cmdcnt; // repetition count static fd_set rfds; // use select() for small sleeps static struct timeval tv; // use select() for small sleeps -static char erase_char; // the users erase character static int rows, columns; // the terminal screen is this size static int crow, ccol, offset; // cursor is on Crow x Ccol with Horz Ofset -static char *SOs, *SOn; // terminal standout start/normal ESC sequence -static char *bell; // terminal bell sequence -static char *Ceol, *Ceos; // Clear-end-of-line and Clear-end-of-screen ESC sequence -static char *CMrc; // Cursor motion arbitrary destination ESC sequence -static char *CMup, *CMdown; // Cursor motion up and down ESC sequence static Byte *status_buffer; // mesages to the user -static Byte last_input_char; // last char read from user -static Byte last_forward_char; // last char searched for with 'f' static Byte *cfn; // previous, current, and next file name static Byte *text, *end, *textend; // pointers to the user data in memory static Byte *screen; // pointer to the virtual screen buffer @@ -160,6 +184,9 @@ static Byte *screenbegin; // index into text[], of top line on the screen static Byte *dot; // where all the action takes place static int tabstop; static struct termios term_orig, term_vi; // remember what the cooked mode was +static Byte erase_char; // the users erase character +static Byte last_input_char; // last char read from user +static Byte last_forward_char; // last char searched for with 'f' #ifdef CONFIG_FEATURE_VI_OPTIMIZE_CURSOR static int last_row; // where the cursor was last moved to @@ -167,6 +194,9 @@ static int last_row; // where the cursor was last moved to #ifdef CONFIG_FEATURE_VI_USE_SIGNALS static jmp_buf restart; // catch_sig() #endif /* CONFIG_FEATURE_VI_USE_SIGNALS */ +#if defined(CONFIG_FEATURE_VI_USE_SIGNALS) || defined(CONFIG_FEATURE_VI_CRASHME) +static int my_pid; +#endif #ifdef CONFIG_FEATURE_VI_WIN_RESIZE static struct winsize winsize; // remember the window size #endif /* CONFIG_FEATURE_VI_WIN_RESIZE */ @@ -181,11 +211,6 @@ static Byte *modifying_cmds; // cmds that modify text[] #ifdef CONFIG_FEATURE_VI_READONLY static int vi_readonly, readonly; #endif /* CONFIG_FEATURE_VI_READONLY */ -#ifdef CONFIG_FEATURE_VI_SETOPTS -static int autoindent; -static int showmatch; -static int ignorecase; -#endif /* CONFIG_FEATURE_VI_SETOPTS */ #ifdef CONFIG_FEATURE_VI_YANKMARK static Byte *reg[28]; // named register a-z, "D", and "U" 0-25,26,27 static int YDreg, Ureg; // default delete register and orig line for "U" @@ -202,7 +227,6 @@ static void do_cmd(Byte); // execute a command static void sync_cursor(Byte *, int *, int *); // synchronize the screen cursor to dot static Byte *begin_line(Byte *); // return pointer to cur line B-o-l static Byte *end_line(Byte *); // return pointer to cur line E-o-l -extern inline Byte *dollar_line(Byte *); // return pointer to just before NL static Byte *prev_line(Byte *); // return pointer to prev line B-o-l static Byte *next_line(Byte *); // return pointer to next line B-o-l static Byte *end_screen(void); // get pointer to last char on screen @@ -232,13 +256,12 @@ static Byte *text_hole_delete(Byte *, Byte *); // at "p", delete a 'size' byte h static Byte *text_hole_make(Byte *, int); // at "p", make a 'size' byte hole static Byte *yank_delete(Byte *, Byte *, int, int); // yank text[] into register then delete static void show_help(void); // display some help info -extern inline void print_literal(Byte *, Byte *); // copy s to buf, convert unprintable static void rawmode(void); // set "raw" mode on tty static void cookmode(void); // return to "cooked" mode on tty static int mysleep(int); // sleep for 'h' 1/100 seconds static Byte readit(void); // read (maybe cursor) key from stdin static Byte get_one_char(void); // read 1 char from stdin -static int file_size(Byte *); // what is the byte size of "fn" +static int file_size(const Byte *); // what is the byte size of "fn" static int file_insert(Byte *, Byte *, int); static int file_write(Byte *, Byte *, Byte *); static void place_cursor(int, int, int); @@ -248,17 +271,18 @@ static void clear_to_eos(void); static void standout_start(void); // send "start reverse video" sequence static void standout_end(void); // send "end reverse video" sequence static void flash(int); // flash the terminal screen -static void beep(void); // beep the terminal -static void indicate_error(char); // use flash or beep to indicate error static void show_status_line(void); // put a message on the bottom line -static void psb(char *, ...); // Print Status Buf -static void psbs(char *, ...); // Print Status Buf in standout mode +static void psb(const char *, ...); // Print Status Buf +static void psbs(const char *, ...); // Print Status Buf in standout mode static void ni(Byte *); // display messages static void edit_status(void); // show file status on status line static void redraw(int); // force a full screen refresh static void format_line(Byte*, Byte*, int); static void refresh(int); // update the terminal from screen[] +static void Indicate_Error(void); // use flash or beep to indicate error +#define indicate_error(c) Indicate_Error() + #ifdef CONFIG_FEATURE_VI_SEARCH static Byte *char_search(Byte *, Byte *, int, int); // search for pattern starting at p static int mycmp(Byte *, Byte *, int); // string cmp based in "ignorecase" @@ -269,12 +293,10 @@ static Byte *get_one_address(Byte *, int *); // get colon addr, if present static Byte *get_address(Byte *, int *, int *); // get two colon addrs, if present static void colon(Byte *); // execute the "colon" mode cmds #endif /* CONFIG_FEATURE_VI_COLON */ -static Byte *get_input_line(Byte *); // get input line- use "status line" #ifdef CONFIG_FEATURE_VI_USE_SIGNALS static void winch_sig(int); // catch window size changes static void suspend_sig(int); // catch ctrl-Z -static void alarm_sig(int); // catch alarm time-outs -static void catch_sig(int); // catch ctrl-C +static void catch_sig(int); // catch ctrl-C and alarm time-outs static void core_sig(int); // catch a core dump signal #endif /* CONFIG_FEATURE_VI_USE_SIGNALS */ #ifdef CONFIG_FEATURE_VI_DOT_CMD @@ -296,7 +318,6 @@ static Byte *string_insert(Byte *, Byte *); // insert the string at 'p' static Byte *text_yank(Byte *, Byte *, int); // save copy of "p" into a register static Byte what_reg(void); // what is letter of current YDreg static void check_context(Byte); // remember context for '' command -extern inline Byte *swap_context(Byte *); // goto new context for '' command #endif /* CONFIG_FEATURE_VI_YANKMARK */ #ifdef CONFIG_FEATURE_VI_CRASHME static void crash_dummy(); @@ -305,26 +326,28 @@ static int crashme = 0; #endif /* CONFIG_FEATURE_VI_CRASHME */ +static void write1(const char *out) +{ + fputs(out, stdout); +} + extern int vi_main(int argc, char **argv) { int c; + RESERVE_CONFIG_BUFFER(STATUS_BUFFER, 200); #ifdef CONFIG_FEATURE_VI_YANKMARK int i; #endif /* CONFIG_FEATURE_VI_YANKMARK */ - - CMrc= "\033[%d;%dH"; // Terminal Crusor motion ESC sequence - CMup= "\033[A"; // move cursor up one line, same col - CMdown="\n"; // move cursor down one line, same col - Ceol= "\033[0K"; // Clear from cursor to end of line - Ceos= "\033[0J"; // Clear from cursor to end of screen - SOs = "\033[7m"; // Terminal standout mode on - SOn = "\033[0m"; // Terminal standout mode off - bell= "\007"; // Terminal bell sequence +#if defined(CONFIG_FEATURE_VI_USE_SIGNALS) || defined(CONFIG_FEATURE_VI_CRASHME) + my_pid = getpid(); +#endif #ifdef CONFIG_FEATURE_VI_CRASHME - (void) srand((long) getpid()); + (void) srand((long) my_pid); #endif /* CONFIG_FEATURE_VI_CRASHME */ - status_buffer = (Byte *) xmalloc(200); // hold messages to user + + status_buffer = STATUS_BUFFER; + #ifdef CONFIG_FEATURE_VI_READONLY vi_readonly = readonly = FALSE; if (strncmp(argv[0], "view", 4) == 0) { @@ -332,11 +355,7 @@ extern int vi_main(int argc, char **argv) vi_readonly = TRUE; } #endif /* CONFIG_FEATURE_VI_READONLY */ -#ifdef CONFIG_FEATURE_VI_SETOPTS - autoindent = 1; - ignorecase = 1; - showmatch = 1; -#endif /* CONFIG_FEATURE_VI_SETOPTS */ + vi_setops = VI_AUTOINDENT | VI_SHOWMATCH | VI_IGNORECASE | VI_ERR_METHOD; #ifdef CONFIG_FEATURE_VI_YANKMARK for (i = 0; i < 28; i++) { reg[i] = 0; @@ -395,11 +414,10 @@ extern int vi_main(int argc, char **argv) static void edit_file(Byte * fn) { - char c; + Byte c; int cnt, size, ch; #ifdef CONFIG_FEATURE_VI_USE_SIGNALS - char *msg; int sig; #endif /* CONFIG_FEATURE_VI_USE_SIGNALS */ #ifdef CONFIG_FEATURE_VI_YANKMARK @@ -435,33 +453,20 @@ static void edit_file(Byte * fn) mark[26] = mark[27] = text; // init "previous context" #endif /* CONFIG_FEATURE_VI_YANKMARK */ - err_method = 1; // flash last_forward_char = last_input_char = '\0'; crow = 0; ccol = 0; edit_status(); #ifdef CONFIG_FEATURE_VI_USE_SIGNALS - signal(SIGHUP, catch_sig); - signal(SIGINT, catch_sig); - signal(SIGALRM, alarm_sig); - signal(SIGTERM, catch_sig); - signal(SIGQUIT, core_sig); - signal(SIGILL, core_sig); - signal(SIGTRAP, core_sig); - signal(SIGIOT, core_sig); - signal(SIGABRT, core_sig); - signal(SIGFPE, core_sig); - signal(SIGBUS, core_sig); - signal(SIGSEGV, core_sig); -#ifdef SIGSYS - signal(SIGSYS, core_sig); -#endif + catch_sig(0); + core_sig(0); signal(SIGWINCH, winch_sig); signal(SIGTSTP, suspend_sig); sig = setjmp(restart); if (sig != 0) { - msg = ""; + const char *msg = ""; + if (sig == SIGWINCH) msg = "(window resize)"; if (sig == SIGHUP) @@ -496,6 +501,7 @@ static void edit_file(Byte * fn) #endif /* CONFIG_FEATURE_VI_DOT_CMD */ redraw(FALSE); // dont force every col re-draw show_status_line(); + fflush(stdout); //------This is the main Vi cmd handling loop ----------------------- while (editing > 0) { @@ -549,212 +555,6 @@ static void edit_file(Byte * fn) cookmode(); } -static Byte readbuffer[BUFSIZ]; - -#ifdef CONFIG_FEATURE_VI_CRASHME -static int totalcmds = 0; -static int Mp = 85; // Movement command Probability -static int Np = 90; // Non-movement command Probability -static int Dp = 96; // Delete command Probability -static int Ip = 97; // Insert command Probability -static int Yp = 98; // Yank command Probability -static int Pp = 99; // Put command Probability -static int M = 0, N = 0, I = 0, D = 0, Y = 0, P = 0, U = 0; -char chars[20] = "\t012345 abcdABCD-=.$"; -char *words[20] = { "this", "is", "a", "test", - "broadcast", "the", "emergency", "of", - "system", "quick", "brown", "fox", - "jumped", "over", "lazy", "dogs", - "back", "January", "Febuary", "March" -}; -char *lines[20] = { - "You should have received a copy of the GNU General Public License\n", - "char c, cm, *cmd, *cmd1;\n", - "generate a command by percentages\n", - "Numbers may be typed as a prefix to some commands.\n", - "Quit, discarding changes!\n", - "Forced write, if permission originally not valid.\n", - "In general, any ex or ed command (such as substitute or delete).\n", - "I have tickets available for the Blazers vs LA Clippers for Monday, Janurary 1 at 1:00pm.\n", - "Please get w/ me and I will go over it with you.\n", - "The following is a list of scheduled, committed changes.\n", - "1. Launch Norton Antivirus (Start, Programs, Norton Antivirus)\n", - "Reminder....Town Meeting in Central Perk cafe today at 3:00pm.\n", - "Any question about transactions please contact Sterling Huxley.\n", - "I will try to get back to you by Friday, December 31.\n", - "This Change will be implemented on Friday.\n", - "Let me know if you have problems accessing this;\n", - "Sterling Huxley recently added you to the access list.\n", - "Would you like to go to lunch?\n", - "The last command will be automatically run.\n", - "This is too much english for a computer geek.\n", -}; -char *multilines[20] = { - "You should have received a copy of the GNU General Public License\n", - "char c, cm, *cmd, *cmd1;\n", - "generate a command by percentages\n", - "Numbers may be typed as a prefix to some commands.\n", - "Quit, discarding changes!\n", - "Forced write, if permission originally not valid.\n", - "In general, any ex or ed command (such as substitute or delete).\n", - "I have tickets available for the Blazers vs LA Clippers for Monday, Janurary 1 at 1:00pm.\n", - "Please get w/ me and I will go over it with you.\n", - "The following is a list of scheduled, committed changes.\n", - "1. Launch Norton Antivirus (Start, Programs, Norton Antivirus)\n", - "Reminder....Town Meeting in Central Perk cafe today at 3:00pm.\n", - "Any question about transactions please contact Sterling Huxley.\n", - "I will try to get back to you by Friday, December 31.\n", - "This Change will be implemented on Friday.\n", - "Let me know if you have problems accessing this;\n", - "Sterling Huxley recently added you to the access list.\n", - "Would you like to go to lunch?\n", - "The last command will be automatically run.\n", - "This is too much english for a computer geek.\n", -}; - -// create a random command to execute -static void crash_dummy() -{ - static int sleeptime; // how long to pause between commands - char c, cm, *cmd, *cmd1; - int i, cnt, thing, rbi, startrbi, percent; - - // "dot" movement commands - cmd1 = " \n\r\002\004\005\006\025\0310^$-+wWeEbBhjklHL"; - - // is there already a command running? - if (strlen((char *) readbuffer) > 0) - goto cd1; - cd0: - startrbi = rbi = 0; - sleeptime = 0; // how long to pause between commands - memset(readbuffer, '\0', BUFSIZ - 1); // clear the read buffer - // generate a command by percentages - percent = (int) lrand48() % 100; // get a number from 0-99 - if (percent < Mp) { // Movement commands - // available commands - cmd = cmd1; - M++; - } else if (percent < Np) { // non-movement commands - cmd = "mz<>\'\""; // available commands - N++; - } else if (percent < Dp) { // Delete commands - cmd = "dx"; // available commands - D++; - } else if (percent < Ip) { // Inset commands - cmd = "iIaAsrJ"; // available commands - I++; - } else if (percent < Yp) { // Yank commands - cmd = "yY"; // available commands - Y++; - } else if (percent < Pp) { // Put commands - cmd = "pP"; // available commands - P++; - } else { - // We do not know how to handle this command, try again - U++; - goto cd0; - } - // randomly pick one of the available cmds from "cmd[]" - i = (int) lrand48() % strlen(cmd); - cm = cmd[i]; - if (strchr(":\024", cm)) - goto cd0; // dont allow colon or ctrl-T commands - readbuffer[rbi++] = cm; // put cmd into input buffer - - // now we have the command- - // there are 1, 2, and multi char commands - // find out which and generate the rest of command as necessary - if (strchr("dmryz<>\'\"", cm)) { // 2-char commands - cmd1 = " \n\r0$^-+wWeEbBhjklHL"; - if (cm == 'm' || cm == '\'' || cm == '\"') { // pick a reg[] - cmd1 = "abcdefghijklmnopqrstuvwxyz"; - } - thing = (int) lrand48() % strlen(cmd1); // pick a movement command - c = cmd1[thing]; - readbuffer[rbi++] = c; // add movement to input buffer - } - if (strchr("iIaAsc", cm)) { // multi-char commands - if (cm == 'c') { - // change some thing - thing = (int) lrand48() % strlen(cmd1); // pick a movement command - c = cmd1[thing]; - readbuffer[rbi++] = c; // add movement to input buffer - } - thing = (int) lrand48() % 4; // what thing to insert - cnt = (int) lrand48() % 10; // how many to insert - for (i = 0; i < cnt; i++) { - if (thing == 0) { // insert chars - readbuffer[rbi++] = chars[((int) lrand48() % strlen(chars))]; - } else if (thing == 1) { // insert words - strcat((char *) readbuffer, words[(int) lrand48() % 20]); - strcat((char *) readbuffer, " "); - sleeptime = 0; // how fast to type - } else if (thing == 2) { // insert lines - strcat((char *) readbuffer, lines[(int) lrand48() % 20]); - sleeptime = 0; // how fast to type - } else { // insert multi-lines - strcat((char *) readbuffer, multilines[(int) lrand48() % 20]); - sleeptime = 0; // how fast to type - } - } - strcat((char *) readbuffer, "\033"); - } - cd1: - totalcmds++; - if (sleeptime > 0) - (void) mysleep(sleeptime); // sleep 1/100 sec -} - -// test to see if there are any errors -static void crash_test() -{ - static time_t oldtim; - time_t tim; - char d[2], buf[BUFSIZ], msg[BUFSIZ]; - - msg[0] = '\0'; - if (end < text) { - strcat((char *) msg, "end<text "); - } - if (end > textend) { - strcat((char *) msg, "end>textend "); - } - if (dot < text) { - strcat((char *) msg, "dot<text "); - } - if (dot > end) { - strcat((char *) msg, "dot>end "); - } - if (screenbegin < text) { - strcat((char *) msg, "screenbegin<text "); - } - if (screenbegin > end - 1) { - strcat((char *) msg, "screenbegin>end-1 "); - } - - if (strlen(msg) > 0) { - alarm(0); - sprintf(buf, "\n\n%d: \'%c\' %s\n\n\n%s[Hit return to continue]%s", - totalcmds, last_input_char, msg, SOs, SOn); - write(1, buf, strlen(buf)); - while (read(0, d, 1) > 0) { - if (d[0] == '\n' || d[0] == '\r') - break; - } - alarm(3); - } - tim = (time_t) time((time_t *) 0); - if (tim >= (oldtim + 3)) { - sprintf((char *) status_buffer, - "Tot=%d: M=%d N=%d I=%d D=%d Y=%d P=%d U=%d size=%d", - totalcmds, M, N, I, D, Y, P, U, end - text + 1); - oldtim = tim; - } - return; -} -#endif /* CONFIG_FEATURE_VI_CRASHME */ - //----- The Colon commands ------------------------------------- #ifdef CONFIG_FEATURE_VI_COLON static Byte *get_one_address(Byte * p, int *addr) // get colon addr, if present @@ -848,6 +648,23 @@ ga0: return (p); } +#ifdef CONFIG_FEATURE_VI_SETOPTS +static void setops(const Byte *args, const char *opname, int flg_no, + const char *short_opname, int opt) +{ + const char *a = (char *) args + flg_no; + int l = strlen(opname) - 1; /* opname have + ' ' */ + + if (strncasecmp(a, opname, l) == 0 || + strncasecmp(a, short_opname, 2) == 0) { + if(flg_no) + vi_setops &= ~opt; + else + vi_setops |= opt; + } +} +#endif + static void colon(Byte * buf) { Byte c, *orig_buf, *buf1, *q, *r; @@ -1065,19 +882,27 @@ static void colon(Byte * buf) } place_cursor(rows - 1, 0, FALSE); // go to Status line, bottom of screen clear_to_eol(); // clear the line - write(1, "\r\n", 2); + puts("\r"); for (; q <= r; q++) { + int c_is_no_print; + c = *q; - if (c > '~') + c_is_no_print = c > 127 && !Isprint(c); + if (c_is_no_print) { + c = '.'; standout_start(); + } if (c == '\n') { - write(1, "$\r", 2); - } else if (*q < ' ') { - write(1, "^", 1); + write1("$\r"); + } else if (c < ' ' || c == 127) { + putchar('^'); + if(c == 127) + c = '?'; + else c += '@'; } - write(1, &c, 1); - if (c > '~') + putchar(c); + if (c_is_no_print) standout_end(); } #ifdef CONFIG_FEATURE_VI_SET @@ -1185,23 +1010,11 @@ static void colon(Byte * buf) if (strncasecmp((char *) args, "no", 2) == 0) i = 2; // ":set noautoindent" #ifdef CONFIG_FEATURE_VI_SETOPTS - if (strncasecmp((char *) args + i, "autoindent", 10) == 0 || - strncasecmp((char *) args + i, "ai", 2) == 0) { - autoindent = (i == 2) ? 0 : 1; - } - if (strncasecmp((char *) args + i, "flash", 5) == 0 || - strncasecmp((char *) args + i, "fl", 2) == 0) { - err_method = (i == 2) ? 0 : 1; - } - if (strncasecmp((char *) args + i, "ignorecase", 10) == 0 || - strncasecmp((char *) args + i, "ic", 2) == 0) { - ignorecase = (i == 2) ? 0 : 1; - } - if (strncasecmp((char *) args + i, "showmatch", 9) == 0 || - strncasecmp((char *) args + i, "sm", 2) == 0) { - showmatch = (i == 2) ? 0 : 1; - } - if (strncasecmp((char *) args + i, "tabstop", 7) == 0) { + setops(args, "autoindent ", i, "ai", VI_AUTOINDENT); + setops(args, "flash ", i, "fl", VI_ERR_METHOD); + setops(args, "ignorecase ", i, "ic", VI_IGNORECASE); + setops(args, "showmatch ", i, "ic", VI_SHOWMATCH); + if (strncasecmp((char *) args + i, "tabstop=%d ", 7) == 0) { sscanf(strchr((char *) args + i, '='), "=%d", &ch); if (ch > 0 && ch < columns - 1) tabstop = ch; @@ -1318,9 +1131,7 @@ static void colon(Byte * buf) #ifdef CONFIG_FEATURE_VI_SEARCH colon_s_fail: psb(":s expression missing delimiters"); - return; #endif - } static void Hit_Return(void) @@ -1328,7 +1139,7 @@ static void Hit_Return(void) char c; standout_start(); // start reverse video - write(1, "[Hit return to continue]", 24); + write1("[Hit return to continue]"); standout_end(); // end reverse video while ((c = get_one_char()) != '\n' && c != '\r') /*do nothing */ ; @@ -1392,7 +1203,7 @@ static void sync_cursor(Byte * d, int *row, int *col) if (*tp == '\t') { // 7 - (co % 8 ) co += ((tabstop - 1) - (co % tabstop)); - } else if (*tp < ' ') { + } else if (*tp < ' ' || *tp == 127) { co++; // display as ^X, use 2 columns } } while (tp++ < d && ++co); @@ -1442,7 +1253,7 @@ static Byte *end_line(Byte * p) // return pointer to NL of cur line line return (p); } -extern inline Byte *dollar_line(Byte * p) // return pointer to just before NL line +static inline Byte *dollar_line(Byte * p) // return pointer to just before NL line { while (p < end - 1 && *p != '\n') p++; // go to cur line E-o-l @@ -1547,7 +1358,7 @@ static Byte *move_to_col(Byte * p, int l) if (*p == '\t') { // 7 - (co % 8 ) co += ((tabstop - 1) - (co % tabstop)); - } else if (*p < ' ') { + } else if (*p < ' ' || *p == 127) { co++; // display as ^X, use 2 columns } } while (++co <= l && p++ < end); @@ -1787,7 +1598,7 @@ static Byte *char_insert(Byte * p, Byte c) // insert the char c at 'p' p = text_hole_delete(p, p); // shrink buffer 1 char #ifdef CONFIG_FEATURE_VI_DOT_CMD // also rmove char from last_modifying_cmd - if (strlen((char *) last_modifying_cmd) > 0) { + if (last_modifying_cmd != 0 && strlen((char *) last_modifying_cmd) > 0) { Byte *q; q = last_modifying_cmd; @@ -2130,7 +1941,7 @@ static void show_help(void) ); } -extern inline void print_literal(Byte * buf, Byte * s) // copy s to buf, convert unprintable +static inline void print_literal(Byte * buf, Byte * s) // copy s to buf, convert unprintable { Byte c, b[2]; @@ -2139,19 +1950,25 @@ extern inline void print_literal(Byte * buf, Byte * s) // copy s to buf, convert if (strlen((char *) s) <= 0) s = (Byte *) "(NULL)"; for (; *s > '\0'; s++) { + int c_is_no_print; + c = *s; - if (*s > '~') { - strcat((char *) buf, SOs); - c = *s - 128; + c_is_no_print = c > 127 && !Isprint(c); + if (c_is_no_print) { + strcat((char *) buf, SOn); + c = '.'; } - if (*s < ' ') { + if (c < ' ' || c == 127) { strcat((char *) buf, "^"); + if(c == 127) + c = '?'; + else c += '@'; } b[0] = c; strcat((char *) buf, (char *) b); - if (*s > '~') - strcat((char *) buf, SOn); + if (c_is_no_print) + strcat((char *) buf, SOs); if (*s == '\n') { strcat((char *) buf, "$"); } @@ -2259,7 +2076,7 @@ static void check_context(Byte cmd) return; } -extern inline Byte *swap_context(Byte * p) // goto new context for '' command make this the current context +static inline Byte *swap_context(Byte * p) // goto new context for '' command make this the current context { Byte *tmp; @@ -2301,6 +2118,7 @@ static void rawmode(void) static void cookmode(void) { + fflush(stdout); tcsetattr(0, TCSANOW, &term_orig); } @@ -2348,7 +2166,7 @@ static void cont_sig(int sig) signal(SIGTSTP, suspend_sig); signal(SIGCONT, SIG_DFL); - kill(getpid(), SIGCONT); + kill(my_pid, SIGCONT); } //----- Come here when we get a Suspend signal ------------------- @@ -2360,7 +2178,7 @@ static void suspend_sig(int sig) signal(SIGCONT, cont_sig); signal(SIGTSTP, SIG_DFL); - kill(getpid(), SIGTSTP); + kill(my_pid, SIGTSTP); } //----- Come here when we get a signal --------------------------- @@ -2369,12 +2187,8 @@ static void catch_sig(int sig) signal(SIGHUP, catch_sig); signal(SIGINT, catch_sig); signal(SIGTERM, catch_sig); - longjmp(restart, sig); -} - -static void alarm_sig(int sig) -{ signal(SIGALRM, catch_sig); + if(sig) longjmp(restart, sig); } @@ -2393,15 +2207,18 @@ static void core_sig(int sig) signal(SIGSYS, core_sig); #endif + if(sig) { // signaled dot = bound_dot(dot); // make sure "dot" is valid longjmp(restart, sig); + } } #endif /* CONFIG_FEATURE_VI_USE_SIGNALS */ static int mysleep(int hund) // sleep for 'h' 1/100 seconds { // Don't hang- Wait 5/100 seconds- 1 Sec= 1000000 + fflush(stdout); FD_ZERO(&rfds); FD_SET(0, &rfds); tv.tv_sec = 0; @@ -2410,60 +2227,66 @@ static int mysleep(int hund) // sleep for 'h' 1/100 seconds return (FD_ISSET(0, &rfds)); } +static Byte readbuffer[BUFSIZ]; +static int readed_for_parse; + //----- IO Routines -------------------------------------------- static Byte readit(void) // read (maybe cursor) key from stdin { Byte c; - int i, bufsiz, cnt, cmdindex; + int n; struct esc_cmds { - Byte *seq; + const char *seq; Byte val; }; - static struct esc_cmds esccmds[] = { - {(Byte *) "OA", (Byte) VI_K_UP}, // cursor key Up - {(Byte *) "OB", (Byte) VI_K_DOWN}, // cursor key Down - {(Byte *) "OC", (Byte) VI_K_RIGHT}, // Cursor Key Right - {(Byte *) "OD", (Byte) VI_K_LEFT}, // cursor key Left - {(Byte *) "OH", (Byte) VI_K_HOME}, // Cursor Key Home - {(Byte *) "OF", (Byte) VI_K_END}, // Cursor Key End - {(Byte *) "[A", (Byte) VI_K_UP}, // cursor key Up - {(Byte *) "[B", (Byte) VI_K_DOWN}, // cursor key Down - {(Byte *) "[C", (Byte) VI_K_RIGHT}, // Cursor Key Right - {(Byte *) "[D", (Byte) VI_K_LEFT}, // cursor key Left - {(Byte *) "[H", (Byte) VI_K_HOME}, // Cursor Key Home - {(Byte *) "[F", (Byte) VI_K_END}, // Cursor Key End - {(Byte *) "[2~", (Byte) VI_K_INSERT}, // Cursor Key Insert - {(Byte *) "[5~", (Byte) VI_K_PAGEUP}, // Cursor Key Page Up - {(Byte *) "[6~", (Byte) VI_K_PAGEDOWN}, // Cursor Key Page Down - {(Byte *) "OP", (Byte) VI_K_FUN1}, // Function Key F1 - {(Byte *) "OQ", (Byte) VI_K_FUN2}, // Function Key F2 - {(Byte *) "OR", (Byte) VI_K_FUN3}, // Function Key F3 - {(Byte *) "OS", (Byte) VI_K_FUN4}, // Function Key F4 - {(Byte *) "[15~", (Byte) VI_K_FUN5}, // Function Key F5 - {(Byte *) "[17~", (Byte) VI_K_FUN6}, // Function Key F6 - {(Byte *) "[18~", (Byte) VI_K_FUN7}, // Function Key F7 - {(Byte *) "[19~", (Byte) VI_K_FUN8}, // Function Key F8 - {(Byte *) "[20~", (Byte) VI_K_FUN9}, // Function Key F9 - {(Byte *) "[21~", (Byte) VI_K_FUN10}, // Function Key F10 - {(Byte *) "[23~", (Byte) VI_K_FUN11}, // Function Key F11 - {(Byte *) "[24~", (Byte) VI_K_FUN12}, // Function Key F12 - {(Byte *) "[11~", (Byte) VI_K_FUN1}, // Function Key F1 - {(Byte *) "[12~", (Byte) VI_K_FUN2}, // Function Key F2 - {(Byte *) "[13~", (Byte) VI_K_FUN3}, // Function Key F3 - {(Byte *) "[14~", (Byte) VI_K_FUN4}, // Function Key F4 + static const struct esc_cmds esccmds[] = { + {"OA", (Byte) VI_K_UP}, // cursor key Up + {"OB", (Byte) VI_K_DOWN}, // cursor key Down + {"OC", (Byte) VI_K_RIGHT}, // Cursor Key Right + {"OD", (Byte) VI_K_LEFT}, // cursor key Left + {"OH", (Byte) VI_K_HOME}, // Cursor Key Home + {"OF", (Byte) VI_K_END}, // Cursor Key End + {"[A", (Byte) VI_K_UP}, // cursor key Up + {"[B", (Byte) VI_K_DOWN}, // cursor key Down + {"[C", (Byte) VI_K_RIGHT}, // Cursor Key Right + {"[D", (Byte) VI_K_LEFT}, // cursor key Left + {"[H", (Byte) VI_K_HOME}, // Cursor Key Home + {"[F", (Byte) VI_K_END}, // Cursor Key End + {"[1~", (Byte) VI_K_HOME}, // Cursor Key Home + {"[2~", (Byte) VI_K_INSERT}, // Cursor Key Insert + {"[4~", (Byte) VI_K_END}, // Cursor Key End + {"[5~", (Byte) VI_K_PAGEUP}, // Cursor Key Page Up + {"[6~", (Byte) VI_K_PAGEDOWN}, // Cursor Key Page Down + {"OP", (Byte) VI_K_FUN1}, // Function Key F1 + {"OQ", (Byte) VI_K_FUN2}, // Function Key F2 + {"OR", (Byte) VI_K_FUN3}, // Function Key F3 + {"OS", (Byte) VI_K_FUN4}, // Function Key F4 + {"[15~", (Byte) VI_K_FUN5}, // Function Key F5 + {"[17~", (Byte) VI_K_FUN6}, // Function Key F6 + {"[18~", (Byte) VI_K_FUN7}, // Function Key F7 + {"[19~", (Byte) VI_K_FUN8}, // Function Key F8 + {"[20~", (Byte) VI_K_FUN9}, // Function Key F9 + {"[21~", (Byte) VI_K_FUN10}, // Function Key F10 + {"[23~", (Byte) VI_K_FUN11}, // Function Key F11 + {"[24~", (Byte) VI_K_FUN12}, // Function Key F12 + {"[11~", (Byte) VI_K_FUN1}, // Function Key F1 + {"[12~", (Byte) VI_K_FUN2}, // Function Key F2 + {"[13~", (Byte) VI_K_FUN3}, // Function Key F3 + {"[14~", (Byte) VI_K_FUN4}, // Function Key F4 }; #define ESCCMDS_COUNT (sizeof(esccmds)/sizeof(struct esc_cmds)) (void) alarm(0); // turn alarm OFF while we wait for input + fflush(stdout); + n = readed_for_parse; // get input from User- are there already input chars in Q? - bufsiz = strlen((char *) readbuffer); - if (bufsiz <= 0) { + if (n <= 0) { ri0: // the Q is empty, wait for a typed char - bufsiz = read(0, readbuffer, BUFSIZ - 1); - if (bufsiz < 0) { + n = read(0, readbuffer, BUFSIZ - 1); + if (n < 0) { if (errno == EINTR) goto ri0; // interrupted sys call if (errno == EBADF) @@ -2475,14 +2298,10 @@ static Byte readit(void) // read (maybe cursor) key from stdin if (errno == EIO) editing = 0; errno = 0; - bufsiz = 0; } - readbuffer[bufsiz] = '\0'; - } - // return char if it is not part of ESC sequence - if (readbuffer[0] != 27) - goto ri1; - + if(n <= 0) + return 0; // error + if (readbuffer[0] == 27) { // This is an ESC char. Is this Esc sequence? // Could be bare Esc key. See if there are any // more chars to read after the ESC. This would @@ -2493,34 +2312,44 @@ static Byte readit(void) // read (maybe cursor) key from stdin tv.tv_usec = 50000; // Wait 5/100 seconds- 1 Sec=1000000 // keep reading while there are input chars and room in buffer - while (select(1, &rfds, NULL, NULL, &tv) > 0 && bufsiz <= (BUFSIZ - 5)) { + while (select(1, &rfds, NULL, NULL, &tv) > 0 && n <= (BUFSIZ - 5)) { // read the rest of the ESC string - i = read(0, (void *) (readbuffer + bufsiz), BUFSIZ - bufsiz); - if (i > 0) { - bufsiz += i; - readbuffer[bufsiz] = '\0'; // Terminate the string + int r = read(0, (void *) (readbuffer + n), BUFSIZ - n); + if (r > 0) { + n += r; + } + } } + readed_for_parse = n; } + c = readbuffer[0]; + if(c == 27 && n > 1) { // Maybe cursor or function key? - for (cmdindex = 0; cmdindex < ESCCMDS_COUNT; cmdindex++) { - cnt = strlen((char *) esccmds[cmdindex].seq); - i = strncmp((char *) esccmds[cmdindex].seq, (char *) readbuffer, cnt); - if (i == 0) { + const struct esc_cmds *eindex; + + for (eindex = esccmds; eindex < &esccmds[ESCCMDS_COUNT]; eindex++) { + int cnt = strlen(eindex->seq); + + if(n <= cnt) + continue; + if(strncmp(eindex->seq, (char *) readbuffer + 1, cnt)) + continue; // is a Cursor key- put derived value back into Q - readbuffer[0] = esccmds[cmdindex].val; - // squeeze out the ESC sequence - for (i = 1; i < cnt; i++) { - memmove(readbuffer + 1, readbuffer + 2, BUFSIZ - 2); - readbuffer[BUFSIZ - 1] = '\0'; - } + c = eindex->val; + // for squeeze out the ESC sequence + n = cnt + 1; break; } + if(eindex == &esccmds[ESCCMDS_COUNT]) { + /* defined ESC sequence not found, set only one ESC */ + n = 1; } - ri1: - c = readbuffer[0]; - // remove one char from Q - memmove(readbuffer, readbuffer + 1, BUFSIZ - 1); - readbuffer[BUFSIZ - 1] = '\0'; + } else { + n = 1; + } + // remove key sequence from Q + readed_for_parse -= n; + memmove(readbuffer, readbuffer + n, BUFSIZ - n); (void) alarm(3); // we are done waiting for input, turn alarm ON return (c); } @@ -2561,7 +2390,6 @@ static Byte get_one_char() // add new char to q last_modifying_cmd[len] = c; } - } } #else /* CONFIG_FEATURE_VI_DOT_CMD */ @@ -2581,7 +2409,7 @@ static Byte *get_input_line(Byte * prompt) // get input line- use "status line" *status_buffer = '\0'; // clear the status buffer place_cursor(rows - 1, 0, FALSE); // go to Status line, bottom of screen clear_to_eol(); // clear the line - write(1, prompt, strlen((char *) prompt)); // write out the :, /, or ? prompt + write1(prompt); // write out the :, /, or ? prompt for (i = strlen((char *) buf); i < BUFSIZ;) { c = get_one_char(); // read user input @@ -2591,14 +2419,14 @@ static Byte *get_input_line(Byte * prompt) // get input line- use "status line" i--; // backup to prev char buf[i] = '\0'; // erase the char buf[i + 1] = '\0'; // null terminate buffer - write(1, " ", 3); // erase char on screen + write1("\b \b"); // erase char on screen if (i <= 0) { // user backs up before b-o-l, exit break; } } else { buf[i] = c; // save char in buffer buf[i + 1] = '\0'; // make sure buffer is null terminated - write(1, buf + i, 1); // echo the char back to user + putchar(c); // echo the char back to user i++; } } @@ -2608,7 +2436,7 @@ static Byte *get_input_line(Byte * prompt) // get input line- use "status line" return (obufp); } -static int file_size(Byte * fn) // what is the byte size of "fn" +static int file_size(const Byte * fn) // what is the byte size of "fn" { struct stat st_buf; int cnt, sr; @@ -2729,7 +2557,6 @@ static void place_cursor(int row, int col, int opti) { char cm1[BUFSIZ]; char *cm; - int l; #ifdef CONFIG_FEATURE_VI_OPTIMIZE_CURSOR char cm2[BUFSIZ]; Byte *screenp; @@ -2784,32 +2611,31 @@ static void place_cursor(int row, int col, int opti) } */ #endif /* CONFIG_FEATURE_VI_OPTIMIZE_CURSOR */ pc0: - l= strlen(cm); - if (l) write(1, cm, l); // move the cursor + write1(cm); // move the cursor } //----- Erase from cursor to end of line ----------------------- static void clear_to_eol() { - write(1, Ceol, strlen(Ceol)); // Erase from cursor to end of line + write1(Ceol); // Erase from cursor to end of line } //----- Erase from cursor to end of screen ----------------------- static void clear_to_eos() { - write(1, Ceos, strlen(Ceos)); // Erase from cursor to end of screen + write1(Ceos); // Erase from cursor to end of screen } //----- Start standout mode ------------------------------------ static void standout_start() // send "start reverse video" sequence { - write(1, SOs, strlen(SOs)); // Start reverse video mode + write1(SOs); // Start reverse video mode } //----- End standout mode -------------------------------------- static void standout_end() // send "end reverse video" sequence { - write(1, SOn, strlen(SOn)); // End reverse video mode + write1(SOn); // End reverse video mode } //----- Flash the screen -------------------------------------- @@ -2822,19 +2648,14 @@ static void flash(int h) redraw(TRUE); } -static void beep() -{ - write(1, bell, strlen(bell)); // send out a bell character -} - -static void indicate_error(char c) +static void Indicate_Error(void) { #ifdef CONFIG_FEATURE_VI_CRASHME if (crashme > 0) return; // generate a random command #endif /* CONFIG_FEATURE_VI_CRASHME */ - if (err_method == 0) { - beep(); + if (!err_method) { + write1(bell); // send out a bell character } else { flash(10); } @@ -2859,7 +2680,7 @@ static void show_status_line(void) if (cnt > 0 && last_cksum != cksum) { last_cksum= cksum; // remember if we have seen this line place_cursor(rows - 1, 0, FALSE); // put cursor on status line - write(1, status_buffer, cnt); + write1(status_buffer); clear_to_eol(); place_cursor(crow, ccol, FALSE); // put cursor back in correct place } @@ -2867,7 +2688,7 @@ static void show_status_line(void) //----- format the status buffer, the bottom line of screen ------ // print status buffer, with STANDOUT mode -static void psbs(char *format, ...) +static void psbs(const char *format, ...) { va_list args; @@ -2882,7 +2703,7 @@ static void psbs(char *format, ...) } // print status buffer -static void psb(char *format, ...) +static void psb(const char *format, ...) { va_list args; @@ -2954,7 +2775,10 @@ static void format_line(Byte *dest, Byte *src, int li) } if (c == '\n') break; - if (c < ' ' || c > '~') { + if (c > 127 && !Isprint(c)) { + c = '.'; + } + if (c < ' ' || c == 127) { if (c == '\t') { c = ' '; // co % 8 != 7 @@ -2963,8 +2787,10 @@ static void format_line(Byte *dest, Byte *src, int li) } } else { dest[co++] = '^'; - c |= '@'; // make it visible - c &= 0x7f; // get rid of hi bit + if(c == 127) + c = '?'; + else + c += '@'; // make it visible } } // the co++ is done here so that the column will @@ -3067,7 +2893,15 @@ static void refresh(int full_screen) } // write line out to terminal - write(1, sp+cs, ce-cs+1); + { + int nic = ce-cs+1; + char *out = sp+cs; + + while(nic-- > 0) { + putchar(*out); + out++; + } + } #ifdef CONFIG_FEATURE_VI_OPTIMIZE_CURSOR last_row = li; #endif /* CONFIG_FEATURE_VI_OPTIMIZE_CURSOR */ @@ -3131,12 +2965,14 @@ static void do_cmd(Byte c) } if (cmd_mode == 2) { + // flip-flop Insert/Replace mode + if (c == VI_K_INSERT) goto dc_i; // we are 'R'eplacing the current *dot with new char if (*dot == '\n') { // don't Replace past E-o-l cmd_mode = 1; // convert to insert } else { - if (1 <= c && c <= 127) { // only ASCII chars + if (1 <= c || Isprint(c)) { if (c != 27) dot = yank_delete(dot, dot, 0, YANKDEL); // delete char dot = char_insert(dot, c); // insert new char @@ -3148,8 +2984,8 @@ static void do_cmd(Byte c) // hitting "Insert" twice means "R" replace mode if (c == VI_K_INSERT) goto dc5; // insert the char c at "dot" - if (1 <= c && c <= 127) { - dot = char_insert(dot, c); // only ASCII chars + if (1 <= c || Isprint(c)) { + dot = char_insert(dot, c); } goto dc1; } @@ -3202,7 +3038,7 @@ key_cmd_mode: default: // unrecognised command buf[0] = c; buf[1] = '\0'; - if (c <= ' ') { + if (c < ' ') { buf[0] = '^'; buf[1] = c + '@'; buf[2] = '\0'; @@ -3953,3 +3789,208 @@ key_cmd_mode: if (*dot == '\n' && cnt > 0 && cmd_mode == 0) dot--; } + +#ifdef CONFIG_FEATURE_VI_CRASHME +static int totalcmds = 0; +static int Mp = 85; // Movement command Probability +static int Np = 90; // Non-movement command Probability +static int Dp = 96; // Delete command Probability +static int Ip = 97; // Insert command Probability +static int Yp = 98; // Yank command Probability +static int Pp = 99; // Put command Probability +static int M = 0, N = 0, I = 0, D = 0, Y = 0, P = 0, U = 0; +char chars[20] = "\t012345 abcdABCD-=.$"; +char *words[20] = { "this", "is", "a", "test", + "broadcast", "the", "emergency", "of", + "system", "quick", "brown", "fox", + "jumped", "over", "lazy", "dogs", + "back", "January", "Febuary", "March" +}; +char *lines[20] = { + "You should have received a copy of the GNU General Public License\n", + "char c, cm, *cmd, *cmd1;\n", + "generate a command by percentages\n", + "Numbers may be typed as a prefix to some commands.\n", + "Quit, discarding changes!\n", + "Forced write, if permission originally not valid.\n", + "In general, any ex or ed command (such as substitute or delete).\n", + "I have tickets available for the Blazers vs LA Clippers for Monday, Janurary 1 at 1:00pm.\n", + "Please get w/ me and I will go over it with you.\n", + "The following is a list of scheduled, committed changes.\n", + "1. Launch Norton Antivirus (Start, Programs, Norton Antivirus)\n", + "Reminder....Town Meeting in Central Perk cafe today at 3:00pm.\n", + "Any question about transactions please contact Sterling Huxley.\n", + "I will try to get back to you by Friday, December 31.\n", + "This Change will be implemented on Friday.\n", + "Let me know if you have problems accessing this;\n", + "Sterling Huxley recently added you to the access list.\n", + "Would you like to go to lunch?\n", + "The last command will be automatically run.\n", + "This is too much english for a computer geek.\n", +}; +char *multilines[20] = { + "You should have received a copy of the GNU General Public License\n", + "char c, cm, *cmd, *cmd1;\n", + "generate a command by percentages\n", + "Numbers may be typed as a prefix to some commands.\n", + "Quit, discarding changes!\n", + "Forced write, if permission originally not valid.\n", + "In general, any ex or ed command (such as substitute or delete).\n", + "I have tickets available for the Blazers vs LA Clippers for Monday, Janurary 1 at 1:00pm.\n", + "Please get w/ me and I will go over it with you.\n", + "The following is a list of scheduled, committed changes.\n", + "1. Launch Norton Antivirus (Start, Programs, Norton Antivirus)\n", + "Reminder....Town Meeting in Central Perk cafe today at 3:00pm.\n", + "Any question about transactions please contact Sterling Huxley.\n", + "I will try to get back to you by Friday, December 31.\n", + "This Change will be implemented on Friday.\n", + "Let me know if you have problems accessing this;\n", + "Sterling Huxley recently added you to the access list.\n", + "Would you like to go to lunch?\n", + "The last command will be automatically run.\n", + "This is too much english for a computer geek.\n", +}; + +// create a random command to execute +static void crash_dummy() +{ + static int sleeptime; // how long to pause between commands + char c, cm, *cmd, *cmd1; + int i, cnt, thing, rbi, startrbi, percent; + + // "dot" movement commands + cmd1 = " \n\r\002\004\005\006\025\0310^$-+wWeEbBhjklHL"; + + // is there already a command running? + if (readed_for_parse > 0) + goto cd1; + cd0: + startrbi = rbi = 0; + sleeptime = 0; // how long to pause between commands + memset(readbuffer, '\0', BUFSIZ); // clear the read buffer + // generate a command by percentages + percent = (int) lrand48() % 100; // get a number from 0-99 + if (percent < Mp) { // Movement commands + // available commands + cmd = cmd1; + M++; + } else if (percent < Np) { // non-movement commands + cmd = "mz<>\'\""; // available commands + N++; + } else if (percent < Dp) { // Delete commands + cmd = "dx"; // available commands + D++; + } else if (percent < Ip) { // Inset commands + cmd = "iIaAsrJ"; // available commands + I++; + } else if (percent < Yp) { // Yank commands + cmd = "yY"; // available commands + Y++; + } else if (percent < Pp) { // Put commands + cmd = "pP"; // available commands + P++; + } else { + // We do not know how to handle this command, try again + U++; + goto cd0; + } + // randomly pick one of the available cmds from "cmd[]" + i = (int) lrand48() % strlen(cmd); + cm = cmd[i]; + if (strchr(":\024", cm)) + goto cd0; // dont allow colon or ctrl-T commands + readbuffer[rbi++] = cm; // put cmd into input buffer + + // now we have the command- + // there are 1, 2, and multi char commands + // find out which and generate the rest of command as necessary + if (strchr("dmryz<>\'\"", cm)) { // 2-char commands + cmd1 = " \n\r0$^-+wWeEbBhjklHL"; + if (cm == 'm' || cm == '\'' || cm == '\"') { // pick a reg[] + cmd1 = "abcdefghijklmnopqrstuvwxyz"; + } + thing = (int) lrand48() % strlen(cmd1); // pick a movement command + c = cmd1[thing]; + readbuffer[rbi++] = c; // add movement to input buffer + } + if (strchr("iIaAsc", cm)) { // multi-char commands + if (cm == 'c') { + // change some thing + thing = (int) lrand48() % strlen(cmd1); // pick a movement command + c = cmd1[thing]; + readbuffer[rbi++] = c; // add movement to input buffer + } + thing = (int) lrand48() % 4; // what thing to insert + cnt = (int) lrand48() % 10; // how many to insert + for (i = 0; i < cnt; i++) { + if (thing == 0) { // insert chars + readbuffer[rbi++] = chars[((int) lrand48() % strlen(chars))]; + } else if (thing == 1) { // insert words + strcat((char *) readbuffer, words[(int) lrand48() % 20]); + strcat((char *) readbuffer, " "); + sleeptime = 0; // how fast to type + } else if (thing == 2) { // insert lines + strcat((char *) readbuffer, lines[(int) lrand48() % 20]); + sleeptime = 0; // how fast to type + } else { // insert multi-lines + strcat((char *) readbuffer, multilines[(int) lrand48() % 20]); + sleeptime = 0; // how fast to type + } + } + strcat((char *) readbuffer, "\033"); + } + readed_for_parse = strlen(readbuffer); + cd1: + totalcmds++; + if (sleeptime > 0) + (void) mysleep(sleeptime); // sleep 1/100 sec +} + +// test to see if there are any errors +static void crash_test() +{ + static time_t oldtim; + time_t tim; + char d[2], buf[BUFSIZ], msg[BUFSIZ]; + + msg[0] = '\0'; + if (end < text) { + strcat((char *) msg, "end<text "); + } + if (end > textend) { + strcat((char *) msg, "end>textend "); + } + if (dot < text) { + strcat((char *) msg, "dot<text "); + } + if (dot > end) { + strcat((char *) msg, "dot>end "); + } + if (screenbegin < text) { + strcat((char *) msg, "screenbegin<text "); + } + if (screenbegin > end - 1) { + strcat((char *) msg, "screenbegin>end-1 "); + } + + if (strlen(msg) > 0) { + alarm(0); + printf(buf, "\n\n%d: \'%c\' %s\n\n\n%s[Hit return to continue]%s", + totalcmds, last_input_char, msg, SOs, SOn); + fflush(stdout); + while (read(0, d, 1) > 0) { + if (d[0] == '\n' || d[0] == '\r') + break; + } + alarm(3); + } + tim = (time_t) time((time_t *) 0); + if (tim >= (oldtim + 3)) { + sprintf((char *) status_buffer, + "Tot=%d: M=%d N=%d I=%d D=%d Y=%d P=%d U=%d size=%d", + totalcmds, M, N, I, D, Y, P, U, end - text + 1); + oldtim = tim; + } + return; +} +#endif /* CONFIG_FEATURE_VI_CRASHME */ |