/*
* tclCmdIL.c --
*
* This file contains the top-level command routines for most of
* the Tcl built-in commands whose names begin with the letters
* I through L. It contains only commands in the generic core
* (i.e. those that don't depend much upon UNIX facilities).
*
* Copyright (c) 1987-1993 The Regents of the University of California.
* Copyright (c) 1994-1995 Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* SCCS: @(#) tclCmdIL.c 1.120 96/07/10 17:16:03
*/
#include "tclInt.h"
#include "tclPort.h"
/*
* The following variable holds the full path name of the binary
* from which this application was executed, or NULL if it isn't
* know. The value of the variable is set by the procedure
* Tcl_FindExecutable. The storage space is dynamically allocated.
*/
/*
* The variables below are used to implement the "lsort" command.
* Unfortunately, this use of static variables prevents "lsort"
* from being thread-safe, but there's no alternative given the
* current implementation of qsort. In a threaded environment
* these variables should be made thread-local if possible, or else
* "lsort" needs internal mutual exclusion.
*/
* NULL means no lsort is active. */
/* Mode for sorting: compare as strings,
* compare as numbers, or call
* user-defined command for
* comparison. */
* pre-initialized to hold base of
* command. */
* 1 means increasing order. */
* problem occurred while sorting; this
* executing a comparison command, so
* the sort was aborted. */
/*
* Forward declarations for procedures defined in this file:
*/
/*
*----------------------------------------------------------------------
*
* Tcl_IfCmd --
*
* This procedure is invoked to process the "if" Tcl command.
* See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
int
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
i = 1;
while (1) {
/*
* At this point in the loop, argv and argc refer to an expression
* to test, either for the main expression or an expression
* following an "elseif". The arguments after the expression must
* be "then" (optional) and a script to execute if the expression is
* true.
*/
if (i >= argc) {
return TCL_ERROR;
}
return result;
}
i++;
i++;
}
if (i >= argc) {
return TCL_ERROR;
}
if (value) {
}
/*
* The expression evaluated to false. Skip the command, then
* see if there is an "else" or "elseif" clause.
*/
i++;
if (i >= argc) {
return TCL_OK;
}
i++;
continue;
}
break;
}
/*
* Couldn't find a "then" or "elseif" clause to execute. Check now
* for an "else" clause. We know that there's at least one more
* argument when we get here.
*/
i++;
if (i >= argc) {
"wrong # args: no script following \"else\" argument",
(char *) NULL);
return TCL_ERROR;
}
}
}
/*
*----------------------------------------------------------------------
*
* Tcl_IncrCmd --
*
* This procedure is invoked to process the "incr" Tcl command.
* See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
int
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
int value;
" varName ?increment?\"", (char *) NULL);
return TCL_ERROR;
}
return TCL_ERROR;
}
"\n (reading value of variable to increment)");
return TCL_ERROR;
}
if (argc == 2) {
value += 1;
} else {
int increment;
"\n (reading increment)");
return TCL_ERROR;
}
}
return TCL_ERROR;
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* Tcl_JoinCmd --
*
* This procedure is invoked to process the "join" Tcl command.
* See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
int
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
char *joinString;
char **listArgv;
int listArgc, i;
if (argc == 2) {
joinString = " ";
} else if (argc == 3) {
} else {
" list ?joinString?\"", (char *) NULL);
return TCL_ERROR;
}
return TCL_ERROR;
}
for (i = 0; i < listArgc; i++) {
if (i == 0) {
} else {
}
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* Tcl_LindexCmd --
*
* This procedure is invoked to process the "lindex" Tcl command.
* See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
int
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
if (argc != 3) {
" list index\"", (char *) NULL);
return TCL_ERROR;
}
returnLast = 1;
} else {
returnLast = 0;
return TCL_ERROR;
}
}
if (index < 0) {
return TCL_OK;
}
return result;
}
if ((*next == 0) && returnLast) {
break;
}
p = next;
}
if (size == 0) {
return TCL_OK;
}
if (size >= TCL_RESULT_SIZE) {
}
if (parenthesized) {
} else {
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* Tcl_LinsertCmd --
*
* This procedure is invoked to process the "linsert" Tcl command.
* See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
int
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
if (argc < 4) {
" list index element ?element ...?\"", (char *) NULL);
return TCL_ERROR;
}
return TCL_ERROR;
}
/*
* Skip over the first "index" elements of the list, then add
* all of those elements to the result.
*/
size = 0;
return result;
}
}
if (*p == 0) {
} else {
char *end;
end++;
}
}
*end = 0;
}
/*
* Add the new list elements.
*/
for (i = 3; i < argc; i++) {
}
/*
* Append the remainder of the original list.
*/
if (*p != 0) {
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* Tcl_ListCmd --
*
* This procedure is invoked to process the "list" Tcl command.
* See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
int
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
if (argc >= 2) {
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* Tcl_LlengthCmd --
*
* This procedure is invoked to process the "llength" Tcl command.
* See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
int
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
char *element, *p;
if (argc != 2) {
" list\"", (char *) NULL);
return TCL_ERROR;
}
(int *) NULL);
return result;
}
if (*element == 0) {
break;
}
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* Tcl_LrangeCmd --
*
* This procedure is invoked to process the "lrange" Tcl command.
* See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
int
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
if (argc != 4) {
" list first last\"", (char *) NULL);
return TCL_ERROR;
}
firstIsEnd = 1;
} else {
firstIsEnd = 0;
return TCL_ERROR;
}
}
if (first < 0) {
first = 0;
}
} else {
return TCL_ERROR;
}
}
return TCL_OK;
}
/*
* Extract a range of fields.
*/
(int *) NULL);
return result;
}
if (*next == 0) {
if (firstIsEnd) {
} else {
}
break;
}
}
count++) {
(int *) NULL);
return result;
}
}
return TCL_OK;
}
/*
* Chop off trailing spaces.
*/
end--;
}
c = *end;
*end = 0;
*end = c;
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* Tcl_LreplaceCmd --
*
* This procedure is invoked to process the "lreplace" Tcl command.
* See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
int
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
if (argc < 4) {
" list first last ?element element ...?\"", (char *) NULL);
return TCL_ERROR;
}
firstIsEnd = 1;
} else {
firstIsEnd = 0;
"\": must be integer or \"end\"", (char *) NULL);
return TCL_ERROR;
}
}
} else {
"\": must be integer or \"end\"", (char *) NULL);
return TCL_ERROR;
}
}
if (first < 0) {
first = 0;
}
/*
* Skip over the elements of the list before "first".
*/
size = 0;
(int *) NULL);
return result;
}
if ((*next == 0) && firstIsEnd) {
break;
}
}
if (*p1 == 0) {
return TCL_ERROR;
}
/*
* Skip over the elements of the list up through "last".
*/
(int *) NULL);
return result;
}
}
/*
* Add the elements before "first" to the result. Remove any
* trailing white space, to make the result look as clean as
* possible (this matters primarily if the replacement string is
* empty).
*/
p1--;
}
*p1 = 0;
/*
* Add the new list elements.
*/
for (i = 4; i < argc; i++) {
}
/*
* Append the remainder of the original list.
*/
if (*p2 != 0) {
} else {
}
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* Tcl_LsearchCmd --
*
* This procedure is invoked to process the "lsearch" Tcl command.
* See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
int
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
#define EXACT 0
int listArgc;
char **listArgv;
if (argc == 4) {
} else {
"\": must be -exact, -glob, or -regexp", (char *) NULL);
return TCL_ERROR;
}
} else if (argc != 3) {
" ?mode? list pattern\"", (char *) NULL);
return TCL_ERROR;
}
return TCL_ERROR;
}
index = -1;
for (i = 0; i < listArgc; i++) {
match = 0;
switch (mode) {
case EXACT:
break;
case GLOB:
break;
case REGEXP:
if (match < 0) {
return TCL_ERROR;
}
break;
}
if (match) {
index = i;
break;
}
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* Tcl_LsortCmd --
*
* This procedure is invoked to process the "lsort" Tcl command.
* See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
int
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
int listArgc, i, c;
char **listArgv;
* prevent compiler warning. */
if (argc < 2) {
" ?-ascii? ?-integer? ?-real? ?-increasing? ?-decreasing?",
" ?-command string? list\"", (char *) NULL);
return TCL_ERROR;
}
if (sortInterp != NULL) {
return TCL_ERROR;
}
/*
* Parse arguments to set up the mode for the sort.
*/
sortInterp = interp;
sortIncreasing = 1;
if (length < 2) {
"\": must be -ascii, -integer, -real, -increasing",
" -decreasing, or -command", (char *) NULL);
goto done;
}
c = argv[i][1];
if (i == argc-2) {
" followed by comparison command", (char *) NULL);
goto done;
}
i++;
} else if ((c == 'd')
sortIncreasing = 0;
sortIncreasing = 1;
} else if ((c == 'r')
} else {
goto badSwitch;
}
}
}
goto done;
}
}
}
done:
sortInterp = NULL;
return sortCode;
}
/*
*----------------------------------------------------------------------
*
* SortCompareProc --
*
* This procedure is invoked by qsort to determine the proper
* ordering between two elements.
*
* Results:
* < 0 means first is "smaller" than "second", > 0 means "first"
* is larger than "second", and 0 means they should be treated
* as equal.
*
* Side effects:
* None, unless a user-defined comparison command does something
* weird.
*
*----------------------------------------------------------------------
*/
static int
{
int order;
order = 0;
/*
* Once an error has occurred, skip any future comparisons
* so as to preserve the error message in sortInterp->result.
*/
return order;
}
int a, b;
"\n (converting list element from string to integer)");
return order;
}
if (a > b) {
order = 1;
} else if (b > a) {
order = -1;
}
double a, b;
"\n (converting list element from string to real)");
return order;
}
if (a > b) {
order = 1;
} else if (b > a) {
order = -1;
}
} else {
int oldLength;
char *end;
/*
* Generate and evaluate a command to determine which string comes
* first.
*/
"\n (user-defined comparison command)");
return order;
}
/*
* Parse the result of the command.
*/
"comparison command returned non-numeric result",
(char *) NULL);
return order;
}
}
if (!sortIncreasing) {
}
return order;
}