-/* $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[{]}";
/* 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 */
int f;
char *s;
{
+ CLINE;
if (*s != '(')
s = skipspace(s);
if (*s == '(') {
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();
if (strEQ(d,"oct"))
UNI(O_OCT);
if (strEQ(d,"opendir"))
- FOP2(O_OPENDIR);
+ FOP2(O_OPEN_DIR);
break;
case 'p': case 'P':
SNARFWORD;
}
STR *
-scanconst(string,len)
+scanconst(spat,string,len)
+SPAT *spat;
char *string;
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);
}
*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;
}
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 */
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;
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] != ')') ||
#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,
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) {
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) {
}
if (*s == 'g') {
s++;
- spat->spat_flags &= ~SPAT_ONCE;
+ spat->spat_flags |= SPAT_GLOBAL;
}
if (*s == 'i') {
s++;
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))
{
STR *tmpstr;
char *tmps;
+ CLINE;
multi_start = curcmd->c_line;
if (hereis)
multi_open = multi_close = '<';