@@ -1,45 +1,42 @@ - /* ================================================================== - FILE: "/home/joze/src/tclreadline/tclreadline.c" - LAST MODIFICATION: "Mit, 10 Jan 2001 06:29:33 +0100 (joze)" - (C) 1998 - 2001 by Johannes Zellner, + FILE: tclreadline.c $Id$ --- tclreadline -- gnu readline for tcl http://www.zellner.org/tclreadline/ - Copyright (c) 1998 - 2001, Johannes Zellner + Copyright (c) 1998 - 2014, Johannes Zellner This software is copyright under the BSD license. - ================================================================== */ + ================================================================== */ #ifdef HAVE_CONFIG_H -# include "config.h" +# include "config.h" #endif #include #include #include #include #if defined (READLINE_LIBRARY) -# include -# include +# include +# include #else -# include -# include +# include +# include #endif /* - * this prototype is missing + * this prototype may be missing * in readline.h */ void rl_extend_line_buffer(int len); #ifdef EXECUTING_MACRO_HACK /** - * this prototype is private in readline's file `macro.c'. + * this prototype may be private in readline's file `macro.c'. * We need it here to decide, if we should read more * characters from a macro. Dirty, but it should work. */ extern char* EXECUTING_MACRO_NAME; #endif @@ -47,12 +44,12 @@ #include "tclreadline.h" static const char* tclrl_library = TCLRL_LIBRARY; static const char* tclrl_version_str = TCLRL_VERSION_STR; static const char* tclrl_patchlevel_str = TCLRL_PATCHLEVEL_STR; -#define MALLOC(size) malloc((int) size) -#define FREE(ptr) if (ptr) { free((char*) ptr); ptr = 0; } +#define MALLOC(size) malloc(size) +#define FREE(ptr) free(ptr); ptr = NULL enum { _CMD_SET = (1 << 0), _CMD_GET = (1 << 1) }; @@ -84,11 +81,11 @@ static char* TclReadline0generator(char* text, int state); static char* TclReadlineKnownCommands(char* text, int state, int mode); static int TclReadlineParse(char** args, int maxargs, char* buf); -enum { +enum { LINE_PENDING = -1, LINE_EOF = (1 << 8), LINE_COMPLETE = (1 << 9) }; @@ -137,22 +134,22 @@ static char* stripleft(char* in) { char* ptr = in; while (*ptr && *ptr <= ' ') - ptr++; + ptr++; if (in != ptr) - memmove(in, ptr, strlen(ptr) + 1); + memmove(in, ptr, strlen(ptr) + 1); return in; } static char* stripright(char* in) { char* ptr; for (ptr = strchr(in, '\0') - 1; ptr >= in && *ptr <= ' '; ptr--) - *ptr = '\0'; + *ptr = '\0'; return in; } static char* stripwhite(char* in) @@ -183,374 +180,373 @@ int i, len = strlen(quotechars); Tcl_DString result; Tcl_DStringInit(&result); for (ptr = text; ptr && *ptr; ptr++) { - for (i = 0; i < len; i++) { - if (quotechars[i] == *ptr) { - Tcl_DStringAppend(&result, "\\", 1); - break; - } - } - Tcl_DStringAppend(&result, ptr, 1); + for (i = 0; i < len; i++) { + if (quotechars[i] == *ptr) { + Tcl_DStringAppend(&result, "\\", 1); + break; + } + } + Tcl_DStringAppend(&result, ptr, 1); } result_c = strdup(Tcl_DStringValue(&result)); return result_c; } -static int TclReadlineCmd(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[]) +static int +TclReadlineCmd(ClientData clientData, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[]) { int obj_idx, status; static char *subCmds[] = { - "read", "initialize", "write", "add", "complete", - "customcompleter", "builtincompleter", "eofchar", - "reset-terminal", "bell", "text", "update", - (char *) NULL + "read", "initialize", "write", "add", "complete", + "customcompleter", "builtincompleter", "eofchar", + "reset-terminal", "bell", "text", "update", + (char *) NULL }; enum SubCmdIdx { - TCLRL_READ, TCLRL_INITIALIZE, TCLRL_WRITE, TCLRL_ADD, TCLRL_COMPLETE, - TCLRL_CUSTOMCOMPLETER, TCLRL_BUILTINCOMPLETER, TCLRL_EOFCHAR, - TCLRL_RESET_TERMINAL, TCLRL_BELL, TCLRL_TEXT, TCLRL_UPDATE + TCLRL_READ, TCLRL_INITIALIZE, TCLRL_WRITE, TCLRL_ADD, TCLRL_COMPLETE, + TCLRL_CUSTOMCOMPLETER, TCLRL_BUILTINCOMPLETER, TCLRL_EOFCHAR, + TCLRL_RESET_TERMINAL, TCLRL_BELL, TCLRL_TEXT, TCLRL_UPDATE }; Tcl_ResetResult(interp); /* clear the result space */ if (objc < 2) { - Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?"); - return TCL_ERROR; + Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?"); + return TCL_ERROR; } status = Tcl_GetIndexFromObj - (interp, objv[1], subCmds, "option", 0, (int *) &obj_idx); + (interp, objv[1], subCmds, "option", 0, (int *) &obj_idx); - if (status != TCL_OK) { - return status; - } + if (status != TCL_OK) + return status; switch (obj_idx) { - case TCLRL_READ: - - rl_callback_handler_install( - objc == 3 ? Tcl_GetStringFromObj(objv[2], 0) - : "% ", TclReadlineLineCompleteHandler); - - Tcl_CreateFileHandler(0, TCL_READABLE, - TclReadlineReadHandler, (ClientData) NULL); - - /** - * Main Loop. - * XXX each modification of the global variables - * which terminates the main loop must call - * rl_callback_handler_remove() to leave - * readline in a defined state. XXX - */ - tclrl_state = LINE_PENDING; - - while (!TclReadlineLineComplete()) { + case TCLRL_READ: + + rl_callback_handler_install( + objc == 3 ? Tcl_GetStringFromObj(objv[2], 0) + : "% ", TclReadlineLineCompleteHandler); + + Tcl_CreateFileHandler(0, TCL_READABLE, + TclReadlineReadHandler, (ClientData) NULL); + + /** + * Main Loop. + * XXX each modification of the global variables + * which terminates the main loop must call + * rl_callback_handler_remove() to leave + * readline in a defined state. XXX + */ + tclrl_state = LINE_PENDING; + + while (!TclReadlineLineComplete()) { #ifdef EXECUTING_MACRO_NAME - /** - * check first, if more characters are - * available from _rl_executing_macro, - * because Tcl_DoOneEvent() will (naturally) - * not detect this `event'. - */ - if (EXECUTING_MACRO_NAME) - TclReadlineReadHandler((ClientData) NULL, TCL_READABLE); - else + /** + * check first, if more characters are + * available from _rl_executing_macro, + * because Tcl_DoOneEvent() will (naturally) + * not detect this `event'. + */ + if (EXECUTING_MACRO_NAME) + TclReadlineReadHandler((ClientData) NULL, TCL_READABLE); + else #endif - Tcl_DoOneEvent(TCL_ALL_EVENTS); - } - - Tcl_DeleteFileHandler(0); - - switch (tclrl_state) { - - case LINE_COMPLETE: - - return TCL_OK; - /* NOTREACHED */ - break; - - case LINE_EOF: - if (tclrl_eof_string) - return Tcl_Eval(interp, tclrl_eof_string); - else - return TCL_OK; - /* NOTREACHED */ - break; - - default: - return tclrl_state; - /* NOTREACHED */ - break; - } - break; - - case TCLRL_INITIALIZE: - if (3 != objc) { - Tcl_WrongNumArgs(interp, 2, objv, "historyfile"); - return TCL_ERROR; - } else { - return TclReadlineInitialize(interp, - Tcl_GetStringFromObj(objv[2], 0)); - } - break; - - case TCLRL_WRITE: - if (3 != objc) { - Tcl_WrongNumArgs(interp, 2, objv, "historyfile"); - return TCL_ERROR; - } else if (write_history(Tcl_GetStringFromObj(objv[2], 0))) { - Tcl_AppendResult(interp, "unable to write history to `", - Tcl_GetStringFromObj(objv[2], 0), "'\n", (char*) NULL); - return TCL_ERROR; - } - if (tclrl_history_length >= 0) { - history_truncate_file(Tcl_GetStringFromObj(objv[2], 0), - tclrl_history_length); - } - return TCL_OK; - break; - - case TCLRL_ADD: - if (3 != objc) { - Tcl_WrongNumArgs(interp, 2, objv, "completerLine"); - return TCL_ERROR; - } else if (TclReadlineKnownCommands( - Tcl_GetStringFromObj(objv[2], 0), - (int) 0, _CMD_SET)) { - Tcl_AppendResult(interp, "unable to add command \"", - Tcl_GetStringFromObj(objv[2], 0), "\"\n", (char*) NULL); - } - break; - - case TCLRL_COMPLETE: - if (3 != objc) { - Tcl_WrongNumArgs(interp, 2, objv, "line"); - return TCL_ERROR; - } else if (Tcl_CommandComplete(Tcl_GetStringFromObj(objv[2], 0))) { - Tcl_AppendResult(interp, "1", (char*) NULL); - } else { - Tcl_AppendResult(interp, "0", (char*) NULL); - } - break; - - case TCLRL_CUSTOMCOMPLETER: - if (objc > 3) { - Tcl_WrongNumArgs(interp, 2, objv, "?scriptCompleter?"); - return TCL_ERROR; - } else if (3 == objc) { - if (tclrl_custom_completer) - FREE(tclrl_custom_completer); - if (!blank_line(Tcl_GetStringFromObj(objv[2], 0))) - tclrl_custom_completer = - stripwhite(strdup(Tcl_GetStringFromObj(objv[2], 0))); - } - Tcl_AppendResult(interp, tclrl_custom_completer, (char*) NULL); - break; - - case TCLRL_BUILTINCOMPLETER: - if (objc > 3) { - Tcl_WrongNumArgs(interp, 2, objv, "?boolean?"); - return TCL_ERROR; - } else if (3 == objc) { - int bool = tclrl_use_builtin_completer; - if (TCL_OK != Tcl_GetBoolean(interp, - Tcl_GetStringFromObj(objv[2], 0), - &bool)) { - Tcl_AppendResult(interp, - "wrong # args: should be a boolean value.", - (char*) NULL); - return TCL_ERROR; - } else { - tclrl_use_builtin_completer = bool; - } - } - Tcl_AppendResult(interp, tclrl_use_builtin_completer ? "1" : "0", - (char*) NULL); - break; - - case TCLRL_EOFCHAR: - if (objc > 3) { - Tcl_WrongNumArgs(interp, 2, objv, "?script?"); - return TCL_ERROR; - } else if (3 == objc) { - if (tclrl_eof_string) - FREE(tclrl_eof_string); - if (!blank_line(Tcl_GetStringFromObj(objv[2], 0))) - tclrl_eof_string = - stripwhite(strdup(Tcl_GetStringFromObj(objv[2], 0))); - } - Tcl_AppendResult(interp, tclrl_eof_string, (char*) NULL); - break; - - case TCLRL_RESET_TERMINAL: - /* TODO: add this to the completer */ - if (objc > 3) { - Tcl_WrongNumArgs(interp, 2, objv, "?terminal-name?"); - return TCL_ERROR; - } - if (3 == objc) { - /* - * - tcl8.0 doesn't have Tcl_GetStringFromObj() - * - rl_reset_terminal() might be defined - * to take no arguments. This might produce - * a compiler warning. - */ - rl_reset_terminal(Tcl_GetStringFromObj(objv[2], 0)); + Tcl_DoOneEvent(TCL_ALL_EVENTS); + } + + Tcl_DeleteFileHandler(0); + + switch (tclrl_state) { + + case LINE_COMPLETE: + return TCL_OK; + /* NOTREACHED */ + break; + + case LINE_EOF: + if (tclrl_eof_string) + return Tcl_Eval(interp, tclrl_eof_string); + else + return TCL_OK; + /* NOTREACHED */ + break; + + default: + return tclrl_state; + /* NOTREACHED */ + break; + } + break; + + case TCLRL_INITIALIZE: + if (3 != objc) { + Tcl_WrongNumArgs(interp, 2, objv, "historyfile"); + return TCL_ERROR; + } else { + return TclReadlineInitialize(interp, + Tcl_GetStringFromObj(objv[2], 0)); + } + break; + + case TCLRL_WRITE: + if (3 != objc) { + Tcl_WrongNumArgs(interp, 2, objv, "historyfile"); + return TCL_ERROR; + } else if (write_history(Tcl_GetStringFromObj(objv[2], 0))) { + Tcl_AppendResult(interp, "unable to write history to `", + Tcl_GetStringFromObj(objv[2], 0), "'\n", (char*) NULL); + return TCL_ERROR; + } + if (tclrl_history_length >= 0) { + history_truncate_file(Tcl_GetStringFromObj(objv[2], 0), + tclrl_history_length); + } + return TCL_OK; + break; + + case TCLRL_ADD: + if (3 != objc) { + Tcl_WrongNumArgs(interp, 2, objv, "completerLine"); + return TCL_ERROR; + } else if (TclReadlineKnownCommands( + Tcl_GetStringFromObj(objv[2], 0), + (int) 0, _CMD_SET)) { + Tcl_AppendResult(interp, "unable to add command \"", + Tcl_GetStringFromObj(objv[2], 0), "\"\n", (char*) NULL); + } + break; + + case TCLRL_COMPLETE: + if (3 != objc) { + Tcl_WrongNumArgs(interp, 2, objv, "line"); + return TCL_ERROR; + } else if (Tcl_CommandComplete(Tcl_GetStringFromObj(objv[2], 0))) { + Tcl_AppendResult(interp, "1", (char*) NULL); + } else { + Tcl_AppendResult(interp, "0", (char*) NULL); + } + break; + + case TCLRL_CUSTOMCOMPLETER: + if (objc > 3) { + Tcl_WrongNumArgs(interp, 2, objv, "?scriptCompleter?"); + return TCL_ERROR; + } else if (3 == objc) { + if (tclrl_custom_completer) + FREE(tclrl_custom_completer); + if (!blank_line(Tcl_GetStringFromObj(objv[2], 0))) + tclrl_custom_completer = + stripwhite(strdup(Tcl_GetStringFromObj(objv[2], 0))); + } + Tcl_AppendResult(interp, tclrl_custom_completer, (char*) NULL); + break; + + case TCLRL_BUILTINCOMPLETER: + if (objc > 3) { + Tcl_WrongNumArgs(interp, 2, objv, "?boolean?"); + return TCL_ERROR; + } else if (3 == objc) { + int bool = tclrl_use_builtin_completer; + if (TCL_OK != Tcl_GetBoolean(interp, + Tcl_GetStringFromObj(objv[2], 0), + &bool)) { + Tcl_AppendResult(interp, + "wrong # args: should be a boolean value.", + (char*) NULL); + return TCL_ERROR; + } else { + tclrl_use_builtin_completer = bool; + } + } + Tcl_AppendResult(interp, tclrl_use_builtin_completer ? "1" : "0", + (char*) NULL); + break; + + case TCLRL_EOFCHAR: + if (objc > 3) { + Tcl_WrongNumArgs(interp, 2, objv, "?script?"); + return TCL_ERROR; + } else if (3 == objc) { + if (tclrl_eof_string) + FREE(tclrl_eof_string); + if (!blank_line(Tcl_GetStringFromObj(objv[2], 0))) + tclrl_eof_string = + stripwhite(strdup(Tcl_GetStringFromObj(objv[2], 0))); + } + Tcl_AppendResult(interp, tclrl_eof_string, (char*) NULL); + break; + + case TCLRL_RESET_TERMINAL: + /* TODO: add this to the completer */ + if (objc > 3) { + Tcl_WrongNumArgs(interp, 2, objv, "?terminal-name?"); + return TCL_ERROR; + } + if (3 == objc) { + /* + * - tcl8.0 doesn't have Tcl_GetStringFromObj() + * - rl_reset_terminal() might be defined + * to take no arguments. This might produce + * a compiler warning. + */ + rl_reset_terminal(Tcl_GetStringFromObj(objv[2], 0)); #ifdef CLEANUP_AFER_SIGNAL - } else { - rl_cleanup_after_signal(); + } else { + rl_cleanup_after_signal(); #endif - } - break; - - case TCLRL_BELL: - if (objc != 2) { - Tcl_WrongNumArgs(interp, 2, objv, ""); - return TCL_ERROR; - } - - - /* - * ring the terminal bell obeying the current - * settings -- audible or visible. - */ - - ding(); - break; + } + break; + + case TCLRL_BELL: + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, ""); + return TCL_ERROR; + } + + + /* + * ring the terminal bell obeying the current + * settings -- audible or visible. + */ + + ding(); + break; case TCLRL_UPDATE: - if (objc != 2) { - Tcl_WrongNumArgs(interp, 2, objv, ""); - return TCL_ERROR; - } - - /* Update the input line */ - - if (rl_line_buffer) { - rl_forced_update_display(); - } - - break; + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, ""); + return TCL_ERROR; + } + + /* Update the input line */ + + if (rl_line_buffer) { + rl_forced_update_display(); + } + + break; case TCLRL_TEXT: - if (objc != 2) { - Tcl_WrongNumArgs(interp, 2, objv, ""); - return TCL_ERROR; - } - - /* Return the current input line */ - Tcl_SetObjResult(interp, - Tcl_NewStringObj(rl_line_buffer ? rl_line_buffer : "", -1)); - break; - - default: - goto BAD_COMMAND; - /* NOTREACHED */ - break; + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, ""); + return TCL_ERROR; + } + + /* Return the current input line */ + Tcl_SetObjResult(interp, + Tcl_NewStringObj(rl_line_buffer ? rl_line_buffer : "", -1)); + break; + + default: + goto BAD_COMMAND; + /* NOTREACHED */ + break; } return TCL_OK; BAD_COMMAND: Tcl_AppendResult(interp, - "wrong # args: should be \"readline option ?arg ...?\"", - (char*) NULL); + "wrong # args: should be \"readline option ?arg ...?\"", + (char*) NULL); return TCL_ERROR; } static void TclReadlineReadHandler(ClientData clientData, int mask) { if (mask & TCL_READABLE) { #ifdef EXECUTING_MACRO_NAME - do { + do { #endif - rl_callback_read_char(); + rl_callback_read_char(); #ifdef EXECUTING_MACRO_NAME - /** - * check, if we're inside a macro and - * if so, read all macro characters - * until the next eol. - */ - } while (EXECUTING_MACRO_NAME && !TclReadlineLineComplete()); + /** + * check, if we're inside a macro and + * if so, read all macro characters + * until the next eol. + */ + } while (EXECUTING_MACRO_NAME && !TclReadlineLineComplete()); #endif } } static void TclReadlineLineCompleteHandler(char* ptr) { if (!ptr) { /* */ - TclReadlineTerminate(LINE_EOF); - - } else { - - /** - * From version 0.9.3 upwards, all lines are - * returned, even empty lines. (Only non-empty - * lines are stuffed in readline's history.) - * The calling script is responsible for handling - * empty strings. - */ - - char* expansion = (char*) NULL; - int status = history_expand(ptr, &expansion); - - if (status >= 2) { - /* TODO: make this a valid tcl output */ - printf("%s\n", expansion); - free(ptr); - free(expansion); - return; - } else if (status <= -1) { - Tcl_AppendResult - (tclrl_interp, "error in history expansion: ", expansion, "\n", (char*) NULL); - TclReadlineTerminate(TCL_ERROR); - free(ptr); - free(expansion); - return; - } else { - Tcl_AppendResult(tclrl_interp, expansion, (char*) NULL); - } - -#ifdef EXECUTING_MACRO_NAME - /** - * don't stuff macro lines - * into readline's history. - */ - if(!EXECUTING_MACRO_NAME) { -#endif - /** - * don't stuff empty lines - * into readline's history. - * don't stuff twice the same - * line into readline's history. - */ - if (expansion && *expansion && (!tclrl_last_line || - strcmp(tclrl_last_line, expansion))) { - add_history(expansion); - } - if (tclrl_last_line) - free(tclrl_last_line); - tclrl_last_line = strdup(expansion); -#ifdef EXECUTING_MACRO_NAME - } -#endif - /** - * tell the calling routines to terminate. - */ - TclReadlineTerminate(LINE_COMPLETE); - FREE(ptr); - FREE(expansion); + TclReadlineTerminate(LINE_EOF); + + } else { + + /** + * From version 0.9.3 upwards, all lines are + * returned, even empty lines. (Only non-empty + * lines are stuffed in readline's history.) + * The calling script is responsible for handling + * empty strings. + */ + + char* expansion = (char*) NULL; + int status = history_expand(ptr, &expansion); + + if (status >= 2) { + /* TODO: make this a valid tcl output */ + printf("%s\n", expansion); + FREE(ptr); + FREE(expansion); + return; + } else if (status <= -1) { + Tcl_AppendResult + (tclrl_interp, "error in history expansion: ", expansion, "\n", (char*) NULL); + TclReadlineTerminate(TCL_ERROR); + FREE(ptr); + FREE(expansion); + return; + } else { + Tcl_AppendResult(tclrl_interp, expansion, (char*) NULL); + } + + #ifdef EXECUTING_MACRO_NAME + /** + * don't stuff macro lines + * into readline's history. + */ + if(!EXECUTING_MACRO_NAME) { + #endif + /** + * don't stuff empty lines + * into readline's history. + * don't stuff twice the same + * line into readline's history. + */ + if (expansion && *expansion && (!tclrl_last_line || + strcmp(tclrl_last_line, expansion))) { + add_history(expansion); + } + if (tclrl_last_line) + FREE(tclrl_last_line); + tclrl_last_line = strdup(expansion); + #ifdef EXECUTING_MACRO_NAME + } + #endif + /** + * tell the calling routines to terminate. + */ + TclReadlineTerminate(LINE_COMPLETE); + FREE(ptr); + FREE(expansion); } } int Tclreadline_SafeInit(Tcl_Interp *interp) @@ -561,38 +557,38 @@ int Tclreadline_Init(Tcl_Interp *interp) { int status; Tcl_CreateObjCommand(interp, "::tclreadline::readline", TclReadlineCmd, - (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); + (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); tclrl_interp = interp; if (TCL_OK != (status = Tcl_LinkVar(interp, "::tclreadline::historyLength", - (char*) &tclrl_history_length, TCL_LINK_INT))) - return status; + (char*) &tclrl_history_length, TCL_LINK_INT))) + return status; if (TCL_OK != (status = Tcl_LinkVar(interp, "::tclreadline::library", - (char*) &tclrl_library, TCL_LINK_STRING | TCL_LINK_READ_ONLY))) - return status; + (char*) &tclrl_library, TCL_LINK_STRING | TCL_LINK_READ_ONLY))) + return status; if (TCL_OK != (status = Tcl_LinkVar(interp, "::tclreadline::version", - (char*) &tclrl_version_str, TCL_LINK_STRING | TCL_LINK_READ_ONLY))) - return status; + (char*) &tclrl_version_str, TCL_LINK_STRING | TCL_LINK_READ_ONLY))) + return status; if (TCL_OK != (status = Tcl_LinkVar(interp, "::tclreadline::patchLevel", - (char*) &tclrl_patchlevel_str, TCL_LINK_STRING | TCL_LINK_READ_ONLY))) - return status; + (char*) &tclrl_patchlevel_str, TCL_LINK_STRING | TCL_LINK_READ_ONLY))) + return status; if (TCL_OK != (status = Tcl_LinkVar(interp, "::tclreadline::license", - (char*) &tclrl_license, TCL_LINK_STRING | TCL_LINK_READ_ONLY))) - return status; + (char*) &tclrl_license, TCL_LINK_STRING | TCL_LINK_READ_ONLY))) + return status; if (TCL_OK != (status = Tcl_LinkVar(interp, "tclreadline_library", - (char*) &tclrl_library, TCL_LINK_STRING | TCL_LINK_READ_ONLY))) - return status; + (char*) &tclrl_library, TCL_LINK_STRING | TCL_LINK_READ_ONLY))) + return status; if (TCL_OK != (status = Tcl_LinkVar(interp, "tclreadline_version", - (char*) &tclrl_version_str, TCL_LINK_STRING | TCL_LINK_READ_ONLY))) - return status; + (char*) &tclrl_version_str, TCL_LINK_STRING | TCL_LINK_READ_ONLY))) + return status; if (TCL_OK != (status = Tcl_LinkVar(interp, "tclreadline_patchLevel", - (char*) &tclrl_patchlevel_str, TCL_LINK_STRING | TCL_LINK_READ_ONLY))) - return status; + (char*) &tclrl_patchlevel_str, TCL_LINK_STRING | TCL_LINK_READ_ONLY))) + return status; return Tcl_PkgProvide(interp, "tclreadline", (char*)tclrl_version_str); } static int @@ -602,11 +598,11 @@ /* rl_special_prefixes = "${\"["; */ rl_special_prefixes = "$"; /** * default is " \t\n\"\\'`@$><=;|&{(" * removed "(" <-- arrays - * removed "{" <-- `${' variables + * removed "{" <-- `${' variables * removed "<" <-- completion lists with < ... > * added "[]" * added "}" */ /* 11.Sep rl_basic_word_break_characters = " \t\n\"\\@$}=;|&[]"; */ @@ -629,34 +625,34 @@ rl_filename_quoting_desired = 1; */ using_history(); if (!tclrl_eof_string) - tclrl_eof_string = strdup("puts {}; exit"); + tclrl_eof_string = strdup("puts {}; exit"); /* * try to read historyfile in home * directory. If this failes, this * is *not* an error. */ rl_attempted_completion_function = (CPPFunction *) TclReadlineCompletion; if (read_history(historyfile)) { - if (write_history(historyfile)) { - Tcl_AppendResult (interp, "warning: `", - historyfile, "' is not writable.", (char*) NULL); - } + if (write_history(historyfile)) { + Tcl_AppendResult (interp, "warning: `", + historyfile, "' is not writable.", (char*) NULL); + } } return TCL_OK; } static int blank_line(char* str) { char* ptr; for (ptr = str; ptr && *ptr; ptr++) { - if (!ISWHITE(*ptr)) - return 0; + if (!ISWHITE(*ptr)) + return 0; } return 1; } static char** @@ -665,96 +661,94 @@ char** matches = (char**) NULL; int status; rl_completion_append_character = ' '; /* reset, just in case ... */ if (text && ('!' == text[0] - || (start && rl_line_buffer[start - 1] == '!' /* for '$' */))) { - char* expansion = (char*) NULL; - int oldlen = strlen(rl_line_buffer); - status = history_expand(rl_line_buffer, &expansion); - if (status >= 1) { - rl_extend_line_buffer(strlen(expansion) + 1); - strcpy(rl_line_buffer, expansion); - rl_end = strlen(expansion); - rl_point += strlen(expansion) - oldlen; - FREE(expansion); - /* - * TODO: - * because we return 0 == matches, - * the filename completer will still beep. - rl_inhibit_completion = 1; - */ - return matches; - } - FREE(expansion); + || (start && rl_line_buffer[start - 1] == '!' /* for '$' */))) { + char* expansion = (char*) NULL; + int oldlen = strlen(rl_line_buffer); + status = history_expand(rl_line_buffer, &expansion); + if (status >= 1) { + rl_extend_line_buffer(strlen(expansion) + 1); + strcpy(rl_line_buffer, expansion); + rl_end = strlen(expansion); + rl_point += strlen(expansion) - oldlen; + FREE(expansion); + /* + * TODO: + * because we return 0 == matches, + * the filename completer will still beep. + rl_inhibit_completion = 1; + */ + return matches; + } + FREE(expansion); } if (tclrl_custom_completer) { - char start_s[BUFSIZ], end_s[BUFSIZ]; - Tcl_Obj* obj; - Tcl_Obj** objv; - int objc; - int state; - char* quoted_text = TclReadlineQuote(text, "$[]{}\""); - char* quoted_rl_line_buffer = TclReadlineQuote(rl_line_buffer, "$[]{}\""); - sprintf(start_s, "%d", start); - sprintf(end_s, "%d", end); - Tcl_ResetResult(tclrl_interp); /* clear result space */ - state = Tcl_VarEval(tclrl_interp, tclrl_custom_completer, - " \"", quoted_text, "\" ", start_s, " ", end_s, - " \"", quoted_rl_line_buffer, "\"", (char*) NULL); - if (TCL_OK != state) { - Tcl_AppendResult (tclrl_interp, " `", tclrl_custom_completer, - " \"", quoted_text, "\" ", start_s, " ", end_s, - " \"", quoted_rl_line_buffer, "\"' failed.", (char*) NULL); - TclReadlineTerminate(state); - free(quoted_text); - free(quoted_rl_line_buffer); - return matches; - } - free(quoted_text); - quoted_text = NULL; - free(quoted_rl_line_buffer); - quoted_rl_line_buffer = NULL; - obj = Tcl_GetObjResult(tclrl_interp); - status = Tcl_ListObjGetElements(tclrl_interp, obj, &objc, &objv); - if (TCL_OK != status) - return matches; - - if (objc) { - int i, length; - matches = (char**) MALLOC(sizeof(char*) * (objc + 1)); - for (i = 0; i < objc; i++) { - matches[i] = strdup(Tcl_GetStringFromObj(objv[i], &length)); - if (1 == objc && !strlen(matches[i])) { - FREE(matches[i]); - FREE(matches); - Tcl_ResetResult(tclrl_interp); /* clear result space */ - return (char**) NULL; - } - } - - /** - * this is a special one: - * if the script returns exactly two arguments - * and the second argument is the empty string, - * the rl_completion_append_character is set - * temporaryly to NULL. - */ - if (2 == objc && !strlen(matches[1])) { - i--; - FREE(matches[1]); - rl_completion_append_character = '\0'; - } - - matches[i] = (char*) NULL; /* terminate */ - } - Tcl_ResetResult(tclrl_interp); /* clear result space */ + char start_s[BUFSIZ], end_s[BUFSIZ]; + Tcl_Obj* obj; + Tcl_Obj** objv; + int objc; + int state; + char* quoted_text = TclReadlineQuote(text, "$[]{}\""); + char* quoted_rl_line_buffer = TclReadlineQuote(rl_line_buffer, "$[]{}\""); + sprintf(start_s, "%d", start); + sprintf(end_s, "%d", end); + Tcl_ResetResult(tclrl_interp); /* clear result space */ + state = Tcl_VarEval(tclrl_interp, tclrl_custom_completer, + " \"", quoted_text, "\" ", start_s, " ", end_s, + " \"", quoted_rl_line_buffer, "\"", (char*) NULL); + if (TCL_OK != state) { + Tcl_AppendResult (tclrl_interp, " `", tclrl_custom_completer, + " \"", quoted_text, "\" ", start_s, " ", end_s, + " \"", quoted_rl_line_buffer, "\"' failed.", (char*) NULL); + TclReadlineTerminate(state); + FREE(quoted_text); + FREE(quoted_rl_line_buffer); + return matches; + } + FREE(quoted_text); + FREE(quoted_rl_line_buffer); + obj = Tcl_GetObjResult(tclrl_interp); + status = Tcl_ListObjGetElements(tclrl_interp, obj, &objc, &objv); + if (TCL_OK != status) + return matches; + + if (objc) { + int i, length; + matches = (char**) MALLOC(sizeof(char*) * (objc + 1)); + for (i = 0; i < objc; i++) { + matches[i] = strdup(Tcl_GetStringFromObj(objv[i], &length)); + if (1 == objc && !strlen(matches[i])) { + FREE(matches[i]); + FREE(matches); + Tcl_ResetResult(tclrl_interp); /* clear result space */ + return (char**) NULL; + } + } + + /** + * this is a special one: + * if the script returns exactly two arguments + * and the second argument is the empty string, + * the rl_completion_append_character is set + * temporarily to NULL. + */ + if (2 == objc && !strlen(matches[1])) { + i--; + FREE(matches[1]); + rl_completion_append_character = '\0'; + } + + matches[i] = (char*) NULL; /* terminate */ + } + Tcl_ResetResult(tclrl_interp); /* clear result space */ } if (!matches && tclrl_use_builtin_completer) { - matches = rl_completion_matches(text, (rl_compentry_func_t *)TclReadline0generator); + matches = rl_completion_matches(text, (rl_compentry_func_t *)TclReadline0generator); } return matches; } @@ -778,116 +772,117 @@ int sub; switch (mode) { - case _CMD_SET: - - new = (cmds_t *) MALLOC(sizeof(cmds_t)); - new->next = (cmds_t *) NULL; - - if (!cmds) { - cmds = new; - cmds->prev = new; - } - else { - cmds->prev->next = new; - cmds->prev = new; - } - - tmp = strdup(text); - argc = TclReadlineParse(args, sizeof(args), tmp); - - new->cmd = (char**) MALLOC(sizeof(char*) * (argc + 1)); - - for (i = 0; i < argc; i++) - new->cmd[i] = args[i]; - - new->cmd[argc] = (char*) NULL; - - return (char*) NULL; - break; - - - case _CMD_GET: - - local_line = strdup(rl_line_buffer); - sub = TclReadlineParse(args, sizeof(args), local_line); - - if (0 == sub || (1 == sub && '\0' != text[0])) { - if (!state) { - new = cmds; - len = strlen(text); - } - while (new && (name = new->cmd)) { - new = new->next; - if (!strncmp(name[0], text, len)) - return strdup(name[0]); - } - return (char*) NULL; - } else { - - if (!state) { - - new = cmds; - len = strlen(text); - - while (new && (name = new->cmd)) { - if (!strcmp(name[0], args[0])) - break; - new = new->next; - } - - if (!new) - return (char*) NULL; - - for (i = 0; new->cmd[i]; i++) /* EMPTY */; - - if (sub < i && !strncmp(new->cmd[sub], text, len)) - return strdup(new->cmd[sub]); - else - return (char*) NULL; - - } - else - return (char*) NULL; - - /* NOTREACHED */ - break; - } - - - default: - return (char*) NULL; - break; - - } - /* NOTREACHED */ + case _CMD_SET: + + new = (cmds_t *) MALLOC(sizeof(cmds_t)); + new->next = (cmds_t *) NULL; + + if (!cmds) { + cmds = new; + cmds->prev = new; + } else { + cmds->prev->next = new; + cmds->prev = new; + } + + tmp = strdup(text); + argc = TclReadlineParse(args, sizeof(args), tmp); + + new->cmd = (char**) MALLOC(sizeof(char*) * (argc + 1)); + + for (i = 0; i < argc; i++) + new->cmd[i] = args[i]; + + new->cmd[argc] = (char*) NULL; + + return (char*) NULL; + /* NOTREACHED */ + break; + + + case _CMD_GET: + + local_line = strdup(rl_line_buffer); + sub = TclReadlineParse(args, sizeof(args), local_line); + + if (0 == sub || (1 == sub && '\0' != text[0])) { + if (!state) { + new = cmds; + len = strlen(text); + } + while (new && (name = new->cmd)) { + new = new->next; + if (!strncmp(name[0], text, len)) + return strdup(name[0]); + } + return (char*) NULL; + } else { + + if (!state) { + + new = cmds; + len = strlen(text); + + while (new && (name = new->cmd)) { + if (!strcmp(name[0], args[0])) + break; + new = new->next; + } + + if (!new) + return (char*) NULL; + + for (i = 0; new->cmd[i]; i++) /* EMPTY */; + + if (sub < i && !strncmp(new->cmd[sub], text, len)) + return strdup(new->cmd[sub]); + else + return (char*) NULL; + + } + else + return (char*) NULL; + } + + /* NOTREACHED */ + break; + + + default: + return (char*) NULL; + /* NOTREACHED */ + break; + + } } static int TclReadlineParse(char** args, int maxargs, char* buf) { int nr = 0; while (*buf != '\0' && nr < maxargs) { - /* - * Strip whitespace. Use nulls, so - * that the previous argument is terminated - * automatically. - */ - while (ISWHITE(*buf)) - *buf++ = '\0'; - - if (!(*buf)) /* don't count the terminating NULL */ - break; - - *args++ = buf; - nr++; - - while (('\0' != *buf) && !ISWHITE(*buf)) - buf++; + /* + * Strip whitespace. Use nulls, so + * that the previous argument is terminated + * automatically. + */ + while (ISWHITE(*buf)) + *buf++ = '\0'; + + if (!(*buf)) /* don't count the terminating NULL */ + break; + + *args++ = buf; + nr++; + + while (('\0' != *buf) && !ISWHITE(*buf)) + buf++; } *args = '\0'; return nr; } +