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

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