|
|
1.1 root 1: /*
2: * File: ocat.c
3: * Contents: cat, lconcat
4: */
5:
6: #include "../h/rt.h"
7:
8: /*
9: * x || y - concatenate strings x and y.
10: */
11:
12: /* >cat */
13: OpDcl(cat,2,"||")
14: {
15: char sbuf1[MaxCvtLen]; /* buffers for conversion to string */
16: char sbuf2[MaxCvtLen];
17: extern char *alcstr();
18:
19: /*
20: * Convert arguments to strings if necessary.
21: */
22: if (cvstr(&Arg1, sbuf1) == NULL)
23: runerr(103, &Arg1);
24: if (cvstr(&Arg2, sbuf2) == NULL)
25: runerr(103, &Arg2);
26:
27: /*
28: * Ensure space for the resulting string.
29: */
30: strreq(StrLen(Arg1) + StrLen(Arg2));
31:
32: if (StrLoc(Arg1) + StrLen(Arg1) == strfree)
33: /*
34: * The end of Arg1 is at the end of the string space. Hence, Arg1
35: * was the last string allocated. Arg1 is not copied. Instead,
36: * Arg2 is appended to the string space and the result is pointed
37: * to the start of Arg1.
38: */
39: StrLoc(Arg0) = StrLoc(Arg1);
40: else
41: /*
42: * Otherwise, append Arg1 to the end of the string space and point
43: * the result to the start of Arg1.
44: */
45: StrLoc(Arg0) = alcstr(StrLoc(Arg1),StrLen(Arg1));
46: /*
47: * Append Arg2 to the end of the string space.
48: */
49: alcstr(StrLoc(Arg2),StrLen(Arg2));
50: /*
51: * Set the length of the result and return.
52: */
53: StrLen(Arg0) = StrLen(Arg1) + StrLen(Arg2);
54: Return;
55: }
56: /* <cat */
57:
58:
59: /*
60: * x ||| y - concatenate lists x and y.
61: */
62:
63: OpDcl(lconcat,2,"|||")
64: {
65: register struct b_list *bp1, *bp2;
66: register struct b_lelem *lp1, *lp2;
67: word size1, size2;
68:
69: /*
70: * x and y must be lists.
71: */
72: if (Qual(Arg1) || Arg1.dword != D_List)
73: runerr(108, &Arg1);
74: if (Qual(Arg2) || Arg2.dword != D_List)
75: runerr(108, &Arg2);
76:
77: /*
78: * Get the size of both lists.
79: */
80: size1 = BlkLoc(Arg1)->list.size;
81: size2 = BlkLoc(Arg2)->list.size;
82:
83: /*
84: * Make a copy of both lists.
85: */
86: cplist(&Arg1, &Arg1, (word)1, size1 + 1);
87: cplist(&Arg2, &Arg2, (word)1, size2 + 1);
88:
89: /*
90: * Get a pointer to both lists. bp1 points to the copy of x and is
91: * the list that will be returned.
92: */
93: bp1 = (struct b_list *) BlkLoc(Arg1);
94: bp2 = (struct b_list *) BlkLoc(Arg2);
95:
96: /*
97: * Perform the concatenation by hooking the lists together so
98: * that the next list of x is y and the previous list of y is x.
99: */
100: lp1 = (struct b_lelem *) BlkLoc(bp1->listtail);
101: lp2 = (struct b_lelem *) BlkLoc(bp2->listhead);
102:
103: lp1->listnext.dword = D_Lelem;
104: BlkLoc(lp1->listnext) = (union block *) lp2;
105:
106: lp2->listprev.dword = D_Lelem;
107: BlkLoc(lp2->listprev) = (union block *) lp1;
108:
109: /*
110: * Adjust the size field to reflect the length of the concatenated lists.
111: */
112: bp1->size = size1 + size2;
113: BlkLoc(bp1->listtail) = BlkLoc(bp2->listtail);
114:
115: Arg0 = Arg1;
116: Return;
117: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.