Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Add the 'info commands' and 'info vars' sub-commands to the TH1 core language, with tests. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA1: |
810e6c1e687c161fcd343e302e13e6f3 |
| User & Date: | mistachkin 2015-04-05 18:17:34.284 |
Context
|
2015-04-05
| ||
| 19:37 | Change the name of a new TH1 function to help clarify its purpose. ... (check-in: 22b3d0b6ab user: mistachkin tags: trunk) | |
| 18:17 | Add the 'info commands' and 'info vars' sub-commands to the TH1 core language, with tests. ... (check-in: 810e6c1e68 user: mistachkin tags: trunk) | |
| 04:40 | Normalize capitalization of Tcl on the TH1 commands page. ... (check-in: 0c63df2422 user: mistachkin tags: trunk) | |
Changes
Changes to src/th.c.
1 2 3 4 5 6 7 8 9 10 11 | /* ** The implementation of the TH core. This file contains the parser, and ** the implementation of the interface in th.h. */ #include "config.h" #include "th.h" #include <string.h> #include <assert.h> | | | | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
/*
** The implementation of the TH core. This file contains the parser, and
** the implementation of the interface in th.h.
*/
#include "config.h"
#include "th.h"
#include <string.h>
#include <assert.h>
typedef struct Th_Command Th_Command;
typedef struct Th_Frame Th_Frame;
typedef struct Th_Variable Th_Variable;
typedef struct Th_InterpAndList Th_InterpAndList;
/*
** Interpreter structure.
*/
struct Th_Interp {
Th_Vtab *pVtab; /* Copy of the argument passed to Th_CreateInterp() */
char *zResult; /* Current interpreter result (Th_Malloc()ed) */
|
| ︙ | ︙ | |||
85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
*/
struct Th_Variable {
int nRef; /* Number of references to this structure */
int nData; /* Number of bytes at Th_Variable.zData */
char *zData; /* Data for scalar variables */
Th_Hash *pHash; /* Data for array variables */
};
/*
** Hash table API:
*/
#define TH_HASHSIZE 257
struct Th_Hash {
Th_HashEntry *a[TH_HASHSIZE];
| > > > > > > > > > > > | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
*/
struct Th_Variable {
int nRef; /* Number of references to this structure */
int nData; /* Number of bytes at Th_Variable.zData */
char *zData; /* Data for scalar variables */
Th_Hash *pHash; /* Data for array variables */
};
/*
** This structure is used to pass complete context information to the
** hash iteration callback functions that need a Th_Interp and a list
** to operate on, e.g. thListAppend().
*/
struct Th_InterpAndList {
Th_Interp *interp; /* Associated interpreter context */
char **pzList; /* IN/OUT: Ptr to ptr to list */
int *pnList; /* IN/OUT: Current length of *pzList */
};
/*
** Hash table API:
*/
#define TH_HASHSIZE 257
struct Th_Hash {
Th_HashEntry *a[TH_HASHSIZE];
|
| ︙ | ︙ | |||
296 297 298 299 300 301 302 303 304 305 306 307 308 309 |
if( pCommand->xDel ){
pCommand->xDel((Th_Interp *)pContext, pCommand->pContext);
}
Th_Free((Th_Interp *)pContext, pEntry->pData);
pEntry->pData = 0;
return 1;
}
/*
** Push a new frame onto the stack.
*/
static int thPushFrame(Th_Interp *interp, Th_Frame *pFrame){
pFrame->paVar = Th_HashNew(interp);
pFrame->pCaller = interp->pFrame;
| > > > > > > > > > > > > > > > | 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 |
if( pCommand->xDel ){
pCommand->xDel((Th_Interp *)pContext, pCommand->pContext);
}
Th_Free((Th_Interp *)pContext, pEntry->pData);
pEntry->pData = 0;
return 1;
}
/*
** Argument pEntry points to an entry in a hash table. The key is
** the list element to be added.
**
** Argument pContext is a pointer to the Th_InterpAndList structure.
**
** Always returns non-zero.
*/
static int thListAppend(Th_HashEntry *pEntry, void *pContext){
Th_InterpAndList *pInterpAndList = (Th_InterpAndList *)pContext;
Th_ListAppend(pInterpAndList->interp, pInterpAndList->pzList,
pInterpAndList->pnList, pEntry->zKey, pEntry->nKey);
return 1;
}
/*
** Push a new frame onto the stack.
*/
static int thPushFrame(Th_Interp *interp, Th_Frame *pFrame){
pFrame->paVar = Th_HashNew(interp);
pFrame->pCaller = interp->pFrame;
|
| ︙ | ︙ | |||
2830 2831 2832 2833 2834 2835 2836 |
*z++ = zExp[i];
}
}
*z = '\0';
return Th_SetResult(interp, zBuf, -1);
}
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 |
*z++ = zExp[i];
}
}
*z = '\0';
return Th_SetResult(interp, zBuf, -1);
}
/*
** Appends all currently registered command names to the specified list
** and returns TH_OK upon success. Any other return value indicates an
** error.
*/
int Th_ListAppendCommands(Th_Interp *interp, char **pzList, int *pnList){
Th_InterpAndList *p = (Th_InterpAndList *)Th_Malloc(
interp, sizeof(Th_InterpAndList)
);
p->interp = interp;
p->pzList = pzList;
p->pnList = pnList;
Th_HashIterate(interp, interp->paCmd, thListAppend, p);
Th_Free(interp, p);
return TH_OK;
}
/*
** Appends all variable names for the current frame to the specified list
** and returns TH_OK upon success. Any other return value indicates an
** error. If the current frame cannot be obtained, TH_ERROR is returned.
*/
int Th_ListAppendVariables(Th_Interp *interp, char **pzList, int *pnList){
Th_Frame *pFrame = getFrame(interp, 0);
if( pFrame ){
Th_InterpAndList *p = (Th_InterpAndList *)Th_Malloc(
interp, sizeof(Th_InterpAndList)
);
p->interp = interp;
p->pzList = pzList;
p->pnList = pnList;
Th_HashIterate(interp, pFrame->paVar, thListAppend, p);
Th_Free(interp, p);
return TH_OK;
}else{
return TH_ERROR;
}
}
|
Changes to src/th.h.
| ︙ | ︙ | |||
136 137 138 139 140 141 142 143 144 145 146 147 148 149 | ** Functions for handling numbers and pointers. */ int Th_ToInt(Th_Interp *, const char *, int, int *); int Th_ToDouble(Th_Interp *, const char *, int, double *); int Th_SetResultInt(Th_Interp *, int); int Th_SetResultDouble(Th_Interp *, double); /* ** Drop in replacements for the corresponding standard library functions. */ int th_strlen(const char *); int th_isdigit(char); int th_isspace(char); int th_isalnum(char); | > > > > > > | 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | ** Functions for handling numbers and pointers. */ int Th_ToInt(Th_Interp *, const char *, int, int *); int Th_ToDouble(Th_Interp *, const char *, int, double *); int Th_SetResultInt(Th_Interp *, int); int Th_SetResultDouble(Th_Interp *, double); /* ** Functions for handling command and variable introspection. */ int Th_ListAppendCommands(Th_Interp *, char **, int *); int Th_ListAppendVariables(Th_Interp *, char **, int *); /* ** Drop in replacements for the corresponding standard library functions. */ int th_strlen(const char *); int th_isdigit(char); int th_isspace(char); int th_isalnum(char); |
| ︙ | ︙ |
Changes to src/th_lang.c.
| ︙ | ︙ | |||
846 847 848 849 850 851 852 | Th_SetResult(interp, z, n); return TH_OK; } /* ** TH Syntax: ** | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 |
Th_SetResult(interp, z, n);
return TH_OK;
}
/*
** TH Syntax:
**
** info exists VARNAME
*/
static int info_exists_command(
Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl
){
int rc;
if( argc!=3 ){
return Th_WrongNumArgs(interp, "info exists var");
}
rc = Th_ExistsVar(interp, argv[2], argl[2]);
Th_SetResultInt(interp, rc);
return TH_OK;
}
/*
** TH Syntax:
**
** info commands
*/
static int info_commands_command(
Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl
){
int rc;
char *zElem = 0;
int nElem = 0;
if( argc!=2 ){
return Th_WrongNumArgs(interp, "info commands");
}
rc = Th_ListAppendCommands(interp, &zElem, &nElem);
if( rc!=TH_OK ){
return rc;
}
Th_SetResult(interp, zElem, nElem);
return TH_OK;
}
/*
** TH Syntax:
**
** info vars
*/
static int info_vars_command(
Th_Interp *interp, void *ctx, int argc, const char **argv, int *argl
){
int rc;
char *zElem = 0;
int nElem = 0;
if( argc!=2 ){
return Th_WrongNumArgs(interp, "info vars");
}
rc = Th_ListAppendVariables(interp, &zElem, &nElem);
if( rc!=TH_OK ){
return rc;
}
Th_SetResult(interp, zElem, nElem);
return TH_OK;
}
/*
** TH Syntax:
**
** unset VAR
*/
static int unset_command(
|
| ︙ | ︙ | |||
941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 |
};
return Th_CallSubCommand(interp, ctx, argc, argv, argl, aSub);
}
/*
** TH Syntax:
**
** info exists VARNAME
*/
static int info_command(
Th_Interp *interp,
void *ctx,
int argc,
const char **argv,
int *argl
){
static const Th_SubCommand aSub[] = {
| > > > | > | 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 |
};
return Th_CallSubCommand(interp, ctx, argc, argv, argl, aSub);
}
/*
** TH Syntax:
**
** info commands
** info exists VARNAME
** info vars
*/
static int info_command(
Th_Interp *interp,
void *ctx,
int argc,
const char **argv,
int *argl
){
static const Th_SubCommand aSub[] = {
{ "commands", info_commands_command },
{ "exists", info_exists_command },
{ "vars", info_vars_command },
{ 0, 0 }
};
return Th_CallSubCommand(interp, ctx, argc, argv, argl, aSub);
}
/*
** Convert the script level frame specification (used by the commands
|
| ︙ | ︙ |
Changes to test/th1.test.
| ︙ | ︙ | |||
846 847 848 849 850 851 852 |
fossil test-th-eval "reinitialize; globalState configuration"
test th1-reinitialize-1 {$RESULT eq ""}
###############################################################################
fossil test-th-eval "reinitialize 1; globalState configuration"
test th1-reinitialize-2 {$RESULT ne ""}
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 |
fossil test-th-eval "reinitialize; globalState configuration"
test th1-reinitialize-1 {$RESULT eq ""}
###############################################################################
fossil test-th-eval "reinitialize 1; globalState configuration"
test th1-reinitialize-2 {$RESULT ne ""}
###############################################################################
#
# NOTE: This test may fail if the command names do not always come
# out in a deterministic order from TH1.
#
fossil test-th-eval "info commands"
test th1-info-commands-1 {$RESULT eq {linecount htmlize date stime\
enable_output uplevel http expr utime styleFooter catch if tclReady\
searchable reinitialize combobox lindex query html anoncap randhex\
llength for set break regexp styleHeader puts return checkout decorate\
artifact trace wiki proc hascap globalState continue getParameter\
hasfeature setting breakpoint upvar render repository string unset\
setParameter list error info rename anycap httpize}}
###############################################################################
fossil test-th-eval "info vars"
test th1-info-vars-1 {$RESULT eq ""}
###############################################################################
fossil test-th-eval "set x 1; info vars"
test th1-info-vars-2 {$RESULT eq "x"}
###############################################################################
fossil test-th-eval "set x 1; unset x; info vars"
test th1-info-vars-3 {$RESULT eq ""}
###############################################################################
fossil test-th-eval "proc foo {} {set x 1; info vars}; foo"
test th1-info-vars-4 {$RESULT eq "x"}
###############################################################################
fossil test-th-eval "set y 1; proc foo {} {set x 1; uplevel 1 {info vars}}; foo"
test th1-info-vars-5 {$RESULT eq "y"}
|
Changes to www/th1.md.
| ︙ | ︙ | |||
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | * break * catch SCRIPT ?VARIABLE? * continue * error ?STRING? * expr EXPR * for INIT-SCRIPT TEST-EXPR NEXT-SCRIPT BODY-SCRIPT * if EXPR SCRIPT (elseif EXPR SCRIPT)* ?else SCRIPT? * info exists VARNAME * lindex LIST INDEX * list ARG ... * llength LIST * proc NAME ARG-LIST BODY-SCRIPT * rename OLD NEW * return ?-code CODE? ?VALUE? * set VARNAME VALUE | > > | 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | * break * catch SCRIPT ?VARIABLE? * continue * error ?STRING? * expr EXPR * for INIT-SCRIPT TEST-EXPR NEXT-SCRIPT BODY-SCRIPT * if EXPR SCRIPT (elseif EXPR SCRIPT)* ?else SCRIPT? * info commands * info exists VARNAME * info vars * lindex LIST INDEX * list ARG ... * llength LIST * proc NAME ARG-LIST BODY-SCRIPT * rename OLD NEW * return ?-code CODE? ?VALUE? * set VARNAME VALUE |
| ︙ | ︙ |