From 1e102f41b22d41ff31df8802143e973b9d6c9afc Mon Sep 17 00:00:00 2001 From: Steve Bennett Date: Mon, 6 Jan 2014 08:18:20 +1000 Subject: file: simplify [file stat], var now optional The varname is now optional. The return value is a dictionary. Signed-off-by: Steve Bennett --- jim-file.c | 109 ++++++++++++++++++++++++++++++++---------------------------- jim_tcl.txt | 13 ++++---- 2 files changed, 64 insertions(+), 58 deletions(-) diff --git a/jim-file.c b/jim-file.c index 6b834a2..23b431f 100644 --- a/jim-file.c +++ b/jim-file.c @@ -142,54 +142,57 @@ static const char *JimGetFileType(int mode) * *---------------------------------------------------------------------- */ - -static int set_array_int_value(Jim_Interp *interp, Jim_Obj *container, const char *key, - jim_wide value) +static void AppendStatElement(Jim_Interp *interp, Jim_Obj *listObj, const char *key, int value) { - Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1); - Jim_Obj *valobj = Jim_NewWideObj(interp, value); - - if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) { - Jim_FreeObj(interp, nameobj); - Jim_FreeObj(interp, valobj); - return JIM_ERR; - } - return JIM_OK; + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, key, -1)); + Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, value)); } -static int set_array_string_value(Jim_Interp *interp, Jim_Obj *container, const char *key, - const char *value) +static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb) { - Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1); - Jim_Obj *valobj = Jim_NewStringObj(interp, value, -1); + /* 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_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) { - Jim_FreeObj(interp, nameobj); - Jim_FreeObj(interp, valobj); - return JIM_ERR; - } - return JIM_OK; -} + if (Jim_IsShared(objPtr)) + objPtr = Jim_DuplicateObj(interp, objPtr); -static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb) -{ - if (set_array_int_value(interp, varName, "dev", sb->st_dev) != JIM_OK) { - Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName); - return JIM_ERR; + /* 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); } - set_array_int_value(interp, varName, "ino", sb->st_ino); - set_array_int_value(interp, varName, "mode", sb->st_mode); - set_array_int_value(interp, varName, "nlink", sb->st_nlink); - set_array_int_value(interp, varName, "uid", sb->st_uid); - set_array_int_value(interp, varName, "gid", sb->st_gid); - set_array_int_value(interp, varName, "size", sb->st_size); - set_array_int_value(interp, varName, "atime", sb->st_atime); - set_array_int_value(interp, varName, "mtime", sb->st_mtime); - set_array_int_value(interp, varName, "ctime", sb->st_ctime); - set_array_string_value(interp, varName, "type", JimGetFileType((int)sb->st_mode)); /* And also return the value */ - Jim_SetResult(interp, Jim_GetVariable(interp, varName, 0)); + Jim_SetResult(interp, listObj); return JIM_OK; } @@ -553,10 +556,7 @@ static int file_stat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb) return JIM_OK; } -#ifndef HAVE_LSTAT -#define lstat stat -#endif - +#ifdef HAVE_LSTAT static int file_lstat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb) { const char *path = Jim_String(filename); @@ -567,6 +567,9 @@ static int file_lstat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb) } return JIM_OK; } +#else +#define file_lstat file_stat +#endif static int file_cmd_atime(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { @@ -695,6 +698,7 @@ static int file_cmd_type(Jim_Interp *interp, int argc, Jim_Obj *const *argv) return JIM_OK; } +#ifdef HAVE_LSTAT static int file_cmd_lstat(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { struct stat sb; @@ -702,8 +706,11 @@ static int file_cmd_lstat(Jim_Interp *interp, int argc, Jim_Obj *const *argv) if (file_lstat(interp, argv[0], &sb) != JIM_OK) { return JIM_ERR; } - return StoreStatData(interp, argv[1], &sb); + return StoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb); } +#else +#define file_cmd_lstat file_cmd_stat +#endif static int file_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { @@ -712,7 +719,7 @@ static int file_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv) if (file_stat(interp, argv[0], &sb) != JIM_OK) { return JIM_ERR; } - return StoreStatData(interp, argv[1], &sb); + return StoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb); } static const jim_subcmd_type file_command_table[] = { @@ -854,18 +861,18 @@ static const jim_subcmd_type file_command_table[] = { /* Description: Size of file */ }, { "stat", - "name var", + "name ?var?", file_cmd_stat, + 1, 2, - 2, - /* Description: Stores results of stat in var array */ + /* Description: Returns results of stat, and may store in var array */ }, { "lstat", - "name var", + "name ?var?", file_cmd_lstat, + 1, 2, - 2, - /* Description: Stores results of lstat in var array */ + /* Description: Returns results of lstat, and may store in var array */ }, { "type", "name", diff --git a/jim_tcl.txt b/jim_tcl.txt index 0e1be5d..6009555 100644 --- a/jim_tcl.txt +++ b/jim_tcl.txt @@ -61,6 +61,7 @@ Changes between 0.74 and 0.75 6. Add `socket pair` for a bidirectional pipe 7. Add --random-hash to randomise hash tables for greater security 8. `dict` now supports 'for', 'values', 'incr', 'append', 'lappend', 'update', 'info' and 'replace' +9. `file stat` no longer requires the variable name Changes between 0.73 and 0.74 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -2336,12 +2337,9 @@ abbreviation for +'option'+ is acceptable. The valid options are: If the file doesn't exist or its size cannot be queried then an error is generated. -+*file stat* 'name varName'+:: - Invoke the 'stat' kernel call on +'name'+, and use the - variable given by +'varName'+ to hold information returned from - the kernel call. - +'varName'+ is treated as an array variable, - and the following elements of that variable are set: 'atime', ++*file stat* 'name ?varName?'+:: + Invoke the 'stat' kernel call on +'name'+, and return the result + as a dictionary with the following keys: 'atime', 'ctime', 'dev', 'gid', 'ino', 'mode', 'mtime', 'nlink', 'size', 'type', 'uid'. Each element except 'type' is a decimal string with the value of @@ -2349,7 +2347,8 @@ abbreviation for +'option'+ is acceptable. The valid options are: manual entry for 'stat' for details on the meanings of the values. The 'type' element gives the type of the file in the same form returned by the command `file type`. - This command returns an empty string. + If +'varName'+ is specified, it is taken to be the name of an array + variable and the values are also stored into the array. +*file tail* 'name'+:: Return all of the characters in +'name'+ after the last slash. -- cgit v1.1