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