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