int fbsql_numrows(Tcl_Interp *interp, int sql_number, int argc, char **argv) { Tcl_Obj *obj_result; /* set result object pointer */ obj_result = Tcl_GetObjResult(interp); Tcl_SetIntObj(obj_result,connection[sql_number].NUMROWS); return TCL_OK; }
CommandDef (length, clientData, interp, objc, objv) { Handle *handle; if (objc != 2) { Tcl_WrongNumArgs (interp, 1, objv, "filename"); return TCL_ERROR; } if (DbfGetHandleFromObj (interp, objv[1], &handle) != TCL_OK) { return TCL_ERROR; } Tcl_SetIntObj (Tcl_GetObjResult (interp), DBFGetRecordCount (handle->dbfHandle)); return TCL_OK; }
static void SetAttributeObj (Tcl_Obj * const objPtr, DBFHandle const dbfHandle, int const record, int const field) { if (DBFIsAttributeNULL (dbfHandle, record, field)) { return; } switch (DBFGetFieldInfo (dbfHandle, field, NULL, NULL, NULL)) { case FTInteger: Tcl_SetIntObj (objPtr, DBFReadIntegerAttribute (dbfHandle, record, field)); break; case FTDouble: Tcl_SetDoubleObj (objPtr, DBFReadDoubleAttribute (dbfHandle, record, field)); break; default: Tcl_SetStringObj (objPtr, DBFReadStringAttribute (dbfHandle, record, field), -1); } }
/* ** The "sqlite" command below creates a new Tcl command for each ** connection it opens to an SQLite database. This routine is invoked ** whenever one of those connection-specific commands is executed ** in Tcl. For example, if you run Tcl code like this: ** ** sqlite db1 "my_database" ** db1 close ** ** The first command opens a connection to the "my_database" database ** and calls that connection "db1". The second command causes this ** subroutine to be invoked. */ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ SqliteDb *pDb = (SqliteDb*)cd; int choice; int rc = TCL_OK; static const char *DB_strs[] = { "authorizer", "busy", "changes", "close", "commit_hook", "complete", "errorcode", "eval", "function", "last_insert_rowid", "last_statement_changes", "onecolumn", "progress", "rekey", "timeout", "trace", 0 }; enum DB_enum { DB_AUTHORIZER, DB_BUSY, DB_CHANGES, DB_CLOSE, DB_COMMIT_HOOK, DB_COMPLETE, DB_ERRORCODE, DB_EVAL, DB_FUNCTION, DB_LAST_INSERT_ROWID, DB_LAST_STATEMENT_CHANGES, DB_ONECOLUMN, DB_PROGRESS, DB_REKEY, DB_TIMEOUT, DB_TRACE }; if( objc<2 ){ Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ..."); return TCL_ERROR; } if( Tcl_GetIndexFromObj(interp, objv[1], DB_strs, "option", 0, &choice) ){ return TCL_ERROR; } switch( (enum DB_enum)choice ){ /* $db authorizer ?CALLBACK? ** ** Invoke the given callback to authorize each SQL operation as it is ** compiled. 5 arguments are appended to the callback before it is ** invoked: ** ** (1) The authorization type (ex: SQLITE_CREATE_TABLE, SQLITE_INSERT, ...) ** (2) First descriptive name (depends on authorization type) ** (3) Second descriptive name ** (4) Name of the database (ex: "main", "temp") ** (5) Name of trigger that is doing the access ** ** The callback should return on of the following strings: SQLITE_OK, ** SQLITE_IGNORE, or SQLITE_DENY. Any other return value is an error. ** ** If this method is invoked with no arguments, the current authorization ** callback string is returned. */ case DB_AUTHORIZER: { if( objc>3 ){ Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?"); }else if( objc==2 ){ if( pDb->zAuth ){ Tcl_AppendResult(interp, pDb->zAuth, 0); } }else{ char *zAuth; int len; if( pDb->zAuth ){ Tcl_Free(pDb->zAuth); } zAuth = Tcl_GetStringFromObj(objv[2], &len); if( zAuth && len>0 ){ pDb->zAuth = Tcl_Alloc( len + 1 ); strcpy(pDb->zAuth, zAuth); }else{ pDb->zAuth = 0; } #ifndef SQLITE_OMIT_AUTHORIZATION if( pDb->zAuth ){ pDb->interp = interp; sqlite_set_authorizer(pDb->db, auth_callback, pDb); }else{ sqlite_set_authorizer(pDb->db, 0, 0); } #endif } break; } /* $db busy ?CALLBACK? ** ** Invoke the given callback if an SQL statement attempts to open ** a locked database file. */ case DB_BUSY: { if( objc>3 ){ Tcl_WrongNumArgs(interp, 2, objv, "CALLBACK"); return TCL_ERROR; }else if( objc==2 ){ if( pDb->zBusy ){ Tcl_AppendResult(interp, pDb->zBusy, 0); } }else{ char *zBusy; int len; if( pDb->zBusy ){ Tcl_Free(pDb->zBusy); } zBusy = Tcl_GetStringFromObj(objv[2], &len); if( zBusy && len>0 ){ pDb->zBusy = Tcl_Alloc( len + 1 ); strcpy(pDb->zBusy, zBusy); }else{ pDb->zBusy = 0; } if( pDb->zBusy ){ pDb->interp = interp; sqlite_busy_handler(pDb->db, DbBusyHandler, pDb); }else{ sqlite_busy_handler(pDb->db, 0, 0); } } break; } /* $db progress ?N CALLBACK? ** ** Invoke the given callback every N virtual machine opcodes while executing ** queries. */ case DB_PROGRESS: { if( objc==2 ){ if( pDb->zProgress ){ Tcl_AppendResult(interp, pDb->zProgress, 0); } }else if( objc==4 ){ char *zProgress; int len; int N; if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &N) ){ return TCL_ERROR; }; if( pDb->zProgress ){ Tcl_Free(pDb->zProgress); } zProgress = Tcl_GetStringFromObj(objv[3], &len); if( zProgress && len>0 ){ pDb->zProgress = Tcl_Alloc( len + 1 ); strcpy(pDb->zProgress, zProgress); }else{ pDb->zProgress = 0; } #ifndef SQLITE_OMIT_PROGRESS_CALLBACK if( pDb->zProgress ){ pDb->interp = interp; sqlite_progress_handler(pDb->db, N, DbProgressHandler, pDb); }else{ sqlite_progress_handler(pDb->db, 0, 0, 0); } #endif }else{ Tcl_WrongNumArgs(interp, 2, objv, "N CALLBACK"); return TCL_ERROR; } break; } /* ** $db changes ** ** Return the number of rows that were modified, inserted, or deleted by ** the most recent "eval". */ case DB_CHANGES: { Tcl_Obj *pResult; int nChange; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 2, objv, ""); return TCL_ERROR; } nChange = sqlite_changes(pDb->db); pResult = Tcl_GetObjResult(interp); Tcl_SetIntObj(pResult, nChange); break; } /* ** $db last_statement_changes ** ** Return the number of rows that were modified, inserted, or deleted by ** the last statment to complete execution (excluding changes due to ** triggers) */ case DB_LAST_STATEMENT_CHANGES: { Tcl_Obj *pResult; int lsChange; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 2, objv, ""); return TCL_ERROR; } lsChange = sqlite_last_statement_changes(pDb->db); pResult = Tcl_GetObjResult(interp); Tcl_SetIntObj(pResult, lsChange); break; } /* $db close ** ** Shutdown the database */ case DB_CLOSE: { Tcl_DeleteCommand(interp, Tcl_GetStringFromObj(objv[0], 0)); break; } /* $db commit_hook ?CALLBACK? ** ** Invoke the given callback just before committing every SQL transaction. ** If the callback throws an exception or returns non-zero, then the ** transaction is aborted. If CALLBACK is an empty string, the callback ** is disabled. */ case DB_COMMIT_HOOK: { if( objc>3 ){ Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?"); }else if( objc==2 ){ if( pDb->zCommit ){ Tcl_AppendResult(interp, pDb->zCommit, 0); } }else{ char *zCommit; int len; if( pDb->zCommit ){ Tcl_Free(pDb->zCommit); } zCommit = Tcl_GetStringFromObj(objv[2], &len); if( zCommit && len>0 ){ pDb->zCommit = Tcl_Alloc( len + 1 ); strcpy(pDb->zCommit, zCommit); }else{ pDb->zCommit = 0; } if( pDb->zCommit ){ pDb->interp = interp; sqlite_commit_hook(pDb->db, DbCommitHandler, pDb); }else{ sqlite_commit_hook(pDb->db, 0, 0); } } break; } /* $db complete SQL ** ** Return TRUE if SQL is a complete SQL statement. Return FALSE if ** additional lines of input are needed. This is similar to the ** built-in "info complete" command of Tcl. */ case DB_COMPLETE: { Tcl_Obj *pResult; int isComplete; if( objc!=3 ){ Tcl_WrongNumArgs(interp, 2, objv, "SQL"); return TCL_ERROR; } isComplete = sqlite_complete( Tcl_GetStringFromObj(objv[2], 0) ); pResult = Tcl_GetObjResult(interp); Tcl_SetBooleanObj(pResult, isComplete); break; } /* ** $db errorcode ** ** Return the numeric error code that was returned by the most recent ** call to sqlite_exec(). */ case DB_ERRORCODE: { Tcl_SetObjResult(interp, Tcl_NewIntObj(pDb->rc)); break; } /* ** $db eval $sql ?array { ...code... }? ** ** The SQL statement in $sql is evaluated. For each row, the values are ** placed in elements of the array named "array" and ...code... is executed. ** If "array" and "code" are omitted, then no callback is every invoked. ** If "array" is an empty string, then the values are placed in variables ** that have the same name as the fields extracted by the query. */ case DB_EVAL: { CallbackData cbData; char *zErrMsg; char *zSql; #ifdef UTF_TRANSLATION_NEEDED Tcl_DString dSql; int i; #endif if( objc!=5 && objc!=3 ){ Tcl_WrongNumArgs(interp, 2, objv, "SQL ?ARRAY-NAME CODE?"); return TCL_ERROR; } pDb->interp = interp; zSql = Tcl_GetStringFromObj(objv[2], 0); #ifdef UTF_TRANSLATION_NEEDED Tcl_DStringInit(&dSql); Tcl_UtfToExternalDString(NULL, zSql, -1, &dSql); zSql = Tcl_DStringValue(&dSql); #endif Tcl_IncrRefCount(objv[2]); if( objc==5 ){ cbData.interp = interp; cbData.once = 1; cbData.zArray = Tcl_GetStringFromObj(objv[3], 0); cbData.pCode = objv[4]; cbData.tcl_rc = TCL_OK; cbData.nColName = 0; cbData.azColName = 0; zErrMsg = 0; Tcl_IncrRefCount(objv[3]); Tcl_IncrRefCount(objv[4]); rc = sqlite_exec(pDb->db, zSql, DbEvalCallback, &cbData, &zErrMsg); Tcl_DecrRefCount(objv[4]); Tcl_DecrRefCount(objv[3]); if( cbData.tcl_rc==TCL_BREAK ){ cbData.tcl_rc = TCL_OK; } }else{ Tcl_Obj *pList = Tcl_NewObj(); cbData.tcl_rc = TCL_OK; rc = sqlite_exec(pDb->db, zSql, DbEvalCallback2, pList, &zErrMsg); Tcl_SetObjResult(interp, pList); } pDb->rc = rc; if( rc==SQLITE_ABORT ){ if( zErrMsg ) free(zErrMsg); rc = cbData.tcl_rc; }else if( zErrMsg ){ Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE); free(zErrMsg); rc = TCL_ERROR; }else if( rc!=SQLITE_OK ){ Tcl_AppendResult(interp, sqlite_error_string(rc), 0); rc = TCL_ERROR; }else{ } Tcl_DecrRefCount(objv[2]); #ifdef UTF_TRANSLATION_NEEDED Tcl_DStringFree(&dSql); if( objc==5 && cbData.azColName ){ for(i=0; i<cbData.nColName; i++){ if( cbData.azColName[i] ) free(cbData.azColName[i]); } free(cbData.azColName); cbData.azColName = 0; } #endif return rc; } /* ** $db function NAME SCRIPT ** ** Create a new SQL function called NAME. Whenever that function is ** called, invoke SCRIPT to evaluate the function. */ case DB_FUNCTION: { SqlFunc *pFunc; char *zName; char *zScript; int nScript; if( objc!=4 ){ Tcl_WrongNumArgs(interp, 2, objv, "NAME SCRIPT"); return TCL_ERROR; } zName = Tcl_GetStringFromObj(objv[2], 0); zScript = Tcl_GetStringFromObj(objv[3], &nScript); pFunc = (SqlFunc*)Tcl_Alloc( sizeof(*pFunc) + nScript + 1 ); if( pFunc==0 ) return TCL_ERROR; pFunc->interp = interp; pFunc->pNext = pDb->pFunc; pFunc->zScript = (char*)&pFunc[1]; strcpy(pFunc->zScript, zScript); sqlite_create_function(pDb->db, zName, -1, tclSqlFunc, pFunc); sqlite_function_type(pDb->db, zName, SQLITE_NUMERIC); break; } /* ** $db last_insert_rowid ** ** Return an integer which is the ROWID for the most recent insert. */ case DB_LAST_INSERT_ROWID: { Tcl_Obj *pResult; int rowid; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 2, objv, ""); return TCL_ERROR; } rowid = sqlite_last_insert_rowid(pDb->db); pResult = Tcl_GetObjResult(interp); Tcl_SetIntObj(pResult, rowid); break; } /* ** $db onecolumn SQL ** ** Return a single column from a single row of the given SQL query. */ case DB_ONECOLUMN: { char *zSql; char *zErrMsg = 0; if( objc!=3 ){ Tcl_WrongNumArgs(interp, 2, objv, "SQL"); return TCL_ERROR; } zSql = Tcl_GetStringFromObj(objv[2], 0); rc = sqlite_exec(pDb->db, zSql, DbEvalCallback3, interp, &zErrMsg); if( rc==SQLITE_ABORT ){ rc = SQLITE_OK; }else if( zErrMsg ){ Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE); free(zErrMsg); rc = TCL_ERROR; }else if( rc!=SQLITE_OK ){ Tcl_AppendResult(interp, sqlite_error_string(rc), 0); rc = TCL_ERROR; } break; } /* ** $db rekey KEY ** ** Change the encryption key on the currently open database. */ case DB_REKEY: { int nKey; void *pKey; if( objc!=3 ){ Tcl_WrongNumArgs(interp, 2, objv, "KEY"); return TCL_ERROR; } pKey = Tcl_GetByteArrayFromObj(objv[2], &nKey); #ifdef SQLITE_HAS_CODEC rc = sqlite_rekey(pDb->db, pKey, nKey); if( rc ){ Tcl_AppendResult(interp, sqlite_error_string(rc), 0); rc = TCL_ERROR; } #endif break; } /* ** $db timeout MILLESECONDS ** ** Delay for the number of milliseconds specified when a file is locked. */ case DB_TIMEOUT: { int ms; if( objc!=3 ){ Tcl_WrongNumArgs(interp, 2, objv, "MILLISECONDS"); return TCL_ERROR; } if( Tcl_GetIntFromObj(interp, objv[2], &ms) ) return TCL_ERROR; sqlite_busy_timeout(pDb->db, ms); break; } /* $db trace ?CALLBACK? ** ** Make arrangements to invoke the CALLBACK routine for each SQL statement ** that is executed. The text of the SQL is appended to CALLBACK before ** it is executed. */ case DB_TRACE: { if( objc>3 ){ Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?"); }else if( objc==2 ){ if( pDb->zTrace ){ Tcl_AppendResult(interp, pDb->zTrace, 0); } }else{ char *zTrace; int len; if( pDb->zTrace ){ Tcl_Free(pDb->zTrace); } zTrace = Tcl_GetStringFromObj(objv[2], &len); if( zTrace && len>0 ){ pDb->zTrace = Tcl_Alloc( len + 1 ); strcpy(pDb->zTrace, zTrace); }else{ pDb->zTrace = 0; } if( pDb->zTrace ){ pDb->interp = interp; sqlite_trace(pDb->db, DbTraceHandler, pDb); }else{ sqlite_trace(pDb->db, 0, 0); } } break; } } /* End of the SWITCH statement */ return rc; }
/* ARGSUSED */ int Tcl_ThreadObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); int option; static const char *threadOptions[] = { "create", "exit", "id", "join", "names", "send", "wait", "errorproc", NULL }; enum options { THREAD_CREATE, THREAD_EXIT, THREAD_ID, THREAD_JOIN, THREAD_NAMES, THREAD_SEND, THREAD_WAIT, THREAD_ERRORPROC }; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?args?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], threadOptions, "option", 0, &option) != TCL_OK) { return TCL_ERROR; } /* * Make sure the initial thread is on the list before doing anything. */ if (tsdPtr->interp == NULL) { Tcl_MutexLock(&threadMutex); tsdPtr->interp = interp; ListUpdateInner(tsdPtr); Tcl_CreateThreadExitHandler(ThreadExitProc, NULL); Tcl_MutexUnlock(&threadMutex); } switch ((enum options)option) { case THREAD_CREATE: { char *script; int joinable, len; if (objc == 2) { /* * Neither joinable nor special script */ joinable = 0; script = "testthread wait"; /* Just enter event loop */ } else if (objc == 3) { /* * Possibly -joinable, then no special script, no joinable, then * its a script. */ script = Tcl_GetStringFromObj(objv[2], &len); if ((len > 1) && (script [0] == '-') && (script [1] == 'j') && (0 == strncmp (script, "-joinable", (size_t) len))) { joinable = 1; script = "testthread wait"; /* Just enter event loop */ } else { /* * Remember the script */ joinable = 0; } } else if (objc == 4) { /* * Definitely a script available, but is the flag -joinable? */ script = Tcl_GetStringFromObj(objv[2], &len); joinable = ((len > 1) && (script [0] == '-') && (script [1] == 'j') && (0 == strncmp(script, "-joinable", (size_t) len))); script = Tcl_GetString(objv[3]); } else { Tcl_WrongNumArgs(interp, 2, objv, "?-joinable? ?script?"); return TCL_ERROR; } return TclCreateThread(interp, script, joinable); } case THREAD_EXIT: if (objc > 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } ListRemove(NULL); Tcl_ExitThread(0); return TCL_OK; case THREAD_ID: if (objc == 2) { Tcl_Obj *idObj = Tcl_NewLongObj((long) Tcl_GetCurrentThread()); Tcl_SetObjResult(interp, idObj); return TCL_OK; } else { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } case THREAD_JOIN: { long id; int result, status; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "id"); return TCL_ERROR; } if (Tcl_GetLongFromObj(interp, objv[2], &id) != TCL_OK) { return TCL_ERROR; } result = Tcl_JoinThread ((Tcl_ThreadId) id, &status); if (result == TCL_OK) { Tcl_SetIntObj (Tcl_GetObjResult (interp), status); } else { char buf [20]; sprintf(buf, "%ld", id); Tcl_AppendResult(interp, "cannot join thread ", buf, NULL); } return result; } case THREAD_NAMES: if (objc > 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } return TclThreadList(interp); case THREAD_SEND: { long id; char *script; int wait, arg; if ((objc != 4) && (objc != 5)) { Tcl_WrongNumArgs(interp, 2, objv, "?-async? id script"); return TCL_ERROR; } if (objc == 5) { if (strcmp("-async", Tcl_GetString(objv[2])) != 0) { Tcl_WrongNumArgs(interp, 2, objv, "?-async? id script"); return TCL_ERROR; } wait = 0; arg = 3; } else { wait = 1; arg = 2; } if (Tcl_GetLongFromObj(interp, objv[arg], &id) != TCL_OK) { return TCL_ERROR; } arg++; script = Tcl_GetString(objv[arg]); return TclThreadSend(interp, (Tcl_ThreadId) id, script, wait); } case THREAD_ERRORPROC: { /* * Arrange for this proc to handle thread death errors. */ char *proc; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "proc"); return TCL_ERROR; } Tcl_MutexLock(&threadMutex); errorThreadId = Tcl_GetCurrentThread(); if (errorProcString) { ckfree(errorProcString); } proc = Tcl_GetString(objv[2]); errorProcString = ckalloc(strlen(proc)+1); strcpy(errorProcString, proc); Tcl_MutexUnlock(&threadMutex); return TCL_OK; } case THREAD_WAIT: while (1) { (void) Tcl_DoOneEvent(TCL_ALL_EVENTS); } } return TCL_OK; }
static int TestintobjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int intValue, varIndex, i; long longValue; const char *index, *subCmd, *string; if (objc < 3) { wrongNumArgs: Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?"); return TCL_ERROR; } index = Tcl_GetString(objv[2]); if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { return TCL_ERROR; } subCmd = Tcl_GetString(objv[1]); if (strcmp(subCmd, "set") == 0) { if (objc != 4) { goto wrongNumArgs; } string = Tcl_GetString(objv[3]); if (Tcl_GetInt(interp, string, &i) != TCL_OK) { return TCL_ERROR; } intValue = i; /* * If the object currently bound to the variable with index varIndex * has ref count 1 (i.e. the object is unshared) we can modify that * object directly. Otherwise, if RC>1 (i.e. the object is shared), we * must create a new object to modify/set and decrement the old * formerly-shared object's ref count. This is "copy on write". */ if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { Tcl_SetIntObj(varPtr[varIndex], intValue); } else { SetVarToObj(varIndex, Tcl_NewIntObj(intValue)); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else if (strcmp(subCmd, "set2") == 0) { /* doesn't set result */ if (objc != 4) { goto wrongNumArgs; } string = Tcl_GetString(objv[3]); if (Tcl_GetInt(interp, string, &i) != TCL_OK) { return TCL_ERROR; } intValue = i; if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { Tcl_SetIntObj(varPtr[varIndex], intValue); } else { SetVarToObj(varIndex, Tcl_NewIntObj(intValue)); } } else if (strcmp(subCmd, "setlong") == 0) { if (objc != 4) { goto wrongNumArgs; } string = Tcl_GetString(objv[3]); if (Tcl_GetInt(interp, string, &i) != TCL_OK) { return TCL_ERROR; } intValue = i; if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { Tcl_SetLongObj(varPtr[varIndex], intValue); } else { SetVarToObj(varIndex, Tcl_NewLongObj(intValue)); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else if (strcmp(subCmd, "setmaxlong") == 0) { long maxLong = LONG_MAX; if (objc != 3) { goto wrongNumArgs; } if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { Tcl_SetLongObj(varPtr[varIndex], maxLong); } else { SetVarToObj(varIndex, Tcl_NewLongObj(maxLong)); } } else if (strcmp(subCmd, "ismaxlong") == 0) { if (objc != 3) { goto wrongNumArgs; } if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } if (Tcl_GetLongFromObj(interp, varPtr[varIndex], &longValue) != TCL_OK) { return TCL_ERROR; } Tcl_AppendToObj(Tcl_GetObjResult(interp), ((longValue == LONG_MAX)? "1" : "0"), -1); } else if (strcmp(subCmd, "get") == 0) { if (objc != 3) { goto wrongNumArgs; } if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } Tcl_SetObjResult(interp, varPtr[varIndex]); } else if (strcmp(subCmd, "get2") == 0) { if (objc != 3) { goto wrongNumArgs; } if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } string = Tcl_GetString(varPtr[varIndex]); Tcl_AppendToObj(Tcl_GetObjResult(interp), string, -1); } else if (strcmp(subCmd, "inttoobigtest") == 0) { /* * If long ints have more bits than ints on this platform, verify that * Tcl_GetIntFromObj returns an error if the long int held in an * integer object's internal representation is too large to fit in an * int. */ if (objc != 3) { goto wrongNumArgs; } #if (INT_MAX == LONG_MAX) /* int is same size as long int */ Tcl_AppendToObj(Tcl_GetObjResult(interp), "1", -1); #else if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { Tcl_SetLongObj(varPtr[varIndex], LONG_MAX); } else { SetVarToObj(varIndex, Tcl_NewLongObj(LONG_MAX)); } if (Tcl_GetIntFromObj(interp, varPtr[varIndex], &i) != TCL_OK) { Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), "1", -1); return TCL_OK; } Tcl_AppendToObj(Tcl_GetObjResult(interp), "0", -1); #endif } else if (strcmp(subCmd, "mult10") == 0) { if (objc != 3) { goto wrongNumArgs; } if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } if (Tcl_GetIntFromObj(interp, varPtr[varIndex], &intValue) != TCL_OK) { return TCL_ERROR; } if (!Tcl_IsShared(varPtr[varIndex])) { Tcl_SetIntObj(varPtr[varIndex], intValue * 10); } else { SetVarToObj(varIndex, Tcl_NewIntObj(intValue * 10)); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else if (strcmp(subCmd, "div10") == 0) { if (objc != 3) { goto wrongNumArgs; } if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } if (Tcl_GetIntFromObj(interp, varPtr[varIndex], &intValue) != TCL_OK) { return TCL_ERROR; } if (!Tcl_IsShared(varPtr[varIndex])) { Tcl_SetIntObj(varPtr[varIndex], intValue / 10); } else { SetVarToObj(varIndex, Tcl_NewIntObj(intValue / 10)); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "bad option \"", Tcl_GetString(objv[1]), "\": must be set, get, get2, mult10, or div10", NULL); return TCL_ERROR; } return TCL_OK; }
static int TestindexobjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int allowAbbrev, index, index2, setError, i, result; const char **argv; static const char *const tablePtr[] = {"a", "b", "check", NULL}; /* * Keep this structure declaration in sync with tclIndexObj.c */ struct IndexRep { void *tablePtr; /* Pointer to the table of strings. */ int offset; /* Offset between table entries. */ int index; /* Selected index into table. */ }; struct IndexRep *indexRep; if ((objc == 3) && (strcmp(Tcl_GetString(objv[1]), "check") == 0)) { /* * This code checks to be sure that the results of Tcl_GetIndexFromObj * are properly cached in the object and returned on subsequent * lookups. */ if (Tcl_GetIntFromObj(interp, objv[2], &index2) != TCL_OK) { return TCL_ERROR; } Tcl_GetIndexFromObj(NULL, objv[1], tablePtr, "token", 0, &index); indexRep = (struct IndexRep *) objv[1]->internalRep.otherValuePtr; indexRep->index = index2; result = Tcl_GetIndexFromObj(NULL, objv[1], tablePtr, "token", 0, &index); if (result == TCL_OK) { Tcl_SetIntObj(Tcl_GetObjResult(interp), index); } return result; } if (objc < 5) { Tcl_AppendToObj(Tcl_GetObjResult(interp), "wrong # args", -1); return TCL_ERROR; } if (Tcl_GetBooleanFromObj(interp, objv[1], &setError) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetBooleanFromObj(interp, objv[2], &allowAbbrev) != TCL_OK) { return TCL_ERROR; } argv = (const char **) ckalloc((unsigned) ((objc-3) * sizeof(char *))); for (i = 4; i < objc; i++) { argv[i-4] = Tcl_GetString(objv[i]); } argv[objc-4] = NULL; /* * Tcl_GetIndexFromObj assumes that the table is statically-allocated so * that its address is different for each index object. If we accidently * allocate a table at the same address as that cached in the index * object, clear out the object's cached state. */ if (objv[3]->typePtr != NULL && !strcmp("index", objv[3]->typePtr->name)) { indexRep = (struct IndexRep *) objv[3]->internalRep.otherValuePtr; if (indexRep->tablePtr == (void *) argv) { objv[3]->typePtr->freeIntRepProc(objv[3]); objv[3]->typePtr = NULL; } } result = Tcl_GetIndexFromObj((setError? interp : NULL), objv[3], argv, "token", (allowAbbrev? 0 : TCL_EXACT), &index); ckfree((char *) argv); if (result == TCL_OK) { Tcl_SetIntObj(Tcl_GetObjResult(interp), index); } return result; }
static int TeststringobjCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Tcl_UniChar *unicode; int varIndex, option, i, length; #define MAX_STRINGS 11 const char *index, *string, *strings[MAX_STRINGS+1]; TestString *strPtr; static const char *const options[] = { "append", "appendstrings", "get", "get2", "length", "length2", "set", "set2", "setlength", "maxchars", "getunicode", "appendself", "appendself2", NULL }; if (objc < 3) { wrongNumArgs: Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?"); return TCL_ERROR; } index = Tcl_GetString(objv[2]); if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0, &option) != TCL_OK) { return TCL_ERROR; } switch (option) { case 0: /* append */ if (objc != 5) { goto wrongNumArgs; } if (Tcl_GetIntFromObj(interp, objv[4], &length) != TCL_OK) { return TCL_ERROR; } if (varPtr[varIndex] == NULL) { SetVarToObj(varIndex, Tcl_NewObj()); } /* * If the object bound to variable "varIndex" is shared, we must * "copy on write" and append to a copy of the object. */ if (Tcl_IsShared(varPtr[varIndex])) { SetVarToObj(varIndex, Tcl_DuplicateObj(varPtr[varIndex])); } string = Tcl_GetString(objv[3]); Tcl_AppendToObj(varPtr[varIndex], string, length); Tcl_SetObjResult(interp, varPtr[varIndex]); break; case 1: /* appendstrings */ if (objc > (MAX_STRINGS+3)) { goto wrongNumArgs; } if (varPtr[varIndex] == NULL) { SetVarToObj(varIndex, Tcl_NewObj()); } /* * If the object bound to variable "varIndex" is shared, we must * "copy on write" and append to a copy of the object. */ if (Tcl_IsShared(varPtr[varIndex])) { SetVarToObj(varIndex, Tcl_DuplicateObj(varPtr[varIndex])); } for (i = 3; i < objc; i++) { strings[i-3] = Tcl_GetString(objv[i]); } for ( ; i < 12 + 3; i++) { strings[i - 3] = NULL; } Tcl_AppendStringsToObj(varPtr[varIndex], strings[0], strings[1], strings[2], strings[3], strings[4], strings[5], strings[6], strings[7], strings[8], strings[9], strings[10], strings[11]); Tcl_SetObjResult(interp, varPtr[varIndex]); break; case 2: /* get */ if (objc != 3) { goto wrongNumArgs; } if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } Tcl_SetObjResult(interp, varPtr[varIndex]); break; case 3: /* get2 */ if (objc != 3) { goto wrongNumArgs; } if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } string = Tcl_GetString(varPtr[varIndex]); Tcl_AppendToObj(Tcl_GetObjResult(interp), string, -1); break; case 4: /* length */ if (objc != 3) { goto wrongNumArgs; } Tcl_SetIntObj(Tcl_GetObjResult(interp), (varPtr[varIndex] != NULL) ? varPtr[varIndex]->length : -1); break; case 5: /* length2 */ if (objc != 3) { goto wrongNumArgs; } if (varPtr[varIndex] != NULL) { Tcl_ConvertToType(NULL, varPtr[varIndex], Tcl_GetObjType("string")); strPtr = (TestString *) (varPtr[varIndex])->internalRep.otherValuePtr; length = (int) strPtr->allocated; } else { length = -1; } Tcl_SetIntObj(Tcl_GetObjResult(interp), length); break; case 6: /* set */ if (objc != 4) { goto wrongNumArgs; } /* * If the object currently bound to the variable with index * varIndex has ref count 1 (i.e. the object is unshared) we can * modify that object directly. Otherwise, if RC>1 (i.e. the * object is shared), we must create a new object to modify/set * and decrement the old formerly-shared object's ref count. This * is "copy on write". */ string = Tcl_GetStringFromObj(objv[3], &length); if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { Tcl_SetStringObj(varPtr[varIndex], string, length); } else { SetVarToObj(varIndex, Tcl_NewStringObj(string, length)); } Tcl_SetObjResult(interp, varPtr[varIndex]); break; case 7: /* set2 */ if (objc != 4) { goto wrongNumArgs; } SetVarToObj(varIndex, objv[3]); break; case 8: /* setlength */ if (objc != 4) { goto wrongNumArgs; } if (Tcl_GetIntFromObj(interp, objv[3], &length) != TCL_OK) { return TCL_ERROR; } if (varPtr[varIndex] != NULL) { Tcl_SetObjLength(varPtr[varIndex], length); } break; case 9: /* maxchars */ if (objc != 3) { goto wrongNumArgs; } if (varPtr[varIndex] != NULL) { Tcl_ConvertToType(NULL, varPtr[varIndex], Tcl_GetObjType("string")); strPtr = (TestString *) (varPtr[varIndex])->internalRep.otherValuePtr; length = strPtr->maxChars; } else { length = -1; } Tcl_SetIntObj(Tcl_GetObjResult(interp), length); break; case 10: /* getunicode */ if (objc != 3) { goto wrongNumArgs; } Tcl_GetUnicodeFromObj(varPtr[varIndex], NULL); break; case 11: /* appendself */ if (objc != 4) { goto wrongNumArgs; } if (varPtr[varIndex] == NULL) { SetVarToObj(varIndex, Tcl_NewObj()); } /* * If the object bound to variable "varIndex" is shared, we must * "copy on write" and append to a copy of the object. */ if (Tcl_IsShared(varPtr[varIndex])) { SetVarToObj(varIndex, Tcl_DuplicateObj(varPtr[varIndex])); } string = Tcl_GetStringFromObj(varPtr[varIndex], &length); if (Tcl_GetIntFromObj(interp, objv[3], &i) != TCL_OK) { return TCL_ERROR; } if ((i < 0) || (i > length)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "index value out of range", -1)); return TCL_ERROR; } Tcl_AppendToObj(varPtr[varIndex], string + i, length - i); Tcl_SetObjResult(interp, varPtr[varIndex]); break; case 12: /* appendself2 */ if (objc != 4) { goto wrongNumArgs; } if (varPtr[varIndex] == NULL) { SetVarToObj(varIndex, Tcl_NewObj()); } /* * If the object bound to variable "varIndex" is shared, we must * "copy on write" and append to a copy of the object. */ if (Tcl_IsShared(varPtr[varIndex])) { SetVarToObj(varIndex, Tcl_DuplicateObj(varPtr[varIndex])); } unicode = Tcl_GetUnicodeFromObj(varPtr[varIndex], &length); if (Tcl_GetIntFromObj(interp, objv[3], &i) != TCL_OK) { return TCL_ERROR; } if ((i < 0) || (i > length)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "index value out of range", -1)); return TCL_ERROR; } Tcl_AppendUnicodeToObj(varPtr[varIndex], unicode + i, length - i); Tcl_SetObjResult(interp, varPtr[varIndex]); break; } return TCL_OK; }
static void setIntResult (Tcl_Interp *interp, int value) { Tcl_SetIntObj(Tcl_GetObjResult(interp), value); }