static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb) { /* Just use a list to store the data */ Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); AppendStatElement(interp, listObj, "dev", sb->st_dev); AppendStatElement(interp, listObj, "ino", sb->st_ino); AppendStatElement(interp, listObj, "mode", sb->st_mode); AppendStatElement(interp, listObj, "nlink", sb->st_nlink); AppendStatElement(interp, listObj, "uid", sb->st_uid); AppendStatElement(interp, listObj, "gid", sb->st_gid); AppendStatElement(interp, listObj, "size", sb->st_size); AppendStatElement(interp, listObj, "atime", sb->st_atime); AppendStatElement(interp, listObj, "mtime", sb->st_mtime); AppendStatElement(interp, listObj, "ctime", sb->st_ctime); Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "type", -1)); Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, JimGetFileType((int)sb->st_mode), -1)); /* Was a variable specified? */ if (varName) { Jim_Obj *objPtr = Jim_GetVariable(interp, varName, JIM_NONE); if (objPtr) { if (Jim_DictSize(interp, objPtr) < 0) { /* This message matches the one from Tcl */ Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName); Jim_FreeNewObj(interp, listObj); return JIM_ERR; } if (Jim_IsShared(objPtr)) objPtr = Jim_DuplicateObj(interp, objPtr); /* Just cheat here and append as a list and convert to a dict */ Jim_ListAppendList(interp, objPtr, listObj); Jim_DictSize(interp, objPtr); Jim_InvalidateStringRep(objPtr); Jim_FreeNewObj(interp, listObj); listObj = objPtr; } Jim_SetVariable(interp, varName, listObj); } /* And also return the value */ Jim_SetResult(interp, listObj); return JIM_OK; }
/* [tcl::prefix] */ 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 (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; } 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_ERROR: if (++i == argc) { Jim_SetResultString(interp, "missing error options", -1); return JIM_ERR; } errorObj = argv[i]; if (Jim_Length(errorObj) % 2) { Jim_SetResultString(interp, "error options must have an even number of elements", -1); return JIM_ERR; } break; case OPT_MATCH_MESSAGE: if (++i == argc) { Jim_SetResultString(interp, "missing message", -1); return JIM_ERR; } message = Jim_String(argv[i]); break; } } /* Do the match */ 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); } 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 (tablesize == 0) { Jim_SetResultFormatted(interp, "bad %s \"%#s\": no valid options", message, stringObj); return JIM_ERR; } if (errorObj) { if (Jim_Length(errorObj) == 0) { Jim_SetEmptyResult(interp); return JIM_OK; } /* Do this the easy way. Build a list to evaluate */ 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); } return JIM_ERR; } case OPT_ALL: if (argc != 4) { Jim_WrongNumArgs(interp, 2, argv, "table string"); return JIM_ERR; } 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 (Jim_StringCompareLenObj(interp, argv[3], valObj, 0) == 0) { Jim_ListAppendElement(interp, objPtr, valObj); } } Jim_SetResult(interp, objPtr); return JIM_OK; } case OPT_LONGEST: if (argc != 4) { Jim_WrongNumArgs(interp, 2, argv, "table string"); return JIM_ERR; } 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 (Jim_StringCompareLenObj(interp, stringObj, valObj, 0)) { /* Does not begin with 'string' */ continue; } if (longeststr == NULL) { longestlen = Jim_Utf8Length(interp, valObj); longeststr = Jim_String(valObj); } else { longestlen = JimStringCommonLength(longeststr, longestlen, Jim_String(valObj), Jim_Utf8Length(interp, valObj)); } } if (longeststr) { Jim_SetResultString(interp, longeststr, longestlen); } return JIM_OK; } } return JIM_ERR; /* Cannot ever get here */ }