date and time created 85/05/31 12:51:02 by bloom
[unix-history] / usr / src / usr.bin / ex / ex_subr.c
index a5ccf85..91fbbaf 100644 (file)
@@ -1,4 +1,5 @@
-/* Copyright (c) 1979 Regents of the University of California */
+/* Copyright (c) 1981 Regents of the University of California */
+static char *sccsid = "@(#)ex_subr.c   5.1.1.1 %G%";
 #include "ex.h"
 #include "ex_re.h"
 #include "ex_tty.h"
 #include "ex.h"
 #include "ex_re.h"
 #include "ex_tty.h"
@@ -56,6 +57,21 @@ column(cp)
        return (qcolumn(cp, (char *) 0));
 }
 
        return (qcolumn(cp, (char *) 0));
 }
 
+/*
+ * Ignore a comment to the end of the line.
+ * This routine eats the trailing newline so don't call newline().
+ */
+comment()
+{
+       register int c;
+
+       do {
+               c = getchar();
+       } while (c != '\n' && c != EOF);
+       if (c == EOF)
+               ungetchar(c);
+}
+
 Copy(to, from, size)
        register char *from, *to;
        register int size;
 Copy(to, from, size)
        register char *from, *to;
        register int size;
@@ -179,6 +195,8 @@ ignnEOF()
 
        if (c == EOF)
                ungetchar(c);
 
        if (c == EOF)
                ungetchar(c);
+       else if (c=='"')
+               comment();
 }
 
 iswhite(c)
 }
 
 iswhite(c)
@@ -316,10 +334,14 @@ mesg(str)
 
 /*VARARGS2*/
 merror(seekpt, i)
 
 /*VARARGS2*/
 merror(seekpt, i)
-#ifdef lint
+#ifdef VMUNIX
        char *seekpt;
 #else
        char *seekpt;
 #else
+# ifdef lint
+       char *seekpt;
+# else
        int seekpt;
        int seekpt;
+# endif
 #endif
        int i;
 {
 #endif
        int i;
 {
@@ -330,7 +352,7 @@ merror(seekpt, i)
        merror1(seekpt);
        if (*cp == '\n')
                putnl(), cp++;
        merror1(seekpt);
        if (*cp == '\n')
                putnl(), cp++;
-       if (inopen && CE)
+       if (inopen > 0 && CE)
                vclreol();
        if (SO && SE)
                putpad(SO);
                vclreol();
        if (SO && SE)
                putpad(SO);
@@ -340,16 +362,24 @@ merror(seekpt, i)
 }
 
 merror1(seekpt)
 }
 
 merror1(seekpt)
-#ifdef lint
+#ifdef VMUNIX
        char *seekpt;
 #else
        char *seekpt;
 #else
+# ifdef lint
+       char *seekpt;
+# else
        int seekpt;
        int seekpt;
+# endif
 #endif
 {
 
 #endif
 {
 
+#ifdef VMUNIX
+       strcpy(linebuf, seekpt);
+#else
        lseek(erfile, (long) seekpt, 0);
        if (read(erfile, linebuf, 128) < 2)
                CP(linebuf, "ERROR");
        lseek(erfile, (long) seekpt, 0);
        if (read(erfile, linebuf, 128) < 2)
                CP(linebuf, "ERROR");
+#endif
 }
 
 morelines()
 }
 
 morelines()
@@ -425,13 +455,15 @@ putmk1(addr, n)
        int n;
 {
        register line *markp;
        int n;
 {
        register line *markp;
+       register oldglobmk;
 
 
+       oldglobmk = *addr & 1;
        *addr &= ~1;
        for (markp = (anymarks ? names : &names['z'-'a'+1]);
          markp <= &names['z'-'a'+1]; markp++)
                if (*markp == *addr)
                        *markp = n;
        *addr &= ~1;
        for (markp = (anymarks ? names : &names['z'-'a'+1]);
          markp <= &names['z'-'a'+1]; markp++)
                if (*markp == *addr)
                        *markp = n;
-       *addr = n;
+       *addr = n | oldglobmk;
 }
 
 char *
 }
 
 char *
@@ -498,12 +530,18 @@ save(a1, a2)
 {
        register int more;
 
 {
        register int more;
 
+       if (!FIXUNDO)
+               return;
+#ifdef TRACE
+       if (trace)
+               vudump("before save");
+#endif
        undkind = UNDNONE;
        undadot = dot;
        more = (a2 - a1 + 1) - (unddol - dol);
        while (more > (endcore - truedol))
                if (morelines() < 0)
        undkind = UNDNONE;
        undadot = dot;
        more = (a2 - a1 + 1) - (unddol - dol);
        while (more > (endcore - truedol))
                if (morelines() < 0)
-                       error("Out of memory@saving lines for undo - try using ed or re");
+                       error("Out of memory@saving lines for undo - try using ed");
        if (more)
                (*(more > 0 ? copywR : copyw))(unddol + more + 1, unddol + 1,
                    (truedol - unddol));
        if (more)
                (*(more > 0 ? copywR : copyw))(unddol + more + 1, unddol + 1,
                    (truedol - unddol));
@@ -514,6 +552,10 @@ save(a1, a2)
        unddel = a1 - 1;
        undap1 = a1;
        undap2 = a2 + 1;
        unddel = a1 - 1;
        undap1 = a1;
        undap2 = a2 + 1;
+#ifdef TRACE
+       if (trace)
+               vudump("after save");
+#endif
 }
 
 save12()
 }
 
 save12()
@@ -577,58 +619,6 @@ smerror(seekpt, cp)
                putpad(SE);
 }
 
                putpad(SE);
 }
 
-#define        std_nerrs (sizeof std_errlist / sizeof std_errlist[0])
-
-#define        error(i)        i
-
-#ifdef lint
-char   *std_errlist[] = {
-#else
-short  std_errlist[] = {
-#endif
-       error("Error 0"),
-       error("Not super-user"),
-       error("No such file or directory"),
-       error("No such process"),
-       error("Interrupted system call"),
-       error("Physical I/O error"),
-       error("No such device or address"),
-       error("Argument list too long"),
-       error("Exec format error"),
-       error("Bad file number"),
-       error("No children"),
-       error("No more processes"),
-       error("Not enough core"),
-       error("Permission denied"),
-       error("Bad address"),
-       error("Block device required"),
-       error("Mount device busy"),
-       error("File exists"),
-       error("Cross-device link"),
-       error("No such device"),
-       error("Not a directory"),
-       error("Is a directory"),
-       error("Invalid argument"),
-       error("File table overflow"),
-       error("Too many open files"),
-       error("Not a typewriter"),
-       error("Text file busy"),
-       error("File too large"),
-       error("No space left on device"),
-       error("Illegal seek"),
-       error("Read-only file system"),
-       error("Too many links"),
-       error("Broken pipe")
-#ifndef QUOTA
-       , error("Math argument")
-       , error("Result too large")
-#else
-       , error("Quota exceeded")
-#endif
-};
-
-#undef error
-
 char *
 strend(cp)
        register char *cp;
 char *
 strend(cp)
        register char *cp;
@@ -649,15 +639,36 @@ strcLIN(dp)
 syserror()
 {
        register int e = errno;
 syserror()
 {
        register int e = errno;
+       extern int sys_nerr;
+       extern char *sys_errlist[];
 
        dirtcnt = 0;
        putchar(' ');
 
        dirtcnt = 0;
        putchar(' ');
-       if (e >= 0 && errno <= std_nerrs)
-               error(std_errlist[e]);
+       if (e >= 0 && e <= sys_nerr)
+               error(sys_errlist[e]);
        else
                error("System error %d", e);
 }
 
        else
                error("System error %d", e);
 }
 
+/*
+ * Return the column number that results from being in column col and
+ * hitting a tab, where tabs are set every ts columns.  Work right for
+ * the case where col > COLUMNS, even if ts does not divide COLUMNS.
+ */
+tabcol(col, ts)
+int col, ts;
+{
+       int offset, result;
+
+       if (col >= COLUMNS) {
+               offset = COLUMNS * (col/COLUMNS);
+               col -= offset;
+       } else
+               offset = 0;
+       result = col + ts - (col % ts) + offset;
+       return (result);
+}
+
 char *
 vfindcol(i)
        int i;
 char *
 vfindcol(i)
        int i;
@@ -742,3 +753,184 @@ markit(addr)
                markDOT();
 }
 
                markDOT();
 }
 
+/*
+ * The following code is defensive programming against a bug in the
+ * pdp-11 overlay implementation.  Sometimes it goes nuts and asks
+ * for an overlay with some garbage number, which generates an emt
+ * trap.  This is a less than elegant solution, but it is somewhat
+ * better than core dumping and losing your work, leaving your tty
+ * in a weird state, etc.
+ */
+int _ovno;
+onemt()
+{
+       int oovno;
+
+       signal(SIGEMT, onemt);
+       oovno = _ovno;
+       /* 2 and 3 are valid on 11/40 type vi, so */
+       if (_ovno < 0 || _ovno > 3)
+               _ovno = 0;
+       error("emt trap, _ovno is %d @ - try again");
+}
+
+/*
+ * When a hangup occurs our actions are similar to a preserve
+ * command.  If the buffer has not been [Modified], then we do
+ * nothing but remove the temporary files and exit.
+ * Otherwise, we sync the temp file and then attempt a preserve.
+ * If the preserve succeeds, we unlink our temp files.
+ * If the preserve fails, we leave the temp files as they are
+ * as they are a backup even without preservation if they
+ * are not removed.
+ */
+onhup()
+{
+
+       /*
+        * USG tty driver can send multiple HUP's!!
+        */
+       signal(SIGINT, SIG_IGN);
+       signal(SIGHUP, SIG_IGN);
+       if (chng == 0) {
+               cleanup(1);
+               exit(0);
+       }
+       if (setexit() == 0) {
+               if (preserve()) {
+                       cleanup(1);
+                       exit(0);
+               }
+       }
+       exit(1);
+}
+
+/*
+ * An interrupt occurred.  Drain any output which
+ * is still in the output buffering pipeline.
+ * Catch interrupts again.  Unless we are in visual
+ * reset the output state (out of -nl mode, e.g).
+ * Then like a normal error (with the \n before Interrupt
+ * suppressed in visual mode).
+ */
+onintr()
+{
+
+#ifndef CBREAK
+       signal(SIGINT, onintr);
+#else
+       signal(SIGINT, inopen ? vintr : onintr);
+#endif
+       alarm(0);       /* in case we were called from map */
+       draino();
+       if (!inopen) {
+               pstop();
+               setlastchar('\n');
+#ifdef CBREAK
+       }
+#else
+       } else
+               vraw();
+#endif
+       error("\nInterrupt" + inopen);
+}
+
+/*
+ * If we are interruptible, enable interrupts again.
+ * In some critical sections we turn interrupts off,
+ * but not very often.
+ */
+setrupt()
+{
+
+       if (ruptible) {
+#ifndef CBREAK
+               signal(SIGINT, onintr);
+#else
+               signal(SIGINT, inopen ? vintr : onintr);
+#endif
+#ifdef SIGTSTP
+               if (dosusp)
+                       signal(SIGTSTP, onsusp);
+#endif
+       }
+}
+
+preserve()
+{
+
+#ifdef VMUNIX
+       tflush();
+#endif
+       synctmp();
+       pid = fork();
+       if (pid < 0)
+               return (0);
+       if (pid == 0) {
+               close(0);
+               dup(tfile);
+               execl(EXPRESERVE, "expreserve", (char *) 0);
+               exit(1);
+       }
+       waitfor();
+       if (rpid == pid && status == 0)
+               return (1);
+       return (0);
+}
+
+#ifndef V6
+exit(i)
+       int i;
+{
+
+# ifdef TRACE
+       if (trace)
+               fclose(trace);
+# endif
+       _exit(i);
+}
+#endif
+
+#ifdef SIGTSTP
+/*
+ * We have just gotten a susp.  Suspend and prepare to resume.
+ */
+onsusp()
+{
+       ttymode f;
+       int omask;
+       struct winsize win;
+
+       f = setty(normf);
+       vnfl();
+       putpad(TE);
+       flush();
+
+       (void) sigsetmask(0);
+       signal(SIGTSTP, SIG_DFL);
+       kill(0, SIGTSTP);
+
+       /* the pc stops here */
+
+       signal(SIGTSTP, onsusp);
+       vcontin(0);
+       setty(f);
+       if (!inopen)
+               error(0);
+       else {
+               if (ioctl(0, TIOCGWINSZ, &win) >= 0)
+                       if (win.ws_row != winsz.ws_row ||
+                           win.ws_col != winsz.ws_col)
+                               winch();
+               if (vcnt < 0) {
+                       vcnt = -vcnt;
+                       if (state == VISUAL)
+                               vclear();
+                       else if (state == CRTOPEN)
+                               vcnt = 0;
+               }
+               vdirty(0, LINES);
+               vrepaint(cursor);
+       }
+}
+#endif