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