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