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