Commit | Line | Data |
378cc40b |
1 | /* $Header: str.c,v 2.0 88/06/05 00:11:07 root Exp $ |
8d063cd8 |
2 | * |
3 | * $Log: str.c,v $ |
378cc40b |
4 | * Revision 2.0 88/06/05 00:11:07 root |
5 | * Baseline version 2.0. |
8d063cd8 |
6 | * |
7 | */ |
8 | |
8d063cd8 |
9 | #include "EXTERN.h" |
8d063cd8 |
10 | #include "perl.h" |
11 | |
12 | str_reset(s) |
13 | register char *s; |
14 | { |
15 | register STAB *stab; |
16 | register STR *str; |
17 | register int i; |
18 | register int max; |
19 | register SPAT *spat; |
20 | |
21 | if (!*s) { /* reset ?? searches */ |
22 | for (spat = spat_root; spat != Nullspat; spat = spat->spat_next) { |
23 | spat->spat_flags &= ~SPAT_USED; |
24 | } |
25 | return; |
26 | } |
27 | |
28 | /* reset variables */ |
29 | |
30 | while (*s) { |
31 | i = *s; |
32 | if (s[1] == '-') { |
33 | s += 2; |
34 | } |
35 | max = *s++; |
36 | for ( ; i <= max; i++) { |
37 | for (stab = stab_index[i]; stab; stab = stab->stab_next) { |
38 | str = stab->stab_val; |
39 | str->str_cur = 0; |
378cc40b |
40 | str->str_nok = 0; |
8d063cd8 |
41 | if (str->str_ptr != Nullch) |
42 | str->str_ptr[0] = '\0'; |
378cc40b |
43 | if (stab->stab_array) { |
44 | aclear(stab->stab_array); |
45 | } |
46 | if (stab->stab_hash) { |
47 | hclear(stab->stab_hash); |
48 | } |
8d063cd8 |
49 | } |
50 | } |
51 | } |
52 | } |
53 | |
54 | str_numset(str,num) |
55 | register STR *str; |
56 | double num; |
57 | { |
58 | str->str_nval = num; |
59 | str->str_pok = 0; /* invalidate pointer */ |
60 | str->str_nok = 1; /* validate number */ |
61 | } |
62 | |
378cc40b |
63 | extern int errno; |
64 | |
8d063cd8 |
65 | char * |
66 | str_2ptr(str) |
67 | register STR *str; |
68 | { |
69 | register char *s; |
378cc40b |
70 | int olderrno; |
8d063cd8 |
71 | |
72 | if (!str) |
73 | return ""; |
74 | GROWSTR(&(str->str_ptr), &(str->str_len), 24); |
75 | s = str->str_ptr; |
76 | if (str->str_nok) { |
378cc40b |
77 | olderrno = errno; /* some Xenix systems wipe out errno here */ |
78 | #if defined(scs) && defined(ns32000) |
79 | gcvt(str->str_nval,20,s); |
80 | #else |
81 | #ifdef apollo |
82 | if (str->str_nval == 0.0) |
83 | strcpy(s,"0"); |
84 | else |
85 | #endif /*apollo*/ |
8d063cd8 |
86 | sprintf(s,"%.20g",str->str_nval); |
378cc40b |
87 | #endif /*scs*/ |
88 | errno = olderrno; |
8d063cd8 |
89 | while (*s) s++; |
90 | } |
378cc40b |
91 | else if (dowarn) |
92 | warn("Use of uninitialized variable"); |
8d063cd8 |
93 | *s = '\0'; |
94 | str->str_cur = s - str->str_ptr; |
95 | str->str_pok = 1; |
96 | #ifdef DEBUGGING |
97 | if (debug & 32) |
98 | fprintf(stderr,"0x%lx ptr(%s)\n",str,str->str_ptr); |
99 | #endif |
100 | return str->str_ptr; |
101 | } |
102 | |
103 | double |
104 | str_2num(str) |
105 | register STR *str; |
106 | { |
107 | if (!str) |
108 | return 0.0; |
109 | if (str->str_len && str->str_pok) |
110 | str->str_nval = atof(str->str_ptr); |
378cc40b |
111 | else { |
112 | if (dowarn) |
113 | fprintf(stderr,"Use of uninitialized variable in %s line %ld.\n", |
114 | filename,(long)line); |
8d063cd8 |
115 | str->str_nval = 0.0; |
378cc40b |
116 | } |
8d063cd8 |
117 | str->str_nok = 1; |
118 | #ifdef DEBUGGING |
119 | if (debug & 32) |
120 | fprintf(stderr,"0x%lx num(%g)\n",str,str->str_nval); |
121 | #endif |
122 | return str->str_nval; |
123 | } |
124 | |
125 | str_sset(dstr,sstr) |
126 | STR *dstr; |
127 | register STR *sstr; |
128 | { |
129 | if (!sstr) |
130 | str_nset(dstr,No,0); |
131 | else if (sstr->str_nok) |
132 | str_numset(dstr,sstr->str_nval); |
133 | else if (sstr->str_pok) |
134 | str_nset(dstr,sstr->str_ptr,sstr->str_cur); |
135 | else |
136 | str_nset(dstr,"",0); |
137 | } |
138 | |
139 | str_nset(str,ptr,len) |
140 | register STR *str; |
141 | register char *ptr; |
142 | register int len; |
143 | { |
144 | GROWSTR(&(str->str_ptr), &(str->str_len), len + 1); |
145 | bcopy(ptr,str->str_ptr,len); |
146 | str->str_cur = len; |
147 | *(str->str_ptr+str->str_cur) = '\0'; |
148 | str->str_nok = 0; /* invalidate number */ |
149 | str->str_pok = 1; /* validate pointer */ |
150 | } |
151 | |
152 | str_set(str,ptr) |
153 | register STR *str; |
154 | register char *ptr; |
155 | { |
156 | register int len; |
157 | |
158 | if (!ptr) |
159 | ptr = ""; |
160 | len = strlen(ptr); |
161 | GROWSTR(&(str->str_ptr), &(str->str_len), len + 1); |
162 | bcopy(ptr,str->str_ptr,len+1); |
163 | str->str_cur = len; |
164 | str->str_nok = 0; /* invalidate number */ |
165 | str->str_pok = 1; /* validate pointer */ |
166 | } |
167 | |
168 | str_chop(str,ptr) /* like set but assuming ptr is in str */ |
169 | register STR *str; |
170 | register char *ptr; |
171 | { |
172 | if (!(str->str_pok)) |
173 | str_2ptr(str); |
174 | str->str_cur -= (ptr - str->str_ptr); |
175 | bcopy(ptr,str->str_ptr, str->str_cur + 1); |
176 | str->str_nok = 0; /* invalidate number */ |
177 | str->str_pok = 1; /* validate pointer */ |
178 | } |
179 | |
180 | str_ncat(str,ptr,len) |
181 | register STR *str; |
182 | register char *ptr; |
183 | register int len; |
184 | { |
185 | if (!(str->str_pok)) |
186 | str_2ptr(str); |
187 | GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + len + 1); |
188 | bcopy(ptr,str->str_ptr+str->str_cur,len); |
189 | str->str_cur += len; |
190 | *(str->str_ptr+str->str_cur) = '\0'; |
191 | str->str_nok = 0; /* invalidate number */ |
192 | str->str_pok = 1; /* validate pointer */ |
193 | } |
194 | |
195 | str_scat(dstr,sstr) |
196 | STR *dstr; |
197 | register STR *sstr; |
198 | { |
378cc40b |
199 | if (!sstr) |
200 | return; |
8d063cd8 |
201 | if (!(sstr->str_pok)) |
202 | str_2ptr(sstr); |
203 | if (sstr) |
204 | str_ncat(dstr,sstr->str_ptr,sstr->str_cur); |
205 | } |
206 | |
207 | str_cat(str,ptr) |
208 | register STR *str; |
209 | register char *ptr; |
210 | { |
211 | register int len; |
212 | |
213 | if (!ptr) |
214 | return; |
215 | if (!(str->str_pok)) |
216 | str_2ptr(str); |
217 | len = strlen(ptr); |
218 | GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + len + 1); |
219 | bcopy(ptr,str->str_ptr+str->str_cur,len+1); |
220 | str->str_cur += len; |
221 | str->str_nok = 0; /* invalidate number */ |
222 | str->str_pok = 1; /* validate pointer */ |
223 | } |
224 | |
225 | char * |
226 | str_append_till(str,from,delim,keeplist) |
227 | register STR *str; |
228 | register char *from; |
229 | register int delim; |
230 | char *keeplist; |
231 | { |
232 | register char *to; |
233 | register int len; |
234 | |
235 | if (!from) |
236 | return Nullch; |
237 | len = strlen(from); |
238 | GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + len + 1); |
239 | str->str_nok = 0; /* invalidate number */ |
240 | str->str_pok = 1; /* validate pointer */ |
241 | to = str->str_ptr+str->str_cur; |
242 | for (; *from; from++,to++) { |
243 | if (*from == '\\' && from[1] && delim != '\\') { |
244 | if (!keeplist) { |
245 | if (from[1] == delim || from[1] == '\\') |
246 | from++; |
247 | else |
248 | *to++ = *from++; |
249 | } |
250 | else if (index(keeplist,from[1])) |
251 | *to++ = *from++; |
252 | else |
253 | from++; |
254 | } |
255 | else if (*from == delim) |
256 | break; |
257 | *to = *from; |
258 | } |
259 | *to = '\0'; |
260 | str->str_cur = to - str->str_ptr; |
261 | return from; |
262 | } |
263 | |
264 | STR * |
265 | str_new(len) |
266 | int len; |
267 | { |
268 | register STR *str; |
269 | |
270 | if (freestrroot) { |
271 | str = freestrroot; |
272 | freestrroot = str->str_link.str_next; |
273 | str->str_link.str_magic = Nullstab; |
274 | } |
275 | else { |
276 | str = (STR *) safemalloc(sizeof(STR)); |
277 | bzero((char*)str,sizeof(STR)); |
278 | } |
279 | if (len) |
280 | GROWSTR(&(str->str_ptr), &(str->str_len), len + 1); |
281 | return str; |
282 | } |
283 | |
284 | void |
285 | str_grow(str,len) |
286 | register STR *str; |
287 | int len; |
288 | { |
289 | if (len && str) |
290 | GROWSTR(&(str->str_ptr), &(str->str_len), len + 1); |
291 | } |
292 | |
293 | /* make str point to what nstr did */ |
294 | |
295 | void |
296 | str_replace(str,nstr) |
297 | register STR *str; |
298 | register STR *nstr; |
299 | { |
300 | safefree(str->str_ptr); |
301 | str->str_ptr = nstr->str_ptr; |
302 | str->str_len = nstr->str_len; |
303 | str->str_cur = nstr->str_cur; |
304 | str->str_pok = nstr->str_pok; |
305 | if (str->str_nok = nstr->str_nok) |
306 | str->str_nval = nstr->str_nval; |
307 | safefree((char*)nstr); |
308 | } |
309 | |
310 | void |
311 | str_free(str) |
312 | register STR *str; |
313 | { |
314 | if (!str) |
315 | return; |
316 | if (str->str_len) |
317 | str->str_ptr[0] = '\0'; |
318 | str->str_cur = 0; |
319 | str->str_nok = 0; |
320 | str->str_pok = 0; |
321 | str->str_link.str_next = freestrroot; |
322 | freestrroot = str; |
323 | } |
324 | |
325 | str_len(str) |
326 | register STR *str; |
327 | { |
328 | if (!str) |
329 | return 0; |
330 | if (!(str->str_pok)) |
331 | str_2ptr(str); |
332 | if (str->str_len) |
333 | return str->str_cur; |
334 | else |
335 | return 0; |
336 | } |
337 | |
338 | char * |
339 | str_gets(str,fp) |
340 | register STR *str; |
341 | register FILE *fp; |
342 | { |
343 | #ifdef STDSTDIO /* Here is some breathtakingly efficient cheating */ |
344 | |
345 | register char *bp; /* we're going to steal some values */ |
346 | register int cnt; /* from the stdio struct and put EVERYTHING */ |
36ce8bec |
347 | register STDCHAR *ptr; /* in the innermost loop into registers */ |
348 | register char newline = record_separator;/* (assuming >= 6 registers) */ |
8d063cd8 |
349 | int i; |
350 | int bpx; |
351 | int obpx; |
352 | register int get_paragraph; |
353 | register char *oldbp; |
354 | |
355 | if (get_paragraph = !newline) { /* yes, that's an assignment */ |
356 | newline = '\n'; |
357 | oldbp = Nullch; /* remember last \n position (none) */ |
358 | } |
359 | cnt = fp->_cnt; /* get count into register */ |
360 | str->str_nok = 0; /* invalidate number */ |
361 | str->str_pok = 1; /* validate pointer */ |
362 | if (str->str_len <= cnt) /* make sure we have the room */ |
363 | GROWSTR(&(str->str_ptr), &(str->str_len), cnt+1); |
364 | bp = str->str_ptr; /* move these two too to registers */ |
365 | ptr = fp->_ptr; |
366 | for (;;) { |
367 | screamer: |
368 | while (--cnt >= 0) { /* this */ /* eat */ |
369 | if ((*bp++ = *ptr++) == newline) /* really */ /* dust */ |
370 | goto thats_all_folks; /* screams */ /* sed :-) */ |
371 | } |
372 | |
373 | fp->_cnt = cnt; /* deregisterize cnt and ptr */ |
374 | fp->_ptr = ptr; |
375 | i = _filbuf(fp); /* get more characters */ |
376 | cnt = fp->_cnt; |
377 | ptr = fp->_ptr; /* reregisterize cnt and ptr */ |
378 | |
379 | bpx = bp - str->str_ptr; /* prepare for possible relocation */ |
380 | if (get_paragraph && oldbp) |
381 | obpx = oldbp - str->str_ptr; |
378cc40b |
382 | GROWSTR(&(str->str_ptr), &(str->str_len), bpx + cnt + 2); |
8d063cd8 |
383 | bp = str->str_ptr + bpx; /* reconstitute our pointer */ |
384 | if (get_paragraph && oldbp) |
385 | oldbp = str->str_ptr + obpx; |
386 | |
387 | if (i == newline) { /* all done for now? */ |
388 | *bp++ = i; |
389 | goto thats_all_folks; |
390 | } |
391 | else if (i == EOF) /* all done for ever? */ |
392 | goto thats_really_all_folks; |
393 | *bp++ = i; /* now go back to screaming loop */ |
394 | } |
395 | |
396 | thats_all_folks: |
397 | if (get_paragraph && bp - 1 != oldbp) { |
398 | oldbp = bp; /* remember where this newline was */ |
399 | goto screamer; /* and go back to the fray */ |
400 | } |
401 | thats_really_all_folks: |
402 | fp->_cnt = cnt; /* put these back or we're in trouble */ |
403 | fp->_ptr = ptr; |
404 | *bp = '\0'; |
405 | str->str_cur = bp - str->str_ptr; /* set length */ |
406 | |
407 | #else /* !STDSTDIO */ /* The big, slow, and stupid way */ |
408 | |
409 | static char buf[4192]; |
410 | |
411 | if (fgets(buf, sizeof buf, fp) != Nullch) |
412 | str_set(str, buf); |
413 | else |
414 | str_set(str, No); |
415 | |
416 | #endif /* STDSTDIO */ |
417 | |
418 | return str->str_cur ? str->str_ptr : Nullch; |
419 | } |
420 | |
421 | |
422 | STR * |
423 | interp(str,s) |
424 | register STR *str; |
425 | register char *s; |
426 | { |
427 | register char *t = s; |
428 | char *envsave = envname; |
429 | envname = Nullch; |
430 | |
431 | str_set(str,""); |
432 | while (*s) { |
378cc40b |
433 | if (*s == '\\' && s[1] == '\\') { |
434 | str_ncat(str, t, s++ - t); |
435 | t = s++; |
436 | } |
437 | else if (*s == '\\' && s[1] == '$') { |
8d063cd8 |
438 | str_ncat(str, t, s++ - t); |
439 | t = s++; |
440 | } |
441 | else if (*s == '$' && s[1] && s[1] != '|') { |
442 | str_ncat(str,t,s-t); |
443 | s = scanreg(s,tokenbuf); |
444 | str_cat(str,reg_get(tokenbuf)); |
445 | t = s; |
446 | } |
447 | else |
448 | s++; |
449 | } |
450 | envname = envsave; |
451 | str_ncat(str,t,s-t); |
452 | return str; |
453 | } |
454 | |
455 | void |
456 | str_inc(str) |
457 | register STR *str; |
458 | { |
459 | register char *d; |
460 | |
461 | if (!str) |
462 | return; |
463 | if (str->str_nok) { |
464 | str->str_nval += 1.0; |
465 | str->str_pok = 0; |
466 | return; |
467 | } |
378cc40b |
468 | if (!str->str_pok || !*str->str_ptr) { |
8d063cd8 |
469 | str->str_nval = 1.0; |
470 | str->str_nok = 1; |
471 | return; |
472 | } |
378cc40b |
473 | d = str->str_ptr; |
474 | while (isalpha(*d)) d++; |
475 | while (isdigit(*d)) d++; |
476 | if (*d) { |
8d063cd8 |
477 | str_numset(str,atof(str->str_ptr) + 1.0); /* punt */ |
478 | return; |
479 | } |
378cc40b |
480 | d--; |
8d063cd8 |
481 | while (d >= str->str_ptr) { |
378cc40b |
482 | if (isdigit(*d)) { |
483 | if (++*d <= '9') |
484 | return; |
485 | *(d--) = '0'; |
486 | } |
487 | else { |
488 | ++*d; |
489 | if (isalpha(*d)) |
490 | return; |
491 | *(d--) -= 'z' - 'a' + 1; |
492 | } |
8d063cd8 |
493 | } |
494 | /* oh,oh, the number grew */ |
495 | GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + 2); |
496 | str->str_cur++; |
497 | for (d = str->str_ptr + str->str_cur; d > str->str_ptr; d--) |
498 | *d = d[-1]; |
378cc40b |
499 | if (isdigit(d[1])) |
500 | *d = '1'; |
501 | else |
502 | *d = d[1]; |
8d063cd8 |
503 | } |
504 | |
505 | void |
506 | str_dec(str) |
507 | register STR *str; |
508 | { |
8d063cd8 |
509 | if (!str) |
510 | return; |
511 | if (str->str_nok) { |
512 | str->str_nval -= 1.0; |
513 | str->str_pok = 0; |
514 | return; |
515 | } |
516 | if (!str->str_pok) { |
517 | str->str_nval = -1.0; |
518 | str->str_nok = 1; |
519 | return; |
520 | } |
378cc40b |
521 | str_numset(str,atof(str->str_ptr) - 1.0); |
8d063cd8 |
522 | } |
523 | |
524 | /* make a string that will exist for the duration of the expression eval */ |
525 | |
526 | STR * |
527 | str_static(oldstr) |
528 | STR *oldstr; |
529 | { |
530 | register STR *str = str_new(0); |
531 | static long tmps_size = -1; |
532 | |
533 | str_sset(str,oldstr); |
534 | if (++tmps_max > tmps_size) { |
535 | tmps_size = tmps_max; |
536 | if (!(tmps_size & 127)) { |
537 | if (tmps_size) |
538 | tmps_list = (STR**)saferealloc((char*)tmps_list, |
378cc40b |
539 | (MEM_SIZE)((tmps_size + 128) * sizeof(STR*)) ); |
8d063cd8 |
540 | else |
541 | tmps_list = (STR**)safemalloc(128 * sizeof(char*)); |
542 | } |
543 | } |
544 | tmps_list[tmps_max] = str; |
545 | return str; |
546 | } |
547 | |
548 | STR * |
549 | str_make(s) |
550 | char *s; |
551 | { |
552 | register STR *str = str_new(0); |
553 | |
554 | str_set(str,s); |
555 | return str; |
556 | } |
557 | |
558 | STR * |
559 | str_nmake(n) |
560 | double n; |
561 | { |
562 | register STR *str = str_new(0); |
563 | |
564 | str_numset(str,n); |
565 | return str; |
566 | } |