fix the process linkages, but was that fd's got closed more than
[unix-history] / usr / src / usr.bin / sed / process.c
index a9fee4b..9892d18 100644 (file)
@@ -10,7 +10,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)process.c  5.1 (Berkeley) %G%";
+static char sccsid[] = "@(#)process.c  5.5 (Berkeley) %G%";
 #endif /* not lint */
 
 #include <sys/types.h>
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -49,9 +49,8 @@ static inline int      applies __P((struct s_command *));
 static void             cspace __P((SPACE *, char *, size_t, int));
 static void             flush_appends __P((void));
 static void             lputs __P((char *));
 static void             cspace __P((SPACE *, char *, size_t, int));
 static void             flush_appends __P((void));
 static void             lputs __P((char *));
-static inline int       match __P((struct s_addr *));
-static int              regexec_check __P((regex_t *, const char *,
-                           int, regmatch_t[], int));
+static inline int       regexec_e __P((regex_t *, const char *,
+                           size_t, regmatch_t [], int));
 static void             regsub __P((regmatch_t *, char *, char *, SPACE *));
 static int              substitute __P((struct s_command *));
 
 static void             regsub __P((regmatch_t *, char *, char *, SPACE *));
 static int              substitute __P((struct s_command *));
 
@@ -64,6 +63,9 @@ static int sdone;             /* If any substitutes since last line input. */
                                /* Iov structure for 'w' commands. */
 static struct iovec iov[2] = { NULL, 0, "\n", 1 };
 
                                /* Iov structure for 'w' commands. */
 static struct iovec iov[2] = { NULL, 0, "\n", 1 };
 
+static regex_t *defpreg;
+static size_t defnmatch;
+
 void
 process()
 {
 void
 process()
 {
@@ -106,16 +108,14 @@ redirect:
                        case 'd':
                                if (pd)
                                        goto new;
                        case 'd':
                                if (pd)
                                        goto new;
-                               psl = 0;
-                               ps[0] = '\0';
+                               pd = 1;
                                goto new;
                        case 'D':
                                if (pd)
                                        goto new;
                                goto new;
                        case 'D':
                                if (pd)
                                        goto new;
-                               if ((p = strchr(ps, '\n')) == NULL) {
-                                       psl = 0;
-                                       ps[0] = '\0';
-                               } else {
+                               if ((p = strchr(ps, '\n')) == NULL)
+                                       pd = 1;
+                               else {
                                        psl -= (p - ps) - 1;
                                        memmove(ps, p + 1, psl);
                                }
                                        psl -= (p - ps) - 1;
                                        memmove(ps, p + 1, psl);
                                }
@@ -241,6 +241,15 @@ new:               if (!nflag && !pd)
        } /* for all lines */
 }
 
        } /* for all lines */
 }
 
+/*
+ * TRUE if the address passed matches the current program state
+ * (lastline, linenumber, ps).
+ */
+#define        MATCH(a)                                                        \
+       (a)->type == AT_RE ?                                            \
+           regexec_e((a)->u.r, ps, 0, NULL, 0) :                       \
+           (a)->type == AT_LINE ? linenum == (a)->u.l : lastline
+
 /*
  * Return TRUE if the command applies to the current line.  Sets the inrange
  * flag to process ranges.  Interprets the non-select (``!'') flag.
 /*
  * Return TRUE if the command applies to the current line.  Sets the inrange
  * flag to process ranges.  Interprets the non-select (``!'') flag.
@@ -256,12 +265,12 @@ applies(cp)
                r = 1;
        else if (cp->a2)
                if (cp->inrange) {
                r = 1;
        else if (cp->a2)
                if (cp->inrange) {
-                       if (match(cp->a2)) {
+                       if (MATCH(cp->a2)) {
                                cp->inrange = 0;
                                lastaddr = 1;
                        }
                        r = 1;
                                cp->inrange = 0;
                                lastaddr = 1;
                        }
                        r = 1;
-               } else if (match(cp->a1)) {
+               } else if (MATCH(cp->a1)) {
                        /*
                         * If the second address is a number less than or
                         * equal to the line number first selected, only
                        /*
                         * If the second address is a number less than or
                         * equal to the line number first selected, only
@@ -277,38 +286,10 @@ applies(cp)
                } else
                        r = 0;
        else
                } else
                        r = 0;
        else
-               r = match(cp->a1);
+               r = MATCH(cp->a1);
        return (cp->nonsel ? ! r : r);
 }
 
        return (cp->nonsel ? ! r : r);
 }
 
-/*
- * Return TRUE if the address passed matches the current program
- * state (linenumber, ps, lastline)
- */
-static int inline
-match(a)
-       struct s_addr *a;
-{
-       int eval;
-
-       switch (a->type) {
-       case AT_RE:
-               switch (eval = regexec(a->u.r, ps, 0, NULL, 0)) {
-               case 0:
-                       return (1);
-               case REG_NOMATCH:
-                       return (0);
-               default:
-                       err(FATAL, "RE error: %s", strregerror(eval, a->u.r));
-               }
-       case AT_LINE:
-               return (linenum == a->u.l);
-       case AT_LAST:
-               return (lastline);
-       }
-       /* NOTREACHED */
-}
-
 /*
  * substitute --
  *     Do substitutions in the pattern space.  Currently, we build a
 /*
  * substitute --
  *     Do substitutions in the pattern space.  Currently, we build a
@@ -320,14 +301,23 @@ substitute(cp)
        struct s_command *cp;
 {
        SPACE tspace;
        struct s_command *cp;
 {
        SPACE tspace;
-       static regex_t *re;
+       regex_t *re;
+       size_t nsub;
        int n, re_off;
        char *endp, *s;
 
        s = ps;
        int n, re_off;
        char *endp, *s;
 
        s = ps;
-       re = &cp->u.s->re;
-       if (regexec_check(re,
-           s, re->re_nsub + 1, cp->u.s->pmatch, 0) == REG_NOMATCH)
+       re = cp->u.s->re;
+       if (re == NULL) {
+               nsub = 1;
+               if (defpreg != NULL && cp->u.s->maxbref > defnmatch) {
+                       linenum = cp->u.s->linenum;
+                       err(COMPILE, "\\%d not defined in the RE",
+                           cp->u.s->maxbref);
+               }
+       } else
+               nsub = re->re_nsub + 1;
+       if (!regexec_e(re, s, nsub, cp->u.s->pmatch, 0))
                return (0);
 
        SS.len = 0;                             /* Clean substitute space. */
                return (0);
 
        SS.len = 0;                             /* Clean substitute space. */
@@ -345,16 +335,15 @@ substitute(cp)
                        regsub(cp->u.s->pmatch, s, cp->u.s->new, &SS);
                        /* Move past this match. */
                        s += cp->u.s->pmatch[0].rm_eo;
                        regsub(cp->u.s->pmatch, s, cp->u.s->new, &SS);
                        /* Move past this match. */
                        s += cp->u.s->pmatch[0].rm_eo;
-               } while(regexec_check(re, s, re->re_nsub + 1,
-                   cp->u.s->pmatch, REG_NOTBOL) != REG_NOMATCH);
+               } while(regexec_e(re, s, nsub, cp->u.s->pmatch, REG_NOTBOL));
                /* Copy trailing retained string. */
                cspace(&SS, s, strlen(s), 0);
                break;
        default:                                /* Nth occurrence */
                while (--n) {
                        s += cp->u.s->pmatch[0].rm_eo;
                /* Copy trailing retained string. */
                cspace(&SS, s, strlen(s), 0);
                break;
        default:                                /* Nth occurrence */
                while (--n) {
                        s += cp->u.s->pmatch[0].rm_eo;
-                       if (regexec_check(re, s, re->re_nsub + 1,
-                           cp->u.s->pmatch, REG_NOTBOL) == REG_NOMATCH)
+                       if (!regexec_e(re,
+                           s, nsub, cp->u.s->pmatch, REG_NOTBOL))
                                return (0);
                }
                /* FALLTHROUGH */
                                return (0);
                }
                /* FALLTHROUGH */
@@ -479,27 +468,33 @@ lputs(s)
                err(FATAL, "stdout: %s", strerror(errno ? errno : EIO));
 }
 
                err(FATAL, "stdout: %s", strerror(errno ? errno : EIO));
 }
 
-/*
- * Regexec with checking for errors
- */
-static int
-regexec_check(preg, string, nmatch, pmatch, eflags)
+static inline int
+regexec_e(preg, string, nmatch, pmatch, eflags)
        regex_t *preg;
        const char *string;
        regex_t *preg;
        const char *string;
-       int nmatch;
+       size_t nmatch;
        regmatch_t pmatch[];
        int eflags;
 {
        int eval;
 
        regmatch_t pmatch[];
        int eflags;
 {
        int eval;
 
-       switch (eval = regexec(preg, string, nmatch, pmatch, eflags)) {
+       if (preg == NULL) {
+               if (defpreg == NULL)
+                       err(FATAL, "first RE may not be empty");
+       } else {
+               defpreg = preg;
+               defnmatch = nmatch;
+       }
+
+       eval = regexec(defpreg,
+           string, pmatch == NULL ? 0 : defnmatch, pmatch, eflags);
+       switch(eval) {
        case 0:
        case 0:
-               return (0);
+               return (1);
        case REG_NOMATCH:
        case REG_NOMATCH:
-               return (REG_NOMATCH);
-       default:
-               err(FATAL, "RE error: %s", strregerror(eval, preg));
+               return (0);
        }
        }
+       err(FATAL, "RE error: %s", strregerror(eval, defpreg));
        /* NOTREACHED */
 }
 
        /* NOTREACHED */
 }
 
@@ -609,10 +604,12 @@ cfclose(cp)
                        if (cp->u.s->wfd != -1 && close(cp->u.s->wfd))
                                err(FATAL,
                                    "%s: %s", cp->u.s->wfile, strerror(errno));
                        if (cp->u.s->wfd != -1 && close(cp->u.s->wfd))
                                err(FATAL,
                                    "%s: %s", cp->u.s->wfile, strerror(errno));
+                       cp->u.s->wfd = -1;
                        break;
                case 'w':
                        if (cp->u.fd != -1 && close(cp->u.fd))
                                err(FATAL, "%s: %s", cp->t, strerror(errno));
                        break;
                case 'w':
                        if (cp->u.fd != -1 && close(cp->u.fd))
                                err(FATAL, "%s: %s", cp->t, strerror(errno));
+                       cp->u.fd = -1;
                        break;
                case '{':
                        cfclose(cp->u.c);
                        break;
                case '{':
                        cfclose(cp->u.c);