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