1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
/*
* File: ocat.r -- caterr, lconcat
*/
"x || y - concatenate strings x and y."
operator{1} || cater(x, y)
if !cnv:string(x) then
runerr(103, x)
if !cnv:string(y) then
runerr(103, y)
abstract {
return string
}
body {
char *s, *s2;
word len, i;
/*
* Optimization 1: The strings to be concatenated are already
* adjacent in memory; no allocation is required.
*/
if (StrLoc(x) + StrLen(x) == StrLoc(y)) {
StrLoc(result) = StrLoc(x);
StrLen(result) = StrLen(x) + StrLen(y);
return result;
}
else if ((StrLoc(x) + StrLen(x) == strfree)
&& (DiffPtrs(strend,strfree) > StrLen(y))) {
/*
* Optimization 2: The end of x is at the end of the string space.
* Hence, x was the last string allocated and need not be
* re-allocated. y is appended to the string space and the
* result is pointed to the start of x.
*/
result = x;
/*
* Append y to the end of the string space.
*/
Protect(alcstr(StrLoc(y),StrLen(y)), runerr(0));
/*
* Set the length of the result and return.
*/
StrLen(result) = StrLen(x) + StrLen(y);
return result;
}
/*
* Otherwise, allocate space for x and y, and copy them
* to the end of the string space.
*/
Protect(StrLoc(result) = alcstr(NULL, StrLen(x) + StrLen(y)), runerr(0));
s = StrLoc(result);
s2 = StrLoc(x);
len = StrLen(x);
for(i = 0; i < len; i++)
*s++ = *s2++;
s2 = StrLoc(y);
len = StrLen(y);
for(i = 0; i < len; i++)
*s++ = *s2++;
/*
* Set the length of the result and return.
*/
StrLen(result) = StrLen(x) + StrLen(y);
return result;
}
end
"x ||| y - concatenate lists x and y."
operator{1} ||| lconcat(x, y)
/*
* x and y must be lists.
*/
if !is:list(x) then
runerr(108, x)
if !is:list(y) then
runerr(108, y)
abstract {
return new list(store[(type(x) ++ type(y)).lst_elem])
}
body {
register struct b_list *bp1;
register struct b_lelem *lp1;
word size1, size2, size3;
/*
* Get the size of both lists.
*/
size1 = BlkLoc(x)->list.size;
size2 = BlkLoc(y)->list.size;
size3 = size1 + size2;
Protect(bp1 = (struct b_list *)alclist(size3), runerr(0));
Protect(lp1 = (struct b_lelem *)alclstb(size3,(word)0,size3), runerr(0));
bp1->listhead = bp1->listtail = (union block *)lp1;
#ifdef ListFix
lp1->listprev = lp1->listnext = (union block *)bp1;
#endif /* ListFix */
/*
* Make a copy of both lists in adjacent slots.
*/
cpslots(&x, lp1->lslots, (word)1, size1 + 1);
cpslots(&y, lp1->lslots + size1, (word)1, size2 + 1);
BlkLoc(x) = (union block *)bp1;
EVValD(&x, E_Lcreate);
return x;
}
end
|