mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
restore 'test --man --' oddness (re: fa6a180f
)
Following a community objection to its removal, the inline 'test'
manual page along with its strange method of invocation is
restored. I've taken the opportunity to correct several mistakes,
add some missing info, do some copy-editing, and document the way
to get these docs in the main (k)sh.1 manual.
Discussion:
fa6a180f (commitcomment-41897553)
This commit is contained in:
parent
fa6a180fdd
commit
77beec1e0d
4 changed files with 132 additions and 1 deletions
|
@ -202,8 +202,26 @@ int b_test(int argc, char *argv[],Shbltin_t *context)
|
|||
exitval = (*argv[2]!=0);
|
||||
goto done;
|
||||
}
|
||||
if(cp[0] != '-' || cp[2])
|
||||
if(cp[0] != '-' || cp[2] || cp[1]=='?')
|
||||
{ /*
|
||||
* The following ugly hack supports 'test --man --' and '[ --man -- ]' and related
|
||||
* getopts documentation options (which all overload the error message mechanism).
|
||||
* This is the only way to make the 'test' command self-documenting; supporting the
|
||||
* getopts doc options without the extra '--' argument would break the test/[ syntax.
|
||||
*/
|
||||
if(cp[0]=='-' && (cp[1]=='-' || cp[1]=='?') &&
|
||||
strcmp(argv[2],"--")==0)
|
||||
{
|
||||
char *av[3];
|
||||
av[0] = argv[0];
|
||||
av[1] = argv[1];
|
||||
av[2] = 0;
|
||||
optget(av,sh_opttest);
|
||||
errormsg(SH_DICT,ERROR_usage(2), "%s",opt_info.arg);
|
||||
return(2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
exitval = (!test_unop(tdata.sh,cp[1],argv[2]));
|
||||
goto done;
|
||||
case 2:
|
||||
|
|
|
@ -55,6 +55,109 @@ const Shtable_t shtab_testops[] =
|
|||
"", 0
|
||||
};
|
||||
|
||||
const char sh_opttest[] =
|
||||
"[-1c?\n@(#)$Id: test (AT&T Research/ksh93) 2020-08-31 $\n]"
|
||||
USAGE_LICENSE
|
||||
"[+NAME?test, [ - evaluate expression]"
|
||||
"[+DESCRIPTION?\btest\b evaluates expressions and returns its result using the "
|
||||
"exit status. Option parsing is not performed; all arguments, "
|
||||
"including \b--\b, are processed as operands. It is essential to quote "
|
||||
"expression arguments to suppress empty removal, field splitting, file "
|
||||
"name generation, and constructs such as redirection. If the command "
|
||||
"is invoked as \b[\b, a final \b]]\b argument is required and "
|
||||
"discarded. The evaluation of the expression depends on the number of "
|
||||
"operands, as follows:]"
|
||||
"{"
|
||||
"[+0?Evaluates to false.]"
|
||||
"[+1?True if argument is not an empty string.]"
|
||||
"[+2?If first operand is \b!\b, the result is True if the second "
|
||||
"operand is an empty string. Otherwise, it is evaluated "
|
||||
"as one of the unary expressions defined below. If the "
|
||||
"unary operator is invalid and the second argument is \b--\b, "
|
||||
"then the first argument is processed as a \bgetopts\b(1) "
|
||||
"help option.]"
|
||||
"[+3?If first operand is \b!\b, the result is True if the second "
|
||||
"and third operand evaluated as a unary expression is False. "
|
||||
"Otherwise, the three operands are evaluated as one of the "
|
||||
"binary expressions listed below.]"
|
||||
"[+4?If first operand is \b!\b, the result is True if the next "
|
||||
"three operands are a valid binary expression that is False.]"
|
||||
"}"
|
||||
"[+?For the following unary and binary operators:]"
|
||||
"{"
|
||||
"[+?If any \afile\a is a symlink, it is followed before testing, "
|
||||
"except for \b-L\b/\b-h\b"
|
||||
#if SHOPT_TEST_L
|
||||
"/\b-l\b"
|
||||
#endif
|
||||
".]"
|
||||
"[+?If any \afile\a is of the form \b/dev/fd/\b\an\a, "
|
||||
"then file descriptor \an\a is checked.]"
|
||||
"[+?Operators marked with a * are not part of the POSIX standard.]"
|
||||
"}"
|
||||
"[+UNARY OPERATORS?These evaluate as True if:]{"
|
||||
"[+-a \afile\a *?Same as \b-e\b.]"
|
||||
"[+-b \afile\a?\afile\a is a block special file.]"
|
||||
"[+-c \afile\a?\afile\a is a character special file.]"
|
||||
"[+-d \afile\a?\afile\a is a directory.]"
|
||||
"[+-e \afile\a?\afile\a exists and is not a broken symlink.]"
|
||||
"[+-f \afile\a?\afile\a is a regular file.]"
|
||||
"[+-g \afile\a?\afile\a has its set-group-id bit set.]"
|
||||
"[+-h \afile\a?Same as \b-L\b.]"
|
||||
"[+-k \afile\a *?\afile\a has its sticky bit on.]"
|
||||
#if SHOPT_TEST_L
|
||||
"[+-l \afile\a *?Same as \b-L\b.]"
|
||||
#endif
|
||||
"[+-n \astring\a?Length of \astring\a is non-zero.]"
|
||||
"[+-o \aoption\a *?Shell option \aoption\a is enabled.]"
|
||||
"[+-p \afile\a?\afile\a is a FIFO.]"
|
||||
"[+-r \afile\a?\afile\a is readable.]"
|
||||
"[+-s \afile\a?\afile\a has size > 0.]"
|
||||
"[+-t \anum\a?File descriptor number \anum\a is "
|
||||
"open and associated with a terminal.]"
|
||||
"[+-u \afile\a?\afile\a has its set-user-id bit set.]"
|
||||
"[+-v \avarname\a *?The variable \avarname\a is set.]"
|
||||
"[+-w \afile\a?\afile\a is writable.]"
|
||||
"[+-x \afile\a?\afile\a is executable, or if directory, searchable.]"
|
||||
"[+-z \astring\a?\astring\a is a zero-length string.]"
|
||||
"[+-G \afile\a *?Group of \afile\a is the effective "
|
||||
"group ID of the current process.]"
|
||||
"[+-L \afile\a?\afile\a is a symbolic link.]"
|
||||
"[+-N \afile\a *?\afile\a has been modified since it was last read.]"
|
||||
"[+-O \afile\a *?\afile\a exists and owner is the effective "
|
||||
"user ID of the current process.]"
|
||||
"[+-R \avarname\a *?\avarname\a is a name reference.]"
|
||||
"[+-S \afile\a?\afile\a is a socket.]"
|
||||
"}"
|
||||
"[+BINARY OPERATORS?These evaluate as True if:]{"
|
||||
"[+\astring1\a = \astring2\a?\astring1\a is equal to \astring2\a.]"
|
||||
"[+\astring1\a == \astring2\a *?Same as \b=\b.]"
|
||||
"[+\astring1\a != \astring2\a?\astring1\a is not equal to \astring2\a.]"
|
||||
"[+\anum1\a -eq \anum2\a?\anum1\a is numerically equal to \anum2\a.]"
|
||||
"[+\anum1\a -ne \anum2\a?\anum1\a is not numerically equal to \anum2\a.]"
|
||||
"[+\anum1\a -lt \anum2\a?\anum1\a is less than \anum2\a.]"
|
||||
"[+\anum1\a -le \anum2\a?\anum1\a is less than or equal to \anum2\a.]"
|
||||
"[+\anum1\a -gt \anum2\a?\anum1\a is greater than \anum2\a.]"
|
||||
"[+\anum1\a -ge \anum2\a?\anum1\a is greater than or equal to \anum2\a.]"
|
||||
"[+\afile1\a -nt \afile2\a *?\afile1\a is newer than \afile2\a "
|
||||
"or \afile1\a does not exist.]"
|
||||
"[+\afile1\a -ot \afile2\a *?\afile1\a is older than \afile2\a "
|
||||
"or \afile2\a does not exist.]"
|
||||
"[+\afile1\a -ef \afile2\a *?\afile1\a \afile1\a is a hard link or "
|
||||
"symbolic link to \afile2\a.]"
|
||||
"}"
|
||||
"\n"
|
||||
"\nexpression\n"
|
||||
"\n"
|
||||
"[+EXIT STATUS?]{"
|
||||
"[+0?The expression evaluated to True.]"
|
||||
"[+1?The expression evaluated to False.]"
|
||||
"[+>1?An error occurred.]"
|
||||
"}"
|
||||
|
||||
"[+SEE ALSO?\blet\b(1), \bexpr\b(1)]"
|
||||
;
|
||||
|
||||
const char test_opchars[] = "HLNRSVOGCaeohrwxdcbfugkv"
|
||||
#if SHOPT_TEST_L
|
||||
"l"
|
||||
|
|
|
@ -61,6 +61,7 @@ extern int test_unop(Shell_t*,int, const char*);
|
|||
extern int test_inode(const char*, const char*);
|
||||
extern int test_binop(Shell_t*,int, const char*, const char*);
|
||||
|
||||
extern const char sh_opttest[];
|
||||
extern const char test_opchars[];
|
||||
extern const char e_argument[];
|
||||
extern const char e_missing[];
|
||||
|
|
|
@ -7219,6 +7219,15 @@ grammatical ambiguities in the expressions. To avoid the many pitfalls
|
|||
arising from these issues, the \f3[[\fP compound command should be used
|
||||
instead. The primary purpose of the \f3test\fP and \f3[\fP commands is
|
||||
compatibility with other shells that lack \f3[[\fP.
|
||||
.RS
|
||||
.PP
|
||||
The \f3test\fP/\f3[\fP command does not parse options except if there are
|
||||
two arguments and the second is \f3--\fP. To access the inline documentation
|
||||
with an option such as \f3--man\fP, you need one of the forms
|
||||
.B test\ --man\ --
|
||||
or
|
||||
.BR [\ --man\ --\ ] .
|
||||
.RE
|
||||
.TP
|
||||
\f3times\fP
|
||||
Displays the accumulated user and system CPU times, one line with the times
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue