perl 4.0 patch 14: patch #11, continued
[p5sagit/p5-mst-13.2.git] / toke.c
diff --git a/toke.c b/toke.c
index 77c9dee..d46a960 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -1,11 +1,24 @@
-/* $Header: toke.c,v 4.0 91/03/20 01:42:14 lwall Locked $
+/* $RCSfile: toke.c,v $$Revision: 4.0.1.3 $$Date: 91/06/10 01:32:26 $
  *
- *    Copyright (c) 1989, Larry Wall
+ *    Copyright (c) 1991, Larry Wall
  *
- *    You may distribute under the terms of the GNU General Public License
- *    as specified in the README file that comes with the perl 3.0 kit.
+ *    You may distribute under the terms of either the GNU General Public
+ *    License or the Artistic License, as specified in the README file.
  *
  * $Log:       toke.c,v $
+ * Revision 4.0.1.3  91/06/10  01:32:26  lwall
+ * patch10: m'$foo' now treats string as single quoted
+ * patch10: certain pattern optimizations were botched
+ * 
+ * Revision 4.0.1.2  91/06/07  12:05:56  lwall
+ * patch4: new copyright notice
+ * patch4: debugger lost track of lines in eval
+ * patch4: //o and s///o now optimize themselves fully at runtime
+ * patch4: added global modifier for pattern matches
+ * 
+ * Revision 4.0.1.1  91/04/12  09:18:18  lwall
+ * patch1: perl -de "print" wouldn't stop at the first statement
+ * 
  * Revision 4.0  91/03/20  01:42:14  lwall
  * 4.0 baseline.
  * 
 #include <sys/file.h>
 #endif
 
+#ifdef f_next
+#undef f_next
+#endif
+
 /* which backslash sequences to keep in m// or s// */
 
 static char *patleave = "\\.^$@dDwWsSbB+*?|()-nrtf0123456789[{]}";
@@ -74,7 +91,7 @@ void checkcomma();
 /* This does similarly for list operators, merely by pretending that the
  * paren came before the listop rather than after.
  */
-#define LOP(f) return(*s == '(' || (s = skipspace(s), *s == '(') ? \
+#define LOP(f) return(CLINE, *s == '(' || (s = skipspace(s), *s == '(') ? \
        (*s = META('('), bufptr = oldbufptr, '(') : \
        (yylval.ival=f,expectterm = TRUE,bufptr = s,(int)LISTOP))
 /* grandfather return to old style */
@@ -118,6 +135,7 @@ lop(f,s)
 int f;
 char *s;
 {
+    CLINE;
     if (*s != '(')
        s = skipspace(s);
     if (*s == '(') {
@@ -322,13 +340,6 @@ yylex()
                s++;
            if (s < d)
                s++;
-           if (perldb) {
-               STR *str = Str_new(85,0);
-
-               str_nset(str,linestr->str_ptr, s - linestr->str_ptr);
-               astore(stab_xarray(curcmd->c_filestab),(int)curcmd->c_line,str);
-               str_chop(linestr, s);
-           }
            if (in_format) {
                bufptr = s;
                yylval.formval = load_format();
@@ -943,7 +954,7 @@ yylex()
        if (strEQ(d,"oct"))
            UNI(O_OCT);
        if (strEQ(d,"opendir"))
-           FOP2(O_OPENDIR);
+           FOP2(O_OPEN_DIR);
        break;
     case 'p': case 'P':
        SNARFWORD;
@@ -1413,7 +1424,8 @@ char *dest;
 }
 
 STR *
-scanconst(string,len)
+scanconst(spat,string,len)
+SPAT *spat;
 char *string;
 int len;
 {
@@ -1421,10 +1433,13 @@ int len;
     register char *t;
     register char *d;
     register char *e;
+    char *origstring = string;
+    static char *vert = "|";
 
-    if (index(string,'|')) {
+    if (ninstr(string, string+len, vert, vert+1))
        return Nullstr;
-    }
+    if (*string == '^')
+       string++, len--;
     retstr = Str_new(86,len);
     str_nset(retstr,string,len);
     t = str_get(retstr);
@@ -1484,6 +1499,12 @@ int len;
     }
     *d = '\0';
     retstr->str_cur = d - t;
+    if (d == t+len)
+       spat->spat_flags |= SPAT_ALL;
+    if (*origstring != '^')
+       spat->spat_flags |= SPAT_SCANFIRST;
+    spat->spat_short = retstr;
+    spat->spat_slen = d - t;
     return retstr;
 }
 
@@ -1497,6 +1518,7 @@ register char *s;
     int len;
     SPAT savespat;
     STR *str = Str_new(93,0);
+    char delim;
 
     Newz(801,spat,1,SPAT);
     spat->spat_next = curstash->tbl_spatroot;  /* link into spat list */
@@ -1521,8 +1543,8 @@ register char *s;
        yylval.arg = Nullarg;
        return s;
     }
-    s++;
-    while (*s == 'i' || *s == 'o') {
+    delim = *s++;
+    while (*s == 'i' || *s == 'o' || *s == 'g') {
        if (*s == 'i') {
            s++;
            sawi = TRUE;
@@ -1532,10 +1554,18 @@ register char *s;
            s++;
            spat->spat_flags |= SPAT_KEEP;
        }
+       if (*s == 'g') {
+           s++;
+           spat->spat_flags |= SPAT_GLOBAL;
+       }
     }
     len = str->str_cur;
     e = str->str_ptr + len;
-    for (d = str->str_ptr; d < e; d++) {
+    if (delim == '\'')
+       d = e;
+    else
+       d = str->str_ptr;
+    for (; d < e; d++) {
        if (*d == '\\')
            d++;
        else if ((*d == '$' && d[1] && d[1] != '|' && d[1] != ')') ||
@@ -1571,23 +1601,7 @@ register char *s;
 #else
        (void)bcopy((char *)spat, (char *)&savespat, sizeof(SPAT));
 #endif
-    if (*str->str_ptr == '^') {
-       spat->spat_short = scanconst(str->str_ptr+1,len-1);
-       if (spat->spat_short) {
-           spat->spat_slen = spat->spat_short->str_cur;
-           if (spat->spat_slen == len - 1)
-               spat->spat_flags |= SPAT_ALL;
-       }
-    }
-    else {
-       spat->spat_flags |= SPAT_SCANFIRST;
-       spat->spat_short = scanconst(str->str_ptr,len);
-       if (spat->spat_short) {
-           spat->spat_slen = spat->spat_short->str_cur;
-           if (spat->spat_slen == len)
-               spat->spat_flags |= SPAT_ALL;
-       }
-    }  
+    scanconst(spat,str->str_ptr,len);
     if ((spat->spat_flags & SPAT_ALL) && (spat->spat_flags & SPAT_SCANFIRST)) {
        fbmcompile(spat->spat_short, spat->spat_flags & SPAT_FOLD);
        spat->spat_regexp = regcomp(str->str_ptr,str->str_ptr+len,
@@ -1666,17 +1680,7 @@ register char *s;
            goto get_repl;              /* skip compiling for now */
        }
     }
-    if (*str->str_ptr == '^') {
-       spat->spat_short = scanconst(str->str_ptr+1,len-1);
-       if (spat->spat_short)
-           spat->spat_slen = spat->spat_short->str_cur;
-    }
-    else {
-       spat->spat_flags |= SPAT_SCANFIRST;
-       spat->spat_short = scanconst(str->str_ptr,len);
-       if (spat->spat_short)
-           spat->spat_slen = spat->spat_short->str_cur;
-    }
+    scanconst(spat,str->str_ptr,len);
 get_repl:
     s = scanstr(s);
     if (s >= bufend) {
@@ -1686,7 +1690,6 @@ get_repl:
        return s;
     }
     spat->spat_repl = yylval.arg;
-    spat->spat_flags |= SPAT_ONCE;
     if ((spat->spat_repl[1].arg_type & A_MASK) == A_SINGLE)
        spat->spat_flags |= SPAT_CONST;
     else if ((spat->spat_repl[1].arg_type & A_MASK) == A_DOUBLE) {
@@ -1715,7 +1718,7 @@ get_repl:
        }
        if (*s == 'g') {
            s++;
-           spat->spat_flags &= ~SPAT_ONCE;
+           spat->spat_flags |= SPAT_GLOBAL;
        }
        if (*s == 'i') {
            s++;
@@ -1744,10 +1747,20 @@ get_repl:
     return s;
 }
 
+void
 hoistmust(spat)
 register SPAT *spat;
 {
-    if (spat->spat_regexp->regmust) {  /* is there a better short-circuit? */
+    if (!spat->spat_short && spat->spat_regexp->regstart &&
+       (!spat->spat_regexp->regmust || spat->spat_regexp->reganch & ROPT_ANCH)
+       ) {
+       if (!(spat->spat_regexp->reganch & ROPT_ANCH))
+           spat->spat_flags |= SPAT_SCANFIRST;
+       else if (spat->spat_flags & SPAT_FOLD)
+           return;
+       spat->spat_short = str_smake(spat->spat_regexp->regstart);
+    }
+    else if (spat->spat_regexp->regmust) {/* is there a better short-circuit? */
        if (spat->spat_short &&
          str_eq(spat->spat_short,spat->spat_regexp->regmust))
        {
@@ -2115,6 +2128,7 @@ register char *s;
            STR *tmpstr;
            char *tmps;
 
+           CLINE;
            multi_start = curcmd->c_line;
            if (hereis)
                multi_open = multi_close = '<';