source: trunk/third/perl/x2p/str.c @ 14545

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