static char Sccsid[] = "xed.c @(#)xed.c 1.1 10/1/82 Berkeley "; # /* * V7.15 81/09/16 14:22 Fixed bug causing bus errors occasionally * V7.14 81/09/10 21:50 -B dynamically allocated line buffer * V7.13 81/07/25 22:51 added -O and "long" pointers * * Editor * * Major additions beginning 77/04 * Conversion to version 7 79/12 * Conversion to VAX 80/11 * * Purdue University, Engineering Computer Network * * Tgi -- Room 337A * Electrical Engineering Dept * Purdue University * West Lafayette, Indiana * 47907 * 317/49-41592 */ #define XED /* enable powerful stuff */ #define V7 /* enable environment stuff for protocol */ /* * At the entry to a function (PDP-11) the following sequence * of instructions is executed: * func: jsr r5,csv * csv: mov r5,r0 * csv+2: mov sp,r5 * If a signal occurs between the first and second, or between the * second and third instructions, r5 will NOT contain a valid * stack address. Hence, when longjmp() attempts to validate * the environment pointer (r5) links, an instruction will be * fetched instead of a valid pointer, and will generally cause * one of "memory fault", "bus error", or "illegal instruction" * resulting in the loss of the editing session. * * Due to this wonderful feature of version 7 ingenuity, I have * reverted to using setexit/reset, since they are simpler and * do not assume that I do not know what I am doing. * * 80/11/10 V7.01 Tgi */ #ifndef pdp11 #include jmp_buf _env_rst; #define setexit() setjmp(_env_rst) #define reset() longjmp(_env_rst,1) #endif #include #include /* * Machine-dependent definitions */ #ifdef pdp11 # define BPB 8 /* bits per byte */ # define BPW (BPB*sizeof(int))/* bits per word */ # define BPWC 4 /* log2(BPW) */ # define BPWM 017 /* mask of BPWC bits */ typedef short block; typedef short charac; typedef short filedes; typedef short flag; typedef int (*func)(); typedef short linep; #endif #ifdef vax # define BPB 8 /* bits per byte */ # define BPW (BPB*sizeof(int))/* bits per word */ # define BPWC 5 /* log2(BPW) */ # define BPWM 037 /* mask of BPWC bits */ typedef long block; typedef int charac; typedef short filedes; typedef char flag; typedef int (*func)(); typedef long linep; /* NEW */ #endif /* * conditional compilation */ #ifdef XED # define AGAIN /* enable "o" "again" command */ # define ALLOC 1024 /* line buffer size */ # define APLMAP /* enable Apl character mapping */ # define DEBUG /* enable "du" command */ # define DUMB 0 /* enable command to disable spcl chars */ # define EOL /* enable special eol stuff */ # define EXTMARK /* extended "k" capability */ # define G_VFY /* enable verifying on "g" command */ # define HELP "/etc/xed.doc" # ifdef pdp11 /* only needed on 16-bit machines */ # define HUGE /* enable "huge" file stuff */ # endif # define PAGE /* enable proper line counting on ":" */ # define PARENS /* enable "b" suffix to count parentheses */ # define PIPE /* enable | command to pipe to process */ # define PROMPT ">" # define STRLEN /* enable string-length counting code */ # define TABS ((LBSIZE+sizeof(int)-1)/sizeof(int)) /* words for tab stops */ # define TTL "XED\tV7.15" /* #define TTL_NL 9 /* location of newline in TTL */ # define UNDO /* enable "u"ndo command */ # define USE /* enable "@" command */ # define XDEL /* enable undelete stuff */ # define YINT /* enable special interrupt processing */ #endif /* * stuff for EED, instead of XED */ #ifndef XED # define HELP "/etc/eed.doc" # define PROMPT "*" # define TTL "EED" #else # define EEDHELP "/etc/eed.doc" # define EEDPROMPT "*" # define EEDTTL "EED" #endif /* * stuff normally enabled */ #define CLEAR "\33:\33H\33J\32\14" /* HP-2640A, Lear ADM-3A */ #define CMDS "edsav" /* all commands written if exists */ #ifndef DUMB # define DUMB 1 /* enable command to disable spcl chars */ #endif /* * special stuff, occasionally enabled */ #define LOG "/a/tgi/etc/xed.log" /* feature use logging */ /* * data #defines */ #define BAK 4 /* file.bak - backup() */ #define BLKSIZE 512 /* disk block size (bytes) */ #define BS1 0100000 /* stty() */ #define CBACK 14 /* back-reference: \(blah\)more\1 */ #define CBRA 1 /* \( */ #define CCHR 2 /* literal character */ #define CCL 6 /* character class [x...y] */ #define CCOUNT (80-1) /* terminal width */ #define CDOL 10 /* ...$ */ #define CDOT 4 /* . */ #define CEOF 11 /* end of pattern */ #define CKET 12 /* \) */ #define EOF -1 /* end of file */ #define ESIZE 128 /* regular expression size */ #define FILE 0 /* no extension - backup() */ #define FNSIZE 64 /* max size of pathname to file */ #define GBSIZE 256 /* max global command length */ #define HUP 3 /* file.hup - backup() */ #define INT 2 /* file.int - backup() */ #define LBSIZE 512 /* max line length */ #define LMASK 077 /* mask for "locked" file */ #define LMODE (MODE&~LMASK) /* mode for "locked" file */ #define MODCNT 35 /* default mod count before auto-write */ #define MODE 0666 /* mode for normal files */ #define NBRA 9 /* number of \( \) pairs */ #define NCCL 8 /* not in character class: [^x...y] */ #define PAGSIZ 22 /* page size for ":" command */ #define READ 0 /* getblock: read function */ #define SIGBUS 10 /* Bus error */ #define SIGEMT 7 /* EMT trap */ #define SIGFPE 8 /* Floating Point Exception */ #define SIGHUP 1 /* Hangup signal */ #define SIGILL 4 /* Illegal instruction */ #define SIGINT 2 /* Interrupt signal */ #define SIGIOT 6 /* IOT trap */ #define SIGPIP 13 /* Broken pipe for ! stuff */ #define SIGQIT 3 /* Quit signal */ #define SIGSEGV 11 /* Memory fault */ #define SIGSYS 12 /* Bad system call */ #define SIGTRC 5 /* Trace/BPT for mail stuff */ #define SIGTRM 15 /* Termination */ #define STAR 1 /* * */ #define TABFILL '\t' /* fill character for tab expansion */ #define TMP 1 /* file.edt - backup() */ #define TRM 5 /* file.trm - backup() */ #define TTSIZE (512+4) /* terminal output buffer size */ #define WRITE 1 /* getblock: write function */ #define ever (;;) #define error errfunc #define ctrl(x) ((x)&037) #ifdef AGAIN char agbuf[GBSIZE], /* save area for "again" command */ *agp = 0; /* "again" command pointer */ flag agf = 0; /* "again" flag (executing the command) */ #endif #ifdef ALLOC int lbsize = LBSIZE;/* line buffer size */ #endif #ifdef APLMAP flag aplmap = 0; /* Apl character mapping */ #include "aplmap.h" /* apl ADM-3A char set mapping tables */ #endif #ifdef CKPT char *cfname = "/tmp/ce00000";/* filename for checkpoint */ int recovry = 0, /* non-zero to recover checkpointed session */ tfnum; /* index into tfname for "00000" string */ #endif #ifdef CLEAR char *clears = CLEAR;/* screen-clear sequence */ flag zflg = 0; /* if "stty bs1" not set */ /* bs1 displays ctrl-z as ^Z on tty */ #endif #ifdef CMDS filedes cmd = 0; /* file des for command-save file */ char cmdfil[] = CMDS;/* command-save file */ #endif #ifdef DEBUG flag tflg = 0; /* tracing flag */ #endif #ifdef DUMB flag dumbf = DUMB; /* 1 = disable special chars in patterns */ #endif #ifdef EOL charac eol = 0; /* "end-of-line" char for multiple commands */ /* per line */ flag prompt3 = 1; /* disable prompts for "eol" stuff */ #endif #ifdef G_VFY flag gaskf = 0; /* verify mode on global command */ #endif #ifdef HELP filedes doc = 0; /* "help" file descriptor */ char *help = HELP; /* "help" file name */ #endif #ifdef LOG char logfile[]= LOG; /* logging use of features */ filedes lfile = 0; /* logging file descriptor */ short logamp; /* since s/x/&/ may be done many times */ struct logstat { short l_uid; /* user id of caller */ char l_xed, /* 1 if xed, 0 if eed, 2 if apled */ l_inter; /* 1 if interactive */ /* command features */ short lc_shell, /* ! */ lc_pipe, /* | */ lc_piplus, /* |+ */ lc_piminus, /* |- */ lc_dpipe, /* || */ lc_pfrom, /* |< */ lc_pto, /* |> */ lc_at, /* @ */ lc_colon, /* : */ lc_star, /* * */ lc_clnminus, /* :- */ lc_comment, /* : stuff or * stuff */ lc_append, /* a */ lc_abort, /* abort */ lc_aspace, /* a line */ lc_aslash, /* a/string/ */ lc_browse, /* bN */ lc_change, /* c */ lc_cslash, /* c/s1/s2/ */ lc_copy, /* coNN */ lc_delete, /* d */ lc_depth, /* d=NN */ lc_directory, /* d path */ lc_edit, /* e file */ lc_eol, /* e=C */ lc_errmsg, /* eNN */ lc_exp, /* exp */ lc_eplus, /* e+ */ lc_eminus, /* e- */ lc_fshow, /* f */ lc_fset, /* f file */ lc_fillset, /* f=C */ lc_global, /* g/str/cmd */ lc_gvfy, /* g/str/vcmd */ lc_header, /* h */ lc_help, /* help */ lc_insert, /* i */ lc_islash, /* i/string/ */ lc_join, /* j */ lc_jglue, /* j/glue/ */ lc_klist, /* k */ lc_kset, /* kC */ lc_list, /* l */ lc_move, /* mNN */ lc_moove, /* moNN */ lc_magic, /* m */ lc_numbers, /* n */ lc_numinus, /* n- */ lc_numplus, /* n+ */ lc_o, /* o ^Q */ lc_print, /* p */ lc_pprint, /* pp */ lc_quit, /* q */ lc_qimm, /* qi */ lc_quote, /* q=C */ lc_read, /* r */ lc_substitute, /* s/s1/s2/ */ lc_stop, /* s */ lc_savecount, /* saNN */ lc_tablist, /* t */ lc_tabset, /* t,NN */ lc_tabchar, /* t=C */ lc_transfer, /* tNN */ lc_undo, /* u */ lc_vglobal, /* v/str/cmd */ lc_write, /* w */ lc_wonto, /* w> */ lc_wimm, /* wi */ lc_width, /* w=NN */ lc_xundelete, /* x */ lc_yintr, /* y */ lc_yminus, /* y- */ lc_yplus, /* y+ */ /* address features */ la_dot, /* . */ la_dotdot, /* .. */ la_dol, /* $ */ la_num, /* NN */ la_plus, /* + */ la_minus, /* - */ la_caret, /* ^ */ la_quote, /* 'a */ la_letter, /* A */ la_slash, /* /str/ */ la_query, /* ?str? */ la_equal, /* = */ /* pattern features */ lp_caret, /* ^ */ lp_dol, /* $ */ lp_dot, /* . */ lp_star, /* * */ lp_ccl, /* [ ] */ lp_nccl, /* [^ ] */ lp_paren, /* \( \) */ lp_digit, /* \1 \2 \3 ... */ /* substitution features */ lp_amp, /* & */ /* miscellaneous features */ lm_quote, /* ...q */ lm_bracket, /* ...b */ lm_overwrite; /* -O,wi */ /* resources */ long lt_start, /* starting time */ lt_end, /* elapsed time */ lt_usercpu, /* user cpu time */ lt_syscpu, /* system cpu time */ lt_kidscpu, /* total ! kids time */ lt_rlines, /* total lines read */ lt_wlines; /* total lines written */ } logstats; #endif #ifdef PAGE int ccount = CCOUNT;/* terminal width */ #endif #ifdef PARENS int parenc[3] = {0, 0, 0};/* parentheses counts */ flag parenf = 0; /* count parentheses and brackets */ #endif #ifdef PIPE filedes pfile = 0; /* "pipe" file descriptor */ char *pfname = "/tmp/ep00000";/* for "double-piping" */ flag piperr = 0, /* pipe error flag - shell() */ pno = -1, /* piping line numbering flag (default n-) */ strict = 1; /* strict exit status checking for | */ #endif #ifdef STRLEN charac quotec = '\0', /* quote character other than " or ' */ quotec2 = '\0'; /* closing quote */ int quotef = 0; /* length of strings within " or ' chars */ #endif #ifdef TABS charac tabfill = TABFILL,/* fill character */ tabc = 0; /* tab character - if 0 no tab processing */ int maxtab = -1, /* last column number with tab stop */ tabs[TABS]; /* each bit on = tab stop */ #endif #ifdef UNDO linep undo_oldp, /* original line pointer */ undo_newp; /* replacement line */ #endif #ifdef USE filedes alt = 0; /* alternate command input file */ char altfile[FNSIZE]; flag eflg2 = 0; /* another kludge */ #endif #ifdef XDEL linep deleted = 0; /* pointer to deleted line pointers */ int ndeleted = 0; /* number of lines */ #endif #ifdef YINT flag yflg = 0; /* page upon interrupt */ linep *yplus = 0; /* page from this line - if zero, from dot */ #endif /* * globals */ block iblock = -1, /* block number of input buffer */ oblock = -1; /* output buffer block number */ char *braelist[NBRA], /* bracket \( \) end list */ *braslist[NBRA], /* bracket \( \) start list */ dotbak[] = ".bak", dotedt[] = ".edt", /* "file saved" file */ dothup[] = ".hup", dotint[] = ".int", dottrm[] = ".trm", *dots[] = { dothup, dottrm, dotedt, dotint, 0 }, expbuf[ESIZE + 4], /* expression buffer */ file[FNSIZE], /* filename buffer */ #ifndef ALLOC genbuf[LBSIZE], /* generated line buffer */ #else *genbuf, /* generated line buffer pointer */ #endif ibuff[BLKSIZE], /* input tmpfile buffer */ line[TTSIZE + 4], /* terminal output buffer */ #ifndef ALLOC linebuf[LBSIZE], /* line buffer for getline()/putline() */ #else *linebuf, /* line buffer for getline()/putline() */ #endif no[] = "no ", null[] = "", /* "" */ obuff[BLKSIZE], /* output tmpfile buffer */ off[] = "off", on[] = "on", prcntu[] = "%u\n", /* %u */ quote_s[] = "s", /* "s" */ rhsbuf[LBSIZE / 2], /* right-hand-side expression buffer */ savedfile[FNSIZE], /* saved filename */ tempfile[FNSIZE], /* scratch area for filename */ *editor, /* argv[0] */ *e_prompt = PROMPT,/* editor command prompt */ *fmtlno = "%7u=",/* format for line-number output */ *globp, /* global command pointer */ *linp = line, /* line pointer */ *linebp, *loc1, /* start pointer of & string */ *loc2, /* end pointer of & string */ *locs, *nextip, *overfile, /* filename mode was changed on */ *tfname = "/tmp/e00000",/* "buffer" name */ *ver = TTL; /* ID message */ charac lastc = 0, /* peekc set to lastc on interrupt */ peekc = 0; /* one character pushback */ int brcount = 1, /* number of lines to output on "newline" */ col = 0, /* column counter for calculating line wraps */ line_num, /* integer for line number on output */ modcount = MODCNT,/* number of mods before auto-write */ overmode, /* mode of overridden file */ mods = 0, /* number of mods */ nbra = 0, /* count of currently defined \( \) pairs */ ninbuf, /* bytes in tmpfile input buffer */ nleft, /* bytes remaining in tmpfile output buffer */ num_reads = 0, /* indicator to aid text_modified-- */ /* first read isn't really a modify */ pcount = PAGSIZ-1,/* number of lines to display on ":" command */ s_cnt = 0, /* counter for "s/str1/str2/nn" */ s_tmp = 0, /* scratch var for same */ savf, /* counter for auto-write stuff */ text_modified = 0;/* flag--on if text was modified */ filedes fout = 1, /* putchar() writes on this fildes */ io = 0, /* file descriptor for "r", "w", "e" */ tfile = -1; /* file des for "buffer" */ flag aflg = 0, /* "apl mode" flag */ appflg = 0, /* append flag (if "w>file") */ badf = 0, /* bad read on temp file */ bflg = 0, /* "back-up" flag -- Generate back-up file */ bflg2 = 0, /* Secondary "back-up" flag */ circfl, /* reg expr started with ^ */ curt = 0, /* short error messages -- ie: '?' */ deltflg = 0, /* don't delete .edt file upon exit */ eflg = 0, /* echo input flag */ eof = 0, /* eof was last char typed */ fflg = 0, /* "create" flag */ globf2 = 0, /* kludge for -f */ #ifdef HUGE hugef = 0, /* -h is process huge file */ hugef2 = 0, /* getblock() conversion to huge */ #endif hupflag = 0, /* hangup signal has been caught */ ichanged, /* ibuf has been changed */ iflg = 0, /* file.int and exit on interrupt */ immflg = 0, /* immediate flag -- q and e */ io_w = 0, /* writing in progress */ listf = 0, /* list control chars explicitly */ noshell = 0, /* true if no ! command allowed */ over = 0, /* override permissions on write if possible */ pflag, /* print line after doing command */ pipef = 0, /* for talking to pipes */ prompt1 = 1, /* flag--enable or disable line-num prompts */ prompt2 = 1, /* flag--enable or disable ALL prompting */ reading = 0, /* waiting on tty read */ seekf = 0, /* no seek to EOF on error on fd 0 */ termflg = 0; /* if termination signal (15) occurred */ linep *addr1, /* lower line bound */ *addr2, /* upper line bound */ *dol, /* last line in file */ *dot, /* "current" line */ *dotdot, /* last different "dot" */ *endcore, /* current end of memory */ *fendcore, /* start of dynamic area */ *lastdot, /* last "dot" */ names['z' - 'a' + 1], /* "k" command markers */ #ifdef EXTMARK names2['z' - 'a' + 1], /* "k" command markers */ #endif *old_a1, /* previous address bounds */ *old_a2, tline, /* pointer to next available pos in tmpfile */ *zero; /* anchor line for all other lines */ /* * magic constants used in many places */ #ifdef pdp11 # define _1a ~0377 # define _2a 0400 # define _3a 0377 # define _4a 0774 # define _5a 255 # define _6a 077776 # define _1b ~0177 # define _2b 0200 # define _3b 0777 # define _4b 0774 # define _5b 511 # define _6b 077777 #endif #ifdef vax # define _1a ~0377 # define _2a 0400 # define _3a 077777777 # define _4a 0774 # define _5a 65535 # define _6a 077777776 #endif #ifdef HUGE int _1[] = { _1a, _1b }, /* tl &= _1; getline() */ _2[] = { _2a, _2b }, /* tl += _2; getline()... */ _3[] = { _3a, _3b }, /* bno = ... & _3; getblock() */ _4[] = { _4a, _4b }, /* off = ... & _4; getblock() */ _5[] = { _5a, _5b }, /* if (bno >= _5)... getblock() */ _6[] = { _6a, _6b }; /* tline += ... & _6; */ #else # define _1 _1a # define _2 _2a # define _3 _3a # define _4 _4a # define _5 _5a # define _6 _6a #endif /* * error messages * * (there are more than these) */ char *errtext[] = { /* 0 */ "syntax is k[a-z]", /* 1 */ "illegal command format", /* 2 */ "no command", /* 3 */ "no tab character", /* 4 */ "can't change filename", /* 5 */ "file name syntax", /* 6 */ "recursive \"@\" command", /* 7 */ "null file name illegal", /* 8 */ "unrecognized command", /* 9 */ "no tabs set", /* 10 */ "global command not allowed with huge file", /* 11 */ "file name too long", /* 12 */ "expanded line too long", /* 13 */ "no such line", /* 14 */ "can't fork", /* 15 */ "can't write to process", /* 16 */ "no lines", /* 17 */ "backup(FILE) error (?)", /* 18 */ "string not found", /* 19 */ " ' must be followed by [a-z]", /* 20 */ "address syntax error", /* 21 */ "lower address bound > upper one", /* 22 */ "address illegal here", /* 23 */ "non-existent line number", /* 24 */ "bottom of file reached", /* 25 */ "command syntax error", /* 26 */ "\"advance\" error (?)", /* 27 */ "null string illegal", /* 28 */ "destination not found", /* 29 */ "INTERRUPT!", /* 30 */ "line too long", /* 31 */ "missing destination address", /* 32 */ "I/O error--file not saved!", /* 33 */ "file overflows available memory", /* 34 */ "file too large (TMPERR)", /* 35 */ "I/O error on temp file (TMPERR)", /* 36 */ "open error on temp file (TMPERR)", /* 37 */ "recursive global command", /* 38 */ "global command list too long", /* 39 */ "substitute pattern not found", /* 40 */ "missing substring", /* 41 */ "string2 too long", /* 42 */ "substring too long", /* 43 */ "substituted string too long", /* 44 */ "too many \\(", /* 45 */ "unbalanced \\( \\)", /* 46 */ "\\n illegal", /* 47 */ "unimplemented feature", /* 48 */ "[nothing written]", /* 49 */ "pattern too complicated", /* 50 */ "can't create temp file (TMPERR)", /* 51 */ "bad directory", /* 52 */ "no ! allowed", /* 53 */ "can't read ", /* 54 */ "can't create ", /* 55 */ "%u line%s\n", /* 56 */ "[file saved]", /* 57 */ "\nHangup!\n", /* 58 */ "\nTerminated...\n", /* 59 */ "EOF illegal here", /* 60 */ "can't join to line 0", /* 61 */ "! not allowed with global command", /* 62 */ "no filename specified", /* 63 */ "not enough \\( \\) pairs", /* 64 */ "can't create pipe file (PIPERR)", /* 65 */ "open error on pipe file (PIPERR)", /* 66 */ "can't checkpoint", /* 67 */ "can't recover", }; #define NERR (sizeof errtext / sizeof errtext[0]) /* * ! error strings */ char *status[] = { /* 0 */ 0, /* 1 */ "hangup", /* 2 */ "interrupt", /* 3 */ "quit", /* 4 */ "illegal instruction", /* 5 */ "bpt", /* 6 */ "iot", /* 7 */ "emt", /* 8 */ "fpp", /* 9 */ "killed", /* 10 */ "bus error", /* 11 */ "memory fault", /* 12 */ "bad sys call", /* 13 */ "broken pipe", /* 14 */ "alarm", /* 15 */ "terminated", #ifdef pdp11 /* 16 */ "time limit", #else /* 16 */ 0, /* 17 */ "stopped", /* 18 */ "terminal stop", /* 19 */ "continue", /* 20 */ "child status changed", /* 21 */ "terminal input", /* 22 */ "terminal output", /* 23 */ "terminal input ready", /* 24 */ "cpu timelimit exceeded", /* 25 */ "filesize limit exceeded", #endif }; #define NSTR (sizeof status / sizeof status[0]) #define putsn(x) (puts2((x)),putchar('\n')) #define min(x,y) ((x)<(y)?(x):(y)) #define max(x,y) ((x)>(y)?(x):(y)) /* * function declarations */ linep *findmark(); char *getblock(); long lseek(); func signal(); #ifndef CKPT int badsig(), #else int checkpoint(), #endif hangup(), mail(), onintr(), term(); /* * signals */ struct sigtab { int s_sig, s_func; } sigtab1[] = { #ifdef CKPT SIGILL, checkpoint, SIGIOT, checkpoint, SIGEMT, checkpoint, SIGFPE, checkpoint, SIGBUS, checkpoint, SIGSEGV, checkpoint, SIGSYS, checkpoint, #else SIGILL, badsig, SIGIOT, badsig, SIGEMT, badsig, SIGFPE, badsig, SIGBUS, badsig, SIGSEGV, badsig, SIGSYS, badsig, #endif 0, 0, }, sigtab2[] = { SIGTRC, mail, SIGHUP, hangup, SIGTRM, term, SIGINT, onintr, 0, 0, }; main(argc, argv) char **argv; { #ifdef CKPT extern checkpoint(); #else extern badsig(); #endif extern onintr(), hangup(), mail(), term(); #ifdef DEBUG #ifdef EXPDMP extern expdmp(); #endif #endif register n; register char *p1, *p2, *ep; func savint; signal(SIGQIT, 1); savint = signal(SIGINT, 1); ep = *argv; #ifdef XED p1 = ep; p2 = p1; while (*p1) if (*p1++ == '/' && *p1 && *p1 != '/') p2 = p1; p1 = p2; *argv = p2; n = 0; while (*p1) if (*p1++ == 'x') { /* xed .vs. eed */ ++n; break; } if (n == 0) { e_prompt = EEDPROMPT; ver = EEDTTL; help = EEDHELP; dumbf = 1; } #ifdef LOG logstats.l_xed = n; #endif #endif prompt2 = istty(0); #ifdef V7 if (getenv("_OVERWRITE_")) ++over; #endif while (--argc) if (**++argv == '-') { while (*++*argv) { switch (**argv) { case '!': /* no ! allowed */ noshell = 1; break; #ifdef APLMAP case 'A': /* apl char mapping */ aplmap = 1; errtext[29] = "G interrupt G"; p1 = ver; while (*p1) { if ('A' <= *p1 && *p1 <= 'Z') *p1 |= 040; ++p1; } #endif case 'a': /* apl mode */ aflg = 1; fmtlno = "[ %u ]\t"; #ifdef DUMB dumbf = 1; #endif #ifdef XED #ifdef TTL_NL ver[TTL_NL] = 0; #endif #endif break; case 'b': /* file.bak on entry */ bflg = 1; bflg2 = 1; break; #ifdef PAGE case 'c': /* crt depth in lines */ ++*argv; n = argnum(argv); if (n >= 0) pcount = n; break; #endif case 'd': /* don't delete .edt file */ deltflg = 1; break; case 'e': /* echo input commands */ eflg = 1; break; case 'f': /* create mode */ fflg = 1; break; #ifdef HUGE case 'h': /* edit "huge" file */ hugef = 1; break; #endif case 'i': /* file.int on interrupt */ iflg = 1; break; case 'k': /* kill verbose messages */ curt = 1; break; #ifdef EOL case 'l': /* set eol char to "x" */ if (*++*argv) eol = **argv; else --*argv; break; #endif case 'm': /* mod cnt for autosave */ ++*argv; n = argnum(argv); if (n >= 0) modcount = n; break; case 'n': /* no line num */ prompt1 = 0; break; case 'o': /* no seek to EOF on error */ seekf = 1; break; case 'p': /* force prompts for pipe */ pipef = 1; prompt2 = 1; break; case 'q': /* don't inhibit quits */ signal(SIGQIT, 0); break; #ifdef DUMB case 'r': /* spcl char meaning */ dumbf ^= 01; break; #endif case 's': /* silent mode */ prompt2 = 0; break; #ifdef TABS case 't': /* tab char */ if (*++*argv) tabc = **argv; else --*argv; break; #endif #ifdef TABS case 'v': /* tab fill char */ if (*++*argv) tabfill = **argv; else --*argv; break; #endif #ifdef PAGE case 'w': /* crt width */ ++*argv; n = argnum(argv); if (--n >= 2) ccount = n; break; #endif #ifdef YINT case 'y': /* page on interrupt */ yflg = 1; break; #endif #ifdef USE case '@': /* set "@" filename */ p2 = altfile; p1 = ++*argv; while (*p1 && p2 < &altfile[FNSIZE - 2]) *p2++ = *p1++; if (*p1) { p2 = altfile; putsn(errtext[11]); } *p2 = '\0'; *argv = &p1[-1]; break; #endif #ifdef ALLOC case 'B': /* line buffer size */ ++*argv; n = argnum(argv); if (n >= LBSIZE) lbsize = n; break; #endif #ifdef DEBUG case 'D': /* trace mode -- debug */ tflg = 1; break; #ifdef EXPDMP case 'Q': /* show pattern on quit */ signal(SIGQIT, expdmp); break; #endif #endif #ifdef XED case 'I': /* suppress ID message */ ver = 0; break; case 'P': /* prompt */ p1 = *argv; e_prompt = ++p1; while (*p1++); *argv = &p1[-2]; break; case 'L': /* line number prompt */ p1 = *argv; fmtlno = ++p1; while (*p1++); *argv = &p1[-2]; break; case 'C': /* screen-clear */ p1 = *argv; clears = ++p1; while (*p1++); *argv = &p1[-2]; break; #ifdef CKPT case 'R': /* recover */ ++*argv; if ((recovry = argnum(argv)) == 0) recovry = 1; break; #endif case 'O': /* over-ride write perm */ over ^= 01; break; case 'T': /* temp filename */ p1 = *argv; tfname = ++p1; #ifdef PIPE while (*p1) if (*p1++ == ':') { p1[-1] = '\0'; pfname = p1; #ifdef CKPT break; #endif } #endif #ifdef CKPT while (*p1) if (*p1++ == ':') { p1[-1] = '\0'; cfname = p1; } #endif *argv = &p1[-1]; break; #endif default: /* tabs stops/illegals */ if (!**argv || **argv == '-' #ifdef TABS || **argv == ',' #endif ) break; #ifdef TABS if (**argv < '0' || **argv > '9') { #endif printf("bad flag: -%c\n", **argv); exit(1); #ifdef TABS } n = argnum(argv); settab(n); #endif } } } else { p1 = *argv; p2 = savedfile; while (*p2++ = *p1++) if (p2 >= &savedfile[FNSIZE - 2]) { putsn(errtext[11]); exit(1); } globf2 = 1; if (fflg) globp = "a\n"; else globp = "r\n"; } #ifdef YINT if (iflg) yflg = 0; #endif #ifdef ALLOC linebuf = sbrk(lbsize); genbuf = sbrk(lbsize); #endif fendcore = sbrk(0); #ifdef CKPT if ((n = recovry) == 0) #endif n = getpid(); #ifdef PIPE tmpname(pfname, n); #endif #ifdef CKPT tmpname(cfname, n); #endif tmpname(tfname, n); /* MUST be last call to tmpname */ #ifdef LOG logstats.l_uid = getuid(); time(&logstats.lt_start); if (prompt2) ++logstats.l_inter; if (aflg) logstats.l_xed = 2; /* magic num for apled */ #endif #ifdef CKPT if (recovry) recover(); #endif editor = ep; if (prompt2) { #ifdef CMDS if ((cmd = open(cmdfil, 1)) > 0) lseek(cmd, 0L, 2); else cmd = 0; #endif if (ver) putsn(ver); /* XED V0.00 ... */ flush_buf(); } else modcount = 0; #ifdef CMDS if (cmd && *savedfile) { write(cmd, "e,", 2); p1 = savedfile; while (*p1++); write(cmd, savedfile, --p1 - savedfile); write(cmd, "\n", 1); } #endif signals(sigtab1); setexit(); if (((int)savint & 01) == 0) signals(sigtab2); #ifdef YINT else yflg = 0; #endif #ifdef CKPT if (!recovry) #endif init(); setexit(); cant: do { commands(0); } while (are_you_sure()); if (immflg == 0) { if (fflg) if (backup(FILE)) text_modified = 0; else goto cant; if (text_modified == 0) backup(-TMP); else if (modcount && eof) if (backup(TMP) && prompt2) if (!curt) putsn(errtext[56]); } delexit(0); } abort() { register char *p; register charac c; setnoaddr(); peekc = 0; p = "ort\n"; while (*p) if ((c = getchar()) != *p++) { peekc = c; errmsg(25); } #ifdef LOG ++logstats.lc_abort; #endif delexit(1); } linep * address() { register minus; register charac c; register linep *a1, *start; register n, relerr; minus = 0; a1 = 0; for ever { c = getchar(); if ('0' <= c && c <= '9') { peekc = c; n = getnum(); if (a1 == 0) { a1 = zero; n += aflg; #ifdef LOG if (!globp) ++logstats.la_num; #endif } if (minus < 0) n = -n; a1 += n; minus = 0; continue; } relerr = 0; if (a1 || minus) relerr++; switch (c) { case ' ': case '\t': continue; case '+': minus += brcount; if (a1 == 0) a1 = dot; #ifdef LOG if (!globp) ++logstats.la_plus; #endif continue; case '-': case '^': /* for upwards compatibility */ minus -= brcount; if (a1 == 0) a1 = dot; #ifdef LOG if (!globp) if (c == '^') ++logstats.la_caret; else ++logstats.la_minus; #endif continue; /* search: */ case '?': minus++; case '/': compile(c); if (a1 == 0) a1 = dot; if (a1 < zero) a1 = zero; if (a1 > dol) a1 = dol; start = a1; #ifdef LOG if (!globp) if (minus) ++logstats.la_query; else ++logstats.la_slash; #endif for ever { if (minus == 0) { if (++a1 > dol) a1 = zero; } else { if (--a1 < zero) a1 = dol; } if (execute(0, a1)) { minus = 0; relerr = 0; break; } if (a1