1: static char Sccsid[] = "xed.c @(#)xed.c 1.1 10/1/82 Berkeley ";
2: #
3:
4: /*
5: * V7.15 81/09/16 14:22 Fixed bug causing bus errors occasionally
6: * V7.14 81/09/10 21:50 -B dynamically allocated line buffer
7: * V7.13 81/07/25 22:51 added -O and "long" pointers
8: *
9: * Editor
10: *
11: * Major additions beginning 77/04
12: * Conversion to version 7 79/12
13: * Conversion to VAX 80/11
14: *
15: * Purdue University, Engineering Computer Network
16: *
17: * Tgi -- Room 337A
18: * Electrical Engineering Dept
19: * Purdue University
20: * West Lafayette, Indiana
21: * 47907
22: * 317/49-41592
23: */
24:
25: #define XED /* enable powerful stuff */
26: #define V7 /* enable environment stuff for protocol */
27:
28: /*
29: * At the entry to a function (PDP-11) the following sequence
30: * of instructions is executed:
31: * func: jsr r5,csv
32: * csv: mov r5,r0
33: * csv+2: mov sp,r5
34: * If a signal occurs between the first and second, or between the
35: * second and third instructions, r5 will NOT contain a valid
36: * stack address. Hence, when longjmp() attempts to validate
37: * the environment pointer (r5) links, an instruction will be
38: * fetched instead of a valid pointer, and will generally cause
39: * one of "memory fault", "bus error", or "illegal instruction"
40: * resulting in the loss of the editing session.
41: *
42: * Due to this wonderful feature of version 7 ingenuity, I have
43: * reverted to using setexit/reset, since they are simpler and
44: * do not assume that I do not know what I am doing.
45: *
46: * 80/11/10 V7.01 Tgi
47: */
48:
49: #ifndef pdp11
50: #include <setjmp.h>
51: jmp_buf _env_rst;
52: #define setexit() setjmp(_env_rst)
53: #define reset() longjmp(_env_rst,1)
54: #endif
55:
56: #include <sys/types.h>
57: #include <sys/stat.h>
58:
59: /*
60: * Machine-dependent definitions
61: */
62:
63: #ifdef pdp11
64: # define BPB 8 /* bits per byte */
65: # define BPW (BPB*sizeof(int))/* bits per word */
66: # define BPWC 4 /* log2(BPW) */
67: # define BPWM 017 /* mask of BPWC bits */
68: typedef short block;
69: typedef short charac;
70: typedef short filedes;
71: typedef short flag;
72: typedef int (*func)();
73: typedef short linep;
74: #endif
75:
76: #ifdef vax
77: # define BPB 8 /* bits per byte */
78: # define BPW (BPB*sizeof(int))/* bits per word */
79: # define BPWC 5 /* log2(BPW) */
80: # define BPWM 037 /* mask of BPWC bits */
81: typedef long block;
82: typedef int charac;
83: typedef short filedes;
84: typedef char flag;
85: typedef int (*func)();
86: typedef long linep; /* NEW */
87: #endif
88:
89: /*
90: * conditional compilation
91: */
92:
93: #ifdef XED
94: # define AGAIN /* enable "o" "again" command */
95: # define ALLOC 1024 /* line buffer size */
96: # define APLMAP /* enable Apl character mapping */
97: # define DEBUG /* enable "du" command */
98: # define DUMB 0 /* enable command to disable spcl chars */
99: # define EOL /* enable special eol stuff */
100: # define EXTMARK /* extended "k" capability */
101: # define G_VFY /* enable verifying on "g" command */
102: # define HELP "/etc/xed.doc"
103: # ifdef pdp11 /* only needed on 16-bit machines */
104: # define HUGE /* enable "huge" file stuff */
105: # endif
106: # define PAGE /* enable proper line counting on ":" */
107: # define PARENS /* enable "b" suffix to count parentheses */
108: # define PIPE /* enable | command to pipe to process */
109: # define PROMPT ">"
110: # define STRLEN /* enable string-length counting code */
111: # define TABS ((LBSIZE+sizeof(int)-1)/sizeof(int)) /* words for tab stops */
112: # define TTL "XED\tV7.15"
113: /* #define TTL_NL 9 /* location of newline in TTL */
114: # define UNDO /* enable "u"ndo command */
115: # define USE /* enable "@" command */
116: # define XDEL /* enable undelete stuff */
117: # define YINT /* enable special interrupt processing */
118: #endif
119:
120: /*
121: * stuff for EED, instead of XED
122: */
123:
124: #ifndef XED
125: # define HELP "/etc/eed.doc"
126: # define PROMPT "*"
127: # define TTL "EED"
128: #else
129: # define EEDHELP "/etc/eed.doc"
130: # define EEDPROMPT "*"
131: # define EEDTTL "EED"
132: #endif
133:
134: /*
135: * stuff normally enabled
136: */
137:
138: #define CLEAR "\33:\33H\33J\32\14" /* HP-2640A, Lear ADM-3A */
139: #define CMDS "edsav" /* all commands written if exists */
140: #ifndef DUMB
141: # define DUMB 1 /* enable command to disable spcl chars */
142: #endif
143:
144: /*
145: * special stuff, occasionally enabled
146: */
147:
148: #define LOG "/a/tgi/etc/xed.log" /* feature use logging */
149:
150: /*
151: * data #defines
152: */
153:
154: #define BAK 4 /* file.bak - backup() */
155: #define BLKSIZE 512 /* disk block size (bytes) */
156: #define BS1 0100000 /* stty() */
157: #define CBACK 14 /* back-reference: \(blah\)more\1 */
158: #define CBRA 1 /* \( */
159: #define CCHR 2 /* literal character */
160: #define CCL 6 /* character class [x...y] */
161: #define CCOUNT (80-1) /* terminal width */
162: #define CDOL 10 /* ...$ */
163: #define CDOT 4 /* . */
164: #define CEOF 11 /* end of pattern */
165: #define CKET 12 /* \) */
166: #define EOF -1 /* end of file */
167: #define ESIZE 128 /* regular expression size */
168: #define FILE 0 /* no extension - backup() */
169: #define FNSIZE 64 /* max size of pathname to file */
170: #define GBSIZE 256 /* max global command length */
171: #define HUP 3 /* file.hup - backup() */
172: #define INT 2 /* file.int - backup() */
173: #define LBSIZE 512 /* max line length */
174: #define LMASK 077 /* mask for "locked" file */
175: #define LMODE (MODE&~LMASK) /* mode for "locked" file */
176: #define MODCNT 35 /* default mod count before auto-write */
177: #define MODE 0666 /* mode for normal files */
178: #define NBRA 9 /* number of \( \) pairs */
179: #define NCCL 8 /* not in character class: [^x...y] */
180: #define PAGSIZ 22 /* page size for ":" command */
181: #define READ 0 /* getblock: read function */
182: #define SIGBUS 10 /* Bus error */
183: #define SIGEMT 7 /* EMT trap */
184: #define SIGFPE 8 /* Floating Point Exception */
185: #define SIGHUP 1 /* Hangup signal */
186: #define SIGILL 4 /* Illegal instruction */
187: #define SIGINT 2 /* Interrupt signal */
188: #define SIGIOT 6 /* IOT trap */
189: #define SIGPIP 13 /* Broken pipe for ! stuff */
190: #define SIGQIT 3 /* Quit signal */
191: #define SIGSEGV 11 /* Memory fault */
192: #define SIGSYS 12 /* Bad system call */
193: #define SIGTRC 5 /* Trace/BPT for mail stuff */
194: #define SIGTRM 15 /* Termination */
195: #define STAR 1 /* * */
196: #define TABFILL '\t' /* fill character for tab expansion */
197: #define TMP 1 /* file.edt - backup() */
198: #define TRM 5 /* file.trm - backup() */
199: #define TTSIZE (512+4) /* terminal output buffer size */
200: #define WRITE 1 /* getblock: write function */
201: #define ever (;;)
202:
203: #define error errfunc
204: #define ctrl(x) ((x)&037)
205:
206: #ifdef AGAIN
207: char agbuf[GBSIZE], /* save area for "again" command */
208: *agp = 0; /* "again" command pointer */
209: flag agf = 0; /* "again" flag (executing the command) */
210: #endif
211:
212: #ifdef ALLOC
213: int lbsize = LBSIZE;/* line buffer size */
214: #endif
215:
216: #ifdef APLMAP
217: flag aplmap = 0; /* Apl character mapping */
218: #include "aplmap.h" /* apl ADM-3A char set mapping tables */
219: #endif
220:
221: #ifdef CKPT
222: char *cfname = "/tmp/ce00000";/* filename for checkpoint */
223: int recovry = 0, /* non-zero to recover checkpointed session */
224: tfnum; /* index into tfname for "00000" string */
225: #endif
226:
227: #ifdef CLEAR
228: char *clears = CLEAR;/* screen-clear sequence */
229: flag zflg = 0; /* if "stty bs1" not set */
230: /* bs1 displays ctrl-z as ^Z on tty */
231: #endif
232:
233: #ifdef CMDS
234: filedes cmd = 0; /* file des for command-save file */
235: char cmdfil[] = CMDS;/* command-save file */
236: #endif
237:
238: #ifdef DEBUG
239: flag tflg = 0; /* tracing flag */
240: #endif
241:
242: #ifdef DUMB
243: flag dumbf = DUMB; /* 1 = disable special chars in patterns */
244: #endif
245:
246: #ifdef EOL
247: charac eol = 0; /* "end-of-line" char for multiple commands */
248: /* per line */
249: flag prompt3 = 1; /* disable prompts for "eol" stuff */
250: #endif
251:
252: #ifdef G_VFY
253: flag gaskf = 0; /* verify mode on global command */
254: #endif
255:
256: #ifdef HELP
257: filedes doc = 0; /* "help" file descriptor */
258: char *help = HELP; /* "help" file name */
259: #endif
260:
261: #ifdef LOG
262: char logfile[]= LOG; /* logging use of features */
263: filedes lfile = 0; /* logging file descriptor */
264: short logamp; /* since s/x/&/ may be done many times */
265: struct logstat {
266: short l_uid; /* user id of caller */
267: char l_xed, /* 1 if xed, 0 if eed, 2 if apled */
268: l_inter; /* 1 if interactive */
269: /* command features */
270: short lc_shell, /* ! */
271: lc_pipe, /* | */
272: lc_piplus, /* |+ */
273: lc_piminus, /* |- */
274: lc_dpipe, /* || */
275: lc_pfrom, /* |< */
276: lc_pto, /* |> */
277: lc_at, /* @ */
278: lc_colon, /* : */
279: lc_star, /* * */
280: lc_clnminus, /* :- */
281: lc_comment, /* : stuff or * stuff */
282: lc_append, /* a */
283: lc_abort, /* abort */
284: lc_aspace, /* a line */
285: lc_aslash, /* a/string/ */
286: lc_browse, /* bN */
287: lc_change, /* c */
288: lc_cslash, /* c/s1/s2/ */
289: lc_copy, /* coNN */
290: lc_delete, /* d */
291: lc_depth, /* d=NN */
292: lc_directory, /* d path */
293: lc_edit, /* e file */
294: lc_eol, /* e=C */
295: lc_errmsg, /* eNN */
296: lc_exp, /* exp */
297: lc_eplus, /* e+ */
298: lc_eminus, /* e- */
299: lc_fshow, /* f */
300: lc_fset, /* f file */
301: lc_fillset, /* f=C */
302: lc_global, /* g/str/cmd */
303: lc_gvfy, /* g/str/vcmd */
304: lc_header, /* h */
305: lc_help, /* help */
306: lc_insert, /* i */
307: lc_islash, /* i/string/ */
308: lc_join, /* j */
309: lc_jglue, /* j/glue/ */
310: lc_klist, /* k */
311: lc_kset, /* kC */
312: lc_list, /* l */
313: lc_move, /* mNN */
314: lc_moove, /* moNN */
315: lc_magic, /* m */
316: lc_numbers, /* n */
317: lc_numinus, /* n- */
318: lc_numplus, /* n+ */
319: lc_o, /* o ^Q */
320: lc_print, /* p */
321: lc_pprint, /* pp */
322: lc_quit, /* q */
323: lc_qimm, /* qi */
324: lc_quote, /* q=C */
325: lc_read, /* r */
326: lc_substitute, /* s/s1/s2/ */
327: lc_stop, /* s */
328: lc_savecount, /* saNN */
329: lc_tablist, /* t */
330: lc_tabset, /* t,NN */
331: lc_tabchar, /* t=C */
332: lc_transfer, /* tNN */
333: lc_undo, /* u */
334: lc_vglobal, /* v/str/cmd */
335: lc_write, /* w */
336: lc_wonto, /* w> */
337: lc_wimm, /* wi */
338: lc_width, /* w=NN */
339: lc_xundelete, /* x */
340: lc_yintr, /* y */
341: lc_yminus, /* y- */
342: lc_yplus, /* y+ */
343: /* address features */
344: la_dot, /* . */
345: la_dotdot, /* .. */
346: la_dol, /* $ */
347: la_num, /* NN */
348: la_plus, /* + */
349: la_minus, /* - */
350: la_caret, /* ^ */
351: la_quote, /* 'a */
352: la_letter, /* A */
353: la_slash, /* /str/ */
354: la_query, /* ?str? */
355: la_equal, /* = */
356: /* pattern features */
357: lp_caret, /* ^ */
358: lp_dol, /* $ */
359: lp_dot, /* . */
360: lp_star, /* * */
361: lp_ccl, /* [ ] */
362: lp_nccl, /* [^ ] */
363: lp_paren, /* \( \) */
364: lp_digit, /* \1 \2 \3 ... */
365: /* substitution features */
366: lp_amp, /* & */
367: /* miscellaneous features */
368: lm_quote, /* ...q */
369: lm_bracket, /* ...b */
370: lm_overwrite; /* -O,wi */
371: /* resources */
372: long lt_start, /* starting time */
373: lt_end, /* elapsed time */
374: lt_usercpu, /* user cpu time */
375: lt_syscpu, /* system cpu time */
376: lt_kidscpu, /* total ! kids time */
377: lt_rlines, /* total lines read */
378: lt_wlines; /* total lines written */
379: } logstats;
380: #endif
381:
382: #ifdef PAGE
383: int ccount = CCOUNT;/* terminal width */
384: #endif
385:
386: #ifdef PARENS
387: int parenc[3] = {0, 0, 0};/* parentheses counts */
388: flag parenf = 0; /* count parentheses and brackets */
389: #endif
390:
391: #ifdef PIPE
392: filedes pfile = 0; /* "pipe" file descriptor */
393: char *pfname = "/tmp/ep00000";/* for "double-piping" */
394: flag piperr = 0, /* pipe error flag - shell() */
395: pno = -1, /* piping line numbering flag (default n-) */
396: strict = 1; /* strict exit status checking for | */
397: #endif
398:
399: #ifdef STRLEN
400: charac quotec = '\0', /* quote character other than " or ' */
401: quotec2 = '\0'; /* closing quote */
402: int quotef = 0; /* length of strings within " or ' chars */
403: #endif
404:
405: #ifdef TABS
406: charac tabfill = TABFILL,/* fill character */
407: tabc = 0; /* tab character - if 0 no tab processing */
408: int maxtab = -1, /* last column number with tab stop */
409: tabs[TABS]; /* each bit on = tab stop */
410: #endif
411:
412: #ifdef UNDO
413: linep undo_oldp, /* original line pointer */
414: undo_newp; /* replacement line */
415: #endif
416:
417: #ifdef USE
418: filedes alt = 0; /* alternate command input file */
419: char altfile[FNSIZE];
420: flag eflg2 = 0; /* another kludge */
421: #endif
422:
423: #ifdef XDEL
424: linep deleted = 0; /* pointer to deleted line pointers */
425: int ndeleted = 0; /* number of lines */
426: #endif
427:
428: #ifdef YINT
429: flag yflg = 0; /* page upon interrupt */
430: linep *yplus = 0; /* page from this line - if zero, from dot */
431: #endif
432:
433: /*
434: * globals
435: */
436:
437: block iblock = -1, /* block number of input buffer */
438: oblock = -1; /* output buffer block number */
439:
440: char *braelist[NBRA], /* bracket \( \) end list */
441: *braslist[NBRA], /* bracket \( \) start list */
442: dotbak[] = ".bak",
443: dotedt[] = ".edt", /* "file saved" file */
444: dothup[] = ".hup",
445: dotint[] = ".int",
446: dottrm[] = ".trm",
447: *dots[] = { dothup, dottrm, dotedt, dotint, 0 },
448: expbuf[ESIZE + 4], /* expression buffer */
449: file[FNSIZE], /* filename buffer */
450: #ifndef ALLOC
451: genbuf[LBSIZE], /* generated line buffer */
452: #else
453: *genbuf, /* generated line buffer pointer */
454: #endif
455: ibuff[BLKSIZE], /* input tmpfile buffer */
456: line[TTSIZE + 4], /* terminal output buffer */
457: #ifndef ALLOC
458: linebuf[LBSIZE], /* line buffer for getline()/putline() */
459: #else
460: *linebuf, /* line buffer for getline()/putline() */
461: #endif
462: no[] = "no ",
463: null[] = "", /* "" */
464: obuff[BLKSIZE], /* output tmpfile buffer */
465: off[] = "off",
466: on[] = "on",
467: prcntu[] = "%u\n", /* %u */
468: quote_s[] = "s", /* "s" */
469: rhsbuf[LBSIZE / 2], /* right-hand-side expression buffer */
470: savedfile[FNSIZE], /* saved filename */
471: tempfile[FNSIZE], /* scratch area for filename */
472:
473: *editor, /* argv[0] */
474: *e_prompt = PROMPT,/* editor command prompt */
475: *fmtlno = "%7u=",/* format for line-number output */
476: *globp, /* global command pointer */
477: *linp = line, /* line pointer */
478: *linebp,
479: *loc1, /* start pointer of & string */
480: *loc2, /* end pointer of & string */
481: *locs,
482: *nextip,
483: *overfile, /* filename mode was changed on */
484: *tfname = "/tmp/e00000",/* "buffer" name */
485: *ver = TTL; /* ID message */
486:
487: charac lastc = 0, /* peekc set to lastc on interrupt */
488: peekc = 0; /* one character pushback */
489:
490: int brcount = 1, /* number of lines to output on "newline" */
491: col = 0, /* column counter for calculating line wraps */
492: line_num, /* integer for line number on output */
493: modcount = MODCNT,/* number of mods before auto-write */
494: overmode, /* mode of overridden file */
495: mods = 0, /* number of mods */
496: nbra = 0, /* count of currently defined \( \) pairs */
497: ninbuf, /* bytes in tmpfile input buffer */
498: nleft, /* bytes remaining in tmpfile output buffer */
499: num_reads = 0, /* indicator to aid text_modified-- */
500: /* first read isn't really a modify */
501: pcount = PAGSIZ-1,/* number of lines to display on ":" command */
502: s_cnt = 0, /* counter for "s/str1/str2/nn" */
503: s_tmp = 0, /* scratch var for same */
504: savf, /* counter for auto-write stuff */
505: text_modified = 0;/* flag--on if text was modified */
506:
507: filedes fout = 1, /* putchar() writes on this fildes */
508: io = 0, /* file descriptor for "r", "w", "e" */
509: tfile = -1; /* file des for "buffer" */
510:
511: flag aflg = 0, /* "apl mode" flag */
512: appflg = 0, /* append flag (if "w>file") */
513: badf = 0, /* bad read on temp file */
514: bflg = 0, /* "back-up" flag -- Generate back-up file */
515: bflg2 = 0, /* Secondary "back-up" flag */
516: circfl, /* reg expr started with ^ */
517: curt = 0, /* short error messages -- ie: '?' */
518: deltflg = 0, /* don't delete .edt file upon exit */
519: eflg = 0, /* echo input flag */
520: eof = 0, /* eof was last char typed */
521: fflg = 0, /* "create" flag */
522: globf2 = 0, /* kludge for -f */
523: #ifdef HUGE
524: hugef = 0, /* -h is process huge file */
525: hugef2 = 0, /* getblock() conversion to huge */
526: #endif
527: hupflag = 0, /* hangup signal has been caught */
528: ichanged, /* ibuf has been changed */
529: iflg = 0, /* file.int and exit on interrupt */
530: immflg = 0, /* immediate flag -- q and e */
531: io_w = 0, /* writing in progress */
532: listf = 0, /* list control chars explicitly */
533: noshell = 0, /* true if no ! command allowed */
534: over = 0, /* override permissions on write if possible */
535: pflag, /* print line after doing command */
536: pipef = 0, /* for talking to pipes */
537: prompt1 = 1, /* flag--enable or disable line-num prompts */
538: prompt2 = 1, /* flag--enable or disable ALL prompting */
539: reading = 0, /* waiting on tty read */
540: seekf = 0, /* no seek to EOF on error on fd 0 */
541: termflg = 0; /* if termination signal (15) occurred */
542:
543: linep *addr1, /* lower line bound */
544: *addr2, /* upper line bound */
545: *dol, /* last line in file */
546: *dot, /* "current" line */
547: *dotdot, /* last different "dot" */
548: *endcore, /* current end of memory */
549: *fendcore, /* start of dynamic area */
550: *lastdot, /* last "dot" */
551: names['z' - 'a' + 1], /* "k" command markers */
552: #ifdef EXTMARK
553: names2['z' - 'a' + 1], /* "k" command markers */
554: #endif
555: *old_a1, /* previous address bounds */
556: *old_a2,
557: tline, /* pointer to next available pos in tmpfile */
558: *zero; /* anchor line for all other lines */
559:
560: /*
561: * magic constants used in many places
562: */
563:
564: #ifdef pdp11
565: # define _1a ~0377
566: # define _2a 0400
567: # define _3a 0377
568: # define _4a 0774
569: # define _5a 255
570: # define _6a 077776
571: # define _1b ~0177
572: # define _2b 0200
573: # define _3b 0777
574: # define _4b 0774
575: # define _5b 511
576: # define _6b 077777
577: #endif
578:
579: #ifdef vax
580: # define _1a ~0377
581: # define _2a 0400
582: # define _3a 077777777
583: # define _4a 0774
584: # define _5a 65535
585: # define _6a 077777776
586: #endif
587:
588: #ifdef HUGE
589: int _1[] = { _1a, _1b }, /* tl &= _1; getline() */
590: _2[] = { _2a, _2b }, /* tl += _2; getline()... */
591: _3[] = { _3a, _3b }, /* bno = ... & _3; getblock() */
592: _4[] = { _4a, _4b }, /* off = ... & _4; getblock() */
593: _5[] = { _5a, _5b }, /* if (bno >= _5)... getblock() */
594: _6[] = { _6a, _6b }; /* tline += ... & _6; */
595: #else
596: # define _1 _1a
597: # define _2 _2a
598: # define _3 _3a
599: # define _4 _4a
600: # define _5 _5a
601: # define _6 _6a
602: #endif
603:
604: /*
605: * error messages
606: *
607: * (there are more than these)
608: */
609:
610: char *errtext[] = {
611: /* 0 */ "syntax is k[a-z]",
612: /* 1 */ "illegal command format",
613: /* 2 */ "no command",
614: /* 3 */ "no tab character",
615: /* 4 */ "can't change filename",
616: /* 5 */ "file name syntax",
617: /* 6 */ "recursive \"@\" command",
618: /* 7 */ "null file name illegal",
619: /* 8 */ "unrecognized command",
620: /* 9 */ "no tabs set",
621: /* 10 */ "global command not allowed with huge file",
622: /* 11 */ "file name too long",
623: /* 12 */ "expanded line too long",
624: /* 13 */ "no such line",
625: /* 14 */ "can't fork",
626: /* 15 */ "can't write to process",
627: /* 16 */ "no lines",
628: /* 17 */ "backup(FILE) error (?)",
629: /* 18 */ "string not found",
630: /* 19 */ " ' must be followed by [a-z]",
631: /* 20 */ "address syntax error",
632: /* 21 */ "lower address bound > upper one",
633: /* 22 */ "address illegal here",
634: /* 23 */ "non-existent line number",
635: /* 24 */ "bottom of file reached",
636: /* 25 */ "command syntax error",
637: /* 26 */ "\"advance\" error (?)",
638: /* 27 */ "null string illegal",
639: /* 28 */ "destination not found",
640: /* 29 */ "INTERRUPT!",
641: /* 30 */ "line too long",
642: /* 31 */ "missing destination address",
643: /* 32 */ "I/O error--file not saved!",
644: /* 33 */ "file overflows available memory",
645: /* 34 */ "file too large (TMPERR)",
646: /* 35 */ "I/O error on temp file (TMPERR)",
647: /* 36 */ "open error on temp file (TMPERR)",
648: /* 37 */ "recursive global command",
649: /* 38 */ "global command list too long",
650: /* 39 */ "substitute pattern not found",
651: /* 40 */ "missing substring",
652: /* 41 */ "string2 too long",
653: /* 42 */ "substring too long",
654: /* 43 */ "substituted string too long",
655: /* 44 */ "too many \\(",
656: /* 45 */ "unbalanced \\( \\)",
657: /* 46 */ "\\n illegal",
658: /* 47 */ "unimplemented feature",
659: /* 48 */ "[nothing written]",
660: /* 49 */ "pattern too complicated",
661: /* 50 */ "can't create temp file (TMPERR)",
662: /* 51 */ "bad directory",
663: /* 52 */ "no ! allowed",
664: /* 53 */ "can't read ",
665: /* 54 */ "can't create ",
666: /* 55 */ "%u line%s\n",
667: /* 56 */ "[file saved]",
668: /* 57 */ "\nHangup!\n",
669: /* 58 */ "\nTerminated...\n",
670: /* 59 */ "EOF illegal here",
671: /* 60 */ "can't join to line 0",
672: /* 61 */ "! not allowed with global command",
673: /* 62 */ "no filename specified",
674: /* 63 */ "not enough \\( \\) pairs",
675: /* 64 */ "can't create pipe file (PIPERR)",
676: /* 65 */ "open error on pipe file (PIPERR)",
677: /* 66 */ "can't checkpoint",
678: /* 67 */ "can't recover",
679: };
680: #define NERR (sizeof errtext / sizeof errtext[0])
681:
682: /*
683: * ! error strings
684: */
685:
686: char *status[] = {
687: /* 0 */ 0,
688: /* 1 */ "hangup",
689: /* 2 */ "interrupt",
690: /* 3 */ "quit",
691: /* 4 */ "illegal instruction",
692: /* 5 */ "bpt",
693: /* 6 */ "iot",
694: /* 7 */ "emt",
695: /* 8 */ "fpp",
696: /* 9 */ "killed",
697: /* 10 */ "bus error",
698: /* 11 */ "memory fault",
699: /* 12 */ "bad sys call",
700: /* 13 */ "broken pipe",
701: /* 14 */ "alarm",
702: /* 15 */ "terminated",
703: #ifdef pdp11
704: /* 16 */ "time limit",
705: #else
706: /* 16 */ 0,
707: /* 17 */ "stopped",
708: /* 18 */ "terminal stop",
709: /* 19 */ "continue",
710: /* 20 */ "child status changed",
711: /* 21 */ "terminal input",
712: /* 22 */ "terminal output",
713: /* 23 */ "terminal input ready",
714: /* 24 */ "cpu timelimit exceeded",
715: /* 25 */ "filesize limit exceeded",
716: #endif
717: };
718: #define NSTR (sizeof status / sizeof status[0])
719:
720: #define putsn(x) (puts2((x)),putchar('\n'))
721: #define min(x,y) ((x)<(y)?(x):(y))
722: #define max(x,y) ((x)>(y)?(x):(y))
723:
724: /*
725: * function declarations
726: */
727:
728: linep *findmark();
729: char *getblock();
730: long lseek();
731: func signal();
732: #ifndef CKPT
733: int badsig(),
734: #else
735: int checkpoint(),
736: #endif
737: hangup(),
738: mail(),
739: onintr(),
740: term();
741:
742: /*
743: * signals
744: */
745:
746: struct sigtab {
747: int s_sig,
748: s_func;
749: } sigtab1[] = {
750: #ifdef CKPT
751: SIGILL, checkpoint,
752: SIGIOT, checkpoint,
753: SIGEMT, checkpoint,
754: SIGFPE, checkpoint,
755: SIGBUS, checkpoint,
756: SIGSEGV, checkpoint,
757: SIGSYS, checkpoint,
758: #else
759: SIGILL, badsig,
760: SIGIOT, badsig,
761: SIGEMT, badsig,
762: SIGFPE, badsig,
763: SIGBUS, badsig,
764: SIGSEGV, badsig,
765: SIGSYS, badsig,
766: #endif
767: 0, 0,
768: }, sigtab2[] = {
769: SIGTRC, mail,
770: SIGHUP, hangup,
771: SIGTRM, term,
772: SIGINT, onintr,
773: 0, 0,
774: };
775:
776: main(argc, argv)
777: char **argv;
778: {
779: #ifdef CKPT
780: extern checkpoint();
781: #else
782: extern badsig();
783: #endif
784: extern onintr(), hangup(), mail(), term();
785: #ifdef DEBUG
786: #ifdef EXPDMP
787: extern expdmp();
788: #endif
789: #endif
790: register n;
791: register char *p1, *p2, *ep;
792: func savint;
793:
794: signal(SIGQIT, 1);
795: savint = signal(SIGINT, 1);
796: ep = *argv;
797: #ifdef XED
798: p1 = ep;
799: p2 = p1;
800: while (*p1)
801: if (*p1++ == '/' && *p1 && *p1 != '/')
802: p2 = p1;
803: p1 = p2;
804: *argv = p2;
805: n = 0;
806: while (*p1)
807: if (*p1++ == 'x') { /* xed .vs. eed */
808: ++n;
809: break;
810: }
811: if (n == 0) {
812: e_prompt = EEDPROMPT;
813: ver = EEDTTL;
814: help = EEDHELP;
815: dumbf = 1;
816: }
817: #ifdef LOG
818: logstats.l_xed = n;
819: #endif
820: #endif
821: prompt2 = istty(0);
822: #ifdef V7
823: if (getenv("_OVERWRITE_"))
824: ++over;
825: #endif
826: while (--argc)
827: if (**++argv == '-') {
828: while (*++*argv) {
829: switch (**argv) {
830: case '!': /* no ! allowed */
831: noshell = 1;
832: break;
833: #ifdef APLMAP
834: case 'A': /* apl char mapping */
835: aplmap = 1;
836: errtext[29] = "G interrupt G";
837: p1 = ver;
838: while (*p1) {
839: if ('A' <= *p1 && *p1 <= 'Z')
840: *p1 |= 040;
841: ++p1;
842: }
843: #endif
844: case 'a': /* apl mode */
845: aflg = 1;
846: fmtlno = "[ %u ]\t";
847: #ifdef DUMB
848: dumbf = 1;
849: #endif
850: #ifdef XED
851: #ifdef TTL_NL
852: ver[TTL_NL] = 0;
853: #endif
854: #endif
855: break;
856: case 'b': /* file.bak on entry */
857: bflg = 1;
858: bflg2 = 1;
859: break;
860: #ifdef PAGE
861: case 'c': /* crt depth in lines */
862: ++*argv;
863: n = argnum(argv);
864: if (n >= 0)
865: pcount = n;
866: break;
867: #endif
868: case 'd': /* don't delete .edt file */
869: deltflg = 1;
870: break;
871: case 'e': /* echo input commands */
872: eflg = 1;
873: break;
874: case 'f': /* create mode */
875: fflg = 1;
876: break;
877: #ifdef HUGE
878: case 'h': /* edit "huge" file */
879: hugef = 1;
880: break;
881: #endif
882: case 'i': /* file.int on interrupt */
883: iflg = 1;
884: break;
885: case 'k': /* kill verbose messages */
886: curt = 1;
887: break;
888: #ifdef EOL
889: case 'l': /* set eol char to "x" */
890: if (*++*argv)
891: eol = **argv;
892: else
893: --*argv;
894: break;
895: #endif
896: case 'm': /* mod cnt for autosave */
897: ++*argv;
898: n = argnum(argv);
899: if (n >= 0)
900: modcount = n;
901: break;
902: case 'n': /* no line num */
903: prompt1 = 0;
904: break;
905: case 'o': /* no seek to EOF on error */
906: seekf = 1;
907: break;
908: case 'p': /* force prompts for pipe */
909: pipef = 1;
910: prompt2 = 1;
911: break;
912: case 'q': /* don't inhibit quits */
913: signal(SIGQIT, 0);
914: break;
915: #ifdef DUMB
916: case 'r': /* spcl char meaning */
917: dumbf ^= 01;
918: break;
919: #endif
920: case 's': /* silent mode */
921: prompt2 = 0;
922: break;
923: #ifdef TABS
924: case 't': /* tab char */
925: if (*++*argv)
926: tabc = **argv;
927: else
928: --*argv;
929: break;
930: #endif
931: #ifdef TABS
932: case 'v': /* tab fill char */
933: if (*++*argv)
934: tabfill = **argv;
935: else
936: --*argv;
937: break;
938: #endif
939: #ifdef PAGE
940: case 'w': /* crt width */
941: ++*argv;
942: n = argnum(argv);
943: if (--n >= 2)
944: ccount = n;
945: break;
946: #endif
947: #ifdef YINT
948: case 'y': /* page on interrupt */
949: yflg = 1;
950: break;
951: #endif
952: #ifdef USE
953: case '@': /* set "@" filename */
954: p2 = altfile;
955: p1 = ++*argv;
956: while (*p1 && p2 < &altfile[FNSIZE - 2])
957: *p2++ = *p1++;
958: if (*p1) {
959: p2 = altfile;
960: putsn(errtext[11]);
961: }
962: *p2 = '\0';
963: *argv = &p1[-1];
964: break;
965: #endif
966: #ifdef ALLOC
967: case 'B': /* line buffer size */
968: ++*argv;
969: n = argnum(argv);
970: if (n >= LBSIZE)
971: lbsize = n;
972: break;
973: #endif
974: #ifdef DEBUG
975: case 'D': /* trace mode -- debug */
976: tflg = 1;
977: break;
978: #ifdef EXPDMP
979: case 'Q': /* show pattern on quit */
980: signal(SIGQIT, expdmp);
981: break;
982: #endif
983: #endif
984: #ifdef XED
985: case 'I': /* suppress ID message */
986: ver = 0;
987: break;
988: case 'P': /* prompt */
989: p1 = *argv;
990: e_prompt = ++p1;
991: while (*p1++);
992: *argv = &p1[-2];
993: break;
994: case 'L': /* line number prompt */
995: p1 = *argv;
996: fmtlno = ++p1;
997: while (*p1++);
998: *argv = &p1[-2];
999: break;
1000: case 'C': /* screen-clear */
1001: p1 = *argv;
1002: clears = ++p1;
1003: while (*p1++);
1004: *argv = &p1[-2];
1005: break;
1006: #ifdef CKPT
1007: case 'R': /* recover */
1008: ++*argv;
1009: if ((recovry = argnum(argv)) == 0)
1010: recovry = 1;
1011: break;
1012: #endif
1013: case 'O': /* over-ride write perm */
1014: over ^= 01;
1015: break;
1016: case 'T': /* temp filename */
1017: p1 = *argv;
1018: tfname = ++p1;
1019: #ifdef PIPE
1020: while (*p1)
1021: if (*p1++ == ':') {
1022: p1[-1] = '\0';
1023: pfname = p1;
1024: #ifdef CKPT
1025: break;
1026: #endif
1027: }
1028: #endif
1029: #ifdef CKPT
1030: while (*p1)
1031: if (*p1++ == ':') {
1032: p1[-1] = '\0';
1033: cfname = p1;
1034: }
1035: #endif
1036: *argv = &p1[-1];
1037: break;
1038: #endif
1039: default: /* tabs stops/illegals */
1040: if (!**argv || **argv == '-'
1041: #ifdef TABS
1042: || **argv == ','
1043: #endif
1044: )
1045: break;
1046: #ifdef TABS
1047: if (**argv < '0' ||
1048: **argv > '9') {
1049: #endif
1050: printf("bad flag: -%c\n",
1051: **argv);
1052: exit(1);
1053: #ifdef TABS
1054: }
1055: n = argnum(argv);
1056: settab(n);
1057: #endif
1058: }
1059: }
1060: } else {
1061: p1 = *argv;
1062: p2 = savedfile;
1063: while (*p2++ = *p1++)
1064: if (p2 >= &savedfile[FNSIZE - 2]) {
1065: putsn(errtext[11]);
1066: exit(1);
1067: }
1068: globf2 = 1;
1069: if (fflg)
1070: globp = "a\n";
1071: else
1072: globp = "r\n";
1073: }
1074:
1075:
1076: #ifdef YINT
1077: if (iflg)
1078: yflg = 0;
1079: #endif
1080: #ifdef ALLOC
1081: linebuf = sbrk(lbsize);
1082: genbuf = sbrk(lbsize);
1083: #endif
1084: fendcore = sbrk(0);
1085: #ifdef CKPT
1086: if ((n = recovry) == 0)
1087: #endif
1088: n = getpid();
1089: #ifdef PIPE
1090: tmpname(pfname, n);
1091: #endif
1092: #ifdef CKPT
1093: tmpname(cfname, n);
1094: #endif
1095: tmpname(tfname, n); /* MUST be last call to tmpname */
1096: #ifdef LOG
1097: logstats.l_uid = getuid();
1098: time(&logstats.lt_start);
1099: if (prompt2)
1100: ++logstats.l_inter;
1101: if (aflg)
1102: logstats.l_xed = 2; /* magic num for apled */
1103: #endif
1104: #ifdef CKPT
1105: if (recovry)
1106: recover();
1107: #endif
1108: editor = ep;
1109: if (prompt2) {
1110: #ifdef CMDS
1111: if ((cmd = open(cmdfil, 1)) > 0)
1112: lseek(cmd, 0L, 2);
1113: else
1114: cmd = 0;
1115: #endif
1116: if (ver)
1117: putsn(ver); /* XED V0.00 ... */
1118: flush_buf();
1119: } else
1120: modcount = 0;
1121: #ifdef CMDS
1122: if (cmd && *savedfile) {
1123: write(cmd, "e,", 2);
1124: p1 = savedfile;
1125: while (*p1++);
1126: write(cmd, savedfile, --p1 - savedfile);
1127: write(cmd, "\n", 1);
1128: }
1129: #endif
1130: signals(sigtab1);
1131: setexit();
1132: if (((int)savint & 01) == 0)
1133: signals(sigtab2);
1134: #ifdef YINT
1135: else
1136: yflg = 0;
1137: #endif
1138: #ifdef CKPT
1139: if (!recovry)
1140: #endif
1141: init();
1142: setexit();
1143: cant: do {
1144: commands(0);
1145: } while (are_you_sure());
1146: if (immflg == 0) {
1147: if (fflg)
1148: if (backup(FILE))
1149: text_modified = 0;
1150: else
1151: goto cant;
1152: if (text_modified == 0)
1153: backup(-TMP);
1154: else if (modcount && eof)
1155: if (backup(TMP) && prompt2)
1156: if (!curt)
1157: putsn(errtext[56]);
1158: }
1159: delexit(0);
1160: }
1161:
1162: abort() {
1163: register char *p;
1164: register charac c;
1165:
1166: setnoaddr();
1167: peekc = 0;
1168: p = "ort\n";
1169: while (*p)
1170: if ((c = getchar()) != *p++) {
1171: peekc = c;
1172: errmsg(25);
1173: }
1174: #ifdef LOG
1175: ++logstats.lc_abort;
1176: #endif
1177: delexit(1);
1178: }
1179:
1180: linep *
1181: address() {
1182: register minus;
1183: register charac c;
1184: register linep *a1, *start;
1185: register n, relerr;
1186:
1187: minus = 0;
1188: a1 = 0;
1189: for ever {
1190: c = getchar();
1191: if ('0' <= c && c <= '9') {
1192: peekc = c;
1193: n = getnum();
1194: if (a1 == 0) {
1195: a1 = zero;
1196: n += aflg;
1197: #ifdef LOG
1198: if (!globp)
1199: ++logstats.la_num;
1200: #endif
1201: }
1202: if (minus < 0)
1203: n = -n;
1204: a1 += n;
1205: minus = 0;
1206: continue;
1207: }
1208: relerr = 0;
1209: if (a1 || minus)
1210: relerr++;
1211: switch (c) {
1212: case ' ':
1213: case '\t':
1214: continue;
1215:
1216: case '+':
1217: minus += brcount;
1218: if (a1 == 0)
1219: a1 = dot;
1220: #ifdef LOG
1221: if (!globp)
1222: ++logstats.la_plus;
1223: #endif
1224: continue;
1225:
1226: case '-':
1227: case '^': /* for upwards compatibility */
1228: minus -= brcount;
1229: if (a1 == 0)
1230: a1 = dot;
1231: #ifdef LOG
1232: if (!globp)
1233: if (c == '^')
1234: ++logstats.la_caret;
1235: else
1236: ++logstats.la_minus;
1237: #endif
1238: continue;
1239:
1240: /* search: */
1241: case '?':
1242: minus++;
1243: case '/':
1244: compile(c);
1245: if (a1 == 0)
1246: a1 = dot;
1247: if (a1 < zero)
1248: a1 = zero;
1249: if (a1 > dol)
1250: a1 = dol;
1251: start = a1;
1252: #ifdef LOG
1253: if (!globp)
1254: if (minus)
1255: ++logstats.la_query;
1256: else
1257: ++logstats.la_slash;
1258: #endif
1259: for ever {
1260: if (minus == 0) {
1261: if (++a1 > dol)
1262: a1 = zero;
1263: } else {
1264: if (--a1 < zero)
1265: a1 = dol;
1266: }
1267: if (execute(0, a1)) {
1268: minus = 0;
1269: relerr = 0;
1270: break;
1271: }
1272: if (a1 == start)
1273: errmsg(18);
1274: }
1275: break;
1276:
1277: case '$':
1278: a1 = dol;
1279: #ifdef LOG
1280: if (!globp)
1281: ++logstats.la_dol;
1282: #endif
1283: break;
1284:
1285: case '.':
1286: if ((peekc = getchar()) == '.') {
1287: peekc = 0;
1288: a1 = dotdot;
1289: #ifdef LOG
1290: if (!globp)
1291: ++logstats.la_dotdot;
1292: #endif
1293: } else {
1294: a1 = dot;
1295: #ifdef LOG
1296: if (!globp)
1297: ++logstats.la_dot;
1298: #endif
1299: }
1300: break;
1301:
1302: case '\'':
1303: if (((c = getchar()) | 040) < 'a' ||
1304: (c | 040) > 'z') {
1305: peekc = c;
1306: errmsg(19);
1307: }
1308: c |= 040;
1309: #ifdef LOG
1310: if (!globp)
1311: ++logstats.la_quote;
1312: #endif
1313: casemark:
1314: #ifdef EXTMARK
1315: n = 3;
1316: if ((peekc = getchar()) == '^') {
1317: n = 1;
1318: peekc = 0;
1319: } else if (peekc == '$') {
1320: n = 2;
1321: if (names2[c - 'a'] == 0)
1322: n = 1;
1323: peekc = 0;
1324: }
1325: if (n & 01)
1326: if ((a1=findmark(names[c-'a'],0))==0) {
1327: a1 = dol;
1328: n = 0;
1329: }
1330: if (n > 1 && names2[c - 'a']) {
1331: if (n == 3) {
1332: if (addr1 || addr2)
1333: errmsg(20);
1334: addr1 = a1;
1335: }
1336: a1 = findmark(names2[c - 'a'], dol);
1337: if (n == 2)
1338: break;
1339: addr2 = a1;
1340: return(0);
1341: }
1342: #else
1343: a1 = findmark(names[c - 'a'], dol);
1344: #endif
1345: break;
1346:
1347: case '=':
1348: #ifdef LOG
1349: if (!globp)
1350: ++logstats.la_equal;
1351: #endif
1352: if ((peekc = getchar()) == '^')
1353: a1 = old_a1;
1354: else if (peekc == '$')
1355: a1 = old_a2;
1356: else {
1357: if (addr1 || addr2 || a1)
1358: errmsg(20);
1359: addr1 = old_a1;
1360: addr2 = old_a2;
1361: return(0);
1362: }
1363: peekc = 0;
1364: break;
1365:
1366: default:
1367: if ('A' <= c && c <= 'Z') {
1368: c |= 040;
1369: #ifdef LOG
1370: if (!globp)
1371: ++logstats.la_letter;
1372: #endif
1373: goto casemark;
1374: }
1375: peekc = c;
1376: if (a1 == 0)
1377: if (c == ',' || c == ';')
1378: if (dot + 1 > dol)
1379: return(dol);
1380: else
1381: return(dot + 1);
1382: else
1383: return(0);
1384: a1 += minus;
1385: if (a1 < zero)
1386: a1 = zero + (zero != dol);
1387: else if (a1 > dol)
1388: a1 = dol;
1389: return(a1);
1390: }
1391: if (relerr)
1392: errmsg(20);
1393: }
1394: }
1395:
1396: advance(alp, aep) {
1397: register char *lp, *ep, *curlp;
1398: register s_sav, i;
1399:
1400: lp = alp;
1401: ep = aep;
1402: for ever switch (*ep++) {
1403:
1404: case CCHR:
1405: if (*ep++ == *lp++)
1406: continue;
1407: return(0);
1408:
1409: case CDOT:
1410: if (*lp++)
1411: continue;
1412: return(0);
1413:
1414: case CDOL:
1415: if (*lp == 0)
1416: continue;
1417: return(0);
1418:
1419: case CEOF:
1420: loc2 = lp;
1421: if (--s_tmp > 0)
1422: return(0);
1423: return(1);
1424:
1425: case CCL:
1426: case NCCL:
1427: if (cclass(ep, *lp++, ep[-1] == CCL)) {
1428: ep += *ep;
1429: continue;
1430: }
1431: return(0);
1432:
1433: case CBRA:
1434: braslist[*ep++] = lp;
1435: continue;
1436:
1437: case CKET:
1438: braelist[*ep++] = lp;
1439: continue;
1440:
1441: case CBACK:
1442: if (braelist[i = *ep++] == 0)
1443: errmsg(63);
1444: if (backref(i, lp)) {
1445: lp += braelist[i] - braslist[i];
1446: continue;
1447: }
1448: return(0);
1449:
1450: case CBACK | STAR:
1451: if (braelist[i = *ep++] == 0)
1452: errmsg(63);
1453: curlp = lp;
1454: while (backref(i, lp))
1455: lp += braelist[i] - braslist[i];
1456: while (lp >= curlp) {
1457: if (advance(lp, ep))
1458: return(1);
1459: lp -= braelist[i] - braslist[i];
1460: }
1461: continue;
1462:
1463: case CDOT | STAR:
1464: curlp = lp;
1465: while (*lp++);
1466: goto star;
1467:
1468: case CCHR | STAR:
1469: curlp = lp;
1470: while (*lp++ == *ep);
1471: ep++;
1472: goto star;
1473:
1474: case CCL | STAR:
1475: case NCCL | STAR:
1476: curlp = lp;
1477: while (cclass(ep, *lp++, ep[-1] == (CCL | STAR)));
1478: ep += *ep;
1479: /* goto star; */
1480:
1481: star:
1482: s_sav = s_tmp;
1483: do {
1484: if (--lp == locs)
1485: break;
1486: if (advance(lp, ep))
1487: return(1);
1488: s_tmp = s_sav;
1489: } while (lp > curlp);
1490: --s_tmp;
1491: return(0);
1492:
1493: default:
1494: errmsg(-26);
1495: }
1496: }
1497:
1498: linep *
1499: append(f, a, single, bkpf)
1500: func f;
1501: linep *a;
1502: {
1503: register linep *a1, *a2, *rdot;
1504: register nline, tl;
1505:
1506: nline = 0;
1507: dot = a;
1508: while ((*f)(single) == 0) {
1509: if (dol >= endcore) {
1510: if (sbrk(1024) == -1)
1511: errmsg(33);
1512: endcore = (int)endcore + 1024;
1513: }
1514: tl = putline();
1515: nline++;
1516: a1 = ++dol;
1517: a2 = a1 + 1;
1518: rdot = ++dot;
1519: while (a1 > rdot)
1520: *--a2 = *--a1;
1521: *rdot = tl;
1522: if (bkpf) {
1523: mods++;
1524: backchk();
1525: }
1526: if (single)
1527: break;
1528: }
1529: return(nline);
1530: }
1531:
1532: are_you_sure() {
1533: #ifdef USE
1534: if (alt)
1535: return(1);
1536: #endif
1537: if (!text_modified || fflg || immflg || zero == dol)
1538: return(0);
1539: return(yes_no(curt? "?forget" :
1540: "did you forget to save your text", 1, 1, 0));
1541: }
1542:
1543: argnum(ap)
1544: char **ap;
1545: {
1546: register n;
1547: register char *p;
1548:
1549: p = *ap;
1550: n = 0;
1551: while ('0' <= *p && *p <= '9')
1552: n = n * 10 + *p++ - '0';
1553: *ap = --p;
1554: return(n);
1555: }
1556:
1557: backchk() {
1558: if (modcount == 0)
1559: return;
1560: if (mods >= modcount) {
1561: mods = 0;
1562: #ifdef EOL
1563: if (backup(TMP) && prompt2 && prompt3)
1564: #endif
1565: #ifndef EOL
1566: if (backup(TMP) && prompt2)
1567: #endif
1568: if (!curt)
1569: putsn(errtext[56]);
1570: }
1571: }
1572:
1573: backref(an, alp)
1574: char *alp;
1575: {
1576: register n;
1577: register char *bp, *lp;
1578:
1579: n = an;
1580: bp = braslist[n];
1581: lp = alp;
1582: while (*bp++ == *lp++)
1583: if (bp >= braelist[n])
1584: return(1);
1585: return(0);
1586: }
1587:
1588: backup(af) {
1589: register char *p1, *p2, *t2;
1590: register linep *a1, *a2;
1591: register func savint, savhup;
1592:
1593: if (io) {
1594: putsn("******** backup: I/O in progress");
1595: return(0);
1596: }
1597: flush_buf();
1598: p1 = savedfile;
1599: t2 = p2 = file;
1600: while (*p2 = *p1++)
1601: if (*p2++ == '/')
1602: t2 = p2;
1603: if (p2 > t2 + 10)
1604: p2 = t2 + 10;
1605: if (af != FILE && p2 >= &file[FNSIZE - 6])
1606: errmsg(11);
1607: switch (af < 0? -af : af) {
1608: case FILE: p1 = 0; break;
1609: case TMP: p1 = dotedt; break;
1610: case INT: p1 = dotint; break;
1611: case HUP: p1 = dothup; break;
1612: case BAK: p1 = dotbak; break;
1613: case TRM: p1 = dottrm; break;
1614: default: errmsg(-17);
1615: }
1616: if (p1)
1617: while (*p2++ = *p1++);
1618: if (af < 0) {
1619: if (deltflg)
1620: return(1);
1621: return(!unlink(file));
1622: }
1623: if (dol == zero && !fflg) {
1624: if (af == FILE)
1625: if (curt)
1626: putsn("?48");
1627: else
1628: putsn(errtext[48]);
1629: return(1);
1630: }
1631: if (dol == zero)
1632: return(1);
1633: if (!iflg) {
1634: savhup = signal(SIGHUP, 1);
1635: savint = signal(SIGINT, 1);
1636: }
1637: if (over && af == FILE)
1638: override();
1639: io = create(file, (af == FILE? MODE : LMODE));
1640: if (overfile) {
1641: chmod(overfile, overmode);
1642: overfile = 0;
1643: }
1644: if (io < 0) {
1645: io = 0;
1646: if (af != TMP) {
1647: if (curt)
1648: putsn("?54");
1649: else {
1650: puts2(errtext[54]);
1651: putsn(file);
1652: }
1653: }
1654: if (!iflg) {
1655: signal(SIGHUP, savhup);
1656: signal(SIGINT, savint);
1657: }
1658: return(0);
1659: }
1660: io_w++;
1661: a1 = addr1;
1662: a2 = addr2;
1663: addr1 = zero + 1;
1664: addr2 = dol;
1665: putfile();
1666: close(io);
1667: io = 0;
1668: io_w = 0;
1669: addr1 = a1;
1670: addr2 = a2;
1671: if (!iflg) {
1672: signal(SIGHUP, savhup);
1673: signal(SIGINT, savint);
1674: }
1675: return(1);
1676: }
1677:
1678: #ifndef CKPT
1679: badsig(an) {
1680: register n;
1681:
1682: if (n = backup(TMP))
1683: putsn(errtext[56]);
1684: puts(" Fatal Signal: ");
1685: if (0 < an && an < NSTR && status[an])
1686: putsn(status[an]);
1687: else
1688: printf("%d\n", an);
1689: flush_buf();
1690: if (n)
1691: exit(1);
1692: error();
1693: }
1694: #endif
1695:
1696: blkio(b, buf, iofcn)
1697: func iofcn;
1698: {
1699: lseek(tfile, 512L * b, 0);
1700: if ((*iofcn)(tfile, buf, BLKSIZE) != BLKSIZE) {
1701: badf++;
1702: errmsg(-35);
1703: }
1704: }
1705:
1706: cclass(aset, ac, af)
1707: char *aset;
1708: charac ac;
1709: {
1710: register char *set;
1711: register n;
1712: register charac c, m;
1713:
1714: set = aset;
1715: if ((c = ac) == 0)
1716: return(0);
1717: n = *set++;
1718: while (--n)
1719: if (set[1] == '-' && n > 2) {
1720: c = min(set[0], set[2]);
1721: m = max(set[0], set[2]);
1722: do {
1723: if (c == ac)
1724: return(af);
1725: } while (++c != m);
1726: set += 2;
1727: c = ac;
1728: } else
1729: if (*set++ == c)
1730: return(af);
1731: return(!af);
1732: }
1733:
1734: #ifdef CKPT
1735: checkpoint(asig) {
1736: extern etext;
1737: register filedes f;
1738: register char *p;
1739: register func savint, savqit;
1740: int n;
1741:
1742: savint = signal(SIGINT, 1);
1743: savqit = signal(SIGQIT, 1);
1744: p = &etext; /* won't work for -n, -i, or -z */
1745: n = (char *)dol - p;
1746: n += sizeof (int);
1747: if ((f = create(cfname, LMODE)) < 0 ||
1748: write(f, &n, sizeof n) != sizeof n) {
1749: n = 66;
1750: goto cerror;
1751: }
1752: #ifdef pdp11 /* 16 bit byte count only */
1753: if (n < 0) {
1754: if (write(f, etext, 32256) != 32256) {
1755: n = 66;
1756: goto cerror;
1757: }
1758: n -= 32256; /* 63 blocks, since 64 is < 0 */
1759: p += 32256;
1760: }
1761: #endif
1762: if (write(f, p, n) != n)
1763: n = 66;
1764: else
1765: n = 0;
1766: cerror:
1767: close(f);
1768: if (n) {
1769: signal(SIGINT, savint);
1770: signal(SIGQIT, savqit);
1771: recovry = 0;
1772: errmsg(n);
1773: }
1774: if (asig) {
1775: puts2(status[asig]);
1776: if (!curt)
1777: puts(": Fatal error");
1778: }
1779: if (curt)
1780: puts2("?CKPT ");
1781: else {
1782: puts2("Editing session checkpointed to \"");
1783: puts2(cfname);
1784: puts("\".\nTo recover your work, type:");
1785: if (editor && *editor)
1786: puts2(editor);
1787: else
1788: puts2("edit");
1789: puts2(" -R");
1790: }
1791: puts(&tfname[tfnum]);
1792: exit(1);
1793: }
1794: #endif
1795:
1796: chk() {
1797: register charac c;
1798: register char *p2, *p1, *t2, **p;
1799: register charac oldc;
1800: long t;
1801: struct stat s;
1802:
1803: if (*savedfile == '\0')
1804: return(0);
1805: t2 = p2 = file;
1806: p1 = savedfile;
1807: if (stat(p1, &s) >= 0)
1808: t = s.st_mtime;
1809: else
1810: t = 0L;
1811: while (*p2 = *p1++)
1812: if (*p2++ == '/')
1813: t2 = p2;
1814: if (p2 > t2 + 10)
1815: p2 = t2 + 10;
1816: if (p2 >= &file[FNSIZE - 6])
1817: return(0);
1818: t2 = p2;
1819: p = dots;
1820: while (p1 = *p++) {
1821: p2 = t2;
1822: while (*p2++ = *p1++);
1823: if (stat(file, &s) >= 0 && s.st_mtime >= t) {
1824: if (curt) {
1825: puts2("?\"");
1826: puts2(file);
1827: puts2("\" ");
1828: } else {
1829: putsn("When you were last editing this file");
1830: putsn("you did not exit the editor normally,");
1831: puts2("leaving the file: \"");
1832: puts2(file);
1833: if (p1 == dotedt) {
1834: putsn("\".\nIt contains your file up to the last \"[file saved]\"");
1835: putsn("message. This file will be deleted if you do");
1836: putsn("not read it into the editor now. If you read");
1837: putsn("it, then decide not to use it, exit the editor");
1838: putsn("with \"qi\".");
1839: } else
1840: putsn("\".");
1841: }
1842: return(yes_no(curt? "read" : "Do you wish to read it",
1843: 1, -1, 0));
1844: }
1845: }
1846: return(0);
1847: }
1848:
1849: _cleanup() {
1850: flush_buf();
1851: }
1852:
1853: #ifdef CLEAR
1854: clear() {
1855: register l, i;
1856:
1857: l = listf;
1858: listf = 0;
1859: puts2(clears); /* clear sequence */
1860: flush_buf();
1861: i = 5;
1862: while (--i >= 0)
1863: putchar(0); /* ADM-3A's need padding at 19.2 */
1864: putchar('\n');
1865: listf = l;
1866: }
1867: #endif
1868:
1869: commands(baseflg) {
1870: extern getfile(), gettty();
1871: register linep *a1;
1872: register charac c;
1873: register char *p;
1874: register r, num;
1875:
1876: for ever {
1877: #ifdef AGAIN
1878: if (agp) {
1879: *agp++ = '\n';
1880: *agp = '\0';
1881: }
1882: agf = 0;
1883: agp = 0;
1884: #endif
1885: immflg = 0;
1886: #ifdef LOG
1887: if (logamp) {
1888: ++logstats.lp_amp;
1889: logamp = 0;
1890: }
1891: #endif
1892: if (!globp && (hupflag || termflg)) {
1893: if (hupflag) {
1894: backup(HUP);
1895: puts2(errtext[57]);
1896: } else {
1897: backup(TRM);
1898: puts2(errtext[58]);
1899: }
1900: delexit(1);
1901: }
1902: if (pflag) {
1903: pflag = 0;
1904: addr1 = addr2 = dot;
1905: goto print;
1906: }
1907: if (!globp) {
1908: #ifdef USE
1909: if (!alt) {
1910: #endif
1911: if (modcount) {
1912: if (text_modified > savf)
1913: mods++;
1914: savf = text_modified;
1915: backchk();
1916: }
1917: #ifdef EOL
1918: #ifdef USE
1919: if (prompt2 && prompt3 && !eflg2)
1920: #endif
1921: #ifndef USE
1922: if (prompt2 && prompt3)
1923: #endif
1924: #endif
1925: #ifndef EOL
1926: #ifdef USE
1927: if (prompt2 && !eflg2)
1928: #endif
1929: #ifndef USE
1930: if (prompt2)
1931: #endif
1932: #endif
1933: {
1934: puts2(e_prompt);
1935: flush_buf();
1936: }
1937: #ifdef USE
1938: }
1939: #endif
1940: }
1941: if (!globp) {
1942: if (dotdot > dol)
1943: dotdot = dol;
1944: if (dotdot < zero)
1945: dotdot = zero;
1946: if (dot != lastdot) {
1947: dotdot = lastdot;
1948: lastdot = dot;
1949: }
1950: }
1951: addr1 = 0;
1952: addr2 = 0;
1953: s_tmp = 0;
1954: s_cnt = 0;
1955: r = 1;
1956: do {
1957: addr1 = addr2;
1958: if ((a1 = address()) == 0) {
1959: c = getchar();
1960: break;
1961: }
1962: addr2 = a1;
1963: if ((c = getchar()) == ';') {
1964: c = ',';
1965: dot = a1;
1966: }
1967: } while (c == ',' && --r >= 0);
1968: if (addr1 == 0)
1969: addr1 = addr2;
1970: if (!globp && !baseflg) {
1971: if (addr1) {
1972: old_a1 = addr1;
1973: old_a2 = addr2;
1974: }
1975: }
1976: line_num = (addr1? addr1 : dot) - zero;
1977: #ifdef AGAIN
1978: if (c == 'o' || c == ctrl('Q')) { /* again command "o" */
1979: if (c != ctrl('Q') && (peekc = getchar()) != '\n')
1980: errmsg(1);
1981: if (c == ctrl('Q'))
1982: putchar(lastc = '\n');
1983: if (*agbuf == 0)
1984: errmsg(2);
1985: agf++;
1986: agp = agbuf;
1987: c = *agp++;
1988: peekc = 0;
1989: #ifdef LOG
1990: ++logstats.lc_o;
1991: #endif
1992: } else if (baseflg == 0 && globp == 0)
1993: if (c != '\n') {
1994: agp = agbuf;
1995: *agp++ = c; /* first char not yet saved */
1996: }
1997: #endif
1998:
1999: switch (c) {
2000: case 'a':
2001: if ((peekc = getchar()) == 'b')
2002: abort();
2003: setdot();
2004: #ifdef XED
2005: if (peekc != ' ' && peekc != '\n') {
2006: c = peekc;
2007: peekc = 0;
2008: if (tack(c, 1))
2009: text_modified++;
2010: #ifdef LOG
2011: ++logstats.lc_aslash;
2012: #endif
2013: continue;
2014: }
2015: #endif
2016: line_num++;
2017: num = addr2;
2018: #ifdef LOG
2019: ++logstats.lc_append;
2020: #endif
2021: caseadd:
2022: if ((c = getchar()) == ' ') {
2023: r = 1;
2024: #ifdef LOG
2025: ++logstats.lc_aspace;
2026: #endif
2027: } else {
2028: #ifndef XED
2029: if (c != '\n') {
2030: peekc = c;
2031: newline();
2032: }
2033: #endif
2034: r = 0;
2035: }
2036: if (append(gettty, num, r, 1))
2037: text_modified++;
2038: continue;
2039:
2040: case 'b':
2041: setnoaddr();
2042: white_space();
2043: if ((brcount = setnum(1)) <= 0)
2044: brcount = 1;
2045: #ifdef LOG
2046: ++logstats.lc_browse;
2047: #endif
2048: continue;
2049:
2050: case 'c':
2051: if ((peekc = getchar()) == 'o') { /* co == t */
2052: peekc = 0;
2053: #ifdef LOG
2054: ++logstats.lc_copy;
2055: #endif
2056: goto casecopy;
2057: }
2058: if (peekc != '\n')
2059: goto casesub;
2060: newline();
2061: setdot();
2062: nonzero();
2063: delete();
2064: text_modified++;
2065: #ifdef LOG
2066: ++logstats.lc_change;
2067: #endif
2068: append(gettty, addr1 - 1, 0, 0);
2069: continue;
2070:
2071: case 'd':
2072: #ifdef DEBUG
2073: /* *du Dump command (testing only) */
2074: if ((peekc = getchar()) == 'u') {
2075: peekc = 0;
2076: dump();
2077: continue;
2078: }
2079: #endif
2080: if ((peekc = getchar()) == ' ' || peekc == ',') {
2081: peekc = 0;
2082: white_space();
2083: p = linebuf;
2084: if ((c = getchar()) == '\n')
2085: errmsg(51);
2086: do {
2087: *p++ = c;
2088: #ifndef ALLOC
2089: if (p >= &linebuf[LBSIZE - 2])
2090: #else
2091: if (p >= &linebuf[lbsize - 2])
2092: #endif
2093: errmsg(11);
2094: } while ((c = getchar()) >= 0 && c != '\n');
2095: *p = 0;
2096: #ifdef LOG
2097: ++logstats.lc_directory;
2098: #endif
2099: if (chdir(linebuf) < 0)
2100: errmsg(51);
2101: continue;
2102: }
2103: #ifdef PAGE
2104: if (peekc == '=') { /* d=<depth> */
2105: peekc = 0;
2106: setnoaddr();
2107: pcount = setnum(PAGSIZ);
2108: #ifdef LOG
2109: ++logstats.lc_depth;
2110: #endif
2111: continue;
2112: }
2113: #endif
2114: newline();
2115: setdot();
2116: nonzero();
2117: delete();
2118: text_modified++;
2119: #ifdef LOG
2120: ++logstats.lc_delete;
2121: #endif
2122: continue;
2123:
2124: case 'e':
2125: eagain:
2126: if ((peekc = getchar()) != '\n') {
2127: #ifdef EOL
2128: if (peekc == '=') { /* e=c - set eol to 'c' */
2129: peekc = 0;
2130: if (immflg)
2131: errmsg(8);
2132: setnoaddr();
2133: eol = setchar(0);
2134: #ifdef LOG
2135: ++logstats.lc_eol;
2136: #endif
2137: continue;
2138: }
2139: #endif
2140: #ifdef TABS
2141: if (peekc == 'x') {
2142: peekc = 0;
2143: if (immflg)
2144: errmsg(8);
2145: if ((c = getchar()) != 'p')
2146: errmsg(8);
2147: newline();
2148: if (!tabc)
2149: errmsg(3);
2150: if (maxtab < 0)
2151: errmsg(9);
2152: if (exp())
2153: text_modified++;
2154: #ifdef LOG
2155: ++logstats.lc_exp;
2156: #endif
2157: continue;
2158: }
2159: #endif
2160: if ('0' <= peekc && peekc <= '9') {
2161: c = getnum();
2162: newline();
2163: if (0 <= c && c < NERR)
2164: printf("%3d: %s\n",
2165: c, errtext[c]);
2166: #ifdef LOG
2167: ++logstats.lc_errmsg;
2168: #endif
2169: continue;
2170: }
2171: if (peekc == '+' || peekc == '-') {
2172: c = peekc;
2173: peekc = 0;
2174: newline();
2175: curt = c == '-';
2176: #ifdef LOG
2177: if (curt)
2178: ++logstats.lc_eminus;
2179: else
2180: ++logstats.lc_eplus;
2181: #endif
2182: continue;
2183: }
2184: if (peekc == 'i') {
2185: peekc = 0;
2186: if (immflg)
2187: errmsg(8);
2188: immflg++;
2189: goto eagain;
2190: }
2191: setnoaddr();
2192: if (fflg)
2193: errmsg(4);
2194: if (peekc != ' ' && peekc != ',')
2195: illfnm: errmsg(5);
2196: scopy(savedfile, tempfile);
2197: if (zero == dol || text_modified == 0)
2198: backup(-TMP);
2199: savedfile[0] = 0;
2200: filename();
2201: if (text_modified && are_you_sure()) {
2202: scopy(tempfile, savedfile);
2203: error();
2204: }
2205: peekc = '\n';
2206: } else {
2207: setnoaddr();
2208: if (text_modified) {
2209: r = peekc;
2210: peekc = 0;
2211: if (are_you_sure()) {
2212: peekc = r;
2213: error();
2214: }
2215: peekc = r;
2216: }
2217: if (zero == dol || text_modified == 0)
2218: backup(-TMP);
2219: }
2220: if (init())
2221: continue;
2222: #ifdef LOG
2223: ++logstats.lc_edit;
2224: #endif
2225: goto caseread;
2226:
2227: case 'f':
2228: setnoaddr();
2229: #ifdef TABS
2230: if ((peekc = getchar()) == '=') { /* f=c fill char */
2231: peekc = 0;
2232: tabfill = setchar(TABFILL);
2233: #ifdef LOG
2234: ++logstats.lc_fillset;
2235: #endif
2236: continue;
2237: }
2238: #endif
2239: if ((c = getchar()) != '\n') {
2240: if (fflg)
2241: errmsg(4);
2242: peekc = c;
2243: filename();
2244: scopy(file, savedfile);
2245: #ifdef LOG
2246: ++logstats.lc_fset;
2247: #endif
2248: if (prompt2 == 0)
2249: continue;
2250: }
2251: #ifdef LOG
2252: else
2253: ++logstats.lc_fshow;
2254: #endif
2255: putsn(savedfile);
2256: continue;
2257:
2258: case 'g':
2259: global(1);
2260: continue;
2261:
2262: case 'h':
2263: #ifdef HELP
2264: if ((peekc = getchar()) == 'e') { /* he[lp] */
2265: peekc = 0;
2266: setnoaddr();
2267: skip_rest();
2268: #ifdef LOG
2269: ++logstats.lc_help;
2270: #endif
2271: if ((doc = open(help, 0)) > 0) {
2272: while ((c = read(doc, linebuf,
2273: #ifndef ALLOC
2274: LBSIZE)) > 0)
2275: #else
2276: lbsize)) > 0)
2277: #endif
2278: write(1, linebuf, c);
2279: close(doc);
2280: }
2281: doc = 0;
2282: continue;
2283: }
2284: #endif
2285: if (zero != dol) {
2286: setdot();
2287: nonzero();
2288: }
2289: #ifdef LOG
2290: ++logstats.lc_header;
2291: #endif
2292: header();
2293: continue;
2294:
2295: case 'i':
2296: setdot();
2297: #ifdef XED
2298: if ((peekc = getchar()) != ' ' && peekc != '\n') {
2299: c = peekc;
2300: peekc = 0;
2301: if (tack(c, 0))
2302: text_modified++;
2303: #ifdef LOG
2304: ++logstats.lc_islash;
2305: #endif
2306: continue;
2307: }
2308: #endif
2309: nonzero();
2310: num = addr2 - 1;
2311: #ifdef LOG
2312: ++logstats.lc_insert;
2313: #endif
2314: goto caseadd;
2315:
2316: #ifdef XED
2317: case 'j':
2318: setdot();
2319: nonzero();
2320: join();
2321: text_modified++;
2322: continue;
2323: #endif
2324:
2325: case 'k':
2326: if ((c = getchar()) == '\n') {
2327: setnoaddr();
2328: #ifdef LOG
2329: ++logstats.lc_klist;
2330: #endif
2331: printmarks();
2332: continue;
2333: }
2334: if ('A' <= c && c <= 'Z')
2335: c |= 040;
2336: if (c < 'a' || c > 'z')
2337: errmsg(0);
2338: newline();
2339: setdot();
2340: nonzero();
2341: #ifdef HUGE
2342: r = hugef ^ 01;
2343: #else
2344: #define r 1
2345: #endif
2346: #ifdef EXTMARK
2347: if (addr1 != addr2) {
2348: names[c - 'a'] = *addr1 | r;
2349: names2[c - 'a'] = *addr2 | r;
2350: } else {
2351: names[c - 'a'] = *addr2 | r;
2352: names2[c - 'a'] = 0;
2353: }
2354: #else
2355: names[c - 'a'] = *addr2 | r;
2356: #endif
2357: #ifdef LOG
2358: ++logstats.lc_kset;
2359: #endif
2360: continue;
2361: #ifndef HUGE
2362: #undef r
2363: #endif
2364:
2365: case 'm':
2366: #ifdef DUMB
2367: if ((peekc = getchar()) == '\n') {
2368: setnoaddr();
2369: peekc = 0;
2370: dumbf ^= 01;
2371: #ifdef LOG
2372: ++logstats.lc_magic;
2373: #endif
2374: if (curt)
2375: putsn(dumbf? off : on);
2376: else {
2377: puts2("\"$&[^.*\\(\\)\" have ");
2378: if (dumbf)
2379: puts2(no);
2380: putsn("special meaning");
2381: }
2382: continue;
2383: }
2384: #endif
2385: if ((peekc = getchar()) == 'o') { /* mo == m */
2386: peekc = 0;
2387: #ifdef LOG
2388: ++logstats.lc_moove;
2389: #endif
2390: }
2391: #ifdef LOG
2392: else
2393: ++logstats.lc_move;
2394: #endif
2395: move(0);
2396: text_modified++;
2397: continue;
2398:
2399: case 'n':
2400: setnoaddr();
2401: #ifdef PIPE
2402: if ((peekc = getchar()) == '+') {
2403: peekc = 0;
2404: newline();
2405: pno = 1;
2406: #ifdef LOG
2407: ++logstats.lc_numplus;
2408: #endif
2409: continue;
2410: }
2411: if (peekc == '-') {
2412: peekc = 0;
2413: newline();
2414: pno = -1;
2415: #ifdef LOG
2416: ++logstats.lc_numinus;
2417: #endif
2418: continue;
2419: }
2420: #endif
2421: newline();
2422: prompt1 ^= 01;
2423: #ifdef LOG
2424: ++logstats.lc_numbers;
2425: #endif
2426: if (curt)
2427: putsn(prompt1? on : off);
2428: else {
2429: if (prompt1 == 0)
2430: puts2(no);
2431: putsn("line numbers");
2432: }
2433: continue;
2434:
2435: case '\n':
2436: if (globp || addr2 > dol)
2437: continue;
2438: if (addr2 == 0) {
2439: addr1 = addr2 = dot + 1;
2440: if (addr2 <= dol)
2441: line_num++;
2442: if (brcount != 1) {
2443: addr2 = dot + brcount;
2444: if (addr1 > dol)
2445: continue;
2446: if (addr2 > dol)
2447: addr2 = dol;
2448: if (addr2 < zero)
2449: addr2 = zero;
2450: #ifdef CLEAR
2451: if (zflg && addr2 - addr1 > pcount / 2)
2452: clear();
2453: #endif
2454: }
2455: }
2456: if (addr2 <= dol) {
2457: pflag = 0;
2458: goto print;
2459: }
2460: continue;
2461:
2462: case 'l':
2463: listf++;
2464: #ifdef LOG
2465: ++logstats.lc_list;
2466: #endif
2467: case 'p':
2468: if ((peekc = getchar()) == 'a') {
2469: peekc = 0;
2470: case ':':
2471: case '*':
2472: num = 0;
2473: if (c == ':' || c == '*') {
2474: if ((peekc = getchar()) == ' ' ||
2475: peekc == '\t') {
2476: skip_rest(); /* comments */
2477: #ifdef LOG
2478: ++logstats.lc_comment;
2479: #endif
2480: continue;
2481: }
2482: r = peekc;
2483: peekc = 0;
2484: #ifdef LOG
2485: if (r == '-' || r == '+')
2486: ++logstats.lc_clnminus;
2487: else if (c == '*')
2488: ++logstats.lc_star;
2489: else
2490: ++logstats.lc_colon;
2491: #endif
2492: while (r == '-' || r == '^' || r == '+') {
2493: if (r == '+')
2494: ++num;
2495: else
2496: --num;
2497: r = getchar();
2498: }
2499: peekc = r;
2500: }
2501: #ifdef LOG
2502: else
2503: if (c != 'p')
2504: ++logstats.lc_print;
2505: #endif
2506: newline();
2507: pflag = 0;
2508: if (addr1 == addr2) {
2509: if (num == -1 && c == ':') {
2510: if (addr2 == 0)
2511: addr2 = dot;
2512: addr1 = addr2 - pcount;
2513: if (addr1 <= zero)
2514: addr1 = zero + 1;
2515: #ifdef CLEAR
2516: if (zflg)
2517: clear();
2518: #endif
2519: goto print;
2520: }
2521: num *= pcount;
2522: if (c == '*')
2523: num -= (pcount + 1) / 2;
2524: if (addr1 == 0)
2525: a1 = dot + (num? num : 1);
2526: else
2527: a1 = addr1 + num;
2528: if (a1 <= zero)
2529: a1 = zero + 1;
2530: addr1 = addr2 = a1;
2531: }
2532: nonzero();
2533: if (addr1 == addr2 || addr2 > dol ||
2534: addr2 <= zero)
2535: addr2 = dol;
2536: setdot();
2537: #ifdef CLEAR
2538: if (zflg && addr2 - addr1 > pcount / 2)
2539: clear();
2540: #endif
2541: #ifndef PAGE
2542: if (addr2 > addr1 + pcount)
2543: addr2 = addr1 + pcount;
2544: goto print;
2545: #else
2546: page();
2547: listf = 0;
2548: #ifdef PARENS
2549: parenf = 0;
2550: #endif
2551: #ifdef STRLEN
2552: quotef = 0;
2553: #endif
2554: continue;
2555: #endif
2556: } else if (peekc == 'p' || peekc == 'l') {
2557: peekc = 0;
2558: addr1 = zero + 1;
2559: addr2 = dol;
2560: #ifdef LOG
2561: ++logstats.lc_pprint;
2562: #endif
2563: }
2564: newline();
2565: pflag = 0;
2566: print:
2567: setdot();
2568: nonzero();
2569: a1 = addr1;
2570: #ifdef PARENS
2571: parenc[0] = 0;
2572: parenc[1] = 0;
2573: parenc[2] = 0;
2574: #endif
2575: do {
2576: col = 0;
2577: printlno(line_num = a1 - zero);
2578: puts(getline(*a1++));
2579: } while (a1 <= addr2);
2580: dot = addr2;
2581: listf = 0;
2582: #ifdef PARENS
2583: parenf = 0;
2584: #endif
2585: #ifdef STRLEN
2586: quotef = 0;
2587: #endif
2588: continue;
2589:
2590: case 'q':
2591: if ((peekc = getchar()) == 'i') { /* qi - immediate */
2592: peekc = 0;
2593: newline();
2594: immflg++;
2595: #ifdef LOG
2596: ++logstats.lc_qimm;
2597: #endif
2598: return;
2599: }
2600: #ifdef STRLEN
2601: if (peekc == '=') { /* q=cc set quote chars */
2602: peekc = 0;
2603: if ((c = getchar()) == '\\')
2604: c = getchar();
2605: quotec = quotec2 = c;
2606: #ifdef LOG
2607: ++logstats.lc_quote;
2608: #endif
2609: if (c != '\n') {
2610: if ((c = getchar()) == '\\')
2611: c = getchar();
2612: if (c == '\n')
2613: continue;
2614: quotec2 = c;
2615: } else {
2616: quotec = 0;
2617: quotec2 = 0;
2618: continue;
2619: }
2620: if (c != '\n')
2621: newline();
2622: continue;
2623: }
2624: #endif
2625: setnoaddr();
2626: if ((peekc = getchar()) != '\n')
2627: errmsg(25);
2628: peekc = 0;
2629: #ifdef LOG
2630: ++logstats.lc_quit;
2631: #endif
2632: return;
2633:
2634: case 'r':
2635: #ifdef LOG
2636: ++logstats.lc_read;
2637: #endif
2638: caseread:
2639: filename();
2640: if ((io = open(file, 0)) < 0) {
2641: io = 0;
2642: lastc = '\n';
2643: if (curt)
2644: errmsg(53);
2645: puts2(errtext[53]);
2646: putsn(file);
2647: error();
2648: }
2649: setall();
2650: ninbuf = 0;
2651: r = append(getfile, addr2, 0, 0);
2652: if (prompt2)
2653: printf((curt? prcntu : errtext[55]),
2654: r, (r == 1? null : quote_s));
2655: close(io);
2656: io = 0;
2657: #ifdef LOG
2658: logstats.lt_rlines += r;
2659: #endif
2660: if (num_reads++ || fflg) {
2661: if (r)
2662: text_modified++;
2663: } /* else
2664: text_modified = 0; */
2665: if ((c == 'e' && bflg == 1) || bflg2 == 1) {
2666: bflg2 = 0;
2667: backup(BAK);
2668: }
2669: continue;
2670:
2671: case 's':
2672: if (!globp && (peekc = getchar()) == '\n') { /* w;q */
2673: setnoaddr();
2674: #ifdef LOG
2675: ++logstats.lc_stop;
2676: #endif
2677: if (text_modified && !fflg)
2678: if (backup(FILE) == 0)
2679: error(); /* errmsg(10) */
2680: peekc = text_modified = 0;
2681: #ifdef LOG
2682: logstats.lt_wlines += dol - zero;
2683: #endif
2684: return;
2685: }
2686: if (peekc == 'a') { /* sa - count before auto-save */
2687: setnoaddr();
2688: peekc = 0;
2689: modcount = setnum(MODCNT);
2690: mods = 0;
2691: #ifdef LOG
2692: ++logstats.lc_savecount;
2693: #endif
2694: continue;
2695: }
2696: casesub:
2697: setdot();
2698: nonzero();
2699: substitute(globp);
2700: text_modified++;
2701: #ifdef LOG
2702: if (c == 's')
2703: ++logstats.lc_substitute;
2704: else
2705: ++logstats.lc_cslash;
2706: #endif
2707: continue;
2708:
2709: case 't':
2710: #ifdef TABS
2711: if ((peekc = getchar()) == '=') { /* t=c tab char */
2712: setnoaddr();
2713: peekc = 0;
2714: tabc = setchar(0);
2715: #ifdef LOG
2716: ++logstats.lc_tabchar;
2717: #endif
2718: continue;
2719: } else if (peekc == ',') { /* t,nn set tabs */
2720: setnoaddr();
2721: #ifdef LOG
2722: ++logstats.lc_tabset;
2723: #endif
2724: while ((c = getchar()) == ',') {
2725: while ((c = getchar()) == ',');
2726: if ((c < '0' || c > '9') && c != '-')
2727: break;
2728: peekc = c;
2729: settab(getsnum());
2730: }
2731: peekc = c;
2732: newline();
2733: continue;
2734: } else if (peekc == '\n') { /* list tabs */
2735: setnoaddr();
2736: peekc = 0;
2737: #ifdef LOG
2738: ++logstats.lc_tablist;
2739: #endif
2740: listabs();
2741: continue;
2742: }
2743: #endif
2744: #ifdef LOG
2745: ++logstats.lc_transfer;
2746: #endif
2747: casecopy:
2748: move(1);
2749: text_modified++;
2750: continue;
2751:
2752: #ifdef UNDO
2753: case 'u':
2754: setnoaddr();
2755: newline();
2756: undo();
2757: #ifdef LOG
2758: ++logstats.lc_undo;
2759: #endif
2760: continue;
2761: #endif
2762:
2763: case 'v':
2764: global(0);
2765: continue;
2766:
2767: case 'w':
2768: #ifdef PAGE
2769: if ((peekc = getchar()) == '=') { /* w=<width> */
2770: peekc = 0;
2771: ccount = setnum(CCOUNT);
2772: #ifdef LOG
2773: ++logstats.lc_width;
2774: #endif
2775: continue;
2776: }
2777: #endif
2778: if ((peekc = getchar()) == 'i') { /* wi over-ride */
2779: ++immflg;
2780: peekc = 0;
2781: #ifdef LOG
2782: ++logstats.lc_wimm;
2783: #endif
2784: }
2785: #ifdef LOG
2786: else
2787: ++logstats.lc_write;
2788: #endif
2789: filename();
2790: #ifdef LOG
2791: if (appflg) {
2792: --logstats.lc_write;
2793: ++logstats.lc_wonto;
2794: }
2795: #endif
2796: if (globp) {
2797: setdot();
2798: appflg++;
2799: } else
2800: setall();
2801: if (dol == zero) {
2802: if (curt)
2803: putsn("?48");
2804: else
2805: putsn(errtext[48]);
2806: if (!fflg || appflg)
2807: continue;
2808: }
2809: if (over || immflg)
2810: override();
2811: if (appflg)
2812: io = open(file, 1);
2813: if (!appflg || io < 0)
2814: io = creat(file, MODE);
2815: if (overfile) {
2816: chmod(overfile, overmode);
2817: overfile = 0;
2818: }
2819: if (io < 0) {
2820: io = 0;
2821: if (curt)
2822: errmsg(54);
2823: puts2(errtext[54]);
2824: putsn(file);
2825: error();
2826: }
2827: io_w++;
2828: if (appflg)
2829: lseek(io, 0L, 2); /* append onto file */
2830: putfile();
2831: close(io);
2832: io = 0;
2833: io_w = 0;
2834: if (addr1 == zero + 1 && addr2 == dol)
2835: text_modified = 0;
2836: #ifdef LOG
2837: logstats.lt_wlines += dol - zero;
2838: #endif
2839: continue;
2840:
2841: #ifdef USE
2842: case '@':
2843: setnoaddr();
2844: if (alt)
2845: errmsg(6);
2846: if ((peekc = getchar()) == 'p')
2847: peekc = 0;
2848: else
2849: eflg2++;
2850: if ((peekc = getchar()) == '\n' && altfile[0]) {
2851: peekc = 0;
2852: goto altname;
2853: }
2854: if ((c = getchar()) != ' ' && c != '\t' && c != ',')
2855: errmsg(5);
2856: white_space();
2857: if ((c = getchar()) == '\n')
2858: errmsg(7);
2859: p = altfile;
2860: *p++ = c;
2861: while ((c = getchar()) != '\n') {
2862: if (c < 0)
2863: errmsg(59);
2864: *p++ = c;
2865: }
2866: *p = '\0';
2867: altname:
2868: #ifdef LOG
2869: ++logstats.lc_at;
2870: #endif
2871: if ((alt = open(altfile, 0)) < 0) {
2872: alt = 0; /* this MUST be 0 */
2873: lastc = '\n';
2874: if (curt)
2875: errmsg(53);
2876: puts2(errtext[53]);
2877: putsn(altfile);
2878: error();
2879: }
2880: continue;
2881: #endif
2882:
2883: #ifdef DEBUG
2884: case '#': /* toggle debug flag */
2885: if (addr1 != addr2 || addr1 != zero)
2886: goto illcmd;
2887: newline();
2888: tflg ^= 01;
2889: continue;
2890:
2891: #ifdef XDEL
2892: case '`':
2893: setnoaddr();
2894: newline();
2895: if (ndeleted == 0)
2896: errmsg(16);
2897: printf("deleted = %o ndeleted = %d\n", deleted, ndeleted);
2898: { register n, *bp, nl;
2899: int tl;
2900:
2901: tl = deleted;
2902: bp = getblock(tl, READ);
2903: #ifdef HUGE
2904: tl &= _1[hugef];
2905: #else
2906: tl &= _1;
2907: #endif
2908: nl = nleft / sizeof(linep);
2909: for (n = 0; n < ndeleted; n++) {
2910: printf("%7d: %6o\n", n + 1, *bp++);
2911: if (--nl <= 0) {
2912: #ifdef HUGE
2913: bp = getblock(tl += _2[hugef], READ);
2914: #else
2915: bp = getblock(tl += _2, READ);
2916: #endif
2917: nl = nleft / sizeof(linep);
2918: }
2919: }
2920: }
2921: continue;
2922: #endif
2923: #endif
2924:
2925: #ifdef XDEL
2926: case 'x':
2927: newline();
2928: r = undelete();
2929: #ifdef LOG
2930: ++logstats.lc_xundelete;
2931: #endif
2932: if (prompt2)
2933: printf((curt? prcntu : errtext[55]),
2934: r, (r == 1? null : quote_s));
2935: text_modified++;
2936: continue;
2937: #endif
2938:
2939: #ifdef YINT
2940: case 'y':
2941: if ((c = getchar()) == '+') {
2942: setdot();
2943: nonzero();
2944: newline();
2945: if (zero == dol)
2946: yplus = 0;
2947: else
2948: yplus = *addr2 | 01;
2949: yflg = 1;
2950: #ifdef LOG
2951: ++logstats.lc_yplus;
2952: #endif
2953: } else if (c == '-') {
2954: setnoaddr();
2955: newline();
2956: yflg = 0;
2957: #ifdef LOG
2958: ++logstats.lc_yminus;
2959: #endif
2960: } else {
2961: setnoaddr();
2962: peekc = c;
2963: newline();
2964: yflg = 1;
2965: yplus = 0;
2966: #ifdef LOG
2967: ++logstats.lc_yintr;
2968: #endif
2969: }
2970: continue;
2971: #endif
2972:
2973: #ifdef PIPE
2974: case '|':
2975: #ifndef XED
2976: if (globp) /* turkeys will be turkeys */
2977: errmsg(61);
2978: #endif
2979: if (noshell)
2980: errmsg(52);
2981: if ((peekc = getchar()) == '+') {
2982: peekc = 0;
2983: newline();
2984: setnoaddr();
2985: strict++;
2986: #ifdef LOG
2987: ++logstats.lc_piplus;
2988: #endif
2989: continue;
2990: } else if (peekc == '-') {
2991: peekc = 0;
2992: newline();
2993: setnoaddr();
2994: strict = 0;
2995: #ifdef LOG
2996: ++logstats.lc_piminus;
2997: #endif
2998: continue;
2999: }
3000: setdot();
3001: shell();
3002: continue;
3003: #endif
3004:
3005: case '!':
3006: #ifndef XED
3007: if (globp)
3008: errmsg(61);
3009: #endif
3010: if (noshell)
3011: errmsg(52);
3012: setnoaddr();
3013: shell();
3014: continue;
3015:
3016: #ifdef CKPT
3017: case 'z':
3018: newline();
3019: setnoaddr();
3020: checkpoint(0); /* doesn't return */
3021: #endif
3022:
3023: case EOF:
3024: #ifdef USE
3025: if (!baseflg && alt) {
3026: close(alt);
3027: alt = 0;
3028: eflg2 = 0;
3029: continue;
3030: }
3031: #endif
3032: return;
3033:
3034: }
3035: illcmd:
3036: errmsg(8);
3037: } /* nothing lasts "for ever" */
3038: }
3039:
3040: compile(aeof)
3041: charac aeof;
3042: {
3043: register charac eof, c;
3044: register char *ep, *lastep, *bracketp;
3045: register cclcnt;
3046: char bracket[NBRA];
3047:
3048: ep = expbuf;
3049: lastep = 0;
3050: eof = aeof;
3051: bracketp = bracket;
3052: if ((c = getchar()) == eof || c == '\n') {
3053: if (*ep == 0)
3054: errmsg(27);
3055: if (c == '\n')
3056: peekc = c;
3057: return;
3058: }
3059: circfl = 0;
3060: nbra = 0;
3061: if (
3062: #ifdef DUMB
3063: !dumbf &&
3064: #endif
3065: c == '^') {
3066: c = getchar();
3067: circfl++;
3068: #ifdef LOG
3069: ++logstats.lp_caret;
3070: #endif
3071: }
3072: /* if (c == '*') { /* if first = *, then quote it */
3073: /* *ep++ = CCHR; */
3074: /* *ep++ = c; */
3075: /* c = 0; */
3076: /* } */
3077: peekc = c;
3078: for ever {
3079: if (ep >= &expbuf[ESIZE - 2 - (bracketp - bracket) * 2])
3080: break;
3081: c = getchar();
3082: if (c == eof || c == '\n') {
3083: while (bracketp > bracket) {
3084: *ep++ = CKET;
3085: *ep++ = *--bracketp;
3086: }
3087: *ep++ = CEOF;
3088: if (c == '\n') {
3089: if (prompt2)
3090: pflag++;
3091: peekc = c;
3092: }
3093: return;
3094: }
3095: if (c != '*')
3096: lastep = ep;
3097: #ifdef DUMB
3098: if (dumbf && c >= 0)
3099: goto defchar;
3100: #endif
3101: switch (c) {
3102: case '\\':
3103: if ((c = getchar()) == '(') {
3104: if (nbra >= NBRA) {
3105: c = 44;
3106: goto cerror;
3107: }
3108: *bracketp++ = nbra;
3109: *ep++ = CBRA;
3110: *ep++ = nbra++;
3111: #ifdef LOG
3112: ++logstats.lp_paren;
3113: #endif
3114: continue;
3115: }
3116: if (c == ')') {
3117: if (bracketp <= bracket) {
3118: c = 45;
3119: goto cerror;
3120: }
3121: *ep++ = CKET;
3122: *ep++ = *--bracketp;
3123: continue;
3124: }
3125: if ('1' <= c && c < '1' + nbra) {
3126: *ep++ = CBACK;
3127: *ep++ = c - '1';
3128: #ifdef LOG
3129: ++logstats.lp_digit;
3130: #endif
3131: continue;
3132: }
3133: if (c == '\n') {
3134: c = 46;
3135: goto cerror;
3136: }
3137: defchar:
3138: default:
3139: *ep++ = CCHR;
3140: *ep++ = c;
3141: continue;
3142:
3143: case '.':
3144: *ep++ = CDOT;
3145: #ifdef LOG
3146: ++logstats.lp_dot;
3147: #endif
3148: continue;
3149:
3150: case '*':
3151: if (lastep == 0 ||
3152: *lastep == CBRA || *lastep == CKET)
3153: goto defchar;
3154: *lastep |= STAR;
3155: #ifdef LOG
3156: ++logstats.lp_star;
3157: #endif
3158: continue;
3159:
3160: case '$':
3161: if ((peekc = getchar()) != eof && peekc != '\n')
3162: goto defchar;
3163: *ep++ = CDOL;
3164: #ifdef LOG
3165: ++logstats.lp_dol;
3166: #endif
3167: continue;
3168:
3169: case '[':
3170: *ep++ = CCL;
3171: *ep++ = 0;
3172: cclcnt = 1;
3173: if ((c = getchar()) == '^') {
3174: c = getchar();
3175: ep[-2] = NCCL;
3176: #ifdef LOG
3177: ++logstats.lp_nccl;
3178: #endif
3179: }
3180: #ifdef LOG
3181: else
3182: ++logstats.lp_ccl;
3183: #endif
3184: do {
3185: if (c == '\\')
3186: c = getchar();
3187: if (c == '\n') {
3188: peekc = c;
3189: break;
3190: }
3191: if (c < 0) {
3192: c = 59;
3193: goto cerror;
3194: }
3195: *ep++ = c;
3196: cclcnt++;
3197: if (ep >= &expbuf[ESIZE - 2]) {
3198: c = 49;
3199: goto cerror;
3200: }
3201: } while ((c = getchar()) != ']');
3202: lastep[1] = cclcnt;
3203: continue;
3204:
3205: case EOF:
3206: c = 59;
3207: goto cerror;
3208: }
3209: }
3210: c = 42;
3211: cerror:
3212: expbuf[0] = '\0';
3213: nbra = 0;
3214: errmsg(c);
3215: }
3216:
3217: compsub() {
3218: register charac seof, c;
3219: register char *p;
3220:
3221: if ((seof = getchar()) == '\n')
3222: errmsg(40);
3223: compile(seof);
3224: p = rhsbuf;
3225: for ever {
3226: c = getchar();
3227: if (c < 0)
3228: errmsg(59);
3229: if (c == '\\')
3230: c = getchar() | 0200;
3231: if (c == '\n') {
3232: *p = 0;
3233: peekc = 0;
3234: if (prompt2)
3235: pflag++;
3236: return(0);
3237: }
3238: if (c == seof)
3239: break;
3240: *p++ = c;
3241: if (p >= &rhsbuf[LBSIZE / 2 - 2])
3242: errmsg(41);
3243: }
3244: *p = '\0';
3245: p = 0;
3246: if ((peekc = getchar()) == 'g') { /* if in 'glob' */
3247: peekc = 0;
3248: p = 1;
3249: } else if ('0' <= peekc && peekc <= '9')
3250: if ((s_cnt = getnum()) < 0)
3251: s_cnt = 0;
3252: newline();
3253: return(p);
3254: }
3255:
3256: create(as, am)
3257: char *as;
3258: {
3259: register savmask;
3260: register func savint, savqit;
3261: register ret;
3262:
3263: if (am == LMODE) {
3264: savint = signal(SIGINT, 1);
3265: savqit = signal(SIGQIT, 1);
3266: savmask = umask(LMASK);
3267: }
3268: ret = creat(as, am);
3269: if (am == LMODE) {
3270: umask(savmask);
3271: signal(SIGINT, savint);
3272: signal(SIGQIT, savqit);
3273: }
3274: return(ret);
3275: }
3276:
3277: delete() {
3278: register linep *a1, *a2, *a3;
3279:
3280: a1 = addr1;
3281: a2 = addr2 + 1;
3282: #ifdef XDEL
3283: if (!globp)
3284: saveline();
3285: #endif
3286: a3 = dol;
3287: dol -= a2 - a1;
3288: do {
3289: *a1++ = *a2++;
3290: } while (a2 <= a3);
3291: a1 = addr1;
3292: if (a1 > dol)
3293: a1 = dol;
3294: dot = a1;
3295: }
3296:
3297: delexit(aretcode) {
3298: #ifdef LOG
3299: #include <sys/times.h>
3300: struct tms t;
3301: #endif
3302:
3303: unlink(tfname);
3304: #ifdef LOG
3305: if ((io = open(LOG, 1)) >= 0) {
3306: time(&logstats.lt_end);
3307: times(&t);
3308: logstats.lt_usercpu = t.tms_utime;
3309: logstats.lt_syscpu = t.tms_stime;
3310: logstats.lt_kidscpu = t.tms_cutime + t.tms_cstime;
3311: lseek(io, 0L, 2);
3312: write(io, &logstats, sizeof logstats);
3313: }
3314: #endif
3315: exit(aretcode);
3316: }
3317:
3318: dosub() {
3319: register char *lp, *sp, *rp;
3320: register charac c;
3321:
3322: lp = linebuf;
3323: sp = genbuf;
3324: rp = rhsbuf;
3325: while (lp < loc1)
3326: *sp++ = *lp++;
3327: while (c = *rp++) {
3328: #ifdef DUMB
3329: if (!dumbf)
3330: #endif
3331: if (c == '&') {
3332: #ifdef LOG
3333: ++logamp;
3334: #endif
3335: sp = place(sp, loc1, loc2);
3336: continue;
3337: } else if (c < 0 && (c &= 0177) >= '1' &&
3338: c < nbra + '1') {
3339: c -= '1';
3340: sp = place(sp,braslist[c],braelist[c]);
3341: continue;
3342: }
3343: *sp++ = c & 0177;
3344: #ifndef ALLOC
3345: if (sp >= &genbuf[LBSIZE - 2])
3346: #else
3347: if (sp >= &genbuf[lbsize - 2])
3348: #endif
3349: errmsg(42);
3350: }
3351: lp = loc2;
3352: loc2 = sp + (linebuf - genbuf);
3353: while (*sp++ = *lp++)
3354: #ifndef ALLOC
3355: if (sp >= &genbuf[LBSIZE - 2])
3356: #else
3357: if (sp >= &genbuf[lbsize - 2])
3358: #endif
3359: errmsg(43);
3360: lp = linebuf;
3361: sp = genbuf;
3362: while (*lp++ = *sp++);
3363: }
3364:
3365: #ifdef DEBUG
3366: dump() {
3367: register linep *i;
3368: register b, o;
3369:
3370: setdot();
3371: nonzero();
3372: newline();
3373: line_num = addr1 - zero;
3374: for (i = addr1; i <= addr2; i++) {
3375: #ifdef HUGE
3376: b = (*i >> (8 - hugef)) & _3[hugef];
3377: o = (*i << (1 + hugef)) & _4[hugef];
3378: #else
3379: b = (*i >> 8) & _3;
3380: o = (*i << 1) & _4;
3381: #endif
3382: printlno(line_num++);
3383: #ifdef pdp11
3384: printf("%6o:%7o%6d/%d\n", i, *i, b, o);
3385: #else
3386: printf("%6o:%7o%6d/%d\n", i, *i&(unsigned)(unsigned short)-1, b, o);
3387: #endif
3388: }
3389: dot = addr2;
3390: }
3391: #endif
3392:
3393: echo(ch)
3394: charac ch;
3395: {
3396: #ifdef AGAIN
3397: static charac lastchar;
3398: #endif
3399: #ifdef USE
3400: if (eflg || alt && !eflg2)
3401: #endif
3402: #ifndef USE
3403: if (eflg)
3404: #endif
3405: write(2, &ch, 1);
3406: #ifdef AGAIN
3407: if (!agf && agp) { /* save current command for "again" */
3408: if (agp >= &agbuf[GBSIZE - 2])
3409: agp = agbuf[0] = 0;
3410: else
3411: *agp++ = ch;
3412: if (ch == '\n' && lastchar != '\\')
3413: agp = *agp = 0;
3414: }
3415: lastchar = ch;
3416: #endif
3417: return(ch);
3418: }
3419:
3420: errfunc() {
3421: if (io) {
3422: close(io);
3423: io = 0;
3424: io_w = 0;
3425: }
3426: if (overfile) {
3427: chmod(overfile, overmode);
3428: overfile = 0;
3429: }
3430: #ifdef HELP
3431: if (doc) {
3432: close(doc);
3433: doc = 0;
3434: }
3435: #endif
3436: #ifdef PIPE
3437: if (pfile) {
3438: close(pfile);
3439: unlink(pfname);
3440: pfile = 0;
3441: }
3442: #endif
3443: /* puts("?"); */
3444: if (!seekf)
3445: lseek(0, 0L, 2);
3446: pflag = 0;
3447: listf = 0;
3448: #ifdef PARENS
3449: parenf = 0;
3450: #endif
3451: #ifdef STRLEN
3452: quotef = 0;
3453: #endif
3454: if (globp) {
3455: lastc = '\n';
3456: globp = 0;
3457: }
3458: peekc = lastc;
3459: skip_rest();
3460: eflg2 = 0;
3461: reset();
3462: }
3463:
3464: errmsg(n) {
3465: extern errno;
3466:
3467: listf = 0;
3468: #ifdef PARENS
3469: parenf = 0;
3470: #endif
3471: #ifdef STRLEN
3472: quotef = 0;
3473: #endif
3474: col = 0;
3475: if (n < 0) {
3476: puts2("\7******** ");
3477: printf("%d ", errno);
3478: n = -n;
3479: }
3480: if (curt)
3481: printf("?%d\n", n);
3482: else
3483: if (0 <= n && n < NERR)
3484: putsn(errtext[n]);
3485: else
3486: printf("bad error number: %d\n", n);
3487: error();
3488: }
3489:
3490: execute(gf, addr)
3491: linep *addr;
3492: {
3493: register char *p1, *p2;
3494: register charac c;
3495:
3496: if (gf) {
3497: if (circfl)
3498: return(0);
3499: p1 = linebuf;
3500: p2 = genbuf;
3501: while (*p1++ = *p2++);
3502: locs = p1 = loc2;
3503: } else {
3504: if (addr == zero)
3505: return(0);
3506: p1 = getline(*addr);
3507: locs = 0;
3508: }
3509: p2 = expbuf;
3510: c = NBRA;
3511: while (--c >= 0) {
3512: braslist[c] = 0;
3513: braelist[c] = 0;
3514: }
3515: if (circfl) {
3516: loc1 = p1;
3517: return(advance(p1, p2));
3518: }
3519: /* fast check for first character */
3520: if (*p2 == CCHR) {
3521: c = p2[1];
3522: do {
3523: if (*p1 != c)
3524: continue;
3525: if (advance(p1, p2)) {
3526: loc1 = p1;
3527: return(1);
3528: }
3529: } while (*p1++);
3530: return(0);
3531: }
3532: /* regular algorithm */
3533: do {
3534: if (advance(p1, p2)) {
3535: loc1 = p1;
3536: return(1);
3537: }
3538: } while (*p1++);
3539: return(0);
3540: }
3541:
3542: #ifdef TABS
3543: exp() {
3544: register n;
3545: register linep p, *a1;
3546:
3547: setdot();
3548: nonzero();
3549: n = 0;
3550: for (a1 = addr1; a1 <= addr2; a1++) {
3551: getline(*a1);
3552: if (expand()) {
3553: n++;
3554: p = *a1;
3555: *a1 = putline();
3556: savemark(p, *a1);
3557: }
3558: }
3559: dot = addr2;
3560: return(n);
3561: }
3562:
3563: expand() {
3564: register char *p2;
3565: register charac c;
3566: register n;
3567: register char *p1;
3568: register cnt, i;
3569: register flag tabflg;
3570:
3571: p1 = linebuf;
3572: p2 = genbuf;
3573: while (*p2++ = *p1++);
3574: p2 = linebuf;
3575: p1 = genbuf;
3576: cnt = col = n = 0;
3577: while (c = *p1++) {
3578: if (c == tabc && col < maxtab) {
3579: n = col;
3580: c = tabfill;
3581: if (c == '\t') {
3582: n = col;
3583: tabflg = 0;
3584: while (n < maxtab) {
3585: if ((++n & 07) == 0) {
3586: *p2++ = c;
3587: tabflg++;
3588: if (p2 >=
3589: #ifndef ALLOC
3590: &linebuf[LBSIZE - 2]
3591: #else
3592: &linebuf[lbsize - 2]
3593: #endif
3594: || n >= TABS * BPW)
3595: goto experr;
3596: }
3597: if (tabs[n >> BPWC] >> (n & BPWM) & 01)
3598: if (*p1 == tabc &&
3599: n < maxtab) {
3600: p1++;
3601: cnt++;
3602: } else
3603: break;
3604: }
3605: i = n;
3606: if (tabflg)
3607: n &= 07;
3608: else
3609: n -= col;
3610: col = i;
3611: while (n--) {
3612: *p2++ = ' ';
3613: #ifndef ALLOC
3614: if (p2 >= &linebuf[LBSIZE - 2])
3615: #else
3616: if (p2 >= &linebuf[lbsize - 2])
3617: #endif
3618: goto experr;
3619: }
3620: cnt++;
3621: continue;
3622: }
3623: do {
3624: *p2++ = c;
3625: #ifndef ALLOC
3626: if (p2 >= &linebuf[LBSIZE - 2]
3627: #else
3628: if (p2 >= &linebuf[lbsize - 2]
3629: #endif
3630: || n >= TABS * BPW)
3631: goto experr;
3632: n++;
3633: } while (!(tabs[n >> BPWC] >> (n & BPWM) & 01));
3634: col = n;
3635: cnt++;
3636: continue;
3637: } else if ('\0' < c && c < ' ') {
3638: switch (c) {
3639: case '\b':
3640: col -= 2;
3641: break;
3642: case '\t':
3643: col += 7 - (col & 07);
3644: break;
3645: case '\r':
3646: col = -1;
3647: break;
3648: default:
3649: col--;
3650: }
3651: }
3652: if (c) {
3653: *p2++ = c;
3654: col++;
3655: #ifndef ALLOC
3656: if (p2 >= &linebuf[LBSIZE - 2] ||
3657: #else
3658: if (p2 >= &linebuf[lbsize - 2] ||
3659: #endif
3660: col >= TABS * BPW)
3661: experr: errmsg(12);
3662: }
3663: }
3664: *p2++ = 0;
3665: return(cnt);
3666: }
3667: #endif
3668:
3669: #ifdef DEBUG
3670: #ifdef EXPDMP
3671: expdmp() {
3672: register n;
3673: register char *ep, **p;
3674: register flag star;
3675:
3676: signal(SIGQIT, expdmp);
3677: ep = expbuf;
3678: putchar('"');
3679: if (circfl)
3680: putchar('^');
3681: while (*ep) {
3682: n = 0;
3683: star = 0;
3684: switch (*ep++) {
3685: case CCHR | STAR:
3686: star++;
3687: case CCHR:
3688: putchar(*ep++);
3689: break;
3690: case CDOT | STAR:
3691: star++;
3692: case CDOT:
3693: putchar('.');
3694: break;
3695: case CDOL:
3696: putchar('$');
3697: break;
3698: case CEOF:
3699: putchar('"');
3700: goto done;
3701: case NCCL | STAR:
3702: star++;
3703: case NCCL:
3704: n++;
3705: goto ccl;
3706: case CCL | STAR:
3707: star++;
3708: case CCL: ccl:
3709: putchar('[');
3710: if (n)
3711: putchar('^');
3712: n = *ep++;
3713: while (--n)
3714: putchar(*ep++);
3715: putchar(']');
3716: break;
3717: case CBRA:
3718: putchar('\\');
3719: putchar('(');
3720: ep++;
3721: break;
3722: case CKET:
3723: putchar('\\');
3724: putchar(')');
3725: ep++;
3726: break;
3727: case CBACK | STAR:
3728: star++;
3729: case CBACK:
3730: putchar('\\');
3731: putchar(*ep++ + '1');
3732: break;
3733: default:
3734: putchar('?');
3735: break;
3736: }
3737: if (star)
3738: putchar('*');
3739: }
3740: done: putchar('\n');
3741: if (reading)
3742: reset();
3743: }
3744: #endif
3745: #endif
3746:
3747: filename() {
3748: register char *p1, *p2;
3749: register charac c;
3750:
3751: appflg = 0;
3752: c = getchar();
3753: if (c < 0)
3754: errmsg(59);
3755: if (c == '\n') {
3756: noname:
3757: if (savedfile[0] == 0)
3758: errmsg(62);
3759: scopy(savedfile, file);
3760: return;
3761: }
3762: if (c != ' ' && c != '\t' && c != ',' && c != '>')
3763: errmsg(5);
3764: if (c != ',')
3765: peekc = c;
3766: white_space();
3767: if ((c = getchar()) == '>') {
3768: while ((c = getchar()) == '>');
3769: appflg++;
3770: if (c == '\n')
3771: goto noname;
3772: peekc = c;
3773: white_space();
3774: c = getchar();
3775: }
3776: if (c == '\n')
3777: errmsg(7);
3778: p1 = file;
3779: do {
3780: *p1++ = c;
3781: if (p1 >= &file[FNSIZE - 2])
3782: errmsg(11);
3783: } while ((c = getchar()) != '\n');
3784: *p1++ = 0;
3785: if (savedfile[0] == 0)
3786: scopy(file, savedfile);
3787: }
3788:
3789: linep *
3790: findmark(alp, adflt)
3791: linep alp, *adflt;
3792: {
3793: register linep *a, v;
3794: #ifdef HUGE
3795: register i;
3796:
3797: i = hugef ^ 01;
3798: #endif
3799: v = alp;
3800: for (a = zero + 1; a <= dol; a++)
3801: if (v == (*a |
3802: #ifdef HUGE
3803: i
3804: #else
3805: 1
3806: #endif
3807: ))
3808: return(a);
3809: return(adflt);
3810: }
3811:
3812: flush_buf() {
3813: register n;
3814:
3815: if (n = linp - line) {
3816: linp = line;
3817: write(fout, line, n);
3818: }
3819: }
3820:
3821: #ifdef G_VFY
3822: gask(a1)
3823: linep *a1;
3824: {
3825: register charac c;
3826:
3827: col = 0;
3828: printlno(line_num = a1 - zero);
3829: puts(linebuf);
3830: puts2("Ok? ");
3831: flush_buf();
3832: if ((c = getchar()) < 0) {
3833: putchar('\n');
3834: return(-1);
3835: }
3836: if (c == '\n')
3837: return(1);
3838: skip_rest();
3839: return(c != 'n');
3840: }
3841: #endif
3842:
3843: char *
3844: getblock(atl, iof) {
3845: extern read(), write();
3846: register bno, off;
3847: register linep *a;
3848: #ifdef HUGE
3849: register flag c;
3850: register func savint;
3851:
3852: bno = (atl >> (8 - hugef)) & _3[hugef];
3853: off = (atl << (1 + hugef)) & _4[hugef];
3854: #else
3855: bno = (atl >> 8) & _3;
3856: off = (atl << 1) & _4;
3857: #endif
3858: if (bno >=
3859: #ifdef HUGE
3860: _5[hugef]
3861: #else
3862: _5
3863: #endif
3864: ) {
3865: #ifdef HUGE
3866: if (!hugef && !globp) { /* let's try converting to huge */
3867: if (!curt) {
3868: putsn("File too large for normal editing.");
3869: puts2("Conversion to \"huge\" mode disallows ");
3870: puts2("use of the global command.");
3871: }
3872: c = yes_no(curt? "?huge" : "Do you wish to convert",
3873: 1, 0, 0);
3874: if (c) {
3875: savint = signal(SIGINT, 1);
3876: for (a = zero + 1; a <= dol; a++)
3877: *a = ((unsigned)*a) >> 1;
3878: hugef++;
3879: hugef2++; /* conversion occurred */
3880: atl = (atl >> 1) & _6[hugef];
3881: #ifdef XDEL
3882: ndeleted = 0; /* useless pointers */
3883: deleted = 0;
3884: #endif
3885: signal(SIGINT, savint);
3886: goto huger;
3887: }
3888: }
3889: #endif
3890: errmsg(34);
3891: }
3892: #ifdef HUGE
3893: huger:
3894: #endif
3895: nleft = BLKSIZE - off;
3896: if (bno == iblock && !badf) {
3897: ichanged |= iof;
3898: return(ibuff + off);
3899: }
3900: if (bno == oblock)
3901: return(obuff + off);
3902: if (iof == READ) {
3903: if (ichanged) {
3904: blkio(iblock, ibuff, write);
3905: ichanged = 0;
3906: }
3907: iblock = bno;
3908: blkio(bno, ibuff, read);
3909: return(ibuff + off);
3910: }
3911: if (oblock >= 0)
3912: blkio(oblock, obuff, write);
3913: oblock = bno;
3914: return(obuff + off);
3915: }
3916:
3917: charac
3918: getchar() {
3919: flush_buf();
3920: eof = 0;
3921: if (lastc = peekc) {
3922: peekc = 0;
3923: return(lastc);
3924: }
3925: if (globp) {
3926: if (lastc = *globp++) {
3927: if (globf2 && *globp == 0)
3928: globp = globf2 = 0;
3929: return(lastc);
3930: }
3931: globp = 0;
3932: return(EOF);
3933: }
3934: #ifdef AGAIN
3935: if (agf
3936: #ifdef USE
3937: && !alt
3938: #endif
3939: ) { /* "again" stuff */
3940: if (lastc = *agp++)
3941: return(lastc);
3942: agf = agp = 0;
3943: }
3944: #endif
3945: reading++;
3946: #ifdef USE
3947: if (read(alt, &lastc, 1) <= 0) {
3948: #endif
3949: #ifndef USE
3950: if (read(0, &lastc, 1) <= 0) {
3951: #endif
3952: reading = 0;
3953: eof++;
3954: return(lastc = EOF);
3955: }
3956: reading = 0;
3957: lastc &= 0177;
3958: #ifdef APLMAP
3959: if (aplmap && lastc > ' ')
3960: lastc = map_ascii[lastc - (' ' + 1)];
3961: #endif
3962: #ifdef EOL
3963: if (lastc == '\n')
3964: prompt3 = 1;
3965: else if (eol && lastc == eol) {
3966: lastc = '\n';
3967: prompt3 = 0;
3968: }
3969: #endif
3970: #ifdef CMDS
3971: if (cmd)
3972: write(cmd, &lastc, 1);
3973: #endif
3974: eof = 0;
3975: return(echo(lastc));
3976: }
3977:
3978: getcopy() {
3979: if (addr1 > addr2)
3980: return(EOF);
3981: getline(*addr1++);
3982: return(0);
3983: }
3984:
3985: getfile() {
3986: register charac c;
3987: register char *lp, *fp;
3988:
3989: lp = linebuf;
3990: fp = nextip;
3991: do {
3992: if (--ninbuf < 0) {
3993: #ifndef ALLOC
3994: if ((ninbuf = read(io, genbuf, LBSIZE) - 1) < 0)
3995: #else
3996: if ((ninbuf = read(io, genbuf, lbsize) - 1) < 0)
3997: #endif
3998: if (lp == linebuf)
3999: return(EOF);
4000: else {
4001: lp++;
4002: break;
4003: }
4004: fp = genbuf;
4005: }
4006: #ifndef ALLOC
4007: if (lp >= &linebuf[LBSIZE - 2] && (*fp & 0177) != '\n') {
4008: #else
4009: if (lp >= &linebuf[lbsize - 2] && (*fp & 0177) != '\n') {
4010: #endif
4011: printf((curt? "?long%u\n" : "line %u in file too long\n"),
4012: dot - zero + 1);
4013: flush_buf();
4014: lp++;
4015: ninbuf++;
4016: break;
4017: }
4018: if ((*lp++ = c = *fp++ & 0177) == 0) {
4019: lp--;
4020: continue;
4021: }
4022: } while (c != '\n');
4023: *--lp = 0;
4024: nextip = fp;
4025: return(0);
4026: }
4027:
4028: getline(tl) {
4029: register char *bp, *lp;
4030: register nl;
4031:
4032: #ifdef DEBUG
4033: if (tflg)
4034: printf("getline:\t%o\n", tl);
4035: #endif
4036: lp = linebuf;
4037: bp = getblock(tl, READ);
4038: #ifdef HUGE
4039: if (hugef2) {
4040: hugef2 = 0;
4041: tl = (tl >> 1) & _6[hugef];
4042: }
4043: tl &= _1[hugef];
4044: #else
4045: tl &= _1;
4046: #endif
4047: nl = nleft;
4048: while (*lp++ = *bp++)
4049: if (--nl <= 0) {
4050: #ifdef HUGE
4051: bp = getblock(tl += _2[hugef], READ);
4052: #else
4053: bp = getblock(tl += _2, READ);
4054: #endif
4055: nl = nleft;
4056: }
4057: return(linebuf);
4058: }
4059:
4060: getnum() {
4061: register n;
4062: register charac c;
4063:
4064: n = 0;
4065: while ('0' <= (c = getchar()) && c <= '9')
4066: n = n * 10 + c - '0';
4067: peekc = c;
4068: return(n);
4069: }
4070:
4071: getsnum() {
4072: register sign;
4073:
4074: if (sign = (peekc = getchar()) == '-')
4075: peekc = 0;
4076: return(sign? -getnum() : getnum());
4077: }
4078:
4079: getsub() {
4080: register char *p1, *p2;
4081:
4082: p1 = linebuf;
4083: if ((p2 = linebp) == 0)
4084: return(EOF);
4085: while (*p1++ = *p2++);
4086: linebp = 0;
4087: return(0);
4088: }
4089:
4090: gettty(single) {
4091: register charac c;
4092: register char *p, *gf;
4093: #ifdef TABS
4094: int tabf;
4095:
4096: tabf = 0;
4097: #endif
4098: p = linebuf;
4099: gf = globp;
4100: #ifdef EOL
4101: if (prompt2 && prompt3 && !single) {
4102: #endif
4103: #ifndef EOL
4104: if (prompt2 && !single) {
4105: #endif
4106: printlno(line_num);
4107: flush_buf();
4108: }
4109: line_num++;
4110: while ((c = getchar()) != '\n') {
4111: if (c < 0) {
4112: if (gf)
4113: peekc = c;
4114: else if (prompt2 && (prompt1 || !zflg))
4115: putchar('\n');
4116: if (p > linebuf)
4117: break;
4118: return(c);
4119: }
4120: if ((c &= 0177) == 0)
4121: continue;
4122: #ifdef TABS
4123: if (tabc && c == tabc)
4124: tabf++;
4125: #endif
4126: *p++ = c;
4127: #ifndef ALLOC
4128: if (p >= &linebuf[LBSIZE - 2])
4129: #else
4130: if (p >= &linebuf[lbsize - 2])
4131: #endif
4132: errmsg(30);
4133: }
4134: *p++ = 0;
4135: #ifdef TABS
4136: if (tabf)
4137: expand();
4138: #endif
4139: if (!single && linebuf[0] == '.' && linebuf[1] == 0)
4140: return(EOF);
4141: return(0);
4142: }
4143:
4144: global(k) {
4145: register char *gp;
4146: register charac c;
4147: register linep *a1;
4148: register flag globpf;
4149: char globuf[GBSIZE];
4150:
4151: #ifdef HUGE
4152: if (hugef)
4153: errmsg(10);
4154: #endif
4155: if (globp)
4156: errmsg(37);
4157: setall();
4158: nonzero();
4159: if ((c = getchar()) == '\n')
4160: peekc = c;
4161: compile(c);
4162: #ifdef G_VFY
4163: gaskf = 0;
4164: if ((peekc = getchar()) == 'v') {
4165: gaskf++;
4166: peekc = 0;
4167: }
4168: #endif
4169: globpf = pflag;
4170: if (peekc == '\n')
4171: globpf = 0;
4172: pflag = 0;
4173: gp = globuf;
4174: if ((peekc = getchar()) < 0)
4175: errmsg(59);
4176: if (peekc == '\n') {
4177: *gp++ = 'p';
4178: peekc = 0;
4179: } else
4180: while ((c = getchar()) != '\n') {
4181: if (c == '\\') {
4182: c = getchar();
4183: if (c != '\n')
4184: *gp++ = '\\';
4185: }
4186: if (c < 0)
4187: errmsg(59);
4188: *gp++ = c;
4189: if (gp >= &globuf[GBSIZE - 2])
4190: errmsg(38);
4191: }
4192: *gp++ = '\n';
4193: *gp = 0;
4194: c = 0;
4195: #ifdef LOG
4196: #ifdef G_VFY
4197: if (gaskf)
4198: ++logstats.lc_gvfy;
4199: #endif
4200: if (k)
4201: ++logstats.lc_global;
4202: else
4203: ++logstats.lc_vglobal;
4204: #endif
4205: for (a1 = zero + 1; a1 <= dol; a1++) {
4206: *a1 &= ~01;
4207: s_tmp = 0;
4208: if (a1 >= addr1 && a1 <= addr2 && execute(0, a1) == k)
4209: #ifdef G_VFY
4210: if (!gaskf || (c = gask(a1)))
4211: if (c < 0)
4212: addr2 = a1;
4213: else
4214: #endif
4215: *a1 |= 01;
4216: }
4217: for (a1 = zero + 1; a1 <= dol; a1++)
4218: if (*a1 & 01) {
4219: *a1 &= ~01;
4220: dot = a1;
4221: globp = globuf;
4222: pflag = globpf;
4223: commands(1);
4224: a1 = zero;
4225: }
4226: }
4227:
4228: hangup() {
4229: signal(SIGHUP, 1);
4230: if (reading) {
4231: backup(HUP);
4232: if (fout != 1) {
4233: flush_buf();
4234: fout = 1;
4235: }
4236: puts2(errtext[57]);
4237: delexit(1);
4238: }
4239: hupflag++;
4240: }
4241:
4242: () {
4243: register colnum, number;
4244: register flag lf;
4245:
4246: number = 0;
4247: if ((peekc = getchar()) != '\n') {
4248: white_space();
4249: number = getnum();
4250: }
4251: if (!number)
4252: number = ccount - (prompt1? 8 : 0);
4253: newline();
4254: if (zero != dol)
4255: dot = addr2;
4256: lf = listf;
4257: listf = 0;
4258: if (prompt1)
4259: putchar('\t');
4260: for (colnum = 0; colnum < number / 10; colnum++)
4261: printf("%10d", colnum + 1);
4262: putchar('\n');
4263: if (prompt1)
4264: putchar('\t');
4265: for (colnum = 1; colnum <= number; colnum++)
4266: #ifdef TABS
4267: if (colnum < (TABS << BPWC) &&
4268: (tabs[(colnum - 1) >> BPWC] >>
4269: ((colnum - 1) & BPWM) & 01))
4270: putchar('-');
4271: else
4272: #endif
4273: putchar(colnum % 10 + '0');
4274: putchar('\n');
4275: listf = lf;
4276: }
4277:
4278: init() {
4279: register n;
4280: register char *p;
4281:
4282: if (tfile > 0)
4283: close(tfile);
4284: if (io) {
4285: close(io);
4286: io = 0;
4287: io_w = 0;
4288: }
4289: #ifdef HELP
4290: if (doc) {
4291: close(doc);
4292: doc = 0;
4293: }
4294: #endif
4295: #ifdef USE
4296: if (alt) {
4297: close(alt);
4298: alt = 0;
4299: eflg2 = 0;
4300: }
4301: #endif
4302: #ifdef PIPE
4303: if (pfile) {
4304: close(pfile);
4305: unlink(pfname);
4306: pfile = 0;
4307: }
4308: #endif
4309: tline = 0;
4310: #ifdef XDEL
4311: deleted = 0;
4312: ndeleted = 0;
4313: #endif
4314: num_reads = 0;
4315: text_modified = 0;
4316: #ifdef YINT
4317: yplus = 0;
4318: #endif
4319: #ifdef UNDO
4320: undo_oldp = 0;
4321: undo_newp = 0;
4322: #endif
4323: #ifdef V7
4324: if (overfile) {
4325: chmod(overfile, overmode);
4326: overfile = 0;
4327: }
4328: #endif
4329: iblock = oblock = -1;
4330: badf = 0;
4331: ichanged = 0;
4332: if ((n = create(tfname, LMODE)) < 0) {
4333: putsn(errtext[50]);
4334: exit(1);
4335: }
4336: close(n);
4337: if ((tfile = open(tfname, 2)) < 0) {
4338: putsn(errtext[36]);
4339: exit(1);
4340: }
4341: addr1 = addr2 = dot = dotdot = lastdot = zero = dol = fendcore;
4342: endcore = fendcore - 2;
4343: brk(fendcore);
4344: n = 26;
4345: while (--n >= 0) { /* kill marks */
4346: names[n] = 0;
4347: #ifdef EXTMARK
4348: names2[n] = 0;
4349: #endif
4350: }
4351: p = globp;
4352: globp = 0;
4353: if (chk()) {
4354: if ((io = open(file, 0)) < 0) {
4355: io = 0;
4356: lastc = '\n';
4357: if (curt)
4358: putsn("?53");
4359: else {
4360: puts2(errtext[53]);
4361: putsn(file);
4362: }
4363: flush_buf();
4364: } else {
4365: n = append(getfile, addr1, 0, 0);
4366: if (prompt2)
4367: printf((curt? prcntu : errtext[55]),
4368: n, (n == 1? null : quote_s));
4369: if (n) {
4370: num_reads++;
4371: text_modified++;
4372: }
4373: if (io) {
4374: close(io);
4375: io = 0;
4376: io_w = 0;
4377: }
4378: }
4379: return(1);
4380: }
4381: globp = p;
4382: return(0);
4383: }
4384:
4385: istty(fd) {
4386: register r;
4387: short buf[3]; /* naughty int's */
4388:
4389: buf[2] = BS1;
4390: r = 0;
4391: if (gtty(fd, buf) >= 0)
4392: ++r;
4393: #ifdef CLEAR
4394: zflg = (buf[2] & BS1) == 0;
4395: #endif
4396: if (pipef
4397: #ifdef V7
4398: || getenv("_NO_STDIO_BUF")
4399: #endif
4400: )
4401: ++r;
4402: return(r);
4403: }
4404:
4405: #ifdef XED
4406: join() {
4407: register linep *a1;
4408: register char *p1, *p2;
4409: register charac c, ceof;
4410:
4411: setdot();
4412: nonzero();
4413: if (addr1 == addr2)
4414: --addr1;
4415: if (addr1 <= zero)
4416: errmsg(60);
4417:
4418: p2 = rhsbuf;
4419: if ((c = peekc = getchar()) < 0)
4420: errmsg(59);
4421: ceof = 0;
4422: if (peekc != '\n' && peekc != 'p' && peekc != 'l'
4423: #ifdef PARENS
4424: && peekc != 'b'
4425: #endif
4426: #ifdef STRLEN
4427: && peekc != 'q'
4428: #endif
4429: ) {
4430: ceof = peekc;
4431: peekc = 0;
4432: while ((c = getchar()) != ceof && c != '\n') {
4433: if (c < 0)
4434: errmsg(59);
4435: if (c == '\\')
4436: if ((c = getchar()) == '\n')
4437: errmsg(46);
4438: *p2++ = c;
4439: if (p2 >= &rhsbuf[LBSIZE / 2 - 2])
4440: errmsg(42);
4441: }
4442: if (c != '\n')
4443: c = '\0';
4444: else
4445: if (prompt2)
4446: pflag++;
4447: if (p2 != rhsbuf)
4448: *p2 = '\0';
4449: if (*rhsbuf == 0)
4450: errmsg(27);
4451: #ifdef LOG
4452: ++logstats.lc_jglue;
4453: #endif
4454: }
4455: #ifdef LOG
4456: else
4457: ++logstats.lc_join;
4458: #endif
4459: peekc = c;
4460: newline();
4461:
4462: p1 = rhsbuf;
4463: while (*p1)
4464: if (*p1++ == '\n')
4465: errmsg(46);
4466:
4467: p2 = genbuf;
4468: a1 = addr1;
4469:
4470: while (a1 <= addr2) {
4471: p1 = getline(*a1++);
4472: while (*p2++ = *p1++)
4473: #ifndef ALLOC
4474: if (p2 >= &genbuf[LBSIZE - 2])
4475: #else
4476: if (p2 >= &genbuf[lbsize - 2])
4477: #endif
4478: errmsg(12);
4479: --p2;
4480: if (ceof && a1 <= addr2) {
4481: p1 = rhsbuf;
4482: while (*p2++ = *p1++)
4483: #ifndef ALLOC
4484: if (p2 >= &genbuf[LBSIZE - 2])
4485: #else
4486: if (p2 >= &genbuf[lbsize - 2])
4487: #endif
4488: errmsg(12);
4489: --p2;
4490: }
4491: }
4492: *p2 = '\0';
4493:
4494: p1 = genbuf;
4495: p2 = linebuf;
4496: while (*p2++ = *p1++);
4497:
4498: a1 = putline();
4499: savemark(*addr1, a1);
4500: *addr1++ = a1;
4501: delete();
4502: dot = --addr1;
4503: if (dot > dol)
4504: dot = dol;
4505: }
4506: #endif
4507:
4508: #ifdef TABS
4509: listabs() {
4510: register n;
4511:
4512: if (maxtab < 0)
4513: errmsg(9);
4514: n = next_tab(-1);
4515: printf("tabs: %d", n + 1);
4516: while ((n = next_tab(n)) >= 0)
4517: printf(",%d", n + 1);
4518: putchar('\n');
4519: }
4520: #endif
4521:
4522: mail() {
4523: delexit(1);
4524: }
4525:
4526: move(cflag) {
4527: extern getcopy();
4528: register linep *adt, *ad1, *ad2;
4529:
4530: setdot();
4531: nonzero();
4532: if ((adt = address()) == 0)
4533: errmsg(31);
4534: ad1 = addr1;
4535: ad2 = addr2;
4536: newline();
4537: if (cflag) {
4538: ad1 = dol;
4539: append(getcopy, ad1++, 0, 0);
4540: ad2 = dol;
4541: }
4542: ad2++;
4543: if (adt < ad1) {
4544: dot = adt + (ad2 - ad1);
4545: if (++adt == ad1)
4546: return;
4547: reverse(adt, ad1);
4548: reverse(ad1, ad2);
4549: reverse(adt, ad2);
4550: } else if (adt >= ad2) {
4551: dot = adt++;
4552: reverse(ad1, ad2);
4553: reverse(ad2, adt);
4554: reverse(ad1, adt);
4555: } else
4556: errmsg(28);
4557: }
4558:
4559: newline() {
4560: register charac c;
4561:
4562: if ((c = getchar()) == '\n')
4563: return;
4564: if (c == 'p' || c == 'l'
4565: #ifdef PARENS
4566: || c == 'b'
4567: #endif
4568: #ifdef STRLEN
4569: || c == 'q'
4570: #endif
4571: ) {
4572: pflag++;
4573: if (c == 'l')
4574: listf++;
4575: #ifdef PARENS
4576: else if (c == 'b')
4577: parenf++;
4578: #endif
4579: #ifdef STRLEN
4580: else if (c == 'q')
4581: quotef++;
4582: #endif
4583: if (getchar() == '\n')
4584: return;
4585: }
4586: errmsg(25);
4587: }
4588:
4589: #ifdef TABS
4590: next_tab(acol) {
4591: register n;
4592:
4593: if ((n = acol) < maxtab) {
4594: do {
4595: n++;
4596: } while (!(tabs[n >> BPWC] >> (n & BPWM) & 01));
4597: return(n);
4598: }
4599: return(-1);
4600: }
4601: #endif
4602:
4603: nonzero() {
4604: if (addr1 <= zero)
4605: errmsg(23);
4606: if (addr2 > dol)
4607: errmsg(24);
4608: }
4609:
4610: #ifdef PIPE
4611: oil_spilled() {
4612: if (!iflg) {
4613: signal(SIGINT, 1);
4614: signal(SIGQIT, 1);
4615: }
4616: signal(SIGPIP, 1);
4617: piperr++;
4618: }
4619: #endif
4620:
4621: onintr() {
4622: register char *p1, *p2;
4623:
4624: signal(SIGINT, onintr);
4625: #ifdef USE
4626: if (alt) {
4627: close(alt);
4628: alt = 0;
4629: eflg2 = 0;
4630: }
4631: #endif
4632: if (io) {
4633: if (curt)
4634: putsn("?intI/O");
4635: else {
4636: puts2("\7Interrupted I/O!!!\7\nWarning: \"");
4637: puts2(file);
4638: if (io_w) {
4639: putsn("\" is probably truncated.");
4640: puts2("You should probably re-write it.");
4641: } else {
4642: putsn("\" was not read entirely.");
4643: puts2("If you write the buffer, ");
4644: puts2("part of the file may be lost.");
4645: }
4646: }
4647: flush_buf();
4648: }
4649: #ifdef EOL
4650: prompt3 = 1;
4651: #endif
4652: if (fout != 1) {
4653: close(fout);
4654: fout = 1;
4655: }
4656: #ifdef YINT
4657: if (!globp && reading && yflg) {
4658: globp = ".:\n";
4659: if (yplus) {
4660: dot = findmark(yplus, 0);
4661: } else
4662: globp++;
4663: peekc = 0;
4664: putchar('\n');
4665: commands(1);
4666: reset();
4667: }
4668: #endif
4669: if (iflg) {
4670: signal(SIGINT, 1);
4671: backup(INT);
4672: delexit(1);
4673: }
4674: putchar(lastc = '\n');
4675: errmsg(29);
4676: }
4677:
4678: override() {
4679: struct stat s;
4680:
4681: if (access(file, 02) < 0) {
4682: if (stat(file, &s) >= 0 && (s.st_mode & S_IFMT) == S_IFREG) {
4683: overmode = s.st_mode & 07777;
4684: if (chmod(file, overmode) < 0)
4685: return;
4686: if (immflg == 0) {
4687: if (curt) {
4688: puts2("?\"");
4689: puts2(file);
4690: puts2("\" ");
4691: } else {
4692: puts2("The file \"");
4693: puts2(file);
4694: puts2("\" is write-protected.");
4695: }
4696: if (yes_no(curt? "override" :
4697: "Do you wish to over-ride the permission",
4698: 0, 1, 1))
4699: return;
4700: }
4701: overfile = file;
4702: if (chmod(overfile, overmode | 0200) < 0)
4703: overfile = 0;
4704: else {
4705: putsn("[over-riding]");
4706: #ifdef LOG
4707: ++logstats.lm_overwrite;
4708: #endif
4709: }
4710: }
4711: }
4712: }
4713:
4714: #ifdef PAGE
4715: page() {
4716: register cl, n;
4717: register char *p, *pp;
4718: register linep *a, *b;
4719: register l;
4720:
4721: a = addr1;
4722: if (addr2 != addr1)
4723: b = addr2;
4724: else
4725: b = dol;
4726: #ifdef PARENS
4727: parenc[0] = 0;
4728: parenc[1] = 0;
4729: parenc[2] = 0;
4730: #endif
4731: for (n = pcount; n >= 0 && a <= b; n--) {
4732: pp = p = getline(*a);
4733: cl = prompt1? 8 : 0;
4734: l = 0;
4735: while (*p) {
4736: if (*p < ' ' || *p > '~')
4737: switch (*p) {
4738: case '\b':
4739: if (listf)
4740: cl++;
4741: else {
4742: cl--;
4743: if (aflg
4744: #ifdef PARENS
4745: && !parenf
4746: #endif
4747: #ifdef STRLEN
4748: && !quotef
4749: #endif
4750: )
4751: l++;
4752: }
4753: break;
4754: case '\t':
4755: if (listf)
4756: cl++;
4757: else
4758: cl += 8 - cl % 8;
4759: break;
4760: case '\r':
4761: if (listf)
4762: cl += 2;
4763: else
4764: cl = 0;
4765: break;
4766: case ctrl('L'): /* ADM-3A's */
4767: if (listf)
4768: cl++;
4769: cl++;
4770: break;
4771: default:
4772: if (listf || zflg)
4773: cl += 2;
4774: }
4775: else
4776: cl++;
4777: #ifdef PARENS
4778: if (parenf && paren(*p))
4779: l++;
4780: #endif
4781: #ifdef STRLEN
4782: /* if (quotef && (*p == '"' || *p == '\'')) */
4783: if (quotef && (quotec? *p == quotec :
4784: *p == '"' || *p == '\''))
4785: l++;
4786: #endif
4787: if (cl < 0)
4788: cl = 0;
4789: else if (cl > ccount) {
4790: cl = 0;
4791: if (--n < 0)
4792: goto done;
4793: }
4794: p++;
4795: }
4796: if (l)
4797: if (--n < 0)
4798: goto done;
4799: col = 0;
4800: printlno(line_num = a - zero);
4801: puts(pp);
4802: a++;
4803: }
4804: done:
4805: dot = a - 1;
4806: }
4807: #endif
4808:
4809: #ifdef PARENS
4810: paren(ac) {
4811: switch (ac) {
4812: case '(': return(1);
4813: case '[': return(2);
4814: case '{': return(3);
4815: case ')': return(-1);
4816: case ']': return(-2);
4817: case '}': return(-3);
4818: }
4819: return(0);
4820: }
4821: #endif
4822:
4823: place(asp, al1, al2) {
4824: register char *sp, *l1, *l2;
4825:
4826: sp = asp;
4827: l1 = al1;
4828: l2 = al2;
4829: while (l1 < l2) {
4830: *sp++ = *l1++;
4831: #ifndef ALLOC
4832: if (sp >= &genbuf[LBSIZE - 2])
4833: #else
4834: if (sp >= &genbuf[lbsize - 2])
4835: #endif
4836: errmsg(42);
4837: }
4838: return(sp);
4839: }
4840:
4841: /*VARARGS*/
4842: printf(as, aarglist)
4843: char *as;
4844: {
4845: register *args, w;
4846: register char *q;
4847: register flag f;
4848:
4849: args = &aarglist;
4850: while (*as) {
4851: if (*as != '%') {
4852: putchar(*as++);
4853: continue;
4854: }
4855: if (*++as == '\0')
4856: return;
4857: w = 0; /* no default width */
4858: f = 0; /* unsigned default */
4859: while ('0' <= *as && *as <= '9')
4860: w = w * 10 + *as++ - '0';
4861: if (*as == '\0')
4862: return;
4863: switch (*as++) {
4864: case 'c': /* char */
4865: putchar(*args++);
4866: continue;
4867: case 'd': /* signed decimal */
4868: f = 1; /* signed */
4869: case 'u': /* unsigned decimal */
4870: printfn(*args++, 10, f, w);
4871: continue;
4872: case 'o': /* unsigned octal */
4873: printfn(*args++, 8, 0, w);
4874: continue;
4875: case 's': /* string */
4876: q = *args++;
4877: while (*q) {
4878: putchar(*q++);
4879: --w;
4880: }
4881: while (--w > 0)
4882: putchar(' ');
4883: continue;
4884: default:
4885: putchar(as[-1]);
4886: continue;
4887: }
4888: }
4889: }
4890:
4891: printfn(an, ab, af, aw) {
4892: register w;
4893: register unsigned n;
4894: register char *p;
4895: char buf[(sizeof(int) != 2? 10 : 6) + 2];
4896:
4897: w = aw;
4898: p = &buf[sizeof buf];
4899: *--p = '\0';
4900: n = an;
4901: if (af)
4902: if (an < 0)
4903: n = -an;
4904: else
4905: af = 0;
4906: do {
4907: *--p = n % ab + '0';
4908: --w;
4909: } while (n /= ab);
4910: if (af) {
4911: *--p = '-';
4912: --w;
4913: }
4914: while (--w >= 0)
4915: putchar(' ');
4916: while (*p)
4917: putchar(*p++);
4918: }
4919:
4920: printlno(an) {
4921: register flag l;
4922:
4923: if (prompt1) {
4924: l = listf;
4925: listf = 0;
4926: printf(fmtlno, an - aflg);
4927: col = 8;
4928: listf = l;
4929: }
4930: }
4931:
4932: printmarks() {
4933: register linep *a1;
4934: register charac c;
4935: register n, i;
4936:
4937: #ifdef HUGE
4938: i = hugef ^ 01;
4939: #endif
4940: for (c = 'a' - 'a'; c <= 'z' - 'a'; c++) {
4941: if (names[c] == 0) /* zap marks to deleted lines */
4942: continue;
4943: n = 0;
4944: for (a1 = zero + 1; a1 <= dol; a1++)
4945: if (names[c] == (*a1 |
4946: #ifdef HUGE
4947: i
4948: #else
4949: 01
4950: #endif
4951: )) {
4952: n++;
4953: printf("%c=%u", c + 'a', a1 - zero);
4954: #ifdef EXTMARK
4955: if (names2[c]) {
4956: for (a1++; a1 <= dol; a1++)
4957: if (names2[c] == (*a1 | 01)) {
4958: printf(",%u", a1 - zero);
4959: break;
4960: }
4961: }
4962: #endif
4963: putchar(' ');
4964: break;
4965: }
4966: if (n == 0)
4967: names[c] = 0; /* clear unknown marks */
4968: }
4969: putchar('\n');
4970: }
4971:
4972: putchar(ac)
4973: charac ac;
4974: {
4975: register char *lp;
4976: register charac c;
4977:
4978: lp = linp;
4979: c = ac;
4980: #ifdef APLMAP
4981: if (aplmap && fout == 1 && c > ' ')
4982: c = map_apl[c - (' ' + 1)];
4983: #endif
4984: if (listf) {
4985: if (++col >= ccount - 1) {
4986: col = 1;
4987: if (c != '\n') {
4988: *lp++ = '\\';
4989: *lp++ = '\n';
4990: }
4991: }
4992: if (c == '\t') {
4993: c = '>';
4994: goto esc;
4995: }
4996: if (c == '\b') {
4997: c = '<';
4998: esc:
4999: *lp++ = '-';
5000: *lp++ = '\b';
5001: *lp++ = c;
5002: goto out;
5003: }
5004: if (c < ' ' && c != '\n' || c == 0177) {
5005: *lp++ = '^';
5006: *lp++ = c ^ 0100;
5007: col++;
5008: goto out;
5009: }
5010: }
5011: *lp++ = c;
5012: out:
5013: if (lp >= &line[TTSIZE]) {
5014: linp = line;
5015: write(fout, line, lp - line);
5016: return;
5017: }
5018: linp = lp;
5019: }
5020:
5021: putfile() {
5022: register char *fp, *lp;
5023: register nib;
5024: register linep *a1;
5025:
5026: nib = BLKSIZE;
5027: fp = genbuf;
5028: a1 = addr1;
5029: do {
5030: lp = getline(*a1++);
5031: for ever {
5032: if (--nib < 0) {
5033: wte(io, genbuf, fp - genbuf);
5034: nib = BLKSIZE - 1;
5035: fp = genbuf;
5036: }
5037: if ((*fp++ = *lp++) == 0) {
5038: fp[-1] = '\n';
5039: break;
5040: }
5041: }
5042: } while (a1 <= addr2);
5043: wte(io, genbuf, fp - genbuf);
5044: }
5045:
5046: putline() {
5047: register char *bp, *lp;
5048: register nl, tl;
5049:
5050: lp = linebuf;
5051: tl = tline;
5052: #ifdef DEBUG
5053: if (tflg)
5054: printf("putline:\t%o\n", tl);
5055: #endif
5056: bp = getblock(tl, WRITE);
5057: #ifdef HUGE
5058: if (hugef2) {
5059: hugef2 = 0;
5060: tl = tline = (tline >> 1) & _6[hugef];
5061: }
5062: tl &= _1[hugef];
5063: #else
5064: tl &= _1;
5065: #endif
5066: nl = nleft;
5067: while (*bp = *lp++) {
5068: if (*bp++ == '\n') {
5069: *--bp = 0;
5070: linebp = lp;
5071: break;
5072: }
5073: if (--nl <= 0) {
5074: #ifdef HUGE
5075: bp = getblock(tl += _2[hugef], WRITE);
5076: #else
5077: bp = getblock(tl += _2, WRITE);
5078: #endif
5079: nl = nleft;
5080: }
5081: }
5082: nl = tline;
5083: #ifdef HUGE
5084: tline += (((lp - linebuf) + 03) >> (1 + hugef)) & _6[hugef];
5085: #else
5086: tline += (((lp - linebuf) + 03) >> 1) & _6;
5087: #endif
5088: return(nl);
5089: }
5090:
5091: #ifdef PARENS
5092: putparen(an) {
5093: register c;
5094:
5095: an %= 10 + 26 + 26;
5096: if (an < 0)
5097: an += 10 + 26 + 26;
5098: c = '0';
5099: if (an > 9 + 26)
5100: c = 'a' - (10 + 26);
5101: else if (an > 9)
5102: c = 'A' - 10;
5103: putchar(c + an);
5104: }
5105: #endif
5106:
5107: puts(as) {
5108: register n;
5109: register flag ovp;
5110: register char *sp, *s;
5111:
5112: sp = as;
5113: ovp = 0;
5114: while (*sp) {
5115: if (aflg &&
5116: #ifdef PARENS
5117: !parenf &&
5118: #endif
5119: #ifdef STRLEN
5120: !quotef &&
5121: #endif
5122: !listf && *sp == '\b') {
5123: ovp = 1;
5124: sp += 2;
5125: continue;
5126: }
5127: #ifdef PARENS
5128: if (!ovp && parenf && !listf && paren(*sp))
5129: ovp = 1;
5130: #endif
5131: #ifdef STRLEN
5132: /* if (!ovp && quotef && !listf && (*sp == '"' || *sp == '\'')) */
5133: if (!ovp && quotef && !listf && (
5134: quotec? *sp == quotec : *sp == '"' || *sp == '\''))
5135: ovp = 1;
5136: #endif
5137: putchar(*sp++);
5138: }
5139: sp = as;
5140: if (aflg && ovp &&
5141: #ifdef PARENS
5142: !parenf &&
5143: #endif
5144: #ifdef STRLEN
5145: !quotef &&
5146: #endif
5147: !listf) {
5148: putchar('\n');
5149: if (prompt1)
5150: putchar('\t');
5151: for (; *sp; sp++)
5152: if (sp[1] == '\b' && sp[2]) {
5153: putchar(sp[2]);
5154: sp += 2;
5155: } else if (*sp == '\t')
5156: putchar('\t');
5157: else if (*sp >= ' ')
5158: putchar(' ');
5159: ovp = 0;
5160: }
5161: #ifdef PARENS
5162: if (parenf && ovp && !listf) {
5163: putchar('\n');
5164: if (prompt1)
5165: putchar('\t');
5166: for (; *sp; sp++)
5167: if (n = paren(*sp)) {
5168: if (n < 0) {
5169: n = -n - 1;
5170: putparen(parenc[n]--);
5171: } else
5172: putparen(++parenc[--n]);
5173: } else if (*sp == '\t' || *sp >= ' ')
5174: putchar(*sp == '\t'? '\t' : ' ');
5175: ovp = 0;
5176: }
5177: #endif
5178: #ifdef STRLEN
5179: if (quotef && ovp && !listf) {
5180: s = null;
5181: n = 0;
5182: ovp = 0;
5183: putchar('\n');
5184: if (prompt1)
5185: putchar('\t');
5186: for (; *sp; sp++) {
5187: /* if (n == 0 && (*sp == '"' || *sp == '\'') || */
5188: if (n == 0 && (quotec? *sp == (ovp?
5189: quotec : quotec2) : *sp == '"' || *sp == '\'') ||
5190: *sp == n) {
5191: if (ovp) {
5192: ovp = 0;
5193: goto not;
5194: }
5195: if (n)
5196: n = 0;
5197: else {
5198: s = sp++;
5199: n = 0;
5200: while (*sp && *sp != *s) {
5201: if (*sp == '\\') {
5202: if ('0' <= *++sp && *sp <= '7') {
5203: if ('0' <= *++sp && *sp <= '7')
5204: if ('0' <= *++sp && *sp <= '7')
5205: sp++;
5206: } else
5207: sp++;
5208: } else
5209: sp++;
5210: n++;
5211: }
5212: sp = s;
5213: s = &"00000"[5];
5214: do {
5215: *--s = n % 10 + '0';
5216: } while (n /= 10);
5217: n = *sp;
5218: }
5219: }
5220: not: if (*s)
5221: putchar(*s++);
5222: else
5223: putchar(*sp == '\t'? '\t' : ' ');
5224: if (*sp == '\\')
5225: ovp ^= 01;
5226: }
5227: ovp = 0;
5228: }
5229: #endif
5230: putchar('\n');
5231: }
5232:
5233: puts2(as) {
5234: register char *sp;
5235:
5236: sp = as;
5237: while (*sp)
5238: putchar(*sp++);
5239: }
5240:
5241: #ifdef CKPT
5242: recover() {
5243: extern etext;
5244: register filedes f;
5245: register char *p;
5246: register func savint, savqit;
5247: int n;
5248:
5249: savint = signal(SIGINT, 1);
5250: savqit = signal(SIGQIT, 1);
5251: if ((f = open(cfname, 0)) < 0 ||
5252: read(f, &n, sizeof n) != sizeof n) {
5253: n = 67;
5254: goto cerror;
5255: }
5256: p = &etext;
5257: if (brk(p + n) == -1) {
5258: n = 67;
5259: goto cerror;
5260: }
5261: #ifdef pdp11 /* 16 bit byte count only */
5262: if (n < 0) {
5263: if (read(f, p, 32256) != 32256) {
5264: n = 67;
5265: goto cerror;
5266: }
5267: n -= 32256; /* 63 blocks, since 64 is < 0 */
5268: p += 32256;
5269: }
5270: #endif
5271: if (read(f, p, n) != n ||
5272: (tfile = open(tfname, 2)) < 0)
5273: n = 67;
5274: else
5275: n = 0;
5276: recovry = 1; /* overwritten by reading data space */
5277: cerror:
5278: if (n) {
5279: puts(errtext[n]);
5280: exit(1);
5281: }
5282: if (f > 0)
5283: close(f);
5284:
5285: /*
5286: * "initialize" special stuff to restore order
5287: */
5288:
5289: globp = 0;
5290: io = 0;
5291: io_w = 0;
5292: #ifdef HELP
5293: doc = 0;
5294: #endif
5295: #ifdef USE
5296: alt = 0;
5297: #endif
5298: #ifdef AGAIN
5299: agf = 0;
5300: agp = 0;
5301: #endif
5302: #ifdef EOL
5303: prompt3 = 1;
5304: #endif
5305: #ifdef PIPE
5306: if (pfile) {
5307: unlink(pfname);
5308: pfile = 0;
5309: }
5310: #endif
5311:
5312: signal(SIGINT, savint);
5313: signal(SIGQIT, savqit);
5314: }
5315: #endif
5316:
5317: reverse(aa1, aa2) {
5318: register linep *a1, *a2, t;
5319:
5320: a1 = aa1;
5321: a2 = aa2;
5322: for ever {
5323: t = *--a2;
5324: if (a2 <= a1)
5325: return;
5326: *a2 = *a1;
5327: *a1++ = t;
5328: }
5329: }
5330:
5331: #ifdef XDEL
5332: saveline() {
5333: register linep *a1, *a2, *bp;
5334: register nl, tl;
5335:
5336: a1 = addr1;
5337: a2 = addr2;
5338: ndeleted = a2 - a1 + 1;
5339: tl = tline;
5340: #ifdef DEBUG
5341: if (tflg)
5342: printf("saveline:\t%o\n", tl);
5343: #endif
5344: bp = getblock(tl, WRITE);
5345: #ifdef HUGE
5346: if (hugef2) {
5347: hugef2 = 0;
5348: tl = (tl >> 1) & _6[hugef];
5349: }
5350: tl &= _1[hugef];
5351: #else
5352: tl &= _1;
5353: #endif
5354: nl = nleft / sizeof(linep);
5355: while (a1 <= a2) {
5356: *bp++ = *a1++;
5357: if (--nl <= 0) {
5358: #ifdef HUGE
5359: bp = getblock(tl += _2[hugef], WRITE);
5360: if (hugef2) {
5361: hugef2 = 0;
5362: tl = (tl >> 1) & _6[hugef];
5363: }
5364: #else
5365: bp = getblock(tl += _2, WRITE);
5366: #endif
5367: nl = nleft / sizeof(linep);
5368: }
5369: }
5370: deleted = tline;
5371: #ifdef HUGE
5372: tline += ((a2 - addr1 + 1) << (1 - hugef)) & _6[hugef];
5373: #else
5374: tline += ((a2 - addr1 + 1) << 1) & _6;
5375: #endif
5376: }
5377: #endif
5378:
5379: savemark(p1, p2)
5380: linep p1, p2;
5381: {
5382: register n;
5383: #ifdef HUGE
5384: register i;
5385:
5386: i = hugef ^ 01;
5387: p1 |= i;
5388: p2 |= i;
5389: #else
5390: p1 |= 01;
5391: p2 |= 01;
5392: #endif
5393: /* save "marks" on lines so marked */
5394: for (n = 0; n <= 'z' - 'a'; n++) {
5395: if (names[n] == 0) /* zap marks to deleted lines */
5396: continue;
5397: if (names[n] == p1)
5398: names[n] = p2;
5399: #ifdef EXTMARK
5400: if (names2[n] && names2[n] == p1)
5401: names2[n] = p2;
5402: #endif
5403: }
5404: #ifdef YINT
5405: /* don't lose "y+" line either */
5406: if (yplus == p1)
5407: yplus = p2;
5408: #endif
5409: #ifdef UNDO
5410: /* and remember the line for "undo" */
5411: undo_oldp = p1;
5412: undo_newp = p2;
5413: #endif
5414: }
5415:
5416: scopy(ass, ads)
5417: char *ass, *ads;
5418: {
5419: register char *p, *q;
5420:
5421: p = ass;
5422: q = ads;
5423: while (*q++ = *p++)
5424: ;
5425: return(ads);
5426: }
5427:
5428: setall() {
5429: if (addr2 == 0) {
5430: addr1 = zero + (zero != dol);
5431: addr2 = dol;
5432: }
5433: setdot();
5434: }
5435:
5436: setchar(adflt) {
5437: register charac c;
5438:
5439: if ((c = getchar()) == '\\')
5440: c = getchar();
5441: if (c < 0)
5442: errmsg(59);
5443: if (c == '\n')
5444: return(adflt);
5445: newline();
5446: return(c);
5447: }
5448:
5449: setdot() {
5450: if (addr2 == 0)
5451: addr1 = addr2 = dot;
5452: if (addr1 > addr2)
5453: errmsg(21);
5454: }
5455:
5456: setnoaddr() {
5457: if (addr2)
5458: errmsg(22);
5459: }
5460:
5461: setnum(adflt) {
5462: register n;
5463:
5464: white_space();
5465: n = adflt;
5466: if ('0' <= (peekc = getchar()) && peekc <= '9')
5467: n = getnum();
5468: newline();
5469: return(n);
5470: }
5471:
5472: #ifdef TABS
5473: settab(acs) {
5474: register *p, i, n;
5475:
5476: if (acs == 0) {
5477: maxtab = -1;
5478: n = TABS;
5479: p = tabs;
5480: while (--n >= 0)
5481: *p++ = 0;
5482: return;
5483: }
5484: i = 0;
5485: if (acs < 0) {
5486: acs = -acs;
5487: i++;
5488: }
5489: if (--acs < TABS * BPW) {
5490: p = &tabs[acs >> BPWC];
5491: *p |= 01 << (n = acs & BPWM);
5492: if (i) {
5493: *p ^= 01 << n;
5494: if (acs == maxtab) { /* find new maxtab */
5495: for (n = TABS - 1; n >= 0; --n)
5496: if (tabs[n >> BPWC] >> (n & BPWM) & 01)
5497: break;
5498: maxtab = n;
5499: }
5500: } else if (acs > maxtab)
5501: maxtab = acs;
5502: }
5503: }
5504: #endif
5505:
5506: shell() {
5507: #ifdef PIPE
5508: extern oil_spilled();
5509: #endif
5510: register pid, wpid;
5511: register linep *a;
5512: register dp, df, nopipe, c, e, savint, savqit;
5513: register linep *dest;
5514: int retcode, p[2];
5515:
5516: #ifdef PIPE
5517: dp = 0;
5518: df = 0;
5519: if (addr2) {
5520: #ifdef LOG
5521: ++logstats.lc_pipe;
5522: #endif
5523: dest = 0;
5524: nopipe = 0;
5525: if ((peekc = getchar()) == '|') {
5526: nonzero();
5527: peekc = 0;
5528: dp++;
5529: df++;
5530: #ifdef LOG
5531: --logstats.lc_pipe;
5532: ++logstats.lc_dpipe;
5533: #endif
5534: }
5535: if ((peekc = getchar()) == '>') {
5536: nonzero();
5537: #ifdef LOG
5538: --logstats.lc_pipe;
5539: ++logstats.lc_pto;
5540: #endif
5541: goto pi;
5542: } else if ((peekc = getchar()) == '<') {
5543: nopipe++;
5544: #ifdef LOG
5545: --logstats.lc_pipe;
5546: ++logstats.lc_pfrom;
5547: #endif
5548: pi: peekc = 0;
5549: dp++;
5550: dest = addr2;
5551: }
5552: if (dp && '0' <= (peekc = getchar()) && peekc <= '9') {
5553: c = getnum();
5554: dest = zero + c;
5555: if (dest < zero)
5556: dest = zero + 1;
5557: if (dest > dol)
5558: dest = dol;
5559: }
5560: }
5561: #ifdef LOG
5562: else
5563: ++logstats.lc_shell;
5564: #endif
5565: piperr = 0;
5566: if (!iflg)
5567: if (addr2) {
5568: savint = signal(SIGINT, oil_spilled);
5569: savqit = signal(SIGQIT, oil_spilled);
5570: } else {
5571: #endif
5572: savint = signal(SIGINT, 1);
5573: savqit = signal(SIGQIT, 1);
5574: #ifdef PIPE
5575: }
5576: if (addr2 && pipe(p) < 0) {
5577: c = 15;
5578: errm: if (!iflg) {
5579: signal(SIGINT, savint);
5580: signal(SIGQIT, savqit);
5581: }
5582: if (c)
5583: errmsg(c);
5584: error();
5585: }
5586: if (dp) {
5587: if ((pfile = create(pfname, LMODE)) < 0) {
5588: pfile = 0;
5589: c = 64;
5590: goto errm;
5591: }
5592: if ((io = open(pfname, 0)) < 0) {
5593: io = 0;
5594: c = 65;
5595: goto errm;
5596: }
5597: }
5598: #endif
5599: if ((pid = fork()) < 0) {
5600: #ifdef PIPE
5601: if (addr2) {
5602: close(p[0]);
5603: close(p[1]);
5604: }
5605: #endif
5606: c = 14;
5607: goto errm;
5608: }
5609: if (pid == 0) {
5610: /* kid */ if (!iflg) {
5611: /* kid */ signal(SIGHUP, 0);
5612: /* kid */ signal(SIGINT, 0);
5613: /* kid */ signal(SIGQIT, 0);
5614: /* kid */ }
5615: #ifdef PIPE
5616: /* kid */ if (addr2) {
5617: /* kid */ close(0);
5618: /* kid */ dup(p[0]);
5619: /* kid */ close(p[0]);
5620: /* kid */ close(p[1]);
5621: /* kid */ if (dp) {
5622: /* kid */ close(1);
5623: /* kid */ dup(pfile);
5624: /* kid */ close(pfile);
5625: /* kid */ }
5626: /* kid */ }
5627: #endif
5628: /* kid */ execl("/bin/sh", "!sh", "-t", 0);
5629: /* kid */ write(2, "No shell!\n", 10);
5630: /* kid */ exit(0177);
5631: }
5632: #ifdef CMDS
5633: if (cmd && !addr2)
5634: write(cmd, "<UNIX>\n", 7);
5635: #endif
5636: #ifdef PIPE
5637: if (addr2) {
5638: signal(SIGPIP, oil_spilled);
5639: close(p[0]);
5640: e = eflg2;
5641: eflg2++;
5642: fout = p[1];
5643: while ((c = getchar()) >= 0 && c != '\n')
5644: putchar(c);
5645: putchar('\n');
5646: if (!nopipe) {
5647: line_num = (a = addr1) - zero - aflg;
5648: do {
5649: if (pno >= 0)
5650: printlno(line_num++);
5651: puts(getline(*a++));
5652: } while (a <= addr2 && !piperr);
5653: }
5654: flush_buf();
5655: fout = 1;
5656: eflg2 = e;
5657: close(p[1]);
5658: if (!iflg) {
5659: signal(SIGINT, 1);
5660: signal(SIGQIT, 1);
5661: }
5662: }
5663: #endif
5664: while ((wpid = wait(&retcode)) != pid && wpid >= 0);
5665: #ifdef CMDS
5666: if (cmd)
5667: lseek(cmd, 0L, 2);
5668: #endif
5669: #ifdef PIPE
5670: if (addr2)
5671: signal(SIGPIP, 0);
5672: #endif
5673: if (c = retcode & 0177) {
5674: if (0 < c && c < NSTR && status[c])
5675: puts2(status[c]);
5676: else
5677: printf("signal %d", c);
5678: if (retcode & 0200)
5679: puts2(" -- core dumped");
5680: putchar(lastc = '\n');
5681: c = 0;
5682: goto errm;
5683: } else if (df && strict && retcode >> 8) {
5684: printf("exit status %d\n", retcode >> 8);
5685: c = 0;
5686: goto errm;
5687: }
5688: #ifdef PIPE
5689: else if (addr2) {
5690: if (piperr) {
5691: putsn(status[SIGPIP]);
5692: c = 0;
5693: goto errm;
5694: }
5695: if (dp) {
5696: if (df) {
5697: c = addr2 != dol;
5698: delete();
5699: if (dest == 0)
5700: dest = dot - c;
5701: } else if (dest == 0)
5702: dest = addr2;
5703: if (dest < zero)
5704: dest = zero;
5705: if (c = append(getfile, dest, 0, 0))
5706: text_modified++;
5707: if (prompt2)
5708: printf((curt? prcntu : errtext[55]),
5709: c, (c == 1? null : quote_s));
5710: close(io);
5711: io = 0;
5712: unlink(pfname);
5713: close(pfile);
5714: pfile = 0;
5715: }
5716: }
5717: #endif
5718: if (!iflg) {
5719: signal(SIGINT, savint);
5720: signal(SIGQIT, savqit);
5721: }
5722: if (!addr2)
5723: putsn("!");
5724: #ifdef CLEAR
5725: istty(1); /* in case bs1 changed */
5726: #endif
5727: }
5728:
5729: signals(ast)
5730: struct sigtab *ast;
5731: {
5732: register n;
5733: register struct sigtab *s;
5734:
5735: s = ast - 1;
5736: while (n = (++s)->s_sig)
5737: signal(n, s->s_func);
5738: }
5739:
5740: skip_rest() {
5741: register charac c;
5742:
5743: while ((c = getchar()) >= 0 && c != '\n');
5744: }
5745:
5746: substitute(inglob) {
5747: extern getsub();
5748: register linep *a1, p;
5749: register nl;
5750: register flag gsubf;
5751:
5752: gsubf = compsub(); /* 0 or 1 depending on 'g' */
5753: for (a1 = addr1; a1 <= addr2; a1++) {
5754: s_tmp = s_cnt;
5755: if (execute(0, a1) == 0)
5756: continue;
5757: inglob |= 01;
5758: dosub();
5759: if (gsubf)
5760: while (*loc2) {
5761: if (execute(1) == 0)
5762: break;
5763: dosub();
5764: }
5765: p = *a1;
5766: *a1 = putline();
5767: savemark(p, *a1);
5768: nl = append(getsub, a1, 0, 0);
5769: a1 += nl;
5770: addr2 += nl;
5771: }
5772: if (inglob == 0)
5773: errmsg(39);
5774: }
5775:
5776: #ifdef XED
5777: tack(aeof, aflag)
5778: char aeof;
5779: {
5780: register n;
5781: register char *p1, *p2;
5782: register linep *a;
5783: register charac c;
5784:
5785: nonzero();
5786: setdot();
5787: p1 = rhsbuf; /* i/TEXT screwed for long lines */
5788: while ((c = getchar()) != aeof && c != '\n') {
5789: if (c == '\\')
5790: if ((c = getchar()) == '\n')
5791: break;
5792: if (c < 0)
5793: errmsg(59);
5794: *p1++ = c;
5795: if (p1 >= &rhsbuf[LBSIZE / 2 - 2])
5796: errmsg(42);
5797: }
5798: if (*rhsbuf == 0)
5799: errmsg(27);
5800: if (c == '\n') {
5801: if (prompt2)
5802: pflag++;
5803: } else
5804: newline();
5805: if (p1 != rhsbuf)
5806: *p1 = 0;
5807: else
5808: while (*p1)
5809: p1++;
5810: n = p1 - rhsbuf;
5811: for (a = addr1; a <= addr2; a++) {
5812: getline(*a);
5813: for (p2 = linebuf; *p2; p2++);
5814: #ifndef ALLOC
5815: if (p2 + n >= &linebuf[LBSIZE / 2 - 2])
5816: #else
5817: if (p2 + n >= &linebuf[lbsize / 2 - 2])
5818: #endif
5819: errmsg(30);
5820: if (aflag) { /* $ */
5821: p1 = rhsbuf;
5822: while (*p2++ = *p1++);
5823: } else { /* ^ */
5824: p1 = p2 + n;
5825: *p1 = *p2;
5826: while (p2 > linebuf)
5827: *--p1 = *--p2;
5828: p1 = linebuf;
5829: p2 = rhsbuf;
5830: while (*p2)
5831: *p1++ = *p2++;
5832: }
5833: p2 = *a;
5834: *a = putline();
5835: savemark(p2, *a);
5836: }
5837: dot = addr2;
5838: return(addr2 - addr1 + 1);
5839: }
5840: #endif
5841:
5842: term() {
5843: signal(SIGTRM, 1);
5844: if (reading) {
5845: backup(TRM);
5846: if (fout != 1) {
5847: flush_buf();
5848: fout = 1;
5849: }
5850: puts2(errtext[58]);
5851: delexit(1);
5852: }
5853: termflg++;
5854: }
5855:
5856: tmpname(as, an)
5857: char *as;
5858: {
5859: register unsigned n;
5860: register char *p, c;
5861:
5862: p = as;
5863: n = an;
5864: while (*p)
5865: p++;
5866: while (--p >= as)
5867: if ((c = *p) == '0' || (c | 040) == 'x') {
5868: *p = n % 10 + '0';
5869: n /= 10;
5870: #ifdef CKPT
5871: tfnum = p - as;
5872: #endif
5873: }
5874: return(as);
5875: }
5876:
5877: #ifdef XDEL
5878: undelete() {
5879: register linep *a1, *a2, *bp;
5880: register tl, nl, num;
5881:
5882: if ((tl = deleted) == 0)
5883: errmsg(16);
5884: #ifdef DEBUG
5885: if (tflg)
5886: printf("undelete:\t%o\n", tl);
5887: #endif
5888: setdot();
5889: a1 = dol + 1;
5890: a2 = a1 + ndeleted;
5891: bp = addr2 + 1;
5892: if (dol + ndeleted > endcore) {
5893: num = ((ndeleted * 2) + 1023) & ~01777;
5894: if (sbrk(num) == -1)
5895: errmsg(33);
5896: endcore = (int)endcore + num;
5897: }
5898: while (a1 > bp)
5899: *--a2 = *--a1;
5900: dol += ndeleted;
5901: a1 = addr2 + 1;
5902: a2 = a1 + ndeleted;
5903: bp = getblock(tl, READ);
5904: #ifdef HUGE
5905: tl &= _1[hugef];
5906: #else
5907: tl &= _1;
5908: #endif
5909: nl = nleft / sizeof(linep);
5910: while (a1 < a2) {
5911: *a1++ = *bp++;
5912: if (--nl <= 0) {
5913: #ifdef HUGE
5914: bp = getblock(tl += _2[hugef], READ);
5915: #else
5916: bp = getblock(tl += _2, READ);
5917: #endif
5918: nl = nleft / sizeof(linep);
5919: }
5920: }
5921: dot = a2 - 1;
5922: return(ndeleted);
5923: }
5924: #endif
5925:
5926: #ifdef UNDO
5927: undo() {
5928: register linep *a, t, o;
5929:
5930: if (undo_newp == 0 || (a = findmark(undo_newp, 0)) == 0)
5931: errmsg(13);
5932: t = *a |
5933: #ifdef HUGE
5934: hugef ^
5935: #endif
5936: 01;
5937: o = undo_oldp;
5938: savemark(*a, o);
5939: *a = o;
5940: undo_newp = o;
5941: undo_oldp = t;
5942: dot = a;
5943: if (text_modified == 0)
5944: text_modified++;
5945: }
5946: #endif
5947:
5948: white_space() {
5949: register charac c;
5950:
5951: while ((c = getchar()) == ' ' || c == '\t');
5952: peekc = c;
5953: }
5954:
5955: wte(fd, buf, len)
5956: char buf[];
5957: {
5958: if (write(fd, buf, len) != len)
5959: errmsg(-32);
5960: }
5961:
5962: /*
5963: * as a prompt string
5964: * ay yes response, !no response
5965: * ad default (\n) response, <0 means no default allowed
5966: * aef end-of-file response
5967: */
5968: yes_no(as, ay, ad, aef)
5969: char *as;
5970: {
5971: register charac c, p;
5972: register n;
5973: register flag l;
5974:
5975: l = listf;
5976: listf = 0;
5977: p = peekc;
5978: peekc = 0;
5979: for ever {
5980: putchar('\n');
5981: puts2(as);
5982: puts2("? ");
5983: for (n = 0; n < 5; n++) {
5984: flush_buf();
5985: if ((c = getchar()) < 0) {
5986: putchar('\n');
5987: n = aef;
5988: goto ret;
5989: }
5990: if (c != '\n')
5991: skip_rest();
5992: else if (ad >= 0) {
5993: n = ad;
5994: goto ret;
5995: }
5996: if (c == 'y' || c == 'n') {
5997: n = ay;
5998: if (c != 'y')
5999: n ^= 01;
6000: goto ret;
6001: }
6002: puts2("yes or no? ");
6003: }
6004: }
6005: ret:
6006: listf = l;
6007: peekc = p;
6008: return(n);
6009: }