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