perl 3.0 patch #44 patch #42, continued
[p5sagit/p5-mst-13.2.git] / str.c
CommitLineData
27e2fb84 1/* $Header: str.c,v 3.0.1.12 91/01/11 18:26:54 lwall Locked $
a687059c 2 *
3 * Copyright (c) 1989, Larry Wall
4 *
5 * You may distribute under the terms of the GNU General Public License
6 * as specified in the README file that comes with the perl 3.0 kit.
8d063cd8 7 *
8 * $Log: str.c,v $
27e2fb84 9 * Revision 3.0.1.12 91/01/11 18:26:54 lwall
10 * patch42: s/^foo/bar/ occasionally brought on core dumps
11 * patch42: undid unwarranted assumptions about memcmp() return value
12 * patch42: ('a' .. 'z') could lose its value in a loop
13 *
4e8eb4f0 14 * Revision 3.0.1.11 90/11/13 15:27:14 lwall
15 * patch41: fixed a couple of malloc/free problems
16 *
34de22dd 17 * Revision 3.0.1.10 90/11/10 02:06:29 lwall
18 * patch38: temp string values are now copied less often
19 * patch38: array slurps are now faster and take less memory
20 * patch38: fixed a memory leakage on local(*foo)
21 *
395c3793 22 * Revision 3.0.1.9 90/10/16 10:41:21 lwall
23 * patch29: the undefined value could get defined by devious means
24 * patch29: undefined values compared inconsistently
25 * patch29: taintperl now checks for world writable PATH components
26 *
e929a76b 27 * Revision 3.0.1.8 90/08/09 05:22:18 lwall
28 * patch19: the number to string converter wasn't allocating enough space
29 * patch19: tainting didn't work on setgid scripts
30 *
0f85fab0 31 * Revision 3.0.1.7 90/03/27 16:24:11 lwall
32 * patch16: strings with prefix chopped off sometimes freed wrong
33 * patch16: taint check blows up on undefined array element
34 *
79a0689e 35 * Revision 3.0.1.6 90/03/12 17:02:14 lwall
36 * patch13: substr as lvalue didn't invalidate old numeric value
37 *
9f68db38 38 * Revision 3.0.1.5 90/02/28 18:30:38 lwall
39 * patch9: you may now undef $/ to have no input record separator
40 * patch9: nested evals clobbered their longjmp environment
41 * patch9: sometimes perl thought ordinary data was a symbol table entry
42 * patch9: insufficient space allocated for numeric string on sun4
43 * patch9: underscore in an array name in a double-quoted string not recognized
44 * patch9: "@foo{}" not recognized unless %foo defined
45 * patch9: "$foo[$[]" gives error
46 *
663a0e37 47 * Revision 3.0.1.4 89/12/21 20:21:35 lwall
48 * patch7: errno may now be a macro with an lvalue
49 * patch7: made nested or recursive foreach work right
50 *
ffed7fef 51 * Revision 3.0.1.3 89/11/17 15:38:23 lwall
52 * patch5: some machines typedef unchar too
53 * patch5: substitution on leading components occasionally caused <> corruption
54 *
ae986130 55 * Revision 3.0.1.2 89/11/11 04:56:22 lwall
56 * patch2: uchar gives Crays fits
57 *
03a14243 58 * Revision 3.0.1.1 89/10/26 23:23:41 lwall
59 * patch1: string ordering tests were wrong
60 * patch1: $/ now works even when STDSTDIO undefined
61 *
a687059c 62 * Revision 3.0 89/10/18 15:23:38 lwall
63 * 3.0 baseline
8d063cd8 64 *
65 */
66
8d063cd8 67#include "EXTERN.h"
8d063cd8 68#include "perl.h"
a687059c 69#include "perly.h"
8d063cd8 70
a687059c 71extern char **environ;
72
73#ifndef str_get
74char *
75str_get(str)
76STR *str;
8d063cd8 77{
a687059c 78#ifdef TAINT
79 tainted |= str->str_tainted;
80#endif
81 return str->str_pok ? str->str_ptr : str_2ptr(str);
82}
83#endif
8d063cd8 84
a687059c 85/* dlb ... guess we have a "crippled cc".
86 * dlb the following functions are usually macros.
87 */
88#ifndef str_true
89str_true(Str)
90STR *Str;
91{
92 if (Str->str_pok) {
93 if (*Str->str_ptr > '0' ||
94 Str->str_cur > 1 ||
95 (Str->str_cur && *Str->str_ptr != '0'))
96 return 1;
97 return 0;
8d063cd8 98 }
a687059c 99 if (Str->str_nok)
100 return (Str->str_u.str_nval != 0.0);
101 return 0;
102}
103#endif /* str_true */
8d063cd8 104
a687059c 105#ifndef str_gnum
106double str_gnum(Str)
107STR *Str;
108{
109#ifdef TAINT
110 tainted |= Str->str_tainted;
111#endif /* TAINT*/
112 if (Str->str_nok)
113 return Str->str_u.str_nval;
114 return str_2num(Str);
115}
116#endif /* str_gnum */
117/* dlb ... end of crutch */
8d063cd8 118
a687059c 119char *
120str_grow(str,newlen)
121register STR *str;
e929a76b 122#ifndef MSDOS
a687059c 123register int newlen;
e929a76b 124#else
125unsigned long newlen;
126#endif
a687059c 127{
128 register char *s = str->str_ptr;
129
e929a76b 130#ifdef MSDOS
131 if (newlen >= 0x10000) {
132 fprintf(stderr, "Allocation too large: %lx\n", newlen);
133 exit(1);
134 }
135#endif /* MSDOS */
a687059c 136 if (str->str_state == SS_INCR) { /* data before str_ptr? */
137 str->str_len += str->str_u.str_useful;
138 str->str_ptr -= str->str_u.str_useful;
139 str->str_u.str_useful = 0L;
140 bcopy(s, str->str_ptr, str->str_cur+1);
141 s = str->str_ptr;
142 str->str_state = SS_NORM; /* normal again */
143 if (newlen > str->str_len)
144 newlen += 10 * (newlen - str->str_cur); /* avoid copy each time */
145 }
146 if (newlen > str->str_len) { /* need more room? */
147 if (str->str_len)
148 Renew(s,newlen,char);
149 else
150 New(703,s,newlen,char);
151 str->str_ptr = s;
152 str->str_len = newlen;
8d063cd8 153 }
a687059c 154 return s;
8d063cd8 155}
156
157str_numset(str,num)
158register STR *str;
159double num;
160{
0f85fab0 161 if (str->str_pok) {
162 str->str_pok = 0; /* invalidate pointer */
163 if (str->str_state == SS_INCR)
e929a76b 164 Str_Grow(str,0);
0f85fab0 165 }
a687059c 166 str->str_u.str_nval = num;
167 str->str_state = SS_NORM;
a687059c 168 str->str_nok = 1; /* validate number */
169#ifdef TAINT
170 str->str_tainted = tainted;
171#endif
8d063cd8 172}
173
174char *
175str_2ptr(str)
176register STR *str;
177{
178 register char *s;
378cc40b 179 int olderrno;
8d063cd8 180
181 if (!str)
182 return "";
8d063cd8 183 if (str->str_nok) {
9f68db38 184 STR_GROW(str, 30);
a687059c 185 s = str->str_ptr;
378cc40b 186 olderrno = errno; /* some Xenix systems wipe out errno here */
187#if defined(scs) && defined(ns32000)
a687059c 188 gcvt(str->str_u.str_nval,20,s);
378cc40b 189#else
190#ifdef apollo
a687059c 191 if (str->str_u.str_nval == 0.0)
192 (void)strcpy(s,"0");
378cc40b 193 else
194#endif /*apollo*/
a687059c 195 (void)sprintf(s,"%.20g",str->str_u.str_nval);
378cc40b 196#endif /*scs*/
197 errno = olderrno;
8d063cd8 198 while (*s) s++;
9f68db38 199#ifdef hcx
200 if (s[-1] == '.')
201 s--;
202#endif
8d063cd8 203 }
a687059c 204 else {
205 if (str == &str_undef)
206 return No;
207 if (dowarn)
208 warn("Use of uninitialized variable");
9f68db38 209 STR_GROW(str, 30);
a687059c 210 s = str->str_ptr;
211 }
8d063cd8 212 *s = '\0';
213 str->str_cur = s - str->str_ptr;
214 str->str_pok = 1;
215#ifdef DEBUGGING
216 if (debug & 32)
217 fprintf(stderr,"0x%lx ptr(%s)\n",str,str->str_ptr);
218#endif
219 return str->str_ptr;
220}
221
222double
223str_2num(str)
224register STR *str;
225{
226 if (!str)
227 return 0.0;
0f85fab0 228 if (str->str_state == SS_INCR)
e929a76b 229 Str_Grow(str,0); /* just force copy down */
a687059c 230 str->str_state = SS_NORM;
8d063cd8 231 if (str->str_len && str->str_pok)
a687059c 232 str->str_u.str_nval = atof(str->str_ptr);
233 else {
234 if (str == &str_undef)
235 return 0.0;
378cc40b 236 if (dowarn)
a687059c 237 warn("Use of uninitialized variable");
238 str->str_u.str_nval = 0.0;
378cc40b 239 }
8d063cd8 240 str->str_nok = 1;
241#ifdef DEBUGGING
242 if (debug & 32)
a687059c 243 fprintf(stderr,"0x%lx num(%g)\n",str,str->str_u.str_nval);
8d063cd8 244#endif
a687059c 245 return str->str_u.str_nval;
8d063cd8 246}
247
34de22dd 248/* Note: str_sset() should not be called with a source string that needs
249 * be reused, since it may destroy the source string if it is marked
250 * as temporary.
251 */
252
8d063cd8 253str_sset(dstr,sstr)
254STR *dstr;
255register STR *sstr;
256{
a687059c 257#ifdef TAINT
0f85fab0 258 if (sstr)
259 tainted |= sstr->str_tainted;
a687059c 260#endif
395c3793 261 if (sstr == dstr || dstr == &str_undef)
9f68db38 262 return;
8d063cd8 263 if (!sstr)
a687059c 264 dstr->str_pok = dstr->str_nok = 0;
265 else if (sstr->str_pok) {
34de22dd 266
267 /*
268 * Check to see if we can just swipe the string. If so, it's a
269 * possible small lose on short strings, but a big win on long ones.
4e8eb4f0 270 * It might even be a win on short strings if dstr->str_ptr
271 * has to be allocated and sstr->str_ptr has to be freed.
34de22dd 272 */
273
274 if (sstr->str_pok & SP_TEMP) { /* slated for free anyway? */
4e8eb4f0 275 if (dstr->str_ptr) {
276 if (dstr->str_state == SS_INCR)
277 dstr->str_ptr -= dstr->str_u.str_useful;
34de22dd 278 Safefree(dstr->str_ptr);
4e8eb4f0 279 }
280 dstr->str_ptr = sstr->str_ptr;
281 dstr->str_len = sstr->str_len;
282 dstr->str_cur = sstr->str_cur;
283 dstr->str_state = sstr->str_state;
284 dstr->str_pok = sstr->str_pok & ~SP_TEMP;
285#ifdef TAINT
286 dstr->str_tainted = sstr->str_tainted;
34de22dd 287#endif
4e8eb4f0 288 sstr->str_ptr = Nullch;
289 sstr->str_len = 0;
290 sstr->str_pok = 0; /* wipe out any weird flags */
291 sstr->str_state = 0; /* so sstr frees uneventfully */
a687059c 292 }
27e2fb84 293 else { /* have to copy actual string */
294 if (dstr->str_ptr) {
295 if (dstr->str_state == SS_INCR) {
296 Str_Grow(dstr,0);
297 }
298 }
34de22dd 299 str_nset(dstr,sstr->str_ptr,sstr->str_cur);
27e2fb84 300 }
4e8eb4f0 301 if (dstr->str_nok = sstr->str_nok)
302 dstr->str_u.str_nval = sstr->str_u.str_nval;
303 else {
304#ifdef STRUCTCOPY
305 dstr->str_u = sstr->str_u;
306#else
307 dstr->str_u.str_nval = sstr->str_u.str_nval;
308#endif
309 if (dstr->str_cur == sizeof(STBP)) {
310 char *tmps = dstr->str_ptr;
a687059c 311
34de22dd 312 if (*tmps == 'S' && bcmp(tmps,"StB",4) == 0) {
313 if (!dstr->str_magic) {
314 dstr->str_magic = str_smake(sstr->str_magic);
315 dstr->str_magic->str_rare = 'X';
316 }
395c3793 317 }
a687059c 318 }
319 }
320 }
321 else if (sstr->str_nok)
322 str_numset(dstr,sstr->str_u.str_nval);
663a0e37 323 else {
0f85fab0 324 if (dstr->str_state == SS_INCR)
e929a76b 325 Str_Grow(dstr,0); /* just force copy down */
0f85fab0 326
663a0e37 327#ifdef STRUCTCOPY
328 dstr->str_u = sstr->str_u;
329#else
330 dstr->str_u.str_nval = sstr->str_u.str_nval;
331#endif
a687059c 332 dstr->str_pok = dstr->str_nok = 0;
663a0e37 333 }
8d063cd8 334}
335
336str_nset(str,ptr,len)
337register STR *str;
338register char *ptr;
e929a76b 339register STRLEN len;
8d063cd8 340{
395c3793 341 if (str == &str_undef)
342 return;
a687059c 343 STR_GROW(str, len + 1);
0f85fab0 344 if (ptr)
345 (void)bcopy(ptr,str->str_ptr,len);
8d063cd8 346 str->str_cur = len;
347 *(str->str_ptr+str->str_cur) = '\0';
348 str->str_nok = 0; /* invalidate number */
349 str->str_pok = 1; /* validate pointer */
a687059c 350#ifdef TAINT
351 str->str_tainted = tainted;
352#endif
8d063cd8 353}
354
355str_set(str,ptr)
356register STR *str;
357register char *ptr;
358{
e929a76b 359 register STRLEN len;
8d063cd8 360
395c3793 361 if (str == &str_undef)
362 return;
8d063cd8 363 if (!ptr)
364 ptr = "";
365 len = strlen(ptr);
a687059c 366 STR_GROW(str, len + 1);
367 (void)bcopy(ptr,str->str_ptr,len+1);
8d063cd8 368 str->str_cur = len;
369 str->str_nok = 0; /* invalidate number */
370 str->str_pok = 1; /* validate pointer */
a687059c 371#ifdef TAINT
372 str->str_tainted = tainted;
373#endif
8d063cd8 374}
375
376str_chop(str,ptr) /* like set but assuming ptr is in str */
377register STR *str;
378register char *ptr;
379{
e929a76b 380 register STRLEN delta;
a687059c 381
8d063cd8 382 if (!(str->str_pok))
a687059c 383 fatal("str_chop: internal inconsistency");
384 delta = ptr - str->str_ptr;
385 str->str_len -= delta;
386 str->str_cur -= delta;
387 str->str_ptr += delta;
388 if (str->str_state == SS_INCR)
389 str->str_u.str_useful += delta;
390 else {
391 str->str_u.str_useful = delta;
392 str->str_state = SS_INCR;
393 }
8d063cd8 394 str->str_nok = 0; /* invalidate number */
a687059c 395 str->str_pok = 1; /* validate pointer (and unstudy str) */
8d063cd8 396}
397
398str_ncat(str,ptr,len)
399register STR *str;
400register char *ptr;
e929a76b 401register STRLEN len;
8d063cd8 402{
395c3793 403 if (str == &str_undef)
404 return;
8d063cd8 405 if (!(str->str_pok))
a687059c 406 (void)str_2ptr(str);
407 STR_GROW(str, str->str_cur + len + 1);
408 (void)bcopy(ptr,str->str_ptr+str->str_cur,len);
8d063cd8 409 str->str_cur += len;
410 *(str->str_ptr+str->str_cur) = '\0';
411 str->str_nok = 0; /* invalidate number */
412 str->str_pok = 1; /* validate pointer */
a687059c 413#ifdef TAINT
414 str->str_tainted |= tainted;
415#endif
8d063cd8 416}
417
418str_scat(dstr,sstr)
419STR *dstr;
420register STR *sstr;
421{
a687059c 422#ifdef TAINT
423 tainted |= sstr->str_tainted;
424#endif
378cc40b 425 if (!sstr)
426 return;
8d063cd8 427 if (!(sstr->str_pok))
a687059c 428 (void)str_2ptr(sstr);
8d063cd8 429 if (sstr)
430 str_ncat(dstr,sstr->str_ptr,sstr->str_cur);
431}
432
433str_cat(str,ptr)
434register STR *str;
435register char *ptr;
436{
e929a76b 437 register STRLEN len;
8d063cd8 438
395c3793 439 if (str == &str_undef)
440 return;
8d063cd8 441 if (!ptr)
442 return;
443 if (!(str->str_pok))
a687059c 444 (void)str_2ptr(str);
8d063cd8 445 len = strlen(ptr);
a687059c 446 STR_GROW(str, str->str_cur + len + 1);
447 (void)bcopy(ptr,str->str_ptr+str->str_cur,len+1);
8d063cd8 448 str->str_cur += len;
449 str->str_nok = 0; /* invalidate number */
450 str->str_pok = 1; /* validate pointer */
a687059c 451#ifdef TAINT
452 str->str_tainted |= tainted;
453#endif
8d063cd8 454}
455
456char *
a687059c 457str_append_till(str,from,fromend,delim,keeplist)
8d063cd8 458register STR *str;
459register char *from;
a687059c 460register char *fromend;
8d063cd8 461register int delim;
462char *keeplist;
463{
464 register char *to;
e929a76b 465 register STRLEN len;
8d063cd8 466
395c3793 467 if (str == &str_undef)
468 return Nullch;
8d063cd8 469 if (!from)
470 return Nullch;
a687059c 471 len = fromend - from;
472 STR_GROW(str, str->str_cur + len + 1);
8d063cd8 473 str->str_nok = 0; /* invalidate number */
474 str->str_pok = 1; /* validate pointer */
475 to = str->str_ptr+str->str_cur;
a687059c 476 for (; from < fromend; from++,to++) {
477 if (*from == '\\' && from+1 < fromend && delim != '\\') {
8d063cd8 478 if (!keeplist) {
479 if (from[1] == delim || from[1] == '\\')
480 from++;
481 else
482 *to++ = *from++;
483 }
a687059c 484 else if (from[1] && index(keeplist,from[1]))
8d063cd8 485 *to++ = *from++;
486 else
487 from++;
488 }
489 else if (*from == delim)
490 break;
491 *to = *from;
492 }
493 *to = '\0';
494 str->str_cur = to - str->str_ptr;
495 return from;
496}
497
498STR *
a687059c 499#ifdef LEAKTEST
500str_new(x,len)
501int x;
502#else
8d063cd8 503str_new(len)
a687059c 504#endif
e929a76b 505STRLEN len;
8d063cd8 506{
507 register STR *str;
508
509 if (freestrroot) {
510 str = freestrroot;
a687059c 511 freestrroot = str->str_magic;
512 str->str_magic = Nullstr;
513 str->str_state = SS_NORM;
8d063cd8 514 }
515 else {
a687059c 516 Newz(700+x,str,1,STR);
8d063cd8 517 }
518 if (len)
a687059c 519 STR_GROW(str, len + 1);
8d063cd8 520 return str;
521}
522
523void
a687059c 524str_magic(str, stab, how, name, namlen)
8d063cd8 525register STR *str;
a687059c 526STAB *stab;
527int how;
528char *name;
e929a76b 529STRLEN namlen;
a687059c 530{
395c3793 531 if (str == &str_undef || str->str_magic)
a687059c 532 return;
533 str->str_magic = Str_new(75,namlen);
534 str = str->str_magic;
535 str->str_u.str_stab = stab;
536 str->str_rare = how;
537 if (name)
538 str_nset(str,name,namlen);
539}
540
541void
542str_insert(bigstr,offset,len,little,littlelen)
543STR *bigstr;
e929a76b 544STRLEN offset;
545STRLEN len;
a687059c 546char *little;
e929a76b 547STRLEN littlelen;
8d063cd8 548{
a687059c 549 register char *big;
550 register char *mid;
551 register char *midend;
552 register char *bigend;
553 register int i;
554
395c3793 555 if (bigstr == &str_undef)
556 return;
79a0689e 557 bigstr->str_nok = 0;
558 bigstr->str_pok = SP_VALID; /* disable possible screamer */
559
a687059c 560 i = littlelen - len;
561 if (i > 0) { /* string might grow */
562 STR_GROW(bigstr, bigstr->str_cur + i + 1);
563 big = bigstr->str_ptr;
564 mid = big + offset + len;
565 midend = bigend = big + bigstr->str_cur;
566 bigend += i;
567 *bigend = '\0';
568 while (midend > mid) /* shove everything down */
569 *--bigend = *--midend;
570 (void)bcopy(little,big+offset,littlelen);
571 bigstr->str_cur += i;
572 return;
573 }
574 else if (i == 0) {
575 (void)bcopy(little,bigstr->str_ptr+offset,len);
576 return;
577 }
578
579 big = bigstr->str_ptr;
580 mid = big + offset;
581 midend = mid + len;
582 bigend = big + bigstr->str_cur;
583
584 if (midend > bigend)
585 fatal("panic: str_insert");
586
a687059c 587 if (mid - big > bigend - midend) { /* faster to shorten from end */
588 if (littlelen) {
589 (void)bcopy(little, mid, littlelen);
590 mid += littlelen;
591 }
592 i = bigend - midend;
593 if (i > 0) {
594 (void)bcopy(midend, mid, i);
595 mid += i;
596 }
597 *mid = '\0';
598 bigstr->str_cur = mid - big;
599 }
600 else if (i = mid - big) { /* faster from front */
601 midend -= littlelen;
602 mid = midend;
603 str_chop(bigstr,midend-i);
604 big += i;
605 while (i--)
606 *--midend = *--big;
607 if (littlelen)
608 (void)bcopy(little, mid, littlelen);
609 }
610 else if (littlelen) {
611 midend -= littlelen;
612 str_chop(bigstr,midend);
613 (void)bcopy(little,midend,littlelen);
614 }
615 else {
616 str_chop(bigstr,midend);
617 }
618 STABSET(bigstr);
8d063cd8 619}
620
621/* make str point to what nstr did */
622
623void
624str_replace(str,nstr)
625register STR *str;
626register STR *nstr;
627{
395c3793 628 if (str == &str_undef)
629 return;
a687059c 630 if (str->str_state == SS_INCR)
e929a76b 631 Str_Grow(str,0); /* just force copy down */
a687059c 632 if (nstr->str_state == SS_INCR)
e929a76b 633 Str_Grow(nstr,0);
a687059c 634 if (str->str_ptr)
635 Safefree(str->str_ptr);
8d063cd8 636 str->str_ptr = nstr->str_ptr;
637 str->str_len = nstr->str_len;
638 str->str_cur = nstr->str_cur;
639 str->str_pok = nstr->str_pok;
a687059c 640 str->str_nok = nstr->str_nok;
641#ifdef STRUCTCOPY
642 str->str_u = nstr->str_u;
643#else
644 str->str_u.str_nval = nstr->str_u.str_nval;
645#endif
646#ifdef TAINT
647 str->str_tainted = nstr->str_tainted;
648#endif
34de22dd 649 if (nstr->str_magic)
650 str_free(nstr->str_magic);
a687059c 651 Safefree(nstr);
8d063cd8 652}
653
654void
655str_free(str)
656register STR *str;
657{
395c3793 658 if (!str || str == &str_undef)
8d063cd8 659 return;
a687059c 660 if (str->str_state) {
661 if (str->str_state == SS_FREE) /* already freed */
662 return;
663 if (str->str_state == SS_INCR && !(str->str_pok & 2)) {
664 str->str_ptr -= str->str_u.str_useful;
665 str->str_len += str->str_u.str_useful;
666 }
667 }
668 if (str->str_magic)
669 str_free(str->str_magic);
670#ifdef LEAKTEST
8d063cd8 671 if (str->str_len)
a687059c 672 Safefree(str->str_ptr);
673 if ((str->str_pok & SP_INTRP) && str->str_u.str_args)
674 arg_free(str->str_u.str_args);
675 Safefree(str);
676#else /* LEAKTEST */
677 if (str->str_len) {
678 if (str->str_len > 127) { /* next user not likely to want more */
679 Safefree(str->str_ptr); /* so give it back to malloc */
680 str->str_ptr = Nullch;
681 str->str_len = 0;
682 }
683 else
684 str->str_ptr[0] = '\0';
685 }
686 if ((str->str_pok & SP_INTRP) && str->str_u.str_args)
687 arg_free(str->str_u.str_args);
8d063cd8 688 str->str_cur = 0;
689 str->str_nok = 0;
690 str->str_pok = 0;
a687059c 691 str->str_state = SS_FREE;
692#ifdef TAINT
693 str->str_tainted = 0;
694#endif
695 str->str_magic = freestrroot;
8d063cd8 696 freestrroot = str;
a687059c 697#endif /* LEAKTEST */
8d063cd8 698}
699
e929a76b 700STRLEN
8d063cd8 701str_len(str)
702register STR *str;
703{
704 if (!str)
705 return 0;
706 if (!(str->str_pok))
a687059c 707 (void)str_2ptr(str);
708 if (str->str_ptr)
8d063cd8 709 return str->str_cur;
710 else
711 return 0;
712}
713
a687059c 714str_eq(str1,str2)
715register STR *str1;
716register STR *str2;
717{
395c3793 718 if (!str1 || str1 == &str_undef)
719 return (str2 == Nullstr || str2 == &str_undef || !str2->str_cur);
720 if (!str2 || str2 == &str_undef)
721 return !str1->str_cur;
a687059c 722
723 if (!str1->str_pok)
724 (void)str_2ptr(str1);
725 if (!str2->str_pok)
726 (void)str_2ptr(str2);
727
728 if (str1->str_cur != str2->str_cur)
729 return 0;
730
731 return !bcmp(str1->str_ptr, str2->str_ptr, str1->str_cur);
732}
733
734str_cmp(str1,str2)
735register STR *str1;
736register STR *str2;
737{
738 int retval;
739
395c3793 740 if (!str1 || str1 == &str_undef)
741 return (str2 == Nullstr || str2 == &str_undef || !str2->str_cur)?0:-1;
742 if (!str2 || str2 == &str_undef)
743 return str1->str_cur != 0;
a687059c 744
745 if (!str1->str_pok)
746 (void)str_2ptr(str1);
747 if (!str2->str_pok)
748 (void)str_2ptr(str2);
749
750 if (str1->str_cur < str2->str_cur) {
751 if (retval = memcmp(str1->str_ptr, str2->str_ptr, str1->str_cur))
27e2fb84 752 return retval < 0 ? -1 : 1;
a687059c 753 else
03a14243 754 return -1;
a687059c 755 }
756 else if (retval = memcmp(str1->str_ptr, str2->str_ptr, str2->str_cur))
27e2fb84 757 return retval < 0 ? -1 : 1;
a687059c 758 else if (str1->str_cur == str2->str_cur)
759 return 0;
760 else
03a14243 761 return 1;
a687059c 762}
763
8d063cd8 764char *
a687059c 765str_gets(str,fp,append)
8d063cd8 766register STR *str;
767register FILE *fp;
a687059c 768int append;
8d063cd8 769{
8d063cd8 770 register char *bp; /* we're going to steal some values */
771 register int cnt; /* from the stdio struct and put EVERYTHING */
36ce8bec 772 register STDCHAR *ptr; /* in the innermost loop into registers */
9f68db38 773 register int newline = record_separator;/* (assuming >= 6 registers) */
8d063cd8 774 int i;
e929a76b 775 STRLEN bpx;
776 STRLEN obpx;
8d063cd8 777 register int get_paragraph;
778 register char *oldbp;
34de22dd 779 int shortbuffered;
8d063cd8 780
395c3793 781 if (str == &str_undef)
782 return Nullch;
a687059c 783 if (get_paragraph = !rslen) { /* yes, that's an assignment */
8d063cd8 784 newline = '\n';
785 oldbp = Nullch; /* remember last \n position (none) */
786 }
03a14243 787#ifdef STDSTDIO /* Here is some breathtakingly efficient cheating */
8d063cd8 788 cnt = fp->_cnt; /* get count into register */
789 str->str_nok = 0; /* invalidate number */
790 str->str_pok = 1; /* validate pointer */
34de22dd 791 if (str->str_len <= cnt + 1) { /* make sure we have the room */
792 if (cnt > 80 && str->str_len > 0) {
4e8eb4f0 793 shortbuffered = cnt - str->str_len + 1;
794 cnt = str->str_len - 1;
34de22dd 795 }
796 else {
797 shortbuffered = 0;
798 STR_GROW(str, append+cnt+2);/* (remembering cnt can be -1) */
799 }
800 }
801 else
802 shortbuffered = 0;
a687059c 803 bp = str->str_ptr + append; /* move these two too to registers */
8d063cd8 804 ptr = fp->_ptr;
805 for (;;) {
806 screamer:
807 while (--cnt >= 0) { /* this */ /* eat */
808 if ((*bp++ = *ptr++) == newline) /* really */ /* dust */
809 goto thats_all_folks; /* screams */ /* sed :-) */
810 }
811
34de22dd 812 if (shortbuffered) { /* oh well, must extend */
813 cnt = shortbuffered;
814 shortbuffered = 0;
815 if (get_paragraph && oldbp)
816 obpx = oldbp - str->str_ptr;
817 bpx = bp - str->str_ptr; /* prepare for possible relocation */
27e2fb84 818 str->str_cur = bpx;
34de22dd 819 STR_GROW(str, str->str_len + append + cnt + 2);
820 bp = str->str_ptr + bpx; /* reconstitute our pointer */
821 if (get_paragraph && oldbp)
822 oldbp = str->str_ptr + obpx;
823 continue;
824 }
825
8d063cd8 826 fp->_cnt = cnt; /* deregisterize cnt and ptr */
827 fp->_ptr = ptr;
828 i = _filbuf(fp); /* get more characters */
829 cnt = fp->_cnt;
830 ptr = fp->_ptr; /* reregisterize cnt and ptr */
831
832 bpx = bp - str->str_ptr; /* prepare for possible relocation */
833 if (get_paragraph && oldbp)
834 obpx = oldbp - str->str_ptr;
ffed7fef 835 str->str_cur = bpx;
a687059c 836 STR_GROW(str, bpx + cnt + 2);
8d063cd8 837 bp = str->str_ptr + bpx; /* reconstitute our pointer */
838 if (get_paragraph && oldbp)
839 oldbp = str->str_ptr + obpx;
840
841 if (i == newline) { /* all done for now? */
842 *bp++ = i;
843 goto thats_all_folks;
844 }
845 else if (i == EOF) /* all done for ever? */
846 goto thats_really_all_folks;
847 *bp++ = i; /* now go back to screaming loop */
848 }
849
850thats_all_folks:
851 if (get_paragraph && bp - 1 != oldbp) {
852 oldbp = bp; /* remember where this newline was */
853 goto screamer; /* and go back to the fray */
854 }
855thats_really_all_folks:
34de22dd 856 if (shortbuffered)
857 cnt += shortbuffered;
8d063cd8 858 fp->_cnt = cnt; /* put these back or we're in trouble */
859 fp->_ptr = ptr;
860 *bp = '\0';
861 str->str_cur = bp - str->str_ptr; /* set length */
862
863#else /* !STDSTDIO */ /* The big, slow, and stupid way */
864
03a14243 865 {
866 static char buf[8192];
867 char * bpe = buf + sizeof(buf) - 3;
868
869screamer:
870 bp = buf;
871filler:
872 while ((i = getc(fp)) != EOF && (*bp++ = i) != newline && bp < bpe);
873 if (i == newline && get_paragraph &&
874 (i = getc(fp)) != EOF && (*bp++ = i) != newline && bp < bpe)
875 goto filler;
8d063cd8 876
03a14243 877 *bp = '\0';
a687059c 878 if (append)
879 str_cat(str, buf);
880 else
881 str_set(str, buf);
03a14243 882 if (i != newline && i != EOF) {
883 append = -1;
884 goto screamer;
885 }
a687059c 886 }
8d063cd8 887
888#endif /* STDSTDIO */
889
a687059c 890 return str->str_cur - append ? str->str_ptr : Nullch;
8d063cd8 891}
892
a687059c 893ARG *
894parselist(str)
895STR *str;
896{
897 register CMD *cmd;
898 register ARG *arg;
e929a76b 899 CMD *oldcurcmd = curcmd;
395c3793 900 int oldperldb = perldb;
a687059c 901 int retval;
8d063cd8 902
395c3793 903 perldb = 0;
a687059c 904 str_sset(linestr,str);
905 in_eval++;
906 oldoldbufptr = oldbufptr = bufptr = str_get(linestr);
907 bufend = bufptr + linestr->str_cur;
9f68db38 908 if (++loop_ptr >= loop_max) {
909 loop_max += 128;
910 Renew(loop_stack, loop_max, struct loop);
911 }
912 loop_stack[loop_ptr].loop_label = "_EVAL_";
913 loop_stack[loop_ptr].loop_sp = 0;
914#ifdef DEBUGGING
915 if (debug & 4) {
916 deb("(Pushing label #%d _EVAL_)\n", loop_ptr);
917 }
918#endif
919 if (setjmp(loop_stack[loop_ptr].loop_env)) {
920 in_eval--;
921 loop_ptr--;
395c3793 922 perldb = oldperldb;
a687059c 923 fatal("%s\n",stab_val(stabent("@",TRUE))->str_ptr);
924 }
9f68db38 925#ifdef DEBUGGING
926 if (debug & 4) {
e929a76b 927 char *tmps = loop_stack[loop_ptr].loop_label;
9f68db38 928 deb("(Popping label #%d %s)\n",loop_ptr,
929 tmps ? tmps : "" );
930 }
931#endif
932 loop_ptr--;
a687059c 933 error_count = 0;
e929a76b 934 curcmd = &compiling;
935 curcmd->c_line = oldcurcmd->c_line;
a687059c 936 retval = yyparse();
e929a76b 937 curcmd = oldcurcmd;
395c3793 938 perldb = oldperldb;
a687059c 939 in_eval--;
940 if (retval || error_count)
941 fatal("Invalid component in string or format");
942 cmd = eval_root;
943 arg = cmd->c_expr;
944 if (cmd->c_type != C_EXPR || cmd->c_next || arg->arg_type != O_LIST)
945 fatal("panic: error in parselist %d %x %d", cmd->c_type,
946 cmd->c_next, arg ? arg->arg_type : -1);
a687059c 947 Safefree(cmd);
948 return arg;
949}
950
951void
952intrpcompile(src)
953STR *src;
8d063cd8 954{
a687059c 955 register char *s = str_get(src);
956 register char *send = s + src->str_cur;
957 register STR *str;
958 register char *t;
959 STR *toparse;
e929a76b 960 STRLEN len;
a687059c 961 register int brackets;
962 register char *d;
963 STAB *stab;
964 char *checkpoint;
8d063cd8 965
a687059c 966 toparse = Str_new(76,0);
967 str = Str_new(77,0);
968
969 str_nset(str,"",0);
970 str_nset(toparse,"",0);
971 t = s;
972 while (s < send) {
973 if (*s == '\\' && s[1] && index("$@[{\\]}",s[1])) {
974 str_ncat(str, t, s - t);
975 ++s;
976 if (*nointrp && s+1 < send)
977 if (*s != '@' && (*s != '$' || index(nointrp,s[1])))
978 str_ncat(str,s-1,1);
979 str_ncat(str, "$b", 2);
980 str_ncat(str, s, 1);
981 ++s;
982 t = s;
8d063cd8 983 }
a687059c 984 else if ((*s == '@' || (*s == '$' && !index(nointrp,s[1]))) &&
985 s+1 < send) {
8d063cd8 986 str_ncat(str,t,s-t);
8d063cd8 987 t = s;
9f68db38 988 if (*s == '$' && s[1] == '#' && (isalpha(s[2]) || s[2] == '_'))
a687059c 989 s++;
990 s = scanreg(s,send,tokenbuf);
991 if (*t == '@' &&
9f68db38 992 (!(stab = stabent(tokenbuf,FALSE)) ||
993 (*s == '{' ? !stab_xhash(stab) : !stab_xarray(stab)) )) {
a687059c 994 str_ncat(str,"@",1);
995 s = ++t;
996 continue; /* grandfather @ from old scripts */
997 }
998 str_ncat(str,"$a",2);
999 str_ncat(toparse,",",1);
1000 if (t[1] != '{' && (*s == '[' || *s == '{' /* }} */ ) &&
1001 (stab = stabent(tokenbuf,FALSE)) &&
1002 ((*s == '[') ? (stab_xarray(stab) != 0) : (stab_xhash(stab) != 0)) ) {
1003 brackets = 0;
1004 checkpoint = s;
1005 do {
1006 switch (*s) {
9f68db38 1007 case '[':
1008 if (s[-1] != '$')
1009 brackets++;
1010 break;
1011 case '{':
a687059c 1012 brackets++;
1013 break;
9f68db38 1014 case ']':
1015 if (s[-1] != '$')
1016 brackets--;
1017 break;
1018 case '}':
a687059c 1019 brackets--;
1020 break;
1021 case '\'':
1022 case '"':
1023 if (s[-1] != '$') {
1024 s = cpytill(tokenbuf,s+1,send,*s,&len);
1025 if (s >= send)
1026 fatal("Unterminated string");
1027 }
1028 break;
1029 }
1030 s++;
1031 } while (brackets > 0 && s < send);
1032 if (s > send)
1033 fatal("Unmatched brackets in string");
1034 if (*nointrp) { /* we're in a regular expression */
1035 d = checkpoint;
1036 if (*d == '{' && s[-1] == '}') { /* maybe {n,m} */
1037 ++d;
1038 if (isdigit(*d)) { /* matches /^{\d,?\d*}$/ */
1039 if (*++d == ',')
1040 ++d;
1041 while (isdigit(*d))
1042 d++;
1043 if (d == s - 1)
1044 s = checkpoint; /* Is {n,m}! Backoff! */
1045 }
1046 }
1047 else if (*d == '[' && s[-1] == ']') { /* char class? */
1048 int weight = 2; /* let's weigh the evidence */
1049 char seen[256];
ffed7fef 1050 unsigned char un_char = 0, last_un_char;
a687059c 1051
1052 Zero(seen,256,char);
1053 *--s = '\0';
1054 if (d[1] == '^')
1055 weight += 150;
1056 else if (d[1] == '$')
1057 weight -= 3;
1058 if (isdigit(d[1])) {
1059 if (d[2]) {
1060 if (isdigit(d[2]) && !d[3])
1061 weight -= 10;
1062 }
1063 else
1064 weight -= 100;
1065 }
1066 for (d++; d < s; d++) {
ffed7fef 1067 last_un_char = un_char;
1068 un_char = (unsigned char)*d;
a687059c 1069 switch (*d) {
1070 case '&':
1071 case '$':
ffed7fef 1072 weight -= seen[un_char] * 10;
a687059c 1073 if (isalpha(d[1]) || isdigit(d[1]) ||
1074 d[1] == '_') {
1075 d = scanreg(d,s,tokenbuf);
1076 if (stabent(tokenbuf,FALSE))
1077 weight -= 100;
1078 else
1079 weight -= 10;
1080 }
1081 else if (*d == '$' && d[1] &&
1082 index("[#!%*<>()-=",d[1])) {
1083 if (!d[2] || /*{*/ index("])} =",d[2]))
1084 weight -= 10;
1085 else
1086 weight -= 1;
1087 }
1088 break;
1089 case '\\':
ffed7fef 1090 un_char = 254;
a687059c 1091 if (d[1]) {
1092 if (index("wds",d[1]))
1093 weight += 100;
1094 else if (seen['\''] || seen['"'])
1095 weight += 1;
1096 else if (index("rnftb",d[1]))
1097 weight += 40;
1098 else if (isdigit(d[1])) {
1099 weight += 40;
1100 while (d[1] && isdigit(d[1]))
1101 d++;
1102 }
1103 }
1104 else
1105 weight += 100;
1106 break;
1107 case '-':
395c3793 1108 if (last_un_char < (unsigned char) d[1]
1109 || d[1] == '\\') {
ffed7fef 1110 if (index("aA01! ",last_un_char))
a687059c 1111 weight += 30;
1112 if (index("zZ79~",d[1]))
1113 weight += 30;
1114 }
1115 else
1116 weight -= 1;
1117 default:
1118 if (isalpha(*d) && d[1] && isalpha(d[1])) {
1119 bufptr = d;
1120 if (yylex() != WORD)
1121 weight -= 150;
1122 d = bufptr;
1123 }
ffed7fef 1124 if (un_char == last_un_char + 1)
a687059c 1125 weight += 5;
ffed7fef 1126 weight -= seen[un_char];
a687059c 1127 break;
1128 }
ffed7fef 1129 seen[un_char]++;
a687059c 1130 }
1131#ifdef DEBUGGING
1132 if (debug & 512)
1133 fprintf(stderr,"[%s] weight %d\n",
1134 checkpoint+1,weight);
1135#endif
1136 *s++ = ']';
1137 if (weight >= 0) /* probably a character class */
1138 s = checkpoint;
1139 }
1140 }
1141 }
1142 if (*t == '@')
1143 str_ncat(toparse, "join($\",", 8);
1144 if (t[1] == '{' && s[-1] == '}') {
1145 str_ncat(toparse, t, 1);
1146 str_ncat(toparse, t+2, s - t - 3);
1147 }
1148 else
1149 str_ncat(toparse, t, s - t);
1150 if (*t == '@')
1151 str_ncat(toparse, ")", 1);
1152 t = s;
1153 }
1154 else
1155 s++;
1156 }
1157 str_ncat(str,t,s-t);
1158 if (toparse->str_ptr && *toparse->str_ptr == ',') {
1159 *toparse->str_ptr = '(';
1160 str_ncat(toparse,",$$);",5);
1161 str->str_u.str_args = parselist(toparse);
1162 str->str_u.str_args->arg_len--; /* ignore $$ reference */
1163 }
1164 else
1165 str->str_u.str_args = Nullarg;
1166 str_free(toparse);
1167 str->str_pok |= SP_INTRP;
1168 str->str_nok = 0;
1169 str_replace(src,str);
1170}
1171
1172STR *
1173interp(str,src,sp)
1174register STR *str;
1175STR *src;
1176int sp;
1177{
1178 register char *s;
1179 register char *t;
1180 register char *send;
1181 register STR **elem;
1182
395c3793 1183 if (str == &str_undef)
1184 return Nullstr;
a687059c 1185 if (!(src->str_pok & SP_INTRP)) {
1186 int oldsave = savestack->ary_fill;
1187
1188 (void)savehptr(&curstash);
395c3793 1189 curstash = curcmd->c_stash; /* so stabent knows right package */
a687059c 1190 intrpcompile(src);
1191 restorelist(oldsave);
1192 }
1193 s = src->str_ptr; /* assumed valid since str_pok set */
1194 t = s;
1195 send = s + src->str_cur;
1196
1197 if (src->str_u.str_args) {
1198 (void)eval(src->str_u.str_args,G_ARRAY,sp);
1199 /* Assuming we have correct # of args */
1200 elem = stack->ary_array + sp;
1201 }
1202
1203 str_nset(str,"",0);
1204 while (s < send) {
1205 if (*s == '$' && s+1 < send) {
1206 str_ncat(str,t,s-t);
1207 switch(*++s) {
1208 case 'a':
1209 str_scat(str,*++elem);
1210 break;
1211 case 'b':
1212 str_ncat(str,++s,1);
1213 break;
1214 }
1215 t = ++s;
8d063cd8 1216 }
1217 else
1218 s++;
1219 }
8d063cd8 1220 str_ncat(str,t,s-t);
1221 return str;
1222}
1223
1224void
1225str_inc(str)
1226register STR *str;
1227{
1228 register char *d;
1229
395c3793 1230 if (!str || str == &str_undef)
8d063cd8 1231 return;
1232 if (str->str_nok) {
a687059c 1233 str->str_u.str_nval += 1.0;
8d063cd8 1234 str->str_pok = 0;
1235 return;
1236 }
378cc40b 1237 if (!str->str_pok || !*str->str_ptr) {
a687059c 1238 str->str_u.str_nval = 1.0;
8d063cd8 1239 str->str_nok = 1;
13281fa4 1240 str->str_pok = 0;
8d063cd8 1241 return;
1242 }
378cc40b 1243 d = str->str_ptr;
1244 while (isalpha(*d)) d++;
1245 while (isdigit(*d)) d++;
1246 if (*d) {
8d063cd8 1247 str_numset(str,atof(str->str_ptr) + 1.0); /* punt */
1248 return;
1249 }
378cc40b 1250 d--;
8d063cd8 1251 while (d >= str->str_ptr) {
378cc40b 1252 if (isdigit(*d)) {
1253 if (++*d <= '9')
1254 return;
1255 *(d--) = '0';
1256 }
1257 else {
1258 ++*d;
1259 if (isalpha(*d))
1260 return;
1261 *(d--) -= 'z' - 'a' + 1;
1262 }
8d063cd8 1263 }
1264 /* oh,oh, the number grew */
a687059c 1265 STR_GROW(str, str->str_cur + 2);
8d063cd8 1266 str->str_cur++;
1267 for (d = str->str_ptr + str->str_cur; d > str->str_ptr; d--)
1268 *d = d[-1];
378cc40b 1269 if (isdigit(d[1]))
1270 *d = '1';
1271 else
1272 *d = d[1];
8d063cd8 1273}
1274
1275void
1276str_dec(str)
1277register STR *str;
1278{
395c3793 1279 if (!str || str == &str_undef)
8d063cd8 1280 return;
1281 if (str->str_nok) {
a687059c 1282 str->str_u.str_nval -= 1.0;
8d063cd8 1283 str->str_pok = 0;
1284 return;
1285 }
1286 if (!str->str_pok) {
a687059c 1287 str->str_u.str_nval = -1.0;
8d063cd8 1288 str->str_nok = 1;
1289 return;
1290 }
378cc40b 1291 str_numset(str,atof(str->str_ptr) - 1.0);
8d063cd8 1292}
1293
a687059c 1294/* Make a string that will exist for the duration of the expression
1295 * evaluation. Actually, it may have to last longer than that, but
1296 * hopefully cmd_exec won't free it until it has been assigned to a
1297 * permanent location. */
1298
1299static long tmps_size = -1;
8d063cd8 1300
1301STR *
1302str_static(oldstr)
1303STR *oldstr;
1304{
a687059c 1305 register STR *str = Str_new(78,0);
8d063cd8 1306
1307 str_sset(str,oldstr);
1308 if (++tmps_max > tmps_size) {
1309 tmps_size = tmps_max;
1310 if (!(tmps_size & 127)) {
1311 if (tmps_size)
a687059c 1312 Renew(tmps_list, tmps_size + 128, STR*);
8d063cd8 1313 else
a687059c 1314 New(702,tmps_list, 128, STR*);
8d063cd8 1315 }
1316 }
1317 tmps_list[tmps_max] = str;
34de22dd 1318 if (str->str_pok)
1319 str->str_pok |= SP_TEMP;
8d063cd8 1320 return str;
1321}
1322
a687059c 1323/* same thing without the copying */
1324
8d063cd8 1325STR *
a687059c 1326str_2static(str)
1327register STR *str;
1328{
395c3793 1329 if (str == &str_undef)
1330 return str;
a687059c 1331 if (++tmps_max > tmps_size) {
1332 tmps_size = tmps_max;
1333 if (!(tmps_size & 127)) {
1334 if (tmps_size)
1335 Renew(tmps_list, tmps_size + 128, STR*);
1336 else
1337 New(704,tmps_list, 128, STR*);
1338 }
1339 }
1340 tmps_list[tmps_max] = str;
34de22dd 1341 if (str->str_pok)
1342 str->str_pok |= SP_TEMP;
a687059c 1343 return str;
1344}
1345
1346STR *
1347str_make(s,len)
8d063cd8 1348char *s;
e929a76b 1349STRLEN len;
8d063cd8 1350{
a687059c 1351 register STR *str = Str_new(79,0);
8d063cd8 1352
a687059c 1353 if (!len)
1354 len = strlen(s);
1355 str_nset(str,s,len);
8d063cd8 1356 return str;
1357}
1358
1359STR *
1360str_nmake(n)
1361double n;
1362{
a687059c 1363 register STR *str = Str_new(80,0);
8d063cd8 1364
1365 str_numset(str,n);
1366 return str;
1367}
a687059c 1368
1369/* make an exact duplicate of old */
1370
1371STR *
1372str_smake(old)
1373register STR *old;
1374{
1375 register STR *new = Str_new(81,0);
1376
1377 if (!old)
1378 return Nullstr;
1379 if (old->str_state == SS_FREE) {
1380 warn("semi-panic: attempt to dup freed string");
1381 return Nullstr;
1382 }
1383 if (old->str_state == SS_INCR && !(old->str_pok & 2))
e929a76b 1384 Str_Grow(old,0);
a687059c 1385 if (new->str_ptr)
1386 Safefree(new->str_ptr);
1387 Copy(old,new,1,STR);
27e2fb84 1388 if (old->str_ptr) {
a687059c 1389 new->str_ptr = nsavestr(old->str_ptr,old->str_len);
27e2fb84 1390 new->str_pok &= ~SP_TEMP;
1391 }
a687059c 1392 return new;
1393}
1394
1395str_reset(s,stash)
1396register char *s;
1397HASH *stash;
1398{
1399 register HENT *entry;
1400 register STAB *stab;
1401 register STR *str;
1402 register int i;
1403 register SPAT *spat;
1404 register int max;
1405
1406 if (!*s) { /* reset ?? searches */
1407 for (spat = stash->tbl_spatroot;
1408 spat != Nullspat;
1409 spat = spat->spat_next) {
1410 spat->spat_flags &= ~SPAT_USED;
1411 }
1412 return;
1413 }
1414
1415 /* reset variables */
1416
395c3793 1417 if (!stash->tbl_array)
1418 return;
a687059c 1419 while (*s) {
1420 i = *s;
1421 if (s[1] == '-') {
1422 s += 2;
1423 }
1424 max = *s++;
1425 for ( ; i <= max; i++) {
1426 for (entry = stash->tbl_array[i];
1427 entry;
1428 entry = entry->hent_next) {
1429 stab = (STAB*)entry->hent_val;
1430 str = stab_val(stab);
1431 str->str_cur = 0;
1432 str->str_nok = 0;
1433#ifdef TAINT
1434 str->str_tainted = tainted;
1435#endif
1436 if (str->str_ptr != Nullch)
1437 str->str_ptr[0] = '\0';
1438 if (stab_xarray(stab)) {
1439 aclear(stab_xarray(stab));
1440 }
1441 if (stab_xhash(stab)) {
395c3793 1442 hclear(stab_xhash(stab), FALSE);
a687059c 1443 if (stab == envstab)
1444 environ[0] = Nullch;
1445 }
1446 }
1447 }
1448 }
1449}
1450
1451#ifdef TAINT
1452taintproper(s)
1453char *s;
1454{
1455#ifdef DEBUGGING
1456 if (debug & 2048)
1457 fprintf(stderr,"%s %d %d %d\n",s,tainted,uid, euid);
1458#endif
e929a76b 1459 if (tainted && (!euid || euid != uid || egid != gid)) {
a687059c 1460 if (!unsafe)
1461 fatal("%s", s);
1462 else if (dowarn)
1463 warn("%s", s);
1464 }
1465}
1466
1467taintenv()
1468{
1469 register STR *envstr;
1470
1471 envstr = hfetch(stab_hash(envstab),"PATH",4,FALSE);
395c3793 1472 if (envstr == &str_undef || envstr->str_tainted) {
a687059c 1473 tainted = 1;
395c3793 1474 if (envstr->str_tainted == 2)
1475 taintproper("Insecure directory in PATH");
1476 else
1477 taintproper("Insecure PATH");
a687059c 1478 }
1479 envstr = hfetch(stab_hash(envstab),"IFS",3,FALSE);
395c3793 1480 if (envstr != &str_undef && envstr->str_tainted) {
a687059c 1481 tainted = 1;
1482 taintproper("Insecure IFS");
1483 }
1484}
1485#endif /* TAINT */