1
8
9
10
11
12
15
30
31
35
36
37
38
39
40
41
42
43
44
47
50
51
52
53
54
55
56
57
59
60
61
62
63
64
65
66
67
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
91
92
93
94
124
125
126
127
131
132
133
134
135
140
144
145
149
150
151
152
153
154
155
156
157
158
159
163
164
165
166
167
173
174
175
176
177
178
182
183
184
185
186
187
188
189
190
191
192
193
197
198
202
205
206
209
210
211
212
213
214
215
/* ... */
#include <jim.h>
#include "utf8.h"
/* ... */
static int JimStringCommonLength(const char *str1, int charlen1, const char *str2, int charlen2)
{
int maxlen = 0;
while (charlen1-- && charlen2--) {
int c1;
int c2;
str1 += utf8_tounicode(str1, &c1);
str2 += utf8_tounicode(str2, &c2);
if (c1 != c2) {
break;
}if (c1 != c2) { ... }
maxlen++;
}while (charlen1-- && charlen2--) { ... }
return maxlen;
}{ ... }
/* ... */
int JimStringComparePrefix(Jim_Interp *interp, Jim_Obj *firstObjPtr, Jim_Obj *secondObjPtr)
{
int l1 = Jim_Utf8Length(interp, firstObjPtr);
const char *s2 = Jim_String(secondObjPtr);
int l2 = Jim_Utf8Length(interp, secondObjPtr);
Jim_Obj *objPtr;
int ret;
if (l2 > l1) {
objPtr = Jim_NewStringObjUtf8(interp, s2, l1);
}if (l2 > l1) { ... }
else {
objPtr = secondObjPtr;
}else { ... }
Jim_IncrRefCount(objPtr);
ret = Jim_StringCompareObj(interp, firstObjPtr, objPtr, 0);
Jim_DecrRefCount(interp, objPtr);
return ret;
}{ ... }
/* ... */
static int Jim_TclPrefixCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Jim_Obj *objPtr;
Jim_Obj *stringObj;
int option;
static const char * const options[] = { "match", "all", "longest", NULL };
enum { OPT_MATCH, OPT_ALL, OPT_LONGEST };
if (argc < 2) {
Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arg ...?");
return JIM_ERR;
}if (argc < 2) { ... }
if (Jim_GetEnum(interp, argv[1], options, &option, NULL, JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK)
return Jim_CheckShowCommands(interp, argv[1], options);
switch (option) {
case OPT_MATCH:{
int i;
int ret;
int tablesize;
const char **table;
Jim_Obj *tableObj;
Jim_Obj *errorObj = NULL;
const char *message = "option";
static const char * const matchoptions[] = { "-error", "-exact", "-message", NULL };
enum { OPT_MATCH_ERROR, OPT_MATCH_EXACT, OPT_MATCH_MESSAGE };
int flags = JIM_ERRMSG | JIM_ENUM_ABBREV;
if (argc < 4) {
Jim_WrongNumArgs(interp, 2, argv, "?options? table string");
return JIM_ERR;
}if (argc < 4) { ... }
tableObj = argv[argc - 2];
stringObj = argv[argc - 1];
argc -= 2;
for (i = 2; i < argc; i++) {
int matchoption;
if (Jim_GetEnum(interp, argv[i], matchoptions, &matchoption, "option", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK)
return JIM_ERR;
switch (matchoption) {
case OPT_MATCH_EXACT:
flags &= ~JIM_ENUM_ABBREV;
break;
case OPT_MATCH_EXACT:
case OPT_MATCH_ERROR:
if (++i == argc) {
Jim_SetResultString(interp, "missing error options", -1);
return JIM_ERR;
}if (++i == argc) { ... }
errorObj = argv[i];
if (Jim_Length(errorObj) % 2) {
Jim_SetResultString(interp, "error options must have an even number of elements", -1);
return JIM_ERR;
}if (Jim_Length(errorObj) % 2) { ... }
break;
case OPT_MATCH_ERROR:
case OPT_MATCH_MESSAGE:
if (++i == argc) {
Jim_SetResultString(interp, "missing message", -1);
return JIM_ERR;
}if (++i == argc) { ... }
message = Jim_String(argv[i]);
break;case OPT_MATCH_MESSAGE:
}switch (matchoption) { ... }
}for (i = 2; i < argc; i++) { ... }
tablesize = Jim_ListLength(interp, tableObj);
table = Jim_Alloc((tablesize + 1) * sizeof(*table));
for (i = 0; i < tablesize; i++) {
Jim_ListIndex(interp, tableObj, i, &objPtr, JIM_NONE);
table[i] = Jim_String(objPtr);
}for (i = 0; i < tablesize; i++) { ... }
table[i] = NULL;
ret = Jim_GetEnum(interp, stringObj, table, &i, message, flags);
Jim_Free(table);
if (ret == JIM_OK) {
Jim_ListIndex(interp, tableObj, i, &objPtr, JIM_NONE);
Jim_SetResult(interp, objPtr);
return JIM_OK;
}if (ret == JIM_OK) { ... }
if (tablesize == 0) {
Jim_SetResultFormatted(interp, "bad %s \"%#s\": no valid options", message, stringObj);
return JIM_ERR;
}if (tablesize == 0) { ... }
if (errorObj) {
if (Jim_Length(errorObj) == 0) {
Jim_SetEmptyResult(interp);
return JIM_OK;
}if (Jim_Length(errorObj) == 0) { ... }
objPtr = Jim_NewStringObj(interp, "return -level 0 -code error", -1);
Jim_ListAppendList(interp, objPtr, errorObj);
Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp));
return Jim_EvalObjList(interp, objPtr);
}if (errorObj) { ... }
return JIM_ERR;
...}
case OPT_MATCH:
case OPT_ALL:
if (argc != 4) {
Jim_WrongNumArgs(interp, 2, argv, "table string");
return JIM_ERR;
}if (argc != 4) { ... }
else {
int i;
int listlen = Jim_ListLength(interp, argv[2]);
objPtr = Jim_NewListObj(interp, NULL, 0);
for (i = 0; i < listlen; i++) {
Jim_Obj *valObj = Jim_ListGetIndex(interp, argv[2], i);
if (JimStringComparePrefix(interp, argv[3], valObj) == 0) {
Jim_ListAppendElement(interp, objPtr, valObj);
}if (JimStringComparePrefix(interp, argv[3], valObj) == 0) { ... }
}for (i = 0; i < listlen; i++) { ... }
Jim_SetResult(interp, objPtr);
return JIM_OK;
}else { ... }
case OPT_ALL:
case OPT_LONGEST:
if (argc != 4) {
Jim_WrongNumArgs(interp, 2, argv, "table string");
return JIM_ERR;
}if (argc != 4) { ... }
else if (Jim_ListLength(interp, argv[2])) {
const char *longeststr = NULL;
int longestlen = 0;
int i;
int listlen = Jim_ListLength(interp, argv[2]);
stringObj = argv[3];
for (i = 0; i < listlen; i++) {
Jim_Obj *valObj = Jim_ListGetIndex(interp, argv[2], i);
if (JimStringComparePrefix(interp, stringObj, valObj)) {
continue;
}if (JimStringComparePrefix(interp, stringObj, valObj)) { ... }
if (longeststr == NULL) {
longestlen = Jim_Utf8Length(interp, valObj);
longeststr = Jim_String(valObj);
}if (longeststr == NULL) { ... }
else {
longestlen = JimStringCommonLength(longeststr, longestlen, Jim_String(valObj), Jim_Utf8Length(interp, valObj));
}else { ... }
}for (i = 0; i < listlen; i++) { ... }
if (longeststr) {
Jim_SetResultString(interp, longeststr, longestlen);
}if (longeststr) { ... }
return JIM_OK;
}else if (Jim_ListLength(interp, argv[2])) { ... }
case OPT_LONGEST: }switch (option) { ... }
return JIM_ERR;
}{ ... }
int Jim_tclprefixInit(Jim_Interp *interp)
{
Jim_PackageProvideCheck(interp, "tclprefix");
Jim_CreateCommand(interp, "tcl::prefix", Jim_TclPrefixCoreCommand, NULL, NULL);
return JIM_OK;
}{ ... }