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