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 |
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 |
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 |
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 | { |
25 | register char *s; |
26 | |
27 | if (!str) |
aab39148 |
28 | return (char *)""; /* probably safe - won't be written to */ |
8d063cd8 |
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 |
41 | #endif |
42 | return str->str_ptr; |
43 | } |
44 | |
9c8d0b29 |
45 | void |
f0f333f4 |
46 | str_sset(STR *dstr, register STR *sstr) |
8d063cd8 |
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 |
60 | { |
61 | GROWSTR(&(str->str_ptr), &(str->str_len), len + 1); |
2ef53570 |
62 | memcpy(str->str_ptr,ptr,len); |
8d063cd8 |
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 | { |
72 | register int len; |
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 |
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 |
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 |
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 |
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 | { |
109 | register int len; |
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 |
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 | { |
126 | register STR *str; |
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 |
135 | } |
136 | if (len) |
137 | GROWSTR(&(str->str_ptr), &(str->str_len), len + 1); |
138 | return str; |
139 | } |
140 | |
8d063cd8 |
141 | /* make str point to what nstr did */ |
142 | |
143 | void |
f0f333f4 |
144 | str_free(register STR *str) |
8d063cd8 |
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 |
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 |
173 | #if defined(USE_STDIO_PTR) && defined(STDIO_PTR_LVALUE) && defined(STDIO_CNT_LVALUE) |
174 | /* Here is some breathtakingly efficient cheating */ |
8d063cd8 |
175 | |
176 | register char *bp; /* we're going to steal some values */ |
177 | register int cnt; /* from the stdio struct and put EVERYTHING */ |
378cc40b |
178 | register STDCHAR *ptr; /* in the innermost loop into registers */ |
8d063cd8 |
179 | register char newline = '\n'; /* (assuming at least 6 registers) */ |
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 |
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 |
203 | if (bp <= str->str_ptr || bp[-2] != '\\') |
204 | goto thats_all_folks; |
205 | else { |
206 | line++; |
207 | bp -= 2; |
208 | } |
3f939f22 |
209 | } |
8d063cd8 |
210 | } |
211 | |
16d20bd9 |
212 | FILE_cnt(fp) = cnt; /* deregisterize cnt and ptr */ |
cc00df79 |
213 | FILE_ptr(fp) = (void*)ptr; /* LHS STDCHAR* cast non-portable */ |
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 |
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 */ |
5faea5d5 |
233 | FILE_ptr(fp) = (void*)ptr; /* LHS STDCHAR* cast non-portable */ |
8d063cd8 |
234 | *bp = '\0'; |
235 | str->str_cur = bp - str->str_ptr; /* set length */ |
236 | |
c2960299 |
237 | #else /* USE_STDIO_PTR && STDIO_PTR_LVALUE && STDIO_CNT_LVALUE */ |
238 | /* The big, slow, and stupid way */ |
8d063cd8 |
239 | |
240 | static char buf[4192]; |
241 | |
d34ed59f |
242 | if (fgets(buf, sizeof buf, fp) != NULL) |
8d063cd8 |
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 |
250 | } |
251 | |
8d063cd8 |
252 | STR * |
aab39148 |
253 | str_make(const char *s) |
8d063cd8 |
254 | { |
255 | register STR *str = str_new(0); |
256 | |
257 | str_set(str,s); |
258 | return str; |
259 | } |
260 | |