|
|
1.1 root 1: /*
2: * File: fstr.c
3: * Contents: center, left, map, repl, reverse, right, trim
4: */
5:
6: #include "../h/rt.h"
7:
8: /*
9: * center(s1,n,s2) - pad s1 on left and right with s2 to length n.
10: */
11:
12: FncDcl(center,3)
13: {
14: register char *s, *st;
15: word cnt, slen, hcnt;
16: char *sbuf, *s3;
17: char sbuf1[MaxCvtLen], sbuf2[MaxCvtLen];
18: extern char *alcstr();
19:
20: /*
21: * s1 must be a string. n must be a non-negative integer and defaults
22: * to 1. s2 must be a string and defaults to a blank.
23: */
24: if (cvstr(&Arg1, sbuf1) == NULL)
25: runerr(103, &Arg1);
26: defshort(&Arg2, 1);
27: if ((cnt = IntVal(Arg2)) < 0)
28: runerr(205, &Arg2);
29: defstr(&Arg3, sbuf2, &blank);
30:
31: strreq(cnt);
32:
33: if (StrLen(Arg3) == 0) {
34: /*
35: * The padding string is null, make it a blank.
36: */
37: slen = 1;
38: s3 = " ";
39: }
40: else {
41: slen = StrLen(Arg3);
42: s3 = StrLoc(Arg3);
43: }
44:
45: /*
46: * Get n bytes of string space for the new string. Start at the right
47: * of the new string and copy s2 into it from right to left as
48: * many times as will fit in the right half of the new string.
49: */
50: sbuf = alcstr(NULL, cnt);
51: hcnt = cnt / 2;
52: s = sbuf + cnt;
53: while (s > sbuf + hcnt) {
54: st = s3 + slen;
55: while (st > s3 && s > sbuf + hcnt)
56: *--s = *--st;
57: }
58:
59: /*
60: * Start at the left end of the new string and copy s1 into it from
61: * left to right as many time as will fit in the left half of the
62: * new string.
63: */
64: s = sbuf;
65: while (s < sbuf + hcnt) {
66: st = s3;
67: while (st < s3 + slen && s < sbuf + hcnt)
68: *s++ = *st++;
69: }
70:
71: slen = StrLen(Arg1);
72: if (cnt < slen) {
73: /*
74: * s1 is larger than the field to center it in. The source for the
75: * copy starts at the appropriate point in s1 and the destination
76: * starts at the left end of of the new string.
77: */
78: s = sbuf;
79: st = StrLoc(Arg1) + slen/2 - hcnt + (~cnt&slen&1);
80: }
81: else {
82: /*
83: * s1 is smaller than the field to center it in. The source for the
84: * copy starts at the left end of s1 and the destination starts at
85: * the appropriate point in the new string.
86: */
87: s = sbuf + hcnt - slen/2 - (~cnt&slen&1);
88: st = StrLoc(Arg1);
89: }
90: /*
91: * Perform the copy, moving min(*s1,n) bytes from st to s.
92: */
93: if (slen > cnt)
94: slen = cnt;
95: while (slen-- > 0)
96: *s++ = *st++;
97:
98: /*
99: * Return the new string.
100: */
101: StrLen(Arg0) = cnt;
102: StrLoc(Arg0) = sbuf;
103: Return;
104: }
105:
106:
107: /*
108: * left(s1,n,s2) - pad s1 on right with s2 to length n.
109: */
110:
111: FncDcl(left,3)
112: {
113: register char *s, *st;
114: word cnt, slen;
115: char *sbuf, *s3, sbuf1[MaxCvtLen], sbuf2[MaxCvtLen];
116: extern char *alcstr();
117:
118: /*
119: * s1 must be a string. n must be a non-negative integer and defaults
120: * to 1. s2 must be a string and defaults to a blank.
121: */
122: if (cvstr(&Arg1, sbuf1) == NULL)
123: runerr(103, &Arg1);
124: defshort(&Arg2, 1);
125: if ((cnt = IntVal(Arg2)) < 0)
126: runerr(205, &Arg2);
127: defstr(&Arg3, sbuf2, &blank);
128:
129: strreq(cnt);
130: if (StrLen(Arg3) == 0) {
131: /*
132: * The padding string is null, make it a blank.
133: */
134: slen = 1;
135: s3 = " ";
136: }
137: else {
138: slen = StrLen(Arg3);
139: s3 = StrLoc(Arg3);
140: }
141:
142: /*
143: * Get n bytes of string space. Start at the right end of the new
144: * string and copy s2 into the new string as many times as it fits.
145: * Note that s2 is copied from right to left.
146: */
147: sbuf = alcstr(NULL, cnt);
148: s = sbuf + cnt;
149: while (s > sbuf) {
150: st = s3 + slen;
151: while (st > s3 && s > sbuf)
152: *--s = *--st;
153: }
154:
155: /*
156: * Copy s1 into the new string, starting at the left end. If *s1 > n,
157: * only copy n bytes.
158: */
159: s = sbuf;
160: slen = StrLen(Arg1);
161: st = StrLoc(Arg1);
162: if (slen > cnt)
163: slen = cnt;
164: while (slen-- > 0)
165: *s++ = *st++;
166:
167: /*
168: * Return the new string.
169: */
170: StrLen(Arg0) = cnt;
171: StrLoc(Arg0) = sbuf;
172: Return;
173: }
174:
175: /*
176: * map(s1,s2,s3) - map s1, using s2 and s3.
177: */
178:
179: /* >map */
180: FncDcl(map,3)
181: {
182: register int i;
183: register word slen;
184: register char *s1, *s2, *s3;
185: char sbuf1[MaxCvtLen], sbuf2[MaxCvtLen], sbuf3[MaxCvtLen];
186: static char maptab[256];
187: extern char *alcstr();
188:
189: /*
190: * s1 must be a string; s2 and s3 default to &ucase and &lcase,
191: * respectively.
192: */
193: if (cvstr(&Arg1, sbuf1) == NULL)
194: runerr(103, &Arg1);
195: if (ChkNull(Arg2))
196: Arg2 = ucase;
197: if (ChkNull(Arg3))
198: Arg3 = lcase;
199:
200: /*
201: * If s2 and s3 are the same as for the last call of map,
202: * the current values in maptab can be used. Otherwise, the
203: * mapping information must information must be recomputed.
204: */
205: if (!EqlDesc(maps2,Arg2) || !EqlDesc(maps3,Arg3)) {
206: maps2 = Arg2;
207: maps3 = Arg3;
208:
209: /*
210: * Convert s2 and s3 to strings. They must be of the
211: * same length.
212: */
213: if (cvstr(&Arg2, sbuf2) == NULL)
214: runerr(103, &Arg2);
215: if (cvstr(&Arg3, sbuf3) == NULL)
216: runerr(103, &Arg3);
217: if (StrLen(Arg2) != StrLen(Arg3))
218: runerr(208, 0);
219:
220: /*
221: * The array maptab is used to perform the mapping. First,
222: * maptab[i] is initialized with i for i from 0 to 255.
223: * Then, for each character in s2, the position in maptab
224: * corresponding the value of the character is assigned
225: * the value of the character in s3 that is in the same
226: * position as the character from s2.
227: */
228: s2 = StrLoc(Arg2);
229: s3 = StrLoc(Arg3);
230: for (i = 0; i <= 255; i++)
231: maptab[i] = i;
232: for (slen = 0; slen < StrLen(Arg2); slen++)
233: maptab[s2[slen]&0377] = s3[slen];
234: }
235:
236: if (StrLen(Arg1) == 0) {
237: Arg0 = emptystr;
238: Return;
239: }
240:
241: /*
242: * The result is a string the size of s1; ensure that much space.
243: */
244: slen = StrLen(Arg1);
245: strreq(slen);
246: s1 = StrLoc(Arg1);
247:
248: /*
249: * Create the result string, but specify no value for it.
250: */
251: StrLen(Arg0) = slen;
252: StrLoc(Arg0) = alcstr(NULL, slen);
253: s2 = StrLoc(Arg0);
254: /*
255: * Run through the string using values in maptab to do the
256: * mapping.
257: */
258: while (slen-- > 0)
259: *s2++ = maptab[(*s1++)&0377];
260: Return;
261: }
262: /* <map */
263:
264: /*
265: * repl(s,n) - concatenate n copies of string s.
266: */
267:
268: /* >repl */
269: FncDcl(repl,2)
270: {
271: register char *sloc;
272: register int cnt;
273: long len;
274: char sbuf[MaxCvtLen];
275: extern char *alcstr();
276:
277: /*
278: * Make sure that Arg1 is a string.
279: */
280: if (cvstr(&Arg1, sbuf) == NULL)
281: runerr(103, &Arg1);
282:
283: /*
284: * Make sure that Arg2 is an integer.
285: */
286: switch (cvint(&Arg2, &len)) {
287:
288: case T_Integer:
289: if ((cnt = (int)len) >= 0) /* make sure count is not negative */
290: break;
291: runerr(205, &Arg2);
292:
293: case T_Longint:
294: runerr(205, &Arg2);
295:
296: default:
297: runerr(101, &Arg2);
298: }
299:
300: /*
301: * Make sure the resulting string will not be too long.
302: */
303: if ((len * StrLen(Arg1)) > MaxStrLen)
304: runerr(205, 0);
305:
306: /*
307: * Return an empty string if Arg2 is 0.
308: */
309: if (cnt == 0)
310: Arg0 = emptystr;
311:
312: else {
313: /*
314: * Ensure enough space for the replicated string and allocate
315: * a copy of s. Then allocate and copy s n - 1 times.
316: */
317: strreq(cnt * StrLen(Arg1));
318: sloc = alcstr(StrLoc(Arg1), StrLen(Arg1));
319: cnt--;
320: while (cnt--)
321: alcstr(StrLoc(Arg1), StrLen(Arg1));
322:
323: /*
324: * Make Arg0 a descriptor for the replicated string.
325: */
326: StrLen(Arg0) = (int)len * StrLen(Arg1);
327: StrLoc(Arg0) = sloc;
328: }
329: Return;
330: }
331: /* <repl */
332:
333:
334: /*
335: * reverse(s) - reverse string s.
336: */
337:
338: /* >reverse */
339: FncDcl(reverse,1)
340: {
341: register char c, *floc, *lloc;
342: register word slen;
343: char sbuf[MaxCvtLen];
344: extern char *alcstr();
345:
346: /*
347: * Make sure that Arg1 is a string.
348: */
349: if (cvstr(&Arg1, sbuf) == NULL)
350: runerr(103, &Arg1);
351: /* <reverse */
352:
353: /*
354: * Ensure that there is enough room and allocate a copy of s.
355: */
356: slen = StrLen(Arg1);
357: strreq(slen);
358: StrLen(Arg0) = slen;
359: StrLoc(Arg0) = alcstr(StrLoc(Arg1), slen);
360:
361: /*
362: * Point floc at the start of s and lloc at the end of s. Work floc
363: * and sloc along s in opposite directions, swapping the characters
364: * at floc and lloc.
365: */
366: floc = StrLoc(Arg0);
367: lloc = floc + --slen;
368: while (floc < lloc) {
369: c = *floc;
370: *floc++ = *lloc;
371: *lloc-- = c;
372: }
373: Return;
374: }
375:
376:
377: /*
378: * right(s1,n,s2) - pad s1 on left with s2 to length n.
379: */
380:
381: FncDcl(right,3)
382: {
383: register char *s, *st;
384: word cnt, slen;
385: char *sbuf, *s3, sbuf1[MaxCvtLen], sbuf2[MaxCvtLen];
386: extern char *alcstr();
387:
388: /*
389: * s1 must be a string. n must be a non-negative integer and defaults
390: * to 1. s2 must be a string and defaults to a blank.
391: */
392: if (cvstr(&Arg1, sbuf1) == NULL)
393: runerr(103, &Arg1);
394: defshort(&Arg2, 1);
395: if ((cnt = IntVal(Arg2)) < 0)
396: runerr(205, &Arg2);
397: defstr(&Arg3, sbuf2, &blank);
398:
399: strreq(cnt);
400:
401: if (StrLen(Arg3) == 0) {
402: /*
403: * The padding string is null, make it a blank.
404: */
405: slen = 1;
406: s3 = " ";
407: }
408: else {
409: slen = StrLen(Arg3);
410: s3 = StrLoc(Arg3);
411: }
412:
413: /*
414: * Get n bytes of string space. Start at the left end of the new
415: * string and copy s2 into the new string as many times as it fits.
416: */
417: sbuf = alcstr(NULL, cnt);
418: s = sbuf;
419: while (s < sbuf + cnt) {
420: st = s3;
421: while (st < s3 + slen && s < sbuf + cnt)
422: *s++ = *st++;
423: }
424:
425: /*
426: * Copy s1 into the new string, starting at the right end and copying
427: * s2 from right to left. If *s1 > n, only copy n bytes.
428: */
429: s = sbuf + cnt;
430: slen = StrLen(Arg1);
431: st = StrLoc(Arg1) + slen;
432: if (slen > cnt)
433: slen = cnt;
434: while (slen-- > 0)
435: *--s = *--st;
436:
437: /*
438: * Return the new string.
439: */
440: StrLen(Arg0) = cnt;
441: StrLoc(Arg0) = sbuf;
442: Return;
443: }
444:
445:
446: /*
447: * trim(s,c) - trim trailing characters in c from s.
448: */
449:
450: FncDcl(trim,2)
451: {
452: char *sloc;
453: char sbuf[MaxCvtLen];
454: int *cs, csbuf[CsetSize];
455: extern char *alcstr();
456: static int spcset[CsetSize] = /* just a blank */
457: cset_display(0, 0, 01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
458:
459: /*
460: * s must be a string; c defaults to a cset containing a blank.
461: */
462: switch (cvstr(&Arg1, sbuf)) {
463:
464: case NULL:
465: runerr(103, &Arg1);
466:
467: case Cvt:
468: strreq(StrLen(Arg1));
469: StrLoc(Arg1) = alcstr(StrLoc(Arg1), StrLen(Arg1));
470:
471: }
472:
473: defcset(&Arg2, &cs, csbuf, spcset);
474:
475: /*
476: * Start at the end of s and then back up until a character that is
477: * not in c is found. The actual trimming is done by having a descriptor
478: * that points at the string of s, but has a reduced length.
479: */
480: Arg0 = Arg1;
481: sloc = StrLoc(Arg1) + StrLen(Arg1) - 1;
482: while (sloc >= StrLoc(Arg1) && Testb(*sloc, cs)) {
483: sloc--;
484: StrLen(Arg0)--;
485: }
486: Return;
487: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.