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