line |
stmt |
bran |
cond |
sub |
time |
code |
1
|
|
|
|
|
|
/* str.c |
2
|
|
|
|
|
|
* |
3
|
|
|
|
|
|
* Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1999, |
4
|
|
|
|
|
|
* 2001, 2002, 2005 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
|
|
|
|
|
|
|
10
|
|
|
|
|
|
#include "EXTERN.h" |
11
|
|
|
|
|
|
#include "a2p.h" |
12
|
|
|
|
|
|
#include "util.h" |
13
|
|
|
|
|
|
|
14
|
|
|
|
|
|
void |
15
|
0
|
|
|
|
|
str_numset(STR *str, double num) |
16
|
|
|
|
|
|
{ |
17
|
0
|
|
|
|
|
str->str_nval = num; |
18
|
0
|
|
|
|
|
str->str_pok = 0; /* invalidate pointer */ |
19
|
0
|
|
|
|
|
str->str_nok = 1; /* validate number */ |
20
|
0
|
|
|
|
|
} |
21
|
|
|
|
|
|
|
22
|
|
|
|
|
|
char * |
23
|
0
|
|
|
|
|
str_2ptr(STR *str) |
24
|
|
|
|
|
|
{ |
25
|
|
|
|
|
|
char *s; |
26
|
|
|
|
|
|
|
27
|
0
|
|
|
|
|
if (!str) |
28
|
|
|
|
|
|
return (char *)""; /* probably safe - won't be written to */ |
29
|
0
|
|
|
|
|
GROWSTR(&(str->str_ptr), &(str->str_len), 24); |
30
|
0
|
|
|
|
|
s = str->str_ptr; |
31
|
0
|
|
|
|
|
if (str->str_nok) { |
32
|
0
|
|
|
|
|
sprintf(s,"%.20g",str->str_nval); |
33
|
0
|
|
|
|
|
while (*s) s++; |
34
|
|
|
|
|
|
} |
35
|
0
|
|
|
|
|
*s = '\0'; |
36
|
0
|
|
|
|
|
str->str_cur = s - str->str_ptr; |
37
|
0
|
|
|
|
|
str->str_pok = 1; |
38
|
|
|
|
|
|
#ifdef DEBUGGING |
39
|
|
|
|
|
|
if (debug & 32) |
40
|
|
|
|
|
|
fprintf(stderr,"0x%lx ptr(%s)\n",(unsigned long)str,str->str_ptr); |
41
|
|
|
|
|
|
#endif |
42
|
0
|
|
|
|
|
return str->str_ptr; |
43
|
|
|
|
|
|
} |
44
|
|
|
|
|
|
|
45
|
|
|
|
|
|
void |
46
|
0
|
|
|
|
|
str_sset(STR *dstr, STR *sstr) |
47
|
|
|
|
|
|
{ |
48
|
0
|
|
|
|
|
if (!sstr) |
49
|
0
|
|
|
|
|
str_nset(dstr,No,0); |
50
|
0
|
|
|
|
|
else if (sstr->str_nok) |
51
|
0
|
|
|
|
|
str_numset(dstr,sstr->str_nval); |
52
|
0
|
|
|
|
|
else if (sstr->str_pok) |
53
|
0
|
|
|
|
|
str_nset(dstr,sstr->str_ptr,sstr->str_cur); |
54
|
|
|
|
|
|
else |
55
|
0
|
|
|
|
|
str_nset(dstr,"",0); |
56
|
0
|
|
|
|
|
} |
57
|
|
|
|
|
|
|
58
|
|
|
|
|
|
void |
59
|
0
|
|
|
|
|
str_nset(STR *str, const char *ptr, int len) |
60
|
|
|
|
|
|
{ |
61
|
0
|
|
|
|
|
GROWSTR(&(str->str_ptr), &(str->str_len), len + 1); |
62
|
0
|
|
|
|
|
memcpy(str->str_ptr,ptr,len); |
63
|
0
|
|
|
|
|
str->str_cur = len; |
64
|
0
|
|
|
|
|
*(str->str_ptr+str->str_cur) = '\0'; |
65
|
0
|
|
|
|
|
str->str_nok = 0; /* invalidate number */ |
66
|
0
|
|
|
|
|
str->str_pok = 1; /* validate pointer */ |
67
|
0
|
|
|
|
|
} |
68
|
|
|
|
|
|
|
69
|
|
|
|
|
|
void |
70
|
0
|
|
|
|
|
str_set(STR *str, const char *ptr) |
71
|
|
|
|
|
|
{ |
72
|
|
|
|
|
|
int len; |
73
|
|
|
|
|
|
|
74
|
0
|
|
|
|
|
if (!ptr) |
75
|
|
|
|
|
|
ptr = ""; |
76
|
0
|
|
|
|
|
len = strlen(ptr); |
77
|
0
|
|
|
|
|
GROWSTR(&(str->str_ptr), &(str->str_len), len + 1); |
78
|
0
|
|
|
|
|
memcpy(str->str_ptr,ptr,len+1); |
79
|
0
|
|
|
|
|
str->str_cur = len; |
80
|
0
|
|
|
|
|
str->str_nok = 0; /* invalidate number */ |
81
|
0
|
|
|
|
|
str->str_pok = 1; /* validate pointer */ |
82
|
0
|
|
|
|
|
} |
83
|
|
|
|
|
|
|
84
|
|
|
|
|
|
void |
85
|
0
|
|
|
|
|
str_ncat(STR *str, const char *ptr, int len) |
86
|
|
|
|
|
|
{ |
87
|
0
|
|
|
|
|
if (!(str->str_pok)) |
88
|
0
|
|
|
|
|
str_2ptr(str); |
89
|
0
|
|
|
|
|
GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + len + 1); |
90
|
0
|
|
|
|
|
memcpy(str->str_ptr+str->str_cur, ptr, len); |
91
|
0
|
|
|
|
|
str->str_cur += len; |
92
|
0
|
|
|
|
|
*(str->str_ptr+str->str_cur) = '\0'; |
93
|
0
|
|
|
|
|
str->str_nok = 0; /* invalidate number */ |
94
|
0
|
|
|
|
|
str->str_pok = 1; /* validate pointer */ |
95
|
0
|
|
|
|
|
} |
96
|
|
|
|
|
|
|
97
|
|
|
|
|
|
void |
98
|
0
|
|
|
|
|
str_scat(STR *dstr, STR *sstr) |
99
|
|
|
|
|
|
{ |
100
|
0
|
|
|
|
|
if (!(sstr->str_pok)) |
101
|
0
|
|
|
|
|
str_2ptr(sstr); |
102
|
0
|
|
|
|
|
if (sstr) |
103
|
0
|
|
|
|
|
str_ncat(dstr,sstr->str_ptr,sstr->str_cur); |
104
|
0
|
|
|
|
|
} |
105
|
|
|
|
|
|
|
106
|
|
|
|
|
|
void |
107
|
0
|
|
|
|
|
str_cat(STR *str, const char *ptr) |
108
|
|
|
|
|
|
{ |
109
|
|
|
|
|
|
int len; |
110
|
|
|
|
|
|
|
111
|
0
|
|
|
|
|
if (!ptr) |
112
|
0
|
|
|
|
|
return; |
113
|
0
|
|
|
|
|
if (!(str->str_pok)) |
114
|
0
|
|
|
|
|
str_2ptr(str); |
115
|
0
|
|
|
|
|
len = strlen(ptr); |
116
|
0
|
|
|
|
|
GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + len + 1); |
117
|
0
|
|
|
|
|
memcpy(str->str_ptr+str->str_cur, ptr, len+1); |
118
|
0
|
|
|
|
|
str->str_cur += len; |
119
|
0
|
|
|
|
|
str->str_nok = 0; /* invalidate number */ |
120
|
0
|
|
|
|
|
str->str_pok = 1; /* validate pointer */ |
121
|
|
|
|
|
|
} |
122
|
|
|
|
|
|
|
123
|
|
|
|
|
|
STR * |
124
|
0
|
|
|
|
|
str_new(int len) |
125
|
|
|
|
|
|
{ |
126
|
|
|
|
|
|
STR *str; |
127
|
|
|
|
|
|
|
128
|
0
|
|
|
|
|
if (freestrroot) { |
129
|
0
|
|
|
|
|
str = freestrroot; |
130
|
0
|
|
|
|
|
freestrroot = str->str_link.str_next; |
131
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
else { |
133
|
0
|
|
|
|
|
str = (STR *) safemalloc(sizeof(STR)); |
134
|
|
|
|
|
|
memset((char*)str,0,sizeof(STR)); |
135
|
|
|
|
|
|
} |
136
|
0
|
|
|
|
|
if (len) |
137
|
0
|
|
|
|
|
GROWSTR(&(str->str_ptr), &(str->str_len), len + 1); |
138
|
0
|
|
|
|
|
return str; |
139
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
141
|
|
|
|
|
|
/* make str point to what nstr did */ |
142
|
|
|
|
|
|
|
143
|
|
|
|
|
|
void |
144
|
0
|
|
|
|
|
str_free(STR *str) |
145
|
|
|
|
|
|
{ |
146
|
0
|
|
|
|
|
if (!str) |
147
|
0
|
|
|
|
|
return; |
148
|
0
|
|
|
|
|
if (str->str_len) |
149
|
0
|
|
|
|
|
str->str_ptr[0] = '\0'; |
150
|
0
|
|
|
|
|
str->str_cur = 0; |
151
|
0
|
|
|
|
|
str->str_nok = 0; |
152
|
0
|
|
|
|
|
str->str_pok = 0; |
153
|
0
|
|
|
|
|
str->str_link.str_next = freestrroot; |
154
|
0
|
|
|
|
|
freestrroot = str; |
155
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
157
|
|
|
|
|
|
int |
158
|
0
|
|
|
|
|
str_len(STR *str) |
159
|
|
|
|
|
|
{ |
160
|
0
|
|
|
|
|
if (!str) |
161
|
|
|
|
|
|
return 0; |
162
|
0
|
|
|
|
|
if (!(str->str_pok)) |
163
|
0
|
|
|
|
|
str_2ptr(str); |
164
|
0
|
|
|
|
|
if (str->str_len) |
165
|
0
|
|
|
|
|
return str->str_cur; |
166
|
|
|
|
|
|
else |
167
|
|
|
|
|
|
return 0; |
168
|
|
|
|
|
|
} |
169
|
|
|
|
|
|
|
170
|
|
|
|
|
|
char * |
171
|
0
|
|
|
|
|
str_gets(STR *str, FILE *fp) |
172
|
|
|
|
|
|
{ |
173
|
|
|
|
|
|
#if defined(USE_STDIO_PTR) && defined(STDIO_PTR_LVALUE) && defined(STDIO_CNT_LVALUE) |
174
|
|
|
|
|
|
/* Here is some breathtakingly efficient cheating */ |
175
|
|
|
|
|
|
|
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) */ |
180
|
|
|
|
|
|
int i; |
181
|
|
|
|
|
|
int bpx; |
182
|
|
|
|
|
|
|
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); |
188
|
|
|
|
|
|
if (i == EOF) return NULL; |
189
|
|
|
|
|
|
*(--((*fp)->_ptr)) = (unsigned char) i; |
190
|
|
|
|
|
|
(*fp)->_cnt++; |
191
|
|
|
|
|
|
#endif |
192
|
|
|
|
|
|
|
193
|
|
|
|
|
|
cnt = FILE_cnt(fp); /* get count into register */ |
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 */ |
199
|
|
|
|
|
|
ptr = (STDCHAR*)FILE_ptr(fp); |
200
|
|
|
|
|
|
for (;;) { |
201
|
|
|
|
|
|
while (--cnt >= 0) { |
202
|
|
|
|
|
|
if ((*bp++ = *ptr++) == newline) { |
203
|
|
|
|
|
|
if (bp <= str->str_ptr || bp[-2] != '\\') |
204
|
|
|
|
|
|
goto thats_all_folks; |
205
|
|
|
|
|
|
else { |
206
|
|
|
|
|
|
line++; |
207
|
|
|
|
|
|
bp -= 2; |
208
|
|
|
|
|
|
} |
209
|
|
|
|
|
|
} |
210
|
|
|
|
|
|
} |
211
|
|
|
|
|
|
|
212
|
|
|
|
|
|
FILE_cnt(fp) = cnt; /* deregisterize cnt and ptr */ |
213
|
|
|
|
|
|
FILE_ptr(fp) = ptr; |
214
|
|
|
|
|
|
i = getc(fp); /* get more characters */ |
215
|
|
|
|
|
|
cnt = FILE_cnt(fp); |
216
|
|
|
|
|
|
ptr = (STDCHAR*)FILE_ptr(fp); /* reregisterize cnt and ptr */ |
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: |
232
|
|
|
|
|
|
FILE_cnt(fp) = cnt; /* put these back or we're in trouble */ |
233
|
|
|
|
|
|
FILE_ptr(fp) = ptr; |
234
|
|
|
|
|
|
*bp = '\0'; |
235
|
|
|
|
|
|
str->str_cur = bp - str->str_ptr; /* set length */ |
236
|
|
|
|
|
|
|
237
|
|
|
|
|
|
#else /* USE_STDIO_PTR && STDIO_PTR_LVALUE && STDIO_CNT_LVALUE */ |
238
|
|
|
|
|
|
/* The big, slow, and stupid way */ |
239
|
|
|
|
|
|
|
240
|
|
|
|
|
|
static char buf[4192]; |
241
|
|
|
|
|
|
|
242
|
0
|
|
|
|
|
if (fgets(buf, sizeof buf, fp) != NULL) |
243
|
0
|
|
|
|
|
str_set(str, buf); |
244
|
|
|
|
|
|
else |
245
|
0
|
|
|
|
|
str_set(str, No); |
246
|
|
|
|
|
|
|
247
|
|
|
|
|
|
#endif /* USE_STDIO_PTR && STDIO_PTR_LVALUE && STDIO_CNT_LVALUE */ |
248
|
|
|
|
|
|
|
249
|
0
|
|
|
|
|
return str->str_cur ? str->str_ptr : NULL; |
250
|
|
|
|
|
|
} |
251
|
|
|
|
|
|
|
252
|
|
|
|
|
|
STR * |
253
|
0
|
|
|
|
|
str_make(const char *s) |
254
|
|
|
|
|
|
{ |
255
|
0
|
|
|
|
|
STR *str = str_new(0); |
256
|
|
|
|
|
|
|
257
|
0
|
|
|
|
|
str_set(str,s); |
258
|
0
|
|
|
|
|
return str; |
259
|
|
|
|
|
|
} |
260
|
|
|
|
|
|
|