1 /* $RCSfile: str.c,v $$Revision: 4.0.1.6 $$Date: 92/06/11 21:14:21 $
3 * Copyright (c) 1991, Larry Wall
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Artistic License, as specified in the README file.
9 * Revision 4.0.1.6 92/06/11 21:14:21 lwall
10 * patch34: quotes containing subscripts containing variables didn't parse right
12 * Revision 4.0.1.5 92/06/08 15:40:43 lwall
13 * patch20: removed implicit int declarations on functions
14 * patch20: Perl now distinguishes overlapped copies from non-overlapped
15 * patch20: paragraph mode now skips extra newlines automatically
16 * patch20: fixed memory leak in doube-quote interpretation
17 * patch20: made /\$$foo/ look for literal '$foo'
18 * patch20: "$var{$foo'bar}" didn't scan subscript correctly
19 * patch20: a splice on non-existent array elements could dump core
20 * patch20: running taintperl explicitly now does checks even if $< == $>
22 * Revision 4.0.1.4 91/11/05 18:40:51 lwall
23 * patch11: $foo .= <BAR> could overrun malloced memory
24 * patch11: \$ didn't always make it through double-quoter to regexp routines
25 * patch11: prepared for ctype implementations that don't define isascii()
27 * Revision 4.0.1.3 91/06/10 01:27:54 lwall
28 * patch10: $) and $| incorrectly handled in run-time patterns
30 * Revision 4.0.1.2 91/06/07 11:58:13 lwall
31 * patch4: new copyright notice
32 * patch4: taint check on undefined string could cause core dump
34 * Revision 4.0.1.1 91/04/12 09:15:30 lwall
35 * patch1: fixed undefined environ problem
36 * patch1: substr($ENV{"PATH"},0,0) = "/foo:" didn't modify environment
37 * patch1: $foo .= <BAR> could cause core dump for certain lengths of $foo
39 * Revision 4.0 91/03/20 01:39:55 lwall
57 tainted |= str->str_tainted;
59 return str->str_pok ? str->str_ptr : str_2ptr(str);
63 /* dlb ... guess we have a "crippled cc".
64 * dlb the following functions are usually macros.
72 if (*Str->str_ptr > '0' ||
74 (Str->str_cur && *Str->str_ptr != '0'))
79 return (Str->str_u.str_nval != 0.0);
89 tainted |= Str->str_tainted;
92 return Str->str_u.str_nval;
96 /* dlb ... end of crutch */
104 unsigned long newlen;
107 register char *s = str->str_ptr;
110 if (newlen >= 0x10000) {
111 fprintf(stderr, "Allocation too large: %lx\n", newlen);
115 if (str->str_state == SS_INCR) { /* data before str_ptr? */
116 str->str_len += str->str_u.str_useful;
117 str->str_ptr -= str->str_u.str_useful;
118 str->str_u.str_useful = 0L;
119 Move(s, str->str_ptr, str->str_cur+1, char);
121 str->str_state = SS_NORM; /* normal again */
122 if (newlen > str->str_len)
123 newlen += 10 * (newlen - str->str_cur); /* avoid copy each time */
125 if (newlen > str->str_len) { /* need more room? */
127 Renew(s,newlen,char);
129 New(703,s,newlen,char);
131 str->str_len = newlen;
142 str->str_pok = 0; /* invalidate pointer */
143 if (str->str_state == SS_INCR)
146 str->str_u.str_nval = num;
147 str->str_state = SS_NORM;
148 str->str_nok = 1; /* validate number */
150 str->str_tainted = tainted;
166 olderrno = errno; /* some Xenix systems wipe out errno here */
167 #if defined(scs) && defined(ns32000)
168 gcvt(str->str_u.str_nval,20,s);
171 if (str->str_u.str_nval == 0.0)
175 (void)sprintf(s,"%.20g",str->str_u.str_nval);
185 if (str == &str_undef)
188 warn("Use of uninitialized variable");
193 str->str_cur = s - str->str_ptr;
197 fprintf(stderr,"0x%lx ptr(%s)\n",str,str->str_ptr);
208 if (str->str_state == SS_INCR)
209 Str_Grow(str,0); /* just force copy down */
210 str->str_state = SS_NORM;
211 if (str->str_len && str->str_pok)
212 str->str_u.str_nval = atof(str->str_ptr);
214 if (str == &str_undef)
217 warn("Use of uninitialized variable");
218 str->str_u.str_nval = 0.0;
223 fprintf(stderr,"0x%lx num(%g)\n",str,str->str_u.str_nval);
225 return str->str_u.str_nval;
228 /* Note: str_sset() should not be called with a source string that needs
229 * be reused, since it may destroy the source string if it is marked
240 tainted |= sstr->str_tainted;
242 if (sstr == dstr || dstr == &str_undef)
245 dstr->str_pok = dstr->str_nok = 0;
246 else if (sstr->str_pok) {
249 * Check to see if we can just swipe the string. If so, it's a
250 * possible small lose on short strings, but a big win on long ones.
251 * It might even be a win on short strings if dstr->str_ptr
252 * has to be allocated and sstr->str_ptr has to be freed.
255 if (sstr->str_pok & SP_TEMP) { /* slated for free anyway? */
257 if (dstr->str_state == SS_INCR)
258 dstr->str_ptr -= dstr->str_u.str_useful;
259 Safefree(dstr->str_ptr);
261 dstr->str_ptr = sstr->str_ptr;
262 dstr->str_len = sstr->str_len;
263 dstr->str_cur = sstr->str_cur;
264 dstr->str_state = sstr->str_state;
265 dstr->str_pok = sstr->str_pok & ~SP_TEMP;
267 dstr->str_tainted = sstr->str_tainted;
269 sstr->str_ptr = Nullch;
271 sstr->str_pok = 0; /* wipe out any weird flags */
272 sstr->str_state = 0; /* so sstr frees uneventfully */
274 else { /* have to copy actual string */
276 if (dstr->str_state == SS_INCR) {
280 str_nset(dstr,sstr->str_ptr,sstr->str_cur);
283 if (dstr->str_nok = sstr->str_nok)
284 dstr->str_u.str_nval = sstr->str_u.str_nval;
287 dstr->str_u = sstr->str_u;
289 dstr->str_u.str_nval = sstr->str_u.str_nval;
291 if (dstr->str_cur == sizeof(STBP)) {
292 char *tmps = dstr->str_ptr;
294 if (*tmps == 'S' && bcmp(tmps,"StB",4) == 0) {
295 if (dstr->str_magic && dstr->str_magic->str_rare == 'X') {
296 str_free(dstr->str_magic);
297 dstr->str_magic = Nullstr;
299 if (!dstr->str_magic) {
300 dstr->str_magic = str_smake(sstr->str_magic);
301 dstr->str_magic->str_rare = 'X';
307 else if (sstr->str_nok)
308 str_numset(dstr,sstr->str_u.str_nval);
310 if (dstr->str_state == SS_INCR)
311 Str_Grow(dstr,0); /* just force copy down */
314 dstr->str_u = sstr->str_u;
316 dstr->str_u.str_nval = sstr->str_u.str_nval;
318 dstr->str_pok = dstr->str_nok = 0;
323 str_nset(str,ptr,len)
328 if (str == &str_undef)
330 STR_GROW(str, len + 1);
332 Move(ptr,str->str_ptr,len,char);
334 *(str->str_ptr+str->str_cur) = '\0';
335 str->str_nok = 0; /* invalidate number */
336 str->str_pok = 1; /* validate pointer */
338 str->str_tainted = tainted;
349 if (str == &str_undef)
354 STR_GROW(str, len + 1);
355 Move(ptr,str->str_ptr,len+1,char);
357 str->str_nok = 0; /* invalidate number */
358 str->str_pok = 1; /* validate pointer */
360 str->str_tainted = tainted;
365 str_chop(str,ptr) /* like set but assuming ptr is in str */
369 register STRLEN delta;
371 if (!ptr || !(str->str_pok))
373 delta = ptr - str->str_ptr;
374 str->str_len -= delta;
375 str->str_cur -= delta;
376 str->str_ptr += delta;
377 if (str->str_state == SS_INCR)
378 str->str_u.str_useful += delta;
380 str->str_u.str_useful = delta;
381 str->str_state = SS_INCR;
383 str->str_nok = 0; /* invalidate number */
384 str->str_pok = 1; /* validate pointer (and unstudy str) */
388 str_ncat(str,ptr,len)
393 if (str == &str_undef)
397 STR_GROW(str, str->str_cur + len + 1);
398 Move(ptr,str->str_ptr+str->str_cur,len,char);
400 *(str->str_ptr+str->str_cur) = '\0';
401 str->str_nok = 0; /* invalidate number */
402 str->str_pok = 1; /* validate pointer */
404 str->str_tainted |= tainted;
416 tainted |= sstr->str_tainted;
418 if (!(sstr->str_pok))
419 (void)str_2ptr(sstr);
421 str_ncat(dstr,sstr->str_ptr,sstr->str_cur);
431 if (str == &str_undef)
438 STR_GROW(str, str->str_cur + len + 1);
439 Move(ptr,str->str_ptr+str->str_cur,len+1,char);
441 str->str_nok = 0; /* invalidate number */
442 str->str_pok = 1; /* validate pointer */
444 str->str_tainted |= tainted;
449 str_append_till(str,from,fromend,delim,keeplist)
452 register char *fromend;
459 if (str == &str_undef)
463 len = fromend - from;
464 STR_GROW(str, str->str_cur + len + 1);
465 str->str_nok = 0; /* invalidate number */
466 str->str_pok = 1; /* validate pointer */
467 to = str->str_ptr+str->str_cur;
468 for (; from < fromend; from++,to++) {
469 if (*from == '\\' && from+1 < fromend && delim != '\\') {
471 if (from[1] == delim || from[1] == '\\')
476 else if (from[1] && index(keeplist,from[1]))
481 else if (*from == delim)
486 str->str_cur = to - str->str_ptr;
503 freestrroot = str->str_magic;
504 str->str_magic = Nullstr;
505 str->str_state = SS_NORM;
508 Newz(700+x,str,1,STR);
511 STR_GROW(str, len + 1);
516 str_magic(str, stab, how, name, namlen)
523 if (str == &str_undef || str->str_magic)
525 str->str_magic = Str_new(75,namlen);
526 str = str->str_magic;
527 str->str_u.str_stab = stab;
530 str_nset(str,name,namlen);
534 str_insert(bigstr,offset,len,little,littlelen)
543 register char *midend;
544 register char *bigend;
547 if (bigstr == &str_undef)
550 bigstr->str_pok = SP_VALID; /* disable possible screamer */
553 if (i > 0) { /* string might grow */
554 STR_GROW(bigstr, bigstr->str_cur + i + 1);
555 big = bigstr->str_ptr;
556 mid = big + offset + len;
557 midend = bigend = big + bigstr->str_cur;
560 while (midend > mid) /* shove everything down */
561 *--bigend = *--midend;
562 Move(little,big+offset,littlelen,char);
563 bigstr->str_cur += i;
568 Move(little,bigstr->str_ptr+offset,len,char);
573 big = bigstr->str_ptr;
576 bigend = big + bigstr->str_cur;
579 fatal("panic: str_insert");
581 if (mid - big > bigend - midend) { /* faster to shorten from end */
583 Move(little, mid, littlelen,char);
588 Move(midend, mid, i,char);
592 bigstr->str_cur = mid - big;
595 else if (i = mid - big) { /* faster from front */
598 str_chop(bigstr,midend-i);
603 Move(little, mid, littlelen,char);
605 else if (littlelen) {
607 str_chop(bigstr,midend);
608 Move(little,midend,littlelen,char);
611 str_chop(bigstr,midend);
616 /* make str point to what nstr did */
619 str_replace(str,nstr)
623 if (str == &str_undef)
625 if (str->str_state == SS_INCR)
626 Str_Grow(str,0); /* just force copy down */
627 if (nstr->str_state == SS_INCR)
630 Safefree(str->str_ptr);
631 str->str_ptr = nstr->str_ptr;
632 str->str_len = nstr->str_len;
633 str->str_cur = nstr->str_cur;
634 str->str_pok = nstr->str_pok;
635 str->str_nok = nstr->str_nok;
637 str->str_u = nstr->str_u;
639 str->str_u.str_nval = nstr->str_u.str_nval;
642 str->str_tainted = nstr->str_tainted;
645 str_free(nstr->str_magic);
653 if (!str || str == &str_undef)
655 if (str->str_state) {
656 if (str->str_state == SS_FREE) /* already freed */
658 if (str->str_state == SS_INCR && !(str->str_pok & 2)) {
659 str->str_ptr -= str->str_u.str_useful;
660 str->str_len += str->str_u.str_useful;
664 str_free(str->str_magic);
665 str->str_magic = freestrroot;
668 Safefree(str->str_ptr);
669 str->str_ptr = Nullch;
671 if ((str->str_pok & SP_INTRP) && str->str_u.str_args)
672 arg_free(str->str_u.str_args);
676 if (str->str_len > 127) { /* next user not likely to want more */
677 Safefree(str->str_ptr); /* so give it back to malloc */
678 str->str_ptr = Nullch;
682 str->str_ptr[0] = '\0';
684 if ((str->str_pok & SP_INTRP) && str->str_u.str_args)
685 arg_free(str->str_u.str_args);
689 str->str_state = SS_FREE;
691 str->str_tainted = 0;
694 #endif /* LEAKTEST */
716 if (!str1 || str1 == &str_undef)
717 return (str2 == Nullstr || str2 == &str_undef || !str2->str_cur);
718 if (!str2 || str2 == &str_undef)
719 return !str1->str_cur;
722 (void)str_2ptr(str1);
724 (void)str_2ptr(str2);
726 if (str1->str_cur != str2->str_cur)
729 return !bcmp(str1->str_ptr, str2->str_ptr, str1->str_cur);
739 if (!str1 || str1 == &str_undef)
740 return (str2 == Nullstr || str2 == &str_undef || !str2->str_cur)?0:-1;
741 if (!str2 || str2 == &str_undef)
742 return str1->str_cur != 0;
745 (void)str_2ptr(str1);
747 (void)str_2ptr(str2);
749 if (str1->str_cur < str2->str_cur) {
751 if (retval = memcmp(str1->str_ptr, str2->str_ptr, str1->str_cur))
752 return retval < 0 ? -1 : 1;
757 else if (retval = memcmp(str1->str_ptr, str2->str_ptr, str2->str_cur))
758 return retval < 0 ? -1 : 1;
759 else if (str1->str_cur == str2->str_cur)
766 str_gets(str,fp,append)
771 register char *bp; /* we're going to steal some values */
772 register int cnt; /* from the stdio struct and put EVERYTHING */
773 register STDCHAR *ptr; /* in the innermost loop into registers */
774 register int newline = rschar;/* (assuming >= 6 registers) */
779 if (str == &str_undef)
781 if (rspara) { /* have to do this both before and after */
782 do { /* to make sure file boundaries work right */
790 #ifdef STDSTDIO /* Here is some breathtakingly efficient cheating */
791 cnt = fp->_cnt; /* get count into register */
792 str->str_nok = 0; /* invalidate number */
793 str->str_pok = 1; /* validate pointer */
794 if (str->str_len - append <= cnt + 1) { /* make sure we have the room */
795 if (cnt > 80 && str->str_len > append) {
796 shortbuffered = cnt - str->str_len + append + 1;
797 cnt -= shortbuffered;
801 STR_GROW(str, append+cnt+2);/* (remembering cnt can be -1) */
806 bp = str->str_ptr + append; /* move these two too to registers */
810 while (--cnt >= 0) { /* this */ /* eat */
811 if ((*bp++ = *ptr++) == newline) /* really */ /* dust */
812 goto thats_all_folks; /* screams */ /* sed :-) */
815 if (shortbuffered) { /* oh well, must extend */
818 bpx = bp - str->str_ptr; /* prepare for possible relocation */
820 STR_GROW(str, str->str_len + append + cnt + 2);
821 bp = str->str_ptr + bpx; /* reconstitute our pointer */
825 fp->_cnt = cnt; /* deregisterize cnt and ptr */
827 i = _filbuf(fp); /* get more characters */
829 ptr = fp->_ptr; /* reregisterize cnt and ptr */
831 bpx = bp - str->str_ptr; /* prepare for possible relocation */
833 STR_GROW(str, bpx + cnt + 2);
834 bp = str->str_ptr + bpx; /* reconstitute our pointer */
836 if (i == newline) { /* all done for now? */
838 goto thats_all_folks;
840 else if (i == EOF) /* all done for ever? */
841 goto thats_really_all_folks;
842 *bp++ = i; /* now go back to screaming loop */
846 if (rslen > 1 && (bp - str->str_ptr < rslen || bcmp(bp - rslen, rs, rslen)))
847 goto screamer; /* go back to the fray */
848 thats_really_all_folks:
850 cnt += shortbuffered;
851 fp->_cnt = cnt; /* put these back or we're in trouble */
854 str->str_cur = bp - str->str_ptr; /* set length */
856 #else /* !STDSTDIO */ /* The big, slow, and stupid way */
859 static char buf[8192];
860 char * bpe = buf + sizeof(buf) - 3;
864 while ((i = getc(fp)) != EOF && (*bp++ = i) != newline && bp < bpe) ;
871 if (i != EOF /* joy */
877 (str->str_cur < rslen
879 bcmp(str->str_ptr + str->str_cur - rslen, rs, rslen)
890 #endif /* STDSTDIO */
901 return str->str_cur - append ? str->str_ptr : Nullch;
910 CMD *oldcurcmd = curcmd;
911 int oldperldb = perldb;
915 str_sset(linestr,str);
917 oldoldbufptr = oldbufptr = bufptr = str_get(linestr);
918 bufend = bufptr + linestr->str_cur;
919 if (++loop_ptr >= loop_max) {
921 Renew(loop_stack, loop_max, struct loop);
923 loop_stack[loop_ptr].loop_label = "_EVAL_";
924 loop_stack[loop_ptr].loop_sp = 0;
927 deb("(Pushing label #%d _EVAL_)\n", loop_ptr);
930 if (setjmp(loop_stack[loop_ptr].loop_env)) {
934 fatal("%s\n",stab_val(stabent("@",TRUE))->str_ptr);
938 char *tmps = loop_stack[loop_ptr].loop_label;
939 deb("(Popping label #%d %s)\n",loop_ptr,
946 curcmd->c_line = oldcurcmd->c_line;
951 if (retval || error_count)
952 fatal("Invalid component in string or format");
955 if (cmd->c_type != C_EXPR || cmd->c_next || arg->arg_type != O_LIST)
956 fatal("panic: error in parselist %d %x %d", cmd->c_type,
957 cmd->c_next, arg ? arg->arg_type : -1);
958 cmd->c_expr = Nullarg;
968 register char *s = str_get(src);
969 register char *send = s + src->str_cur;
974 register int brackets;
980 toparse = Str_new(76,0);
984 str_nset(toparse,"",0);
987 if (*s == '\\' && s[1] && index("$@[{\\]}lLuUE",s[1])) {
988 str_ncat(str, t, s - t);
991 str_ncat(str, "$c", 2);
992 sawcase = (*s != 'E');
995 if (*nointrp) { /* in a regular expression */
996 if (*s == '@') /* always strip \@ */ /*SUPPRESS 530*/
998 else /* don't strip \\, \[, \{ etc. */
1001 str_ncat(str, "$b", 2);
1003 str_ncat(str, s, 1);
1007 else if (*s == '$' && s+1 < send && *nointrp && index(nointrp,s[1])) {
1008 str_ncat(str, t, s - t);
1009 str_ncat(str, "$b", 2);
1010 str_ncat(str, s, 2);
1014 else if ((*s == '@' || *s == '$') && s+1 < send) {
1015 str_ncat(str,t,s-t);
1017 if (*s == '$' && s[1] == '#' && (isALPHA(s[2]) || s[2] == '_'))
1019 s = scanident(s,send,tokenbuf);
1021 (!(stab = stabent(tokenbuf,FALSE)) ||
1022 (*s == '{' ? !stab_xhash(stab) : !stab_xarray(stab)) )) {
1023 str_ncat(str,"@",1);
1025 continue; /* grandfather @ from old scripts */
1027 str_ncat(str,"$a",2);
1028 str_ncat(toparse,",",1);
1029 if (t[1] != '{' && (*s == '[' || *s == '{' /* }} */ ) &&
1030 (stab = stabent(tokenbuf,FALSE)) &&
1031 ((*s == '[') ? (stab_xarray(stab) != 0) : (stab_xhash(stab) != 0)) ) {
1053 s = scanident(s,send,tokenbuf);
1058 s = cpytill(tokenbuf,s+1,send,*s,&len);
1060 fatal("Unterminated string");
1064 } while (brackets > 0 && s < send);
1066 fatal("Unmatched brackets in string");
1067 if (*nointrp) { /* we're in a regular expression */
1069 if (*d == '{' && s[-1] == '}') { /* maybe {n,m} */
1071 if (isDIGIT(*d)) { /* matches /^{\d,?\d*}$/ */
1077 s = checkpoint; /* Is {n,m}! Backoff! */
1080 else if (*d == '[' && s[-1] == ']') { /* char class? */
1081 int weight = 2; /* let's weigh the evidence */
1083 unsigned char un_char = 0, last_un_char;
1085 Zero(seen,256,char);
1089 else if (d[1] == '$')
1091 if (isDIGIT(d[1])) {
1093 if (isDIGIT(d[2]) && !d[3])
1099 for (d++; d < s; d++) {
1100 last_un_char = un_char;
1101 un_char = (unsigned char)*d;
1105 weight -= seen[un_char] * 10;
1106 if (isALNUM(d[1])) {
1107 d = scanident(d,s,tokenbuf);
1108 if (stabent(tokenbuf,FALSE))
1113 else if (*d == '$' && d[1] &&
1114 index("[#!%*<>()-=",d[1])) {
1115 if (!d[2] || /*{*/ index("])} =",d[2]))
1124 if (index("wds",d[1]))
1126 else if (seen['\''] || seen['"'])
1128 else if (index("rnftb",d[1]))
1130 else if (isDIGIT(d[1])) {
1132 while (d[1] && isDIGIT(d[1]))
1140 if (last_un_char < (unsigned char) d[1]
1142 if (index("aA01! ",last_un_char))
1144 if (index("zZ79~",d[1]))
1150 if (isALPHA(*d) && d[1] && isALPHA(d[1])) {
1152 if (yylex() != WORD)
1156 if (un_char == last_un_char + 1)
1158 weight -= seen[un_char];
1165 fprintf(stderr,"[%s] weight %d\n",
1166 checkpoint+1,weight);
1169 if (weight >= 0) /* probably a character class */
1175 str_ncat(toparse, "join($\",", 8);
1176 if (t[1] == '{' && s[-1] == '}') {
1177 str_ncat(toparse, t, 1);
1178 str_ncat(toparse, t+2, s - t - 3);
1181 str_ncat(toparse, t, s - t);
1183 str_ncat(toparse, ")", 1);
1189 str_ncat(str,t,s-t);
1191 str_ncat(str, "$cE", 3);
1192 if (toparse->str_ptr && *toparse->str_ptr == ',') {
1193 *toparse->str_ptr = '(';
1194 str_ncat(toparse,",$$);",5);
1195 str->str_u.str_args = parselist(toparse);
1196 str->str_u.str_args->arg_len--; /* ignore $$ reference */
1199 str->str_u.str_args = Nullarg;
1201 str->str_pok |= SP_INTRP;
1203 str_replace(src,str);
1214 register char *send;
1215 register STR **elem;
1222 if (str == &str_undef)
1224 if (!(src->str_pok & SP_INTRP)) {
1225 int oldsave = savestack->ary_fill;
1227 (void)savehptr(&curstash);
1228 curstash = curcmd->c_stash; /* so stabent knows right package */
1230 restorelist(oldsave);
1232 s = src->str_ptr; /* assumed valid since str_pok set */
1234 send = s + src->str_cur;
1236 if (src->str_u.str_args) {
1237 (void)eval(src->str_u.str_args,G_ARRAY,sp);
1238 /* Assuming we have correct # of args */
1239 elem = stack->ary_array + sp;
1244 if (*s == '$' && s+1 < send) {
1246 str_ncat(str,t,s-t);
1249 fatal("panic: unknown interp cookie\n");
1252 str_scat(str,*++elem);
1255 str_ncat(str,++s,1);
1258 if (docase && str->str_cur >= docase) {
1259 char *b = str->str_ptr + --docase;
1262 lcase(b, str->str_ptr + str->str_cur);
1264 ucase(b, str->str_ptr + str->str_cur);
1266 if (u) /* note that l & u are independent of L & U */
1272 docase = str->str_cur + 1;
1291 docase = L = U = l = u = 0;
1302 str_ncat(str,t,s-t);
1309 register char *send;
1321 register char *send;
1336 if (!str || str == &str_undef)
1339 str->str_u.str_nval += 1.0;
1343 if (!str->str_pok || !*str->str_ptr) {
1344 str->str_u.str_nval = 1.0;
1350 while (isALPHA(*d)) d++;
1351 while (isDIGIT(*d)) d++;
1353 str_numset(str,atof(str->str_ptr) + 1.0); /* punt */
1357 while (d >= str->str_ptr) {
1367 *(d--) -= 'z' - 'a' + 1;
1370 /* oh,oh, the number grew */
1371 STR_GROW(str, str->str_cur + 2);
1373 for (d = str->str_ptr + str->str_cur; d > str->str_ptr; d--)
1385 if (!str || str == &str_undef)
1388 str->str_u.str_nval -= 1.0;
1392 if (!str->str_pok) {
1393 str->str_u.str_nval = -1.0;
1397 str_numset(str,atof(str->str_ptr) - 1.0);
1400 /* Make a string that will exist for the duration of the expression
1401 * evaluation. Actually, it may have to last longer than that, but
1402 * hopefully cmd_exec won't free it until it has been assigned to a
1403 * permanent location. */
1405 static long tmps_size = -1;
1411 register STR *str = Str_new(78,0);
1413 str_sset(str,oldstr);
1414 if (++tmps_max > tmps_size) {
1415 tmps_size = tmps_max;
1416 if (!(tmps_size & 127)) {
1418 Renew(tmps_list, tmps_size + 128, STR*);
1420 New(702,tmps_list, 128, STR*);
1423 tmps_list[tmps_max] = str;
1425 str->str_pok |= SP_TEMP;
1429 /* same thing without the copying */
1435 if (!str || str == &str_undef)
1437 if (++tmps_max > tmps_size) {
1438 tmps_size = tmps_max;
1439 if (!(tmps_size & 127)) {
1441 Renew(tmps_list, tmps_size + 128, STR*);
1443 New(704,tmps_list, 128, STR*);
1446 tmps_list[tmps_max] = str;
1448 str->str_pok |= SP_TEMP;
1457 register STR *str = Str_new(79,0);
1461 str_nset(str,s,len);
1469 register STR *str = Str_new(80,0);
1475 /* make an exact duplicate of old */
1481 register STR *new = Str_new(81,0);
1485 if (old->str_state == SS_FREE) {
1486 warn("semi-panic: attempt to dup freed string");
1489 if (old->str_state == SS_INCR && !(old->str_pok & 2))
1492 Safefree(new->str_ptr);
1493 StructCopy(old,new,STR);
1495 new->str_ptr = nsavestr(old->str_ptr,old->str_len);
1496 new->str_pok &= ~SP_TEMP;
1506 register HENT *entry;
1507 register STAB *stab;
1510 register SPAT *spat;
1513 if (!*s) { /* reset ?? searches */
1514 for (spat = stash->tbl_spatroot;
1516 spat = spat->spat_next) {
1517 spat->spat_flags &= ~SPAT_USED;
1522 /* reset variables */
1524 if (!stash->tbl_array)
1532 for ( ; i <= max; i++) {
1533 for (entry = stash->tbl_array[i];
1535 entry = entry->hent_next) {
1536 stab = (STAB*)entry->hent_val;
1537 str = stab_val(stab);
1541 str->str_tainted = tainted;
1543 if (str->str_ptr != Nullch)
1544 str->str_ptr[0] = '\0';
1545 if (stab_xarray(stab)) {
1546 aclear(stab_xarray(stab));
1548 if (stab_xhash(stab)) {
1549 hclear(stab_xhash(stab), FALSE);
1550 if (stab == envstab)
1551 environ[0] = Nullch;
1565 fprintf(stderr,"%s %d %d %d\n",s,tainted,uid, euid);
1567 if (tainted && (!euid || euid != uid || egid != gid || taintanyway)) {
1578 register STR *envstr;
1580 envstr = hfetch(stab_hash(envstab),"PATH",4,FALSE);
1581 if (envstr == &str_undef || envstr->str_tainted) {
1583 if (envstr->str_tainted == 2)
1584 taintproper("Insecure directory in PATH");
1586 taintproper("Insecure PATH");
1588 envstr = hfetch(stab_hash(envstab),"IFS",3,FALSE);
1589 if (envstr != &str_undef && envstr->str_tainted) {
1591 taintproper("Insecure IFS");