1 /* $Id: str.c,v 1.26 2020-10-18 00:46:41 phil Exp $ */
2
3 /*
4 * str.c - string functions
5 * 10/27/93
6 */
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif /* HAVE_CONFIG_H defined */
11
12 #include <stdlib.h> /* before stdio(?) */
13 #include <stdarg.h>
14 #include <ctype.h>
15 #include <stdio.h> /* for lib.h */
16
17 #include "h.h"
18 #include "snotypes.h"
19 #include "macros.h"
20 #include "lib.h" /* for prototypes */
21 #include "str.h"
22
23 void
trimsp(struct spec * sp1,struct spec * sp2)24 trimsp(struct spec *sp1, struct spec *sp2) {
25 register char *cp;
26 register int len;
27
28 len = S_L(sp2);
29 cp = S_SP(sp2) + len - 1;
30
31 while (len > 0 && isspace((unsigned char)*cp)) {
32 len--;
33 cp--;
34 }
35
36 _SPEC(sp1) = _SPEC(sp2);
37 S_L(sp1) = len;
38 }
39
40 void
raise1(struct spec * sp)41 raise1(struct spec *sp) {
42 register char *cp;
43 register int len;
44
45 len = S_L(sp);
46 cp = S_SP(sp);
47
48 while (len-- > 0) {
49 if (islower((unsigned char)*cp))
50 *cp = toupper((unsigned char)*cp);
51 cp++;
52 }
53 }
54
55 /* 8/19/96 -- for GENVUP/VPXPTR */
56 int
raise2(struct spec * sp1,struct spec * sp2)57 raise2(struct spec *sp1, struct spec *sp2) {
58 register char *sp, *dp;
59 register int len;
60 register int raised;
61
62 len = S_L(sp1);
63 sp = S_SP(sp1);
64 dp = S_SP(sp2);
65 raised = 0;
66
67 while (len-- > 0) {
68 if (islower((unsigned char)*sp)) {
69 *dp++ = toupper((unsigned char)*sp);
70 sp++;
71 raised++;
72 }
73 else
74 *dp++ = *sp++;
75 }
76 return raised > 0;
77 }
78
79 /* support for LPAD/RPAD 8/26/96 */
80 int
pad(struct descr * dir,struct spec * out,struct spec * subj,struct spec * pad)81 pad(struct descr *dir, /* LPAD=0,RPAD=1 */
82 struct spec *out,
83 struct spec *subj,
84 struct spec *pad) {
85 int npad;
86 size_t slen;
87 char *dp;
88 char pc;
89
90 slen = S_L(subj);
91 npad = S_L(out) - slen;
92 dp = S_SP(out);
93
94 if (S_L(pad) == 0) /* null string */
95 pc = ' '; /* default to space */
96 else
97 pc = *S_SP(pad);
98
99 if (D_A(dir) == 0) { /* LPAD */
100 while (npad-- > 0)
101 *dp++ = pc;
102 }
103
104 memcpy(dp, S_SP(subj), slen);
105 dp += slen;
106
107 if (D_A(dir) != 0) { /* RPAD */
108 while (npad-- > 0)
109 *dp++ = pc;
110 }
111
112 return 0;
113 }
114
115 /* support for REVERSE 9/18/96 */
116 int
reverse(struct spec * dest,struct spec * src)117 reverse(struct spec *dest, struct spec *src) {
118 register char *sp, *dp;
119 register int len;
120
121 len = S_L(src);
122 sp = S_SP(src) + len;
123 dp = S_SP(dest);
124
125 while (len--) {
126 *dp++ = *--sp;
127 }
128 return 0;
129 }
130
131 /* support for SUBSTR 9/18/96 */
132 int
substr(struct spec * dest,struct spec * src,struct descr * pos)133 substr(struct spec *dest, struct spec *src, struct descr *pos) {
134 register char *sp, *dp;
135 register int len;
136
137 sp = S_SP(src) + D_A(pos);
138 dp = S_SP(dest);
139 len = S_L(dest);
140
141 while (len--) {
142 *dp++ = *sp++;
143 }
144 return 0;
145 }
146
147 /* copy from specifier to c-string */
148 void
spec2str(struct spec * sp,char * dest,int size)149 spec2str(struct spec *sp, char *dest, int size) {
150 int l;
151
152 l = S_L(sp);
153 if (l > size-1)
154 l = size-1;
155
156 strncpy(dest, S_SP(sp), l);
157 dest[l] = '\0';
158 }
159
160 /* 2/15/2012 */
161 /* copy from specifier to c-string */
162 char *
mspec2str(struct spec * sp)163 mspec2str(struct spec *sp) {
164 int l = S_L(sp) + 1;
165 char *str = malloc(l);
166 if (str)
167 spec2str(sp, str, l);
168 return str;
169 }
170
171 /* 6/12/98 */
172
173 /*#define APDSP_NLENS 4096*/
174 #ifdef APDSP_NLENS
175 int apdsp_lens[APDSP_NLENS];
176 #endif /* APDSP_NLENS defined */
177
178 void
apdsp(struct spec * base,struct spec * str)179 apdsp(struct spec *base, struct spec *str) {
180 size_t len;
181 register char *src, *dst;
182
183 len = S_L(str);
184 src = S_SP(str);
185 dst = S_SP(base)+S_L(base);
186
187 #ifdef APDSP_NLENS
188 if (len > APDSP_NLENS)
189 apdsp_lens[APDSP_NLENS-1]++;
190 else
191 apdsp_lens[len]++;
192 #endif /* APDSP_NLENS defined */
193
194 S_L(base) += len;
195
196 #define THRESH 4
197 if (len >= THRESH) { /* XXX also check alignment? */
198 memcpy(dst, src, len);
199 }
200 else {
201 while (len > 0) {
202 *dst++ = *src++;
203 len--;
204 }
205 }
206 }
207
208 /* added 3/4/2012 */
209 char *
strjoin(const char * str0,...)210 strjoin(const char *str0, ...) {
211 va_list vp;
212 int len;
213 char *str;
214 const char *tp;
215
216 va_start(vp, str0);
217 len = strlen(str0) + 1;
218 while ((tp = va_arg(vp, const char *)))
219 len += strlen(tp);
220 va_end(vp);
221
222 str = malloc(len);
223 if (!str)
224 return NULL;
225
226 va_start(vp, str0);
227 strcpy(str, str0);
228 while ((tp = va_arg(vp, const char *)))
229 strcat(str, tp);
230 va_end(vp);
231 return str;
232 }
233
234 #ifdef BLOCKS
235 /* for BLOCKS; translated from the BAL macro 9/26/2013 */
236 /*
237 #define DEBUG_MERGSP
238 #define DEBUG_MERGSP2
239 */
240 #ifdef DEBUG_MERGSP2
241 #define DUMP(S,L) dump(#S, S, L)
242 static void
dump(char * n,char * s,int l)243 dump(char *n, char *s, int l) {
244 fprintf(stderr, "%-4s '", n);
245 while (l-- > 0) {
246 char c = *s++;
247 if (c == '\0') c = '~';
248 fputc(c, stderr);
249 }
250 fprintf(stderr, "'\n");
251 }
252 #else
253 #define DUMP(S,L)
254 #endif
255
256 void
mergsp(struct spec * sp1,struct spec * sp2,struct spec * sp3)257 mergsp(struct spec *sp1, struct spec *sp2, struct spec *sp3) {
258 int len = S_L(sp2); /* GR1 "length" */
259 char *dest = S_SP(sp1); /* GR2 "first string" */
260 char *src = S_SP(sp2); /* GR3 "2nd string" */
261 char bg = *S_SP(sp3); /* GR4 "background" */
262 char c; /* GR5 */
263 #ifdef DEBUG_MERGSP
264 fprintf(stderr, "mergsp len %d bg '%c'\n", len, bg);
265 #endif
266 if (len < 1)
267 return;
268 DUMP(src, len);
269 DUMP(dest, len);
270 do {
271 --len;
272 c = src[len];
273 if (c != bg)
274 dest[len] = c;
275 } while (len > 0);
276 DUMP(dest, S_L(sp2));
277 }
278
279 /* 10/11/2013 BLOCKS BLAND routine requires BLT-like behavior! */
280 void
movblk2(struct descr * d1,struct descr * d2,int_t len)281 movblk2(struct descr *d1, struct descr *d2, int_t len) {
282 while (len > 0) {
283 *++d1 = *++d2;
284 len -= DESCR;
285 }
286 }
287 #endif /* BLOCKS */
288