1 From: Tony Balinski <ajbj@free.fr>
6 source/macro.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7 1 file changed, 123 insertions(+)
9 diff --quilt old/source/macro.c new/source/macro.c
10 --- old/source/macro.c
11 +++ new/source/macro.c
12 @@ -276,6 +276,8 @@ static int stringCompareMS(WindowInfo *w
13 DataValue *result, char **errMsg);
14 static int splitMS(WindowInfo *window, DataValue *argList, int nArgs,
15 DataValue *result, char **errMsg);
16 +static int joinMS(WindowInfo *window, DataValue *argList, int nArgs,
17 + DataValue *result, char **errMsg);
19 static int setBacklightStringMS(WindowInfo *window, DataValue *argList,
20 int nArgs, DataValue *result, char **errMsg);
21 @@ -551,6 +553,7 @@ static const BuiltInSubrName MacroSubrs[
22 { "timer_remove", timerRemoveMS },
23 { "escape_literal", escapeLiteralMS },
24 { "full_file_name", fullFileNameMS },
26 { NULL, NULL } /* sentinel */
29 @@ -4815,6 +4818,126 @@ static int splitMS(WindowInfo *window, D
33 +** This function is intended to concatenate values in an array of strings into a
34 +** single string. It acts as the inverse-operation to split().
36 +** string = join(array, separator[, start[, end]]))
38 +** It will only concatenate consecutive integer-indexed elements. If start and
39 +** end are given, these are the lower and upper bounds of the index range to
40 +** use; the element array[end] will not be accessed. By default, start is 0 and
41 +** end will be one beyond the last valid integer index of a contiguous sequence
42 +** starting at start.
44 +static int joinMS(WindowInfo *window, DataValue *argList, int nArgs,
45 + DataValue *result, char **errMsg)
47 + char stringStorage[TYPE_INT_STR_SIZE(int)];
49 + int start, end, index;
50 + size_t size, sepLen, separatorLen;
51 + char indexStr[TYPE_INT_STR_SIZE(int)], *pos;
52 + DataValue *array, element;
54 + result->tag = STRING_TAG;
55 + result->val.str.rep = PERM_ALLOC_STR("");
56 + result->val.str.len = 0;
58 + if (nArgs < 1 || nArgs > 4) {
59 + return wrongNArgsErr(errMsg);
61 + if (argList[0].tag != ARRAY_TAG) {
62 + M_FAILURE("first argument must be an array: %s");
64 + array = &argList[0];
66 + if (!readStringArg(argList[1], &sepStr, stringStorage, errMsg)) {
67 + M_FAILURE("second argument (separator) must be scalar: %s");
71 + sepStr = stringStorage;
75 + if (!readIntArg(argList[2], &start, errMsg))
76 + M_FAILURE("third argument (start index) must be numeric: %s");
82 + if (!readIntArg(argList[3], &end, errMsg))
83 + M_FAILURE("fourth argument (end index) must be numeric: %s");
91 + /* right: now for the real work */
92 + /* count the space we need to build the result string */
95 + separatorLen = strlen(sepStr);
96 + for (index = start; index != end; ++index) {
97 + if (ArrayGet(array, longAsStr(index), &element)) {
99 + sepLen = separatorLen;
101 + switch (element.tag) {
103 + size += strlen(longAsStr(element.val.n));
106 + size += element.val.str.len;
109 + M_FAILURE("cannot append non-scalar element to string: %s");
118 + /* allocate a string result */
119 + AllocNString(&result->val.str, size + 1);
120 + M_STR_ALLOC_ASSERT(*result);
121 + pos = result->val.str.rep;
123 + /* now fill it in */
125 + for (index = start; index != end; ++index) {
126 + if (ArrayGet(array, longAsStr(index), &element)) {
127 + memcpy(pos, sepStr, sepLen);
129 + sepLen = separatorLen;
131 + switch (element.tag) {
133 + strcpy(pos, longAsStr(element.val.n));
134 + pos += strlen(pos);
137 + memcpy(pos, element.val.str.rep, element.val.str.len);
138 + pos += element.val.str.len;
141 + M_FAILURE("internal error - inaccessible code attained: %s");
153 ** Set the backlighting string resource for the current window. If no parameter
154 ** is passed or the value "default" is passed, it attempts to set the preference
155 ** value of the resource. If the empty string is passed, the backlighting string