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