summaryrefslogtreecommitdiff
path: root/str.c
diff options
context:
space:
mode:
Diffstat (limited to 'str.c')
-rw-r--r--str.c215
1 files changed, 118 insertions, 97 deletions
diff --git a/str.c b/str.c
index 7ec76fe906..7f7efc3462 100644
--- a/str.c
+++ b/str.c
@@ -1,4 +1,5 @@
-/* $Header: str.c,v 3.0.1.12 91/01/11 18:26:54 lwall Locked $
+#undef STDSTDIO
+/* $Header: str.c,v 4.0 91/03/20 01:39:55 lwall Locked $
*
* Copyright (c) 1989, Larry Wall
*
@@ -6,61 +7,8 @@
* as specified in the README file that comes with the perl 3.0 kit.
*
* $Log: str.c,v $
- * Revision 3.0.1.12 91/01/11 18:26:54 lwall
- * patch42: s/^foo/bar/ occasionally brought on core dumps
- * patch42: undid unwarranted assumptions about memcmp() return value
- * patch42: ('a' .. 'z') could lose its value in a loop
- *
- * Revision 3.0.1.11 90/11/13 15:27:14 lwall
- * patch41: fixed a couple of malloc/free problems
- *
- * Revision 3.0.1.10 90/11/10 02:06:29 lwall
- * patch38: temp string values are now copied less often
- * patch38: array slurps are now faster and take less memory
- * patch38: fixed a memory leakage on local(*foo)
- *
- * Revision 3.0.1.9 90/10/16 10:41:21 lwall
- * patch29: the undefined value could get defined by devious means
- * patch29: undefined values compared inconsistently
- * patch29: taintperl now checks for world writable PATH components
- *
- * Revision 3.0.1.8 90/08/09 05:22:18 lwall
- * patch19: the number to string converter wasn't allocating enough space
- * patch19: tainting didn't work on setgid scripts
- *
- * Revision 3.0.1.7 90/03/27 16:24:11 lwall
- * patch16: strings with prefix chopped off sometimes freed wrong
- * patch16: taint check blows up on undefined array element
- *
- * Revision 3.0.1.6 90/03/12 17:02:14 lwall
- * patch13: substr as lvalue didn't invalidate old numeric value
- *
- * Revision 3.0.1.5 90/02/28 18:30:38 lwall
- * patch9: you may now undef $/ to have no input record separator
- * patch9: nested evals clobbered their longjmp environment
- * patch9: sometimes perl thought ordinary data was a symbol table entry
- * patch9: insufficient space allocated for numeric string on sun4
- * patch9: underscore in an array name in a double-quoted string not recognized
- * patch9: "@foo{}" not recognized unless %foo defined
- * patch9: "$foo[$[]" gives error
- *
- * Revision 3.0.1.4 89/12/21 20:21:35 lwall
- * patch7: errno may now be a macro with an lvalue
- * patch7: made nested or recursive foreach work right
- *
- * Revision 3.0.1.3 89/11/17 15:38:23 lwall
- * patch5: some machines typedef unchar too
- * patch5: substitution on leading components occasionally caused <> corruption
- *
- * Revision 3.0.1.2 89/11/11 04:56:22 lwall
- * patch2: uchar gives Crays fits
- *
- * Revision 3.0.1.1 89/10/26 23:23:41 lwall
- * patch1: string ordering tests were wrong
- * patch1: $/ now works even when STDSTDIO undefined
- *
- * Revision 3.0 89/10/18 15:23:38 lwall
- * 3.0 baseline
+ * Revision 4.0 91/03/20 01:39:55 lwall
+ * 4.0 baseline.
*
*/
@@ -68,7 +16,9 @@
#include "perl.h"
#include "perly.h"
+#ifndef __STDC__
extern char **environ;
+#endif /* ! __STDC__ */
#ifndef str_get
char *
@@ -379,8 +329,8 @@ register char *ptr;
{
register STRLEN delta;
- if (!(str->str_pok))
- fatal("str_chop: internal inconsistency");
+ if (!ptr || !(str->str_pok))
+ return;
delta = ptr - str->str_ptr;
str->str_len -= delta;
str->str_cur -= delta;
@@ -667,9 +617,12 @@ register STR *str;
}
if (str->str_magic)
str_free(str->str_magic);
+ str->str_magic = freestrroot;
#ifdef LEAKTEST
- if (str->str_len)
+ if (str->str_len) {
Safefree(str->str_ptr);
+ str->str_ptr = Nullch;
+ }
if ((str->str_pok & SP_INTRP) && str->str_u.str_args)
arg_free(str->str_u.str_args);
Safefree(str);
@@ -692,7 +645,6 @@ register STR *str;
#ifdef TAINT
str->str_tainted = 0;
#endif
- str->str_magic = freestrroot;
freestrroot = str;
#endif /* LEAKTEST */
}
@@ -770,20 +722,13 @@ int append;
register char *bp; /* we're going to steal some values */
register int cnt; /* from the stdio struct and put EVERYTHING */
register STDCHAR *ptr; /* in the innermost loop into registers */
- register int newline = record_separator;/* (assuming >= 6 registers) */
+ register int newline = rschar;/* (assuming >= 6 registers) */
int i;
STRLEN bpx;
- STRLEN obpx;
- register int get_paragraph;
- register char *oldbp;
int shortbuffered;
if (str == &str_undef)
return Nullch;
- if (get_paragraph = !rslen) { /* yes, that's an assignment */
- newline = '\n';
- oldbp = Nullch; /* remember last \n position (none) */
- }
#ifdef STDSTDIO /* Here is some breathtakingly efficient cheating */
cnt = fp->_cnt; /* get count into register */
str->str_nok = 0; /* invalidate number */
@@ -812,14 +757,10 @@ int append;
if (shortbuffered) { /* oh well, must extend */
cnt = shortbuffered;
shortbuffered = 0;
- if (get_paragraph && oldbp)
- obpx = oldbp - str->str_ptr;
bpx = bp - str->str_ptr; /* prepare for possible relocation */
str->str_cur = bpx;
STR_GROW(str, str->str_len + append + cnt + 2);
bp = str->str_ptr + bpx; /* reconstitute our pointer */
- if (get_paragraph && oldbp)
- oldbp = str->str_ptr + obpx;
continue;
}
@@ -830,13 +771,9 @@ int append;
ptr = fp->_ptr; /* reregisterize cnt and ptr */
bpx = bp - str->str_ptr; /* prepare for possible relocation */
- if (get_paragraph && oldbp)
- obpx = oldbp - str->str_ptr;
str->str_cur = bpx;
STR_GROW(str, bpx + cnt + 2);
bp = str->str_ptr + bpx; /* reconstitute our pointer */
- if (get_paragraph && oldbp)
- oldbp = str->str_ptr + obpx;
if (i == newline) { /* all done for now? */
*bp++ = i;
@@ -848,10 +785,8 @@ int append;
}
thats_all_folks:
- if (get_paragraph && bp - 1 != oldbp) {
- oldbp = bp; /* remember where this newline was */
- goto screamer; /* and go back to the fray */
- }
+ if (rslen > 1 && (bp - str->str_ptr < rslen || bcmp(bp - rslen, rs, rslen)))
+ goto screamer; /* go back to the fray */
thats_really_all_folks:
if (shortbuffered)
cnt += shortbuffered;
@@ -868,18 +803,27 @@ thats_really_all_folks:
screamer:
bp = buf;
-filler:
- while ((i = getc(fp)) != EOF && (*bp++ = i) != newline && bp < bpe);
- if (i == newline && get_paragraph &&
- (i = getc(fp)) != EOF && (*bp++ = i) != newline && bp < bpe)
- goto filler;
+ while ((i = getc(fp)) != EOF && (*bp++ = i) != newline && bp < bpe) ;
*bp = '\0';
if (append)
str_cat(str, buf);
else
str_set(str, buf);
- if (i != newline && i != EOF) {
+ if (i != EOF /* joy */
+ &&
+ (i != newline
+ ||
+ (rslen > 1
+ &&
+ (str->str_cur < rslen
+ ||
+ bcmp(str->str_ptr + str->str_cur - rslen, rs, rslen)
+ )
+ )
+ )
+ )
+ {
append = -1;
goto screamer;
}
@@ -945,6 +889,7 @@ STR *str;
fatal("panic: error in parselist %d %x %d", cmd->c_type,
cmd->c_next, arg ? arg->arg_type : -1);
Safefree(cmd);
+ eval_root = Nullcmd;
return arg;
}
@@ -962,6 +907,7 @@ STR *src;
register char *d;
STAB *stab;
char *checkpoint;
+ int sawcase = 0;
toparse = Str_new(76,0);
str = Str_new(77,0);
@@ -970,13 +916,19 @@ STR *src;
str_nset(toparse,"",0);
t = s;
while (s < send) {
- if (*s == '\\' && s[1] && index("$@[{\\]}",s[1])) {
+ if (*s == '\\' && s[1] && index("$@[{\\]}lLuUE",s[1])) {
str_ncat(str, t, s - t);
++s;
- if (*nointrp && s+1 < send)
- if (*s != '@' && (*s != '$' || index(nointrp,s[1])))
- str_ncat(str,s-1,1);
- str_ncat(str, "$b", 2);
+ if (isalpha(*s)) {
+ str_ncat(str, "$c", 2);
+ sawcase = (*s != 'E');
+ }
+ else {
+ if (*nointrp && s+1 < send)
+ if (*s != '@' && (*s != '$' || index(nointrp,s[1])))
+ str_ncat(str,s-1,1);
+ str_ncat(str, "$b", 2);
+ }
str_ncat(str, s, 1);
++s;
t = s;
@@ -987,7 +939,7 @@ STR *src;
t = s;
if (*s == '$' && s[1] == '#' && (isalpha(s[2]) || s[2] == '_'))
s++;
- s = scanreg(s,send,tokenbuf);
+ s = scanident(s,send,tokenbuf);
if (*t == '@' &&
(!(stab = stabent(tokenbuf,FALSE)) ||
(*s == '{' ? !stab_xhash(stab) : !stab_xarray(stab)) )) {
@@ -1072,7 +1024,7 @@ STR *src;
weight -= seen[un_char] * 10;
if (isalpha(d[1]) || isdigit(d[1]) ||
d[1] == '_') {
- d = scanreg(d,s,tokenbuf);
+ d = scanident(d,s,tokenbuf);
if (stabent(tokenbuf,FALSE))
weight -= 100;
else
@@ -1155,6 +1107,8 @@ STR *src;
s++;
}
str_ncat(str,t,s-t);
+ if (sawcase)
+ str_ncat(str, "$cE", 3);
if (toparse->str_ptr && *toparse->str_ptr == ',') {
*toparse->str_ptr = '(';
str_ncat(toparse,",$$);",5);
@@ -1179,6 +1133,11 @@ int sp;
register char *t;
register char *send;
register STR **elem;
+ int docase = 0;
+ int l = 0;
+ int u = 0;
+ int L = 0;
+ int U = 0;
if (str == &str_undef)
return Nullstr;
@@ -1203,7 +1162,8 @@ int sp;
str_nset(str,"",0);
while (s < send) {
if (*s == '$' && s+1 < send) {
- str_ncat(str,t,s-t);
+ if (s-t > 0)
+ str_ncat(str,t,s-t);
switch(*++s) {
case 'a':
str_scat(str,*++elem);
@@ -1211,16 +1171,77 @@ int sp;
case 'b':
str_ncat(str,++s,1);
break;
+ case 'c':
+ if (docase && str->str_cur >= docase) {
+ char *b = str->str_ptr + --docase;
+
+ if (L)
+ lcase(b, str->str_ptr + str->str_cur);
+ else if (U)
+ ucase(b, str->str_ptr + str->str_cur);
+
+ if (u) /* note that l & u are independent of L & U */
+ ucase(b, b+1);
+ else if (l)
+ lcase(b, b+1);
+ l = u = 0;
+ }
+ docase = str->str_cur + 1;
+ switch (*++s) {
+ case 'u':
+ u = 1;
+ l = 0;
+ break;
+ case 'U':
+ U = 1;
+ L = 0;
+ break;
+ case 'l':
+ l = 1;
+ u = 0;
+ break;
+ case 'L':
+ L = 1;
+ U = 0;
+ break;
+ case 'E':
+ docase = L = U = l = u = 0;
+ break;
+ }
+ break;
}
t = ++s;
}
else
s++;
}
- str_ncat(str,t,s-t);
+ if (s-t > 0)
+ str_ncat(str,t,s-t);
return str;
}
+ucase(s,send)
+register char *s;
+register char *send;
+{
+ while (s < send) {
+ if (isascii(*s) && islower(*s))
+ *s = toupper(*s);
+ s++;
+ }
+}
+
+lcase(s,send)
+register char *s;
+register char *send;
+{
+ while (s < send) {
+ if (isascii(*s) && isupper(*s))
+ *s = tolower(*s);
+ s++;
+ }
+}
+
void
str_inc(str)
register STR *str;
@@ -1299,7 +1320,7 @@ register STR *str;
static long tmps_size = -1;
STR *
-str_static(oldstr)
+str_mortal(oldstr)
STR *oldstr;
{
register STR *str = Str_new(78,0);
@@ -1323,7 +1344,7 @@ STR *oldstr;
/* same thing without the copying */
STR *
-str_2static(str)
+str_2mortal(str)
register STR *str;
{
if (str == &str_undef)