Commit | Line | Data |
---|---|---|
8665f9e4 | 1 | /* str.c |
a687059c | 2 | * |
4bb101f2 | 3 | * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1999, |
8665f9e4 | 4 | * 2001, 2002, 2005 by Larry Wall and others |
a687059c | 5 | * |
d48672a2 LW |
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. | |
8d063cd8 LW |
8 | */ |
9 | ||
8d063cd8 | 10 | #include "EXTERN.h" |
8d063cd8 | 11 | #include "a2p.h" |
9c8d0b29 | 12 | #include "util.h" |
8d063cd8 | 13 | |
9c8d0b29 | 14 | void |
f0f333f4 | 15 | str_numset(register STR *str, double num) |
8d063cd8 LW |
16 | { |
17 | str->str_nval = num; | |
18 | str->str_pok = 0; /* invalidate pointer */ | |
19 | str->str_nok = 1; /* validate number */ | |
20 | } | |
21 | ||
22 | char * | |
f0f333f4 | 23 | str_2ptr(register STR *str) |
8d063cd8 | 24 | { |
eb578fdb | 25 | char *s; |
8d063cd8 LW |
26 | |
27 | if (!str) | |
aab39148 | 28 | return (char *)""; /* probably safe - won't be written to */ |
8d063cd8 LW |
29 | GROWSTR(&(str->str_ptr), &(str->str_len), 24); |
30 | s = str->str_ptr; | |
31 | if (str->str_nok) { | |
32 | sprintf(s,"%.20g",str->str_nval); | |
33 | while (*s) s++; | |
34 | } | |
35 | *s = '\0'; | |
36 | str->str_cur = s - str->str_ptr; | |
37 | str->str_pok = 1; | |
38 | #ifdef DEBUGGING | |
39 | if (debug & 32) | |
68dc0745 | 40 | fprintf(stderr,"0x%lx ptr(%s)\n",(unsigned long)str,str->str_ptr); |
8d063cd8 LW |
41 | #endif |
42 | return str->str_ptr; | |
43 | } | |
44 | ||
9c8d0b29 | 45 | void |
f0f333f4 | 46 | str_sset(STR *dstr, register STR *sstr) |
8d063cd8 LW |
47 | { |
48 | if (!sstr) | |
49 | str_nset(dstr,No,0); | |
50 | else if (sstr->str_nok) | |
51 | str_numset(dstr,sstr->str_nval); | |
52 | else if (sstr->str_pok) | |
53 | str_nset(dstr,sstr->str_ptr,sstr->str_cur); | |
54 | else | |
55 | str_nset(dstr,"",0); | |
56 | } | |
57 | ||
9c8d0b29 | 58 | void |
aab39148 | 59 | str_nset(register STR *str, register const char *ptr, register int len) |
8d063cd8 LW |
60 | { |
61 | GROWSTR(&(str->str_ptr), &(str->str_len), len + 1); | |
2ef53570 | 62 | memcpy(str->str_ptr,ptr,len); |
8d063cd8 LW |
63 | str->str_cur = len; |
64 | *(str->str_ptr+str->str_cur) = '\0'; | |
65 | str->str_nok = 0; /* invalidate number */ | |
66 | str->str_pok = 1; /* validate pointer */ | |
67 | } | |
68 | ||
9c8d0b29 | 69 | void |
aab39148 | 70 | str_set(register STR *str, register const char *ptr) |
8d063cd8 | 71 | { |
eb578fdb | 72 | int len; |
8d063cd8 LW |
73 | |
74 | if (!ptr) | |
75 | ptr = ""; | |
76 | len = strlen(ptr); | |
77 | GROWSTR(&(str->str_ptr), &(str->str_len), len + 1); | |
2ef53570 | 78 | memcpy(str->str_ptr,ptr,len+1); |
8d063cd8 LW |
79 | str->str_cur = len; |
80 | str->str_nok = 0; /* invalidate number */ | |
81 | str->str_pok = 1; /* validate pointer */ | |
82 | } | |
83 | ||
9c8d0b29 | 84 | void |
aab39148 | 85 | str_ncat(register STR *str, register const char *ptr, register int len) |
8d063cd8 LW |
86 | { |
87 | if (!(str->str_pok)) | |
88 | str_2ptr(str); | |
89 | GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + len + 1); | |
2ef53570 | 90 | memcpy(str->str_ptr+str->str_cur, ptr, len); |
8d063cd8 LW |
91 | str->str_cur += len; |
92 | *(str->str_ptr+str->str_cur) = '\0'; | |
93 | str->str_nok = 0; /* invalidate number */ | |
94 | str->str_pok = 1; /* validate pointer */ | |
95 | } | |
96 | ||
9c8d0b29 | 97 | void |
f0f333f4 | 98 | str_scat(STR *dstr, register STR *sstr) |
8d063cd8 LW |
99 | { |
100 | if (!(sstr->str_pok)) | |
101 | str_2ptr(sstr); | |
102 | if (sstr) | |
103 | str_ncat(dstr,sstr->str_ptr,sstr->str_cur); | |
104 | } | |
105 | ||
9c8d0b29 | 106 | void |
aab39148 | 107 | str_cat(register STR *str, register const char *ptr) |
8d063cd8 | 108 | { |
eb578fdb | 109 | int len; |
8d063cd8 LW |
110 | |
111 | if (!ptr) | |
112 | return; | |
113 | if (!(str->str_pok)) | |
114 | str_2ptr(str); | |
115 | len = strlen(ptr); | |
116 | GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + len + 1); | |
2ef53570 | 117 | memcpy(str->str_ptr+str->str_cur, ptr, len+1); |
8d063cd8 LW |
118 | str->str_cur += len; |
119 | str->str_nok = 0; /* invalidate number */ | |
120 | str->str_pok = 1; /* validate pointer */ | |
121 | } | |
122 | ||
8d063cd8 | 123 | STR * |
f0f333f4 | 124 | str_new(int len) |
8d063cd8 | 125 | { |
eb578fdb | 126 | STR *str; |
8d063cd8 LW |
127 | |
128 | if (freestrroot) { | |
129 | str = freestrroot; | |
130 | freestrroot = str->str_link.str_next; | |
131 | } | |
132 | else { | |
133 | str = (STR *) safemalloc(sizeof(STR)); | |
2ef53570 | 134 | memset((char*)str,0,sizeof(STR)); |
8d063cd8 LW |
135 | } |
136 | if (len) | |
137 | GROWSTR(&(str->str_ptr), &(str->str_len), len + 1); | |
138 | return str; | |
139 | } | |
140 | ||
8d063cd8 LW |
141 | /* make str point to what nstr did */ |
142 | ||
143 | void | |
f0f333f4 | 144 | str_free(register STR *str) |
8d063cd8 LW |
145 | { |
146 | if (!str) | |
147 | return; | |
148 | if (str->str_len) | |
149 | str->str_ptr[0] = '\0'; | |
150 | str->str_cur = 0; | |
151 | str->str_nok = 0; | |
152 | str->str_pok = 0; | |
153 | str->str_link.str_next = freestrroot; | |
154 | freestrroot = str; | |
155 | } | |
156 | ||
9c8d0b29 | 157 | int |
f0f333f4 | 158 | str_len(register STR *str) |
8d063cd8 LW |
159 | { |
160 | if (!str) | |
161 | return 0; | |
162 | if (!(str->str_pok)) | |
163 | str_2ptr(str); | |
164 | if (str->str_len) | |
165 | return str->str_cur; | |
166 | else | |
167 | return 0; | |
168 | } | |
169 | ||
170 | char * | |
f0f333f4 | 171 | str_gets(register STR *str, register FILE *fp) |
8d063cd8 | 172 | { |
c2960299 AD |
173 | #if defined(USE_STDIO_PTR) && defined(STDIO_PTR_LVALUE) && defined(STDIO_CNT_LVALUE) |
174 | /* Here is some breathtakingly efficient cheating */ | |
8d063cd8 | 175 | |
eb578fdb KW |
176 | char *bp; /* we're going to steal some values */ |
177 | int cnt; /* from the stdio struct and put EVERYTHING */ | |
178 | STDCHAR *ptr; /* in the innermost loop into registers */ | |
179 | char newline = '\n'; /* (assuming at least 6 registers) */ | |
8d063cd8 LW |
180 | int i; |
181 | int bpx; | |
182 | ||
44a8e56a | 183 | #if defined(VMS) |
184 | /* An ungetc()d char is handled separately from the regular | |
185 | * buffer, so we getc() it back out and stuff it in the buffer. | |
186 | */ | |
187 | i = getc(fp); | |
d34ed59f | 188 | if (i == EOF) return NULL; |
44a8e56a | 189 | *(--((*fp)->_ptr)) = (unsigned char) i; |
190 | (*fp)->_cnt++; | |
191 | #endif | |
192 | ||
16d20bd9 | 193 | cnt = FILE_cnt(fp); /* get count into register */ |
8d063cd8 LW |
194 | str->str_nok = 0; /* invalidate number */ |
195 | str->str_pok = 1; /* validate pointer */ | |
196 | if (str->str_len <= cnt) /* make sure we have the room */ | |
197 | GROWSTR(&(str->str_ptr), &(str->str_len), cnt+1); | |
198 | bp = str->str_ptr; /* move these two too to registers */ | |
cc00df79 | 199 | ptr = (STDCHAR*)FILE_ptr(fp); |
8d063cd8 | 200 | for (;;) { |
378cc40b | 201 | while (--cnt >= 0) { |
3f939f22 | 202 | if ((*bp++ = *ptr++) == newline) { |
378cc40b LW |
203 | if (bp <= str->str_ptr || bp[-2] != '\\') |
204 | goto thats_all_folks; | |
205 | else { | |
206 | line++; | |
207 | bp -= 2; | |
208 | } | |
3f939f22 | 209 | } |
8d063cd8 LW |
210 | } |
211 | ||
16d20bd9 | 212 | FILE_cnt(fp) = cnt; /* deregisterize cnt and ptr */ |
cfb8f080 | 213 | FILE_ptr(fp) = ptr; |
44a8e56a | 214 | i = getc(fp); /* get more characters */ |
16d20bd9 | 215 | cnt = FILE_cnt(fp); |
5faea5d5 | 216 | ptr = (STDCHAR*)FILE_ptr(fp); /* reregisterize cnt and ptr */ |
8d063cd8 LW |
217 | |
218 | bpx = bp - str->str_ptr; /* prepare for possible relocation */ | |
219 | GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + cnt + 1); | |
220 | bp = str->str_ptr + bpx; /* reconstitute our pointer */ | |
221 | ||
222 | if (i == newline) { /* all done for now? */ | |
223 | *bp++ = i; | |
224 | goto thats_all_folks; | |
225 | } | |
226 | else if (i == EOF) /* all done for ever? */ | |
227 | goto thats_all_folks; | |
228 | *bp++ = i; /* now go back to screaming loop */ | |
229 | } | |
230 | ||
231 | thats_all_folks: | |
16d20bd9 | 232 | FILE_cnt(fp) = cnt; /* put these back or we're in trouble */ |
cfb8f080 | 233 | FILE_ptr(fp) = ptr; |
8d063cd8 LW |
234 | *bp = '\0'; |
235 | str->str_cur = bp - str->str_ptr; /* set length */ | |
236 | ||
c2960299 AD |
237 | #else /* USE_STDIO_PTR && STDIO_PTR_LVALUE && STDIO_CNT_LVALUE */ |
238 | /* The big, slow, and stupid way */ | |
8d063cd8 LW |
239 | |
240 | static char buf[4192]; | |
241 | ||
d34ed59f | 242 | if (fgets(buf, sizeof buf, fp) != NULL) |
8d063cd8 LW |
243 | str_set(str, buf); |
244 | else | |
245 | str_set(str, No); | |
246 | ||
c2960299 | 247 | #endif /* USE_STDIO_PTR && STDIO_PTR_LVALUE && STDIO_CNT_LVALUE */ |
8d063cd8 | 248 | |
d34ed59f | 249 | return str->str_cur ? str->str_ptr : NULL; |
8d063cd8 LW |
250 | } |
251 | ||
8d063cd8 | 252 | STR * |
aab39148 | 253 | str_make(const char *s) |
8d063cd8 | 254 | { |
eb578fdb | 255 | STR *str = str_new(0); |
8d063cd8 LW |
256 | |
257 | str_set(str,s); | |
258 | return str; | |
259 | } | |
260 |