This source file includes following definitions.
- Tcl_ProcCmd
- Tcl_GetVar
- Tcl_SetVar
- Tcl_ParseVar
- Tcl_SetCmd
- Tcl_GlobalCmd
- Tcl_UplevelCmd
- TclFindProc
- TclIsProc
- TclDeleteVars
- InterpProc
- ProcDeleteProc
- FindVar
- NewVar
#ifndef lint
static char rcsid[] = "$Header: /sprite/src/lib/tcl/RCS/tclProc.c,v 1.31 90/01/27 14:44:24 ouster Exp $ SPRITE (Berkeley)";
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "tclInt.h"
extern Var * FindVar();
extern int InterpProc();
extern Var * NewVar();
extern void ProcDeleteProc();
int
Tcl_ProcCmd(dummy, interp, argc, argv)
ClientData dummy;
Tcl_Interp *interp;
int argc;
char **argv;
{
register Interp *iPtr = (Interp *) interp;
register Proc *procPtr;
int result, argCount, i;
char **argArray;
if (argc != 4) {
sprintf(iPtr->result,
"wrong # args: should be \"%.50s name args body\"",
argv[0]);
return TCL_ERROR;
}
procPtr = (Proc *) ckalloc(sizeof(Proc));
procPtr->iPtr = iPtr;
procPtr->command = (char *) ckalloc((unsigned) strlen(argv[3]) + 1);
strcpy(procPtr->command, argv[3]);
procPtr->argPtr = NULL;
Tcl_CreateCommand(interp, argv[1], InterpProc,
(ClientData) procPtr, ProcDeleteProc);
result = Tcl_SplitList(interp, argv[2], &argCount, &argArray);
if (result != TCL_OK) {
return result;
}
for (i = 0; i < argCount; i++) {
int fieldCount, nameLength, valueLength;
char **fieldValues;
register Var *argPtr;
result = Tcl_SplitList(interp, argArray[i], &fieldCount,
&fieldValues);
if (result != TCL_OK) {
goto procError;
}
if (fieldCount > 2) {
sprintf(iPtr->result,
"too many fields in argument specifier \"%.50s\"",
argArray[i]);
result = TCL_ERROR;
goto procError;
}
if ((fieldCount == 0) || (*fieldValues[0] == 0)) {
sprintf(iPtr->result,
"procedure \"%.50s\" has argument with no name", argv[1]);
result = TCL_ERROR;
goto procError;
}
nameLength = strlen(fieldValues[0]);
if (fieldCount == 2) {
valueLength = strlen(fieldValues[1]);
} else {
valueLength = 0;
}
if (procPtr->argPtr == NULL) {
argPtr = (Var *) ckalloc(VAR_SIZE(nameLength, valueLength));
procPtr->argPtr = argPtr;
} else {
argPtr->nextPtr = (Var *) ckalloc(VAR_SIZE(nameLength, valueLength));
argPtr = argPtr->nextPtr;
}
strcpy(argPtr->name, fieldValues[0]);
if (fieldCount == 2) {
argPtr->value = argPtr->name + nameLength + 1;
strcpy(argPtr->value, fieldValues[1]);
} else {
argPtr->value = NULL;
}
argPtr->valueLength = valueLength;
argPtr->flags = 0;
argPtr->nextPtr = NULL;
ckfree((char *) fieldValues);
}
ckfree((char *) argArray);
return TCL_OK;
procError:
ckfree((char *) argArray);
return result;
}
char *
Tcl_GetVar(interp, varName, global)
Tcl_Interp *interp;
char *varName;
int global;
{
Var *varPtr;
Interp *iPtr = (Interp *) interp;
if (global || (iPtr->varFramePtr == NULL)) {
varPtr = FindVar(&iPtr->globalPtr, varName);
} else {
varPtr = FindVar(&iPtr->varFramePtr->varPtr, varName);
}
if (varPtr == NULL) {
return NULL;
}
if (varPtr->flags & VAR_GLOBAL) {
varPtr = varPtr->globalPtr;
}
if (varPtr->value == NULL) {
return "";
}
return varPtr->value;
}
void
Tcl_SetVar(interp, varName, newValue, global)
Tcl_Interp *interp;
char *varName;
char *newValue;
int global;
{
register Var *varPtr, **varListPtr;
register Interp *iPtr = (Interp *) interp;
int valueLength;
if (global || (iPtr->varFramePtr == NULL)) {
varListPtr = &iPtr->globalPtr;
} else {
varListPtr = &iPtr->varFramePtr->varPtr;
}
varPtr = FindVar(varListPtr, varName);
if (varPtr == NULL) {
varPtr = NewVar(varName, newValue);
varPtr->nextPtr = *varListPtr;
*varListPtr = varPtr;
} else {
if (varPtr->flags & VAR_GLOBAL) {
varPtr = varPtr->globalPtr;
}
valueLength = strlen(newValue);
if (valueLength > varPtr->valueLength) {
if (varPtr->flags & VAR_DYNAMIC) {
ckfree(varPtr->value);
}
varPtr->value = (char *) ckalloc((unsigned) valueLength + 1);
varPtr->flags |= VAR_DYNAMIC;
varPtr->valueLength = valueLength;
}
strcpy(varPtr->value, newValue);
}
}
char *
Tcl_ParseVar(interp, string, termPtr)
Tcl_Interp *interp;
register char *string;
char **termPtr;
{
char *name, c, *result;
string++;
if (*string == '{') {
string++;
name = string;
while ((*string != '}') && (*string != 0)) {
string++;
}
if (termPtr != 0) {
if (*string != 0) {
*termPtr = string+1;
} else {
*termPtr = string;
}
}
} else {
name = string;
while (isalnum(*string) || (*string == '_')) {
string++;
}
if (termPtr != 0) {
*termPtr = string;
}
}
c = *string;
*string = 0;
result = Tcl_GetVar(interp, name, 0);
if (!result) {
Tcl_Return(interp, (char *) NULL, TCL_STATIC);
sprintf(interp->result, "couldn't find variable \"%.50s\"", name);
}
*string = c;
return result;
}
int
Tcl_SetCmd(dummy, interp, argc, argv)
ClientData dummy;
register Tcl_Interp *interp;
int argc;
char **argv;
{
if (argc == 2) {
char *value;
value = Tcl_GetVar(interp, argv[1], 0);
if (value == 0) {
sprintf(interp->result, "couldn't find variable \"%.50s\"",
argv[1]);
return TCL_ERROR;
}
interp->result = value;
return TCL_OK;
} else if (argc == 3) {
Tcl_SetVar(interp, argv[1], argv[2], 0);
return TCL_OK;
} else {
sprintf(interp->result,
"wrong # args: should be \"%.50s varName [newValue]\"",
argv[0]);
return TCL_ERROR;
}
}
int
Tcl_GlobalCmd(dummy, interp, argc, argv)
ClientData dummy;
Tcl_Interp *interp;
int argc;
char **argv;
{
register Var *varPtr;
register Interp *iPtr = (Interp *) interp;
Var *gVarPtr;
if (argc < 2) {
sprintf(iPtr->result,
"too few args: should be \"%.50s varName varName ...\"",
argv[0]);
return TCL_ERROR;
}
if (iPtr->varFramePtr == NULL) {
return TCL_OK;
}
for (argc--, argv++; argc > 0; argc--, argv++) {
gVarPtr = FindVar(&iPtr->globalPtr, *argv);
if (gVarPtr == NULL) {
gVarPtr = NewVar(*argv, "");
gVarPtr->nextPtr = iPtr->globalPtr;
iPtr->globalPtr = gVarPtr;
}
varPtr = NewVar(*argv, "");
varPtr->flags |= VAR_GLOBAL;
varPtr->globalPtr = gVarPtr;
varPtr->nextPtr = iPtr->varFramePtr->varPtr;
iPtr->varFramePtr->varPtr = varPtr;
}
return TCL_OK;
}
int
Tcl_UplevelCmd(dummy, interp, argc, argv)
ClientData dummy;
Tcl_Interp *interp;
int argc;
char **argv;
{
register Interp *iPtr = (Interp *) interp;
int level, result;
char *end;
CallFrame *savedVarFramePtr, *framePtr;
if (argc < 3) {
sprintf(iPtr->result,
"too few args: should be \"%.50s level command ...\"",
argv[0]);
return TCL_ERROR;
}
level = strtol(argv[1], &end, 10);
if ((end == argv[1]) || (*end != '\0')) {
levelError:
sprintf(iPtr->result, "bad level \"%.50s\"", argv[1]);
return TCL_ERROR;
}
savedVarFramePtr = iPtr->varFramePtr;
if (level < 0) {
if (savedVarFramePtr == NULL) {
goto levelError;
}
level += savedVarFramePtr->level;
}
if (level == 0) {
iPtr->varFramePtr = NULL;
} else {
for (framePtr = savedVarFramePtr; framePtr != NULL;
framePtr = framePtr->callerVarPtr) {
if (framePtr->level == level) {
break;
}
}
if (framePtr == NULL) {
goto levelError;
}
iPtr->varFramePtr = framePtr;
}
if (argc == 3) {
result = Tcl_Eval(interp, argv[2], 0, (char **) NULL);
} else {
char *cmd;
cmd = Tcl_Concat(argc-2, argv+2);
result = Tcl_Eval(interp, cmd, 0, (char **) NULL);
}
if (result == TCL_ERROR) {
char msg[60];
sprintf(msg, " (\"uplevel\" body line %d)", interp->errorLine);
Tcl_AddErrorInfo(interp, msg);
}
iPtr->varFramePtr = savedVarFramePtr;
return result;
}
Proc *
TclFindProc(iPtr, procName)
Interp *iPtr;
char *procName;
{
Command *cmdPtr;
cmdPtr = TclFindCmd(iPtr, procName, 0);
if (cmdPtr == NULL) {
return NULL;
}
if (cmdPtr->proc != InterpProc) {
return NULL;
}
return (Proc *) cmdPtr->clientData;
}
Proc *
TclIsProc(cmdPtr)
Command *cmdPtr;
{
if (cmdPtr->proc == InterpProc) {
return (Proc *) cmdPtr->clientData;
}
return (Proc *) 0;
}
void
TclDeleteVars(iPtr)
Interp *iPtr;
{
register Var *varPtr;
for (varPtr = iPtr->globalPtr; varPtr != NULL; varPtr = varPtr->nextPtr) {
if (varPtr->flags & VAR_DYNAMIC) {
ckfree(varPtr->value);
}
ckfree((char *) varPtr);
}
}
int
InterpProc(procPtr, interp, argc, argv)
register Proc *procPtr;
Tcl_Interp *interp;
int argc;
char **argv;
{
char **args;
register Var *formalPtr, *argPtr;
register Interp *iPtr = (Interp *) interp;
CallFrame frame;
char *value, *end;
int result;
iPtr = procPtr->iPtr;
frame.varPtr = NULL;
if (iPtr->varFramePtr != NULL) {
frame.level = iPtr->varFramePtr->level + 1;
} else {
frame.level = 1;
}
frame.argc = argc;
frame.argv = argv;
frame.callerPtr = iPtr->framePtr;
frame.callerVarPtr = iPtr->varFramePtr;
iPtr->framePtr = &frame;
iPtr->varFramePtr = &frame;
for (formalPtr = procPtr->argPtr, args = argv+1, argc -= 1;
formalPtr != NULL;
formalPtr = formalPtr->nextPtr, args++, argc--) {
if ((formalPtr->nextPtr == NULL)
&& (strcmp(formalPtr->name, "args") == 0)) {
if (argc < 0) {
argc = 0;
}
value = Tcl_Merge(argc, args);
argPtr = NewVar(formalPtr->name, value);
ckfree(value);
argPtr->nextPtr = frame.varPtr;
frame.varPtr = argPtr;
argc = 0;
break;
} else if (argc > 0) {
value = *args;
} else if (formalPtr->value != NULL) {
value = formalPtr->value;
} else {
sprintf(iPtr->result,
"no value given for parameter \"%s\" to \"%s\"",
formalPtr->name, argv[0]);
result = TCL_ERROR;
goto procDone;
}
argPtr = NewVar(formalPtr->name, value);
argPtr->nextPtr = frame.varPtr;
frame.varPtr = argPtr;
}
if (argc > 0) {
sprintf(iPtr->result, "called \"%s\" with too many arguments",
argv[0]);
result = TCL_ERROR;
goto procDone;
}
result = Tcl_Eval(interp, procPtr->command, 0, &end);
if (result == TCL_RETURN) {
result = TCL_OK;
} else if (result == TCL_ERROR) {
char msg[100];
sprintf(msg, " (procedure \"%.50s\" line %d)", argv[0],
iPtr->errorLine);
Tcl_AddErrorInfo(interp, msg);
} else if (result == TCL_BREAK) {
iPtr->result = "invoked \"break\" outside of a loop";
result = TCL_ERROR;
} else if (result == TCL_CONTINUE) {
iPtr->result = "invoked \"continue\" outside of a loop";
result = TCL_ERROR;
}
procDone:
for (argPtr = frame.varPtr; argPtr != NULL; argPtr = argPtr->nextPtr) {
if (argPtr->flags & VAR_DYNAMIC) {
ckfree(argPtr->value);
}
ckfree((char *) argPtr);
}
iPtr->framePtr = frame.callerPtr;
iPtr->varFramePtr = frame.callerVarPtr;
return result;
}
void
ProcDeleteProc(procPtr)
register Proc *procPtr;
{
register Var *argPtr;
ckfree((char *) procPtr->command);
for (argPtr = procPtr->argPtr; argPtr != NULL; argPtr = argPtr->nextPtr) {
if (argPtr->flags & VAR_DYNAMIC) {
ckfree(argPtr->value);
}
ckfree((char *) argPtr);
}
ckfree((char *) procPtr);
}
Var *
FindVar(varListPtr, varName)
Var **varListPtr;
char *varName;
{
register Var *prev, *cur;
register char c;
c = *varName;
for (prev = NULL, cur = *varListPtr; cur != NULL;
prev = cur, cur = cur->nextPtr) {
if ((cur->name[0] == c) && (strcmp(cur->name, varName) == 0)) {
if (prev != NULL) {
prev->nextPtr = cur->nextPtr;
cur->nextPtr = *varListPtr;
*varListPtr = cur;
}
return cur;
}
}
return NULL;
}
Var *
NewVar(name, value)
char *name;
char *value;
{
register Var *varPtr;
int nameLength, valueLength;
nameLength = strlen(name);
valueLength = strlen(value);
if (valueLength < 20) {
valueLength = 20;
}
varPtr = (Var *) ckalloc(VAR_SIZE(nameLength, valueLength));
strcpy(varPtr->name, name);
varPtr->value = varPtr->name + nameLength + 1;
strcpy(varPtr->value, value);
varPtr->valueLength = valueLength;
varPtr->flags = 0;
varPtr->globalPtr = NULL;
varPtr->nextPtr = NULL;
return varPtr;
}