diff options
Diffstat (limited to 'libtecla-1.4.1')
114 files changed, 0 insertions, 39366 deletions
diff --git a/libtecla-1.4.1/CHANGES b/libtecla-1.4.1/CHANGES deleted file mode 100644 index 45073e0..0000000 --- a/libtecla-1.4.1/CHANGES +++ /dev/null @@ -1,1492 +0,0 @@ -In the following log, modification dates are listed using the European -convention in which the day comes before the month (ie. DD/MM/YYYY). -The most recent modifications are listed first. - -25/05/2002 mcs@astro.caltech.edu (based on suggestions by Paul Smith) - pathutil.c - Apparently, under QNX pathconf("/",_PC_PATH_MAX) returns - EINVAL. At Paul's suggestion I have modified the code to - silently substitute the existing MAX_PATHLEN_FALLBACK - value if pathconf() returns an error of any kind. - homedir.c - Under QNX, sysconf(_SC_GETPW_R_SIZE_MAX) also apparently - returns EINVAL, so as with pathconf() I modified the code - to substitute a fallback default, rather than - complaining and failing. - enhance.c - Paul told me that the inclusion of sys/termios.h was - causing compilation of enhance.c to fail under QNX. This - line is a bug. The correct thing to do is include - termios.h without a sub-directory prefix, as I was - already doing futher up in the file, so I have just - removed the errant include line. - -12/02/2002 mcs@astro.caltech.edu - getline.c configure.in configure - Mac OS X doesn't have a term.h or termcap.h, but it does - define prototypes for tputs() and setupterm(), so the - default prototypes that I was including if no headers - where available, upset it. I've removed these prototypes. - I also now conditionally include whichever is found of - curses.h and ncurses/curses.h for both termcap and - terminfo (before I wasn't including curses.h when - termcap was selected). - -12/02/2002 mcs@astro.caltech.edu - Updated version number to 1.4.1, ready for a micro - release. - -12/02/2002 mcs@astro.caltech.edu - html/index.html - Added Mac OS X and Cygwin to the list of systems that - can compile libtecla. - -12/02/2002 mcs@astro.caltech.edu - getline.c - Under Mac OS X, the tputs() callback function returns - void, instead of the int return value used by other - systems. This declaration is now used if both __MACH__ - and __APPLE__ are defined. Hopefully these are the - correct system macros to check. Thanks for Stephan - Fiedler for providing information on Mac OS X. - -11/02/2002 mcs@astro.caltech.edu - configure.in configure getline.c - Some systems don't have term.h, and others have it hidden - in an ncurses sub-directory of the standard system include - directory. If term.h can't be found, simply don't include - it. If it is in an ncurses sub-directory, include - ncurses/term.h instead of term.h. - -04/02/2002 mcs@astro.caltech.edu - configure.in configure Makefile.in Makefile.rules - Use ranlib on systems that need it (Mac OS X). Also, - make all components of the installation directories where - needed, instead of assuming that they exist. - -04/02/2002 mcs@astro.caltech.edu - getline.c - When the tab completion binding was unbound from the tab - key, hitting the tab key caused gl_get_line() to ring the - bell instead of inserting a tab character. This is - problematic when using the 'enhance' program with - Jython, since tabs are important in Python. I have - corrected this. - -10/12/2001 Version 1.4.0 released. - -10/12/2001 mcs@astro.caltech.edu - getline.c - If the TIOCGWINSZ ioctl doesn't work, as is the case when - running in an emacs shell, leave the size unchanged, rather - than returning a fatal error. - -07/12/2001 mcs@astro.caltech.edu - configure.in configure - Now that the configure version of CFLAGS is included in - the makefile, I noticed that the optimization flags -g - and -O2 had been added. It turns out that if CFLAGS isn't - already set, the autoconf AC_PROG_CC macro initializes it - with these two optimization flags. Since this would break - backwards compatibility in embedded distributions that - already use the OPT= makefile argument, and because - turning debugging on needlessly bloats the library, I now - make sure that CFLAGS is set before calling this macro. - -07/12/2001 mcs@astro.caltech.edu - enhance.c - Use argv[0] in error reports instead of using a - hardcoded macro. - -07/12/2001 mcs@astro.caltech.edu - getline.c - The cut buffer wasn't being cleared after being - used as a work buffer by gl_load_history(). - -06/12/2001 mcs@astro.caltech.edu - configure.in configure - I removed my now redundant definition of SUN_TPUTS from - CFLAGS. I also added "-I/usr/include" to CFLAGS under - Solaris to prevent gcc from seeing conflicting versions - of system header files in /usr/local/include. - -06/12/2001 Markus Gyger (logged here by mcs) - Lots of files. - Lots of corrections to misspellings and typos in the - comments. - getline.c - Markus reverted a supposed fix that I added a day or two - ago. I had incorrectly thought that in Solaris 8, Sun had - finally brought their declaration of the callback - function of tputs() into line with other systems, but it - turned out that gcc was pulling in a GNU version of - term.h from /usr/local/include, and this was what - confused me. - -05/12/2001 mcs@astro.caltech.edu - Makefile.in - I added @CFLAGS@ to the CFLAGS assignment, so that - if CFLAGS is set as an environment variable when - configure is run, the corresponding make variable - includes its values in the output makefile. - -05/12/2001 mcs@astro.caltech.edu - getline.c libtecla.h libtecla.map man3/gl_get_line.3 - man3/gl_last_signal.3 - I added a function that programs can use to find out - which signal caused gl_get_line() to return EINTR. - -05/12/2001 mcs@astro.caltech.edu - getline.c - When the newline action was triggered by a printable - character, it failed to display that character. It now - does. Also, extra control codes that I had added, to - clear to the end of the display after the carriage return, - but before displaying the prompt, were confusing expect - scripts, so I have removed them. This step is now done - instead in gl_redisplay() after displaying the full input - line. - -05/12/2001 mcs@astro.caltech.edu - getline.c man3/gl_get_line.3 - A user convinced me that continuing to invoke meta - keybindings for meta characters that are printable is a - bad idea, as is allowing users to ask to have setlocale() - called behind the application's back. I have thus changed - this. The setlocale configuration option has gone, and - gl_get_line() is now completely 8-bit clean, by default. - This means that if a meta character is printable, it is - treated as a literal character, rather than a potential - M-c binding. Meta bindings can still be invoked via - their Esc-c equivalents, and indeed most terminal - emulators either output such escape pairs by default when - the meta character is pressed, or can be configured to do - so. I have documented how to configure xterm to do this, - in the man page. - -03/12/2001 mcs@astro.caltech.edu - getline.c man3/gl_get_line.3 - gl_get_line() by default now prints any 8-bit printable - characters that don't match keybindings. Previously - characters > 127 were only printed if preceded by the - literal-next action. Alternatively, by placing the - command literal_if_printable in the tecla configuration - file, all printable characters are treated as literal - characters, even if they are bound to action functions. - - For international users of programs written by - programmers that weren't aware of the need to call - setlocale() to support alternate character sets, the - configuration file can now also contain the single-word - command "setlocale", which tells gl_get_line() to remedy - this. - -27/11/2001 mcs@astro.caltech.edu - demo.c demo2.c enhance man3/gl_get_line.3 - All demos and programs now call setlocale(LC_CTYPE,""). - This makes them support character sets of different - locales, where specified with the LC_CTYPE, LC_ALL, or - LANG environment variables. I also added this to the demo - in the man page, and documented its effect. - -27/11/2001 mcs@astro.caltech.edu - getline.c - When displaying unsigned characters with values over - 127 literally, previously it was assumed that they would - all be displayable. Now isprint() is consulted, and if it - says that a character isn't printable, the character code - is displayed in octal like \307. In non-C locales, some - characters with values > 127 are displayable, and - isprint() tells gl_get_line() which are and which aren't. - -27/11/2001 mcs@astro.caltech.edu - getline.c pathutil.c history.c enhance.c demo2.c - All arguments of the ctype.h character class functions - are now cast to (int)(unsigned char). Previously they - were cast to (int), which doesn't correctly conform to - the requirements of the C standard, and could cause - problems for characters with values > 127 on systems - with signed char's. - -26/11/2001 mcs@astro.caltech.edu - man3/enhance.3 man3/libtecla.3 - I started writing a man page for the enhance program. - -26/11/2001 mcs@astro.caltech.edu - Makefile.in Makefile.rules INSTALL - It is now possible to specify whether the demos and other - programs are to be built, by overriding the default - values of the DEMOS, PROGRAMS and PROGRAMS_R variables. - I have also documented the BINDIR variable and the - install_bin makefile target. - -22/11/2001 mcs@astro.caltech.edu - getline.c libtecla.h libtecla.map man3/gl_get_line.3 - man3/gl_ignore_signal.3 man3/gl_trap_signal.3 - Signal handling has now been modified to be customizable. - Signals that are trapped by default can be removed from - the list of trapped signals, and signals that aren't - currently trapped, can be added to the list. Applications - can also specify the signal and terminal environments in - which an application's signal handler is invoked, and - what gl_get_line() does after the signal handler returns. - -13/11/2001 mcs@astro.caltech.edu - getline.c man3/gl_get_line.3 - Added half-bright, reverse-video and blinking text to the - available prompt formatting options. - getline.c - Removed ^O from the default VT100 sgr0 capability - string. Apparently it can cause problems with some - terminal emulators, and we don't need it, since it turns - off the alternative character set mode, which we don't - use. - getline.c - gl_tigetstr() and gl_tgetstr() didn't guard against the - error returns of tigetstr() and tgetstr() respectively. - They now do. - -11/11/2001 mcs@astro.caltech.edu - getline.c libtecla.h libtecla.map man3/gl_get_line.3 - man3/gl_prompt_style.3 - Although the default remains to display the prompt string - literally, the new gl_prompt_style() function can be used - to enable text attribute formatting directives in prompt - strings, such as underlining, bold font, and highlighting - directives. - -09/11/2001 mcs@astro.caltech.edu - enhance.c Makefile.rules configure.in configure - I added a new program to the distribution that allows one - to run most third party programs with the tecla library - providing command-line editing. - -08/11/2001 mcs@astro.caltech.edu - libtecla.h getline.c man3/gl_get_line.3 history.c history.h - I added a max_lines argument to gl_show_history() and - _glh_show_history(). This can optionally be used to - set a limit on the number of history lines displayed. - libtecla.h getline.c man3/gl_get_line.3 - I added a new function called gl_replace_prompt(). This - can be used by gl_get_line() callback functions to - request that a new prompt be use when they return. - -06/11/2001 mcs@astro.caltech.edu - getline.c man3/gl_get_line.3 - I implemented, bound and documented the list-history - action, used for listing historical lines of the current - history group. - getline.c man3/gl_get_line.3 man3/gl_echo_mode.3 - I wrote functions to specify and query whether subsequent - lines will be visible as they are being typed. - -28/10/2001 mcs@astro.caltech.edu - getline.c man3/gl_get_line.3 - For those cases where a terminal provides its own - high-level terminal editing facilities, you can now - specify an edit-mode argument of 'none'. This disables - all tecla key bindings, and by using canonical terminal - input mode instead of raw input mode, editing is left up - to the terminal driver. - -21/10/2001 mcs@astro.caltech.edu - libtecla.h getline.c history.c history.h - man3/gl_get_line.3 man3/gl_history_info.3 - I added the new gl_state_of_history(), - gl_range_of_history() and gl_size_of_history() - functions for querying information about the - history list. - history.c - While testing the new gl_size_of_history() - function, I noticed that when the history buffer - wrapped, any location nodes of old lines between - the most recent line and the end of the buffer - weren't being removed. This could result in bogus - entries appearing at the start of the history list. - Now fixed. - -20/10/2001 mcs@astro.caltech.edu - - libtecla.h getline.c history.c history.h - man3/gl_get_line.3 man3/gl_lookup_history.3 - I added a function called gl_lookup_history(), that - the application can use to lookup lines in the history - list. - libtecla.h getline.c history.c history.h man3/gl_get_line.3 - gl_show_history() now takes a format string argument - to control how the line is displayed, and with what - information. It also now provides the option of either - displaying all history lines or just those of the - current history group. - getline.c man3/gl_get_line.3 - gl_get_line() only archives lines in the history buffer - if the newline action was invoked by a newline or - carriage return character. - -16/10/2001 mcs@astro.caltech.edu - - history.c history.h getline.c libtecla.h libtecla.map - man3/gl_get_line.3 man3/gl_resize_history.3 - man3/gl_limit_history.3 man3/gl_clear_history.3 - man3/gl_toggle_history.3 - I added a number of miscellaneous history configuration - functions. You can now resize or delete the history - buffer, limit the number of lines that are allowed in the - buffer, clear either all history or just the history of - the current history group, and temporarily enable and - disable the history mechanism. - -13/10/2001 mcs@astro.caltech.edu - - getline.c - tputs_fp is now only declared if using termcap or - terminfo. - getline.c libtecla.map man3/gl_get_line.3 - man3/gl_terminal_size.3 - I added a public gl_terminal_size() function for - updating and querying the current size of the terminal. - update_version configure.in libtecla.h - A user noted that on systems where the configure script - couldn't be used, it was inconvenient to have the version - number macros set by the configure script, so they are - now specified in libtecla.h. To reduce the likelihood - that the various files where the version number now - appears might get out of sync, I have written the - update_version script, which changes the version number - in all of these files to a given value. - -01/10/2001 mcs@astro.caltech.edu - - getline.c history.c history.h man3/gl_get_line.3 - I added a max_lines argument to gl_save_history(), to - allow people to optionally place a ceiling on the number - of history lines saved. Specifying this as -1 sets the - ceiling to infinity. - -01/10/2001 mcs@astro.caltech.edu - - configure.in configure - Under digital unix, getline wouldn't compile with - _POSIX_C_SOURCE set, due to type definitions needed by - select being excluded by this flag. Defining the - _OSF_SOURCE macro as well on this system, resolved this. - -30/09/2001 mcs@astro.caltech.edu - - getline.c libtecla.h history.c history.h man3/gl_get_line.3 - man3/gl_group_history.3 - I implemented history streams. History streams - effectively allow multiple history lists to be stored in - a single history buffer. Lines in the buffer are tagged - with the current stream identification number, and - lookups only consider lines that are marked with the - current stream identifier. - getline.c libtecla.h history.c history.h man3/gl_get_line.3 - man3/gl_show_history.3 - The new gl_show_history function displays the current - history to a given stdio output stream. - -29/09/2001 mcs@astro.caltech.edu - - getline.c - Previously new_GetLine() installed a persistent signal - handler to be sure to catch the SIGWINCH (terminal size - change) signal between calls to gl_get_line(). This had - the drawback that if multiple GetLine objects were - created, only the first GetLine object used after the - signal was received, would see the signal and adapt to - the new terminal size. Instead of this, a signal handler - for sigwinch is only installed while gl_get_line() is - running, and just after installing this handler, - gl_get_line() checks for terminal size changes that - might have occurred while the signal handler wasn't - installed. - getline.c - Dynamically allocated copies of capability strings looked - up in the terminfo or termcap databases are now made, so - that calls to setupterm() etc for one GetLine object - don't get trashed when another GetLine object calls - setupterm() etc. It is now safe to allocate and use - multiple GetLine objects, albeit only within a single - thread. - -28/09/2001 mcs@astro.caltech.edu - - version.c Makefile.rules - I added a function for querying the version number of - the library. - -26/09/2001 mcs@astro.caltech.edu - - getline.c man3/gl_get_line.3 - I added the new gl_watch_fd() function, which allows - applications to register callback functions to be invoked - when activity is seen on arbitrary file descriptors while - gl_get_line() is awaiting keyboard input from the user. - - keytab.c - If a request is received to delete a non-existent - binding, which happens to be an ambiguous prefix of other - bindings no complaint is now generated about it being - ambiguous. - -23/09/2001 mcs@astro.caltech.edu - - getline.c history.c history.h man3/gl_get_line.3 - libtecla.map demo.c - I added new public functions for saving and restoring the - contents of the history list. The demo program now uses - these functions to load and save history in ~/.demo_history. - -23/09/2001 mcs@astro.caltech.edu - - getline.c - On trying the demo for the first time on a KDE konsole - terminal, I discovered that the default M-O binding - to repeat history was hiding the arrow keys, which are - M-OA etc. I have removed this binding. The M-o (ie the - lower case version of this), is still bound. - -18/09/2001 mcs@astro.caltech.edu - - getline.c man3/gl_get_line.3 libtecla.map - Automatic reading of ~/.teclarc is now postponed until - the first call to gl_get_line(), to give the application - the chance to specify alternative configuration sources - with the new function gl_configure_getline(). The latter - function allows configuration to be done with a string, a - specified application-specific file, and/or a specified - user-specific file. I also added a read-init-files action - function, for re-reading the configuration files, if any. - This is by default bound to ^X^R. This is all documented - in gl_get_line.3. - -08/09/2001 mcs@astro.caltech.edu - - getline.c man3/gl_get_line.3 - It is now possible to bind actions to key-sequences - that start with printable characters. Previously - keysequences were required to start with meta or control - characters. This is documented in gl_get_line.3. - - getline.c man3/gl_get_line.3 - A customized completion function can now arrange for - gl_get_line() to return the current input line whenever a - successful completion has been made. This is signalled by - setting the last character of the optional continuation - suffix to a newline character. This is documented in - gl_get_line.3. - -05/07/2001 Bug reported by Mike MacFaden, fixed by mcs - - configure.in - There was a bug in the configure script that only - revealed itself on systems without termcap but not - terminfo (eg. NetBSD). I traced the bug back to a lack of - sufficient quoting of multi-line m4 macro arguments in - configure.in, and have now fixed this and recreated the - configure script. - -05/07/2001 Bug reported and patched by Mike MacFaden (patch modified - by mcs to match original intentions). - - getline.c - getline.c wouldn't compile when termcap was selected as - the terminal information database. setupterm() was being - passed a non-existent variable, in place of the term[] - argument of gl_control_strings(). Also if - gl_change_terminal() is called with term==NULL, "ansi" - is now substituted. - -02/07/2001 Version 1.3.3 released. - -27/06/2001 mcs@astro.caltech.edu - - getline.c expand.c cplmatch.c - Added checks to fprintf() statements that write to the - terminal. - getline.c - Move the cursor to the end of the line before suspending, - so that the cursor doesn't get left in the middle of the - input line. - Makefile.in - On systems that don't support shared libraries, the - distclean target of make deleted libtecla.h. This has - now been fixed. - getline.c - gl_change_terminal() was being called by gl_change_editor(), - with the unwanted side effect that raw terminal modes were - stored as those to be restored later, if called by an - action function. gl_change_terminal() was being called in - this case to re-establish terminal-specific key bindings, - so I have just split this part of the function out into - a separate function for both gl_change_editor() and - gl_change_terminal() to call. - -12/06/2001 mcs@astro.caltech.edu - - getline.c - Signal handling has been improved. Many more signals are - now trapped, and instead of using a simple flag set by a - signal handler, race conditions are avoided by blocking - signals during most of the gl_get_line() code, and - unblocking them via calls to sigsetjmp(), just before - attempting to read each new character from the user. - The matching use of siglongjmp() in the signal - handlers ensures that signals are reblocked correctly - before they are handled. In most cases, signals cause - gl_get_line() to restore the terminal modes and signal - handlers of the calling application, then resend the - signal to the application. In the case of SIGINT, SIGHUP, - SIGPIPE, and SIGQUIT, if the process still exists after - the signals are resent, gl_get_line() immediately returns - with appropriate values assigned to errno. If SIGTSTP, - SIGTTIN or SIGTTOU signals are received, the process is - suspended. If any other signal is received, and the - process continues to exist after the signal is resent to - the calling application, line input is resumed after the - terminal is put back into raw mode, the gl_get_line() - signal handling is restored, and the input line redrawn. - man/gl_get_line(3) - I added a SIGNAL HANDLING section to the gl_get_line() - man page, describing the new signal handling features. - -21/05/2001 Version 1.3.2 released. - -21/05/2001 mcs@astro.caltech.edu - - getline.c - When vi-replace-char was used to replace the character at - the end of the line, it left the cursor one character to - its right instead of on top of it. Now rememdied. - getline.c - When undoing, to properly emulate vi, the cursor is now - left at the leftmost of the saved and current cursor - positions. - getline.c man3/gl_get_line.3 - Implemented find-parenthesis (%), delete-to-paren (M-d%), - vi-change-to-paren (M-c%), copy-to-paren (M-y%). - cplfile.c pcache.c - In three places I was comparing the last argument of - strncmp() to zero instead of the return value of - strncmp(). - -20/05/2001 mcs@astro.caltech.edu - - getline.c man3/gl_get_line.3 - Implemented and documented the vi-repeat-change action, - bound to the period key. This repeats the last action - that modified the input line. - -19/05/2001 mcs@astro.caltech.edu - - man3/gl_get_line.3 - I documented the new action functions and bindings - provided by Tim Eliseo, plus the ring-bell action and - the new "nobeep" configuration option. - getline.c - I modified gl_change_editor() to remove and reinstate the - terminal settings as well as the default bindings, since - these have editor-specific differences. I also modified - it to not abort if a key-sequence can't be bound for some - reason. This allows the new vi-mode and emacs-mode - bindings to be used safely. - getline.c - When the line was re-displayed on receipt of a SIGWINCH - signal, the result wasn't visible until the next - character was typed, since a call to fflush() was needed. - gl_redisplay_line() now calls gl_flush_output() to remedy - this. - -17/05/2001 mcs@astro.catlech.edu - - getline.c - Under Linux, calling fflush(gl->output_fd) hangs if - terminal output has been suspended with ^S. With the - tecla library taking responsability for reading the stop - and start characters this was a problem, because once - hung in fflush(), the keyboard input loop wasn't entered, - so the user couldn't type the start character to resume - output. To remedy this, I now have the terminal process - these characters, rather than the library. - -12/05/2001 mcs@astro.caltech.edu - - getline.c - The literal-next action is now implemented as a single - function which reads the next character itself. - Previously it just set a flag which effected the - interpretation of the next character read by the input - loop. - getline.c - Added a ring-bell action function. This is currently - unbound to any key by default, but it is used internally, - and can be used by users that want to disable any of the - default key-bindings. - -12/05/2001 Tim Eliseo (logged here by mcs) - - getline.c - Don't reset gl->number until after calling an action - function. By looking at whether gl->number is <0 or - not, action functions can then tell whether the count - that they were passed was explicitly specified by the - user, as opposed to being defaulted to 1. - getline.c - In vi, the position at which input mode is entered - acts as a barrier to backward motion for the few - backward moving actions that are enabled in input mode. - Tim added this barrier to getline. - getline.c - In gl_get_line() after reading an input line, or - having the read aborted by a signal, the sig_atomic_t - gl_pending_signal was being compared to zero instead - of -1 to see if no signals had been received. - gl_get_line() will thus have been calling raise(-1), - which luckily didn't seem to do anything. Tim also - arranged for errno to be set to EINTR when a signal - aborts gl_get_line(). - getline.c - The test in gl_add_char_to_line() for detecting - when overwriting a character with a wider character, - had a < where it needed a >. Overwriting with a wider - character thus overwrote trailing characters. Tim also - removed a redundant copy of the character into the - line buffer. - getline.c - gl_cursor_left() and gl->cursor_right() were executing - a lot of redundant code, when the existing call to the - recently added gl_place_cursor() function, does all that - is necessary. - getline.c - Remove redundant code from backward_kill_line() by - re-implimenting in terms of gl_place_cursor() and - gl_delete_chars(). - getline.c - gl_forward_delete_char() now records characters in cut - buffer when in vi command mode. - getline.c - In vi mode gl_backward_delete_char() now only deletes - up to the point at which input mode was entered. Also - gl_delete_chars() restores from the undo buffer when - deleting in vi insert mode. - getline.c - Added action functions, vi-delete-goto-column, - vi-change-to-bol, vi-change-line, emacs-mode, vi-mode, - vi-forward-change-find, vi-backward-change-find, - vi-forward-change-to, vi-backward-change-to, - vi-change-goto-col, forward-delete-find, backward-delete-find, - forward-delete-to, backward-delete-to, - delete-refind, delete-invert-refind, forward-copy-find, - backward-copy-find, forward-copy-to, backward-copy-to - copy-goto-column, copy-rest-of-line, copy-to-bol, copy-line, - history-re-search-forward, history-re-search-backward. - -06/05/2001 Version 1.3.1 released. - -03/05/2001 mcs@astro.caltech.edu - - configure.in - Old versions of GNU ld don't accept version scripts. - Under Linux I thus added a test to try out ld with - the --version-script argument to see if it works. - If not, version scripts aren't used. - configure.in - My test for versions of Solaris earlier than 7 - failed when confronted by a three figure version - number (2.5.1). Fixed. - -30/04/2001 mcs@astro.caltech.edu - - getline.c - In vi mode, history-search-backward and - history-search-forward weren't doing anything when - invoked at the start of an empty line, whereas - they should have acted like up-history and down-history. - Makefile.in Makefile.rules - When shared libraries are being created, the build - procedure now arranges for any alternate library - links to be created as well, before linking the - demos. Without this the demos always linked to the - static libraries (which was perfectly ok, but wasn't a - good example). - Makefile.in Makefile.rules - On systems on which shared libraries were being created, - if there were no alternate list of names, make would - abort due to a Bourne shell 'for' statement that didn't - have any arguments. Currently there are no systems who's - shared library configurations would trigger this - problem. - Makefile.rules - The demos now relink to take account of changes to the - library. - configure.in configure - When determining whether the reentrant version of the - library should be compiled by default, the configure - script now attempts to compile a dummy program that - includes all of the appropriate system headers and - defines _POSIX_C_SOURCE. This should now be a robust test - on systems which use C macros to alias these function - names to other internal functions. - configure.in - Under Solaris 2.6 and earlier, the curses library is in - /usr/ccs/lib. Gcc wasn't finding this. In addition to - remedying this, I had to remove "-z text" from - LINK_SHARED under Solaris to get it to successfully - compile the shared library against the static curses - library. - configure.in - Under Linux the -soname directive was being used - incorrectly, citing the fully qualified name of the - library instead of its major version alias. This will - unfortunately mean that binaries linked with the 1.2.3 - and 1.2.4 versions of the shared library won't use - later versions of the library unless relinked. - -30/04/2001 mcs@astro.caltech.edu - - getline.c - In gl_get_input_line(), don't redundantly copy the - start_line if start_line == gl->line. - -30/04/2001 Version 1.3.0 released. - -28/04/2001 mcs@astro.caltech.edu - - configure.in - I removed the --no-undefined directive from the Linux - LINK_SHARED command. After recent patches to our RedHat - 7.0 systems ld started reporting some internal symbols of - libc as being undefined. Using nm on libc indicated that - the offending symbols are indeed defined, albeit as - "common" symbols, so there appears to be a bug in - RedHat's ld. Removing this flag allows the tecla shared - library to compile, and programs appear to function fine. - man3/gl_get_line.3 - The default key-sequence used to invoke the - read-from-file action was incorrectly cited as ^Xi - instead of ^X^F. - -26/04/2001 mcs@astro.caltech.edu - - getline.c man3/gl_get_line.3 - A new vi-style editing mode was added. This involved - adding many new action functions, adding support for - specifying editing modes in users' ~/.teclarc files, - writing a higher level cursor motion function to support - the different line-end bounds required in vi command - mode, and a few small changes to support the fact that vi - has two modes, input mode and command mode with different - bindings. - - When vi editing mode is enabled, any binding that starts - with an escape or a meta character, is interpreted as a - command-mode binding, and switches the library to vi - command mode if not already in that mode. Once in command - mode the first character of all keysequences entered - until input mode is re-enabled, are quietly coerced to - meta characters before being looked up in the key-binding - table. So, for example, in the key-binding table, the - standard vi command-mode 'w' key, which moves the cursor - one word to the right, is represented by M-w. This - emulates vi's dual sets of bindings in a natural way - without needing large changes to the library, or new - binding syntaxes. Since cursor keys normally emit - keysequences which start with escape, it also does - something sensible when a cursor key is pressed during - input mode (unlike true vi, which gets upset). - - I also added a ^Xg binding for the new list-glob action - to both the emacs and vi key-binding tables. This lists - the files that match the wild-card expression that - precedes it on the command line. - - The function that reads in ~/.teclarc used to tell - new_GetLine() to abort if it encountered anything that it - didn't understand in this file. It now just reports an - error and continues onto the next line. - Makefile.in: - When passing LIBS=$(LIBS) to recursive invokations of - make, quotes weren't included around the $(LIBS) part. - This would cause problems if LIBS ever contained more - than one word (with the supplied configure script this - doesn't happen currently). I added these quotes. - expand.c man3/ef_expand_file.3: - I wrote a new public function called ef_list_expansions(), - to list the matching filenames returned by - ef_expand_file(). - - I also fixed the example in the man page, which cited - exp->file instead of exp->files, and changed the - dangerous name 'exp' with 'expn'. - keytab.c: - Key-binding tables start with 100 elements, and are - supposedly incremented in size by 100 elements whenever - the a table runs out of space. The realloc arguments to - do this were wrong. This would have caused problems if - anybody added a lot of personal bindings in their - ~/.teclarc file. I only noticed it because the number of - key bindings needed by the new vi mode exceeded this - number. - libtecla.map - ef_expand_file() is now reported as having been added in - the upcoming 1.3.0 release. - -25/03/2001 Markus Gyger (logged here by mcs) - - Makefile.in: - Make symbolic links to alternative shared library names - relative instead of absolute. - Makefile.rules: - The HP-UX libtecla.map.opt file should be made in the - compilation directory, to allow the source code directory - to be on a readonly filesystem. - cplmatch.c demo2.c history.c pcache.c - To allow the library to be compiled with a C++ compiler, - without generating warnings, a few casts were added where - void* return values were being assigned directly to - none void* pointer variables. - -25/03/2001 mcs@astro.caltech.edu - - libtecla.map: - Added comment header to explain the purpose of the file. - Also added cpl_init_FileArgs to the list of exported - symbols. This symbol is deprecated, and no longer - documented, but for backwards compatibility, it should - still be exported. - configure: - I had forgotten to run autoconf before releasing version - 1.2.4, so I have just belatedly done so. This enables - Markus' changes to "configure.in" documented previously, - (see 17/03/2001). - -20/03/2001 John Levon (logged here by mcs) - - libtecla.h - A couple of the function prototypes in libtecla.h have - (FILE *) argument declarations, which means that stdio.h - needs to be included. The header file should be self - contained, so libtecla.h now includes stdio.h. - -18/03/2001 Version 1.2.4 released. - - README html/index.html configure.in - Incremented minor version from 3 to 4. - -18/03/2001 mcs@astro.caltech.edu - - getline.c - The fix for the end-of-line problem that I released a - couple of weeks ago, only worked for the first line, - because I was handling this case when the cursor position - was equal to the last column, rather than when the cursor - position modulo ncolumn was zero. - Makefile.in Makefile.rules - The demos are now made by default, their rules now being - int Makefile.rules instead of Makefile.in. - INSTALL - I documented how to compile the library in a different - directory than the distribution directory. - I also documented features designed to facilitate - configuring and building the library as part of another - package. - -17/03/2001 Markus Gyger (logged here by mcs) - - getline.c - Until now cursor motions were done one at a time. Markus - has added code to make use the of the terminfo capability - that moves the cursor by more than one position at a - time. This greatly improves performance when editing near - the start of long lines. - getline.c - To further improve performance, Markus switched from - writing one character at a time to the terminal, using - the write() system call, to using C buffered output - streams. The output buffer is only flushed when - necessary. - Makefile.rules Makefile.in configure.in - Added support for compiling for different architectures - in different directories. Simply create another directory - and run the configure script located in the original - directory. - Makefile.in configure.in libtecla.map - Under Solaris, Linux and HP-UX, symbols that are to be - exported by tecla shared libraries are explicitly specified - via symbol map files. Only publicly documented functions - are thus visible to applications. - configure.in - When linking shared libraries under Solaris SPARC, - registers that are reserved for applications are marked - as off limits to the library, using -xregs=no%appl when - compiling with Sun cc, or -mno-app-regs when compiling - with gcc. Also removed -z redlocsym for Solaris, which - caused problems under some releases of ld. - homedir.c (after minor changes by mcs) - Under ksh, ~+ expands to the current value of the ksh - PWD environment variable, which contains the path of - the current working directory, including any symbolic - links that were traversed to get there. The special - username "+" is now treated equally by tecla, except - that it substitutes the return value of getcwd() if PWD - either isn't set, or if it points at a different - directory than that reported by getcwd(). - -08/03/2001 Version 1.2.3 released. - -08/03/2001 mcs@astro.caltech.edu - - getline.c - On compiling the library under HP-UX for the first time - I encountered and fixed a couple of bugs: - - 1. On all systems except Solaris, the callback function - required by tputs() takes an int argument for the - character that is to be printed. Under Solaris it - takes a char argument. The callback function was - passing this argument, regardless of type, to write(), - which wrote the first byte of the argument. This was - fine under Solaris and under little-endian systems, - because the first byte contained the character to be - written, but on big-endian systems, it always wrote - the zero byte at the other end of the word. As a - result, no control characters were being written to - the terminal. - 2. While attempting to start a newline after the user hit - enter, the library was outputting the control sequence - for moving the cursor down, instead of the newline - character. On many systems the control sequence for - moving the cursor down happends to be a newline - character, but under HP-UX it isn't. The result was - that no new line was being started under HP-UX. - -04/03/2001 mcs@astro.caltech.edu - - configure.in Makefile.in Makefile.stub configure config.guess - config.sub Makefile.rules install-sh PORTING README INSTALL - Configuration and compilation of the library is now - performed with the help of an autoconf configure - script. In addition to relieving the user of the need to - edit the Makefile, this also allows automatic compilation - of the reentrant version of the library on platforms that - can handle it, along with the creation of shared - libraries where configured. On systems that aren't known - to the configure script, just the static tecla library is - compiled. This is currently the case on all systems - except Linux, Solaris and HP-UX. In the hope that - installers will provide specific conigurations for other - systems, the configure.in script is heavily commented, - and instructions on how to use are included in a new - PORTING file. - -24/02/2001 Version 1.2b released. - -22/02/2001 mcs@astro.caltech.edu - - getline.c - It turns out that most terminals, but not all, on writing - a character in the rightmost column, don't wrap the - cursor onto the next line until the next character is - output. This library wasn't aware of this and thus if one - tried to reposition the cursor from the last column, - gl_get_line() thought that it was moving relative to a - point on the next line, and thus moved the cursor up a - line. The fix was to write one extra character when in - the last column to force the cursor onto the next line, - then backup the cursor to the start of the new line. - getline.c - On terminal initialization, the dynamic LINES and COLUMNS - environment variables were ignored unless - terminfo/termcap didn't return sensible dimensions. In - practice, when present they should override the static - versions in the terminfo/termcap databases. This is the - new behavior. In reality this probably won't have caused - many problems, because a SIGWINCH signal which informs of - terminal size changes is sent when the terminal is - opened, so the dimensions established during - initialization quickly get updated on most systems. - -18/02/2001 Version 1.2a released. - -18/02/2001 mcs@astro.caltech.edu - - getline.c - Three months ago I moved the point at which termios.h - was included in getline.c. Unfortunately, I didn't notice - that this moved it to after the test for TIOCGWINSZ being - defined. This resulted in SIGWINCH signals not being - trapped for, and thus terminal size changes went - unnoticed. I have now moved the test to after the - inclusion of termios.h. - -12/02/2001 Markus Gyger (described here by mcs) - - man3/pca_lookup_file.3 man3/gl_get_line.3 - man3/ef_expand_file.3 man3/cpl_complete_word.3 - In the 1.2 release of the library, all functions in the - library were given man pages. Most of these simply - include one of the above 4 man pages, which describe the - functions while describing the modules that they are in. - Markus added all of these function names to the lists in - the "NAME" headers of the respective man pages. - Previously only the primary function of each module was - named there. - -11/02/2001 mcs@astro.caltech.edu - - getline.c - On entering a line that wrapped over two or more - terminal, if the user pressed enter when the cursor - wasn't on the last of the wrapped lines, the text of the - wrapped lines that followed it got mixed up with the next - line written by the application, or the next input - line. Somehow this slipped through the cracks and wasn't - noticed until now. Anyway, it is fixed now. - -09/02/2001 Version 1.2 released. - -04/02/2001 mcs@astro.caltech.edu - - pcache.c libtecla.h - With all filesystems local, demo2 was very fast to start - up, but on a Sun system with one of the target - directories being on a remote nfs mounted filesystem, the - startup time was many seconds. This was due to the - executable selection callback being applied to all files - in the path at startup. To avoid this, all files are now - included in the cache, and the application specified - file-selection callback is only called on files as they - are matched. Whether the callback rejected or accepted - them is then cached so that the next time an already - checked file is looked at, the callback doesn't have to - be called. As a result, startup is now fast on all - systems, and since usually there are only a few matching - file completions at a time, the delay during completion - is also usually small. The only exception is if the user - tries to complete an empty string, at which point all - files have to be checked. Having done this once, however, - doing it again is fast. - man3/pca_lookup_file.3 - I added a man page documenting the new PathCache module. - man3/<many-new-files>.3 - I have added man pages for all of the functions in each - of the modules. These 1-line pages use the .so directive - to redirect nroff to the man page of the parent module. - man Makefile update_html - I renamed man to man3 to make it easier to test man page - rediction, and updated Makefile and update_html - accordingly. I also instructed update_html to ignore - 1-line man pages when making html equivalents of the man - pages. - cplmatch.c - In cpl_list_completions() the size_t return value of - strlen() was being used as the length argument of a "%*s" - printf directive. This ought to be an int, so the return - value of strlen() is now cast to int. This would have - caused problems on architectures where the size of a - size_t is not equal to the size of an int. - -02/02/2001 mcs@astro.caltech.edu - - getline.c - Under UNIX, certain terminal bindings are set using the - stty command. This, for example, specifies which control - key generates a user-interrupt (usually ^C or ^Y). What I - hadn't realized was that ASCII NUL is used as the way to - specify that one of these bindings is unset. I have now - modified the code to skip unset bindings, leaving the - corresponding action bound to the built-in default, or a - user provided binding. - -28/01/2001 mcs@astro.caltech.edu - - pcache.c libtecla.h - A new module was added which supports searching for files - in any colon separated list of directories, such as the - unix execution PATH environment variable. Files in these - directories, after being individually okayed for - inclusion via an application provided callback, are - cached in a PathCache object. You can then look up the - full pathname of a given filename, or you can use the - provided completion callback to list possible completions - in the path-list. The contents of relative directories, - such as ".", obviously can't be cached, so these - directories are read on the fly during lookups and - completions. The obvious application of this facility is - to provide Tab-completion of commands, and thus a - callback to place executable files in the cache, is - provided. - demo2.c - This new program demonstrates the new PathCache - module. It reads and processes lines of input until the - word 'exit' is entered, or C-d is pressed. The default - tab-completion callback is replaced with one which at the - start of a line, looks up completions of commands in the - user's execution path, and when invoked in other parts of - the line, reverts to normal filename completion. Whenever - a new line is entered, it extracts the first word on the - line, looks it up in the user's execution path to see if - it corresponds to a known command file, and if so, - displays the full pathname of the file, along with the - remaining arguments. - cplfile.c - I added an optional pair of callback function/data - members to the new cpl_file_completions() configuration - structure. Where provided, this callback is asked - on a file-by-file basis, which files should be included - in the list of file completions. For example, a callback - is provided for listing only completions of executable - files. - cplmatch.c - When listing completions, the length of the type suffix - of each completion wasn't being taken into account - correctly when computing the column widths. Thus the - listing appeared ragged sometimes. This is now fixed. - pathutil.c - I added a function for prepending a string to a path, - and another for testing whether a pathname referred to - an executable file. - -28/01/2001 mcs@astro.caltech.edu - - libtecla.h cplmatch.c man/cpl_complete_word.3 - The use of a publically defined structure to configure - the cpl_file_completions() callback was flawed, so a new - approach has been designed, and the old method, albeit - still supported, is no longer documented in the man - pages. The definition of the CplFileArgs structure in - libtecla.h is now accompanied by comments warning people - not to modify it, since modifications could break - applications linked to shared versions of the tecla - library. The new method involves an opaque CplFileConf - object, instances of which are returned by a provided - constructor function, configured with provided accessor - functions, and when no longer needed, deleted with a - provided destructor function. This is documented in the - cpl_complete_word man page. The cpl_file_completions() - callback distinguishes what type of configuration - structure it has been sent by virtue of a code placed at - the beginning of the CplFileConf argument by its - constructor. - -04/01/2001 mcs@astro.caltech.edu (Release of version 1.1j) - - getline.c - I added upper-case bindings for the default meta-letter - keysequences such as M-b. They thus continue to work - when the user has caps-lock on. - Makefile - I re-implemented the "install" target in terms of new - install_lib, install_inc and install_man targets. When - distributing the library with other packages, these new - targets allows for finer grained control of the - installation process. - -30/12/2000 mcs@astro.caltech.edu - - getline.c man/gl_get_line.3 - I realized that the recall-history action that I - implemented wasn't what Markus had asked me for. What he - actually wanted was for down-history to continue going - forwards through a previous history recall session if no - history recall session had been started while entering - the current line. I have thus removed the recall-history - action and modified the down-history action function - accordingly. - -24/12/2000 mcs@astro.caltech.edu - - getline.c - I modified gl_get_line() to allow the previously returned - line to be passed in the start_line argument. - getline.c man/gl_get_line.3 - I added a recall-history action function, bound to M^P. - This recalls the last recalled history line, regardless - of whether it was from the current or previous line. - -13/12/2000 mcs@astro.caltech.edu (Release of version 1.1i) - - getline.c history.h history.c man/gl_get_line.3 - I implemented the equivalent of the ksh Operate action. I - have named the tecla equivalent "repeat-history". This - causes the line that is to be edited to returned, and - arranges for the next most recent history line to be - preloaded on the next call to gl_get_line(). Repeated - invocations of this action thus result in successive - history lines being repeated - hence the - name. Implementing the ksh Operate action was suggested - by Markus Gyger. In ksh it is bound to ^O, but since ^O - is traditionally bound by the default terminal settings, - to stop-output, I have bound the tecla equivalent to M-o. - -01/12/2000 mcs@astro.caltech.edu (Release of version 1.1h) - - getline.c keytab.c keytab.h man/gl_get_line.3 - I added a digit-argument action, to allow repeat - counts for actions to be entered. As in both tcsh - and readline, this is bound by default to each of - M-0, M-1 through to M-9, the number being appended - to the current repeat count. Once one of these has been - pressed, the subsequent digits of the repeat count can be - typed with or without the meta key pressed. It is also - possible to bind digit-argument to other keys, with or - without a numeric final keystroke. See man page for - details. - - getline.c man/gl_get_line.3 - Markus noted that my choice of M-< for the default - binding of read-from-file, could be confusing, since - readline binds this to beginning-of-history. I have - thus rebound it to ^X^F (ie. like find-file in emacs). - - getline.c history.c history.h man/gl_get_line.3 - I have now implemented equivalents of the readline - beginning-of-history and end-of-history actions. - These are bound to M-< and M-> respectively. - - history.c history.h - I Moved the definition of the GlHistory type, and - its subordinate types from history.h to history.c. - There is no good reason for any other module to - have access to the innards of this structure. - -27/11/2000 mcs@astro.caltech.edu (Release of version 1.1g) - - getline.c man/gl_get_line.3 - I added a "read-from-file" action function and bound it - by default to M-<. This causes gl_get_line() to - temporarily return input from the file who's name - precedes the cursor. - -26/11/2000 mcs@astro.caltech.edu - - getline.c keytab.c keytab.h man/gl_get_line.3 - I have reworked some of the keybinding code again. - - Now, within key binding strings, in addition to the - previously existing notation, you can now use M-a to - denote meta-a, and C-a to denote control-a. For example, - a key binding which triggers when the user presses the - meta key, the control key and the letter [ - simultaneously, can now be denoted by M-C-[, or M-^[ or - \EC-[ or \E^[. - - I also updated the man page to use M- instead of \E in - the list of default bindings, since this looks cleaner. - - getline.c man/gl_get_line.3 - I added a copy-region-as-kill action function and - gave it a default binding to M-w. - -22/11/2000 mcs@astro.caltech.edu - - *.c - Markus Gyger sent me a copy of a previous version of - the library, with const qualifiers added in appropriate - places. I have done the same for the latest version. - Among other things, this gets rid of the warnings - that are generated if one tells the compiler to - const qualify literal strings. - - getline.c getline.h glconf.c - I have moved the contents of glconf.c and the declaration - of the GetLine structure into getline.c. This is cleaner, - since now only functions in getline.c can mess with the - innards of GetLine objects. It also clears up some problems - with system header inclusion order under Solaris, and also - the possibility that this might result in inconsistent - system macro definitions, which in turn could cause different - declarations of the structure to be seen in different files. - - hash.c - I wrote a wrapper function to go around strcmp(), such that - when hash.c is compiled with a C++ compiler, the pointer - to the wrapper function is a C++ function pointer. - This makes it compatible with comparison function pointer - recorded in the hash table. - - cplmatch.c getline.c libtecla.h - Markus noted that the Sun C++ compiler wasn't able to - match up the declaration of cpl_complete_word() in - libtecla.h, where it is surrounded by a extern "C" {} - wrapper, with the definition of this function in - cplmatch.c. My suspicion is that the compiler looks not - only at the function name, but also at the function - arguments to see if two functions match, and that the - match_fn() argument, being a fully blown function pointer - declaration, got interpetted as that of a C function in - one case, and a C++ function in the other, thus - preventing a match. - - To fix this I now define a CplMatchFn typedef in libtecla.h, - and use this to declare the match_fn callback. - -20/11/2000 (Changes suggested by Markus Gyger to support C++ compilers): - expand.c - Renamed a variable called "explicit" to "xplicit", to - avoid conflicts when compiling with C++ compilers. - *.c - Added explicit casts when converting from (void *) to - other pointer types. This isn't needed in C but it is - in C++. - getline.c - tputs() has a strange declaration under Solaris. I was - enabling this declaration when the SPARC feature-test - macro was set. Markus changed the test to hinge on the - __sun and __SVR4 macros. - direader.c glconf.c stringrp.c - I had omitted to include string.h in these two files. - - Markus also suggested some other changes, which are still - under discussion. With the just above changes however, the - library compiles without complaint using g++. - -19/11/2000 mcs@astro.caltech.edu - getline.h getline.c keytab.c keytab.h glconf.c - man/gl_get_line.3 - I added support for backslash escapes (include \e - for the keyboard escape key) and literal binary - characters to the characters allowed within key sequences - of key bindings. - - getline.h getline.c keytab.c keytab.h glconf.c - man/gl_get_line.3 - I introduced symbolic names for the arrow keys, and - modified the library to use the cursor key sequences - reported by terminfo/termcap in addition to the default - ANSI ones. Anything bound to the symbolically named arrow - keys also gets bound to the default and terminfo/termcap - cursor key sequences. Note that under Solaris - terminfo/termcap report the properties of hardware X - terminals when TERM is xterm instead of the terminal - emulator properties, and the cursor keys on these two - systems generate different key sequences. This is an - example of why extra default sequences are needed. - - getline.h getline.c keytab.c - For some reason I was using \e to represent the escape - character. This is supported by gcc, which thus doesn't - emit a warning except with the -pedantic flag, but isn't - part of standard C. I now use a macro to define escape - as \033 in getline.h, and this is now used wherever the - escape character is needed. - -17/11/2000 mcs@astro.caltech.edu (Release of version 1.1d) - - getline.c, man/gl_get_line(3), html/gl_get_line.html - In tcsh ^D is bound to a function which does different - things depending on where the cursor is within the input - line. I have implemented its equivalent in the tecla - library. When invoked at the end of the line this action - function displays possible completions. When invoked on - an empty line it causes gl_get_line() to return NULL, - thus signalling end of input. When invoked within a line - it invokes forward-delete-char, as before. The new action - function is called del-char-or-list-or-eof. - - getline.c, man/gl_get_line(3), html/gl_get_line.html - I found that the complete-word and expand-file actions - had underscores in their names instead of hyphens. This - made them different from all other action functions, so I - have changed the underscores to hyphens. - - homedir.c - On SCO UnixWare while getpwuid_r() is available, the - associated _SC_GETPW_R_SIZE_MAX macro used by sysconf() - to find out how big to make the buffer to pass to this - function to cater for any password entry, doesn't - exist. I also hadn't catered for the case where sysconf() - reports that this limit is indeterminate. I have thus - change the code to substitute a default limit of 1024 if - either the above macro isn't defined or if sysconf() says - that the associated limit is indeterminate. - -17/11/2000 mcs@astro.caltech.edu (Release of version 1.1c) - - getline.c, getline.h, history.c, history.h - I have modified the way that the history recall functions - operate, to make them better emulate the behavior of - tcsh. Previously the history search bindings always - searched for the prefix that preceded the cursor, then - left the cursor at the same point in the line, so that a - following search would search using the same prefix. This - isn't how tcsh operates. On finding a matching line, tcsh - puts the cursor at the end of the line, but arranges for - the followup search to continue with the same prefix, - unless the user does any cursor motion or character - insertion operations in between, in which case it changes - the search prefix to the new set of characters that are - before the cursor. There are other complications as well, - which I have attempted to emulate. As far as I can - tell, the tecla history recall facilities now fully - emulate those of tcsh. - -16/11/2000 mcs@astro.caltech.edu (Release of version 1.1b) - - demo.c: - One can now quit from the demo by typing exit. - - keytab.c: - The first entry of the table was getting deleted - by _kt_clear_bindings() regardless of the source - of the binding. This deleted the up-arrow binding. - Symptoms noted by gazelle@yin.interaccess.com. - - getline.h: - Depending on which system include files were include - before the inclusion of getline.h, SIGWINCH and - TIOCGWINSZ might or might not be defined. This resulted - in different definitions of the GetLine object in - different files, and thus some very strange bugs! I have - now added #includes for the necessary system header files - in getline.h itself. The symptom was that on creating a - ~/.teclarc file, the demo program complained of a NULL - argument to kt_set_keybinding() for the first line of the - file. - -15/11/2000 mcs@astro.caltech.edu (Release of version 1.1a) - - demo.c: - I had neglected to check the return value of - new_GetLine() in the demo program. Oops. - - getline.c libtecla.h: - I wrote gl_change_terminal(). This allows one to change to - a different terminal or I/O stream, by specifying the - stdio streams to use for input and output, along with the - type of terminal that they are connected to. - - getline.c libtecla.h: - Renamed GetLine::isterm to GetLine::is_term. Standard - C reserves names that start with "is" followed by - alphanumeric characters, so this avoids potential - clashes in the future. - - keytab.c keytab.h - Each key-sequence can now have different binding - functions from different sources, with the user provided - binding having the highest precedence, followed by the - default binding, followed by any terminal specific - binding. This allows gl_change_terminal() to redefine the - terminal-specific bindings each time that - gl_change_terminal() is called, without overwriting the - user specified or default bindings. In the future, it will - also allow for reconfiguration of user specified - bindings after the call to new_GetLine(). Ie. deleting a - user specified binding should reinstate any default or - terminal specific binding. - - man/cpl_complete_word.3 html/cpl_complete_word.html - man/ef_expand_file.3 html/ef_expand_file.html - man/gl_get_line.3 html/gl_get_line.html - I added sections on thread safety to the man pages of the - individual modules. - - man/gl_get_line.3 html/gl_get_line.html - I documented the new gl_change_terminal() function. - - man/gl_get_line.3 html/gl_get_line.html - In the description of the ~/.teclarc configuration file, - I had omitted the 'bind' command word in the example - entry. I have now remedied this. diff --git a/libtecla-1.4.1/INSTALL b/libtecla-1.4.1/INSTALL deleted file mode 100644 index 1a1b036..0000000 --- a/libtecla-1.4.1/INSTALL +++ /dev/null @@ -1,168 +0,0 @@ -To compile and optionally install the library, it is first necessary -to create a makefile for your system, by typing: - - ./configure - -The Makefile that this generates is designed to install the files of -the library in subdirectories of /usr/local/. If you would prefer to -install them under a different directory, you can type: - - ./configure --prefix /wherever - -Where you would replace /wherever with your chosen directory. Other -command-line options are available, and can be listed by typing: - - ./configure --help - -Having run the configure script, you are then ready to make the -library. To do this, just type: - - make - -What 'make' does depends on whether the configure script knows about -your system. If the configure script doesn't know anything specific -about your system, it will arrange for 'make' to produce the static -tecla library, called libtecla.a, and if possible, the reentrant -version of this called libtecla_r.a. If it does know about your -system, it will also create shared libraries if possible. If you are -on a system that isn't known, and you would like shared libraries to -be compiled, please read the file called PORTING to see how this can -be achieved. - -To install the library, its include file and it manual pages, type: - - make install - -Note that this will also compile the library if you haven't already -done so. - -Having compiled the library, if you wish, you can test it by running -the demo programs. After building the library, you should find two -programs, called demo and demo2, in the current directory. - -The first of the demos programs reads input lines from the user, and -writes what was typed back to the screen. While typing a line of -input, you can experiment with line editing, tab completion, history -recall etc.. For details about these line editing features, see the -man page gl_get_line(3). If you haven't installed this yet, you can -see it anyway by typing: - - nroff -man man3/gl_get_line.3 | more - -The second demo program, called demo2, demonstrates command-completion -with the UNIX PATH. If you type in a partial command name, and press -TAB, the command name will be completed if possible, and possible -completions will be listed if it is ambiguous. When you then enter the -line, the demo program then prints out the full pathname of the -command that you typed. If you type anything after the command name, -filename completion with the tab key reverts to its default behavior -of completing filenames in the current directory. - -COMPILING IN A DIFFERENT DIRECTORY ----------------------------------- -If you unpack the distribution in a directory which is visible from -multiple hosts which have different architectures, you have the option -of compiling the library for the different architectures in different -directories. You might for example create a sub-directory for each -architecture, under the top level directory of the distribution. You -would then log in to a host of one of these architectures, cd to the -sub-directory that you created for it, and type: - - ../configure - -The configure script then creates a makefile in the current directory -which is designed to build the library, object files, demos etc for -the architecture of the current host, in the current directory, using -the original source code in ../. You then repeat this procedure on -hosts of other architectures. - -The compilation directories don't have to be sub-directories of the -top level directory of the distribution. That was just described as an -example. They can be anywhere you like. - -Every rule in the makefiles that are generated by the configure -script, cites the paths of the target and source files explicitly, so -this procedure should work on any system, without the need for vpath -makefile support. - -EMBEDDING IN OTHER PACKAGE DISTRIBUTIONS ----------------------------------------- - -If you distribute the library with another package, which has its own -heirarchy and configuration procedures, the following installation -options may be of interest to you. At first glance, the use of a GNU -configure script by the tecla library, may appear to reduce your -options for controlling what gets made, and where it gets installed, -but this isn't the case, because many of the parameters configured by -the configure script are assigned to make variables which can be -overriden when you run make. - -For example, lets say that you have your own configuration script in -the parent directory of the libtecla top-level directory. In your -configuration script, you would first need to have the following line: - - (cd libtecla; ./configure) - -Now, from your makefile or whatever script you use to build your -application, you would need to make the library. Assuming that your -makefile or build script is in the parent directory of the libtecla -distribution, the following line tells make to just make the -non-reentrant, static version of the tecla library, and to install it -and the tecla include file in sub-directories called lib and include -in your current directory. - - (cd libtecla; make LIBDIR=../lib INCDIR=../include TARGETS=normal TARGET_LIBS="static" install_lib install_inc) - -First, the LIBDIR=../lib means that on installing the library, it -should be placed in the directory libtecla/../lib. Similarly INCDIR -tells make where to place the include files. The install_lib and -install_inc targets tell make to install the libraries and the include -file. Because the install_man and install_bin targets have been -omitted in this example, the man pages and programs aren't installed. -If you were to include these additional targets then you could use the -MANDIR and BINDIR variables, respectively to control where they were -installed. - -The TARGETS variable is used to specify which of the normal and -reentrant versions of the library are compiled. This can contain one -or both of the words "normal" and "reentrant". If you don't specify -this when you invoke make, the default value generated by the -configure script will be used. Depending on whether reentrant POSIX -functions are available for compilation of the reentrant version, this -will be either "normal" or "normal reentrant". - -The TARGET_LIBS variable is used to specify which of the static and -shared libraries are to be built. This can contain one or both of the -words "static" and "shared". If you don't specify this when you invoke -make, the default value generated by the configure script will be -used. Depending on whether the configure script knows how to create -shared libraries on the target system, this will be either "static" or -"static shared". Beware that shared libraries aren't supported on many -systems, so requiring "shared" will limit which systems you can -compile your package on. Also note that unless your package installs -the tecla library in a directory which all users of your program will -have access to, you should only compile the static version. -Instructions for adding shared-library creation rules for new systems -are included in the PORTING file. - -The OPT variable can be used to change the default optimization from -the default of "-O" to something else. - -The DEMOS variable controls whether the demo programs are built. -Normally this has the value "demos", which tells the makefile to build -the demo programs. Setting it to an empty string stops the demos from -being built. - -The PROGRAMS variable is used to specify which programs are to be -built and subsequently installed. All available programs are built by -default. Currently there is only one such program, selected by -specifying the word "enhance". This program uses tecla-enhanced -pseudo-terminals to layer command line editing on top of third party -programs. - -The PROGRAMS_R variable serves the same purpose as the PROGRAMS -variable, except that programs listed here are linked with the -reentrant version of the library, and should be specified with a _r -suffix. Currently this variable is empty by default. - -Martin Shepherd (mcs@astro.caltech.edu) diff --git a/libtecla-1.4.1/LICENSE.TERMS b/libtecla-1.4.1/LICENSE.TERMS deleted file mode 100644 index 275eef5..0000000 --- a/libtecla-1.4.1/LICENSE.TERMS +++ /dev/null @@ -1,28 +0,0 @@ -Copyright (c) 2000, 2001 by Martin C. Shepherd. - -All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, and/or sell copies of the Software, and to permit persons -to whom the Software is furnished to do so, provided that the above -copyright notice(s) and this permission notice appear in all copies of -the Software and that both the above copyright notice(s) and this -permission notice appear in supporting documentation. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL -INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING -FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, -NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION -WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -Except as contained in this notice, the name of a copyright holder -shall not be used in advertising or otherwise to promote the sale, use -or other dealings in this Software without prior written authorization -of the copyright holder. diff --git a/libtecla-1.4.1/Makefile b/libtecla-1.4.1/Makefile deleted file mode 100644 index 15116b5..0000000 --- a/libtecla-1.4.1/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -default: - ./configure - make diff --git a/libtecla-1.4.1/Makefile.in b/libtecla-1.4.1/Makefile.in deleted file mode 100644 index f691375..0000000 --- a/libtecla-1.4.1/Makefile.in +++ /dev/null @@ -1,225 +0,0 @@ -#----------------------------------------------------------------------- -# This is the template that the libtecla configure script uses to create -# the libtecla Makefile. It does this by replacing all instances of -# @name@ with the value of the correspondingly named configuration -# variable. You should find another file in the same directory as this -# one, called "configure.in". The latter file contains extensive comments -# explaining how this all works. -#----------------------------------------------------------------------- - -# Where is the source code? - -srcdir = @srcdir@ - -# Where do you want to install the library, its header file, and the man pages? - -prefix=@prefix@ -exec_prefix=@exec_prefix@ -LIBDIR=@libdir@ -INCDIR=@includedir@ -MANDIR=@mandir@ -BINDIR=@bindir@ - -# Which C compiler do you want to use? - -CC = @CC@ - -# If 'make' doesn't define the MAKE variable, define it here. - -@SET_MAKE@ - -# To use RANLIB set the RANLIB variable to ranlib. Otherwise set it to -# :, which is the bourne shell do-nothing command. - -RANLIB = @RANLIB@ - -# The following optional defines change the characteristics of the library. -# -# USE_TERMINFO -# Use the terminfo terminal information database when looking up -# terminal characteristics. Most modern UNIX and UNIX-like operating -# systems support terminfo, so this define should normally be included. -# If in doubt leave it in, and see if the library compiles. -# USE_TERMCAP -# If you don't have terminfo but do have the termcap database, replace -# the -DUSE_TERMINFO with -DUSE_TERMCAP. If there is a termcap.h in -# /usr/include/, also add -DHAVE_TERMCAP_H. -# -# If neither USE_TERMINFO nor USE_TERMCAP are included, ANSI VT100 control -# sequences will be used to control all terminal types. -# -# For Solaris and Linux, use: -# -# DEFINES = -DUSE_TERMINFO -# - -DEFINES = @DEFS@ - -# -# The following defines are used in addition to the above when compiling -# the reentrant version of the library. Note that the definition of -# _POSIX_C_SOURCE to request reentrant functions, has the unfortunate -# side-effect on some systems of stopping the TIOCGWINSZ ioctl macro from -# getting defined. This in turn stops the library from being -# able to respond to terminal size changes. Under Solaris this can be -# remedied by adding -D__EXTENSIONS__. On linux this isn't necessary. -# If you don't get this right, the library will still work, but -# it will get confused if the terminal size gets changed and you try to -# edit a line that exceeds the terminal width. -# -# Thus on Solaris you should use: -# -# DEFINES_R = -D_POSIX_C_SOURCE=199506L -D__EXTENSIONS__ -# -# and on linux you should use: -# -# DEFINES_R = -D_POSIX_C_SOURCE=199506L -# - -DEFINES_R = -D_POSIX_C_SOURCE=199506L - -# -# The compiler optimization flags. I like to keep this separate so -# that I can set it to -g from the 'make' command line without having -# to edit this file when debugging the library. If you aren't working -# on modifying the library, leave this set to -O. -# - -OPT = -O - -# -# These are paranoid gcc warning flags to use when compiling new code. -# Simply invoke make with WARNING_FLAGS='$(PEDANTIC_FLAGS)'. -# -PEDANTIC_FLAGS=-Wall -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls - -# -# Specify any extra compiler warning options that you want to use. -# Leave this blank unless you are porting the library to a new system, -# or modifying the library. -# - -WARNING_FLAGS= - -# -# If you want to compile the demo program, specify any system -# libraries that are needed for the terminal I/O functions. -# -# If you are using terminfo, you will probably only need -lcurses. -# For termcap you may need -ltermcap or -ltermlib. -# -# For Solaris, use: -# -# LIBS = -lcurses -# -# For linux, use: -# -# LIBS = -lncurses -# - -LIBS = @LIBS@ - -# -# List the default target libraries. This should be one or -# both of the words "normal" and "reentrant". -# -TARGETS = @TARGETS@ - -# -# List which types of the above libraries are required. -# This should be one or both of the words "static" and "shared". -# -TARGET_LIBS = @TARGET_LIBS@ - -# -# If you want the demo programs to be built, the following variable -# should be assigned the single word: demos. If it isn't assigned -# anything, the demo programs won't be built. -# -DEMOS = demos - -# -# List the programs that are to be made by default. -# -PROGRAMS = enhance - -# -# List programs for which reentrant versions are to be built by default. -# -PROGRAMS_R = - -#----------------------------------------------------------------------- -# You shouldn't need to change anything below this line. -#----------------------------------------------------------------------- - -CFLAGS = $(OPT) $(WARNING_FLAGS) $(DEFINES) @CFLAGS@ @SHARED_CFLAGS@ - -default: $(TARGETS) - -normal: - @$(MAKE) -f $(srcdir)/Makefile.rules TARGETS="$(TARGET_LIBS)" SUFFIX="" CFLAGS="$(CFLAGS)" CC="$(CC)" OBJDIR=normal_obj LINK_SHARED='@LINK_SHARED@' SHARED_EXT='@SHARED_EXT@' SHARED_ALT='@SHARED_ALT@' LIBS='$(LIBS)' srcdir='$(srcdir)' LIBDIR='$(LIBDIR)' LN_S='@LN_S@' DEMOS="$(DEMOS)" PROGRAMS='$(PROGRAMS)' RANLIB='$(RANLIB)' - -reentrant: - @$(MAKE) -f $(srcdir)/Makefile.rules TARGETS="$(TARGET_LIBS)" SUFFIX="_r" CFLAGS="$(CFLAGS) $(DEFINES_R)" CC="$(CC)" OBJDIR=reentrant_obj LINK_SHARED='@LINK_SHARED@' SHARED_EXT='@SHARED_EXT@' SHARED_ALT='@SHARED_ALT@' LIBS='$(LIBS)' srcdir='$(srcdir)' LIBDIR='$(LIBDIR)' LN_S='@LN_S@' DEMOS="$(DEMOS)" PROGRAMS='$(PROGRAMS_R)' RANLIB='$(RANLIB)' - -demos: normal - -demos_r: reentrant - -clean: - rm -rf *.o normal_obj reentrant_obj libtecla*.a demo demo2 demo_r demo2_r enhance *~ man3/*~ html/*~ compile_reentrant compile_normal - @endings="@SHARED_EXT@ @SHARED_ALT@" ; \ - for alt in $$endings ; do \ - lib="libtecla*$$alt" ; \ - rm -f $$lib; echo rm -f $$lib ; \ - done - -distclean: clean - rm -f config.cache config.status config.log Makefile libtecla.map.opt - cp $(srcdir)/Makefile.stub Makefile - -install_lib: $(TARGETS) $(LIBDIR) - @for lib in libtecla.a libtecla_r.a ; do \ - if [ -f $$lib ] ; then \ - cp $$lib $(LIBDIR)/ ; chmod ugo+r $(LIBDIR)/$$lib; \ - echo "cp $$lib $(LIBDIR)/ ; chmod ugo+r $(LIBDIR)/$$lib"; \ - fi ; \ - done - @for lib in libtecla libtecla_r ; do \ - src="$$lib@SHARED_EXT@"; \ - if [ -f $$src ] ; then \ - dst="$(LIBDIR)/$$src"; \ - cp -f $$src $$dst; chmod a=rX $$dst; \ - echo "cp -f $$src $$dst ; chmod a=rX $$dst"; \ - endings="@SHARED_ALT@" ; \ - for alt in $$endings ; do \ - lnk="$$lib$$alt"; \ - (cd $(LIBDIR); rm -f $$lnk; @LN_S@ $$src $$lnk); \ - echo "(cd $(LIBDIR); rm -f $$lnk; @LN_S@ $$src $$lnk)"; \ - done ; \ - fi ; \ - done - -install_inc: $(INCDIR) - @if [ -f $(srcdir)/libtecla.h ]; then \ - cp $(srcdir)/libtecla.h $(INCDIR)/ ; chmod ugo+r $(INCDIR)/libtecla.h; \ - echo "cp $(srcdir)/libtecla.h $(INCDIR)/ ; chmod ugo+r $(INCDIR)/libtecla.h"; \ - fi - -install_man: $(MANDIR) $(MANDIR)/man3 - cd $(srcdir)/man3 && for page in *.3; do cp $$page $(MANDIR)/man3; chmod ugo+r $(MANDIR)/man3/$$page; done - -install_bin: $(BINDIR) $(PROGRAMS) $(PROGRAMS_R) - progs="$(PROGRAMS) $(PROGRAMS_R)"; \ - for prog in $$progs; do \ - cp $$prog $(BINDIR)/; \ - chmod ugo+rx $(BINDIR)/$$prog; \ - done - -install: install_lib install_inc install_man install_bin - -# Make any missing installation directories. - -$(MANDIR) $(MANDIR)/man3 $(LIBDIR) $(INCDIR) $(BINDIR): - $(srcdir)/install-sh -d $@ - chmod ugo+rx $@ diff --git a/libtecla-1.4.1/Makefile.rules b/libtecla-1.4.1/Makefile.rules deleted file mode 100644 index 6552057..0000000 --- a/libtecla-1.4.1/Makefile.rules +++ /dev/null @@ -1,142 +0,0 @@ -default: $(OBJDIR) $(TARGETS) $(DEMOS) $(PROGRAMS) - -#----------------------------------------------------------------------- -# You shouldn't need to change anything in this file. -#----------------------------------------------------------------------- - -# Create the directory in which the object files will be created. - -$(OBJDIR): - mkdir $(OBJDIR) - -# Construct the compilation command. - -COMPILE = $(CC) -c $(CFLAGS) -o $@ - -LIB_OBJECTS = $(OBJDIR)/getline.o $(OBJDIR)/keytab.o $(OBJDIR)/freelist.o \ - $(OBJDIR)/strngmem.o $(OBJDIR)/hash.o $(OBJDIR)/history.o \ - $(OBJDIR)/direader.o $(OBJDIR)/homedir.o $(OBJDIR)/pathutil.o \ - $(OBJDIR)/expand.o $(OBJDIR)/stringrp.o $(OBJDIR)/cplfile.o \ - $(OBJDIR)/cplmatch.o $(OBJDIR)/pcache.o $(OBJDIR)/version.o - -# List all of the programs that this makefile can build. - -PROGS = demo$(SUFFIX) demo2$(SUFFIX) enhance$(SUFFIX) - -static: libtecla$(SUFFIX).a - -libtecla$(SUFFIX).a: $(LIB_OBJECTS) - ar -ru $@ $(LIB_OBJECTS); \ - $(RANLIB) $@; \ - rm -f $(PROGS) - -shared: libtecla$(SUFFIX)$(SHARED_EXT) - -libtecla$(SUFFIX)$(SHARED_EXT): $(LIB_OBJECTS) $(srcdir)/libtecla.map \ - libtecla.map.opt - $(LINK_SHARED) - @endings="$(SHARED_ALT)" ; \ - for alt in $$endings ; do \ - lnk="libtecla$(SUFFIX)$$alt"; \ - echo "rm -f $$lnk; $(LN_S) $@ $$lnk"; \ - rm -f $$lnk; $(LN_S) $@ $$lnk; \ - done; \ - rm -f $(PROGS) - -libtecla.map.opt: $(srcdir)/libtecla.map - sed -n 's/^[ ]*\([_a-zA-Z0-9]*\)[ ]*;.*/+e \1/p' $? >$@ - -demos: demo$(SUFFIX) demo2$(SUFFIX) - -demo$(SUFFIX): $(OBJDIR)/demo.o - LD_RUN_PATH="$(LIBDIR):$$LD_RUN_PATH:`pwd`" $(CC) $(CFLAGS) -o $@ \ - $(OBJDIR)/demo.o -L. -ltecla$(SUFFIX) $(LIBS) - -demo2$(SUFFIX): $(OBJDIR)/demo2.o - LD_RUN_PATH="$(LIBDIR):$$LD_RUN_PATH:`pwd`" $(CC) $(CFLAGS) -o $@ \ - $(OBJDIR)/demo2.o -L. -ltecla$(SUFFIX) $(LIBS) - -enhance$(SUFFIX): $(OBJDIR)/enhance.o - LD_RUN_PATH="$(LIBDIR):$$LD_RUN_PATH:`pwd`" $(CC) $(CFLAGS) -o $@ \ - $(OBJDIR)/enhance.o -L. -ltecla$(SUFFIX) $(LIBS) - -#----------------------------------------------------------------------- -# Object file dependencies. -#----------------------------------------------------------------------- - -$(OBJDIR)/getline.o: $(srcdir)/getline.c $(srcdir)/pathutil.h \ - $(srcdir)/libtecla.h $(OBJDIR)/keytab.h $(srcdir)/history.h \ - $(srcdir)/freelist.h $(srcdir)/stringrp.h $(srcdir)/getline.h - $(COMPILE) $(srcdir)/getline.c - -$(OBJDIR)/keytab.o: $(srcdir)/keytab.c $(OBJDIR)/keytab.h \ - $(srcdir)/strngmem.h $(srcdir)/getline.h - $(COMPILE) $(srcdir)/keytab.c - -$(OBJDIR)/strngmem.o: $(srcdir)/strngmem.c $(srcdir)/strngmem.h \ - $(srcdir)/freelist.h - $(COMPILE) $(srcdir)/strngmem.c - -$(OBJDIR)/freelist.o: $(srcdir)/freelist.c $(srcdir)/freelist.h - $(COMPILE) $(srcdir)/freelist.c - -$(OBJDIR)/hash.o: $(srcdir)/hash.c $(srcdir)/hash.h $(srcdir)/strngmem.h \ - $(srcdir)/freelist.h - $(COMPILE) $(srcdir)/hash.c - -$(OBJDIR)/history.o: $(srcdir)/history.c $(srcdir)/history.h \ - $(srcdir)/freelist.h - $(COMPILE) $(srcdir)/history.c - -$(OBJDIR)/expand.o: $(srcdir)/expand.c $(srcdir)/freelist.h \ - $(srcdir)/direader.h $(srcdir)/pathutil.h $(srcdir)/homedir.h \ - $(srcdir)/stringrp.h $(srcdir)/libtecla.h - $(COMPILE) $(srcdir)/expand.c - -$(OBJDIR)/direader.o: $(srcdir)/direader.c $(srcdir)/direader.h - $(COMPILE) $(srcdir)/direader.c - -$(OBJDIR)/homedir.o: $(srcdir)/homedir.c $(srcdir)/pathutil.h \ - $(srcdir)/homedir.h - $(COMPILE) $(srcdir)/homedir.c - -$(OBJDIR)/pathutil.o: $(srcdir)/pathutil.c $(srcdir)/pathutil.h - $(COMPILE) $(srcdir)/pathutil.c - -$(OBJDIR)/stringrp.o: $(srcdir)/stringrp.c $(srcdir)/freelist.h \ - $(srcdir)/stringrp.h - $(COMPILE) $(srcdir)/stringrp.c - -$(OBJDIR)/cplfile.o: $(srcdir)/cplfile.c $(srcdir)/libtecla.h \ - $(srcdir)/direader.h $(srcdir)/homedir.h $(srcdir)/pathutil.h \ - $(srcdir)/cplfile.h - $(COMPILE) $(srcdir)/cplfile.c - -$(OBJDIR)/cplmatch.o: $(srcdir)/cplmatch.c $(srcdir)/libtecla.h \ - $(srcdir)/stringrp.h $(srcdir)/pathutil.h $(srcdir)/cplfile.h - $(COMPILE) $(srcdir)/cplmatch.c - -$(OBJDIR)/pcache.o: $(srcdir)/pcache.c $(srcdir)/libtecla.h \ - $(srcdir)/pathutil.h $(srcdir)/homedir.h $(srcdir)/freelist.h \ - $(srcdir)/direader.h $(srcdir)/stringrp.h - $(COMPILE) $(srcdir)/pcache.c - -$(OBJDIR)/demo.o: $(srcdir)/demo.c $(srcdir)/libtecla.h - $(COMPILE) $(srcdir)/demo.c - -$(OBJDIR)/demo2.o: $(srcdir)/demo2.c $(srcdir)/libtecla.h - $(COMPILE) $(srcdir)/demo2.c - -$(OBJDIR)/version.o: $(srcdir)/version.c $(srcdir)/libtecla.h - $(COMPILE) $(srcdir)/version.c - -$(OBJDIR)/enhance.o: $(srcdir)/enhance.c $(srcdir)/libtecla.h - $(COMPILE) $(srcdir)/enhance.c - -#----------------------------------------------------------------------- -# Include file dependencies. -#----------------------------------------------------------------------- - -$(OBJDIR)/keytab.h: $(srcdir)/keytab.h $(srcdir)/libtecla.h \ - $(srcdir)/hash.h $(srcdir)/strngmem.h - cp $(srcdir)/keytab.h $@ diff --git a/libtecla-1.4.1/Makefile.stub b/libtecla-1.4.1/Makefile.stub deleted file mode 100644 index 15116b5..0000000 --- a/libtecla-1.4.1/Makefile.stub +++ /dev/null @@ -1,3 +0,0 @@ -default: - ./configure - make diff --git a/libtecla-1.4.1/PORTING b/libtecla-1.4.1/PORTING deleted file mode 100644 index db39818..0000000 --- a/libtecla-1.4.1/PORTING +++ /dev/null @@ -1,38 +0,0 @@ -The Tecla library was written with portability in mind, so no -modifications to the source code should be needed on UNIX or LINUX -platforms. The default compilation and linking arrangements should -also work unchanged on these systems, but if no specific configuration -has been provided for your system, shared libraries won't be compiled. -Configuring these requires modifications to be made to the file: - - configure.in - -This file is heavily commented (comments start with the word dnl) and -is relatively simple, so the instructions and suggestions that you -find in this file should be sufficient to help you figure out how to -add a configuration for your system. This file is an input file to the -GNU autoconf program, which uses it as a template for generating the -distributed configure script. If autoconf is installed on your system, -creating a new configure script is a simple matter of typing. - - autoconf - -To avoid confusion with the leftovers of the previous configuration, -you should then do the following: - - rm -f config.cache - ./configure - make clean - ./configure - make - -The first ./configure creates a new makefile for your system, allowing -you to type 'make clean' to discard any files that were compiled with -the previous configuration. Since 'make clean' also deletes the new -makefile, a second invokation of the configure script is then -performed to re-create the makefile. The final make then creates the -tecla library from scratch. - -Once you have confirmed that the new configuration works, please send -the modified "configure.in" template to mcs@astro.caltech.edu, so that -your changes can be included in subsequent releases. diff --git a/libtecla-1.4.1/README b/libtecla-1.4.1/README deleted file mode 100644 index 894819d..0000000 --- a/libtecla-1.4.1/README +++ /dev/null @@ -1,53 +0,0 @@ -This is version 1.4.1 of the tecla command-line editing library. - -For the current official release, please direct your browser to: - - http://www.astro.caltech.edu/~mcs/tecla/index.html - -The tecla library provides UNIX and LINUX programs with interactive -command line editing facilities, similar to those of the unix tcsh -shell. In addition to simple command-line editing, it supports recall -of previously entered command lines, TAB completion of file names, and -in-line wild-card expansion of filenames. The internal functions -which perform file-name completion and wild-card expansion are also -available externally for optional use by programs, along with a module -for tab-completion and lookup of filenames in a list of directories. - -Note that special care has been taken to allow the use of this library -in threaded programs. The option to enable this is discussed in the -Makefile, and specific discussions of thread safety are presented in -the included man pages. - -For instructions on how to compile and install the library, please see -the INSTALL file, which should be in the same directory as this file. - -Copyright and Disclaimer ------------------------- -Copyright (c) 2000, 2001 by Martin C. Shepherd. - -All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, and/or sell copies of the Software, and to permit persons -to whom the Software is furnished to do so, provided that the above -copyright notice(s) and this permission notice appear in all copies of -the Software and that both the above copyright notice(s) and this -permission notice appear in supporting documentation. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL -INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING -FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, -NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION -WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -Except as contained in this notice, the name of a copyright holder -shall not be used in advertising or otherwise to promote the sale, use -or other dealings in this Software without prior written authorization -of the copyright holder. diff --git a/libtecla-1.4.1/RELEASE.NOTES b/libtecla-1.4.1/RELEASE.NOTES deleted file mode 100644 index 1b18a4a..0000000 --- a/libtecla-1.4.1/RELEASE.NOTES +++ /dev/null @@ -1,357 +0,0 @@ -This file lists major changes which accompany each new release. - -Version 1.4.1: - - This is a maintenance release. It includes minor changes to support - Mac OS X (Darwin), the QNX real-time operating system, and Cygwin - under Windows. It also fixes an oversight that was preventing the - tab key from inserting tab characters when users unbound the - complete-word action from it. - -Version 1.4.0: - - The contents of the history list can now be saved and restored with - the new gl_save_history() and gl_load_history() functions. - - Event handlers can now be registered to watch for and respond to I/O - on arbitrary file descriptors while gl_get_line() is waiting for - terminal input from the user. See the gl_get_line(3) man page - for details on gl_watch_fd(). - - As an optional alternative to getting configuration information only - from ~/.teclarc, the new gl_configure_getline() function allows - configuration commands to be taken from any of, a string, a - specified application-specific file, and/or a specified - user-specific file. See the gl_get_line(3) man page for details. - - The version number of the library can now be queried using the - libtecla_version() function. See the libtecla(3) man page. - - The new gl_group_history() function allows applications to group - different types of input line in the history buffer, and arrange for - only members of the appropriate group to be recalled on a given call - to gl_get_line(). See the gl_get_line(3) man page. - - The new gl_show_history() function displays the current history list - to a given stdio output stream. See the gl_get_line(3) man page. - - new_GetLine() now allows you to specify a history buffer size of - zero, thus requesting that no history buffer be allocated. You can - subsequently resize or delete the history buffer at any time, by - calling gl_resize_history(), limit the number of lines that are - allowed in the buffer by calling gl_limit_history(), clear either - all history lines from the history list, or just the history lines - that are associated with the current history group, by calling - gl_clear_history, and toggle the history mechanism on and off by - calling gl_toggle_history(). - - The new gl_terminal_size() function can be used to query the - current terminal size. It can also be used to supply a default - terminal size on systems where no mechanism is available for - looking up the size. - - The contents and configuration of the history list can now be - obtained by the calling application, by calling the new - gl_lookup_history(), gl_state_of_history(), gl_range_of_history() - and gl_size_of_history() functions. See the gl_get_line(3) man page. - - Echoing of the input line as it is typed, can now be turned on and - off via the new gl_echo_mode() function. While echoing is disabled, - newly entered input lines are omitted from the history list. See - the gl_get_line(3) man page. - - While the default remains to display the prompt string literally, - the new gl_prompt_style() function can be used to enable text - attribute formatting directives in prompt strings, such as - underlining, bold font, and highlighting directives. - - Signal handling in gl_get_line() is now customizable. The default - signal handling behavior remains essentially the same, except that - the SIGTSTP, SIGTTIN and SIGTTOU are now forwarded to the - corresponding signal handler of the calling program, instead of - causing a SIGSTOP to be sent to the application. It is now possible - to remove signals from the list that are trapped by gl_get_line(), - as well as add new signals to this list. The signal and terminal - environments in which the signal handler of the calling program is - invoked, and what gl_get_line() does after the signal handler - returns, is now customizable on a per signal basis. You can now also - query the last signal that was caught by gl_get_line(). This is - useful when gl_get_line() aborts with errno=EINTR, and you need to - know which signal caused it to abort. - - Key-sequences bound to action functions can now start with printable - characters. Previously only keysequences starting with control or - meta characters were permitted. - - gl_get_line() is now 8-bit clean. If the calling program has - correctly called setlocale(LC_CTYPE,""), then the user can select an - alternate locale by setting the standard LC_CTYPE, LC_ALL, or LANG - environment variables, and international characters can then be - entered directly, either by using a non-US keyboard, or by using a - compose key on a standard US keyboard. Note that in locales in which - meta characters become printable, meta characters no longer match - M-c bindings, which then have to be entered using their escape-c - equivalents. Fortunately most modern terminal emulators either - output the escape-c version by default when the meta key is used, or - can be configured to do so (see the gl_get_line(3) man page), so in - most cases you can continue to use the meta key. - - Completion callback functions can now tell gl_get_line() to return - the input line immediately after a successful tab completion, simply - by setting the last character of the optional continuation suffix to - a newline character (ie. in the call to cpl_add_completion()). - - It is now safe to create and use multiple GetLine objects, albeit - still only from a single thread. In conjunction with the new - gl_configure_getline() function, this optionally allows multiple - GetLine objects with different bindings to be used to implement - different input modes. - - The edit-mode configuration command now accepts the argument, - none. This tells gl_get_line() to revert to using just the native - line editing facilities provided by the terminal driver. This could - be used if the termcap or terminfo entry of the host terminal were - badly corrupted. - - Application callback functions invoked by gl_get_line() can now - change the displayed prompt using the gl_replace_prompt() function. - - Their is now an optional program distributed with the library. This - is a beta release of a program which adds tecla command-line editing - to virtually any third party application without the application - needing to be linked to the library. See the enhance(3) man page for - further details. Although built and installed by default, the - INSTALL document explains how to prevent this. - - The INSTALL document now explains how you can stop the demo programs - from being built and installed. - - NetBSD/termcap fixes. Mike MacFaden reported two problems that he - saw when compiling libtecla under NetBSD. Both cases were related to - the use of termcap. Most systems use terminfo, so this problem has - gone unnoticed until now, and won't have affected the grand majority - of users. The configure script had a bug which prevented the check - for CPP working properly, and getline.c wouldn't compile due to an - undeclared variable when USE_TERMCAP was defined. Both problems have - now been fixed. Note that if you successfully compiled version - 1.3.3, this problem didn't affect you. - - An unfortunate and undocumented binding of the key-sequence M-O was - shadowing the arrow-key bindings on systems that use ^[OA etc. I - have removed this binding (the documented lower case M-o binding - remains bound). Under the KDE konsole terminal this was causing the - arrow keys to do something other than expected. - - There was a bug in the history list code which could result in - strange entries appearing at the start of the history list once - enough history lines had been added to the list to cause the - circular history buffer to wrap. This is now fixed. - -Version 1.3.3: - - Signal handling has been re-written, and documentation of its - behaviour has been added to the gl_get_line(3) man page. In addition - to eliminating race conditions, and appropriately setting errno for - those signals that abort gl_get_line(), many more signals are now - intercepted, making it less likely that the terminal will be left in - raw mode by a signal that isn't trapped by gl_get_line(). - - A bug was also fixed that was leaving the terminal in raw mode if - the editing mode was changed interactively between vi and emacs. - This was only noticeable when running programs from old shells that - don't reset terminal modes. - -Version 1.3.2: - - Tim Eliseo contributed a number of improvements to vi mode, - including a fuller set of vi key-bindings, implementation of the vi - constraint that the cursor can't backup past the point at which - input mode was entered, and restoration of overwritten characters - when backspacing in overwrite mode. There are also now new bindings - to allow users to toggle between vi and emacs modes interactively. - The terminal bell is now used in some circumstances, such as when an - unrecognized key sequence is entered. This can be turned off by the - new nobeep option in the tecla configuration file. - - Unrelated to the above, a problem under Linux which prevented ^Q - from being used to resume terminal output after the user had pressed - ^S, has been fixed. - -Version 1.3.1: - - In vi mode a bug was preventing the history-search-backward and - history-search-forward actions from doing anything when invoked on - empty lines. On empty lines they now act like up-history and - down-history respectively, as in emacs mode. - - When creating shared libraries under Linux, the -soname directive - was being used incorrectly. The result is that Linux binaries linked - with the 1.2.3, 1.2.4 and 1.3.0 versions of the tecla shared - libraries, will refuse to see other versions of the shared library - until relinked with version 1.3.1 or higher. - - The configure script can now handle the fact that under Solaris-2.6 - and earlier, the only curses library is a static one that hides in - /usr/ccs/lib. Under Linux it now also caters for old versions of GNU - ld which don't accept version scripts. - - The demos are now linked against the shared version of the library - if possible. Previously they were always linked with the static - version. - -Version 1.3.0: - - The major change in this release is the addition of an optional vi - command-line editing mode in gl_get_line(), along with lots of new - action functions to support its bindings. To enable this, first - create a ~/.teclarc file if you don't already have one, then add the - following line to it. - - edit-mode vi - - The default vi bindings, which are designed to mimic those of the vi - editor as closely as possible, are described in the gl_get_line(3) - man page. - - A new convenience function called ef_list_expansions() has been - added for listing filename expansions. See the ef_list_expansions(3) - man page for details. This is used in a new list-glob binding, bound - to ^Xg in emacs mode, and ^G in vi input mode. - - A bug has been fixed in the key-binding table expansion code. This - bug would have caused problems to anybody who defined more than - about 18 personalized key-bindings in their ~/.teclarc file. - -Version 1.2.4: - - Buffered I/O is now used for writing to terminals, and where - supported, cursor motion is done with move-n-positions terminfo - capabilities instead of doing lots of move-1-position requests. This - greatly improves how the library feels over slow links. - - You can now optionally compile different architectures in different - directories, without having to make multiple copies of the - distribution. This is documented in the INSTALL file. - - The ksh ~+ directive is now supported. - - Thanks to Markus Gyger for the above improvements. - - Documentation has been added to the INSTALL file describing features - designed to facilitate configuration and installation of the library - as part of larger packages. These features are intended to remove - the need to modify the tecla distribution's configuration and build - procedures when embedding the libtecla distribution in other package - distributions. - - A previous fix to stop the cursor from warping when the last - character of the input line was in the last column of the terminal, - was only being used for the first terminal line of the input line. - It is now used for all subsequent lines as well, as originally - intended. - -Version 1.2.3: - - The installation procedure has been better automated with the - addition of an autoconf configure script. This means that installers - can now compile and install the library by typing: - - ./configure - make - make install - - On all systems this makes at least the normal static version of the - tecla library. It also makes the reentrant version if reentrant - POSIX functions are detected. Under Solaris, Linux and HP-UX the - configuration script arranges for shared libraries to be compiled in - addition to the static libraries. It is hoped that installers will - return information about how to compile shared libraries on other - systems, for inclusion in future releases, and to this end, a new - PORTING guide has been provided. - - The versioning number scheme has been changed. This release would - have been 1.2c, but instead will be refered to as 1.2.3. The - versioning scheme, based on conventions used by Sun Microsystems, is - described in configure.in. - - The library was also tested under HP-UX, and this revealed two - serious bugs, both of which have now been fixed. - - The first bug prevented the library from writing control codes to - terminals on big-endian machines, with the exception of those - running under Solaris. This was due to an int variable being used - where a char was needed. - - The second bug had the symptom that on systems that don't use the - newline character as the control code for moving the cursor down a - line, a newline wasn't started when the user hit enter. - -Version 1.2b: - - Two more minor bug fixes: - - Many terminals don't wrap the cursor to the next line when a - character is written to the rightmost terminal column. Instead, they - delay starting a new line until one more character is written, at - which point they move the cursor two positions. gl_get_line() - wasn't aware of this, so cursor repositionings just after writing - the last character of a column, caused it to erroneously go up a - line. This has now been remedied, using a method that should work - regardless of whether a terminal exhibits this behavior or not. - - Some systems dynamically record the current terminal dimensions in - environment variables called LINES and COLUMNS. On such systems, - during the initial terminal setup, these values should override the - static values read from the terminal information databases, and now - do. Previously they were only used if the dimensions returned by - terminfo/termcap looked bogus. - -Version 1.2a: - - This minor release fixes the following two bugs: - - The initial terminal size and subsequent changes thereto, weren't - being noticed by gl_get_line(). This was because the test for the - existence of TIOCWINSZ was erroneously placed before the inclusion - of termios.h. One of the results was that on input lines that - spanned more than one terminal line, the cursor occasionally jumped - unexpectedly to the previous terminal line. - - On entering a line that wrapped over multiple terminal lines, - gl_get_line() simply output a carriage-return line-feed at the point - at which the user pressed return. Thus if one typed in such a line, - then moved back onto one of the earlier terminal lines before - hitting return, the cursor was left on a line containing part of the - line that had just been entered. This didn't do any harm, but it - looked a mess. - -Version 1.2: - - A new facility for looking up and completing filenames in UNIX-style - paths has now been added (eg. you can search for, or complete - commands using the UNIX PATH environment variable). See the - pca_lookup_file(3) man page. - - The already existing filename completion callback can now be made - selective in what types of files it lists. See the - cpl_complete_word(3) man page. - - Due to its potential to break applications when changed, the use of - the publically defined CplFileArgs structure to configure the - cpl_file_completions() callback is now deprecated. The definition - of this structure has been frozen, and its documentation has been - removed from the man pages. It will remain supported, but if you - have used it, you are recommended to switch to the new method, which - involves a new opaque configuration object, allocated via a provided - constructor function, configured via accessor functions, and - eventually deleted with a provided destructor function. The - cpl_file_completions() callback distinguishes which structure type - it has been sent by virtue of a code placed at the start of the new - structure by the constructor. It is assumed that no existing - applications set the boolean 'escaped' member of the CplFileArgs - structure to 4568. The new method is documented in the - cpl_complete_word(3) man page. - -Version 1.1j - - This was the initial public release on freshmeat.org. diff --git a/libtecla-1.4.1/config.guess b/libtecla-1.4.1/config.guess deleted file mode 100644 index 0ce538b..0000000 --- a/libtecla-1.4.1/config.guess +++ /dev/null @@ -1,1183 +0,0 @@ -#! /bin/sh -# Attempt to guess a canonical system name. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000 -# Free Software Foundation, Inc. -# -# This file is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Written by Per Bothner <bothner@cygnus.com>. -# Please send patches to <config-patches@gnu.org>. -# -# This script attempts to guess a canonical system name similar to -# config.sub. If it succeeds, it prints the system name on stdout, and -# exits with 0. Otherwise, it exits with 1. -# -# The plan is that this can be called by configure scripts if you -# don't specify an explicit system type (host/target name). -# -# Only a few systems have been added to this list; please add others -# (but try to keep the structure clean). -# - -# Use $HOST_CC if defined. $CC may point to a cross-compiler -if test x"$CC_FOR_BUILD" = x; then - if test x"$HOST_CC" != x; then - CC_FOR_BUILD="$HOST_CC" - else - if test x"$CC" != x; then - CC_FOR_BUILD="$CC" - else - CC_FOR_BUILD=cc - fi - fi -fi - - -# This is needed to find uname on a Pyramid OSx when run in the BSD universe. -# (ghazi@noc.rutgers.edu 8/24/94.) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then - PATH=$PATH:/.attbin ; export PATH -fi - -UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown -UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown -UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown -UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown - -dummy=dummy-$$ -trap 'rm -f $dummy.c $dummy.o $dummy; exit 1' 1 2 15 - -# Note: order is significant - the case branches are not exclusive. - -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - *:NetBSD:*:*) - # Netbsd (nbsd) targets should (where applicable) match one or - # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, - # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently - # switched to ELF, *-*-netbsd* would select the old - # object file format. This provides both forward - # compatibility and a consistent mechanism for selecting the - # object file format. - # Determine the machine/vendor (is the vendor relevant). - case "${UNAME_MACHINE}" in - amiga) machine=m68k-cbm ;; - arm32) machine=arm-unknown ;; - atari*) machine=m68k-atari ;; - sun3*) machine=m68k-sun ;; - mac68k) machine=m68k-apple ;; - macppc) machine=powerpc-apple ;; - hp3[0-9][05]) machine=m68k-hp ;; - ibmrt|romp-ibm) machine=romp-ibm ;; - *) machine=${UNAME_MACHINE}-unknown ;; - esac - # The Operating System including object format. - if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep __ELF__ >/dev/null - then - # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). - # Return netbsd for either. FIX? - os=netbsd - else - os=netbsdelf - fi - # The OS release - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: - # contains redundant information, the shorter form: - # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" - exit 0 ;; - alpha:OSF1:*:*) - if test $UNAME_RELEASE = "V4.0"; then - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - fi - # A Vn.n version is a released version. - # A Tn.n version is a released field test version. - # A Xn.n version is an unreleased experimental baselevel. - # 1.2 uses "1.2" for uname -r. - cat <<EOF >$dummy.s - .data -\$Lformat: - .byte 37,100,45,37,120,10,0 # "%d-%x\n" - - .text - .globl main - .align 4 - .ent main -main: - .frame \$30,16,\$26,0 - ldgp \$29,0(\$27) - .prologue 1 - .long 0x47e03d80 # implver \$0 - lda \$2,-1 - .long 0x47e20c21 # amask \$2,\$1 - lda \$16,\$Lformat - mov \$0,\$17 - not \$1,\$18 - jsr \$26,printf - ldgp \$29,0(\$26) - mov 0,\$16 - jsr \$26,exit - .end main -EOF - $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null - if test "$?" = 0 ; then - case `./$dummy` in - 0-0) - UNAME_MACHINE="alpha" - ;; - 1-0) - UNAME_MACHINE="alphaev5" - ;; - 1-1) - UNAME_MACHINE="alphaev56" - ;; - 1-101) - UNAME_MACHINE="alphapca56" - ;; - 2-303) - UNAME_MACHINE="alphaev6" - ;; - 2-307) - UNAME_MACHINE="alphaev67" - ;; - esac - fi - rm -f $dummy.s $dummy - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - exit 0 ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit 0 ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit 0 ;; - Amiga*:UNIX_System_V:4.0:*) - echo m68k-cbm-sysv4 - exit 0;; - amiga:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos - exit 0 ;; - arc64:OpenBSD:*:*) - echo mips64el-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - arc:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - hkmips:OpenBSD:*:*) - echo mips-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - pmax:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - sgi:OpenBSD:*:*) - echo mips-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - wgrisc:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - *:OS/390:*:*) - echo i370-ibm-openedition - exit 0 ;; - arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} - exit 0;; - SR2?01:HI-UX/MPP:*:*) - echo hppa1.1-hitachi-hiuxmpp - exit 0;; - Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) - # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - if test "`(/bin/universe) 2>/dev/null`" = att ; then - echo pyramid-pyramid-sysv3 - else - echo pyramid-pyramid-bsd - fi - exit 0 ;; - NILE*:*:*:dcosx) - echo pyramid-pyramid-svr4 - exit 0 ;; - sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - i86pc:SunOS:5.*:*) - echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - sun4*:SunOS:6*:*) - # According to config.sub, this is the proper way to canonicalize - # SunOS6. Hard to guess exactly what SunOS6 will be like, but - # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - sun4*:SunOS:*:*) - case "`/usr/bin/arch -k`" in - Series*|S4*) - UNAME_RELEASE=`uname -v` - ;; - esac - # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` - exit 0 ;; - sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} - exit 0 ;; - sun*:*:4.2BSD:*) - UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 - case "`/bin/arch`" in - sun3) - echo m68k-sun-sunos${UNAME_RELEASE} - ;; - sun4) - echo sparc-sun-sunos${UNAME_RELEASE} - ;; - esac - exit 0 ;; - aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} - exit 0 ;; - atari*:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - # The situation for MiNT is a little confusing. The machine name - # can be virtually everything (everything which is not - # "atarist" or "atariste" at least should have a processor - # > m68000). The system name ranges from "MiNT" over "FreeMiNT" - # to the lowercase version "mint" (or "freemint"). Finally - # the system name "TOS" denotes a system which is actually not - # MiNT. But MiNT is downward compatible to TOS, so this should - # be no problem. - atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; - atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; - *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; - milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit 0 ;; - hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit 0 ;; - *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit 0 ;; - sun3*:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mac68k:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mvme68k:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mvme88k:OpenBSD:*:*) - echo m88k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} - exit 0 ;; - RISC*:Mach:*:*) - echo mips-dec-mach_bsd4.3 - exit 0 ;; - RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} - exit 0 ;; - VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} - exit 0 ;; - 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} - exit 0 ;; - mips:*:*:UMIPS | mips:*:*:RISCos) - sed 's/^ //' << EOF >$dummy.c -#ifdef __cplusplus -#include <stdio.h> /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif - #if defined (host_mips) && defined (MIPSEB) - #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); - #endif - #endif - exit (-1); - } -EOF - $CC_FOR_BUILD $dummy.c -o $dummy \ - && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ - && rm $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - echo mips-mips-riscos${UNAME_RELEASE} - exit 0 ;; - Night_Hawk:Power_UNIX:*:*) - echo powerpc-harris-powerunix - exit 0 ;; - m88k:CX/UX:7*:*) - echo m88k-harris-cxux7 - exit 0 ;; - m88k:*:4*:R4*) - echo m88k-motorola-sysv4 - exit 0 ;; - m88k:*:3*:R3*) - echo m88k-motorola-sysv3 - exit 0 ;; - AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] - then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] - then - echo m88k-dg-dgux${UNAME_RELEASE} - else - echo m88k-dg-dguxbcs${UNAME_RELEASE} - fi - else - echo i586-dg-dgux${UNAME_RELEASE} - fi - exit 0 ;; - M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit 0 ;; - M88*:*:R3*:*) - # Delta 88k system running SVR3 - echo m88k-motorola-sysv3 - exit 0 ;; - XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - echo m88k-tektronix-sysv3 - exit 0 ;; - Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - echo m68k-tektronix-bsd - exit 0 ;; - *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit 0 ;; - ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' - i?86:AIX:*:*) - echo i386-ibm-aix - exit 0 ;; - *:AIX:2:3) - if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - sed 's/^ //' << EOF >$dummy.c - #include <sys/systemcfg.h> - - main() - { - if (!__power_pc()) - exit(1); - puts("powerpc-ibm-aix3.2.5"); - exit(0); - } -EOF - $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - echo rs6000-ibm-aix3.2.5 - elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - echo rs6000-ibm-aix3.2.4 - else - echo rs6000-ibm-aix3.2 - fi - exit 0 ;; - *:AIX:*:4) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'` - if /usr/sbin/lsattr -EHl ${IBM_CPU_ID} | grep POWER >/dev/null 2>&1; then - IBM_ARCH=rs6000 - else - IBM_ARCH=powerpc - fi - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=4.${UNAME_RELEASE} - fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit 0 ;; - *:AIX:*:*) - echo rs6000-ibm-aix - exit 0 ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) - echo romp-ibm-bsd4.4 - exit 0 ;; - ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit 0 ;; # report: romp-ibm BSD 4.3 - *:BOSX:*:*) - echo rs6000-bull-bosx - exit 0 ;; - DPX/2?00:B.O.S.:*:*) - echo m68k-bull-sysv3 - exit 0 ;; - 9000/[34]??:4.3bsd:1.*:*) - echo m68k-hp-bsd - exit 0 ;; - hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - echo m68k-hp-bsd4.4 - exit 0 ;; - 9000/[34678]??:HP-UX:*:*) - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; - 9000/[678][0-9][0-9]) - sed 's/^ //' << EOF >$dummy.c - - #define _HPUX_SOURCE - #include <stdlib.h> - #include <unistd.h> - - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); - - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } -EOF - (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy` - rm -f $dummy.c $dummy - esac - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit 0 ;; - 3050*:HI-UX:*:*) - sed 's/^ //' << EOF >$dummy.c - #include <unistd.h> - int - main () - { - long cpu = sysconf (_SC_CPU_VERSION); - /* The order matters, because CPU_IS_HP_MC68K erroneously returns - true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct - results, however. */ - if (CPU_IS_PA_RISC (cpu)) - { - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; - case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; - default: puts ("hppa-hitachi-hiuxwe2"); break; - } - } - else if (CPU_IS_HP_MC68K (cpu)) - puts ("m68k-hitachi-hiuxwe2"); - else puts ("unknown-hitachi-hiuxwe2"); - exit (0); - } -EOF - $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - echo unknown-hitachi-hiuxwe2 - exit 0 ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) - echo hppa1.1-hp-bsd - exit 0 ;; - 9000/8??:4.3bsd:*:*) - echo hppa1.0-hp-bsd - exit 0 ;; - *9??*:MPE/iX:*:*) - echo hppa1.0-hp-mpeix - exit 0 ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) - echo hppa1.1-hp-osf - exit 0 ;; - hp8??:OSF1:*:*) - echo hppa1.0-hp-osf - exit 0 ;; - i?86:OSF1:*:*) - if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk - else - echo ${UNAME_MACHINE}-unknown-osf1 - fi - exit 0 ;; - parisc*:Lites*:*:*) - echo hppa1.1-hp-lites - exit 0 ;; - hppa*:OpenBSD:*:*) - echo hppa-unknown-openbsd - exit 0 ;; - C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd - exit 0 ;; - C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit 0 ;; - C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd - exit 0 ;; - C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd - exit 0 ;; - C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd - exit 0 ;; - CRAY*X-MP:*:*:*) - echo xmp-cray-unicos - exit 0 ;; - CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} - exit 0 ;; - CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ - | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ - -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ - exit 0 ;; - CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*T3E:*:*:*) - echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY-2:*:*:*) - echo cray2-cray-unicos - exit 0 ;; - F300:UNIX_System_V:*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit 0 ;; - F301:UNIX_System_V:*:*) - echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'` - exit 0 ;; - hp300:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - i?86:BSD/386:*:* | i?86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} - exit 0 ;; - sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} - exit 0 ;; - *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} - exit 0 ;; - *:FreeBSD:*:*) - echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit 0 ;; - *:OpenBSD:*:*) - echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - exit 0 ;; - i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin - exit 0 ;; - i*:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 - exit 0 ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i386-pc-interix - exit 0 ;; - i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin - exit 0 ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit 0 ;; - prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - *:GNU:*:*) - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit 0 ;; - *:Linux:*:*) - - # The BFD linker knows what the default object file format is, so - # first see if it will tell us. cd to the root directory to prevent - # problems with other programs or directories called `ld' in the path. - ld_help_string=`cd /; ld --help 2>&1` - ld_supported_emulations=`echo $ld_help_string \ - | sed -ne '/supported emulations:/!d - s/[ ][ ]*/ /g - s/.*supported emulations: *// - s/ .*// - p'` - case "$ld_supported_emulations" in - *ia64) - echo "${UNAME_MACHINE}-unknown-linux" - exit 0 - ;; - i?86linux) - echo "${UNAME_MACHINE}-pc-linux-gnuaout" - exit 0 - ;; - elf_i?86) - echo "${UNAME_MACHINE}-pc-linux" - exit 0 - ;; - i?86coff) - echo "${UNAME_MACHINE}-pc-linux-gnucoff" - exit 0 - ;; - sparclinux) - echo "${UNAME_MACHINE}-unknown-linux-gnuaout" - exit 0 - ;; - armlinux) - echo "${UNAME_MACHINE}-unknown-linux-gnuaout" - exit 0 - ;; - elf32arm*) - echo "${UNAME_MACHINE}-unknown-linux-gnuoldld" - exit 0 - ;; - armelf_linux*) - echo "${UNAME_MACHINE}-unknown-linux-gnu" - exit 0 - ;; - m68klinux) - echo "${UNAME_MACHINE}-unknown-linux-gnuaout" - exit 0 - ;; - elf32ppc | elf32ppclinux) - # Determine Lib Version - cat >$dummy.c <<EOF -#include <features.h> -#if defined(__GLIBC__) -extern char __libc_version[]; -extern char __libc_release[]; -#endif -main(argc, argv) - int argc; - char *argv[]; -{ -#if defined(__GLIBC__) - printf("%s %s\n", __libc_version, __libc_release); -#else - printf("unkown\n"); -#endif - return 0; -} -EOF - LIBC="" - $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null - if test "$?" = 0 ; then - ./$dummy | grep 1\.99 > /dev/null - if test "$?" = 0 ; then - LIBC="libc1" - fi - fi - rm -f $dummy.c $dummy - echo powerpc-unknown-linux-gnu${LIBC} - exit 0 - ;; - esac - - if test "${UNAME_MACHINE}" = "alpha" ; then - cat <<EOF >$dummy.s - .data - \$Lformat: - .byte 37,100,45,37,120,10,0 # "%d-%x\n" - - .text - .globl main - .align 4 - .ent main - main: - .frame \$30,16,\$26,0 - ldgp \$29,0(\$27) - .prologue 1 - .long 0x47e03d80 # implver \$0 - lda \$2,-1 - .long 0x47e20c21 # amask \$2,\$1 - lda \$16,\$Lformat - mov \$0,\$17 - not \$1,\$18 - jsr \$26,printf - ldgp \$29,0(\$26) - mov 0,\$16 - jsr \$26,exit - .end main -EOF - LIBC="" - $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null - if test "$?" = 0 ; then - case `./$dummy` in - 0-0) - UNAME_MACHINE="alpha" - ;; - 1-0) - UNAME_MACHINE="alphaev5" - ;; - 1-1) - UNAME_MACHINE="alphaev56" - ;; - 1-101) - UNAME_MACHINE="alphapca56" - ;; - 2-303) - UNAME_MACHINE="alphaev6" - ;; - 2-307) - UNAME_MACHINE="alphaev67" - ;; - esac - - objdump --private-headers $dummy | \ - grep ld.so.1 > /dev/null - if test "$?" = 0 ; then - LIBC="libc1" - fi - fi - rm -f $dummy.s $dummy - echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0 - elif test "${UNAME_MACHINE}" = "mips" ; then - cat >$dummy.c <<EOF -#ifdef __cplusplus -#include <stdio.h> /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif -#ifdef __MIPSEB__ - printf ("%s-unknown-linux-gnu\n", argv[1]); -#endif -#ifdef __MIPSEL__ - printf ("%sel-unknown-linux-gnu\n", argv[1]); -#endif - return 0; -} -EOF - $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - elif test "${UNAME_MACHINE}" = "s390"; then - echo s390-ibm-linux && exit 0 - else - # Either a pre-BFD a.out linker (linux-gnuoldld) - # or one that does not give us useful --help. - # GCC wants to distinguish between linux-gnuoldld and linux-gnuaout. - # If ld does not provide *any* "supported emulations:" - # that means it is gnuoldld. - echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations:" - test $? != 0 && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0 - - case "${UNAME_MACHINE}" in - i?86) - VENDOR=pc; - ;; - *) - VENDOR=unknown; - ;; - esac - # Determine whether the default compiler is a.out or elf - cat >$dummy.c <<EOF -#include <features.h> -#ifdef __cplusplus -#include <stdio.h> /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif -#ifdef __ELF__ -# ifdef __GLIBC__ -# if __GLIBC__ >= 2 - printf ("%s-${VENDOR}-linux-gnu\n", argv[1]); -# else - printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); -# endif -# else - printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); -# endif -#else - printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]); -#endif - return 0; -} -EOF - $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - fi ;; -# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions -# are messed up and put the nodename in both sysname and nodename. - i?86:DYNIX/ptx:4*:*) - echo i386-sequent-sysv4 - exit 0 ;; - i?86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, - # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} - exit 0 ;; - i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` - if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} - else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} - fi - exit 0 ;; - i?86:*:5:7*) - # Fixed at (any) Pentium or better - UNAME_MACHINE=i586 - if [ ${UNAME_SYSTEM} = "UnixWare" ] ; then - echo ${UNAME_MACHINE}-sco-sysv${UNAME_RELEASE}uw${UNAME_VERSION} - else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE} - fi - exit 0 ;; - i?86:*:3.2:*) - if test -f /usr/options/cb.name; then - UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` - echo ${UNAME_MACHINE}-pc-isc$UNAME_REL - elif /bin/uname -X 2>/dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` - (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ - && UNAME_MACHINE=i586 - (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ - && UNAME_MACHINE=i686 - (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ - && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL - else - echo ${UNAME_MACHINE}-pc-sysv32 - fi - exit 0 ;; - i?86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit 0 ;; - pc:*:*:*) - # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i386. - echo i386-pc-msdosdjgpp - exit 0 ;; - Intel:Mach:3*:*) - echo i386-pc-mach3 - exit 0 ;; - paragon:*:*:*) - echo i860-intel-osf1 - exit 0 ;; - i860:*:4.*:*) # i860-SVR4 - if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 - else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 - fi - exit 0 ;; - mini*:CTIX:SYS*5:*) - # "miniframe" - echo m68010-convergent-sysv - exit 0 ;; - M68*:*:R3V[567]*:*) - test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; - 3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0) - OS_REL='' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && echo i486-ncr-sysv4.3${OS_REL} && exit 0 - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; - 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && echo i486-ncr-sysv4 && exit 0 ;; - m68*:LynxOS:2.*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit 0 ;; - i?86:LynxOS:2.*:* | i?86:LynxOS:3.[01]*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} - exit 0 ;; - RM*:ReliantUNIX-*:*:*) - echo mips-sni-sysv4 - exit 0 ;; - RM*:SINIX-*:*:*) - echo mips-sni-sysv4 - exit 0 ;; - *:SINIX-*:*:*) - if uname -p 2>/dev/null >/dev/null ; then - UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 - else - echo ns32k-sni-sysv - fi - exit 0 ;; - PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says <Richard.M.Bartel@ccMail.Census.GOV> - echo i586-unisys-sysv4 - exit 0 ;; - *:UNIX_System_V:4*:FTX*) - # From Gerald Hewes <hewes@openmarket.com>. - # How about differentiating between stratus architectures? -djm - echo hppa1.1-stratus-sysv4 - exit 0 ;; - *:*:*:FTX*) - # From seanf@swdc.stratus.com. - echo i860-stratus-sysv4 - exit 0 ;; - mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} - exit 0 ;; - news*:NEWS-OS:*:6*) - echo mips-sony-newsos6 - exit 0 ;; - R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} - else - echo mips-unknown-sysv${UNAME_RELEASE} - fi - exit 0 ;; - BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - echo powerpc-be-beos - exit 0 ;; - BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. - echo powerpc-apple-beos - exit 0 ;; - BePC:BeOS:*:*) # BeOS running on Intel PC compatible. - echo i586-pc-beos - exit 0 ;; - SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} - exit 0 ;; - SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} - exit 0 ;; - Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} - exit 0 ;; - *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} - exit 0 ;; - *:Darwin:*:*) - echo `uname -p`-apple-darwin${UNAME_RELEASE} - exit 0 ;; - *:procnto*:*:* | *:QNX:[0123456789]*:*) - if test "${UNAME_MACHINE}" = "x86pc"; then - UNAME_MACHINE=pc - fi - echo `uname -p`-${UNAME_MACHINE}-nto-qnx - exit 0 ;; - *:QNX:*:4*) - echo i386-pc-qnx - exit 0 ;; - NSR-W:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} - exit 0 ;; - BS2000:POSIX*:*:*) - echo bs2000-siemens-sysv - exit 0 ;; - DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit 0 ;; -esac - -#echo '(No uname command or uname output not recognized.)' 1>&2 -#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 - -cat >$dummy.c <<EOF -#ifdef _SEQUENT_ -# include <sys/types.h> -# include <sys/utsname.h> -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include <sys/param.h> - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); -#endif - -#if defined (NeXT) -#if !defined (__ARCHITECTURE__) -#define __ARCHITECTURE__ "m68k" -#endif - int version; - version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -#if !defined (ultrix) - printf ("vax-dec-bsd\n"); exit (0); -#else - printf ("vax-dec-ultrix\n"); exit (0); -#endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} -EOF - -$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm $dummy.c $dummy && exit 0 -rm -f $dummy.c $dummy - -# Apollos put the system type in the environment. - -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit 0 ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit 0 ;; - c34*) - echo c34-convex-bsd - exit 0 ;; - c38*) - echo c38-convex-bsd - exit 0 ;; - c4*) - echo c4-convex-bsd - exit 0 ;; - esac -fi - -#echo '(Unable to guess system type)' 1>&2 - -exit 1 diff --git a/libtecla-1.4.1/config.sub b/libtecla-1.4.1/config.sub deleted file mode 100644 index c8e7785..0000000 --- a/libtecla-1.4.1/config.sub +++ /dev/null @@ -1,1268 +0,0 @@ -#! /bin/sh -# Configuration validation subroutine script, version 1.1. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000 -# Free Software Foundation, Inc. -# -# This file is (in principle) common to ALL GNU software. -# The presence of a machine in this file suggests that SOME GNU software -# can handle that machine. It does not imply ALL GNU software can. -# -# This file is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Written by Per Bothner <bothner@cygnus.com>. -# Please send patches to <config-patches@gnu.org>. -# -# Configuration subroutine to validate and canonicalize a configuration type. -# Supply the specified configuration type as an argument. -# If it is invalid, we print an error message on stderr and exit with code 1. -# Otherwise, we print the canonical config type on stdout and succeed. - -# This file is supposed to be the same for all GNU packages -# and recognize all the CPU types, system types and aliases -# that are meaningful with *any* GNU software. -# Each package is responsible for reporting which valid configurations -# it does not support. The user should be able to distinguish -# a failure to support a valid configuration from a meaningless -# configuration. - -# The goal of this file is to map all the various variations of a given -# machine specification into a single specification in the form: -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or in some cases, the newer four-part form: -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM -# It is wrong to echo any other type of specification. - -if [ x$1 = x ] -then - echo Configuration name missing. 1>&2 - echo "Usage: $0 CPU-MFR-OPSYS" 1>&2 - echo "or $0 ALIAS" 1>&2 - echo where ALIAS is a recognized configuration type. 1>&2 - exit 1 -fi - -# First pass through any local machine types. -case $1 in - *local*) - echo $1 - exit 0 - ;; - *) - ;; -esac - -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac - -### Let's recognize common machines as not being operating systems so -### that things like config.sub decstation-3100 work. We also -### recognize some manufacturers as not being operating systems, so we -### can provide default operating systems below. -case $os in - -sun*os*) - # Prevent following clause from handling this invalid input. - ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple) - os= - basic_machine=$1 - ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 - ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*) - os=-lynxos - ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; - -psos*) - os=-psos - ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; -esac - -# Decode aliases for certain CPU-COMPANY combinations. -case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - tahoe | i860 | ia64 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \ - | arme[lb] | pyramid | mn10200 | mn10300 | tron | a29k \ - | 580 | i960 | h8300 \ - | x86 | ppcbe | mipsbe | mipsle | shbe | shle | armbe | armle \ - | hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \ - | hppa64 \ - | alpha | alphaev[4-8] | alphaev56 | alphapca5[67] \ - | alphaev6[78] \ - | we32k | ns16k | clipper | i370 | sh | powerpc | powerpcle \ - | 1750a | dsp16xx | pdp11 | mips16 | mips64 | mipsel | mips64el \ - | mips64orion | mips64orionel | mipstx39 | mipstx39el \ - | mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \ - | mips64vr5000 | miprs64vr5000el | mcore \ - | sparc | sparclet | sparclite | sparc64 | sparcv9 | v850 | c4x \ - | thumb | d10v | fr30 | avr) - basic_machine=$basic_machine-unknown - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | z8k | v70 | h8500 | w65 | pj | pjl) - ;; - - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i[34567]86) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - # FIXME: clean up the formatting here. - vax-* | tahoe-* | i[34567]86-* | i860-* | ia64-* | m32r-* | m68k-* | m68000-* \ - | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \ - | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \ - | power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \ - | xmp-* | ymp-* \ - | x86-* | ppcbe-* | mipsbe-* | mipsle-* | shbe-* | shle-* | armbe-* | armle-* \ - | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* \ - | hppa2.0n-* | hppa64-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphapca5[67]-* \ - | alphaev6[78]-* \ - | we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \ - | clipper-* | orion-* \ - | sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \ - | sparc64-* | sparcv9-* | sparc86x-* | mips16-* | mips64-* | mipsel-* \ - | mips64el-* | mips64orion-* | mips64orionel-* \ - | mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \ - | mipstx39-* | mipstx39el-* | mcore-* \ - | f301-* | armv*-* | s390-* | sv1-* | t3e-* \ - | m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \ - | thumb-* | v850-* | d30v-* | tic30-* | c30-* | fr30-* \ - | bs2000-*) - ;; - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att - ;; - 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-cbm - ;; - amigaos | amigados) - basic_machine=m68k-cbm - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-cbm - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | ymp) - basic_machine=ymp-cray - os=-unicos - ;; - cray2) - basic_machine=cray2-cray - os=-unicos - ;; - [ctj]90-cray) - basic_machine=c90-cray - os=-unicos - ;; - crds | unos) - basic_machine=m68k-crds - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd - ;; - encore | umax | mmax) - basic_machine=ns32k-encore - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose - ;; - fx2800) - basic_machine=i860-alliant - ;; - genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp - ;; - hp9k3[2-9][0-9]) - basic_machine=m68k-hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; -# I'm not sure what "Sysv32" means. Should this be sysv3.2? - i[34567]86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i[34567]86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i[34567]86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i[34567]86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta - ;; - i386-go32 | go32) - basic_machine=i386-unknown - os=-go32 - ;; - i386-mingw32 | mingw32) - basic_machine=i386-unknown - os=-mingw32 - ;; - iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) - ;; - *) - os=-irix4 - ;; - esac - ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mipsel*-linux*) - basic_machine=mipsel-unknown - os=-linux-gnu - ;; - mips*-linux*) - basic_machine=mips-unknown - os=-linux-gnu - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - mmix*) - basic_machine=mmix-knuth - os=-mmixware - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - msdos) - basic_machine=i386-unknown - os=-msdos - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos - ;; - news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) - ;; - -ns2*) - os=-nextstep2 - ;; - *) - os=-nextstep3 - ;; - esac - ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - np1) - basic_machine=np1-gould - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k - ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - pbd) - basic_machine=sparc-tti - ;; - pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pentium | p5 | k5 | k6 | nexen) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86) - basic_machine=i686-pc - ;; - pentiumii | pentium2) - basic_machine=i786-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexen-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pn) - basic_machine=pn-gould - ;; - power) basic_machine=rs6000-ibm - ;; - ppc) basic_machine=powerpc-unknown - ;; - ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle | ppc-le | powerpc-little) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sequent) - basic_machine=i386-sequent - ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; - sparclite-wrs) - basic_machine=sparclite-wrs - os=-vxworks - ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 - ;; - spur) - basic_machine=spur-unknown - ;; - st2000) - basic_machine=m68k-tandem - ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 - ;; - sun2) - basic_machine=m68000-sun - ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 - ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 - ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 - ;; - sun3 | sun3-*) - basic_machine=m68k-sun - ;; - sun4) - basic_machine=sparc-sun - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - ;; - sv1) - basic_machine=sv1-cray - os=-unicos - ;; - symmetry) - basic_machine=i386-sequent - os=-dynix - ;; - t3e) - basic_machine=t3e-cray - os=-unicos - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - tower | tower-32) - basic_machine=m68k-ncr - ;; - udi29k) - basic_machine=a29k-amd - os=-udi - ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=-none - ;; - vaxv) - basic_machine=vax-dec - os=-sysv - ;; - vms) - basic_machine=vax-dec - os=-vms - ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks - ;; - w65*) - basic_machine=w65-wdc - os=-none - ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf - ;; - xmp) - basic_machine=xmp-cray - os=-unicos - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - none) - basic_machine=none-none - os=-none - ;; - -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond - ;; - op50n) - basic_machine=hppa1.1-oki - ;; - op60c) - basic_machine=hppa1.1-oki - ;; - mips) - if [ x$os = x-linux-gnu ]; then - basic_machine=mips-unknown - else - basic_machine=mips-mips - fi - ;; - romp) - basic_machine=romp-ibm - ;; - rs6000) - basic_machine=rs6000-ibm - ;; - vax) - basic_machine=vax-dec - ;; - pdp11) - basic_machine=pdp11-dec - ;; - we32k) - basic_machine=we32k-att - ;; - sparc | sparcv9) - basic_machine=sparc-sun - ;; - cydra) - basic_machine=cydra-cydrome - ;; - orion) - basic_machine=orion-highlevel - ;; - orion105) - basic_machine=clipper-highlevel - ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple - ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple - ;; - c4x*) - basic_machine=c4x-none - os=-coff - ;; - *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; -esac - -# Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` - ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` - ;; - *) - ;; -esac - -# Decode manufacturer-specific aliases for certain operating systems. - -if [ x"$os" != x"" ] -then -case $os in - # First match some system type aliases - # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. - -solaris1 | -solaris1.*) - os=`echo $os | sed -e 's|solaris1|sunos4|'` - ;; - -solaris) - os=-solaris2 - ;; - -svr4*) - os=-sysv4 - ;; - -unixware*) - os=-sysv4.2uw - ;; - -gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` - ;; - # First accept the basic system types. - # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ - | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit*) - # Remember, each alternative MUST END IN *, to match a version number. - ;; - -qnx*) - case $basic_machine in - x86-* | i[34567]86-*) - ;; - *) - os=-nto$os - ;; - esac - ;; - -nto*) - os=-nto-qnx - ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) - ;; - -mac*) - os=`echo $os | sed -e 's|mac|macos|'` - ;; - -linux*) - os=`echo $os | sed -e 's|linux|linux-gnu|'` - ;; - -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` - ;; - -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` - ;; - -opened*) - os=-openedition - ;; - -wince*) - os=-wince - ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; - -utek*) - os=-bsd - ;; - -dynix*) - os=-bsd - ;; - -acis*) - os=-aos - ;; - -386bsd) - os=-bsd - ;; - -ctix* | -uts*) - os=-sysv - ;; - -ns2 ) - os=-nextstep2 - ;; - -nsk) - os=-nsk - ;; - # Preserve the version number of sinix5. - -sinix5.*) - os=`echo $os | sed -e 's|sinix|sysv|'` - ;; - -sinix*) - os=-sysv4 - ;; - -triton*) - os=-sysv3 - ;; - -oss*) - os=-sysv3 - ;; - -svr4) - os=-sysv4 - ;; - -svr3) - os=-sysv3 - ;; - -sysvr4) - os=-sysv4 - ;; - # This must come after -sysvr4. - -sysv*) - ;; - -ose*) - os=-ose - ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; - -*mint | -*MiNT) - os=-mint - ;; - -none) - ;; - *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 - exit 1 - ;; -esac -else - -# Here we handle the default operating systems that come with various machines. -# The value should be what the vendor currently ships out the door with their -# machine or put another way, the most popular os provided with the machine. - -# Note that if you're going to try to match "-MANUFACTURER" here (say, -# "-sun"), then you have to tell the case statement up towards the top -# that MANUFACTURER isn't an operating system. Otherwise, code above -# will signal an error saying that MANUFACTURER isn't an operating -# system, and we'll never get to this point. - -case $basic_machine in - *-acorn) - os=-riscix1.2 - ;; - arm*-rebel) - os=-linux - ;; - arm*-semi) - os=-aout - ;; - pdp11-*) - os=-none - ;; - *-dec | vax-*) - os=-ultrix4.2 - ;; - m68*-apollo) - os=-domain - ;; - i386-sun) - os=-sunos4.0.2 - ;; - m68000-sun) - os=-sunos3 - # This also exists in the configure program, but was not the - # default. - # os=-sunos4 - ;; - m68*-cisco) - os=-aout - ;; - mips*-cisco) - os=-elf - ;; - mips*-*) - os=-elf - ;; - *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 - ;; - sparc-* | *-sun) - os=-sunos4.1.1 - ;; - *-be) - os=-beos - ;; - *-ibm) - os=-aix - ;; - *-wec) - os=-proelf - ;; - *-winbond) - os=-proelf - ;; - *-oki) - os=-proelf - ;; - *-hp) - os=-hpux - ;; - *-hitachi) - os=-hiux - ;; - i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv - ;; - *-cbm) - os=-amigaos - ;; - *-dg) - os=-dgux - ;; - *-dolphin) - os=-sysv3 - ;; - m68k-ccur) - os=-rtu - ;; - m88k-omron*) - os=-luna - ;; - *-next ) - os=-nextstep - ;; - *-sequent) - os=-ptx - ;; - *-crds) - os=-unos - ;; - *-ns) - os=-genix - ;; - i370-*) - os=-mvs - ;; - *-next) - os=-nextstep3 - ;; - *-gould) - os=-sysv - ;; - *-highlevel) - os=-bsd - ;; - *-encore) - os=-bsd - ;; - *-sgi) - os=-irix - ;; - *-siemens) - os=-sysv4 - ;; - *-masscomp) - os=-rtu - ;; - f301-fujitsu) - os=-uxpv - ;; - *-rom68k) - os=-coff - ;; - *-*bug) - os=-coff - ;; - *-apple) - os=-macos - ;; - *-atari*) - os=-mint - ;; - *) - os=-none - ;; -esac -fi - -# Here we handle the case where we know the os, and the CPU type, but not the -# manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) - vendor=acorn - ;; - -sunos*) - vendor=sun - ;; - -aix*) - vendor=ibm - ;; - -beos*) - vendor=be - ;; - -hpux*) - vendor=hp - ;; - -mpeix*) - vendor=hp - ;; - -hiux*) - vendor=hitachi - ;; - -unos*) - vendor=crds - ;; - -dgux*) - vendor=dg - ;; - -luna*) - vendor=omron - ;; - -genix*) - vendor=ns - ;; - -mvs* | -opened*) - vendor=ibm - ;; - -ptx*) - vendor=sequent - ;; - -vxsim* | -vxworks*) - vendor=wrs - ;; - -aux*) - vendor=apple - ;; - -hms*) - vendor=hitachi - ;; - -mpw* | -macos*) - vendor=apple - ;; - -*mint | -*MiNT) - vendor=atari - ;; - esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` - ;; -esac - -echo $basic_machine$os diff --git a/libtecla-1.4.1/configure b/libtecla-1.4.1/configure deleted file mode 100755 index feaa587..0000000 --- a/libtecla-1.4.1/configure +++ /dev/null @@ -1,1939 +0,0 @@ -#! /bin/sh - -# Guess values for system-dependent variables and create Makefiles. -# Generated automatically using autoconf version 2.13 -# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. -# -# This configure script is free software; the Free Software Foundation -# gives unlimited permission to copy, distribute and modify it. - -# Defaults: -ac_help= -ac_default_prefix=/usr/local -# Any additions from configure.in: - -# Initialize some variables set by options. -# The variables have the same names as the options, with -# dashes changed to underlines. -build=NONE -cache_file=./config.cache -exec_prefix=NONE -host=NONE -no_create= -nonopt=NONE -no_recursion= -prefix=NONE -program_prefix=NONE -program_suffix=NONE -program_transform_name=s,x,x, -silent= -site= -srcdir= -target=NONE -verbose= -x_includes=NONE -x_libraries=NONE -bindir='${exec_prefix}/bin' -sbindir='${exec_prefix}/sbin' -libexecdir='${exec_prefix}/libexec' -datadir='${prefix}/share' -sysconfdir='${prefix}/etc' -sharedstatedir='${prefix}/com' -localstatedir='${prefix}/var' -libdir='${exec_prefix}/lib' -includedir='${prefix}/include' -oldincludedir='/usr/include' -infodir='${prefix}/info' -mandir='${prefix}/man' - -# Initialize some other variables. -subdirs= -MFLAGS= MAKEFLAGS= -SHELL=${CONFIG_SHELL-/bin/sh} -# Maximum number of lines to put in a shell here document. -ac_max_here_lines=12 - -ac_prev= -for ac_option -do - - # If the previous option needs an argument, assign it. - if test -n "$ac_prev"; then - eval "$ac_prev=\$ac_option" - ac_prev= - continue - fi - - case "$ac_option" in - -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; - *) ac_optarg= ;; - esac - - # Accept the important Cygnus configure options, so we can diagnose typos. - - case "$ac_option" in - - -bindir | --bindir | --bindi | --bind | --bin | --bi) - ac_prev=bindir ;; - -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) - bindir="$ac_optarg" ;; - - -build | --build | --buil | --bui | --bu) - ac_prev=build ;; - -build=* | --build=* | --buil=* | --bui=* | --bu=*) - build="$ac_optarg" ;; - - -cache-file | --cache-file | --cache-fil | --cache-fi \ - | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) - ac_prev=cache_file ;; - -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ - | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) - cache_file="$ac_optarg" ;; - - -datadir | --datadir | --datadi | --datad | --data | --dat | --da) - ac_prev=datadir ;; - -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ - | --da=*) - datadir="$ac_optarg" ;; - - -disable-* | --disable-*) - ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` - # Reject names that are not valid shell variable names. - if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then - { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } - fi - ac_feature=`echo $ac_feature| sed 's/-/_/g'` - eval "enable_${ac_feature}=no" ;; - - -enable-* | --enable-*) - ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` - # Reject names that are not valid shell variable names. - if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then - { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } - fi - ac_feature=`echo $ac_feature| sed 's/-/_/g'` - case "$ac_option" in - *=*) ;; - *) ac_optarg=yes ;; - esac - eval "enable_${ac_feature}='$ac_optarg'" ;; - - -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ - | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ - | --exec | --exe | --ex) - ac_prev=exec_prefix ;; - -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ - | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ - | --exec=* | --exe=* | --ex=*) - exec_prefix="$ac_optarg" ;; - - -gas | --gas | --ga | --g) - # Obsolete; use --with-gas. - with_gas=yes ;; - - -help | --help | --hel | --he) - # Omit some internal or obsolete options to make the list less imposing. - # This message is too long to be a string in the A/UX 3.1 sh. - cat << EOF -Usage: configure [options] [host] -Options: [defaults in brackets after descriptions] -Configuration: - --cache-file=FILE cache test results in FILE - --help print this message - --no-create do not create output files - --quiet, --silent do not print \`checking...' messages - --version print the version of autoconf that created configure -Directory and file names: - --prefix=PREFIX install architecture-independent files in PREFIX - [$ac_default_prefix] - --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX - [same as prefix] - --bindir=DIR user executables in DIR [EPREFIX/bin] - --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] - --libexecdir=DIR program executables in DIR [EPREFIX/libexec] - --datadir=DIR read-only architecture-independent data in DIR - [PREFIX/share] - --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] - --sharedstatedir=DIR modifiable architecture-independent data in DIR - [PREFIX/com] - --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] - --libdir=DIR object code libraries in DIR [EPREFIX/lib] - --includedir=DIR C header files in DIR [PREFIX/include] - --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] - --infodir=DIR info documentation in DIR [PREFIX/info] - --mandir=DIR man documentation in DIR [PREFIX/man] - --srcdir=DIR find the sources in DIR [configure dir or ..] - --program-prefix=PREFIX prepend PREFIX to installed program names - --program-suffix=SUFFIX append SUFFIX to installed program names - --program-transform-name=PROGRAM - run sed PROGRAM on installed program names -EOF - cat << EOF -Host type: - --build=BUILD configure for building on BUILD [BUILD=HOST] - --host=HOST configure for HOST [guessed] - --target=TARGET configure for TARGET [TARGET=HOST] -Features and packages: - --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) - --enable-FEATURE[=ARG] include FEATURE [ARG=yes] - --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] - --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --x-includes=DIR X include files are in DIR - --x-libraries=DIR X library files are in DIR -EOF - if test -n "$ac_help"; then - echo "--enable and --with options recognized:$ac_help" - fi - exit 0 ;; - - -host | --host | --hos | --ho) - ac_prev=host ;; - -host=* | --host=* | --hos=* | --ho=*) - host="$ac_optarg" ;; - - -includedir | --includedir | --includedi | --included | --include \ - | --includ | --inclu | --incl | --inc) - ac_prev=includedir ;; - -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ - | --includ=* | --inclu=* | --incl=* | --inc=*) - includedir="$ac_optarg" ;; - - -infodir | --infodir | --infodi | --infod | --info | --inf) - ac_prev=infodir ;; - -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) - infodir="$ac_optarg" ;; - - -libdir | --libdir | --libdi | --libd) - ac_prev=libdir ;; - -libdir=* | --libdir=* | --libdi=* | --libd=*) - libdir="$ac_optarg" ;; - - -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ - | --libexe | --libex | --libe) - ac_prev=libexecdir ;; - -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ - | --libexe=* | --libex=* | --libe=*) - libexecdir="$ac_optarg" ;; - - -localstatedir | --localstatedir | --localstatedi | --localstated \ - | --localstate | --localstat | --localsta | --localst \ - | --locals | --local | --loca | --loc | --lo) - ac_prev=localstatedir ;; - -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ - | --localstate=* | --localstat=* | --localsta=* | --localst=* \ - | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) - localstatedir="$ac_optarg" ;; - - -mandir | --mandir | --mandi | --mand | --man | --ma | --m) - ac_prev=mandir ;; - -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) - mandir="$ac_optarg" ;; - - -nfp | --nfp | --nf) - # Obsolete; use --without-fp. - with_fp=no ;; - - -no-create | --no-create | --no-creat | --no-crea | --no-cre \ - | --no-cr | --no-c) - no_create=yes ;; - - -no-recursion | --no-recursion | --no-recursio | --no-recursi \ - | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) - no_recursion=yes ;; - - -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ - | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ - | --oldin | --oldi | --old | --ol | --o) - ac_prev=oldincludedir ;; - -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ - | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ - | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) - oldincludedir="$ac_optarg" ;; - - -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) - ac_prev=prefix ;; - -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) - prefix="$ac_optarg" ;; - - -program-prefix | --program-prefix | --program-prefi | --program-pref \ - | --program-pre | --program-pr | --program-p) - ac_prev=program_prefix ;; - -program-prefix=* | --program-prefix=* | --program-prefi=* \ - | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) - program_prefix="$ac_optarg" ;; - - -program-suffix | --program-suffix | --program-suffi | --program-suff \ - | --program-suf | --program-su | --program-s) - ac_prev=program_suffix ;; - -program-suffix=* | --program-suffix=* | --program-suffi=* \ - | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) - program_suffix="$ac_optarg" ;; - - -program-transform-name | --program-transform-name \ - | --program-transform-nam | --program-transform-na \ - | --program-transform-n | --program-transform- \ - | --program-transform | --program-transfor \ - | --program-transfo | --program-transf \ - | --program-trans | --program-tran \ - | --progr-tra | --program-tr | --program-t) - ac_prev=program_transform_name ;; - -program-transform-name=* | --program-transform-name=* \ - | --program-transform-nam=* | --program-transform-na=* \ - | --program-transform-n=* | --program-transform-=* \ - | --program-transform=* | --program-transfor=* \ - | --program-transfo=* | --program-transf=* \ - | --program-trans=* | --program-tran=* \ - | --progr-tra=* | --program-tr=* | --program-t=*) - program_transform_name="$ac_optarg" ;; - - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - silent=yes ;; - - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) - ac_prev=sbindir ;; - -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ - | --sbi=* | --sb=*) - sbindir="$ac_optarg" ;; - - -sharedstatedir | --sharedstatedir | --sharedstatedi \ - | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ - | --sharedst | --shareds | --shared | --share | --shar \ - | --sha | --sh) - ac_prev=sharedstatedir ;; - -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ - | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ - | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ - | --sha=* | --sh=*) - sharedstatedir="$ac_optarg" ;; - - -site | --site | --sit) - ac_prev=site ;; - -site=* | --site=* | --sit=*) - site="$ac_optarg" ;; - - -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) - ac_prev=srcdir ;; - -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) - srcdir="$ac_optarg" ;; - - -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ - | --syscon | --sysco | --sysc | --sys | --sy) - ac_prev=sysconfdir ;; - -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ - | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) - sysconfdir="$ac_optarg" ;; - - -target | --target | --targe | --targ | --tar | --ta | --t) - ac_prev=target ;; - -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) - target="$ac_optarg" ;; - - -v | -verbose | --verbose | --verbos | --verbo | --verb) - verbose=yes ;; - - -version | --version | --versio | --versi | --vers) - echo "configure generated by autoconf version 2.13" - exit 0 ;; - - -with-* | --with-*) - ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` - # Reject names that are not valid shell variable names. - if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then - { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } - fi - ac_package=`echo $ac_package| sed 's/-/_/g'` - case "$ac_option" in - *=*) ;; - *) ac_optarg=yes ;; - esac - eval "with_${ac_package}='$ac_optarg'" ;; - - -without-* | --without-*) - ac_package=`echo $ac_option|sed -e 's/-*without-//'` - # Reject names that are not valid shell variable names. - if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then - { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } - fi - ac_package=`echo $ac_package| sed 's/-/_/g'` - eval "with_${ac_package}=no" ;; - - --x) - # Obsolete; use --with-x. - with_x=yes ;; - - -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ - | --x-incl | --x-inc | --x-in | --x-i) - ac_prev=x_includes ;; - -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ - | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) - x_includes="$ac_optarg" ;; - - -x-libraries | --x-libraries | --x-librarie | --x-librari \ - | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) - ac_prev=x_libraries ;; - -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ - | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) - x_libraries="$ac_optarg" ;; - - -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } - ;; - - *) - if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then - echo "configure: warning: $ac_option: invalid host type" 1>&2 - fi - if test "x$nonopt" != xNONE; then - { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } - fi - nonopt="$ac_option" - ;; - - esac -done - -if test -n "$ac_prev"; then - { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } -fi - -trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 - -# File descriptor usage: -# 0 standard input -# 1 file creation -# 2 errors and warnings -# 3 some systems may open it to /dev/tty -# 4 used on the Kubota Titan -# 6 checking for... messages and results -# 5 compiler messages saved in config.log -if test "$silent" = yes; then - exec 6>/dev/null -else - exec 6>&1 -fi -exec 5>./config.log - -echo "\ -This file contains any messages produced by compilers while -running configure, to aid debugging if configure makes a mistake. -" 1>&5 - -# Strip out --no-create and --no-recursion so they do not pile up. -# Also quote any args containing shell metacharacters. -ac_configure_args= -for ac_arg -do - case "$ac_arg" in - -no-create | --no-create | --no-creat | --no-crea | --no-cre \ - | --no-cr | --no-c) ;; - -no-recursion | --no-recursion | --no-recursio | --no-recursi \ - | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; - *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) - ac_configure_args="$ac_configure_args '$ac_arg'" ;; - *) ac_configure_args="$ac_configure_args $ac_arg" ;; - esac -done - -# NLS nuisances. -# Only set these to C if already set. These must not be set unconditionally -# because not all systems understand e.g. LANG=C (notably SCO). -# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! -# Non-C LC_CTYPE values break the ctype check. -if test "${LANG+set}" = set; then LANG=C; export LANG; fi -if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi -if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi -if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi - -# confdefs.h avoids OS command line length limits that DEFS can exceed. -rm -rf conftest* confdefs.h -# AIX cpp loses on an empty file, so make sure it contains at least a newline. -echo > confdefs.h - -# A filename unique to this package, relative to the directory that -# configure is in, which we can look for to find out if srcdir is correct. -ac_unique_file=getline.c - -# Find the source files, if location was not specified. -if test -z "$srcdir"; then - ac_srcdir_defaulted=yes - # Try the directory containing this script, then its parent. - ac_prog=$0 - ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` - test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. - srcdir=$ac_confdir - if test ! -r $srcdir/$ac_unique_file; then - srcdir=.. - fi -else - ac_srcdir_defaulted=no -fi -if test ! -r $srcdir/$ac_unique_file; then - if test "$ac_srcdir_defaulted" = yes; then - { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } - else - { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } - fi -fi -srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` - -# Prefer explicitly selected file to automatically selected ones. -if test -z "$CONFIG_SITE"; then - if test "x$prefix" != xNONE; then - CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" - else - CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" - fi -fi -for ac_site_file in $CONFIG_SITE; do - if test -r "$ac_site_file"; then - echo "loading site script $ac_site_file" - . "$ac_site_file" - fi -done - -if test -r "$cache_file"; then - echo "loading cache $cache_file" - . $cache_file -else - echo "creating cache $cache_file" - > $cache_file -fi - -ac_ext=c -# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. -ac_cpp='$CPP $CPPFLAGS' -ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' -ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' -cross_compiling=$ac_cv_prog_cc_cross - -ac_exeext= -ac_objext=o -if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then - # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. - if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then - ac_n= ac_c=' -' ac_t=' ' - else - ac_n=-n ac_c= ac_t= - fi -else - ac_n= ac_c='\c' ac_t= -fi - - - - - -MAJOR_VER="1" - - - -MINOR_VER="4" - - - -MICRO_VER="1" - - -CFLAGS="$CFLAGS" -# Extract the first word of "gcc", so it can be a program name with args. -set dummy gcc; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:543: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" - ac_dummy="$PATH" - for ac_dir in $ac_dummy; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - ac_cv_prog_CC="gcc" - break - fi - done - IFS="$ac_save_ifs" -fi -fi -CC="$ac_cv_prog_CC" -if test -n "$CC"; then - echo "$ac_t""$CC" 1>&6 -else - echo "$ac_t""no" 1>&6 -fi - -if test -z "$CC"; then - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:573: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" - ac_prog_rejected=no - ac_dummy="$PATH" - for ac_dir in $ac_dummy; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then - ac_prog_rejected=yes - continue - fi - ac_cv_prog_CC="cc" - break - fi - done - IFS="$ac_save_ifs" -if test $ac_prog_rejected = yes; then - # We found a bogon in the path, so make sure we never use it. - set dummy $ac_cv_prog_CC - shift - if test $# -gt 0; then - # We chose a different compiler from the bogus one. - # However, it has the same basename, so the bogon will be chosen - # first if we set CC to just the basename; use the full file name. - shift - set dummy "$ac_dir/$ac_word" "$@" - shift - ac_cv_prog_CC="$@" - fi -fi -fi -fi -CC="$ac_cv_prog_CC" -if test -n "$CC"; then - echo "$ac_t""$CC" 1>&6 -else - echo "$ac_t""no" 1>&6 -fi - - if test -z "$CC"; then - case "`uname -s`" in - *win32* | *WIN32*) - # Extract the first word of "cl", so it can be a program name with args. -set dummy cl; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:624: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" - ac_dummy="$PATH" - for ac_dir in $ac_dummy; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - ac_cv_prog_CC="cl" - break - fi - done - IFS="$ac_save_ifs" -fi -fi -CC="$ac_cv_prog_CC" -if test -n "$CC"; then - echo "$ac_t""$CC" 1>&6 -else - echo "$ac_t""no" 1>&6 -fi - ;; - esac - fi - test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } -fi - -echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:656: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 - -ac_ext=c -# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. -ac_cpp='$CPP $CPPFLAGS' -ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' -ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' -cross_compiling=$ac_cv_prog_cc_cross - -cat > conftest.$ac_ext << EOF - -#line 667 "configure" -#include "confdefs.h" - -main(){return(0);} -EOF -if { (eval echo configure:672: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - ac_cv_prog_cc_works=yes - # If we can't run a trivial program, we are probably using a cross compiler. - if (./conftest; exit) 2>/dev/null; then - ac_cv_prog_cc_cross=no - else - ac_cv_prog_cc_cross=yes - fi -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - ac_cv_prog_cc_works=no -fi -rm -fr conftest* -ac_ext=c -# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. -ac_cpp='$CPP $CPPFLAGS' -ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' -ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' -cross_compiling=$ac_cv_prog_cc_cross - -echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 -if test $ac_cv_prog_cc_works = no; then - { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } -fi -echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:698: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 -echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 -cross_compiling=$ac_cv_prog_cc_cross - -echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:703: checking whether we are using GNU C" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.c <<EOF -#ifdef __GNUC__ - yes; -#endif -EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:712: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then - ac_cv_prog_gcc=yes -else - ac_cv_prog_gcc=no -fi -fi - -echo "$ac_t""$ac_cv_prog_gcc" 1>&6 - -if test $ac_cv_prog_gcc = yes; then - GCC=yes -else - GCC= -fi - -ac_test_CFLAGS="${CFLAGS+set}" -ac_save_CFLAGS="$CFLAGS" -CFLAGS= -echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:731: checking whether ${CC-cc} accepts -g" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - echo 'void f(){}' > conftest.c -if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then - ac_cv_prog_cc_g=yes -else - ac_cv_prog_cc_g=no -fi -rm -f conftest* - -fi - -echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 -if test "$ac_test_CFLAGS" = set; then - CFLAGS="$ac_save_CFLAGS" -elif test $ac_cv_prog_cc_g = yes; then - if test "$GCC" = yes; then - CFLAGS="-g -O2" - else - CFLAGS="-g" - fi -else - if test "$GCC" = yes; then - CFLAGS="-O2" - else - CFLAGS= - fi -fi - - - -echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 -echo "configure:765: checking whether ${MAKE-make} sets \${MAKE}" >&5 -set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` -if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftestmake <<\EOF -all: - @echo 'ac_maketemp="${MAKE}"' -EOF -# GNU make sometimes prints "make[1]: Entering...", which would confuse us. -eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` -if test -n "$ac_maketemp"; then - eval ac_cv_prog_make_${ac_make}_set=yes -else - eval ac_cv_prog_make_${ac_make}_set=no -fi -rm -f conftestmake -fi -if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then - echo "$ac_t""yes" 1>&6 - SET_MAKE= -else - echo "$ac_t""no" 1>&6 - SET_MAKE="MAKE=${MAKE-make}" -fi - - - -echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 -echo "configure:794: checking whether ln -s works" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - rm -f conftestdata -if ln -s X conftestdata 2>/dev/null -then - rm -f conftestdata - ac_cv_prog_LN_S="ln -s" -else - ac_cv_prog_LN_S=ln -fi -fi -LN_S="$ac_cv_prog_LN_S" -if test "$ac_cv_prog_LN_S" = "ln -s"; then - echo "$ac_t""yes" 1>&6 -else - echo "$ac_t""no" 1>&6 -fi - - - -for ac_prog in gawk mawk nawk awk -do -# Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:821: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_AWK'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test -n "$AWK"; then - ac_cv_prog_AWK="$AWK" # Let the user override the test. -else - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" - ac_dummy="$PATH" - for ac_dir in $ac_dummy; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - ac_cv_prog_AWK="$ac_prog" - break - fi - done - IFS="$ac_save_ifs" -fi -fi -AWK="$ac_cv_prog_AWK" -if test -n "$AWK"; then - echo "$ac_t""$AWK" 1>&6 -else - echo "$ac_t""no" 1>&6 -fi - -test -n "$AWK" && break -done - - - -# Extract the first word of "ranlib", so it can be a program name with args. -set dummy ranlib; ac_word=$2 -echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:855: checking for $ac_word" >&5 -if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test -n "$RANLIB"; then - ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. -else - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" - ac_dummy="$PATH" - for ac_dir in $ac_dummy; do - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$ac_word; then - ac_cv_prog_RANLIB="ranlib" - break - fi - done - IFS="$ac_save_ifs" - test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" -fi -fi -RANLIB="$ac_cv_prog_RANLIB" -if test -n "$RANLIB"; then - echo "$ac_t""$RANLIB" 1>&6 -else - echo "$ac_t""no" 1>&6 -fi - - - -ac_aux_dir= -for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do - if test -f $ac_dir/install-sh; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install-sh -c" - break - elif test -f $ac_dir/install.sh; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install.sh -c" - break - fi -done -if test -z "$ac_aux_dir"; then - { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } -fi -ac_config_guess=$ac_aux_dir/config.guess -ac_config_sub=$ac_aux_dir/config.sub -ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. - - -# Do some error checking and defaulting for the host and target type. -# The inputs are: -# configure --host=HOST --target=TARGET --build=BUILD NONOPT -# -# The rules are: -# 1. You are not allowed to specify --host, --target, and nonopt at the -# same time. -# 2. Host defaults to nonopt. -# 3. If nonopt is not specified, then host defaults to the current host, -# as determined by config.guess. -# 4. Target and build default to nonopt. -# 5. If nonopt is not specified, then target and build default to host. - -# The aliases save the names the user supplied, while $host etc. -# will get canonicalized. -case $host---$target---$nonopt in -NONE---*---* | *---NONE---* | *---*---NONE) ;; -*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;; -esac - - -# Make sure we can run config.sub. -if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then : -else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } -fi - -echo $ac_n "checking host system type""... $ac_c" 1>&6 -echo "configure:931: checking host system type" >&5 - -host_alias=$host -case "$host_alias" in -NONE) - case $nonopt in - NONE) - if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then : - else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; } - fi ;; - *) host_alias=$nonopt ;; - esac ;; -esac - -host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias` -host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` -host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` -host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` -echo "$ac_t""$host" 1>&6 - -echo $ac_n "checking target system type""... $ac_c" 1>&6 -echo "configure:952: checking target system type" >&5 - -target_alias=$target -case "$target_alias" in -NONE) - case $nonopt in - NONE) target_alias=$host_alias ;; - *) target_alias=$nonopt ;; - esac ;; -esac - -target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias` -target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` -target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` -target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` -echo "$ac_t""$target" 1>&6 - -echo $ac_n "checking build system type""... $ac_c" 1>&6 -echo "configure:970: checking build system type" >&5 - -build_alias=$build -case "$build_alias" in -NONE) - case $nonopt in - NONE) build_alias=$host_alias ;; - *) build_alias=$nonopt ;; - esac ;; -esac - -build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias` -build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` -build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` -build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` -echo "$ac_t""$build" 1>&6 - -test "$host_alias" != "$target_alias" && - test "$program_prefix$program_suffix$program_transform_name" = \ - NONENONEs,x,x, && - program_prefix=${target_alias}- - - - -case $target in -*-sun-solaris2.[0-6]|*-sun-solaris2.[0-6].*) - LIBS="$LIBS -L/usr/ccs/lib" - ;; -esac - - -echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:1002: checking how to run the C preprocessor" >&5 -# On Suns, sometimes $CPP names a directory. -if test -n "$CPP" && test -d "$CPP"; then - CPP= -fi -if test -z "$CPP"; then -if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - # This must be in double quotes, not single quotes, because CPP may get - # substituted into the Makefile and "${CC-cc}" will confuse make. - CPP="${CC-cc} -E" - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. - cat > conftest.$ac_ext <<EOF -#line 1017 "configure" -#include "confdefs.h" -#include <assert.h> -Syntax Error -EOF -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1023: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } -ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` -if test -z "$ac_err"; then - : -else - echo "$ac_err" >&5 - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - CPP="${CC-cc} -E -traditional-cpp" - cat > conftest.$ac_ext <<EOF -#line 1034 "configure" -#include "confdefs.h" -#include <assert.h> -Syntax Error -EOF -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1040: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } -ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` -if test -z "$ac_err"; then - : -else - echo "$ac_err" >&5 - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - CPP="${CC-cc} -nologo -E" - cat > conftest.$ac_ext <<EOF -#line 1051 "configure" -#include "confdefs.h" -#include <assert.h> -Syntax Error -EOF -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1057: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } -ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` -if test -z "$ac_err"; then - : -else - echo "$ac_err" >&5 - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - CPP=/lib/cpp -fi -rm -f conftest* -fi -rm -f conftest* -fi -rm -f conftest* - ac_cv_prog_CPP="$CPP" -fi - CPP="$ac_cv_prog_CPP" -else - ac_cv_prog_CPP="$CPP" -fi -echo "$ac_t""$CPP" 1>&6 - -echo $ac_n "checking for tigetstr in -lcurses""... $ac_c" 1>&6 -echo "configure:1082: checking for tigetstr in -lcurses" >&5 -ac_lib_var=`echo curses'_'tigetstr | sed 'y%./+-%__p_%'` -if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_save_LIBS="$LIBS" -LIBS="-lcurses $LIBS" -cat > conftest.$ac_ext <<EOF -#line 1090 "configure" -#include "confdefs.h" -/* Override any gcc2 internal prototype to avoid an error. */ -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char tigetstr(); - -int main() { -tigetstr() -; return 0; } -EOF -if { (eval echo configure:1101: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" -fi -rm -f conftest* -LIBS="$ac_save_LIBS" - -fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 - - cat >> confdefs.h <<\EOF -#define USE_TERMINFO 1 -EOF - - LIBS="$LIBS -lcurses" - -else - echo "$ac_t""no" 1>&6 -echo $ac_n "checking for tigetstr in -lncurses""... $ac_c" 1>&6 -echo "configure:1126: checking for tigetstr in -lncurses" >&5 -ac_lib_var=`echo ncurses'_'tigetstr | sed 'y%./+-%__p_%'` -if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_save_LIBS="$LIBS" -LIBS="-lncurses $LIBS" -cat > conftest.$ac_ext <<EOF -#line 1134 "configure" -#include "confdefs.h" -/* Override any gcc2 internal prototype to avoid an error. */ -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char tigetstr(); - -int main() { -tigetstr() -; return 0; } -EOF -if { (eval echo configure:1145: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" -fi -rm -f conftest* -LIBS="$ac_save_LIBS" - -fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 - - cat >> confdefs.h <<\EOF -#define USE_TERMINFO 1 -EOF - - LIBS="$LIBS -lncurses" - -else - echo "$ac_t""no" 1>&6 -echo $ac_n "checking for tgetstr in -lcurses""... $ac_c" 1>&6 -echo "configure:1170: checking for tgetstr in -lcurses" >&5 -ac_lib_var=`echo curses'_'tgetstr | sed 'y%./+-%__p_%'` -if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - ac_save_LIBS="$LIBS" -LIBS="-lcurses $LIBS" -cat > conftest.$ac_ext <<EOF -#line 1178 "configure" -#include "confdefs.h" -/* Override any gcc2 internal prototype to avoid an error. */ -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char tgetstr(); - -int main() { -tgetstr() -; return 0; } -EOF -if { (eval echo configure:1189: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=yes" -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_lib_$ac_lib_var=no" -fi -rm -f conftest* -LIBS="$ac_save_LIBS" - -fi -if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$ac_t""yes" 1>&6 - - cat >> confdefs.h <<\EOF -#define USE_TERMCAP 1 -EOF - - LIBS="$LIBS -lcurses" - ac_safe=`echo "termcap.h" | sed 'y%./+-%__p_%'` -echo $ac_n "checking for termcap.h""... $ac_c" 1>&6 -echo "configure:1212: checking for termcap.h" >&5 -if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext <<EOF -#line 1217 "configure" -#include "confdefs.h" -#include <termcap.h> -EOF -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1222: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } -ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` -if test -z "$ac_err"; then - rm -rf conftest* - eval "ac_cv_header_$ac_safe=yes" -else - echo "$ac_err" >&5 - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_header_$ac_safe=no" -fi -rm -f conftest* -fi -if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then - echo "$ac_t""yes" 1>&6 - cat >> confdefs.h <<\EOF -#define HAVE_TERMCAP_H 1 -EOF - -else - echo "$ac_t""no" 1>&6 -fi - - -else - echo "$ac_t""no" 1>&6 -fi - -fi - -fi - - - -ac_safe=`echo "term.h" | sed 'y%./+-%__p_%'` -echo $ac_n "checking for term.h""... $ac_c" 1>&6 -echo "configure:1259: checking for term.h" >&5 -if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext <<EOF -#line 1264 "configure" -#include "confdefs.h" -#include <term.h> -EOF -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1269: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } -ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` -if test -z "$ac_err"; then - rm -rf conftest* - eval "ac_cv_header_$ac_safe=yes" -else - echo "$ac_err" >&5 - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_header_$ac_safe=no" -fi -rm -f conftest* -fi -if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then - echo "$ac_t""yes" 1>&6 - cat >> confdefs.h <<\EOF -#define HAVE_TERM_H 1 -EOF - -else - echo "$ac_t""no" 1>&6 - - ac_safe=`echo "ncurses/term.h" | sed 'y%./+-%__p_%'` -echo $ac_n "checking for ncurses/term.h""... $ac_c" 1>&6 -echo "configure:1294: checking for ncurses/term.h" >&5 -if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext <<EOF -#line 1299 "configure" -#include "confdefs.h" -#include <ncurses/term.h> -EOF -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1304: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } -ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` -if test -z "$ac_err"; then - rm -rf conftest* - eval "ac_cv_header_$ac_safe=yes" -else - echo "$ac_err" >&5 - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_header_$ac_safe=no" -fi -rm -f conftest* -fi -if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then - echo "$ac_t""yes" 1>&6 - cat >> confdefs.h <<\EOF -#define HAVE_NCURSES_TERM_H 1 -EOF - -else - echo "$ac_t""no" 1>&6 -fi - - -fi - - - -ac_safe=`echo "curses.h" | sed 'y%./+-%__p_%'` -echo $ac_n "checking for curses.h""... $ac_c" 1>&6 -echo "configure:1335: checking for curses.h" >&5 -if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext <<EOF -#line 1340 "configure" -#include "confdefs.h" -#include <curses.h> -EOF -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1345: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } -ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` -if test -z "$ac_err"; then - rm -rf conftest* - eval "ac_cv_header_$ac_safe=yes" -else - echo "$ac_err" >&5 - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_header_$ac_safe=no" -fi -rm -f conftest* -fi -if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then - echo "$ac_t""yes" 1>&6 - cat >> confdefs.h <<\EOF -#define HAVE_CURSES_H 1 -EOF - -else - echo "$ac_t""no" 1>&6 - - ac_safe=`echo "ncurses/curses.h" | sed 'y%./+-%__p_%'` -echo $ac_n "checking for ncurses/curses.h""... $ac_c" 1>&6 -echo "configure:1370: checking for ncurses/curses.h" >&5 -if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - cat > conftest.$ac_ext <<EOF -#line 1375 "configure" -#include "confdefs.h" -#include <ncurses/curses.h> -EOF -ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1380: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } -ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` -if test -z "$ac_err"; then - rm -rf conftest* - eval "ac_cv_header_$ac_safe=yes" -else - echo "$ac_err" >&5 - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_header_$ac_safe=no" -fi -rm -f conftest* -fi -if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then - echo "$ac_t""yes" 1>&6 - cat >> confdefs.h <<\EOF -#define HAVE_NCURSES_CURSES_H 1 -EOF - -else - echo "$ac_t""no" 1>&6 -fi - - -fi - - - - -TARGETS="normal reentrant" - - -echo $ac_n "checking for reentrant functions""... $ac_c" 1>&6 -echo "configure:1414: checking for reentrant functions" >&5 -if eval "test \"`echo '$''{'tecla_cv_reentrant'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - - KEPT_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -D_POSIX_C_SOURCE=199506L" - cat > conftest.$ac_ext <<EOF -#line 1422 "configure" -#include "confdefs.h" - -#include <unistd.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <dirent.h> -#include <pwd.h> - -int main() { - - (void) readdir_r(NULL, NULL, NULL); - (void) getpwuid_r(geteuid(), NULL, NULL, 0, NULL); - (void) getpwnam_r(NULL, NULL, NULL, 0, NULL); - -; return 0; } -EOF -if { (eval echo configure:1439: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - tecla_cv_reentrant=yes -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - tecla_cv_reentrant=no -fi -rm -f conftest* - CFLAGS="$KEPT_CFLAGS" - -fi - -echo "$ac_t""$tecla_cv_reentrant" 1>&6 - - -if test $tecla_cv_reentrant = no; then - TARGETS="normal" -fi - - -echo $ac_n "checking for select system call""... $ac_c" 1>&6 -echo "configure:1462: checking for select system call" >&5 -if eval "test \"`echo '$''{'tecla_cv_select'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - - cat > conftest.$ac_ext <<EOF -#line 1468 "configure" -#include "confdefs.h" - -#ifdef HAVE_SELECT_H -#include <select.h> -#endif -#include <sys/time.h> -#include <sys/types.h> -#include <unistd.h> - -int main() { - - fd_set fds; - int nready; - FD_ZERO(&fds); - FD_SET(1, &fds); - nready = select(2, &fds, &fds, &fds, NULL); - -; return 0; } -EOF -if { (eval echo configure:1488: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - tecla_cv_select=yes -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - tecla_cv_select=no -fi -rm -f conftest* - -fi - -echo "$ac_t""$tecla_cv_select" 1>&6 - - -if test $tecla_cv_select = yes; then - cat >> confdefs.h <<\EOF -#define HAVE_SELECT 1 -EOF - -fi - - -echo $ac_n "checking for SysV pseudo-terminals""... $ac_c" 1>&6 -echo "configure:1513: checking for SysV pseudo-terminals" >&5 -if eval "test \"`echo '$''{'tecla_cv_sysv_pty'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - - cat > conftest.$ac_ext <<EOF -#line 1519 "configure" -#include "confdefs.h" - -#include <stdlib.h> -#include <unistd.h> -#include <stropts.h> - -int main() { - - char *name = ptsname(0); - int i1 = grantpt(0); - int i2 = unlockpt(0); - int i3 = ioctl(0, I_PUSH, "ptem"); - return 0; - -; return 0; } -EOF -if { (eval echo configure:1536: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - tecla_cv_sysv_pty=yes -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - tecla_cv_sysv_pty=no -fi -rm -f conftest* - -fi - -echo "$ac_t""$tecla_cv_sysv_pty" 1>&6 - - -if test $tecla_cv_sysv_pty = yes; then - cat >> confdefs.h <<\EOF -#define HAVE_SYSV_PTY 1 -EOF - -fi - - - -SHARED_EXT="" - - - -SHARED_ALT="" - - - -SHARED_CFLAGS="" - - - -LINK_SHARED="" - - -case $target in -*solaris*) - cat >> confdefs.h <<\EOF -#define __EXTENSIONS__ 1 -EOF - - SHARED_EXT=".so.${MAJOR_VER}" - SHARED_ALT=".so" - LINK_SHARED='ld -G -M $$(srcdir)/libtecla.map -o $$@ -h $$(@F) -z defs -i $$(LIB_OBJECTS) $$(LIBS) -lc' - SHARED_CFLAGS="-Kpic" - case $CC in - */cc|cc) SHARED_CFLAGS="$SHARED_CFLAGS -xstrconst" ;; - gcc) CFLAGS="-I/usr/include $CFLAGS" ;; - esac - case $target in - *sparc*) SHARED_CFLAGS="$SHARED_CFLAGS -xregs=no%appl" - esac - ;; -*linux*) - SHARED_EXT=".so.${MAJOR_VER}.${MINOR_VER}.${MICRO_VER}" - SHARED_ALT=".so .so.${MAJOR_VER}" - - - echo $ac_n "checking for --version-script in GNU ld""... $ac_c" 1>&6 -echo "configure:1600: checking for --version-script in GNU ld" >&5 -if eval "test \"`echo '$''{'tecla_cv_gnu_ld_script'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - - if (echo 'void dummy(void) {return;}' > dummy.c; $CC -c -fpic dummy.c; \ - ld -o dummy.so dummy.o -shared --version-script=$srcdir/libtecla.map) 1>&2 2>/dev/null; then - tecla_cv_gnu_ld_script=yes - else - tecla_cv_gnu_ld_script=no - fi - rm -f dummy.c dummy.o dummy.so - -fi - -echo "$ac_t""$tecla_cv_gnu_ld_script" 1>&6 - if test $tecla_cv_gnu_ld_script = yes; then - VERSION_OPT='--version-script=$$(srcdir)/libtecla.map' - else - VERSION_OPT='' - fi - - LINK_SHARED='ld -o $$@ -soname libtecla$$(SUFFIX).so.'${MAJOR_VER}' -shared '$VERSION_OPT' $$(LIB_OBJECTS) $$(LIBS) -lc' - SHARED_CFLAGS="-fpic" - ;; -*hpux*) - SHARED_EXT=".${MAJOR_VER}" - SHARED_ALT=".sl" - LINK_SHARED='ld -b +h $$(@F) +k +vshlibunsats -o $$@ -c libtecla.map.opt $$(LIB_OBJECTS) $$(LIBS) -lc' - SHARED_CFLAGS="+z" - ;; -*dec-osf*) - cat >> confdefs.h <<\EOF -#define _OSF_SOURCE 1 -EOF - - ;; -esac - - -if test "$GCC"_ = "yes"_ && test "$LINK_SHARED"_ != "_" ; then - SHARED_CFLAGS="-fpic" - case $target_os in - sparc*solaris*) SHARED_CFLAGS="$SHARED_CFLAGS -mno-app-regs" - esac - LINK_SHARED="$LINK_SHARED `gcc -print-libgcc-file-name`" -fi - - - - - -if test "$LINK_SHARED"_ != "_"; then - TARGET_LIBS="static shared" -else - TARGET_LIBS="static" - LINK_SHARED="@:" -fi - - -trap '' 1 2 15 -cat > confcache <<\EOF -# This file is a shell script that caches the results of configure -# tests run on this system so they can be shared between configure -# scripts and configure runs. It is not useful on other systems. -# If it contains results you don't want to keep, you may remove or edit it. -# -# By default, configure uses ./config.cache as the cache file, -# creating it if it does not exist already. You can give configure -# the --cache-file=FILE option to use a different cache file; that is -# what configure does when it calls configure scripts in -# subdirectories, so they share the cache. -# Giving --cache-file=/dev/null disables caching, for debugging configure. -# config.status only pays attention to the cache file if you give it the -# --recheck option to rerun configure. -# -EOF -# The following way of writing the cache mishandles newlines in values, -# but we know of no workaround that is simple, portable, and efficient. -# So, don't put newlines in cache variables' values. -# Ultrix sh set writes to stderr and can't be redirected directly, -# and sets the high bit in the cache file unless we assign to the vars. -(set) 2>&1 | - case `(ac_space=' '; set | grep ac_space) 2>&1` in - *ac_space=\ *) - # `set' does not quote correctly, so add quotes (double-quote substitution - # turns \\\\ into \\, and sed turns \\ into \). - sed -n \ - -e "s/'/'\\\\''/g" \ - -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" - ;; - *) - # `set' quotes correctly as required by POSIX, so do not add quotes. - sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' - ;; - esac >> confcache -if cmp -s $cache_file confcache; then - : -else - if test -w $cache_file; then - echo "updating cache $cache_file" - cat confcache > $cache_file - else - echo "not updating unwritable cache $cache_file" - fi -fi -rm -f confcache - -trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 - -test "x$prefix" = xNONE && prefix=$ac_default_prefix -# Let make expand exec_prefix. -test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' - -# Any assignment to VPATH causes Sun make to only execute -# the first set of double-colon rules, so remove it if not needed. -# If there is a colon in the path, we need to keep it. -if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' -fi - -trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 - -# Transform confdefs.h into DEFS. -# Protect against shell expansion while executing Makefile rules. -# Protect against Makefile macro expansion. -cat > conftest.defs <<\EOF -s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g -s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g -s%\[%\\&%g -s%\]%\\&%g -s%\$%$$%g -EOF -DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '` -rm -f conftest.defs - - -# Without the "./", some shells look in PATH for config.status. -: ${CONFIG_STATUS=./config.status} - -echo creating $CONFIG_STATUS -rm -f $CONFIG_STATUS -cat > $CONFIG_STATUS <<EOF -#! /bin/sh -# Generated automatically by configure. -# Run this file to recreate the current configuration. -# This directory was configured as follows, -# on host `(hostname || uname -n) 2>/dev/null | sed 1q`: -# -# $0 $ac_configure_args -# -# Compiler output produced by configure, useful for debugging -# configure, is in ./config.log if it exists. - -ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" -for ac_option -do - case "\$ac_option" in - -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) - echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" - exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; - -version | --version | --versio | --versi | --vers | --ver | --ve | --v) - echo "$CONFIG_STATUS generated by autoconf version 2.13" - exit 0 ;; - -help | --help | --hel | --he | --h) - echo "\$ac_cs_usage"; exit 0 ;; - *) echo "\$ac_cs_usage"; exit 1 ;; - esac -done - -ac_given_srcdir=$srcdir - -trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 -EOF -cat >> $CONFIG_STATUS <<EOF - -# Protect against being on the right side of a sed subst in config.status. -sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g; - s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF -$ac_vpsub -$extrasub -s%@SHELL@%$SHELL%g -s%@CFLAGS@%$CFLAGS%g -s%@CPPFLAGS@%$CPPFLAGS%g -s%@CXXFLAGS@%$CXXFLAGS%g -s%@FFLAGS@%$FFLAGS%g -s%@DEFS@%$DEFS%g -s%@LDFLAGS@%$LDFLAGS%g -s%@LIBS@%$LIBS%g -s%@exec_prefix@%$exec_prefix%g -s%@prefix@%$prefix%g -s%@program_transform_name@%$program_transform_name%g -s%@bindir@%$bindir%g -s%@sbindir@%$sbindir%g -s%@libexecdir@%$libexecdir%g -s%@datadir@%$datadir%g -s%@sysconfdir@%$sysconfdir%g -s%@sharedstatedir@%$sharedstatedir%g -s%@localstatedir@%$localstatedir%g -s%@libdir@%$libdir%g -s%@includedir@%$includedir%g -s%@oldincludedir@%$oldincludedir%g -s%@infodir@%$infodir%g -s%@mandir@%$mandir%g -s%@MAJOR_VER@%$MAJOR_VER%g -s%@MINOR_VER@%$MINOR_VER%g -s%@MICRO_VER@%$MICRO_VER%g -s%@CC@%$CC%g -s%@SET_MAKE@%$SET_MAKE%g -s%@LN_S@%$LN_S%g -s%@AWK@%$AWK%g -s%@RANLIB@%$RANLIB%g -s%@host@%$host%g -s%@host_alias@%$host_alias%g -s%@host_cpu@%$host_cpu%g -s%@host_vendor@%$host_vendor%g -s%@host_os@%$host_os%g -s%@target@%$target%g -s%@target_alias@%$target_alias%g -s%@target_cpu@%$target_cpu%g -s%@target_vendor@%$target_vendor%g -s%@target_os@%$target_os%g -s%@build@%$build%g -s%@build_alias@%$build_alias%g -s%@build_cpu@%$build_cpu%g -s%@build_vendor@%$build_vendor%g -s%@build_os@%$build_os%g -s%@CPP@%$CPP%g -s%@TARGETS@%$TARGETS%g -s%@SHARED_EXT@%$SHARED_EXT%g -s%@SHARED_ALT@%$SHARED_ALT%g -s%@SHARED_CFLAGS@%$SHARED_CFLAGS%g -s%@LINK_SHARED@%$LINK_SHARED%g -s%@TARGET_LIBS@%$TARGET_LIBS%g - -CEOF -EOF - -cat >> $CONFIG_STATUS <<\EOF - -# Split the substitutions into bite-sized pieces for seds with -# small command number limits, like on Digital OSF/1 and HP-UX. -ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. -ac_file=1 # Number of current file. -ac_beg=1 # First line for current file. -ac_end=$ac_max_sed_cmds # Line after last line for current file. -ac_more_lines=: -ac_sed_cmds="" -while $ac_more_lines; do - if test $ac_beg -gt 1; then - sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file - else - sed "${ac_end}q" conftest.subs > conftest.s$ac_file - fi - if test ! -s conftest.s$ac_file; then - ac_more_lines=false - rm -f conftest.s$ac_file - else - if test -z "$ac_sed_cmds"; then - ac_sed_cmds="sed -f conftest.s$ac_file" - else - ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" - fi - ac_file=`expr $ac_file + 1` - ac_beg=$ac_end - ac_end=`expr $ac_end + $ac_max_sed_cmds` - fi -done -if test -z "$ac_sed_cmds"; then - ac_sed_cmds=cat -fi -EOF - -cat >> $CONFIG_STATUS <<EOF - -CONFIG_FILES=\${CONFIG_FILES-"Makefile"} -EOF -cat >> $CONFIG_STATUS <<\EOF -for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then - # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". - case "$ac_file" in - *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` - ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; - *) ac_file_in="${ac_file}.in" ;; - esac - - # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. - - # Remove last slash and all that follows it. Not all systems have dirname. - ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` - if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then - # The file is in a subdirectory. - test ! -d "$ac_dir" && mkdir "$ac_dir" - ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" - # A "../" for each directory in $ac_dir_suffix. - ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` - else - ac_dir_suffix= ac_dots= - fi - - case "$ac_given_srcdir" in - .) srcdir=. - if test -z "$ac_dots"; then top_srcdir=. - else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; - /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; - *) # Relative path. - srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" - top_srcdir="$ac_dots$ac_given_srcdir" ;; - esac - - - echo creating "$ac_file" - rm -f "$ac_file" - configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." - case "$ac_file" in - *Makefile*) ac_comsub="1i\\ -# $configure_input" ;; - *) ac_comsub= ;; - esac - - ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` - sed -e "$ac_comsub -s%@configure_input@%$configure_input%g -s%@srcdir@%$srcdir%g -s%@top_srcdir@%$top_srcdir%g -" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file -fi; done -rm -f conftest.s* - -EOF -cat >> $CONFIG_STATUS <<EOF - -EOF -cat >> $CONFIG_STATUS <<\EOF - -exit 0 -EOF -chmod +x $CONFIG_STATUS -rm -fr confdefs* $ac_clean_files -test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 - diff --git a/libtecla-1.4.1/configure.in b/libtecla-1.4.1/configure.in deleted file mode 100644 index 3b083b9..0000000 --- a/libtecla-1.4.1/configure.in +++ /dev/null @@ -1,412 +0,0 @@ -dnl This is the input file which autoconf uses to construct a -dnl "configure" script for the tecla library. It is a bourne shell -dnl script which autoconf pre-processes with the m4 preprocessor to -dnl expand autoconf-defined m4 macros such as AC_INIT(). The -dnl following line just initializes autoconf. Autoconf interprets the -dnl single argument as the name of an arbitrary file, which it uses to -dnl ensure that it is being run correctly from the directory which -dnl contains the libtecla source code. - -AC_INIT(getline.c) - -dnl Here we set the major version number of the tecla library. -dnl Incrementing this number implies that a change has been made to -dnl the library's public interface, which makes it binary incompatible -dnl with programs that were linked with previous shared versions of -dnl the tecla library. Incompatible changes of this type should be -dnl avoided at all costs, so it is hoped that the major version number -dnl won't ever have to change. The major version number must be a -dnl small integer number, preferably a single numeric digit. - -AC_SUBST(MAJOR_VER) -MAJOR_VER="1" - -dnl Set the minor version number of the tecla library. This number -dnl should be incremented by one whenever additional functionality, -dnl such as new functions or modules, are added to the library. The -dnl idea is that a program that was linked with a shared library of -dnl the same major version number, but a lower minor version number, -dnl will continue to function when the run-time loader links it -dnl against the updated version. The minor version number must be a -dnl small integer number, which should be reset to 0 whenever the -dnl major version number is incremented. - -AC_SUBST(MINOR_VER) -MINOR_VER="4" - -dnl Set the micro version number of the tecla library. This is -dnl incremented whenever modifications to the library are made which -dnl make no changes to the public interface, but which fix bugs and/or -dnl improve the behind-the-scenes implementation. The micro version -dnl number should be reset to 0 whenever the minor version number is -dnl incremented. The micro version number must be a small integer -dnl number. - -AC_SUBST(MICRO_VER) -MICRO_VER="1" - -dnl The AC_PROG_CC line looks for a C compiler, and if gcc is chosen, -dnl sets the $GCC shell variable to "yes". Make sure that CFLAGS is -dnl set to something first, to prevent AC_PROG_CC from substituting -g -dnl for the optimization level. - -CFLAGS="$CFLAGS" -AC_PROG_CC - -dnl Apparently not all implementations of the 'make' command define -dnl the MAKE variable. The following directive creates a variable -dnl called SET_MAKE which when expanded in a makefile is either empty -dnl if the local 'make' command was found to define the MAKE variable, -dnl or contains an assignment which will give the MAKE variable the -dnl value 'make'. - -AC_PROG_MAKE_SET - -dnl The following directive causes autoconf to see if symbolic links -dnl are supported on the current filesystem. If so, it sets the -dnl variable LN_S to "ln -s". Otherwise it sets LN_S to just "ln". -dnl This allows us to create symbolic links where possible, but falls -dnl back to creating hard links where symbolic links aren't available. - -AC_PROG_LN_S - -dnl The following macro searches for the best implementation of awk -dnl on the host system, and records it in the AWK shell variable. - -AC_PROG_AWK - -dnl If ranlib is needed on the target system, the RANLIB make variable -dnl is set to ranlib. Otherwise it is set to :, which is the do-nothing -dnl command of the bourne shell. - -AC_PROG_RANLIB - -dnl The following directive tells autoconf to figure out the target -dnl system type and assign a canonical name for this to the $target -dnl shell variable. This is used below in the target-specific case -dnl statement. - -AC_CANONICAL_SYSTEM - -dnl In early versions of Solaris, some libraries are in /usr/ccs/lib, -dnl where gcc doesn't look. The tests below for the curses library -dnl would thus fail without this directory being added to the search -dnl path. We thus add it here before the tests. Note that in the -dnl following, since [ and ] are m4 quotes, and m4 will remove the -dnl outermost quotes when it processes this file, we have to double -dnl them up here to get [0-6] to appear in the output configure -dnl script. - -case $target in -*-sun-solaris2.[[0-6]]|*-sun-solaris2.[[0-6]].*) - LIBS="$LIBS -L/usr/ccs/lib" - ;; -esac - -dnl The following lines look for terminfo functions in the normal -dnl curses library. If not found, they are searched for in the GNU -dnl ncurses library. If the terminfo functions still aren't found, -dnl then termcap functions are searched for in the curses library. If -dnl either set of functions is found, the corresponding variable -dnl USE_TERMINFO or USE_TERMCAP is arranged to be defined in CFLAGS, -dnl via the exported DEFINES shell variable, and the library in which -dnl they were found is appended to the LIBS shell variable. - -AC_CHECK_LIB(curses, tigetstr, [ - AC_DEFINE(USE_TERMINFO) - LIBS="$LIBS -lcurses" -], [AC_CHECK_LIB(ncurses, tigetstr, [ - AC_DEFINE(USE_TERMINFO) - LIBS="$LIBS -lncurses" -], [AC_CHECK_LIB(curses, tgetstr, [ - AC_DEFINE(USE_TERMCAP) - LIBS="$LIBS -lcurses" - AC_CHECK_HEADER(termcap.h, AC_DEFINE(HAVE_TERMCAP_H)) -])])]) - -dnl Some systems don't have term.h, some systems squirrel it away -dnl in an ncurses sub-directory of the system include directory. -dnl If term.h exists in the normal location, arrange for HAVE_TERM_H -dnl to be added to CFLAGS in the Makefile, by appending it to the -dnl DEFINES shell variable. Otherwise, if it exists under an ncurses -dnl sub-directory, arrange for HAVE_NCURSES_TERM_H to be set instead. -dnl If it isn't found in either of these places, neither of these -dnl variables is set, so term.h just doesn't get included. - -AC_CHECK_HEADER(term.h, AC_DEFINE(HAVE_TERM_H), [ - AC_CHECK_HEADER(ncurses/term.h, AC_DEFINE(HAVE_NCURSES_TERM_H)) -]) - -dnl Do the same search for curses.h. - -AC_CHECK_HEADER(curses.h, AC_DEFINE(HAVE_CURSES_H), [ - AC_CHECK_HEADER(ncurses/curses.h, AC_DEFINE(HAVE_NCURSES_CURSES_H)) -]) - -dnl The following variable lists the targets that will be created if -dnl the user runs make without any arguments. Initially we assume -dnl that we can create both the normal and the reentrant versions -dnl of the library. - -AC_SUBST(TARGETS) -TARGETS="normal reentrant" - -dnl Check for reentrant functions by attempting to compile and link a -dnl temporary program which calls them, being sure to include the -dnl appropriate headers and define _POSIX_C_SOURCE, just in case any -dnl of the functions are defined as macros. In the following, -dnl AC_CACHE_CHECK outputs the message "checking for reentrant -dnl functions". If this check has been done before, it assigns the -dnl cached yes/no value to tecla_cv_reentrant. Otherwise it uses -dnl AC_TRY_LINK() to attempt to compile and link the specified dummy -dnl program, and sets tecla_cv_reentrant to yes or no, depending on -dnl whether this succeeds. Finally it caches the value of -dnl tecla_cv_reentrant in the file config.cache, and writes "yes" or -dnl "no" to the terminal. - -AC_CACHE_CHECK(for reentrant functions, tecla_cv_reentrant, [ - KEPT_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -D_POSIX_C_SOURCE=199506L" - AC_TRY_LINK([ -#include <unistd.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <dirent.h> -#include <pwd.h> - ], [ - (void) readdir_r(NULL, NULL, NULL); - (void) getpwuid_r(geteuid(), NULL, NULL, 0, NULL); - (void) getpwnam_r(NULL, NULL, NULL, 0, NULL); - ], tecla_cv_reentrant=yes, tecla_cv_reentrant=no) - CFLAGS="$KEPT_CFLAGS" -]) - -dnl If the necessary reentrant functions weren't found to be -dnl available, default to only compiling the non-reentrant version of -dnl the library. - -if test $tecla_cv_reentrant = no; then - TARGETS="normal" -fi - -dnl Check for the select system call with the normal arguments, -dnl by attempting to compile and link a temporary program which -dnl calls it, being sure to include the appropriate headers. -dnl In the following, AC_CACHE_CHECK outputs the message -dnl "checking for select system call". If this check has been done -dnl before, it assigns the cached yes/no value to tecla_cv_select. -dnl Otherwise it uses AC_TRY_LINK() to attempt to compile and link -dnl the specified dummy program, and sets tecla_cv_select to yes -dnl or no, depending on whether this succeeds. Finally it caches -dnl the value of tecla_cv_select in the file config.cache, and -dnl writes "yes" or "no" to the terminal. - -AC_CACHE_CHECK(for select system call, tecla_cv_select, [ - AC_TRY_LINK([ -#ifdef HAVE_SELECT_H -#include <select.h> -#endif -#include <sys/time.h> -#include <sys/types.h> -#include <unistd.h> - ], [ - fd_set fds; - int nready; - FD_ZERO(&fds); - FD_SET(1, &fds); - nready = select(2, &fds, &fds, &fds, NULL); - ], tecla_cv_select=yes, tecla_cv_select=no) -]) - -dnl If the select function was available, arrange for HAVE_SELECT to -dnl be defined by CFLAGS. - -if test $tecla_cv_select = yes; then - AC_DEFINE(HAVE_SELECT) -fi - -dnl Check if this system supports the system V pseudo terminal interface. - -AC_CACHE_CHECK(for SysV pseudo-terminals, tecla_cv_sysv_pty, [ - AC_TRY_LINK([ -#include <stdlib.h> -#include <unistd.h> -#include <stropts.h> - ], [ - char *name = ptsname(0); - int i1 = grantpt(0); - int i2 = unlockpt(0); - int i3 = ioctl(0, I_PUSH, "ptem"); - return 0; - ], tecla_cv_sysv_pty=yes, tecla_cv_sysv_pty=no) -]) - -dnl If the system-V pseudo-terminal interface is available, arrange -dnl for HAVE_SYSV_PTY to be defined by CFLAGS. - -if test $tecla_cv_sysv_pty = yes; then - AC_DEFINE(HAVE_SYSV_PTY) -fi - -dnl The following variable contains the extension to append to -dnl "libtecla" and "libtecla_r" when creating shared libraries on the -dnl target platform. This is system dependent and is ignored if -dnl LINK_SHARED remains an empty string. On most platforms that -dnl support shared libaries, this will be .so.$MAJOR_VER, where -dnl MAJOR_VER is the major version number described above, which on -dnl some systems, tells the run-time loader if the program being -dnl loaded is binary compatible with a given version of the library -dnl (see the discussion of MAJOR_VER near the top of this file). -dnl The following empty default can be overriden on a system by system -dnl basis later in this file. - -AC_SUBST(SHARED_EXT) -SHARED_EXT="" - -dnl When a shared library is installed with the extension $SHARED_EXT, -dnl you can optionally produce other copies of this library with -dnl different extensions. This is done using symbolic or hard links, -dnl depending on what is available on the current filesystem, and the -dnl extensions to use for these links are listed in the following -dnl variable, separated by spaces. The following empty default can be -dnl overriden on a system by system basis later in this file. - -AC_SUBST(SHARED_ALT) -SHARED_ALT="" - -dnl The following variable lists extra compilation flags needed to -dnl create object files that can be included in shared libraries. -dnl Normally one would include a flag to tell the C compiler to -dnl compile position-independent code. This option commonly includes -dnl the acronym 'pic'. - -AC_SUBST(SHARED_CFLAGS) -SHARED_CFLAGS="" - -dnl On systems that support shared libraries, the following variable -dnl provides the command needed to make a shared library. In this -dnl variable, $$@ will be replaced with the name of the shared -dnl library, $$(LIB_OBJECTS) will be replaced with a space separated -dnl list of the object files that are to be included in the library, -dnl and libtecla$$(SUFFIX) will be the name of the library being -dnl built, minus the system-specific extension (eg. libtecla or -dnl libtecla_r). If LINK_SHARED is left as an empty string, shared -dnl library creation will not attempted. If your system supports -dnl shared library creation, you should override the default value of -dnl this variable in the target-specific case statement later in this -dnl file. - -AC_SUBST(LINK_SHARED) -LINK_SHARED="" - -dnl The following bourne shell case statement is where system -dnl dependencies can be added. In particular, if your system supports -dnl shared library creation, the following switch is the place to -dnl configure it. To do so you will first need to find out what target -dnl type was just assigned by the AC_CANONICAL_SYSTEM macro executed -dnl previously. The target type of your current system can be -dnl determined by cd'ing to the top level directory of the tecla -dnl distribution, and typing the command "sh config.guess". This will -dnl report what autoconf thinks the system type is. Note that this -dnl will be very specific, so if you know that the configuration -dnl parameters that you are about to provide apply to different -dnl versions of the current system type, you can express this in the -dnl case statement by using a wild-card in place of the version -dnl number, or by using an | alternation to list one or more version -dnl names. Beware that autoconf uses [] as quote characters, so if you -dnl want to use a regexp character range like [a-z], you should write -dnl this as [[a-z]]. - -case $target in -*solaris*) - AC_DEFINE(__EXTENSIONS__) - SHARED_EXT=".so.${MAJOR_VER}" - SHARED_ALT=".so" - LINK_SHARED='ld -G -M $$(srcdir)/libtecla.map -o $$@ -h $$(@F) -z defs -i $$(LIB_OBJECTS) $$(LIBS) -lc' - SHARED_CFLAGS="-Kpic" - case $CC in - */cc|cc) SHARED_CFLAGS="$SHARED_CFLAGS -xstrconst" ;; - gcc) CFLAGS="-I/usr/include $CFLAGS" ;; - esac - case $target in - *sparc*) SHARED_CFLAGS="$SHARED_CFLAGS -xregs=no%appl" - esac - ;; -*linux*) - SHARED_EXT=".so.${MAJOR_VER}.${MINOR_VER}.${MICRO_VER}" - SHARED_ALT=".so .so.${MAJOR_VER}" - -dnl See if the installed version of Gnu ld accepts version scripts. - - AC_CACHE_CHECK([for --version-script in GNU ld], tecla_cv_gnu_ld_script, [ - if (echo 'void dummy(void) {return;}' > dummy.c; $CC -c -fpic dummy.c; \ - ld -o dummy.so dummy.o -shared --version-script=$srcdir/libtecla.map) 1>&2 2>/dev/null; then - tecla_cv_gnu_ld_script=yes - else - tecla_cv_gnu_ld_script=no - fi - rm -f dummy.c dummy.o dummy.so - ]) - if test $tecla_cv_gnu_ld_script = yes; then - VERSION_OPT='--version-script=$$(srcdir)/libtecla.map' - else - VERSION_OPT='' - fi - - LINK_SHARED='ld -o $$@ -soname libtecla$$(SUFFIX).so.'${MAJOR_VER}' -shared '$VERSION_OPT' $$(LIB_OBJECTS) $$(LIBS) -lc' - SHARED_CFLAGS="-fpic" - ;; -*hpux*) - SHARED_EXT=".${MAJOR_VER}" - SHARED_ALT=".sl" - LINK_SHARED='ld -b +h $$(@F) +k +vshlibunsats -o $$@ -c libtecla.map.opt $$(LIB_OBJECTS) $$(LIBS) -lc' - SHARED_CFLAGS="+z" - ;; -*dec-osf*) - AC_DEFINE(_OSF_SOURCE) - ;; -esac - -dnl The following statement checks to see if the GNU C compiler has -dnl been chosen instead of the normal compiler of the host operating -dnl system. If it has, and shared library creation has been -dnl configured, it replaces the shared-library-specific C compilation -dnl flags with those supported by gcc. Also append the gcc run-time -dnl library to the shared library link line. - -if test "$GCC"_ = "yes"_ && test "$LINK_SHARED"_ != "_" ; then - SHARED_CFLAGS="-fpic" - case $target_os in - sparc*solaris*) SHARED_CFLAGS="$SHARED_CFLAGS -mno-app-regs" - esac - LINK_SHARED="$LINK_SHARED `gcc -print-libgcc-file-name`" -fi - -dnl The following variable will list which types of libraries, -dnl "static", and possibly "shared", are to be created and installed. - -AC_SUBST(TARGET_LIBS) - -dnl If shared library creation has been configured, add shared -dnl libraries to the list of libraries to be built. - -if test "$LINK_SHARED"_ != "_"; then - TARGET_LIBS="static shared" -else - TARGET_LIBS="static" - LINK_SHARED="@:" -fi - -dnl The following directive must always be the last line of any -dnl autoconf script. It causes autoconf to create the configure -dnl script, which for each argument of AC_OUTPUT, will look for a -dnl filename formed by appending ".in" to the argument, preprocess -dnl that file, replacing @VAR@ directives with the corresponding value -dnl of the specified shell variable VAR, as set above in this file, -dnl and write the resulting output to the filename given in the -dnl argument. Note that only shell variables that were exported above -dnl with the AC_SUBST() directive will be substituted in @VAR@ -dnl directives (some macros like AC_PROG_CC also call AC_SUBST for you -dnl for the variables that they output). - -AC_OUTPUT(Makefile) diff --git a/libtecla-1.4.1/cplfile.c b/libtecla-1.4.1/cplfile.c deleted file mode 100644 index 73eef1d..0000000 --- a/libtecla-1.4.1/cplfile.c +++ /dev/null @@ -1,874 +0,0 @@ -/* - * Copyright (c) 2000, 2001 by Martin C. Shepherd. - * - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL - * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - */ - -/* - * Standard includes. - */ -#include <stdio.h> -#include <stdlib.h> -#include <limits.h> -#include <errno.h> -#include <string.h> -#include <ctype.h> - -/* - * Local includes. - */ -#include "libtecla.h" -#include "direader.h" -#include "homedir.h" -#include "pathutil.h" -#include "cplfile.h" - -/* - * Set the maximum length allowed for usernames. - * names. - */ -#define USR_LEN 100 - -/* - * Set the maximum length allowed for environment variable names. - */ -#define ENV_LEN 100 - -/* - * Set the max length of the error-reporting string. There is no point - * in this being longer than the width of a typical terminal window. - * In composing error messages, I have assumed that this number is - * at least 80, so you don't decrease it below this number. - */ -#define ERRLEN 200 - -/* - * The resources needed to complete a filename are maintained in objects - * of the following type. - */ -struct CompleteFile { - DirReader *dr; /* A directory reader */ - HomeDir *home; /* A home directory expander */ - PathName *path; /* The buffer in which to accumulate the path */ - PathName *buff; /* A pathname work buffer */ - char usrnam[USR_LEN+1]; /* The buffer used when reading the names of */ - /* users. */ - char envnam[ENV_LEN+1]; /* The buffer used when reading the names of */ - /* environment variables. */ - char errmsg[ERRLEN+1]; /* The error-report buffer */ -}; - -static int cf_expand_home_dir(CompleteFile *cf, const char *user); -static int cf_complete_username(CompleteFile *cf, WordCompletion *cpl, - const char *prefix, const char *line, - int word_start, int word_end, int escaped); -static HOME_DIR_FN(cf_homedir_callback); -static int cf_complete_entry(CompleteFile *cf, WordCompletion *cpl, - const char *line, int word_start, int word_end, - int escaped, CplCheckFn *check_fn, - void *check_data); -static char *cf_read_name(CompleteFile *cf, const char *type, - const char *string, int slen, - char *nambuf, int nammax); -static int cf_prepare_suffix(CompleteFile *cf, const char *suffix, - int add_escapes); - -/* - * A stack based object of the following type is used to pass data to the - * cf_homedir_callback() function. - */ -typedef struct { - CompleteFile *cf; /* The file-completion resource object */ - WordCompletion *cpl; /* The string-completion rsource object */ - const char *prefix; /* The username prefix to be completed */ - const char *line; /* The line from which the prefix was extracted */ - int word_start; /* The index in line[] of the start of the username */ - int word_end; /* The index in line[] following the end of the prefix */ - int escaped; /* If true, add escapes to the completion suffixes */ -} CfHomeArgs; - -/*....................................................................... - * Create a new file-completion object. - * - * Output: - * return CompleteFile * The new object, or NULL on error. - */ -CompleteFile *_new_CompleteFile(void) -{ - CompleteFile *cf; /* The object to be returned */ -/* - * Allocate the container. - */ - cf = (CompleteFile *) malloc(sizeof(CompleteFile)); - if(!cf) { - fprintf(stderr, "_new_CompleteFile: Insufficient memory.\n"); - return NULL; - }; -/* - * Before attempting any operation that might fail, initialize the - * container at least up to the point at which it can safely be passed - * to _del_CompleteFile(). - */ - cf->dr = NULL; - cf->home = NULL; - cf->path = NULL; - cf->buff = NULL; - cf->usrnam[0] = '\0'; - cf->envnam[0] = '\0'; - cf->errmsg[0] = '\0'; -/* - * Create the object that is used for reading directories. - */ - cf->dr = _new_DirReader(); - if(!cf->dr) - return _del_CompleteFile(cf); -/* - * Create the object that is used to lookup home directories. - */ - cf->home = _new_HomeDir(); - if(!cf->home) - return _del_CompleteFile(cf); -/* - * Create the buffer in which the completed pathname is accumulated. - */ - cf->path = _new_PathName(); - if(!cf->path) - return _del_CompleteFile(cf); -/* - * Create a pathname work buffer. - */ - cf->buff = _new_PathName(); - if(!cf->buff) - return _del_CompleteFile(cf); - return cf; -} - -/*....................................................................... - * Delete a file-completion object. - * - * Input: - * cf CompleteFile * The object to be deleted. - * Output: - * return CompleteFile * The deleted object (always NULL). - */ -CompleteFile *_del_CompleteFile(CompleteFile *cf) -{ - if(cf) { - cf->dr = _del_DirReader(cf->dr); - cf->home = _del_HomeDir(cf->home); - cf->path = _del_PathName(cf->path); - cf->buff = _del_PathName(cf->buff); - free(cf); - }; - return NULL; -} - -/*....................................................................... - * Look up the possible completions of the incomplete filename that - * lies between specified indexes of a given command-line string. - * - * Input: - * cpl WordCompletion * The object in which to record the completions. - * cf CompleteFile * The filename-completion resource object. - * line const char * The string containing the incomplete filename. - * word_start int The index of the first character in line[] - * of the incomplete filename. - * word_end int The index of the character in line[] that - * follows the last character of the incomplete - * filename. - * escaped int If true, backslashes in line[] are - * interpreted as escaping the characters - * that follow them, and any spaces, tabs, - * backslashes, or wildcard characters in the - * returned suffixes will be similarly escaped. - * If false, backslashes will be interpreted as - * literal parts of the file name, and no - * backslashes will be added to the returned - * suffixes. - * check_fn CplCheckFn * If not zero, this argument specifies a - * function to call to ask whether a given - * file should be included in the list - * of completions. - * check_data void * Anonymous data to be passed to check_fn(). - * Output: - * return int 0 - OK. - * 1 - Error. A description of the error can be - * acquired by calling _cf_last_error(cf). - */ -int _cf_complete_file(WordCompletion *cpl, CompleteFile *cf, - const char *line, int word_start, int word_end, - int escaped, CplCheckFn *check_fn, void *check_data) -{ - const char *lptr; /* A pointer into line[] */ - int nleft; /* The number of characters still to be processed */ - /* in line[]. */ -/* - * Check the arguments. - */ - if(!cpl || !cf || !line || word_end < word_start) { - if(cf) - strcpy(cf->errmsg, "_cf_complete_file: Invalid arguments"); - return 1; - }; -/* - * Clear the buffer in which the filename will be constructed. - */ - _pn_clear_path(cf->path); -/* - * How many characters are to be processed? - */ - nleft = word_end - word_start; -/* - * Get a pointer to the start of the incomplete filename. - */ - lptr = line + word_start; -/* - * If the first character is a tilde, then perform home-directory - * interpolation. - */ - if(nleft > 0 && *lptr == '~') { - int slen; - if(!cf_read_name(cf, "User", ++lptr, --nleft, cf->usrnam, USR_LEN)) - return 1; -/* - * Advance over the username in the input line. - */ - slen = strlen(cf->usrnam); - lptr += slen; - nleft -= slen; -/* - * If we haven't hit the end of the input string then we have a complete - * username to translate to the corresponding home directory. - */ - if(nleft > 0) { - if(cf_expand_home_dir(cf, cf->usrnam)) - return 1; -/* - * ~user and ~ are usually followed by a directory separator to - * separate them from the file contained in the home directory. - * If the home directory is the root directory, then we don't want - * to follow the home directory by a directory separator, so we should - * skip over it so that it doesn't get copied into the filename. - */ - if(strcmp(cf->path->name, FS_ROOT_DIR) == 0 && - strncmp(lptr, FS_DIR_SEP, FS_DIR_SEP_LEN) == 0) { - lptr += FS_DIR_SEP_LEN; - nleft -= FS_DIR_SEP_LEN; - }; -/* - * If we have reached the end of the input string, then the username - * may be incomplete, and we should attempt to complete it. - */ - } else { -/* - * Look up the possible completions of the username. - */ - return cf_complete_username(cf, cpl, cf->usrnam, line, word_start+1, - word_end, escaped); - }; - }; -/* - * Copy the rest of the path, stopping to expand $envvar expressions - * where encountered. - */ - while(nleft > 0) { - int seglen; /* The length of the next segment to be copied */ -/* - * Find the length of the next segment to be copied, stopping if an - * unescaped '$' is seen, or the end of the path is reached. - */ - for(seglen=0; seglen < nleft; seglen++) { - int c = lptr[seglen]; - if(escaped && c == '\\') - seglen++; - else if(c == '$') - break; -/* - * We will be completing the last component of the file name, - * so whenever a directory separator is seen, assume that it - * might be the start of the last component, and mark the character - * that follows it as the start of the name that is to be completed. - */ - if(nleft >= FS_DIR_SEP_LEN && - strncmp(lptr + seglen, FS_DIR_SEP, FS_DIR_SEP_LEN)==0) { - word_start = (lptr + seglen) - line + FS_DIR_SEP_LEN; - }; - }; -/* - * We have reached either the end of the filename or the start of - * $environment_variable expression. Record the newly checked - * segment of the filename in the output filename, removing - * backslash-escapes where needed. - */ - if(_pn_append_to_path(cf->path, lptr, seglen, escaped) == NULL) { - strcpy(cf->errmsg, "Insufficient memory to complete filename"); - return 1; - }; - lptr += seglen; - nleft -= seglen; -/* - * If the above loop finished before we hit the end of the filename, - * then this was because an unescaped $ was seen. In this case, interpolate - * the value of the environment variable that follows it into the output - * filename. - */ - if(nleft > 0) { - char *value; /* The value of the environment variable */ - int vlen; /* The length of the value string */ - int nlen; /* The length of the environment variable name */ -/* - * Read the name of the environment variable. - */ - if(!cf_read_name(cf, "Environment", ++lptr, --nleft, cf->envnam, ENV_LEN)) - return 1; -/* - * Advance over the environment variable name in the input line. - */ - nlen = strlen(cf->envnam); - lptr += nlen; - nleft -= nlen; -/* - * Get the value of the environment variable. - */ - value = getenv(cf->envnam); - if(!value) { - const char *fmt = "Unknown environment variable: %.*s"; - sprintf(cf->errmsg, fmt, ERRLEN - strlen(fmt), cf->envnam); - return 1; - }; - vlen = strlen(value); -/* - * If we are at the start of the filename and the first character of the - * environment variable value is a '~', attempt home-directory - * interpolation. - */ - if(cf->path->name[0] == '\0' && value[0] == '~') { - if(!cf_read_name(cf, "User", value+1, vlen-1, cf->usrnam, USR_LEN) || - cf_expand_home_dir(cf, cf->usrnam)) - return 1; -/* - * If the home directory is the root directory, and the ~usrname expression - * was followed by a directory separator, prevent the directory separator - * from being appended to the root directory by skipping it in the - * input line. - */ - if(strcmp(cf->path->name, FS_ROOT_DIR) == 0 && - strncmp(lptr, FS_DIR_SEP, FS_DIR_SEP_LEN) == 0) { - lptr += FS_DIR_SEP_LEN; - nleft -= FS_DIR_SEP_LEN; - }; - } else { -/* - * Append the value of the environment variable to the output path. - */ - if(_pn_append_to_path(cf->path, value, strlen(value), escaped)==NULL) { - strcpy(cf->errmsg, "Insufficient memory to complete filename"); - return 1; - }; -/* - * Prevent extra directory separators from being added. - */ - if(nleft >= FS_DIR_SEP_LEN && - strcmp(cf->path->name, FS_ROOT_DIR) == 0 && - strncmp(lptr, FS_DIR_SEP, FS_DIR_SEP_LEN) == 0) { - lptr += FS_DIR_SEP_LEN; - nleft -= FS_DIR_SEP_LEN; - } else if(vlen > FS_DIR_SEP_LEN && - strcmp(value + vlen - FS_DIR_SEP_LEN, FS_DIR_SEP)==0) { - cf->path->name[vlen-FS_DIR_SEP_LEN] = '\0'; - }; - }; -/* - * If adding the environment variable didn't form a valid directory, - * we can't complete the line, since there is no way to separate append - * a partial filename to an environment variable reference without - * that appended part of the name being seen later as part of the - * environment variable name. Thus if the currently constructed path - * isn't a directory, quite now with no completions having been - * registered. - */ - if(!_pu_path_is_dir(cf->path->name)) - return 0; -/* - * For the reasons given above, if we have reached the end of the filename - * with the expansion of an environment variable, the only allowed - * completion involves the addition of a directory separator. - */ - if(nleft == 0) { - if(cpl_add_completion(cpl, line, lptr-line, word_end, FS_DIR_SEP, - "", "")) { - strncpy(cf->errmsg, cpl_last_error(cpl), ERRLEN); - cf->errmsg[ERRLEN] = '\0'; - return 1; - }; - return 0; - }; - }; - }; -/* - * Complete the filename if possible. - */ - return cf_complete_entry(cf, cpl, line, word_start, word_end, escaped, - check_fn, check_data); -} - -/*....................................................................... - * Return a description of the last path-completion error that occurred. - * - * Input: - * cf CompleteFile * The path-completion resource object. - * Output: - * return const char * The description of the last error. - */ -const char *_cf_last_error(CompleteFile *cf) -{ - return cf ? cf->errmsg : "NULL CompleteFile argument"; -} - -/*....................................................................... - * Lookup the home directory of the specified user, or the current user - * if no name is specified, appending it to output pathname. - * - * Input: - * cf CompleteFile * The pathname completion resource object. - * user const char * The username to lookup, or "" to lookup the - * current user. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int cf_expand_home_dir(CompleteFile *cf, const char *user) -{ -/* - * Attempt to lookup the home directory. - */ - const char *home_dir = _hd_lookup_home_dir(cf->home, user); -/* - * Failed? - */ - if(!home_dir) { - strncpy(cf->errmsg, _hd_last_home_dir_error(cf->home), ERRLEN); - cf->errmsg[ERRLEN] = '\0'; - return 1; - }; -/* - * Append the home directory to the pathname string. - */ - if(_pn_append_to_path(cf->path, home_dir, -1, 0) == NULL) { - strcpy(cf->errmsg, "Insufficient memory for home directory expansion"); - return 1; - }; - return 0; -} - -/*....................................................................... - * Lookup and report all completions of a given username prefix. - * - * Input: - * cf CompleteFile * The filename-completion resource object. - * cpl WordCompletion * The object in which to record the completions. - * prefix const char * The prefix of the usernames to lookup. - * line const char * The command-line in which the username appears. - * word_start int The index within line[] of the start of the - * username that is being completed. - * word_end int The index within line[] of the character which - * follows the incomplete username. - * escaped int True if the completions need to have special - * characters escaped. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int cf_complete_username(CompleteFile *cf, WordCompletion *cpl, - const char *prefix, const char *line, - int word_start, int word_end, int escaped) -{ -/* - * Set up a container of anonymous arguments to be sent to the - * username-lookup iterator. - */ - CfHomeArgs args; - args.cf = cf; - args.cpl = cpl; - args.prefix = prefix; - args.line = line; - args.word_start = word_start; - args.word_end = word_end; - args.escaped = escaped; -/* - * Iterate through the list of users, recording those which start - * with the specified prefix. - */ - if(_hd_scan_user_home_dirs(cf->home, &args, cf_homedir_callback)) { - strncpy(cf->errmsg, _hd_last_home_dir_error(cf->home), ERRLEN); - cf->errmsg[ERRLEN] = '\0'; - return 1; - }; - return 0; -} - -/*....................................................................... - * The user/home-directory scanner callback function (see homedir.h) - * used by cf_complete_username(). - */ -static HOME_DIR_FN(cf_homedir_callback) -{ -/* - * Get the file-completion resources from the anonymous data argument. - */ - CfHomeArgs *args = (CfHomeArgs *) data; - WordCompletion *cpl = args->cpl; - CompleteFile *cf = args->cf; -/* - * Get the length of the username prefix. - */ - int prefix_len = strlen(args->prefix); -/* - * Get the length of the latest user name that is to be compared to - * the prefix. - */ - int name_len = strlen(usrnam); -/* - * See if the latest username starts with the prefix that we are - * searching for, and record its suffix in the array of matches if so. - */ - if(name_len >= prefix_len && strncmp(args->prefix, usrnam, prefix_len)==0) { -/* - * Copy the username into the pathname work buffer, adding backslash - * escapes where needed. - */ - if(cf_prepare_suffix(cf, usrnam+prefix_len, args->escaped)) { - strncpy(errmsg, cf->errmsg, maxerr); - errmsg[maxerr] = '\0'; - return 1; - }; -/* - * Report the completion suffix that was copied above. - */ - if(cpl_add_completion(cpl, args->line, args->word_start, args->word_end, - cf->buff->name, FS_DIR_SEP, FS_DIR_SEP)) { - strncpy(errmsg, cpl_last_error(cpl), maxerr); - errmsg[maxerr] = '\0'; - return 1; - }; - }; - return 0; -} - -/*....................................................................... - * Report possible completions of the filename in cf->path->name[]. - * - * Input: - * cf CompleteFile * The file-completion resource object. - * cpl WordCompletion * The object in which to record the completions. - * line const char * The input line, as received by the callback - * function. - * word_start int The index within line[] of the start of the - * last component of the filename that is being - * completed. - * word_end int The index within line[] of the character which - * follows the incomplete filename. - * escaped int If true, escape special characters in the - * completion suffixes. - * check_fn CplCheckFn * If not zero, this argument specifies a - * function to call to ask whether a given - * file should be included in the list - * of completions. - * check_data void * Anonymous data to be passed to check_fn(). - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int cf_complete_entry(CompleteFile *cf, WordCompletion *cpl, - const char *line, int word_start, int word_end, - int escaped, CplCheckFn *check_fn, - void *check_data) -{ - const char *dirpath; /* The name of the parent directory */ - int start; /* The index of the start of the last filename */ - /* component in the transcribed filename. */ - const char *prefix; /* The filename prefix to be completed */ - int prefix_len; /* The length of the filename prefix */ - const char *file_name; /* The lastest filename being compared */ - int waserr = 0; /* True after errors */ - int terminated=0; /* True if the directory part had to be terminated */ -/* - * Get the pathname string and its current length. - */ - char *pathname = cf->path->name; - int pathlen = strlen(pathname); -/* - * Locate the start of the final component of the pathname. - */ - for(start=pathlen - 1; start >= 0 && - strncmp(pathname + start, FS_DIR_SEP, FS_DIR_SEP_LEN) != 0; start--) - ; -/* - * Is the parent directory the root directory? - */ - if(start==0 || - (start < 0 && strncmp(pathname, FS_ROOT_DIR, FS_ROOT_DIR_LEN) == 0)) { - dirpath = FS_ROOT_DIR; - start += FS_ROOT_DIR_LEN; -/* - * If we found a directory separator then the part which precedes the - * last component is the name of the directory to be opened. - */ - } else if(start > 0) { -/* - * The _dr_open_dir() function requires the directory name to be '\0' - * terminated, so temporarily do this by overwriting the first character - * of the directory separator. - */ - pathname[start] = '\0'; - dirpath = pathname; - terminated = 1; -/* - * We reached the start of the pathname before finding a directory - * separator, so arrange to open the current working directory. - */ - } else { - start = 0; - dirpath = FS_PWD; - }; -/* - * Attempt to open the directory. - */ - if(_dr_open_dir(cf->dr, dirpath, NULL)) { - const char *fmt = "Can't open directory: %.*s"; - sprintf(cf->errmsg, fmt, ERRLEN - strlen(fmt), dirpath); - return 1; - }; -/* - * If removed above, restore the directory separator and skip over it - * to the start of the filename. - */ - if(terminated) { - memcpy(pathname + start, FS_DIR_SEP, FS_DIR_SEP_LEN); - start += FS_DIR_SEP_LEN; - }; -/* - * Get the filename prefix and its length. - */ - prefix = pathname + start; - prefix_len = strlen(prefix); -/* - * Traverse the directory, looking for files who's prefixes match the - * last component of the pathname. - */ - while((file_name = _dr_next_file(cf->dr)) != NULL && !waserr) { - int name_len = strlen(file_name); -/* - * Is the latest filename a possible completion of the filename prefix? - */ - if(name_len >= prefix_len && strncmp(prefix, file_name, prefix_len)==0) { -/* - * When listing all files in a directory, don't list files that start - * with '.'. This is how hidden files are denoted in UNIX. - */ - if(prefix_len > 0 || file_name[0] != '.') { -/* - * Copy the completion suffix into the work pathname cf->buff->name, - * adding backslash escapes if needed. - */ - if(cf_prepare_suffix(cf, file_name + prefix_len, escaped)) { - waserr = 1; - } else { -/* - * We want directories to be displayed with directory suffixes, - * and other fully completed filenames to be followed by spaces. - * To check the type of the file, append the current suffix - * to the path being completed, check the filetype, then restore - * the path to its original form. - */ - const char *cont_suffix = ""; /* The suffix to add if fully */ - /* completed. */ - const char *type_suffix = ""; /* The suffix to add when listing */ - if(_pn_append_to_path(cf->path, file_name + prefix_len, - -1, escaped) == NULL) { - strcpy(cf->errmsg, "Insufficient memory to complete filename."); - return 1; - }; -/* - * Specify suffixes according to the file type. - */ - if(_pu_path_is_dir(cf->path->name)) { - cont_suffix = FS_DIR_SEP; - type_suffix = FS_DIR_SEP; - } else if(!check_fn || check_fn(check_data, cf->path->name)) { - cont_suffix = " "; - } else { - cf->path->name[pathlen] = '\0'; - continue; - }; -/* - * Remove the temporarily added suffix. - */ - cf->path->name[pathlen] = '\0'; -/* - * Record the latest completion. - */ - if(cpl_add_completion(cpl, line, word_start, word_end, cf->buff->name, - type_suffix, cont_suffix)) - waserr = 1; - }; - }; - }; - }; -/* - * Close the directory. - */ - _dr_close_dir(cf->dr); - return waserr; -} - -/*....................................................................... - * Read a username or environment variable name, stopping when a directory - * separator is seen, when the end of the string is reached, or the - * output buffer overflows. - * - * Input: - * cf CompleteFile * The file-completion resource object. - * type char * The capitalized name of the type of name being read. - * string char * The string who's prefix contains the name. - * slen int The number of characters in string[]. - * nambuf char * The output name buffer. - * nammax int The longest string that will fit in nambuf[], excluding - * the '\0' terminator. - * Output: - * return char * A pointer to nambuf on success. On error NULL is - * returned and a description of the error is recorded - * in cf->errmsg[]. - */ -static char *cf_read_name(CompleteFile *cf, const char *type, - const char *string, int slen, - char *nambuf, int nammax) -{ - int namlen; /* The number of characters in nambuf[] */ - const char *sptr; /* A pointer into string[] */ -/* - * Work out the max number of characters that should be copied. - */ - int nmax = nammax < slen ? nammax : slen; -/* - * Get the environment variable name that follows the dollar. - */ - for(sptr=string,namlen=0; - namlen < nmax && (slen-namlen < FS_DIR_SEP_LEN || - strncmp(sptr, FS_DIR_SEP, FS_DIR_SEP_LEN) != 0); - namlen++) { - nambuf[namlen] = *sptr++; - }; -/* - * Did the name overflow the buffer? - */ - if(namlen >= nammax) { - const char *fmt = "%.*s name too long"; - sprintf(cf->errmsg, fmt, ERRLEN - strlen(fmt), type); - return NULL; - }; -/* - * Terminate the string. - */ - nambuf[namlen] = '\0'; - return nambuf; -} - -/*....................................................................... - * Using the work buffer cf->buff, make a suitably escaped copy of a - * given completion suffix, ready to be passed to cpl_add_completion(). - * - * Input: - * cf CompleteFile * The file-completion resource object. - * suffix char * The suffix to be copied. - * add_escapes int If true, escape special characters. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int cf_prepare_suffix(CompleteFile *cf, const char *suffix, - int add_escapes) -{ - const char *sptr; /* A pointer into suffix[] */ - int nbsl; /* The number of backslashes to add to the suffix */ - int i; -/* - * How long is the suffix? - */ - int suffix_len = strlen(suffix); -/* - * Clear the work buffer. - */ - _pn_clear_path(cf->buff); -/* - * Count the number of backslashes that will have to be added to - * escape spaces, tabs, backslashes and wildcard characters. - */ - nbsl = 0; - if(add_escapes) { - for(sptr = suffix; *sptr; sptr++) { - switch(*sptr) { - case ' ': case '\t': case '\\': case '*': case '?': case '[': - nbsl++; - break; - }; - }; - }; -/* - * Arrange for the output path buffer to have sufficient room for the - * both the suffix and any backslashes that have to be inserted. - */ - if(_pn_resize_path(cf->buff, suffix_len + nbsl) == NULL) { - strcpy(cf->errmsg, "Insufficient memory to complete filename"); - return 1; - }; -/* - * If the suffix doesn't need any escapes, copy it directly into the - * work buffer. - */ - if(nbsl==0) { - strcpy(cf->buff->name, suffix); - } else { -/* - * Make a copy with special characters escaped? - */ - if(nbsl > 0) { - const char *src = suffix; - char *dst = cf->buff->name; - for(i=0; i<suffix_len; i++) { - switch(*src) { - case ' ': case '\t': case '\\': case '*': case '?': case '[': - *dst++ = '\\'; - }; - *dst++ = *src++; - }; - *dst = '\0'; - }; - }; - return 0; -} diff --git a/libtecla-1.4.1/cplfile.h b/libtecla-1.4.1/cplfile.h deleted file mode 100644 index 31683ba..0000000 --- a/libtecla-1.4.1/cplfile.h +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef cplfile_h -#define cplfile_h - -/* - * Copyright (c) 2000, 2001 by Martin C. Shepherd. - * - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL - * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - */ - -typedef struct CompleteFile CompleteFile; - -/* - * Create a file-completion resource object. - */ -CompleteFile *_new_CompleteFile(void); -/* - * Delete a file-completion resource object. - */ -CompleteFile *_del_CompleteFile(CompleteFile *cf); - -/*....................................................................... - * Complete the string between path[0] and path[len-1] as a pathname, - * leaving the last component uncompleted if it is potentially ambiguous, - * and returning an array of possible completions. Note that the returned - * container belongs to the 'cf' object and its contents will change on - * subsequent calls to this function. - * - * Input: - * cpl WordCompletion * The object in which to record the completions. - * cf CompleteFile * The filename-completion resource object. - * line const char * The string containing the incomplete filename. - * word_start int The index of the first character in line[] - * of the incomplete filename. - * word_end int The index of the character in line[] that - * follows the last character of the incomplete - * filename. - * escaped int If true, backslashes in path[] are - * interpreted as escaping the characters - * that follow them, and any spaces, tabs, - * backslashes, or wildcard characters in the - * returned suffixes will be similarly be escaped. - * If false, backslashes will be interpreted as - * literal parts of the file name, and no - * backslashes will be added to the returned - * suffixes. - * check_fn CplCheckFn * If not zero, this argument specifies a - * function to call to ask whether a given - * file should be included in the list - * of completions. - * check_data void * Anonymous data to be passed to check_fn(). - * Output: - * return int 0 - OK. - * 1 - Error. A description of the error can be - * acquired by calling cf_last_error(cf). - */ -int _cf_complete_file(WordCompletion *cpl, CompleteFile *cf, - const char *line, int word_start, int word_end, - int escaped, CplCheckFn *check_fn, void *check_data); - -/*....................................................................... - * Return a description of the error that occurred on the last call to - * cf_complete_file(). - * - * Input: - * cf CompleteFile * The path-completion resource object. - * Output: - * return char * The description of the last error. - */ -const char *_cf_last_error(CompleteFile *cf); - -#endif diff --git a/libtecla-1.4.1/cplmatch.c b/libtecla-1.4.1/cplmatch.c deleted file mode 100644 index 111f5bd..0000000 --- a/libtecla-1.4.1/cplmatch.c +++ /dev/null @@ -1,927 +0,0 @@ -/* - * Copyright (c) 2000, 2001 by Martin C. Shepherd. - * - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL - * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - */ - -/* - * Standard includes. - */ -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -/* - * Local includes. - */ -#include "libtecla.h" -#include "stringrp.h" -#include "pathutil.h" -#include "cplfile.h" - -/* - * Specify the number of strings to allocate when the string free-list - * is exhausted. This also sets the number of elements to expand the - * matches[] array by whenever it is found to be too small. - */ -#define STR_BLK_FACT 100 - -/* - * Set the max length of the error-reporting string. There is no point - * in this being longer than the width of a typical terminal window. - * In composing error messages, I have assumed that this number is - * at least 80, so don't decrease it below 80. - */ -#define ERRLEN 200 - -/* - * Completion matches are recorded in containers of the following - * type. - */ -struct WordCompletion { - StringGroup *sg; /* Memory for a group of strings */ - int matches_dim; /* The allocated size of result.matches[] */ - char errmsg[ERRLEN+1]; /* The error-reporting buffer */ - CplMatches result; /* Completions to be returned to the caller */ - CompleteFile *cf; /* The resources used for filename completion */ -}; - -static void cpl_sort_matches(WordCompletion *cpl); -static void cpl_zap_duplicates(WordCompletion *cpl); -static void cpl_clear_completions(WordCompletion *cpl); -static int cpl_cmp_matches(const void *v1, const void *v2); -static int cpl_cmp_suffixes(const void *v1, const void *v2); - -/* - * The new_CplFileConf() constructor sets the integer first member of - * the returned object to the following magic number. On seeing this, - * cpl_file_completions() knows when it is passed a valid CplFileConf - * object. - */ -#define CFC_ID_CODE 4568 - -/* - * A pointer to a structure of the following type can be passed to - * the builtin file-completion callback function to modify its behavior. - */ -struct CplFileConf { - int id; /* new_CplFileConf() sets this to CFC_ID_CODE */ - int escaped; /* If none-zero, backslashes in the input line are */ - /* interpreted as escaping special characters and */ - /* spaces, and any special characters and spaces in */ - /* the listed completions will also be escaped with */ - /* added backslashes. This is the default behaviour. */ - /* If zero, backslashes are interpreted as being */ - /* literal parts of the filename, and none are added */ - /* to the completion suffixes. */ - int file_start; /* The index in the input line of the first character */ - /* of the filename. If you specify -1 here, */ - /* cpl_file_completions() identifies the */ - /* the start of the filename by looking backwards for */ - /* an unescaped space, or the beginning of the line. */ - CplCheckFn *chk_fn; /* If not zero, this argument specifies a */ - /* function to call to ask whether a given */ - /* file should be included in the list */ - /* of completions. */ - void *chk_data; /* Anonymous data to be passed to check_fn(). */ -}; - -static void cpl_init_FileConf(CplFileConf *cfc); - -/*....................................................................... - * Create a new string-completion object. - * - * Output: - * return WordCompletion * The new object, or NULL on error. - */ -WordCompletion *new_WordCompletion(void) -{ - WordCompletion *cpl; /* The object to be returned */ -/* - * Allocate the container. - */ - cpl = (WordCompletion *) malloc(sizeof(WordCompletion)); - if(!cpl) { - fprintf(stderr, "new_WordCompletion: Insufficient memory.\n"); - return NULL; - }; -/* - * Before attempting any operation that might fail, initialize the - * container at least up to the point at which it can safely be passed - * to del_WordCompletion(). - */ - cpl->sg = NULL; - cpl->matches_dim = 0; - cpl->result.suffix = NULL; - cpl->result.cont_suffix = NULL; - cpl->result.matches = NULL; - cpl->result.nmatch = 0; - cpl->cf = NULL; -/* - * Allocate an object that allows a group of strings to be allocated - * efficiently by placing many of them in contiguous string segments. - */ - cpl->sg = _new_StringGroup(_pu_pathname_dim()); - if(!cpl->sg) - return del_WordCompletion(cpl); -/* - * Allocate an array for matching completions. This will be extended later - * if needed. - */ - cpl->matches_dim = STR_BLK_FACT; - cpl->result.matches = (CplMatch *) malloc(sizeof(cpl->result.matches[0]) * - cpl->matches_dim); - if(!cpl->result.matches) { - fprintf(stderr, - "new_WordCompletion: Insufficient memory to allocate array of matches.\n"); - return del_WordCompletion(cpl); - }; -/* - * Allocate a filename-completion resource object. - */ - cpl->cf = _new_CompleteFile(); - if(!cpl->cf) - return del_WordCompletion(cpl); - return cpl; -} - -/*....................................................................... - * Delete a string-completion object. - * - * Input: - * cpl WordCompletion * The object to be deleted. - * Output: - * return WordCompletion * The deleted object (always NULL). - */ -WordCompletion *del_WordCompletion(WordCompletion *cpl) -{ - if(cpl) { - cpl->sg = _del_StringGroup(cpl->sg); - if(cpl->result.matches) { - free(cpl->result.matches); - cpl->result.matches = NULL; - cpl->cf = _del_CompleteFile(cpl->cf); - }; - free(cpl); - }; - return NULL; -} - -/*....................................................................... - * This function is designed to be called by CplMatchFn callback - * functions. It adds one possible completion of the token that is being - * completed to an array of completions. If the completion needs any - * special quoting to be valid when displayed in the input line, this - * quoting must be included in the string. - * - * Input: - * cpl WordCompletion * The argument of the same name that was passed - * to the calling CplMatchFn callback function. - * line const char * The input line, as received by the callback - * function. - * word_start int The index within line[] of the start of the - * word that is being completed. - * word_end int The index within line[] of the character which - * follows the incomplete word, as received by the - * calling callback function. - * suffix const char * The appropriately quoted string that could - * be appended to the incomplete token to complete - * it. A copy of this string will be allocated - * internally. - * type_suffix const char * When listing multiple completions, gl_get_line() - * appends this string to the completion to indicate - * its type to the user. If not pertinent pass "". - * Otherwise pass a literal or static string. - * cont_suffix const char * If this turns out to be the only completion, - * gl_get_line() will append this string as - * a continuation. For example, the builtin - * file-completion callback registers a directory - * separator here for directory matches, and a - * space otherwise. If the match were a function - * name you might want to append an open - * parenthesis, etc.. If not relevant pass "". - * Otherwise pass a literal or static string. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int cpl_add_completion(WordCompletion *cpl, const char *line, - int word_start, int word_end, const char *suffix, - const char *type_suffix, const char *cont_suffix) -{ - CplMatch *match; /* The container of the new match */ - char *string; /* A newly allocated copy of the completion string */ -/* - * Check the arguments. - */ - if(!cpl) - return 1; - if(!suffix) - return 0; - if(!type_suffix) - type_suffix = ""; - if(!cont_suffix) - cont_suffix = ""; -/* - * Do we need to extend the array of matches[]? - */ - if(cpl->result.nmatch+1 > cpl->matches_dim) { - int needed = cpl->matches_dim + STR_BLK_FACT; - CplMatch *matches = (CplMatch *) realloc(cpl->result.matches, - sizeof(cpl->result.matches[0]) * needed); - if(!matches) { - strcpy(cpl->errmsg, "Insufficient memory to extend array of matches."); - return 1; - }; - cpl->result.matches = matches; - cpl->matches_dim = needed; - }; -/* - * Allocate memory to store the combined completion prefix and the - * new suffix. - */ - string = _sg_alloc_string(cpl->sg, word_end-word_start + strlen(suffix)); - if(!string) { - strcpy(cpl->errmsg, "Insufficient memory to extend array of matches."); - return 1; - }; -/* - * Compose the string. - */ - strncpy(string, line + word_start, word_end - word_start); - strcpy(string + word_end - word_start, suffix); -/* - * Record the new match. - */ - match = cpl->result.matches + cpl->result.nmatch++; - match->completion = string; - match->suffix = string + word_end - word_start; - match->type_suffix = type_suffix; -/* - * Record the continuation suffix. - */ - cpl->result.cont_suffix = cont_suffix; - return 0; -} - -/*....................................................................... - * Sort the array of matches. - * - * Input: - * cpl WordCompletion * The completion resource object. - */ -static void cpl_sort_matches(WordCompletion *cpl) -{ - qsort(cpl->result.matches, cpl->result.nmatch, - sizeof(cpl->result.matches[0]), cpl_cmp_matches); -} - -/*....................................................................... - * This is a qsort() comparison function used to sort matches. - * - * Input: - * v1, v2 void * Pointers to the two matches to be compared. - * Output: - * return int -1 -> v1 < v2. - * 0 -> v1 == v2 - * 1 -> v1 > v2 - */ -static int cpl_cmp_matches(const void *v1, const void *v2) -{ - const CplMatch *m1 = (const CplMatch *) v1; - const CplMatch *m2 = (const CplMatch *) v2; - return strcmp(m1->completion, m2->completion); -} - -/*....................................................................... - * Sort the array of matches in order of their suffixes. - * - * Input: - * cpl WordCompletion * The completion resource object. - */ -static void cpl_sort_suffixes(WordCompletion *cpl) -{ - qsort(cpl->result.matches, cpl->result.nmatch, - sizeof(cpl->result.matches[0]), cpl_cmp_suffixes); -} - -/*....................................................................... - * This is a qsort() comparison function used to sort matches in order of - * their suffixes. - * - * Input: - * v1, v2 void * Pointers to the two matches to be compared. - * Output: - * return int -1 -> v1 < v2. - * 0 -> v1 == v2 - * 1 -> v1 > v2 - */ -static int cpl_cmp_suffixes(const void *v1, const void *v2) -{ - const CplMatch *m1 = (const CplMatch *) v1; - const CplMatch *m2 = (const CplMatch *) v2; - return strcmp(m1->suffix, m2->suffix); -} - -/*....................................................................... - * Find the common prefix of all of the matching completion matches, - * and record a pointer to it in cpl->result.suffix. Note that this has - * the side effect of sorting the matches into suffix order. - * - * Input: - * cpl WordCompletion * The completion resource object. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int cpl_common_suffix(WordCompletion *cpl) -{ - CplMatches *result; /* The result container */ - const char *first, *last; /* The first and last matching suffixes */ - int length; /* The length of the common suffix */ -/* - * Get the container of the array of matching files. - */ - result = &cpl->result; -/* - * No matching completions? - */ - if(result->nmatch < 1) - return 0; -/* - * Sort th matches into suffix order. - */ - cpl_sort_suffixes(cpl); -/* - * Given that the array of matches is sorted, the first and last - * suffixes are those that differ most in their prefixes, so the common - * prefix of these strings is the longest common prefix of all of the - * suffixes. - */ - first = result->matches[0].suffix; - last = result->matches[result->nmatch - 1].suffix; -/* - * Find the point at which the first and last matching strings - * first difffer. - */ - while(*first && *first == *last) { - first++; - last++; - }; -/* - * How long is the common suffix? - */ - length = first - result->matches[0].suffix; -/* - * Allocate memory to record the common suffix. - */ - result->suffix = _sg_alloc_string(cpl->sg, length); - if(!result->suffix) { - strcpy(cpl->errmsg, - "Insufficient memory to record common completion suffix."); - return 1; - }; -/* - * Record the common suffix. - */ - strncpy(result->suffix, result->matches[0].suffix, length); - result->suffix[length] = '\0'; - return 0; -} - -/*....................................................................... - * Discard the contents of the array of possible completion matches. - * - * Input: - * cpl WordCompletion * The word-completion resource object. - */ -static void cpl_clear_completions(WordCompletion *cpl) -{ -/* - * Discard all of the strings. - */ - _clr_StringGroup(cpl->sg); -/* - * Record the fact that the array is now empty. - */ - cpl->result.nmatch = 0; - cpl->result.suffix = NULL; - cpl->result.cont_suffix = ""; -/* - * Also clear the error message. - */ - cpl->errmsg[0] = '\0'; - return; -} - -/*....................................................................... - * Given an input line and the point at which it completion is to be - * attempted, return an array of possible completions. - * - * Input: - * cpl WordCompletion * The completion resource object. - * line char * The current input line. - * word_end int The index of the character in line[] which - * follows the end of the token that is being - * completed. - * data void * Anonymous 'data' to be passed to match_fn(). - * match_fn CplMatchFn * The function that will identify the prefix - * to be completed from the input line, and - * record completion matches. - * Output: - * return CplMatches * The container of the array of possible - * completions. The returned pointer refers - * to a container owned by the parent WordCompletion - * object, and its contents thus potentially - * change on every call to cpl_matches(). - * On error, NULL is returned, and a description - * of the error can be acquired by calling - * cpl_last_error(cpl). - */ -CplMatches *cpl_complete_word(WordCompletion *cpl, const char *line, - int word_end, void *data, - CplMatchFn *match_fn) -{ - int line_len; /* The total length of the input line */ -/* - * How long is the input line? - */ - line_len = strlen(line); -/* - * Check the arguments. - */ - if(!cpl || !line || !match_fn || word_end < 0 || word_end > line_len) { - if(cpl) - strcpy(cpl->errmsg, "cpl_complete_word: Invalid arguments."); - return NULL; - }; -/* - * Clear the return container. - */ - cpl_clear_completions(cpl); -/* - * Have the matching function record possible completion matches in - * cpl->result.matches. - */ - if(match_fn(cpl, data, line, word_end)) { - if(cpl->errmsg[0] == '\0') - strcpy(cpl->errmsg, "Error completing word."); - return NULL; - }; -/* - * Record a copy of the common initial part of all of the prefixes - * in cpl->result.common. - */ - if(cpl_common_suffix(cpl)) - return NULL; -/* - * Sort the matches into lexicographic order. - */ - cpl_sort_matches(cpl); -/* - * Discard any duplicate matches. - */ - cpl_zap_duplicates(cpl); -/* - * If there is more than one match, discard the continuation suffix. - */ - if(cpl->result.nmatch > 1) - cpl->result.cont_suffix = ""; -/* - * Return the array of matches. - */ - return &cpl->result; -} - -/*....................................................................... - * Print out an array of matching completions. - * - * Input: - * result CplMatches * The container of the sorted array of - * completions. - * fp FILE * The output stream to write to. - * term_width int The width of the terminal. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int cpl_list_completions(CplMatches *result, FILE *fp, int term_width) -{ - int maxlen; /* The length of the longest matching string */ - int width; /* The width of a column */ - int ncol; /* The number of columns to list */ - int nrow; /* The number of rows needed to list all of the matches */ - int row,col; /* The row and column being written to */ - int i; -/* - * Check the arguments. - */ - if(!result || !fp) { - fprintf(stderr, "cpl_list_completions: NULL argument(s).\n"); - return 1; - }; -/* - * Not enough space to list anything? - */ - if(term_width < 1) - return 0; -/* - * Work out the maximum length of the matching strings. - */ - maxlen = 0; - for(i=0; i<result->nmatch; i++) { - CplMatch *match = result->matches + i; - int len = strlen(match->completion) + - strlen(match->type_suffix); - if(len > maxlen) - maxlen = len; - }; -/* - * Nothing to list? - */ - if(maxlen == 0) - return 0; -/* - * Split the available terminal width into columns of maxlen + 2 characters. - */ - width = maxlen + 2; - ncol = term_width / width; -/* - * If the column width is greater than the terminal width, the matches will - * just have to overlap onto the next line. - */ - if(ncol < 1) - ncol = 1; -/* - * How many rows will be needed? - */ - nrow = (result->nmatch + ncol - 1) / ncol; -/* - * Print the matches out in ncol columns, sorted in row order within each - * column. - */ - for(row=0; row < nrow; row++) { - for(col=0; col < ncol; col++) { - int m = col*nrow + row; - if(m < result->nmatch) { - CplMatch *match = result->matches + m; - if(fprintf(fp, "%s%-*s%s", match->completion, - (int) (ncol > 1 ? maxlen - strlen(match->completion):0), - match->type_suffix, col<ncol-1 ? " " : "\r\n") < 0) - return 1; - } else { - if(fprintf(fp, "\r\n") < 0) - return 1; - break; - }; - }; - }; - return 0; -} - -/*....................................................................... - * Return a description of the string-completion error that occurred. - * - * Input: - * cpl WordCompletion * The string-completion resource object. - * Output: - * return const char * The description of the last error. - */ -const char *cpl_last_error(WordCompletion *cpl) -{ - return cpl ? cpl->errmsg : "NULL WordCompletion argument"; -} - -/*....................................................................... - * When an error occurs while performing a completion, you registerf a - * terse description of the error by calling cpl_record_error(). This - * message will then be returned on the next call to cpl_last_error(). - * - * Input: - * cpl WordCompletion * The string-completion resource object that was - * originally passed to the callback. - * errmsg const char * The description of the error. - */ -void cpl_record_error(WordCompletion *cpl, const char *errmsg) -{ - if(cpl && errmsg) { - strncpy(cpl->errmsg, errmsg, ERRLEN); - cpl->errmsg[ERRLEN] = '\0'; - }; -} - -/*....................................................................... - * This is the builtin completion callback function which performs file - * completion. - * - * Input: - * cpl WordCompletion * An opaque pointer to the object that will - * contain the matches. This should be filled - * via zero or more calls to cpl_add_completion(). - * data void * Either NULL to request the default - * file-completion behavior, or a pointer to a - * CplFileConf structure, whose members specify - * a different behavior. - * line char * The current input line. - * word_end int The index of the character in line[] which - * follows the end of the token that is being - * completed. - * Output - * return int 0 - OK. - * 1 - Error. - */ -CPL_MATCH_FN(cpl_file_completions) -{ - const char *start_path; /* The pointer to the start of the pathname */ - /* in line[]. */ - CplFileConf *conf; /* The new-style configuration object. */ -/* - * The following configuration object will be used if the caller didn't - * provide one. - */ - CplFileConf default_conf; -/* - * This function can be called externally, so check its arguments. - */ - if(!cpl) - return 1; - if(!line || word_end < 0) { - strcpy(cpl->errmsg, "cpl_file_completions: Invalid arguments."); - return 1; - }; -/* - * The 'data' argument is either a CplFileConf pointer, identifiable - * by having an integer id code as its first member, or the deprecated - * CplFileArgs pointer, or can be NULL to request the default - * configuration. - */ - if(data && *(int *)data == CFC_ID_CODE) { - conf = (CplFileConf *) data; - } else { -/* - * Select the defaults. - */ - conf = &default_conf; - cpl_init_FileConf(&default_conf); -/* - * If we have been passed an instance of the deprecated CplFileArgs - * structure, copy its configuration parameters over the defaults. - */ - if(data) { - CplFileArgs *args = (CplFileArgs *) data; - conf->escaped = args->escaped; - conf->file_start = args->file_start; - }; - }; -/* - * Get the start of the filename. If not specified by the caller - * identify it by searching backwards in the input line for an - * unescaped space or the start of the line. - */ - if(conf->file_start < 0) { - start_path = _pu_start_of_path(line, word_end); - if(!start_path) { - strcpy(cpl->errmsg, "Unable to find the start of the filename."); - return 1; - }; - } else { - start_path = line + conf->file_start; - }; -/* - * Perform the completion. - */ - if(_cf_complete_file(cpl, cpl->cf, line, start_path - line, word_end, - conf->escaped, conf->chk_fn, conf->chk_data)) { - cpl_record_error(cpl, _cf_last_error(cpl->cf)); - return 1; - }; - return 0; -} - -/*....................................................................... - * Initialize a CplFileArgs structure with default configuration - * parameters. Note that the CplFileArgs configuration type is - * deprecated. The opaque CplFileConf object should be used in future - * applications. - * - * Input: - * cfa CplFileArgs * The configuration object of the - * cpl_file_completions() callback. - */ -void cpl_init_FileArgs(CplFileArgs *cfa) -{ - if(cfa) { - cfa->escaped = 1; - cfa->file_start = -1; - }; -} - -/*....................................................................... - * Initialize a CplFileConf structure with default configuration - * parameters. - * - * Input: - * cfc CplFileConf * The configuration object of the - * cpl_file_completions() callback. - */ -static void cpl_init_FileConf(CplFileConf *cfc) -{ - if(cfc) { - cfc->id = CFC_ID_CODE; - cfc->escaped = 1; - cfc->file_start = -1; - cfc->chk_fn = 0; - cfc->chk_data = NULL; - }; -} - -/*....................................................................... - * Create a new CplFileConf object and initialize it with defaults. - * - * Output: - * return CplFileConf * The new object, or NULL on error. - */ -CplFileConf *new_CplFileConf(void) -{ - CplFileConf *cfc; /* The object to be returned */ -/* - * Allocate the container. - */ - cfc = (CplFileConf *)malloc(sizeof(CplFileConf)); - if(!cfc) - return NULL; -/* - * Before attempting any operation that might fail, initialize the - * container at least up to the point at which it can safely be passed - * to del_CplFileConf(). - */ - cpl_init_FileConf(cfc); - return cfc; -} - -/*....................................................................... - * Delete a CplFileConf object. - * - * Input: - * cfc CplFileConf * The object to be deleted. - * Output: - * return CplFileConf * The deleted object (always NULL). - */ -CplFileConf *del_CplFileConf(CplFileConf *cfc) -{ - if(cfc) { -/* - * Delete the container. - */ - free(cfc); - }; - return NULL; -} - -/*....................................................................... - * If backslashes in the filename should be treated as literal - * characters, call the following function with literal=1. Otherwise - * the default is to treat them as escape characters, used for escaping - * spaces etc.. - * - * Input: - * cfc CplFileConf * The cpl_file_completions() configuration object - * to be configured. - * literal int Pass non-zero here to enable literal interpretation - * of backslashes. Pass 0 to turn off literal - * interpretation. - */ -void cfc_literal_escapes(CplFileConf *cfc, int literal) -{ - if(cfc) - cfc->escaped = !literal; -} - -/*....................................................................... - * Call this function if you know where the index at which the - * filename prefix starts in the input line. Otherwise by default, - * or if you specify start_index to be -1, the filename is taken - * to start after the first unescaped space preceding the cursor, - * or the start of the line, which ever comes first. - * - * Input: - * cfc CplFileConf * The cpl_file_completions() configuration object - * to be configured. - * start_index int The index of the start of the filename in - * the input line, or -1 to select the default. - */ -void cfc_file_start(CplFileConf *cfc, int start_index) -{ - if(cfc) - cfc->file_start = start_index; -} - -/*....................................................................... - * If you only want certain types of files to be included in the - * list of completions, you use the following function to specify a - * callback function which will be called to ask whether a given file - * should be included. - * - * Input: - * cfc CplFileConf * The cpl_file_completions() configuration object - * to be configured. - * chk_fn CplCheckFn * Zero to disable filtering, or a pointer to a - * function that returns 1 if a given file should - * be included in the list of completions. - * chk_data void * Anonymous data to be passed to chk_fn() - * every time that it is called. - */ -void cfc_set_check_fn(CplFileConf *cfc, CplCheckFn *chk_fn, void *chk_data) -{ - if(cfc) { - cfc->chk_fn = chk_fn; - cfc->chk_data = chk_data; - }; -} - -/*....................................................................... - * The following CplCheckFn callback returns non-zero if the specified - * filename is that of an executable. - */ -CPL_CHECK_FN(cpl_check_exe) -{ - return _pu_path_is_exe(pathname); -} - -/*....................................................................... - * Remove duplicates from a sorted array of matches. - * - * Input: - * cpl WordCompletion * The completion resource object. - */ -static void cpl_zap_duplicates(WordCompletion *cpl) -{ - CplMatch *matches; /* The array of matches */ - int nmatch; /* The number of elements in matches[] */ - const char *completion; /* The completion string of the last unique match */ - const char *type_suffix; /* The type of the last unique match */ - int src; /* The index of the match being considered */ - int dst; /* The index at which to record the next */ - /* unique match. */ -/* - * Get the array of matches and the number of matches that it - * contains. - */ - matches = cpl->result.matches; - nmatch = cpl->result.nmatch; -/* - * No matches? - */ - if(nmatch < 1) - return; -/* - * Initialize the comparison strings with the first match. - */ - completion = matches[0].completion; - type_suffix = matches[0].type_suffix; -/* - * Go through the array of matches, copying each new unrecorded - * match at the head of the array, while discarding duplicates. - */ - for(src=dst=1; src<nmatch; src++) { - CplMatch *match = matches + src; - if(strcmp(completion, match->completion) != 0 || - strcmp(type_suffix, match->type_suffix) != 0) { - if(src != dst) - matches[dst] = *match; - dst++; - completion = match->completion; - type_suffix = match->type_suffix; - }; - }; -/* - * Record the number of unique matches that remain. - */ - cpl->result.nmatch = dst; - return; -} diff --git a/libtecla-1.4.1/demo.c b/libtecla-1.4.1/demo.c deleted file mode 100644 index 8bee92d..0000000 --- a/libtecla-1.4.1/demo.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2000, 2001 by the California Institute of Technology. - * - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL - * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <ctype.h> -#include <string.h> -#include <errno.h> -#include <locale.h> - -#include <unistd.h> -#include <sys/stat.h> - -#include "libtecla.h" - -int main(int argc, char *argv[]) -{ - char *line; /* A line of input */ - GetLine *gl; /* The line editor */ - int major,minor,micro; /* The version number of the library */ -/* - * Create the line editor, specifying a max line length of 500 bytes, - * and 10000 bytes to allocate to storage of historical input lines. - */ - gl = new_GetLine(500, 5000); - if(!gl) - return 1; -/* - * If the user has the LC_CTYPE or LC_ALL environment variables set, - * enable display of characters corresponding to the specified locale. - */ - (void) setlocale(LC_CTYPE, ""); -/* - * Lookup and display the version number of the library. - */ - libtecla_version(&major, &minor, µ); - printf("Welcome to the demo program of libtecla version %d.%d.%d\n", - major, minor, micro); -/* - * Load history. - */ - (void) gl_load_history(gl, "~/.demo_history", "#"); -/* - * Read lines of input from the user and print them to stdout. - */ - do { -/* - * Get a new line from the user. - */ - line = gl_get_line(gl, "$ ", NULL, 0); - if(!line) - break; -/* - * Display what was entered. - */ - if(printf("You entered: %s", line) < 0 || fflush(stdout)) - break; -/* - * If the user types "exit", quit the program. - */ - if(strcmp(line, "exit\n")==0) - break; - else if(strcmp(line, "history\n")==0) - gl_show_history(gl, stdout, "%N %T %H\n", 0, -1); - else if(strcmp(line, "size\n")==0) { - GlTerminalSize size = gl_terminal_size(gl, 80, 24); - printf("Terminal size = %d columns x %d lines.\n", size.ncolumn, - size.nline); - }; - } while(1); -/* - * Save historical command lines. - */ - (void) gl_save_history(gl, "~/.demo_history", "#", -1); -/* - * Clean up. - */ - gl = del_GetLine(gl); - return 0; -} - diff --git a/libtecla-1.4.1/demo2.c b/libtecla-1.4.1/demo2.c deleted file mode 100644 index e1e80c6..0000000 --- a/libtecla-1.4.1/demo2.c +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Copyright (c) 2000, 2001 by Martin C. Shepherd. - * - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL - * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <ctype.h> -#include <string.h> -#include <errno.h> -#include <locale.h> - -#include <unistd.h> -#include <sys/stat.h> - -#include "libtecla.h" - -/* - * Encapsulate the resources needed by this demo. - */ -typedef struct { - GetLine *gl; /* The line editor */ - PathCache *pc; /* A cache of executables in the user's path */ - PcaPathConf *ppc; /* The configuration argument of pca_path_completions() */ -} DemoRes; - -/* - * The following functions allocate and free instances of the above - * structure. - */ -static DemoRes *new_DemoRes(void); -static DemoRes *del_DemoRes(DemoRes *res); - -/* - * Search backwards for the start of a pathname. - */ -static char *start_of_path(const char *string, int back_from); - -/* - * Find the array indexes of the first character of the first - * space-delimited word in the specified string, and of the character - * that follows it. - */ -static int get_word_limits(const char *string, int *wa, int *wb); - -/* - * This is the demonstration completion callback function (defined below). - */ -static CPL_MATCH_FN(demo_cpl_fn); - -/*....................................................................... - * This demo takes no arguments. It reads lines of input until the - * word 'exit' is entered, or C-d is pressed. It replaces the default - * tab-completion callback with one which when invoked at the start of - * a line, looks up completions of commands in the user's execution - * path, and when invoked in other parts of the line, reverts to - * normal filename completion. Whenever a new line is entered, it - * extracts the first word on the line, looks it up in the user's - * execution path to see if it corresponds to a known executable file, - * and if so, displays the full pathname of the file, along with the - * remaining arguments. - */ -int main(int argc, char *argv[]) -{ - char *line; /* A line of input */ - DemoRes *res; /* The resources of the demo */ - int wa,wb; /* The delimiting indexes of a word in line[] */ - int major,minor,micro; /* The version number of the library */ -/* - * Allocate the resources needed by this demo. - */ - res = new_DemoRes(); - if(!res) - return 1; -/* - * If the user has the LC_CTYPE or LC_ALL environment variables set, - * enable display of characters corresponding to the specified locale. - */ - (void) setlocale(LC_CTYPE, ""); -/* - * Lookup and display the version number of the library. - */ - libtecla_version(&major, &minor, µ); - printf("Welcome to the demo2 program of libtecla version %d.%d.%d\n", - major, minor, micro); -/* - * Read lines of input from the user and print them to stdout. - */ - do { -/* - * Get a new line from the user. - */ - line = gl_get_line(res->gl, "$ ", NULL, 0); - if(!line) - break; -/* - * Work out the extent of the first word in the input line, and - * try to identify this as a command in the path, displaying the - * full pathname of the match if found. - */ - if(get_word_limits(line, &wa, &wb) == 0) { - char *cmd = pca_lookup_file(res->pc, line + wa, wb-wa, 0); - if(cmd) { - printf("Command=%s\n", cmd); - printf("Arguments=%s", line+wb); - } else { - printf("Command not found\n"); - }; - }; -/* - * If the user types "exit", quit the program. - */ - if(strcmp(line, "exit\n")==0) - break; - } while(1); -/* - * Clean up. - */ - res = del_DemoRes(res); - return 0; -} - -/*....................................................................... - * This completion callback searches for completions of executables in - * the user's path when invoked on a word at the start of the path, and - * performs normal filename completion elsewhere. - */ -static CPL_MATCH_FN(demo_cpl_fn) -{ -/* - * Get the resource object that was passed to gl_customize_completion(). - */ - DemoRes *res = (DemoRes *) data; -/* - * Find the start of the filename prefix to be completed, searching - * backwards for the first unescaped space, or the start of the line. - */ - char *start = start_of_path(line, word_end); -/* - * Skip spaces preceding the start of the prefix. - */ - while(start > line && isspace((int)(unsigned char) start[-1])) - start--; -/* - * If the filename prefix is at the start of the line, attempt - * to complete the filename as a command in the path. Otherwise - * perform normal filename completion. - */ - return (start == line) ? - pca_path_completions(cpl, res->ppc, line, word_end) : - cpl_file_completions(cpl, NULL, line, word_end); -} - -/*....................................................................... - * Search backwards for the potential start of a filename. This - * looks backwards from the specified index in a given string, - * stopping at the first unescaped space or the start of the line. - * - * Input: - * string const char * The string to search backwards in. - * back_from int The index of the first character in string[] - * that follows the pathname. - * Output: - * return char * The pointer to the first character of - * the potential pathname, or NULL on error. - */ -static char *start_of_path(const char *string, int back_from) -{ - int i, j; -/* - * Search backwards from the specified index. - */ - for(i=back_from-1; i>=0; i--) { - int c = string[i]; -/* - * Stop on unescaped spaces. - */ - if(isspace((int)(unsigned char)c)) { -/* - * The space can't be escaped if we are at the start of the line. - */ - if(i==0) - break; -/* - * Find the extent of the escape characters which precedes the space. - */ - for(j=i-1; j>=0 && string[j]=='\\'; j--) - ; -/* - * If there isn't an odd number of escape characters before the space, - * then the space isn't escaped. - */ - if((i - 1 - j) % 2 == 0) - break; - }; - }; - return (char *)string + i + 1; -} - -/*....................................................................... - * Create a new DemoRes object containing the resources needed by the - * demo. - * - * Output: - * return DemoRes * The new object, or NULL on error. - */ -static DemoRes *new_DemoRes(void) -{ - DemoRes *res; /* The object to be returned */ -/* - * Allocate the container. - */ - res = (DemoRes *)malloc(sizeof(DemoRes)); - if(!res) { - fprintf(stderr, "new_DemoRes: Insufficient memory.\n"); - return NULL; - }; -/* - * Before attempting any operation that might fail, initialize the - * container at least up to the point at which it can safely be passed - * to del_DemoRes(). - */ - res->gl = NULL; - res->pc = NULL; - res->ppc = NULL; -/* - * Create the line editor, specifying a max line length of 500 bytes, - * and 10000 bytes to allocate to storage of historical input lines. - */ - res->gl = new_GetLine(500, 10000); - if(!res->gl) - return del_DemoRes(res); -/* - * Enable text attribute formatting directives in prompt strings. - */ - gl_prompt_style(res->gl, GL_FORMAT_PROMPT); -/* - * Allocate a cache of the executable files found in the user's path. - */ - res->pc = new_PathCache(); - if(!res->pc) - return del_DemoRes(res); -/* - * Populate the cache with the contents of the user's path. - */ - if(pca_scan_path(res->pc, getenv("PATH"))) - return del_DemoRes(res); -/* - * Arrange for susequent calls to pca_lookup_file() and pca_path_completions() - * to only report files that are executable by the user. - */ - pca_set_check_fn(res->pc, cpl_check_exe, NULL); -/* - * Allocate a configuration object for use with pca_path_completions(). - */ - res->ppc = new_PcaPathConf(res->pc); - if(!res->ppc) - return del_DemoRes(res); -/* - * Replace the builtin filename completion callback with one which - * searches for completions of executables in the user's path when - * invoked on a word at the start of the path, and completes files - * elsewhere. - */ - if(gl_customize_completion(res->gl, res, demo_cpl_fn)) - return del_DemoRes(res); - return res; -} - -/*....................................................................... - * Delete a DemoRes object. - * - * Input: - * res DemoRes * The object to be deleted. - * Output: - * return DemoRes * The deleted object (always NULL). - */ -static DemoRes *del_DemoRes(DemoRes *res) -{ - if(res) { - res->gl = del_GetLine(res->gl); - res->pc = del_PathCache(res->pc); - res->ppc = del_PcaPathConf(res->ppc); - free(res); - }; - return NULL; -} - -/*....................................................................... - * Return the limits of the word at the start of a given string, ignoring - * leading white-space, and interpretting the first unescaped space, tab or - * the end of the line, as the end of the word. - * - * Input: - * string const char * The string to tokenize. - * Input/Output: - * wa,wb int * The indexes of the first character of the word, - * and the character which follows the last - * character of the word, will be assigned to - * *wa and *wb, respectively. - * Output: - * return int 0 - A word was found. - * 1 - No word was found before the end of the - * string. - */ -static int get_word_limits(const char *string, int *wa, int *wb) -{ - int escaped = 0; /* True if the next character is escaped */ -/* - * Skip leading white-space. - */ - for(*wa=0; isspace((int)(unsigned char)string[*wa]); (*wa)++) - ; -/* - * Find the first unescaped space, stopping early if the end of the - * string is reached. - */ - for(*wb = *wa; ; (*wb)++) { - int c = string[*wb]; - if(c=='\\') - escaped = !escaped; - else if((!escaped && isspace((int)(unsigned char)c)) || c=='\0') - break; - }; - return *wa == *wb; -} diff --git a/libtecla-1.4.1/direader.c b/libtecla-1.4.1/direader.c deleted file mode 100644 index 8a81fbf..0000000 --- a/libtecla-1.4.1/direader.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright (c) 2000, 2001 by Martin C. Shepherd. - * - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL - * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - */ - -/* - * Standard includes. - */ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -/* - * Operating system includes. - */ -#include <unistd.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <dirent.h> - -#include "direader.h" - -/* - * Use the reentrant POSIX threads version of readdir()? - */ -#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199506L -#define USE_READDIR_R 1 -#endif - -/* - * Set the max length of the error-reporting string. There is no point - * in this being longer than the width of a typical terminal window. - * In composing error messages, I have assumed that this number is - * at least 80, so you don't decrease it below this number. - */ -#define ERRLEN 200 - -/* - * Objects of the following type are used to maintain the resources - * needed to read directories. - */ -struct DirReader { - DIR *dir; /* The directory stream (if open, NULL otherwise) */ - struct dirent *file; /* The latest directory entry */ - char errmsg[ERRLEN+1]; /* Error-report buffer */ -#ifdef USE_READDIR_R - struct dirent *buffer; /* A buffer used by the threaded version of readdir */ - int buffer_dim; /* The allocated size of buffer[] */ -#endif -}; - -static int _dr_path_is_dir(const char *pathname); - -/*....................................................................... - * Create a new DirReader object. - * - * Output: - * return DirReader * The new object, or NULL on error. - */ -DirReader *_new_DirReader(void) -{ - DirReader *dr; /* The object to be returned */ -/* - * Allocate the container. - */ - dr = (DirReader *) malloc(sizeof(DirReader)); - if(!dr) { - fprintf(stderr, "_new_DirReader: Insufficient memory.\n"); - return NULL; - }; -/* - * Before attempting any operation that might fail, initialize the - * container at least up to the point at which it can safely be passed - * to _del_DirReader(). - */ - dr->dir = NULL; - dr->file = NULL; - dr->errmsg[0] = '\0'; -#ifdef USE_READDIR_R - dr->buffer = NULL; - dr->buffer_dim = 0; -#endif - return dr; -} - -/*....................................................................... - * Delete a DirReader object. - * - * Input: - * dr DirReader * The object to be deleted. - * Output: - * return DirReader * The deleted object (always NULL). - */ -DirReader *_del_DirReader(DirReader *dr) -{ - if(dr) { - _dr_close_dir(dr); -#ifdef USE_READDIR_R - free(dr->buffer); -#endif - free(dr); - }; - return NULL; -} - -/*....................................................................... - * Open a new directory. - * - * Input: - * dr DirReader * The directory reader resource object. - * path const char * The directory to be opened. - * Input/Output: - * errmsg char ** If an error occurs and errmsg isn't NULL, a - * pointer to an error description will be assigned - * to *errmsg. - * Output: - * return int 0 - OK. - * 1 - Error (see *errmsg for a description). - */ -int _dr_open_dir(DirReader *dr, const char *path, char **errmsg) -{ - DIR *dir = NULL; /* The directory stream */ -/* - * If a directory is already open, close it first. - */ - (void) _dr_close_dir(dr); -/* - * Is the path a directory? - */ - if(!_dr_path_is_dir(path)) { - if(errmsg) { - const char *fmt = "Can't open directory: %.*s\n"; - sprintf(dr->errmsg, fmt, ERRLEN - strlen(fmt), path); - *errmsg = dr->errmsg; - }; - return 1; - }; -/* - * Attempt to open the directory. - */ - dir = opendir(path); - if(!dir) { - if(errmsg) { - const char *fmt = "Can't open directory: %.*s\n"; - sprintf(dr->errmsg, fmt, ERRLEN - strlen(fmt), path); - *errmsg = dr->errmsg; - }; - return 1; - }; -/* - * If using POSIX threads, allocate a buffer for readdir_r(). - */ -#ifdef USE_READDIR_R - { - size_t size; - int name_max = pathconf(path, _PC_NAME_MAX); -#ifdef NAME_MAX - if(name_max < 0) - name_max = NAME_MAX; -#endif - if(name_max < 0) { - if(errmsg) { - strcpy(dr->errmsg, "Unable to deduce readdir() buffer size."); - *errmsg = dr->errmsg; - }; - closedir(dir); - return 1; - }; -/* - * How big a buffer do we need to allocate? - */ - size = sizeof(struct dirent) + name_max; -/* - * Extend the buffer? - */ - if(size > dr->buffer_dim || !dr->buffer) { - struct dirent *buffer = (struct dirent *) (dr->buffer ? - realloc(dr->buffer, size) : - malloc(size)); - if(!buffer) { - if(errmsg) { - strcpy(dr->errmsg, "Insufficient memory for readdir() buffer."); - *errmsg = dr->errmsg; - }; - closedir(dir); - return 1; - }; - dr->buffer = buffer; - dr->buffer_dim = size; - }; - }; -#endif -/* - * Record the successfully opened directory. - */ - dr->dir = dir; - return 0; -} - -/*....................................................................... - * If the DirReader object is currently contains an open directory, - * close it. - * - * Input: - * dr DirReader * The directory reader resource object. - */ -void _dr_close_dir(DirReader *dr) -{ - if(dr && dr->dir) { - closedir(dr->dir); - dr->dir = NULL; - dr->file = NULL; - dr->errmsg[0] = '\0'; - }; -} - -/*....................................................................... - * Read the next file from the directory opened with _dr_open_dir(). - * - * Input: - * dr DirReader * The directory reader resource object. - * Output: - * return char * The name of the new file, or NULL if we reached - * the end of the directory. - */ -char *_dr_next_file(DirReader *dr) -{ -/* - * Are we currently reading a directory? - */ - if(dr->dir) { -/* - * Read the next directory entry. - */ -#ifdef USE_READDIR_R - if(readdir_r(dr->dir, dr->buffer, &dr->file) == 0 && dr->file) - return dr->file->d_name; -#else - dr->file = readdir(dr->dir); - if(dr->file) - return dr->file->d_name; -#endif - }; -/* - * When the end of a directory is reached, close it. - */ - _dr_close_dir(dr); - return NULL; -} - -/*....................................................................... - * Return 1 if the specified pathname refers to a directory. - * - * Input: - * pathname const char * The path to test. - * Output: - * return int 0 - Not a directory. - * 1 - pathname[] refers to a directory. - */ -static int _dr_path_is_dir(const char *pathname) -{ - struct stat statbuf; /* The file-statistics return buffer */ -/* - * Look up the file attributes. - */ - if(stat(pathname, &statbuf) < 0) - return 0; -/* - * Is the file a directory? - */ - return S_ISDIR(statbuf.st_mode) != 0; -} diff --git a/libtecla-1.4.1/direader.h b/libtecla-1.4.1/direader.h deleted file mode 100644 index 2cf178e..0000000 --- a/libtecla-1.4.1/direader.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef dirreader_h -#define dirreader_h - -/* - * Copyright (c) 2000, 2001 by Martin C. Shepherd. - * - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL - * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - */ - -typedef struct DirReader DirReader; - -DirReader *_new_DirReader(void); -DirReader *_del_DirReader(DirReader *dr); - -int _dr_open_dir(DirReader *dr, const char *pathname, char **errmsg); -char *_dr_next_file(DirReader *dr); -void _dr_close_dir(DirReader *dr); - -#endif diff --git a/libtecla-1.4.1/enhance.c b/libtecla-1.4.1/enhance.c deleted file mode 100644 index 72f5061..0000000 --- a/libtecla-1.4.1/enhance.c +++ /dev/null @@ -1,689 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <signal.h> -#include <locale.h> - -#include <unistd.h> -#include <termios.h> - -#include <fcntl.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <dirent.h> - -#if HAVE_SYSV_PTY -#include <stropts.h> /* System-V stream I/O */ -char *ptsname(int fd); -int grantpt(int fd); -int unlockpt(int fd); -#endif - -#include "libtecla.h" - -/* - * Pseudo-terminal devices are found in the following directory. - */ -#define PTY_DEV_DIR "/dev/" - -/* - * Pseudo-terminal controller device file names start with the following - * prefix. - */ -#define PTY_CNTRL "pty" - -/* - * Pseudo-terminal slave device file names start with the following - * prefix. - */ -#define PTY_SLAVE "tty" - -/* - * Specify the maximum suffix length for the control and slave device - * names. - */ -#define PTY_MAX_SUFFIX 10 - -/* - * Set the maximum length of the master and slave terminal device filenames, - * including space for a terminating '\0'. - */ -#define PTY_MAX_NAME (sizeof(PTY_DEV_DIR)-1 + \ - (sizeof(PTY_SLAVE) > sizeof(PTY_CNTRL) ? \ - sizeof(PTY_SLAVE) : sizeof(PTY_CNTRL))-1 \ - + PTY_MAX_SUFFIX + 1) -/* - * Set the maximum length of an input line. - */ -#define PTY_MAX_LINE 4096 - -/* - * Set the size of the buffer used for accumulating bytes written by the - * user's terminal to its stdout. - */ -#define PTY_MAX_READ 1000 - -/* - * Set the amount of memory used to record history. - */ -#define PTY_HIST_SIZE 10000 - -/* - * Set the timeout delay used to check for quickly arriving - * sequential output from the application. - */ -#define PTY_READ_TIMEOUT 100000 /* micro-seconds */ - -static int pty_open_master(const char *prog, int *cntrl, char *slave_name); -static int pty_open_slave(const char *prog, char *slave_name); -static int pty_child(const char *prog, int slave, char *argv[]); -static int pty_parent(const char *prog, int cntrl); -static int pty_stop_parent(int waserr, int cntrl, GetLine *gl, char *rbuff); -static GL_FD_EVENT_FN(pty_read_from_program); -static int pty_write_to_fd(int fd, const char *string, int n); -static void pty_child_exited(int sig); -static int pty_master_readable(int fd, long usec); - -/*....................................................................... - * Run a program with enhanced terminal editing facilities. - * - * Usage: - * enhance program [args...] - */ -int main(int argc, char *argv[]) -{ - int cntrl = -1; /* The fd of the pseudo-terminal controller device */ - int slave = -1; /* The fd of the pseudo-terminal slave device */ - pid_t pid; /* The return value of fork() */ - int status; /* The return statuses of the parent and child functions */ - char slave_name[PTY_MAX_NAME]; /* The filename of the slave end of the */ - /* pseudo-terminal. */ - char *prog; /* The name of the program (ie. argv[0]) */ -/* - * Check the arguments. - */ - if(argc < 2) { - fprintf(stderr, "Usage: %s <program> [arguments...]\n", argv[0]); - return 1; - }; -/* - * Get the name of the program. - */ - prog = argv[0]; -/* - * If the user has the LC_CTYPE or LC_ALL environment variables set, - * enable display of characters corresponding to the specified locale. - */ - (void) setlocale(LC_CTYPE, ""); -/* - * If the program is taking its input from a pipe or a file, or - * sending its output to something other than a terminal, run the - * program without tecla. - */ - if(!isatty(STDIN_FILENO) || !isatty(STDOUT_FILENO)) { - if(execvp(argv[1], argv + 1) < 0) { - fprintf(stderr, "%s: Unable to execute %s (%s).\n", prog, argv[1], - strerror(errno)); - fflush(stderr); - _exit(1); - }; - }; -/* - * Open the master side of a pseudo-terminal pair, and return - * the corresponding file descriptor and the filename of the - * slave end of the pseudo-terminal. - */ - if(pty_open_master(prog, &cntrl, slave_name)) - return 1; -/* - * Set up a signal handler to watch for the child process exiting. - */ - signal(SIGCHLD, pty_child_exited); -/* - * The above signal handler sends the parent process a SIGINT signal. - * This signal is caught by gl_get_line(), which resets the terminal - * settings, and if the application signal handler for this signal - * doesn't abort the process, gl_get_line() returns NULL with errno - * set to EINTR. Arrange to ignore the signal, so that gl_get_line() - * returns and we have a chance to cleanup. - */ - signal(SIGINT, SIG_IGN); -/* - * We will read user input in one process, and run the user's program - * in a child process. - */ - pid = fork(); - if(pid < 0) { - fprintf(stderr, "%s: Unable to fork child process (%s).\n", prog, - strerror(errno)); - return 1; - }; -/* - * Are we the parent? - */ - if(pid!=0) { - status = pty_parent(prog, cntrl); - close(cntrl); - } else { - close(cntrl); /* The child doesn't use the slave device */ - signal(SIGCHLD, pty_child_exited); - if((slave = pty_open_slave(prog, slave_name)) >= 0) { - status = pty_child(prog, slave, argv + 1); - close(slave); - } else { - status = 1; - }; - }; - return status; -} - -/*....................................................................... - * Open the master side of a pseudo-terminal pair, and return - * the corresponding file descriptor and the filename of the - * slave end of the pseudo-terminal. - * - * Input/Output: - * prog const char * The name of this program. - * cntrl int * The file descriptor of the pseudo-terminal - * controller device will be assigned tp *cntrl. - * slave_name char * The file-name of the pseudo-terminal slave device - * will be recorded in slave_name[], which must have - * at least PTY_MAX_NAME elements. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int pty_open_master(const char *prog, int *cntrl, char *slave_name) -{ - char master_name[PTY_MAX_NAME]; /* The filename of the master device */ - DIR *dir; /* The directory iterator */ - struct dirent *file; /* A file in "/dev" */ -/* - * Mark the controller device as not opened yet. - */ - *cntrl = -1; -/* - * On systems with the Sys-V pseudo-terminal interface, we don't - * have to search for a free master terminal. We just open /dev/ptmx, - * and if there is a free master terminal device, we are given a file - * descriptor connected to it. - */ -#if HAVE_SYSV_PTY - *cntrl = open("/dev/ptmx", O_RDWR); - if(*cntrl >= 0) { -/* - * Get the filename of the slave side of the pseudo-terminal. - */ - char *name = ptsname(*cntrl); - if(name) { - if(strlen(name)+1 > PTY_MAX_NAME) { - fprintf(stderr, "%s: Slave pty filename too long.\n", prog); - return 1; - }; - strcpy(slave_name, name); -/* - * If unable to get the slave name, discard the controller file descriptor, - * ready to try a search instead. - */ - } else { - close(*cntrl); - *cntrl = -1; - }; - } else { -#endif -/* - * On systems without /dev/ptmx, or if opening /dev/ptmx failed, - * we open one master terminal after another, until one that isn't - * in use by another program is found. - * - * Open the devices directory. - */ - dir = opendir(PTY_DEV_DIR); - if(!dir) { - fprintf(stderr, "%s: Couldn't open %s (%s)\n", prog, PTY_DEV_DIR, - strerror(errno)); - return 1; - }; -/* - * Look for pseudo-terminal controller device files in the devices - * directory. - */ - while(*cntrl < 0 && (file = readdir(dir))) { - if(strncmp(file->d_name, PTY_CNTRL, sizeof(PTY_CNTRL)-1) == 0) { -/* - * Get the common extension of the control and slave filenames. - */ - const char *ext = file->d_name + sizeof(PTY_CNTRL)-1; - if(strlen(ext) > PTY_MAX_SUFFIX) - continue; -/* - * Attempt to open the control file. - */ - strcpy(master_name, PTY_DEV_DIR); - strcat(master_name, PTY_CNTRL); - strcat(master_name, ext); - *cntrl = open(master_name, O_RDWR); - if(*cntrl < 0) - continue; -/* - * Attempt to open the matching slave file. - */ - strcpy(slave_name, PTY_DEV_DIR); - strcat(slave_name, PTY_SLAVE); - strcat(slave_name, ext); - }; - }; - closedir(dir); -#if HAVE_SYSV_PTY - }; -#endif -/* - * Did we fail to find a pseudo-terminal pair that we could open? - */ - if(*cntrl < 0) { - fprintf(stderr, "%s: Unable to find a free pseudo-terminal.\n", prog); - return 1; - }; -/* - * System V systems require the program that opens the master to - * grant access to the slave side of the pseudo-terminal. - */ -#ifdef HAVE_SYSV_PTY - if(grantpt(*cntrl) < 0 || - unlockpt(*cntrl) < 0) { - fprintf(stderr, "%s: Unable to unlock terminal (%s).\n", prog, - strerror(errno)); - return 1; - }; -#endif -/* - * Success. - */ - return 0; -} - -/*....................................................................... - * Open the slave end of a pseudo-terminal. - * - * Input: - * prog const char * The name of this program. - * slave_name char * The filename of the slave device. - * Output: - * return int The file descriptor of the successfully opened - * slave device, or < 0 on error. - */ -static int pty_open_slave(const char *prog, char *slave_name) -{ - int fd; /* The file descriptor of the slave device */ -/* - * Place the process in its own process group. In system-V based - * OS's, this ensures that when the pseudo-terminal is opened, it - * becomes the controlling terminal of the process. - */ - if(setsid() < 0) { - fprintf(stderr, "%s: Unable to form new process group (%s).\n", prog, - strerror(errno)); - return -1; - }; -/* - * Attempt to open the specified device. - */ - fd = open(slave_name, O_RDWR); - if(fd < 0) { - fprintf(stderr, "%s: Unable to open pseudo-terminal slave device (%s).\n", - prog, strerror(errno)); - return -1; - }; -/* - * On system-V streams based systems, we need to push the stream modules - * that implement pseudo-terminal and termio interfaces. At least on - * Solaris, which pushes these automatically when a slave is opened, - * this is redundant, so ignore errors when pushing the modules. - */ -#if HAVE_SYSV_PTY - (void) ioctl(fd, I_PUSH, "ptem"); - (void) ioctl(fd, I_PUSH, "ldterm"); -/* - * On BSD based systems other than SunOS 4.x, the following makes the - * pseudo-terminal the controlling terminal of the child process. - * According to the pseudo-terminal example code in Steven's - * Advanced programming in the unix environment, the !defined(CIBAUD) - * part of the clause prevents this from being used under SunOS. Since - * I only have his code with me, and won't have access to the book, - * I don't know why this is necessary. - */ -#elif defined(TIOCSCTTY) && !defined(CIBAUD) - if(ioctl(fd, TIOCSCTTY, (char *) 0) < 0) { - fprintf(stderr, "%s: Unable to establish controlling terminal (%s).\n", - prog, strerror(errno)); - close(fd); - return -1; - }; -#endif - return fd; -} - -/*....................................................................... - * Read input from the controlling terminal of the program, using - * gl_get_line(), and feed it to the user's program running in a child - * process, via the controller side of the pseudo-terminal. Also pass - * data received from the user's program via the conroller end of - * the pseudo-terminal, to stdout. - * - * Input: - * prog const char * The name of this program. - * cntrl int The file descriptor of the controller end of the - * pseudo-terminal. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int pty_parent(const char *prog, int cntrl) -{ - GetLine *gl = NULL; /* The gl_get_line() resource object */ - char *line; /* An input line read from the user */ - char *rbuff=NULL; /* A buffer for reading from the pseudo terminal */ -/* - * Allocate the gl_get_line() resource object. - */ - gl = new_GetLine(PTY_MAX_LINE, PTY_HIST_SIZE); - if(!gl) - return pty_stop_parent(1, cntrl, gl, rbuff); -/* - * Allocate a buffer to use to accumulate bytes read from the - * pseudo-terminal. - */ - rbuff = (char *) malloc(PTY_MAX_READ+1); - if(!rbuff) - return pty_stop_parent(1, cntrl, gl, rbuff); - rbuff[0] = '\0'; -/* - * Register an event handler to watch for data appearing from the - * user's program on the controller end of the pseudo terminal. - */ - if(gl_watch_fd(gl, cntrl, GLFD_READ, pty_read_from_program, rbuff)) - return pty_stop_parent(1, cntrl, gl, rbuff); -/* - * Read input lines from the user and pass them on to the user's program, - * by writing to the controller end of the pseudo-terminal. - */ - while((line=gl_get_line(gl, rbuff, NULL, 0))) { - if(pty_write_to_fd(cntrl, line, strlen(line))) - return pty_stop_parent(1, cntrl, gl, rbuff); - rbuff[0] = '\0'; - }; - return pty_stop_parent(0, cntrl, gl, rbuff); -} - -/*....................................................................... - * This is a private return function of pty_parent(), used to release - * dynamically allocated resources, close the controller end of the - * pseudo-terminal, and wait for the child to exit. It returns the - * exit status of the child process, unless the caller reports an - * error itself, in which case the caller's error status is returned. - * - * Input: - * waserr int True if the caller is calling this function because - * an error occured. - * cntrl int The file descriptor of the controller end of the - * pseudo-terminal. - * gl GetLine * The resource object of gl_get_line(). - * rbuff char * The buffer used to accumulate bytes read from - * the pseudo-terminal. - * Output: - * return int The desired exit status of the program. - */ -static int pty_stop_parent(int waserr, int cntrl, GetLine *gl, char *rbuff) -{ - int status; /* The return status of the child process */ -/* - * Close the controller end of the terminal. - */ - close(cntrl); -/* - * Delete the resource object. - */ - gl = del_GetLine(gl); -/* - * Delete the read buffer. - */ - if(rbuff) - free(rbuff); -/* - * Wait for the user's program to end. - */ - (void) wait(&status); -/* - * Return either our error status, or the return status of the child - * program. - */ - return waserr ? 1 : status; -} - -/*....................................................................... - * Run the user's program, with its stdin and stdout connected to the - * slave end of the psuedo-terminal. - * - * Input: - * prog const char * The name of this program. - * slave int The file descriptor of the slave end of the - * pseudo terminal. - * argv char *[] The argument vector to pass to the user's program, - * where argv[0] is the name of the user's program, - * and the last argument is followed by a pointer - * to NULL. - * Output: - * return int If this function returns at all, an error must - * have occured when trying to overlay the process - * with the user's program. In this case 1 is - * returned. - */ -static int pty_child(const char *prog, int slave, char *argv[]) -{ - struct termios attr; /* The terminal attributes */ -/* - * We need to stop the pseudo-terminal from echoing everything that we send it. - */ - if(tcgetattr(slave, &attr)) { - fprintf(stderr, "%s: Can't get pseudo-terminal attributes (%s).\n", prog, - strerror(errno)); - return 1; - }; - attr.c_lflag &= ~(ECHO); - while(tcsetattr(slave, TCSADRAIN, &attr)) { - if(errno != EINTR) { - fprintf(stderr, "%s: tcsetattr error: %s\n", prog, strerror(errno)); - return 1; - }; - }; -/* - * Arrange for stdin, stdout and stderr to be connected to the slave device, - * ignoring errors that imply that either stdin or stdout is closed. - */ - while(dup2(slave, STDIN_FILENO) < 0 && errno==EINTR) - ; - while(dup2(slave, STDOUT_FILENO) < 0 && errno==EINTR) - ; - while(dup2(slave, STDERR_FILENO) < 0 && errno==EINTR) - ; -/* - * Run the user's program. - */ - if(execvp(argv[0], argv) < 0) { - fprintf(stderr, "%s: Unable to execute %s (%s).\n", prog, argv[0], - strerror(errno)); - fflush(stderr); - _exit(1); - }; - return 0; /* This should never be reached */ -} - -/*....................................................................... - * This is the event-handler that is called by gl_get_line() whenever - * there is tet waiting to be read from the user's program, via the - * controller end of the pseudo-terminal. See libtecla.h for details - * about its arguments. - */ -static GL_FD_EVENT_FN(pty_read_from_program) -{ - char *nlptr; /* A pointer to the last newline in the accumulated string */ - char *crptr; /* A pointer to the last '\r' in the accumulated string */ - char *nextp; /* A pointer to the next unprocessed character */ -/* - * Get the read buffer in which we are accumulating a line to be - * forwarded to stdout. - */ - char *rbuff = (char *) data; -/* - * New data may arrive while we are processing the current read, and - * it is more efficient to display this here than to keep returning to - * gl_get_line() and have it display the latest prefix as a prompt, - * followed by the current input line, so we loop, delaying a bit at - * the end of each iteration to check for more data arriving from - * the application, before finally returning to gl_get_line() when - * no more input is available. - */ - do { -/* - * Get the current length of the output string. - */ - int len = strlen(rbuff); -/* - * Read the text from the program. - */ - int nnew = read(fd, rbuff + len, PTY_MAX_READ - len); - if(nnew < 0) - return GLFD_ABORT; - len += nnew; -/* - * Nul terminate the accumulated string. - */ - rbuff[len] = '\0'; -/* - * Find the last newline and last carriage return in the buffer, if any. - */ - nlptr = strrchr(rbuff, '\n'); - crptr = strrchr(rbuff, '\r'); -/* - * We want to output up to just before the last newline or carriage - * return. If there are no newlines of carriage returns in the line, - * and the buffer is full, then we should output the whole line. In - * all cases a new output line will be started after the latest text - * has been output. The intention is to leave any incomplete line - * in the buffer, for (perhaps temporary) use as the current prompt. - */ - if(nlptr) { - nextp = crptr && crptr < nlptr ? crptr : nlptr; - } else if(crptr) { - nextp = crptr; - } else if(len >= PTY_MAX_READ) { - nextp = rbuff + len; - } else { - nextp = NULL; - }; -/* - * Do we have any text to output yet? - */ - if(nextp) { -/* - * If there was already some text in rbuff before this function - * was called, then it will have been used as a prompt. Arrange - * to rewrite this prefix, plus the new suffix, by moving back to - * the start of the line. - */ - if(len > 0) - (void) pty_write_to_fd(STDOUT_FILENO, "\r", 1); -/* - * Write everything up to the last newline to stdout. - */ - (void) pty_write_to_fd(STDOUT_FILENO, rbuff, nextp - rbuff); -/* - * Start a new line. - */ - (void) pty_write_to_fd(STDOUT_FILENO, "\r\n", 2); -/* - * Skip trailing carriage returns and newlines. - */ - while(*nextp=='\n' || *nextp=='\r') - nextp++; -/* - * Move any unwritten text following the newline, to the start of the - * buffer. - */ - memmove(rbuff, nextp, len - (nextp - rbuff) + 1); - }; - } while(pty_master_readable(fd, PTY_READ_TIMEOUT)); -/* - * Make the incomplete line in the output buffer the current prompt. - */ - gl_replace_prompt(gl, rbuff); - return GLFD_REFRESH; -} - -/*....................................................................... - * Write a given string to a specified file descriptor. - * - * Input: - * fd int The file descriptor to write to. - * string const char * The string to write (of at least 'n' characters). - * n int The number of characters to write. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int pty_write_to_fd(int fd, const char *string, int n) -{ - int ndone = 0; /* The number of characters written so far */ -/* - * Do as many writes as are needed to write the whole string. - */ - while(ndone < n) { - int nnew = write(fd, string + ndone, n - ndone); - if(nnew > 0) - ndone += nnew; - else if(errno != EINTR) - return 1; - }; - return 0; -} - -/*....................................................................... - * This is the signal handler that is called when the child process - * that is running the user's program exits for any reason. It closes - * the slave end of the terminal, so that gl_get_line() in the parent - * process sees an end of file. - */ -static void pty_child_exited(int sig) -{ - raise(SIGINT); -} - -/*....................................................................... - * Return non-zero after a given amount of time if there is data waiting - * to be read from a given file descriptor. - * - * Input: - * fd int The descriptor to watch. - * usec long The number of micro-seconds to wait for input to - * arrive before giving up. - * Output: - * return int 0 - No data is waiting to be read (or select isn't - * available). - * 1 - Data is waiting to be read. - */ -static int pty_master_readable(int fd, long usec) -{ -#if HAVE_SELECT - fd_set rfds; /* The set of file descriptors to check */ - struct timeval timeout; /* The timeout */ - FD_ZERO(&rfds); - FD_SET(fd, &rfds); - timeout.tv_sec = 0; - timeout.tv_usec = usec; - return select(fd+1, &rfds, NULL, NULL, &timeout) == 1; -#else - return 0; -#endif -} diff --git a/libtecla-1.4.1/expand.c b/libtecla-1.4.1/expand.c deleted file mode 100644 index c1600ab..0000000 --- a/libtecla-1.4.1/expand.c +++ /dev/null @@ -1,1265 +0,0 @@ -/* - * Copyright (c) 2000, 2001 by Martin C. Shepherd. - * - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL - * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -#include "freelist.h" -#include "direader.h" -#include "pathutil.h" -#include "homedir.h" -#include "stringrp.h" -#include "libtecla.h" - -/* - * Specify the number of elements to extend the files[] array by - * when it proves to be too small. This also sets the initial size - * of the array. - */ -#define MATCH_BLK_FACT 256 - -/* - * A list of directory iterators is maintained using nodes of the - * following form. - */ -typedef struct DirNode DirNode; -struct DirNode { - DirNode *next; /* The next directory in the list */ - DirNode *prev; /* The node that precedes this node in the list */ - DirReader *dr; /* The directory reader object */ -}; - -typedef struct { - FreeList *mem; /* Memory for DirNode list nodes */ - DirNode *head; /* The head of the list of used and unused cache nodes */ - DirNode *next; /* The next unused node between head and tail */ - DirNode *tail; /* The tail of the list of unused cache nodes */ -} DirCache; - -/* - * Specify how many directory cache nodes to allocate at a time. - */ -#define DIR_CACHE_BLK 20 - -/* - * Set the maximum length allowed for usernames. - */ -#define USR_LEN 100 - -/* - * Set the maximum length allowed for environment variable names. - */ -#define ENV_LEN 100 - -/* - * Set the max length of the error-reporting string. There is no point - * in this being longer than the width of a typical terminal window. - * In composing error messages, I have assumed that this number is - * at least 80, so you don't decrease it below this number. - */ -#define ERRLEN 200 - -struct ExpandFile { - StringGroup *sg; /* A list of string segments in which */ - /* matching filenames are stored. */ - DirCache cache; /* The cache of directory reader objects */ - PathName *path; /* The pathname being matched */ - HomeDir *home; /* Home-directory lookup object */ - int files_dim; /* The allocated dimension of result.files[] */ - char usrnam[USR_LEN+1]; /* A user name */ - char envnam[ENV_LEN+1]; /* An environment variable name */ - char errmsg[ERRLEN+1]; /* Error-report buffer */ - FileExpansion result; /* The container used to return the results of */ - /* expanding a path. */ -}; - -static int ef_record_pathname(ExpandFile *ef, const char *pathname, - int remove_escapes); -static char *ef_cache_pathname(ExpandFile *ef, const char *pathname, - int remove_escapes); -static void ef_clear_files(ExpandFile *ef); - -static DirNode *ef_open_dir(ExpandFile *ef, const char *pathname); -static DirNode *ef_close_dir(ExpandFile *ef, DirNode *node); -static char *ef_expand_special(ExpandFile *ef, const char *path, int pathlen); -static int ef_match_relative_pathname(ExpandFile *ef, DirReader *dr, - const char *pattern, int separate); -static int ef_matches_range(int c, const char *pattern, const char **endp); -static int ef_string_matches_pattern(const char *file, const char *pattern, - int xplicit, const char *nextp); -static int ef_cmp_strings(const void *v1, const void *v2); - -/*....................................................................... - * Create the resources needed to expand filenames. - * - * Output: - * return ExpandFile * The new object, or NULL on error. - */ -ExpandFile *new_ExpandFile(void) -{ - ExpandFile *ef; /* The object to be returned */ -/* - * Allocate the container. - */ - ef = (ExpandFile *) malloc(sizeof(ExpandFile)); - if(!ef) { - fprintf(stderr, "new_ExpandFile: Insufficient memory.\n"); - return NULL; - }; -/* - * Before attempting any operation that might fail, initialize the - * container at least up to the point at which it can safely be passed - * to del_ExpandFile(). - */ - ef->sg = NULL; - ef->cache.mem = NULL; - ef->cache.head = NULL; - ef->cache.next = NULL; - ef->cache.tail = NULL; - ef->path = NULL; - ef->home = NULL; - ef->result.files = NULL; - ef->result.nfile = 0; - ef->usrnam[0] = '\0'; - ef->envnam[0] = '\0'; - ef->errmsg[0] = '\0'; -/* - * Allocate a list of string segments for storing filenames. - */ - ef->sg = _new_StringGroup(_pu_pathname_dim()); - if(!ef->sg) - return del_ExpandFile(ef); -/* - * Allocate a freelist for allocating directory cache nodes. - */ - ef->cache.mem = _new_FreeList("new_ExpandFile", sizeof(DirNode), DIR_CACHE_BLK); - if(!ef->cache.mem) - return del_ExpandFile(ef); -/* - * Allocate a pathname buffer. - */ - ef->path = _new_PathName(); - if(!ef->path) - return del_ExpandFile(ef); -/* - * Allocate an object for looking up home-directories. - */ - ef->home = _new_HomeDir(); - if(!ef->home) - return del_ExpandFile(ef); -/* - * Allocate an array for files. This will be extended later if needed. - */ - ef->files_dim = MATCH_BLK_FACT; - ef->result.files = (char **) malloc(sizeof(ef->result.files[0]) * - ef->files_dim); - if(!ef->result.files) { - fprintf(stderr, - "new_ExpandFile: Insufficient memory to allocate array of files.\n"); - return del_ExpandFile(ef); - }; - return ef; -} - -/*....................................................................... - * Delete a ExpandFile object. - * - * Input: - * ef ExpandFile * The object to be deleted. - * Output: - * return ExpandFile * The deleted object (always NULL). - */ -ExpandFile *del_ExpandFile(ExpandFile *ef) -{ - if(ef) { - DirNode *dnode; -/* - * Delete the string segments. - */ - ef->sg = _del_StringGroup(ef->sg); -/* - * Delete the cached directory readers. - */ - for(dnode=ef->cache.head; dnode; dnode=dnode->next) - dnode->dr = _del_DirReader(dnode->dr); -/* - * Delete the memory from which the DirNode list was allocated, thus - * deleting the list at the same time. - */ - ef->cache.mem = _del_FreeList("del_ExpandFile", ef->cache.mem, 1); - ef->cache.head = ef->cache.tail = ef->cache.next = NULL; -/* - * Delete the pathname buffer. - */ - ef->path = _del_PathName(ef->path); -/* - * Delete the home-directory lookup object. - */ - ef->home = _del_HomeDir(ef->home); -/* - * Delete the array of pointers to files. - */ - if(ef->result.files) { - free(ef->result.files); - ef->result.files = NULL; - }; -/* - * Delete the container. - */ - free(ef); - }; - return NULL; -} - -/*....................................................................... - * Expand a pathname, converting ~user/ and ~/ patterns at the start - * of the pathname to the corresponding home directories, replacing - * $envvar with the value of the corresponding environment variable, - * and then, if there are any wildcards, matching these against existing - * filenames. - * - * If no errors occur, a container is returned containing the array of - * files that resulted from the expansion. If there were no wildcards - * in the input pathname, this will contain just the original pathname - * after expansion of ~ and $ expressions. If there were any wildcards, - * then the array will contain the files that matched them. Note that - * if there were any wildcards but no existing files match them, this - * is counted as an error and NULL is returned. - * - * The supported wildcards and their meanings are: - * * - Match any sequence of zero or more characters. - * ? - Match any single character. - * [chars] - Match any single character that appears in 'chars'. - * If 'chars' contains an expression of the form a-b, - * then any character between a and b, including a and b, - * matches. The '-' character looses its special meaning - * as a range specifier when it appears at the start - * of the sequence of characters. - * [^chars] - The same as [chars] except that it matches any single - * character that doesn't appear in 'chars'. - * - * Wildcard expressions are applied to individual filename components. - * They don't match across directory separators. A '.' character at - * the beginning of a filename component must also be matched - * explicitly by a '.' character in the input pathname, since these - * are UNIX's hidden files. - * - * Input: - * ef ExpandFile * The pathname expansion resource object. - * path char * The path name to be expanded. - * pathlen int The length of the suffix of path[] that - * constitutes the filename to be expanded, - * or -1 to specify that the whole of the - * path string should be used. Note that - * regardless of the value of this argument, - * path[] must contain a '\0' terminated - * string, since this function checks that - * pathlen isn't mistakenly too long. - * Output: - * return FileExpansion * A pointer to a container within the given - * ExpandFile object. This contains an array - * of the pathnames that resulted from expanding - * ~ and $ expressions and from matching any - * wildcards, sorted into lexical order. - * This container and its contents will be - * recycled on subsequent calls, so if you need - * to keep the results of two successive runs, - * you will either have to allocate a private - * copy of the array, or use two ExpandFile - * objects. - * - * On error NULL is returned. A description - * of the error can be acquired by calling the - * ef_last_error() function. - */ -FileExpansion *ef_expand_file(ExpandFile *ef, const char *path, int pathlen) -{ - DirNode *dnode; /* A directory-reader cache node */ - const char *dirname; /* The name of the top level directory of the search */ - const char *pptr; /* A pointer into path[] */ - int wild; /* True if the path contains any wildcards */ -/* - * Check the arguments. - */ - if(!ef || !path) { - if(ef) - strcpy(ef->errmsg, "ef_expand_file: NULL path argument"); - else - fprintf(stderr, "ef_expand_file: NULL argument(s).\n"); - return NULL; - }; -/* - * If the caller specified that the whole of path[] be matched, - * work out the corresponding length. - */ - if(pathlen < 0 || pathlen > strlen(path)) - pathlen = strlen(path); -/* - * Discard previous expansion results. - */ - ef_clear_files(ef); -/* - * Preprocess the path, expanding ~/, ~user/ and $envvar references, - * using ef->path as a work directory and returning a pointer to - * a copy of the resulting pattern in the cache. - */ - path = ef_expand_special(ef, path, pathlen); - if(!path) - return NULL; -/* - * Clear the pathname buffer. - */ - _pn_clear_path(ef->path); -/* - * Does the pathname contain any wildcards? - */ - for(wild=0,pptr=path; !wild && *pptr; pptr++) { - switch(*pptr) { - case '\\': /* Skip escaped characters */ - if(pptr[1]) - pptr++; - break; - case '*': case '?': case '[': /* A wildcard character? */ - wild = 1; - break; - }; - }; -/* - * If there are no wildcards to match, copy the current expanded - * path into the output array, removing backslash escapes while doing so. - */ - if(!wild) { - if(ef_record_pathname(ef, path, 1)) - return NULL; -/* - * Does the filename exist? - */ - ef->result.exists = _pu_file_exists(ef->result.files[0]); -/* - * Match wildcards against existing files. - */ - } else { -/* - * Only existing files that match the pattern will be returned in the - * cache. - */ - ef->result.exists = 1; -/* - * Treat matching of the root-directory as a special case since it - * isn't contained in a directory. - */ - if(strcmp(path, FS_ROOT_DIR) == 0) { - if(ef_record_pathname(ef, FS_ROOT_DIR, 0)) - return NULL; - } else { -/* - * What should the top level directory of the search be? - */ - if(strncmp(path, FS_ROOT_DIR, FS_ROOT_DIR_LEN) == 0) { - dirname = FS_ROOT_DIR; - if(!_pn_append_to_path(ef->path, FS_ROOT_DIR, -1, 0)) { - strcpy(ef->errmsg, "Insufficient memory to record path"); - return NULL; - }; - path += FS_ROOT_DIR_LEN; - } else { - dirname = FS_PWD; - }; -/* - * Open the top-level directory of the search. - */ - dnode = ef_open_dir(ef, dirname); - if(!dnode) - return NULL; -/* - * Recursively match successive directory components of the path. - */ - if(ef_match_relative_pathname(ef, dnode->dr, path, 0)) { - dnode = ef_close_dir(ef, dnode); - return NULL; - }; -/* - * Cleanup. - */ - dnode = ef_close_dir(ef, dnode); - }; -/* - * No files matched? - */ - if(ef->result.nfile < 1) { - strcpy(ef->errmsg, "No files match"); - return NULL; - }; -/* - * Sort the pathnames that matched. - */ - qsort(ef->result.files, ef->result.nfile, sizeof(ef->result.files[0]), - ef_cmp_strings); - }; -/* - * Return the result container. - */ - return &ef->result; -} - -/*....................................................................... - * Attempt to recursively match the given pattern with the contents of - * the current directory, descending sub-directories as needed. - * - * Input: - * ef ExpandFile * The pathname expansion resource object. - * dr DirReader * The directory reader object of the directory - * to be searched. - * pattern const char * The pattern to match with files in the current - * directory. - * separate int When appending a filename from the specified - * directory to ef->pathname, insert a directory - * separator between the existing pathname and - * the filename, unless separate is zero. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int ef_match_relative_pathname(ExpandFile *ef, DirReader *dr, - const char *pattern, int separate) -{ - const char *nextp; /* The pointer to the character that follows the part */ - /* of the pattern that is to be matched with files */ - /* in the current directory. */ - char *file; /* The name of the file being matched */ - int pathlen; /* The length of ef->pathname[] on entry to this */ - /* function */ -/* - * Record the current length of the pathname string recorded in - * ef->pathname[]. - */ - pathlen = strlen(ef->path->name); -/* - * Get a pointer to the character that follows the end of the part of - * the pattern that should be matched to files within the current directory. - * This will either point to a directory separator, or to the '\0' terminator - * of the pattern string. - */ - for(nextp=pattern; *nextp && strncmp(nextp, FS_DIR_SEP, FS_DIR_SEP_LEN) != 0; - nextp++) - ; -/* - * Read each file from the directory, attempting to match it to the - * current pattern. - */ - while((file=_dr_next_file(dr)) != NULL) { -/* - * Does the latest file match the pattern up to nextp? - */ - if(ef_string_matches_pattern(file, pattern, file[0]=='.', nextp)) { -/* - * Append the new directory entry to the current matching pathname. - */ - if((separate && _pn_append_to_path(ef->path, FS_DIR_SEP, -1, 0)==NULL) || - _pn_append_to_path(ef->path, file, -1, 0)==NULL) { - strcpy(ef->errmsg, "Insufficient memory to record path"); - return 1; - }; -/* - * If we have reached the end of the pattern, record the accumulated - * pathname in the list of matching files. - */ - if(*nextp == '\0') { - if(ef_record_pathname(ef, ef->path->name, 0)) - return 1; -/* - * If the matching directory entry is a subdirectory, and the - * next character of the pattern is a directory separator, - * recursively call the current function to scan the sub-directory - * for matches. - */ - } else if(_pu_path_is_dir(ef->path->name) && - strncmp(nextp, FS_DIR_SEP, FS_DIR_SEP_LEN) == 0) { -/* - * If the pattern finishes with the directory separator, then - * record the pathame as matching. - */ - if(nextp[FS_DIR_SEP_LEN] == '\0') { - if(ef_record_pathname(ef, ef->path->name, 0)) - return 1; -/* - * Match files within the directory. - */ - } else { - DirNode *subdnode = ef_open_dir(ef, ef->path->name); - if(subdnode) { - if(ef_match_relative_pathname(ef, subdnode->dr, - nextp+FS_DIR_SEP_LEN, 1)) { - subdnode = ef_close_dir(ef, subdnode); - return 1; - }; - subdnode = ef_close_dir(ef, subdnode); - }; - }; - }; -/* - * Remove the latest filename from the pathname string, so that - * another matching file can be appended. - */ - ef->path->name[pathlen] = '\0'; - }; - }; - return 0; -} - -/*....................................................................... - * Record a new matching filename. - * - * Input: - * ef ExpandFile * The filename-match resource object. - * pathname const char * The pathname to record. - * remove_escapes int If true, remove backslash escapes in the - * recorded copy of the pathname. - * Output: - * return int 0 - OK. - * 1 - Error (ef->errmsg will contain a - * description of the error). - */ -static int ef_record_pathname(ExpandFile *ef, const char *pathname, - int remove_escapes) -{ - char *copy; /* The recorded copy of pathname[] */ -/* - * Attempt to make a copy of the pathname in the cache. - */ - copy = ef_cache_pathname(ef, pathname, remove_escapes); - if(!copy) - return 1; -/* - * If there isn't room to record a pointer to the recorded pathname in the - * array of files, attempt to extend the array. - */ - if(ef->result.nfile + 1 > ef->files_dim) { - int files_dim = ef->files_dim + MATCH_BLK_FACT; - char **files = (char **) realloc(ef->result.files, - files_dim * sizeof(files[0])); - if(!files) { - sprintf(ef->errmsg, - "Insufficient memory to record all of the matching filenames"); - return 1; - }; - ef->result.files = files; - ef->files_dim = files_dim; - }; -/* - * Record a pointer to the new match. - */ - ef->result.files[ef->result.nfile++] = copy; - return 0; -} - -/*....................................................................... - * Record a pathname in the cache. - * - * Input: - * ef ExpandFile * The filename-match resource object. - * pathname char * The pathname to record. - * remove_escapes int If true, remove backslash escapes in the - * copy of the pathname. - * Output: - * return char * The pointer to the copy of the pathname. - * On error NULL is returned and a description - * of the error is left in ef->errmsg[]. - */ -static char *ef_cache_pathname(ExpandFile *ef, const char *pathname, - int remove_escapes) -{ - char *copy = _sg_store_string(ef->sg, pathname, remove_escapes); - if(!copy) - strcpy(ef->errmsg, "Insufficient memory to store pathname"); - return copy; -} - -/*....................................................................... - * Clear the results of the previous expansion operation, ready for the - * next. - * - * Input: - * ef ExpandFile * The pathname expansion resource object. - */ -static void ef_clear_files(ExpandFile *ef) -{ - _clr_StringGroup(ef->sg); - _pn_clear_path(ef->path); - ef->result.exists = 0; - ef->result.nfile = 0; - ef->errmsg[0] = '\0'; - return; -} - -/*....................................................................... - * Get a new directory reader object from the cache. - * - * Input: - * ef ExpandFile * The pathname expansion resource object. - * pathname const char * The pathname of the directory. - * Output: - * return DirNode * The cache entry of the new directory reader, - * or NULL on error. On error, ef->errmsg will - * contain a description of the error. - */ -static DirNode *ef_open_dir(ExpandFile *ef, const char *pathname) -{ - char *errmsg = NULL; /* An error message from a called function */ - DirNode *node; /* The cache node used */ -/* - * Get the directory reader cache. - */ - DirCache *cache = &ef->cache; -/* - * Extend the cache if there are no free cache nodes. - */ - if(!cache->next) { - node = (DirNode *) _new_FreeListNode(cache->mem); - if(!node) { - sprintf(ef->errmsg, "Insufficient memory to open a new directory"); - return NULL; - }; -/* - * Initialize the cache node. - */ - node->next = NULL; - node->prev = NULL; - node->dr = NULL; -/* - * Allocate a directory reader object. - */ - node->dr = _new_DirReader(); - if(!node->dr) { - sprintf(ef->errmsg, "Insufficient memory to open a new directory"); - node = (DirNode *) _del_FreeListNode(cache->mem, node); - return NULL; - }; -/* - * Append the node to the cache list. - */ - node->prev = cache->tail; - if(cache->tail) - cache->tail->next = node; - else - cache->head = node; - cache->next = cache->tail = node; - }; -/* - * Get the first unused node, but don't remove it from the list yet. - */ - node = cache->next; -/* - * Attempt to open the specified directory. - */ - if(_dr_open_dir(node->dr, pathname, &errmsg)) { - strncpy(ef->errmsg, errmsg, ERRLEN); - ef->errmsg[ERRLEN] = '\0'; - return NULL; - }; -/* - * Now that we have successfully opened the specified directory, - * remove the cache node from the list, and relink the list around it. - */ - cache->next = node->next; - if(node->prev) - node->prev->next = node->next; - else - cache->head = node->next; - if(node->next) - node->next->prev = node->prev; - else - cache->tail = node->prev; - node->next = node->prev = NULL; -/* - * Return the successfully initialized cache node to the caller. - */ - return node; -} - -/*....................................................................... - * Return a directory reader object to the cache, after first closing - * the directory that it was managing. - * - * Input: - * ef ExpandFile * The pathname expansion resource object. - * node DirNode * The cache entry of the directory reader, as returned - * by ef_open_dir(). - * Output: - * return DirNode * The deleted DirNode (ie. allways NULL). - */ -static DirNode *ef_close_dir(ExpandFile *ef, DirNode *node) -{ -/* - * Get the directory reader cache. - */ - DirCache *cache = &ef->cache; -/* - * Close the directory. - */ - _dr_close_dir(node->dr); -/* - * Return the node to the tail of the cache list. - */ - node->next = NULL; - node->prev = cache->tail; - if(cache->tail) - cache->tail->next = node; - else - cache->head = cache->tail = node; - if(!cache->next) - cache->next = node; - return NULL; -} - -/*....................................................................... - * Return non-zero if the specified file name matches a given glob - * pattern. - * - * Input: - * file const char * The file-name component to be matched to the pattern. - * pattern const char * The start of the pattern to match against file[]. - * xplicit int If non-zero, the first character must be matched - * explicitly (ie. not with a wildcard). - * nextp const char * The pointer to the the character following the - * end of the pattern in pattern[]. - * Output: - * return int 0 - Doesn't match. - * 1 - The file-name string matches the pattern. - */ -static int ef_string_matches_pattern(const char *file, const char *pattern, - int xplicit, const char *nextp) -{ - const char *pptr = pattern; /* The pointer used to scan the pattern */ - const char *fptr = file; /* The pointer used to scan the filename string */ -/* - * Match each character of the pattern in turn. - */ - while(pptr < nextp) { -/* - * Handle the next character of the pattern. - */ - switch(*pptr) { -/* - * A match zero-or-more characters wildcard operator. - */ - case '*': -/* - * Skip the '*' character in the pattern. - */ - pptr++; -/* - * If wildcards aren't allowed, the pattern doesn't match. - */ - if(xplicit) - return 0; -/* - * If the pattern ends with a the '*' wildcard, then the - * rest of the filename matches this. - */ - if(pptr >= nextp) - return 1; -/* - * Using the wildcard to match successively longer sections of - * the remaining characters of the filename, attempt to match - * the tail of the filename against the tail of the pattern. - */ - for( ; *fptr; fptr++) { - if(ef_string_matches_pattern(fptr, pptr, 0, nextp)) - return 1; - }; - return 0; /* The pattern following the '*' didn't match */ - break; -/* - * A match-one-character wildcard operator. - */ - case '?': -/* - * If there is a character to be matched, skip it and advance the - * pattern pointer. - */ - if(!xplicit && *fptr) { - fptr++; - pptr++; -/* - * If we hit the end of the filename string, there is no character - * matching the operator, so the string doesn't match. - */ - } else { - return 0; - }; - break; -/* - * A character range operator, with the character ranges enclosed - * in matching square brackets. - */ - case '[': - if(xplicit || !ef_matches_range(*fptr++, ++pptr, &pptr)) - return 0; - break; -/* - * A backslash in the pattern prevents the following character as - * being seen as a special character. - */ - case '\\': - pptr++; - /* Note fallthrough to default */ -/* - * A normal character to be matched explicitly. - */ - default: - if(*fptr == *pptr) { - fptr++; - pptr++; - } else { - return 0; - }; - break; - }; -/* - * After passing the first character, turn off the explicit match - * requirement. - */ - xplicit = 0; - }; -/* - * To get here the pattern must have been exhausted. If the filename - * string matched, then the filename string must also have been - * exhausted. - */ - return *fptr == '\0'; -} - -/*....................................................................... - * Match a character range expression terminated by an unescaped close - * square bracket. - * - * Input: - * c int The character to be matched with the range - * pattern. - * pattern const char * The range pattern to be matched (ie. after the - * initiating '[' character). - * endp const char ** On output a pointer to the character following the - * range expression will be assigned to *endp. - * Output: - * return int 0 - Doesn't match. - * 1 - The character matched. - */ -static int ef_matches_range(int c, const char *pattern, const char **endp) -{ - const char *pptr = pattern; /* The pointer used to scan the pattern */ - int invert = 0; /* True to invert the sense of the match */ - int matched = 0; /* True if the character matched the pattern */ -/* - * If the first character is a caret, the sense of the match is - * inverted and only if the character isn't one of those in the - * range, do we say that it matches. - */ - if(*pptr == '^') { - pptr++; - invert = 1; - }; -/* - * The hyphen is only a special character when it follows the first - * character of the range (not including the caret). - */ - if(*pptr == '-') { - pptr++; - if(c == '-') { - *endp = pptr; - matched = 1; - }; -/* - * Skip other leading '-' characters since they make no sense. - */ - while(*pptr == '-') - pptr++; - }; -/* - * The hyphen is only a special character when it follows the first - * character of the range (not including the caret or a hyphen). - */ - if(*pptr == ']') { - pptr++; - if(c == ']') { - *endp = pptr; - matched = 1; - }; - }; -/* - * Having dealt with the characters that have special meanings at - * the beginning of a character range expression, see if the - * character matches any of the remaining characters of the range, - * up until a terminating ']' character is seen. - */ - while(!matched && *pptr && *pptr != ']') { -/* - * Is this a range of characters signaled by the two end characters - * separated by a hyphen? - */ - if(*pptr == '-') { - if(pptr[1] != ']') { - if(c >= pptr[-1] && c <= pptr[1]) - matched = 1; - pptr += 2; - }; -/* - * A normal character to be compared directly. - */ - } else if(*pptr++ == c) { - matched = 1; - }; - }; -/* - * Find the terminating ']'. - */ - while(*pptr && *pptr != ']') - pptr++; -/* - * Did we find a terminating ']'? - */ - if(*pptr == ']') { - *endp = pptr + 1; - return matched ? !invert : invert; - }; -/* - * If the pattern didn't end with a ']' then it doesn't match, regardless - * of the value of the required sense of the match. - */ - *endp = pptr; - return 0; -} - -/*....................................................................... - * This is a qsort() comparison function used to sort strings. - * - * Input: - * v1, v2 void * Pointers to the two strings to be compared. - * Output: - * return int -1 -> v1 < v2. - * 0 -> v1 == v2 - * 1 -> v1 > v2 - */ -static int ef_cmp_strings(const void *v1, const void *v2) -{ - char * const *s1 = (char * const *) v1; - char * const *s2 = (char * const *) v2; - return strcmp(*s1, *s2); -} - -/*....................................................................... - * Preprocess a path, expanding ~/, ~user/ and $envvar references, using - * ef->path as a work buffer, then copy the result into a cache entry, - * and return a pointer to this copy. - * - * Input: - * ef ExpandFile * The resource object of the file matcher. - * pathlen int The length of the prefix of path[] to be expanded. - * Output: - * return char * A pointer to a copy of the output path in the - * cache. On error NULL is returned, and a description - * of the error is left in ef->errmsg[]. - */ -static char *ef_expand_special(ExpandFile *ef, const char *path, int pathlen) -{ - int spos; /* The index of the start of the path segment that needs */ - /* to be copied from path[] to the output pathname. */ - int ppos; /* The index of a character in path[] */ - char *pptr; /* A pointer into the output path */ - int escaped; /* True if the previous character was a '\' */ - int i; -/* - * Clear the pathname buffer. - */ - _pn_clear_path(ef->path); -/* - * We need to perform two passes, one to expand environment variables - * and a second to do tilde expansion. This caters for the case - * where an initial dollar expansion yields a tilde expression. - */ - escaped = 0; - for(spos=ppos=0; ppos < pathlen; ppos++) { - int c = path[ppos]; - if(escaped) { - escaped = 0; - } else if(c == '\\') { - escaped = 1; - } else if(c == '$') { - int envlen; /* The length of the environment variable */ - char *value; /* The value of the environment variable */ -/* - * Record the preceding unrecorded part of the pathname. - */ - if(spos < ppos && _pn_append_to_path(ef->path, path + spos, ppos-spos, 0) - == NULL) { - strcpy(ef->errmsg, "Insufficient memory to expand path"); - return NULL; - }; -/* - * Skip the dollar. - */ - ppos++; -/* - * Copy the environment variable name that follows the dollar into - * ef->envnam[], stopping if a directory separator or end of string - * is seen. - */ - for(envlen=0; envlen<ENV_LEN && ppos < pathlen && - strncmp(path + ppos, FS_DIR_SEP, FS_DIR_SEP_LEN); envlen++) - ef->envnam[envlen] = path[ppos++]; -/* - * If the username overflowed the buffer, treat it as invalid (note that - * on most unix systems only 8 characters are allowed in a username, - * whereas our ENV_LEN is much bigger than that. - */ - if(envlen >= ENV_LEN) { - strcpy(ef->errmsg, "Environment variable name too long"); - return NULL; - }; -/* - * Terminate the environment variable name. - */ - ef->envnam[envlen] = '\0'; -/* - * Lookup the value of the environment variable. - */ - value = getenv(ef->envnam); - if(!value) { - const char *fmt = "No expansion found for: $%.*s"; - sprintf(ef->errmsg, fmt, ERRLEN - strlen(fmt), ef->envnam); - return NULL; - }; -/* - * Copy the value of the environment variable into the output pathname. - */ - if(_pn_append_to_path(ef->path, value, -1, 0) == NULL) { - strcpy(ef->errmsg, "Insufficient memory to expand path"); - return NULL; - }; -/* - * Record the start of the uncopied tail of the input pathname. - */ - spos = ppos; - }; - }; -/* - * Record the uncopied tail of the pathname. - */ - if(spos < ppos && _pn_append_to_path(ef->path, path + spos, ppos-spos, 0) - == NULL) { - strcpy(ef->errmsg, "Insufficient memory to expand path"); - return NULL; - }; -/* - * If the first character of the resulting pathname is a tilde, - * then attempt to substitute the home directory of the specified user. - */ - pptr = ef->path->name; - if(*pptr == '~' && path[0] != '\\') { - int usrlen; /* The length of the username following the tilde */ - const char *homedir; /* The home directory of the user */ - int homelen; /* The length of the home directory string */ - int plen; /* The current length of the path */ - int skip=0; /* The number of characters to skip after the ~user */ -/* - * Get the current length of the output path. - */ - plen = strlen(ef->path->name); -/* - * Skip the tilde. - */ - pptr++; -/* - * Copy the optional username that follows the tilde into ef->usrnam[]. - */ - for(usrlen=0; usrlen<USR_LEN && *pptr && - strncmp(pptr, FS_DIR_SEP, FS_DIR_SEP_LEN); usrlen++) - ef->usrnam[usrlen] = *pptr++; -/* - * If the username overflowed the buffer, treat it as invalid (note that - * on most unix systems only 8 characters are allowed in a username, - * whereas our USR_LEN is much bigger than that. - */ - if(usrlen >= USR_LEN) { - strcpy(ef->errmsg, "Username too long"); - return NULL; - }; -/* - * Terminate the username string. - */ - ef->usrnam[usrlen] = '\0'; -/* - * Lookup the home directory of the user. - */ - homedir = _hd_lookup_home_dir(ef->home, ef->usrnam); - if(!homedir) { - strncpy(ef->errmsg, _hd_last_home_dir_error(ef->home), ERRLEN); - ef->errmsg[ERRLEN] = '\0'; - return NULL; - }; - homelen = strlen(homedir); -/* - * ~user and ~ are usually followed by a directory separator to - * separate them from the file contained in the home directory. - * If the home directory is the root directory, then we don't want - * to follow the home directory by a directory separator, so we must - * erase it. - */ - if(strcmp(homedir, FS_ROOT_DIR) == 0 && - strncmp(pptr, FS_DIR_SEP, FS_DIR_SEP_LEN) == 0) { - skip = FS_DIR_SEP_LEN; - }; -/* - * If needed, increase the size of the pathname buffer to allow it - * to accomodate the home directory instead of the tilde expression. - * Note that pptr may not be valid after this call. - */ - if(_pn_resize_path(ef->path, plen - usrlen - 1 - skip + homelen)==NULL) { - strcpy(ef->errmsg, "Insufficient memory to expand filename"); - return NULL; - }; -/* - * Move the part of the pathname that follows the tilde expression to - * the end of where the home directory will need to be inserted. - */ - memmove(ef->path->name + homelen, - ef->path->name + 1 + usrlen + skip, plen - usrlen - 1 - skip+1); -/* - * Write the home directory at the beginning of the string. - */ - for(i=0; i<homelen; i++) - ef->path->name[i] = homedir[i]; - }; -/* - * Copy the result into the cache, and return a pointer to the copy. - */ - return ef_cache_pathname(ef, ef->path->name, 0); -} - -/*....................................................................... - * Return a description of the last path-expansion error that occurred. - * - * Input: - * ef ExpandFile * The path-expansion resource object. - * Output: - * return char * The description of the last error. - */ -const char *ef_last_error(ExpandFile *ef) -{ - return ef ? ef->errmsg : "NULL ExpandFile argument"; -} - -/*....................................................................... - * Print out an array of matching files. - * - * Input: - * result FileExpansion * The container of the sorted array of - * expansions. - * fp FILE * The output stream to write to. - * term_width int The width of the terminal. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int ef_list_expansions(FileExpansion *result, FILE *fp, int term_width) -{ - int maxlen; /* The length of the longest matching string */ - int width; /* The width of a column */ - int ncol; /* The number of columns to list */ - int nrow; /* The number of rows needed to list all of the expansions */ - int row,col; /* The row and column being written to */ - int i; -/* - * Check the arguments. - */ - if(!result || !fp) { - fprintf(stderr, "ef_list_expansions: NULL argument(s).\n"); - return 1; - }; -/* - * Not enough space to list anything? - */ - if(term_width < 1) - return 0; -/* - * Work out the maximum length of the matching filenames. - */ - maxlen = 0; - for(i=0; i<result->nfile; i++) { - int len = strlen(result->files[i]); - if(len > maxlen) - maxlen = len; - }; -/* - * Nothing to list? - */ - if(maxlen == 0) - return 0; -/* - * Split the available terminal width into columns of maxlen + 2 characters. - */ - width = maxlen + 2; - ncol = term_width / width; -/* - * If the column width is greater than the terminal width, the matches will - * just have to overlap onto the next line. - */ - if(ncol < 1) - ncol = 1; -/* - * How many rows will be needed? - */ - nrow = (result->nfile + ncol - 1) / ncol; -/* - * Print the expansions out in ncol columns, sorted in row order within each - * column. - */ - for(row=0; row < nrow; row++) { - for(col=0; col < ncol; col++) { - int m = col*nrow + row; - if(m < result->nfile) { - const char *filename = result->files[m]; - if(fprintf(fp, "%s%-*s%s", filename, - (int) (ncol > 1 ? maxlen - strlen(filename):0), "", - col<ncol-1 ? " " : "\r\n") < 0) - return 1; - } else { - if(fprintf(fp, "\r\n") < 0) - return 1; - break; - }; - }; - }; - return 0; -} - diff --git a/libtecla-1.4.1/freelist.c b/libtecla-1.4.1/freelist.c deleted file mode 100644 index 4fe0472..0000000 --- a/libtecla-1.4.1/freelist.c +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Copyright (c) 2000, 2001 by Martin C. Shepherd. - * - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL - * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - */ - -#include <stdio.h> -#include <stdlib.h> - -#include "freelist.h" - -typedef struct FreeListBlock FreeListBlock; -struct FreeListBlock { - FreeListBlock *next; /* The next block in the list */ - char *nodes; /* The array of free-list nodes */ -}; - -struct FreeList { - size_t node_size; /* The size of a free-list node */ - unsigned blocking_factor; /* The number of nodes per block */ - long nbusy; /* The number of nodes that are in use */ - FreeListBlock *block; /* The head of the list of free-list blocks */ - void *free_list; /* The free-list of nodes */ -}; - -static FreeListBlock *_new_FreeListBlock(FreeList *fl); -static FreeListBlock *_del_FreeListBlock(FreeListBlock *fl); -static void _thread_FreeListBlock(FreeList *fl, FreeListBlock *block); - -/*....................................................................... - * Allocate a new free-list from blocks of 'blocking_factor' objects of size - * node_size. - * - * Input: - * caller const char * The name of the calling function, for use in - * error messages, or NULL to not report errors - * to stderr. - * node_size size_t The size of the free-list nodes to be returned - * by _new_FreeListNode(). Use sizeof() to - * determine this. - * blocking_factor unsigned The number of objects of size 'object_size' - * to allocate per block. - * Output: - * return FreeList * The new freelist, or NULL on error. - */ -FreeList *_new_FreeList(const char *caller, size_t node_size, - unsigned blocking_factor) -{ - FreeList *fl; /* The new free-list container */ -/* - * When a free-list node is on the free-list, it is used as a (void *) - * link field. Roundup node_size to a mulitple of the size of a void - * pointer. This, plus the fact that the array of nodes is obtained via - * malloc, which returns memory suitably aligned for any object, will - * ensure that the first sizeof(void *) bytes of each node will be - * suitably aligned to use as a (void *) link pointer. - */ - node_size = sizeof(void *) * - ((node_size + sizeof(void *) - 1) / sizeof(void *)); -/* - * Enfore a minimum block size. - */ - if(blocking_factor < 1) - blocking_factor = 1; -/* - * Allocate the container of the free list. - */ - fl = (FreeList *) malloc(sizeof(FreeList)); - if(!fl) { - if(caller) - fprintf(stderr, "_new_FreeList (%s): Insufficient memory.\n", caller); - return NULL; - }; -/* - * Before attempting any operation that might fail, initialize the - * container at least up to the point at which it can safely be passed - * to _del_FreeList(). - */ - fl->node_size = node_size; - fl->blocking_factor = blocking_factor; - fl->nbusy = 0; - fl->block = NULL; - fl->free_list = NULL; -/* - * Allocate the first block of memory. - */ - fl->block = _new_FreeListBlock(fl); - if(!fl->block) { - if(caller) - fprintf(stderr, "_new_FreeList (%s): Insufficient memory.\n", caller); - return _del_FreeList(caller, fl, 1); - }; -/* - * Add the new list of nodes to the free-list. - */ - fl->free_list = fl->block->nodes; -/* - * Return the free-list for use. - */ - return fl; -} - -/*....................................................................... - * Re-thread a freelist to reclaim all allocated nodes. - * This function should not be called unless if it is known that none - * of the currently allocated nodes are still being used. - * - * Input: - * fl FreeList * The free-list to be reset, or NULL. - */ -void _rst_FreeList(FreeList *fl) -{ - if(fl) { - FreeListBlock *block; -/* - * Re-thread the nodes of each block into individual free-lists. - */ - for(block=fl->block; block; block=block->next) - _thread_FreeListBlock(fl, block); -/* - * Link all of the block freelists into one large freelist. - */ - fl->free_list = NULL; - for(block=fl->block; block; block=block->next) { -/* - * Locate the last node of the current block. - */ - char *last_node = block->nodes + fl->node_size * - (fl->blocking_factor - 1); -/* - * Make the link-field of the last node point to the first - * node of the current freelist, then make the first node of the - * new block the start of the freelist. - */ - *(void **)last_node = fl->free_list; - fl->free_list = block->nodes; - }; -/* - * All allocated nodes have now been returned to the freelist. - */ - fl->nbusy = 0; - }; -} - -/*....................................................................... - * Delete a free-list. - * - * Input: - * caller const char * The name of the calling function, for use in - * error messages, or NULL if error messages - * shouldn't be reported to stderr. - * fl FreeList * The free-list to be deleted, or NULL. - * force int If force==0 then _del_FreeList() will complain - * and refuse to delete the free-list if any - * of nodes have not been returned to the free-list. - * If force!=0 then _del_FreeList() will not check - * whether any nodes are still in use and will - * always delete the list. - * Output: - * return FreeList * Always NULL (even if the list couldn't be - * deleted). - */ -FreeList *_del_FreeList(const char *caller, FreeList *fl, int force) -{ - if(fl) { -/* - * Check whether any nodes are in use. - */ - if(!force && _busy_FreeListNodes(fl) != 0) { - if(caller) - fprintf(stderr, "_del_FreeList (%s): %ld nodes are still in use.\n", - caller, _busy_FreeListNodes(fl)); - return NULL; - }; -/* - * Delete the list blocks. - */ - { - FreeListBlock *next = fl->block; - while(next) { - FreeListBlock *block = next; - next = block->next; - block = _del_FreeListBlock(block); - }; - }; - fl->block = NULL; - fl->free_list = NULL; -/* - * Discard the container. - */ - free(fl); - }; - return NULL; -} - -/*....................................................................... - * Allocate a new object from a free-list. - * - * Input: - * fl FreeList * The free-list to return an object from. - * Output: - * return void * A new object of the size that was specified via - * the node_size argument of _new_FreeList() when - * the free-list was created, or NULL if there - * is insufficient memory, or 'fl' is NULL. - */ -void *_new_FreeListNode(FreeList *fl) -{ - void *node; /* The node to be returned */ -/* - * Check arguments. - */ - if(!fl) - return NULL; -/* - * If the free-list has been exhausted extend it by allocating - * another block of nodes. - */ - if(!fl->free_list) { - FreeListBlock *block = _new_FreeListBlock(fl); - if(!block) - return NULL; -/* - * Prepend the new block to the list of free-list blocks. - */ - block->next = fl->block; - fl->block = block; -/* - * Add the new list of nodes to the free-list. - */ - fl->free_list = fl->block->nodes; - }; -/* - * Remove and return a node from the front of the free list. - */ - node = fl->free_list; - fl->free_list = *(void **)node; -/* - * Record the loss of a node from the free-list. - */ - fl->nbusy++; -/* - * Return the node. - */ - return node; -} - -/*....................................................................... - * Return an object to the free-list that it was allocated from. - * - * Input: - * caller const char * The name of the calling function, for use in - * error messages, or NULL to not report errors - * to stderr. - * fl FreeList * The free-list from which the object was taken. - * object void * The node to be returned. - * Output: - * return void * Always NULL. - */ -void *_del_FreeListNode(FreeList *fl, void *object) -{ -/* - * Check arguments. - */ - if(!fl) - return NULL; -/* - * Return the node to the head of the free list. - */ - if(object) { - *(void **)object = fl->free_list; - fl->free_list = object; -/* - * Record the return of the node to the free-list. - */ - fl->nbusy--; - }; - return NULL; -} - -/*....................................................................... - * Return a count of the number of nodes that are currently allocated. - * - * Input: - * fl FreeList * The list to count wrt, or NULL. - * Output: - * return long The number of nodes (or 0 if fl==NULL). - */ -long _busy_FreeListNodes(FreeList *fl) -{ - return fl ? fl->nbusy : 0; -} - -/*....................................................................... - * Allocate a new list of free-list nodes. On return the nodes will - * be linked together as a list starting with the node at the lowest - * address and ending with a NULL next pointer. - * - * Input: - * fl FreeList * The free-list to allocate the list for. - * Output: - * return FreeListBlock * The new linked block of free-list nodes, - * or NULL on error. - */ -static FreeListBlock *_new_FreeListBlock(FreeList *fl) -{ - FreeListBlock *block; /* The new block to be returned */ -/* - * Allocate the container. - */ - block = (FreeListBlock *) malloc(sizeof(FreeListBlock)); - if(!block) - return NULL; -/* - * Before attempting any operation that might fail, initialize the - * container at least up to the point at which it can safely be passed - * to _del_FreeListBlock(). - */ - block->next = NULL; - block->nodes = NULL; -/* - * Allocate the block of nodes. - */ - block->nodes = (char *) malloc(fl->node_size * fl->blocking_factor); - if(!block->nodes) - return _del_FreeListBlock(block); -/* - * Initialize the block as a linked list of FreeListNode's. - */ - _thread_FreeListBlock(fl, block); - return block; -} - -/*....................................................................... - * Link each node of a freelist block to the node that follows it. - * - * Input: - * fl FreeList * The freelist that contains the block. - * block FreeListBlock * The block to be threaded. - */ -static void _thread_FreeListBlock(FreeList *fl, FreeListBlock *block) -{ - char *mem = block->nodes; - int i; - for(i=0; i<fl->blocking_factor - 1; i++, mem += fl->node_size) - *(void **)mem = mem + fl->node_size; /* Link to the next node */ - *(void **)mem = NULL; /* Terminate the list */ -} - -/*....................................................................... - * Delete a free-list block. - * - * Input: - * fl FreeListBlock * The block to be deleted, or NULL. - * Output: - * return FreeListBlock * Always NULL. - */ -static FreeListBlock *_del_FreeListBlock(FreeListBlock *fl) -{ - if(fl) { - fl->next = NULL; - if(fl->nodes) - free(fl->nodes); - fl->nodes = NULL; - free(fl); - }; - return NULL; -} diff --git a/libtecla-1.4.1/freelist.h b/libtecla-1.4.1/freelist.h deleted file mode 100644 index 84e6aef..0000000 --- a/libtecla-1.4.1/freelist.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef freelist_h -#define freelist_h - -/* - * Copyright (c) 2000, 2001 by Martin C. Shepherd. - * - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL - * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - */ - -/* - * This module provides a memory allocation scheme that helps to - * prevent memory fragmentation by allocating large blocks of - * fixed sized objects and forming them into a free-list for - * subsequent allocations. The free-list is expanded as needed. - */ -typedef struct FreeList FreeList; - -/* - * Allocate a new free-list from blocks of 'blocking_factor' objects of size - * node_size. The node_size argument should be determined by applying - * the sizeof() operator to the object type that you intend to allocate from - * the freelist. - */ -FreeList *_new_FreeList(const char *caller, size_t node_size, - unsigned blocking_factor); - -/* - * If it is known that none of the nodes currently allocated from - * a freelist are still in use, the following function can be called - * to return all nodes to the freelist without the overhead of - * having to call del_FreeListNode() for every allocated node. The - * nodes of the freelist can then be reused by future callers to - * new_FreeListNode(). - */ -void _rst_FreeList(FreeList *fl); - -/* - * Delete a free-list. - */ -FreeList *_del_FreeList(const char *caller, FreeList *fl, int force); - -/* - * Determine the number of nodes that are currently allocated. - */ -long _busy_FreeListNodes(FreeList *fl); - -/* - * Allocate a new object from a free-list. - */ -void *_new_FreeListNode(FreeList *fl); - -/* - * Return an object to the free-list that it was allocated from. - */ -void *_del_FreeListNode(FreeList *fl, void *object); - -#endif diff --git a/libtecla-1.4.1/getline.c b/libtecla-1.4.1/getline.c deleted file mode 100644 index 242fae3..0000000 --- a/libtecla-1.4.1/getline.c +++ /dev/null @@ -1,8346 +0,0 @@ -/* - * Copyright (c) 2000, 2001 by Martin C. Shepherd. - * - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL - * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - */ - -/* - * Standard headers. - */ -#include <stdio.h> -#include <stdlib.h> -#include <signal.h> -#include <string.h> -#include <errno.h> -#include <ctype.h> -#include <setjmp.h> - -/* - * UNIX headers. - */ -#include <sys/ioctl.h> -#ifdef HAVE_SELECT -#include <sys/time.h> -#include <sys/types.h> -#endif - -/* - * Handle the different sources of terminal control string and size - * information. Note that if no terminal information database is available, - * ANSI VT100 control sequences are used. - */ -#if defined(USE_TERMINFO) || defined(USE_TERMCAP) -/* - * Include curses.h or ncurses/curses.h depending on which is available. - */ -#ifdef HAVE_CURSES_H -#include <curses.h> -#elif defined(HAVE_NCURSES_CURSES_H) -#include <ncurses/curses.h> -#endif -/* - * Include term.h where available. - */ -#if defined(HAVE_TERM_H) -#include <term.h> -#elif defined(HAVE_NCURSES_TERM_H) -#include <ncurses/term.h> -#endif -/* - * When using termcap, include termcap.h on systems that have it. - * Otherwise assume that all prototypes are provided by curses.h. - */ -#if defined(USE_TERMCAP) && defined(HAVE_TERMCAP_H) -#include <termcap.h> -#endif -/* - * Unfortunately both terminfo and termcap require one to use the tputs() - * function to output terminal control characters, and this function - * doesn't allow one to specify a file stream. As a result, the following - * file-scope variable is used to pass the current output file stream. - * This is bad, but there doesn't seem to be any alternative. - */ -static FILE *tputs_fp = NULL; -/* - * Under Solaris default Curses the output function that tputs takes is - * declared to have a char argument. On all other systems and on Solaris - * X/Open Curses (Issue 4, Version 2) it expects an int argument (using - * c89 or options -I /usr/xpg4/include -L /usr/xpg4/lib -R /usr/xpg4/lib - * selects XPG4v2 Curses on Solaris 2.6 and later). - * - * Similarly, under Mac OS X, the return value of the tputs output - * function is declared as void, whereas it is declared as int on - * other systems. - */ -#if defined __sun && defined __SVR4 && !defined _XOPEN_CURSES -static int gl_tputs_putchar(char c) {return putc(c, tputs_fp);} -#elif defined(__APPLE__) && defined(__MACH__) -static void gl_tputs_putchar(int c) {(void) putc(c, tputs_fp);} -#else -static int gl_tputs_putchar(int c) {return putc(c, tputs_fp);} -#endif -#endif - -/* - * POSIX headers. - */ -#include <unistd.h> -#include <termios.h> - -/* - * Does the system provide the signal and ioctl query facility used - * to inform the process of terminal window size changes? - */ -#if defined(SIGWINCH) && defined(TIOCGWINSZ) -#define USE_SIGWINCH 1 -#endif - -/* - * Provide typedefs for standard POSIX structures. - */ -typedef struct sigaction SigAction; -typedef struct termios Termios; - -/* - * Local headers. - */ -#include "pathutil.h" -#include "libtecla.h" -#include "keytab.h" -#include "history.h" -#include "freelist.h" -#include "stringrp.h" -#include "getline.h" - -/* - * Enumerate the available editing styles. - */ -typedef enum { - GL_EMACS_MODE, /* Emacs style editing */ - GL_VI_MODE, /* Vi style editing */ - GL_NO_EDITOR /* Fall back to the basic OS-provided editing */ -} GlEditor; - -/* - * In vi mode, the following datatype is used to implement the - * undo command. It records a copy of the input line from before - * the command-mode action which edited the input line. - */ -typedef struct { - char *line; /* A historical copy of the input line */ - int buff_curpos; /* The historical location of the cursor in */ - /* line[] when the line was modified. */ - int ntotal; /* The number of characters in line[] */ - int saved; /* True once a line has been saved after the */ - /* last call to gl_interpret_char(). */ -} ViUndo; - -/* - * In vi mode, the following datatype is used to record information - * needed by the vi-repeat-change command. - */ -typedef struct { - KtKeyFn *fn; /* The last action function that made a */ - /* change to the line. */ - int count; /* The repeat count that was passed to the */ - /* above command. */ - int input_curpos; /* Whenever vi command mode is entered, the */ - /* the position at which it was first left */ - /* is recorded here. */ - int command_curpos; /* Whenever vi command mode is entered, the */ - /* the location of the cursor is recorded */ - /* here. */ - char input_char; /* Commands that call gl_read_character() */ - /* record the character here, so that it can */ - /* used on repeating the function. */ - int saved; /* True if a function has been saved since the */ - /* last call to gl_interpret_char(). */ - int active; /* True while a function is being repeated. */ -} ViRepeat; - -/* - * The following datatype is used to encapsulate information specific - * to vi mode. - */ -typedef struct { - ViUndo undo; /* Information needed to implement the vi */ - /* undo command. */ - ViRepeat repeat; /* Information needed to implement the vi */ - /* repeat command. */ - int command; /* True in vi command-mode */ - int find_forward; /* True if the last character search was in the */ - /* forward direction. */ - int find_onto; /* True if the last character search left the */ - /* on top of the located character, as opposed */ - /* to just before or after it. */ - char find_char; /* The last character sought, or '\0' if no */ - /* searches have been performed yet. */ -} ViMode; - -#ifdef HAVE_SELECT -/* - * Define a type for recording a file-descriptor callback and its associated - * data. - */ -typedef struct { - GlFdEventFn *fn; /* The callback function */ - void *data; /* Anonymous data to pass to the callback function */ -} GlFdHandler; - -/* - * A list of nodes of the following type is used to record file-activity - * event handlers, but only on systems that have the select() system call. - */ -typedef struct GlFdNode GlFdNode; -struct GlFdNode { - GlFdNode *next; /* The next in the list of nodes */ - int fd; /* The file descriptor being watched */ - GlFdHandler rd; /* The callback to call when fd is readable */ - GlFdHandler wr; /* The callback to call when fd is writable */ - GlFdHandler ur; /* The callback to call when fd has urgent data */ -}; - -/* - * Set the number of the above structures to allocate every time that - * the freelist of GlFdNode's becomes exhausted. - */ -#define GLFD_FREELIST_BLOCKING 10 - -/* - * Listen for and handle file-descriptor events. - */ -static int gl_event_handler(GetLine *gl); - -static int gl_call_fd_handler(GetLine *gl, GlFdHandler *gfh, int fd, - GlFdEvent event); -#endif - -/* - * Each signal that gl_get_line() traps is described by a list node - * of the following type. - */ -typedef struct GlSignalNode GlSignalNode; -struct GlSignalNode { - GlSignalNode *next; /* The next signal in the list */ - int signo; /* The number of the signal */ - sigset_t proc_mask; /* A process mask which only includes signo */ - SigAction original; /* The signal disposition of the calling program */ - /* for this signal. */ - unsigned flags; /* A bitwise union of GlSignalFlags enumerators */ - GlAfterSignal after; /* What to do after the signal has been handled */ - int errno_value; /* What to set errno to */ -}; - -/* - * Set the number of the above structures to allocate every time that - * the freelist of GlSignalNode's becomes exhausted. - */ -#define GLS_FREELIST_BLOCKING 30 - -/* - * Define the contents of the GetLine object. - * Note that the typedef for this object can be found in libtecla.h. - */ -struct GetLine { - GlHistory *glh; /* The line-history buffer */ - WordCompletion *cpl; /* String completion resource object */ - CplMatchFn(*cpl_fn); /* The tab completion callback function */ - void *cpl_data; /* Callback data to pass to cpl_fn() */ - ExpandFile *ef; /* ~user/, $envvar and wildcard expansion */ - /* resource object. */ - StringGroup *capmem; /* Memory for recording terminal capability */ - /* strings. */ - int input_fd; /* The file descriptor to read on */ - int output_fd; /* The file descriptor to write to */ - FILE *input_fp; /* A stream wrapper around input_fd */ - FILE *output_fp; /* A stream wrapper around output_fd */ - FILE *file_fp; /* When input is being temporarily taken from */ - /* a file, this is its file-pointer. Otherwise */ - /* it is NULL. */ - char *term; /* The terminal type specified on the last call */ - /* to gl_change_terminal(). */ - int is_term; /* True if stdin is a terminal */ - size_t linelen; /* The max number of characters per line */ - char *line; /* A line-input buffer of allocated size */ - /* linelen+2. The extra 2 characters are */ - /* reserved for "\n\0". */ - char *cutbuf; /* A cut-buffer of the same size as line[] */ - const char *prompt; /* The current prompt string */ - int prompt_len; /* The length of the prompt string */ - int prompt_changed; /* True after a callback changes the prompt */ - int prompt_style; /* How the prompt string is displayed */ - FreeList *sig_mem; /* Memory for nodes of the signal list */ - GlSignalNode *sigs; /* The head of the list of signals */ - sigset_t old_signal_set; /* The signal set on entry to gl_get_line() */ - sigset_t new_signal_set; /* The set of signals that we are trapping */ - Termios oldattr; /* Saved terminal attributes. */ - KeyTab *bindings; /* A table of key-bindings */ - int ntotal; /* The number of characters in gl->line[] */ - int buff_curpos; /* The cursor position within gl->line[] */ - int term_curpos; /* The cursor position on the terminal */ - int buff_mark; /* A marker location in the buffer */ - int insert_curpos; /* The cursor position at start of insert */ - int insert; /* True in insert mode */ - int number; /* If >= 0, a numeric argument is being read */ - int endline; /* True to tell gl_get_input_line() to return */ - /* the current contents of gl->line[] */ - KtKeyFn *current_fn; /* The action function that is currently being */ - /* invoked. */ - int current_count; /* The repeat count passed to current_fn() */ - GlhLineID preload_id; /* When not zero, this should be the ID of a */ - /* line in the history buffer for potential */ - /* recall. */ - int preload_history; /* If true, preload the above history line when */ - /* gl_get_input_line() is next called. */ - long keyseq_count; /* The number of key sequences entered by the */ - /* the user since new_GetLine() was called. */ - long last_search; /* The value of oper_count during the last */ - /* history search operation. */ - GlEditor editor; /* The style of editing, (eg. vi or emacs) */ - int silence_bell; /* True if gl_ring_bell() should do nothing. */ - ViMode vi; /* Parameters used when editing in vi mode */ - const char *left; /* The string that moves the cursor 1 character */ - /* left. */ - const char *right; /* The string that moves the cursor 1 character */ - /* right. */ - const char *up; /* The string that moves the cursor 1 character */ - /* up. */ - const char *down; /* The string that moves the cursor 1 character */ - /* down. */ - const char *home; /* The string that moves the cursor home */ - const char *bol; /* Move cursor to beginning of line */ - const char *clear_eol; /* The string that clears from the cursor to */ - /* the end of the line. */ - const char *clear_eod; /* The string that clears from the cursor to */ - /* the end of the display. */ - const char *u_arrow; /* The string returned by the up-arrow key */ - const char *d_arrow; /* The string returned by the down-arrow key */ - const char *l_arrow; /* The string returned by the left-arrow key */ - const char *r_arrow; /* The string returned by the right-arrow key */ - const char *sound_bell; /* The string needed to ring the terminal bell */ - const char *bold; /* Switch to the bold font */ - const char *underline; /* Underline subsequent characters */ - const char *standout; /* Turn on standout mode */ - const char *dim; /* Switch to a dim font */ - const char *reverse; /* Turn on reverse video */ - const char *blink; /* Switch to a blinking font */ - const char *text_attr_off; /* Turn off all text attributes */ - int nline; /* The height of the terminal in lines */ - int ncolumn; /* The width of the terminal in columns */ -#ifdef USE_TERMCAP - char *tgetent_buf; /* The buffer that is used by tgetent() to */ - /* store a terminal description. */ - char *tgetstr_buf; /* The buffer that is used by tgetstr() to */ - /* store terminal capabilities. */ -#endif -#ifdef USE_TERMINFO - const char *left_n; /* The parameter string that moves the cursor */ - /* n characters left. */ - const char *right_n; /* The parameter string that moves the cursor */ - /* n characters right. */ -#endif - char *app_file; /* The pathname of the application-specific */ - /* .teclarc configuration file, or NULL. */ - char *user_file; /* The pathname of the user-specific */ - /* .teclarc configuration file, or NULL. */ - int configured; /* True as soon as any teclarc configuration */ - /* file has been read. */ - int echo; /* True to display the line as it is being */ - /* entered. If 0, only the prompt will be */ - /* displayed, and the line will not be */ - /* archived in the history list. */ - int last_signal; /* The last signal that was caught by */ - /* the last call to gl_get_line(), or -1 */ - /* if no signal has been caught yet. */ -#ifdef HAVE_SELECT - FreeList *fd_node_mem; /* A freelist of GlFdNode structures */ - GlFdNode *fd_nodes; /* The list of fd event descriptions */ - fd_set rfds; /* The set of fds to watch for readability */ - fd_set wfds; /* The set of fds to watch for writability */ - fd_set ufds; /* The set of fds to watch for urgent data */ - int max_fd; /* The maximum file-descriptor being watched */ -#endif -}; - -/* - * Define the max amount of space needed to store a termcap terminal - * description. Unfortunately this has to be done by guesswork, so - * there is the potential for buffer overflows if we guess too small. - * Fortunately termcap has been replaced by terminfo on most - * platforms, and with terminfo this isn't an issue. The value that I - * am using here is the conventional value, as recommended by certain - * web references. - */ -#ifdef USE_TERMCAP -#define TERMCAP_BUF_SIZE 2048 -#endif - -/* - * Set the size of the string segments used to store terminal capability - * strings. - */ -#define CAPMEM_SEGMENT_SIZE 512 - -/* - * If no terminal size information is available, substitute the - * following vt100 default sizes. - */ -#define GL_DEF_NLINE 24 -#define GL_DEF_NCOLUMN 80 - -/* - * List the signals that we need to catch. In general these are - * those that by default terminate or suspend the process, since - * in such cases we need to restore terminal settings. - */ -static const struct GlDefSignal { - int signo; /* The number of the signal */ - unsigned flags; /* A bitwise union of GlSignalFlags enumerators */ - GlAfterSignal after; /* What to do after the signal has been delivered */ - int errno_value; /* What to set errno to */ -} gl_signal_list[] = { - {SIGABRT, GLS_SUSPEND_INPUT, GLS_ABORT, EINTR}, - {SIGINT, GLS_SUSPEND_INPUT, GLS_ABORT, EINTR}, - {SIGTERM, GLS_SUSPEND_INPUT, GLS_ABORT, EINTR}, - {SIGALRM, GLS_RESTORE_ENV, GLS_CONTINUE, 0}, - {SIGCONT, GLS_RESTORE_ENV, GLS_CONTINUE, 0}, -#if defined(SIGHUP) -#ifdef ENOTTY - {SIGHUP, GLS_SUSPEND_INPUT, GLS_ABORT, ENOTTY}, -#else - {SIGHUP, GLS_SUSPEND_INPUT, GLS_ABORT, EINTR}, -#endif -#endif -#if defined(SIGPIPE) -#ifdef EPIPE - {SIGPIPE, GLS_SUSPEND_INPUT, GLS_ABORT, EPIPE}, -#else - {SIGPIPE, GLS_SUSPEND_INPUT, GLS_ABORT, EINTR}, -#endif -#endif -#ifdef SIGPWR - {SIGPWR, GLS_RESTORE_ENV, GLS_CONTINUE, 0}, -#endif -#ifdef SIGQUIT - {SIGQUIT, GLS_SUSPEND_INPUT, GLS_ABORT, EINTR}, -#endif -#ifdef SIGTSTP - {SIGTSTP, GLS_SUSPEND_INPUT, GLS_CONTINUE, 0}, -#endif -#ifdef SIGTTIN - {SIGTTIN, GLS_SUSPEND_INPUT, GLS_CONTINUE, 0}, -#endif -#ifdef SIGTTOU - {SIGTTOU, GLS_SUSPEND_INPUT, GLS_CONTINUE, 0}, -#endif -#ifdef SIGUSR1 - {SIGUSR1, GLS_RESTORE_ENV, GLS_CONTINUE, 0}, -#endif -#ifdef SIGUSR2 - {SIGUSR2, GLS_RESTORE_ENV, GLS_CONTINUE, 0}, -#endif -#ifdef SIGVTALRM - {SIGVTALRM, GLS_RESTORE_ENV, GLS_CONTINUE, 0}, -#endif -#ifdef SIGWINCH - {SIGWINCH, GLS_RESTORE_ENV, GLS_CONTINUE, 0}, -#endif -#ifdef SIGXCPU - {SIGXCPU, GLS_RESTORE_ENV, GLS_CONTINUE, 0}, -#endif -}; - -/* - * Define file-scope variables for use in signal handlers. - */ -static volatile sig_atomic_t gl_pending_signal = -1; -static sigjmp_buf gl_setjmp_buffer; - -static void gl_signal_handler(int signo); - -static int gl_check_caught_signal(GetLine *gl); - -/* - * Define a tab to be a string of 8 spaces. - */ -#define TAB_WIDTH 8 - -/* - * Does the system send us SIGWINCH signals when the terminal size - * changes? - */ -#ifdef USE_SIGWINCH -static int gl_resize_terminal(GetLine *gl, int redisplay); -#endif - -/* - * Getline calls this to temporarily override certain signal handlers - * of the calling program. - */ -static int gl_override_signal_handlers(GetLine *gl); - -/* - * Getline calls this to restore the signal handlers of the calling - * program. - */ -static int gl_restore_signal_handlers(GetLine *gl); - -/* - * Put the terminal into raw input mode, after saving the original - * terminal attributes in gl->oldattr. - */ -static int gl_raw_terminal_mode(GetLine *gl); - -/* - * Restore the terminal attributes from gl->oldattr. - */ -static int gl_restore_terminal_attributes(GetLine *gl); - -/* - * Read a line from the user in raw mode. - */ -static int gl_get_input_line(GetLine *gl, const char *start_line, - int start_pos); - -/* - * Set the largest key-sequence that can be handled. - */ -#define GL_KEY_MAX 64 - -/* - * Handle the receipt of the potential start of a new key-sequence from - * the user. - */ -static int gl_interpret_char(GetLine *gl, char c); - -/* - * Bind a single control or meta character to an action. - */ -static int gl_bind_control_char(GetLine *gl, KtBinder binder, - char c, const char *action); - -/* - * Set up terminal-specific key bindings. - */ -static int gl_bind_terminal_keys(GetLine *gl); - -/* - * Lookup terminal control string and size information. - */ -static int gl_control_strings(GetLine *gl, const char *term); - -/* - * Wrappers around the terminfo and termcap functions that lookup - * strings in the terminal information databases. - */ -#ifdef USE_TERMINFO -static const char *gl_tigetstr(GetLine *gl, const char *name); -#elif defined(USE_TERMCAP) -static const char *gl_tgetstr(GetLine *gl, const char *name, char **bufptr); -#endif - -/* - * Output a binary string directly to the terminal. - */ -static int gl_output_raw_string(GetLine *gl, const char *string); - -/* - * Output a terminal control sequence. - */ -static int gl_output_control_sequence(GetLine *gl, int nline, - const char *string); - -/* - * Output a character or string to the terminal after converting tabs - * to spaces and control characters to a caret followed by the modified - * character. - */ -static int gl_output_char(GetLine *gl, char c, char pad); -static int gl_output_string(GetLine *gl, const char *string, char pad); - -/* - * Delete nc characters starting from the one under the cursor. - * Optionally copy the deleted characters to the cut buffer. - */ -static int gl_delete_chars(GetLine *gl, int nc, int cut); - -/* - * Add a character to the line buffer at the current cursor position, - * inserting or overwriting according the current mode. - */ -static int gl_add_char_to_line(GetLine *gl, char c); - -/* - * Insert/append a string to the line buffer and terminal at the current - * cursor position. - */ -static int gl_add_string_to_line(GetLine *gl, const char *s); - -/* - * Read a single character from the terminal. - */ -static int gl_read_character(GetLine *gl, char *c); - - -/* - * Move the terminal cursor n positions to the left or right. - */ -static int gl_terminal_move_cursor(GetLine *gl, int n); - -/* - * Move the terminal cursor to a given position. - */ -static int gl_set_term_curpos(GetLine *gl, int term_curpos); - -/* - * Set the position of the cursor both in the line input buffer and on the - * terminal. - */ -static int gl_place_cursor(GetLine *gl, int buff_curpos); - -/* - * Return the terminal cursor position that corresponds to a given - * line buffer cursor position. - */ -static int gl_buff_curpos_to_term_curpos(GetLine *gl, int buff_curpos); - -/* - * Return the number of terminal characters needed to display a - * given raw character. - */ -static int gl_displayed_char_width(GetLine *gl, char c, int term_curpos); - -/* - * Return the number of terminal characters needed to display a - * given substring. - */ -static int gl_displayed_string_width(GetLine *gl, const char *string, int nc, - int term_curpos); -/* - * Return non-zero if 'c' is to be considered part of a word. - */ -static int gl_is_word_char(int c); - -/* - * Read a tecla configuration file. - */ -static int _gl_read_config_file(GetLine *gl, const char *filename, KtBinder who); - -/* - * Read a tecla configuration string. - */ -static int _gl_read_config_string(GetLine *gl, const char *buffer, KtBinder who); - -/* - * Define the callback function used by _gl_parse_config_line() to - * read the next character of a configuration stream. - */ -#define GLC_GETC_FN(fn) int (fn)(void *stream) -typedef GLC_GETC_FN(GlcGetcFn); - -static GLC_GETC_FN(glc_file_getc); /* Read from a file */ -static GLC_GETC_FN(glc_buff_getc); /* Read from a string */ - -/* - * Parse a single configuration command line. - */ -static int _gl_parse_config_line(GetLine *gl, void *stream, GlcGetcFn *getc_fn, - const char *origin, KtBinder who, int *lineno); - -/* - * Bind the actual arrow key bindings to match those of the symbolic - * arrow-key bindings. - */ -static int _gl_bind_arrow_keys(GetLine *gl); - -/* - * Copy the binding of the specified symbolic arrow-key binding to - * the terminal specific, and default arrow-key key-sequences. - */ -static int _gl_rebind_arrow_key(KeyTab *bindings, const char *name, - const char *term_seq, - const char *def_seq1, - const char *def_seq2); - -/* - * After the gl_read_from_file() action has been used to tell gl_get_line() - * to temporarily read input from a file, gl_revert_input() arranges - * for input to be reverted to the input stream last registered with - * gl_change_terminal(). - */ -static void gl_revert_input(GetLine *gl); - -/* - * Flush unwritten characters to the terminal. - */ -static int gl_flush_output(GetLine *gl); - -/* - * Change the editor style being emulated. - */ -static int gl_change_editor(GetLine *gl, GlEditor editor); - -/* - * Searching in a given direction, return the index of a given (or - * read) character in the input line, or the character that precedes - * it in the specified search direction. Return -1 if not found. - */ -static int gl_find_char(GetLine *gl, int count, int forward, int onto, char c); - -/* - * Return the buffer index of the nth word ending after the cursor. - */ -static int gl_nth_word_end_forward(GetLine *gl, int n); - -/* - * Return the buffer index of the nth word start after the cursor. - */ -static int gl_nth_word_start_forward(GetLine *gl, int n); - -/* - * Return the buffer index of the nth word start before the cursor. - */ -static int gl_nth_word_start_backward(GetLine *gl, int n); - -/* - * When called when vi command mode is enabled, this function saves the - * current line and cursor position for potential restoration later - * by the vi undo command. - */ -static void gl_save_for_undo(GetLine *gl); - -/* - * If in vi mode, switch to vi command mode. - */ -static void gl_vi_command_mode(GetLine *gl); - -/* - * In vi mode this is used to delete up to or onto a given or read - * character in the input line. Also switch to insert mode if requested - * after the deletion. - */ -static int gl_delete_find(GetLine *gl, int count, char c, int forward, - int onto, int change); - -/* - * Copy the characters between the cursor and the count'th instance of - * a specified (or read) character in the input line, into the cut buffer. - */ -static int gl_copy_find(GetLine *gl, int count, char c, int forward, int onto); - -/* - * Return the line index of the parenthesis that either matches the one under - * the cursor, or not over a parenthesis character, the index of the next - * close parenthesis. Return -1 if not found. - */ -static int gl_index_of_matching_paren(GetLine *gl); - -/* - * Replace a malloc'd string (or NULL), with another malloc'd copy of - * a string (or NULL). - */ -static int gl_record_string(char **sptr, const char *string); - -/* - * Enumerate text display attributes as powers of two, suitable for - * use in a bit-mask. - */ -typedef enum { - GL_TXT_STANDOUT=1, /* Display text highlighted */ - GL_TXT_UNDERLINE=2, /* Display text underlined */ - GL_TXT_REVERSE=4, /* Display text with reverse video */ - GL_TXT_BLINK=8, /* Display blinking text */ - GL_TXT_DIM=16, /* Display text in a dim font */ - GL_TXT_BOLD=32 /* Display text using a bold font */ -} GlTextAttr; - -/* - * Display the prompt regardless of the current visibility mode. - */ -static int gl_display_prompt(GetLine *gl); - -/* - * Return the number of characters used by the prompt on the terminal. - */ -static int gl_displayed_prompt_width(GetLine *gl); - -/* - * Prepare the return the current input line to the caller of gl_get_line(). - */ -static int gl_line_ended(GetLine *gl, int newline_char, int archive); - -/* - * Set the maximum length of a line in a user's tecla configuration - * file (not counting comments). - */ -#define GL_CONF_BUFLEN 100 - -/* - * Set the maximum number of arguments supported by individual commands - * in tecla configuration files. - */ -#define GL_CONF_MAXARG 10 - -/* - * Prototype the available action functions. - */ -static KT_KEY_FN(gl_user_interrupt); -static KT_KEY_FN(gl_abort); -static KT_KEY_FN(gl_suspend); -static KT_KEY_FN(gl_stop_output); -static KT_KEY_FN(gl_start_output); -static KT_KEY_FN(gl_literal_next); -static KT_KEY_FN(gl_cursor_left); -static KT_KEY_FN(gl_cursor_right); -static KT_KEY_FN(gl_insert_mode); -static KT_KEY_FN(gl_beginning_of_line); -static KT_KEY_FN(gl_end_of_line); -static KT_KEY_FN(gl_delete_line); -static KT_KEY_FN(gl_kill_line); -static KT_KEY_FN(gl_forward_word); -static KT_KEY_FN(gl_backward_word); -static KT_KEY_FN(gl_forward_delete_char); -static KT_KEY_FN(gl_backward_delete_char); -static KT_KEY_FN(gl_forward_delete_word); -static KT_KEY_FN(gl_backward_delete_word); -static KT_KEY_FN(gl_delete_refind); -static KT_KEY_FN(gl_delete_invert_refind); -static KT_KEY_FN(gl_delete_to_column); -static KT_KEY_FN(gl_delete_to_parenthesis); -static KT_KEY_FN(gl_forward_delete_find); -static KT_KEY_FN(gl_backward_delete_find); -static KT_KEY_FN(gl_forward_delete_to); -static KT_KEY_FN(gl_backward_delete_to); -static KT_KEY_FN(gl_upcase_word); -static KT_KEY_FN(gl_downcase_word); -static KT_KEY_FN(gl_capitalize_word); -static KT_KEY_FN(gl_redisplay); -static KT_KEY_FN(gl_clear_screen); -static KT_KEY_FN(gl_transpose_chars); -static KT_KEY_FN(gl_set_mark); -static KT_KEY_FN(gl_exchange_point_and_mark); -static KT_KEY_FN(gl_kill_region); -static KT_KEY_FN(gl_copy_region_as_kill); -static KT_KEY_FN(gl_yank); -static KT_KEY_FN(gl_up_history); -static KT_KEY_FN(gl_down_history); -static KT_KEY_FN(gl_history_search_backward); -static KT_KEY_FN(gl_history_re_search_backward); -static KT_KEY_FN(gl_history_search_forward); -static KT_KEY_FN(gl_history_re_search_forward); -static KT_KEY_FN(gl_complete_word); -static KT_KEY_FN(gl_expand_filename); -static KT_KEY_FN(gl_del_char_or_list_or_eof); -static KT_KEY_FN(gl_list_or_eof); -static KT_KEY_FN(gl_read_from_file); -static KT_KEY_FN(gl_beginning_of_history); -static KT_KEY_FN(gl_end_of_history); -static KT_KEY_FN(gl_digit_argument); -static KT_KEY_FN(gl_newline); -static KT_KEY_FN(gl_repeat_history); -static KT_KEY_FN(gl_vi_insert); -static KT_KEY_FN(gl_vi_overwrite); -static KT_KEY_FN(gl_change_case); -static KT_KEY_FN(gl_vi_insert_at_bol); -static KT_KEY_FN(gl_vi_append_at_eol); -static KT_KEY_FN(gl_vi_append); -static KT_KEY_FN(gl_list_glob); -static KT_KEY_FN(gl_backward_kill_line); -static KT_KEY_FN(gl_goto_column); -static KT_KEY_FN(gl_forward_to_word); -static KT_KEY_FN(gl_vi_replace_char); -static KT_KEY_FN(gl_vi_change_rest_of_line); -static KT_KEY_FN(gl_vi_change_line); -static KT_KEY_FN(gl_vi_change_to_bol); -static KT_KEY_FN(gl_vi_change_refind); -static KT_KEY_FN(gl_vi_change_invert_refind); -static KT_KEY_FN(gl_vi_change_to_column); -static KT_KEY_FN(gl_vi_change_to_parenthesis); -static KT_KEY_FN(gl_vi_forward_change_word); -static KT_KEY_FN(gl_vi_backward_change_word); -static KT_KEY_FN(gl_vi_forward_change_find); -static KT_KEY_FN(gl_vi_backward_change_find); -static KT_KEY_FN(gl_vi_forward_change_to); -static KT_KEY_FN(gl_vi_backward_change_to); -static KT_KEY_FN(gl_vi_forward_change_char); -static KT_KEY_FN(gl_vi_backward_change_char); -static KT_KEY_FN(gl_forward_copy_char); -static KT_KEY_FN(gl_backward_copy_char); -static KT_KEY_FN(gl_forward_find_char); -static KT_KEY_FN(gl_backward_find_char); -static KT_KEY_FN(gl_forward_to_char); -static KT_KEY_FN(gl_backward_to_char); -static KT_KEY_FN(gl_repeat_find_char); -static KT_KEY_FN(gl_invert_refind_char); -static KT_KEY_FN(gl_append_yank); -static KT_KEY_FN(gl_backward_copy_word); -static KT_KEY_FN(gl_forward_copy_word); -static KT_KEY_FN(gl_copy_to_bol); -static KT_KEY_FN(gl_copy_refind); -static KT_KEY_FN(gl_copy_invert_refind); -static KT_KEY_FN(gl_copy_to_column); -static KT_KEY_FN(gl_copy_to_parenthesis); -static KT_KEY_FN(gl_copy_rest_of_line); -static KT_KEY_FN(gl_copy_line); -static KT_KEY_FN(gl_backward_copy_find); -static KT_KEY_FN(gl_forward_copy_find); -static KT_KEY_FN(gl_backward_copy_to); -static KT_KEY_FN(gl_forward_copy_to); -static KT_KEY_FN(gl_vi_undo); -static KT_KEY_FN(gl_emacs_editing_mode); -static KT_KEY_FN(gl_vi_editing_mode); -static KT_KEY_FN(gl_ring_bell); -static KT_KEY_FN(gl_vi_repeat_change); -static KT_KEY_FN(gl_find_parenthesis); -static KT_KEY_FN(gl_read_init_files); -static KT_KEY_FN(gl_list_history); - -/* - * Name the available action functions. - */ -static const struct {const char *name; KT_KEY_FN(*fn);} gl_actions[] = { - {"user-interrupt", gl_user_interrupt}, - {"abort", gl_abort}, - {"suspend", gl_suspend}, - {"stop-output", gl_stop_output}, - {"start-output", gl_start_output}, - {"literal-next", gl_literal_next}, - {"cursor-right", gl_cursor_right}, - {"cursor-left", gl_cursor_left}, - {"insert-mode", gl_insert_mode}, - {"beginning-of-line", gl_beginning_of_line}, - {"end-of-line", gl_end_of_line}, - {"delete-line", gl_delete_line}, - {"kill-line", gl_kill_line}, - {"forward-word", gl_forward_word}, - {"backward-word", gl_backward_word}, - {"forward-delete-char", gl_forward_delete_char}, - {"backward-delete-char", gl_backward_delete_char}, - {"forward-delete-word", gl_forward_delete_word}, - {"backward-delete-word", gl_backward_delete_word}, - {"delete-refind", gl_delete_refind}, - {"delete-invert-refind", gl_delete_invert_refind}, - {"delete-to-column", gl_delete_to_column}, - {"delete-to-parenthesis", gl_delete_to_parenthesis}, - {"forward-delete-find", gl_forward_delete_find}, - {"backward-delete-find", gl_backward_delete_find}, - {"forward-delete-to", gl_forward_delete_to}, - {"backward-delete-to", gl_backward_delete_to}, - {"upcase-word", gl_upcase_word}, - {"downcase-word", gl_downcase_word}, - {"capitalize-word", gl_capitalize_word}, - {"redisplay", gl_redisplay}, - {"clear-screen", gl_clear_screen}, - {"transpose-chars", gl_transpose_chars}, - {"set-mark", gl_set_mark}, - {"exchange-point-and-mark", gl_exchange_point_and_mark}, - {"kill-region", gl_kill_region}, - {"copy-region-as-kill", gl_copy_region_as_kill}, - {"yank", gl_yank}, - {"up-history", gl_up_history}, - {"down-history", gl_down_history}, - {"history-search-backward", gl_history_search_backward}, - {"history-re-search-backward", gl_history_re_search_backward}, - {"history-search-forward", gl_history_search_forward}, - {"history-re-search-forward", gl_history_re_search_forward}, - {"complete-word", gl_complete_word}, - {"expand-filename", gl_expand_filename}, - {"del-char-or-list-or-eof", gl_del_char_or_list_or_eof}, - {"read-from-file", gl_read_from_file}, - {"beginning-of-history", gl_beginning_of_history}, - {"end-of-history", gl_end_of_history}, - {"digit-argument", gl_digit_argument}, - {"newline", gl_newline}, - {"repeat-history", gl_repeat_history}, - {"vi-insert", gl_vi_insert}, - {"vi-overwrite", gl_vi_overwrite}, - {"vi-insert-at-bol", gl_vi_insert_at_bol}, - {"vi-append-at-eol", gl_vi_append_at_eol}, - {"vi-append", gl_vi_append}, - {"change-case", gl_change_case}, - {"list-glob", gl_list_glob}, - {"backward-kill-line", gl_backward_kill_line}, - {"goto-column", gl_goto_column}, - {"forward-to-word", gl_forward_to_word}, - {"vi-replace-char", gl_vi_replace_char}, - {"vi-change-rest-of-line", gl_vi_change_rest_of_line}, - {"vi-change-line", gl_vi_change_line}, - {"vi-change-to-bol", gl_vi_change_to_bol}, - {"vi-change-refind", gl_vi_change_refind}, - {"vi-change-invert-refind", gl_vi_change_invert_refind}, - {"vi-change-to-column", gl_vi_change_to_column}, - {"vi-change-to-parenthesis", gl_vi_change_to_parenthesis}, - {"forward-copy-char", gl_forward_copy_char}, - {"backward-copy-char", gl_backward_copy_char}, - {"forward-find-char", gl_forward_find_char}, - {"backward-find-char", gl_backward_find_char}, - {"forward-to-char", gl_forward_to_char}, - {"backward-to-char", gl_backward_to_char}, - {"repeat-find-char", gl_repeat_find_char}, - {"invert-refind-char", gl_invert_refind_char}, - {"append-yank", gl_append_yank}, - {"backward-copy-word", gl_backward_copy_word}, - {"forward-copy-word", gl_forward_copy_word}, - {"copy-to-bol", gl_copy_to_bol}, - {"copy-refind", gl_copy_refind}, - {"copy-invert-refind", gl_copy_invert_refind}, - {"copy-to-column", gl_copy_to_column}, - {"copy-to-parenthesis", gl_copy_to_parenthesis}, - {"copy-rest-of-line", gl_copy_rest_of_line}, - {"copy-line", gl_copy_line}, - {"backward-copy-find", gl_backward_copy_find}, - {"forward-copy-find", gl_forward_copy_find}, - {"backward-copy-to", gl_backward_copy_to}, - {"forward-copy-to", gl_forward_copy_to}, - {"list-or-eof", gl_list_or_eof}, - {"vi-undo", gl_vi_undo}, - {"vi-backward-change-word", gl_vi_backward_change_word}, - {"vi-forward-change-word", gl_vi_forward_change_word}, - {"vi-backward-change-find", gl_vi_backward_change_find}, - {"vi-forward-change-find", gl_vi_forward_change_find}, - {"vi-backward-change-to", gl_vi_backward_change_to}, - {"vi-forward-change-to", gl_vi_forward_change_to}, - {"vi-backward-change-char", gl_vi_backward_change_char}, - {"vi-forward-change-char", gl_vi_forward_change_char}, - {"emacs-mode", gl_emacs_editing_mode}, - {"vi-mode", gl_vi_editing_mode}, - {"ring-bell", gl_ring_bell}, - {"vi-repeat-change", gl_vi_repeat_change}, - {"find-parenthesis", gl_find_parenthesis}, - {"read-init-files", gl_read_init_files}, - {"list-history", gl_list_history}, -}; - -/* - * Define the default key-bindings in emacs mode. - */ -static const KtKeyBinding gl_emacs_bindings[] = { - {"right", "cursor-right"}, - {"^F", "cursor-right"}, - {"left", "cursor-left"}, - {"^B", "cursor-left"}, - {"M-i", "insert-mode"}, - {"M-I", "insert-mode"}, - {"^A", "beginning-of-line"}, - {"^E", "end-of-line"}, - {"^U", "delete-line"}, - {"^K", "kill-line"}, - {"M-f", "forward-word"}, - {"M-F", "forward-word"}, - {"M-b", "backward-word"}, - {"M-B", "backward-word"}, - {"^D", "del-char-or-list-or-eof"}, - {"^H", "backward-delete-char"}, - {"^?", "backward-delete-char"}, - {"M-d", "forward-delete-word"}, - {"M-D", "forward-delete-word"}, - {"M-^H", "backward-delete-word"}, - {"M-^?", "backward-delete-word"}, - {"M-u", "upcase-word"}, - {"M-U", "upcase-word"}, - {"M-l", "downcase-word"}, - {"M-L", "downcase-word"}, - {"M-c", "capitalize-word"}, - {"M-C", "capitalize-word"}, - {"^R", "redisplay"}, - {"^L", "clear-screen"}, - {"^T", "transpose-chars"}, - {"^@", "set-mark"}, - {"^X^X", "exchange-point-and-mark"}, - {"^W", "kill-region"}, - {"M-w", "copy-region-as-kill"}, - {"M-W", "copy-region-as-kill"}, - {"^Y", "yank"}, - {"^P", "up-history"}, - {"up", "up-history"}, - {"^N", "down-history"}, - {"down", "down-history"}, - {"M-p", "history-search-backward"}, - {"M-P", "history-search-backward"}, - {"M-n", "history-search-forward"}, - {"M-N", "history-search-forward"}, - {"\t", "complete-word"}, - {"^X*", "expand-filename"}, - {"^X^F", "read-from-file"}, - {"^X^R", "read-init-files"}, - {"^Xg", "list-glob"}, - {"^XG", "list-glob"}, - {"^Xh", "list-history"}, - {"^XH", "list-history"}, - {"M-<", "beginning-of-history"}, - {"M->", "end-of-history"}, - {"M-0", "digit-argument"}, - {"M-1", "digit-argument"}, - {"M-2", "digit-argument"}, - {"M-3", "digit-argument"}, - {"M-4", "digit-argument"}, - {"M-5", "digit-argument"}, - {"M-6", "digit-argument"}, - {"M-7", "digit-argument"}, - {"M-8", "digit-argument"}, - {"M-9", "digit-argument"}, - {"\r", "newline"}, - {"\n", "newline"}, - {"M-o", "repeat-history"}, - {"M-C-v", "vi-mode"}, -}; - -/* - * Define the default key-bindings in vi mode. Note that in vi-mode - * meta-key bindings are command-mode bindings. For example M-i first - * switches to command mode if not already in that mode, then moves - * the cursor one position right, as in vi. - */ -static const KtKeyBinding gl_vi_bindings[] = { - {"^D", "list-or-eof"}, - {"^G", "list-glob"}, - {"^H", "backward-delete-char"}, - {"\t", "complete-word"}, - {"\r", "newline"}, - {"\n", "newline"}, - {"^L", "clear-screen"}, - {"^N", "down-history"}, - {"^P", "up-history"}, - {"^R", "redisplay"}, - {"^U", "backward-kill-line"}, - {"^W", "backward-delete-word"}, - {"^X^F", "read-from-file"}, - {"^X^R", "read-init-files"}, - {"^X*", "expand-filename"}, - {"^?", "backward-delete-char"}, - {"M- ", "cursor-right"}, - {"M-$", "end-of-line"}, - {"M-*", "expand-filename"}, - {"M-+", "down-history"}, - {"M--", "up-history"}, - {"M-<", "beginning-of-history"}, - {"M->", "end-of-history"}, - {"M-^", "beginning-of-line"}, - {"M-;", "repeat-find-char"}, - {"M-,", "invert-refind-char"}, - {"M-|", "goto-column"}, - {"M-~", "change-case"}, - {"M-.", "vi-repeat-change"}, - {"M-%", "find-parenthesis"}, - {"M-0", "digit-argument"}, - {"M-1", "digit-argument"}, - {"M-2", "digit-argument"}, - {"M-3", "digit-argument"}, - {"M-4", "digit-argument"}, - {"M-5", "digit-argument"}, - {"M-6", "digit-argument"}, - {"M-7", "digit-argument"}, - {"M-8", "digit-argument"}, - {"M-9", "digit-argument"}, - {"M-a", "vi-append"}, - {"M-A", "vi-append-at-eol"}, - {"M-b", "backward-word"}, - {"M-B", "backward-word"}, - {"M-C", "vi-change-rest-of-line"}, - {"M-cb", "vi-backward-change-word"}, - {"M-cB", "vi-backward-change-word"}, - {"M-cc", "vi-change-line"}, - {"M-ce", "vi-forward-change-word"}, - {"M-cE", "vi-forward-change-word"}, - {"M-cw", "vi-forward-change-word"}, - {"M-cW", "vi-forward-change-word"}, - {"M-cF", "vi-backward-change-find"}, - {"M-cf", "vi-forward-change-find"}, - {"M-cT", "vi-backward-change-to"}, - {"M-ct", "vi-forward-change-to"}, - {"M-c;", "vi-change-refind"}, - {"M-c,", "vi-change-invert-refind"}, - {"M-ch", "vi-backward-change-char"}, - {"M-c^H", "vi-backward-change-char"}, - {"M-c^?", "vi-backward-change-char"}, - {"M-cl", "vi-forward-change-char"}, - {"M-c ", "vi-forward-change-char"}, - {"M-c^", "vi-change-to-bol"}, - {"M-c0", "vi-change-to-bol"}, - {"M-c$", "vi-change-rest-of-line"}, - {"M-c|", "vi-change-to-column"}, - {"M-c%", "vi-change-to-parenthesis"}, - {"M-dh", "backward-delete-char"}, - {"M-d^H", "backward-delete-char"}, - {"M-d^?", "backward-delete-char"}, - {"M-dl", "forward-delete-char"}, - {"M-d ", "forward-delete-char"}, - {"M-dd", "delete-line"}, - {"M-db", "backward-delete-word"}, - {"M-dB", "backward-delete-word"}, - {"M-de", "forward-delete-word"}, - {"M-dE", "forward-delete-word"}, - {"M-dw", "forward-delete-word"}, - {"M-dW", "forward-delete-word"}, - {"M-dF", "backward-delete-find"}, - {"M-df", "forward-delete-find"}, - {"M-dT", "backward-delete-to"}, - {"M-dt", "forward-delete-to"}, - {"M-d;", "delete-refind"}, - {"M-d,", "delete-invert-refind"}, - {"M-d^", "backward-kill-line"}, - {"M-d0", "backward-kill-line"}, - {"M-d$", "kill-line"}, - {"M-D", "kill-line"}, - {"M-d|", "delete-to-column"}, - {"M-d%", "delete-to-parenthesis"}, - {"M-e", "forward-word"}, - {"M-E", "forward-word"}, - {"M-f", "forward-find-char"}, - {"M-F", "backward-find-char"}, - {"M--", "up-history"}, - {"M-h", "cursor-left"}, - {"M-H", "beginning-of-history"}, - {"M-i", "vi-insert"}, - {"M-I", "vi-insert-at-bol"}, - {"M-j", "down-history"}, - {"M-J", "history-search-forward"}, - {"M-k", "up-history"}, - {"M-K", "history-search-backward"}, - {"M-l", "cursor-right"}, - {"M-L", "end-of-history"}, - {"M-n", "history-re-search-forward"}, - {"M-N", "history-re-search-backward"}, - {"M-p", "append-yank"}, - {"M-P", "yank"}, - {"M-r", "vi-replace-char"}, - {"M-R", "vi-overwrite"}, - {"M-s", "vi-forward-change-char"}, - {"M-S", "vi-change-line"}, - {"M-t", "forward-to-char"}, - {"M-T", "backward-to-char"}, - {"M-u", "vi-undo"}, - {"M-w", "forward-to-word"}, - {"M-W", "forward-to-word"}, - {"M-x", "forward-delete-char"}, - {"M-X", "backward-delete-char"}, - {"M-yh", "backward-copy-char"}, - {"M-y^H", "backward-copy-char"}, - {"M-y^?", "backward-copy-char"}, - {"M-yl", "forward-copy-char"}, - {"M-y ", "forward-copy-char"}, - {"M-ye", "forward-copy-word"}, - {"M-yE", "forward-copy-word"}, - {"M-yw", "forward-copy-word"}, - {"M-yW", "forward-copy-word"}, - {"M-yb", "backward-copy-word"}, - {"M-yB", "backward-copy-word"}, - {"M-yf", "forward-copy-find"}, - {"M-yF", "backward-copy-find"}, - {"M-yt", "forward-copy-to"}, - {"M-yT", "backward-copy-to"}, - {"M-y;", "copy-refind"}, - {"M-y,", "copy-invert-refind"}, - {"M-y^", "copy-to-bol"}, - {"M-y0", "copy-to-bol"}, - {"M-y$", "copy-rest-of-line"}, - {"M-yy", "copy-line"}, - {"M-Y", "copy-line"}, - {"M-y|", "copy-to-column"}, - {"M-y%", "copy-to-parenthesis"}, - {"M-^E", "emacs-mode"}, - {"M-^H", "cursor-left"}, - {"M-^?", "cursor-left"}, - {"M-^L", "clear-screen"}, - {"M-^N", "down-history"}, - {"M-^P", "up-history"}, - {"M-^R", "redisplay"}, - {"M-^D", "list-or-eof"}, - {"M-\r", "newline"}, - {"M-\t", "complete-word"}, - {"M-\n", "newline"}, - {"M-^X^R", "read-init-files"}, - {"M-^Xh", "list-history"}, - {"M-^XH", "list-history"}, - {"down", "down-history"}, - {"up", "up-history"}, - {"left", "cursor-left"}, - {"right", "cursor-right"}, -}; - -/*....................................................................... - * Create a new GetLine object. - * - * Input: - * linelen size_t The maximum line length to allow for. - * histlen size_t The number of bytes to allocate for recording - * a circular buffer of history lines. - * Output: - * return GetLine * The new object, or NULL on error. - */ -GetLine *new_GetLine(size_t linelen, size_t histlen) -{ - GetLine *gl; /* The object to be returned */ - int i; -/* - * Check the arguments. - */ - if(linelen < 10) { - fprintf(stderr, "new_GetLine: Line length too small.\n"); - return NULL; - }; -/* - * Allocate the container. - */ - gl = (GetLine *) malloc(sizeof(GetLine)); - if(!gl) { - fprintf(stderr, "new_GetLine: Insufficient memory.\n"); - return NULL; - }; -/* - * Before attempting any operation that might fail, initialize the - * container at least up to the point at which it can safely be passed - * to del_GetLine(). - */ - gl->glh = NULL; - gl->cpl = NULL; - gl->cpl_fn = cpl_file_completions; - gl->cpl_data = NULL; - gl->ef = NULL; - gl->capmem = NULL; - gl->term = NULL; - gl->is_term = 0; - gl->input_fd = -1; - gl->output_fd = -1; - gl->input_fp = NULL; - gl->output_fp = NULL; - gl->file_fp = NULL; - gl->linelen = linelen; - gl->line = NULL; - gl->cutbuf = NULL; - gl->linelen = linelen; - gl->prompt = ""; - gl->prompt_len = 0; - gl->prompt_changed = 0; - gl->prompt_style = GL_LITERAL_PROMPT; - gl->vi.undo.line = NULL; - gl->vi.undo.buff_curpos = 0; - gl->vi.undo.ntotal = 0; - gl->vi.undo.saved = 0; - gl->vi.repeat.fn = 0; - gl->vi.repeat.count = 0; - gl->vi.repeat.input_curpos = 0; - gl->vi.repeat.command_curpos = 0; - gl->vi.repeat.input_char = '\0'; - gl->vi.repeat.saved = 0; - gl->vi.repeat.active = 0; - gl->sig_mem = NULL; - gl->sigs = NULL; - sigemptyset(&gl->old_signal_set); - sigemptyset(&gl->new_signal_set); - gl->bindings = NULL; - gl->ntotal = 0; - gl->buff_curpos = 0; - gl->term_curpos = 0; - gl->buff_mark = 0; - gl->insert_curpos = 0; - gl->insert = 1; - gl->number = -1; - gl->endline = 0; - gl->current_fn = 0; - gl->current_count = 0; - gl->preload_id = 0; - gl->preload_history = 0; - gl->keyseq_count = 0; - gl->last_search = -1; - gl->editor = GL_EMACS_MODE; - gl->silence_bell = 0; - gl->vi.command = 0; - gl->vi.find_forward = 0; - gl->vi.find_onto = 0; - gl->vi.find_char = '\0'; - gl->left = NULL; - gl->right = NULL; - gl->up = NULL; - gl->down = NULL; - gl->home = NULL; - gl->bol = 0; - gl->clear_eol = NULL; - gl->clear_eod = NULL; - gl->u_arrow = NULL; - gl->d_arrow = NULL; - gl->l_arrow = NULL; - gl->r_arrow = NULL; - gl->sound_bell = NULL; - gl->bold = NULL; - gl->underline = NULL; - gl->standout = NULL; - gl->dim = NULL; - gl->reverse = NULL; - gl->blink = NULL; - gl->text_attr_off = NULL; - gl->nline = 0; - gl->ncolumn = 0; -#ifdef USE_TERMINFO - gl->left_n = NULL; - gl->right_n = NULL; -#elif defined(USE_TERMCAP) - gl->tgetent_buf = NULL; - gl->tgetstr_buf = NULL; -#endif - gl->app_file = NULL; - gl->user_file = NULL; - gl->configured = 0; - gl->echo = 1; - gl->last_signal = -1; -#ifdef HAVE_SELECT - gl->fd_node_mem = NULL; - gl->fd_nodes = NULL; - FD_ZERO(&gl->rfds); - FD_ZERO(&gl->wfds); - FD_ZERO(&gl->ufds); - gl->max_fd = 0; -#endif -/* - * Allocate the history buffer. - */ - gl->glh = _new_GlHistory(histlen); - if(!gl->glh) - return del_GetLine(gl); -/* - * Allocate the resource object for file-completion. - */ - gl->cpl = new_WordCompletion(); - if(!gl->cpl) - return del_GetLine(gl); -/* - * Allocate the resource object for file-completion. - */ - gl->ef = new_ExpandFile(); - if(!gl->ef) - return del_GetLine(gl); -/* - * Allocate a string-segment memory allocator for use in storing terminal - * capablity strings. - */ - gl->capmem = _new_StringGroup(CAPMEM_SEGMENT_SIZE); - if(!gl->capmem) - return del_GetLine(gl); -/* - * Allocate a line buffer, leaving 2 extra characters for the terminating - * '\n' and '\0' characters - */ - gl->line = (char *) malloc(linelen + 2); - if(!gl->line) { - fprintf(stderr, - "new_GetLine: Insufficient memory to allocate line buffer.\n"); - return del_GetLine(gl); - }; - gl->line[0] = '\0'; -/* - * Allocate a cut buffer. - */ - gl->cutbuf = (char *) malloc(linelen + 2); - if(!gl->cutbuf) { - fprintf(stderr, - "new_GetLine: Insufficient memory to allocate cut buffer.\n"); - return del_GetLine(gl); - }; - gl->cutbuf[0] = '\0'; -/* - * Allocate a vi undo buffer. - */ - gl->vi.undo.line = (char *) malloc(linelen + 2); - if(!gl->vi.undo.line) { - fprintf(stderr, - "new_GetLine: Insufficient memory to allocate undo buffer.\n"); - return del_GetLine(gl); - }; - gl->vi.undo.line[0] = '\0'; -/* - * Allocate a freelist from which to allocate nodes for the list - * of signals. - */ - gl->sig_mem = _new_FreeList("new_GetLine", sizeof(GlSignalNode), - GLS_FREELIST_BLOCKING); - if(!gl->sig_mem) - return del_GetLine(gl); -/* - * Install dispositions for the default list of signals that gl_get_line() - * traps. - */ - for(i=0; i<sizeof(gl_signal_list)/sizeof(gl_signal_list[0]); i++) { - const struct GlDefSignal *sig = gl_signal_list + i; - if(gl_trap_signal(gl, sig->signo, sig->flags, sig->after, - sig->errno_value)) - return del_GetLine(gl); - }; -/* - * Allocate an empty table of key bindings. - */ - gl->bindings = _new_KeyTab(); - if(!gl->bindings) - return del_GetLine(gl); -/* - * Define the available actions that can be bound to key sequences. - */ - for(i=0; i<sizeof(gl_actions)/sizeof(gl_actions[0]); i++) { - if(_kt_set_action(gl->bindings, gl_actions[i].name, gl_actions[i].fn)) - return del_GetLine(gl); - }; -/* - * Set up the default bindings. - */ - if(gl_change_editor(gl, gl->editor)) - return del_GetLine(gl); -/* - * Allocate termcap buffers. - */ -#ifdef USE_TERMCAP - gl->tgetent_buf = (char *) malloc(TERMCAP_BUF_SIZE); - gl->tgetstr_buf = (char *) malloc(TERMCAP_BUF_SIZE); - if(!gl->tgetent_buf || !gl->tgetstr_buf) { - fprintf(stderr, "new_GetLine: Insufficient memory for termcap buffers.\n"); - return del_GetLine(gl); - }; -#endif -/* - * Set up for I/O assuming stdin and stdout. - */ - if(gl_change_terminal(gl, stdin, stdout, getenv("TERM"))) - return del_GetLine(gl); -/* - * Create a freelist for use in allocating GlFdNode list nodes. - */ -#ifdef HAVE_SELECT - gl->fd_node_mem = _new_FreeList("new_GetLine", sizeof(GlFdNode), - GLFD_FREELIST_BLOCKING); - if(!gl->fd_node_mem) - return del_GetLine(gl); -#endif -/* - * We are done for now. - */ - return gl; -} - -/*....................................................................... - * Delete a GetLine object. - * - * Input: - * gl GetLine * The object to be deleted. - * Output: - * return GetLine * The deleted object (always NULL). - */ -GetLine *del_GetLine(GetLine *gl) -{ - if(gl) { - gl->glh = _del_GlHistory(gl->glh); - gl->cpl = del_WordCompletion(gl->cpl); - gl->ef = del_ExpandFile(gl->ef); - gl->capmem = _del_StringGroup(gl->capmem); - if(gl->line) - free(gl->line); - if(gl->cutbuf) - free(gl->cutbuf); - if(gl->vi.undo.line) - free(gl->vi.undo.line); - gl->sig_mem = _del_FreeList(NULL, gl->sig_mem, 1); - gl->sigs = NULL; /* Already freed by freeing sig_mem */ - gl->bindings = _del_KeyTab(gl->bindings); -#ifdef USE_TERMCAP - if(gl->tgetent_buf) - free(gl->tgetent_buf); - if(gl->tgetstr_buf) - free(gl->tgetstr_buf); -#endif - if(gl->file_fp) - fclose(gl->file_fp); - if(gl->term) - free(gl->term); -#ifdef HAVE_SELECT - gl->fd_node_mem = _del_FreeList(NULL, gl->fd_node_mem, 1); -#endif - free(gl); - }; - return NULL; -} - -/*....................................................................... - * Bind a control or meta character to an action. - * - * Input: - * gl GetLine * The resource object of this program. - * binder KtBinder The source of the binding. - * c char The control or meta character. - * If this is '\0', the call is ignored. - * action const char * The action name to bind the key to. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_bind_control_char(GetLine *gl, KtBinder binder, char c, - const char *action) -{ - char keyseq[2]; -/* - * Quietly reject binding to the NUL control character, since this - * is an ambiguous prefix of all bindings. - */ - if(c == '\0') - return 0; -/* - * Making sure not to bind characters which aren't either control or - * meta characters. - */ - if(IS_CTRL_CHAR(c) || IS_META_CHAR(c)) { - keyseq[0] = c; - keyseq[1] = '\0'; - } else { - return 0; - }; -/* - * Install the binding. - */ - return _kt_set_keybinding(gl->bindings, binder, keyseq, action); -} - -/*....................................................................... - * Read a line from the user. - * - * Input: - * gl GetLine * A resource object returned by new_GetLine(). - * prompt char * The prompt to prefix the line with. - * start_line char * The initial contents of the input line, or NULL - * if it should start out empty. - * start_pos int If start_line isn't NULL, this specifies the - * index of the character over which the cursor - * should initially be positioned within the line. - * If you just want it to follow the last character - * of the line, send -1. - * Output: - * return char * An internal buffer containing the input line, or - * NULL at the end of input. If the line fitted in - * the buffer there will be a '\n' newline character - * before the terminating '\0'. If it was truncated - * there will be no newline character, and the remains - * of the line should be retrieved via further calls - * to this function. - */ -char *gl_get_line(GetLine *gl, const char *prompt, - const char *start_line, int start_pos) -{ - int waserr = 0; /* True if an error occurs */ -/* - * Check the arguments. - */ - if(!gl || !prompt) { - fprintf(stderr, "gl_get_line: NULL argument(s).\n"); - return NULL; - }; -/* - * If this is the first call to this function since new_GetLine(), - * complete any postponed configuration. - */ - if(!gl->configured) { - (void) gl_configure_getline(gl, NULL, NULL, TECLA_CONFIG_FILE); - gl->configured = 1; - }; -/* - * If input is temporarily being taken from a file, return lines - * from the file until the file is exhausted, then revert to - * the normal input stream. - */ - if(gl->file_fp) { - if(fgets(gl->line, gl->linelen, gl->file_fp)) - return gl->line; - gl_revert_input(gl); - }; -/* - * Is input coming from a non-interactive source? - */ - if(!gl->is_term) - return fgets(gl->line, gl->linelen, gl->input_fp); -/* - * Record the new prompt and its displayed width. - */ - gl_replace_prompt(gl, prompt); -/* - * Before installing our signal handler functions, record the fact - * that there are no pending signals. - */ - gl_pending_signal = -1; -/* - * Temporarily override the signal handlers of the calling program, - * so that we can intercept signals that would leave the terminal - * in a bad state. - */ - waserr = gl_override_signal_handlers(gl); -/* - * After recording the current terminal settings, switch the terminal - * into raw input mode. - */ - waserr = waserr || gl_raw_terminal_mode(gl); -/* - * Attempt to read the line. - */ - waserr = waserr || gl_get_input_line(gl, start_line, start_pos); -/* - * Restore terminal settings. - */ - gl_restore_terminal_attributes(gl); -/* - * Restore the signal handlers. - */ - gl_restore_signal_handlers(gl); -/* - * Having restored the program terminal and signal environment, - * re-submit any signals that were received. - */ - if(gl_pending_signal != -1) { - raise(gl_pending_signal); - waserr = 1; - }; -/* - * If gl_get_input_line() aborted input due to the user asking to - * temporarily read lines from a file, read the first line from - * this file. - */ - if(!waserr && gl->file_fp) - return gl_get_line(gl, prompt, NULL, 0); -/* - * Return the new input line. - */ - return waserr ? NULL : gl->line; -} - -/*....................................................................... - * Record of the signal handlers of the calling program, so that they - * can be restored later. - * - * Input: - * gl GetLine * The resource object of this library. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_override_signal_handlers(GetLine *gl) -{ - GlSignalNode *sig; /* A node in the list of signals to be caught */ -/* - * Set up our signal handler. - */ - SigAction act; - act.sa_handler = gl_signal_handler; - sigemptyset(&act.sa_mask); - act.sa_flags = 0; -/* - * Get the process signal mask so that we can see which signals the - * calling program currently has blocked, and so that we can restore this - * mask before returning to the calling program. - */ - if(sigprocmask(SIG_SETMASK, NULL, &gl->old_signal_set) == -1) { - fprintf(stderr, "gl_get_line(): sigprocmask error: %s\n", strerror(errno)); - return 1; - }; -/* - * Form a new process signal mask from the list of signals that we have - * been asked to trap. - */ - sigemptyset(&gl->new_signal_set); - for(sig=gl->sigs; sig; sig=sig->next) { -/* - * Trap this signal? If it is blocked by the calling program and we - * haven't been told to unblock it, don't arrange to trap this signal. - */ - if(sig->flags & GLS_UNBLOCK_SIG || - !sigismember(&gl->old_signal_set, sig->signo)) { - if(sigaddset(&gl->new_signal_set, sig->signo) == -1) { - fprintf(stderr, "gl_get_line(): sigaddset error: %s\n", - strerror(errno)); - return 1; - }; - }; - }; -/* - * Before installing our signal handlers, block all of the signals - * that we are going to be trapping. - */ - if(sigprocmask(SIG_BLOCK, &gl->new_signal_set, NULL) == -1) { - fprintf(stderr, "gl_get_line(): sigprocmask error: %s\n", strerror(errno)); - return 1; - }; -/* - * Override the actions of the signals that we are trapping. - */ - for(sig=gl->sigs; sig; sig=sig->next) { - if(sigismember(&gl->new_signal_set, sig->signo) && - sigaction(sig->signo, &act, &sig->original)) { - fprintf(stderr, "gl_get_line(): sigaction error: %s\n", strerror(errno)); - return 1; - }; - }; -/* - * Just in case a SIGWINCH signal was sent to the process while our - * SIGWINCH signal handler wasn't in place, check to see if the terminal - * size needs updating. - */ -#ifdef USE_SIGWINCH - if(gl_resize_terminal(gl, 0)) - return 1; -#endif - return 0; -} - -/*....................................................................... - * Restore the signal handlers of the calling program. - * - * Input: - * gl GetLine * The resource object of this library. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_restore_signal_handlers(GetLine *gl) -{ - GlSignalNode *sig; /* A node in the list of signals to be caught */ -/* - * Restore application signal handlers that were overriden - * by gl_override_signal_handlers(). - */ - for(sig=gl->sigs; sig; sig=sig->next) { - if(sigismember(&gl->new_signal_set, sig->signo) && - sigaction(sig->signo, &sig->original, NULL)) { - fprintf(stderr, "gl_get_line(): sigaction error: %s\n", strerror(errno)); - return 1; - }; - }; -/* - * Restore the original signal mask. - */ - if(sigprocmask(SIG_SETMASK, &gl->old_signal_set, NULL) == -1) { - fprintf(stderr, "gl_get_line(): sigprocmask error: %s\n", strerror(errno)); - return 1; - }; - return 0; -} - -/*....................................................................... - * This signal handler simply records the fact that a given signal was - * caught in the file-scope gl_pending_signal variable. - */ -static void gl_signal_handler(int signo) -{ - gl_pending_signal = signo; - siglongjmp(gl_setjmp_buffer, 1); -} - -/*....................................................................... - * Switch the terminal into raw mode after storing the previous terminal - * settings in gl->attributes. - * - * Input: - * gl GetLine * The resource object of this program. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_raw_terminal_mode(GetLine *gl) -{ - Termios newattr; /* The new terminal attributes */ -/* - * Record the current terminal attributes. - */ - if(tcgetattr(gl->input_fd, &gl->oldattr)) { - fprintf(stderr, "getline(): tcgetattr error: %s\n", strerror(errno)); - return 1; - }; -/* - * This function shouldn't do anything but record the current terminal - * attritubes if editing has been disabled. - */ - if(gl->editor == GL_NO_EDITOR) - return 0; -/* - * Modify the existing attributes. - */ - newattr = gl->oldattr; -/* - * Turn off local echo, canonical input mode and extended input processing. - */ - newattr.c_lflag &= ~(ECHO | ICANON | IEXTEN); -/* - * Don't translate carriage return to newline, turn off input parity - * checking, don't strip off 8th bit, turn off output flow control. - */ - newattr.c_iflag &= ~(ICRNL | INPCK | ISTRIP); -/* - * Clear size bits, turn off parity checking, and allow 8-bit characters. - */ - newattr.c_cflag &= ~(CSIZE | PARENB); - newattr.c_cflag |= CS8; -/* - * Turn off output processing. - */ - newattr.c_oflag &= ~(OPOST); -/* - * Request one byte at a time, without waiting. - */ - newattr.c_cc[VMIN] = 1; - newattr.c_cc[VTIME] = 0; -/* - * Install the new terminal modes. - */ - while(tcsetattr(gl->input_fd, TCSADRAIN, &newattr)) { - if (errno != EINTR) { - fprintf(stderr, "getline(): tcsetattr error: %s\n", strerror(errno)); - return 1; - }; - }; - return 0; -} - -/*....................................................................... - * Restore the terminal attributes recorded in gl->oldattr. - * - * Input: - * gl GetLine * The resource object of this library. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_restore_terminal_attributes(GetLine *gl) -{ - int waserr = 0; -/* - * Before changing the terminal attributes, make sure that all output - * has been passed to the terminal. - */ - if(gl_flush_output(gl)) - waserr = 1; -/* - * Reset the terminal attributes to the values that they had on - * entry to gl_get_line(). - */ - while(tcsetattr(gl->input_fd, TCSADRAIN, &gl->oldattr)) { - if(errno != EINTR) { - fprintf(stderr, "gl_get_line(): tcsetattr error: %s\n", strerror(errno)); - waserr = 1; - break; - }; - }; - return waserr; -} - -/*....................................................................... - * Read a new input line from the user. - * - * Input: - * gl GetLine * The resource object of this library. - * start_line char * The initial contents of the input line, or NULL - * if it should start out empty. - * start_pos int If start_line isn't NULL, this specifies the - * index of the character over which the cursor - * should initially be positioned within the line. - * If you just want it to follow the last character - * of the line, send -1. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_get_input_line(GetLine *gl, const char *start_line, int start_pos) -{ - char c; /* The character being read */ -/* - * Reset the properties of the line. - */ - gl->ntotal = 0; - gl->buff_curpos = 0; - gl->term_curpos = 0; - gl->insert_curpos = 0; - gl->number = -1; - gl->endline = 0; - gl->vi.command = 0; - gl->vi.undo.line[0] = '\0'; - gl->vi.undo.ntotal = 0; - gl->vi.undo.buff_curpos = 0; - gl->vi.repeat.fn = 0; - gl->last_signal = -1; -/* - * Reset the history search pointers. - */ - if(_glh_cancel_search(gl->glh)) - return 1; -/* - * Draw the prompt at the start of the line. - */ - if(gl_display_prompt(gl)) - return 1; -/* - * Present an initial line? - */ - if(start_line) { - char *cptr; /* A pointer into gl->line[] */ -/* - * Load the line into the buffer, and display it. - */ - if(start_line != gl->line) - strncpy(gl->line, start_line, gl->linelen); - gl->line[gl->linelen] = '\0'; - gl->ntotal = strlen(gl->line); -/* - * Strip off any trailing newline and carriage return characters. - */ - for(cptr=gl->line + gl->ntotal - 1; cptr >= gl->line && - (*cptr=='\n' || *cptr=='\r'); cptr--,gl->ntotal--) - ; - if(gl->ntotal < 0) - gl->ntotal = 0; - gl->line[gl->ntotal] = '\0'; -/* - * Display the string that remains. - */ - if(gl_output_string(gl, gl->line, '\0')) - return 1; -/* - * Where should the cursor be placed within the line? - */ - if(start_pos < 0 || start_pos > gl->ntotal) { - if(gl_place_cursor(gl, gl->ntotal)) - return 1; - } else { - if(gl_place_cursor(gl, start_pos)) - return 1; - }; - } else { - gl->line[0] = '\0'; - }; -/* - * Preload a history line? - */ - if(gl->preload_history) { - gl->preload_history = 0; - if(gl->preload_id) { - if(_glh_recall_line(gl->glh, gl->preload_id, gl->line, gl->linelen)) { - gl->ntotal = strlen(gl->line); - gl->buff_curpos = strlen(gl->line); - }; - gl->preload_id = 0; - }; - gl_redisplay(gl, 1); - }; -/* - * Read one character at a time. - */ - while(gl_read_character(gl, &c) == 0) { -/* - * Increment the count of the number of key sequences entered. - */ - gl->keyseq_count++; -/* - * Interpret the character either as the start of a new key-sequence, - * as a continuation of a repeat count, or as a printable character - * to be added to the line. - */ - if(gl_interpret_char(gl, c)) - break; -/* - * If we just ran an action function which temporarily asked for - * input to be taken from a file, abort this call. - */ - if(gl->file_fp) - return 0; -/* - * Has the line been completed? - */ - if(gl->endline) - return gl_line_ended(gl, isprint((int)(unsigned char) c) ? c : '\n', - gl->echo && (c=='\n' || c=='\r')); - }; -/* - * To get here, gl_read_character() must have returned non-zero. See - * if this was because a signal was caught that requested that the - * current line be returned. - */ - if(gl->endline) - return gl_line_ended(gl, '\n', gl->echo); - return 1; -} - -/*....................................................................... - * Add a character to the line buffer at the current cursor position, - * inserting or overwriting according the current mode. - * - * Input: - * gl GetLine * The resource object of this library. - * c char The character to be added. - * Output: - * return int 0 - OK. - * 1 - Insufficient room. - */ -static int gl_add_char_to_line(GetLine *gl, char c) -{ -/* - * Keep a record of the current cursor position. - */ - int buff_curpos = gl->buff_curpos; - int term_curpos = gl->term_curpos; -/* - * Work out the displayed width of the new character. - */ - int width = gl_displayed_char_width(gl, c, term_curpos); -/* - * If we are in insert mode, or at the end of the line, - * check that we can accomodate a new character in the buffer. - * If not, simply return, leaving it up to the calling program - * to check for the absence of a newline character. - */ - if((gl->insert || buff_curpos >= gl->ntotal) && gl->ntotal >= gl->linelen) - return 0; -/* - * Are we adding characters to the line (ie. inserting or appending)? - */ - if(gl->insert || buff_curpos >= gl->ntotal) { -/* - * If inserting, make room for the new character. - */ - if(buff_curpos < gl->ntotal) { - memmove(gl->line + buff_curpos + 1, gl->line + buff_curpos, - gl->ntotal - buff_curpos); - }; -/* - * Copy the character into the buffer. - */ - gl->line[buff_curpos] = c; - gl->buff_curpos++; -/* - * If the line was extended, update the record of the string length - * and terminate the extended string. - */ - gl->ntotal++; - gl->line[gl->ntotal] = '\0'; -/* - * Redraw the line from the cursor position to the end of the line, - * and move the cursor to just after the added character. - */ - if(gl_output_string(gl, gl->line + buff_curpos, '\0') || - gl_set_term_curpos(gl, term_curpos + width)) - return 1; -/* - * Are we overwriting an existing character? - */ - } else { -/* - * Get the widths of the character to be overwritten and the character - * that is going to replace it. - */ - int old_width = gl_displayed_char_width(gl, gl->line[buff_curpos], - term_curpos); -/* - * Overwrite the character in the buffer. - */ - gl->line[buff_curpos] = c; -/* - * If we are replacing with a narrower character, we need to - * redraw the terminal string to the end of the line, then - * overwrite the trailing old_width - width characters - * with spaces. - */ - if(old_width > width) { - if(gl_output_string(gl, gl->line + buff_curpos, '\0')) - return 1; -/* - * Clear to the end of the terminal. - */ - if(gl_output_control_sequence(gl, gl->nline, gl->clear_eod)) - return 1; -/* - * Move the cursor to the end of the new character. - */ - if(gl_set_term_curpos(gl, term_curpos + width)) - return 1; - gl->buff_curpos++; -/* - * If we are replacing with a wider character, then we will be - * inserting new characters, and thus extending the line. - */ - } else if(width > old_width) { -/* - * Redraw the line from the cursor position to the end of the line, - * and move the cursor to just after the added character. - */ - if(gl_output_string(gl, gl->line + buff_curpos, '\0') || - gl_set_term_curpos(gl, term_curpos + width)) - return 1; - gl->buff_curpos++; -/* - * The original and replacement characters have the same width, - * so simply overwrite. - */ - } else { -/* - * Copy the character into the buffer. - */ - gl->line[buff_curpos] = c; - gl->buff_curpos++; -/* - * Overwrite the original character. - */ - if(gl_output_char(gl, c, gl->line[gl->buff_curpos])) - return 1; - }; - }; - return 0; -} - -/*....................................................................... - * Insert/append a string to the line buffer and terminal at the current - * cursor position. - * - * Input: - * gl GetLine * The resource object of this library. - * s char * The string to be added. - * Output: - * return int 0 - OK. - * 1 - Insufficient room. - */ -static int gl_add_string_to_line(GetLine *gl, const char *s) -{ - int buff_slen; /* The length of the string being added to line[] */ - int term_slen; /* The length of the string being written to the terminal */ - int buff_curpos; /* The original value of gl->buff_curpos */ - int term_curpos; /* The original value of gl->term_curpos */ -/* - * Keep a record of the current cursor position. - */ - buff_curpos = gl->buff_curpos; - term_curpos = gl->term_curpos; -/* - * How long is the string to be added? - */ - buff_slen = strlen(s); - term_slen = gl_displayed_string_width(gl, s, buff_slen, term_curpos); -/* - * Check that we can accomodate the string in the buffer. - * If not, simply return, leaving it up to the calling program - * to check for the absence of a newline character. - */ - if(gl->ntotal + buff_slen > gl->linelen) - return 0; -/* - * Move the characters that follow the cursor in the buffer by - * buff_slen characters to the right. - */ - if(gl->ntotal > gl->buff_curpos) { - memmove(gl->line + gl->buff_curpos + buff_slen, gl->line + gl->buff_curpos, - gl->ntotal - gl->buff_curpos); - }; -/* - * Copy the string into the buffer. - */ - memcpy(gl->line + gl->buff_curpos, s, buff_slen); - gl->ntotal += buff_slen; - gl->buff_curpos += buff_slen; -/* - * Maintain the buffer properly terminated. - */ - gl->line[gl->ntotal] = '\0'; -/* - * Write the modified part of the line to the terminal, then move - * the terminal cursor to the end of the displayed input string. - */ - if(gl_output_string(gl, gl->line + buff_curpos, '\0') || - gl_set_term_curpos(gl, term_curpos + term_slen)) - return 1; - return 0; -} - -/*....................................................................... - * Read a single character from the terminal. - * - * Input: - * gl GetLine * The resource object of this library. - * Output: - * return int 0 - OK. - * 1 - Either an I/O error occurred, or a signal was - * caught who's disposition is to abort gl_get_line() - * or to have gl_get_line() return the current line - * as though the user had pressed return. In the - * latter case gl->endline will be non-zero. - */ -static int gl_read_character(GetLine *gl, char *c) -{ -/* - * Before waiting for a new character to be input, flush unwritten - * characters to the terminal. - */ - if(gl_flush_output(gl)) - return 1; -/* - * We may have to repeat the read if window change signals are received. - */ - for(;;) { -/* - * If the endline flag becomes set, don't wait for another character. - */ - if(gl->endline) - return 1; -/* - * Since the code in this function can block, trap signals. - */ - if(sigsetjmp(gl_setjmp_buffer, 1)==0) { -/* - * Unblock the signals that we are trapping. - */ - if(sigprocmask(SIG_UNBLOCK, &gl->new_signal_set, NULL) == -1) { - fprintf(stderr, "getline(): sigprocmask error: %s\n", strerror(errno)); - return 1; - }; -/* - * If select() is available, watch for activity on any file descriptors - * that the user has registered, and for data available on the terminal - * file descriptor. - */ -#ifdef HAVE_SELECT - if(gl_event_handler(gl)) - return 1; -#endif -/* - * Read one character from the terminal. This could take more - * than one call if an interrupt that we aren't trapping is - * received. - */ - while(read(gl->input_fd, (void *)c, 1) != 1) { - if(errno != EINTR) { -#ifdef EAGAIN - if(!errno) /* This can happen with SysV O_NDELAY */ - errno = EAGAIN; -#endif - return 1; - }; - }; -/* - * Block all of the signals that we are trapping. - */ - if(sigprocmask(SIG_BLOCK, &gl->new_signal_set, NULL) == -1) { - fprintf(stderr, "getline(): sigprocmask error: %s\n", strerror(errno)); - return 1; - }; - return 0; - }; -/* - * To get here, one of the signals that we are trapping must have - * been received. Note that by using sigsetjmp() instead of setjmp() - * the signal mask that was blocking these signals will have been - * reinstated, so we can be sure that no more of these signals will - * be received until we explicitly unblock them again. - */ - if(gl_check_caught_signal(gl)) - return 1; - }; -} - -/*....................................................................... - * This function is called to handle signals caught between calls to - * sigsetjmp() and siglongjmp(). - * - * Input: - * gl GetLine * The resource object of this library. - * Output: - * return int 0 - Signal handled internally. - * 1 - Signal requires gl_get_line() to abort. - */ -static int gl_check_caught_signal(GetLine *gl) -{ - GlSignalNode *sig; /* The signal disposition */ - SigAction keep_action; /* The signal disposition of tecla signal handlers */ -/* - * Was no signal caught? - */ - if(gl_pending_signal == -1) - return 0; -/* - * Record the signal that was caught, so that the user can query it later. - */ - gl->last_signal = gl_pending_signal; -/* - * Did we receive a terminal size signal? - */ -#ifdef USE_SIGWINCH - if(gl_pending_signal == SIGWINCH && gl_resize_terminal(gl, 1)) - return 1; -#endif -/* - * Lookup the requested disposition of this signal. - */ - for(sig=gl->sigs; sig && sig->signo != gl_pending_signal; sig=sig->next) - ; - if(!sig) - return 0; -/* - * Start a fresh line? - */ - if(sig->flags & GLS_RESTORE_LINE) { - if(gl_set_term_curpos(gl, gl_buff_curpos_to_term_curpos(gl, gl->ntotal)) || - gl_output_raw_string(gl, "\r\n")) - return 1; - }; -/* - * Restore terminal settings to how they were before gl_get_line() was - * called? - */ - if(sig->flags & GLS_RESTORE_TTY) - gl_restore_terminal_attributes(gl); -/* - * Restore signal handlers to how they were before gl_get_line() was - * called? If this hasn't been requested, only reinstate the signal - * handler of the signal that we are handling. - */ - if(sig->flags & GLS_RESTORE_SIG) { - gl_restore_signal_handlers(gl); - } else { - (void) sigaction(sig->signo, &sig->original, &keep_action); - (void) sigprocmask(SIG_UNBLOCK, &sig->proc_mask, NULL); - }; -/* - * Forward the signal to the application's signal handler. - */ - if(!(sig->flags & GLS_DONT_FORWARD)) - raise(gl_pending_signal); - gl_pending_signal = -1; -/* - * Reinstate our signal handlers. - */ - if(sig->flags & GLS_RESTORE_SIG) { - gl_override_signal_handlers(gl); - } else { - (void) sigaction(sig->signo, &keep_action, NULL); - (void) sigprocmask(SIG_BLOCK, &sig->proc_mask, NULL); - }; -/* - * Do we need to reinstate our terminal settings? - */ - if(sig->flags & GLS_RESTORE_TTY) - gl_raw_terminal_mode(gl); -/* - * Redraw the line? - */ - if(sig->flags & GLS_REDRAW_LINE && gl_redisplay(gl, 1)) - return 1; -/* - * Set errno. - */ - errno = sig->errno_value; -/* - * What next? - */ - switch(sig->after) { - case GLS_RETURN: - return gl_newline(gl, 1); - break; - case GLS_ABORT: - return 1; - break; - case GLS_CONTINUE: - return 0; - break; - }; - return 0; -} - -/*....................................................................... - * Get pertinent terminal control strings and the initial terminal size. - * - * Input: - * gl GetLine * The resource object of this library. - * term char * The type of the terminal. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_control_strings(GetLine *gl, const char *term) -{ - int bad_term = 0; /* True if term is unusable */ -/* - * Discard any existing control strings from a previous terminal. - */ - gl->left = NULL; - gl->right = NULL; - gl->up = NULL; - gl->down = NULL; - gl->home = NULL; - gl->bol = 0; - gl->clear_eol = NULL; - gl->clear_eod = NULL; - gl->u_arrow = NULL; - gl->d_arrow = NULL; - gl->l_arrow = NULL; - gl->r_arrow = NULL; - gl->sound_bell = NULL; - gl->bold = NULL; - gl->underline = NULL; - gl->standout = NULL; - gl->dim = NULL; - gl->reverse = NULL; - gl->blink = NULL; - gl->text_attr_off = NULL; - gl->nline = 0; - gl->ncolumn = 0; -#ifdef USE_TERMINFO - gl->left_n = NULL; - gl->right_n = NULL; -#endif -/* - * If possible lookup the information in a terminal information - * database. - */ -#ifdef USE_TERMINFO - if(!term || setupterm((char *)term, gl->input_fd, NULL) == ERR) { - bad_term = 1; - } else { - _clr_StringGroup(gl->capmem); - gl->left = gl_tigetstr(gl, "cub1"); - gl->right = gl_tigetstr(gl, "cuf1"); - gl->up = gl_tigetstr(gl, "cuu1"); - gl->down = gl_tigetstr(gl, "cud1"); - gl->home = gl_tigetstr(gl, "home"); - gl->clear_eol = gl_tigetstr(gl, "el"); - gl->clear_eod = gl_tigetstr(gl, "ed"); - gl->u_arrow = gl_tigetstr(gl, "kcuu1"); - gl->d_arrow = gl_tigetstr(gl, "kcud1"); - gl->l_arrow = gl_tigetstr(gl, "kcub1"); - gl->r_arrow = gl_tigetstr(gl, "kcuf1"); - gl->left_n = gl_tigetstr(gl, "cub"); - gl->right_n = gl_tigetstr(gl, "cuf"); - gl->sound_bell = gl_tigetstr(gl, "bel"); - gl->bold = gl_tigetstr(gl, "bold"); - gl->underline = gl_tigetstr(gl, "smul"); - gl->standout = gl_tigetstr(gl, "smso"); - gl->dim = gl_tigetstr(gl, "dim"); - gl->reverse = gl_tigetstr(gl, "rev"); - gl->blink = gl_tigetstr(gl, "blink"); - gl->text_attr_off = gl_tigetstr(gl, "sgr0"); - }; -#elif defined(USE_TERMCAP) - if(!term || tgetent(gl->tgetent_buf, (char *)term) < 0) { - bad_term = 1; - } else { - char *tgetstr_buf_ptr = gl->tgetstr_buf; - _clr_StringGroup(gl->capmem); - gl->left = gl_tgetstr(gl, "le", &tgetstr_buf_ptr); - gl->right = gl_tgetstr(gl, "nd", &tgetstr_buf_ptr); - gl->up = gl_tgetstr(gl, "up", &tgetstr_buf_ptr); - gl->down = gl_tgetstr(gl, "do", &tgetstr_buf_ptr); - gl->home = gl_tgetstr(gl, "ho", &tgetstr_buf_ptr); - gl->clear_eol = gl_tgetstr(gl, "ce", &tgetstr_buf_ptr); - gl->clear_eod = gl_tgetstr(gl, "cd", &tgetstr_buf_ptr); - gl->u_arrow = gl_tgetstr(gl, "ku", &tgetstr_buf_ptr); - gl->d_arrow = gl_tgetstr(gl, "kd", &tgetstr_buf_ptr); - gl->l_arrow = gl_tgetstr(gl, "kl", &tgetstr_buf_ptr); - gl->r_arrow = gl_tgetstr(gl, "kr", &tgetstr_buf_ptr); - gl->sound_bell = gl_tgetstr(gl, "bl", &tgetstr_buf_ptr); - gl->bold = gl_tgetstr(gl, "md", &tgetstr_buf_ptr); - gl->underline = gl_tgetstr(gl, "us", &tgetstr_buf_ptr); - gl->standout = gl_tgetstr(gl, "so", &tgetstr_buf_ptr); - gl->dim = gl_tgetstr(gl, "mh", &tgetstr_buf_ptr); - gl->reverse = gl_tgetstr(gl, "mr", &tgetstr_buf_ptr); - gl->blink = gl_tgetstr(gl, "mb", &tgetstr_buf_ptr); - gl->text_attr_off = gl_tgetstr(gl, "me", &tgetstr_buf_ptr); - }; -#endif -/* - * Report term being unusable. - */ - if(bad_term) { - fprintf(stderr, "Bad terminal type: \"%s\". Will assume vt100.\n", - term ? term : "(null)"); - }; -/* - * Fill in missing information with ANSI VT100 strings. - */ - if(!gl->left) - gl->left = "\b"; /* ^H */ - if(!gl->right) - gl->right = GL_ESC_STR "[C"; - if(!gl->up) - gl->up = GL_ESC_STR "[A"; - if(!gl->down) - gl->down = "\n"; - if(!gl->home) - gl->home = GL_ESC_STR "[H"; - if(!gl->bol) - gl->bol = "\r"; - if(!gl->clear_eol) - gl->clear_eol = GL_ESC_STR "[K"; - if(!gl->clear_eod) - gl->clear_eod = GL_ESC_STR "[J"; - if(!gl->u_arrow) - gl->u_arrow = GL_ESC_STR "[A"; - if(!gl->d_arrow) - gl->d_arrow = GL_ESC_STR "[B"; - if(!gl->l_arrow) - gl->l_arrow = GL_ESC_STR "[D"; - if(!gl->r_arrow) - gl->r_arrow = GL_ESC_STR "[C"; - if(!gl->sound_bell) - gl->sound_bell = "\a"; - if(!gl->bold) - gl->bold = GL_ESC_STR "[1m"; - if(!gl->underline) - gl->underline = GL_ESC_STR "[4m"; - if(!gl->standout) - gl->standout = GL_ESC_STR "[1;7m"; - if(!gl->dim) - gl->dim = ""; /* Not available */ - if(!gl->reverse) - gl->reverse = GL_ESC_STR "[7m"; - if(!gl->blink) - gl->blink = GL_ESC_STR "[5m"; - if(!gl->text_attr_off) - gl->text_attr_off = GL_ESC_STR "[m"; -/* - * Find out the current terminal size. - */ - (void) gl_terminal_size(gl, GL_DEF_NCOLUMN, GL_DEF_NLINE); - return 0; -} - -#ifdef USE_TERMINFO -/*....................................................................... - * This is a private function of gl_control_strings() used to look up - * a termninal capability string from the terminfo database and make - * a private copy of it. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * name const char * The name of the terminfo string to look up. - * Output: - * return const char * The local copy of the capability, or NULL - * if not available. - */ -static const char *gl_tigetstr(GetLine *gl, const char *name) -{ - const char *value = tigetstr((char *)name); - if(!value || value == (char *) -1) - return NULL; - return _sg_store_string(gl->capmem, value, 0); -} -#elif defined(USE_TERMCAP) -/*....................................................................... - * This is a private function of gl_control_strings() used to look up - * a termninal capability string from the termcap database and make - * a private copy of it. Note that some emulations of tgetstr(), such - * as that used by Solaris, ignores the buffer pointer that is past to - * it, so we can't assume that a private copy has been made that won't - * be trashed by another call to gl_control_strings() by another - * GetLine object. So we make what may be a redundant private copy - * of the string in gl->capmem. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * name const char * The name of the terminfo string to look up. - * Input/Output: - * bufptr char ** On input *bufptr points to the location in - * gl->tgetstr_buf at which to record the - * capability string. On output *bufptr is - * incremented over the stored string. - * Output: - * return const char * The local copy of the capability, or NULL - * on error. - */ -static const char *gl_tgetstr(GetLine *gl, const char *name, char **bufptr) -{ - const char *value = tgetstr((char *)name, bufptr); - if(!value || value == (char *) -1) - return NULL; - return _sg_store_string(gl->capmem, value, 0); -} -#endif - -/*....................................................................... - * This is an action function that implements a user interrupt (eg. ^C). - */ -static KT_KEY_FN(gl_user_interrupt) -{ - raise(SIGINT); - return 1; -} - -/*....................................................................... - * This is an action function that implements the abort signal. - */ -static KT_KEY_FN(gl_abort) -{ - raise(SIGABRT); - return 1; -} - -/*....................................................................... - * This is an action function that sends a suspend signal (eg. ^Z) to the - * the parent process. - */ -static KT_KEY_FN(gl_suspend) -{ - raise(SIGTSTP); - return 0; -} - -/*....................................................................... - * This is an action function that halts output to the terminal. - */ -static KT_KEY_FN(gl_stop_output) -{ - tcflow(gl->output_fd, TCOOFF); - return 0; -} - -/*....................................................................... - * This is an action function that resumes halted terminal output. - */ -static KT_KEY_FN(gl_start_output) -{ - tcflow(gl->output_fd, TCOON); - return 0; -} - -/*....................................................................... - * This is an action function that allows the next character to be accepted - * without any interpretation as a special character. - */ -static KT_KEY_FN(gl_literal_next) -{ - char c; /* The character to be added to the line */ - int i; -/* - * Get the character to be inserted literally. - */ - if(gl_read_character(gl, &c)) - return 1; -/* - * Add the character to the line 'count' times. - */ - for(i=0; i<count; i++) - gl_add_char_to_line(gl, c); - return 0; -} - -/*....................................................................... - * Return the number of characters needed to display a given character - * on the screen. Tab characters require eight spaces, and control - * characters are represented by a caret followed by the modified - * character. - * - * Input: - * gl GetLine * The resource object of this library. - * c char The character to be displayed. - * term_curpos int The destination terminal location of the character. - * This is needed because the width of tab characters - * depends on where they are, relative to the - * preceding tab stops. - * Output: - * return int The number of terminal charaters needed. - */ -static int gl_displayed_char_width(GetLine *gl, char c, int term_curpos) -{ - if(c=='\t') - return TAB_WIDTH - ((term_curpos % gl->ncolumn) % TAB_WIDTH); - if(IS_CTRL_CHAR(c)) - return 2; - if(!isprint((int)(unsigned char) c)) { - char string[TAB_WIDTH + 4]; - sprintf(string, "\\%o", (int)(unsigned char)c); - return strlen(string); - }; - return 1; -} - -/*....................................................................... - * Work out the length of given string of characters on the terminal. - * - * Input: - * gl GetLine * The resource object of this library. - * string char * The string to be measured. - * nc int The number of characters to be measured, or -1 - * to measure the whole string. - * term_curpos int The destination terminal location of the character. - * This is needed because the width of tab characters - * depends on where they are, relative to the - * preceding tab stops. - * Output: - * return int The number of displayed characters. - */ -static int gl_displayed_string_width(GetLine *gl, const char *string, int nc, - int term_curpos) -{ - int slen=0; /* The displayed number of characters */ - int i; -/* - * How many characters are to be measured? - */ - if(nc < 0) - nc = strlen(string); -/* - * Add up the length of the displayed string. - */ - for(i=0; i<nc; i++) - slen += gl_displayed_char_width(gl, string[i], term_curpos + slen); - return slen; -} - -/*....................................................................... - * Write a string directly to the terminal. - * - * Input: - * gl GetLine * The resource object of this program. - * string char * The string to be written. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_output_raw_string(GetLine *gl, const char *string) -{ - if(gl->echo) { - int ndone = 0; /* The number of characters written so far */ -/* - * How long is the string to be written? - */ - int slen = strlen(string); -/* - * Attempt to write the string to the terminal, restarting the - * write if a signal is caught. - */ - while(ndone < slen) { - int nnew = fwrite(string + ndone, sizeof(char), slen-ndone, - gl->output_fp); - if(nnew > 0) - ndone += nnew; - else if(errno != EINTR) - return 1; - }; - }; - return 0; -} - -/*....................................................................... - * Output a terminal control sequence. When using terminfo, - * this must be a sequence returned by tgetstr() or tigetstr() - * respectively. - * - * Input: - * gl GetLine * The resource object of this library. - * nline int The number of lines affected by the operation, - * or 1 if not relevant. - * string char * The control sequence to be sent. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_output_control_sequence(GetLine *gl, int nline, - const char *string) -{ - if(gl->echo) { -#if defined(USE_TERMINFO) || defined(USE_TERMCAP) - tputs_fp = gl->output_fp; - errno = 0; - tputs((char *)string, nline, gl_tputs_putchar); - return errno != 0; -#else - return gl_output_raw_string(gl, string); -#endif - }; - return 0; -} - -/*....................................................................... - * Move the terminal cursor n characters to the left or right. - * - * Input: - * gl GetLine * The resource object of this program. - * n int number of positions to the right (> 0) or left (< 0). - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_terminal_move_cursor(GetLine *gl, int n) -{ - int cur_row, cur_col; /* The current terminal row and column index of */ - /* the cursor wrt the start of the input line. */ - int new_row, new_col; /* The target terminal row and column index of */ - /* the cursor wrt the start of the input line. */ -/* - * How far can we move left? - */ - if(gl->term_curpos + n < 0) - n = gl->term_curpos; -/* - * Break down the current and target cursor locations into rows and columns. - */ - cur_row = gl->term_curpos / gl->ncolumn; - cur_col = gl->term_curpos % gl->ncolumn; - new_row = (gl->term_curpos + n) / gl->ncolumn; - new_col = (gl->term_curpos + n) % gl->ncolumn; -/* - * Move down to the next line. - */ - for(; cur_row < new_row; cur_row++) { - if(gl_output_control_sequence(gl, 1, gl->down)) - return 1; - }; -/* - * Move up to the previous line. - */ - for(; cur_row > new_row; cur_row--) { - if(gl_output_control_sequence(gl, 1, gl->up)) - return 1; - }; -/* - * Move to the right within the target line? - */ - if(cur_col < new_col) { -#ifdef USE_TERMINFO -/* - * Use a parameterized control sequence if it generates less control - * characters (guess based on ANSI terminal termcap entry). - */ - if(gl->right_n != NULL && new_col - cur_col > 1) { - if(gl_output_control_sequence(gl, 1, tparm((char *)gl->right_n, - (long)(new_col - cur_col), 0l, 0l, 0l, 0l, 0l, 0l, 0l, 0l))) - return 1; - } else -#endif - { - for(; cur_col < new_col; cur_col++) { - if(gl_output_control_sequence(gl, 1, gl->right)) - return 1; - }; - }; -/* - * Move to the left within the target line? - */ - } else if(cur_col > new_col) { -#ifdef USE_TERMINFO -/* - * Use a parameterized control sequence if it generates less control - * characters (guess based on ANSI terminal termcap entry). - */ - if(gl->left_n != NULL && cur_col - new_col > 3) { - if(gl_output_control_sequence(gl, 1, tparm((char *)gl->left_n, - (long)(cur_col - new_col), 0l, 0l, 0l, 0l, 0l, 0l, 0l, 0l))) - return 1; - } else -#endif - { - for(; cur_col > new_col; cur_col--) { - if(gl_output_control_sequence(gl, 1, gl->left)) - return 1; - }; - }; - } -/* - * Update the recorded position of the terminal cursor. - */ - gl->term_curpos += n; - return 0; -} - -/*....................................................................... - * Write a character to the terminal after expanding tabs and control - * characters to their multi-character representations. - * - * Input: - * gl GetLine * The resource object of this program. - * c char The character to be output. - * pad char Many terminals have the irritating feature that - * when one writes a character in the last column of - * of the terminal, the cursor isn't wrapped to the - * start of the next line until one more character - * is written. Some terminals don't do this, so - * after such a write, we don't know where the - * terminal is unless we output an extra character. - * This argument specifies the character to write. - * If at the end of the input line send '\0' or a - * space, and a space will be written. Otherwise, - * pass the next character in the input line - * following the one being written. - * Output: - * return int 0 - OK. - */ -static int gl_output_char(GetLine *gl, char c, char pad) -{ - char string[TAB_WIDTH + 4]; /* A work area for composing compound strings */ - int nchar; /* The number of terminal characters */ - int i; -/* - * Check for special characters. - */ - if(c == '\t') { -/* - * How many spaces do we need to represent a tab at the current terminal - * column? - */ - nchar = gl_displayed_char_width(gl, '\t', gl->term_curpos); -/* - * Compose the tab string. - */ - for(i=0; i<nchar; i++) - string[i] = ' '; - } else if(IS_CTRL_CHAR(c)) { - string[0] = '^'; - string[1] = CTRL_TO_CHAR(c); - nchar = 2; - } else if(!isprint((int)(unsigned char) c)) { - sprintf(string, "\\%o", (int)(unsigned char)c); - nchar = strlen(string); - } else { - string[0] = c; - nchar = 1; - }; -/* - * Terminate the string. - */ - string[nchar] = '\0'; -/* - * Write the string to the terminal. - */ - if(gl_output_raw_string(gl, string)) - return 1; -/* - * Except for one exception to be described in a moment, the cursor should - * now have been positioned after the character that was just output. - */ - gl->term_curpos += nchar; -/* - * If the new character ended exactly at the end of a line, - * most terminals won't move the cursor onto the next line until we - * have written a character on the next line, so append an extra - * space then move the cursor back. - */ - if(gl->term_curpos % gl->ncolumn == 0) { - int term_curpos = gl->term_curpos; - if(gl_output_char(gl, pad ? pad : ' ', ' ') || - gl_set_term_curpos(gl, term_curpos)) - return 1; - }; - return 0; -} - -/*....................................................................... - * Write a string to the terminal after expanding tabs and control - * characters to their multi-character representations. - * - * Input: - * gl GetLine * The resource object of this program. - * string char * The string to be output. - * pad char Many terminals have the irritating feature that - * when one writes a character in the last column of - * of the terminal, the cursor isn't wrapped to the - * start of the next line until one more character - * is written. Some terminals don't do this, so - * after such a write, we don't know where the - * terminal is unless we output an extra character. - * This argument specifies the character to write. - * If at the end of the input line send '\0' or a - * space, and a space will be written. Otherwise, - * pass the next character in the input line - * following the one being written. - * Output: - * return int 0 - OK. - */ -static int gl_output_string(GetLine *gl, const char *string, char pad) -{ - const char *cptr; /* A pointer into string[] */ - for(cptr=string; *cptr; cptr++) { - char nextc = cptr[1]; - if(gl_output_char(gl, *cptr, nextc ? nextc : pad)) - return 1; - }; - return 0; -} - -/*....................................................................... - * Given a character position within gl->line[], work out the - * corresponding gl->term_curpos position on the terminal. - * - * Input: - * gl GetLine * The resource object of this library. - * buff_curpos int The position within gl->line[]. - * - * Output: - * return int The gl->term_curpos position on the terminal. - */ -static int gl_buff_curpos_to_term_curpos(GetLine *gl, int buff_curpos) -{ - return gl->prompt_len + gl_displayed_string_width(gl, gl->line, buff_curpos, - gl->prompt_len); -} - -/*....................................................................... - * Move the terminal cursor position. - * - * Input: - * gl GetLine * The resource object of this library. - * term_curpos int The destination terminal cursor position. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_set_term_curpos(GetLine *gl, int term_curpos) -{ - return gl_terminal_move_cursor(gl, term_curpos - gl->term_curpos); -} - -/*....................................................................... - * This is an action function that moves the buffer cursor one character - * left, and updates the terminal cursor to match. - */ -static KT_KEY_FN(gl_cursor_left) -{ - return gl_place_cursor(gl, gl->buff_curpos - count); -} - -/*....................................................................... - * This is an action function that moves the buffer cursor one character - * right, and updates the terminal cursor to match. - */ -static KT_KEY_FN(gl_cursor_right) -{ - return gl_place_cursor(gl, gl->buff_curpos + count); -} - -/*....................................................................... - * This is an action function that toggles between overwrite and insert - * mode. - */ -static KT_KEY_FN(gl_insert_mode) -{ - gl->insert = !gl->insert; - return 0; -} - -/*....................................................................... - * This is an action function which moves the cursor to the beginning of - * the line. - */ -static KT_KEY_FN(gl_beginning_of_line) -{ - return gl_place_cursor(gl, 0); -} - -/*....................................................................... - * This is an action function which moves the cursor to the end of - * the line. - */ -static KT_KEY_FN(gl_end_of_line) -{ - return gl_place_cursor(gl, gl->ntotal); -} - -/*....................................................................... - * This is an action function which deletes the entire contents of the - * current line. - */ -static KT_KEY_FN(gl_delete_line) -{ -/* - * If in vi command mode, preserve the current line for potential - * use by vi-undo. - */ - gl_save_for_undo(gl); -/* - * Copy the contents of the line to the cut buffer. - */ - strcpy(gl->cutbuf, gl->line); -/* - * Clear the buffer. - */ - gl->ntotal = 0; - gl->line[0] = '\0'; -/* - * Move the terminal cursor to just after the prompt. - */ - if(gl_place_cursor(gl, 0)) - return 1; -/* - * Clear from the end of the prompt to the end of the terminal. - */ - if(gl_output_control_sequence(gl, gl->nline, gl->clear_eod)) - return 1; - return 0; -} - -/*....................................................................... - * This is an action function which deletes all characters between the - * current cursor position and the end of the line. - */ -static KT_KEY_FN(gl_kill_line) -{ -/* - * If in vi command mode, preserve the current line for potential - * use by vi-undo. - */ - gl_save_for_undo(gl); -/* - * Copy the part of the line that is about to be deleted to the cut buffer. - */ - strcpy(gl->cutbuf, gl->line + gl->buff_curpos); -/* - * Terminate the buffered line at the current cursor position. - */ - gl->ntotal = gl->buff_curpos; - gl->line[gl->ntotal] = '\0'; -/* - * Clear the part of the line that follows the cursor. - */ - if(gl_output_control_sequence(gl, gl->nline, gl->clear_eod)) - return 1; -/* - * Explicitly reset the cursor position to allow vi command mode - * constraints on its position to be set. - */ - return gl_place_cursor(gl, gl->buff_curpos); -} - -/*....................................................................... - * This is an action function which deletes all characters between the - * start of the line and the current cursor position. - */ -static KT_KEY_FN(gl_backward_kill_line) -{ -/* - * How many characters are to be deleted from before the cursor? - */ - int nc = gl->buff_curpos - gl->insert_curpos; - if (!nc) - return 0; -/* - * Move the cursor to the start of the line, or in vi input mode, - * the start of the sub-line at which insertion started, and delete - * up to the old cursor position. - */ - return gl_place_cursor(gl, gl->insert_curpos) || - gl_delete_chars(gl, nc, gl->editor == GL_EMACS_MODE || gl->vi.command); -} - -/*....................................................................... - * This is an action function which moves the cursor forward by a word. - */ -static KT_KEY_FN(gl_forward_word) -{ - return gl_place_cursor(gl, gl_nth_word_end_forward(gl, count) + - (gl->editor==GL_EMACS_MODE)); -} - -/*....................................................................... - * This is an action function which moves the cursor forward to the start - * of the next word. - */ -static KT_KEY_FN(gl_forward_to_word) -{ - return gl_place_cursor(gl, gl_nth_word_start_forward(gl, count)); -} - -/*....................................................................... - * This is an action function which moves the cursor backward by a word. - */ -static KT_KEY_FN(gl_backward_word) -{ - return gl_place_cursor(gl, gl_nth_word_start_backward(gl, count)); -} - -/*....................................................................... - * Delete one or more characters, starting with the one under the cursor. - * - * Input: - * gl GetLine * The resource object of this library. - * nc int The number of characters to delete. - * cut int If true, copy the characters to the cut buffer. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_delete_chars(GetLine *gl, int nc, int cut) -{ -/* - * If in vi command mode, preserve the current line for potential - * use by vi-undo. - */ - gl_save_for_undo(gl); -/* - * If there are fewer than nc characters following the cursor, limit - * nc to the number available. - */ - if(gl->buff_curpos + nc > gl->ntotal) - nc = gl->ntotal - gl->buff_curpos; -/* - * Copy the about to be deleted region to the cut buffer. - */ - if(cut) { - memcpy(gl->cutbuf, gl->line + gl->buff_curpos, nc); - gl->cutbuf[nc] = '\0'; - } -/* - * Nothing to delete? - */ - if(nc <= 0) - return 0; -/* - * In vi overwrite mode, restore any previously overwritten characters - * from the undo buffer. - */ - if(gl->editor == GL_VI_MODE && !gl->vi.command && !gl->insert) { -/* - * How many of the characters being deleted can be restored from the - * undo buffer? - */ - int nrestore = gl->buff_curpos + nc <= gl->vi.undo.ntotal ? - nc : gl->vi.undo.ntotal - gl->buff_curpos; -/* - * Restore any available characters. - */ - if(nrestore > 0) - memcpy(gl->line + gl->buff_curpos, gl->vi.undo.line + gl->buff_curpos, - nrestore); -/* - * If their were insufficient characters in the undo buffer, then this - * implies that we are deleting from the end of the line, so we need - * to terminate the line either where the undo buffer ran out, or if - * we are deleting from beyond the end of the undo buffer, at the current - * cursor position. - */ - if(nc != nrestore) { - gl->ntotal = gl->vi.undo.ntotal > gl->buff_curpos ? gl->vi.undo.ntotal : - gl->buff_curpos; - gl->line[gl->ntotal] = '\0'; - }; - } else { -/* - * Copy the remaining part of the line back over the deleted characters. - */ - memmove(gl->line + gl->buff_curpos, gl->line + gl->buff_curpos + nc, - gl->ntotal - gl->buff_curpos - nc + 1); - gl->ntotal -= nc; - }; -/* - * Redraw the remaining characters following the cursor. - */ - if(gl_output_string(gl, gl->line + gl->buff_curpos, '\0')) - return 1; -/* - * Clear to the end of the terminal. - */ - if(gl_output_control_sequence(gl, gl->nline, gl->clear_eod)) - return 1; -/* - * Place the cursor at the start of where the deletion was performed. - */ - return gl_place_cursor(gl, gl->buff_curpos); -} - -/*....................................................................... - * This is an action function which deletes character(s) under the - * cursor without moving the cursor. - */ -static KT_KEY_FN(gl_forward_delete_char) -{ -/* - * Delete 'count' characters. - */ - return gl_delete_chars(gl, count, gl->vi.command); -} - -/*....................................................................... - * This is an action function which deletes character(s) under the - * cursor and moves the cursor back one character. - */ -static KT_KEY_FN(gl_backward_delete_char) -{ -/* - * Restrict the deletion count to the number of characters that - * precede the insertion point. - */ - if(count > gl->buff_curpos - gl->insert_curpos) - count = gl->buff_curpos - gl->insert_curpos; -/* - * If in vi command mode, preserve the current line for potential - * use by vi-undo. - */ - gl_save_for_undo(gl); - return gl_cursor_left(gl, count) || - gl_delete_chars(gl, count, gl->vi.command); -} - -/*....................................................................... - * Starting from the cursor position delete to the specified column. - */ -static KT_KEY_FN(gl_delete_to_column) -{ - if (--count >= gl->buff_curpos) - return gl_forward_delete_char(gl, count - gl->buff_curpos); - else - return gl_backward_delete_char(gl, gl->buff_curpos - count); -} - -/*....................................................................... - * Starting from the cursor position delete characters to a matching - * parenthesis. - */ -static KT_KEY_FN(gl_delete_to_parenthesis) -{ - int curpos = gl_index_of_matching_paren(gl); - if(curpos >= 0) { - gl_save_for_undo(gl); - if(curpos >= gl->buff_curpos) - return gl_forward_delete_char(gl, curpos - gl->buff_curpos + 1); - else - return gl_backward_delete_char(gl, ++gl->buff_curpos - curpos + 1); - }; - return 0; -} - -/*....................................................................... - * This is an action function which deletes from the cursor to the end - * of the word that the cursor is either in or precedes. - */ -static KT_KEY_FN(gl_forward_delete_word) -{ -/* - * If in vi command mode, preserve the current line for potential - * use by vi-undo. - */ - gl_save_for_undo(gl); -/* - * In emacs mode delete to the end of the word. In vi mode delete to the - * start of the net word. - */ - if(gl->editor == GL_EMACS_MODE) { - return gl_delete_chars(gl, - gl_nth_word_end_forward(gl,count) - gl->buff_curpos + 1, 1); - } else { - return gl_delete_chars(gl, - gl_nth_word_start_forward(gl,count) - gl->buff_curpos, - gl->vi.command); - }; -} - -/*....................................................................... - * This is an action function which deletes the word that precedes the - * cursor. - */ -static KT_KEY_FN(gl_backward_delete_word) -{ -/* - * Keep a record of the current cursor position. - */ - int buff_curpos = gl->buff_curpos; -/* - * If in vi command mode, preserve the current line for potential - * use by vi-undo. - */ - gl_save_for_undo(gl); -/* - * Move back 'count' words. - */ - if(gl_backward_word(gl, count)) - return 1; -/* - * Delete from the new cursor position to the original one. - */ - return gl_delete_chars(gl, buff_curpos - gl->buff_curpos, - gl->editor == GL_EMACS_MODE || gl->vi.command); -} - -/*....................................................................... - * Searching in a given direction, delete to the count'th - * instance of a specified or queried character, in the input line. - * - * Input: - * gl GetLine * The getline resource object. - * count int The number of times to search. - * c char The character to be searched for, or '\0' if - * the character should be read from the user. - * forward int True if searching forward. - * onto int True if the search should end on top of the - * character, false if the search should stop - * one character before the character in the - * specified search direction. - * change int If true, this function is being called upon - * to do a vi change command, in which case the - * user will be left in insert mode after the - * deletion. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_delete_find(GetLine *gl, int count, char c, int forward, - int onto, int change) -{ -/* - * Search for the character, and abort the deletion if not found. - */ - int pos = gl_find_char(gl, count, forward, onto, c); - if(pos < 0) - return 0; -/* - * If in vi command mode, preserve the current line for potential - * use by vi-undo. - */ - gl_save_for_undo(gl); -/* - * Allow the cursor to be at the end of the line if this is a change - * command. - */ - if(change) - gl->vi.command = 0; -/* - * Delete the appropriate span of characters. - */ - if(forward) { - if(gl_delete_chars(gl, pos - gl->buff_curpos + 1, 1)) - return 1; - } else { - int buff_curpos = gl->buff_curpos; - if(gl_place_cursor(gl, pos) || - gl_delete_chars(gl, buff_curpos - gl->buff_curpos, 1)) - return 1; - }; -/* - * If this is a change operation, switch the insert mode. - */ - if(change && gl_vi_insert(gl, 0)) - return 1; - return 0; -} - -/*....................................................................... - * This is an action function which deletes forward from the cursor up to and - * including a specified character. - */ -static KT_KEY_FN(gl_forward_delete_find) -{ - return gl_delete_find(gl, count, '\0', 1, 1, 0); -} - -/*....................................................................... - * This is an action function which deletes backward from the cursor back to - * and including a specified character. - */ -static KT_KEY_FN(gl_backward_delete_find) -{ - return gl_delete_find(gl, count, '\0', 0, 1, 0); -} - -/*....................................................................... - * This is an action function which deletes forward from the cursor up to but - * not including a specified character. - */ -static KT_KEY_FN(gl_forward_delete_to) -{ - return gl_delete_find(gl, count, '\0', 1, 0, 0); -} - -/*....................................................................... - * This is an action function which deletes backward from the cursor back to - * but not including a specified character. - */ -static KT_KEY_FN(gl_backward_delete_to) -{ - return gl_delete_find(gl, count, '\0', 0, 0, 0); -} - -/*....................................................................... - * This is an action function which deletes to a character specified by a - * previous search. - */ -static KT_KEY_FN(gl_delete_refind) -{ - return gl_delete_find(gl, count, gl->vi.find_char, gl->vi.find_forward, - gl->vi.find_onto, 0); -} - -/*....................................................................... - * This is an action function which deletes to a character specified by a - * previous search, but in the opposite direction. - */ -static KT_KEY_FN(gl_delete_invert_refind) -{ - return gl_delete_find(gl, count, gl->vi.find_char, - !gl->vi.find_forward, gl->vi.find_onto, 0); -} - -/*....................................................................... - * This is an action function which converts the characters in the word - * following the cursor to upper case. - */ -static KT_KEY_FN(gl_upcase_word) -{ -/* - * Locate the count'th word ending after the cursor. - */ - int last = gl_nth_word_end_forward(gl, count); -/* - * If in vi command mode, preserve the current line for potential - * use by vi-undo. - */ - gl_save_for_undo(gl); -/* - * Upcase characters from the current cursor position to 'last'. - */ - while(gl->buff_curpos <= last) { - char *cptr = gl->line + gl->buff_curpos++; -/* - * Convert the character to upper case? - */ - if(islower((int)(unsigned char) *cptr)) - *cptr = toupper((int) *cptr); -/* - * Write the possibly modified character back. Note that for non-modified - * characters we want to do this as well, so as to advance the cursor. - */ - if(gl_output_char(gl, *cptr, cptr[1])) - return 1; - }; - return gl_place_cursor(gl, gl->buff_curpos); /* bounds check */ -} - -/*....................................................................... - * This is an action function which converts the characters in the word - * following the cursor to lower case. - */ -static KT_KEY_FN(gl_downcase_word) -{ -/* - * Locate the count'th word ending after the cursor. - */ - int last = gl_nth_word_end_forward(gl, count); -/* - * If in vi command mode, preserve the current line for potential - * use by vi-undo. - */ - gl_save_for_undo(gl); -/* - * Upcase characters from the current cursor position to 'last'. - */ - while(gl->buff_curpos <= last) { - char *cptr = gl->line + gl->buff_curpos++; -/* - * Convert the character to upper case? - */ - if(isupper((int)(unsigned char) *cptr)) - *cptr = tolower((int) *cptr); -/* - * Write the possibly modified character back. Note that for non-modified - * characters we want to do this as well, so as to advance the cursor. - */ - if(gl_output_char(gl, *cptr, cptr[1])) - return 1; - }; - return gl_place_cursor(gl, gl->buff_curpos); /* bounds check */ -} - -/*....................................................................... - * This is an action function which converts the first character of the - * following word to upper case, in order to capitalize the word, and - * leaves the cursor at the end of the word. - */ -static KT_KEY_FN(gl_capitalize_word) -{ - char *cptr; /* &gl->line[gl->buff_curpos] */ - int first; /* True for the first letter of the word */ - int i; -/* - * Keep a record of the current insert mode and the cursor position. - */ - int insert = gl->insert; -/* - * If in vi command mode, preserve the current line for potential - * use by vi-undo. - */ - gl_save_for_undo(gl); -/* - * We want to overwrite the modified word. - */ - gl->insert = 0; -/* - * Capitalize 'count' words. - */ - for(i=0; i<count && gl->buff_curpos < gl->ntotal; i++) { - int pos = gl->buff_curpos; -/* - * If we are not already within a word, skip to the start of the word. - */ - for(cptr = gl->line + pos ; pos<gl->ntotal && !gl_is_word_char((int) *cptr); - pos++, cptr++) - ; -/* - * Move the cursor to the new position. - */ - if(gl_place_cursor(gl, pos)) - return 1; -/* - * While searching for the end of the word, change lower case letters - * to upper case. - */ - for(first=1; gl->buff_curpos<gl->ntotal && gl_is_word_char((int) *cptr); - gl->buff_curpos++, cptr++) { -/* - * Convert the character to upper case? - */ - if(first) { - if(islower((int)(unsigned char) *cptr)) - *cptr = toupper((int) *cptr); - } else { - if(isupper((int)(unsigned char) *cptr)) - *cptr = tolower((int) *cptr); - }; - first = 0; -/* - * Write the possibly modified character back. Note that for non-modified - * characters we want to do this as well, so as to advance the cursor. - */ - if(gl_output_char(gl, *cptr, cptr[1])) - return 1; - }; - }; -/* - * Restore the insertion mode. - */ - gl->insert = insert; - return gl_place_cursor(gl, gl->buff_curpos); /* bounds check */ -} - -/*....................................................................... - * This is an action function which redraws the current line. - */ -static KT_KEY_FN(gl_redisplay) -{ -/* - * Keep a record of the current cursor position. - */ - int buff_curpos = gl->buff_curpos; -/* - * Move the cursor to the start of the terminal line, and clear from there - * to the end of the display. - */ - if(gl_set_term_curpos(gl, 0) || - gl_output_control_sequence(gl, gl->nline, gl->clear_eod)) - return 1; -/* - * Display the current prompt. - */ - if(gl_display_prompt(gl)) - return 1; -/* - * Render the part of the line that the user has typed in so far. - */ - if(gl_output_string(gl, gl->line, '\0')) - return 1; -/* - * Restore the cursor position. - */ - if(gl_place_cursor(gl, buff_curpos)) - return 1; -/* - * Flush the redisplayed line to the terminal. - */ - return gl_flush_output(gl); -} - -/*....................................................................... - * This is an action function which clears the display and redraws the - * input line from the home position. - */ -static KT_KEY_FN(gl_clear_screen) -{ -/* - * Record the current cursor position. - */ - int buff_curpos = gl->buff_curpos; -/* - * Home the cursor and clear from there to the end of the display. - */ - if(gl_output_control_sequence(gl, gl->nline, gl->home) || - gl_output_control_sequence(gl, gl->nline, gl->clear_eod)) - return 1; -/* - * Redisplay the line. - */ - gl->term_curpos = 0; - gl->buff_curpos = 0; - if(gl_redisplay(gl,1)) - return 1; -/* - * Restore the cursor position. - */ - return gl_place_cursor(gl, buff_curpos); -} - -/*....................................................................... - * This is an action function which swaps the character under the cursor - * with the character to the left of the cursor. - */ -static KT_KEY_FN(gl_transpose_chars) -{ - char from[3]; /* The original string of 2 characters */ - char swap[3]; /* The swapped string of two characters */ -/* - * If we are at the beginning or end of the line, there aren't two - * characters to swap. - */ - if(gl->buff_curpos < 1 || gl->buff_curpos >= gl->ntotal) - return 0; -/* - * If in vi command mode, preserve the current line for potential - * use by vi-undo. - */ - gl_save_for_undo(gl); -/* - * Get the original and swapped strings of the two characters. - */ - from[0] = gl->line[gl->buff_curpos - 1]; - from[1] = gl->line[gl->buff_curpos]; - from[2] = '\0'; - swap[0] = gl->line[gl->buff_curpos]; - swap[1] = gl->line[gl->buff_curpos - 1]; - swap[2] = '\0'; -/* - * Move the cursor to the start of the two characters. - */ - if(gl_place_cursor(gl, gl->buff_curpos-1)) - return 1; -/* - * Swap the two characters in the buffer. - */ - gl->line[gl->buff_curpos] = swap[0]; - gl->line[gl->buff_curpos+1] = swap[1]; -/* - * If the sum of the displayed width of the two characters - * in their current and final positions is the same, swapping can - * be done by just overwriting with the two swapped characters. - */ - if(gl_displayed_string_width(gl, from, -1, gl->term_curpos) == - gl_displayed_string_width(gl, swap, -1, gl->term_curpos)) { - int insert = gl->insert; - gl->insert = 0; - if(gl_output_char(gl, swap[0], swap[1]) || - gl_output_char(gl, swap[1], gl->line[gl->buff_curpos+2])) - return 1; - gl->insert = insert; -/* - * If the swapped substring has a different displayed size, we need to - * redraw everything after the first of the characters. - */ - } else { - if(gl_output_string(gl, gl->line + gl->buff_curpos, '\0') || - gl_output_control_sequence(gl, gl->nline, gl->clear_eod)) - return 1; - }; -/* - * Advance the cursor to the character after the swapped pair. - */ - return gl_place_cursor(gl, gl->buff_curpos + 2); -} - -/*....................................................................... - * This is an action function which sets a mark at the current cursor - * location. - */ -static KT_KEY_FN(gl_set_mark) -{ - gl->buff_mark = gl->buff_curpos; - return 0; -} - -/*....................................................................... - * This is an action function which swaps the mark location for the - * cursor location. - */ -static KT_KEY_FN(gl_exchange_point_and_mark) -{ -/* - * Get the old mark position, and limit to the extent of the input - * line. - */ - int old_mark = gl->buff_mark <= gl->ntotal ? gl->buff_mark : gl->ntotal; -/* - * Make the current cursor position the new mark. - */ - gl->buff_mark = gl->buff_curpos; -/* - * Move the cursor to the old mark position. - */ - return gl_place_cursor(gl, old_mark); -} - -/*....................................................................... - * This is an action function which deletes the characters between the - * mark and the cursor, recording them in gl->cutbuf for later pasting. - */ -static KT_KEY_FN(gl_kill_region) -{ -/* - * If in vi command mode, preserve the current line for potential - * use by vi-undo. - */ - gl_save_for_undo(gl); -/* - * Limit the mark to be within the line. - */ - if(gl->buff_mark > gl->ntotal) - gl->buff_mark = gl->ntotal; -/* - * If there are no characters between the cursor and the mark, simply clear - * the cut buffer. - */ - if(gl->buff_mark == gl->buff_curpos) { - gl->cutbuf[0] = '\0'; - return 0; - }; -/* - * If the mark is before the cursor, swap the cursor and the mark. - */ - if(gl->buff_mark < gl->buff_curpos && gl_exchange_point_and_mark(gl,1)) - return 1; -/* - * Delete the characters. - */ - if(gl_delete_chars(gl, gl->buff_mark - gl->buff_curpos, 1)) - return 1; -/* - * Make the mark the same as the cursor position. - */ - gl->buff_mark = gl->buff_curpos; - return 0; -} - -/*....................................................................... - * This is an action function which records the characters between the - * mark and the cursor, in gl->cutbuf for later pasting. - */ -static KT_KEY_FN(gl_copy_region_as_kill) -{ - int ca, cb; /* The indexes of the first and last characters in the region */ - int mark; /* The position of the mark */ -/* - * Get the position of the mark, limiting it to lie within the line. - */ - mark = gl->buff_mark > gl->ntotal ? gl->ntotal : gl->buff_mark; -/* - * If there are no characters between the cursor and the mark, clear - * the cut buffer. - */ - if(mark == gl->buff_curpos) { - gl->cutbuf[0] = '\0'; - return 0; - }; -/* - * Get the line indexes of the first and last characters in the region. - */ - if(mark < gl->buff_curpos) { - ca = mark; - cb = gl->buff_curpos - 1; - } else { - ca = gl->buff_curpos; - cb = mark - 1; - }; -/* - * Copy the region to the cut buffer. - */ - memcpy(gl->cutbuf, gl->line + ca, cb + 1 - ca); - gl->cutbuf[cb + 1 - ca] = '\0'; - return 0; -} - -/*....................................................................... - * This is an action function which inserts the contents of the cut - * buffer at the current cursor location. - */ -static KT_KEY_FN(gl_yank) -{ - int i; -/* - * Set the mark at the current location. - */ - gl->buff_mark = gl->buff_curpos; -/* - * Do nothing else if the cut buffer is empty. - */ - if(gl->cutbuf[0] == '\0') - return gl_ring_bell(gl, 1); -/* - * If in vi command mode, preserve the current line for potential - * use by vi-undo. - */ - gl_save_for_undo(gl); -/* - * Insert the string count times. - */ - for(i=0; i<count; i++) { - if(gl_add_string_to_line(gl, gl->cutbuf)) - return 1; - }; -/* - * gl_add_string_to_line() leaves the cursor after the last character that - * was pasted, whereas vi leaves the cursor over the last character pasted. - */ - if(gl->editor == GL_VI_MODE && gl_cursor_left(gl, 1)) - return 1; - return 0; -} - -/*....................................................................... - * This is an action function which inserts the contents of the cut - * buffer one character beyond the current cursor location. - */ -static KT_KEY_FN(gl_append_yank) -{ - int was_command = gl->vi.command; - int i; -/* - * If the cut buffer is empty, ring the terminal bell. - */ - if(gl->cutbuf[0] == '\0') - return gl_ring_bell(gl, 1); -/* - * Set the mark at the current location + 1. - */ - gl->buff_mark = gl->buff_curpos + 1; -/* - * If in vi command mode, preserve the current line for potential - * use by vi-undo. - */ - gl_save_for_undo(gl); -/* - * Arrange to paste the text in insert mode after the current character. - */ - if(gl_vi_append(gl, 0)) - return 1; -/* - * Insert the string count times. - */ - for(i=0; i<count; i++) { - if(gl_add_string_to_line(gl, gl->cutbuf)) - return 1; - }; -/* - * Switch back to command mode if necessary. - */ - if(was_command) - gl_vi_command_mode(gl); - return 0; -} - -#ifdef USE_SIGWINCH -/*....................................................................... - * Respond to the receipt of a window change signal. - * - * Input: - * gl GetLine * The resource object of this library. - * redisplay int If true redisplay the current line after - * getting the new window size. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_resize_terminal(GetLine *gl, int redisplay) -{ - int lines_used; /* The number of lines currently in use */ - struct winsize size; /* The new size information */ - int i; -/* - * Record the fact that the sigwinch signal has been noted. - */ - if(gl_pending_signal == SIGWINCH) - gl_pending_signal = -1; -/* - * Query the new terminal window size. Ignore invalid responses. - */ - if(ioctl(gl->output_fd, TIOCGWINSZ, &size) == 0 && - size.ws_row > 0 && size.ws_col > 0) { -/* - * Redisplay the input line? - */ - if(redisplay) { -/* - * How many lines are currently displayed. - */ - lines_used = (gl_displayed_string_width(gl,gl->line,-1,gl->prompt_len) + - gl->prompt_len + gl->ncolumn - 1) / gl->ncolumn; -/* - * Move to the cursor to the start of the line. - */ - for(i=1; i<lines_used; i++) { - if(gl_output_control_sequence(gl, 1, gl->up)) - return 1; - }; - if(gl_output_control_sequence(gl, 1, gl->bol)) - return 1; -/* - * Clear to the end of the terminal. - */ - if(gl_output_control_sequence(gl, size.ws_row, gl->clear_eod)) - return 1; -/* - * Record the fact that the cursor is now at the beginning of the line. - */ - gl->term_curpos = 0; - }; -/* - * Update the recorded window size. - */ - gl->nline = size.ws_row; - gl->ncolumn = size.ws_col; - }; -/* - * Redisplay the line? - */ - return redisplay ? gl_redisplay(gl,1) : 0; -} -#endif - -/*....................................................................... - * This is the action function that recalls the previous line in the - * history buffer. - */ -static KT_KEY_FN(gl_up_history) -{ -/* - * In vi mode, switch to command mode, since the user is very - * likely to want to move around newly recalled lines. - */ - gl_vi_command_mode(gl); -/* - * Forget any previous recall session. - */ - gl->preload_id = 0; -/* - * We don't want a search prefix for this function. - */ - if(_glh_search_prefix(gl->glh, gl->line, 0)) - return 1; -/* - * Recall the count'th next older line in the history list. If the first one - * fails we can return since nothing has changed otherwise we must continue - * and update the line state. - */ - if(_glh_find_backwards(gl->glh, gl->line, gl->linelen) == NULL) - return 0; - while(--count && _glh_find_backwards(gl->glh, gl->line, gl->linelen)) - ; -/* - * Record the number of characters in the new string. - */ - gl->ntotal = strlen(gl->line); -/* - * Arrange to have the cursor placed at the end of the new line. - */ - gl->buff_curpos = strlen(gl->line); -/* - * Erase and display the new line. - */ - return gl_redisplay(gl,1); -} - -/*....................................................................... - * This is the action function that recalls the next line in the - * history buffer. - */ -static KT_KEY_FN(gl_down_history) -{ -/* - * In vi mode, switch to command mode, since the user is very - * likely to want to move around newly recalled lines. - */ - gl_vi_command_mode(gl); -/* - * If no search is currently in progress continue a previous recall - * session from a previous entered line if possible. - */ - if(_glh_line_id(gl->glh, 0) == 0 && gl->preload_id) { - _glh_recall_line(gl->glh, gl->preload_id, gl->line, gl->linelen); - gl->preload_id = 0; - } else { -/* - * We don't want a search prefix for this function. - */ - if(_glh_search_prefix(gl->glh, gl->line, 0)) - return 1; -/* - * Recall the count'th next newer line in the history list. If the first one - * fails we can return since nothing has changed otherwise we must continue - * and update the line state. - */ - if(_glh_find_forwards(gl->glh, gl->line, gl->linelen) == NULL) - return 0; - while(--count && _glh_find_forwards(gl->glh, gl->line, gl->linelen)) - ; - }; -/* - * Record the number of characters in the new string. - */ - gl->ntotal = strlen(gl->line); -/* - * Arrange to have the cursor placed at the end of the new line. - */ - gl->buff_curpos = strlen(gl->line); -/* - * Erase and display the new line. - */ - return gl_redisplay(gl,1); -} - -/*....................................................................... - * This is the action function that recalls the previous line in the - * history buffer whos prefix matches the characters that currently - * precede the cursor. By setting count=-1, this can be used internally - * to force searching for the prefix used in the last search. - */ -static KT_KEY_FN(gl_history_search_backward) -{ -/* - * In vi mode, switch to command mode, since the user is very - * likely to want to move around newly recalled lines. - */ - gl_vi_command_mode(gl); -/* - * Forget any previous recall session. - */ - gl->preload_id = 0; -/* - * If the previous thing that the user did wasn't to execute a history - * search function, set the search prefix equal to the string that - * precedes the cursor. In vi command mode include the character that - * is under the cursor in the string. If count<0 force a repeat search - * even if the last command wasn't a history command. - */ - if(gl->last_search != gl->keyseq_count - 1 && count>=0 && - _glh_search_prefix(gl->glh, gl->line, gl->buff_curpos + - (gl->editor==GL_VI_MODE && gl->ntotal>0))) - return 1; -/* - * Record the key sequence number in which this search function is - * being executed, so that the next call to this function or - * gl_history_search_forward() knows if any other operations - * were performed in between. - */ - gl->last_search = gl->keyseq_count; -/* - * Search backwards for a match to the part of the line which precedes the - * cursor. - */ - if(_glh_find_backwards(gl->glh, gl->line, gl->linelen) == NULL) - return 0; -/* - * Record the number of characters in the new string. - */ - gl->ntotal = strlen(gl->line); -/* - * Arrange to have the cursor placed at the end of the new line. - */ - gl->buff_curpos = strlen(gl->line); -/* - * Erase and display the new line. - */ - return gl_redisplay(gl,1); -} - -/*....................................................................... - * This is the action function that recalls the previous line in the - * history buffer who's prefix matches that specified in an earlier call - * to gl_history_search_backward() or gl_history_search_forward(). - */ -static KT_KEY_FN(gl_history_re_search_backward) -{ - return gl_history_search_backward(gl, -1); -} - -/*....................................................................... - * This is the action function that recalls the next line in the - * history buffer who's prefix matches that specified in the earlier call - * to gl_history_search_backward) which started the history search. - * By setting count=-1, this can be used internally to force searching - * for the prefix used in the last search. - */ -static KT_KEY_FN(gl_history_search_forward) -{ -/* - * In vi mode, switch to command mode, since the user is very - * likely to want to move around newly recalled lines. - */ - gl_vi_command_mode(gl); -/* - * If the previous thing that the user did wasn't to execute a history - * search function, set the search prefix equal to the string that - * precedes the cursor. In vi command mode include the character that - * is under the cursor in the string. If count<0 force a repeat search - * even if the last command wasn't a history command. - */ - if(gl->last_search != gl->keyseq_count - 1 && count>=0 && - _glh_search_prefix(gl->glh, gl->line, gl->buff_curpos + - (gl->editor==GL_VI_MODE && gl->ntotal>0))) - return 1; -/* - * Record the key sequence number in which this search function is - * being executed, so that the next call to this function or - * gl_history_search_backward() knows if any other operations - * were performed in between. - */ - gl->last_search = gl->keyseq_count; -/* - * Search forwards for the next matching line. - */ - if(_glh_find_forwards(gl->glh, gl->line, gl->linelen) == NULL) - return 0; -/* - * Record the number of characters in the new string. - */ - gl->ntotal = strlen(gl->line); -/* - * Arrange for the cursor to be placed at the end of the new line. - */ - gl->buff_curpos = strlen(gl->line); -/* - * Erase and display the new line. - */ - return gl_redisplay(gl,1); -} - -/*....................................................................... - * This is the action function that recalls the next line in the - * history buffer who's prefix matches that specified in an earlier call - * to gl_history_search_backward() or gl_history_search_forward(). - */ -static KT_KEY_FN(gl_history_re_search_forward) -{ - return gl_history_search_forward(gl, -1); -} - -/*....................................................................... - * This is the tab completion function that completes the filename that - * precedes the cursor position. - */ -static KT_KEY_FN(gl_complete_word) -{ - CplMatches *matches; /* The possible completions */ - int redisplay=0; /* True if the whole line needs to be redrawn */ - int suffix_len; /* The length of the completion extension */ - int cont_len; /* The length of any continuation suffix */ - int nextra; /* The number of characters being added to the */ - /* total length of the line. */ - int buff_pos; /* The buffer index at which the completion is */ - /* to be inserted. */ -/* - * In vi command mode, switch to append mode so that the character below - * the character is included in the completion (otherwise people can't - * complete at the end of the line). - */ - if(gl->vi.command && gl_vi_append(gl, 0)) - return 1; -/* - * Get the cursor position at which the completion is to be inserted. - */ - buff_pos = gl->buff_curpos; -/* - * Perform the completion. - */ - matches = cpl_complete_word(gl->cpl, gl->line, gl->buff_curpos, gl->cpl_data, - gl->cpl_fn); - if(!matches) { - if(gl->echo && - fprintf(gl->output_fp, "\r\n%s\n", cpl_last_error(gl->cpl)) < 0) - return 1; - gl->term_curpos = 0; - redisplay = 1; -/* - * Are there any completions? - */ - } else if(matches->nmatch >= 1) { -/* - * If there any ambiguous matches, report them, starting on a new line. - */ - if(matches->nmatch > 1 && gl->echo) { - if(fprintf(gl->output_fp, "\r\n") < 0) - return 1; - cpl_list_completions(matches, gl->output_fp, gl->ncolumn); - redisplay = 1; - }; -/* - * If the callback called gl_change_prompt(), we will need to redisplay - * the whole line. - */ - if(gl->prompt_changed) - redisplay = 1; -/* - * Get the length of the suffix and any continuation suffix to add to it. - */ - suffix_len = strlen(matches->suffix); - cont_len = strlen(matches->cont_suffix); -/* - * If there is an unambiguous match, and the continuation suffix ends in - * a newline, strip that newline and arrange to have getline return - * after this action function returns. - */ - if(matches->nmatch==1 && cont_len > 0 && - matches->cont_suffix[cont_len - 1] == '\n') { - cont_len--; - if(gl_newline(gl, 1)) - return 1; - }; -/* - * Work out the number of characters that are to be added. - */ - nextra = suffix_len + cont_len; -/* - * Is there anything to be added? - */ - if(nextra) { -/* - * Will there be space for the expansion in the line buffer? - */ - if(gl->ntotal + nextra < gl->linelen) { -/* - * Make room to insert the filename extension. - */ - memmove(gl->line + gl->buff_curpos + nextra, gl->line + gl->buff_curpos, - gl->ntotal - gl->buff_curpos); -/* - * Insert the filename extension. - */ - memcpy(gl->line + gl->buff_curpos, matches->suffix, suffix_len); -/* - * Add the terminating characters. - */ - memcpy(gl->line + gl->buff_curpos + suffix_len, matches->cont_suffix, - cont_len); -/* - * Record the increased length of the line. - */ - gl->ntotal += nextra; -/* - * Place the cursor position at the end of the completion. - */ - gl->buff_curpos += nextra; -/* - * Terminate the extended line. - */ - gl->line[gl->ntotal] = '\0'; -/* - * If we don't have to redisplay the whole line, redisplay the part - * of the line which follows the original cursor position, and place - * the cursor at the end of the completion. - */ - if(!redisplay) { - if(gl_output_control_sequence(gl, gl->nline, gl->clear_eod) || - gl_output_string(gl, gl->line + buff_pos, '\0') || - gl_place_cursor(gl, gl->buff_curpos)) - return 1; - }; - } else { - fprintf(stderr, - "\r\nInsufficient room in line for file completion.\r\n"); - redisplay = 1; - }; - }; - }; -/* - * Redisplay the whole line? - */ - if(redisplay) { - gl->term_curpos = 0; - if(gl_redisplay(gl,1)) - return 1; - }; - return 0; -} - -/*....................................................................... - * This is the function that expands the filename that precedes the - * cursor position. It expands ~user/ expressions, $envvar expressions, - * and wildcards. - */ -static KT_KEY_FN(gl_expand_filename) -{ - char *start_path; /* The pointer to the start of the pathname in */ - /* gl->line[]. */ - FileExpansion *result; /* The results of the filename expansion */ - int pathlen; /* The length of the pathname being expanded */ - int redisplay=0; /* True if the whole line needs to be redrawn */ - int length; /* The number of characters needed to display the */ - /* expanded files. */ - int nextra; /* The number of characters to be added */ - int i,j; -/* - * In vi command mode, switch to append mode so that the character below - * the character is included in the completion (otherwise people can't - * complete at the end of the line). - */ - if(gl->vi.command && gl_vi_append(gl, 0)) - return 1; -/* - * Locate the start of the filename that precedes the cursor position. - */ - start_path = _pu_start_of_path(gl->line, - gl->buff_curpos > 0 ? gl->buff_curpos : 0); - if(!start_path) - return 1; -/* - * Get the length of the string that is to be expanded. - */ - pathlen = gl->buff_curpos - (start_path - gl->line); -/* - * Attempt to expand it. - */ - result = ef_expand_file(gl->ef, start_path, pathlen); -/* - * If there was an error, report the error on a new line, then redraw - * the original line. - */ - if(!result) { - if(gl->echo && - fprintf(gl->output_fp, "\r\n%s\n", ef_last_error(gl->ef)) < 0) - return 1; - gl->term_curpos = 0; - return gl_redisplay(gl,1); - }; -/* - * If no files matched, report this as well. - */ - if(result->nfile == 0 || !result->exists) { - if(gl->echo && fprintf(gl->output_fp, "\r\nNo files match.\n") < 0) - return 1; - gl->term_curpos = 0; - return gl_redisplay(gl,1); - }; -/* - * If in vi command mode, preserve the current line for potential use by - * vi-undo. - */ - gl_save_for_undo(gl); -/* - * Work out how much space we will need to display all of the matching - * filenames, taking account of the space that we need to place between - * them, and the number of additional '\' characters needed to escape - * spaces, tabs and backslash characters in the individual filenames. - */ - length = 0; - for(i=0; i<result->nfile; i++) { - char *file = result->files[i]; - while(*file) { - int c = *file++; - switch(c) { - case ' ': case '\t': case '\\': case '*': case '?': case '[': - length++; /* Count extra backslash characters */ - }; - length++; /* Count the character itself */ - }; - length++; /* Count the space that follows each filename */ - }; -/* - * Work out the number of characters that are to be added. - */ - nextra = length - pathlen; -/* - * Will there be space for the expansion in the line buffer? - */ - if(gl->ntotal + nextra >= gl->linelen) { - fprintf(stderr, "\r\nInsufficient room in line for file expansion.\r\n"); - redisplay = 1; - } else { -/* - * Do we need to move the part of the line that followed the unexpanded - * filename? - */ - if(nextra != 0) { - memmove(gl->line + gl->buff_curpos + nextra, gl->line + gl->buff_curpos, - gl->ntotal - gl->buff_curpos); - }; -/* - * Insert the filenames, separated by spaces, and with internal spaces, - * tabs and backslashes escaped with backslashes. - */ - for(i=0,j=start_path - gl->line; i<result->nfile; i++) { - char *file = result->files[i]; - while(*file) { - int c = *file++; - switch(c) { - case ' ': case '\t': case '\\': case '*': case '?': case '[': - gl->line[j++] = '\\'; - }; - gl->line[j++] = c; - }; - gl->line[j++] = ' '; - }; -/* - * Record the increased length of the line. - */ - gl->ntotal += nextra; -/* - * Place the cursor position at the end of the expansion. - */ - gl->buff_curpos += nextra; -/* - * Terminate the extended line. - */ - gl->line[gl->ntotal] = '\0'; - }; -/* - * Display the whole line on a new line? - */ - if(redisplay) { - gl->term_curpos = 0; - return gl_redisplay(gl,1); - }; -/* - * Otherwise redisplay the part of the line which follows the start of - * the original filename. - */ - if(gl_set_term_curpos(gl, gl_buff_curpos_to_term_curpos(gl, start_path - gl->line)) || - gl_output_control_sequence(gl, gl->nline, gl->clear_eod) || - gl_output_string(gl, start_path, gl->line[gl->buff_curpos])) - return 1; -/* - * Restore the cursor position to the end of the expansion. - */ - return gl_place_cursor(gl, gl->buff_curpos); -} - -/*....................................................................... - * This is the action function that lists glob expansions of the - * filename that precedes the cursor position. It expands ~user/ - * expressions, $envvar expressions, and wildcards. - */ -static KT_KEY_FN(gl_list_glob) -{ - char *start_path; /* The pointer to the start of the pathname in */ - /* gl->line[]. */ - FileExpansion *result; /* The results of the filename expansion */ - int pathlen; /* The length of the pathname being expanded */ -/* - * Locate the start of the filename that precedes the cursor position. - */ - start_path = _pu_start_of_path(gl->line, - gl->buff_curpos > 0 ? gl->buff_curpos : 0); - if(!start_path) - return 1; -/* - * Get the length of the string that is to be expanded. - */ - pathlen = gl->buff_curpos - (start_path - gl->line); -/* - * Attempt to expand it. - */ - result = ef_expand_file(gl->ef, start_path, pathlen); -/* - * If there was an error, report the error. - */ - if(!result) { - if(gl->echo && - fprintf(gl->output_fp, "\r\n%s\n", ef_last_error(gl->ef)) < 0) - return 1; -/* - * If no files matched, report this as well. - */ - } else if(result->nfile == 0 || !result->exists) { - if(gl->echo && fprintf(gl->output_fp, "\r\nNo files match.\n") < 0) - return 1; -/* - * List the matching expansions. - */ - } else if(gl->echo) { - if(fprintf(gl->output_fp, "\r\n") < 0) - return 1; - ef_list_expansions(result, gl->output_fp, gl->ncolumn); - }; -/* - * Redisplay the line being edited. - */ - gl->term_curpos = 0; - return gl_redisplay(gl,1); -} - -/*....................................................................... - * Return non-zero if a character should be considered a part of a word. - * - * Input: - * c int The character to be tested. - * Output: - * return int True if the character should be considered part of a word. - */ -static int gl_is_word_char(int c) -{ - return isalnum((int)(unsigned char)c) || strchr(GL_WORD_CHARS, c) != NULL; -} - -/*....................................................................... - * Override the builtin file-completion callback that is bound to the - * "complete_word" action function. - * - * Input: - * gl GetLine * The resource object of the command-line input - * module. - * data void * This is passed to match_fn() whenever it is - * called. It could, for example, point to a - * symbol table where match_fn() could look - * for possible completions. - * match_fn CplMatchFn * The function that will identify the prefix - * to be completed from the input line, and - * report matching symbols. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_customize_completion(GetLine *gl, void *data, CplMatchFn *match_fn) -{ -/* - * Check the arguments. - */ - if(!gl || !match_fn) { - fprintf(stderr, "gl_customize_completion: NULL argument(s).\n"); - return 1; - }; -/* - * Record the new completion function and its callback data. - */ - gl->cpl_fn = match_fn; - gl->cpl_data = data; - return 0; -} - -/*....................................................................... - * Change the terminal (or stream) that getline interacts with. - * - * Input: - * gl GetLine * The resource object of the command-line input - * module. - * input_fp FILE * The stdio stream to read from. - * output_fp FILE * The stdio stream to write to. - * term char * The terminal type. This can be NULL if - * either or both of input_fp and output_fp don't - * refer to a terminal. Otherwise it should refer - * to an entry in the terminal information database. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_change_terminal(GetLine *gl, FILE *input_fp, FILE *output_fp, - const char *term) -{ - int is_term = 0; /* True if both input_fd and output_fd are associated */ - /* with a terminal. */ -/* - * Require that input_fp and output_fp both be valid. - */ - if(!input_fp || !output_fp) { - fprintf(stderr, "\r\ngl_change_terminal: Bad input/output stream(s).\n"); - return 1; - }; -/* - * If we are displacing a previous terminal, remove it from the list - * of fds being watched. - */ -#ifdef HAVE_SELECT - if(gl->input_fd >= 0) - FD_CLR(gl->input_fd, &gl->rfds); -#endif -/* - * Record the file descriptors and streams. - */ - gl->input_fp = input_fp; - gl->input_fd = fileno(input_fp); - gl->output_fp = output_fp; - gl->output_fd = fileno(output_fp); -/* - * Make sure that the file descriptor will be visible in the set to - * be watched. - */ -#ifdef HAVE_SELECT - FD_SET(gl->input_fd, &gl->rfds); - if(gl->input_fd > gl->max_fd) - gl->max_fd = gl->input_fd; -#endif -/* - * Disable terminal interaction until we have enough info to interact - * with the terminal. - */ - gl->is_term = 0; -/* - * For terminal editing, we need both output_fd and input_fd to refer to - * a terminal. While we can't verify that they both point to the same - * terminal, we can verify that they point to terminals. - */ - is_term = isatty(gl->input_fd) && isatty(gl->output_fd); -/* - * If we are interacting with a terminal and no terminal type has been - * specified, treat it as a generic ANSI terminal. - */ - if(is_term && !term) - term = "ansi"; -/* - * Make a copy of the terminal type string. - */ - if(term != gl->term) { -/* - * Delete any old terminal type string. - */ - if(gl->term) { - free(gl->term); - gl->term = NULL; - }; -/* - * Make a copy of the new terminal-type string, if any. - */ - if(term) { - gl->term = (char *) malloc(strlen(term)+1); - if(gl->term) - strcpy(gl->term, term); - }; - }; -/* - * Clear any terminal-specific key bindings that were taken from the - * settings of the last terminal. - */ - _kt_clear_bindings(gl->bindings, KTB_TERM); -/* - * If we have a terminal install new bindings for it. - */ - if(is_term) { -/* - * Get the current settings of the terminal. - */ - if(tcgetattr(gl->input_fd, &gl->oldattr)) { - fprintf(stderr, "\r\ngl_change_terminal: tcgetattr error: %s\n", - strerror(errno)); - return 1; - }; -/* - * Lookup the terminal control string and size information. - */ - if(gl_control_strings(gl, term)) - return 1; -/* - * We now have enough info to interact with the terminal. - */ - gl->is_term = 1; -/* - * Bind terminal-specific keys. - */ - if(gl_bind_terminal_keys(gl)) - return 1; - }; - return 0; -} - -/*....................................................................... - * Set up terminal-specific key bindings. - * - * Input: - * gl GetLine * The resource object of the command-line input - * module. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_bind_terminal_keys(GetLine *gl) -{ -/* - * Install key-bindings for the special terminal characters. - */ - if(gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VINTR], - "user-interrupt") || - gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VQUIT], "abort") || - gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VSUSP], "suspend")) - return 1; -/* - * In vi-mode, arrange for the above characters to be seen in command - * mode. - */ - if(gl->editor == GL_VI_MODE) { - if(gl_bind_control_char(gl, KTB_TERM, MAKE_META(gl->oldattr.c_cc[VINTR]), - "user-interrupt") || - gl_bind_control_char(gl, KTB_TERM, MAKE_META(gl->oldattr.c_cc[VQUIT]), - "abort") || - gl_bind_control_char(gl, KTB_TERM, MAKE_META(gl->oldattr.c_cc[VSUSP]), - "suspend")) - return 1; - }; -/* - * Non-universal special keys. - */ -#ifdef VLNEXT - if(gl_bind_control_char(gl, KTB_TERM, gl->oldattr.c_cc[VLNEXT], - "literal-next")) - return 1; -#else - if(_kt_set_keybinding(gl->bindings, KTB_TERM, "^V", "literal-next")) - return 1; -#endif -/* - * Bind action functions to the terminal-specific arrow keys - * looked up by gl_control_strings(). - */ - if(_gl_bind_arrow_keys(gl)) - return 1; - return 0; -} - -/*....................................................................... - * This function is normally bound to control-D. When it is invoked within - * a line it deletes the character which follows the cursor. When invoked - * at the end of the line it lists possible file completions, and when - * invoked on an empty line it causes gl_get_line() to return EOF. This - * function emulates the one that is normally bound to control-D by tcsh. - */ -static KT_KEY_FN(gl_del_char_or_list_or_eof) -{ -/* - * If we have an empty line arrange to return EOF. - */ - if(gl->ntotal < 1) { - return 1; -/* - * If we are at the end of the line list possible completions. - */ - } else if(gl->buff_curpos >= gl->ntotal) { -/* - * Get the list of possible completions. - */ - CplMatches *matches = cpl_complete_word(gl->cpl, gl->line, gl->buff_curpos, - gl->cpl_data, gl->cpl_fn); - if(!matches) { - if(gl->echo && - fprintf(gl->output_fp, "\r\n%s\n", cpl_last_error(gl->cpl)) < 0) - return 1; - gl->term_curpos = 0; -/* - * List the matches. - */ - } else if(matches->nmatch > 0 && gl->echo) { - if(fprintf(gl->output_fp, "\r\n") < 0) - return 1; - cpl_list_completions(matches, gl->output_fp, gl->ncolumn); - }; -/* - * Redisplay the line unchanged. - */ - return gl_redisplay(gl,1); -/* - * Within the line delete the character that follows the cursor. - */ - } else { -/* - * If in vi command mode, first preserve the current line for potential use - * by vi-undo. - */ - gl_save_for_undo(gl); -/* - * Delete 'count' characters. - */ - return gl_forward_delete_char(gl, count); - }; -} - -/*....................................................................... - * This function is normally bound to control-D in vi mode. When it is - * invoked within a line it lists possible file completions, and when - * invoked on an empty line it causes gl_get_line() to return EOF. This - * function emulates the one that is normally bound to control-D by tcsh. - */ -static KT_KEY_FN(gl_list_or_eof) -{ -/* - * If we have an empty line arrange to return EOF. - */ - if(gl->ntotal < 1) { - return 1; -/* - * Otherwise list possible completions. - */ - } else { -/* - * Get the list of possible completions. - */ - CplMatches *matches = cpl_complete_word(gl->cpl, gl->line, gl->buff_curpos, - gl->cpl_data, gl->cpl_fn); - if(!matches) { - if(gl->echo && - fprintf(gl->output_fp, "\r\n%s\n", cpl_last_error(gl->cpl)) < 0) - return 1; - gl->term_curpos = 0; -/* - * List the matches. - */ - } else if(matches->nmatch > 0 && gl->echo) { - if(fprintf(gl->output_fp, "\r\n") < 0) - return 1; - cpl_list_completions(matches, gl->output_fp, gl->ncolumn); - }; -/* - * Redisplay the line unchanged. - */ - return gl_redisplay(gl,1); - }; -} - -/*....................................................................... - * Where the user has used the symbolic arrow-key names to specify - * arrow key bindings, bind the specified action functions to the default - * and terminal specific arrow key sequences. - * - * Input: - * gl GetLine * The getline resource object. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int _gl_bind_arrow_keys(GetLine *gl) -{ -/* - * Process each of the arrow keys. - */ - if(_gl_rebind_arrow_key(gl->bindings, "up", gl->u_arrow, "^[[A", "^[OA") || - _gl_rebind_arrow_key(gl->bindings, "down", gl->d_arrow, "^[[B", "^[OB") || - _gl_rebind_arrow_key(gl->bindings, "left", gl->l_arrow, "^[[D", "^[OD") || - _gl_rebind_arrow_key(gl->bindings, "right", gl->r_arrow, "^[[C", "^[OC")) - return 1; - return 0; -} - -/*....................................................................... - * Lookup the action function of a symbolic arrow-key binding, and bind - * it to the terminal-specific and default arrow-key sequences. Note that - * we don't trust the terminal-specified key sequences to be correct. - * The main reason for this is that on some machines the xterm terminfo - * entry is for hardware X-terminals, rather than xterm terminal emulators - * and the two terminal types emit different character sequences when the - * their cursor keys are pressed. As a result we also supply a couple - * of default key sequences. - * - * Input: - * bindings KeyTab * The table of key bindings. - * name char * The symbolic name of the arrow key. - * term_seq char * The terminal-specific arrow-key sequence. - * def_seq1 char * The first default arrow-key sequence. - * def_seq2 char * The second arrow-key sequence. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int _gl_rebind_arrow_key(KeyTab *bindings, const char *name, - const char *term_seq, const char *def_seq1, - const char *def_seq2) -{ - int first,last; /* The indexes of the first and last matching entries */ -/* - * Lookup the key binding for the symbolic name of the arrow key. This - * will either be the default action, or a user provided one. - */ - if(_kt_lookup_keybinding(bindings, name, strlen(name), &first, &last) - == KT_EXACT_MATCH) { -/* - * Get the action function. - */ - KtKeyFn *key_fn = bindings->table[first].keyfn; -/* - * Bind this to each of the specified key sequences. - */ - if((term_seq && _kt_set_keyfn(bindings, KTB_TERM, term_seq, key_fn)) || - (def_seq1 && _kt_set_keyfn(bindings, KTB_NORM, def_seq1, key_fn)) || - (def_seq2 && _kt_set_keyfn(bindings, KTB_NORM, def_seq2, key_fn))) - return 1; - }; - return 0; -} - -/*....................................................................... - * Read getline configuration information from a given file. - * - * Input: - * gl GetLine * The getline resource object. - * filename const char * The name of the file to read configuration - * information from. The contents of this file - * are as described in the gl_get_line(3) man - * page for the default ~/.teclarc configuration - * file. - * who KtBinder Who bindings are to be installed for. - * Output: - * return int 0 - OK. - * 1 - Irrecoverable error. - */ -static int _gl_read_config_file(GetLine *gl, const char *filename, KtBinder who) -{ - FileExpansion *expansion; /* The expansion of the filename */ - FILE *fp; /* The opened file */ - int waserr = 0; /* True if an error occurred while reading */ - int lineno = 1; /* The line number being processed */ -/* - * Check the arguments. - */ - if(!gl || !filename) { - fprintf(stderr, "_gl_read_config_file: Invalid arguments.\n"); - return 1; - }; -/* - * Expand the filename. - */ - expansion = ef_expand_file(gl->ef, filename, -1); - if(!expansion) { - fprintf(stderr, "Unable to expand %s (%s).\n", filename, - ef_last_error(gl->ef)); - return 1; - }; -/* - * Attempt to open the file. - */ - fp = fopen(expansion->files[0], "r"); -/* - * It isn't an error for there to be no configuration file. - */ - if(!fp) - return 0; -/* - * Parse the contents of the file. - */ - while(!waserr && !feof(fp)) - waserr = _gl_parse_config_line(gl, fp, glc_file_getc, filename, who, - &lineno); -/* - * Bind action functions to the terminal-specific arrow keys. - */ - if(_gl_bind_arrow_keys(gl)) - return 1; -/* - * Clean up. - */ - (void) fclose(fp); - return waserr; -} - -/*....................................................................... - * Read GetLine configuration information from a string. The contents of - * the string are the same as those described in the gl_get_line(3) - * man page for the contents of the ~/.teclarc configuration file. - */ -static int _gl_read_config_string(GetLine *gl, const char *buffer, KtBinder who) -{ - const char *bptr; /* A pointer into buffer[] */ - int waserr = 0; /* True if an error occurred while reading */ - int lineno = 1; /* The line number being processed */ -/* - * Check the arguments. - */ - if(!gl || !buffer) { - fprintf(stderr, "_gl_read_config_string: Invalid arguments.\n"); - return 1; - }; -/* - * Get a pointer to the start of the buffer. - */ - bptr = buffer; -/* - * Parse the contents of the buffer. - */ - while(!waserr && *bptr) - waserr = _gl_parse_config_line(gl, &bptr, glc_buff_getc, "", who, &lineno); -/* - * Bind action functions to the terminal-specific arrow keys. - */ - if(_gl_bind_arrow_keys(gl)) - return 1; - return waserr; -} - -/*....................................................................... - * Parse the next line of a getline configuration file. - * - * Input: - * gl GetLine * The getline resource object. - * stream void * The pointer representing the stream to be read - * by getc_fn(). - * getc_fn GlcGetcFn * A callback function which when called with - * 'stream' as its argument, returns the next - * unread character from the stream. - * origin const char * The name of the entity being read (eg. a - * file name). - * who KtBinder Who bindings are to be installed for. - * Input/Output: - * lineno int * The line number being processed is to be - * maintained in *lineno. - * Output: - * return int 0 - OK. - * 1 - Irrecoverable error. - */ -static int _gl_parse_config_line(GetLine *gl, void *stream, GlcGetcFn *getc_fn, - const char *origin, KtBinder who, int *lineno) -{ - char buffer[GL_CONF_BUFLEN+1]; /* The input line buffer */ - char *argv[GL_CONF_MAXARG]; /* The argument list */ - int argc = 0; /* The number of arguments in argv[] */ - int c; /* A character from the file */ - int escaped = 0; /* True if the next character is escaped */ - int i; -/* - * Skip spaces and tabs. - */ - do c = getc_fn(stream); while(c==' ' || c=='\t'); -/* - * Comments extend to the end of the line. - */ - if(c=='#') - do c = getc_fn(stream); while(c != '\n' && c != EOF); -/* - * Ignore empty lines. - */ - if(c=='\n' || c==EOF) { - (*lineno)++; - return 0; - }; -/* - * Record the buffer location of the start of the first argument. - */ - argv[argc] = buffer; -/* - * Read the rest of the line, stopping early if a comment is seen, or - * the buffer overflows, and replacing sequences of spaces with a - * '\0', and recording the thus terminated string as an argument. - */ - i = 0; - while(i<GL_CONF_BUFLEN) { -/* - * Did we hit the end of the latest argument? - */ - if(c==EOF || (!escaped && (c==' ' || c=='\n' || c=='\t' || c=='#'))) { -/* - * Terminate the argument. - */ - buffer[i++] = '\0'; - argc++; -/* - * Skip spaces and tabs. - */ - while(c==' ' || c=='\t') - c = getc_fn(stream); -/* - * If we hit the end of the line, or the start of a comment, exit the loop. - */ - if(c==EOF || c=='\n' || c=='#') - break; -/* - * Start recording the next argument. - */ - if(argc >= GL_CONF_MAXARG) { - fprintf(stderr, "%s:%d: Too many arguments.\n", origin, *lineno); - do c = getc_fn(stream); while(c != '\n' && c != EOF); /* Skip past eol */ - return 0; - }; - argv[argc] = buffer + i; -/* - * The next character was preceded by spaces, so it isn't escaped. - */ - escaped = 0; - } else { -/* - * If we hit an unescaped backslash, this means that we should arrange - * to treat the next character like a simple alphabetical character. - */ - if(c=='\\' && !escaped) { - escaped = 1; -/* - * Splice lines where the newline is escaped. - */ - } else if(c=='\n' && escaped) { - (*lineno)++; -/* - * Record a normal character, preserving any preceding backslash. - */ - } else { - if(escaped) - buffer[i++] = '\\'; - if(i>=GL_CONF_BUFLEN) - break; - escaped = 0; - buffer[i++] = c; - }; -/* - * Get the next character. - */ - c = getc_fn(stream); - }; - }; -/* - * Did the buffer overflow? - */ - if(i>=GL_CONF_BUFLEN) { - fprintf(stderr, "%s:%d: Line too long.\n", origin, *lineno); - return 0; - }; -/* - * The first argument should be a command name. - */ - if(strcmp(argv[0], "bind") == 0) { - const char *action = NULL; /* A NULL action removes a keybinding */ - const char *keyseq = NULL; - switch(argc) { - case 3: - action = argv[2]; - case 2: /* Note the intentional fallthrough */ - keyseq = argv[1]; -/* - * Attempt to record the new keybinding. - */ - if(_kt_set_keybinding(gl->bindings, who, keyseq, action)) { - fprintf(stderr, "The error occurred at line %d of %s.\n", *lineno, - origin); - }; - break; - default: - fprintf(stderr, "%s:%d: Wrong number of arguments.\n", origin, *lineno); - }; - } else if(strcmp(argv[0], "edit-mode") == 0) { - if(argc == 2 && strcmp(argv[1], "emacs") == 0) { - gl_change_editor(gl, GL_EMACS_MODE); - } else if(argc == 2 && strcmp(argv[1], "vi") == 0) { - gl_change_editor(gl, GL_VI_MODE); - } else if(argc == 2 && strcmp(argv[1], "none") == 0) { - gl_change_editor(gl, GL_NO_EDITOR); - } else { - fprintf(stderr, "%s:%d: The argument of editor should be vi or emacs.\n", - origin, *lineno); - }; - } else if(strcmp(argv[0], "nobeep") == 0) { - gl->silence_bell = 1; - } else { - fprintf(stderr, "%s:%d: Unknown command name '%s'.\n", origin, *lineno, - argv[0]); - }; -/* - * Skip any trailing comment. - */ - while(c != '\n' && c != EOF) - c = getc_fn(stream); - (*lineno)++; - return 0; -} - -/*....................................................................... - * This is the _gl_parse_config_line() callback function which reads the - * next character from a configuration file. - */ -static GLC_GETC_FN(glc_file_getc) -{ - return fgetc((FILE *) stream); -} - -/*....................................................................... - * This is the _gl_parse_config_line() callback function which reads the - * next character from a buffer. Its stream argument is a pointer to a - * variable which is, in turn, a pointer into the buffer being read from. - */ -static GLC_GETC_FN(glc_buff_getc) -{ - const char **lptr = (char const **) stream; - return **lptr ? *(*lptr)++ : EOF; -} - -/*....................................................................... - * When this action is triggered, it arranges to temporarily read command - * lines from the regular file whos name precedes the cursor. - * The current line is first discarded. - */ -static KT_KEY_FN(gl_read_from_file) -{ - char *start_path; /* The pointer to the start of the pathname in */ - /* gl->line[]. */ - FileExpansion *result; /* The results of the filename expansion */ - int pathlen; /* The length of the pathname being expanded */ - int error_reported = 0; /* True after an error has been reported */ -/* - * Locate the start of the filename that precedes the cursor position. - */ - start_path = _pu_start_of_path(gl->line, - gl->buff_curpos > 0 ? gl->buff_curpos : 0); - if(!start_path) - return 1; -/* - * Get the length of the pathname string. - */ - pathlen = gl->buff_curpos - (start_path - gl->line); -/* - * Attempt to expand the pathname. - */ - result = ef_expand_file(gl->ef, start_path, pathlen); -/* - * If there was an error, report the error on a new line, then redraw - * the original line. - */ - if(!result) { - if(gl->echo && - fprintf(gl->output_fp, "\r\n%s\n", ef_last_error(gl->ef)) < 0) - return 1; - error_reported = 1; -/* - * If no files matched, report this as well. - */ - } else if(result->nfile == 0 || !result->exists) { - if(gl->echo && fprintf(gl->output_fp, "\r\nNo files match.\n") < 0) - return 1; - error_reported = 1; -/* - * Complain if more than one file matches. - */ - } else if(result->nfile > 1) { - if(gl->echo && - fprintf(gl->output_fp, "\r\nMore than one file matches.\n") < 0) - return 1; - error_reported = 1; -/* - * Disallow input from anything but normal files. In principle we could - * also support input from named pipes. Terminal files would be a problem - * since we wouldn't know the terminal type, and other types of files - * might cause the library to lock up. - */ - } else if(!_pu_path_is_file(result->files[0])) { - if(gl->echo && fprintf(gl->output_fp, "\r\nNot a normal file.\n") < 0) - return 1; - error_reported = 1; - } else { -/* - * Attempt to open and install the specified file for reading. - */ - gl->file_fp = fopen(result->files[0], "r"); - if(!gl->file_fp) { - if(gl->echo && fprintf(gl->output_fp, "\r\nUnable to open: %s\n", - result->files[0]) < 0) - return 1; - error_reported = 1; - }; -/* - * Inform the user what is happening. - */ - if(gl->echo && fprintf(gl->output_fp, "\r\n<Taking input from %s>\n", - result->files[0]) < 0) - return 1; - }; -/* - * If an error was reported, redisplay the current line. - */ - if(error_reported) { - gl->term_curpos = 0; - return gl_redisplay(gl,1); - }; - return 0; -} - -/*....................................................................... - * Close any temporary file that is being used for input. - * - * Input: - * gl GetLine * The getline resource object. - */ -static void gl_revert_input(GetLine *gl) -{ - if(gl->file_fp) - fclose(gl->file_fp); - gl->file_fp = NULL; -} - -/*....................................................................... - * This is the action function that recalls the oldest line in the - * history buffer. - */ -static KT_KEY_FN(gl_beginning_of_history) -{ -/* - * In vi mode, switch to command mode, since the user is very - * likely to want to move around newly recalled lines. - */ - gl_vi_command_mode(gl); -/* - * Forget any previous recall session. - */ - gl->preload_id = 0; -/* - * Recall the next oldest line in the history list. - */ - if(_glh_oldest_line(gl->glh, gl->line, gl->linelen) == NULL) - return 0; -/* - * Record the number of characters in the new string. - */ - gl->ntotal = strlen(gl->line); -/* - * Arrange to have the cursor placed at the end of the new line. - */ - gl->buff_curpos = strlen(gl->line); -/* - * Erase and display the new line. - */ - return gl_redisplay(gl,1); -} - -/*....................................................................... - * If a history session is currently in progress, this action function - * recalls the line that was being edited when the session started. If - * no history session is in progress, it does nothing. - */ -static KT_KEY_FN(gl_end_of_history) -{ -/* - * In vi mode, switch to command mode, since the user is very - * likely to want to move around newly recalled lines. - */ - gl_vi_command_mode(gl); -/* - * Forget any previous recall session. - */ - gl->preload_id = 0; -/* - * Recall the next oldest line in the history list. - */ - if(_glh_current_line(gl->glh, gl->line, gl->linelen) == NULL) - return 0; -/* - * Record the number of characters in the new string. - */ - gl->ntotal = strlen(gl->line); -/* - * Arrange to have the cursor placed at the end of the new line. - */ - gl->buff_curpos = strlen(gl->line); -/* - * Erase and display the new line. - */ - return gl_redisplay(gl,1); -} - -/*....................................................................... - * This action function is treated specially, in that its count argument - * is set to the end keystroke of the keysequence that activated it. - * It accumulates a numeric argument, adding one digit on each call in - * which the last keystroke was a numeric digit. - */ -static KT_KEY_FN(gl_digit_argument) -{ -/* - * Was the last keystroke a digit? - */ - int is_digit = isdigit((int)(unsigned char) count); -/* - * In vi command mode, a lone '0' means goto-start-of-line. - */ - if(gl->vi.command && gl->number < 0 && count == '0') - return gl_beginning_of_line(gl, count); -/* - * Are we starting to accumulate a new number? - */ - if(gl->number < 0 || !is_digit) - gl->number = 0; -/* - * Was the last keystroke a digit? - */ - if(is_digit) { -/* - * Read the numeric value of the digit, without assuming ASCII. - */ - int n; - char s[2]; s[0] = count; s[1] = '\0'; - n = atoi(s); -/* - * Append the new digit. - */ - gl->number = gl->number * 10 + n; - }; - return 0; -} - -/*....................................................................... - * The newline action function sets gl->endline to tell - * gl_get_input_line() that the line is now complete. - */ -static KT_KEY_FN(gl_newline) -{ - GlhLineID id; /* The last history line recalled while entering this line */ -/* - * Flag the line as ended. - */ - gl->endline = 1; -/* - * Record the next position in the history buffer, for potential - * recall by an action function on the next call to gl_get_line(). - */ - id = _glh_line_id(gl->glh, 1); - if(id) - gl->preload_id = id; - return 0; -} - -/*....................................................................... - * The 'repeat' action function sets gl->endline to tell - * gl_get_input_line() that the line is now complete, and records the - * ID of the next history line in gl->preload_id so that the next call - * to gl_get_input_line() will preload the line with that history line. - */ -static KT_KEY_FN(gl_repeat_history) -{ - gl->endline = 1; - gl->preload_id = _glh_line_id(gl->glh, 1); - gl->preload_history = 1; - return 0; -} - -/*....................................................................... - * Flush unwritten characters to the terminal. - * - * Input: - * gl GetLine * The getline resource object. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_flush_output(GetLine *gl) -{ -/* - * Attempt to flush output to the terminal, restarting the output - * if a signal is caught. - */ - while(fflush(gl->output_fp) != 0) { - if(errno!=EINTR) - return 1; - }; - return 0; -} - -/*....................................................................... - * Change the style of editing to emulate a given editor. - * - * Input: - * gl GetLine * The getline resource object. - * editor GlEditor The type of editor to emulate. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_change_editor(GetLine *gl, GlEditor editor) -{ -/* - * Install the default key-bindings of the requested editor. - */ - switch(editor) { - case GL_EMACS_MODE: - _kt_clear_bindings(gl->bindings, KTB_NORM); - _kt_clear_bindings(gl->bindings, KTB_TERM); - (void) _kt_add_bindings(gl->bindings, KTB_NORM, gl_emacs_bindings, - sizeof(gl_emacs_bindings)/sizeof(gl_emacs_bindings[0])); - break; - case GL_VI_MODE: - _kt_clear_bindings(gl->bindings, KTB_NORM); - _kt_clear_bindings(gl->bindings, KTB_TERM); - (void) _kt_add_bindings(gl->bindings, KTB_NORM, gl_vi_bindings, - sizeof(gl_vi_bindings)/sizeof(gl_vi_bindings[0])); - break; - case GL_NO_EDITOR: - break; - default: - fprintf(stderr, "gl_change_editor: Unknown editor.\n"); - return 1; - }; -/* - * Record the new editing mode. - */ - gl->editor = editor; - gl->vi.command = 0; /* Start in input mode */ - gl->insert_curpos = 0; -/* - * Reinstate terminal-specific bindings. - */ - if(gl->editor != GL_NO_EDITOR && gl->input_fp) - (void) gl_bind_terminal_keys(gl); - return 0; -} - -/*....................................................................... - * This is an action function that switches to editing using emacs bindings - */ -static KT_KEY_FN(gl_emacs_editing_mode) -{ - return gl_change_editor(gl, GL_EMACS_MODE); -} - -/*....................................................................... - * This is an action function that switches to editing using vi bindings - */ -static KT_KEY_FN(gl_vi_editing_mode) -{ - return gl_change_editor(gl, GL_VI_MODE); -} - -/*....................................................................... - * This is the action function that switches to insert mode. - */ -static KT_KEY_FN(gl_vi_insert) -{ -/* - * If in vi command mode, preserve the current line for potential - * use by vi-undo. - */ - gl_save_for_undo(gl); -/* - * Switch to vi insert mode. - */ - gl->insert = 1; - gl->vi.command = 0; - gl->insert_curpos = gl->buff_curpos; - return 0; -} - -/*....................................................................... - * This is an action function that switches to overwrite mode. - */ -static KT_KEY_FN(gl_vi_overwrite) -{ -/* - * If in vi command mode, preserve the current line for potential - * use by vi-undo. - */ - gl_save_for_undo(gl); -/* - * Switch to vi overwrite mode. - */ - gl->insert = 0; - gl->vi.command = 0; - gl->insert_curpos = gl->buff_curpos; - return 0; -} - -/*....................................................................... - * This action function toggles the case of the character under the - * cursor. - */ -static KT_KEY_FN(gl_change_case) -{ - int i; -/* - * Keep a record of the current insert mode and the cursor position. - */ - int insert = gl->insert; -/* - * If in vi command mode, preserve the current line for potential - * use by vi-undo. - */ - gl_save_for_undo(gl); -/* - * We want to overwrite the modified word. - */ - gl->insert = 0; -/* - * Toggle the case of 'count' characters. - */ - for(i=0; i<count && gl->buff_curpos < gl->ntotal; i++) { - char *cptr = gl->line + gl->buff_curpos++; -/* - * Convert the character to upper case? - */ - if(islower((int)(unsigned char) *cptr)) - *cptr = toupper((int) *cptr); - else if(isupper((int)(unsigned char) *cptr)) - *cptr = tolower((int) *cptr); -/* - * Write the possibly modified character back. Note that for non-modified - * characters we want to do this as well, so as to advance the cursor. - */ - if(gl_output_char(gl, *cptr, cptr[1])) - return 1; - }; -/* - * Restore the insertion mode. - */ - gl->insert = insert; - return gl_place_cursor(gl, gl->buff_curpos); /* bounds check */ -} - -/*....................................................................... - * This is the action function which implements the vi-style action which - * moves the cursor to the start of the line, then switches to insert mode. - */ -static KT_KEY_FN(gl_vi_insert_at_bol) -{ - gl_save_for_undo(gl); - return gl_beginning_of_line(gl, 0) || - gl_vi_insert(gl, 0); - -} - -/*....................................................................... - * This is the action function which implements the vi-style action which - * moves the cursor to the end of the line, then switches to insert mode - * to allow text to be appended to the line. - */ -static KT_KEY_FN(gl_vi_append_at_eol) -{ - gl_save_for_undo(gl); - gl->vi.command = 0; /* Allow cursor at EOL */ - return gl_end_of_line(gl, 0) || - gl_vi_insert(gl, 0); -} - -/*....................................................................... - * This is the action function which implements the vi-style action which - * moves the cursor to right one then switches to insert mode, thus - * allowing text to be appended after the next character. - */ -static KT_KEY_FN(gl_vi_append) -{ - gl_save_for_undo(gl); - gl->vi.command = 0; /* Allow cursor at EOL */ - return gl_cursor_right(gl, 1) || - gl_vi_insert(gl, 0); -} - -/*....................................................................... - * This action function moves the cursor to the column specified by the - * numeric argument. Column indexes start at 1. - */ -static KT_KEY_FN(gl_goto_column) -{ - return gl_place_cursor(gl, count - 1); -} - -/*....................................................................... - * Starting with the character under the cursor, replace 'count' - * characters with the next character that the user types. - */ -static KT_KEY_FN(gl_vi_replace_char) -{ - char c; /* The replacement character */ - int i; -/* - * Keep a record of the current insert mode. - */ - int insert = gl->insert; -/* - * Get the replacement character. - */ - if(gl->vi.repeat.active) { - c = gl->vi.repeat.input_char; - } else { - if(gl_read_character(gl, &c)) - return 1; - gl->vi.repeat.input_char = c; - }; -/* - * Are there 'count' characters to be replaced? - */ - if(gl->ntotal - gl->buff_curpos >= count) { -/* - * If in vi command mode, preserve the current line for potential - * use by vi-undo. - */ - gl_save_for_undo(gl); -/* - * Temporarily switch to overwrite mode. - */ - gl->insert = 0; -/* - * Overwrite the current character plus count-1 subsequent characters - * with the replacement character. - */ - for(i=0; i<count; i++) - gl_add_char_to_line(gl, c); -/* - * Restore the original insert/overwrite mode. - */ - gl->insert = insert; - }; - return gl_place_cursor(gl, gl->buff_curpos); /* bounds check */ -} - -/*....................................................................... - * This is an action function which changes all characters between the - * current cursor position and the end of the line. - */ -static KT_KEY_FN(gl_vi_change_rest_of_line) -{ - gl_save_for_undo(gl); - gl->vi.command = 0; /* Allow cursor at EOL */ - return gl_kill_line(gl, count) || gl_vi_insert(gl, 0); -} - -/*....................................................................... - * This is an action function which changes all characters between the - * start of the line and the current cursor position. - */ -static KT_KEY_FN(gl_vi_change_to_bol) -{ - return gl_backward_kill_line(gl, count) || gl_vi_insert(gl, 0); -} - -/*....................................................................... - * This is an action function which deletes the entire contents of the - * current line and switches to insert mode. - */ -static KT_KEY_FN(gl_vi_change_line) -{ - return gl_delete_line(gl, count) || gl_vi_insert(gl, 0); -} - -/*....................................................................... - * Starting from the cursor position and looking towards the end of the - * line, copy 'count' characters to the cut buffer. - */ -static KT_KEY_FN(gl_forward_copy_char) -{ -/* - * Limit the count to the number of characters available. - */ - if(gl->buff_curpos + count >= gl->ntotal) - count = gl->ntotal - gl->buff_curpos; - if(count < 0) - count = 0; -/* - * Copy the characters to the cut buffer. - */ - memcpy(gl->cutbuf, gl->line + gl->buff_curpos, count); - gl->cutbuf[count] = '\0'; - return 0; -} - -/*....................................................................... - * Starting from the character before the cursor position and looking - * backwards towards the start of the line, copy 'count' characters to - * the cut buffer. - */ -static KT_KEY_FN(gl_backward_copy_char) -{ -/* - * Limit the count to the number of characters available. - */ - if(count > gl->buff_curpos) - count = gl->buff_curpos; - if(count < 0) - count = 0; - gl_place_cursor(gl, gl->buff_curpos - count); -/* - * Copy the characters to the cut buffer. - */ - memcpy(gl->cutbuf, gl->line + gl->buff_curpos, count); - gl->cutbuf[count] = '\0'; - return 0; -} - -/*....................................................................... - * Starting from the cursor position copy to the specified column into the - * cut buffer. - */ -static KT_KEY_FN(gl_copy_to_column) -{ - if (--count >= gl->buff_curpos) - return gl_forward_copy_char(gl, count - gl->buff_curpos); - else - return gl_backward_copy_char(gl, gl->buff_curpos - count); -} - -/*....................................................................... - * Starting from the cursor position copy characters up to a matching - * parenthesis into the cut buffer. - */ -static KT_KEY_FN(gl_copy_to_parenthesis) -{ - int curpos = gl_index_of_matching_paren(gl); - if(curpos >= 0) { - gl_save_for_undo(gl); - if(curpos >= gl->buff_curpos) - return gl_forward_copy_char(gl, curpos - gl->buff_curpos + 1); - else - return gl_backward_copy_char(gl, ++gl->buff_curpos - curpos + 1); - }; - return 0; -} - -/*....................................................................... - * Starting from the cursor position copy the rest of the line into the - * cut buffer. - */ -static KT_KEY_FN(gl_copy_rest_of_line) -{ -/* - * Copy the characters to the cut buffer. - */ - memcpy(gl->cutbuf, gl->line + gl->buff_curpos, gl->ntotal - gl->buff_curpos); - gl->cutbuf[gl->ntotal - gl->buff_curpos] = '\0'; - return 0; -} - -/*....................................................................... - * Copy from the beginning of the line to the cursor position into the - * cut buffer. - */ -static KT_KEY_FN(gl_copy_to_bol) -{ -/* - * Copy the characters to the cut buffer. - */ - memcpy(gl->cutbuf, gl->line, gl->buff_curpos); - gl->cutbuf[gl->buff_curpos] = '\0'; - gl_place_cursor(gl, 0); - return 0; -} - -/*....................................................................... - * Copy the entire line into the cut buffer. - */ -static KT_KEY_FN(gl_copy_line) -{ -/* - * Copy the characters to the cut buffer. - */ - memcpy(gl->cutbuf, gl->line, gl->ntotal); - gl->cutbuf[gl->ntotal] = '\0'; - return 0; -} - -/*....................................................................... - * Search forwards for the next character that the user enters. - */ -static KT_KEY_FN(gl_forward_find_char) -{ - int pos = gl_find_char(gl, count, 1, 1, '\0'); - return pos >= 0 && gl_place_cursor(gl, pos); -} - -/*....................................................................... - * Search backwards for the next character that the user enters. - */ -static KT_KEY_FN(gl_backward_find_char) -{ - int pos = gl_find_char(gl, count, 0, 1, '\0'); - return pos >= 0 && gl_place_cursor(gl, pos); -} - -/*....................................................................... - * Search forwards for the next character that the user enters. Move up to, - * but not onto, the found character. - */ -static KT_KEY_FN(gl_forward_to_char) -{ - int pos = gl_find_char(gl, count, 1, 0, '\0'); - return pos >= 0 && gl_place_cursor(gl, pos); -} - -/*....................................................................... - * Search backwards for the next character that the user enters. Move back to, - * but not onto, the found character. - */ -static KT_KEY_FN(gl_backward_to_char) -{ - int pos = gl_find_char(gl, count, 0, 0, '\0'); - return pos >= 0 && gl_place_cursor(gl, pos); -} - -/*....................................................................... - * Searching in a given direction, return the index of a given (or - * read) character in the input line, or the character that precedes - * it in the specified search direction. Return -1 if not found. - * - * Input: - * gl GetLine * The getline resource object. - * count int The number of times to search. - * forward int True if searching forward. - * onto int True if the search should end on top of the - * character, false if the search should stop - * one character before the character in the - * specified search direction. - * c char The character to be sought, or '\0' if the - * character should be read from the user. - * Output: - * return int The index of the character in gl->line[], or - * -1 if not found. - */ -static int gl_find_char(GetLine *gl, int count, int forward, int onto, char c) -{ - int pos; /* The index reached in searching the input line */ - int i; -/* - * Get a character from the user? - */ - if(!c) { -/* - * If we are in the process of repeating a previous change command, substitute - * the last find character. - */ - if(gl->vi.repeat.active) { - c = gl->vi.find_char; - } else { - if(gl_read_character(gl, &c)) - return -1; -/* - * Record the details of the new search, for use by repeat finds. - */ - gl->vi.find_forward = forward; - gl->vi.find_onto = onto; - gl->vi.find_char = c; - }; - }; -/* - * Which direction should we search? - */ - if(forward) { -/* - * Search forwards 'count' times for the character, starting with the - * character that follows the cursor. - */ - for(i=0, pos=gl->buff_curpos; i<count && pos < gl->ntotal; i++) { -/* - * Advance past the last match (or past the current cursor position - * on the first search). - */ - pos++; -/* - * Search for the next instance of c. - */ - for( ; pos<gl->ntotal && c!=gl->line[pos]; pos++) - ; - }; -/* - * If the character was found and we have been requested to return the - * position of the character that precedes the desired character, then - * we have gone one character too far. - */ - if(!onto && pos<gl->ntotal) - pos--; - } else { -/* - * Search backwards 'count' times for the character, starting with the - * character that precedes the cursor. - */ - for(i=0, pos=gl->buff_curpos; i<count && pos >= gl->insert_curpos; i++) { -/* - * Step back one from the last match (or from the current cursor - * position on the first search). - */ - pos--; -/* - * Search for the next instance of c. - */ - for( ; pos>=gl->insert_curpos && c!=gl->line[pos]; pos--) - ; - }; -/* - * If the character was found and we have been requested to return the - * position of the character that precedes the desired character, then - * we have gone one character too far. - */ - if(!onto && pos>=gl->insert_curpos) - pos++; - }; -/* - * If found, return the cursor position of the count'th match. - * Otherwise ring the terminal bell. - */ - if(pos >= gl->insert_curpos && pos < gl->ntotal) { - return pos; - } else { - (void) gl_ring_bell(gl, 1); - return -1; - } -} - -/*....................................................................... - * Repeat the last character search in the same direction as the last - * search. - */ -static KT_KEY_FN(gl_repeat_find_char) -{ - int pos = gl->vi.find_char ? - gl_find_char(gl, count, gl->vi.find_forward, gl->vi.find_onto, - gl->vi.find_char) : -1; - return pos >= 0 && gl_place_cursor(gl, pos); -} - -/*....................................................................... - * Repeat the last character search in the opposite direction as the last - * search. - */ -static KT_KEY_FN(gl_invert_refind_char) -{ - int pos = gl->vi.find_char ? - gl_find_char(gl, count, !gl->vi.find_forward, gl->vi.find_onto, - gl->vi.find_char) : -1; - return pos >= 0 && gl_place_cursor(gl, pos); -} - -/*....................................................................... - * Search forward from the current position of the cursor for 'count' - * word endings, returning the index of the last one found, or the end of - * the line if there were less than 'count' words. - * - * Input: - * gl GetLine * The getline resource object. - * n int The number of word boundaries to search for. - * Output: - * return int The buffer index of the located position. - */ -static int gl_nth_word_end_forward(GetLine *gl, int n) -{ - int bufpos; /* The buffer index being checked. */ - int i; -/* - * In order to guarantee forward motion to the next word ending, - * we need to start from one position to the right of the cursor - * position, since this may already be at the end of a word. - */ - bufpos = gl->buff_curpos + 1; -/* - * If we are at the end of the line, return the index of the last - * real character on the line. Note that this will be -1 if the line - * is empty. - */ - if(bufpos >= gl->ntotal) - return gl->ntotal - 1; -/* - * Search 'n' times, unless the end of the input line is reached first. - */ - for(i=0; i<n && bufpos<gl->ntotal; i++) { -/* - * If we are not already within a word, skip to the start of the next word. - */ - for( ; bufpos<gl->ntotal && !gl_is_word_char((int)gl->line[bufpos]); - bufpos++) - ; -/* - * Find the end of the next word. - */ - for( ; bufpos<gl->ntotal && gl_is_word_char((int)gl->line[bufpos]); - bufpos++) - ; - }; -/* - * We will have overshot. - */ - return bufpos > 0 ? bufpos-1 : bufpos; -} - -/*....................................................................... - * Search forward from the current position of the cursor for 'count' - * word starts, returning the index of the last one found, or the end of - * the line if there were less than 'count' words. - * - * Input: - * gl GetLine * The getline resource object. - * n int The number of word boundaries to search for. - * Output: - * return int The buffer index of the located position. - */ -static int gl_nth_word_start_forward(GetLine *gl, int n) -{ - int bufpos; /* The buffer index being checked. */ - int i; -/* - * Get the current cursor position. - */ - bufpos = gl->buff_curpos; -/* - * Search 'n' times, unless the end of the input line is reached first. - */ - for(i=0; i<n && bufpos<gl->ntotal; i++) { -/* - * Find the end of the current word. - */ - for( ; bufpos<gl->ntotal && gl_is_word_char((int)gl->line[bufpos]); - bufpos++) - ; -/* - * Skip to the start of the next word. - */ - for( ; bufpos<gl->ntotal && !gl_is_word_char((int)gl->line[bufpos]); - bufpos++) - ; - }; - return bufpos; -} - -/*....................................................................... - * Search backward from the current position of the cursor for 'count' - * word starts, returning the index of the last one found, or the start - * of the line if there were less than 'count' words. - * - * Input: - * gl GetLine * The getline resource object. - * n int The number of word boundaries to search for. - * Output: - * return int The buffer index of the located position. - */ -static int gl_nth_word_start_backward(GetLine *gl, int n) -{ - int bufpos; /* The buffer index being checked. */ - int i; -/* - * Get the current cursor position. - */ - bufpos = gl->buff_curpos; -/* - * Search 'n' times, unless the beginning of the input line (or vi insertion - * point) is reached first. - */ - for(i=0; i<n && bufpos > gl->insert_curpos; i++) { -/* - * Starting one character back from the last search, so as not to keep - * settling on the same word-start, search backwards until finding a - * word character. - */ - while(--bufpos >= gl->insert_curpos && - !gl_is_word_char((int)gl->line[bufpos])) - ; -/* - * Find the start of the word. - */ - while(--bufpos >= gl->insert_curpos && - gl_is_word_char((int)gl->line[bufpos])) - ; -/* - * We will have gone one character too far. - */ - bufpos++; - }; - return bufpos >= gl->insert_curpos ? bufpos : gl->insert_curpos; -} - -/*....................................................................... - * Copy one or more words into the cut buffer without moving the cursor - * or deleting text. - */ -static KT_KEY_FN(gl_forward_copy_word) -{ -/* - * Find the location of the count'th start or end of a word - * after the cursor, depending on whether in emacs or vi mode. - */ - int next = gl->editor == GL_EMACS_MODE ? - gl_nth_word_end_forward(gl, count) : - gl_nth_word_start_forward(gl, count); -/* - * How many characters are to be copied into the cut buffer? - */ - int n = next - gl->buff_curpos; -/* - * Copy the specified segment and terminate the string. - */ - memcpy(gl->cutbuf, gl->line + gl->buff_curpos, n); - gl->cutbuf[n] = '\0'; - return 0; -} - -/*....................................................................... - * Copy one or more words preceding the cursor into the cut buffer, - * without moving the cursor or deleting text. - */ -static KT_KEY_FN(gl_backward_copy_word) -{ -/* - * Find the location of the count'th start of word before the cursor. - */ - int next = gl_nth_word_start_backward(gl, count); -/* - * How many characters are to be copied into the cut buffer? - */ - int n = gl->buff_curpos - next; - gl_place_cursor(gl, next); -/* - * Copy the specified segment and terminate the string. - */ - memcpy(gl->cutbuf, gl->line + next, n); - gl->cutbuf[n] = '\0'; - return 0; -} - -/*....................................................................... - * Copy the characters between the cursor and the count'th instance of - * a specified character in the input line, into the cut buffer. - * - * Input: - * gl GetLine * The getline resource object. - * count int The number of times to search. - * c char The character to be searched for, or '\0' if - * the character should be read from the user. - * forward int True if searching forward. - * onto int True if the search should end on top of the - * character, false if the search should stop - * one character before the character in the - * specified search direction. - * Output: - * return int 0 - OK. - * 1 - Error. - * - */ -static int gl_copy_find(GetLine *gl, int count, char c, int forward, int onto) -{ - int n; /* The number of characters in the cut buffer */ -/* - * Search for the character, and abort the operation if not found. - */ - int pos = gl_find_char(gl, count, forward, onto, c); - if(pos < 0) - return 0; -/* - * Copy the specified segment. - */ - if(forward) { - n = pos + 1 - gl->buff_curpos; - memcpy(gl->cutbuf, gl->line + gl->buff_curpos, n); - } else { - n = gl->buff_curpos - pos; - memcpy(gl->cutbuf, gl->line + pos, n); - if(gl->editor == GL_VI_MODE) - gl_place_cursor(gl, pos); - } -/* - * Terminate the copy. - */ - gl->cutbuf[n] = '\0'; - return 0; -} - -/*....................................................................... - * Copy a section up to and including a specified character into the cut - * buffer without moving the cursor or deleting text. - */ -static KT_KEY_FN(gl_forward_copy_find) -{ - return gl_copy_find(gl, count, '\0', 1, 1); -} - -/*....................................................................... - * Copy a section back to and including a specified character into the cut - * buffer without moving the cursor or deleting text. - */ -static KT_KEY_FN(gl_backward_copy_find) -{ - return gl_copy_find(gl, count, '\0', 0, 1); -} - -/*....................................................................... - * Copy a section up to and not including a specified character into the cut - * buffer without moving the cursor or deleting text. - */ -static KT_KEY_FN(gl_forward_copy_to) -{ - return gl_copy_find(gl, count, '\0', 1, 0); -} - -/*....................................................................... - * Copy a section back to and not including a specified character into the cut - * buffer without moving the cursor or deleting text. - */ -static KT_KEY_FN(gl_backward_copy_to) -{ - return gl_copy_find(gl, count, '\0', 0, 0); -} - -/*....................................................................... - * Copy to a character specified in a previous search into the cut - * buffer without moving the cursor or deleting text. - */ -static KT_KEY_FN(gl_copy_refind) -{ - return gl_copy_find(gl, count, gl->vi.find_char, gl->vi.find_forward, - gl->vi.find_onto); -} - -/*....................................................................... - * Copy to a character specified in a previous search, but in the opposite - * direction, into the cut buffer without moving the cursor or deleting text. - */ -static KT_KEY_FN(gl_copy_invert_refind) -{ - return gl_copy_find(gl, count, gl->vi.find_char, !gl->vi.find_forward, - gl->vi.find_onto); -} - -/*....................................................................... - * Set the position of the cursor in the line input buffer and the - * terminal. - * - * Input: - * gl GetLine * The getline resource object. - * buff_curpos int The new buffer cursor position. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_place_cursor(GetLine *gl, int buff_curpos) -{ -/* - * Don't allow the cursor position to go out of the bounds of the input - * line. - */ - if(buff_curpos >= gl->ntotal) - buff_curpos = gl->vi.command ? gl->ntotal-1 : gl->ntotal; - if(buff_curpos < 0) - buff_curpos = 0; -/* - * Record the new buffer position. - */ - gl->buff_curpos = buff_curpos; -/* - * Move the terminal cursor to the corresponding character. - */ - return gl_set_term_curpos(gl, gl_buff_curpos_to_term_curpos(gl, buff_curpos)); -} - -/*....................................................................... - * In vi command mode, this function saves the current line to the - * historical buffer needed by the undo command. In emacs mode it does - * nothing. In order to allow action functions to call other action - * functions, gl_interpret_char() sets gl->vi.undo.saved to 0 before - * invoking an action, and thereafter once any call to this function - * has set it to 1, further calls are ignored. - * - * Input: - * gl GetLine * The getline resource object. - */ -static void gl_save_for_undo(GetLine *gl) -{ - if(gl->vi.command && !gl->vi.undo.saved) { - strcpy(gl->vi.undo.line, gl->line); - gl->vi.undo.buff_curpos = gl->buff_curpos; - gl->vi.undo.ntotal = gl->ntotal; - gl->vi.undo.saved = 1; - }; - if(gl->vi.command && !gl->vi.repeat.saved && - gl->current_fn != gl_vi_repeat_change) { - gl->vi.repeat.fn = gl->current_fn; - gl->vi.repeat.count = gl->current_count; - gl->vi.repeat.saved = 1; - }; - return; -} - -/*....................................................................... - * In vi mode, restore the line to the way it was before the last command - * mode operation, storing the current line in the buffer so that the - * undo operation itself can subsequently be undone. - */ -static KT_KEY_FN(gl_vi_undo) -{ -/* - * Get pointers into the two lines. - */ - char *undo_ptr = gl->vi.undo.line; - char *line_ptr = gl->line; -/* - * Swap the characters of the two buffers up to the length of the shortest - * line. - */ - while(*undo_ptr && *line_ptr) { - char c = *undo_ptr; - *undo_ptr++ = *line_ptr; - *line_ptr++ = c; - }; -/* - * Copy the rest directly. - */ - if(gl->ntotal > gl->vi.undo.ntotal) { - strcpy(undo_ptr, line_ptr); - *line_ptr = '\0'; - } else { - strcpy(line_ptr, undo_ptr); - *undo_ptr = '\0'; - }; -/* - * Swap the length information. - */ - { - int ntotal = gl->ntotal; - gl->ntotal = gl->vi.undo.ntotal; - gl->vi.undo.ntotal = ntotal; - }; -/* - * Set both cursor positions to the leftmost of the saved and current - * cursor positions to emulate what vi does. - */ - if(gl->buff_curpos < gl->vi.undo.buff_curpos) - gl->vi.undo.buff_curpos = gl->buff_curpos; - else - gl->buff_curpos = gl->vi.undo.buff_curpos; -/* - * Since we have bipassed calling gl_save_for_undo(), record repeat - * information inline. - */ - gl->vi.repeat.fn = gl_vi_undo; - gl->vi.repeat.count = 1; -/* - * Display the restored line. - */ - return gl_redisplay(gl,1); -} - -/*....................................................................... - * Delete the following word and leave the user in vi insert mode. - */ -static KT_KEY_FN(gl_vi_forward_change_word) -{ - gl_save_for_undo(gl); - gl->vi.command = 0; /* Allow cursor at EOL */ - return gl_forward_delete_word(gl, count) || gl_vi_insert(gl, 0); -} - -/*....................................................................... - * Delete the preceding word and leave the user in vi insert mode. - */ -static KT_KEY_FN(gl_vi_backward_change_word) -{ - return gl_backward_delete_word(gl, count) || gl_vi_insert(gl, 0); -} - -/*....................................................................... - * Delete the following section and leave the user in vi insert mode. - */ -static KT_KEY_FN(gl_vi_forward_change_find) -{ - return gl_delete_find(gl, count, '\0', 1, 1, 1); -} - -/*....................................................................... - * Delete the preceding section and leave the user in vi insert mode. - */ -static KT_KEY_FN(gl_vi_backward_change_find) -{ - return gl_delete_find(gl, count, '\0', 0, 1, 1); -} - -/*....................................................................... - * Delete the following section and leave the user in vi insert mode. - */ -static KT_KEY_FN(gl_vi_forward_change_to) -{ - return gl_delete_find(gl, count, '\0', 1, 0, 1); -} - -/*....................................................................... - * Delete the preceding section and leave the user in vi insert mode. - */ -static KT_KEY_FN(gl_vi_backward_change_to) -{ - return gl_delete_find(gl, count, '\0', 0, 0, 1); -} - -/*....................................................................... - * Delete to a character specified by a previous search and leave the user - * in vi insert mode. - */ -static KT_KEY_FN(gl_vi_change_refind) -{ - return gl_delete_find(gl, count, gl->vi.find_char, gl->vi.find_forward, - gl->vi.find_onto, 1); -} - -/*....................................................................... - * Delete to a character specified by a previous search, but in the opposite - * direction, and leave the user in vi insert mode. - */ -static KT_KEY_FN(gl_vi_change_invert_refind) -{ - return gl_delete_find(gl, count, gl->vi.find_char, !gl->vi.find_forward, - gl->vi.find_onto, 1); -} - -/*....................................................................... - * Delete the following character and leave the user in vi insert mode. - */ -static KT_KEY_FN(gl_vi_forward_change_char) -{ - gl_save_for_undo(gl); - gl->vi.command = 0; /* Allow cursor at EOL */ - return gl_delete_chars(gl, count, 1) || gl_vi_insert(gl, 0); -} - -/*....................................................................... - * Delete the preceding character and leave the user in vi insert mode. - */ -static KT_KEY_FN(gl_vi_backward_change_char) -{ - return gl_backward_delete_char(gl, count) || gl_vi_insert(gl, 0); -} - -/*....................................................................... - * Starting from the cursor position change characters to the specified column. - */ -static KT_KEY_FN(gl_vi_change_to_column) -{ - if (--count >= gl->buff_curpos) - return gl_vi_forward_change_char(gl, count - gl->buff_curpos); - else - return gl_vi_backward_change_char(gl, gl->buff_curpos - count); -} - -/*....................................................................... - * Starting from the cursor position change characters to a matching - * parenthesis. - */ -static KT_KEY_FN(gl_vi_change_to_parenthesis) -{ - int curpos = gl_index_of_matching_paren(gl); - if(curpos >= 0) { - gl_save_for_undo(gl); - if(curpos >= gl->buff_curpos) - return gl_vi_forward_change_char(gl, curpos - gl->buff_curpos + 1); - else - return gl_vi_backward_change_char(gl, ++gl->buff_curpos - curpos + 1); - }; - return 0; -} - -/*....................................................................... - * If in vi mode, switch to vi command mode. - * - * Input: - * gl GetLine * The getline resource object. - */ -static void gl_vi_command_mode(GetLine *gl) -{ - if(gl->editor == GL_VI_MODE && !gl->vi.command) { - gl->insert = 1; - gl->vi.command = 1; - gl->vi.repeat.input_curpos = gl->insert_curpos; - gl->vi.repeat.command_curpos = gl->buff_curpos; - gl->insert_curpos = 0; /* unrestrict left motion boundary */ - gl_cursor_left(gl, 1); /* Vi moves left one on entering command mode */ - }; -} - -/*....................................................................... - * This is an action function which rings the terminal bell. - */ -static KT_KEY_FN(gl_ring_bell) -{ - return gl->silence_bell ? 0 : - gl_output_control_sequence(gl, 1, gl->sound_bell); -} - -/*....................................................................... - * This is the action function which implements the vi-repeat-change - * action. - */ -static KT_KEY_FN(gl_vi_repeat_change) -{ - int status; /* The return status of the repeated action function */ - int i; -/* - * Nothing to repeat? - */ - if(!gl->vi.repeat.fn) - return gl_ring_bell(gl, 1); -/* - * Provide a way for action functions to know whether they are being - * called by us. - */ - gl->vi.repeat.active = 1; -/* - * Re-run the recorded function. - */ - status = gl->vi.repeat.fn(gl, gl->vi.repeat.count); -/* - * Mark the repeat as completed. - */ - gl->vi.repeat.active = 0; -/* - * Is we are repeating a function that has just switched to input - * mode to allow the user to type, re-enter the text that the user - * previously entered. - */ - if(status==0 && !gl->vi.command) { -/* - * Make sure that the current line has been saved. - */ - gl_save_for_undo(gl); -/* - * Repeat a previous insertion or overwrite? - */ - if(gl->vi.repeat.input_curpos >= 0 && - gl->vi.repeat.input_curpos <= gl->vi.repeat.command_curpos && - gl->vi.repeat.command_curpos <= gl->vi.undo.ntotal) { -/* - * Using the current line which is saved in the undo buffer, plus - * the range of characters therein, as recorded by gl_vi_command_mode(), - * add the characters that the user previously entered, to the input - * line. - */ - for(i=gl->vi.repeat.input_curpos; i<gl->vi.repeat.command_curpos; i++) { - if(gl_add_char_to_line(gl, gl->vi.undo.line[i])) - return 1; - }; - }; -/* - * Switch back to command mode, now that the insertion has been repeated. - */ - gl_vi_command_mode(gl); - }; - return status; -} - -/*....................................................................... - * If the cursor is currently over a parenthesis character, return the - * index of its matching parenthesis. If not currently over a parenthesis - * character, return the next close parenthesis character to the right of - * the cursor. If the respective parenthesis character isn't found, - * ring the terminal bell and return -1. - * - * Input: - * gl GetLine * The getline resource object. - * Output: - * return int Either the index of the matching parenthesis, - * or -1 if not found. - */ -static int gl_index_of_matching_paren(GetLine *gl) -{ - int i; -/* - * List the recognized parentheses, and their matches. - */ - const char *o_paren = "([{"; - const char *c_paren = ")]}"; - const char *cptr; -/* - * Get the character that is currently under the cursor. - */ - char c = gl->line[gl->buff_curpos]; -/* - * If the character under the cursor is an open parenthesis, look forward - * for the matching close parenthesis. - */ - if((cptr=strchr(o_paren, c))) { - char match = c_paren[cptr - o_paren]; - int matches_needed = 1; - for(i=gl->buff_curpos+1; i<gl->ntotal; i++) { - if(gl->line[i] == c) - matches_needed++; - else if(gl->line[i] == match && --matches_needed==0) - return i; - }; -/* - * If the character under the cursor is an close parenthesis, look forward - * for the matching open parenthesis. - */ - } else if((cptr=strchr(c_paren, c))) { - char match = o_paren[cptr - c_paren]; - int matches_needed = 1; - for(i=gl->buff_curpos-1; i>=0; i--) { - if(gl->line[i] == c) - matches_needed++; - else if(gl->line[i] == match && --matches_needed==0) - return i; - }; -/* - * If not currently over a parenthesis character, search forwards for - * the first close parenthesis (this is what the vi % binding does). - */ - } else { - for(i=gl->buff_curpos+1; i<gl->ntotal; i++) - if(strchr(c_paren, gl->line[i]) != NULL) - return i; - }; -/* - * Not found. - */ - (void) gl_ring_bell(gl, 1); - return -1; -} - -/*....................................................................... - * If the cursor is currently over a parenthesis character, this action - * function moves the cursor to its matching parenthesis. - */ -static KT_KEY_FN(gl_find_parenthesis) -{ - int curpos = gl_index_of_matching_paren(gl); - if(curpos >= 0) - return gl_place_cursor(gl, curpos); - return 0; -} - -/*....................................................................... - * Handle the receipt of the potential start of a new key-sequence from - * the user. - * - * Input: - * gl GetLine * The resource object of this library. - * first_char char The first character of the sequence. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_interpret_char(GetLine *gl, char first_char) -{ - KtKeyFn *keyfn; /* An action function */ - char keyseq[GL_KEY_MAX+1]; /* A special key sequence being read */ - int nkey=0; /* The number of characters in the key sequence */ - int count; /* The repeat count of an action function */ - int ret; /* The return value of an action function */ - int i; -/* - * Get the first character. - */ - char c = first_char; -/* - * If editting is disabled, just add newly entered characters to the - * input line buffer, and watch for the end of the line. - */ - if(gl->editor == GL_NO_EDITOR) { - if(gl->ntotal >= gl->linelen) - return 0; - if(c == '\n' || c == '\r') - return gl_newline(gl, 1); - gl->line[gl->ntotal++] = c; - return 0; - }; -/* - * If the user is in the process of specifying a repeat count and the - * new character is a digit, increment the repeat count accordingly. - */ - if(gl->number >= 0 && isdigit((int)(unsigned char) c)) - return gl_digit_argument(gl, c); -/* - * In vi command mode, all key-sequences entered need to be - * either implicitly or explicitly prefixed with an escape character. - */ - else if(gl->vi.command && c != GL_ESC_CHAR) - keyseq[nkey++] = GL_ESC_CHAR; -/* - * If the first character of the sequence is a printable character, - * then to avoid confusion with the special "up", "down", "left" - * or "right" cursor key bindings, we need to prefix the - * printable character with a backslash escape before looking it up. - */ - else if(!IS_META_CHAR(c) && !IS_CTRL_CHAR(c)) - keyseq[nkey++] = '\\'; -/* - * Compose a potentially multiple key-sequence in gl->keyseq. - */ - while(nkey < GL_KEY_MAX) { - int first, last; /* The matching entries in gl->keys */ -/* - * If the character is an unprintable meta character, split it - * into two characters, an escape character and the character - * that was modified by the meta key. - */ - if(IS_META_CHAR(c)) { - keyseq[nkey++] = GL_ESC_CHAR; - c = META_TO_CHAR(c); - continue; - }; -/* - * Append the latest character to the key sequence. - */ - keyseq[nkey++] = c; -/* - * When doing vi-style editing, an escape at the beginning of any binding - * switches to command mode. - */ - if(keyseq[0] == GL_ESC_CHAR && !gl->vi.command) - gl_vi_command_mode(gl); -/* - * Lookup the key sequence. - */ - switch(_kt_lookup_keybinding(gl->bindings, keyseq, nkey, &first, &last)) { - case KT_EXACT_MATCH: -/* - * Get the matching action function. - */ - keyfn = gl->bindings->table[first].keyfn; -/* - * Get the repeat count, passing the last keystroke if executing the - * digit-argument action. - */ - if(keyfn == gl_digit_argument) { - count = c; - } else { - count = gl->number >= 0 ? gl->number : 1; - }; -/* - * Record the function that is being invoked. - */ - gl->current_fn = keyfn; - gl->current_count = count; -/* - * Mark the current line as not yet preserved for use by the vi undo command. - */ - gl->vi.undo.saved = 0; - gl->vi.repeat.saved = 0; -/* - * Execute the action function. Note the action function can tell - * whether the provided repeat count was defaulted or specified - * explicitly by looking at whether gl->number is -1 or not. If - * it is negative, then no repeat count was specified by the user. - */ - ret = keyfn(gl, count); -/* - * Reset the repeat count after running action functions (other - * than digit-argument). - */ - if(keyfn != gl_digit_argument) - gl->number = -1; - if(ret) - return 1; - return 0; - break; - case KT_AMBIG_MATCH: /* Ambiguous match - so look ahead */ - if(gl_read_character(gl, &c)) /* Get the next character */ - return 1; - break; - case KT_NO_MATCH: -/* - * If the first character looked like it might be a prefix of a key-sequence - * but it turned out not to be, ring the bell to tell the user that it - * wasn't recognised. - */ - if(keyseq[0] != '\\' && keyseq[0] != '\t') { - gl_ring_bell(gl, 0); - } else { -/* - * The user typed a single printable character that doesn't match - * the start of any keysequence, so add it to the line in accordance - * with the current repeat count. - */ - count = gl->number >= 0 ? gl->number : 1; - for(i=0; i<count; i++) - gl_add_char_to_line(gl, first_char); - gl->number = -1; - }; - return 0; - break; - case KT_BAD_MATCH: - return 1; - break; - }; - }; -/* - * Key sequence too long to match. - */ - return 0; -} - -/*....................................................................... - * Configure the application and/or user-specific behavior of - * gl_get_line(). - * - * Note that calling this function between calling new_GetLine() and - * the first call to new_GetLine(), disables the otherwise automatic - * reading of ~/.teclarc on the first call to gl_get_line(). - * - * Input: - * gl GetLine * The resource object of this library. - * app_string const char * Either NULL, or a string containing one - * or more .teclarc command lines, separated - * by newline characters. This can be used to - * establish an application-specific - * configuration, without the need for an external - * file. This is particularly useful in embedded - * environments where there is no filesystem. - * app_file const char * Either NULL, or the pathname of an - * application-specific .teclarc file. The - * contents of this file, if provided, are - * read after the contents of app_string[]. - * user_file const char * Either NULL, or the pathname of a - * user-specific .teclarc file. Except in - * embedded applications, this should - * usually be "~/.teclarc". - * Output: - * return int 0 - OK. - * 1 - Bad argument(s). - */ -int gl_configure_getline(GetLine *gl, const char *app_string, - const char *app_file, const char *user_file) -{ -/* - * Check the arguments. - */ - if(!gl) { - fprintf(stderr, "gl_configure_getline: NULL gl argument.\n"); - return 1; - }; -/* - * Mark getline as having been explicitly configured. - */ - gl->configured = 1; -/* - * Start by parsing the configuration string, if provided. - */ - if(app_string) - (void) _gl_read_config_string(gl, app_string, KTB_NORM); -/* - * Now parse the application-specific configuration file, if provided. - */ - if(app_file) - (void) _gl_read_config_file(gl, app_file, KTB_NORM); -/* - * Finally, parse the user-specific configuration file, if provided. - */ - if(user_file) - (void) _gl_read_config_file(gl, user_file, KTB_USER); -/* - * Record the names of the configuration files to allow them to - * be re-read if requested at a later time. - */ - if(gl_record_string(&gl->app_file, app_file) || - gl_record_string(&gl->user_file, user_file)) { - fprintf(stderr, - "Insufficient memory to record tecla configuration file names.\n"); - return 1; - }; - return 0; -} - -/*....................................................................... - * Replace a malloc'd string (or NULL), with another malloc'd copy of - * a string (or NULL). - * - * Input: - * sptr char ** On input if *sptr!=NULL, *sptr will be - * free'd and *sptr will be set to NULL. Then, - * on output, if string!=NULL a malloc'd copy - * of this string will be assigned to *sptr. - * string const char * The string to be copied, or NULL to simply - * discard any existing string. - * Output: - * return int 0 - OK. - * 1 - Malloc failure (no error message is generated). - */ -static int gl_record_string(char **sptr, const char *string) -{ -/* - * If the original string is the same string, don't do anything. - */ - if(*sptr == string || (*sptr && string && strcmp(*sptr, string)==0)) - return 0; -/* - * Discard any existing cached string. - */ - if(*sptr) { - free(*sptr); - *sptr = NULL; - }; -/* - * Allocate memory for a copy of the specified string. - */ - if(string) { - *sptr = (char *) malloc(strlen(string) + 1); - if(!*sptr) - return 1; -/* - * Copy the string. - */ - strcpy(*sptr, string); - }; - return 0; -} - -/*....................................................................... - * Re-read any application-specific and user-specific files previously - * specified via the gl_configure_getline() function. - */ -static KT_KEY_FN(gl_read_init_files) -{ - return gl_configure_getline(gl, NULL, gl->app_file, gl->user_file); -} - -/*....................................................................... - * Save the contents of the history buffer to a given new file. - * - * Input: - * gl GetLine * The resource object of this library. - * filename const char * The name of the new file to write to. - * comment const char * Extra information such as timestamps will - * be recorded on a line started with this - * string, the idea being that the file can - * double as a command file. Specify "" if - * you don't care. - * max_lines int The maximum number of lines to save, or -1 - * to save all of the lines in the history - * list. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_save_history(GetLine *gl, const char *filename, const char *comment, - int max_lines) -{ - FileExpansion *expansion; /* The expansion of the filename */ -/* - * Check the arguments. - */ - if(!gl || !filename || !comment) { - fprintf(stderr, "gl_save_history: NULL argument(s).\n"); - return 1; - }; -/* - * Expand the filename. - */ - expansion = ef_expand_file(gl->ef, filename, -1); - if(!expansion) { - fprintf(stderr, "Unable to expand %s (%s).\n", filename, - ef_last_error(gl->ef)); - return 1; - }; -/* - * Attempt to save to the specified file. - */ - return _glh_save_history(gl->glh, expansion->files[0], comment, max_lines); -} - -/*....................................................................... - * Restore the contents of the history buffer from a given new file. - * - * Input: - * gl GetLine * The resource object of this library. - * filename const char * The name of the new file to write to. - * comment const char * This must be the same string that was - * passed to gl_save_history() when the file - * was written. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_load_history(GetLine *gl, const char *filename, const char *comment) -{ - FileExpansion *expansion; /* The expansion of the filename */ -/* - * Check the arguments. - */ - if(!gl || !filename || !comment) { - fprintf(stderr, "gl_load_history: NULL argument(s).\n"); - return 1; - }; -/* - * Expand the filename. - */ - expansion = ef_expand_file(gl->ef, filename, -1); - if(!expansion) { - fprintf(stderr, "Unable to expand %s (%s).\n", filename, - ef_last_error(gl->ef)); - return 1; - }; -/* - * Attempt to load from the specified file. - */ - if(_glh_load_history(gl->glh, expansion->files[0], comment, - gl->cutbuf, gl->linelen)) { - gl->cutbuf[0] = '\0'; - return 1; - }; - gl->cutbuf[0] = '\0'; - return 0; -} - -/*....................................................................... - * Where possible, register a function and associated data to be called - * whenever a specified event is seen on a file descriptor. - * - * Input: - * gl GetLine * The resource object of the command-line input - * module. - * fd int The file descriptor to watch. - * event GlFdEvent The type of activity to watch for. - * callback GlFdEventFn * The function to call when the specified - * event occurs. Setting this to 0 removes - * any existing callback. - * data void * A pointer to arbitrary data to pass to the - * callback function. - * Output: - * return int 0 - OK. - * 1 - Either gl==NULL, or this facility isn't - * available on the the host system - * (ie. select() isn't available). No - * error message is generated in the latter - * case. - */ -int gl_watch_fd(GetLine *gl, int fd, GlFdEvent event, - GlFdEventFn *callback, void *data) -#if !defined(HAVE_SELECT) -{return 1;} /* The facility isn't supported on this system */ -#else -{ - GlFdNode *prev; /* The node that precedes 'node' in gl->fd_nodes */ - GlFdNode *node; /* The file-descriptor node being checked */ -/* - * Check the arguments. - */ - if(!gl) { - fprintf(stderr, "gl_watch_fd: NULL gl argument.\n"); - return 1; - }; - if(fd < 0) { - fprintf(stderr, "gl_watch_fd: Error fd < 0.\n"); - return 1; - }; -/* - * Search the list of already registered fd activity nodes for the specified - * file descriptor. - */ - for(prev=NULL,node=gl->fd_nodes; node && node->fd != fd; - prev=node, node=node->next) - ; -/* - * Hasn't a node been allocated for this fd yet? - */ - if(!node) { -/* - * If there is no callback to record, just ignore the call. - */ - if(!callback) - return 0; -/* - * Allocate the new node. - */ - node = (GlFdNode *) _new_FreeListNode(gl->fd_node_mem); - if(!node) { - fprintf(stderr, "gl_watch_fd: Insufficient memory.\n"); - return 1; - }; -/* - * Prepend the node to the list. - */ - node->next = gl->fd_nodes; - gl->fd_nodes = node; -/* - * Initialize the node. - */ - node->fd = fd; - node->rd.fn = 0; - node->rd.data = NULL; - node->ur = node->wr = node->rd; - }; -/* - * Record the new callback. - */ - switch(event) { - case GLFD_READ: - node->rd.fn = callback; - node->rd.data = data; - if(callback) - FD_SET(fd, &gl->rfds); - else - FD_CLR(fd, &gl->rfds); - break; - case GLFD_WRITE: - node->wr.fn = callback; - node->wr.data = data; - if(callback) - FD_SET(fd, &gl->wfds); - else - FD_CLR(fd, &gl->wfds); - break; - case GLFD_URGENT: - node->ur.fn = callback; - node->ur.data = data; - if(callback) - FD_SET(fd, &gl->ufds); - else - FD_CLR(fd, &gl->ufds); - break; - }; -/* - * Keep a record of the largest file descriptor being watched. - */ - if(fd > gl->max_fd) - gl->max_fd = fd; -/* - * If we are deleting an existing callback, also delete the parent - * activity node if no callbacks are registered to the fd anymore. - */ - if(!callback) { - if(!node->rd.fn && !node->wr.fn && !node->ur.fn) { - if(prev) - prev->next = node->next; - else - gl->fd_nodes = node->next; - node = (GlFdNode *) _del_FreeListNode(gl->fd_node_mem, node); - }; - }; - return 0; -} - -/*....................................................................... - * When select() is available, this function is called by - * gl_read_character() to respond to file-descriptor events registered by - * the caller. - * - * Input: - * gl GetLine * The resource object of this module. - * Output: - * return int 0 - A character is waiting to be read from the - * terminal. - * 1 - An error occurred. - */ -static int gl_event_handler(GetLine *gl) -{ -/* - * If at any time no external callbacks remain, quit the loop return, - * so that we can simply wait in read(). This is designed as an - * optimization for when no callbacks have been registered on entry to - * this function, but since callbacks can delete themselves, it can - * also help later. - */ - while(gl->fd_nodes) { -/* - * Get the set of descriptors to be watched. - */ - fd_set rfds = gl->rfds; - fd_set wfds = gl->wfds; - fd_set ufds = gl->ufds; -/* - * Wait for activity on any of the file descriptors. - */ - int nready = select(gl->max_fd+1, &rfds, &wfds, &ufds, NULL); -/* - * If select() returns but none of the file descriptors are reported - * to have activity, then select() timed out. - */ - if(nready == 0) { - fprintf(stdout, "\r\nUnexpected select() timeout\r\n"); - return 1; -/* - * If nready < 0, this means an error occurred. - */ - } else if(nready < 0) { - if(errno != EINTR) { -#ifdef EAGAIN - if(!errno) /* This can happen with SysV O_NDELAY */ - errno = EAGAIN; -#endif - return 1; - }; -/* - * If the terminal input file descriptor has data available, return. - */ - } else if(FD_ISSET(gl->input_fd, &rfds)) { - return 0; -/* - * Check for activity on any of the file descriptors registered by the - * calling application, and call the associated callback functions. - */ - } else { - GlFdNode *node; /* The fd event node being checked */ -/* - * Search the list for the file descriptor that caused select() to return. - */ - for(node=gl->fd_nodes; node; node=node->next) { -/* - * Is there urgent out of band data waiting to be read on fd? - */ - if(node->ur.fn && FD_ISSET(node->fd, &ufds)) { - if(gl_call_fd_handler(gl, &node->ur, node->fd, GLFD_URGENT)) - return 1; - break; /* The callback may have changed the list of nodes */ -/* - * Is the fd readable? - */ - } else if(node->rd.fn && FD_ISSET(node->fd, &rfds)) { - if(gl_call_fd_handler(gl, &node->rd, node->fd, GLFD_READ)) - return 1; - break; /* The callback may have changed the list of nodes */ -/* - * Is the fd writable? - */ - } else if(node->wr.fn && FD_ISSET(node->fd, &rfds)) { - if(gl_call_fd_handler(gl, &node->wr, node->fd, GLFD_WRITE)) - return 1; - break; /* The callback may have changed the list of nodes */ - }; - }; - }; - }; - return 0; -} - -/*....................................................................... - * This is a private function of gl_event_handler(), used to call a - * file-descriptor callback. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * gfh GlFdHandler * The I/O handler. - * fd int The file-descriptor being reported. - * event GlFdEvent The I/O event being reported. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_call_fd_handler(GetLine *gl, GlFdHandler *gfh, int fd, - GlFdEvent event) -{ - Termios attr; /* The terminal attributes */ - int redisplay = 0; /* True to have the input line redisplayed */ - int waserr = 0; /* True after any error */ -/* - * We don't want to do a longjmp in the middle of a callback that - * might be modifying global or heap data, so block all the signals - * that we are trapping. - */ - if(sigprocmask(SIG_BLOCK, &gl->new_signal_set, NULL) == -1) { - fprintf(stderr, "getline(): sigprocmask error: %s\n", strerror(errno)); - return 1; - }; -/* - * Re-enable conversion of newline characters to carriage-return/linefeed, - * so that the callback can write to the terminal without having to do - * anything special. - */ - if(tcgetattr(gl->input_fd, &attr)) { - fprintf(stderr, "\r\ngetline(): tcgetattr error: %s\r\n", strerror(errno)); - return 1; - }; - attr.c_oflag |= OPOST; - while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) { - if (errno != EINTR) { - fprintf(stderr, "\r\ngetline(): tcsetattr error: %s\r\n", - strerror(errno)); - return 1; - }; - }; -/* - * Invoke the application's callback function. - */ - switch(gfh->fn(gl, gfh->data, fd, event)) { - default: - case GLFD_ABORT: - waserr = 1; - break; - case GLFD_REFRESH: - redisplay = 1; - break; - case GLFD_CONTINUE: - redisplay = gl->prompt_changed; - break; - }; -/* - * Disable conversion of newline characters to carriage-return/linefeed. - */ - attr.c_oflag &= ~(OPOST); - while(tcsetattr(gl->input_fd, TCSADRAIN, &attr)) { - if(errno != EINTR) { - fprintf(stderr, "\ngetline(): tcsetattr error: %s\n", strerror(errno)); - return 1; - }; - }; -/* - * If requested, redisplay the input line. - */ - if(redisplay && gl_redisplay(gl, 1)) - return 1; -/* - * Unblock the signals that we were trapping before this function - * was called. - */ - if(sigprocmask(SIG_UNBLOCK, &gl->new_signal_set, NULL) == -1) { - fprintf(stderr, "getline(): sigprocmask error: %s\n", strerror(errno)); - return 1; - }; - return waserr; -} -#endif /* HAVE_SELECT */ - -/*....................................................................... - * Switch history groups. History groups represent separate history - * lists recorded within a single history buffer. Different groups - * are distinguished by integer identifiers chosen by the calling - * appplicaton. Initially new_GetLine() sets the group identifier to - * 0. Whenever a new line is appended to the history list, the current - * group identifier is recorded with it, and history lookups only - * consider lines marked with the current group identifier. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * id unsigned The new history group identifier. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_group_history(GetLine *gl, unsigned id) -{ -/* - * Check the arguments. - */ - if(!gl) { - fprintf(stderr, "gl_group_history: NULL argument(s).\n"); - return 1; - }; -/* - * If the group isn't being changed, do nothing. - */ - if(_glh_get_group(gl->glh) == id) - return 0; -/* - * Establish the new group. - */ - if(_glh_set_group(gl->glh, id)) - return 1; -/* - * Prevent history information from the previous group being - * inappropriately used by the next call to gl_get_line(). - */ - gl->preload_history = 0; - gl->last_search = -1; - return 0; -} - -/*....................................................................... - * Display the contents of the history list. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * fp FILE * The stdio output stream to write to. - * fmt const char * A format string. This containing characters to be - * written verbatim, plus any of the following - * format directives: - * %D - The date, formatted like 2001-11-20 - * %T - The time of day, formatted like 23:59:59 - * %N - The sequential entry number of the - * line in the history buffer. - * %G - The number of the history group that - * the line belongs to. - * %% - A literal % character. - * %H - The history line itself. - * Note that a '\n' newline character is not - * appended by default. - * all_groups int If true, display history lines from all - * history groups. Otherwise only display - * those of the current history group. - * max_lines int If max_lines is < 0, all available lines - * are displayed. Otherwise only the most - * recent max_lines lines will be displayed. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_show_history(GetLine *gl, FILE *fp, const char *fmt, int all_groups, - int max_lines) -{ -/* - * Check the arguments. - */ - if(!gl || !fp || !fmt) { - fprintf(stderr, "gl_show_history: NULL argument(s).\n"); - return 1; - }; - return _glh_show_history(gl->glh, fp, fmt, all_groups, max_lines); -} - -/*....................................................................... - * Update if necessary, and return the current size of the terminal. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * def_ncolumn int If the number of columns in the terminal - * can't be determined, substitute this number. - * def_nline int If the number of lines in the terminal can't - * be determined, substitute this number. - * Output: - * return GlTerminalSize The current terminal size. - */ -GlTerminalSize gl_terminal_size(GetLine *gl, int def_ncolumn, int def_nline) -{ - GlTerminalSize size; /* The return value */ - const char *env; /* The value of an environment variable */ - int n; /* A number read from env[] */ -/* - * Set the number of lines and columns to non-sensical values so that - * we know later if they have been set. - */ - gl->nline = 0; - gl->ncolumn = 0; -/* - * Are we reading from a terminal? - */ - if(gl->is_term) { -/* - * Ask the terminal directly if possible. - */ -#ifdef USE_SIGWINCH - (void) gl_resize_terminal(gl, 0); -#endif -/* - * If gl_resize_terminal() couldn't be used, or it returned non-sensical - * values for the number of lines, see if the LINES environment variable - * exists and specifies a believable number. If this doesn't work, - * look up the default size in the terminal information database, - * where available. - */ - if(gl->nline < 1) { - if((env = getenv("LINES")) && (n=atoi(env)) > 0) - gl->nline = n; -#ifdef USE_TERMINFO - else - gl->nline = tigetnum((char *)"lines"); -#elif defined(USE_TERMCAP) - else - gl->nline = tgetnum("li"); -#endif - }; -/* - * If gl_resize_terminal() couldn't be used, or it returned non-sensical - * values for the number of columns, see if the COLUMNS environment variable - * exists and specifies a believable number. If this doesn't work, fall - * lookup the default size in the terminal information database, - * where available. - */ - if(gl->ncolumn < 1) { - if((env = getenv("COLUMNS")) && (n=atoi(env)) > 0) - gl->ncolumn = n; -#ifdef USE_TERMINFO - else - gl->ncolumn = tigetnum((char *)"cols"); -#elif defined(USE_TERMCAP) - else - gl->ncolumn = tgetnum("co"); -#endif - }; - }; -/* - * If we still haven't been able to acquire reasonable values, substitute - * the default values specified by the caller. - */ - if(gl->nline <= 0) - gl->nline = def_nline; - if(gl->ncolumn <= 0) - gl->ncolumn = def_ncolumn; -/* - * Copy the new size into the return value. - */ - size.nline = gl->nline; - size.ncolumn = gl->ncolumn; - return size; -} - -/*....................................................................... - * Resize or delete the history buffer. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * bufsize size_t The number of bytes in the history buffer, or 0 - * to delete the buffer completely. - * Output: - * return int 0 - OK. - * 1 - Insufficient memory (the previous buffer - * will have been retained). No error message - * will be displayed. - */ -int gl_resize_history(GetLine *gl, size_t bufsize) -{ - return gl ? _glh_resize_history(gl->glh, bufsize) : 1; -} - -/*....................................................................... - * Set an upper limit to the number of lines that can be recorded in the - * history list, or remove a previously specified limit. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * max_lines int The maximum number of lines to allow, or -1 to - * cancel a previous limit and allow as many lines - * as will fit in the current history buffer size. - */ -void gl_limit_history(GetLine *gl, int max_lines) -{ - if(gl) - _glh_limit_history(gl->glh, max_lines); -} - -/*....................................................................... - * Discard either all historical lines, or just those associated with the - * current history group. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * all_groups int If true, clear all of the history. If false, - * clear only the stored lines associated with the - * currently selected history group. - */ -void gl_clear_history(GetLine *gl, int all_groups) -{ - if(gl) - _glh_clear_history(gl->glh, all_groups); -} - -/*....................................................................... - * Temporarily enable or disable the gl_get_line() history mechanism. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * enable int If true, turn on the history mechanism. If - * false, disable it. - */ -void gl_toggle_history(GetLine *gl, int enable) -{ - if(gl) - _glh_toggle_history(gl->glh, enable); -} - -/*....................................................................... - * Lookup a history line by its sequential number of entry in the - * history buffer. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * id unsigned long The identification number of the line to - * be returned, where 0 denotes the first line - * that was entered in the history list, and - * each subsequently added line has a number - * one greater than the previous one. For - * the range of lines currently in the list, - * see the gl_range_of_history() function. - * Input/Output: - * line GlHistoryLine * A pointer to the variable in which to - * return the details of the line. - * Output: - * return int 0 - The line is no longer in the history - * list, and *line has not been changed. - * 1 - The requested line can be found in - * *line. Note that line->line is part - * of the history buffer, so a - * private copy should be made if you - * wish to use it after subsequent calls - * to any functions that take *gl as an - * argument. - */ -int gl_lookup_history(GetLine *gl, unsigned long id, GlHistoryLine *line) -{ - return gl ? _glh_lookup_history(gl->glh, (GlhLineID) id, &line->line, - &line->group, &line->timestamp) : 0; -} - -/*....................................................................... - * Query the state of the history list. Note that any of the input/output - * pointers can be specified as NULL. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * Input/Output: - * state GlHistoryState * A pointer to the variable in which to record - * the return values. - */ -void gl_state_of_history(GetLine *gl, GlHistoryState *state) -{ - if(gl && state) - _glh_state_of_history(gl->glh, &state->enabled, &state->group, - &state->max_lines); -} - -/*....................................................................... - * Query the number and range of lines in the history buffer. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * range GlHistoryRange * A pointer to the variable in which to record - * the return values. If range->nline=0, the - * range of lines will be given as 0-0. - */ -void gl_range_of_history(GetLine *gl, GlHistoryRange *range) -{ - if(gl && range) - _glh_range_of_history(gl->glh, &range->oldest, &range->newest, - &range->nlines); -} - -/*....................................................................... - * Return the size of the history buffer and the amount of the - * buffer that is currently in use. - * - * Input: - * gl GetLine * The gl_get_line() resource object. - * Input/Output: - * GlHistorySize size * A pointer to the variable in which to return - * the results. - */ -void gl_size_of_history(GetLine *gl, GlHistorySize *size) -{ - if(gl && size) - _glh_size_of_history(gl->glh, &size->size, &size->used); -} - -/*....................................................................... - * This is the action function that lists the contents of the history - * list. - */ -static KT_KEY_FN(gl_list_history) -{ -/* - * Start a new line. - */ - if(fprintf(gl->output_fp, "\r\n") < 0) - return 1; -/* - * List history lines that belong to the current group. - */ - _glh_show_history(gl->glh, gl->output_fp, "%N %T %H\r\n", 0, - count<=1 ? -1 : count); -/* - * Redisplay the line being edited. - */ - gl->term_curpos = 0; - return gl_redisplay(gl,1); -} - -/*....................................................................... - * Specify whether text that users type should be displayed or hidden. - * In the latter case, only the prompt is displayed, and the final - * input line is not archived in the history list. - * - * Input: - * gl GetLine * The gl_get_line() resource object. - * enable int 0 - Disable echoing. - * 1 - Enable echoing. - * -1 - Just query the mode without changing it. - * Output: - * return int The echoing disposition that was in effect - * before this function was called: - * 0 - Echoing was disabled. - * 1 - Echoing was enabled. - */ -int gl_echo_mode(GetLine *gl, int enable) -{ - if(gl) { - int was_echoing = gl->echo; - if(enable >= 0) - gl->echo = enable; - return was_echoing; - }; - return 1; -} - -/*....................................................................... - * Display the prompt. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_display_prompt(GetLine *gl) -{ - const char *pptr; /* A pointer into gl->prompt[] */ - unsigned old_attr=0; /* The current text display attributes */ - unsigned new_attr=0; /* The requested text display attributes */ -/* - * Temporarily switch to echoing output characters. - */ - int kept_echo = gl->echo; - gl->echo = 1; -/* - * In case the screen got messed up, send a carriage return to - * put the cursor at the beginning of the current terminal line. - */ - if(gl_output_control_sequence(gl, 1, gl->bol)) - return 1; -/* - * Write the prompt, using the currently selected prompt style. - */ - switch(gl->prompt_style) { - case GL_LITERAL_PROMPT: - if(gl_output_string(gl, gl->prompt, '\0')) - return 1; - break; - case GL_FORMAT_PROMPT: - for(pptr=gl->prompt; *pptr; pptr++) { -/* - * Does the latest character appear to be the start of a directive? - */ - if(*pptr == '%') { -/* - * Check for and act on attribute changing directives. - */ - switch(pptr[1]) { -/* - * Add or remove a text attribute from the new set of attributes. - */ - case 'B': case 'U': case 'S': case 'P': case 'F': case 'V': - case 'b': case 'u': case 's': case 'p': case 'f': case 'v': - switch(*++pptr) { - case 'B': /* Switch to a bold font */ - new_attr |= GL_TXT_BOLD; - break; - case 'b': /* Switch to a non-bold font */ - new_attr &= ~GL_TXT_BOLD; - break; - case 'U': /* Start underlining */ - new_attr |= GL_TXT_UNDERLINE; - break; - case 'u': /* Stop underlining */ - new_attr &= ~GL_TXT_UNDERLINE; - break; - case 'S': /* Start highlighting */ - new_attr |= GL_TXT_STANDOUT; - break; - case 's': /* Stop highlighting */ - new_attr &= ~GL_TXT_STANDOUT; - break; - case 'P': /* Switch to a pale font */ - new_attr |= GL_TXT_DIM; - break; - case 'p': /* Switch to a non-pale font */ - new_attr &= ~GL_TXT_DIM; - break; - case 'F': /* Switch to a flashing font */ - new_attr |= GL_TXT_BLINK; - break; - case 'f': /* Switch to a steady font */ - new_attr &= ~GL_TXT_BLINK; - break; - case 'V': /* Switch to reverse video */ - new_attr |= GL_TXT_REVERSE; - break; - case 'v': /* Switch out of reverse video */ - new_attr &= ~GL_TXT_REVERSE; - break; - }; - continue; -/* - * A literal % is represented by %%. Skip the leading %. - */ - case '%': - pptr++; - break; - }; - }; -/* - * Many terminals, when asked to turn off a single text attribute, turn - * them all off, so the portable way to turn one off individually is to - * explicitly turn them all off, then specify those that we want from - * scratch. - */ - if(old_attr & ~new_attr) { - if(gl_output_control_sequence(gl, 1, gl->text_attr_off)) - return 1; - old_attr = 0; - }; -/* - * Install new text attributes? - */ - if(new_attr != old_attr) { - if(new_attr & GL_TXT_BOLD && !(old_attr & GL_TXT_BOLD) && - gl_output_control_sequence(gl, 1, gl->bold)) - return 1; - if(new_attr & GL_TXT_UNDERLINE && !(old_attr & GL_TXT_UNDERLINE) && - gl_output_control_sequence(gl, 1, gl->underline)) - return 1; - if(new_attr & GL_TXT_STANDOUT && !(old_attr & GL_TXT_STANDOUT) && - gl_output_control_sequence(gl, 1, gl->standout)) - return 1; - if(new_attr & GL_TXT_DIM && !(old_attr & GL_TXT_DIM) && - gl_output_control_sequence(gl, 1, gl->dim)) - return 1; - if(new_attr & GL_TXT_REVERSE && !(old_attr & GL_TXT_REVERSE) && - gl_output_control_sequence(gl, 1, gl->reverse)) - return 1; - if(new_attr & GL_TXT_BLINK && !(old_attr & GL_TXT_BLINK) && - gl_output_control_sequence(gl, 1, gl->blink)) - return 1; - old_attr = new_attr; - }; -/* - * Display the latest character. - */ - if(gl_output_char(gl, *pptr, pptr[1])) - return 1; - }; -/* - * Turn off all text attributes now that we have finished drawing - * the prompt. - */ - if(gl_output_control_sequence(gl, 1, gl->text_attr_off)) - return 1; - break; - }; -/* - * Restore the original echo mode. - */ - gl->echo = kept_echo; -/* - * The prompt has now been displayed at least once. - */ - gl->prompt_changed = 0; - return 0; -} - -/*....................................................................... - * This function can be called from gl_get_line() callbacks to have - * the prompt changed when they return. It has no effect if gl_get_line() - * is not currently being invoked. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * prompt const char * The new prompt. - */ -void gl_replace_prompt(GetLine *gl, const char *prompt) -{ - if(gl) { - gl->prompt = prompt ? prompt : ""; - gl->prompt_len = gl_displayed_prompt_width(gl); - gl->prompt_changed = 1; - }; -} - -/*....................................................................... - * Work out the length of the current prompt on the terminal, according - * to the current prompt formatting style. - * - * Input: - * gl GetLine * The resource object of this library. - * Output: - * return int The number of displayed characters. - */ -static int gl_displayed_prompt_width(GetLine *gl) -{ - int slen=0; /* The displayed number of characters */ - const char *pptr; /* A pointer into prompt[] */ -/* - * The length differs according to the prompt display style. - */ - switch(gl->prompt_style) { - case GL_LITERAL_PROMPT: - return gl_displayed_string_width(gl, gl->prompt, -1, 0); - break; - case GL_FORMAT_PROMPT: -/* - * Add up the length of the displayed string, while filtering out - * attribute directives. - */ - for(pptr=gl->prompt; *pptr; pptr++) { -/* - * Does the latest character appear to be the start of a directive? - */ - if(*pptr == '%') { -/* - * Check for and skip attribute changing directives. - */ - switch(pptr[1]) { - case 'B': case 'b': case 'U': case 'u': case 'S': case 's': - pptr++; - continue; -/* - * A literal % is represented by %%. Skip the leading %. - */ - case '%': - pptr++; - break; - }; - }; - slen += gl_displayed_char_width(gl, *pptr, slen); - }; - break; - }; - return slen; -} - -/*....................................................................... - * Specify whether to heed text attribute directives within prompt - * strings. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * style GlPromptStyle The style of prompt (see the definition of - * GlPromptStyle in libtecla.h for details). - */ -void gl_prompt_style(GetLine *gl, GlPromptStyle style) -{ - if(gl) { - if(style != gl->prompt_style) { - gl->prompt_style = style; - gl->prompt_len = gl_displayed_prompt_width(gl); - gl->prompt_changed = 1; - }; - }; -} - -/*....................................................................... - * Tell gl_get_line() how to respond to a given signal. This can be used - * both to override the default responses to signals that gl_get_line() - * normally catches and to add new signals to the list that are to be - * caught. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * signo int The number of the signal to be caught. - * flags unsigned A bitwise union of GlSignalFlags enumerators. - * after GlAfterSignal What to do after the application's signal - * handler has been called. - * errno_value int The value to set errno to. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_trap_signal(GetLine *gl, int signo, unsigned flags, - GlAfterSignal after, int errno_value) -{ - GlSignalNode *sig; -/* - * Check the arguments. - */ - if(!gl) { - fprintf(stderr, "gl_trap_signal: NULL argument(s).\n"); - return 1; - }; -/* - * See if the signal has already been registered. - */ - for(sig=gl->sigs; sig && sig->signo != signo; sig = sig->next) - ; -/* - * If the signal hasn't already been registered, allocate a node for - * it. - */ - if(!sig) { - sig = (GlSignalNode *) _new_FreeListNode(gl->sig_mem); - if(!sig) - return 1; -/* - * Add the new node to the head of the list. - */ - sig->next = gl->sigs; - gl->sigs = sig; -/* - * Record the signal number. - */ - sig->signo = signo; -/* - * Create a signal set that includes just this signal. - */ - sigemptyset(&sig->proc_mask); - if(sigaddset(&sig->proc_mask, signo) == -1) { - fprintf(stderr, "gl_trap_signal: sigaddset error: %s\n", - strerror(errno)); - sig = (GlSignalNode *) _del_FreeListNode(gl->sig_mem, sig); - return 1; - }; - }; -/* - * Record the new signal attributes. - */ - sig->flags = flags; - sig->after = after; - sig->errno_value = errno_value; - return 0; -} - -/*....................................................................... - * Remove a signal from the list of signals that gl_get_line() traps. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * signo int The number of the signal to be ignored. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_ignore_signal(GetLine *gl, int signo) -{ - GlSignalNode *sig; /* The gl->sigs list node of the specified signal */ - GlSignalNode *prev; /* The node that precedes sig in the list */ -/* - * Check the arguments. - */ - if(!gl) { - fprintf(stderr, "gl_ignore_signal: NULL argument(s).\n"); - return 1; - }; -/* - * Find the node of the gl->sigs list which records the disposition - * of the specified signal. - */ - for(prev=NULL,sig=gl->sigs; sig && sig->signo != signo; - prev=sig,sig=sig->next) - ; - if(sig) { -/* - * Remove the node from the list. - */ - if(prev) - prev->next = sig->next; - else - gl->sigs = sig->next; -/* - * Return the node to the freelist. - */ - sig = (GlSignalNode *) _del_FreeListNode(gl->sig_mem, sig); - }; - return 0; -} - -/*....................................................................... - * This function is called when an input line has been completed. It - * appends the specified newline character, terminates the line, - * records the line in the history buffer if appropriate, and positions - * the terminal cursor at the start of the next line. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * newline_char int The newline character to add to the end - * of the line. - * archive int True to have the line archived in the - * history buffer. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int gl_line_ended(GetLine *gl, int newline_char, int archive) -{ -/* - * If the newline character is printable, display it. - */ - if(isprint((int)(unsigned char) newline_char)) { - if(gl_end_of_line(gl, 1) || gl_add_char_to_line(gl, newline_char)) - return 1; - } else { -/* - * Otherwise just append it to the input line buffer. - */ - gl->line[gl->ntotal++] = newline_char; - gl->line[gl->ntotal] = '\0'; - }; -/* - * Add the line to the history buffer if it was entered with a - * newline or carriage return character. - */ - if(archive) - (void) _glh_add_history(gl->glh, gl->line, 0); -/* - * Unless depending on the system-provided line editing, start a new - * line after the end of the line that has just been entered. - */ - if(gl->editor != GL_NO_EDITOR) { - if(gl_end_of_line(gl, 1) || - gl_output_raw_string(gl, "\r\n")) - return 1; - }; - return 0; -} - -/*....................................................................... - * Return the last signal that was caught by the most recent call to - * gl_get_line(), or -1 if no signals were caught. This is useful if - * gl_get_line() returns errno=EINTR and you need to find out what signal - * caused it to abort. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * Output: - * return int The last signal caught by the most recent - * call to gl_get_line(), or -1 if no signals - * were caught. - */ -int gl_last_signal(const GetLine *gl) -{ - return gl ? gl->last_signal : -1; -} diff --git a/libtecla-1.4.1/getline.h b/libtecla-1.4.1/getline.h deleted file mode 100644 index 24b0875..0000000 --- a/libtecla-1.4.1/getline.h +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef getline_h -#define getline_h - -/* - * Copyright (c) 2000, 2001 by Martin C. Shepherd. - * - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL - * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - */ - -/* - * Set the name of the getline configuration file. - */ -#define TECLA_CONFIG_FILE "~/.teclarc" - -/* - * The following macro returns non-zero if a character is - * a control character. - */ -#define IS_CTRL_CHAR(c) ((unsigned char)(c) < ' ' || (unsigned char)(c)=='\177') - -/* - * The following macro returns non-zero if a character is - * a meta character. - */ -#define IS_META_CHAR(c) (((unsigned char)(c) & 0x80) && !isprint((int)(unsigned char)(c))) - -/* - * Return the character that would be produced by pressing the - * specified key plus the control key. - */ -#define MAKE_CTRL(c) ((c)=='?' ? '\177' : ((unsigned char)toupper(c) & ~0x40)) - -/* - * Return the character that would be produced by pressing the - * specified key plus the meta key. - */ -#define MAKE_META(c) ((unsigned char)(c) | 0x80) - -/* - * Given a binary control character, return the character that - * had to be pressed at the same time as the control key. - */ -#define CTRL_TO_CHAR(c) (toupper((unsigned char)(c) | 0x40)) - -/* - * Given a meta character, return the character that was pressed - * at the same time as the meta key. - */ -#define META_TO_CHAR(c) ((unsigned char)(c) & ~0x80) - -/* - * Specify the string of characters other than the alphanumeric characters, - * that are to be considered parts of words. - */ -#define GL_WORD_CHARS "_*\?\\[]" - -/* - * Define the escape character, both as a string and as a character. - */ -#define GL_ESC_STR "\033" -#define GL_ESC_CHAR '\033' - -#endif diff --git a/libtecla-1.4.1/hash.c b/libtecla-1.4.1/hash.c deleted file mode 100644 index 89f8245..0000000 --- a/libtecla-1.4.1/hash.c +++ /dev/null @@ -1,748 +0,0 @@ -/* - * Copyright (c) 2000, 2001 by Martin C. Shepherd. - * - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL - * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <ctype.h> - -#include "hash.h" -#include "strngmem.h" -#include "freelist.h" - -/* - * The following container object contains free-lists to be used - * for allocation of HashTable containers and nodes. - */ -struct HashMemory { - FreeList *hash_memory; /* HashTable free-list */ - FreeList *node_memory; /* HashNode free-list */ - StringMem *string_memory; /* Memory used to allocate hash strings */ -}; - -/* - * Define a hash symbol-table entry. - * See symbol.h for the definition of the Symbol container type. - */ -typedef struct HashNode HashNode; -struct HashNode { - Symbol symbol; /* The symbol stored in the hash-entry */ - HashNode *next; /* The next hash-table entry in a bucket list */ -}; - -/* - * Each hash-table bucket contains a linked list of entries that - * hash to the same bucket. - */ -typedef struct { - HashNode *head; /* The head of the bucket hash-node list */ - int count; /* The number of entries in the list */ -} HashBucket; - -/* - * Set the max length of the error-reporting string. There is no point - * in this being longer than the width of a typical terminal window. - * In composing error messages, I have assumed that this number is - * at least 80, so you don't decrease it below this number. - */ -#define ERRLEN 200 - -/* - * A hash-table consists of 'size' hash buckets. - * Note that the HashTable typedef for this struct is contained in hash.h. - */ -struct HashTable { - char errmsg[ERRLEN+1];/* Error-report buffer */ - HashMemory *mem; /* HashTable free-list */ - int internal_mem; /* True if 'mem' was allocated by _new_HashTable() */ - int case_sensitive; /* True if case is significant in lookup keys */ - int size; /* The number of hash buckets */ - HashBucket *bucket; /* An array of 'size' hash buckets */ - int (*keycmp)(const char *, const char *); /* Key comparison function */ - void *app_data; /* Application-provided data */ - HASH_DEL_FN(*del_fn); /* Application-provided 'app_data' destructor */ -}; - -static HashNode *_del_HashNode(HashTable *hash, HashNode *node); -static HashNode *_new_HashNode(HashTable *hash, const char *name, int code, - void (*fn)(void), void *data, SYM_DEL_FN(*del_fn)); -static HashNode *_find_HashNode(HashTable *hash, HashBucket *bucket, - const char *name, HashNode **prev); -static HashBucket *_find_HashBucket(HashTable *hash, const char *name); -static int _ht_lower_strcmp(const char *node_key, const char *look_key); -static int _ht_strcmp(const char *node_key, const char *look_key); - -/*....................................................................... - * Allocate a free-list for use in allocating hash tables and their nodes. - * - * Input: - * list_count int The number of HashTable containers per free-list - * block. - * node_count int The number of HashTable nodes per free-list block. - * Output: - * return HashMemory * The new free-list for use in allocating hash tables - * and their nodes. - */ -HashMemory *_new_HashMemory(int hash_count, int node_count) -{ - HashMemory *mem; -/* - * Allocate the free-list container. - */ - mem = (HashMemory *) malloc(sizeof(HashMemory)); - if(!mem) { - fprintf(stderr, "_new_HashMemory: Insufficient memory.\n"); - return NULL; - }; -/* - * Initialize the container at least up to the point at which it can - * safely be passed to _del_HashMemory(). - */ - mem->hash_memory = NULL; - mem->node_memory = NULL; - mem->string_memory = NULL; -/* - * Allocate the two free-lists. - */ - mem->hash_memory = _new_FreeList("_new_HashMemory", sizeof(HashTable), - hash_count); - if(!mem->hash_memory) - return _del_HashMemory(mem, 1); - mem->node_memory = _new_FreeList("_new_HashMemory", sizeof(HashNode), - node_count); - if(!mem->node_memory) - return _del_HashMemory(mem, 1); - mem->string_memory = _new_StringMem("_new_HashMemory", 64); - if(!mem->string_memory) - return _del_HashMemory(mem, 1); -/* - * Return the free-list container. - */ - return mem; -} - -/*....................................................................... - * Delete a HashTable free-list. An error will be displayed if the list is - * still in use and the deletion will be aborted. - * - * Input: - * mem HashMemory * The free-list container to be deleted. - * force int If force==0 then _del_HashMemory() will complain - * and refuse to delete the free-list if any - * of nodes have not been returned to the free-list. - * If force!=0 then _del_HashMemory() will not check - * whether any nodes are still in use and will - * always delete the list. - * Output: - * return HashMemory * Always NULL (even if the memory could not be - * deleted). - */ -HashMemory *_del_HashMemory(HashMemory *mem, int force) -{ - const char *caller = "_del_HashMemory"; - if(mem) { - if(!force && (_busy_FreeListNodes(mem->hash_memory) > 0 || - _busy_FreeListNodes(mem->node_memory) > 0)) { - fprintf(stderr, "%s: Free-list in use.\n", caller); - return NULL; - }; - mem->hash_memory = _del_FreeList(caller, mem->hash_memory, force); - mem->node_memory = _del_FreeList(caller, mem->node_memory, force); - mem->string_memory = _del_StringMem(caller, mem->string_memory, force); - free(mem); - }; - return NULL; -} - -/*....................................................................... - * Create a new hash table. - * - * Input: - * mem HashMemory * An optional free-list for use in allocating - * HashTable containers and nodes. See explanation - * in hash.h. If you are going to allocate more - * than one hash table, then it will be more - * efficient to allocate a single free-list for - * all of them than to force each hash table - * to allocate its own private free-list. - * size int The size of the hash table. Best performance - * will be acheived if this is a prime number. - * hcase HashCase Specify how symbol case is considered when - * looking up symbols, from: - * IGNORE_CASE - Upper and lower case versions - * of a letter are treated as - * being identical. - * HONOUR_CASE - Upper and lower case versions - * of a letter are treated as - * being distinct. - * characters in a lookup name is significant. - * app_data void * Optional application data to be registered - * to the table. This is presented to user - * provided SYM_DEL_FN() symbol destructors along - * with the symbol data. - * del_fn() HASH_DEL_FN(*) If you want app_data to be free'd when the - * hash-table is destroyed, register a suitable - * destructor function here. - * Output: - * return HashTable * The new hash table, or NULL on error. - */ -HashTable *_new_HashTable(HashMemory *mem, int size, HashCase hcase, - void *app_data, HASH_DEL_FN(*del_fn)) -{ - HashTable *hash; /* The table to be returned */ - int allocate_mem = !mem; /* True if mem should be internally allocated */ - int i; -/* - * Check arguments. - */ - if(size <= 0) { - fprintf(stderr, "_new_HashTable: Illegal table size (%d).\n", size); - return NULL; - }; -/* - * Allocate an internal free-list? - */ - if(allocate_mem) { - mem = _new_HashMemory(1, 100); - if(!mem) - return NULL; - }; -/* - * Allocate the container. - */ - hash = (HashTable *) _new_FreeListNode(mem->hash_memory); - if(!hash) { - fprintf(stderr, "_new_HashTable: Insufficient memory.\n"); - if(allocate_mem) - mem = _del_HashMemory(mem, 1); - return NULL; - }; -/* - * Before attempting any operation that might fail, initialize - * the container at least up to the point at which it can safely - * be passed to _del_HashTable(). - */ - hash->errmsg[0] = '\0'; - hash->mem = mem; - hash->internal_mem = allocate_mem; - hash->case_sensitive = hcase==HONOUR_CASE; - hash->size = size; - hash->bucket = NULL; - hash->keycmp = hash->case_sensitive ? _ht_strcmp : _ht_lower_strcmp; - hash->app_data = app_data; - hash->del_fn = del_fn; -/* - * Allocate the array of 'size' hash buckets. - */ - hash->bucket = (HashBucket *) malloc(sizeof(HashBucket) * size); - if(!hash->bucket) { - fprintf(stderr, "_new_HashTable: Insufficient memory for %d buckets.\n", - size); - return _del_HashTable(hash); - }; -/* - * Initialize the bucket array. - */ - for(i=0; i<size; i++) { - HashBucket *b = hash->bucket + i; - b->head = NULL; - b->count = 0; - }; -/* - * The table is ready for use - albeit currently empty. - */ - return hash; -} - -/*....................................................................... - * Delete a hash-table. - * - * Input: - * hash HashTable * The hash table to be deleted. - * Output: - * return HashTable * The deleted hash table (always NULL). - */ -HashTable *_del_HashTable(HashTable *hash) -{ - if(hash) { -/* - * Clear and delete the bucket array. - */ - if(hash->bucket) { - _clear_HashTable(hash); - free(hash->bucket); - hash->bucket = NULL; - }; -/* - * Delete application data. - */ - if(hash->del_fn) - hash->del_fn(hash->app_data); -/* - * If the hash table was allocated from an internal free-list, delete - * it and the hash table by deleting the free-list. Otherwise just - * return the hash-table to the external free-list. - */ - if(hash->internal_mem) - _del_HashMemory(hash->mem, 1); - else - hash = (HashTable *) _del_FreeListNode(hash->mem->hash_memory, hash); - }; - return NULL; -} - -/*....................................................................... - * Create and install a new entry in a hash table. If an entry with the - * same name already exists, replace its contents with the new data. - * - * Input: - * hash HashTable * The hash table to insert the symbol into. - * name const char * The name to tag the entry with. - * code int An application-specific code to be stored in - * the entry. - * fn void (*)(void) An application-specific function to be stored - * in the entry. - * data void * An application-specific pointer to data to be - * associated with the entry, or NULL if not - * relevant. - * del_fn SYM_DEL_FN(*) An optional destructor function. When the - * symbol is deleted this function will be called - * with the 'code' and 'data' arguments given - * above. Any application data that was registered - * to the table via the app_data argument of - * _new_HashTable() will also be passed. - * Output: - * return HashNode * The new entry, or NULL if there was insufficient - * memory or the arguments were invalid. - */ -Symbol *_new_HashSymbol(HashTable *hash, const char *name, int code, - void (*fn)(void), void *data, SYM_DEL_FN(*del_fn)) -{ - HashBucket *bucket; /* The hash-bucket associated with the name */ - HashNode *node; /* The new node */ -/* - * Check arguments. - */ - if(!hash || !name) - return NULL; -/* - * Get the hash bucket of the specified name. - */ - bucket = _find_HashBucket(hash, name); -/* - * See if a node with the same name already exists. - */ - node = _find_HashNode(hash, bucket, name, NULL); -/* - * If found, delete its contents by calling the user-supplied - * destructor function, if provided. - */ - if(node) { - if(node->symbol.data && node->symbol.del_fn) { - node->symbol.data = node->symbol.del_fn(hash->app_data, node->symbol.code, - node->symbol.data); - }; -/* - * Allocate a new node if necessary. - */ - } else { - node = _new_HashNode(hash, name, code, fn, data, del_fn); - if(!node) - return NULL; - }; -/* - * Install the node at the head of the hash-bucket list. - */ - node->next = bucket->head; - bucket->head = node; - bucket->count++; - return &node->symbol; -} - -/*....................................................................... - * Remove and delete a given hash-table entry. - * - * Input: - * hash HashTable * The hash table to find the symbol in. - * name const char * The name of the entry. - * Output: - * return HashNode * The deleted hash node (always NULL). - */ -Symbol *_del_HashSymbol(HashTable *hash, const char *name) -{ - if(hash && name) { - HashBucket *bucket = _find_HashBucket(hash, name); - HashNode *prev; /* The node preceding the located node */ - HashNode *node = _find_HashNode(hash, bucket, name, &prev); -/* - * Node found? - */ - if(node) { -/* - * Remove the node from the bucket list. - */ - if(prev) { - prev->next = node->next; - } else { - bucket->head = node->next; - }; -/* - * Record the loss of a node. - */ - bucket->count--; -/* - * Delete the node. - */ - (void) _del_HashNode(hash, node); - }; - }; - return NULL; -} - -/*....................................................................... - * Look up a symbol in the hash table. - * - * Input: - * hash HashTable * The table to look up the string in. - * name const char * The name of the symbol to look up. - * Output: - * return Symbol * The located hash-table symbol, or NULL if not - * found. - */ -Symbol *_find_HashSymbol(HashTable *hash, const char *name) -{ - HashBucket *bucket; /* The hash-table bucket associated with name[] */ - HashNode *node; /* The hash-table node of the requested symbol */ -/* - * Check arguments. - */ - if(!hash) - return NULL; -/* - * Nothing to lookup? - */ - if(!name) - return NULL; -/* - * Hash the name to a hash-table bucket. - */ - bucket = _find_HashBucket(hash, name); -/* - * Find the bucket entry that exactly matches the name. - */ - node = _find_HashNode(hash, bucket, name, NULL); - if(!node) - return NULL; - return &node->symbol; -} - -/*....................................................................... - * Private function used to allocate a hash-table node. - * The caller is responsible for checking that the specified symbol - * is unique and for installing the returned entry in the table. - * - * Input: - * hash HashTable * The table to allocate the node for. - * name const char * The name of the new entry. - * code int A user-supplied context code. - * fn void (*)(void) A user-supplied function pointer. - * data void * A user-supplied data pointer. - * del_fn SYM_DEL_FN(*) An optional 'data' destructor function. - * Output: - * return HashNode * The new node, or NULL on error. - */ -static HashNode *_new_HashNode(HashTable *hash, const char *name, int code, - void (*fn)(void), void *data, SYM_DEL_FN(*del_fn)) -{ - HashNode *node; /* The new node */ -/* - * Allocate the new node from the free list. - */ - node = (HashNode *) _new_FreeListNode(hash->mem->node_memory); - if(!node) - return NULL; -/* - * Before attempting any operation that might fail, initialize the - * contents of 'node' at least up to the point at which it can be - * safely passed to _del_HashNode(). - */ - node->symbol.name = NULL; - node->symbol.code = code; - node->symbol.fn = fn; - node->symbol.data = data; - node->symbol.del_fn = del_fn; - node->next = NULL; -/* - * Allocate a copy of 'name'. - */ - node->symbol.name = _new_StringMemString(hash->mem->string_memory, - strlen(name) + 1); - if(!node->symbol.name) - return _del_HashNode(hash, node); -/* - * If character-case is insignificant in the current table, convert the - * name to lower case while copying it. - */ - if(hash->case_sensitive) { - strcpy(node->symbol.name, name); - } else { - const char *src = name; - char *dst = node->symbol.name; - for( ; *src; src++,dst++) - *dst = tolower(*src); - *dst = '\0'; - }; - return node; -} - -/*....................................................................... - * Private function used to delete a hash-table node. - * The node must have been removed from its list before calling this - * function. - * - * Input: - * hash HashTable * The table for which the node was originally - * allocated. - * node HashNode * The node to be deleted. - * Output: - * return HashNode * The deleted node (always NULL). - */ -static HashNode *_del_HashNode(HashTable *hash, HashNode *node) -{ - if(node) { - node->symbol.name = _del_StringMemString(hash->mem->string_memory, - node->symbol.name); -/* - * Call the user-supplied data-destructor if provided. - */ - if(node->symbol.data && node->symbol.del_fn) - node->symbol.data = node->symbol.del_fn(hash->app_data, - node->symbol.code, - node->symbol.data); -/* - * Return the node to the free-list. - */ - node->next = NULL; - node = (HashNode *) _del_FreeListNode(hash->mem->node_memory, node); - }; - return NULL; -} - -/*....................................................................... - * Private function to locate the hash bucket associated with a given - * name. - * - * This uses a hash-function described in the dragon-book - * ("Compilers - Principles, Techniques and Tools", by Aho, Sethi and - * Ullman; pub. Adison Wesley) page 435. - * - * Input: - * hash HashTable * The table to look up the string in. - * name const char * The name of the symbol to look up. - * Output: - * return HashBucket * The located hash-bucket. - */ -static HashBucket *_find_HashBucket(HashTable *hash, const char *name) -{ - unsigned const char *kp; - unsigned long h = 0L; - if(hash->case_sensitive) { - for(kp=(unsigned const char *) name; *kp; kp++) - h = 65599UL * h + *kp; /* 65599 is a prime close to 2^16 */ - } else { - for(kp=(unsigned const char *) name; *kp; kp++) - h = 65599UL * h + tolower((int)*kp); /* 65599 is a prime close to 2^16 */ - }; - return hash->bucket + (h % hash->size); -} - -/*....................................................................... - * Search for a given name in the entries of a given bucket. - * - * Input: - * hash HashTable * The hash-table being searched. - * bucket HashBucket * The bucket to search (use _find_HashBucket()). - * name const char * The name to search for. - * Output: - * prev HashNode ** If prev!=NULL then the pointer to the node - * preceding the located node in the list will - * be recorded in *prev. This will be NULL either - * if the name is not found or the located node is - * at the head of the list of entries. - * return HashNode * The located hash-table node, or NULL if not - * found. - */ -static HashNode *_find_HashNode(HashTable *hash, HashBucket *bucket, - const char *name, HashNode **prev) -{ - HashNode *last; /* The previously searched node */ - HashNode *node; /* The node that is being searched */ -/* - * Search the list for a node containing the specified name. - */ - for(last=NULL, node=bucket->head; - node && hash->keycmp(node->symbol.name, name)!=0; - last = node, node=node->next) - ; - if(prev) - *prev = node ? last : NULL; - return node; -} - -/*....................................................................... - * When hash->case_sensitive is zero this function is called - * in place of strcmp(). In such cases the hash-table names are stored - * as lower-case versions of the original strings so this function - * performs the comparison against lower-case copies of the characters - * of the string being compared. - * - * Input: - * node_key const char * The lower-case hash-node key being compared - * against. - * look_key const char * The lookup key. - * Output: - * return int <0 if node_key < look_key. - * 0 if node_key == look_key. - * >0 if node_key > look_key. - */ -static int _ht_lower_strcmp(const char *node_key, const char *look_key) -{ - int cn; /* The latest character from node_key[] */ - int cl; /* The latest character from look_key[] */ - do { - cn = *node_key++; - cl = *look_key++; - } while(cn && cn==tolower(cl)); - return cn - tolower(cl); -} - -/*....................................................................... - * This is a wrapper around strcmp for comparing hash-keys in a case - * sensitive manner. The reason for having this wrapper, instead of using - * strcmp() directly, is to make some C++ compilers happy. The problem - * is that when the library is compiled with a C++ compiler, the - * declaration of the comparison function is a C++ declaration, whereas - * strcmp() is a pure C function and thus although it appears to have the - * same declaration, the compiler disagrees. - * - * Input: - * node_key char * The lower-case hash-node key being compared against. - * look_key char * The lookup key. - * Output: - * return int <0 if node_key < look_key. - * 0 if node_key == look_key. - * >0 if node_key > look_key. - */ -static int _ht_strcmp(const char *node_key, const char *look_key) -{ - return strcmp(node_key, look_key); -} - -/*....................................................................... - * Empty a hash-table by deleting all of its entries. - * - * Input: - * hash HashTable * The hash table to clear. - * Output: - * return int 0 - OK. - * 1 - Invalid arguments. - */ -int _clear_HashTable(HashTable *hash) -{ - int i; -/* - * Check the arguments. - */ - if(!hash) - return 1; -/* - * Clear the contents of the bucket array. - */ - for(i=0; i<hash->size; i++) { - HashBucket *bucket = hash->bucket + i; -/* - * Delete the list of active hash nodes from the bucket. - */ - HashNode *node = bucket->head; - while(node) { - HashNode *next = node->next; - (void) _del_HashNode(hash, node); - node = next; - }; -/* - * Mark the bucket as empty. - */ - bucket->head = NULL; - bucket->count = 0; - }; - return 0; -} - -/*....................................................................... - * Execute a given function on each entry of a hash table, returning - * before completion if the the specified function returns non-zero. - * - * Input: - * hash HashTable * The table to traverse. - * scan_fn HASH_SCAN_FN(*) The function to call. - * context void * Optional caller-specific context data - * to be passed to scan_fn(). - * Output: - * return int 0 - OK. - * 1 - Either the arguments were invalid, or - * scan_fn() returned non-zero at some - * point. - */ -int _scan_HashTable(HashTable *hash, HASH_SCAN_FN(*scan_fn), void *context) -{ - int i; -/* - * Check the arguments. - */ - if(!hash || !scan_fn) - return 1; -/* - * Iterate through the buckets of the table. - */ - for(i=0; i<hash->size; i++) { - HashBucket *bucket = hash->bucket + i; - HashNode *node; -/* - * Iterate through the list of symbols that fall into bucket i, - * passing each one to the caller-specified function. - */ - for(node=bucket->head; node; node=node->next) { - if(scan_fn(&node->symbol, context)) - return 1; - }; - }; - return 0; -} diff --git a/libtecla-1.4.1/hash.h b/libtecla-1.4.1/hash.h deleted file mode 100644 index 13c0a2b..0000000 --- a/libtecla-1.4.1/hash.h +++ /dev/null @@ -1,157 +0,0 @@ -#ifndef hash_h -#define hash_h - -/* - * Copyright (c) 2000, 2001 by Martin C. Shepherd. - * - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL - * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - */ - -/* - * The following macro can be used to prototype or define a - * function that deletes the data of a symbol-table entry. - * - * Input: - * app_data void * The _new_HashTable() app_data argument. - * code int The Symbol::code argument. - * sym_data void * The Symbol::data argument to be deleted. - * Output: - * return void * The deleted data (always return NULL). - */ -#define SYM_DEL_FN(fn) void *(fn)(void *app_data, int code, void *sym_data) - -/* - * The following macro can be used to prototype or define a - * function that deletes the application-data of a hash-table. - * - * Input: - * data void * The _new_HashTable() 'app_data' argument to be - * deleted. - * Output: - * return void * The deleted data (always return NULL). - */ -#define HASH_DEL_FN(fn) void *(fn)(void *app_data) - -/* - * The following is a container for recording the context - * of a symbol in a manner that is independant of the particular - * symbol-table implementation. Each hash-table entry contains - * the following user supplied parameters: - * - * 1. An optional integral parameter 'code'. This is useful for - * enumerating a symbol or for describing what type of data - * or function is stored in the symbol. - * - * 2. An optional generic function pointer. This is useful for - * associating functions with names. The user is responsible - * for casting between the generic function type and the - * actual function type. The code field could be used to - * enumerate what type of function to cast to. - * - * 3. An optional generic pointer to a static or heap-allocated - * object. It is up to the user to cast this back to the - * appropriate object type. Again, the code field could be used - * to describe what type of object is stored there. - * If the object is dynamically allocated and should be discarded - * when the symbol is deleted from the symbol table, send a - * destructor function to have it deleted automatically. - */ -typedef struct { - char *name; /* The name of the symbol */ - int code; /* Application supplied integral code */ - void (*fn)(void); /* Application supplied generic function */ - void *data; /* Application supplied context data */ - SYM_DEL_FN(*del_fn); /* Data destructor function */ -} Symbol; - -/* - * HashNode's and HashTable's are small objects. Separately allocating - * many such objects would normally cause memory fragmentation. To - * counter this, HashMemory objects are used. These contain - * dedicated free-lists formed from large dynamically allocated arrays - * of objects. One HashMemory object can be shared between multiple hash - * tables (within a single thread). - */ -typedef struct HashMemory HashMemory; - - /* Create a free-list for allocation of hash tables and their nodes */ - -HashMemory *_new_HashMemory(int hash_count, int node_count); - - /* Delete a redundant free-list if not being used */ - -HashMemory *_del_HashMemory(HashMemory *mem, int force); - -/* - * Declare an alias for the private HashTable structure defined in - * hash.c. - */ -typedef struct HashTable HashTable; - -/* - * Enumerate case-sensitivity options. - */ -typedef enum { - IGNORE_CASE, /* Ignore case when looking up symbols */ - HONOUR_CASE /* Honor case when looking up symbols */ -} HashCase; - - /* Create a new hash-table */ - -HashTable *_new_HashTable(HashMemory *mem, int size, HashCase hcase, - void *app_data, HASH_DEL_FN(*del_fn)); - - /* Delete a reference to a hash-table */ - -HashTable *_del_HashTable(HashTable *hash); - - /* Add an entry to a hash table */ - -Symbol *_new_HashSymbol(HashTable *hash, const char *key, int code, - void (*fn)(void), void *data, SYM_DEL_FN(*del_fn)); - - /* Remove and delete all the entries in a given hash table */ - -int _clear_HashTable(HashTable *hash); - - /* Remove and delete a given hash-table entry */ - -Symbol *_del_HashSymbol(HashTable *hash, const char *key); - - /* Lookup a given hash-table entry */ - -Symbol *_find_HashSymbol(HashTable *hash, const char *key); - - /* Execute a given function on each entry of a hash table, returning */ - /* before completion if the specified function returns non-zero. */ - -#define HASH_SCAN_FN(fn) int (fn)(Symbol *sym, void *context) - -int _scan_HashTable(HashTable *hash, HASH_SCAN_FN(*scan_fn), void *context); - -#endif diff --git a/libtecla-1.4.1/history.c b/libtecla-1.4.1/history.c deleted file mode 100644 index 5a8d94f..0000000 --- a/libtecla-1.4.1/history.c +++ /dev/null @@ -1,2003 +0,0 @@ -/* - * Copyright (c) 2000, 2001 by Martin C. Shepherd. - * - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL - * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <ctype.h> -#include <time.h> -#include <errno.h> - -#include "history.h" -#include "freelist.h" - -/* - * GlLineNode's record the location and length of historical lines in - * a buffer array. - */ -typedef struct GlLineNode GlLineNode; -struct GlLineNode { - long id; /* The unique identifier of this history line */ - time_t timestamp; /* The time at which the line was archived */ - unsigned group; /* The identifier of the history group to which the */ - /* the line belongs. */ - GlLineNode *next; /* The next youngest line in the list */ - GlLineNode *prev; /* The next oldest line in the list */ - int start; /* The start index of the line in the buffer */ - int nchar; /* The total length of the line, including the '\0' */ -}; - -/* - * The number of GlLineNode elements per freelist block. - */ -#define LINE_NODE_BLK 100 - -/* - * Lines are organised in the buffer from oldest to newest. The - * positions of the lines are recorded in a doubly linked list - * of GlLineNode objects. - */ -typedef struct { - FreeList *node_mem; /* A freelist of GlLineNode objects */ - GlLineNode *head; /* The head of the list of lines */ - GlLineNode *tail; /* The tail of the list of lines */ -} GlLineList; - -/* - * All elements of the history mechanism are recorded in an object of - * the following type. - */ -struct GlHistory { - char *buffer; /* A circular buffer used to record historical input */ - /* lines. */ - size_t buflen; /* The length of the buffer array */ - GlLineList list; /* A list of the start of lines in buffer[] */ - GlLineNode *recall; /* The last line recalled, or NULL if no recall */ - /* session is currently active. */ - GlLineNode *id_node;/* The node at which the last ID search terminated */ - const char *prefix; /* A pointer to the line containing the prefix that */ - /* is being searched for. */ - int prefix_len; /* The length of the prefix */ - unsigned long seq; /* The next ID to assign to a line node */ - unsigned group; /* The identifier of the current history group */ - int nline; /* The number of lines currently in the history list */ - int max_lines; /* Either -1 or a ceiling on the number of lines */ - int enable; /* If false, ignore history additions and lookups */ -}; - -static char *_glh_restore_line(GlHistory *glh, char *line, size_t dim); -static int _glh_cant_load_history(GlHistory *glh, const char *filename, - int lineno, const char *message, FILE *fp); -static int _glh_write_timestamp(FILE *fp, time_t timestamp); -static int _glh_decode_timestamp(char *string, char **endp, time_t *t); -static void _glh_discard_node(GlHistory *glh, GlLineNode *node); -static GlLineNode *_glh_find_id(GlHistory *glh, GlhLineID id); - -/*....................................................................... - * Create a line history maintenance object. - * - * Input: - * buflen size_t The number of bytes to allocate to the circular - * buffer that is used to record all of the - * most recent lines of user input that will fit. - * If buflen==0, no buffer will be allocated. - * Output: - * return GlHistory * The new object, or NULL on error. - */ -GlHistory *_new_GlHistory(size_t buflen) -{ - GlHistory *glh; /* The object to be returned */ -/* - * Allocate the container. - */ - glh = (GlHistory *) malloc(sizeof(GlHistory)); - if(!glh) { - fprintf(stderr, "_new_GlHistory: Insufficient memory.\n"); - return NULL; - }; -/* - * Before attempting any operation that might fail, initialize the - * container at least up to the point at which it can safely be passed - * to _del_GlHistory(). - */ - glh->buffer = NULL; - glh->buflen = buflen; - glh->list.node_mem = NULL; - glh->list.head = NULL; - glh->list.tail = NULL; - glh->recall = NULL; - glh->id_node = NULL; - glh->prefix = NULL; - glh->prefix_len = 0; - glh->seq = 0; - glh->group = 0; - glh->nline = 0; - glh->max_lines = -1; - glh->enable = 1; -/* - * Allocate the buffer, if required. - */ - if(buflen > 0) { - glh->buffer = (char *) malloc(sizeof(char) * buflen); - if(!glh->buffer) { - fprintf(stderr, "_new_GlHistory: Insufficient memory.\n"); - return _del_GlHistory(glh); - }; - }; -/* - * Allocate the GlLineNode freelist. - */ - glh->list.node_mem = _new_FreeList("_new_GlHistory", sizeof(GlLineNode), - LINE_NODE_BLK); - if(!glh->list.node_mem) - return _del_GlHistory(glh); - return glh; -} - -/*....................................................................... - * Delete a GlHistory object. - * - * Input: - * glh GlHistory * The object to be deleted. - * Output: - * return GlHistory * The deleted object (always NULL). - */ -GlHistory *_del_GlHistory(GlHistory *glh) -{ - if(glh) { -/* - * Delete the buffer. - */ - if(glh->buffer) { - free(glh->buffer); - glh->buffer = NULL; - }; -/* - * Delete the freelist of GlLineNode's. - */ - glh->list.node_mem = _del_FreeList("_del_GlHistory", glh->list.node_mem, 1); -/* - * The contents of the list were deleted by deleting the freelist. - */ - glh->list.head = NULL; - glh->list.tail = NULL; -/* - * Delete the container. - */ - free(glh); - }; - return NULL; -} - -/*....................................................................... - * Add a new line to the end of the history buffer, wrapping round to the - * start of the buffer if needed. - * - * Input: - * glh GlHistory * The input-line history maintenance object. - * line char * The line to be archived. - * force int Unless this flag is non-zero, empty lines and - * lines which match the previous line in the history - * buffer, aren't archived. This flag requests that - * the line be archived regardless. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int _glh_add_history(GlHistory *glh, const char *line, int force) -{ - GlLineList *list; /* The line location list */ - int nchar; /* The number of characters needed to record the line */ - GlLineNode *node; /* The new line location list node */ - int empty; /* True if the string is empty */ - const char *nlptr;/* A pointer to a newline character in line[] */ - int i; -/* - * Check the arguments. - */ - if(!glh || !line) - return 1; -/* - * Is history enabled? - */ - if(!glh->enable || !glh->buffer || glh->max_lines == 0) - return 0; -/* - * Get the line location list. - */ - list = &glh->list; -/* - * Cancel any ongoing search. - */ - if(_glh_cancel_search(glh)) - return 1; -/* - * See how much buffer space will be needed to record the line? - * - * If the string contains a terminating newline character, arrange to - * have the archived line NUL terminated at this point. - */ - nlptr = strchr(line, '\n'); - if(nlptr) - nchar = (nlptr - line) + 1; - else - nchar = strlen(line) + 1; -/* - * If the line is too big to fit in the buffer, truncate it. - */ - if(nchar > glh->buflen) - nchar = glh->buflen; -/* - * Is the line empty? - */ - empty = 1; - for(i=0; i<nchar-1 && empty; i++) - empty = isspace((int)(unsigned char) line[i]); -/* - * If the line is empty, don't add it to the buffer unless explicitly - * told to. - */ - if(empty && !force) - return 0; -/* - * If the new line is the same as the most recently added line, - * don't add it again, unless explicitly told to. - */ - if(!force && - list->tail && strlen(glh->buffer + list->tail->start) == nchar-1 && - strncmp(line, glh->buffer + list->tail->start, nchar-1)==0) - return 0; -/* - * Allocate the list node that will record the line location. - */ - node = (GlLineNode *) _new_FreeListNode(list->node_mem); - if(!node) - return 1; -/* - * Is the buffer empty? - */ - if(!list->head) { -/* - * Place the line at the beginning of the buffer. - */ - strncpy(glh->buffer, line, nchar); - glh->buffer[nchar-1] = '\0'; -/* - * Record the location of the line. - */ - node->start = 0; -/* - * The buffer has one or more lines in it. - */ - } else { -/* - * Place the start of the new line just after the most recently - * added line. - */ - int start = list->tail->start + list->tail->nchar; -/* - * If there is insufficient room between the end of the most - * recently added line and the end of the buffer, we place the - * line at the beginning of the buffer. To make as much space - * as possible for this line, we first delete any old lines - * at the end of the buffer, then shift the remaining contents - * of the buffer to the end of the buffer. - */ - if(start + nchar >= glh->buflen) { - GlLineNode *last; /* The last line in the buffer */ - GlLineNode *ln; /* A member of the list of line locations */ - int shift; /* The shift needed to move the contents of the */ - /* buffer to its end. */ -/* - * Delete any old lines between the most recent line and the end of the - * buffer. - */ - while(list->head && list->head->start > list->tail->start) - _glh_discard_node(glh, list->head); -/* - * Find the line that is nearest the end of the buffer. - */ - last = NULL; - for(ln=list->head; ln; ln=ln->next) { - if(!last || ln->start > last->start) - last = ln; - }; -/* - * How big a shift is needed to move the existing contents of the - * buffer to the end of the buffer? - */ - shift = last ? (glh->buflen - (last->start + last->nchar)) : 0; -/* - * Is any shift needed? - */ - if(shift > 0) { -/* - * Move the buffer contents to the end of the buffer. - */ - memmove(glh->buffer + shift, glh->buffer, glh->buflen - shift); -/* - * Update the listed locations to reflect the shift. - */ - for(ln=list->head; ln; ln=ln->next) - ln->start += shift; - }; -/* - * The new line should now be located at the start of the buffer. - */ - start = 0; - }; -/* - * Make space for the new line at the beginning of the buffer by - * deleting the oldest lines. This just involves removing them - * from the list of used locations. Also enforce the current - * maximum number of lines. - */ - while(list->head && - ((list->head->start >= start && list->head->start - start < nchar) || - (glh->max_lines >= 0 && glh->nline>=glh->max_lines))) { - _glh_discard_node(glh, list->head); - }; -/* - * Copy the new line into the buffer. - */ - memcpy(glh->buffer + start, line, nchar); - glh->buffer[start + nchar - 1] = '\0'; -/* - * Record its location. - */ - node->start = start; - }; -/* - * Append the line location node to the end of the list. - */ - node->id = glh->seq++; - node->timestamp = time(NULL); - node->group = glh->group; - node->nchar = nchar; - node->next = NULL; - node->prev = list->tail; - if(list->tail) - list->tail->next = node; - else - list->head = node; - list->tail = node; - glh->nline++; - return 0; -} - -/*....................................................................... - * Recall the next oldest line that has the search prefix last recorded - * by _glh_search_prefix(). - * - * Input: - * glh GlHistory * The input-line history maintenance object. - * line char * The input line buffer. On input this should contain - * the current input line, and on output, if anything - * was found, its contents will have been replaced - * with the matching line. - * dim size_t The allocated dimensions of the line buffer. - * Output: - * return char * A pointer to line[0], or NULL if not found. - */ -char *_glh_find_backwards(GlHistory *glh, char *line, size_t dim) -{ - GlLineNode *node; /* The line location node being checked */ - int first; /* True if this is the start of a new search */ -/* - * Check the arguments. - */ - if(!glh || !line) { - fprintf(stderr, "_glh_find_backwards: NULL argument(s).\n"); - return NULL; - }; -/* - * Is history enabled? - */ - if(!glh->enable || !glh->buffer || glh->max_lines == 0) - return NULL; -/* - * Check the line dimensions. - */ - if(dim < strlen(line) + 1) { - fprintf(stderr, - "_glh_find_backwards: 'dim' inconsistent with strlen(line) contents.\n"); - return NULL; - }; -/* - * Is this the start of a new search? - */ - first = glh->recall==NULL; -/* - * If this is the first search backwards, save the current line - * for potential recall later, and mark it as the last line - * recalled. - */ - if(first) { - if(_glh_add_history(glh, line, 1)) - return NULL; - glh->recall = glh->list.tail; - }; -/* - * If there is no search prefix, the prefix last set by glh_search_prefix() - * doesn't exist in the history buffer. - */ - if(!glh->prefix) - return NULL; -/* - * From where should we start the search? - */ - if(glh->recall) - node = glh->recall->prev; - else - node = glh->list.tail; -/* - * Search backwards through the list for the first match with the - * prefix string. - */ - for( ; node && - (node->group != glh->group || - strncmp(glh->buffer + node->start, glh->prefix, glh->prefix_len) != 0); - node = node->prev) - ; -/* - * Was a matching line found? - */ - if(node) { -/* - * Recall the found node as the starting point for subsequent - * searches. - */ - glh->recall = node; -/* - * Copy the matching line into the provided line buffer. - */ - strncpy(line, glh->buffer + node->start, dim); - line[dim-1] = '\0'; - return line; - }; -/* - * No match was found. - */ - return NULL; -} - -/*....................................................................... - * Recall the next newest line that has the search prefix last recorded - * by _glh_search_prefix(). - * - * Input: - * glh GlHistory * The input-line history maintenance object. - * line char * The input line buffer. On input this should contain - * the current input line, and on output, if anything - * was found, its contents will have been replaced - * with the matching line. - * dim size_t The allocated dimensions of the line buffer. - * Output: - * return char * The line requested, or NULL if no matching line - * was found. - */ -char *_glh_find_forwards(GlHistory *glh, char *line, size_t dim) -{ - GlLineNode *node; /* The line location node being checked */ -/* - * Check the arguments. - */ - if(!glh || !line) { - fprintf(stderr, "_glh_find_forwards: NULL argument(s).\n"); - return NULL; - }; -/* - * Is history enabled? - */ - if(!glh->enable || !glh->buffer || glh->max_lines == 0) - return NULL; -/* - * Check the line dimensions. - */ - if(dim < strlen(line) + 1) { - fprintf(stderr, - "_glh_find_forwards: 'dim' inconsistent with strlen(line) contents.\n"); - return NULL; - }; -/* - * From where should we start the search? - */ - if(glh->recall) - node = glh->recall->next; - else - return NULL; -/* - * If there is no search prefix, the prefix last set by glh_search_prefix() - * doesn't exist in the history buffer. - */ - if(!glh->prefix) - return NULL; -/* - * Search forwards through the list for the first match with the - * prefix string. - */ - for( ; node && - (node->group != glh->group || - strncmp(glh->buffer + node->start, glh->prefix, glh->prefix_len) != 0); - node = node->next) - ; -/* - * Was a matching line found? - */ - if(node) { -/* - * Did we hit the line that was originally being edited when the - * current history traversal started? - */ - if(node == glh->list.tail) - return _glh_restore_line(glh, line, dim); -/* - * Copy the matching line into the provided line buffer. - */ - strncpy(line, glh->buffer + node->start, dim); - line[dim-1] = '\0'; -/* - * Record the starting point of the next search. - */ - glh->recall = node; -/* - * Return the matching line to the user. - */ - return line; - }; -/* - * No match was found. - */ - return NULL; -} - -/*....................................................................... - * If a search is in progress, cancel it. - * - * This involves discarding the line that was temporarily saved by - * _glh_find_backwards() when the search was originally started, - * and reseting the search iteration pointer to NULL. - * - * Input: - * glh GlHistory * The input-line history maintenance object. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int _glh_cancel_search(GlHistory *glh) -{ -/* - * Check the arguments. - */ - if(!glh) { - fprintf(stderr, "_glh_cancel_search: NULL argument(s).\n"); - return 1; - }; -/* - * If there wasn't a search in progress, do nothing. - */ - if(!glh->recall) - return 0; -/* - * Delete the node of the preserved line. - */ - _glh_discard_node(glh, glh->list.tail); -/* - * Reset the search pointers. - */ - glh->recall = NULL; - glh->prefix = ""; - glh->prefix_len = 0; - return 0; -} - -/*....................................................................... - * Set the prefix of subsequent history searches. - * - * Input: - * glh GlHistory * The input-line history maintenance object. - * line char * The command line who's prefix is to be used. - * prefix_len int The length of the prefix. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int _glh_search_prefix(GlHistory *glh, const char *line, int prefix_len) -{ - GlLineNode *node; /* The line location node being checked */ -/* - * Check the arguments. - */ - if(!glh) { - fprintf(stderr, "_glh_search_prefix: NULL argument(s).\n"); - return 1; - }; -/* - * Is history enabled? - */ - if(!glh->enable || !glh->buffer || glh->max_lines == 0) - return 0; -/* - * Record a zero length search prefix? - */ - if(prefix_len <= 0) { - glh->prefix_len = 0; - glh->prefix = ""; - return 0; - }; -/* - * Record the length of the new search prefix. - */ - glh->prefix_len = prefix_len; -/* - * If any history line starts with the specified prefix, record a - * pointer to it for comparison in subsequent searches. If the prefix - * doesn't match any of the lines, then simply record NULL to indicate - * that there is no point in searching. Note that _glh_add_history() - * clears this pointer by calling _glh_cancel_search(), so there is - * no danger of it being used after the buffer has been modified. - */ - for(node = glh->list.tail ; node && - (node->group != glh->group || - strncmp(glh->buffer + node->start, line, prefix_len) != 0); - node = node->prev) - ; -/* - * If a matching line was found record it for use as the search - * prefix. - */ - glh->prefix = node ? glh->buffer + node->start : NULL; - return 0; -} - -/*....................................................................... - * Recall the oldest recorded line. - * - * Input: - * glh GlHistory * The input-line history maintenance object. - * line char * The input line buffer. On input this should contain - * the current input line, and on output, its contents - * will have been replaced with the oldest line. - * dim size_t The allocated dimensions of the line buffer. - * Output: - * return char * A pointer to line[0], or NULL if not found. - */ -char *_glh_oldest_line(GlHistory *glh, char *line, size_t dim) -{ - GlLineNode *node; /* The line location node being checked */ - int first; /* True if this is the start of a new search */ -/* - * Check the arguments. - */ - if(!glh || !line) { - fprintf(stderr, "_glh_oldest_line: NULL argument(s).\n"); - return NULL; - }; -/* - * Is history enabled? - */ - if(!glh->enable || !glh->buffer || glh->max_lines == 0) - return NULL; -/* - * Check the line dimensions. - */ - if(dim < strlen(line) + 1) { - fprintf(stderr, - "_glh_oldest_line: 'dim' inconsistent with strlen(line) contents.\n"); - return NULL; - }; -/* - * Is this the start of a new search? - */ - first = glh->recall==NULL; -/* - * If this is the first search backwards, save the current line - * for potential recall later, and mark it as the last line - * recalled. - */ - if(first) { - if(_glh_add_history(glh, line, 1)) - return NULL; - glh->recall = glh->list.tail; - }; -/* - * Locate the oldest line that belongs to the current group. - */ - for(node=glh->list.head; node && node->group != glh->group; - node = node->next) - ; -/* - * No line found? - */ - if(!node) - return NULL; -/* - * Record the above node as the starting point for subsequent - * searches. - */ - glh->recall = node; -/* - * Copy the recalled line into the provided line buffer. - */ - strncpy(line, glh->buffer + node->start, dim); - line[dim-1] = '\0'; - return line; -} - -/*....................................................................... - * Recall the line that was being entered when the search started. - * - * Input: - * glh GlHistory * The input-line history maintenance object. - * line char * The input line buffer. On input this should contain - * the current input line, and on output, its contents - * will have been replaced with the line that was - * being entered when the search was started. - * dim size_t The allocated dimensions of the line buffer. - * Output: - * return char * A pointer to line[0], or NULL if not found. - */ -char *_glh_current_line(GlHistory *glh, char *line, size_t dim) -{ -/* - * Check the arguments. - */ - if(!glh || !line) { - fprintf(stderr, "_glh_current_line: NULL argument(s).\n"); - return NULL; - }; -/* - * Is history enabled? - */ - if(!glh->enable || !glh->buffer || glh->max_lines == 0) - return NULL; -/* - * Check the line dimensions. - */ - if(dim < strlen(line) + 1) { - fprintf(stderr, - "_glh_current_line: 'dim' inconsistent with strlen(line) contents.\n"); - return NULL; - }; -/* - * Restore the original line. - */ - return _glh_restore_line(glh, line, dim); -} - -/*....................................................................... - * Remove the line that was originally being edited when the history - * traversal was started, from its saved position in the history list, - * and place it in the provided line buffer. - * - * Input: - * glh GlHistory * The input-line history maintenance object. - * line char * The input line buffer. On input this should contain - * the current input line, and on output, its contents - * will have been replaced with the saved line. - * dim size_t The allocated dimensions of the line buffer. - * Output: - * return char * A pointer to line[0], or NULL if not found. - */ -static char *_glh_restore_line(GlHistory *glh, char *line, size_t dim) -{ - GlLineNode *tail; /* The tail node to be discarded */ -/* - * If there wasn't a search in progress, do nothing. - */ - if(!glh->recall) - return NULL; -/* - * Get the list node that is to be removed. - */ - tail = glh->list.tail; -/* - * If a pointer to the saved line is being used to record the - * current search prefix, reestablish the search prefix, to - * have it recorded by another history line if possible. - */ - if(glh->prefix == glh->buffer + tail->start) - (void) _glh_search_prefix(glh, glh->buffer + tail->start, glh->prefix_len); -/* - * Copy the recalled line into the input-line buffer. - */ - strncpy(line, glh->buffer + tail->start, dim); - line[dim-1] = '\0'; -/* - * Discard the line-location node. - */ - _glh_discard_node(glh, tail); -/* - * Mark the search as ended. - */ - glh->recall = NULL; - return line; -} - -/*....................................................................... - * Query the id of a history line offset by a given number of lines from - * the one that is currently being recalled. If a recall session isn't - * in progress, or the offset points outside the history list, 0 is - * returned. - * - * Input: - * glh GlHistory * The input-line history maintenance object. - * offset int The line offset (0 for the current line, < 0 - * for an older line, > 0 for a newer line. - * Output: - * return GlhLineID The identifier of the line that is currently - * being recalled, or 0 if no recall session is - * currently in progress. - */ -GlhLineID _glh_line_id(GlHistory *glh, int offset) -{ - GlLineNode *node; /* The line location node being checked */ -/* - * Is history enabled? - */ - if(!glh->enable || !glh->buffer || glh->max_lines == 0) - return 0; -/* - * Search forward 'offset' lines to find the required line. - */ - if(offset >= 0) { - for(node=glh->recall; node && offset != 0; node=node->next) { - if(node->group == glh->group) - offset--; - }; - } else { - for(node=glh->recall; node && offset != 0; node=node->prev) { - if(node->group == glh->group) - offset++; - }; - }; - return node ? node->id : 0; -} - -/*....................................................................... - * Recall a line by its history buffer ID. If the line is no longer - * in the buffer, or the id is zero, NULL is returned. - * - * Input: - * glh GlHistory * The input-line history maintenance object. - * id GlhLineID The ID of the line to be returned. - * line char * The input line buffer. On input this should contain - * the current input line, and on output, its contents - * will have been replaced with the saved line. - * dim size_t The allocated dimensions of the line buffer. - * Output: - * return char * A pointer to line[0], or NULL if not found. - */ -char *_glh_recall_line(GlHistory *glh, GlhLineID id, char *line, size_t dim) -{ - GlLineNode *node; /* The line location node being checked */ -/* - * Is history enabled? - */ - if(!glh->enable || !glh->buffer || glh->max_lines == 0) - return NULL; -/* - * If we are starting a new recall session, save the current line - * for potential recall later. - */ - if(!glh->recall && _glh_add_history(glh, line, 1)) - return NULL; -/* - * Search for the specified line. - */ - node = _glh_find_id(glh, id); -/* - * Not found? - */ - if(!node || node->group != glh->group) - return NULL; -/* - * Record the node of the matching line as the starting point - * for subsequent searches. - */ - glh->recall = node; -/* - * Copy the recalled line into the provided line buffer. - */ - strncpy(line, glh->buffer + node->start, dim); - line[dim-1] = '\0'; - return line; -} - -/*....................................................................... - * Save the current history in a specified file. - * - * Input: - * glh GlHistory * The input-line history maintenance object. - * filename const char * The name of the new file to record the - * history in. - * comment const char * Extra information such as timestamps will - * be recorded on a line started with this - * string, the idea being that the file can - * double as a command file. Specify "" if - * you don't care. - * max_lines int The maximum number of lines to save, or -1 - * to save all of the lines in the history - * list. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int _glh_save_history(GlHistory *glh, const char *filename, const char *comment, - int max_lines) -{ - FILE *fp; /* The output file */ - GlLineNode *node; /* The line being saved */ - GlLineNode *head; /* The head of the list of lines to be saved */ -/* - * Check the arguments. - */ - if(!glh || !filename || !comment) { - fprintf(stderr, "_glh_save_history: NULL argument(s).\n"); - return 1; - }; -/* - * Attempt to open the specified file. - */ - fp = fopen(filename, "w"); - if(!fp) { - fprintf(stderr, "_glh_save_history: Can't open %s (%s).\n", - filename, strerror(errno)); - return 1; - }; -/* - * If a ceiling on the number of lines to save was specified, count - * that number of lines backwards, to find the first line to be saved. - */ - head = NULL; - if(max_lines >= 0) { - for(head=glh->list.tail; head && --max_lines > 0; head=head->prev) - ; - }; - if(!head) - head = glh->list.head; -/* - * Write the contents of the history buffer to the history file, writing - * associated data such as timestamps, to a line starting with the - * specified comment string. - */ - for(node=head; node; node=node->next) { -/* - * Write peripheral information associated with the line, as a comment. - */ - if(fprintf(fp, "%s ", comment) < 0 || - _glh_write_timestamp(fp, node->timestamp) || - fprintf(fp, " %u\n", node->group) < 0) { - fprintf(stderr, "Error writing %s (%s).\n", filename, strerror(errno)); - (void) fclose(fp); - return 1; - }; -/* - * Write the history line. - */ - if(fprintf(fp, "%s\n", glh->buffer + node->start) < 0) { - fprintf(stderr, "Error writing %s (%s).\n", filename, strerror(errno)); - (void) fclose(fp); - return 1; - }; - }; -/* - * Close the history file. - */ - if(fclose(fp) == EOF) { - fprintf(stderr, "Error writing %s (%s).\n", filename, strerror(errno)); - return 1; - }; - return 0; -} - -/*....................................................................... - * Restore previous history lines from a given file. - * - * Input: - * glh GlHistory * The input-line history maintenance object. - * filename const char * The name of the file to read from. - * comment const char * The same comment string that was passed to - * _glh_save_history() when this file was - * written. - * line char * A buffer into which lines can be read. - * dim size_t The allocated dimension of line[]. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int _glh_load_history(GlHistory *glh, const char *filename, const char *comment, - char *line, size_t dim) -{ - FILE *fp; /* The output file */ - size_t comment_len; /* The length of the comment string */ - time_t timestamp; /* The timestamp of the history line */ - unsigned group; /* The identifier of the history group to which */ - /* the line belongs. */ - int lineno; /* The line number being read */ -/* - * Check the arguments. - */ - if(!glh || !filename || !comment || !line) { - fprintf(stderr, "_glh_load_history: NULL argument(s).\n"); - return 1; - }; -/* - * Measure the length of the comment string. - */ - comment_len = strlen(comment); -/* - * Clear the history list. - */ - _glh_clear_history(glh, 1); -/* - * Attempt to open the specified file. Don't treat it as an error - * if the file doesn't exist. - */ - fp = fopen(filename, "r"); - if(!fp) - return 0; -/* - * Attempt to read each line and preceding peripheral info, and add these - * to the history list. - */ - for(lineno=1; fgets(line, dim, fp) != NULL; lineno++) { - char *lptr; /* A pointer into the input line */ -/* - * Check that the line starts with the comment string. - */ - if(strncmp(line, comment, comment_len) != 0) { - return _glh_cant_load_history(glh, filename, lineno, - "Corrupt history parameter line", fp); - }; -/* - * Skip spaces and tabs after the comment. - */ - for(lptr=line+comment_len; *lptr && (*lptr==' ' || *lptr=='\t'); lptr++) - ; -/* - * The next word must be a timestamp. - */ - if(_glh_decode_timestamp(lptr, &lptr, ×tamp)) { - return _glh_cant_load_history(glh, filename, lineno, - "Corrupt timestamp", fp); - }; -/* - * Skip spaces and tabs. - */ - while(*lptr==' ' || *lptr=='\t') - lptr++; -/* - * The next word must be an unsigned integer group number. - */ - group = (int) strtoul(lptr, &lptr, 10); - if(*lptr != ' ' && *lptr != '\n') { - return _glh_cant_load_history(glh, filename, lineno, - "Corrupt group id", fp); - }; -/* - * Skip spaces and tabs. - */ - while(*lptr==' ' || *lptr=='\t') - lptr++; -/* - * There shouldn't be anything left on the line. - */ - if(*lptr != '\n') { - return _glh_cant_load_history(glh, filename, lineno, - "Corrupt parameter line", fp); - }; -/* - * Now read the history line itself. - */ - lineno++; - if(fgets(line, dim, fp) == NULL) - return _glh_cant_load_history(glh, filename, lineno, "Read error", fp); -/* - * Append the line to the history buffer. - */ - if(_glh_add_history(glh, line, 1)) { - return _glh_cant_load_history(glh, filename, lineno, - "Insufficient memory to record line", fp); - }; -/* - * Record the group and timestamp information along with the line. - */ - if(glh->list.tail) { - glh->list.tail->timestamp = timestamp; - glh->list.tail->group = group; - }; - }; -/* - * Close the file. - */ - (void) fclose(fp); - return 0; -} - -/*....................................................................... - * This is a private error return function of _glh_load_history(). - */ -static int _glh_cant_load_history(GlHistory *glh, const char *filename, - int lineno, const char *message, FILE *fp) -{ - fprintf(stderr, "%s:%d: %s.\n", filename, lineno, message); - (void) fclose(fp); - return 1; -} - -/*....................................................................... - * Switch history groups. - * - * Input: - * glh GlHistory * The input-line history maintenance object. - * group unsigned The new group identifier. This will be recorded - * with subsequent history lines, and subsequent - * history searches will only return lines with - * this group identifier. This allows multiple - * separate history lists to exist within - * a single GlHistory object. Note that the - * default group identifier is 0. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int _glh_set_group(GlHistory *glh, unsigned group) -{ -/* - * Check the arguments. - */ - if(!glh) { - fprintf(stderr, "_glh_set_group: NULL argument(s).\n"); - return 1; - }; -/* - * Is the group being changed? - */ - if(group != glh->group) { -/* - * Cancel any ongoing search. - */ - if(_glh_cancel_search(glh)) - return 1; -/* - * Record the new group. - */ - glh->group = group; - }; - return 0; -} - -/*....................................................................... - * Query the current history group. - * - * Input: - * glh GlHistory * The input-line history maintenance object. - * Output: - * return unsigned The group identifier. - */ -int _glh_get_group(GlHistory *glh) -{ - return glh ? glh->group : 0; -} - -/*....................................................................... - * Write a timestamp to a given stdio stream, in the format - * yyyymmddhhmmss - * - * Input: - * fp FILE * The stream to write to. - * timestamp time_t The timestamp to be written. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int _glh_write_timestamp(FILE *fp, time_t timestamp) -{ - struct tm *t; /* THe broken-down calendar time */ -/* - * Get the calendar components corresponding to the given timestamp. - */ - if(timestamp < 0 || (t = localtime(×tamp)) == NULL) { - if(fprintf(fp, "?") < 0) - return 1; - return 0; - }; -/* - * Write the calendar time as yyyymmddhhmmss. - */ - if(fprintf(fp, "%04d%02d%02d%02d%02d%02d", t->tm_year + 1900, t->tm_mon + 1, - t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec) < 0) - return 1; - return 0; -} - -/*....................................................................... - * Read a timestamp from a string. - * - * Input: - * string char * The string to read from. - * Input/Output: - * endp char ** On output *endp will point to the next unprocessed - * character in string[]. - * timestamp time_t * The timestamp will be assigned to *t. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int _glh_decode_timestamp(char *string, char **endp, time_t *timestamp) -{ - unsigned year,month,day,hour,min,sec; /* Calendar time components */ - struct tm t; -/* - * There are 14 characters in the date format yyyymmddhhmmss. - */ - enum {TSLEN=14}; - char timestr[TSLEN+1]; /* The timestamp part of the string */ -/* - * If the time wasn't available at the time that the line was recorded - * it will have been written as "?". Check for this before trying - * to read the timestamp. - */ - if(string[0] == '\?') { - *endp = string+1; - *timestamp = -1; - return 0; - }; -/* - * The timestamp is expected to be written in the form yyyymmddhhmmss. - */ - if(strlen(string) < TSLEN) { - *endp = string; - return 1; - }; -/* - * Copy the timestamp out of the string. - */ - strncpy(timestr, string, TSLEN); - timestr[TSLEN] = '\0'; -/* - * Decode the timestamp. - */ - if(sscanf(timestr, "%4u%2u%2u%2u%2u%2u", &year, &month, &day, &hour, &min, - &sec) != 6) { - *endp = string; - return 1; - }; -/* - * Advance the string pointer over the successfully read timestamp. - */ - *endp = string + TSLEN; -/* - * Copy the read values into a struct tm. - */ - t.tm_sec = sec; - t.tm_min = min; - t.tm_hour = hour; - t.tm_mday = day; - t.tm_wday = 0; - t.tm_yday = 0; - t.tm_mon = month - 1; - t.tm_year = year - 1900; - t.tm_isdst = -1; -/* - * Convert the contents of the struct tm to a time_t. - */ - *timestamp = mktime(&t); - return 0; -} - -/*....................................................................... - * Display the contents of the history list. - * - * Input: - * glh GlHistory * The input-line history maintenance object. - * fp FILE * The stdio stream to write to. - * fmt const char * A format string. This can contain arbitrary - * characters, which are written verbatim, plus - * any of the following format directives: - * %D - The date, like 2001-11-20 - * %T - The time of day, like 23:59:59 - * %N - The sequential entry number of the - * line in the history buffer. - * %G - The history group number of the line. - * %% - A literal % character. - * %H - The history line. - * all_groups int If true, display history lines from all - * history groups. Otherwise only display - * those of the current history group. - * max_lines int If max_lines is < 0, all available lines - * are displayed. Otherwise only the most - * recent max_lines lines will be displayed. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int _glh_show_history(GlHistory *glh, FILE *fp, const char *fmt, - int all_groups, int max_lines) -{ - GlLineNode *node; /* The line being displayed */ - GlLineNode *oldest; /* The oldest line to display */ - enum {TSMAX=32}; /* The maximum length of the date and time string */ - char buffer[TSMAX+1]; /* The buffer in which to write the date and time */ - int idlen; /* The length of displayed ID strings */ - unsigned grpmax; /* The maximum group number in the buffer */ - int grplen; /* The number of characters needed to print grpmax */ -/* - * Check the arguments. - */ - if(!glh || !fp || !fmt) { - fprintf(stderr, "_glh_show_history: NULL argument(s).\n"); - return 1; - }; -/* - * Is history enabled? - */ - if(!glh->enable || !glh->list.head) - return 0; -/* - * Work out the length to display ID numbers, choosing the length of - * the biggest number in the buffer. Smaller numbers will be padded - * with leading zeroes if needed. - */ - sprintf(buffer, "%lu", (unsigned long) glh->list.tail->id); - idlen = strlen(buffer); -/* - * Find the largest group number. - */ - grpmax = 0; - for(node=glh->list.head; node; node=node->next) { - if(node->group > grpmax) - grpmax = node->group; - }; -/* - * Find out how many characters are needed to display the group number. - */ - sprintf(buffer, "%u", (unsigned) grpmax); - grplen = strlen(buffer); -/* - * Find the node that follows the oldest line to be displayed. - */ - if(max_lines < 0) { - oldest = glh->list.head; - } else if(max_lines==0) { - return 0; - } else { - for(oldest=glh->list.tail; oldest; oldest=oldest->prev) { - if((all_groups || oldest->group == glh->group) && --max_lines <= 0) - break; - }; -/* - * If the number of lines in the buffer doesn't exceed the specified - * maximum, start from the oldest line in the buffer. - */ - if(!oldest) - oldest = glh->list.head; - }; -/* - * List the history lines in increasing time order. - */ - for(node=oldest; node; node=node->next) { -/* - * Only display lines from the current history group, unless - * told otherwise. - */ - if(all_groups || node->group == glh->group) { - const char *fptr; /* A pointer into the format string */ - struct tm *t = NULL; /* The broken time version of the timestamp */ -/* - * Work out the calendar representation of the node timestamp. - */ - if(node->timestamp != (time_t) -1) - t = localtime(&node->timestamp); -/* - * Parse the format string. - */ - fptr = fmt; - while(*fptr) { -/* - * Search for the start of the next format directive or the end of the string. - */ - const char *start = fptr; - while(*fptr && *fptr != '%') - fptr++; -/* - * Display any literal characters that precede the located directive. - */ - if(fptr > start && fprintf(fp, "%.*s", (int) (fptr - start), start) < 0) - return 1; -/* - * Did we hit a new directive before the end of the line? - */ - if(*fptr) { -/* - * Obey the directive. Ignore unknown directives. - */ - switch(*++fptr) { - case 'D': /* Display the date */ - if(t && strftime(buffer, TSMAX, "%Y-%m-%d", t) != 0 && - fprintf(fp, "%s", buffer) < 0) - return 1; - break; - case 'T': /* Display the time of day */ - if(t && strftime(buffer, TSMAX, "%H:%M:%S", t) != 0 && - fprintf(fp, "%s", buffer) < 0) - return 1; - break; - case 'N': /* Display the sequential entry number */ - if(fprintf(fp, "%*lu", idlen, (unsigned long) node->id) < 0) - return 1; - break; - case 'G': - if(fprintf(fp, "%*u", grplen, (unsigned) node->group) < 0) - return 1; - break; - case 'H': /* Display the history line */ - if(fprintf(fp, "%s", glh->buffer + node->start) < 0) - return 1; - break; - case '%': /* A literal % symbol */ - if(fputc('%', fp) == EOF) - return 1; - break; - }; -/* - * Skip the directive. - */ - if(*fptr) - fptr++; - }; - }; - }; - }; - return 0; -} - -/*....................................................................... - * Change the size of the history buffer. - * - * Input: - * glh GlHistory * The input-line history maintenance object. - * bufsize size_t The number of bytes in the history buffer, or 0 - * to delete the buffer completely. - * Output: - * return int 0 - OK. - * 1 - Insufficient memory (the previous buffer - * will have been retained). No error message - * will be displayed. - */ -int _glh_resize_history(GlHistory *glh, size_t bufsize) -{ - GlLineNode *node; /* A line location node in the list of lines */ - GlLineNode *prev; /* The line location node preceding 'node' */ -/* - * Check the arguments. - */ - if(!glh) - return bufsize > 0; -/* - * If the new size doesn't differ from the existing size, do nothing. - */ - if(glh->buflen == bufsize) - return 0; -/* - * Cancel any ongoing search. - */ - (void) _glh_cancel_search(glh); -/* - * Create a wholly new buffer? - */ - if(glh->buflen == 0) { - glh->buffer = (char *) malloc(bufsize); - if(!glh->buffer) - return 1; - glh->buflen = bufsize; -/* - * Delete an existing buffer? - */ - } else if(bufsize == 0) { - _glh_clear_history(glh, 1); - free(glh->buffer); - glh->buffer = NULL; - glh->buflen = 0; -/* - * To get here, we must be shrinking or expanding from one - * finite size to another. - */ - } else { -/* - * If we are shrinking the size of the buffer, then we first need - * to discard the oldest lines that won't fit in the new buffer. - */ - if(bufsize < glh->buflen) { - size_t nbytes = 0; /* The number of bytes used in the new buffer */ - GlLineNode *oldest; /* The oldest node to be kept */ -/* - * Searching backwards from the youngest line, find the oldest - * line for which there will be sufficient room in the new buffer. - */ - for(oldest = glh->list.tail; - oldest && (nbytes += oldest->nchar) <= bufsize; - oldest = oldest->prev) - ; -/* - * We will have gone one node too far, unless we reached the oldest line - * without exceeding the target length. - */ - if(oldest) { - nbytes -= oldest->nchar; - oldest = oldest->next; - }; -/* - * Discard the nodes that can't be retained. - */ - while(glh->list.head && glh->list.head != oldest) - _glh_discard_node(glh, glh->list.head); -/* - * If we are increasing the size of the buffer, we need to reallocate - * the buffer before shifting the lines into their new positions. - */ - } else { - char *new_buffer = (char *) realloc(glh->buffer, bufsize); - if(!new_buffer) - return 1; - glh->buffer = new_buffer; - glh->buflen = bufsize; - }; -/* - * If there are any lines to be preserved, copy the block of lines - * that precedes the end of the existing buffer to what will be - * the end of the new buffer. - */ - if(glh->list.head) { - int shift; /* The number of bytes to shift lines in the buffer */ -/* - * Get the oldest line to be kept. - */ - GlLineNode *oldest = glh->list.head; -/* - * Count the number of characters that are used in the lines that - * precede the end of the current buffer (ie. not including those - * lines that have been wrapped to the start of the buffer). - */ - int n = 0; - for(node=oldest,prev=oldest->prev; node && node->start >= oldest->start; - prev=node, node=node->next) - n += node->nchar; -/* - * Move these bytes to the end of the resized buffer. - */ - memmove(glh->buffer + bufsize - n, glh->buffer + oldest->start, n); -/* - * Adjust the buffer pointers to reflect the new locations of the moved - * lines. - */ - shift = bufsize - n - oldest->start; - for(node=prev; node && node->start >= oldest->start; node=node->prev) - node->start += shift; - }; -/* - * Shrink the buffer? - */ - if(bufsize < glh->buflen) { - char *new_buffer = (char *) realloc(glh->buffer, bufsize); - if(new_buffer) - glh->buffer = new_buffer; - glh->buflen = bufsize; /* Mark it as shrunk, regardless of success */ - }; - }; - return 0; -} - -/*....................................................................... - * Set an upper limit to the number of lines that can be recorded in the - * history list, or remove a previously specified limit. - * - * Input: - * glh GlHistory * The input-line history maintenance object. - * max_lines int The maximum number of lines to allow, or -1 to - * cancel a previous limit and allow as many lines - * as will fit in the current history buffer size. - */ -void _glh_limit_history(GlHistory *glh, int max_lines) -{ - if(!glh) - return; -/* - * Apply a new limit? - */ - if(max_lines >= 0 && max_lines != glh->max_lines) { -/* - * Count successively older lines until we reach the start of the - * list, or until we have seen max_lines lines (at which point 'node' - * will be line number max_lines+1). - */ - int nline = 0; - GlLineNode *node; - for(node=glh->list.tail; node && ++nline <= max_lines; node=node->prev) - ; -/* - * Discard any lines that exceed the limit. - */ - if(node) { - GlLineNode *oldest = node->next; /* The oldest line to be kept */ -/* - * Delete nodes from the head of the list until we reach the node that - * is to be kept. - */ - while(glh->list.head && glh->list.head != oldest) - _glh_discard_node(glh, glh->list.head); - }; - }; -/* - * Record the new limit. - */ - glh->max_lines = max_lines; - return; -} - -/*....................................................................... - * Discard either all history, or the history associated with the current - * history group. - * - * Input: - * glh GlHistory * The input-line history maintenance object. - * all_groups int If true, clear all of the history. If false, - * clear only the stored lines associated with the - * currently selected history group. - */ -void _glh_clear_history(GlHistory *glh, int all_groups) -{ -/* - * Check the arguments. - */ - if(!glh) - return; -/* - * Cancel any ongoing search. - */ - (void) _glh_cancel_search(glh); -/* - * Delete all history lines regardless of group? - */ - if(all_groups) { - _rst_FreeList(glh->list.node_mem); - glh->list.head = glh->list.tail = NULL; - glh->nline = 0; - glh->id_node = NULL; -/* - * Just delete lines of the current group? - */ - } else { - GlLineNode *node; /* The line node being checked */ - GlLineNode *prev; /* The line node that precedes 'node' */ - GlLineNode *next; /* The line node that follows 'node' */ -/* - * Search out and delete the line nodes of the current group. - */ - for(node=glh->list.head; node; node=next) { -/* - * Keep a record of the following node before we delete the current - * node. - */ - next = node->next; -/* - * Discard this node? - */ - if(node->group == glh->group) - _glh_discard_node(glh, node); - }; -/* - * If there are any lines left, and we deleted any lines, there will - * be gaps in the buffer. These need to be removed. - */ - if(glh->list.head) { - int epos; /* The index of the last used element in the buffer */ -/* - * Find the line nearest the end of the buffer. - */ - GlLineNode *enode; - for(node=glh->list.head, prev=NULL; - node && node->start >= glh->list.head->start; - prev=node, node = node->next) - ; - enode = prev; -/* - * Move the end line to abutt the end of the buffer, and remove gaps - * between the lines that precede it. - */ - epos = glh->buflen; - for(node=enode; node; node=node->prev) { - int shift = epos - (node->start + node->nchar); - if(shift) { - memmove(glh->buffer + node->start + shift, - glh->buffer + node->start, node->nchar); - node->start += shift; - }; - epos = node->start; - }; -/* - * Move the first line in the buffer to the start of the buffer, and - * remove gaps between the lines that follow it. - */ - epos = 0; - for(node=enode ? enode->next : NULL; node; node=node->next) { - int shift = epos - node->start; - if(shift) { - memmove(glh->buffer + node->start + shift, - glh->buffer + node->start, node->nchar); - node->start += shift; - }; - epos = node->start + node->nchar; - }; - }; - }; - return; -} - -/*....................................................................... - * Temporarily enable or disable the history list. - * - * Input: - * glh GlHistory * The input-line history maintenance object. - * enable int If true, turn on the history mechanism. If - * false, disable it. - */ -void _glh_toggle_history(GlHistory *glh, int enable) -{ - if(glh) - glh->enable = enable; -} - -/*....................................................................... - * Remove a given line location node from the history list, and return - * it to the freelist. - * - * Input: - * glh GlHistory * The input-line history maintenance object. - * node GlLineNode * The node to be removed. This must be currently - * in the list who's head is glh->list.head, or - * be NULL. - */ -static void _glh_discard_node(GlHistory *glh, GlLineNode *node) -{ - if(node) { -/* - * Make the node that precedes the node being removed point - * to the one that follows it. - */ - if(node->prev) - node->prev->next = node->next; - else - glh->list.head = node->next; -/* - * Make the node that follows the node being removed point - * to the one that precedes it. - */ - if(node->next) - node->next->prev = node->prev; - else - glh->list.tail = node->prev; -/* - * If we are deleting the node that is marked as the start point of the - * last ID search, remove the cached starting point. - */ - if(node == glh->id_node) - glh->id_node = NULL; -/* - * Return the node to the free list. - */ - node = (GlLineNode *) _del_FreeListNode(glh->list.node_mem, node); -/* - * Decrement the count of the number of lines in the buffer. - */ - glh->nline--; - }; -} - -/*....................................................................... - * Lookup the details of a given history line, given its id. - * - * Input: - * glh GlHistory * The input-line history maintenance object. - * id GlLineID The sequential number of the line. - * Input/Output: - * line const char ** A pointer to the history line will be assigned - * to *line. - * group unsigned * The group membership of the line will be assigned - * to *group. - * timestamp time_t * The timestamp of the line will be assigned to - * *timestamp. - * Output: - * return int 0 - The requested line wasn't found. - * 1 - The line was found. - */ -int _glh_lookup_history(GlHistory *glh, GlhLineID id, const char **line, - unsigned *group, time_t *timestamp) -{ - GlLineNode *node; /* The located line location node */ -/* - * Check the arguments. - */ - if(!glh) - return 0; -/* - * Search for the line that has the specified ID. - */ - node = _glh_find_id(glh, (GlhLineID) id); -/* - * Not found? - */ - if(!node) - return 0; -/* - * Return the details of the line. - */ - if(line) - *line = glh->buffer + node->start; - if(group) - *group = node->group; - if(timestamp) - *timestamp = node->timestamp; - return 1; -} - -/*....................................................................... - * Lookup a node in the history list by its ID. - * - * Input: - * glh GlHistory * The input-line history maintenance object. - * id GlhLineID The ID of the line to be returned. - * Output: - * return GlLIneNode * The located node, or NULL if not found. - */ -static GlLineNode *_glh_find_id(GlHistory *glh, GlhLineID id) -{ - GlLineNode *node; /* The node being checked */ -/* - * Is history enabled? - */ - if(!glh->enable || !glh->list.head) - return NULL; -/* - * If possible, start at the end point of the last ID search. - * Otherwise start from the head of the list. - */ - node = glh->id_node; - if(!node) - node = glh->list.head; -/* - * Search forwards from 'node'? - */ - if(node->id < id) { - while(node && node->id != id) - node = node->next; - glh->id_node = node ? node : glh->list.tail; -/* - * Search backwards from 'node'? - */ - } else { - while(node && node->id != id) - node = node->prev; - glh->id_node = node ? node : glh->list.head; - }; -/* - * Return the located node (this will be NULL if the ID wasn't found). - */ - return node; -} - -/*....................................................................... - * Query the state of the history list. Note that any of the input/output - * pointers can be specified as NULL. - * - * Input: - * glh GlHistory * The input-line history maintenance object. - * Input/Output: - * enabled int * If history is enabled, *enabled will be - * set to 1. Otherwise it will be assigned 0. - * group unsigned * The current history group ID will be assigned - * to *group. - * max_lines int * The currently requested limit on the number - * of history lines in the list, or -1 if - * unlimited. - */ -void _glh_state_of_history(GlHistory *glh, int *enabled, unsigned *group, - int *max_lines) -{ - if(glh) { - if(enabled) - *enabled = glh->enable; - if(group) - *group = glh->group; - if(max_lines) - *max_lines = glh->max_lines; - }; -} - -/*....................................................................... - * Get the range of lines in the history buffer. - * - * Input: - * glh GlHistory * The input-line history maintenance object. - * Input/Output: - * oldest unsigned long * The sequential entry number of the oldest - * line in the history list will be assigned - * to *oldest, unless there are no lines, in - * which case 0 will be assigned. - * newest unsigned long * The sequential entry number of the newest - * line in the history list will be assigned - * to *newest, unless there are no lines, in - * which case 0 will be assigned. - * nlines int * The number of lines currently in the history - * list. - */ -void _glh_range_of_history(GlHistory *glh, unsigned long *oldest, - unsigned long *newest, int *nlines) -{ - if(glh) { - if(oldest) - *oldest = glh->list.head ? glh->list.head->id : 0; - if(newest) - *newest = glh->list.tail ? glh->list.tail->id : 0; - if(nlines) - *nlines = glh->nline; - }; -} - -/*....................................................................... - * Return the size of the history buffer and the amount of the - * buffer that is currently in use. - * - * Input: - * glh GlHistory * The input-line history maintenance object. - * Input/Output: - * buff_size size_t * The size of the history buffer (bytes). - * buff_used size_t * The amount of the history buffer that - * is currently occupied (bytes). - */ -void _glh_size_of_history(GlHistory *glh, size_t *buff_size, size_t *buff_used) -{ - if(glh) { - if(buff_size) - *buff_size = glh->buflen; -/* - * Determine the amount of buffer space that is currently occupied. - */ - if(buff_used) { - size_t used = 0; - GlLineNode *node; - for(node=glh->list.head; node; node=node->next) - used += node->nchar; - *buff_used = used; - }; - }; -} diff --git a/libtecla-1.4.1/history.h b/libtecla-1.4.1/history.h deleted file mode 100644 index 49671a4..0000000 --- a/libtecla-1.4.1/history.h +++ /dev/null @@ -1,159 +0,0 @@ -#ifndef history_h -#define history_h - -/* - * Copyright (c) 2000, 2001 by Martin C. Shepherd. - * - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL - * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - */ - -#include <stdio.h> /* FILE * */ - -/*----------------------------------------------------------------------- - * This module is used to record and traverse historical lines of user input. - */ - -typedef struct GlHistory GlHistory; - -/* - * Create a new history maintenance object. - */ -GlHistory *_new_GlHistory(size_t buflen); - -/* - * Delete a history maintenance object. - */ -GlHistory *_del_GlHistory(GlHistory *glh); - -int _glh_add_history(GlHistory *glh, const char *line, int force); - -int _glh_search_prefix(GlHistory *glh, const char *line, int prefix_len); - -char *_glh_find_backwards(GlHistory *glh, char *line, size_t dim); -char *_glh_find_forwards(GlHistory *glh, char *line, size_t dim); - -int _glh_cancel_search(GlHistory *glh); - -char *_glh_oldest_line(GlHistory *glh, char *line, size_t dim); -char *_glh_current_line(GlHistory *glh, char *line, size_t dim); - -/* - * Whenever a new line is added to the history buffer, it is given - * a unique ID, recorded in an object of the following type. - */ -typedef unsigned long GlhLineID; - -/* - * Query the id of a history line offset by a given number of lines from - * the one that is currently being recalled. If a recall session isn't - * in progress, or the offset points outside the history list, 0 is - * returned. - */ -GlhLineID _glh_line_id(GlHistory *glh, int offset); - -/* - * Recall a line by its history buffer ID. If the line is no longer - * in the buffer, or the specified id is zero, NULL is returned. - */ -char *_glh_recall_line(GlHistory *glh, GlhLineID id, char *line, size_t dim); - -/* - * Write the contents of the history buffer to a given file. Note that - * ~ and $ expansion are not performed on the filename. - */ -int _glh_save_history(GlHistory *glh, const char *filename, - const char *comment, int max_lines); - -/* - * Restore the contents of the history buffer from a given file. - * Note that ~ and $ expansion are not performed on the filename. - */ -int _glh_load_history(GlHistory *glh, const char *filename, const char *comment, - char *line, size_t dim); - -/* - * Set and query the current history group. - */ -int _glh_set_group(GlHistory *glh, unsigned group); -int _glh_get_group(GlHistory *glh); - -/* - * Display the contents of the history list to the specified stdio - * output group. - */ -int _glh_show_history(GlHistory *glh, FILE *fp, const char *fmt, - int all_groups, int max_lines); - -/* - * Change the size of the history buffer. - */ -int _glh_resize_history(GlHistory *glh, size_t bufsize); - -/* - * Set an upper limit to the number of lines that can be recorded in the - * history list, or remove a previously specified limit. - */ -void _glh_limit_history(GlHistory *glh, int max_lines); - -/* - * Discard either all history, or the history associated with the current - * history group. - */ -void _glh_clear_history(GlHistory *glh, int all_groups); - -/* - * Temporarily enable or disable the history facility. - */ -void _glh_toggle_history(GlHistory *glh, int enable); - -/* - * Lookup a history line by its sequential number of entry in the - * history buffer. - */ -int _glh_lookup_history(GlHistory *glh, GlhLineID id, const char **line, - unsigned *group, time_t *timestamp); - -/* - * Query the state of the history list. - */ -void _glh_state_of_history(GlHistory *glh, int *enabled, unsigned *group, - int *max_lines); - -/* - * Get the range of lines in the history buffer. - */ -void _glh_range_of_history(GlHistory *glh, unsigned long *oldest, - unsigned long *newest, int *nlines); - -/* - * Return the size of the history buffer and the amount of the - * buffer that is currently in use. - */ -void _glh_size_of_history(GlHistory *glh, size_t *buff_size, size_t *buff_used); - -#endif diff --git a/libtecla-1.4.1/homedir.c b/libtecla-1.4.1/homedir.c deleted file mode 100644 index f2029b7..0000000 --- a/libtecla-1.4.1/homedir.c +++ /dev/null @@ -1,399 +0,0 @@ -/* - * Copyright (c) 2000, 2001 by Martin C. Shepherd. - * - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL - * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -#include <unistd.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <pwd.h> - -#include "pathutil.h" -#include "homedir.h" - -/* - * Set the max length of the error-reporting string. There is no point - * in this being longer than the width of a typical terminal window. - * In composing error messages, I have assumed that this number is - * at least 80, so you don't decrease it below this number. - */ -#define ERRLEN 200 - -/* - * Use the reentrant POSIX threads versions of the password lookup functions? - */ -#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199506L -#define THREAD_COMPATIBLE 1 -#endif - -/* - * Provide a password buffer size fallback in case the max size reported - * by sysconf() is said to be indeterminate. - */ -#define DEF_GETPW_R_SIZE_MAX 1024 - -/* - * The resources needed to lookup and record a home directory are - * maintained in objects of the following type. - */ -struct HomeDir { - char errmsg[ERRLEN+1]; /* Error-report buffer */ - char *buffer; /* A buffer for reading password entries and */ - /* directory paths. */ - int buflen; /* The allocated size of buffer[] */ -#ifdef THREAD_COMPATIBLE - struct passwd pwd; /* The password entry of a user */ -#endif -}; - -static const char *hd_getpwd(HomeDir *home); - -/*....................................................................... - * Create a new HomeDir object. - * - * Output: - * return HomeDir * The new object, or NULL on error. - */ -HomeDir *_new_HomeDir(void) -{ - HomeDir *home; /* The object to be returned */ - size_t pathlen; /* The estimated maximum size of a pathname */ -/* - * Allocate the container. - */ - home = (HomeDir *) malloc(sizeof(HomeDir)); - if(!home) { - fprintf(stderr, "_new_HomeDir: Insufficient memory.\n"); - return NULL; - }; -/* - * Before attempting any operation that might fail, initialize the - * container at least up to the point at which it can safely be passed - * to _del_HomeDir(). - */ - home->errmsg[0] = '\0'; - home->buffer = NULL; - home->buflen = 0; -/* - * Allocate the buffer that is used by the reentrant POSIX password-entry - * lookup functions. - */ -#ifdef THREAD_COMPATIBLE -/* - * Get the length of the buffer needed by the reentrant version - * of getpwnam(). - */ -#ifndef _SC_GETPW_R_SIZE_MAX - home->buflen = DEF_GETPW_R_SIZE_MAX; -#else - errno = 0; - home->buflen = sysconf(_SC_GETPW_R_SIZE_MAX); -/* - * If the limit isn't available, substitute a suitably large fallback value. - */ - if(home->buflen < 0 || errno) - home->buflen = DEF_GETPW_R_SIZE_MAX; -#endif -#endif -/* - * If the existing buffer length requirement is too restrictive to record - * a pathname, increase its length. - */ - pathlen = _pu_pathname_dim(); - if(pathlen > home->buflen) - home->buflen = pathlen; -/* - * Allocate a work buffer. - */ - home->buffer = (char *) malloc(home->buflen); - if(!home->buffer) { - fprintf(stderr, "_new_HomeDir: Insufficient memory."); - return _del_HomeDir(home); - }; - return home; -} - -/*....................................................................... - * Delete a HomeDir object. - * - * Input: - * home HomeDir * The object to be deleted. - * Output: - * return HomeDir * The deleted object (always NULL). - */ -HomeDir *_del_HomeDir(HomeDir *home) -{ - if(home) { - if(home->buffer) - free(home->buffer); - free(home); - }; - return NULL; -} - -/*....................................................................... - * Lookup the home directory of a given user in the password file. - * - * Input: - * home HomeDir * The resources needed to lookup the home directory. - * user const char * The name of the user to lookup, or "" to lookup - * the home directory of the person running the - * program. - * Output: - * return const char * The home directory. If the library was compiled - * with threads, this string is part of the HomeDir - * object and will change on subsequent calls. If - * the library wasn't compiled to be reentrant, - * then the string is a pointer into a static string - * in the C library and will change not only on - * subsequent calls to this function, but also if - * any calls are made to the C library password - * file lookup functions. Thus to be safe, you should - * make a copy of this string before calling any - * other function that might do a password file - * lookup. - * - * On error, NULL is returned and a description - * of the error can be acquired by calling - * _hd_last_home_dir_error(). - */ -const char *_hd_lookup_home_dir(HomeDir *home, const char *user) -{ - const char *home_dir; /* A pointer to the home directory of the user */ -/* - * If no username has been specified, arrange to lookup the current - * user. - */ - int login_user = !user || *user=='\0'; -/* - * Check the arguments. - */ - if(!home) { - fprintf(stderr, "_hd_lookup_home_dir: NULL argument(s).\n"); - return NULL; - }; -/* - * Handle the ksh "~+". This expands to the absolute path of the - * current working directory. - */ - if (!login_user && strcmp(user, "+") == 0) { - home_dir = hd_getpwd(home); - if(!home_dir) { - strncpy(home->errmsg, "Cannot determine current directory.", ERRLEN); - home->errmsg[ERRLEN] = '\0'; - return NULL; - } - return home_dir; - }; -/* - * Look up the password entry of the user. - * First the POSIX threads version - this is painful! - */ -#ifdef THREAD_COMPATIBLE - { - struct passwd *ret; /* The returned pointer to pwd */ - int status; /* The return value of getpwnam_r() */ -/* - * Look up the password entry of the specified user. - */ - if(login_user) - status = getpwuid_r(geteuid(), &home->pwd, home->buffer, home->buflen, - &ret); - else - status = getpwnam_r(user, &home->pwd, home->buffer, home->buflen, &ret); - if(status || !ret) { - const char *fmt = "User '%.*s' doesn't exist."; - sprintf(home->errmsg, fmt, ERRLEN - strlen(fmt), user); - return NULL; - }; -/* - * Get a pointer to the string that holds the home directory. - */ - home_dir = home->pwd.pw_dir; - }; -/* - * Now the classic unix version. - */ -#else - { - struct passwd *pwd = login_user ? getpwuid(geteuid()) : getpwnam(user); - if(!pwd) { - const char *fmt = "User '%.*s' doesn't exist."; - sprintf(home->errmsg, fmt, ERRLEN - strlen(fmt), user); - return NULL; - }; -/* - * Get a pointer to the home directory. - */ - home_dir = pwd->pw_dir; - }; -#endif - return home_dir; -} - -/*....................................................................... - * Return a description of the last error that caused _hd_lookup_home_dir() - * to return NULL. - * - * Input: - * home HomeDir * The resources needed to record the home directory. - * Output: - * return char * The description of the last error. - */ -const char *_hd_last_home_dir_error(HomeDir *home) -{ - return home ? home->errmsg : "NULL HomeDir argument"; -} - -/*....................................................................... - * The _hd_scan_user_home_dirs() function calls a user-provided function - * for each username known by the system, passing the function both - * the name and the home directory of the user. - * - * Input: - * home HomeDir * The resource object for reading home - * directories. - * data void * Anonymous data to be passed to the - * callback function. - * callback_fn HOME_DIR_FN(*) The function to call for each user. - * Output: - * return int 0 - Successful completion. - * 1 - An error occurred. A description - * of the error can be obtained by - * calling _hd_last_home_dir_error(). - */ -int _hd_scan_user_home_dirs(HomeDir *home, void *data, HOME_DIR_FN(*callback_fn)) -{ - int waserr = 0; /* True after errors */ -/* - * Check the arguments. - */ - if(!home || !callback_fn) { - if(home) - strcpy(home->errmsg, - "_hd_scan_user_home_dirs: Missing callback function"); - return 1; - }; -/* - * There are no reentrant versions of getpwent() etc for scanning - * the password file, so disable username completion when the - * library is compiled to be reentrant. - */ -#if !defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 199506L - { - struct passwd *pwd; /* The pointer to the latest password entry */ -/* - * Open the password file. - */ - setpwent(); -/* - * Read the contents of the password file, looking for usernames - * that start with the specified prefix, and adding them to the - * list of matches. - */ - while((pwd = getpwent()) != NULL && !waserr) - waserr = callback_fn(data, pwd->pw_name, pwd->pw_dir, home->errmsg, - ERRLEN); -/* - * Close the password file. - */ - endpwent(); - }; -#endif -/* - * Under ksh ~+ stands for the absolute pathname of the current working - * directory. - */ - if (!waserr) { - const char *pwd = hd_getpwd(home); - if(pwd) { - waserr = callback_fn(data, "+", pwd, home->errmsg, ERRLEN); - } else { - waserr = 1; - strncpy(home->errmsg, "Cannot determine current directory.", ERRLEN); - home->errmsg[ERRLEN] = '\0'; - }; - }; - return waserr; -} - -/*....................................................................... - * Return the value of getenv("PWD") if this points to the current - * directory, or the return value of getcwd() otherwise. The reason for - * prefering PWD over getcwd() is that the former preserves the history - * of symbolic links that have been traversed to reach the current - * directory. This function is designed to provide the equivalent - * expansion of the ksh ~+ directive, which normally returns its value - * of PWD. - * - * Input: - * home HomeDir * The resource object for reading home directories. - * Output: - * return const char * A pointer to either home->buffer, where the - * pathname is recorded, the string returned by - * getenv("PWD"), or NULL on error. - */ -static const char *hd_getpwd(HomeDir *home) -{ -/* - * Get the absolute path of the current working directory. - */ - char *cwd = getcwd(home->buffer, home->buflen); -/* - * Some shells set PWD with the path of the current working directory. - * This will differ from cwd in that it won't have had symbolic links - * expanded. - */ - const char *pwd = getenv("PWD"); -/* - * If PWD was set, and it points to the same directory as cwd, return - * its value. Note that it won't be the same if the current shell or - * the current program has changed directories, after inheriting PWD - * from a parent shell. - */ - struct stat cwdstat, pwdstat; - if(pwd && cwd && stat(cwd, &cwdstat)==0 && stat(pwd, &pwdstat)==0 && - cwdstat.st_dev == pwdstat.st_dev && cwdstat.st_ino == pwdstat.st_ino) - return pwd; -/* - * Also return pwd if getcwd() failed, since it represents the best - * information that we have access to. - */ - if(!cwd) - return pwd; -/* - * In the absence of a valid PWD, return cwd. - */ - return cwd; -} diff --git a/libtecla-1.4.1/homedir.h b/libtecla-1.4.1/homedir.h deleted file mode 100644 index 5607802..0000000 --- a/libtecla-1.4.1/homedir.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef homedir_h -#define homedir_h - -/* - * Copyright (c) 2000, 2001 by Martin C. Shepherd. - * - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL - * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - */ - -typedef struct HomeDir HomeDir; - -/* - * The following constructor and destructor functions create and - * delete the resources needed to look up home directories. - */ -HomeDir *_new_HomeDir(void); -HomeDir *_del_HomeDir(HomeDir *home); - -/* - * Return the home directory of a specified user, or NULL if unknown. - */ -const char *_hd_lookup_home_dir(HomeDir *home, const char *user); - -/* - * Get the description of the that occured when _hd_lookup_home_dir() was - * last called. - */ -const char *_hd_last_home_dir_error(HomeDir *home); - -/* - * The _hd_scan_user_home_dirs() function calls a user-provided function - * for each username known by the system, passing the function both - * the name and the home directory of the user. - * - * The following macro can be used to declare both pointers and - * prototypes for the callback functions. The 'data' argument is - * a copy of the 'data' argument passed to _hd_scan_user_home_dirs() - * and is intended for the user of _hd_scan_user_home_dirs() to use - * to pass anonymous context data to the callback function. - * The username and home directories are passed to the callback function - * in the *usrnam and *homedir arguments respectively. - * To abort the scan, and have _hd_scan_user_home_dirs() return 1, the - * callback function can return 1. A description of up to maxerr - * characters before the terminating '\0', can be written to errmsg[]. - * This can then be examined by calling _hd_last_home_dir_error(). - * To indicate success and continue the scan, the callback function - * should return 0. _hd_scan_user_home_dirs() returns 0 on successful - * completion of the scan, or 1 if an error occurred or a call to the - * callback function returned 1. - */ -#define HOME_DIR_FN(fn) int (fn)(void *data, const char *usrnam, const char *homedir, char *errmsg, int maxerr) - -int _hd_scan_user_home_dirs(HomeDir *home, void *data, - HOME_DIR_FN(*callback_fn)); - -#endif diff --git a/libtecla-1.4.1/html/changes.html b/libtecla-1.4.1/html/changes.html deleted file mode 100644 index b309a7b..0000000 --- a/libtecla-1.4.1/html/changes.html +++ /dev/null @@ -1,1495 +0,0 @@ -<HEAD><TITLE>The tecla library change log</TITLE></HEAD> -<BODY bgcolor=add8e6><PRE> -In the following log, modification dates are listed using the European -convention in which the day comes before the month (ie. DD/MM/YYYY). -The most recent modifications are listed first. - -25/05/2002 mcs@astro.caltech.edu (based on suggestions by Paul Smith) - pathutil.c - Apparently, under QNX pathconf("/",_PC_PATH_MAX) returns - EINVAL. At Paul's suggestion I have modified the code to - silently substitute the existing MAX_PATHLEN_FALLBACK - value if pathconf() returns an error of any kind. - homedir.c - Under QNX, sysconf(_SC_GETPW_R_SIZE_MAX) also apparently - returns EINVAL, so as with pathconf() I modified the code - to substitute a fallback default, rather than - complaining and failing. - enhance.c - Paul told me that the inclusion of sys/termios.h was - causing compilation of enhance.c to fail under QNX. This - line is a bug. The correct thing to do is include - termios.h without a sub-directory prefix, as I was - already doing futher up in the file, so I have just - removed the errant include line. - -12/02/2002 mcs@astro.caltech.edu - getline.c configure.in configure - Mac OS X doesn't have a term.h or termcap.h, but it does - define prototypes for tputs() and setupterm(), so the - default prototypes that I was including if no headers - where available, upset it. I've removed these prototypes. - I also now conditionally include whichever is found of - curses.h and ncurses/curses.h for both termcap and - terminfo (before I wasn't including curses.h when - termcap was selected). - -12/02/2002 mcs@astro.caltech.edu - Updated version number to 1.4.1, ready for a micro - release. - -12/02/2002 mcs@astro.caltech.edu - html/index.html - Added Mac OS X and Cygwin to the list of systems that - can compile libtecla. - -12/02/2002 mcs@astro.caltech.edu - getline.c - Under Mac OS X, the tputs() callback function returns - void, instead of the int return value used by other - systems. This declaration is now used if both __MACH__ - and __APPLE__ are defined. Hopefully these are the - correct system macros to check. Thanks for Stephan - Fiedler for providing information on Mac OS X. - -11/02/2002 mcs@astro.caltech.edu - configure.in configure getline.c - Some systems don't have term.h, and others have it hidden - in an ncurses sub-directory of the standard system include - directory. If term.h can't be found, simply don't include - it. If it is in an ncurses sub-directory, include - ncurses/term.h instead of term.h. - -04/02/2002 mcs@astro.caltech.edu - configure.in configure Makefile.in Makefile.rules - Use ranlib on systems that need it (Mac OS X). Also, - make all components of the installation directories where - needed, instead of assuming that they exist. - -04/02/2002 mcs@astro.caltech.edu - getline.c - When the tab completion binding was unbound from the tab - key, hitting the tab key caused gl_get_line() to ring the - bell instead of inserting a tab character. This is - problematic when using the 'enhance' program with - Jython, since tabs are important in Python. I have - corrected this. - -10/12/2001 Version 1.4.0 released. - -10/12/2001 mcs@astro.caltech.edu - getline.c - If the TIOCGWINSZ ioctl doesn't work, as is the case when - running in an emacs shell, leave the size unchanged, rather - than returning a fatal error. - -07/12/2001 mcs@astro.caltech.edu - configure.in configure - Now that the configure version of CFLAGS is included in - the makefile, I noticed that the optimization flags -g - and -O2 had been added. It turns out that if CFLAGS isn't - already set, the autoconf AC_PROG_CC macro initializes it - with these two optimization flags. Since this would break - backwards compatibility in embedded distributions that - already use the OPT= makefile argument, and because - turning debugging on needlessly bloats the library, I now - make sure that CFLAGS is set before calling this macro. - -07/12/2001 mcs@astro.caltech.edu - enhance.c - Use argv[0] in error reports instead of using a - hardcoded macro. - -07/12/2001 mcs@astro.caltech.edu - getline.c - The cut buffer wasn't being cleared after being - used as a work buffer by gl_load_history(). - -06/12/2001 mcs@astro.caltech.edu - configure.in configure - I removed my now redundant definition of SUN_TPUTS from - CFLAGS. I also added "-I/usr/include" to CFLAGS under - Solaris to prevent gcc from seeing conflicting versions - of system header files in /usr/local/include. - -06/12/2001 Markus Gyger (logged here by mcs) - Lots of files. - Lots of corrections to misspellings and typos in the - comments. - getline.c - Markus reverted a supposed fix that I added a day or two - ago. I had incorrectly thought that in Solaris 8, Sun had - finally brought their declaration of the callback - function of tputs() into line with other systems, but it - turned out that gcc was pulling in a GNU version of - term.h from /usr/local/include, and this was what - confused me. - -05/12/2001 mcs@astro.caltech.edu - Makefile.in - I added @CFLAGS@ to the CFLAGS assignment, so that - if CFLAGS is set as an environment variable when - configure is run, the corresponding make variable - includes its values in the output makefile. - -05/12/2001 mcs@astro.caltech.edu - getline.c libtecla.h libtecla.map man3/gl_get_line.3 - man3/gl_last_signal.3 - I added a function that programs can use to find out - which signal caused gl_get_line() to return EINTR. - -05/12/2001 mcs@astro.caltech.edu - getline.c - When the newline action was triggered by a printable - character, it failed to display that character. It now - does. Also, extra control codes that I had added, to - clear to the end of the display after the carriage return, - but before displaying the prompt, were confusing expect - scripts, so I have removed them. This step is now done - instead in gl_redisplay() after displaying the full input - line. - -05/12/2001 mcs@astro.caltech.edu - getline.c man3/gl_get_line.3 - A user convinced me that continuing to invoke meta - keybindings for meta characters that are printable is a - bad idea, as is allowing users to ask to have setlocale() - called behind the application's back. I have thus changed - this. The setlocale configuration option has gone, and - gl_get_line() is now completely 8-bit clean, by default. - This means that if a meta character is printable, it is - treated as a literal character, rather than a potential - M-c binding. Meta bindings can still be invoked via - their Esc-c equivalents, and indeed most terminal - emulators either output such escape pairs by default when - the meta character is pressed, or can be configured to do - so. I have documented how to configure xterm to do this, - in the man page. - -03/12/2001 mcs@astro.caltech.edu - getline.c man3/gl_get_line.3 - gl_get_line() by default now prints any 8-bit printable - characters that don't match keybindings. Previously - characters > 127 were only printed if preceded by the - literal-next action. Alternatively, by placing the - command literal_if_printable in the tecla configuration - file, all printable characters are treated as literal - characters, even if they are bound to action functions. - - For international users of programs written by - programmers that weren't aware of the need to call - setlocale() to support alternate character sets, the - configuration file can now also contain the single-word - command "setlocale", which tells gl_get_line() to remedy - this. - -27/11/2001 mcs@astro.caltech.edu - demo.c demo2.c enhance man3/gl_get_line.3 - All demos and programs now call setlocale(LC_CTYPE,""). - This makes them support character sets of different - locales, where specified with the LC_CTYPE, LC_ALL, or - LANG environment variables. I also added this to the demo - in the man page, and documented its effect. - -27/11/2001 mcs@astro.caltech.edu - getline.c - When displaying unsigned characters with values over - 127 literally, previously it was assumed that they would - all be displayable. Now isprint() is consulted, and if it - says that a character isn't printable, the character code - is displayed in octal like \307. In non-C locales, some - characters with values > 127 are displayable, and - isprint() tells gl_get_line() which are and which aren't. - -27/11/2001 mcs@astro.caltech.edu - getline.c pathutil.c history.c enhance.c demo2.c - All arguments of the ctype.h character class functions - are now cast to (int)(unsigned char). Previously they - were cast to (int), which doesn't correctly conform to - the requirements of the C standard, and could cause - problems for characters with values > 127 on systems - with signed char's. - -26/11/2001 mcs@astro.caltech.edu - man3/enhance.3 man3/libtecla.3 - I started writing a man page for the enhance program. - -26/11/2001 mcs@astro.caltech.edu - Makefile.in Makefile.rules INSTALL - It is now possible to specify whether the demos and other - programs are to be built, by overriding the default - values of the DEMOS, PROGRAMS and PROGRAMS_R variables. - I have also documented the BINDIR variable and the - install_bin makefile target. - -22/11/2001 mcs@astro.caltech.edu - getline.c libtecla.h libtecla.map man3/gl_get_line.3 - man3/gl_ignore_signal.3 man3/gl_trap_signal.3 - Signal handling has now been modified to be customizable. - Signals that are trapped by default can be removed from - the list of trapped signals, and signals that aren't - currently trapped, can be added to the list. Applications - can also specify the signal and terminal environments in - which an application's signal handler is invoked, and - what gl_get_line() does after the signal handler returns. - -13/11/2001 mcs@astro.caltech.edu - getline.c man3/gl_get_line.3 - Added half-bright, reverse-video and blinking text to the - available prompt formatting options. - getline.c - Removed ^O from the default VT100 sgr0 capability - string. Apparently it can cause problems with some - terminal emulators, and we don't need it, since it turns - off the alternative character set mode, which we don't - use. - getline.c - gl_tigetstr() and gl_tgetstr() didn't guard against the - error returns of tigetstr() and tgetstr() respectively. - They now do. - -11/11/2001 mcs@astro.caltech.edu - getline.c libtecla.h libtecla.map man3/gl_get_line.3 - man3/gl_prompt_style.3 - Although the default remains to display the prompt string - literally, the new gl_prompt_style() function can be used - to enable text attribute formatting directives in prompt - strings, such as underlining, bold font, and highlighting - directives. - -09/11/2001 mcs@astro.caltech.edu - enhance.c Makefile.rules configure.in configure - I added a new program to the distribution that allows one - to run most third party programs with the tecla library - providing command-line editing. - -08/11/2001 mcs@astro.caltech.edu - libtecla.h getline.c man3/gl_get_line.3 history.c history.h - I added a max_lines argument to gl_show_history() and - _glh_show_history(). This can optionally be used to - set a limit on the number of history lines displayed. - libtecla.h getline.c man3/gl_get_line.3 - I added a new function called gl_replace_prompt(). This - can be used by gl_get_line() callback functions to - request that a new prompt be use when they return. - -06/11/2001 mcs@astro.caltech.edu - getline.c man3/gl_get_line.3 - I implemented, bound and documented the list-history - action, used for listing historical lines of the current - history group. - getline.c man3/gl_get_line.3 man3/gl_echo_mode.3 - I wrote functions to specify and query whether subsequent - lines will be visible as they are being typed. - -28/10/2001 mcs@astro.caltech.edu - getline.c man3/gl_get_line.3 - For those cases where a terminal provides its own - high-level terminal editing facilities, you can now - specify an edit-mode argument of 'none'. This disables - all tecla key bindings, and by using canonical terminal - input mode instead of raw input mode, editing is left up - to the terminal driver. - -21/10/2001 mcs@astro.caltech.edu - libtecla.h getline.c history.c history.h - man3/gl_get_line.3 man3/gl_history_info.3 - I added the new gl_state_of_history(), - gl_range_of_history() and gl_size_of_history() - functions for querying information about the - history list. - history.c - While testing the new gl_size_of_history() - function, I noticed that when the history buffer - wrapped, any location nodes of old lines between - the most recent line and the end of the buffer - weren't being removed. This could result in bogus - entries appearing at the start of the history list. - Now fixed. - -20/10/2001 mcs@astro.caltech.edu - - libtecla.h getline.c history.c history.h - man3/gl_get_line.3 man3/gl_lookup_history.3 - I added a function called gl_lookup_history(), that - the application can use to lookup lines in the history - list. - libtecla.h getline.c history.c history.h man3/gl_get_line.3 - gl_show_history() now takes a format string argument - to control how the line is displayed, and with what - information. It also now provides the option of either - displaying all history lines or just those of the - current history group. - getline.c man3/gl_get_line.3 - gl_get_line() only archives lines in the history buffer - if the newline action was invoked by a newline or - carriage return character. - -16/10/2001 mcs@astro.caltech.edu - - history.c history.h getline.c libtecla.h libtecla.map - man3/gl_get_line.3 man3/gl_resize_history.3 - man3/gl_limit_history.3 man3/gl_clear_history.3 - man3/gl_toggle_history.3 - I added a number of miscellaneous history configuration - functions. You can now resize or delete the history - buffer, limit the number of lines that are allowed in the - buffer, clear either all history or just the history of - the current history group, and temporarily enable and - disable the history mechanism. - -13/10/2001 mcs@astro.caltech.edu - - getline.c - tputs_fp is now only declared if using termcap or - terminfo. - getline.c libtecla.map man3/gl_get_line.3 - man3/gl_terminal_size.3 - I added a public gl_terminal_size() function for - updating and querying the current size of the terminal. - update_version configure.in libtecla.h - A user noted that on systems where the configure script - couldn't be used, it was inconvenient to have the version - number macros set by the configure script, so they are - now specified in libtecla.h. To reduce the likelihood - that the various files where the version number now - appears might get out of sync, I have written the - update_version script, which changes the version number - in all of these files to a given value. - -01/10/2001 mcs@astro.caltech.edu - - getline.c history.c history.h man3/gl_get_line.3 - I added a max_lines argument to gl_save_history(), to - allow people to optionally place a ceiling on the number - of history lines saved. Specifying this as -1 sets the - ceiling to infinity. - -01/10/2001 mcs@astro.caltech.edu - - configure.in configure - Under digital unix, getline wouldn't compile with - _POSIX_C_SOURCE set, due to type definitions needed by - select being excluded by this flag. Defining the - _OSF_SOURCE macro as well on this system, resolved this. - -30/09/2001 mcs@astro.caltech.edu - - getline.c libtecla.h history.c history.h man3/gl_get_line.3 - man3/gl_group_history.3 - I implemented history streams. History streams - effectively allow multiple history lists to be stored in - a single history buffer. Lines in the buffer are tagged - with the current stream identification number, and - lookups only consider lines that are marked with the - current stream identifier. - getline.c libtecla.h history.c history.h man3/gl_get_line.3 - man3/gl_show_history.3 - The new gl_show_history function displays the current - history to a given stdio output stream. - -29/09/2001 mcs@astro.caltech.edu - - getline.c - Previously new_GetLine() installed a persistent signal - handler to be sure to catch the SIGWINCH (terminal size - change) signal between calls to gl_get_line(). This had - the drawback that if multiple GetLine objects were - created, only the first GetLine object used after the - signal was received, would see the signal and adapt to - the new terminal size. Instead of this, a signal handler - for sigwinch is only installed while gl_get_line() is - running, and just after installing this handler, - gl_get_line() checks for terminal size changes that - might have occurred while the signal handler wasn't - installed. - getline.c - Dynamically allocated copies of capability strings looked - up in the terminfo or termcap databases are now made, so - that calls to setupterm() etc for one GetLine object - don't get trashed when another GetLine object calls - setupterm() etc. It is now safe to allocate and use - multiple GetLine objects, albeit only within a single - thread. - -28/09/2001 mcs@astro.caltech.edu - - version.c Makefile.rules - I added a function for querying the version number of - the library. - -26/09/2001 mcs@astro.caltech.edu - - getline.c man3/gl_get_line.3 - I added the new gl_watch_fd() function, which allows - applications to register callback functions to be invoked - when activity is seen on arbitrary file descriptors while - gl_get_line() is awaiting keyboard input from the user. - - keytab.c - If a request is received to delete a non-existent - binding, which happens to be an ambiguous prefix of other - bindings no complaint is now generated about it being - ambiguous. - -23/09/2001 mcs@astro.caltech.edu - - getline.c history.c history.h man3/gl_get_line.3 - libtecla.map demo.c - I added new public functions for saving and restoring the - contents of the history list. The demo program now uses - these functions to load and save history in ~/.demo_history. - -23/09/2001 mcs@astro.caltech.edu - - getline.c - On trying the demo for the first time on a KDE konsole - terminal, I discovered that the default M-O binding - to repeat history was hiding the arrow keys, which are - M-OA etc. I have removed this binding. The M-o (ie the - lower case version of this), is still bound. - -18/09/2001 mcs@astro.caltech.edu - - getline.c man3/gl_get_line.3 libtecla.map - Automatic reading of ~/.teclarc is now postponed until - the first call to gl_get_line(), to give the application - the chance to specify alternative configuration sources - with the new function gl_configure_getline(). The latter - function allows configuration to be done with a string, a - specified application-specific file, and/or a specified - user-specific file. I also added a read-init-files action - function, for re-reading the configuration files, if any. - This is by default bound to ^X^R. This is all documented - in gl_get_line.3. - -08/09/2001 mcs@astro.caltech.edu - - getline.c man3/gl_get_line.3 - It is now possible to bind actions to key-sequences - that start with printable characters. Previously - keysequences were required to start with meta or control - characters. This is documented in gl_get_line.3. - - getline.c man3/gl_get_line.3 - A customized completion function can now arrange for - gl_get_line() to return the current input line whenever a - successful completion has been made. This is signalled by - setting the last character of the optional continuation - suffix to a newline character. This is documented in - gl_get_line.3. - -05/07/2001 Bug reported by Mike MacFaden, fixed by mcs - - configure.in - There was a bug in the configure script that only - revealed itself on systems without termcap but not - terminfo (eg. NetBSD). I traced the bug back to a lack of - sufficient quoting of multi-line m4 macro arguments in - configure.in, and have now fixed this and recreated the - configure script. - -05/07/2001 Bug reported and patched by Mike MacFaden (patch modified - by mcs to match original intentions). - - getline.c - getline.c wouldn't compile when termcap was selected as - the terminal information database. setupterm() was being - passed a non-existent variable, in place of the term[] - argument of gl_control_strings(). Also if - gl_change_terminal() is called with term==NULL, "ansi" - is now substituted. - -02/07/2001 Version 1.3.3 released. - -27/06/2001 mcs@astro.caltech.edu - - getline.c expand.c cplmatch.c - Added checks to fprintf() statements that write to the - terminal. - getline.c - Move the cursor to the end of the line before suspending, - so that the cursor doesn't get left in the middle of the - input line. - Makefile.in - On systems that don't support shared libraries, the - distclean target of make deleted libtecla.h. This has - now been fixed. - getline.c - gl_change_terminal() was being called by gl_change_editor(), - with the unwanted side effect that raw terminal modes were - stored as those to be restored later, if called by an - action function. gl_change_terminal() was being called in - this case to re-establish terminal-specific key bindings, - so I have just split this part of the function out into - a separate function for both gl_change_editor() and - gl_change_terminal() to call. - -12/06/2001 mcs@astro.caltech.edu - - getline.c - Signal handling has been improved. Many more signals are - now trapped, and instead of using a simple flag set by a - signal handler, race conditions are avoided by blocking - signals during most of the gl_get_line() code, and - unblocking them via calls to sigsetjmp(), just before - attempting to read each new character from the user. - The matching use of siglongjmp() in the signal - handlers ensures that signals are reblocked correctly - before they are handled. In most cases, signals cause - gl_get_line() to restore the terminal modes and signal - handlers of the calling application, then resend the - signal to the application. In the case of SIGINT, SIGHUP, - SIGPIPE, and SIGQUIT, if the process still exists after - the signals are resent, gl_get_line() immediately returns - with appropriate values assigned to errno. If SIGTSTP, - SIGTTIN or SIGTTOU signals are received, the process is - suspended. If any other signal is received, and the - process continues to exist after the signal is resent to - the calling application, line input is resumed after the - terminal is put back into raw mode, the gl_get_line() - signal handling is restored, and the input line redrawn. - man/gl_get_line(3) - I added a SIGNAL HANDLING section to the gl_get_line() - man page, describing the new signal handling features. - -21/05/2001 Version 1.3.2 released. - -21/05/2001 mcs@astro.caltech.edu - - getline.c - When vi-replace-char was used to replace the character at - the end of the line, it left the cursor one character to - its right instead of on top of it. Now rememdied. - getline.c - When undoing, to properly emulate vi, the cursor is now - left at the leftmost of the saved and current cursor - positions. - getline.c man3/gl_get_line.3 - Implemented find-parenthesis (%), delete-to-paren (M-d%), - vi-change-to-paren (M-c%), copy-to-paren (M-y%). - cplfile.c pcache.c - In three places I was comparing the last argument of - strncmp() to zero instead of the return value of - strncmp(). - -20/05/2001 mcs@astro.caltech.edu - - getline.c man3/gl_get_line.3 - Implemented and documented the vi-repeat-change action, - bound to the period key. This repeats the last action - that modified the input line. - -19/05/2001 mcs@astro.caltech.edu - - man3/gl_get_line.3 - I documented the new action functions and bindings - provided by Tim Eliseo, plus the ring-bell action and - the new "nobeep" configuration option. - getline.c - I modified gl_change_editor() to remove and reinstate the - terminal settings as well as the default bindings, since - these have editor-specific differences. I also modified - it to not abort if a key-sequence can't be bound for some - reason. This allows the new vi-mode and emacs-mode - bindings to be used safely. - getline.c - When the line was re-displayed on receipt of a SIGWINCH - signal, the result wasn't visible until the next - character was typed, since a call to fflush() was needed. - gl_redisplay_line() now calls gl_flush_output() to remedy - this. - -17/05/2001 mcs@astro.catlech.edu - - getline.c - Under Linux, calling fflush(gl->output_fd) hangs if - terminal output has been suspended with ^S. With the - tecla library taking responsability for reading the stop - and start characters this was a problem, because once - hung in fflush(), the keyboard input loop wasn't entered, - so the user couldn't type the start character to resume - output. To remedy this, I now have the terminal process - these characters, rather than the library. - -12/05/2001 mcs@astro.caltech.edu - - getline.c - The literal-next action is now implemented as a single - function which reads the next character itself. - Previously it just set a flag which effected the - interpretation of the next character read by the input - loop. - getline.c - Added a ring-bell action function. This is currently - unbound to any key by default, but it is used internally, - and can be used by users that want to disable any of the - default key-bindings. - -12/05/2001 Tim Eliseo (logged here by mcs) - - getline.c - Don't reset gl->number until after calling an action - function. By looking at whether gl->number is <0 or - not, action functions can then tell whether the count - that they were passed was explicitly specified by the - user, as opposed to being defaulted to 1. - getline.c - In vi, the position at which input mode is entered - acts as a barrier to backward motion for the few - backward moving actions that are enabled in input mode. - Tim added this barrier to getline. - getline.c - In gl_get_line() after reading an input line, or - having the read aborted by a signal, the sig_atomic_t - gl_pending_signal was being compared to zero instead - of -1 to see if no signals had been received. - gl_get_line() will thus have been calling raise(-1), - which luckily didn't seem to do anything. Tim also - arranged for errno to be set to EINTR when a signal - aborts gl_get_line(). - getline.c - The test in gl_add_char_to_line() for detecting - when overwriting a character with a wider character, - had a < where it needed a >. Overwriting with a wider - character thus overwrote trailing characters. Tim also - removed a redundant copy of the character into the - line buffer. - getline.c - gl_cursor_left() and gl->cursor_right() were executing - a lot of redundant code, when the existing call to the - recently added gl_place_cursor() function, does all that - is necessary. - getline.c - Remove redundant code from backward_kill_line() by - re-implimenting in terms of gl_place_cursor() and - gl_delete_chars(). - getline.c - gl_forward_delete_char() now records characters in cut - buffer when in vi command mode. - getline.c - In vi mode gl_backward_delete_char() now only deletes - up to the point at which input mode was entered. Also - gl_delete_chars() restores from the undo buffer when - deleting in vi insert mode. - getline.c - Added action functions, vi-delete-goto-column, - vi-change-to-bol, vi-change-line, emacs-mode, vi-mode, - vi-forward-change-find, vi-backward-change-find, - vi-forward-change-to, vi-backward-change-to, - vi-change-goto-col, forward-delete-find, backward-delete-find, - forward-delete-to, backward-delete-to, - delete-refind, delete-invert-refind, forward-copy-find, - backward-copy-find, forward-copy-to, backward-copy-to - copy-goto-column, copy-rest-of-line, copy-to-bol, copy-line, - history-re-search-forward, history-re-search-backward. - -06/05/2001 Version 1.3.1 released. - -03/05/2001 mcs@astro.caltech.edu - - configure.in - Old versions of GNU ld don't accept version scripts. - Under Linux I thus added a test to try out ld with - the --version-script argument to see if it works. - If not, version scripts aren't used. - configure.in - My test for versions of Solaris earlier than 7 - failed when confronted by a three figure version - number (2.5.1). Fixed. - -30/04/2001 mcs@astro.caltech.edu - - getline.c - In vi mode, history-search-backward and - history-search-forward weren't doing anything when - invoked at the start of an empty line, whereas - they should have acted like up-history and down-history. - Makefile.in Makefile.rules - When shared libraries are being created, the build - procedure now arranges for any alternate library - links to be created as well, before linking the - demos. Without this the demos always linked to the - static libraries (which was perfectly ok, but wasn't a - good example). - Makefile.in Makefile.rules - On systems on which shared libraries were being created, - if there were no alternate list of names, make would - abort due to a Bourne shell 'for' statement that didn't - have any arguments. Currently there are no systems who's - shared library configurations would trigger this - problem. - Makefile.rules - The demos now relink to take account of changes to the - library. - configure.in configure - When determining whether the reentrant version of the - library should be compiled by default, the configure - script now attempts to compile a dummy program that - includes all of the appropriate system headers and - defines _POSIX_C_SOURCE. This should now be a robust test - on systems which use C macros to alias these function - names to other internal functions. - configure.in - Under Solaris 2.6 and earlier, the curses library is in - /usr/ccs/lib. Gcc wasn't finding this. In addition to - remedying this, I had to remove "-z text" from - LINK_SHARED under Solaris to get it to successfully - compile the shared library against the static curses - library. - configure.in - Under Linux the -soname directive was being used - incorrectly, citing the fully qualified name of the - library instead of its major version alias. This will - unfortunately mean that binaries linked with the 1.2.3 - and 1.2.4 versions of the shared library won't use - later versions of the library unless relinked. - -30/04/2001 mcs@astro.caltech.edu - - getline.c - In gl_get_input_line(), don't redundantly copy the - start_line if start_line == gl->line. - -30/04/2001 Version 1.3.0 released. - -28/04/2001 mcs@astro.caltech.edu - - configure.in - I removed the --no-undefined directive from the Linux - LINK_SHARED command. After recent patches to our RedHat - 7.0 systems ld started reporting some internal symbols of - libc as being undefined. Using nm on libc indicated that - the offending symbols are indeed defined, albeit as - "common" symbols, so there appears to be a bug in - RedHat's ld. Removing this flag allows the tecla shared - library to compile, and programs appear to function fine. - man3/gl_get_line.3 - The default key-sequence used to invoke the - read-from-file action was incorrectly cited as ^Xi - instead of ^X^F. - -26/04/2001 mcs@astro.caltech.edu - - getline.c man3/gl_get_line.3 - A new vi-style editing mode was added. This involved - adding many new action functions, adding support for - specifying editing modes in users' ~/.teclarc files, - writing a higher level cursor motion function to support - the different line-end bounds required in vi command - mode, and a few small changes to support the fact that vi - has two modes, input mode and command mode with different - bindings. - - When vi editing mode is enabled, any binding that starts - with an escape or a meta character, is interpreted as a - command-mode binding, and switches the library to vi - command mode if not already in that mode. Once in command - mode the first character of all keysequences entered - until input mode is re-enabled, are quietly coerced to - meta characters before being looked up in the key-binding - table. So, for example, in the key-binding table, the - standard vi command-mode 'w' key, which moves the cursor - one word to the right, is represented by M-w. This - emulates vi's dual sets of bindings in a natural way - without needing large changes to the library, or new - binding syntaxes. Since cursor keys normally emit - keysequences which start with escape, it also does - something sensible when a cursor key is pressed during - input mode (unlike true vi, which gets upset). - - I also added a ^Xg binding for the new list-glob action - to both the emacs and vi key-binding tables. This lists - the files that match the wild-card expression that - precedes it on the command line. - - The function that reads in ~/.teclarc used to tell - new_GetLine() to abort if it encountered anything that it - didn't understand in this file. It now just reports an - error and continues onto the next line. - Makefile.in: - When passing LIBS=$(LIBS) to recursive invokations of - make, quotes weren't included around the $(LIBS) part. - This would cause problems if LIBS ever contained more - than one word (with the supplied configure script this - doesn't happen currently). I added these quotes. - expand.c man3/ef_expand_file.3: - I wrote a new public function called ef_list_expansions(), - to list the matching filenames returned by - ef_expand_file(). - - I also fixed the example in the man page, which cited - exp->file instead of exp->files, and changed the - dangerous name 'exp' with 'expn'. - keytab.c: - Key-binding tables start with 100 elements, and are - supposedly incremented in size by 100 elements whenever - the a table runs out of space. The realloc arguments to - do this were wrong. This would have caused problems if - anybody added a lot of personal bindings in their - ~/.teclarc file. I only noticed it because the number of - key bindings needed by the new vi mode exceeded this - number. - libtecla.map - ef_expand_file() is now reported as having been added in - the upcoming 1.3.0 release. - -25/03/2001 Markus Gyger (logged here by mcs) - - Makefile.in: - Make symbolic links to alternative shared library names - relative instead of absolute. - Makefile.rules: - The HP-UX libtecla.map.opt file should be made in the - compilation directory, to allow the source code directory - to be on a readonly filesystem. - cplmatch.c demo2.c history.c pcache.c - To allow the library to be compiled with a C++ compiler, - without generating warnings, a few casts were added where - void* return values were being assigned directly to - none void* pointer variables. - -25/03/2001 mcs@astro.caltech.edu - - libtecla.map: - Added comment header to explain the purpose of the file. - Also added cpl_init_FileArgs to the list of exported - symbols. This symbol is deprecated, and no longer - documented, but for backwards compatibility, it should - still be exported. - configure: - I had forgotten to run autoconf before releasing version - 1.2.4, so I have just belatedly done so. This enables - Markus' changes to "configure.in" documented previously, - (see 17/03/2001). - -20/03/2001 John Levon (logged here by mcs) - - libtecla.h - A couple of the function prototypes in libtecla.h have - (FILE *) argument declarations, which means that stdio.h - needs to be included. The header file should be self - contained, so libtecla.h now includes stdio.h. - -18/03/2001 Version 1.2.4 released. - - README html/index.html configure.in - Incremented minor version from 3 to 4. - -18/03/2001 mcs@astro.caltech.edu - - getline.c - The fix for the end-of-line problem that I released a - couple of weeks ago, only worked for the first line, - because I was handling this case when the cursor position - was equal to the last column, rather than when the cursor - position modulo ncolumn was zero. - Makefile.in Makefile.rules - The demos are now made by default, their rules now being - int Makefile.rules instead of Makefile.in. - INSTALL - I documented how to compile the library in a different - directory than the distribution directory. - I also documented features designed to facilitate - configuring and building the library as part of another - package. - -17/03/2001 Markus Gyger (logged here by mcs) - - getline.c - Until now cursor motions were done one at a time. Markus - has added code to make use the of the terminfo capability - that moves the cursor by more than one position at a - time. This greatly improves performance when editing near - the start of long lines. - getline.c - To further improve performance, Markus switched from - writing one character at a time to the terminal, using - the write() system call, to using C buffered output - streams. The output buffer is only flushed when - necessary. - Makefile.rules Makefile.in configure.in - Added support for compiling for different architectures - in different directories. Simply create another directory - and run the configure script located in the original - directory. - Makefile.in configure.in libtecla.map - Under Solaris, Linux and HP-UX, symbols that are to be - exported by tecla shared libraries are explicitly specified - via symbol map files. Only publicly documented functions - are thus visible to applications. - configure.in - When linking shared libraries under Solaris SPARC, - registers that are reserved for applications are marked - as off limits to the library, using -xregs=no%appl when - compiling with Sun cc, or -mno-app-regs when compiling - with gcc. Also removed -z redlocsym for Solaris, which - caused problems under some releases of ld. - homedir.c (after minor changes by mcs) - Under ksh, ~+ expands to the current value of the ksh - PWD environment variable, which contains the path of - the current working directory, including any symbolic - links that were traversed to get there. The special - username "+" is now treated equally by tecla, except - that it substitutes the return value of getcwd() if PWD - either isn't set, or if it points at a different - directory than that reported by getcwd(). - -08/03/2001 Version 1.2.3 released. - -08/03/2001 mcs@astro.caltech.edu - - getline.c - On compiling the library under HP-UX for the first time - I encountered and fixed a couple of bugs: - - 1. On all systems except Solaris, the callback function - required by tputs() takes an int argument for the - character that is to be printed. Under Solaris it - takes a char argument. The callback function was - passing this argument, regardless of type, to write(), - which wrote the first byte of the argument. This was - fine under Solaris and under little-endian systems, - because the first byte contained the character to be - written, but on big-endian systems, it always wrote - the zero byte at the other end of the word. As a - result, no control characters were being written to - the terminal. - 2. While attempting to start a newline after the user hit - enter, the library was outputting the control sequence - for moving the cursor down, instead of the newline - character. On many systems the control sequence for - moving the cursor down happends to be a newline - character, but under HP-UX it isn't. The result was - that no new line was being started under HP-UX. - -04/03/2001 mcs@astro.caltech.edu - - configure.in Makefile.in Makefile.stub configure config.guess - config.sub Makefile.rules install-sh PORTING README INSTALL - Configuration and compilation of the library is now - performed with the help of an autoconf configure - script. In addition to relieving the user of the need to - edit the Makefile, this also allows automatic compilation - of the reentrant version of the library on platforms that - can handle it, along with the creation of shared - libraries where configured. On systems that aren't known - to the configure script, just the static tecla library is - compiled. This is currently the case on all systems - except Linux, Solaris and HP-UX. In the hope that - installers will provide specific conigurations for other - systems, the configure.in script is heavily commented, - and instructions on how to use are included in a new - PORTING file. - -24/02/2001 Version 1.2b released. - -22/02/2001 mcs@astro.caltech.edu - - getline.c - It turns out that most terminals, but not all, on writing - a character in the rightmost column, don't wrap the - cursor onto the next line until the next character is - output. This library wasn't aware of this and thus if one - tried to reposition the cursor from the last column, - gl_get_line() thought that it was moving relative to a - point on the next line, and thus moved the cursor up a - line. The fix was to write one extra character when in - the last column to force the cursor onto the next line, - then backup the cursor to the start of the new line. - getline.c - On terminal initialization, the dynamic LINES and COLUMNS - environment variables were ignored unless - terminfo/termcap didn't return sensible dimensions. In - practice, when present they should override the static - versions in the terminfo/termcap databases. This is the - new behavior. In reality this probably won't have caused - many problems, because a SIGWINCH signal which informs of - terminal size changes is sent when the terminal is - opened, so the dimensions established during - initialization quickly get updated on most systems. - -18/02/2001 Version 1.2a released. - -18/02/2001 mcs@astro.caltech.edu - - getline.c - Three months ago I moved the point at which termios.h - was included in getline.c. Unfortunately, I didn't notice - that this moved it to after the test for TIOCGWINSZ being - defined. This resulted in SIGWINCH signals not being - trapped for, and thus terminal size changes went - unnoticed. I have now moved the test to after the - inclusion of termios.h. - -12/02/2001 Markus Gyger (described here by mcs) - - man3/pca_lookup_file.3 man3/gl_get_line.3 - man3/ef_expand_file.3 man3/cpl_complete_word.3 - In the 1.2 release of the library, all functions in the - library were given man pages. Most of these simply - include one of the above 4 man pages, which describe the - functions while describing the modules that they are in. - Markus added all of these function names to the lists in - the "NAME" headers of the respective man pages. - Previously only the primary function of each module was - named there. - -11/02/2001 mcs@astro.caltech.edu - - getline.c - On entering a line that wrapped over two or more - terminal, if the user pressed enter when the cursor - wasn't on the last of the wrapped lines, the text of the - wrapped lines that followed it got mixed up with the next - line written by the application, or the next input - line. Somehow this slipped through the cracks and wasn't - noticed until now. Anyway, it is fixed now. - -09/02/2001 Version 1.2 released. - -04/02/2001 mcs@astro.caltech.edu - - pcache.c libtecla.h - With all filesystems local, demo2 was very fast to start - up, but on a Sun system with one of the target - directories being on a remote nfs mounted filesystem, the - startup time was many seconds. This was due to the - executable selection callback being applied to all files - in the path at startup. To avoid this, all files are now - included in the cache, and the application specified - file-selection callback is only called on files as they - are matched. Whether the callback rejected or accepted - them is then cached so that the next time an already - checked file is looked at, the callback doesn't have to - be called. As a result, startup is now fast on all - systems, and since usually there are only a few matching - file completions at a time, the delay during completion - is also usually small. The only exception is if the user - tries to complete an empty string, at which point all - files have to be checked. Having done this once, however, - doing it again is fast. - man3/pca_lookup_file.3 - I added a man page documenting the new PathCache module. - man3/<many-new-files>.3 - I have added man pages for all of the functions in each - of the modules. These 1-line pages use the .so directive - to redirect nroff to the man page of the parent module. - man Makefile update_html - I renamed man to man3 to make it easier to test man page - rediction, and updated Makefile and update_html - accordingly. I also instructed update_html to ignore - 1-line man pages when making html equivalents of the man - pages. - cplmatch.c - In cpl_list_completions() the size_t return value of - strlen() was being used as the length argument of a "%*s" - printf directive. This ought to be an int, so the return - value of strlen() is now cast to int. This would have - caused problems on architectures where the size of a - size_t is not equal to the size of an int. - -02/02/2001 mcs@astro.caltech.edu - - getline.c - Under UNIX, certain terminal bindings are set using the - stty command. This, for example, specifies which control - key generates a user-interrupt (usually ^C or ^Y). What I - hadn't realized was that ASCII NUL is used as the way to - specify that one of these bindings is unset. I have now - modified the code to skip unset bindings, leaving the - corresponding action bound to the built-in default, or a - user provided binding. - -28/01/2001 mcs@astro.caltech.edu - - pcache.c libtecla.h - A new module was added which supports searching for files - in any colon separated list of directories, such as the - unix execution PATH environment variable. Files in these - directories, after being individually okayed for - inclusion via an application provided callback, are - cached in a PathCache object. You can then look up the - full pathname of a given filename, or you can use the - provided completion callback to list possible completions - in the path-list. The contents of relative directories, - such as ".", obviously can't be cached, so these - directories are read on the fly during lookups and - completions. The obvious application of this facility is - to provide Tab-completion of commands, and thus a - callback to place executable files in the cache, is - provided. - demo2.c - This new program demonstrates the new PathCache - module. It reads and processes lines of input until the - word 'exit' is entered, or C-d is pressed. The default - tab-completion callback is replaced with one which at the - start of a line, looks up completions of commands in the - user's execution path, and when invoked in other parts of - the line, reverts to normal filename completion. Whenever - a new line is entered, it extracts the first word on the - line, looks it up in the user's execution path to see if - it corresponds to a known command file, and if so, - displays the full pathname of the file, along with the - remaining arguments. - cplfile.c - I added an optional pair of callback function/data - members to the new cpl_file_completions() configuration - structure. Where provided, this callback is asked - on a file-by-file basis, which files should be included - in the list of file completions. For example, a callback - is provided for listing only completions of executable - files. - cplmatch.c - When listing completions, the length of the type suffix - of each completion wasn't being taken into account - correctly when computing the column widths. Thus the - listing appeared ragged sometimes. This is now fixed. - pathutil.c - I added a function for prepending a string to a path, - and another for testing whether a pathname referred to - an executable file. - -28/01/2001 mcs@astro.caltech.edu - - libtecla.h cplmatch.c man/cpl_complete_word.3 - The use of a publically defined structure to configure - the cpl_file_completions() callback was flawed, so a new - approach has been designed, and the old method, albeit - still supported, is no longer documented in the man - pages. The definition of the CplFileArgs structure in - libtecla.h is now accompanied by comments warning people - not to modify it, since modifications could break - applications linked to shared versions of the tecla - library. The new method involves an opaque CplFileConf - object, instances of which are returned by a provided - constructor function, configured with provided accessor - functions, and when no longer needed, deleted with a - provided destructor function. This is documented in the - cpl_complete_word man page. The cpl_file_completions() - callback distinguishes what type of configuration - structure it has been sent by virtue of a code placed at - the beginning of the CplFileConf argument by its - constructor. - -04/01/2001 mcs@astro.caltech.edu (Release of version 1.1j) - - getline.c - I added upper-case bindings for the default meta-letter - keysequences such as M-b. They thus continue to work - when the user has caps-lock on. - Makefile - I re-implemented the "install" target in terms of new - install_lib, install_inc and install_man targets. When - distributing the library with other packages, these new - targets allows for finer grained control of the - installation process. - -30/12/2000 mcs@astro.caltech.edu - - getline.c man/gl_get_line.3 - I realized that the recall-history action that I - implemented wasn't what Markus had asked me for. What he - actually wanted was for down-history to continue going - forwards through a previous history recall session if no - history recall session had been started while entering - the current line. I have thus removed the recall-history - action and modified the down-history action function - accordingly. - -24/12/2000 mcs@astro.caltech.edu - - getline.c - I modified gl_get_line() to allow the previously returned - line to be passed in the start_line argument. - getline.c man/gl_get_line.3 - I added a recall-history action function, bound to M^P. - This recalls the last recalled history line, regardless - of whether it was from the current or previous line. - -13/12/2000 mcs@astro.caltech.edu (Release of version 1.1i) - - getline.c history.h history.c man/gl_get_line.3 - I implemented the equivalent of the ksh Operate action. I - have named the tecla equivalent "repeat-history". This - causes the line that is to be edited to returned, and - arranges for the next most recent history line to be - preloaded on the next call to gl_get_line(). Repeated - invocations of this action thus result in successive - history lines being repeated - hence the - name. Implementing the ksh Operate action was suggested - by Markus Gyger. In ksh it is bound to ^O, but since ^O - is traditionally bound by the default terminal settings, - to stop-output, I have bound the tecla equivalent to M-o. - -01/12/2000 mcs@astro.caltech.edu (Release of version 1.1h) - - getline.c keytab.c keytab.h man/gl_get_line.3 - I added a digit-argument action, to allow repeat - counts for actions to be entered. As in both tcsh - and readline, this is bound by default to each of - M-0, M-1 through to M-9, the number being appended - to the current repeat count. Once one of these has been - pressed, the subsequent digits of the repeat count can be - typed with or without the meta key pressed. It is also - possible to bind digit-argument to other keys, with or - without a numeric final keystroke. See man page for - details. - - getline.c man/gl_get_line.3 - Markus noted that my choice of M-< for the default - binding of read-from-file, could be confusing, since - readline binds this to beginning-of-history. I have - thus rebound it to ^X^F (ie. like find-file in emacs). - - getline.c history.c history.h man/gl_get_line.3 - I have now implemented equivalents of the readline - beginning-of-history and end-of-history actions. - These are bound to M-< and M-> respectively. - - history.c history.h - I Moved the definition of the GlHistory type, and - its subordinate types from history.h to history.c. - There is no good reason for any other module to - have access to the innards of this structure. - -27/11/2000 mcs@astro.caltech.edu (Release of version 1.1g) - - getline.c man/gl_get_line.3 - I added a "read-from-file" action function and bound it - by default to M-<. This causes gl_get_line() to - temporarily return input from the file who's name - precedes the cursor. - -26/11/2000 mcs@astro.caltech.edu - - getline.c keytab.c keytab.h man/gl_get_line.3 - I have reworked some of the keybinding code again. - - Now, within key binding strings, in addition to the - previously existing notation, you can now use M-a to - denote meta-a, and C-a to denote control-a. For example, - a key binding which triggers when the user presses the - meta key, the control key and the letter [ - simultaneously, can now be denoted by M-C-[, or M-^[ or - \EC-[ or \E^[. - - I also updated the man page to use M- instead of \E in - the list of default bindings, since this looks cleaner. - - getline.c man/gl_get_line.3 - I added a copy-region-as-kill action function and - gave it a default binding to M-w. - -22/11/2000 mcs@astro.caltech.edu - - *.c - Markus Gyger sent me a copy of a previous version of - the library, with const qualifiers added in appropriate - places. I have done the same for the latest version. - Among other things, this gets rid of the warnings - that are generated if one tells the compiler to - const qualify literal strings. - - getline.c getline.h glconf.c - I have moved the contents of glconf.c and the declaration - of the GetLine structure into getline.c. This is cleaner, - since now only functions in getline.c can mess with the - innards of GetLine objects. It also clears up some problems - with system header inclusion order under Solaris, and also - the possibility that this might result in inconsistent - system macro definitions, which in turn could cause different - declarations of the structure to be seen in different files. - - hash.c - I wrote a wrapper function to go around strcmp(), such that - when hash.c is compiled with a C++ compiler, the pointer - to the wrapper function is a C++ function pointer. - This makes it compatible with comparison function pointer - recorded in the hash table. - - cplmatch.c getline.c libtecla.h - Markus noted that the Sun C++ compiler wasn't able to - match up the declaration of cpl_complete_word() in - libtecla.h, where it is surrounded by a extern "C" {} - wrapper, with the definition of this function in - cplmatch.c. My suspicion is that the compiler looks not - only at the function name, but also at the function - arguments to see if two functions match, and that the - match_fn() argument, being a fully blown function pointer - declaration, got interpetted as that of a C function in - one case, and a C++ function in the other, thus - preventing a match. - - To fix this I now define a CplMatchFn typedef in libtecla.h, - and use this to declare the match_fn callback. - -20/11/2000 (Changes suggested by Markus Gyger to support C++ compilers): - expand.c - Renamed a variable called "explicit" to "xplicit", to - avoid conflicts when compiling with C++ compilers. - *.c - Added explicit casts when converting from (void *) to - other pointer types. This isn't needed in C but it is - in C++. - getline.c - tputs() has a strange declaration under Solaris. I was - enabling this declaration when the SPARC feature-test - macro was set. Markus changed the test to hinge on the - __sun and __SVR4 macros. - direader.c glconf.c stringrp.c - I had omitted to include string.h in these two files. - - Markus also suggested some other changes, which are still - under discussion. With the just above changes however, the - library compiles without complaint using g++. - -19/11/2000 mcs@astro.caltech.edu - getline.h getline.c keytab.c keytab.h glconf.c - man/gl_get_line.3 - I added support for backslash escapes (include \e - for the keyboard escape key) and literal binary - characters to the characters allowed within key sequences - of key bindings. - - getline.h getline.c keytab.c keytab.h glconf.c - man/gl_get_line.3 - I introduced symbolic names for the arrow keys, and - modified the library to use the cursor key sequences - reported by terminfo/termcap in addition to the default - ANSI ones. Anything bound to the symbolically named arrow - keys also gets bound to the default and terminfo/termcap - cursor key sequences. Note that under Solaris - terminfo/termcap report the properties of hardware X - terminals when TERM is xterm instead of the terminal - emulator properties, and the cursor keys on these two - systems generate different key sequences. This is an - example of why extra default sequences are needed. - - getline.h getline.c keytab.c - For some reason I was using \e to represent the escape - character. This is supported by gcc, which thus doesn't - emit a warning except with the -pedantic flag, but isn't - part of standard C. I now use a macro to define escape - as \033 in getline.h, and this is now used wherever the - escape character is needed. - -17/11/2000 mcs@astro.caltech.edu (Release of version 1.1d) - - getline.c, man/gl_get_line(3), html/gl_get_line.html - In tcsh ^D is bound to a function which does different - things depending on where the cursor is within the input - line. I have implemented its equivalent in the tecla - library. When invoked at the end of the line this action - function displays possible completions. When invoked on - an empty line it causes gl_get_line() to return NULL, - thus signalling end of input. When invoked within a line - it invokes forward-delete-char, as before. The new action - function is called del-char-or-list-or-eof. - - getline.c, man/gl_get_line(3), html/gl_get_line.html - I found that the complete-word and expand-file actions - had underscores in their names instead of hyphens. This - made them different from all other action functions, so I - have changed the underscores to hyphens. - - homedir.c - On SCO UnixWare while getpwuid_r() is available, the - associated _SC_GETPW_R_SIZE_MAX macro used by sysconf() - to find out how big to make the buffer to pass to this - function to cater for any password entry, doesn't - exist. I also hadn't catered for the case where sysconf() - reports that this limit is indeterminate. I have thus - change the code to substitute a default limit of 1024 if - either the above macro isn't defined or if sysconf() says - that the associated limit is indeterminate. - -17/11/2000 mcs@astro.caltech.edu (Release of version 1.1c) - - getline.c, getline.h, history.c, history.h - I have modified the way that the history recall functions - operate, to make them better emulate the behavior of - tcsh. Previously the history search bindings always - searched for the prefix that preceded the cursor, then - left the cursor at the same point in the line, so that a - following search would search using the same prefix. This - isn't how tcsh operates. On finding a matching line, tcsh - puts the cursor at the end of the line, but arranges for - the followup search to continue with the same prefix, - unless the user does any cursor motion or character - insertion operations in between, in which case it changes - the search prefix to the new set of characters that are - before the cursor. There are other complications as well, - which I have attempted to emulate. As far as I can - tell, the tecla history recall facilities now fully - emulate those of tcsh. - -16/11/2000 mcs@astro.caltech.edu (Release of version 1.1b) - - demo.c: - One can now quit from the demo by typing exit. - - keytab.c: - The first entry of the table was getting deleted - by _kt_clear_bindings() regardless of the source - of the binding. This deleted the up-arrow binding. - Symptoms noted by gazelle@yin.interaccess.com. - - getline.h: - Depending on which system include files were include - before the inclusion of getline.h, SIGWINCH and - TIOCGWINSZ might or might not be defined. This resulted - in different definitions of the GetLine object in - different files, and thus some very strange bugs! I have - now added #includes for the necessary system header files - in getline.h itself. The symptom was that on creating a - ~/.teclarc file, the demo program complained of a NULL - argument to kt_set_keybinding() for the first line of the - file. - -15/11/2000 mcs@astro.caltech.edu (Release of version 1.1a) - - demo.c: - I had neglected to check the return value of - new_GetLine() in the demo program. Oops. - - getline.c libtecla.h: - I wrote gl_change_terminal(). This allows one to change to - a different terminal or I/O stream, by specifying the - stdio streams to use for input and output, along with the - type of terminal that they are connected to. - - getline.c libtecla.h: - Renamed GetLine::isterm to GetLine::is_term. Standard - C reserves names that start with "is" followed by - alphanumeric characters, so this avoids potential - clashes in the future. - - keytab.c keytab.h - Each key-sequence can now have different binding - functions from different sources, with the user provided - binding having the highest precedence, followed by the - default binding, followed by any terminal specific - binding. This allows gl_change_terminal() to redefine the - terminal-specific bindings each time that - gl_change_terminal() is called, without overwriting the - user specified or default bindings. In the future, it will - also allow for reconfiguration of user specified - bindings after the call to new_GetLine(). Ie. deleting a - user specified binding should reinstate any default or - terminal specific binding. - - man/cpl_complete_word.3 html/cpl_complete_word.html - man/ef_expand_file.3 html/ef_expand_file.html - man/gl_get_line.3 html/gl_get_line.html - I added sections on thread safety to the man pages of the - individual modules. - - man/gl_get_line.3 html/gl_get_line.html - I documented the new gl_change_terminal() function. - - man/gl_get_line.3 html/gl_get_line.html - In the description of the ~/.teclarc configuration file, - I had omitted the 'bind' command word in the example - entry. I have now remedied this. -</PRE></BODY> diff --git a/libtecla-1.4.1/html/cpl_complete_word.html b/libtecla-1.4.1/html/cpl_complete_word.html deleted file mode 100644 index 063359d..0000000 --- a/libtecla-1.4.1/html/cpl_complete_word.html +++ /dev/null @@ -1,423 +0,0 @@ -<head> -<title>Manual Page</title> -</head> -<body> -<pre> -</pre><h2>NAME</h2><pre> - cpl_complete_word, cfc_file_start, cfc_literal_escapes, - cfc_set_check_fn, cpl_add_completion, cpl_file_completions, - cpl_last_error, cpl_list_completions, cpl_record_error, - del_CplFileConf, del_WordCompletion, new_CplFileConf, - new_WordCompletion - lookup possible completions for a word - -</pre><h2>SYNOPSIS</h2><pre> - #include <stdio.h> - #include <libtecla.h> - - WordCompletion *new_WordCompletion(void); - - WordCompletion *del_WordCompletion(WordCompletion *cpl); - - #define CPL_MATCH_FN(fn) int (fn)(WordCompletion *cpl, \ - void *data, \ - const char *line, \ - int word_end) - typedef CPL_MATCH_FN(CplMatchFn); - - CPL_MATCH_FN(cpl_file_completions); - - CplMatches *cpl_complete_word(WordCompletion *cpl, - const char *line, - int word_end, void *data, - CplMatchFn *match_fn); - - int cpl_list_completions(CplMatches *result, FILE *fp, - int term_width); - - int cpl_add_completion(WordCompletion *cpl, - const char *line, int word_start, - int word_end, const char *suffix, - const char *type_suffix, - const char *cont_suffix); - - void cpl_record_error(WordCompletion *cpl, - const char *errmsg); - - const char *cpl_last_error(WordCompletion *cpl); - - - -</pre><h2>DESCRIPTION</h2><pre> - The cpl_complete_word() function is part of the tecla - library (see the <a href="libtecla.html">libtecla(3)</a> man page). It is usually called - behind the scenes by <a href="gl_get_line.html">gl_get_line(3)</a>, but can also be called - separately. - - Given an input line containing an incomplete word to be com- - pleted, it calls a user-provided callback function (or the - provided file-completion callback function) to look up all - possible completion suffixes for that word. The callback - function is expected to look backward in the line, starting - from the specified cursor position, to find the start of the - word to be completed, then to look up all possible comple- - tions of that word and record them, one at a time by calling - cpl_add_completion(). - - - Descriptions of the functions of this module are as follows: - - CompleteWord *new_CompleteWord(void) - - This function creates the resources used by the - cpl_complete_word() function. In particular, it maintains - the memory that is used to return the results of calling - cpl_complete_word(). - - CompleteWord *del_CompleteWord(CompleteWord *cpl) - - This function deletes the resources that were returned by a - previous call to new_CompleteWord(). It always returns NULL - (ie. a deleted object). It does nothing if the cpl argument - is NULL. - - The callback functions which lookup possible completions - should be defined with the following macro (which is defined - in libtecla.h). - - #define CPL_MATCH_FN(fn) int (fn)(WordCompletion *cpl, \ - void *data, \ - const char *line, \ - int word_end) - - Functions of this type are called by cpl_complete_word(), - and all of the arguments of the callback are those that were - passed to said function. In particular, the line argument - contains the input line containing the word to be completed, - and word_end is the index of the character that follows the - last character of the incomplete word within this string. - The callback is expected to look backwards from word_end for - the start of the incomplete word. What constitutes the start - of a word clearly depends on the application, so it makes - sense for the callback to take on this responsibility. For - example, the builtin filename completion function looks - backwards until it hits an unescaped space, or the start of - the line. Having found the start of the word, the callback - should then lookup all possible completions of this word, - and record each completion via separate calls to - cpl_add_completion(). If the callback needs access to an - application-specific symbol table, it can pass it and any - other data that it needs, via the data argument. This - removes any need for globals. - - The callback function should return 0 if no errors occur. On - failure it should return 1, and register a terse description - of the error by calling cpl_record_error(). - - void cpl_record_error(WordCompletion *cpl, - const char *errmsg); - - The last error message recorded by calling - cpl_record_error(), can subsequently be queried by calling - cpl_last_error(), as described later. - - int cpl_add_completion(WordCompletion *cpl, - const char *line, int word_start, - int word_end, const char *suffix, - const char *type_suffix, - const char *cont_suffix); - - The cpl_add_completion() function is called zero or more - times by the completion callback function to record each - possible completion in the specified WordCompletion object. - These completions are subsequently returned by - cpl_complete_word(), as described later. The cpl, line, and - word_end arguments should be those that were passed to the - callback function. The word_start argument should be the - index within the input line string of the start of the word - that is being completed. This should equal word_end if a - zero-length string is being completed. The suffix argument - is the string that would have to be appended to the incom- - plete word to complete it. If this needs any quoting (eg. - the addition of backslashes before special charaters) to be - valid within the displayed input line, this should be - included. A copy of the suffix string is allocated inter- - nally, so there is no need to maintain your copy of the - string after cpl_add_completion() returns. - - Note that in the array of possible completions which the - cpl_complete_word() function returns, the suffix recorded by - cpl_add_completion() is listed along with the concatentation - of this suffix with the word that lies between word_start - and word_end in the input line. - - The type_suffix argument specifies an optional string to be - appended to the completion if it is displayed as part of a - list of completions by cpl_list_completions(). The intention - is that this indicate to the user the type of each comple- - tion. For example, the file completion function places a - directory separator after completions that are directories, - to indicate their nature to the user. Similary, if the com- - pletion were a function, you could indicate this to the user - by setting type_suffix to "()". Note that the type_suffix - string isn't copied, so if the argument isn't a literal - string between speech marks, be sure that the string remains - valid for at least as long as the results of - cpl_complete_word() are needed. - - The cont_suffix is a continuation suffix to append to the - completed word in the input line if this is the only comple- - tion. This is something that isn't part of the completion - itself, but that gives the user an indication about how they - might continue to extend the token. For example, the file- - completion callback function adds a directory separator if - the completed word is a directory. If the completed word - were a function name, you could similarly aid the user by - arranging for an open parenthesis to be appended. - - CplMatches *cpl_complete_word(WordCompletion *cpl, - const char *line, - int word_end, void *data, - CplMatchFn *match_fn); - - The cpl_complete_word() is normally called behind the scenes - by <a href="gl_get_line.html">gl_get_line(3)</a>, but can also be called separately if you - separately allocate a WordCompletion object. It performs - word completion, as described at the beginning of this sec- - tion. Its first argument is a resource object previously - returned by new_CompleteWord(). The line argument is the - input line string, containing the word to be completed. The - word_end argument contains the index of the character in the - input line, that just follows the last character of the word - to be completed. When called by gl_get_line(), this is the - character over which the user pressed TAB. The match_fn - argument is the function pointer of the callback function - which will lookup possible completions of the word, as - described above, and the data argument provides a way for - the application to pass arbitrary data to the callback func- - tion. - - If no errors occur, the cpl_complete_word() function returns - a pointer to a CplMatches container, as defined below. This - container is allocated as part of the cpl object that was - passed to cpl_complete_word(), and will thus change on each - call which uses the same cpl argument. - - typedef struct { - char *completion; /* A matching completion */ - /* string */ - char *suffix; /* The part of the */ - /* completion string which */ - /* would have to be */ - /* appended to complete the */ - /* original word. */ - const char *type_suffix; /* A suffix to be added when */ - /* listing completions, to */ - /* indicate the type of the */ - /* completion. */ - } CplMatch; - - typedef struct { - char *suffix; /* The common initial part */ - /* of all of the completion */ - /* suffixes. */ - const char *cont_suffix; /* Optional continuation */ - /* string to be appended to */ - /* the sole completion when */ - /* nmatch==1. */ - CplMatch *matches; /* The array of possible */ - /* completion strings, */ - /* sorted into lexical */ - /* order. */ - int nmatch; /* The number of elements in */ - /* the above matches[] */ - /* array. */ - } CplMatches; - - If an error occurs during completion, cpl_complete_word() - returns NULL. A description of the error can be acquired by - calling the cpl_last_error() function. - - const char *cpl_last_error(WordCompletion *cpl); - - The cpl_last_error() function returns a terse description of - the error which occurred on the last call to - cpl_complete_word() or cpl_add_completion(). - - int cpl_list_completions(CplMatches *result, FILE *fp, - int terminal_width); - - When the cpl_complete_word() function returns multiple pos- - sible completions, the cpl_list_completions() function can - be called upon to list them, suitably arranged across the - available width of the terminal. It arranges for the - displayed columns of completions to all have the same width, - set by the longest completion. It also appends the - type_suffix strings that were recorded with each completion, - thus indicating their types to the user. - - -</pre><h2>THE BUILT-IN FILENAME-COMPLETION CALLBACK</h2><pre> - By default the <a href="gl_get_line.html">gl_get_line(3)</a> function, passes the following - completion callback function to cpl_complete_word(). This - function can also be used separately, either by sending it - to cpl_complete_word(), or by calling it directly from your - own completion callback function. - - CPL_MATCH_FN(cpl_file_completions); - - Certain aspects of the behavior of this callback can be - changed via its data argument. If you are happy with its - default behavior you can pass NULL in this argument. Other- - wise it should be a pointer to a CplFileConf object, previ- - ously allocated by calling new_CplFileConf(). - - CplFileConf *new_CplFileConf(void); - - CplFileConf objects encapsulate the configuration parameters - of cpl_file_completions(). These parameters, which start out - with default values, can be changed by calling the accessor - functions described below. - - By default, the cpl_file_completions() callback function - searches backwards for the start of the filename being com- - pleted, looking for the first un-escaped space or the start - of the input line. If you wish to specify a different loca- - tion, call cfc_file_start() with the index at which the - filename starts in the input line. Passing start_index=-1 - re-enables the default behavior. - - void cfc_file_start(CplFileConf *cfc, int start_index); - - By default, when cpl_file_completions() looks at a filename - in the input line, each lone backslash in the input line is - interpreted as being a special character which removes any - special significance of the character which follows it, such - as a space which should be taken as part of the filename - rather than delimiting the start of the filename. These - backslashes are thus ignored while looking for completions, - and subsequently added before spaces, tabs and literal - backslashes in the list of completions. To have unescaped - backslashes treated as normal characters, call - cfc_literal_escapes() with a non-zero value in its literal - argument. - - void cfc_literal_escapes(CplFileConf *cfc, int literal); - - By default, cpl_file_completions() reports all files who's - names start with the prefix that is being completed. If you - only want a selected subset of these files to be reported in - the list of completions, you can arrange this by providing a - callback function which takes the full pathname of a file, - and returns 0 if the file should be ignored, or 1 if the - file should be included in the list of completions. To - register such a function for use by cpl_file_completions(), - call cfc_set_check_fn(), and pass it a pointer to the func- - tion, together with a pointer to any data that you would - like passed to this callback whenever it is called. Your - callback can make its decisions based on any property of the - file, such as the filename itself, whether the file is read- - able, writable or executable, or even based on what the file - contains. - - #define CPL_CHECK_FN(fn) int (fn)(void *data, \ - const char *pathname) - typedef CPL_CHECK_FN(CplCheckFn); - - void cfc_set_check_fn(CplFileConf *cfc, - CplCheckFn *chk_fn, void *chk_data); - - The cpl_check_exe() function is a provided callback of the - above type, for use with cpl_file_completions(). It returns - non-zero if the filename that it is given represents a nor- - mal file that the user has execute permission to. You could - use this to have cpl_file_completions() only list comple- - tions of executable files. - - When you have finished with a CplFileConf variable, you can - pass it to the del_CplFileConf() destructor function to - reclaim its memory. - - CplFileConf *del_CplFileConf(CplFileConf *cfc); - - - -</pre><h2>THREAD SAFETY</h2><pre> - In multi-threaded programs, you should use the libtecla_r.a - version of the library. This uses POSIX reentrant functions - where available (hence the _r suffix), and disables features - that rely on non-reentrant system functions. In the case of - this module, the only disabled feature is username comple- - tion in ~username/ expressions, in cpl_file_completions(). - - Using the libtecla_r.a version of the library, it is safe to - use the facilities of this module in multiple threads, pro- - vided that each thread uses a separately allocated WordCom- - pletion object. In other words, if two threads want to do - word completion, they should each call new_WordCompletion() - to allocate their own completion objects. - - -</pre><h2>FILES</h2><pre> - libtecla.a - The tecla library - libtecla.h - The tecla header file. - - -</pre><h2>SEE ALSO</h2><pre> - <a href="libtecla.html">libtecla(3)</a>, <a href="gl_get_line.html">gl_get_line(3)</a>, <a href="ef_expand_file.html">ef_expand_file(3)</a>, - <a href="pca_lookup_file.html">pca_lookup_file(3)</a> - - -</pre><h2>AUTHOR</h2><pre> - Martin Shepherd (mcs@astro.caltech.edu) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -</pre> -</body> diff --git a/libtecla-1.4.1/html/ef_expand_file.html b/libtecla-1.4.1/html/ef_expand_file.html deleted file mode 100644 index c1e71c7..0000000 --- a/libtecla-1.4.1/html/ef_expand_file.html +++ /dev/null @@ -1,267 +0,0 @@ -<head> -<title>Manual Page</title> -</head> -<body> -<pre> -</pre><h2>NAME</h2><pre> - ef_expand_file, del_ExpandFile, ef_last_error, - ef_list_expansions, new_ExpandFile - expand filenames con- - taining ~user/$envvar and wildcard expressions - -</pre><h2>SYNOPSIS</h2><pre> - #include <libtecla.h> - - ExpandFile *new_ExpandFile(void); - - ExpandFile *del_ExpandFile(ExpandFile *ef); - - FileExpansion *ef_expand_file(ExpandFile *ef, - const char *path, - int pathlen); - - int ef_list_expansions(FileExpansion *result, FILE *fp, - int term_width); - - const char *ef_last_error(ExpandFile *ef); - - -</pre><h2>DESCRIPTION</h2><pre> - The ef_expand_file() function is part of the tecla library - (see the <a href="libtecla.html">libtecla(3)</a> man page). It expands a specified - filename, converting ~user/ and ~/ expressions at the start - of the filename to the corresponding home directories, - replacing $envvar with the value of the corresponding - environment variable, and then, if there are any wildcards, - matching these against existing filenames. Backslashes in - the input filename are interpreted as escaping any special - meanings of the characters that follow them. Only - backslahes that are themselves preceded by backslashes are - preserved in the expanded filename. - - In the presence of wildcards, the returned list of filenames - only includes the names of existing files which match the - wildcards. Otherwise, the original filename is returned - after expansion of tilde and dollar expressions, and the - result is not checked against existing files. This mimics - the file-globbing behavior of the unix tcsh shell. - - The supported wildcards and their meanings are: - * - Match any sequence of zero or more characters. - ? - Match any single character. - [chars] - Match any single character that appears in - 'chars'. If 'chars' contains an expression of - the form a-b, then any character between a and - b, including a and b, matches. The '-' - character looses its special meaning as a - range specifier when it appears at the start - of the sequence of characters. The ']' - character also looses its significance as the - terminator of the range expression if it - appears immediately after the opening '[', at - which point it is treated one of the - characters of the range. If you want both '-' - and ']' to be part of the range, the '-' - should come first and the ']' second. - - [^chars] - The same as [chars] except that it matches any - single character that doesn't appear in - 'chars'. - - Note that wildcards never match the initial dot in filenames - that start with '.'. The initial '.' must be explicitly - specified in the filename. This again mimics the globbing - behavior of most unix shells, and its rational is based in - the fact that in unix, files with names that start with '.' - are usually hidden configuration files, which are not listed - by default by the ls command. - - The following is a complete example of how to use the file - expansion function. - - #include <stdio.h> - #include <libtecla.h> - - int main(int argc, char *argv[]) - { - ExpandFile *ef; /* The expansion resource object */ - char *filename; /* The filename being expanded */ - FileExpansion *expn; /* The results of the expansion */ - int i; - - ef = new_ExpandFile(); - if(!ef) - return 1; - - for(arg = *(argv++); arg; arg = *(argv++)) { - if((expn = ef_expand_file(ef, arg, -1)) == NULL) { - fprintf(stderr, "Error expanding %s (%s).\n", arg, - ef_last_error(ef)); - } else { - printf("%s matches the following files:\n", arg); - for(i=0; i<expn->nfile; i++) - printf(" %s\n", expn->files[i]); - } - } - - ef = del_ExpandFile(ef); - return 0; - } - - Descriptions of the functions used above are as follows: - - ExpandFile *new_ExpandFile(void) - - This function creates the resources used by the - ef_expand_file() function. In particular, it maintains the - memory that is used to record the array of matching - filenames that is returned by ef_expand_file(). This array - is expanded as needed, so there is no built in limit to the - number of files that can be matched. - - ExpandFile *del_ExpandFile(ExpandFile *ef) - - This function deletes the resources that were returned by a - previous call to new_ExpandFile(). It always returns NULL - (ie a deleted object). It does nothing if the ef argument is - NULL. - - A container of the following type is returned by - ef_expand_file(). - - typedef struct { - int exists; /* True if the files in files[] exist */ - int nfile; /* The number of files in files[] */ - char **files; /* An array of 'nfile' filenames. */ - } FileExpansion; - - FileExpansion *ef_expand_file(ExpandFile *ef, - const char *path, - int pathlen) - - The ef_expand_file() function performs filename expansion, - as documented at the start of this section. Its first argu- - ment is a resource object returned by new_ExpandFile(). A - pointer to the start of the filename to be matched is passed - via the path argument. This must be a normal NUL terminated - string, but unless a length of -1 is passed in pathlen, only - the first pathlen characters will be used in the filename - expansion. If the length is specified as -1, the whole of - the string will be expanded. - - The function returns a pointer to a container who's contents - are the results of the expansion. If there were no wildcards - in the filename, the nfile member will be 1, and the exists - member should be queried if it is important to know if the - expanded file currently exists or not. If there were wild- - cards, then the contained files[] array will contain the - names of the nfile existing files that matched the wild- - carded filename, and the exists member will have the value - 1. Note that the returned container belongs to the specified - ef object, and its contents will change on each call, so if - you need to retain the results of more than one call to - ef_expand_file(), you should either make a private copy of - the returned results, or create multiple file-expansion - resource objects via multiple calls to new_ExpandFile(). - - On error, NULL is returned, and an explanation of the error - can be determined by calling ef_last_error(ef). - - const char *ef_last_error(ExpandFile *ef) - - This function returns the message which describes the error - that occurred on the last call to ef_expand_file(), for the - given (ExpandFile *ef) resource object. - - int ef_list_expansions(FileExpansion *result, FILE *fp, - int terminal_width); - - The ef_list_expansions() function provides a convenient way - to list the filename expansions returned by - ef_expand_file(). Like the unix ls command, it arranges the - filenames into equal width columns, each column having the - width of the largest file. The number of columns used is - thus determined by the length of the longest filename, and - the specified terminal width. Beware that filenames that are - longer than the specified terminal width are printed without - being truncated, so output longer than the specified termi- - nal width can occur. The list is written to the stdio stream - specified by the fp argument. - - -</pre><h2>THREAD SAFETY</h2><pre> - In multi-threaded programs, you should use the libtecla_r.a - version of the library. This uses POSIX reentrant functions - where available (hence the _r suffix), and disables features - that rely on non-reentrant system functions. Currently there - are no features disabled in this module. - - Using the libtecla_r.a version of the library, it is safe to - use the facilities of this module in multiple threads, pro- - vided that each thread uses a separately allocated Expand- - File object. In other words, if two threads want to do file - expansion, they should each call new_ExpandFile() to allo- - cate their own file-expansion objects. - - -</pre><h2>FILES</h2><pre> - libtecla.a - The tecla library - libtecla.h - The tecla header file. - - -</pre><h2>SEE ALSO</h2><pre> - <a href="libtecla.html">libtecla(3)</a>, <a href="gl_get_line.html">gl_get_line(3)</a>, <a href="cpl_complete_word.html">cpl_complete_word(3)</a>, - <a href="pca_lookup_file.html">pca_lookup_file(3)</a> -</pre><h2>AUTHOR</h2><pre> - Martin Shepherd (mcs@astro.caltech.edu) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -</pre> -</body> diff --git a/libtecla-1.4.1/html/enhance.html b/libtecla-1.4.1/html/enhance.html deleted file mode 100644 index 9f6bb09..0000000 --- a/libtecla-1.4.1/html/enhance.html +++ /dev/null @@ -1,111 +0,0 @@ -<head> -<title>Manual Page</title> -</head> -<body> -<pre> -</pre><h2>NAME</h2><pre> - enhance - A program that adds command-line editing to third - party programs. - -</pre><h2>SYNOPSIS</h2><pre> - enhance command [ argument ... ] - - -</pre><h2>DESCRIPTION</h2><pre> - The enhance program provides enhanced command-line editing - facilities to users of third party applications, to which - one doesn't have any source code. It does this by placing a - pseudo-terminal between the application and the real termi- - nal. It uses the tecla command-line editing library to read - input from the real terminal, then forwards each just com- - pleted input line to the application via the pseudo- - terminal. All output from the application is forwarded back - unchanged to the real terminal. - - Whenever the application stops generating output for more - than a tenth of a second, the enhance program treats the - latest incomplete output line as the prompt, and redisplays - any incompleted input line that the user has typed after it. - Note that the small delay, which is imperceptible to the - user, isn't necessary for correct operation of the program. - It is just an optimization, designed to stop the input line - from being redisplayed so often that it slows down output. - - -</pre><h2>DEFICIENCIES</h2><pre> - The one major problem that hasn't been solved yet, is how to - deal with applications that change whether typed input is - echo'd by their controlling terminal. For example, programs - that ask for a password, such as ftp and telnet, temporarily - tell their controlling terminal not to echo what the user - types. Since this request goes to the application side of - the psuedo terminal, the enhance program has no way of know- - ing that this has happened, and continues to echo typed - input to its controlling terminal, while the user types - their password. - - Furthermore, before executing the host application, the - enhance program initially sets the pseudo terminal to noecho - mode, so that everything that it sends to the program - doesn't get redundantly echoed. If a program that switches - to noecho mode explicitly restores echoing afterwards, - rather than restoring the terminal modes that were previ- - ously in force, then subsequently, every time that you enter - a new input line, a duplicate copy will be displayed on the - next line. - - -</pre><h2>FILES</h2><pre> - libtecla.a - The tecla library. - ~/.teclarc - The tecla personal customization file. - - -</pre><h2>SEE ALSO</h2><pre> - <a href="libtecla.html">libtecla(3)</a> - - -</pre><h2>AUTHOR</h2><pre> - Martin Shepherd (mcs@astro.caltech.edu) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -</pre> -</body> diff --git a/libtecla-1.4.1/html/gl_get_line.html b/libtecla-1.4.1/html/gl_get_line.html deleted file mode 100644 index dcc45a0..0000000 --- a/libtecla-1.4.1/html/gl_get_line.html +++ /dev/null @@ -1,2295 +0,0 @@ -<head> -<title>Manual Page</title> -</head> -<body> -<pre> -</pre><h2>NAME</h2><pre> - gl_get_line, new_GetLine, del_GetLine, - gl_customize_completion, gl_change_terminal, - gl_configure_getline, gl_load_history, gl_save_history, - gl_group_history, gl_show_history, gl_watch_fd, - gl_terminal_size, gl_resize_history, gl_limit_history, - gl_clear_history, gl_toggle_history, gl_lookup_history, - gl_state_of_history, gl_range_of_history, - gl_size_of_history, gl_echo_mode, gl_replace_prompt, - gl_prompt_style, gl_ignore_signal, gl_trap_signal, - gl_last_signal - allow the user to compose an input line - -</pre><h2>SYNOPSIS</h2><pre> - #include <stdio.h> - #include <libtecla.h> - - GetLine *new_GetLine(size_t linelen, size_t histlen); - - GetLine *del_GetLine(GetLine *gl); - - char *gl_get_line(GetLine *gl, const char *prompt, - const char *start_line, int start_pos); - - int gl_customize_completion(GetLine *gl, void *data, - CplMatchFn *match_fn); - - int gl_change_terminal(GetLine *gl, FILE *input_fp, - FILE *output_fp, const char *term); - - int gl_configure_getline(GetLine *gl, - const char *app_string, - const char *app_file, - const char *user_file); - - int gl_save_history(GetLine *gl, const char *filename, - const char *comment, int max_lines); - - int gl_load_history(GetLine *gl, const char *filename, - const char *comment); - - int gl_watch_fd(GetLine *gl, int fd, GlFdEvent event, - GlFdEventFn *callback, void *data); - - int gl_group_history(GetLine *gl, unsigned stream); - - int gl_show_history(GetLine *gl, FILE *fp, - const char *fmt, int all_groups, - int max_lines); - - int gl_resize_history(GetLine *gl, size_t bufsize); - - void gl_limit_history(GetLine *gl, int max_lines); - void gl_clear_history(GetLine *gl, int all_groups); - - void gl_toggle_history(GetLine *gl, int enable); - - GlTerminalSize gl_terminal_size(GetLine *gl, - int def_ncolumn, - int def_nline); - - int gl_lookup_history(GetLine *gl, unsigned long id, - GlHistoryLine *hline); - - void gl_state_of_history(GetLine *gl, - GlHistoryState *state); - - void gl_range_of_history(GetLine *gl, - GlHistoryRange *range); - - void gl_size_of_history(GetLine *gl, GlHistorySize *size); - - void gl_echo_mode(GetLine *gl, int enable); - - void gl_replace_prompt(GetLine *gl, const char *prompt); - - void gl_prompt_style(GetLine *gl, GlPromptStyle style); - - int gl_ignore_signal(GetLine *gl, int signo); - - int gl_trap_signal(GetLine *gl, int signo, unsigned flags, - GlAfterSignal after, int errno_value); - - int gl_last_signal(const GetLine *gl); - - - -</pre><h2>DESCRIPTION</h2><pre> - The gl_get_line() function is part of the tecla library (see - the <a href="libtecla.html">libtecla(3)</a> man page). If the user is typing at a termi- - nal, it prompts them for an line of input, then provides - interactive editing facilities, similar to those of the unix - tcsh shell. In addition to simple command-line editing, it - supports recall of previously entered command lines, TAB - completion of file names, and in-line wild-card expansion of - filenames. - - -</pre><h2>AN EXAMPLE</h2><pre> - The following shows a complete example of how to use the - gl_get_line() function to get input from the user: - - #include <stdio.h> - #include <locale.h> - #include <libtecla.h> - int main(int argc, char *argv[]) - { - char *line; /* The line that the user typed */ - GetLine *gl; /* The gl_get_line() resource object */ - - setlocale(LC_CTYPE, ""); /* Adopt the user's choice */ - /* of character set. */ - - gl = new_GetLine(1024, 2048); - if(!gl) - return 1; - - while((line=gl_get_line(gl, "$ ", NULL, -1)) != NULL && - strcmp(line, "exit\n") != 0) - printf("You typed: %s\n", line); - - gl = del_GetLine(gl); - return 0; - } - - In the example, first the resources needed by the - gl_get_line() function are created by calling new_GetLine(). - This allocates the memory used in subsequent calls to the - gl_get_line() function, including the history buffer for - recording previously entered lines. Then one or more lines - are read from the user, until either an error occurs, or the - user types exit. Then finally the resources that were allo- - cated by new_GetLine(), are returned to the system by cal- - ling del_GetLine(). Note the use of the NULL return value of - del_GetLine() to make gl NULL. This is a safety precaution. - If the program subsequently attempts to pass gl to - gl_get_line(), said function will complain, and return an - error, instead of attempting to use the deleted resource - object. - - - -</pre><h2>THE FUNCTIONS USED IN THE EXAMPLE</h2><pre> - The descriptions of the functions used in the example are as - follows: - - GetLine *new_GetLine(size_t linelen, size_t histlen) - - This function creates the resources used by the - gl_get_line() function and returns an opaque pointer to the - object that contains them. The maximum length of an input - line is specified via the linelen argument, and the number - of bytes to allocate for storing history lines is set by the - histlen argument. History lines are stored back-to-back in a - single buffer of this size. Note that this means that the - number of history lines that can be stored at any given - time, depends on the lengths of the individual lines. If - you want to place an upper limit on the number of lines that - can be stored, see the gl_limit_history() function described - later. If you don't want history at all, specify histlen as - zero, and no history buffer will be allocated. - - On error, a message is printed to stderr and NULL is - returned. - - GetLine *del_GetLine(GetLine *gl) - - This function deletes the resources that were returned by a - previous call to new_GetLine(). It always returns NULL (ie a - deleted object). It does nothing if the gl argument is NULL. - - char *gl_get_line(GetLine *gl, const char *prompt, - const char *start_line, int start_pos); - - The gl_get_line() function can be called any number of times - to read input from the user. The gl argument must have been - previously returned by a call to new_GetLine(). The prompt - argument should be a normal NUL terminated string, specify- - ing the prompt to present the user with. By default prompts - are displayed literally, but if enabled with the - gl_prompt_style() function (see later), prompts can contain - directives to do underlining, switch to and from bold fonts, - or turn highlighting on and off. - - If you want to specify the initial contents of the line, for - the user to edit, pass the desired string via the start_line - argument. You can then specify which character of this line - the cursor is initially positioned over, using the start_pos - argument. This should be -1 if you want the cursor to follow - the last character of the start line. If you don't want to - preload the line in this manner, send start_line as NULL, - and set start_pos to -1. - - The gl_get_line() function returns a pointer to the line - entered by the user, or NULL on error or at the end of the - input. The returned pointer is part of the specified gl - resource object, and thus should not be free'd by the - caller, or assumed to be unchanging from one call to the - next. When reading from a user at a terminal, there will - always be a newline character at the end of the returned - line. When standard input is being taken from a pipe or a - file, there will similarly be a newline unless the input - line was too long to store in the internal buffer. In the - latter case you should call gl_get_line() again to read the - rest of the line. Note that this behavior makes - gl_get_line() similar to fgets(). In fact when stdin isn't - connected to a terminal,gl_get_line() just calls fgets(). - - -</pre><h2>OPTIONAL PROMPT FORMATTING</h2><pre> - Whereas by default the prompt string that you specify is - displayed literally, without any special interpretation of - the characters within it, the gl_prompt_style() function can - be used to enable optional formatting directives within the - prompt. - - void gl_prompt_style(GetLine *gl, GlPromptStyle style); - - The style argument, which specifies the formatting style, - can take any of the following values: - - GL_FORMAT_PROMPT - In this style, the formatting - directives described below, when - included in prompt strings, are - interpreted as follows: - - %B - Display subsequent - characters with a bold - font. - %b - Stop displaying characters - with the bold font. - %F - Make subsequent characters - flash. - %f - Turn off flashing - characters. - %U - Underline subsequent - characters. - %u - Stop underlining - characters. - %P - Switch to a pale (half - brightness) font. - %p - Stop using the pale font. - %S - Highlight subsequent - characters (also known as - standout mode). - %s - Stop highlighting - characters. - %V - Turn on reverse video. - %v - Turn off reverse video. - %% - Display a single % - character. - - For example, in this mode, a prompt - string like "%UOK%u$ " would - display the prompt "OK$ ", - but with the OK part - underlined. - - Note that although a pair of - characters that starts with a % - character, but doesn't match any of - the above directives is displayed - literally, if a new directive is - subsequently introduced which does - match, the displayed prompt will - change, so it is better to always - use %% to display a literal %. - - Also note that not all terminals - support all of these text - attributes, and that some substitute - a different attribute for missing - ones. - - GL_LITERAL_PROMPT - In this style, the prompt string is - printed literally. This is the - default style. - - - -</pre><h2>THE AVAILABLE KEY BINDING FUNCTIONS</h2><pre> - The gl_get_line() function provides a number of functions - which can be bound to key sequences. The names of these - functions, and what they do, are given below. - - user-interrupt - Send a SIGINT signal to the - parent process. - abort - Send a SIGABRT signal to the - parent process. - suspend - Suspend the parent process. - stop-output - Pause terminal output. - start-output - Resume paused terminal output. - literal-next - Arrange for the next character - to be treated as a normal - character. This allows control - characters to be entered. - cursor-right - Move the cursor one character - right. - cursor-left - Move the cursor one character - left. - insert-mode - Toggle between insert mode and - overwrite mode. - beginning-of-line - Move the cursor to the - beginning of the line. - end-of-line - Move the cursor to the end of - the line. - delete-line - Delete the contents of the - current line. - kill-line - Delete everything that follows - the cursor. - backward-kill-line - Delete all characters between - the cursor and the start of the - line. - forward-word - Move to the end of the word - which follows the cursor. - forward-to-word - Move the cursor to the start of - the word that follows the - cursor. - backward-word - Move to the start of the word - which precedes the cursor. - goto-column - Move the cursor to the - 1-relative column in the line - specified by any preceding - digit-argument sequences (see - ENTERING REPEAT COUNTS below). - find-parenthesis - If the cursor is currently - over a parenthesis character, - move it to the matching - parenthesis character. If not - over a parenthesis character - move right to the next close - parenthesis. - forward-delete-char - Delete the character under the - cursor. - backward-delete-char - Delete the character which - precedes the cursor. - list-or-eof - This is intended for binding - to ^D. When invoked when the - cursor is within the line it - displays all possible - completions then redisplays - the line unchanged. When - invoked on an empty line, it - signals end-of-input (EOF) to - the caller of gl_get_line(). - del-char-or-list-or-eof - This is intended for binding - to ^D. When invoked when the - cursor is within the line it - invokes forward-delete-char. - When invoked at the end of the - line it displays all possible - completions then redisplays - the line unchanged. When - invoked on an empty line, it - signals end-of-input (EOF) to - the caller of gl_get_line(). - forward-delete-word - Delete the word which follows - the cursor. - backward-delete-word - Delete the word which precedes - the cursor. - upcase-word - Convert all of the characters - of the word which follows the - cursor, to upper case. - downcase-word - Convert all of the characters - of the word which follows the - cursor, to lower case. - capitalize-word - Capitalize the word which - follows the cursor. - change-case - If the next character is upper - case, toggle it to lower case - and vice versa. - redisplay - Redisplay the line. - clear-screen - Clear the terminal, then - redisplay the current line. - transpose-chars - Swap the character under the - cursor with the character just - before the cursor. - set-mark - Set a mark at the position of - the cursor. - exchange-point-and-mark - Move the cursor to the last - mark that was set, and move - the mark to where the cursor - used to be. - kill-region - Delete the characters that lie - between the last mark that was - set, and the cursor. - copy-region-as-kill - Copy the text between the mark - and the cursor to the cut - buffer, without deleting the - original text. - yank - Insert the text that was last - deleted, just before the - current position of the cursor. - append-yank - Paste the current contents of - the cut buffer, after the - cursor. - up-history - Recall the next oldest line - that was entered. Note that - in vi mode you are left in - command mode. - down-history - Recall the next most recent - line that was entered. If no - history recall session is - currently active, the next - line from a previous recall - session is recalled. Note that - in vi mode you are left in - command mode. - history-search-backward - Recall the next oldest line - who's prefix matches the string - which currently precedes the - cursor (in vi command-mode the - character under the cursor is - also included in the search - string). Note that in vi mode - you are left in command mode. - history-search-forward - Recall the next newest line - who's prefix matches the string - which currently precedes the - cursor (in vi command-mode the - character under the cursor is - also included in the search - string). Note that in vi mode - you are left in command mode. - history-re-search-backward -Recall the next oldest line - who's prefix matches that - established by the last - invocation of either - history-search-forward or - history-search-backward. - history-re-search-forward - Recall the next newest line - who's prefix matches that - established by the last - invocation of either - history-search-forward or - history-search-backward. - complete-word - Attempt to complete the - incomplete word which - precedes the cursor. Unless - the host program has customized - word completion, filename - completion is attempted. In vi - commmand mode the character - under the cursor is also - included in the word being - completed, and you are left in - vi insert mode. - expand-filename - Within the command line, expand - wild cards, tilde expressions - and dollar expressions in the - filename which immediately - precedes the cursor. In vi - commmand mode the character - under the cursor is also - included in the filename being - expanded, and you are left in - vi insert mode. - list-glob - List any filenames which match - the wild-card, tilde and dollar - expressions in the filename - which immediately precedes the - cursor, then redraw the input - line unchanged. - list-history - Display the contents of the - history list for the current - history group. If a repeat - count of > 1 is specified, - only that many of the most - recent lines are displayed. - See the "ENTERING REPEAT - COUNTS" section. - read-from-file - Temporarily switch to reading - input from the file who's - name precedes the cursor. - read-init-files - Re-read teclarc configuration - files. - beginning-of-history - Move to the oldest line in the - history list. Note that in vi - mode you are left in command - mode. - end-of-history - Move to the newest line in the - history list (ie. the current - line). Note that in vi mode - this leaves you in command - mode. - digit-argument - Enter a repeat count for the - next key-binding function. - For details, see the ENTERING - REPEAT COUNTS section. - newline - Terminate and return the - current contents of the - line, after appending a - newline character. The newline - character is normally '\n', - but will be the first - character of the key-sequence - that invoked the newline - action, if this happens to be - a printable character. If the - action was invoked by the - '\n' newline character or the - '\r' carriage return - character, the line is - appended to the history - buffer. - repeat-history - Return the line that is being - edited, then arrange for the - next most recent entry in the - history buffer to be recalled - when gl_get_line() is - next called. Repeatedly - invoking this action causes - successive historical input - lines to be re-executed. Note - that this action is equivalent - to the 'Operate' action in - ksh. - ring-bell - Ring the terminal bell, unless - the bell has been silenced via - the nobeep configuration - option (see the THE TECLA - CONFIGURATION FILE section). - forward-copy-char - Copy the next character into - the cut buffer (NB. use repeat - counts to copy more than one). - backward-copy-char - Copy the previous character - into the cut buffer. - forward-copy-word - Copy the next word into the cut - buffer. - backward-copy-word - Copy the previous word into the - cut buffer. - forward-find-char - Move the cursor to the next - occurrence of the next - character that you type. - backward-find-char - Move the cursor to the last - occurrence of the next - character that you type. - forward-to-char - Move the cursor to the - character just before the next - occurrence of the next - character that the user types. - backward-to-char - Move the cursor to the - character just after the last - occurrence before the cursor - of the next character that the - user types. - repeat-find-char - Repeat the last - backward-find-char, - forward-find-char, - backward-to-char or - forward-to-char. - invert-refind-char - Repeat the last - backward-find-char, - forward-find-char, - backward-to-char, or - forward-to-char in the - opposite direction. - delete-to-column - Delete the characters from the - cursor up to the column that - is specified by the repeat - count. - delete-to-parenthesis - Delete the characters from the - cursor up to and including - the matching parenthesis, or - next close parenthesis. - forward-delete-find - Delete the characters from the - cursor up to and including the - following occurence of the - next character typed. - backward-delete-find - Delete the characters from the - cursor up to and including the - preceding occurence of the - next character typed. - forward-delete-to - Delete the characters from the - cursor up to, but not - including, the following - occurence of the next - character typed. - backward-delete-to - Delete the characters from the - cursor up to, but not - including, the preceding - occurence of the next - character typed. - delete-refind - Repeat the last *-delete-find - or *-delete-to action. - delete-invert-refind - Repeat the last *-delete-find - or *-delete-to action, in the - opposite direction. - copy-to-column - Copy the characters from the - cursor up to the column that - is specified by the repeat - count, into the cut buffer. - copy-to-parenthesis - Copy the characters from the - cursor up to and including - the matching parenthesis, or - next close parenthesis, into - the cut buffer. - forward-copy-find - Copy the characters from the - cursor up to and including the - following occurence of the - next character typed, into the - cut buffer. - backward-copy-find - Copy the characters from the - cursor up to and including the - preceding occurence of the - next character typed, into the - cut buffer. - forward-copy-to - Copy the characters from the - cursor up to, but not - including, the following - occurence of the next - character typed, into the cut - buffer. - backward-copy-to - Copy the characters from the - cursor up to, but not - including, the preceding - occurence of the next - character typed, into the cut - buffer. - copy-refind - Repeat the last *-copy-find - or *-copy-to action. - copy-invert-refind - Repeat the last *-copy-find - or *-copy-to action, in the - opposite direction. - vi-mode - Switch to vi mode from emacs - mode. - emacs-mode - Switch to emacs mode from vi - mode. - vi-insert - From vi command mode, switch to - insert mode. - vi-overwrite - From vi command mode, switch to - overwrite mode. - vi-insert-at-bol - From vi command mode, move the - cursor to the start of the line - and switch to insert mode. - vi-append-at-eol - From vi command mode, move the - cursor to the end of the line - and switch to append mode. - vi-append - From vi command mode, move the - cursor one position right, and - switch to insert mode. - vi-replace-char - From vi command mode, replace - the character under the cursor - with the the next character - entered. - vi-forward-change-char - From vi command mode, delete - the next character then enter - insert mode. - vi-backward-change-char - From vi command mode, delete - the preceding character then - enter insert mode. - vi-forward-change-word - From vi command mode, delete - the next word then enter - insert mode. - vi-backward-change-word - From vi command mode, delete - the preceding word then - enter insert mode. - vi-change-rest-of-line - From vi command mode, delete - from the cursor to the end of - the line, then enter insert - mode. - vi-change-line - From vi command mode, delete - the current line, then enter - insert mode. - vi-change-to-bol - From vi command mode, delete - all characters between the - cursor and the beginning of - the line, then enter insert - mode. - vi-change-to-column - From vi command mode, delete - the characters from the cursor - up to the column that is - specified by the repeat count, - then enter insert mode. - vi-change-to-parenthesis - Delete the characters from the - cursor up to and including - the matching parenthesis, or - next close parenthesis, then - enter vi insert mode. - vi-forward-change-find - From vi command mode, delete - the characters from the - cursor up to and including the - following occurence of the - next character typed, then - enter insert mode. - vi-backward-change-find - From vi command mode, delete - the characters from the - cursor up to and including the - preceding occurence of the - next character typed, then - enter insert mode. - vi-forward-change-to - From vi command mode, delete - the characters from the - cursor up to, but not - including, the following - occurence of the next - character typed, then enter - insert mode. - vi-backward-change-to - From vi command mode, delete - the characters from the - cursor up to, but not - including, the preceding - occurence of the next - character typed, then enter - insert mode. - vi-change-refind - Repeat the last - vi-*-change-find or - vi-*-change-to action. - vi-change-invert-refind - Repeat the last - vi-*-change-find or - vi-*-change-to action, in the - opposite direction. - vi-undo - In vi mode, undo the last - editing operation. - vi-repeat-change - In vi command mode, repeat the - last command that modified the - line. - - -</pre><h2>DEFAULT KEY BINDINGS IN EMACS MODE</h2><pre> - The following default key bindings, which can be overriden - by the tecla configuration file, are designed to mimic most - of the bindings of the unix tcsh shell, when it is in emacs - editing mode. - - This is the default editing mode of the tecla library. - - Note that a key sequence like ^A or C-a means hold the - control-key down while pressing the letter A, and that where - you see \E or M- in a binding, this represents the escape - key or the Meta modifier key. Also note that to - gl_get_line(), pressing the escape key before a key is - equivalent to pressing the meta key at the same time as that - key. Thus the key sequence M-p can be typed in two ways, by - pressing the escape key, followed by pressing p, or by - pressing the Meta key at the same time as p. - - Under UNIX the terminal driver sets a number of special keys - for certain functions. The tecla library attempts to use the - same keybindings to maintain consistency. The key sequences - shown for the following 6 bindings are thus just examples of - what they will probably be set to. If you have used the stty - command to change these keys, then the default bindings - should match. - - ^C -> user-interrupt - ^\ -> abort - ^Z -> suspend - ^Q -> start-output - ^S -> stop-output - ^V -> literal-next - - The cursor keys are refered to by name, as follows. This is - necessary because different types of terminals generate dif- - ferent key sequences when their cursor keys are pressed. - - right -> cursor-right - left -> cursor-left - up -> up-history - down -> down-history - - The remaining bindings don't depend on the terminal sett- - tings. - - ^F -> cursor-right - ^B -> cursor-left - M-i -> insert-mode - ^A -> beginning-of-line - ^E -> end-of-line - ^U -> delete-line - ^K -> kill-line - M-f -> forward-word - M-b -> backward-word - ^D -> del-char-or-list-or-eof - ^H -> backward-delete-char - ^? -> backward-delete-char - M-d -> forward-delete-word - M-^H -> backward-delete-word - M-^? -> backward-delete-word - M-u -> upcase-word - M-l -> downcase-word - M-c -> capitalize-word - ^R -> redisplay - ^L -> clear-screen - ^T -> transpose-chars - ^@ -> set-mark - ^X^X -> exchange-point-and-mark - ^W -> kill-region - M-w -> copy-region-as-kill - ^Y -> yank - ^P -> up-history - ^N -> down-history - M-p -> history-search-backward - M-n -> history-search-forward - ^I -> complete-word - ^X* -> expand-filename - ^X^F -> read-from-file - ^X^R -> read-init-files - ^Xg -> list-glob - ^Xh -> list-history - M-< -> beginning-of-history - M-> -> end-of-history - \n -> newline - \r -> newline - M-o -> repeat-history - M-^V -> vi-mode - - M-0, M-1, ... M-9 -> digit-argument (see below) - - Note that ^I is what the TAB key generates, and that ^@ can - be generated not only by pressing the control key and the @ - key simultaneously, but also by pressing the control key and - the space bar at the same time. - - -</pre><h2>DEFAULT KEY BINDINGS IN VI MODE</h2><pre> - The following default key bindings are designed to mimic the - vi style of editing as closely as possible. This means that - very few editing functions are provided in the initial char- - acter input mode, editing functions instead being provided - by the vi command mode. Vi command mode is entered whenever - the escape character is pressed, or whenever a key-sequence - that starts with a meta character is entered. In addition to - mimicing vi, libtecla provides bindings for tab completion, - wild-card expansion of file names, and historical line - recall. - - To learn how to tell the tecla library to use vi mode - instead of the default emacs editing mode, see the section - entitled THE TECLA CONFIGURATION FILE. - - As already mentioned above in the emacs section, Note that a - key sequence like ^A or C-a means hold the control-key down - while pressing the letter A, and that where you see \E or M- - in a binding, this represents the escape key or the Meta - modifier key. Also note that to gl_get_line(), pressing the - escape key before a key is equivalent to pressing the meta - key at the same time as that key. Thus the key sequence M-p - can be typed in two ways, by pressing the escape key, fol- - lowed by pressing p, or by pressing the Meta key at the same - time as p. - - Under UNIX the terminal driver sets a number of special keys - for certain functions. The tecla library attempts to use the - same keybindings to maintain consistency, binding them both - in input mode and in command mode. The key sequences shown - for the following 6 bindings are thus just examples of what - they will probably be set to. If you have used the stty com- - mand to change these keys, then the default bindings should - match. - - ^C -> user-interrupt - ^\ -> abort - ^Z -> suspend - ^Q -> start-output - ^S -> stop-output - ^V -> literal-next - M-^C -> user-interrupt - M-^\ -> abort - M-^Z -> suspend - M-^Q -> start-output - M-^S -> stop-output - - Note that above, most of the bindings are defined twice, - once as a raw control code like ^C and then a second time as - a meta character like M-^C. The former is the binding for vi - input mode, whereas the latter is the binding for vi command - mode. Once in command mode all key-sequences that the user - types that they don't explicitly start with an escape or a - meta key, have their first key secretly converted to a meta - character before the key sequence is looked up in the key - binding table. Thus, once in command mode, when you type the - letter i, for example, the tecla library actually looks up - the binding for M-i. - - The cursor keys are refered to by name, as follows. This is - necessary because different types of terminals generate dif- - ferent key sequences when their cursor keys are pressed. - - right -> cursor-right - left -> cursor-left - up -> up-history - down -> down-history - - The cursor keys normally generate a keysequence that start - with an escape character, so beware that using the arrow - keys will put you into command mode (if you aren't already - in command mode). - - The following are the terminal-independent key bindings for - vi input mode. - - ^D -> list-or-eof - ^G -> list-glob - ^H -> backward-delete-char - ^I -> complete-word - \r -> newline - \n -> newline - ^L -> clear-screen - ^N -> down-history - ^P -> up-history - ^R -> redisplay - ^U -> backward-kill-line - ^W -> backward-delete-word - ^X* -> expand-filename - ^X^F -> read-from-file - ^X^R -> read-init-files - ^? -> backward-delete-char - - The following are the key bindings that are defined in vi - command mode, this being specified by them all starting with - a meta character. As mentioned above, once in command mode - the initial meta character is optional. For example, you - might enter command mode by typing Esc, and then press h - twice to move the cursor two positions to the left. Both h - characters get quietly converted to M-h before being com- - pared to the key-binding table, the first one because Escape - followed by a character is always converted to the - equivalent meta character, and the second because command - mode was already active. - - M-\ -> cursor-right (Meta-space) - M-$ -> end-of-line - M-* -> expand-filename - M-+ -> down-history - M-- -> up-history - M-< -> beginning-of-history - M-> -> end-of-history - M-^ -> beginning-of-line - M-; -> repeat-find-char - M-, -> invert-refind-char - M-| -> goto-column - M-~ -> change-case - M-. -> vi-repeat-change - M-% -> find-parenthesis - M-a -> vi-append - M-A -> vi-append-at-eol - M-b -> backward-word - M-B -> backward-word - M-C -> vi-change-rest-of-line - M-cb -> vi-backward-change-word - M-cB -> vi-backward-change-word - M-cc -> vi-change-line - M-ce -> vi-forward-change-word - M-cE -> vi-forward-change-word - M-cw -> vi-forward-change-word - M-cW -> vi-forward-change-word - M-cF -> vi-backward-change-find - M-cf -> vi-forward-change-find - M-cT -> vi-backward-change-to - M-ct -> vi-forward-change-to - M-c; -> vi-change-refind - M-c, -> vi-change-invert-refind - M-ch -> vi-backward-change-char - M-c^H -> vi-backward-change-char - M-c^? -> vi-backward-change-char - M-cl -> vi-forward-change-char - M-c\ -> vi-forward-change-char (Meta-c-space) - M-c^ -> vi-change-to-bol - M-c0 -> vi-change-to-bol - M-c$ -> vi-change-rest-of-line - M-c| -> vi-change-to-column - M-c% -> vi-change-to-parenthesis - M-dh -> backward-delete-char - M-d^H -> backward-delete-char - M-d^? -> backward-delete-char - M-dl -> forward-delete-char - M-d -> forward-delete-char (Meta-d-space) - M-dd -> delete-line - M-db -> backward-delete-word - M-dB -> backward-delete-word - M-de -> forward-delete-word - M-dE -> forward-delete-word - M-dw -> forward-delete-word - M-dW -> forward-delete-word - M-dF -> backward-delete-find - M-df -> forward-delete-find - M-dT -> backward-delete-to - M-dt -> forward-delete-to - M-d; -> delete-refind - M-d, -> delete-invert-refind - M-d^ -> backward-kill-line - M-d0 -> backward-kill-line - M-d$ -> kill-line - M-D -> kill-line - M-d| -> delete-to-column - M-d% -> delete-to-parenthesis - M-e -> forward-word - M-E -> forward-word - M-f -> forward-find-char - M-F -> backward-find-char - M-- -> up-history - M-h -> cursor-left - M-H -> beginning-of-history - M-i -> vi-insert - M-I -> vi-insert-at-bol - M-j -> down-history - M-J -> history-search-forward - M-k -> up-history - M-K -> history-search-backward - M-l -> cursor-right - M-L -> end-of-history - M-n -> history-re-search-forward - M-N -> history-re-search-backward - M-p -> append-yank - M-P -> yank - M-r -> vi-replace-char - M-R -> vi-overwrite - M-s -> vi-forward-change-char - M-S -> vi-change-line - M-t -> forward-to-char - M-T -> backward-to-char - M-u -> vi-undo - M-w -> forward-to-word - M-W -> forward-to-word - M-x -> forward-delete-char - M-X -> backward-delete-char - M-yh -> backward-copy-char - M-y^H -> backward-copy-char - M-y^? -> backward-copy-char - M-yl -> forward-copy-char - M-y\ -> forward-copy-char (Meta-y-space) - M-ye -> forward-copy-word - M-yE -> forward-copy-word - M-yw -> forward-copy-word - M-yW -> forward-copy-word - M-yb -> backward-copy-word - M-yB -> backward-copy-word - M-yf -> forward-copy-find - M-yF -> backward-copy-find - M-yt -> forward-copy-to - M-yT -> backward-copy-to - M-y; -> copy-refind - M-y, -> copy-invert-refind - M-y^ -> copy-to-bol - M-y0 -> copy-to-bol - M-y$ -> copy-rest-of-line - M-yy -> copy-line - M-Y -> copy-line - M-y| -> copy-to-column - M-y% -> copy-to-parenthesis - M-^E -> emacs-mode - M-^H -> cursor-left - M-^? -> cursor-left - M-^L -> clear-screen - M-^N -> down-history - M-^P -> up-history - M-^R -> redisplay - M-^D -> list-or-eof - M-^I -> complete-word - M-\r -> newline - M-\n -> newline - M-^X^R -> read-init-files - M-^Xh -> list-history - - M-0, M-1, ... M-9 -> digit-argument (see below) - - Note that ^I is what the TAB key generates. - - -</pre><h2>ENTERING REPEAT COUNTS</h2><pre> - Many of the key binding functions described previously, take - an optional count, typed in before the target keysequence. - This is interpreted as a repeat count by most bindings. A - notable exception is the goto-column binding, which inter- - prets the count as a column number. - - By default you can specify this count argument by pressing - the meta key while typing in the numeric count. This relies - on the digit-argument action being bound to Meta-0, Meta-1 - etc. Once any one of these bindings has been activated, you - can optionally take your finger off the meta key to type in - the rest of the number, since every numeric digit thereafter - is treated as part of the number, unless it is preceded by - the literal-next binding. As soon as a non-digit, or literal - digit key is pressed the repeat count is terminated and - either causes the just typed character to be added to the - line that many times, or causes the next key-binding func- - tion to be given that argument. - - For example, in emacs mode, typing: - - M-12a - - causes the letter 'a' to be added to the line 12 times, - whereas - - M-4M-c - - Capitalizes the next 4 words. - - In vi command mode the Meta modifier is automatically added - to all characters typed in, so to enter a count in vi - command-mode, just involves typing in the number, just as at - it does in the vi editor itself. So for example, in vi com- - mand mode, typing: - - 4w2x - - moves the cursor four words to the right, then deletes two - characters. - - You can also bind digit-argument to other key sequences. If - these end in a numeric digit, that digit gets appended to - the current repeat count. If it doesn't end in a numeric - digit, a new repeat count is started with a value of zero, - and can be completed by typing in the number, after letting - go of the key which triggered the digit-argument action. - - -</pre><h2>THE TECLA CONFIGURATION FILE</h2><pre> - By default, the first call to gl_get_line() looks for a file - called .teclarc in your home directory (ie. ~/.teclarc). If - it finds this file, it reads it, interpreting each line as - defining a new key binding or an editing configuration - option. Since the emacs keybindings are installed by - default, if you want to use the non-default vi editing mode, - the most important item to go in this file is the following - line: - - edit-mode vi - - This will re-configure the default bindings for vi-mode. The - complete set of arguments that this command accepts are: - - vi - Install key-bindings like those of the vi - editor. - emacs - Install key-bindings like those of the emacs - editor. This is the default. - none - Use just the native line editing facilities - provided by the terminal driver. - - To prevent the terminal bell from being rung, such as when - an unrecognized control-sequence is typed, place the follow- - ing line in the configuration file: - - nobeep - - An example of a key binding line in the configuration file - is the following. - - bind M-[2~ insert-mode - - On many keyboards, the above key sequence is generated when - one presses the insert key, so with this keybinding, one can - toggle between the emacs-mode insert and overwrite modes by - hitting one key. One could also do it by typing out the - above sequence of characters one by one. As explained above, - the M- part of this sequence can be typed either by pressing - the escape key before the following key, or by pressing the - Meta key at the same time as the following key. Thus if you - had set the above key binding, and the insert key on your - keyboard didn't generate the above key sequence, you could - still type it in either of the following 2 ways. - - 1. Hit the escape key momentarily, then press '[', then '2', then - finally '~'. - - 2. Press the meta key at the same time as pressing the '[' key, - then press '2', then '~'. - - If you set a keybinding for a key-sequence that is already - bound to a function, the new binding overrides the old one. - If in the new binding you omit the name of the new function - to bind to the key-sequence, the original binding becomes - undefined. - - Starting with versions of libtecla later than 1.3.3 it is - now possible to bind keysequences that begin with a print- - able character. Previously key-sequences were required to - start with a control or meta character. - - Note that the special keywords "up", "down", "left" and - "right" refer to the arrow keys, and are thus not treated as - keysequences. So, for example, to rebind the up and down - arrow keys to use the history search mechanism instead of - the simple history recall method, you could place the fol- - lowing in your configuration file: - - bind up history-search-backwards - bind down history-search-backwards - - To unbind an existing binding, you can do this with the bind - command by omitting to name any action to rebind the key - sequence to. For example, by not specifying an action func- - tion, the following command unbinds the default beginning- - of-line action from the ^A key sequence: - - bind ^A - - -</pre><h2>ALTERNATE CONFIGURATION SOURCES</h2><pre> - As mentioned above, by default users have the option of con- - figuring the behavior of gl_get_line() via a configuration - file called .teclarc in their home directories. The fact - that all applications share this same configuration file is - both an advantage and a disadvantage. In most cases it is - an advantage, since it encourages uniformity, and frees the - user from having to configure each application separately. - In some applications, however, this single means of confi- - guration is a problem. This is particularly true of embedded - software, where there's no filesystem to read a configura- - tion file from, and also in applications where a radically - different choice of keybindings is needed to emulate a - legacy keyboard interface. To cater for such cases, the - following function allows the application to control where - configuration information is read from. - - - int gl_configure_getline(GetLine *gl, - const char *app_string, - const char *app_file, - const char *user_file); - - - It allows the configuration commands that would normally be - read from a user's ~/.teclarc file, to be read from any or - none of, a string, an application specific configuration - file, and/or a user-specific configuration file. If this - function is called before the first call to gl_get_line(), - the default behavior of reading ~/.teclarc on the first call - to gl_get_line() is disabled, so all configuration must be - achieved using the configuration sources specified with this - function. - - If app_string != NULL, then it is interpreted as a string - containing one or more configuration commands, separated - from each other in the string by embedded newline charac- - ters. If app_file != NULL then it is interpreted as the full - pathname of an application-specific configuration file. If - user_file != NULL then it is interpreted as the full path- - name of a user-specific configuration file, such as - ~/.teclarc. For example, in the following call, - - gl_configure_getline(gl, "edit-mode vi \n nobeep", - "/usr/share/myapp/teclarc", - "~/.teclarc"); - - the app_string argument causes the calling application to - start in vi edit-mode, instead of the default emacs mode, - and turns off the use of the terminal bell by the library. - It then attempts to read system-wide configuration commands - from an optional file called /usr/share/myapp/teclarc, then - finally reads user-specific configuration commands from an - optional .teclarc file in the user's home directory. Note - that the arguments are listed in ascending order of prior- - ity, with the contents of app_string being potentially over- - riden by commands in app_file, and commands in app_file - potentially being overriden by commands in user_file. - You can call this function as many times as needed, the - results being cumulative, but note that copies of any - filenames specified via the app_file and user_file arguments - are recorded internally for subsequent use by the read- - init-files key-binding function, so if you plan to call this - function multiple times, be sure that the last call speci- - fies the filenames that you want re-read when the user - requests that the configuration files be re-read. - - -</pre><h2>FILENAME AND TILDE COMPLETION</h2><pre> - With the default key bindings, pressing the TAB key (aka. - ^I) results in gl_get_line() attempting to complete the - incomplete filename that precedes the cursor. gl_get_line() - searches backwards from the cursor, looking for the start of - the filename, stopping when it hits either a space or the - start of the line. If more than one file has the specified - prefix, gl_get_line() completes the filename up to the point - at which the ambiguous matches start to differ, then lists - the possible matches. - - In addition to literally written filenames, gl_get_line() - can complete files that start with ~/ and ~user/ expressions - and that contain $envvar expressions. In particular, if you - hit TAB within an incomplete ~user, expression, - gl_get_line() will attempt to complete the username, listing - any ambiguous matches. - - The completion binding is implemented using the - cpl_word_completions() function, which is also available - separately to users of this library. See the - cpl_word_completions(3) man page for more details. - - -</pre><h2>CUSTOMIZED WORD COMPLETION</h2><pre> - If in your application, you would like to have TAB comple- - tion complete other things in addition to or instead of - filenames, you can arrange this by registering an alternate - completion callback function, via a call to the - gl_customize_completion() function. - - int gl_customize_completion(GetLine *gl, void *data, - CplMatchFn *match_fn); - - The data argument provides a way for your application to - pass arbitrary, application-specific information to the - callback function. This is passed to the callback every time - that it is called. It might for example, point to the symbol - table from which possible completions are to be sought. The - match_fn argument specifies the callback function to be - called. The CplMatchFn function type is defined in - libtecla.h, as is a CPL_MATCH_FN() macro that you can use to - declare and prototype callback functions. The declaration - and responsibilities of callback functions are described in - depth in the <a href="cpl_complete_word.html">cpl_complete_word(3)</a> man page. - - In brief, the callback function is responsible for looking - backwards in the input line, back from the point at which - the user pressed TAB, to find the start of the word being - completed. It then must lookup possible completions of this - word, and record them one by one in the WordCompletion - object that is passed to it as an argument, by calling the - cpl_add_completion() function. If the callback function - wishes to provide filename completion in addition to its own - specific completions, it has the option of itself calling - the builtin file-name completion callback. This also, is - documented in the <a href="cpl_complete_word.html">cpl_complete_word(3)</a> man page. - - Note that if you would like gl_get_line() to return the - current input line when a successful completion is been - made, you can arrange this when you call - cpl_add_completion(), by making the last character of the - continuation suffix a newline character. If you do this, the - input line will be updated to display the completion, - together with any contiuation suffix up to the newline char- - acter, then gl_get_line() will return this input line. - - -</pre><h2>FILENAME EXPANSION</h2><pre> - With the default key bindings, pressing ^X* causes - gl_get_line() to expand the filename that precedes the cur- - sor, replacing ~/ and ~user/ expressions with the - corresponding home directories, and replacing $envvar - expressions with the value of the specified environment - variable, then if there are any wildcards, replacing the so - far expanded filename with a space-separated list of the - files which match the wild cards. - - The expansion binding is implemented using the - ef_expand_file() function. See the <a href="ef_expand_file.html">ef_expand_file(3)</a> man - page for more details. - - -</pre><h2>RECALLING PREVIOUSLY TYPED LINES</h2><pre> - Every time that a new line is entered by the user, it is - appended to a list of historical input lines maintained - within the GetLine resource object. You can traverse up and - down this list using the up and down arrow keys. Alterna- - tively, you can do the same with the ^P, and ^N keys, and in - vi command mode you can alternatively use the k and j char- - acters. Thus pressing up-arrow once, replaces the current - input line with the previously entered line. Pressing up- - arrow again, replaces this with the line that was entered - before it, etc.. Having gone back one or more lines into the - history list, one can return to newer lines by pressing - down-arrow one or more times. If you do this sufficient - times, you will return to the original line that you were - entering when you first hit up-arrow. - - Note that in vi mode, all of the history recall functions - switch the library into command mode. - - In emacs mode the M-p and M-n keys work just like the ^P and - ^N keys, except that they skip all but those historical - lines which share the prefix that precedes the cursor. In vi - command mode the upper case K and J characters do the same - thing, except that the string that they search for includes - the character under the cursor as well as what precedes it. - - Thus for example, suppose that you were in emacs mode, and - you had just entered the following list of commands in the - order shown: - - ls ~/tecla/ - cd ~/tecla - ls -l getline.c - emacs ~/tecla/getline.c - - If you next typed: - - ls - - and then hit M-p, then rather than returning the previously - typed emacs line, which doesn't start with "ls", - gl_get_line() would recall the "ls -l getline.c" line. - Pressing M-p again would recall the "ls ~/tecla/" line. - - -</pre><h2>HISTORY FILES</h2><pre> - To save the contents of the history buffer before quitting - your application, and subsequently restore them when you - next start the application, the following functions are pro- - vided. - - - int gl_save_history(GetLine *gl, const char *filename, - const char *comment, int max_lines); - int gl_load_history(GetLine *gl, const char *filename, - const char *comment); - - - The filename argument specifies the name to give the history - file when saving, or the name of an existing history file, - when loading. This may contain home-directory and environ- - ment variable expressions, such as "~/.myapp_history" or - "$HOME/.myapp_history". - Along with each history line, extra information about it, - such as when it was entered by the user, and what its nest- - ing level is, is recorded as a comment preceding the line in - the history file. Writing this as a comment allows the his- - tory file to double as a command file, just in case you wish - to replay a whole session using it. Since comment prefixes - differ in different languages, the comment argument is pro- - vided for specifying the comment prefix. For example, if - your application were a unix shell, such as the bourne - shell, you would specify "#" here. Whatever you choose for - the comment character, you must specify the same prefix to - gl_load_history() that you used when you called - gl_save_history() to write the history file. - - The max_lines must be either -1 to specify that all lines in - the history list be saved, or a positive number specifying a - ceiling on how many of the most recent lines should be - saved. - - Both fuctions return non-zero on error, after writing an - error message to stderr. Note that gl_load_history() does - not consider the non-existence of a file to be an error. - - -</pre><h2>MULTIPLE HISTORY LISTS</h2><pre> - If your application uses a single GetLine object for enter- - ing many different types of input lines, you may wish - gl_get_line() to distinguish the different types of lines in - the history list, and only recall lines that match the - current type of line. To support this requirement, - gl_get_line() marks lines being recorded in the history list - with an integer identifier chosen by the application. Ini- - tially this identifier is set to 0 by new_GetLine(), but it - can be changed subsequently by calling gl_group_history(). - - - int gl_group_history(GetLine *gl, unsigned id); - - - The integer identifier id can be any number chosen by the - application, but note that gl_save_history() and - gl_load_history() preserve the association between identif- - iers and historical input lines between program invokations, - so you should choose fixed identifiers for the different - types of input line used by your application. - - Whenever gl_get_line() appends a new input line to the his- - tory list, the current history identifier is recorded with - it, and when it is asked to recall a historical input line, - it only recalls lines that are marked with the current iden- - tifier. - -</pre><h2>DISPLAYING HISTORY</h2><pre> - The history list can be displayed by calling - gl_show_history(). - - - int gl_show_history(GetLine *gl, FILE *fp, - const char *fmt, - int all_groups, - int max_lines); - - - This displays the current contents of the history list to - the stdio output stream fp. If the max_lines argument is - greater than or equal to zero, then no more than this number - of the most recent lines will be displayed. If the - all_groups argument is non-zero, lines from all history - groups are displayed. Otherwise just those of the currently - selected history group are displayed. The format string - argument, fmt, determines how the line is displayed. This - can contain arbitrary characters which are written verbatim, - interleaved with any of the following format directives: - - %D - The date on which the line was originally - entered, formatted like 2001-11-20. - %T - The time of day when the line was entered, - formatted like 23:59:59. - %N - The sequential entry number of the line in - the history buffer. - %G - The number of the history group which the - line belongs to. - %% - A literal % character. - %H - The history line itself. - - Thus a format string like "%D %T %H0 would output something - like: - - 2001-11-20 10:23:34 Hello world - - Note the inclusion of an explicit newline character in the - format string. - - -</pre><h2>LOOKING UP HISTORY</h2><pre> - The gl_lookup_history() function allows the calling applica- - tion to look up lines in the history list. - - - typedef struct { - const char *line; /* The requested historical */ - /* line. */ - unsigned group; /* The history group to which */ - /* the line belongs. */ - time_t timestamp; /* The date and time at which */ - /* the line was originally */ - /* entered. */ - } GlHistoryLine; - - int gl_lookup_history(GetLine *gl, unsigned long id, - GlHistoryLine *hline); - - - The id argument indicates which line to look up, where the - first line that was entered in the history list after - new_GetLine() was called, is denoted by 0, and subsequently - entered lines are denoted with successively higher numbers. - Note that the range of lines currently preserved in the his- - tory list can be queried by calling the - gl_range_of_history() function, described later. If the - requested line is in the history list, the details of the - line are recorded in the variable pointed to by the hline - argument, and 1 is returned. Otherwise 0 is returned, and - the variable pointed to by hline is left unchanged. - - Beware that the string returned in hline->line is part of - the history buffer, so it must not be modified by the - caller, and will be recycled on the next call to any func- - tion that takes gl as its argument. Therefore you should - make a private copy of this string if you need to keep it - around. - - -</pre><h2>MISCELLANEOUS HISTORY CONFIGURATION</h2><pre> - If you wish to change the size of the history buffer that - was originally specified in the call to new_GetLine(), you - can do so with the gl_resize_history() function. - - - int gl_resize_history(GetLine *gl, size_t histlen); - - - The histlen argument specifies the new size in bytes, and if - you specify this as 0, the buffer will be deleted. - - As mentioned in the discussion of new_GetLine(), the number - of lines that can be stored in the history buffer, depends - on the lengths of the individual lines. For example, a 1000 - byte buffer could equally store 10 lines of average length - 100 bytes, or 2 lines of average length 50 bytes. Although - the buffer is never expanded when new lines are added, a - list of pointers into the buffer does get expanded when - needed to accomodate the number of lines currently stored in - the buffer. To place an upper limit on the number of lines - in the buffer, and thus a ceiling on the amount of memory - used in this list, you can call the gl_limit_history() - function. - - - void gl_limit_history(GetLine *gl, int max_lines); - - - The max_lines should either be a positive number >= 0, - specifying an upper limit on the number of lines in the - buffer, or be -1 to cancel any previously specified limit. - When a limit is in effect, only the max_lines most recently - appended lines are kept in the buffer. Older lines are dis- - carded. - - To discard lines from the history buffer, use the - gl_clear_history() function. - - void gl_clear_history(GetLine *gl, int all_groups); - - The all_groups argument tells the function whether to delete - just the lines associated with the current history group - (see gl_group_history()), or all historical lines in the - buffer. - - The gl_toggle_history() function allows you to toggle his- - tory on and off without losing the current contents of the - history list. - - - void gl_toggle_history(GetLine *gl, int enable); - - - Setting the enable argument to 0 turns off the history - mechanism, and setting it to 1 turns it back on. When his- - tory is turned off, no new lines will be added to the his- - tory list, and history lookup key-bindings will act as - though there is nothing in the history buffer. - - -</pre><h2>QUERYING HISTORY INFORMATION</h2><pre> - The configured state of the history list can be queried with - the gl_history_state() function. - - - typedef struct { - int enabled; /* True if history is enabled */ - unsigned group; /* The current history group */ - int max_lines; /* The current upper limit on the */ - /* number of lines in the history */ - /* list, or -1 if unlimited. */ - } GlHistoryState; - - void gl_state_of_history(GetLine *gl, - GlHistoryState *state); - - On return, the status information is recorded in the vari- - able pointed to by the state argument. - - The gl_range_of_history() function returns the number and - range of lines in the history list. - - - typedef struct { - unsigned long oldest; /* The sequential entry number */ - /* of the oldest line in the */ - /* history list. */ - unsigned long newest; /* The sequential entry number */ - /* of the newest line in the */ - /* history list. */ - int nlines; /* The number of lines in the */ - /* history list. */ - } GlHistoryRange; - - void gl_range_of_history(GetLine *gl, GlHistoryRange *range); - - The return values are recorded in the variable pointed to by - the range argument. If the nlines member of this structure - is greater than zero, then the oldest and newest members - report the range of lines in the list, and - newest=oldest+nlines-1. Otherwise they are both zero. - - The gl_size_of_history() function returns the total size of - the history buffer and the amount of the buffer that is - currently occupied. - - typedef struct { - size_t size; /* The size of the history buffer */ - /* (bytes). */ - size_t used; /* The number of bytes of the */ - /* history buffer that are */ - /* currently occupied. */ - } GlHistorySize; - - void gl_size_of_history(GetLine *gl, GlHistorySize *size); - - On return, the size information is recorded in the variable - pointed to by the size argument. - - -</pre><h2>CHANGING TERMINALS</h2><pre> - The new_GetLine() constructor function assumes that input is - to be read from stdin, and output written to stdout. The - following function allows you to switch to different input - and output streams. - - int gl_change_terminal(GetLine *gl, FILE *input_fp, - FILE *output_fp, const char *term); - - The gl argument is the object that was returned by - new_GetLine(). The input_fp argument specifies the stream - to read from, and output_fp specifies the stream to be writ- - ten to. Only if both of these refer to a terminal, will - interactive terminal input be enabled. Otherwise - gl_get_line() will simply call fgets() to read command - input. If both streams refer to a terminal, then they must - refer to the same terminal, and the type of this terminal - must be specified via the term argument. The value of the - term argument is looked up in the terminal information data- - base (terminfo or termcap), in order to determine which spe- - cial control sequences are needed to control various aspects - of the terminal. new_GetLine() for example, passes the - return value of getenv("TERM") in this argument. Note that - if one or both of input_fp and output_fp don't refer to a - terminal, then it is legal to pass NULL instead of a termi- - nal type. - - Note that if you want to pass file descriptors to - gl_change_terminal(), you can do this by creating stdio - stream wrappers using the POSIX fdopen() function. - - -</pre><h2>EXTERNAL EVENT HANDLING</h2><pre> - While gl_get_line() is waiting for keyboard input from the - user, you can ask it to also watch for activity on arbitrary - file descriptors, such as network sockets, pipes etc, and - have it call functions of your choosing when activity is - seen. This works on any system that has the select() system - call, which is most, if not all flavors of unix. Registering - a file descriptor to be watched by gl_get_line() involves - calling the gl_watch_fd() function. - - - int gl_watch_fd(GetLine *gl, int fd, GlFdEvent event, - GlFdEventFn *callback, void *data); - - - If this returns non-zero, then it means that either your - arguments are invalid, or that this facility isn't supported - on the host system. - - The fd argument is the file descriptor to be watched. The - event argument specifies what type of activity is of - interest, chosen from the following enumerated values: - - - GLFD_READ - Watch for the arrival of data to be read. - GLFD_WRITE - Watch for the ability to write to the file - descriptor without blocking. - GLFD_URGENT - Watch for the arrival of urgent - out-of-band data on the file descriptor. - - - The callback argument is the function to call when the - selected activity is seen. It should be defined with the - following macro, which is defined in libtecla.h. - - - #define GL_FD_EVENT_FN(fn) GlFdStatus (fn)(GetLine *gl, \ - void *data, int fd, \ - GlFdEvent event) - - The data argument of the gl_watch_fd() function is passed to - the callback function for its own use, and can point to any- - thing you like, including NULL. The file descriptor and the - event argument are also passed to the callback function, and - this potentially allows the same callback function to be - registered to more than one type of event and/or more than - one file descriptor. The return value of the callback func- - tion should be one of the following values. - - - GLFD_ABORT - Tell gl_get_line() to abort with an - error (errno won't be set, so set it - appropriately yourself if you need it). - GLFD_REFRESH - Redraw the input line then continue - waiting for input. Return this if - your callback wrote to the terminal. - GLFD_CONTINUE - Continue to wait for input, without - redrawing the line. - - Note that before calling the callback, gl_get_line() blocks - most signals, and leaves its own signal handlers installed, - so if you need to catch a particular signal you will need to - both temporarily install your own signal handler, and - unblock the signal. Be sure to re-block the signal (if it - was originally blocked) and reinstate the original signal - handler, if any, before returning. - - Your callback shouldn't try to read from the terminal, which - is left in raw mode as far as input is concerned. You can - however write to the terminal as usual, since features like - conversion of newline to carriage-return/linefeed are re- - enabled while the callback is running. If your callback - function does write to the terminal, be sure to output a - newline first, and when your callback returns, tell - gl_get_line() that the input line needs to be redrawn, by - returning the GLFD_REFRESH status code. - - To remove a callback function that you previously registered - for a given file descriptor and event, simply call - gl_watch_fd() with the same file descriptor and event argu- - ments, but with a callback argument of 0. The data argument - is ignored in this case. - - -</pre><h2>SIGNAL HANDLING DEFAULTS</h2><pre> - By default, the gl_get_line() function intercepts a number - of signals. This is particularly important for signals which - would by default terminate the process, since the terminal - needs to be restored to a usable state before this happens. - In this section, the signals that are trapped by default, - and how gl_get_line() responds to them, is described. Chang- - ing these defaults is the topic of the following section. - - When the following subset of signals are caught, - gl_get_line() first restores the terminal settings and sig- - nal handling to how they were before gl_get_line() was - called, resends the signal, to allow the calling - application's signal handlers to handle it, then if the pro- - cess still exists, gl_get_line() returns NULL and sets errno - as specified below. - - - SIGINT - This signal is generated both by the keyboard - interrupt key (usually ^C), and the keyboard - break key. - - errno=EINTR - - SIGHUP - This signal is generated when the controlling - terminal exits. - - errno=ENOTTY - - SIGPIPE - This signal is generated when a program attempts - to write to a pipe who's remote end isn't being - read by any process. This can happen for example - if you have called gl_change_terminal() to - redirect output to a pipe hidden under a pseudo - terminal. - - errno=EPIPE - - SIGQUIT - This signal is generated by the keyboard quit - key (usually ^\). - - errno=EINTR - - SIGABRT - This signal is generated by the standard C, - abort() function. By default it both - terminates the process and generates a core - dump. - - errno=EINTR - - SIGTERM - This is the default signal that the UN*X - kill command sends to processes. - - errno=EINTR - - Note that in the case of all of the above signals, POSIX - mandates that by default the process is terminated, with the - addition of a core dump in the case of the SIGQUIT signal. - In other words, if the calling application doesn't override - the default handler by supplying its own signal handler, - receipt of the corresponding signal will terminate the - application before gl_get_line() returns. - - If gl_get_line() aborts with errno set to EINTR, you can - find out what signal caused it to abort, by calling the fol- - lowing function. - - int gl_last_signal(const GetLine *gl); - - This returns the numeric code (eg. SIGINT) of the last sig- - nal that was received during the most recent call to - gl_get_line(), or -1 if no signals were received. - - On systems that support it, when a SIGWINCH (window change) - signal is received, gl_get_line() queries the terminal to - find out its new size, redraws the current input line to - accomodate the new size, then returns to waiting for key- - board input from the user. Unlike other signals, this signal - isn't resent to the application. - - Finally, the following signals cause gl_get_line() to first - restore the terminal and signal environment to that which - prevailed before gl_get_line() was called, then resend the - signal to the application. If the process still exists after - the signal has been delivered, then gl_get_line() then re- - establishes its own signal handlers, switches the terminal - back to raw mode, redisplays the input line, and goes back - to awaiting terminal input from the user. - - SIGCONT - This signal is generated when a suspended - process is resumed. - - SIGPWR - This signal is generated when a power failure - occurs (presumably when the system is on a - UPS). - - SIGALRM - This signal is generated when a timer - expires. - SIGUSR1 - An application specific signal. - - SIGUSR2 - Another application specific signal. - - SIGVTALRM - This signal is generated when a virtual - timer expires (see man setitimer(2)). - - SIGXCPU - This signal is generated when a process - exceeds its soft CPU time limit. - - SIGTSTP - This signal is generated by the terminal - suspend key, which is usually ^Z, or the - delayed terminal suspend key, which is - usually ^Y. - - SIGTTIN - This signal is generated if the program - attempts to read from the terminal while the - program is running in the background. - - SIGTTOU - This signal is generated if the program - attempts to write to the terminal while the - program is running in the background. - - - Obviously not all of the above signals are supported on all - systems, so code to support them is conditionally compiled - into the tecla library. - - Note that if SIGKILL, which by definition can't be caught, - or any of the hardware generated exception signals, such as - SIGSEGV, SIGBUS and SIGFPE, are received and unhandled while - gl_get_line() has the terminal in raw mode, the program will - be terminated without the terminal having been restored to a - usable state. In practice, job-control shells usually reset - the terminal settings when a process relinquishes the con- - trolling terminal, so this is only a problem with older - shells. - - -</pre><h2>CUSTOMIZED SIGNAL HANDLING</h2><pre> - The previous section listed the signals that gl_get_line() - traps by default, and described how it responds to them. - This section describes how to both add and remove signals - from the list of trapped signals, and how to specify how - gl_get_line() should respond to a given signal. - - If you don't need gl_get_line() to do anything in response - to a signal that it normally traps, you can tell to - gl_get_line() to ignore that signal by calling - gl_ignore_signal(). - - int gl_ignore_signal(GetLine *gl, int signo); - The signo argument is the number of the signal (eg. SIGINT) - that you want to have ignored. If the specified signal isn't - currently one of those being trapped, this function does - nothing. - - The gl_trap_signal() function allows you to either add a new - signal to the list that gl_get_line() traps, or modify how - it responds to a signal that it already traps. - - int gl_trap_signal(GetLine *gl, int signo, unsigned flags, - GlAfterSignal after, int errno_value); - - The signo argument is the number of the signal that you wish - to have trapped. The flags argument is a set of flags which - determine the environment in which the application's signal - handler is invoked, the after argument tells gl_get_line() - what to do after the application's signal handler returns, - and errno_value tells gl_get_line() what to set errno to if - told to abort. - - The flags argument is a bitwise OR of zero or more of the - following enumerators: - - GLS_RESTORE_SIG - Restore the caller's signal - environment while handling the - signal. - - GLS_RESTORE_TTY - Restore the caller's terminal settings - while handling the signal. - - GLS_RESTORE_LINE - Move the cursor to the start of the - line following the input line before - invoking the application's signal - handler. - - GLS_REDRAW_LINE - Redraw the input line when the - application's signal handler returns. - - GLS_UNBLOCK_SIG - Normally, if the calling program has - a signal blocked (man sigprocmask), - gl_get_line() does not trap that - signal. This flag tells gl_get_line() - to trap the signal and unblock it for - the duration of the call to - gl_get_line(). - - GLS_DONT_FORWARD - If this flag is included, the signal - will not be forwarded to the signal - handler of the calling program. - - Two commonly useful flag combinations are also enumerated as - follows: - GLS_RESTORE_ENV = GLS_RESTORE_SIG | GLS_RESTORE_TTY | - GLS_REDRAW_LINE - - GLS_SUSPEND_INPUT = GLS_RESTORE_ENV | GLS_RESTORE_LINE - - - If your signal handler, or the default system signal handler - for this signal, if you haven't overriden it, never either - writes to the terminal, nor suspends or terminates the cal- - ling program, then you can safely set the flags argument to - 0. - - If your signal handler always writes to the terminal, reads - from it, or suspends or terminates the program, you should - specify the flags argument as GL_SUSPEND_INPUT, so that: - - 1. The cursor doesn't get left in the middle of the input - line. - 2. So that the user can type in input and have it echoed. - 3. So that you don't need to end each output line with - \r\n, instead of just \n. - - The GL_RESTORE_ENV combination is the same as - GL_SUSPEND_INPUT, except that it doesn't move the cursor, - and if your signal handler doesn't read or write anything to - the terminal, the user won't see any visible indication that - a signal was caught. This can be useful if you have a signal - handler that only occasionally writes to the terminal, where - using GL_SUSPEND_LINE would cause the input line to be - unnecessarily duplicated when nothing had been written to - the terminal. Such a signal handler, when it does write to - the terminal, should be sure to start a new line at the - start of its first write, by writing a new line before - returning. If the signal arrives while the user is entering - a line that only occupies a signal terminal line, or if the - cursor is on the last terminal line of a longer input line, - this will have the same effect as GL_SUSPEND_INPUT. Other- - wise it will start writing on a line that already contains - part of the displayed input line. This doesn't do any harm, - but it looks a bit ugly, which is why the GL_SUSPEND_INPUT - combination is better if you know that you are always going - to be writting to the terminal. - - The after argument, which determines what gl_get_line() does - after the application's signal handler returns (if it - returns), can take any one of the following values: - - GLS_RETURN - Return the completed input line, just as - though the user had pressed the return - key. - - GLS_ABORT - Cause gl_get_line() to return NULL. - GLS_CONTINUE - Resume command line editing. - - The errno_value argument is intended to be combined with the - GLS_ABORT option, telling gl_get_line() what to set the - standard errno variable to before returning NULL to the cal- - ling program. It can also, however, be used with the - GL_RETURN option, in case you wish to have a way to distin- - guish between an input line that was entered using the - return key, and one that was entered by the receipt of a - signal. - - -</pre><h2>THE TERMINAL SIZE</h2><pre> - On most systems the combination of the TIOCGWINSZ ioctl and - the SIGWINCH signal is used to maintain an accurate idea of - the terminal size. The terminal size is newly queried every - time that gl_get_line() is called and whenever a SIGWINCH - signal is received. - - On the few systems where this mechanism isn't available, at - startup new_GetLine() first looks for the LINES and COLUMNS - environment variables. If these aren't found, or they con- - tain unusable values, then if a terminal information data- - base like terminfo or termcap is available, the default size - of the terminal is looked up in this database. If this too - fails to provide the terminal size, a default size of 80 - columns by 24 lines is used. If this default isn't appropri- - ate for your system, gl_terminal_size() can be used to sup- - ply a different fallback. - - The gl_terminal_size() function allows you to query the - current size of the terminal, and install an alternate fall- - back size for cases where the size isn't available. Beware - that the terminal size won't be available if reading from a - pipe or a file, so the default values can be important even - on systems that do support ways of finding out the terminal - size. - - typedef struct { - int nline; /* The terminal has nline lines */ - int ncolumn; /* The terminal has ncolumn columns */ - } GlTerminalSize; - - GlTerminalSize gl_terminal_size(GetLine *gl, - int def_ncolumn, - int def_nline); - - This function first updates gl_get_line()'s idea of the ter- - minal size, then records its findings in the return value. - - The def_ncolumn and def_nline specify the default number of - terminal columns and lines to use if the terminal size can't - be determined. - - -</pre><h2>HIDING WHAT YOU TYPE</h2><pre> - When entering sensitive information, such as passwords, it - is best not to have the text that you are entering echoed on - the terminal. Furthermore, such text should not be recorded - in the history list, since somebody finding your terminal - unattended could then recall it, or somebody snooping - through your directories could see it in your history file. - With this in mind, the gl_echo_mode() function allows you to - toggle on and off the display and archival of any text that - is subsequently entered in calls to gl_get_line(). - - - int gl_echo_mode(GetLine *gl, int enable); - - - The enable argument specifies whether entered text should be - visible or not. If it is 0, then subsequently entered lines - will not be visible on the terminal, and will not be - recorded in the history list. If it is 1, then subsequent - input lines will be displayed as they are entered, and pro- - vided that history hasn't been turned off via a call to - gl_toggle_history(), then they will also be archived in the - history list. Finally, if the enable argument is -1, then - the echoing mode is left unchanged, which allows you to - non-destructively query the current setting via the return - value. In all cases, the return value of the function is 0 - if echoing was disabled before the function was called, and - 1 if it was enabled. - - When echoing is turned off, note that although tab comple- - tion will invisibly complete your prefix as far as possible, - ambiguous completions will not be displayed. - - -</pre><h2>CALLBACK FUNCTION FACILITIES</h2><pre> - Unless otherwise stated, callback functions, such as tab - completion callbacks and event callbacks should not call any - functions in this module. The following functions, however, - are designed specifically to be used by callback functions. - - Calling the gl_replace_prompt() function from a callback - tells gl_get_line() to display a different prompt when the - callback returns. It has no effect if called when - gl_get_line() is not being called. - - void gl_replace_prompt(GetLine *gl, const char *prompt); - - - -</pre><h2>INTERNATIONAL CHARACTER SETS</h2><pre> - Since libtecla version 1.4.0, gl_get_line() has been 8-bit - clean. This means that all 8-bit characters that are print- - able in the user's current locale are now displayed verbatim - and included in the returned input line. Assuming that the - calling program correctly contains a call like the follow- - ing, - - setlocale(LC_CTYPE, ""); - - then the current locale is determined by the first of the - environment variables LC_CTYPE, LC_ALL, and LANG, that is - found to contain a valid locale name. If none of these vari- - ables are defined, or the program neglects to call setlo- - cale, then the default C locale is used, which is US 7-bit - ASCII. On most unix-like platforms, you can get a list of - valid locales by typing the command: - - locale -a - - at the shell prompt. - - -</pre><h2> Meta keys and locales</h2><pre> - Beware that in most locales other than the default C locale, - meta characters become printable, and they are then no - longer considered to match M-c style key bindings. This - allows international characters to be entered with the com- - pose key without unexpectedly triggering meta key bindings. - You can still invoke meta bindings, since there are actually - two ways to do this. For example the binding M-c can also be - invoked by pressing the escape key momentarily, then press- - ing the c key, and this will work regardless of locale. - Moreover, many modern terminal emulators, such as gnome's - gnome-terminal's and KDE's konsole terminals, already gen- - erate escape pairs like this when you use the meta key, - rather than a real meta character, and other emulators usu- - ally have a way to request this behavior, so you can con- - tinue to use the meta key on most systems. - - For example, although xterm terminal emulators generate real - 8-bit meta characters by default when you use the meta key, - they can be configured to output the equivalent escape pair - by setting their EightBitInput X resource to False. You can - either do this by placing a line like the following in your - ~/.Xdefaults file, - - XTerm*EightBitInput: False - - or by starting an xterm with an -xrm '*EightBitInput: False' - command-line argument. In recent versions of xterm you can - toggle this feature on and off with the "Meta Sends Escape" - option in the menu that is displayed when you press the left - mouse button and the control key within an xterm window. In - CDE, dtterms can be similarly coerced to generate escape - pairs in place of meta characters, by setting the - Dtterm*KshMode resource to True. - - -</pre><h2> Entering international characters</h2><pre> - If you don't have a keyboard that generates all of the - international characters that you need, there is usually a - compose key that will allow you to enter special characters, - or a way to create one. For example, under X windows on - unix-like systems, if your keyboard doesn't have a compose - key, you can designate a redundant key to serve this purpose - with the xmodmap command. For example, on many PC keyboards - there is a microsoft-windows key, which is otherwise useless - under Linux. On my PC the xev program reports that pressing - this key generates keycode 115, so to turn this key into a - compose key, I do the following: - - xmodmap -e 'keycode 115 = Multi_key' - - I can then enter an i with a umlaut over it by typing this - key, followed by ", followed by i. - - -</pre><h2>THREAD SAFETY</h2><pre> - In a multi-threaded program, you should use the libtecla_r.a - version of the library. This uses reentrant versions of sys- - tem functions, where available. Unfortunately neither ter- - minfo nor termcap were designed to be reentrant, so you - can't safely use the functions of the getline module in mul- - tiple threads (you can use the separate file-expansion and - word-completion modules in multiple threads, see the - corresponding man pages for details). However due to the use - of POSIX reentrant functions for looking up home directories - etc, it is safe to use this module from a single thread of a - multi-threaded program, provided that your other threads - don't use any termcap or terminfo functions. - - -</pre><h2>FILES</h2><pre> - libtecla.a - The tecla library - libtecla.h - The tecla header file. - ~/.teclarc - The personal tecla customization file. - - -</pre><h2>SEE ALSO</h2><pre> - <a href="libtecla.html">libtecla(3)</a>, <a href="ef_expand_file.html">ef_expand_file(3)</a>, <a href="cpl_complete_word.html">cpl_complete_word(3)</a>, - <a href="pca_lookup_file.html">pca_lookup_file(3)</a> - - -</pre><h2>AUTHOR</h2><pre> - Martin Shepherd (mcs@astro.caltech.edu) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -</pre> -</body> diff --git a/libtecla-1.4.1/html/index.html b/libtecla-1.4.1/html/index.html deleted file mode 100644 index f75a90f..0000000 --- a/libtecla-1.4.1/html/index.html +++ /dev/null @@ -1,116 +0,0 @@ -<HEAD><TITLE>The tecla command-line editing library.</TITLE></HEAD> -<BODY bgcolor=add8e6> -<H1>The Tecla command-line editing library.</H1> - -The tecla library provides UNIX and LINUX programs with interactive -command line editing facilities, similar to those of the UNIX tcsh -shell. In addition to simple command-line editing, it supports recall -of previously entered command lines, TAB completion of file names or -other tokens, and in-line wild-card expansion of filenames. The -internal functions which perform file-name completion and wild-card -expansion are also available externally for optional use by programs. -<P> -In addition, the library includes a path-searching module. This -allows an application to provide completion and lookup of files -located in UNIX style paths. Although not built into the line editor -by default, it can easily be called from custom tab-completion -callback functions. This was originally conceived for completing the -names of executables and providing a way to look up their locations in -the user's PATH environment variable, but it can easily be asked to -look up and complete other types of files in any list of directories. - -<P> -Note that special care has been taken to allow the use of this library -in threaded programs. The option to enable this is discussed in the -Makefile, and specific discussions of thread safety are presented in -the included man pages. -<P> -The current version is version 1.4.1. This may be obtained from: -<P> - <a href="libtecla-1.4.1.tar.gz">http://www.astro.caltech.edu/~mcs/tecla/libtecla-1.4.1.tar.gz</a> -<P> - -For the sake of automated scripts, the following URL always points to -the latest version. Note that the version number can be found in the -README file. - -<P> - <a href="libtecla.tar.gz">http://www.astro.caltech.edu/~mcs/tecla/libtecla.tar.gz</a> -<P> - -The library is distributed under a permissive non-copyleft -<a href="LICENSE.TERMS">free software license</a> (the X11 license with -the name of the copyright holder changed). This is compatible with, -but not as restrictive as the GNU GPL. - -<H2>Release notes</H2> - -The list of major changes that accompany each new release can be found -<a href="release.html">here</a>. - -<H2>Modifications</H2> - -The gory details of changes in the latest and previous versions of the -library can be found <a href="changes.html">here</a>. - -<H2>Library documentation</H2> - -The following are html versions of the libtecla man pages: - -<UL> -<LI> <a href="libtecla.html">libtecla(3)</a> - An introduction to the tecla library. -<LI> <a href="gl_get_line.html">gl_get_line(3)</a> - The interactive line-input function. -<LI> <a href="cpl_complete_word.html">cpl_complete_word(3)</a> - The word (eg. filename) completion function. -<LI> <a href="ef_expand_file.html">ef_expand_file(3)</a> - The filename expansion function. -<LI> <a href="pca_lookup_file.html">pca_lookup_file(3)</a> - A directory-list based filename lookup and completion module. -<LI> <a href="enhance.html">enhance(3)</a> - A program that adds command-line editing to third party programs. -</UL> - -<H2>Portability</H2> - -In principle, the standard version of the library should compile -without any problems on any UNIX or UNIX like system. So far it has -been reported to work on the following systems: - -<pre> - Sun Solaris 2.5,2.6,7,8, with any of gcc, Sun C, or g++. - Mandrake Linux 7.1 etc.., gcc - Red Hat Linux 7 etc.., gcc - Suse Linux 6.4, gcc - IBM AIX 4.3.3, gcc - HP-UX 10.20, HP-UX 11, gcc, c89 - SCO UnixWare 7.1.1 - FreeBSD, gcc - Alpha OSF1, cc, gcc - Mac OS X - Cygwin (running under Windows) - QNX -</pre> - -There haven't been many reports concerning the POSIX reentrant -version, so the absence of any of the above from the following list of -systems on which the reentrant version is known to work, shouldn't be -taken as an indication that the reentrant version doesn't work. - -<pre> - Sun Solaris 2.5,2.6,7,8, with any of gcc, Sun C, or g++. - Mandrake Linux 7.1, gcc - RedHat Linux 7.0,7.1, gcc - SuSe Linux 6.4, gcc - HP-UX 11, gcc - IBM AIX 4.3.3, gcc - Alpha OSF1, cc -</pre> - -The only system that is known to have issues with the reentrant -version of the library is SCO UnixWare 7.1.1. The problem is in the -system provided signal.h, which breaks when POSIX_C_SOURCE is -defined. It has been reported that this can be fixed by editing -signal.h. - -<P> -If you compile the library on a system that isn't mentioned above, -please send E-mail to <b>mcs@astro.caltech.edu</b>. -<HR> -Martin Shepherd (25-May-2002) -</BODY> diff --git a/libtecla-1.4.1/html/libtecla.html b/libtecla-1.4.1/html/libtecla.html deleted file mode 100644 index 914c1e9..0000000 --- a/libtecla-1.4.1/html/libtecla.html +++ /dev/null @@ -1,163 +0,0 @@ -<head> -<title>Manual Page</title> -</head> -<body> -<pre> -</pre><h2>NAME</h2><pre> - libtecla - An interactive command-line input library. - -</pre><h2>SYNOPSIS</h2><pre> - gcc ... -ltecla -lcurses - - -</pre><h2>DESCRIPTION</h2><pre> - The tecla library provides programs with interactive command - line editing facilities, similar to those of the unix tcsh - shell. In addition to simple command-line editing, it sup- - ports recall of previously entered command lines, TAB com- - pletion of file names or other tokens, and in-line wild-card - expansion of filenames. The internal functions which perform - file-name completion and wild-card expansion are also avail- - able externally for optional use by the calling program. - - The various parts of the library are documented in the fol- - lowing man pages: - - <a href="gl_get_line.html">gl_get_line(3)</a> - The interactive line-input module. - <a href="cpl_complete_word.html">cpl_complete_word(3)</a> - The word completion module. - <a href="ef_expand_file.html">ef_expand_file(3)</a> - The filename expansion module. - <a href="pca_lookup_file.html">pca_lookup_file(3)</a> - A directory-list based filename - lookup and completion module. - - In addition there is one optional application distributed - with the library: - - <a href="enhance.html">enhance(3)</a> - Add command-line editing to third - party applications. - - -</pre><h2>THREAD SAFETY</h2><pre> - If the library is compiled with -D_POSIX_C_SOURCE=199506L, - reentrant versions of as many functions as possible are - used. This includes using getpwuid_r() and getpwnam_r() - instead of getpwuid() and getpwnam() when looking up the - home directories of specific users in the password file (for - ~user/ expansion), and readdir_r() instead of readdir() for - reading directory entries when doing filename completion. - The reentrant version of the library is usually called - libtecla_r.a instead of libtecla.a, so if only the latter is - available, it probably isn't the correct version to link - with threaded programs. - - Reentrant functions for iterating through the password file - aren't available, so when the library is compiled to be - reentrant, TAB completion of incomplete usernames in ~user- - name/ expressions is disabled. This doesn't disable expan- - sion of complete ~username expressions, which can be done - reentrantly, or expansion of the parts of filenames that - follow them, so this doesn't remove much functionality. - - The terminfo functions setupterm(), tigetstr(), tigetnum() - and tputs() also aren't reentrant, but very few programs - will want to interact with multiple terminals, so this - shouldn't prevent this library from being used in threaded - programs. - - -</pre><h2>LIBRARY VERSION NUMBER</h2><pre> - The version number of the library can be queried using the - following function. - - void libtecla_version(int *major, int *minor, int *micro); - - - On return, this function records the three components of the - libtecla version number in *major, *minor, *micro. The for- - mal meaning of the three components is as follows. - - - major - Incrementing this number implies that a change has - been made to the library's public interface, which - makes it binary incompatible with programs that - were linked with previous shared versions of the - tecla library. - - minor - This number is incremented by one whenever - additional functionality, such as new functions or - modules, are added to the library. - - micro - This is incremented whenever modifications to the - library are made which make no changes to the - public interface, but which fix bugs and/or improve - the behind-the-scenes implementation. - - - -</pre><h2>TRIVIA</h2><pre> - In Spanish, a "tecla" is the key of a keyboard. Since this - library centers on keyboard input, and given that I wrote - much of the library while working in Chile, this seemed like - a suitable name. - - -</pre><h2>FILES</h2><pre> - libtecla.a - The tecla library. - libtecla.h - The tecla header file. - ~/.teclarc - The tecla personal customization file. - - - -</pre><h2>SEE ALSO</h2><pre> - <a href="gl_get_line.html">gl_get_line(3)</a>, <a href="ef_expand_file.html">ef_expand_file(3)</a>, <a href="cpl_complete_word.html">cpl_complete_word(3)</a>, - <a href="pca_lookup_file.html">pca_lookup_file(3)</a>, <a href="enhance.html">enhance(3)</a> - - -</pre><h2>AUTHOR</h2><pre> - Martin Shepherd (mcs@astro.caltech.edu) - - -</pre><h2>ACKNOWLEDGMENTS</h2><pre> - Markus Gyger - Lots of assistance, including help with - shared libraries, configuration information, - particularly for Solaris; modifications to - support C++ compilers, improvements for ksh - users, faster cursor motion, output - buffering, and changes to make gl_get_line() - 8-bit clean. - Mike MacFaden - Suggestions, feedback and testing that led - to many of the major new functions that were - added in version 1.4.0. - Tim Eliseo - Many vi-mode bindings and fixes. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -</pre> -</body> diff --git a/libtecla-1.4.1/html/pca_lookup_file.html b/libtecla-1.4.1/html/pca_lookup_file.html deleted file mode 100644 index 40c9f2b..0000000 --- a/libtecla-1.4.1/html/pca_lookup_file.html +++ /dev/null @@ -1,371 +0,0 @@ -<head> -<title>Manual Page</title> -</head> -<body> -<pre> -</pre><h2>NAME</h2><pre> - pca_lookup_file, del_PathCache, del_PcaPathConf, - new_PathCache, new_PcaPathConf, pca_last_error, - pca_path_completions, pca_scan_path, pca_set_check_fn, - ppc_file_start, ppc_literal_escapes - lookup a file in a - list of directories - -</pre><h2>SYNOPSIS</h2><pre> - #include <libtecla.h> - - PathCache *new_PathCache(void); - - PathCache *del_PathCache(PathCache *pc); - - int pca_scan_path(PathCache *pc, const char *path); - - void pca_set_check_fn(PathCache *pc, CplCheckFn *check_fn, - void *data); - - char *pca_lookup_file(PathCache *pc, const char *name, - int name_len, int literal); - - const char *pca_last_error(PathCache *pc); - - CPL_MATCH_FN(pca_path_completions); - - - -</pre><h2>DESCRIPTION</h2><pre> - The PathCache object is part of the tecla library (see the - <a href="libtecla.html">libtecla(3)</a> man page). - - PathCache objects allow an application to search for files - in any colon separated list of directories, such as the unix - execution PATH environment variable. Files in absolute - directories are cached in a PathCache object, whereas rela- - tive directories are scanned as needed. Using a PathCache - object, you can look up the full pathname of a simple - filename, or you can obtain a list of the possible comple- - tions of a given filename prefix. By default all files in - the list of directories are targets for lookup and comple- - tion, but a versatile mechanism is provided for only select- - ing specific types of files. The obvious application of this - facility is to provide Tab-completion and lookup of execut- - able commands in the unix PATH, so an optional callback - which rejects all but executable files, is provided. - - -</pre><h2>AN EXAMPLE</h2><pre> - Under UNIX, the following example program looks up and - displays the full pathnames of each of the command names on - the command line. - #include <stdio.h> - #include <stdlib.h> - #include <libtecla.h> - - int main(int argc, char *argv[]) - { - int i; - /* - * Create a cache for executable files. - */ - PathCache *pc = new_PathCache(); - if(!pc) - exit(1); - /* - * Scan the user's PATH for executables. - */ - if(pca_scan_path(pc, getenv("PATH"))) { - fprintf(stderr, "%s\n", pca_last_error(pc)); - exit(1); - } - /* - * Arrange to only report executable files. - */ - pca_set_check_fn(pc, cpl_check_exe, NULL); - /* - * Lookup and display the full pathname of each of the - * commands listed on the command line. - */ - for(i=1; i<argc; i++) { - char *cmd = pca_lookup_file(pc, argv[i], -1, 0); - printf("The full pathname of '%s' is %s\n", argv[i], - cmd ? cmd : "unknown"); - } - pc = del_PathCache(pc); /* Clean up */ - return 0; - } - - The following is an example of what this does on my laptop - under linux: - - $ ./example less more blob - The full pathname of 'less' is /usr/bin/less - The full pathname of 'more' is /bin/more - The full pathname of 'blob' is unknown - $ - - -</pre><h2>FUNCTION DESCRIPTIONS</h2><pre> - In order to use the facilities of this module, you must - first allocate a PathCache object by calling the - new_PathCache() constructor function. - - PathCache *new_PathCache(void) - - This function creates the resources needed to cache and - lookup files in a list of directories. It returns NULL on - error. - - -</pre><h2>POPULATING THE CACHE</h2><pre> - Once you have created a cache, it needs to be populated with - files. To do this, call the pca_scan_path() function. - - int pca_scan_path(PathCache *pc, const char *path); - - Whenever this function is called, it discards the current - contents of the cache, then scans the list of directories - specified in its path argument for files. The path argument - must be a string containing a colon-separated list of direc- - tories, such as "/usr/bin:/home/mcs/bin:.". This can include - directories specified by absolute pathnames such as - "/usr/bin", as well as sub-directories specified by relative - pathnames such as "." or "bin". Files in the absolute direc- - tories are immediately cached in the specified PathCache - object, whereas sub-directories, whose identities obviously - change whenever the current working directory is changed, - are marked to be scanned on the fly whenever a file is - looked up. - - On success this function return 0. On error it returns 1, - and a description of the error can be obtained by calling - pca_last_error(pc). - - -</pre><h2>LOOKING UP FILES</h2><pre> - Once the cache has been populated with files, you can look - up the full pathname of a file, simply by specifying its - filename to pca_lookup_file(). - - char *pca_lookup_file(PathCache *pc, const char *name, - int name_len, int literal); - - To make it possible to pass this function a filename which - is actually part of a longer string, the name_len argument - can be used to specify the length of the filename at the - start of the name[] argument. If you pass -1 for this - length, the length of the string will be determined with - strlen(). If the name[] string might contain backslashes - that escape the special meanings of spaces and tabs within - the filename, give the literal argument, the value 0. Other- - wise, if backslashes should be treated as normal characters, - pass 1 for the value of the literal argument. - - -</pre><h2>FILENAME COMPLETION</h2><pre> - Looking up the potential completions of a filename-prefix in - the filename cache, is achieved by passing the provided - pca_path_completions() callback function to the - cpl_complete_word() function (see the <a href="cpl_complete_word.html">cpl_complete_word(3)</a> - man page). - - CPL_MATCH_FN(pca_path_completions); - - This callback requires that its data argument be a pointer - to a PcaPathConf object. Configuration objects of this type - are allocated by calling new_PcaPathConf(). - - PcaPathConf *new_PcaPathConf(PathCache *pc); - - This function returns an object initialized with default - configuration parameters, which determine how the - cpl_path_completions() callback function behaves. The func- - tions which allow you to individually change these parame- - ters are discussed below. - - By default, the pca_path_completions() callback function - searches backwards for the start of the filename being com- - pleted, looking for the first un-escaped space or the start - of the input line. If you wish to specify a different loca- - tion, call ppc_file_start() with the index at which the - filename starts in the input line. Passing start_index=-1 - re-enables the default behavior. - - void ppc_file_start(PcaPathConf *ppc, int start_index); - - By default, when pca_path_completions() looks at a filename - in the input line, each lone backslash in the input line is - interpreted as being a special character which removes any - special significance of the character which follows it, such - as a space which should be taken as part of the filename - rather than delimiting the start of the filename. These - backslashes are thus ignored while looking for completions, - and subsequently added before spaces, tabs and literal - backslashes in the list of completions. To have unescaped - backslashes treated as normal characters, call - ppc_literal_escapes() with a non-zero value in its literal - argument. - - void ppc_literal_escapes(PcaPathConf *ppc, int literal); - - When you have finished with a PcaPathConf variable, you can - pass it to the del_PcaPathConf() destructor function to - reclaim its memory. - - PcaPathConf *del_PcaPathConf(PcaPathConf *ppc); - -</pre><h2>BEING SELECTIVE</h2><pre> - If you are only interested in certain types or files, such - as, for example, executable files, or files whose names end - in a particular suffix, you can arrange for the file comple- - tion and lookup functions to be selective in the filenames - that they return. This is done by registering a callback - function with your PathCache object. Thereafter, whenever a - filename is found which either matches a filename being - looked up, or matches a prefix which is being completed, - your callback function will be called with the full pathname - of the file, plus any application-specific data that you - provide, and if the callback returns 1 the filename will be - reported as a match, and if it returns 0, it will be - ignored. Suitable callback functions and their prototypes - should be declared with the following macro. The CplCheckFn - typedef is also provided in case you wish to declare - pointers to such functions. - - #define CPL_CHECK_FN(fn) int (fn)(void *data, \ - const char *pathname) - typedef CPL_CHECK_FN(CplCheckFn); - - Registering one of these functions involves calling the - pca_set_check_fn() function. In addition to the callback - function, passed via the check_fn argument, you can pass a - pointer to anything via the data argument. This pointer will - be passed on to your callback function, via its own data - argument, whenever it is called, so this provides a way to - pass appplication specific data to your callback. - - void pca_set_check_fn(PathCache *pc, CplCheckFn *check_fn, - void *data); - - Note that these callbacks are passed the full pathname of - each matching file, so the decision about whether a file is - of interest can be based on any property of the file, not - just its filename. As an example, the provided - cpl_check_exe() callback function looks at the executable - permissions of the file and the permissions of its parent - directories, and only returns 1 if the user has execute per- - mission to the file. This callback function can thus be used - to lookup or complete command names found in the directories - listed in the user's PATH environment variable. The example - program given earlier in this man page provides a demonstra- - tion of this. - - Beware that if somebody tries to complete an empty string, - your callback will get called once for every file in the - cache, which could number in the thousands. If your callback - does anything time consuming, this could result in an unac- - ceptable delay for the user, so callbacks should be kept - short. - To improve performance, whenever one of these callbacks is - called, the choice that it makes is cached, and the next - time the corresponding file is looked up, instead of calling - the callback again, the cached record of whether it was - accepted or rejected is used. Thus if somebody tries to com- - plete an empty string, and hits tab a second time when noth- - ing appears to happen, there will only be one long delay, - since the second pass will operate entirely from the cached - dispositions of the files. These cached dipositions are dis- - carded whenever pca_scan_path() is called, and whenever - pca_set_check_fn() is called with changed callback function - or data arguments. - - -</pre><h2>ERROR HANDLING</h2><pre> - If pca_scan_path() reports that an error occurred by return- - ing 1, you can obtain a terse description of the error by - calling pca_last_error(pc). This returns an internal string - containing an error message. - - const char *pca_last_error(PathCache *pc); - - - -</pre><h2>CLEANING UP</h2><pre> - Once you have finished using a PathCache object, you can - reclaim its resources by passing it to the del_PathCache() - destructor function. This takes a pointer to one of these - objects, and always returns NULL. - - PathCache *del_PathCache(PathCache *pc); - - -</pre><h2>THREAD SAFETY</h2><pre> - In multi-threaded programs, you should use the libtecla_r.a - version of the library. This uses POSIX reentrant functions - where available (hence the _r suffix), and disables features - that rely on non-reentrant system functions. In the case of - this module, the only disabled feature is username comple- - tion in ~username/ expressions, in cpl_path_completions(). - - Using the libtecla_r.a version of the library, it is safe to - use the facilities of this module in multiple threads, pro- - vided that each thread uses a separately allocated PathCache - object. In other words, if two threads want to do path - searching, they should each call new_PathCache() to allocate - their own caches. - - -</pre><h2>FILES</h2><pre> - libtecla.a - The tecla library - libtecla.h - The tecla header file. -</pre><h2>SEE ALSO</h2><pre> - <a href="libtecla.html">libtecla(3)</a>, <a href="gl_get_line.html">gl_get_line(3)</a>, <a href="ef_expand_file.html">ef_expand_file(3)</a>, - <a href="cpl_complete_word.html">cpl_complete_word(3)</a> - - -</pre><h2>AUTHOR</h2><pre> - Martin Shepherd (mcs@astro.caltech.edu) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -</pre> -</body> diff --git a/libtecla-1.4.1/html/release.html b/libtecla-1.4.1/html/release.html deleted file mode 100644 index e0d219c..0000000 --- a/libtecla-1.4.1/html/release.html +++ /dev/null @@ -1,360 +0,0 @@ -<HEAD><TITLE>The tecla library release notes</TITLE></HEAD> -<BODY bgcolor=add8e6><PRE> -This file lists major changes which accompany each new release. - -Version 1.4.1: - - This is a maintenance release. It includes minor changes to support - Mac OS X (Darwin), the QNX real-time operating system, and Cygwin - under Windows. It also fixes an oversight that was preventing the - tab key from inserting tab characters when users unbound the - complete-word action from it. - -Version 1.4.0: - - The contents of the history list can now be saved and restored with - the new gl_save_history() and gl_load_history() functions. - - Event handlers can now be registered to watch for and respond to I/O - on arbitrary file descriptors while gl_get_line() is waiting for - terminal input from the user. See the gl_get_line(3) man page - for details on gl_watch_fd(). - - As an optional alternative to getting configuration information only - from ~/.teclarc, the new gl_configure_getline() function allows - configuration commands to be taken from any of, a string, a - specified application-specific file, and/or a specified - user-specific file. See the gl_get_line(3) man page for details. - - The version number of the library can now be queried using the - libtecla_version() function. See the libtecla(3) man page. - - The new gl_group_history() function allows applications to group - different types of input line in the history buffer, and arrange for - only members of the appropriate group to be recalled on a given call - to gl_get_line(). See the gl_get_line(3) man page. - - The new gl_show_history() function displays the current history list - to a given stdio output stream. See the gl_get_line(3) man page. - - new_GetLine() now allows you to specify a history buffer size of - zero, thus requesting that no history buffer be allocated. You can - subsequently resize or delete the history buffer at any time, by - calling gl_resize_history(), limit the number of lines that are - allowed in the buffer by calling gl_limit_history(), clear either - all history lines from the history list, or just the history lines - that are associated with the current history group, by calling - gl_clear_history, and toggle the history mechanism on and off by - calling gl_toggle_history(). - - The new gl_terminal_size() function can be used to query the - current terminal size. It can also be used to supply a default - terminal size on systems where no mechanism is available for - looking up the size. - - The contents and configuration of the history list can now be - obtained by the calling application, by calling the new - gl_lookup_history(), gl_state_of_history(), gl_range_of_history() - and gl_size_of_history() functions. See the gl_get_line(3) man page. - - Echoing of the input line as it is typed, can now be turned on and - off via the new gl_echo_mode() function. While echoing is disabled, - newly entered input lines are omitted from the history list. See - the gl_get_line(3) man page. - - While the default remains to display the prompt string literally, - the new gl_prompt_style() function can be used to enable text - attribute formatting directives in prompt strings, such as - underlining, bold font, and highlighting directives. - - Signal handling in gl_get_line() is now customizable. The default - signal handling behavior remains essentially the same, except that - the SIGTSTP, SIGTTIN and SIGTTOU are now forwarded to the - corresponding signal handler of the calling program, instead of - causing a SIGSTOP to be sent to the application. It is now possible - to remove signals from the list that are trapped by gl_get_line(), - as well as add new signals to this list. The signal and terminal - environments in which the signal handler of the calling program is - invoked, and what gl_get_line() does after the signal handler - returns, is now customizable on a per signal basis. You can now also - query the last signal that was caught by gl_get_line(). This is - useful when gl_get_line() aborts with errno=EINTR, and you need to - know which signal caused it to abort. - - Key-sequences bound to action functions can now start with printable - characters. Previously only keysequences starting with control or - meta characters were permitted. - - gl_get_line() is now 8-bit clean. If the calling program has - correctly called setlocale(LC_CTYPE,""), then the user can select an - alternate locale by setting the standard LC_CTYPE, LC_ALL, or LANG - environment variables, and international characters can then be - entered directly, either by using a non-US keyboard, or by using a - compose key on a standard US keyboard. Note that in locales in which - meta characters become printable, meta characters no longer match - M-c bindings, which then have to be entered using their escape-c - equivalents. Fortunately most modern terminal emulators either - output the escape-c version by default when the meta key is used, or - can be configured to do so (see the gl_get_line(3) man page), so in - most cases you can continue to use the meta key. - - Completion callback functions can now tell gl_get_line() to return - the input line immediately after a successful tab completion, simply - by setting the last character of the optional continuation suffix to - a newline character (ie. in the call to cpl_add_completion()). - - It is now safe to create and use multiple GetLine objects, albeit - still only from a single thread. In conjunction with the new - gl_configure_getline() function, this optionally allows multiple - GetLine objects with different bindings to be used to implement - different input modes. - - The edit-mode configuration command now accepts the argument, - none. This tells gl_get_line() to revert to using just the native - line editing facilities provided by the terminal driver. This could - be used if the termcap or terminfo entry of the host terminal were - badly corrupted. - - Application callback functions invoked by gl_get_line() can now - change the displayed prompt using the gl_replace_prompt() function. - - Their is now an optional program distributed with the library. This - is a beta release of a program which adds tecla command-line editing - to virtually any third party application without the application - needing to be linked to the library. See the enhance(3) man page for - further details. Although built and installed by default, the - INSTALL document explains how to prevent this. - - The INSTALL document now explains how you can stop the demo programs - from being built and installed. - - NetBSD/termcap fixes. Mike MacFaden reported two problems that he - saw when compiling libtecla under NetBSD. Both cases were related to - the use of termcap. Most systems use terminfo, so this problem has - gone unnoticed until now, and won't have affected the grand majority - of users. The configure script had a bug which prevented the check - for CPP working properly, and getline.c wouldn't compile due to an - undeclared variable when USE_TERMCAP was defined. Both problems have - now been fixed. Note that if you successfully compiled version - 1.3.3, this problem didn't affect you. - - An unfortunate and undocumented binding of the key-sequence M-O was - shadowing the arrow-key bindings on systems that use ^[OA etc. I - have removed this binding (the documented lower case M-o binding - remains bound). Under the KDE konsole terminal this was causing the - arrow keys to do something other than expected. - - There was a bug in the history list code which could result in - strange entries appearing at the start of the history list once - enough history lines had been added to the list to cause the - circular history buffer to wrap. This is now fixed. - -Version 1.3.3: - - Signal handling has been re-written, and documentation of its - behaviour has been added to the gl_get_line(3) man page. In addition - to eliminating race conditions, and appropriately setting errno for - those signals that abort gl_get_line(), many more signals are now - intercepted, making it less likely that the terminal will be left in - raw mode by a signal that isn't trapped by gl_get_line(). - - A bug was also fixed that was leaving the terminal in raw mode if - the editing mode was changed interactively between vi and emacs. - This was only noticeable when running programs from old shells that - don't reset terminal modes. - -Version 1.3.2: - - Tim Eliseo contributed a number of improvements to vi mode, - including a fuller set of vi key-bindings, implementation of the vi - constraint that the cursor can't backup past the point at which - input mode was entered, and restoration of overwritten characters - when backspacing in overwrite mode. There are also now new bindings - to allow users to toggle between vi and emacs modes interactively. - The terminal bell is now used in some circumstances, such as when an - unrecognized key sequence is entered. This can be turned off by the - new nobeep option in the tecla configuration file. - - Unrelated to the above, a problem under Linux which prevented ^Q - from being used to resume terminal output after the user had pressed - ^S, has been fixed. - -Version 1.3.1: - - In vi mode a bug was preventing the history-search-backward and - history-search-forward actions from doing anything when invoked on - empty lines. On empty lines they now act like up-history and - down-history respectively, as in emacs mode. - - When creating shared libraries under Linux, the -soname directive - was being used incorrectly. The result is that Linux binaries linked - with the 1.2.3, 1.2.4 and 1.3.0 versions of the tecla shared - libraries, will refuse to see other versions of the shared library - until relinked with version 1.3.1 or higher. - - The configure script can now handle the fact that under Solaris-2.6 - and earlier, the only curses library is a static one that hides in - /usr/ccs/lib. Under Linux it now also caters for old versions of GNU - ld which don't accept version scripts. - - The demos are now linked against the shared version of the library - if possible. Previously they were always linked with the static - version. - -Version 1.3.0: - - The major change in this release is the addition of an optional vi - command-line editing mode in gl_get_line(), along with lots of new - action functions to support its bindings. To enable this, first - create a ~/.teclarc file if you don't already have one, then add the - following line to it. - - edit-mode vi - - The default vi bindings, which are designed to mimic those of the vi - editor as closely as possible, are described in the gl_get_line(3) - man page. - - A new convenience function called ef_list_expansions() has been - added for listing filename expansions. See the ef_list_expansions(3) - man page for details. This is used in a new list-glob binding, bound - to ^Xg in emacs mode, and ^G in vi input mode. - - A bug has been fixed in the key-binding table expansion code. This - bug would have caused problems to anybody who defined more than - about 18 personalized key-bindings in their ~/.teclarc file. - -Version 1.2.4: - - Buffered I/O is now used for writing to terminals, and where - supported, cursor motion is done with move-n-positions terminfo - capabilities instead of doing lots of move-1-position requests. This - greatly improves how the library feels over slow links. - - You can now optionally compile different architectures in different - directories, without having to make multiple copies of the - distribution. This is documented in the INSTALL file. - - The ksh ~+ directive is now supported. - - Thanks to Markus Gyger for the above improvements. - - Documentation has been added to the INSTALL file describing features - designed to facilitate configuration and installation of the library - as part of larger packages. These features are intended to remove - the need to modify the tecla distribution's configuration and build - procedures when embedding the libtecla distribution in other package - distributions. - - A previous fix to stop the cursor from warping when the last - character of the input line was in the last column of the terminal, - was only being used for the first terminal line of the input line. - It is now used for all subsequent lines as well, as originally - intended. - -Version 1.2.3: - - The installation procedure has been better automated with the - addition of an autoconf configure script. This means that installers - can now compile and install the library by typing: - - ./configure - make - make install - - On all systems this makes at least the normal static version of the - tecla library. It also makes the reentrant version if reentrant - POSIX functions are detected. Under Solaris, Linux and HP-UX the - configuration script arranges for shared libraries to be compiled in - addition to the static libraries. It is hoped that installers will - return information about how to compile shared libraries on other - systems, for inclusion in future releases, and to this end, a new - PORTING guide has been provided. - - The versioning number scheme has been changed. This release would - have been 1.2c, but instead will be refered to as 1.2.3. The - versioning scheme, based on conventions used by Sun Microsystems, is - described in configure.in. - - The library was also tested under HP-UX, and this revealed two - serious bugs, both of which have now been fixed. - - The first bug prevented the library from writing control codes to - terminals on big-endian machines, with the exception of those - running under Solaris. This was due to an int variable being used - where a char was needed. - - The second bug had the symptom that on systems that don't use the - newline character as the control code for moving the cursor down a - line, a newline wasn't started when the user hit enter. - -Version 1.2b: - - Two more minor bug fixes: - - Many terminals don't wrap the cursor to the next line when a - character is written to the rightmost terminal column. Instead, they - delay starting a new line until one more character is written, at - which point they move the cursor two positions. gl_get_line() - wasn't aware of this, so cursor repositionings just after writing - the last character of a column, caused it to erroneously go up a - line. This has now been remedied, using a method that should work - regardless of whether a terminal exhibits this behavior or not. - - Some systems dynamically record the current terminal dimensions in - environment variables called LINES and COLUMNS. On such systems, - during the initial terminal setup, these values should override the - static values read from the terminal information databases, and now - do. Previously they were only used if the dimensions returned by - terminfo/termcap looked bogus. - -Version 1.2a: - - This minor release fixes the following two bugs: - - The initial terminal size and subsequent changes thereto, weren't - being noticed by gl_get_line(). This was because the test for the - existence of TIOCWINSZ was erroneously placed before the inclusion - of termios.h. One of the results was that on input lines that - spanned more than one terminal line, the cursor occasionally jumped - unexpectedly to the previous terminal line. - - On entering a line that wrapped over multiple terminal lines, - gl_get_line() simply output a carriage-return line-feed at the point - at which the user pressed return. Thus if one typed in such a line, - then moved back onto one of the earlier terminal lines before - hitting return, the cursor was left on a line containing part of the - line that had just been entered. This didn't do any harm, but it - looked a mess. - -Version 1.2: - - A new facility for looking up and completing filenames in UNIX-style - paths has now been added (eg. you can search for, or complete - commands using the UNIX PATH environment variable). See the - pca_lookup_file(3) man page. - - The already existing filename completion callback can now be made - selective in what types of files it lists. See the - cpl_complete_word(3) man page. - - Due to its potential to break applications when changed, the use of - the publically defined CplFileArgs structure to configure the - cpl_file_completions() callback is now deprecated. The definition - of this structure has been frozen, and its documentation has been - removed from the man pages. It will remain supported, but if you - have used it, you are recommended to switch to the new method, which - involves a new opaque configuration object, allocated via a provided - constructor function, configured via accessor functions, and - eventually deleted with a provided destructor function. The - cpl_file_completions() callback distinguishes which structure type - it has been sent by virtue of a code placed at the start of the new - structure by the constructor. It is assumed that no existing - applications set the boolean 'escaped' member of the CplFileArgs - structure to 4568. The new method is documented in the - cpl_complete_word(3) man page. - -Version 1.1j - - This was the initial public release on freshmeat.org. -</PRE></BODY> diff --git a/libtecla-1.4.1/install-sh b/libtecla-1.4.1/install-sh deleted file mode 100755 index e9de238..0000000 --- a/libtecla-1.4.1/install-sh +++ /dev/null @@ -1,251 +0,0 @@ -#!/bin/sh -# -# install - install a program, script, or datafile -# This comes from X11R5 (mit/util/scripts/install.sh). -# -# Copyright 1991 by the Massachusetts Institute of Technology -# -# Permission to use, copy, modify, distribute, and sell this software and its -# documentation for any purpose is hereby granted without fee, provided that -# the above copyright notice appear in all copies and that both that -# copyright notice and this permission notice appear in supporting -# documentation, and that the name of M.I.T. not be used in advertising or -# publicity pertaining to distribution of the software without specific, -# written prior permission. M.I.T. makes no representations about the -# suitability of this software for any purpose. It is provided "as is" -# without express or implied warranty. -# -# Calling this script install-sh is preferred over install.sh, to prevent -# `make' implicit rules from creating a file called install from it -# when there is no Makefile. -# -# This script is compatible with the BSD install script, but was written -# from scratch. It can only install one file at a time, a restriction -# shared with many OS's install programs. - - -# set DOITPROG to echo to test this script - -# Don't use :- since 4.3BSD and earlier shells don't like it. -doit="${DOITPROG-}" - - -# put in absolute paths if you don't have them in your path; or use env. vars. - -mvprog="${MVPROG-mv}" -cpprog="${CPPROG-cp}" -chmodprog="${CHMODPROG-chmod}" -chownprog="${CHOWNPROG-chown}" -chgrpprog="${CHGRPPROG-chgrp}" -stripprog="${STRIPPROG-strip}" -rmprog="${RMPROG-rm}" -mkdirprog="${MKDIRPROG-mkdir}" - -transformbasename="" -transform_arg="" -instcmd="$mvprog" -chmodcmd="$chmodprog 0755" -chowncmd="" -chgrpcmd="" -stripcmd="" -rmcmd="$rmprog -f" -mvcmd="$mvprog" -src="" -dst="" -dir_arg="" - -while [ x"$1" != x ]; do - case $1 in - -c) instcmd="$cpprog" - shift - continue;; - - -d) dir_arg=true - shift - continue;; - - -m) chmodcmd="$chmodprog $2" - shift - shift - continue;; - - -o) chowncmd="$chownprog $2" - shift - shift - continue;; - - -g) chgrpcmd="$chgrpprog $2" - shift - shift - continue;; - - -s) stripcmd="$stripprog" - shift - continue;; - - -t=*) transformarg=`echo $1 | sed 's/-t=//'` - shift - continue;; - - -b=*) transformbasename=`echo $1 | sed 's/-b=//'` - shift - continue;; - - *) if [ x"$src" = x ] - then - src=$1 - else - # this colon is to work around a 386BSD /bin/sh bug - : - dst=$1 - fi - shift - continue;; - esac -done - -if [ x"$src" = x ] -then - echo "install: no input file specified" - exit 1 -else - true -fi - -if [ x"$dir_arg" != x ]; then - dst=$src - src="" - - if [ -d $dst ]; then - instcmd=: - chmodcmd="" - else - instcmd=mkdir - fi -else - -# Waiting for this to be detected by the "$instcmd $src $dsttmp" command -# might cause directories to be created, which would be especially bad -# if $src (and thus $dsttmp) contains '*'. - - if [ -f $src -o -d $src ] - then - true - else - echo "install: $src does not exist" - exit 1 - fi - - if [ x"$dst" = x ] - then - echo "install: no destination specified" - exit 1 - else - true - fi - -# If destination is a directory, append the input filename; if your system -# does not like double slashes in filenames, you may need to add some logic - - if [ -d $dst ] - then - dst="$dst"/`basename $src` - else - true - fi -fi - -## this sed command emulates the dirname command -dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` - -# Make sure that the destination directory exists. -# this part is taken from Noah Friedman's mkinstalldirs script - -# Skip lots of stat calls in the usual case. -if [ ! -d "$dstdir" ]; then -defaultIFS=' -' -IFS="${IFS-${defaultIFS}}" - -oIFS="${IFS}" -# Some sh's can't handle IFS=/ for some reason. -IFS='%' -set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` -IFS="${oIFS}" - -pathcomp='' - -while [ $# -ne 0 ] ; do - pathcomp="${pathcomp}${1}" - shift - - if [ ! -d "${pathcomp}" ] ; - then - $mkdirprog "${pathcomp}" - else - true - fi - - pathcomp="${pathcomp}/" -done -fi - -if [ x"$dir_arg" != x ] -then - $doit $instcmd $dst && - - if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && - if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && - if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && - if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi -else - -# If we're going to rename the final executable, determine the name now. - - if [ x"$transformarg" = x ] - then - dstfile=`basename $dst` - else - dstfile=`basename $dst $transformbasename | - sed $transformarg`$transformbasename - fi - -# don't allow the sed command to completely eliminate the filename - - if [ x"$dstfile" = x ] - then - dstfile=`basename $dst` - else - true - fi - -# Make a temp file name in the proper directory. - - dsttmp=$dstdir/#inst.$$# - -# Move or copy the file name to the temp name - - $doit $instcmd $src $dsttmp && - - trap "rm -f ${dsttmp}" 0 && - -# and set any options; do chmod last to preserve setuid bits - -# If any of these fail, we abort the whole thing. If we want to -# ignore errors from any of these, just make sure not to ignore -# errors from the above "$doit $instcmd $src $dsttmp" command. - - if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && - if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && - if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && - if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && - -# Now rename the file to the real destination. - - $doit $rmcmd -f $dstdir/$dstfile && - $doit $mvcmd $dsttmp $dstdir/$dstfile - -fi && - - -exit 0 diff --git a/libtecla-1.4.1/keytab.c b/libtecla-1.4.1/keytab.c deleted file mode 100644 index b2bab8b..0000000 --- a/libtecla-1.4.1/keytab.c +++ /dev/null @@ -1,827 +0,0 @@ -/* - * Copyright (c) 2000, 2001 by Martin C. Shepherd. - * - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL - * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> - -#include "keytab.h" -#include "getline.h" -#include "strngmem.h" - -static int _kt_extend_table(KeyTab *kt); -static int _kt_parse_keybinding_string(const char *keyseq, - char *binary, int *nc); -static int _kt_compare_strings(const char *s1, int n1, const char *s2, int n2); -static void _kt_assign_action(KeySym *sym, KtBinder binder, KtKeyFn *keyfn); -static char _kt_backslash_escape(const char *string, const char **endp); -static int _kt_is_emacs_meta(const char *string); -static int _kt_is_emacs_ctrl(const char *string); - -/*....................................................................... - * Create a new key-binding symbol table. - * - * Output: - * return KeyTab * The new object, or NULL on error. - */ -KeyTab *_new_KeyTab(void) -{ - KeyTab *kt; /* The object to be returned */ -/* - * Allocate the container. - */ - kt = (KeyTab *) malloc(sizeof(KeyTab)); - if(!kt) { - fprintf(stderr, "new_KeyTab: Insufficient memory.\n"); - return NULL; - }; -/* - * Before attempting any operation that might fail, initialize the - * container at least up to the point at which it can safely be passed - * to del_KeyTab(). - */ - kt->size = KT_TABLE_INC; - kt->nkey = 0; - kt->table = NULL; - kt->actions = NULL; - kt->smem = NULL; -/* - * Allocate the table. - */ - kt->table = (KeySym *) malloc(sizeof(kt->table[0]) * kt->size); - if(!kt->table) { - fprintf(stderr, "new_KeyTab: Insufficient memory for table of size %d.\n", - kt->size); - return _del_KeyTab(kt); - }; -/* - * Allocate a hash table of actions. - */ - kt->actions = _new_HashTable(NULL, KT_HASH_SIZE, IGNORE_CASE, NULL, 0); - if(!kt->actions) - return _del_KeyTab(kt); -/* - * Allocate a string allocation object. This allows allocation of - * small strings without fragmenting the heap. - */ - kt->smem = _new_StringMem("new_KeyTab", KT_TABLE_INC); - if(!kt->smem) - return _del_KeyTab(kt); - return kt; -} - -/*....................................................................... - * Delete a KeyTab object. - * - * Input: - * kt KeyTab * The object to be deleted. - * Output: - * return KeyTab * The deleted object (always NULL). - */ -KeyTab *_del_KeyTab(KeyTab *kt) -{ - if(kt) { - if(kt->table) - free(kt->table); - kt->actions = _del_HashTable(kt->actions); - kt->smem = _del_StringMem("del_KeyTab", kt->smem, 1); - free(kt); - }; - return NULL; -} - -/*....................................................................... - * Increase the size of the table to accomodate more keys. - * - * Input: - * kt KeyTab * The table to be extended. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int _kt_extend_table(KeyTab *kt) -{ -/* - * Attempt to increase the size of the table. - */ - KeySym *newtab = (KeySym *) realloc(kt->table, sizeof(kt->table[0]) * - (kt->size + KT_TABLE_INC)); -/* - * Failed? - */ - if(!newtab) { - fprintf(stderr, - "getline(): Insufficient memory to extend keybinding table.\n"); - return 1; - }; -/* - * Install the resized table. - */ - kt->table = newtab; - kt->size += KT_TABLE_INC; - return 0; -} - -/*....................................................................... - * Add, update or remove a keybinding to the table. - * - * Input: - * kt KeyTab * The table to add the binding to. - * binder KtBinder The source of the binding. - * keyseq const char * The key-sequence to bind. - * action char * The action to associate with the key sequence, or - * NULL to remove the action associated with the - * key sequence. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int _kt_set_keybinding(KeyTab *kt, KtBinder binder, const char *keyseq, - const char *action) -{ - KtKeyFn *keyfn; /* The action function */ -/* - * Check arguments. - */ - if(kt==NULL || !keyseq) { - fprintf(stderr, "kt_set_keybinding: NULL argument(s).\n"); - return 1; - }; -/* - * Lookup the function that implements the specified action. - */ - if(!action) { - keyfn = 0; - } else { - Symbol *sym = _find_HashSymbol(kt->actions, action); - if(!sym) { - fprintf(stderr, "getline: Unknown key-binding action: %s\n", action); - return 1; - }; - keyfn = (KtKeyFn *) sym->fn; - }; -/* - * Record the action in the table. - */ - return _kt_set_keyfn(kt, binder, keyseq, keyfn); -} - -/*....................................................................... - * Add, update or remove a keybinding to the table, specifying an action - * function directly. - * - * Input: - * kt KeyTab * The table to add the binding to. - * binder KtBinder The source of the binding. - * keyseq char * The key-sequence to bind. - * keyfn KtKeyFn * The action function, or NULL to remove any existing - * action function. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int _kt_set_keyfn(KeyTab *kt, KtBinder binder, const char *keyseq, - KtKeyFn *keyfn) -{ - const char *kptr; /* A pointer into keyseq[] */ - char *binary; /* The binary version of keyseq[] */ - int nc; /* The number of characters in binary[] */ - int first,last; /* The first and last entries in the table which */ - /* minimally match. */ - int size; /* The size to allocate for the binary string */ -/* - * Check arguments. - */ - if(kt==NULL || !keyseq) { - fprintf(stderr, "kt_set_keybinding: NULL argument(s).\n"); - return 1; - }; -/* - * Work out a pessimistic estimate of how much space will be needed - * for the binary copy of the string, noting that binary meta characters - * embedded in the input string get split into two characters. - */ - for(size=0,kptr = keyseq; *kptr; kptr++) - size += IS_META_CHAR(*kptr) ? 2 : 1; -/* - * Allocate a string that has the length of keyseq[]. - */ - binary = _new_StringMemString(kt->smem, size + 1); - if(!binary) { - fprintf(stderr, - "gl_get_line: Insufficient memory to record key sequence.\n"); - return 1; - }; -/* - * Convert control and octal character specifications to binary characters. - */ - if(_kt_parse_keybinding_string(keyseq, binary, &nc)) { - binary = _del_StringMemString(kt->smem, binary); - return 1; - }; -/* - * Lookup the position in the table at which to insert the binding. - */ - switch(_kt_lookup_keybinding(kt, binary, nc, &first, &last)) { -/* - * If an exact match for the key-sequence is already in the table, - * simply replace its binding function (or delete the entry if - * the new binding is 0). - */ - case KT_EXACT_MATCH: - if(keyfn) { - _kt_assign_action(kt->table + first, binder, keyfn); - } else { - _del_StringMemString(kt->smem, kt->table[first].keyseq); - memmove(kt->table + first, kt->table + first + 1, - (kt->nkey - first - 1) * sizeof(kt->table[0])); - kt->nkey--; - }; - binary = _del_StringMemString(kt->smem, binary); - break; -/* - * If an ambiguous match has been found and we are installing a - * callback, then our new key-sequence would hide all of the ambiguous - * matches, so we shouldn't allow it. - */ - case KT_AMBIG_MATCH: - if(keyfn) { - fprintf(stderr, - "getline: Can't bind \"%s\", because it's a prefix of another binding.\n", - keyseq); - binary = _del_StringMemString(kt->smem, binary); - return 1; - }; - break; -/* - * If the entry doesn't exist, create it. - */ - case KT_NO_MATCH: -/* - * Add a new binding? - */ - if(keyfn) { - KeySym *sym; -/* - * We will need a new entry, extend the table if needed. - */ - if(kt->nkey + 1 > kt->size) { - if(_kt_extend_table(kt)) { - binary = _del_StringMemString(kt->smem, binary); - return 1; - }; - }; -/* - * Make space to insert the new key-sequence before 'last'. - */ - if(last < kt->nkey) { - memmove(kt->table + last + 1, kt->table + last, - (kt->nkey - last) * sizeof(kt->table[0])); - }; -/* - * Insert the new binding in the vacated position. - */ - sym = kt->table + last; - sym->keyseq = binary; - sym->nc = nc; - sym->user_fn = sym->term_fn = sym->norm_fn = sym->keyfn = 0; - _kt_assign_action(sym, binder, keyfn); - kt->nkey++; - }; - break; - case KT_BAD_MATCH: - binary = _del_StringMemString(kt->smem, binary); - return 1; - break; - }; - return 0; -} - -/*....................................................................... - * Perform a min-match lookup of a key-binding. - * - * Input: - * kt KeyTab * The keybinding table to lookup in. - * binary_keyseq char * The binary key-sequence to lookup. - * nc int the number of characters in keyseq[]. - * Input/Output: - * first,last int * If there is an ambiguous or exact match, the indexes - * of the first and last symbols that minimally match - * will be assigned to *first and *last respectively. - * If there is no match, then first and last will - * bracket the location where the symbol should be - * inserted. - * - * Output: - * return KtKeyMatch One of the following enumerators: - * KT_EXACT_MATCH - An exact match was found. - * KT_AMBIG_MATCH - An ambiguous match was found. - * KT_NO_MATCH - No match was found. - * KT_BAD_MATCH - An error occurred while searching. - */ -KtKeyMatch _kt_lookup_keybinding(KeyTab *kt, const char *binary_keyseq, int nc, - int *first, int *last) -{ - int mid; /* The index at which to bisect the table */ - int bot; /* The lowest index of the table not searched yet */ - int top; /* The highest index of the table not searched yet */ - int test; /* The return value of strcmp() */ -/* - * Check the arguments. - */ - if(!kt || !binary_keyseq || !first || !last || nc < 0) { - fprintf(stderr, "kt_lookup_keybinding: NULL argument(s).\n"); - return KT_BAD_MATCH; - }; -/* - * Perform a binary search for the key-sequence. - */ - bot = 0; - top = kt->nkey - 1; - while(top >= bot) { - mid = (top + bot)/2; - test = _kt_compare_strings(kt->table[mid].keyseq, kt->table[mid].nc, - binary_keyseq, nc); - if(test > 0) - top = mid - 1; - else if(test < 0) - bot = mid + 1; - else { - *first = *last = mid; - return KT_EXACT_MATCH; - }; - }; -/* - * An exact match wasn't found, but top is the index just below the - * index where a match would be found, and bot is the index just above - * where the match ought to be found. - */ - *first = top; - *last = bot; -/* - * See if any ambiguous matches exist, and if so make *first and *last - * refer to the first and last matches. - */ - if(*last < kt->nkey && kt->table[*last].nc > nc && - _kt_compare_strings(kt->table[*last].keyseq, nc, binary_keyseq, nc)==0) { - *first = *last; - while(*last+1 < kt->nkey && kt->table[*last+1].nc > nc && - _kt_compare_strings(kt->table[*last+1].keyseq, nc, binary_keyseq, nc)==0) - (*last)++; - return KT_AMBIG_MATCH; - }; -/* - * No match. - */ - return KT_NO_MATCH; -} - -/*....................................................................... - * Convert a keybinding string into a uniq binary representation. - * - * Control characters can be given directly in their binary form, - * expressed as either ^ or C-, followed by the character, expressed in - * octal, like \129 or via C-style backslash escapes, with the addition - * of '\E' to denote the escape key. Similarly, meta characters can be - * given directly in binary or expressed as M- followed by the character. - * Meta characters are recorded as two characters in the binary output - * string, the first being the escape key, and the second being the key - * that was modified by the meta key. This means that binding to - * \EA or ^[A or M-A are all equivalent. - * - * Input: - * keyseq char * The key sequence being added. - * Input/Output: - * binary char * The binary version of the key sequence will be - * assigned to binary[], which must have at least - * as many characters as keyseq[] plus the number - * of embedded binary meta characters. - * nc int * The number of characters assigned to binary[] - * will be recorded in *nc. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int _kt_parse_keybinding_string(const char *keyseq, char *binary, - int *nc) -{ - const char *iptr = keyseq; /* Pointer into keyseq[] */ - char *optr = binary; /* Pointer into binary[] */ -/* - * Parse the input characters until they are exhausted or the - * output string becomes full. - */ - while(*iptr) { -/* - * Check for special characters. - */ - switch(*iptr) { - case '^': /* A control character specification */ -/* - * Convert the caret expression into the corresponding control - * character unless no character follows the caret, in which case - * record a literal caret. - */ - if(iptr[1]) { - *optr++ = MAKE_CTRL(iptr[1]); - iptr += 2; - } else { - *optr++ = *iptr++; - }; - break; -/* - * A backslash-escaped character? - */ - case '\\': -/* - * Convert the escape sequence to a binary character. - */ - *optr++ = _kt_backslash_escape(iptr+1, &iptr); - break; -/* - * Possibly an emacs-style meta character? - */ - case 'M': - if(_kt_is_emacs_meta(iptr)) { - *optr++ = GL_ESC_CHAR; - iptr += 2; - } else { - *optr++ = *iptr++; - }; - break; -/* - * Possibly an emacs-style control character specification? - */ - case 'C': - if(_kt_is_emacs_ctrl(iptr)) { - *optr++ = MAKE_CTRL(iptr[2]); - iptr += 3; - } else { - *optr++ = *iptr++; - }; - break; - default: - -/* - * Convert embedded meta characters into an escape character followed - * by the meta-unmodified character. - */ - if(IS_META_CHAR(*iptr)) { - *optr++ = GL_ESC_CHAR; - *optr++ = META_TO_CHAR(*iptr); - iptr++; -/* - * To allow keysequences that start with printable characters to - * be distinguished from the cursor-key keywords, prepend a backslash - * to the former. This same operation is performed in gl_interpret_char() - * before looking up a keysequence that starts with a printable character. - */ - } else if(iptr==keyseq && !IS_CTRL_CHAR(*iptr) && - strcmp(keyseq, "up") != 0 && strcmp(keyseq, "down") != 0 && - strcmp(keyseq, "left") != 0 && strcmp(keyseq, "right") != 0) { - *optr++ = '\\'; - *optr++ = *iptr++; - } else { - *optr++ = *iptr++; - }; - }; - }; -/* - * How many characters were placed in the output array? - */ - *nc = optr - binary; - return 0; -} - -/*....................................................................... - * Add, remove or modify an action. - * - * Input: - * kt KeyTab * The key-binding table. - * action char * The name of the action. - * fn KtKeyFn * The function that implements the action, or NULL - * to remove an existing action. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int _kt_set_action(KeyTab *kt, const char *action, KtKeyFn *fn) -{ - Symbol *sym; /* The symbol table entry of the action */ -/* - * Check the arguments. - */ - if(!kt || !action) { - fprintf(stderr, "kt_set_action: NULL argument(s).\n"); - return 1; - }; -/* - * If no function was provided, delete an existing action. - */ - if(!fn) { - sym = _del_HashSymbol(kt->actions, action); - return 0; - }; -/* - * If the action already exists, replace its action function. - */ - sym = _find_HashSymbol(kt->actions, action); - if(sym) { - sym->fn = (void (*)(void))fn; - return 0; - }; -/* - * Add a new action. - */ - if(!_new_HashSymbol(kt->actions, action, 0, (void (*)(void))fn, NULL, 0)) { - fprintf(stderr, "Insufficient memory to record new key-binding action.\n"); - return 1; - }; - return 0; -} - -/*....................................................................... - * Compare two strings of specified length which may contain embedded - * ascii NUL's. - * - * Input: - * s1 char * The first of the strings to be compared. - * n1 int The length of the string in s1. - * s2 char * The second of the strings to be compared. - * n2 int The length of the string in s2. - * Output: - * return int < 0 if(s1 < s2) - * 0 if(s1 == s2) - * > 0 if(s1 > s2) - */ -static int _kt_compare_strings(const char *s1, int n1, const char *s2, int n2) -{ - int i; -/* - * Find the first character where the two strings differ. - */ - for(i=0; i<n1 && i<n2 && s1[i]==s2[i]; i++) - ; -/* - * Did we hit the end of either string before finding a difference? - */ - if(i==n1 || i==n2) { - if(n1 == n2) - return 0; - else if(n1==i) - return -1; - else - return 1; - }; -/* - * Compare the two characters that differed to determine which - * string is greatest. - */ - return s1[i] - s2[i]; -} - -/*....................................................................... - * Assign a given action function to a binding table entry. - * - * Input: - * sym KeySym * The binding table entry to be modified. - * binder KtBinder The source of the binding. - * keyfn KtKeyFn * The action function. - */ -static void _kt_assign_action(KeySym *sym, KtBinder binder, KtKeyFn *keyfn) -{ -/* - * Record the action according to its source. - */ - switch(binder) { - case KTB_USER: - sym->user_fn = keyfn; - break; - case KTB_TERM: - sym->term_fn = keyfn; - break; - case KTB_NORM: - default: - sym->norm_fn = keyfn; - break; - }; -/* - * Which of the current set of bindings should be used? - */ - if(sym->user_fn) - sym->keyfn = sym->user_fn; - else if(sym->norm_fn) - sym->keyfn = sym->norm_fn; - else - sym->keyfn = sym->term_fn; - return; -} - -/*....................................................................... - * Remove all key bindings that came from a specified source. - * - * Input: - * kt KeyTab * The table of key bindings. - * binder KtBinder The source of the bindings to be cleared. - */ -void _kt_clear_bindings(KeyTab *kt, KtBinder binder) -{ - int oldkey; /* The index of a key in the original binding table */ - int newkey; /* The index of a key in the updated binding table */ -/* - * If there is no table, then no bindings exist to be deleted. - */ - if(!kt) - return; -/* - * Clear bindings of the given source. - */ - for(oldkey=0; oldkey<kt->nkey; oldkey++) - _kt_assign_action(kt->table + oldkey, binder, 0); -/* - * Delete entries that now don't have a binding from any source. - */ - newkey = 0; - for(oldkey=0; oldkey<kt->nkey; oldkey++) { - KeySym *sym = kt->table + oldkey; - if(!sym->keyfn) { - _del_StringMemString(kt->smem, sym->keyseq); - } else { - if(oldkey != newkey) - kt->table[newkey] = *sym; - newkey++; - }; - }; -/* - * Record the number of keys that were kept. - */ - kt->nkey = newkey; - return; -} - -/*....................................................................... - * Translate a backslash escape sequence to a binary character. - * - * Input: - * string const char * The characters that follow the backslash. - * Input/Output: - * endp const char ** If endp!=NULL, on return *endp will be made to - * point to the character in string[] which follows - * the escape sequence. - * Output: - * return char The binary character. - */ -static char _kt_backslash_escape(const char *string, const char **endp) -{ - char c; /* The output character */ -/* - * Is the backslash followed by one or more octal digits? - */ - switch(*string) { - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - c = strtol(string, (char **)&string, 8); - break; - case 'a': - c = '\a'; - string++; - break; - case 'b': - c = '\b'; - string++; - break; - case 'e': case 'E': /* Escape */ - c = GL_ESC_CHAR; - string++; - break; - case 'f': - c = '\f'; - string++; - break; - case 'n': - c = '\n'; - string++; - break; - case 'r': - c = '\r'; - string++; - break; - case 't': - c = '\t'; - string++; - break; - case 'v': - c = '\v'; - string++; - break; - case '\0': - c = '\\'; - break; - default: - c = *string++; - break; - }; -/* - * Report the character which follows the escape sequence. - */ - if(endp) - *endp = string; - return c; -} - -/*....................................................................... - * Return non-zero if the next two characters are M- and a third character - * follows. Otherwise return 0. - * - * Input: - * string const char * The sub-string to scan. - * Output: - * return int 1 - The next two characters are M- and these - * are followed by at least one character. - * 0 - The next two characters aren't M- or no - * character follows a M- pair. - */ -static int _kt_is_emacs_meta(const char *string) -{ - return *string++ == 'M' && *string++ == '-' && *string; -} - -/*....................................................................... - * Return non-zero if the next two characters are C- and a third character - * follows. Otherwise return 0. - * - * Input: - * string const char * The sub-string to scan. - * Output: - * return int 1 - The next two characters are C- and these - * are followed by at least one character. - * 0 - The next two characters aren't C- or no - * character follows a C- pair. - */ -static int _kt_is_emacs_ctrl(const char *string) -{ - return *string++ == 'C' && *string++ == '-' && *string; -} - -/*....................................................................... - * Merge an array of bindings with existing bindings. - * - * Input: - * kt KeyTab * The table of key bindings. - * binder KtBinder The source of the bindings. - * bindings const KtKeyBinding * The array of bindings. - * n int The number of bindings in bindings[]. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int _kt_add_bindings(KeyTab *kt, KtBinder binder, const KtKeyBinding *bindings, - unsigned n) -{ - int i; -/* - * Check the arguments. - */ - if(!kt || !bindings) { - fprintf(stderr, "_kt_add_bindings: NULL argument(s).\n"); - return 1; - }; -/* - * Install the array of bindings. - */ - for(i=0; i<n; i++) { - if(_kt_set_keybinding(kt, binder, bindings[i].keyseq, bindings[i].action)) - return 1; - }; - return 0; -} - diff --git a/libtecla-1.4.1/keytab.h b/libtecla-1.4.1/keytab.h deleted file mode 100644 index 9436e8f..0000000 --- a/libtecla-1.4.1/keytab.h +++ /dev/null @@ -1,146 +0,0 @@ -#ifndef keytab_h -#define keytab_h - -/* - * Copyright (c) 2000, 2001 by Martin C. Shepherd. - * - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL - * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - */ - -#include "libtecla.h" -#include "hash.h" -#include "strngmem.h" - -/*-----------------------------------------------------------------------* - * This module defines a binary-search symbol table of key-bindings. * - *-----------------------------------------------------------------------*/ - -/* - * All key-binding functions are defined as follows. - * - * Input: - * gl GetLine * The resource object of this library. - * count int A positive repeat count specified by the user, - * or 1. Action functions should ignore this if - * repeating the action multiple times isn't - * appropriate. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -#define KT_KEY_FN(fn) int (fn)(GetLine *gl, int count) - -typedef KT_KEY_FN(KtKeyFn); - -/* - * Define an entry of a key-binding binary symbol table. - */ -typedef struct { - char *keyseq; /* The key sequence that triggers the macro */ - int nc; /* The number of characters in keyseq[] */ - KtKeyFn *user_fn; /* A user specified binding (or 0 if none) */ - KtKeyFn *term_fn; /* A terminal-specific binding (or 0 if none) */ - KtKeyFn *norm_fn; /* The default binding (or 0 if none) */ - KtKeyFn *keyfn; /* The function to execute when this key sequence */ - /* is seen. This is the function above which has */ - /* the highest priority. */ -} KeySym; - -/* - * When allocating or reallocating the key-binding table, how - * many entries should be added? - */ -#define KT_TABLE_INC 100 - -/* - * Define the size of the hash table that is used to associate action - * names with action functions. This should be a prime number. - */ -#define KT_HASH_SIZE 113 - -/* - * Define a binary-symbol-table object. - */ -typedef struct { - int size; /* The allocated dimension of table[] */ - int nkey; /* The current number of members in the table */ - KeySym *table; /* The table of lexically sorted key sequences */ - HashTable *actions; /* The hash table of actions */ - StringMem *smem; /* Memory for allocating strings */ -} KeyTab; - -KeyTab *_new_KeyTab(void); -KeyTab *_del_KeyTab(KeyTab *kt); - -/* - * Enumerate the possible sources of key-bindings. - */ -typedef enum { - KTB_USER, /* This is a binding being set by the user */ - KTB_TERM, /* This is a binding taken from the terminal settings */ - KTB_NORM /* This is the default binding set by the library */ -} KtBinder; - -int _kt_set_keybinding(KeyTab *kt, KtBinder binder, - const char *keyseq, const char *action); -int _kt_set_keyfn(KeyTab *kt, KtBinder binder, const char *keyseq, - KtKeyFn *keyfn); - -int _kt_set_action(KeyTab *kt, const char *action, KtKeyFn *fn); - -typedef enum { - KT_EXACT_MATCH, /* An exact match was found */ - KT_AMBIG_MATCH, /* An ambiguous match was found */ - KT_NO_MATCH, /* No match was found */ - KT_BAD_MATCH /* An error occurred while searching */ -} KtKeyMatch; - -KtKeyMatch _kt_lookup_keybinding(KeyTab *kt, const char *binary_keyseq, - int nc, int *first,int *last); - -/* - * Remove all key bindings that came from a specified source. - */ -void _kt_clear_bindings(KeyTab *kt, KtBinder binder); - -/* - * When installing an array of keybings each binding is defined by - * an element of the following type: - */ -typedef struct { - const char *keyseq; /* The sequence of keys that trigger this binding */ - const char *action; /* The name of the action function that is triggered */ -} KtKeyBinding; - -/* - * Merge an array of bindings with existing bindings. - */ -int _kt_add_bindings(KeyTab *kt, KtBinder binder, const KtKeyBinding *bindings, - unsigned n); - -#endif diff --git a/libtecla-1.4.1/libtecla.h b/libtecla-1.4.1/libtecla.h deleted file mode 100644 index f124dd0..0000000 --- a/libtecla-1.4.1/libtecla.h +++ /dev/null @@ -1,1194 +0,0 @@ -#ifndef libtecla_h -#define libtecla_h - -/* - * Copyright (c) 2000, 2001 by Martin C. Shepherd. - * - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL - * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include <stdio.h> /* FILE * */ -#include <stdlib.h> /* size_t */ -#include <time.h> /* time_t */ - -/* - * The following are the three components of the libtecla version number. - * Note that it is better to use the libtecla_version() function than these - * macros since the macros only tell you which version of the library your - * code was compiled against, whereas the libtecla_version() function - * tells you which version of the shared tecla library your program is - * actually linked to. - */ -#define TECLA_MAJOR_VER 1 -#define TECLA_MINOR_VER 4 -#define TECLA_MICRO_VER 1 - -/*....................................................................... - * Query the version number of the tecla library. - * - * Input: - * major int * The major version number of the library - * will be assigned to *major. This number is - * only incremented when a change to the library is - * made that breaks binary (shared library) and/or - * compilation backwards compatibility. - * minor int * The minor version number of the library - * will be assigned to *minor. This number is - * incremented whenever new functions are added to - * the public API. - * micro int * The micro version number of the library will be - * assigned to *micro. This number is incremented - * whenever internal changes are made that don't - * change the public API, such as bug fixes and - * performance enhancements. - */ -void libtecla_version(int *major, int *minor, int *micro); - -/*----------------------------------------------------------------------- - * The getline module provides interactive command-line input, recall - * and editing by users at terminals. See the gl_getline(3) man page for - * more details. - *-----------------------------------------------------------------------*/ - -/* - * Provide an opaque handle for the resource object that is defined in - * getline.h. - */ -typedef struct GetLine GetLine; - -/* - * The following two functions are used to create and delete the - * resource objects that are used by the gl_getline() function. - */ -GetLine *new_GetLine(size_t linelen, size_t histlen); -GetLine *del_GetLine(GetLine *gl); - -/* - * Read a line into an internal buffer of gl. - */ -char *gl_get_line(GetLine *gl, const char *prompt, const char *start_line, - int start_pos); - -/* - * Configure the application specific and/or user-specific behavior of - * gl_get_line(). - */ -int gl_configure_getline(GetLine *gl, const char *app_string, - const char *app_file, const char *user_file); - -/*----------------------------------------------------------------------- - * The file-expansion module provides facilities for expanding ~user/ and - * $envvar expressions, and for expanding glob-style wildcards. - * See the ef_expand_file(3) man page for more details. - *-----------------------------------------------------------------------*/ - -/* - * ExpandFile objects contain the resources needed to expand pathnames. - */ -typedef struct ExpandFile ExpandFile; - -/* - * The following functions are used to create and delete the resource - * objects that are used by the ef_expand_file() function. - */ -ExpandFile *new_ExpandFile(void); -ExpandFile *del_ExpandFile(ExpandFile *ef); - -/* - * A container of the following type is returned by ef_expand_file(). - */ -typedef struct { - int exists; /* True if the files in files[] currently exist. */ - /* This only time that this may not be true is if */ - /* the input filename didn't contain any wildcards */ - /* and thus wasn't matched against existing files. */ - /* In this case the single entry in 'nfile' may not */ - /* refer to an existing file. */ - int nfile; /* The number of files in files[] */ - char **files; /* An array of 'nfile' filenames. */ -} FileExpansion; - -/* - * The ef_expand_file() function expands a specified pathname, converting - * ~user/ and ~/ patterns at the start of the pathname to the - * corresponding home directories, replacing $envvar with the value of - * the corresponding environment variable, and then, if there are any - * wildcards, matching these against existing filenames. - * - * If no errors occur, a container is returned containing the array of - * files that resulted from the expansion. If there were no wildcards - * in the input pathname, this will contain just the original pathname - * after expansion of ~ and $ expressions. If there were any wildcards, - * then the array will contain the files that matched them. Note that - * if there were any wildcards but no existing files match them, this - * is counted as an error and NULL is returned. - * - * The supported wildcards and their meanings are: - * * - Match any sequence of zero or more characters. - * ? - Match any single character. - * [chars] - Match any single character that appears in 'chars'. - * If 'chars' contains an expression of the form a-b, - * then any character between a and b, including a and b, - * matches. The '-' character looses its special meaning - * as a range specifier when it appears at the start - * of the sequence of characters. - * [^chars] - The same as [chars] except that it matches any single - * character that doesn't appear in 'chars'. - * - * Wildcard expressions are applied to individual filename components. - * They don't match across directory separators. A '.' character at - * the beginning of a filename component must also be matched - * explicitly by a '.' character in the input pathname, since these - * are UNIX's hidden files. - * - * Input: - * fe ExpandFile * The pathname expansion resource object. - * path const char * The path name to be expanded. - * pathlen int The length of the suffix of path[] that - * constitutes the filename to be expanded, - * or -1 to specify that the whole of the - * path string should be used. - * Output: - * return FileExpansion * A pointer to a results container within the - * given ExpandFile object. This contains an - * array of the pathnames that resulted from - * expanding ~ and $ expressions and from - * matching any wildcards, sorted into lexical - * order. - * - * This container and its contents will be - * recycled on subsequent calls, so if you need - * to keep the results of two successive runs, - * you will either have to allocate a private - * copy of the array, or use two ExpandFile - * objects. - * - * On error, NULL is returned. A description - * of the error can be acquired by calling the - * ef_last_error() function. - */ -FileExpansion *ef_expand_file(ExpandFile *ef, const char *path, int pathlen); - -/*....................................................................... - * Print out an array of matching files. - * - * Input: - * result FileExpansion * The container of the sorted array of - * expansions. - * fp FILE * The output stream to write to. - * term_width int The width of the terminal. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int ef_list_expansions(FileExpansion *result, FILE *fp, int term_width); - -/* - * The ef_last_error() function returns a description of the last error - * that occurred in a call ef_expand_file(). Note that this message is - * contained in an array which is allocated as part of *ef, and its - * contents thus potentially change on every call to ef_expand_file(). - */ -const char *ef_last_error(ExpandFile *ef); - -/*----------------------------------------------------------------------- - * The WordCompletion module is used for completing incomplete words, such - * as filenames. Programs can use functions within this module to register - * their own customized completion functions. - *-----------------------------------------------------------------------*/ - -/* - * Ambiguous completion matches are recorded in objects of the - * following type. - */ -typedef struct WordCompletion WordCompletion; - -/* - * Create a new completion object. - */ -WordCompletion *new_WordCompletion(void); - -/* - * Delete a redundant completion object. - */ -WordCompletion *del_WordCompletion(WordCompletion *cpl); - -/*....................................................................... - * Callback functions declared and prototyped using the following macro - * are called upon to return an array of possible completion suffixes - * for the token that precedes a specified location in the given - * input line. It is up to this function to figure out where the token - * starts, and to call cpl_add_completion() to register each possible - * completion before returning. - * - * Input: - * cpl WordCompletion * An opaque pointer to the object that will - * contain the matches. This should be filled - * via zero or more calls to cpl_add_completion(). - * data void * The anonymous 'data' argument that was - * passed to cpl_complete_word() or - * gl_customize_completion()). - * line const char * The current input line. - * word_end int The index of the character in line[] which - * follows the end of the token that is being - * completed. - * Output - * return int 0 - OK. - * 1 - Error. - */ -#define CPL_MATCH_FN(fn) int (fn)(WordCompletion *cpl, void *data, \ - const char *line, int word_end) -typedef CPL_MATCH_FN(CplMatchFn); - -/*....................................................................... - * Optional callback functions declared and prototyped using the - * following macro are called upon to return non-zero if a given - * file, specified by its pathname, is to be included in a list of - * completions. - * - * Input: - * data void * The application specified pointer which - * was specified when this callback function - * was registered. This can be used to have - * anything you like passed to your callback. - * pathname const char * The pathname of the file to be checked to - * see if it should be included in the list - * of completions. - * Output - * return int 0 - Ignore this file. - * 1 - Do include this file in the list - * of completions. - */ -#define CPL_CHECK_FN(fn) int (fn)(void *data, const char *pathname) -typedef CPL_CHECK_FN(CplCheckFn); - -/* - * You can use the following CplCheckFn callback function to only - * have executables included in a list of completions. - */ -CPL_CHECK_FN(cpl_check_exe); - -/* - * cpl_file_completions() is the builtin filename completion callback - * function. This can also be called by your own custom CPL_MATCH_FN() - * callback functions. To do this pass on all of the arguments of your - * custom callback function to cpl_file_completions(), with the exception - * of the (void *data) argument. The data argument should either be passed - * NULL to request the default behaviour of the file-completion function, - * or be passed a pointer to a CplFileConf structure (see below). In the - * latter case the contents of the structure modify the behavior of the - * file-completer. - */ -CPL_MATCH_FN(cpl_file_completions); - -/* - * Objects of the following type can be used to change the default - * behavior of the cpl_file_completions() callback function. - */ -typedef struct CplFileConf CplFileConf; - -/* - * If you want to change the behavior of the cpl_file_completions() - * callback function, call the following function to allocate a - * configuration object, then call one or more of the subsequent - * functions to change any of the default configuration parameters - * that you don't want. This function returns NULL when there is - * insufficient memory. - */ -CplFileConf *new_CplFileConf(void); - -/* - * If backslashes in the prefix being passed to cpl_file_completions() - * should be treated as literal characters, call the following function - * with literal=1. Otherwise the default is to treat them as escape - * characters which remove the special meanings of spaces etc.. - */ -void cfc_literal_escapes(CplFileConf *cfc, int literal); - -/* - * Before calling cpl_file_completions(), call this function if you - * know the index at which the filename prefix starts in the input line. - * Otherwise by default, or if you specify start_index to be -1, the - * filename is taken to start after the first unescaped space preceding - * the cursor, or the start of the line, which ever comes first. - */ -void cfc_file_start(CplFileConf *cfc, int start_index); - -/* - * If you only want certain types of files to be included in the - * list of completions, use the following function to specify a - * callback function which will be called to ask whether a given file - * should be included. The chk_data argument is will be passed to the - * callback function whenever it is called and can be anything you want. - */ -void cfc_set_check_fn(CplFileConf *cfc, CplCheckFn *chk_fn, void *chk_data); - -/* - * The following function deletes a CplFileConf objects previously - * returned by new_CplFileConf(). It always returns NULL. - */ -CplFileConf *del_CplFileConf(CplFileConf *cfc); - -/* - * The following configuration structure is deprecated. Do not change - * its contents, since this will break any programs that still use it, - * and don't use it in new programs. Instead use opaque CplFileConf - * objects as described above. cpl_file_completions() figures out - * what type of structure you pass it, by virtue of a magic int code - * placed at the start of CplFileConf object by new_CplFileConf(). - */ -typedef struct { - int escaped; /* Opposite to the argument of cfc_literal_escapes() */ - int file_start; /* Equivalent to the argument of cfc_file_start() */ -} CplFileArgs; -/* - * This initializes the deprecated CplFileArgs structures. - */ -void cpl_init_FileArgs(CplFileArgs *cfa); - -/*....................................................................... - * When an error occurs while performing a completion, custom completion - * callback functions should register a terse description of the error - * by calling cpl_record_error(). This message will then be returned on - * the next call to cpl_last_error() and used by getline to display an - * error message to the user. - * - * Input: - * cpl WordCompletion * The string-completion resource object that was - * originally passed to the callback. - * errmsg const char * The description of the error. - */ -void cpl_record_error(WordCompletion *cpl, const char *errmsg); - -/*....................................................................... - * This function can be used to replace the builtin filename-completion - * function with one of the user's choice. The user's completion function - * has the option of calling the builtin filename-completion function - * if it believes that the token that it has been presented with is a - * filename (see cpl_file_completions() above). - * - * Input: - * gl GetLine * The resource object of the command-line input - * module. - * data void * This is passed to match_fn() whenever it is - * called. It could, for example, point to a - * symbol table that match_fn() would look up - * matches in. - * match_fn CplMatchFn * The function that will identify the prefix - * to be completed from the input line, and - * report matching symbols. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_customize_completion(GetLine *gl, void *data, CplMatchFn *match_fn); - -/*....................................................................... - * Change the terminal (or stream) that getline interacts with. - * - * Input: - * gl GetLine * The resource object of the command-line input - * module. - * input_fp FILE * The stdio stream to read from. - * output_fp FILE * The stdio stream to write to. - * term const char * The terminal type. This can be NULL if - * either or both of input_fp and output_fp don't - * refer to a terminal. Otherwise it should refer - * to an entry in the terminal information database. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_change_terminal(GetLine *gl, FILE *input_fp, FILE *output_fp, - const char *term); - -/*....................................................................... - * The following functions can be used to save and restore the contents - * of the history buffer. - * - * Input: - * gl GetLine * The resource object of the command-line input - * module. - * filename const char * The name of the new file to write to. - * comment const char * Extra information such as timestamps will - * be recorded on a line started with this - * string, the idea being that the file can - * double as a command file. Specify "" if - * you don't care. Be sure to specify the - * same string to both functions. - * max_lines int The maximum number of lines to save, or -1 - * to save all of the lines in the history - * list. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_save_history(GetLine *gl, const char *filename, const char *comment, - int max_lines); -int gl_load_history(GetLine *gl, const char *filename, const char *comment); - -/* - * Enumerate file-descriptor events that can be waited for. - */ -typedef enum { - GLFD_READ, /* Watch for data waiting to be read from a file descriptor */ - GLFD_WRITE, /* Watch for ability to write to a file descriptor */ - GLFD_URGENT /* Watch for urgent out-of-band data on the file descriptor */ -} GlFdEvent; - -/* - * The following enumeration is used for the return status of file - * descriptor event callbacks. - */ -typedef enum { - GLFD_ABORT, /* Cause gl_get_line() to abort with an error */ - GLFD_REFRESH, /* Redraw the input line and continue waiting for input */ - GLFD_CONTINUE /* Continue to wait for input, without redrawing the line */ -} GlFdStatus; - -/*....................................................................... - * While gl_get_line() is waiting for terminal input, it can also be - * asked to listen for activity on arbitrary file descriptors. - * Callback functions of the following type can be registered to be - * called when activity is seen. If your callback needs to write to - * the terminal or use signals, please see the gl_get_line(3) man - * page. - * - * Input: - * gl GetLine * The gl_get_line() resource object. You can use - * this safely to call gl_watch_fd() or - * gl_watch_time(). The effect of calling other - * functions that take a gl argument is undefined, - * and must be avoided. - * data void * A pointer to arbitrary callback data, as originally - * registered with gl_watch_fd(). - * fd int The file descriptor that has activity. - * event GlFdEvent The activity seen on the file descriptor. The - * inclusion of this argument allows the same - * callback to be registered for multiple events. - * Output: - * return GlFdStatus GLFD_ABORT - Cause gl_get_line() to abort with - * an error (set errno if you need it). - * GLFD_REFRESH - Redraw the input line and continue - * waiting for input. Use this if you - * wrote something to the terminal. - * GLFD_CONTINUE - Continue to wait for input, without - * redrawing the line. - */ -#define GL_FD_EVENT_FN(fn) GlFdStatus (fn)(GetLine *gl, void *data, int fd, \ - GlFdEvent event) -typedef GL_FD_EVENT_FN(GlFdEventFn); - -/*....................................................................... - * Where possible, register a function and associated data to be called - * whenever a specified event is seen on a file descriptor. - * - * Input: - * gl GetLine * The resource object of the command-line input - * module. - * fd int The file descriptor to watch. - * event GlFdEvent The type of activity to watch for. - * callback GlFdEventFn * The function to call when the specified - * event occurs. Setting this to 0 removes - * any existing callback. - * data void * A pointer to arbitrary data to pass to the - * callback function. - * Output: - * return int 0 - OK. - * 1 - Either gl==NULL, or this facility isn't - * available on the the host system - * (ie. select() isn't available). No - * error message is generated in the latter - * case. - */ -int gl_watch_fd(GetLine *gl, int fd, GlFdEvent event, - GlFdEventFn *callback, void *data); - -/*....................................................................... - * Switch history streams. History streams represent separate history - * lists recorded within a single history buffer. Different streams - * are distinguished by integer identifiers chosen by the calling - * appplicaton. Initially new_GetLine() sets the stream identifier to - * 0. Whenever a new line is appended to the history list, the current - * stream identifier is recorded with it, and history lookups only - * consider lines marked with the current stream identifier. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * id unsigned The new history stream identifier. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_group_history(GetLine *gl, unsigned id); - -/*....................................................................... - * Display the contents of the history list. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * fp FILE * The stdio output stream to write to. - * fmt const char * A format string. This containing characters to be - * written verbatim, plus any of the following - * format directives: - * %D - The date, formatted like 2001-11-20 - * %T - The time of day, formatted like 23:59:59 - * %N - The sequential entry number of the - * line in the history buffer. - * %G - The number of the history group that - * the line belongs to. - * %% - A literal % character. - * %H - The history line itself. - * Note that a '\n' newline character is not - * appended by default. - * all_groups int If true, display history lines from all - * history groups. Otherwise only display - * those of the current history group. - * max_lines int If max_lines is < 0, all available lines - * are displayed. Otherwise only the most - * recent max_lines lines will be displayed. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_show_history(GetLine *gl, FILE *fp, const char *fmt, int all_groups, - int max_lines); - -/*....................................................................... - * Resize or delete the history buffer. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * bufsize size_t The number of bytes in the history buffer, or 0 - * to delete the buffer completely. - * Output: - * return int 0 - OK. - * 1 - Insufficient memory (the previous buffer - * will have been retained). No error message - * will be displayed. - */ -int gl_resize_history(GetLine *gl, size_t bufsize); - -/*....................................................................... - * Set an upper limit to the number of lines that can be recorded in the - * history list, or remove a previously specified limit. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * max_lines int The maximum number of lines to allow, or -1 to - * cancel a previous limit and allow as many lines - * as will fit in the current history buffer size. - */ -void gl_limit_history(GetLine *gl, int max_lines); - -/*....................................................................... - * Discard either all historical lines, or just those associated with the - * current history group. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * all_groups int If true, clear all of the history. If false, - * clear only the stored lines associated with the - * currently selected history group. - */ -void gl_clear_history(GetLine *gl, int all_groups); - -/*....................................................................... - * Temporarily enable or disable the gl_get_line() history mechanism. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * enable int If true, turn on the history mechanism. If - * false, disable it. - */ -void gl_toggle_history(GetLine *gl, int enable); - -/* - * Objects of the following type are returned by gl_terminal_size(). - */ -typedef struct { - int nline; /* The terminal has nline lines */ - int ncolumn; /* The terminal has ncolumn columns */ -} GlTerminalSize; - -/*....................................................................... - * Update if necessary, and return the current size of the terminal. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * def_ncolumn int If the number of columns in the terminal - * can't be determined, substitute this number. - * def_nline int If the number of lines in the terminal can't - * be determined, substitute this number. - * Output: - * return GlTerminalSize The current terminal size. - */ -GlTerminalSize gl_terminal_size(GetLine *gl, int def_ncolumn, int def_nline); - -/* - * The gl_lookup_history() function returns information in an - * argument of the following type. - */ -typedef struct { - const char *line; /* The requested history line */ - unsigned group; /* The history group to which the */ - /* line belongs. */ - time_t timestamp; /* The date and time at which the */ - /* line was originally entered. */ -} GlHistoryLine; - -/*....................................................................... - * Lookup a history line by its sequential number of entry in the - * history buffer. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * id unsigned long The identification number of the line to - * be returned, where 0 denotes the first line - * that was entered in the history list, and - * each subsequently added line has a number - * one greater than the previous one. For - * the range of lines currently in the list, - * see the gl_range_of_history() function. - * Input/Output: - * line GlHistoryLine * A pointer to the variable in which to - * return the details of the line. - * Output: - * return int 0 - The line is no longer in the history - * list, and *line has not been changed. - * 1 - The requested line can be found in - * *line. Note that the string in - * line->line is part of the history - * buffer and will change, so a private - * copy should be made if you wish to - * use it after subsequent calls to any - * functions that take gl as an argument. - */ -int gl_lookup_history(GetLine *gl, unsigned long id, GlHistoryLine *line); - -/* - * The gl_state_of_history() function returns information in an argument - * of the following type. - */ -typedef struct { - int enabled; /* True if history is enabled */ - unsigned group; /* The current history group */ - int max_lines; /* The current upper limit on the number of lines */ - /* in the history list, or -1 if unlimited. */ -} GlHistoryState; - -/*....................................................................... - * Query the state of the history list. Note that any of the input/output - * pointers can be specified as NULL. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * Input/Output: - * state GlHistoryState * A pointer to the variable in which to record - * the return values. - */ -void gl_state_of_history(GetLine *gl, GlHistoryState *state); - -/* - * The gl_range_of_history() function returns information in an argument - * of the following type. - */ -typedef struct { - unsigned long oldest; /* The sequential entry number of the oldest */ - /* line in the history list. */ - unsigned long newest; /* The sequential entry number of the newest */ - /* line in the history list. */ - int nlines; /* The number of lines in the history list */ -} GlHistoryRange; - -/*....................................................................... - * Query the number and range of lines in the history buffer. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * range GlHistoryRange * A pointer to the variable in which to record - * the return values. If range->nline=0, the - * range of lines will be given as 0-0. - */ -void gl_range_of_history(GetLine *gl, GlHistoryRange *range); - -/* - * The gl_size_of_history() function returns information in an argument - * of the following type. - */ -typedef struct { - size_t size; /* The size of the history buffer (bytes) */ - size_t used; /* The number of bytes of the history buffer */ - /* that are currently occupied. */ -} GlHistorySize; - -/*....................................................................... - * Return the size of the history buffer and the amount of the - * buffer that is currently in use. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * Input/Output: - * GlHistorySize size * A pointer to the variable in which to return - * the results. - */ -void gl_size_of_history(GetLine *gl, GlHistorySize *size); - -/*....................................................................... - * Specify whether text that users type should be displayed or hidden. - * In the latter case, only the prompt is displayed, and the final - * input line is not archived in the history list. - * - * Input: - * gl GetLine * The input-line history maintenance object. - * enable int 0 - Disable echoing. - * 1 - Enable echoing. - * -1 - Just query the mode without changing it. - * Output: - * return int The echoing disposition that was in effect - * before this function was called: - * 0 - Echoing was disabled. - * 1 - Echoing was enabled. - */ -int gl_echo_mode(GetLine *gl, int enable); - -/*....................................................................... - * This function can be called from gl_get_line() callbacks to have - * the prompt changed when they return. It has no effect if gl_get_line() - * is not currently being invoked. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * prompt const char * The new prompt. - */ -void gl_replace_prompt(GetLine *gl, const char *prompt); - -/* - * Enumerate the available prompt formatting styles. - */ -typedef enum { - GL_LITERAL_PROMPT, /* Display the prompt string literally */ - GL_FORMAT_PROMPT /* The prompt string can contain any of the */ - /* following formatting directives: */ - /* %B - Display subsequent characters */ - /* with a bold font. */ - /* %b - Stop displaying characters */ - /* with the bold font. */ - /* %U - Underline subsequent characters. */ - /* %u - Stop underlining characters. */ - /* %S - Highlight subsequent characters */ - /* (also known as standout mode). */ - /* %s - Stop highlighting characters */ - /* %% - Display a single % character. */ -} GlPromptStyle; - -/*....................................................................... - * Specify whether to heed text attribute directives within prompt - * strings. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * style GlPromptStyle The style of prompt (see the definition of - * GlPromptStyle in libtecla.h for details). - */ -void gl_prompt_style(GetLine *gl, GlPromptStyle style); - -/*....................................................................... - * Remove a signal from the list of signals that gl_get_line() traps. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * signo int The number of the signal to be ignored. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int gl_ignore_signal(GetLine *gl, int signo); - -/* - * A bitwise union of the following enumerators is passed to - * gl_trap_signal() to specify the environment in which the - * application's signal handler is to be called. - */ -typedef enum { - GLS_RESTORE_SIG=1, /* Restore the caller's signal environment */ - /* while handling the signal. */ - GLS_RESTORE_TTY=2, /* Restore the caller's terminal settings */ - /* while handling the signal. */ - GLS_RESTORE_LINE=4, /* Move the cursor to the start of the next line */ - GLS_REDRAW_LINE=8, /* Redraw the input line when the signal handler */ - /* returns. */ - GLS_UNBLOCK_SIG=16, /* Normally a signal who's delivery is found to */ - /* be blocked by the calling application is not */ - /* trapped by gl_get_line(). Including this flag */ - /* causes it to be temporarily unblocked and */ - /* trapped while gl_get_line() is executing. */ - GLS_DONT_FORWARD=32,/* Don't forward the signal to the signal handler */ - /* of the calling program. */ - GLS_RESTORE_ENV = GLS_RESTORE_SIG | GLS_RESTORE_TTY | GLS_REDRAW_LINE, - GLS_SUSPEND_INPUT = GLS_RESTORE_ENV | GLS_RESTORE_LINE -} GlSignalFlags; - -/* - * The following enumerators are passed to gl_trap_signal() to tell - * it what to do after the application's signal handler has been called. - */ -typedef enum { - GLS_RETURN, /* Return the line as though the user had pressed the */ - /* return key. */ - GLS_ABORT, /* Cause gl_get_line() to return NULL */ - GLS_CONTINUE /* After handling the signal, resume command line editing */ -} GlAfterSignal; - -/*....................................................................... - * Tell gl_get_line() how to respond to a given signal. This can be used - * both to override the default responses to signals that gl_get_line() - * normally catches and to add new signals to the list that are to be - * caught. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * signo int The number of the signal to be caught. - * flags unsigned A bitwise union of GlSignalFlags enumerators. - * after GlAfterSignal What to do after the application's signal - * handler has been called. - * errno_value int The value to set errno to. - * Output: - * return int 0 - OK. - * 1 - Insufficient memory to record the - * new signal disposition. - */ -int gl_trap_signal(GetLine *gl, int signo, unsigned flags, - GlAfterSignal after, int errno_value); - -/*....................................................................... - * Return the last signal that was caught by the most recent call to - * gl_get_line(), or -1 if no signals were caught. This is useful if - * gl_get_line() returns errno=EINTR and you need to find out what signal - * caused it to abort. - * - * Input: - * gl GetLine * The resource object of gl_get_line(). - * Output: - * return int The last signal caught by the most recent - * call to gl_get_line(), or -1 if no signals - * were caught. - */ -int gl_last_signal(const GetLine *gl); - -/*....................................................................... - * This function is designed to be called by CPL_MATCH_FN() callback - * functions. It adds one possible completion of the token that is being - * completed to an array of completions. If the completion needs any - * special quoting to be valid when displayed in the input line, this - * quoting must be included in the string. - * - * Input: - * cpl WordCompletion * The argument of the same name that was passed - * to the calling CPL_MATCH_FN() callback function. - * line const char * The input line, as received by the callback - * function. - * word_start int The index within line[] of the start of the - * word that is being completed. If an empty - * string is being completed, set this to be - * the same as word_end. - * word_end int The index within line[] of the character which - * follows the incomplete word, as received by the - * callback function. - * suffix const char * The appropriately quoted string that could - * be appended to the incomplete token to complete - * it. A copy of this string will be allocated - * internally. - * type_suffix const char * When listing multiple completions, gl_get_line() - * appends this string to the completion to indicate - * its type to the user. If not pertinent pass "". - * Otherwise pass a literal or static string. - * cont_suffix const char * If this turns out to be the only completion, - * gl_get_line() will append this string as - * a continuation. For example, the builtin - * file-completion callback registers a directory - * separator here for directory matches, and a - * space otherwise. If the match were a function - * name you might want to append an open - * parenthesis, etc.. If not relevant pass "". - * Otherwise pass a literal or static string. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int cpl_add_completion(WordCompletion *cpl, const char *line, - int word_start, int word_end, const char *suffix, - const char *type_suffix, const char *cont_suffix); - -/* - * Each possible completion string is recorded in an array element of - * the following type. - */ -typedef struct { - char *completion; /* The matching completion string */ - char *suffix; /* The pointer into completion[] at which the */ - /* string was extended. */ - const char *type_suffix; /* A suffix to be added when listing completions */ - /* to indicate the type of the completion. */ -} CplMatch; - -/* - * Completions are returned in a container of the following form. - */ -typedef struct { - char *suffix; /* The common initial part of all of the */ - /* completion suffixes. */ - const char *cont_suffix; /* Optional continuation string to be appended to */ - /* the sole completion when nmatch==1. */ - CplMatch *matches; /* The array of possible completion strings, */ - /* sorted into lexical order. */ - int nmatch; /* The number of elements in matches[] */ -} CplMatches; - -/*....................................................................... - * Given an input line and the point at which completion is to be - * attempted, return an array of possible completions. - * - * Input: - * cpl WordCompletion * The word-completion resource object. - * line const char * The current input line. - * word_end int The index of the character in line[] which - * follows the end of the token that is being - * completed. - * data void * Anonymous 'data' to be passed to match_fn(). - * match_fn CplMatchFn * The function that will identify the prefix - * to be completed from the input line, and - * record completion suffixes. - * Output: - * return CplMatches * The container of the array of possible - * completions. The returned pointer refers - * to a container owned by the parent Completion - * object, and its contents thus potentially - * change on every call to cpl_matches(). - */ -CplMatches *cpl_complete_word(WordCompletion *cpl, const char *line, - int word_end, void *data, - CplMatchFn *match_fn); - -/*....................................................................... - * Print out an array of matching completions. - * - * Input: - * result CplMatches * The container of the sorted array of - * completions. - * fp FILE * The output stream to write to. - * term_width int The width of the terminal. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -int cpl_list_completions(CplMatches *result, FILE *fp, int term_width); - -/*....................................................................... - * Return a description of the error that occurred on the last call to - * cpl_complete_word() or cpl_add_completion(). - * - * Input: - * cpl WordCompletion * The string-completion resource object. - * Output: - * return const char * The description of the last error. - */ -const char *cpl_last_error(WordCompletion *cpl); - -/* - * PathCache objects encapsulate the resources needed to record - * files of interest from comma-separated lists of directories. - */ -typedef struct PathCache PathCache; - -/*....................................................................... - * Create an object who's function is to maintain a cache of filenames - * found within a list of directories, and provide quick lookup and - * completion of selected files in this cache. - * - * Output: - * return PathCache * The new, initially empty cache, or NULL - * on error. - */ -PathCache *new_PathCache(void); - -/*....................................................................... - * Delete a given cache of files, returning the resources that it - * was using to the system. - * - * Input: - * pc PathCache * The cache to be deleted (can be NULL). - * Output: - * return PathCache * The deleted object (ie. allways NULL). - */ -PathCache *del_PathCache(PathCache *pc); - -/*....................................................................... - * Return a description of the last path-caching error that occurred. - * - * Input: - * pc PathCache * The filename cache that suffered the error. - * Output: - * return char * The description of the last error. - */ -const char *pca_last_error(PathCache *pc); - -/*....................................................................... - * Build the list of files of interest contained in a given - * colon-separated list of directories. - * - * Input: - * pc PathCache * The cache in which to store the names of - * the files that are found in the list of - * directories. - * path const char * A colon-separated list of directory - * paths. Under UNIX, when searching for - * executables, this should be the return - * value of getenv("PATH"). - * Output: - * return int 0 - OK. - * 1 - An error occurred. - */ -int pca_scan_path(PathCache *pc, const char *path); - -/*....................................................................... - * If you want subsequent calls to pca_lookup_file() and - * pca_path_completions() to only return the filenames of certain - * types of files, for example executables, or filenames ending in - * ".ps", call this function to register a file-selection callback - * function. This callback function takes the full pathname of a file, - * plus application-specific data, and returns 1 if the file is of - * interest, and zero otherwise. - * - * Input: - * pc PathCache * The filename cache. - * check_fn CplCheckFn * The function to call to see if the name of - * a given file should be included in the - * cache. This determines what type of files - * will reside in the cache. To revert to - * selecting all files, regardless of type, - * pass 0 here. - * data void * You can pass a pointer to anything you - * like here, including NULL. It will be - * passed to your check_fn() callback - * function, for its private use. - */ -void pca_set_check_fn(PathCache *pc, CplCheckFn *check_fn, void *data); - -/*....................................................................... - * Given the simple name of a file, search the cached list of files - * in the order in which they where found in the list of directories - * previously presented to pca_scan_path(), and return the pathname - * of the first file which has this name. - * - * Input: - * pc PathCache * The cached list of files. - * name const char * The name of the file to lookup. - * name_len int The length of the filename substring at the - * beginning of name[], or -1 to assume that the - * filename occupies the whole of the string. - * literal int If this argument is zero, lone backslashes - * in name[] are ignored during comparison - * with filenames in the cache, under the - * assumption that they were in the input line - * soley to escape the special significance of - * characters like spaces. To have them treated - * as normal characters, give this argument a - * non-zero value, such as 1. - * Output: - * return char * The pathname of the first matching file, - * or NULL if not found. Note that the returned - * pointer points to memory owned by *pc, and - * will become invalid on the next call. - */ -char *pca_lookup_file(PathCache *pc, const char *name, int name_len, - int literal); - -/* - * Objects of the following type can be used to change the default - * behavior of the pca_path_completions() callback function. - */ -typedef struct PcaPathConf PcaPathConf; - -/* - * pca_path_completions() is a completion callback function for use directly - * with cpl_complete_word() or gl_customize_completions(), or indirectly - * from your own completion callback function. It requires that a PcaPathConf - * object be passed via its 'void *data' argument (see below). - */ -CPL_MATCH_FN(pca_path_completions); - -/*....................................................................... - * Allocate and initialize a pca_path_completions() configuration object. - * - * Input: - * pc PathCache * The filename cache in which to look for - * file name completions. - * Output: - * return PcaPathConf * The new configuration structure, or NULL - * on error. - */ -PcaPathConf *new_PcaPathConf(PathCache *pc); - -/*....................................................................... - * Deallocate memory, previously allocated by new_PcaPathConf(). - * - * Input: - * ppc PcaPathConf * Any pointer previously returned by - * new_PcaPathConf() [NULL is allowed]. - * Output: - * return PcaPathConf * The deleted structure (always NULL). - */ -PcaPathConf *del_PcaPathConf(PcaPathConf *ppc); - -/* - * If backslashes in the prefix being passed to pca_path_completions() - * should be treated as literal characters, call the following function - * with literal=1. Otherwise the default is to treat them as escape - * characters which remove the special meanings of spaces etc.. - */ -void ppc_literal_escapes(PcaPathConf *ppc, int literal); - -/* - * Before calling pca_path_completions, call this function if you know - * the index at which the filename prefix starts in the input line. - * Otherwise by default, or if you specify start_index to be -1, the - * filename is taken to start after the first unescaped space preceding - * the cursor, or the start of the line, whichever comes first. - */ -void ppc_file_start(PcaPathConf *ppc, int start_index); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/libtecla-1.4.1/libtecla.map b/libtecla-1.4.1/libtecla.map deleted file mode 100644 index 7e774b7..0000000 --- a/libtecla-1.4.1/libtecla.map +++ /dev/null @@ -1,124 +0,0 @@ -# This mapfile (or version script) lists the public symbols that are -# publically exported by each version of the tecla library. This file -# has the format required by the Sun and Linux linkers, and also acts -# as a template from which map files for other systems can be derived -# with awk or sed. -# -# Under Solaris and Linux, this map file is used by ld during shared -# library creation. It has two purposes: -# -# 1. It specifies which symbols in the library are to be made visible -# to applications. This has the dual benefits of reducing namespace -# polution, and of preventing applications from using private -# internal library functions that might change or disappear in -# future releases. -# -# 2. The information listed in this file is recorded in the shared -# library, such that when an application is linked against it, the -# linker can record a dependency in the application which says -# which is the earliest library version which included all of the -# symbols that the application needs. This means that if the -# application is copied to another system that has an earlier -# version of the library, the linker can quickly determine whether -# the earlier version contains all of the symbols that it needs. -# -# Under Linux, mapfiles can also be used to allow multiple -# incompatible versions of a given function to exist in a library, -# thus supporting applications that were compiled against different -# incompatible versions of the library. Since this feature (and the -# inclusion of .symver directives) isn't supported by Solaris, it -# can't be included in this file. Non backwards compatibility in the -# ABI must instead be handled in the more traditional way, by -# incrementing the major version number. -# -# When a new minor release is made, a new tecla_1.x specification -# should be added which inherits the symbols of the previous release -# and lists newly added functions. For example, below you will find -# the following clause: -# -# tecla_1.3 { -# global: -# ef_list_expansions; -# } tecla_1.2; -# -# This says that ef_list_expansions is the name of a public function -# that was added in the 1.3 release, and that the symbols defined in -# the previous tecla_1.2 clause have been inherited by tecla_1.3. -# -# For more details see the following URL: -# -# http://www.usenix.org/publications/library/proceedings/als2000/browndavid.html -#------------------------------------------------------------------------------- - -tecla_1.2 { - global: - cfc_file_start; - cfc_literal_escapes; - cfc_set_check_fn; - cpl_add_completion; - cpl_check_exe; - cpl_complete_word; - cpl_file_completions; - cpl_init_FileArgs; - cpl_last_error; - cpl_list_completions; - cpl_record_error; - del_CplFileConf; - del_ExpandFile; - del_GetLine; - del_PathCache; - del_PcaPathConf; - del_WordCompletion; - ef_expand_file; - ef_last_error; - gl_change_terminal; - gl_customize_completion; - gl_get_line; - new_CplFileConf; - new_ExpandFile; - new_GetLine; - new_PathCache; - new_PcaPathConf; - new_WordCompletion; - pca_last_error; - pca_lookup_file; - pca_path_completions; - pca_scan_path; - pca_set_check_fn; - ppc_file_start; - ppc_literal_escapes; - - local: - *; -}; - -tecla_1.3 { - global: - ef_list_expansions; -} tecla_1.2; - -tecla_1.4 { - global: - gl_configure_getline; - gl_save_history; - gl_load_history; - gl_group_history; - gl_show_history; - gl_resize_history; - gl_limit_history; - gl_clear_history; - gl_toggle_history; - gl_watch_fd; - libtecla_version; - gl_terminal_size; - gl_state_of_history; - gl_range_of_history; - gl_size_of_history; - gl_lookup_history; - gl_echo_mode; - gl_replace_prompt; - gl_prompt_style; - gl_ignore_signal; - gl_trap_signal; - gl_last_signal; -} tecla_1.3; diff --git a/libtecla-1.4.1/man3/cfc_file_start.3 b/libtecla-1.4.1/man3/cfc_file_start.3 deleted file mode 100644 index 36c83a3..0000000 --- a/libtecla-1.4.1/man3/cfc_file_start.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/cpl_complete_word.3 diff --git a/libtecla-1.4.1/man3/cfc_literal_escapes.3 b/libtecla-1.4.1/man3/cfc_literal_escapes.3 deleted file mode 100644 index 36c83a3..0000000 --- a/libtecla-1.4.1/man3/cfc_literal_escapes.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/cpl_complete_word.3 diff --git a/libtecla-1.4.1/man3/cfc_set_check_fn.3 b/libtecla-1.4.1/man3/cfc_set_check_fn.3 deleted file mode 100644 index 36c83a3..0000000 --- a/libtecla-1.4.1/man3/cfc_set_check_fn.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/cpl_complete_word.3 diff --git a/libtecla-1.4.1/man3/cpl_add_completion.3 b/libtecla-1.4.1/man3/cpl_add_completion.3 deleted file mode 100644 index 36c83a3..0000000 --- a/libtecla-1.4.1/man3/cpl_add_completion.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/cpl_complete_word.3 diff --git a/libtecla-1.4.1/man3/cpl_complete_word.3 b/libtecla-1.4.1/man3/cpl_complete_word.3 deleted file mode 100644 index ae76439..0000000 --- a/libtecla-1.4.1/man3/cpl_complete_word.3 +++ /dev/null @@ -1,405 +0,0 @@ -.\" Copyright (C) 2000, 2001 by Martin C. Shepherd -.\" -.\" All rights reserved. -.\" -.\" Permission is hereby granted, free of charge, to any person obtaining a -.\" copy of this software and associated documentation files (the -.\" "Software"), to deal in the Software without restriction, including -.\" without limitation the rights to use, copy, modify, merge, publish, -.\" distribute, and/or sell copies of the Software, and to permit persons -.\" to whom the Software is furnished to do so, provided that the above -.\" copyright notice(s) and this permission notice appear in all copies of -.\" the Software and that both the above copyright notice(s) and this -.\" permission notice appear in supporting documentation. -.\" -.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -.\" OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -.\" HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL -.\" INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING -.\" FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, -.\" NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION -.\" WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -.\" -.\" Except as contained in this notice, the name of a copyright holder -.\" shall not be used in advertising or otherwise to promote the sale, use -.\" or other dealings in this Software without prior written authorization -.\" of the copyright holder. -.TH cpl_complete_word 3 -.SH NAME -cpl_complete_word, cfc_file_start, cfc_literal_escapes, cfc_set_check_fn, cpl_add_completion, cpl_file_completions, cpl_last_error, cpl_list_completions, cpl_record_error, del_CplFileConf, del_WordCompletion, new_CplFileConf, new_WordCompletion \- lookup possible completions for a word -.SH SYNOPSIS -.nf -#include <stdio.h> -#include <libtecla.h> - -WordCompletion *new_WordCompletion(void); - -WordCompletion *del_WordCompletion(WordCompletion *cpl); - -#define CPL_MATCH_FN(fn) int (fn)(WordCompletion *cpl, \\ - void *data, \\ - const char *line, \\ - int word_end) -typedef CPL_MATCH_FN(CplMatchFn); - -CPL_MATCH_FN(cpl_file_completions); - -CplMatches *cpl_complete_word(WordCompletion *cpl, - const char *line, - int word_end, void *data, - CplMatchFn *match_fn); - -int cpl_list_completions(CplMatches *result, FILE *fp, - int term_width); - -int cpl_add_completion(WordCompletion *cpl, - const char *line, int word_start, - int word_end, const char *suffix, - const char *type_suffix, - const char *cont_suffix); - -void cpl_record_error(WordCompletion *cpl, - const char *errmsg); - -const char *cpl_last_error(WordCompletion *cpl); - -.fi - -.SH DESCRIPTION - -The \f3cpl_complete_word()\f1 function is part of the tecla library -(see the libtecla(3) man page). It is usually called behind the scenes -by \f3gl_get_line(3)\f1, but can also be called separately. - -Given an input line containing an incomplete word to be completed, it -calls a user-provided callback function (or the provided -file-completion callback function) to look up all possible completion -suffixes for that word. The callback function is expected to look -backward in the line, starting from the specified cursor position, to -find the start of the word to be completed, then to look up all -possible completions of that word and record them, one at a time by -calling \f3cpl_add_completion()\f1. - -.sp -Descriptions of the functions of this module are as follows: -.sp -.nf - CompleteWord *new_CompleteWord(void) -.fi -.sp -This function creates the resources used by the \f3cpl_complete_word()\f1 -function. In particular, it maintains the memory that is used to -return the results of calling \f3cpl_complete_word()\f1. -.sp -.nf - CompleteWord *del_CompleteWord(CompleteWord *cpl) -.fi -.sp -This function deletes the resources that were returned by a previous -call to \f3new_CompleteWord()\f1. It always returns \f3NULL\f1 (ie. a -deleted object). It does nothing if the \f3cpl\f1 argument is -\f3NULL\f1. -.sp -The callback functions which lookup possible completions should be -defined with the following macro (which is defined in libtecla.h). -.sp -.nf - #define CPL_MATCH_FN(fn) int (fn)(WordCompletion *cpl, \\ - void *data, \\ - const char *line, \\ - int word_end) -.fi -.sp -Functions of this type are called by \f3cpl_complete_word()\f1, and -all of the arguments of the callback are those that were passed to -said function. In particular, the \f3line\f1 argument contains the -input line containing the word to be completed, and \f3word_end\f1 is -the index of the character that follows the last character of the -incomplete word within this string. The callback is expected to look -backwards from \f3word_end\f1 for the start of the incomplete -word. What constitutes the start of a word clearly depends on the -application, so it makes sense for the callback to take on this -responsibility. For example, the builtin filename completion function -looks backwards until it hits an unescaped space, or the start of the -line. Having found the start of the word, the callback should then -lookup all possible completions of this word, and record each -completion via separate calls to \f3cpl_add_completion()\f1. If the -callback needs access to an application-specific symbol table, it can -pass it and any other data that it needs, via the \f3data\f1 -argument. This removes any need for globals. -.sp -The callback function should return 0 if no errors occur. On failure -it should return 1, and register a terse description of the error by -calling \f3cpl_record_error()\f1. -.sp -.nf - void cpl_record_error(WordCompletion *cpl, - const char *errmsg); -.fi -.sp -The last error message recorded by calling \f3cpl_record_error()\f1, -can subsequently be queried by calling \f3cpl_last_error()\f1, as -described later. -.sp -.nf - int cpl_add_completion(WordCompletion *cpl, - const char *line, int word_start, - int word_end, const char *suffix, - const char *type_suffix, - const char *cont_suffix); -.fi -.sp -The \f3cpl_add_completion()\f1 function is called zero or more times -by the completion callback function to record each possible completion -in the specified \f3WordCompletion\f1 object. These completions are -subsequently returned by \f3cpl_complete_word()\f1, as described -later. The \f3cpl\f1, \f3line\f1, and \f3word_end\f1 arguments should -be those that were passed to the callback function. The -\f3word_start\f1 argument should be the index within the input line -string of the start of the word that is being completed. This should -equal \f3word_end\f1 if a zero-length string is being completed. The -\f3suffix\f1 argument is the string that would have to be appended to -the incomplete word to complete it. If this needs any quoting -(eg. the addition of backslashes before special charaters) to be valid -within the displayed input line, this should be included. A copy of -the suffix string is allocated internally, so there is no need to -maintain your copy of the string after \f3cpl_add_completion()\f1 -returns. -.sp -Note that in the array of possible completions which the -\f3cpl_complete_word()\f1 function returns, the suffix recorded by -\f3cpl_add_completion()\f1 is listed along with the concatentation of -this suffix with the word that lies between \f3word_start\f1 and -\f3word_end\f1 in the input line. -.sp -The \f3type_suffix\f1 argument specifies an optional string to be -appended to the completion if it is displayed as part of a list of -completions by \f3cpl_list_completions()\f1. The intention is that -this indicate to the user the type of each completion. For example, -the file completion function places a directory separator after -completions that are directories, to indicate their nature to the -user. Similary, if the completion were a function, you could indicate -this to the user by setting \f3type_suffix\f1 to "()". Note that the -\f3type_suffix\f1 string isn't copied, so if the argument isn't a -literal string between speech marks, be sure that the string remains -valid for at least as long as the results of \f3cpl_complete_word()\f1 -are needed. -.sp -The \f3cont_suffix\f1 is a continuation suffix to append to the -completed word in the input line if this is the only completion. This -is something that isn't part of the completion itself, but that gives -the user an indication about how they might continue to extend the -token. For example, the file-completion callback function adds a -directory separator if the completed word is a directory. If the -completed word were a function name, you could similarly aid the user -by arranging for an open parenthesis to be appended. -.sp -.nf - CplMatches *cpl_complete_word(WordCompletion *cpl, - const char *line, - int word_end, void *data, - CplMatchFn *match_fn); -.fi -.sp -The \f3cpl_complete_word()\f1 is normally called behind the scenes by -\f3gl_get_line(3)\f1, but can also be called separately if you -separately allocate a \f3WordCompletion\f1 object. It performs word -completion, as described at the beginning of this section. Its first -argument is a resource object previously returned by -\f3new_CompleteWord()\f1. The \f3line\f1 argument is the input line -string, containing the word to be completed. The \f3word_end\f1 -argument contains the index of the character in the input line, that -just follows the last character of the word to be completed. When -called by \f3gl_get_line()\f1, this is the character over which the -user pressed \f3TAB\f1. The \f3match_fn\f3 argument is the function -pointer of the callback function which will lookup possible -completions of the word, as described above, and the \f3data\f1 -argument provides a way for the application to pass arbitrary data to -the callback function. -.sp -If no errors occur, the \f3cpl_complete_word()\f1 function returns a -pointer to a \f3CplMatches\f1 container, as defined below. This -container is allocated as part of the \f3cpl\f1 object that was passed -to \f3cpl_complete_word()\f1, and will thus change on each call which -uses the same \f3cpl\f1 argument. -.sp -.nf - typedef struct { - char *completion; /* A matching completion */ - /* string */ - char *suffix; /* The part of the */ - /* completion string which */ - /* would have to be */ - /* appended to complete the */ - /* original word. */ - const char *type_suffix; /* A suffix to be added when */ - /* listing completions, to */ - /* indicate the type of the */ - /* completion. */ - } CplMatch; - - typedef struct { - char *suffix; /* The common initial part */ - /* of all of the completion */ - /* suffixes. */ - const char *cont_suffix; /* Optional continuation */ - /* string to be appended to */ - /* the sole completion when */ - /* nmatch==1. */ - CplMatch *matches; /* The array of possible */ - /* completion strings, */ - /* sorted into lexical */ - /* order. */ - int nmatch; /* The number of elements in */ - /* the above matches[] */ - /* array. */ - } CplMatches; -.fi -.sp -If an error occurs during completion, \f3cpl_complete_word()\f1 -returns NULL. A description of the error can be acquired by calling -the \f3cpl_last_error()\f3 function. -.sp -.nf - const char *cpl_last_error(WordCompletion *cpl); -.fi -.sp -The \f3cpl_last_error()\f3 function returns a terse description of the -error which occurred on the last call to \f3cpl_complete_word()\f1 or -\f3cpl_add_completion()\f1. -.sp -.nf - int cpl_list_completions(CplMatches *result, FILE *fp, - int terminal_width); -.fi -.sp -When the \f3cpl_complete_word()\f1 function returns multiple possible -completions, the \f3cpl_list_completions()\f1 function can be called -upon to list them, suitably arranged across the available width of the -terminal. It arranges for the displayed columns of completions to all -have the same width, set by the longest completion. It also appends -the \f3type_suffix\f1 strings that were recorded with each completion, -thus indicating their types to the user. - -.SH THE BUILT-IN FILENAME-COMPLETION CALLBACK - -By default the \f3gl_get_line(3)\f1 function, passes the following -completion callback function to \f3cpl_complete_word()\f1. This -function can also be used separately, either by sending it to -\f3cpl_complete_word()\f1, or by calling it directly from your -own completion callback function. -.sp -.nf - CPL_MATCH_FN(cpl_file_completions); -.fi -.sp -Certain aspects of the behavior of this callback can be changed via -its \f3data\f1 argument. If you are happy with its default behavior -you can pass \f3NULL\f1 in this argument. Otherwise it should be a -pointer to a \f3CplFileConf\f1 object, previously allocated by calling -\f3new_CplFileConf()\f1. -.sp -.nf - CplFileConf *new_CplFileConf(void); -.fi -.sp -\f3CplFileConf\f1 objects encapsulate the configuration parameters of -\f3cpl_file_completions()\f1. These parameters, which start out with -default values, can be changed by calling the accessor functions -described below. -.sp -By default, the \f3cpl_file_completions()\f3 callback function -searches backwards for the start of the filename being completed, -looking for the first un-escaped space or the start of the input -line. If you wish to specify a different location, call -\f3cfc_file_start()\f1 with the index at which the filename starts in -the input line. Passing start_index=-1 re-enables the default -behavior. -.sp -.nf - void cfc_file_start(CplFileConf *cfc, int start_index); -.fi -.sp -By default, when \f3cpl_file_completions()\f1 looks at a filename in -the input line, each lone backslash in the input line is interpreted -as being a special character which removes any special significance of -the character which follows it, such as a space which should be taken -as part of the filename rather than delimiting the start of the -filename. These backslashes are thus ignored while looking for -completions, and subsequently added before spaces, tabs and literal -backslashes in the list of completions. To have unescaped backslashes -treated as normal characters, call \f3cfc_literal_escapes()\f1 with a -non-zero value in its \f3literal\f1 argument. -.sp -.nf - void cfc_literal_escapes(CplFileConf *cfc, int literal); -.fi -.sp -By default, \f3cpl_file_completions()\f1 reports all files who's names -start with the prefix that is being completed. If you only want a -selected subset of these files to be reported in the list of -completions, you can arrange this by providing a callback function -which takes the full pathname of a file, and returns \f30\f1 if the -file should be ignored, or \f31\f1 if the file should be included in -the list of completions. To register such a function for use by -\f3cpl_file_completions()\f1, call \f3cfc_set_check_fn()\f1, and pass -it a pointer to the function, together with a pointer to any data that -you would like passed to this callback whenever it is called. Your -callback can make its decisions based on any property of the file, -such as the filename itself, whether the file is readable, writable or -executable, or even based on what the file contains. -.sp -.nf - #define CPL_CHECK_FN(fn) int (fn)(void *data, \\ - const char *pathname) - typedef CPL_CHECK_FN(CplCheckFn); - - void cfc_set_check_fn(CplFileConf *cfc, - CplCheckFn *chk_fn, void *chk_data); -.fi -.sp -The \f3cpl_check_exe()\f1 function is a provided callback of the above -type, for use with \f3cpl_file_completions()\f1. It returns non-zero -if the filename that it is given represents a normal file that the -user has execute permission to. You could use this to have -\f3cpl_file_completions()\f1 only list completions of executable -files. -.sp -When you have finished with a \f3CplFileConf\f1 variable, you can pass -it to the \f3del_CplFileConf()\f1 destructor function to reclaim its -memory. -.sp -.nf - CplFileConf *del_CplFileConf(CplFileConf *cfc); -.fi -.sp - -.SH THREAD SAFETY - -In multi-threaded programs, you should use the \f3libtecla_r.a\f1 -version of the library. This uses POSIX reentrant functions where -available (hence the \f3_r\f1 suffix), and disables features that rely -on non-reentrant system functions. In the case of this module, the -only disabled feature is username completion in \f3~username/\f1 -expressions, in \f3cpl_file_completions()\f1. - -Using the \f3libtecla_r.a\f1 version of the library, it is safe to use -the facilities of this module in multiple threads, provided that each -thread uses a separately allocated \f3WordCompletion\f1 object. In -other words, if two threads want to do word completion, they should -each call \f3new_WordCompletion()\f1 to allocate their own completion -objects. - -.SH FILES -.nf -libtecla.a - The tecla library -libtecla.h - The tecla header file. -.fi - -.SH SEE ALSO -libtecla(3), gl_get_line(3), ef_expand_file(3), pca_lookup_file(3) - -.SH AUTHOR -Martin Shepherd (mcs@astro.caltech.edu) diff --git a/libtecla-1.4.1/man3/cpl_file_completions.3 b/libtecla-1.4.1/man3/cpl_file_completions.3 deleted file mode 100644 index 36c83a3..0000000 --- a/libtecla-1.4.1/man3/cpl_file_completions.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/cpl_complete_word.3 diff --git a/libtecla-1.4.1/man3/cpl_last_error.3 b/libtecla-1.4.1/man3/cpl_last_error.3 deleted file mode 100644 index 36c83a3..0000000 --- a/libtecla-1.4.1/man3/cpl_last_error.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/cpl_complete_word.3 diff --git a/libtecla-1.4.1/man3/cpl_list_completions.3 b/libtecla-1.4.1/man3/cpl_list_completions.3 deleted file mode 100644 index 36c83a3..0000000 --- a/libtecla-1.4.1/man3/cpl_list_completions.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/cpl_complete_word.3 diff --git a/libtecla-1.4.1/man3/cpl_record_error.3 b/libtecla-1.4.1/man3/cpl_record_error.3 deleted file mode 100644 index 36c83a3..0000000 --- a/libtecla-1.4.1/man3/cpl_record_error.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/cpl_complete_word.3 diff --git a/libtecla-1.4.1/man3/del_CplFileConf.3 b/libtecla-1.4.1/man3/del_CplFileConf.3 deleted file mode 100644 index 36c83a3..0000000 --- a/libtecla-1.4.1/man3/del_CplFileConf.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/cpl_complete_word.3 diff --git a/libtecla-1.4.1/man3/del_ExpandFile.3 b/libtecla-1.4.1/man3/del_ExpandFile.3 deleted file mode 100644 index f4299df..0000000 --- a/libtecla-1.4.1/man3/del_ExpandFile.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/ef_expand_file.3 diff --git a/libtecla-1.4.1/man3/del_GetLine.3 b/libtecla-1.4.1/man3/del_GetLine.3 deleted file mode 100644 index 6bd3d1f..0000000 --- a/libtecla-1.4.1/man3/del_GetLine.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/gl_get_line.3 diff --git a/libtecla-1.4.1/man3/del_PathCache.3 b/libtecla-1.4.1/man3/del_PathCache.3 deleted file mode 100644 index e5a136e..0000000 --- a/libtecla-1.4.1/man3/del_PathCache.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/pca_lookup_file.3 diff --git a/libtecla-1.4.1/man3/del_PcaPathConf.3 b/libtecla-1.4.1/man3/del_PcaPathConf.3 deleted file mode 100644 index e5a136e..0000000 --- a/libtecla-1.4.1/man3/del_PcaPathConf.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/pca_lookup_file.3 diff --git a/libtecla-1.4.1/man3/del_WordCompletion.3 b/libtecla-1.4.1/man3/del_WordCompletion.3 deleted file mode 100644 index 36c83a3..0000000 --- a/libtecla-1.4.1/man3/del_WordCompletion.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/cpl_complete_word.3 diff --git a/libtecla-1.4.1/man3/ef_expand_file.3 b/libtecla-1.4.1/man3/ef_expand_file.3 deleted file mode 100644 index 88c2d54..0000000 --- a/libtecla-1.4.1/man3/ef_expand_file.3 +++ /dev/null @@ -1,245 +0,0 @@ -.\" Copyright (C) 2000, 2001 by Martin C. Shepherd -.\" -.\" All rights reserved. -.\" -.\" Permission is hereby granted, free of charge, to any person obtaining a -.\" copy of this software and associated documentation files (the -.\" "Software"), to deal in the Software without restriction, including -.\" without limitation the rights to use, copy, modify, merge, publish, -.\" distribute, and/or sell copies of the Software, and to permit persons -.\" to whom the Software is furnished to do so, provided that the above -.\" copyright notice(s) and this permission notice appear in all copies of -.\" the Software and that both the above copyright notice(s) and this -.\" permission notice appear in supporting documentation. -.\" -.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -.\" OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -.\" HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL -.\" INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING -.\" FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, -.\" NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION -.\" WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -.\" -.\" Except as contained in this notice, the name of a copyright holder -.\" shall not be used in advertising or otherwise to promote the sale, use -.\" or other dealings in this Software without prior written authorization -.\" of the copyright holder. -.TH ef_expand_file 3 -.SH NAME -ef_expand_file, del_ExpandFile, ef_last_error, ef_list_expansions, new_ExpandFile \- expand filenames containing ~user/$envvar and wildcard expressions -.SH SYNOPSIS -.nf -#include <libtecla.h> - -ExpandFile *new_ExpandFile(void); - -ExpandFile *del_ExpandFile(ExpandFile *ef); - -FileExpansion *ef_expand_file(ExpandFile *ef, - const char *path, - int pathlen); - -int ef_list_expansions(FileExpansion *result, FILE *fp, - int term_width); - -const char *ef_last_error(ExpandFile *ef); -.fi - -.SH DESCRIPTION - -The \f3ef_expand_file()\f1 function is part of the tecla library -(see the libtecla(3) man page). It expands a specified filename, -converting \f3~user/\f1 and \f3~/\f1 expressions at the start of the -filename to the corresponding home directories, replacing -\f3$envvar\f1 with the value of the corresponding environment -variable, and then, if there are any wildcards, matching these against -existing filenames. Backslashes in the input filename are interpreted -as escaping any special meanings of the characters that follow them. -Only backslahes that are themselves preceded by backslashes are -preserved in the expanded filename. -.sp -In the presence of wildcards, the returned list of filenames only -includes the names of existing files which match the -wildcards. Otherwise, the original filename is returned after -expansion of tilde and dollar expressions, and the result is not -checked against existing files. This mimics the file-globbing behavior -of the unix \f3tcsh\f1 shell. -.sp -The supported wildcards and their meanings are: -.nf - * - Match any sequence of zero or more characters. - ? - Match any single character. - [chars] - Match any single character that appears in - 'chars'. If 'chars' contains an expression of - the form a-b, then any character between a and - b, including a and b, matches. The '-' - character looses its special meaning as a - range specifier when it appears at the start - of the sequence of characters. The ']' - character also looses its significance as the - terminator of the range expression if it - appears immediately after the opening '[', at - which point it is treated one of the - characters of the range. If you want both '-' - and ']' to be part of the range, the '-' - should come first and the ']' second. - - [^chars] - The same as [chars] except that it matches any - single character that doesn't appear in - 'chars'. -.fi - -Note that wildcards never match the initial dot in filenames that -start with '.'. The initial '.' must be explicitly specified in the -filename. This again mimics the globbing behavior of most unix shells, -and its rational is based in the fact that in unix, files with names -that start with '.' are usually hidden configuration files, which are -not listed by default by the ls command. -.sp -The following is a complete example of how to use the file expansion -function. - -.nf - #include <stdio.h> - #include <libtecla.h> - - int main(int argc, char *argv[]) - { - ExpandFile *ef; /* The expansion resource object */ - char *filename; /* The filename being expanded */ - FileExpansion *expn; /* The results of the expansion */ - int i; - - ef = new_ExpandFile(); - if(!ef) - return 1; - - for(arg = *(argv++); arg; arg = *(argv++)) { - if((expn = ef_expand_file(ef, arg, -1)) == NULL) { - fprintf(stderr, "Error expanding %s (%s).\\n", arg, - ef_last_error(ef)); - } else { - printf("%s matches the following files:\\n", arg); - for(i=0; i<expn->nfile; i++) - printf(" %s\\n", expn->files[i]); - } - } - - ef = del_ExpandFile(ef); - return 0; - } -.fi -.sp -Descriptions of the functions used above are as follows: -.sp -.nf - ExpandFile *new_ExpandFile(void) -.fi -.sp -This function creates the resources used by the \f3ef_expand_file()\f1 -function. In particular, it maintains the memory that is used to record the -array of matching filenames that is returned by \f3ef_expand_file()\f1. This -array is expanded as needed, so there is no built in limit to the number of -files that can be matched. -.sp -.nf - ExpandFile *del_ExpandFile(ExpandFile *ef) -.fi -.sp -This function deletes the resources that were returned by a previous call to -\f3new_ExpandFile()\f1. It always returns \f3NULL\f1 (ie a deleted object). It -does nothing if the \f3ef\f1 argument is \f3NULL\f1. -.sp -A container of the following type is returned by \f3ef_expand_file()\f1. -.sp -.nf - typedef struct { - int exists; /* True if the files in files[] exist */ - int nfile; /* The number of files in files[] */ - char **files; /* An array of 'nfile' filenames. */ - } FileExpansion; -.fi -.sp -.nf - FileExpansion *ef_expand_file(ExpandFile *ef, - const char *path, - int pathlen) -.fi -.sp -The \f3ef_expand_file()\f1 function performs filename expansion, as documented -at the start of this section. Its first argument is a resource object returned -by \f3new_ExpandFile()\f1. A pointer to the start of the filename to be matched -is passed via the \f3path\f1 argument. This must be a normal \f3NUL\f1 -terminated string, but unless a length of -1 is passed in \f3pathlen\f1, only -the first \f3pathlen\f1 characters will be used in the filename expansion. If -the length is specified as -1, the whole of the string will be -expanded. -.sp -The function returns a pointer to a container who's contents are the -results of the expansion. If there were no wildcards in the filename, -the \f3nfile\f1 member will be 1, and the \f3exists\f1 member should -be queried if it is important to know if the expanded file currently -exists or not. If there were wildcards, then the contained -\f3files[]\f1 array will contain the names of the \f3nfile\f1 existing -files that matched the wildcarded filename, and the \f3exists\f1 -member will have the value 1. Note that the returned container belongs -to the specified \f3ef\f1 object, and its contents will change on each -call, so if you need to retain the results of more than one call to -\f3ef_expand_file()\f1, you should either make a private copy of the -returned results, or create multiple file-expansion resource objects -via multiple calls to \f3new_ExpandFile()\f1. -.sp -On error, \f3NULL\f1 is returned, and an explanation of the error can -be determined by calling \f3ef_last_error(ef)\f1. -.sp -.nf - const char *ef_last_error(ExpandFile *ef) -.fi -.sp -This function returns the message which describes the error that -occurred on the last call to \f3ef_expand_file()\f1, for the given -\f3(ExpandFile *ef)\f1 resource object. -.sp -.nf - int ef_list_expansions(FileExpansion *result, FILE *fp, - int terminal_width); -.fi -.sp -The \f3ef_list_expansions()\f1 function provides a convenient way to -list the filename expansions returned by \f3ef_expand_file()\f1. Like -the unix \f3ls\f1 command, it arranges the filenames into equal width -columns, each column having the width of the largest file. The number -of columns used is thus determined by the length of the longest -filename, and the specified terminal width. Beware that filenames that -are longer than the specified terminal width are printed without being -truncated, so output longer than the specified terminal width can -occur. The list is written to the stdio stream specified by the -\f3fp\f1 argument. - -.SH THREAD SAFETY - -In multi-threaded programs, you should use the \f3libtecla_r.a\f1 -version of the library. This uses POSIX reentrant functions where -available (hence the \f3_r\f1 suffix), and disables features that rely -on non-reentrant system functions. Currently there are no features -disabled in this module. - -Using the \f3libtecla_r.a\f1 version of the library, it is safe to use -the facilities of this module in multiple threads, provided that each -thread uses a separately allocated \f3ExpandFile\f1 object. In other -words, if two threads want to do file expansion, they should each call -\f3new_ExpandFile()\f1 to allocate their own file-expansion objects. - -.SH FILES -.nf -libtecla.a - The tecla library -libtecla.h - The tecla header file. -.fi - -.SH SEE ALSO -libtecla(3), gl_get_line(3), cpl_complete_word(3), pca_lookup_file(3) - -.SH AUTHOR -Martin Shepherd (mcs@astro.caltech.edu) diff --git a/libtecla-1.4.1/man3/ef_last_error.3 b/libtecla-1.4.1/man3/ef_last_error.3 deleted file mode 100644 index f4299df..0000000 --- a/libtecla-1.4.1/man3/ef_last_error.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/ef_expand_file.3 diff --git a/libtecla-1.4.1/man3/ef_list_expansions.3 b/libtecla-1.4.1/man3/ef_list_expansions.3 deleted file mode 100644 index f4299df..0000000 --- a/libtecla-1.4.1/man3/ef_list_expansions.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/ef_expand_file.3 diff --git a/libtecla-1.4.1/man3/enhance.3 b/libtecla-1.4.1/man3/enhance.3 deleted file mode 100644 index 648ef34..0000000 --- a/libtecla-1.4.1/man3/enhance.3 +++ /dev/null @@ -1,86 +0,0 @@ -.\" Copyright (C) 2000, 2001 by Martin C. Shepherd -.\" -.\" All rights reserved. -.\" -.\" Permission is hereby granted, free of charge, to any person obtaining a -.\" copy of this software and associated documentation files (the -.\" "Software"), to deal in the Software without restriction, including -.\" without limitation the rights to use, copy, modify, merge, publish, -.\" distribute, and/or sell copies of the Software, and to permit persons -.\" to whom the Software is furnished to do so, provided that the above -.\" copyright notice(s) and this permission notice appear in all copies of -.\" the Software and that both the above copyright notice(s) and this -.\" permission notice appear in supporting documentation. -.\" -.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -.\" OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -.\" HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL -.\" INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING -.\" FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, -.\" NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION -.\" WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -.\" -.\" Except as contained in this notice, the name of a copyright holder -.\" shall not be used in advertising or otherwise to promote the sale, use -.\" or other dealings in this Software without prior written authorization -.\" of the copyright holder. -.TH libtecla 3 -.SH NAME -enhance - A program that adds command-line editing to third party programs. -.SH SYNOPSIS -.nf -enhance command [ argument ... ] -.fi - -.SH DESCRIPTION - -The \f3enhance\f1 program provides enhanced command-line editing -facilities to users of third party applications, to which one doesn't -have any source code. It does this by placing a pseudo-terminal -between the application and the real terminal. It uses the tecla -command-line editing library to read input from the real terminal, -then forwards each just completed input line to the application via -the pseudo-terminal. All output from the application is forwarded -back unchanged to the real terminal. -.sp -Whenever the application stops generating output for more than a tenth -of a second, the \f3enhance\f1 program treats the latest incomplete -output line as the prompt, and redisplays any incompleted input line -that the user has typed after it. Note that the small delay, which is -imperceptible to the user, isn't necessary for correct operation of -the program. It is just an optimization, designed to stop the input -line from being redisplayed so often that it slows down output. - -.SH DEFICIENCIES - -The one major problem that hasn't been solved yet, is how to deal with -applications that change whether typed input is echo'd by their -controlling terminal. For example, programs that ask for a password, -such as ftp and telnet, temporarily tell their controlling terminal -not to echo what the user types. Since this request goes to the -application side of the psuedo terminal, the \f3enhance\f1 program has -no way of knowing that this has happened, and continues to echo typed -input to its controlling terminal, while the user types their -password. -.sp -Furthermore, before executing the host application, the \f3enhance\f1 -program initially sets the pseudo terminal to noecho mode, so that -everything that it sends to the program doesn't get redundantly -echoed. If a program that switches to noecho mode explicitly restores -echoing afterwards, rather than restoring the terminal modes that were -previously in force, then subsequently, every time that you enter a -new input line, a duplicate copy will be displayed on the next line. - -.SH FILES -.nf -libtecla.a - The tecla library. -~/.teclarc - The tecla personal customization file. -.fi - -.SH SEE ALSO -libtecla(3) - -.SH AUTHOR -Martin Shepherd (mcs@astro.caltech.edu) diff --git a/libtecla-1.4.1/man3/gl_change_terminal.3 b/libtecla-1.4.1/man3/gl_change_terminal.3 deleted file mode 100644 index 6bd3d1f..0000000 --- a/libtecla-1.4.1/man3/gl_change_terminal.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/gl_get_line.3 diff --git a/libtecla-1.4.1/man3/gl_clear_history.3 b/libtecla-1.4.1/man3/gl_clear_history.3 deleted file mode 100644 index 6bd3d1f..0000000 --- a/libtecla-1.4.1/man3/gl_clear_history.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/gl_get_line.3 diff --git a/libtecla-1.4.1/man3/gl_configure_getline.3 b/libtecla-1.4.1/man3/gl_configure_getline.3 deleted file mode 100644 index 6bd3d1f..0000000 --- a/libtecla-1.4.1/man3/gl_configure_getline.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/gl_get_line.3 diff --git a/libtecla-1.4.1/man3/gl_customize_completion.3 b/libtecla-1.4.1/man3/gl_customize_completion.3 deleted file mode 100644 index 6bd3d1f..0000000 --- a/libtecla-1.4.1/man3/gl_customize_completion.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/gl_get_line.3 diff --git a/libtecla-1.4.1/man3/gl_echo_mode.3 b/libtecla-1.4.1/man3/gl_echo_mode.3 deleted file mode 100644 index 6bd3d1f..0000000 --- a/libtecla-1.4.1/man3/gl_echo_mode.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/gl_get_line.3 diff --git a/libtecla-1.4.1/man3/gl_get_line.3 b/libtecla-1.4.1/man3/gl_get_line.3 deleted file mode 100644 index 51fc9d8..0000000 --- a/libtecla-1.4.1/man3/gl_get_line.3 +++ /dev/null @@ -1,2329 +0,0 @@ -.\" Copyright (C) 2000, 2001 by Martin C. Shepherd -.\" -.\" All rights reserved. -.\" -.\" Permission is hereby granted, free of charge, to any person obtaining a -.\" copy of this software and associated documentation files (the -.\" "Software"), to deal in the Software without restriction, including -.\" without limitation the rights to use, copy, modify, merge, publish, -.\" distribute, and/or sell copies of the Software, and to permit persons -.\" to whom the Software is furnished to do so, provided that the above -.\" copyright notice(s) and this permission notice appear in all copies of -.\" the Software and that both the above copyright notice(s) and this -.\" permission notice appear in supporting documentation. -.\" -.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -.\" OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -.\" HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL -.\" INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING -.\" FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, -.\" NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION -.\" WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -.\" -.\" Except as contained in this notice, the name of a copyright holder -.\" shall not be used in advertising or otherwise to promote the sale, use -.\" or other dealings in this Software without prior written authorization -.\" of the copyright holder. -.TH gl_get_line 3 -.SH NAME -gl_get_line, new_GetLine, del_GetLine, gl_customize_completion, gl_change_terminal, gl_configure_getline, gl_load_history, gl_save_history, gl_group_history, gl_show_history, gl_watch_fd, gl_terminal_size, gl_resize_history, gl_limit_history, gl_clear_history, gl_toggle_history, gl_lookup_history, gl_state_of_history, gl_range_of_history, gl_size_of_history, gl_echo_mode, gl_replace_prompt, gl_prompt_style, gl_ignore_signal, gl_trap_signal, gl_last_signal \- allow the user to compose an input line -.SH SYNOPSIS -.nf -#include <stdio.h> -#include <libtecla.h> - -GetLine *new_GetLine(size_t linelen, size_t histlen); - -GetLine *del_GetLine(GetLine *gl); - -char *gl_get_line(GetLine *gl, const char *prompt, - const char *start_line, int start_pos); - -int gl_customize_completion(GetLine *gl, void *data, - CplMatchFn *match_fn); - -int gl_change_terminal(GetLine *gl, FILE *input_fp, - FILE *output_fp, const char *term); - -int gl_configure_getline(GetLine *gl, - const char *app_string, - const char *app_file, - const char *user_file); - -int gl_save_history(GetLine *gl, const char *filename, - const char *comment, int max_lines); - -int gl_load_history(GetLine *gl, const char *filename, - const char *comment); - -int gl_watch_fd(GetLine *gl, int fd, GlFdEvent event, - GlFdEventFn *callback, void *data); - -int gl_group_history(GetLine *gl, unsigned stream); - -int gl_show_history(GetLine *gl, FILE *fp, - const char *fmt, int all_groups, - int max_lines); - -int gl_resize_history(GetLine *gl, size_t bufsize); - -void gl_limit_history(GetLine *gl, int max_lines); - -void gl_clear_history(GetLine *gl, int all_groups); - -void gl_toggle_history(GetLine *gl, int enable); - -GlTerminalSize gl_terminal_size(GetLine *gl, - int def_ncolumn, - int def_nline); - -int gl_lookup_history(GetLine *gl, unsigned long id, - GlHistoryLine *hline); - -void gl_state_of_history(GetLine *gl, - GlHistoryState *state); - -void gl_range_of_history(GetLine *gl, - GlHistoryRange *range); - -void gl_size_of_history(GetLine *gl, GlHistorySize *size); - -void gl_echo_mode(GetLine *gl, int enable); - -void gl_replace_prompt(GetLine *gl, const char *prompt); - -void gl_prompt_style(GetLine *gl, GlPromptStyle style); - -int gl_ignore_signal(GetLine *gl, int signo); - -int gl_trap_signal(GetLine *gl, int signo, unsigned flags, - GlAfterSignal after, int errno_value); - -int gl_last_signal(const GetLine *gl); - -.fi - -.SH DESCRIPTION - -The \f3gl_get_line()\f1 function is part of the tecla library (see -the libtecla(3) man page). If the user is typing at a terminal, it -prompts them for an line of input, then provides interactive editing -facilities, similar to those of the unix \f3tcsh\f1 shell. In addition -to simple command-line editing, it supports recall of previously -entered command lines, TAB completion of file names, and in-line -wild-card expansion of filenames. -.sp -.SH AN EXAMPLE - -The following shows a complete example of how to use the -\f3gl_get_line()\f1 function to get input from the user: - -.nf - #include <stdio.h> - #include <locale.h> - #include <libtecla.h> - - int main(int argc, char *argv[]) - { - char *line; /* The line that the user typed */ - GetLine *gl; /* The gl_get_line() resource object */ - - setlocale(LC_CTYPE, ""); /* Adopt the user's choice */ - /* of character set. */ - - gl = new_GetLine(1024, 2048); - if(!gl) - return 1; - - while((line=gl_get_line(gl, "$ ", NULL, -1)) != NULL && - strcmp(line, "exit\\n") != 0) - printf("You typed: %s\\n", line); - - gl = del_GetLine(gl); - return 0; - } -.fi -.sp -In the example, first the resources needed by the \f3gl_get_line()\f1 function -are created by calling \f3new_GetLine()\f1. This allocates the memory used in -subsequent calls to the \f3gl_get_line()\f1 function, including the history -buffer for recording previously entered lines. Then one or more lines are read -from the user, until either an error occurs, or the user types \f3exit\f1. Then -finally the resources that were allocated by \f3new_GetLine()\f1, are returned -to the system by calling \f3del_GetLine()\f1. Note the use of the \f3NULL\f1 -return value of \f3del_GetLine()\f1 to make \f3gl\f1 \f3NULL\f1. This is a -safety precaution. If the program subsequently attempts to pass \f3gl\f1 to -\f3gl_get_line()\f1, said function will complain, and return an error, instead of -attempting to use the deleted resource object. - -.sp -.SH THE FUNCTIONS USED IN THE EXAMPLE -The descriptions of the functions used in the example are as follows: -.sp -.nf - GetLine *new_GetLine(size_t linelen, size_t histlen) -.fi -.sp -This function creates the resources used by the \f3gl_get_line()\f1 -function and returns an opaque pointer to the object that contains -them. The maximum length of an input line is specified via the -\f3linelen\f1 argument, and the number of bytes to allocate for -storing history lines is set by the \f3histlen\f1 argument. History -lines are stored back-to-back in a single buffer of this size. Note -that this means that the number of history lines that can be stored at -any given time, depends on the lengths of the individual lines. If -you want to place an upper limit on the number of lines that can be -stored, see the \f3gl_limit_history()\f1 function described later. If -you don't want history at all, specify \f3histlen\f1 as zero, and no -history buffer will be allocated. -.sp -On error, a message is printed to \f3stderr\f1 and \f3NULL\f1 is returned. -.sp -.nf - GetLine *del_GetLine(GetLine *gl) -.fi -.sp -This function deletes the resources that were returned by a previous -call to \f3new_GetLine()\f1. It always returns \f3NULL\f1 (ie a -deleted object). It does nothing if the \f3gl\f1 argument is -\f3NULL\f1. -.sp -.nf - char *gl_get_line(GetLine *gl, const char *prompt, - const char *start_line, int start_pos); -.fi -.sp -The \f3gl_get_line()\f1 function can be called any number of -times to read input from the user. The \f3gl\f1 argument -must have been previously returned by a call to -\f3new_GetLine()\f1. The \f3prompt\f1 argument should be a -normal \f3NUL\f1 terminated string, specifying the prompt to -present the user with. By default prompts are displayed -literally, but if enabled with the \f3gl_prompt_style()\f1 -function (see later), prompts can contain directives to do -underlining, switch to and from bold fonts, or turn -highlighting on and off. - -If you want to specify the initial contents of the line, for -the user to edit, pass the desired string via the -\f3start_line\f1 argument. You can then specify which -character of this line the cursor is initially positioned -over, using the \f3start_pos\f1 argument. This should be -1 -if you want the cursor to follow the last character of the -start line. If you don't want to preload the line in this -manner, send \f3start_line\f1 as \f3NULL\f1, and set -\f3start_pos\f1 to -1. - -The \f3gl_get_line()\f1 function returns a pointer to the line entered -by the user, or \f3NULL\f1 on error or at the end of the input. The -returned pointer is part of the specified \f3gl\f1 resource object, -and thus should not be free'd by the caller, or assumed to be -unchanging from one call to the next. When reading from a user at a -terminal, there will always be a newline character at the end of the -returned line. When standard input is being taken from a pipe or a -file, there will similarly be a newline unless the input line was too -long to store in the internal buffer. In the latter case you should -call \f3gl_get_line()\f1 again to read the rest of the line. Note that -this behavior makes \f3gl_get_line()\f1 similar to \f3fgets()\f1. In -fact when \f3stdin\f1 isn't connected to a terminal,\f3gl_get_line()\f1 -just calls \f3fgets()\f1. - -.SH OPTIONAL PROMPT FORMATTING - -Whereas by default the prompt string that you specify is -displayed literally, without any special interpretation of -the characters within it, the \f3gl_prompt_style()\f1 -function can be used to enable optional formatting -directives within the prompt. -.sp -.nf - void gl_prompt_style(GetLine *gl, GlPromptStyle style); -.fi -.sp -The \f3style\f1 argument, which specifies the formatting -style, can take any of the following values: -.sp -.nf - GL_FORMAT_PROMPT - In this style, the formatting - directives described below, when - included in prompt strings, are - interpreted as follows: - - %B - Display subsequent - characters with a bold - font. - %b - Stop displaying characters - with the bold font. - %F - Make subsequent characters - flash. - %f - Turn off flashing - characters. - %U - Underline subsequent - characters. - %u - Stop underlining - characters. - %P - Switch to a pale (half - brightness) font. - %p - Stop using the pale font. - %S - Highlight subsequent - characters (also known as - standout mode). - %s - Stop highlighting - characters. - %V - Turn on reverse video. - %v - Turn off reverse video. - %% - Display a single % - character. - - For example, in this mode, a prompt - string like \f3"%UOK%u$ "\f1 would - display the prompt \f3"OK$ "\f1, - but with the \f3OK\f1 part - underlined. - - Note that although a pair of - characters that starts with a % - character, but doesn't match any of - the above directives is displayed - literally, if a new directive is - subsequently introduced which does - match, the displayed prompt will - change, so it is better to always - use %% to display a literal %. - - Also note that not all terminals - support all of these text - attributes, and that some substitute - a different attribute for missing - ones. - - GL_LITERAL_PROMPT - In this style, the prompt string is - printed literally. This is the - default style. -.fi -.sp - -.SH THE AVAILABLE KEY BINDING FUNCTIONS - -The \f3gl_get_line()\f1 function provides a number of functions which -can be bound to key sequences. The names of these functions, and what -they do, are given below. - -.nf - user-interrupt - Send a SIGINT signal to the - parent process. - abort - Send a SIGABRT signal to the - parent process. - suspend - Suspend the parent process. - stop-output - Pause terminal output. - start-output - Resume paused terminal output. - literal-next - Arrange for the next character - to be treated as a normal - character. This allows control - characters to be entered. - cursor-right - Move the cursor one character - right. - cursor-left - Move the cursor one character - left. - insert-mode - Toggle between insert mode and - overwrite mode. - beginning-of-line - Move the cursor to the - beginning of the line. - end-of-line - Move the cursor to the end of - the line. - delete-line - Delete the contents of the - current line. - kill-line - Delete everything that follows - the cursor. - backward-kill-line - Delete all characters between - the cursor and the start of the - line. - forward-word - Move to the end of the word - which follows the cursor. - forward-to-word - Move the cursor to the start of - the word that follows the - cursor. - backward-word - Move to the start of the word - which precedes the cursor. - goto-column - Move the cursor to the - 1-relative column in the line - specified by any preceding - digit-argument sequences (see - ENTERING REPEAT COUNTS below). - find-parenthesis - If the cursor is currently - over a parenthesis character, - move it to the matching - parenthesis character. If not - over a parenthesis character - move right to the next close - parenthesis. - forward-delete-char - Delete the character under the - cursor. - backward-delete-char - Delete the character which - precedes the cursor. - list-or-eof - This is intended for binding - to ^D. When invoked when the - cursor is within the line it - displays all possible - completions then redisplays - the line unchanged. When - invoked on an empty line, it - signals end-of-input (EOF) to - the caller of gl_get_line(). - del-char-or-list-or-eof - This is intended for binding - to ^D. When invoked when the - cursor is within the line it - invokes forward-delete-char. - When invoked at the end of the - line it displays all possible - completions then redisplays - the line unchanged. When - invoked on an empty line, it - signals end-of-input (EOF) to - the caller of gl_get_line(). - forward-delete-word - Delete the word which follows - the cursor. - backward-delete-word - Delete the word which precedes - the cursor. - upcase-word - Convert all of the characters - of the word which follows the - cursor, to upper case. - downcase-word - Convert all of the characters - of the word which follows the - cursor, to lower case. - capitalize-word - Capitalize the word which - follows the cursor. - change-case - If the next character is upper - case, toggle it to lower case - and vice versa. - redisplay - Redisplay the line. - clear-screen - Clear the terminal, then - redisplay the current line. - transpose-chars - Swap the character under the - cursor with the character just - before the cursor. - set-mark - Set a mark at the position of - the cursor. - exchange-point-and-mark - Move the cursor to the last - mark that was set, and move - the mark to where the cursor - used to be. - kill-region - Delete the characters that lie - between the last mark that was - set, and the cursor. - copy-region-as-kill - Copy the text between the mark - and the cursor to the cut - buffer, without deleting the - original text. - yank - Insert the text that was last - deleted, just before the - current position of the cursor. - append-yank - Paste the current contents of - the cut buffer, after the - cursor. - up-history - Recall the next oldest line - that was entered. Note that - in vi mode you are left in - command mode. - down-history - Recall the next most recent - line that was entered. If no - history recall session is - currently active, the next - line from a previous recall - session is recalled. Note that - in vi mode you are left in - command mode. - history-search-backward - Recall the next oldest line - who's prefix matches the string - which currently precedes the - cursor (in vi command-mode the - character under the cursor is - also included in the search - string). Note that in vi mode - you are left in command mode. - history-search-forward - Recall the next newest line - who's prefix matches the string - which currently precedes the - cursor (in vi command-mode the - character under the cursor is - also included in the search - string). Note that in vi mode - you are left in command mode. - history-re-search-backward -Recall the next oldest line - who's prefix matches that - established by the last - invocation of either - history-search-forward or - history-search-backward. - history-re-search-forward - Recall the next newest line - who's prefix matches that - established by the last - invocation of either - history-search-forward or - history-search-backward. - complete-word - Attempt to complete the - incomplete word which - precedes the cursor. Unless - the host program has customized - word completion, filename - completion is attempted. In vi - commmand mode the character - under the cursor is also - included in the word being - completed, and you are left in - vi insert mode. - expand-filename - Within the command line, expand - wild cards, tilde expressions - and dollar expressions in the - filename which immediately - precedes the cursor. In vi - commmand mode the character - under the cursor is also - included in the filename being - expanded, and you are left in - vi insert mode. - list-glob - List any filenames which match - the wild-card, tilde and dollar - expressions in the filename - which immediately precedes the - cursor, then redraw the input - line unchanged. - list-history - Display the contents of the - history list for the current - history group. If a repeat - count of > 1 is specified, - only that many of the most - recent lines are displayed. - See the "ENTERING REPEAT - COUNTS" section. - read-from-file - Temporarily switch to reading - input from the file who's - name precedes the cursor. - read-init-files - Re-read teclarc configuration - files. - beginning-of-history - Move to the oldest line in the - history list. Note that in vi - mode you are left in command - mode. - end-of-history - Move to the newest line in the - history list (ie. the current - line). Note that in vi mode - this leaves you in command - mode. - digit-argument - Enter a repeat count for the - next key-binding function. - For details, see the ENTERING - REPEAT COUNTS section. - newline - Terminate and return the - current contents of the - line, after appending a - newline character. The newline - character is normally '\\n', - but will be the first - character of the key-sequence - that invoked the newline - action, if this happens to be - a printable character. If the - action was invoked by the - '\\n' newline character or the - '\\r' carriage return - character, the line is - appended to the history - buffer. - repeat-history - Return the line that is being - edited, then arrange for the - next most recent entry in the - history buffer to be recalled - when \f3gl_get_line()\f1 is - next called. Repeatedly - invoking this action causes - successive historical input - lines to be re-executed. Note - that this action is equivalent - to the 'Operate' action in - ksh. - ring-bell - Ring the terminal bell, unless - the bell has been silenced via - the \f3nobeep\f1 configuration - option (see the THE TECLA - CONFIGURATION FILE section). - forward-copy-char - Copy the next character into - the cut buffer (NB. use repeat - counts to copy more than one). - backward-copy-char - Copy the previous character - into the cut buffer. - forward-copy-word - Copy the next word into the cut - buffer. - backward-copy-word - Copy the previous word into the - cut buffer. - forward-find-char - Move the cursor to the next - occurrence of the next - character that you type. - backward-find-char - Move the cursor to the last - occurrence of the next - character that you type. - forward-to-char - Move the cursor to the - character just before the next - occurrence of the next - character that the user types. - backward-to-char - Move the cursor to the - character just after the last - occurrence before the cursor - of the next character that the - user types. - repeat-find-char - Repeat the last - backward-find-char, - forward-find-char, - backward-to-char or - forward-to-char. - invert-refind-char - Repeat the last - backward-find-char, - forward-find-char, - backward-to-char, or - forward-to-char in the - opposite direction. - delete-to-column - Delete the characters from the - cursor up to the column that - is specified by the repeat - count. - delete-to-parenthesis - Delete the characters from the - cursor up to and including - the matching parenthesis, or - next close parenthesis. - forward-delete-find - Delete the characters from the - cursor up to and including the - following occurence of the - next character typed. - backward-delete-find - Delete the characters from the - cursor up to and including the - preceding occurence of the - next character typed. - forward-delete-to - Delete the characters from the - cursor up to, but not - including, the following - occurence of the next - character typed. - backward-delete-to - Delete the characters from the - cursor up to, but not - including, the preceding - occurence of the next - character typed. - delete-refind - Repeat the last *-delete-find - or *-delete-to action. - delete-invert-refind - Repeat the last *-delete-find - or *-delete-to action, in the - opposite direction. - copy-to-column - Copy the characters from the - cursor up to the column that - is specified by the repeat - count, into the cut buffer. - copy-to-parenthesis - Copy the characters from the - cursor up to and including - the matching parenthesis, or - next close parenthesis, into - the cut buffer. - forward-copy-find - Copy the characters from the - cursor up to and including the - following occurence of the - next character typed, into the - cut buffer. - backward-copy-find - Copy the characters from the - cursor up to and including the - preceding occurence of the - next character typed, into the - cut buffer. - forward-copy-to - Copy the characters from the - cursor up to, but not - including, the following - occurence of the next - character typed, into the cut - buffer. - backward-copy-to - Copy the characters from the - cursor up to, but not - including, the preceding - occurence of the next - character typed, into the cut - buffer. - copy-refind - Repeat the last *-copy-find - or *-copy-to action. - copy-invert-refind - Repeat the last *-copy-find - or *-copy-to action, in the - opposite direction. - vi-mode - Switch to vi mode from emacs - mode. - emacs-mode - Switch to emacs mode from vi - mode. - vi-insert - From vi command mode, switch to - insert mode. - vi-overwrite - From vi command mode, switch to - overwrite mode. - vi-insert-at-bol - From vi command mode, move the - cursor to the start of the line - and switch to insert mode. - vi-append-at-eol - From vi command mode, move the - cursor to the end of the line - and switch to append mode. - vi-append - From vi command mode, move the - cursor one position right, and - switch to insert mode. - vi-replace-char - From vi command mode, replace - the character under the cursor - with the the next character - entered. - vi-forward-change-char - From vi command mode, delete - the next character then enter - insert mode. - vi-backward-change-char - From vi command mode, delete - the preceding character then - enter insert mode. - vi-forward-change-word - From vi command mode, delete - the next word then enter - insert mode. - vi-backward-change-word - From vi command mode, delete - the preceding word then - enter insert mode. - vi-change-rest-of-line - From vi command mode, delete - from the cursor to the end of - the line, then enter insert - mode. - vi-change-line - From vi command mode, delete - the current line, then enter - insert mode. - vi-change-to-bol - From vi command mode, delete - all characters between the - cursor and the beginning of - the line, then enter insert - mode. - vi-change-to-column - From vi command mode, delete - the characters from the cursor - up to the column that is - specified by the repeat count, - then enter insert mode. - vi-change-to-parenthesis - Delete the characters from the - cursor up to and including - the matching parenthesis, or - next close parenthesis, then - enter vi insert mode. - vi-forward-change-find - From vi command mode, delete - the characters from the - cursor up to and including the - following occurence of the - next character typed, then - enter insert mode. - vi-backward-change-find - From vi command mode, delete - the characters from the - cursor up to and including the - preceding occurence of the - next character typed, then - enter insert mode. - vi-forward-change-to - From vi command mode, delete - the characters from the - cursor up to, but not - including, the following - occurence of the next - character typed, then enter - insert mode. - vi-backward-change-to - From vi command mode, delete - the characters from the - cursor up to, but not - including, the preceding - occurence of the next - character typed, then enter - insert mode. - vi-change-refind - Repeat the last - vi-*-change-find or - vi-*-change-to action. - vi-change-invert-refind - Repeat the last - vi-*-change-find or - vi-*-change-to action, in the - opposite direction. - vi-undo - In vi mode, undo the last - editing operation. - vi-repeat-change - In vi command mode, repeat the - last command that modified the - line. -.fi - -.SH DEFAULT KEY BINDINGS IN EMACS MODE - -The following default key bindings, which can be overriden by -the tecla configuration file, are designed to mimic most of -the bindings of the unix \f3tcsh\f1 shell, when it is in -emacs editing mode. -.sp -This is the default editing mode of the tecla library. -.sp -Note that a key sequence like \f3^A\f1 or \f3C-a\f1 means hold the control-key -down while pressing the letter \f3A\f1, and that where you see \f3\\E\f1 or -\f3M-\f1 in a binding, this represents the escape key or the Meta modifier -key. Also note that to \f3gl_get_line()\f1, pressing the escape key before a -key is equivalent to pressing the meta key at the same time as that key. Thus -the key sequence \f3M-p\f1 can be typed in two ways, by pressing the escape -key, followed by pressing \f3p\f1, or by pressing the Meta key at the same time -as \f3p\f1. -.sp -Under UNIX the terminal driver sets a number of special keys for certain -functions. The tecla library attempts to use the same keybindings to maintain -consistency. The key sequences shown for the following 6 bindings are thus just -examples of what they will probably be set to. If you have used the \f3stty\f1 -command to change these keys, then the default bindings should match. - -.nf - ^C -> user-interrupt - ^\\ -> abort - ^Z -> suspend - ^Q -> start-output - ^S -> stop-output - ^V -> literal-next -.fi - -The cursor keys are refered to by name, as follows. This is necessary -because different types of terminals generate different key sequences -when their cursor keys are pressed. - - right -> cursor-right - left -> cursor-left - up -> up-history - down -> down-history - -The remaining bindings don't depend on the terminal setttings. - -.nf - ^F -> cursor-right - ^B -> cursor-left - M-i -> insert-mode - ^A -> beginning-of-line - ^E -> end-of-line - ^U -> delete-line - ^K -> kill-line - M-f -> forward-word - M-b -> backward-word - ^D -> del-char-or-list-or-eof - ^H -> backward-delete-char - ^? -> backward-delete-char - M-d -> forward-delete-word - M-^H -> backward-delete-word - M-^? -> backward-delete-word - M-u -> upcase-word - M-l -> downcase-word - M-c -> capitalize-word - ^R -> redisplay - ^L -> clear-screen - ^T -> transpose-chars - ^@ -> set-mark - ^X^X -> exchange-point-and-mark - ^W -> kill-region - M-w -> copy-region-as-kill - ^Y -> yank - ^P -> up-history - ^N -> down-history - M-p -> history-search-backward - M-n -> history-search-forward - ^I -> complete-word - ^X* -> expand-filename - ^X^F -> read-from-file - ^X^R -> read-init-files - ^Xg -> list-glob - ^Xh -> list-history - M-< -> beginning-of-history - M-> -> end-of-history - \\n -> newline - \\r -> newline - M-o -> repeat-history - M-^V -> vi-mode - - M-0, M-1, ... M-9 -> digit-argument (see below) -.fi - -Note that ^I is what the TAB key generates, and that ^@ can be -generated not only by pressing the control key and the @ key -simultaneously, but also by pressing the control key and the space bar -at the same time. - -.SH DEFAULT KEY BINDINGS IN VI MODE - -The following default key bindings are designed to mimic the -vi style of editing as closely as possible. This means that -very few editing functions are provided in the initial -character input mode, editing functions instead being -provided by the vi command mode. Vi command mode is entered -whenever the escape character is pressed, or whenever a -key-sequence that starts with a meta character is entered. In -addition to mimicing vi, libtecla provides bindings for tab -completion, wild-card expansion of file names, and historical -line recall. -.sp -To learn how to tell the tecla library to use vi mode instead -of the default emacs editing mode, see the section entitled -THE TECLA CONFIGURATION FILE. -.sp -As already mentioned above in the emacs section, Note that a -key sequence like \f3^A\f1 or \f3C-a\f1 means hold the -control-key down while pressing the letter \f3A\f1, and that -where you see \f3\\E\f1 or \f3M-\f1 in a binding, this -represents the escape key or the Meta modifier key. Also note -that to \f3gl_get_line()\f1, pressing the escape key before a -key is equivalent to pressing the meta key at the same time -as that key. Thus the key sequence \f3M-p\f1 can be typed in -two ways, by pressing the escape key, followed by pressing -\f3p\f1, or by pressing the Meta key at the same time as -\f3p\f1. -.sp -Under UNIX the terminal driver sets a number of special keys -for certain functions. The tecla library attempts to use the -same keybindings to maintain consistency, binding them both -in input mode and in command mode. The key sequences shown -for the following 6 bindings are thus just examples of what -they will probably be set to. If you have used the \f3stty\f1 -command to change these keys, then the default bindings -should match. - -.nf - ^C -> user-interrupt - ^\\ -> abort - ^Z -> suspend - ^Q -> start-output - ^S -> stop-output - ^V -> literal-next - M-^C -> user-interrupt - M-^\\ -> abort - M-^Z -> suspend - M-^Q -> start-output - M-^S -> stop-output -.fi - -Note that above, most of the bindings are defined twice, once -as a raw control code like \f3^C\f1 and then a second time as -a meta character like \f3M-^C\f1. The former is the binding -for vi input mode, whereas the latter is the binding for vi -command mode. Once in command mode all key-sequences that the -user types that they don't explicitly start with an escape or -a meta key, have their first key secretly converted to a meta -character before the key sequence is looked up in the key -binding table. Thus, once in command mode, when you type the -letter \f3i\f1, for example, the tecla library actually looks -up the binding for \f3M-i\f1. - -The cursor keys are refered to by name, as follows. This is necessary -because different types of terminals generate different key sequences -when their cursor keys are pressed. - - right -> cursor-right - left -> cursor-left - up -> up-history - down -> down-history - -The cursor keys normally generate a keysequence that start -with an escape character, so beware that using the arrow keys -will put you into command mode (if you aren't already in -command mode). -.sp -The following are the terminal-independent key bindings for vi input -mode. - -.nf - ^D -> list-or-eof - ^G -> list-glob - ^H -> backward-delete-char - ^I -> complete-word - \\r -> newline - \\n -> newline - ^L -> clear-screen - ^N -> down-history - ^P -> up-history - ^R -> redisplay - ^U -> backward-kill-line - ^W -> backward-delete-word - ^X* -> expand-filename - ^X^F -> read-from-file - ^X^R -> read-init-files - ^? -> backward-delete-char -.fi - -The following are the key bindings that are defined in vi -command mode, this being specified by them all starting with -a meta character. As mentioned above, once in command mode -the initial meta character is optional. For example, you -might enter command mode by typing Esc, and then press h -twice to move the cursor two positions to the left. Both h -characters get quietly converted to M-h before being compared -to the key-binding table, the first one because Escape -followed by a character is always converted to the equivalent -meta character, and the second because command mode was -already active. - -.nf - M-\\ -> cursor-right (Meta-space) - M-$ -> end-of-line - M-* -> expand-filename - M-+ -> down-history - M-- -> up-history - M-< -> beginning-of-history - M-> -> end-of-history - M-^ -> beginning-of-line - M-; -> repeat-find-char - M-, -> invert-refind-char - M-| -> goto-column - M-~ -> change-case - M-. -> vi-repeat-change - M-% -> find-parenthesis - M-a -> vi-append - M-A -> vi-append-at-eol - M-b -> backward-word - M-B -> backward-word - M-C -> vi-change-rest-of-line - M-cb -> vi-backward-change-word - M-cB -> vi-backward-change-word - M-cc -> vi-change-line - M-ce -> vi-forward-change-word - M-cE -> vi-forward-change-word - M-cw -> vi-forward-change-word - M-cW -> vi-forward-change-word - M-cF -> vi-backward-change-find - M-cf -> vi-forward-change-find - M-cT -> vi-backward-change-to - M-ct -> vi-forward-change-to - M-c; -> vi-change-refind - M-c, -> vi-change-invert-refind - M-ch -> vi-backward-change-char - M-c^H -> vi-backward-change-char - M-c^? -> vi-backward-change-char - M-cl -> vi-forward-change-char - M-c\\ -> vi-forward-change-char (Meta-c-space) - M-c^ -> vi-change-to-bol - M-c0 -> vi-change-to-bol - M-c$ -> vi-change-rest-of-line - M-c| -> vi-change-to-column - M-c% -> vi-change-to-parenthesis - M-dh -> backward-delete-char - M-d^H -> backward-delete-char - M-d^? -> backward-delete-char - M-dl -> forward-delete-char - M-d -> forward-delete-char (Meta-d-space) - M-dd -> delete-line - M-db -> backward-delete-word - M-dB -> backward-delete-word - M-de -> forward-delete-word - M-dE -> forward-delete-word - M-dw -> forward-delete-word - M-dW -> forward-delete-word - M-dF -> backward-delete-find - M-df -> forward-delete-find - M-dT -> backward-delete-to - M-dt -> forward-delete-to - M-d; -> delete-refind - M-d, -> delete-invert-refind - M-d^ -> backward-kill-line - M-d0 -> backward-kill-line - M-d$ -> kill-line - M-D -> kill-line - M-d| -> delete-to-column - M-d% -> delete-to-parenthesis - M-e -> forward-word - M-E -> forward-word - M-f -> forward-find-char - M-F -> backward-find-char - M-- -> up-history - M-h -> cursor-left - M-H -> beginning-of-history - M-i -> vi-insert - M-I -> vi-insert-at-bol - M-j -> down-history - M-J -> history-search-forward - M-k -> up-history - M-K -> history-search-backward - M-l -> cursor-right - M-L -> end-of-history - M-n -> history-re-search-forward - M-N -> history-re-search-backward - M-p -> append-yank - M-P -> yank - M-r -> vi-replace-char - M-R -> vi-overwrite - M-s -> vi-forward-change-char - M-S -> vi-change-line - M-t -> forward-to-char - M-T -> backward-to-char - M-u -> vi-undo - M-w -> forward-to-word - M-W -> forward-to-word - M-x -> forward-delete-char - M-X -> backward-delete-char - M-yh -> backward-copy-char - M-y^H -> backward-copy-char - M-y^? -> backward-copy-char - M-yl -> forward-copy-char - M-y\\ -> forward-copy-char (Meta-y-space) - M-ye -> forward-copy-word - M-yE -> forward-copy-word - M-yw -> forward-copy-word - M-yW -> forward-copy-word - M-yb -> backward-copy-word - M-yB -> backward-copy-word - M-yf -> forward-copy-find - M-yF -> backward-copy-find - M-yt -> forward-copy-to - M-yT -> backward-copy-to - M-y; -> copy-refind - M-y, -> copy-invert-refind - M-y^ -> copy-to-bol - M-y0 -> copy-to-bol - M-y$ -> copy-rest-of-line - M-yy -> copy-line - M-Y -> copy-line - M-y| -> copy-to-column - M-y% -> copy-to-parenthesis - M-^E -> emacs-mode - M-^H -> cursor-left - M-^? -> cursor-left - M-^L -> clear-screen - M-^N -> down-history - M-^P -> up-history - M-^R -> redisplay - M-^D -> list-or-eof - M-^I -> complete-word - M-\\r -> newline - M-\\n -> newline - M-^X^R -> read-init-files - M-^Xh -> list-history - - M-0, M-1, ... M-9 -> digit-argument (see below) -.fi - -Note that ^I is what the TAB key generates. - -.SH ENTERING REPEAT COUNTS - -Many of the key binding functions described previously, take -an optional count, typed in before the target -keysequence. This is interpreted as a repeat count by most -bindings. A notable exception is the goto-column binding, -which interprets the count as a column number. -.sp -By default you can specify this count argument by pressing -the meta key while typing in the numeric count. This relies -on the \f3digit-argument\f1 action being bound to Meta-0, -Meta-1 etc. Once any one of these bindings has been -activated, you can optionally take your finger off the meta -key to type in the rest of the number, since every numeric -digit thereafter is treated as part of the number, unless it -is preceded by the \f3literal-next\f1 binding. As soon as a -non-digit, or literal digit key is pressed the repeat count -is terminated and either causes the just typed character to -be added to the line that many times, or causes the next -key-binding function to be given that argument. -.sp -For example, in emacs mode, typing: -.sp -.nf - M-12a -.fi -.sp -causes the letter 'a' to be added to the line 12 times, -whereas -.sp -.nf - M-4M-c -.fi -.sp -Capitalizes the next 4 words. -.sp -In vi command mode the Meta modifier is automatically added -to all characters typed in, so to enter a count in vi -command-mode, just involves typing in the number, just as at -it does in the vi editor itself. So for example, in vi -command mode, typing: -.sp -.nf - 4w2x -.fi -.sp -moves the cursor four words to the right, then deletes two characters. -.sp -You can also bind \f3digit-argument\f1 to other key sequences. If -these end in a numeric digit, that digit gets appended to the current -repeat count. If it doesn't end in a numeric digit, a new repeat count -is started with a value of zero, and can be completed by typing in the -number, after letting go of the key which triggered the digit-argument -action. - -.SH THE TECLA CONFIGURATION FILE - -By default, the first call to \f3gl_get_line()\f1 looks for a file -called \f3\&.teclarc\f1 in your home directory (ie. \f3~/.teclarc\f1). -If it finds this file, it reads it, interpreting each line as defining -a new key binding or an editing configuration option. Since the emacs -keybindings are installed by default, if you want to use the -non-default vi editing mode, the most important item to go in this -file is the following line: - -.nf - edit-mode vi -.fi - -This will re-configure the default bindings for vi-mode. The -complete set of arguments that this command accepts are: -.sp -.nf - vi - Install key-bindings like those of the vi - editor. - emacs - Install key-bindings like those of the emacs - editor. This is the default. - none - Use just the native line editing facilities - provided by the terminal driver. -.fi -.sp -To prevent the terminal bell from being rung, such as when -an unrecognized control-sequence is typed, place the -following line in the configuration file: - -.nf - nobeep -.fi - -An example of a key binding line in the configuration file is -the following. - -.nf - bind M-[2~ insert-mode -.fi - -On many keyboards, the above key sequence is generated when one -presses the \f3insert\f1 key, so with this keybinding, one can toggle -between the emacs-mode insert and overwrite modes by hitting one -key. One could also do it by typing out the above sequence of -characters one by one. As explained above, the \f3M-\f1 part of this -sequence can be typed either by pressing the escape key before the -following key, or by pressing the Meta key at the same time as the -following key. Thus if you had set the above key binding, and the -insert key on your keyboard didn't generate the above key sequence, -you could still type it in either of the following 2 ways. - -.nf - 1. Hit the escape key momentarily, then press '[', then '2', then - finally '~'. - - 2. Press the meta key at the same time as pressing the '[' key, - then press '2', then '~'. -.fi - -If you set a keybinding for a key-sequence that is already bound to a function, -the new binding overrides the old one. If in the new binding you omit the name -of the new function to bind to the key-sequence, the original binding becomes -undefined. -.sp -Starting with versions of libtecla later than 1.3.3 it is now possible -to bind keysequences that begin with a printable character. Previously -key-sequences were required to start with a control or meta character. -.sp -Note that the special keywords "up", "down", "left" and "right" refer -to the arrow keys, and are thus not treated as keysequences. So, for -example, to rebind the up and down arrow keys to use the history -search mechanism instead of the simple history recall method, you -could place the following in your configuration file: - -.nf - bind up history-search-backwards - bind down history-search-backwards -.fi -.sp -To unbind an existing binding, you can do this with the bind command -by omitting to name any action to rebind the key sequence to. For -example, by not specifying an action function, the following command -unbinds the default beginning-of-line action from the ^A key sequence: - -.nf - bind ^A -.fi - -.SH ALTERNATE CONFIGURATION SOURCES - -As mentioned above, by default users have the option of configuring -the behavior of \f3gl_get_line()\f1 via a configuration file called -\f3\&.teclarc\f1 in their home directories. The fact that all -applications share this same configuration file is both an advantage -and a disadvantage. In most cases it is an advantage, since it -encourages uniformity, and frees the user from having to configure -each application separately. In some applications, however, this -single means of configuration is a problem. This is particularly true -of embedded software, where there's no filesystem to read a -configuration file from, and also in applications where a radically -different choice of keybindings is needed to emulate a legacy keyboard -interface. To cater for such cases, the following function allows the -application to control where configuration information is read from. - -.sp -.nf - int gl_configure_getline(GetLine *gl, - const char *app_string, - const char *app_file, - const char *user_file); -.fi -.sp - -It allows the configuration commands that would normally be read from -a user's \f3~/.teclarc\f1 file, to be read from any or none of, a -string, an application specific configuration file, and/or a -user-specific configuration file. If this function is called before -the first call to \f3gl_get_line()\f1, the default behavior of -reading \f3~/.teclarc\f1 on the first call to \f3gl_get_line()\f1 is -disabled, so all configuration must be achieved using the -configuration sources specified with this function. - -If \f3app_string != NULL\f1, then it is interpreted as a string -containing one or more configuration commands, separated from each -other in the string by embedded newline characters. If \f3app_file != -NULL\f1 then it is interpreted as the full pathname of an -application-specific configuration file. If \f3user_file != NULL\f1 -then it is interpreted as the full pathname of a user-specific -configuration file, such as \f3~/.teclarc\f1. For example, in the -following call, - - gl_configure_getline(gl, "edit-mode vi \\n nobeep", - "/usr/share/myapp/teclarc", - "~/.teclarc"); - -the \f3app_string\f1 argument causes the calling application to start -in vi edit-mode, instead of the default emacs mode, and turns off the -use of the terminal bell by the library. It then attempts to read -system-wide configuration commands from an optional file called -\f3/usr/share/myapp/teclarc\f1, then finally reads user-specific -configuration commands from an optional \f3\&.teclarc\f1 file in the -user's home directory. Note that the arguments are listed in ascending -order of priority, with the contents of \f3app_string\f1 being -potentially overriden by commands in \f3app_file\f1, and commands in -\f3app_file\f1 potentially being overriden by commands in -\f3user_file\f1. -.sp -You can call this function as many times as needed, the results being -cumulative, but note that copies of any filenames specified via the -\f3app_file\f1 and \f3user_file\f1 arguments are recorded internally -for subsequent use by the \f3read-init-files\f1 key-binding function, -so if you plan to call this function multiple times, be sure that the -last call specifies the filenames that you want re-read when the user -requests that the configuration files be re-read. - -.SH FILENAME AND TILDE COMPLETION - -With the default key bindings, pressing the TAB key (aka. ^I) results -in \f3gl_get_line()\f1 attempting to complete the incomplete filename -that precedes the cursor. \f3gl_get_line()\f1 searches backwards from -the cursor, looking for the start of the filename, stopping when it -hits either a space or the start of the line. If more than one file -has the specified prefix, \f3gl_get_line()\f1 completes the filename -up to the point at which the ambiguous matches start to differ, then -lists the possible matches. -.sp -In addition to literally written filenames, \f3gl_get_line()\f1 can -complete files that start with \f3~/\f1 and \f3~user/\f1 expressions -and that contain \f3$envvar\f1 expressions. In particular, if you hit -TAB within an incomplete \f3~user\f1, expression, \f3gl_get_line()\f1 -will attempt to complete the username, listing any ambiguous matches. -.sp -The completion binding is implemented using the -\f3cpl_word_completions()\f1 function, which is also available -separately to users of this library. See the -\f3cpl_word_completions(3)\f1 man page for more details. - -.SH CUSTOMIZED WORD COMPLETION - -If in your application, you would like to have TAB completion complete -other things in addition to or instead of filenames, you can arrange -this by registering an alternate completion callback function, via a -call to the \f3gl_customize_completion()\f1 function. -.sp -.nf - int gl_customize_completion(GetLine *gl, void *data, - CplMatchFn *match_fn); -.fi -.sp -The \f3data\f1 argument provides a way for your application to pass -arbitrary, application-specific information to the callback -function. This is passed to the callback every time that it is -called. It might for example, point to the symbol table from which -possible completions are to be sought. The \f3match_fn\f1 argument -specifies the callback function to be called. The \f3CplMatchFn\f1 -function type is defined in \f3libtecla.h\f1, as is a -\f3CPL_MATCH_FN()\f1 macro that you can use to declare and prototype -callback functions. The declaration and responsibilities of callback -functions are described in depth in the \f1cpl_complete_word(3)\f1 man -page. -.sp -In brief, the callback function is responsible for looking backwards -in the input line, back from the point at which the user pressed TAB, -to find the start of the word being completed. It then must lookup -possible completions of this word, and record them one by one in the -\f3WordCompletion\f1 object that is passed to it as an argument, by -calling the \f3cpl_add_completion()\f1 function. If the callback -function wishes to provide filename completion in addition to its own -specific completions, it has the option of itself calling the builtin -file-name completion callback. This also, is documented in the -\f3cpl_complete_word(3)\f1 man page. -.sp -Note that if you would like \f3gl_get_line()\f1 to return the current -input line when a successful completion is been made, you can arrange -this when you call \f3cpl_add_completion()\f1, by making the last -character of the continuation suffix a newline character. If you do -this, the input line will be updated to display the completion, -together with any contiuation suffix up to the newline character, then -\f3gl_get_line()\f1 will return this input line. - -.SH FILENAME EXPANSION - -With the default key bindings, pressing \f3^X*\f1 causes -\f3gl_get_line()\f1 to expand the filename that precedes the cursor, -replacing \f3~/\f1 and \f3~user/\f1 expressions with the corresponding -home directories, and replacing \f3$envvar\f1 expressions with the -value of the specified environment variable, then if there are any -wildcards, replacing the so far expanded filename with a -space-separated list of the files which match the wild cards. -.sp -The expansion binding is implemented using the \f3ef_expand_file()\f1 function. -See the \f3ef_expand_file(3)\f1 man page for more details. - -.SH RECALLING PREVIOUSLY TYPED LINES - -Every time that a new line is entered by the user, it is appended to a -list of historical input lines maintained within the GetLine resource -object. You can traverse up and down this list using the up and down -arrow keys. Alternatively, you can do the same with the \f3^P\f1, and -\f3^N\f1 keys, and in vi command mode you can alternatively use the k -and j characters. Thus pressing up-arrow once, replaces the current -input line with the previously entered line. Pressing up-arrow again, -replaces this with the line that was entered before it, etc.. Having -gone back one or more lines into the history list, one can return to -newer lines by pressing down-arrow one or more times. If you do this -sufficient times, you will return to the original line that you were -entering when you first hit up-arrow. -.sp -Note that in vi mode, all of the history recall functions switch the -library into command mode. -.sp -In emacs mode the \f3M-p\f1 and \f3M-n\f1 keys work just like the -\f3^P\f1 and \f3^N\f1 keys, except that they skip all but those -historical lines which share the prefix that precedes the cursor. In -vi command mode the upper case \f3K\f1 and \f3J\f1 characters do the -same thing, except that the string that they search for includes the -character under the cursor as well as what precedes it. -.sp -Thus for example, suppose that you were in emacs mode, and you had -just entered the following list of commands in the order shown: - -.nf - ls ~/tecla/ - cd ~/tecla - ls -l getline.c - emacs ~/tecla/getline.c -.fi - -If you next typed: - -.nf - ls -.fi - -and then hit \f3M-p\f1, then rather than returning the previously -typed emacs line, which doesn't start with "ls", \f3gl_get_line()\f1 -would recall the "ls -l getline.c" line. Pressing \f3M-p\f1 again -would recall the "ls ~/tecla/" line. - -.SH HISTORY FILES - -To save the contents of the history buffer before quitting your -application, and subsequently restore them when you next start the -application, the following functions are provided. - -.sp -.nf - int gl_save_history(GetLine *gl, const char *filename, - const char *comment, int max_lines); - int gl_load_history(GetLine *gl, const char *filename, - const char *comment); -.fi -.sp - -The \f3filename\f1 argument specifies the name to give the history -file when saving, or the name of an existing history file, when -loading. This may contain home-directory and environment variable -expressions, such as "~/.myapp_history" or "$HOME/.myapp_history". -.sp -Along with each history line, extra information about it, such as when -it was entered by the user, and what its nesting level is, is recorded -as a comment preceding the line in the history file. Writing this as a -comment allows the history file to double as a command file, just in -case you wish to replay a whole session using it. Since comment -prefixes differ in different languages, the \f3comment\f1 argument is -provided for specifying the comment prefix. For example, if your -application were a unix shell, such as the bourne shell, you would -specify "#" here. Whatever you choose for the comment character, you -must specify the same prefix to \f3gl_load_history()\f1 that you used -when you called \f3gl_save_history()\f1 to write the history file. -.sp -The \f3max_lines\f1 must be either -1 to specify that all lines in the -history list be saved, or a positive number specifying a ceiling on -how many of the most recent lines should be saved. -.sp -Both fuctions return non-zero on error, after writing an error message -to stderr. Note that \f3gl_load_history()\f1 does not consider the -non-existence of a file to be an error. - -.SH MULTIPLE HISTORY LISTS - -If your application uses a single \f3GetLine\f1 object for entering -many different types of input lines, you may wish \f3gl_get_line()\f1 -to distinguish the different types of lines in the history list, and -only recall lines that match the current type of line. To support this -requirement, \f3gl_get_line()\f1 marks lines being recorded in the -history list with an integer identifier chosen by the application. -Initially this identifier is set to \f10\f3 by \f3new_GetLine()\f1, -but it can be changed subsequently by calling -\f3gl_group_history()\f1. - -.sp -.nf - int gl_group_history(GetLine *gl, unsigned id); -.fi -.sp - -The integer identifier \f3id\f1 can be any number chosen by the -application, but note that \f3gl_save_history()\f1 and -\f3gl_load_history()\f1 preserve the association between identifiers -and historical input lines between program invokations, so you should -choose fixed identifiers for the different types of input line used by -your application. -.sp -Whenever \f3gl_get_line()\f1 appends a new input line to the history -list, the current history identifier is recorded with it, and when it -is asked to recall a historical input line, it only recalls lines that -are marked with the current identifier. - -.SH DISPLAYING HISTORY - -The history list can be displayed by calling \f3gl_show_history()\f1. - -.sp -.nf - int gl_show_history(GetLine *gl, FILE *fp, - const char *fmt, - int all_groups, - int max_lines); -.fi -.sp - -This displays the current contents of the history list to the stdio -output stream \f3fp\f1. If the \f3max_lines\f1 argument is greater -than or equal to zero, then no more than this number of the most -recent lines will be displayed. If the \f3all_groups\f1 argument is -non-zero, lines from all history groups are displayed. Otherwise just -those of the currently selected history group are displayed. The -format string argument, \f3fmt\f1, determines how the line is -displayed. This can contain arbitrary characters which are written -verbatim, interleaved with any of the following format directives: - -.nf - %D - The date on which the line was originally - entered, formatted like 2001-11-20. - %T - The time of day when the line was entered, - formatted like 23:59:59. - %N - The sequential entry number of the line in - the history buffer. - %G - The number of the history group which the - line belongs to. - %% - A literal % character. - %H - The history line itself. -.fi - -Thus a format string like \f3"%D %T %H\n"\f1 would output something like: - -.nf - 2001-11-20 10:23:34 Hello world -.fi - -Note the inclusion of an explicit newline character in the format -string. - -.SH LOOKING UP HISTORY - -The \f3gl_lookup_history()\f1 function allows the calling application -to look up lines in the history list. - -.sp -.nf - typedef struct { - const char *line; /* The requested historical */ - /* line. */ - unsigned group; /* The history group to which */ - /* the line belongs. */ - time_t timestamp; /* The date and time at which */ - /* the line was originally */ - /* entered. */ - } GlHistoryLine; - - int gl_lookup_history(GetLine *gl, unsigned long id, - GlHistoryLine *hline); -.fi -.sp - -The \f3id\f1 argument indicates which line to look up, where the first -line that was entered in the history list after \f3new_GetLine()\f1 -was called, is denoted by 0, and subsequently entered lines are -denoted with successively higher numbers. Note that the range of lines -currently preserved in the history list can be queried by calling the -\f3gl_range_of_history()\f1 function, described later. If the -requested line is in the history list, the details of the line are -recorded in the variable pointed to by the \f3hline\f1 argument, and -\f31\f1 is returned. Otherwise \f30\f1 is returned, and the variable -pointed to by \f3hline\f1 is left unchanged. -.sp -Beware that the string returned in \f3hline->line\f1 is part of the -history buffer, so it must not be modified by the caller, and will be -recycled on the next call to any function that takes \f3gl\f1 as its -argument. Therefore you should make a private copy of this string if -you need to keep it around. - -.SH MISCELLANEOUS HISTORY CONFIGURATION - -If you wish to change the size of the history buffer that was -originally specified in the call to \f3new_GetLine()\f1, you can do so -with the \f3gl_resize_history()\f1 function. - -.sp -.nf - int gl_resize_history(GetLine *gl, size_t histlen); -.fi -.sp - -The \f3histlen\f1 argument specifies the new size in bytes, and if you -specify this as 0, the buffer will be deleted. -.sp -As mentioned in the discussion of \f3new_GetLine()\f1, the number of -lines that can be stored in the history buffer, depends on the lengths -of the individual lines. For example, a 1000 byte buffer could equally -store 10 lines of average length 100 bytes, or 2 lines of average -length 50 bytes. Although the buffer is never expanded when new lines -are added, a list of pointers into the buffer does get expanded when -needed to accomodate the number of lines currently stored in the -buffer. To place an upper limit on the number of lines in the buffer, -and thus a ceiling on the amount of memory used in this list, you can -call the \f3gl_limit_history()\f1 function. - -.sp -.nf - void gl_limit_history(GetLine *gl, int max_lines); -.fi -.sp - -The \f3max_lines\f1 should either be a positive number \f3>= 0\f1, -specifying an upper limit on the number of lines in the buffer, or be -\f3-1\f1 to cancel any previously specified limit. When a limit is in -effect, only the \f3max_lines\f1 most recently appended lines are kept -in the buffer. Older lines are discarded. -.sp -To discard lines from the history buffer, use the -\f3gl_clear_history()\f1 function. -.sp -.nf - void gl_clear_history(GetLine *gl, int all_groups); -.fi -.sp -The \f3all_groups\f1 argument tells the function whether to delete -just the lines associated with the current history group (see -\f3gl_group_history()\f1), or all historical lines in the buffer. -.sp -The \f3gl_toggle_history()\f1 function allows you to toggle history on -and off without losing the current contents of the history list. - -.sp -.nf - void gl_toggle_history(GetLine *gl, int enable); -.fi -.sp - -Setting the \f3enable\f1 argument to 0 turns off the history -mechanism, and setting it to 1 turns it back on. When history is -turned off, no new lines will be added to the history list, and -history lookup key-bindings will act as though there is nothing in the -history buffer. - -.SH QUERYING HISTORY INFORMATION - -The configured state of the history list can be queried with the -\f3gl_history_state()\f1 function. - -.sp -.nf - typedef struct { - int enabled; /* True if history is enabled */ - unsigned group; /* The current history group */ - int max_lines; /* The current upper limit on the */ - /* number of lines in the history */ - /* list, or -1 if unlimited. */ - } GlHistoryState; - - void gl_state_of_history(GetLine *gl, - GlHistoryState *state); -.fi -.sp -On return, the status information is recorded in the variable pointed -to by the \f3state\f1 argument. -.sp -The \f3gl_range_of_history()\f1 function returns the number and -range of lines in the history list. - -.sp -.nf -typedef struct { - unsigned long oldest; /* The sequential entry number */ - /* of the oldest line in the */ - /* history list. */ - unsigned long newest; /* The sequential entry number */ - /* of the newest line in the */ - /* history list. */ - int nlines; /* The number of lines in the */ - /* history list. */ -} GlHistoryRange; - -void gl_range_of_history(GetLine *gl, GlHistoryRange *range); -.fi -.sp -The return values are recorded in the variable pointed to by the -\f3range\f1 argument. If the \f3nlines\f1 member of this structure is -greater than zero, then the \f3oldest\f1 and \f3newest\f1 members -report the range of lines in the list, and \f3newest=oldest+nlines-1\f1. -Otherwise they are both zero. -.sp -The \f3gl_size_of_history()\f1 function returns the total size of the -history buffer and the amount of the buffer that is currently -occupied. -.sp -.nf - typedef struct { - size_t size; /* The size of the history buffer */ - /* (bytes). */ - size_t used; /* The number of bytes of the */ - /* history buffer that are */ - /* currently occupied. */ - } GlHistorySize; - - void gl_size_of_history(GetLine *gl, GlHistorySize *size); -.fi -.sp -On return, the size information is recorded in the variable pointed to -by the \f3size\f1 argument. - -.SH CHANGING TERMINALS - -The \f3new_GetLine()\f1 constructor function assumes that input is to -be read from \f3stdin\f1, and output written to \f3stdout\f1. The -following function allows you to switch to different input and output -streams. -.sp -.nf - int gl_change_terminal(GetLine *gl, FILE *input_fp, - FILE *output_fp, const char *term); -.fi -.sp -The \f3gl\f1 argument is the object that was returned by -\f3new_GetLine()\f1. The \f3input_fp\f1 argument specifies the stream -to read from, and \f3output_fp\f1 specifies the stream to be written -to. Only if both of these refer to a terminal, will interactive -terminal input be enabled. Otherwise \f3gl_get_line()\f1 will simply -call \f3fgets()\f1 to read command input. If both streams refer to a -terminal, then they must refer to the same terminal, and the type of -this terminal must be specified via the \f3term\f1 argument. The value -of the \f3term\f1 argument is looked up in the terminal information -database (terminfo or termcap), in order to determine which special -control sequences are needed to control various aspects of the -terminal. \f3new_GetLine()\f1 for example, passes the return value of -\f3getenv("TERM")\f1 in this argument. Note that if one or both of -\f3input_fp\f1 and \f3output_fp\f1 don't refer to a terminal, then it -is legal to pass \f3NULL\f1 instead of a terminal type. -.sp -Note that if you want to pass file descriptors to -\f3gl_change_terminal()\f1, you can do this by creating stdio stream -wrappers using the POSIX \f3fdopen()\f1 function. - -.SH EXTERNAL EVENT HANDLING - -While \f3gl_get_line()\f1 is waiting for keyboard input from the user, -you can ask it to also watch for activity on arbitrary file -descriptors, such as network sockets, pipes etc, and have it call -functions of your choosing when activity is seen. This works on any -system that has the \f3select()\f1 system call, which is most, if not -all flavors of unix. Registering a file descriptor to be watched by -\f3gl_get_line()\f1 involves calling the \f3gl_watch_fd()\f1 function. - -.sp -.nf - int gl_watch_fd(GetLine *gl, int fd, GlFdEvent event, - GlFdEventFn *callback, void *data); -.fi -.sp - -If this returns non-zero, then it means that either your arguments are -invalid, or that this facility isn't supported on the host system. -.sp -The \f3fd\f1 argument is the file descriptor to be watched. The -\f3event\f1 argument specifies what type of activity is of interest, -chosen from the following enumerated values: - -.sp -.nf - GLFD_READ - Watch for the arrival of data to be read. - GLFD_WRITE - Watch for the ability to write to the file - descriptor without blocking. - GLFD_URGENT - Watch for the arrival of urgent - out-of-band data on the file descriptor. -.fi -.sp - -The \f3callback\f1 argument is the function to call when the selected -activity is seen. It should be defined with the following macro, which -is defined in libtecla.h. - -.sp -.nf - #define GL_FD_EVENT_FN(fn) GlFdStatus (fn)(GetLine *gl, \\ - void *data, int fd, \\ - GlFdEvent event) -.fi -.sp -The \f3data\f1 argument of the \f3gl_watch_fd()\f1 function is passed -to the callback function for its own use, and can point to anything -you like, including \f3NULL\f1. The file descriptor and the event -argument are also passed to the callback function, and this -potentially allows the same callback function to be registered to more -than one type of event and/or more than one file descriptor. The -return value of the callback function should be one of the following -values. - -.sp -.nf - GLFD_ABORT - Tell gl_get_line() to abort with an - error (errno won't be set, so set it - appropriately yourself if you need it). - GLFD_REFRESH - Redraw the input line then continue - waiting for input. Return this if - your callback wrote to the terminal. - GLFD_CONTINUE - Continue to wait for input, without - redrawing the line. -.fi -.sp -Note that before calling the callback, \f3gl_get_line()\f1 blocks most -signals, and leaves its own signal handlers installed, so if you need -to catch a particular signal you will need to both temporarily install -your own signal handler, and unblock the signal. Be sure to re-block -the signal (if it was originally blocked) and reinstate the original -signal handler, if any, before returning. -.sp -Your callback shouldn't try to read from the terminal, which is left -in raw mode as far as input is concerned. You can however write to the -terminal as usual, since features like conversion of newline to -carriage-return/linefeed are re-enabled while the callback is -running. If your callback function does write to the terminal, be sure -to output a newline first, and when your callback returns, tell -\f3gl_get_line()\f1 that the input line needs to be redrawn, by -returning the \f3GLFD_REFRESH\f1 status code. -.sp -To remove a callback function that you previously registered for a -given file descriptor and event, simply call \f3gl_watch_fd()\f1 with -the same file descriptor and \f3event\f1 arguments, but with a -\f3callback\f1 argument of \f30\f1. The \f3data\f1 argument is ignored -in this case. - -.SH SIGNAL HANDLING DEFAULTS - -By default, the \f3gl_get_line()\f1 function intercepts a -number of signals. This is particularly important for -signals which would by default terminate the process, since -the terminal needs to be restored to a usable state before -this happens. In this section, the signals that are trapped -by default, and how gl_get_line() responds to them, is -described. Changing these defaults is the topic of the -following section. -.sp -When the following subset of signals are caught, \f3gl_get_line()\f1 -first restores the terminal settings and signal handling to how they -were before \f3gl_get_line()\f1 was called, resends the signal, to -allow the calling application's signal handlers to handle it, then if -the process still exists, \f3gl_get_line()\f1 returns \f3NULL\f1 and -sets \f3errno\f1 as specified below. - -.sp -.nf - SIGINT - This signal is generated both by the keyboard - interrupt key (usually ^C), and the keyboard - break key. - - errno=EINTR - - SIGHUP - This signal is generated when the controlling - terminal exits. - - errno=ENOTTY - - SIGPIPE - This signal is generated when a program attempts - to write to a pipe who's remote end isn't being - read by any process. This can happen for example - if you have called \f3gl_change_terminal()\f1 to - redirect output to a pipe hidden under a pseudo - terminal. - - errno=EPIPE - - SIGQUIT - This signal is generated by the keyboard quit - key (usually ^\\). - - errno=EINTR - - SIGABRT - This signal is generated by the standard C, - abort() function. By default it both - terminates the process and generates a core - dump. - - errno=EINTR - - SIGTERM - This is the default signal that the UN*X - kill command sends to processes. - - errno=EINTR -.fi -.sp -Note that in the case of all of the above signals, POSIX mandates that -by default the process is terminated, with the addition of a core dump -in the case of the \f3SIGQUIT\f1 signal. In other words, if the -calling application doesn't override the default handler by supplying -its own signal handler, receipt of the corresponding signal will -terminate the application before \f3gl_get_line()\f1 returns. -.sp -If gl_get_line() aborts with errno set to EINTR, you can find out what -signal caused it to abort, by calling the following function. -.sp -.nf - int gl_last_signal(const GetLine *gl); -.fi -.sp -This returns the numeric code (eg. \f3SIGINT\f1) of the last signal -that was received during the most recent call to \f3gl_get_line()\f1, -or \f3-1\f1 if no signals were received. -.sp -On systems that support it, when a SIGWINCH (window change) signal is -received, \f3gl_get_line()\f1 queries the terminal to find out its new -size, redraws the current input line to accomodate the new size, then -returns to waiting for keyboard input from the user. Unlike other -signals, this signal isn't resent to the application. -.sp -Finally, the following signals cause \f3gl_get_line()\f1 to first -restore the terminal and signal environment to that which prevailed -before \f3gl_get_line()\f1 was called, then resend the signal to the -application. If the process still exists after the signal has been -delivered, then \f3gl_get_line()\f1 then re-establishes its own signal -handlers, switches the terminal back to raw mode, redisplays the input -line, and goes back to awaiting terminal input from the user. -.sp -.nf - SIGCONT - This signal is generated when a suspended - process is resumed. - - SIGPWR - This signal is generated when a power failure - occurs (presumably when the system is on a - UPS). - - SIGALRM - This signal is generated when a timer - expires. - - SIGUSR1 - An application specific signal. - - SIGUSR2 - Another application specific signal. - - SIGVTALRM - This signal is generated when a virtual - timer expires (see man setitimer(2)). - - SIGXCPU - This signal is generated when a process - exceeds its soft CPU time limit. - - SIGTSTP - This signal is generated by the terminal - suspend key, which is usually ^Z, or the - delayed terminal suspend key, which is - usually ^Y. - - SIGTTIN - This signal is generated if the program - attempts to read from the terminal while the - program is running in the background. - - SIGTTOU - This signal is generated if the program - attempts to write to the terminal while the - program is running in the background. -.fi -.sp - -Obviously not all of the above signals are supported on all systems, -so code to support them is conditionally compiled into the tecla -library. -.sp -Note that if \f3SIGKILL\f1, which by definition can't be caught, or -any of the hardware generated exception signals, such as -\f3SIGSEGV\f1, \f3SIGBUS\f1 and \f3SIGFPE\f1, are received and -unhandled while \f3gl_get_line()\f1 has the terminal in raw mode, the -program will be terminated without the terminal having been restored -to a usable state. In practice, job-control shells usually reset the -terminal settings when a process relinquishes the controlling -terminal, so this is only a problem with older shells. - -.SH CUSTOMIZED SIGNAL HANDLING - -The previous section listed the signals that -\f3gl_get_line()\f1 traps by default, and described how it -responds to them. This section describes how to both add and -remove signals from the list of trapped signals, and how to -specify how \f3gl_get_line()\f1 should respond to a given -signal. -.sp -If you don't need \f3gl_get_line()\f1 to do anything in -response to a signal that it normally traps, you can tell to -\f3gl_get_line()\f1 to ignore that signal by calling -\f3gl_ignore_signal()\f1. -.sp -.nf - int gl_ignore_signal(GetLine *gl, int signo); -.fi -.sp -The \f3signo\f1 argument is the number of the signal -(eg. \f3SIGINT\f1) that you want to have ignored. If the -specified signal isn't currently one of those being trapped, -this function does nothing. -.sp -The \f3gl_trap_signal()\f1 function allows you to either add -a new signal to the list that \f3gl_get_line()\f1 traps, or -modify how it responds to a signal that it already traps. -.sp -.nf - int gl_trap_signal(GetLine *gl, int signo, unsigned flags, - GlAfterSignal after, int errno_value); -.fi -.sp -The \f3signo\f1 argument is the number of the signal that -you wish to have trapped. The \f3flags\f1 argument is a set -of flags which determine the environment in which the -application's signal handler is invoked, the \f3after\f1 -argument tells \f3gl_get_line()\f1 what to do after the -application's signal handler returns, and \f3errno_value\f1 -tells \f3gl_get_line()\f1 what to set \f3errno\f1 to if told -to abort. -.sp -The \f3flags\f1 argument is a bitwise OR of zero or more of -the following enumerators: -.sp -.nf - GLS_RESTORE_SIG - Restore the caller's signal - environment while handling the - signal. - - GLS_RESTORE_TTY - Restore the caller's terminal settings - while handling the signal. - - GLS_RESTORE_LINE - Move the cursor to the start of the - line following the input line before - invoking the application's signal - handler. - - GLS_REDRAW_LINE - Redraw the input line when the - application's signal handler returns. - - GLS_UNBLOCK_SIG - Normally, if the calling program has - a signal blocked (man sigprocmask), - gl_get_line() does not trap that - signal. This flag tells gl_get_line() - to trap the signal and unblock it for - the duration of the call to - gl_get_line(). - - GLS_DONT_FORWARD - If this flag is included, the signal - will not be forwarded to the signal - handler of the calling program. -.fi -.sp -Two commonly useful flag combinations are also enumerated as -follows: -.sp -.nf - GLS_RESTORE_ENV = GLS_RESTORE_SIG | GLS_RESTORE_TTY | - GLS_REDRAW_LINE - - GLS_SUSPEND_INPUT = GLS_RESTORE_ENV | GLS_RESTORE_LINE -.fi -.sp - -If your signal handler, or the default system signal -handler for this signal, if you haven't overriden it, never -either writes to the terminal, nor suspends or terminates -the calling program, then you can safely set the \f3flags\f1 -argument to \f30\f1. -.sp -If your signal handler always writes to the terminal, reads -from it, or suspends or terminates the program, you should -specify the \f3flags\f1 argument as \f3GL_SUSPEND_INPUT\f1, -so that: -.sp -.nf -1. The cursor doesn't get left in the middle of the input - line. -2. So that the user can type in input and have it echoed. -3. So that you don't need to end each output line with - \f3\\r\\n\f1, instead of just \f3\\n\f1. -.fi -.sp -The \f3GL_RESTORE_ENV\f1 combination is the same as -\f3GL_SUSPEND_INPUT\f1, except that it doesn't move the -cursor, and if your signal handler doesn't read or write -anything to the terminal, the user won't see any visible -indication that a signal was caught. This can be useful if -you have a signal handler that only occasionally writes to -the terminal, where using \f3GL_SUSPEND_LINE\f1 would cause -the input line to be unnecessarily duplicated when nothing -had been written to the terminal. Such a signal handler, -when it does write to the terminal, should be sure to start -a new line at the start of its first write, by writing a -'\\n' character, and should be sure to leave the cursor on a -new line before returning. If the signal arrives while the -user is entering a line that only occupies a signal terminal -line, or if the cursor is on the last terminal line of a -longer input line, this will have the same effect as -\f3GL_SUSPEND_INPUT\f1. Otherwise it will start writing on a -line that already contains part of the displayed input line. -This doesn't do any harm, but it looks a bit ugly, which is -why the \f3GL_SUSPEND_INPUT\f1 combination is better if you -know that you are always going to be writting to the -terminal. -.sp -The \f3after\f1 argument, which determines what -\f3gl_get_line()\f1 does after the application's signal -handler returns (if it returns), can take any one of the -following values: -.sp -.nf - GLS_RETURN - Return the completed input line, just as - though the user had pressed the return - key. - - GLS_ABORT - Cause gl_get_line() to return \f3NULL\f1. - - GLS_CONTINUE - Resume command line editing. -.fi -.sp -The \f3errno_value\f1 argument is intended to be combined -with the \f3GLS_ABORT\f1 option, telling \f3gl_get_line()\f1 -what to set the standard \f3errno\f1 variable to before -returning \f3NULL\f1 to the calling program. It can also, -however, be used with the \f3GL_RETURN\f1 option, in case -you wish to have a way to distinguish between an input line -that was entered using the return key, and one that was -entered by the receipt of a signal. - -.SH THE TERMINAL SIZE - -On most systems the combination of the \f3TIOCGWINSZ\f1 ioctl and the -\f3SIGWINCH\f1 signal is used to maintain an accurate idea of the -terminal size. The terminal size is newly queried every time that -\f3gl_get_line()\f1 is called and whenever a \f3SIGWINCH\f1 signal is -received. -.sp -On the few systems where this mechanism isn't available, at -startup \f3new_GetLine()\f1 first looks for the \f3LINES\f1 -and \f3COLUMNS\f1 environment variables. If these aren't -found, or they contain unusable values, then if a terminal -information database like terminfo or termcap is available, -the default size of the terminal is looked up in this -database. If this too fails to provide the terminal size, a -default size of 80 columns by 24 lines is used. If this -default isn't appropriate for your system, -\f3gl_terminal_size()\f1 can be used to supply a different -fallback. -.sp -The \f3gl_terminal_size()\f1 function allows you to query -the current size of the terminal, and install an alternate -fallback size for cases where the size isn't available. -Beware that the terminal size won't be available if reading -from a pipe or a file, so the default values can be -important even on systems that do support ways of finding -out the terminal size. -.sp -.nf - typedef struct { - int nline; /* The terminal has nline lines */ - int ncolumn; /* The terminal has ncolumn columns */ - } GlTerminalSize; - - GlTerminalSize gl_terminal_size(GetLine *gl, - int def_ncolumn, - int def_nline); -.fi -.sp -This function first updates \f3gl_get_line()\f1's idea of -the terminal size, then records its findings in the return -value. -.sp -The \f3def_ncolumn\f1 and \f3def_nline\f1 specify the -default number of terminal columns and lines to use if the -terminal size can't be determined. - -.SH HIDING WHAT YOU TYPE - -When entering sensitive information, such as passwords, it is best not -to have the text that you are entering echoed on the terminal. -Furthermore, such text should not be recorded in the history list, -since somebody finding your terminal unattended could then recall it, -or somebody snooping through your directories could see it in your -history file. With this in mind, the \f3gl_echo_mode()\f1 -function allows you to toggle on and off the display and archival of -any text that is subsequently entered in calls to \f3gl_get_line()\f1. - -.sp -.nf - int gl_echo_mode(GetLine *gl, int enable); -.fi -.sp - -The \f3enable\f1 argument specifies whether entered text -should be visible or not. If it is \f30\f1, then -subsequently entered lines will not be visible on the -terminal, and will not be recorded in the history list. If -it is \f31\f1, then subsequent input lines will be displayed -as they are entered, and provided that history hasn't been -turned off via a call to \f3gl_toggle_history()\f1, then -they will also be archived in the history list. Finally, if -the \f3enable\f1 argument is \f3-1\f1, then the echoing mode -is left unchanged, which allows you to non-destructively -query the current setting via the return value. In all -cases, the return value of the function is \f30\f1 if -echoing was disabled before the function was called, and -\f31\f1 if it was enabled. -.sp -When echoing is turned off, note that although tab -completion will invisibly complete your prefix as far as -possible, ambiguous completions will not be displayed. - -.SH CALLBACK FUNCTION FACILITIES - -Unless otherwise stated, callback functions, such as tab -completion callbacks and event callbacks should not call any -functions in this module. The following functions, however, -are designed specifically to be used by callback functions. -.sp -Calling the \f3gl_replace_prompt()\f1 function from a -callback tells \f3gl_get_line() to display a different -prompt when the callback returns. It has no effect if called -when \f3gl_get_line()\f1 is not being called. -.sp -.nf - void gl_replace_prompt(GetLine *gl, const char *prompt); -.fi -.sp - -.SH INTERNATIONAL CHARACTER SETS - -Since libtecla version 1.4.0, \f3gl_get_line()\f1 has been 8-bit -clean. This means that all 8-bit characters that are printable in the -user's current locale are now displayed verbatim and included in the -returned input line. Assuming that the calling program correctly -contains a call like the following, -.sp -.nf - setlocale(LC_CTYPE, ""); -.fi -.sp -then the current locale is determined by the first of the environment -variables \f3LC_CTYPE\f1, \f3LC_ALL\f1, and \f3LANG\f1, that is found -to contain a valid locale name. If none of these variables are -defined, or the program neglects to call setlocale, then the default -\f3C\f1 locale is used, which is US 7-bit ASCII. On most unix-like -platforms, you can get a list of valid locales by typing the command: -.sp -.nf - locale -a -.fi -.sp -at the shell prompt. -.sp -.SS "Meta keys and locales" - -Beware that in most locales other than the default C locale, meta -characters become printable, and they are then no longer considered to -match \f3M-c\f1 style key bindings. This allows international -characters to be entered with the compose key without unexpectedly -triggering meta key bindings. You can still invoke meta bindings, -since there are actually two ways to do this. For example the binding -\f3M-c\f1 can also be invoked by pressing the escape key momentarily, -then pressing the \f3c\f1 key, and this will work regardless of -locale. Moreover, many modern terminal emulators, such as gnome's -gnome-terminal's and KDE's konsole terminals, already generate escape -pairs like this when you use the meta key, rather than a real meta -character, and other emulators usually have a way to request this -behavior, so you can continue to use the meta key on most systems. -.sp -For example, although xterm terminal emulators generate real 8-bit -meta characters by default when you use the meta key, they can be -configured to output the equivalent escape pair by setting their -\f3EightBitInput\f1 X resource to \f3False\f1. You can either do this -by placing a line like the following in your \f3~/.Xdefaults\f1 file, -.sp -.nf - XTerm*EightBitInput: False -.sp -.fi -or by starting an xterm with an \f3-xrm '*EightBitInput: False'\f1 -command-line argument. In recent versions of xterm you can toggle this -feature on and off with the \f3"Meta Sends Escape"\f1 option in the -menu that is displayed when you press the left mouse button and the -control key within an xterm window. In CDE, dtterms can be similarly -coerced to generate escape pairs in place of meta characters, by -setting the \f3Dtterm*KshMode\f1 resource to \f3True\f1. -.sp -.SS "Entering international characters" - -If you don't have a keyboard that generates all of the international -characters that you need, there is usually a compose key that will -allow you to enter special characters, or a way to create one. For -example, under X windows on unix-like systems, if your keyboard -doesn't have a compose key, you can designate a redundant key to serve -this purpose with the xmodmap command. For example, on many PC -keyboards there is a microsoft-windows key, which is otherwise useless -under Linux. On my PC the \f3xev\f1 program reports that pressing this -key generates keycode 115, so to turn this key into a compose key, I -do the following: -.sp -.nf - xmodmap -e 'keycode 115 = Multi_key' -.fi -.sp -I can then enter an i with a umlaut over it by typing this key, -followed by \f3"\f1, followed by i. - -.SH THREAD SAFETY - -In a multi-threaded program, you should use the libtecla_r.a version -of the library. This uses reentrant versions of system functions, -where available. Unfortunately neither terminfo nor termcap were -designed to be reentrant, so you can't safely use the functions of the -getline module in multiple threads (you can use the separate -file-expansion and word-completion modules in multiple threads, see -the corresponding man pages for details). However due to the use of -POSIX reentrant functions for looking up home directories etc, it is -safe to use this module from a single thread of a multi-threaded -program, provided that your other threads don't use any termcap or -terminfo functions. - -.SH FILES -.nf -libtecla.a - The tecla library -libtecla.h - The tecla header file. -~/.teclarc - The personal tecla customization file. -.fi - -.SH SEE ALSO -libtecla(3), ef_expand_file(3), cpl_complete_word(3), pca_lookup_file(3) - -.SH AUTHOR -Martin Shepherd (mcs@astro.caltech.edu) diff --git a/libtecla-1.4.1/man3/gl_group_history.3 b/libtecla-1.4.1/man3/gl_group_history.3 deleted file mode 100644 index 6bd3d1f..0000000 --- a/libtecla-1.4.1/man3/gl_group_history.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/gl_get_line.3 diff --git a/libtecla-1.4.1/man3/gl_ignore_signal.3 b/libtecla-1.4.1/man3/gl_ignore_signal.3 deleted file mode 100644 index 6bd3d1f..0000000 --- a/libtecla-1.4.1/man3/gl_ignore_signal.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/gl_get_line.3 diff --git a/libtecla-1.4.1/man3/gl_last_signal.3 b/libtecla-1.4.1/man3/gl_last_signal.3 deleted file mode 100644 index 6bd3d1f..0000000 --- a/libtecla-1.4.1/man3/gl_last_signal.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/gl_get_line.3 diff --git a/libtecla-1.4.1/man3/gl_limit_history.3 b/libtecla-1.4.1/man3/gl_limit_history.3 deleted file mode 100644 index 6bd3d1f..0000000 --- a/libtecla-1.4.1/man3/gl_limit_history.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/gl_get_line.3 diff --git a/libtecla-1.4.1/man3/gl_load_history.3 b/libtecla-1.4.1/man3/gl_load_history.3 deleted file mode 100644 index 6bd3d1f..0000000 --- a/libtecla-1.4.1/man3/gl_load_history.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/gl_get_line.3 diff --git a/libtecla-1.4.1/man3/gl_lookup_history.3 b/libtecla-1.4.1/man3/gl_lookup_history.3 deleted file mode 100644 index 6bd3d1f..0000000 --- a/libtecla-1.4.1/man3/gl_lookup_history.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/gl_get_line.3 diff --git a/libtecla-1.4.1/man3/gl_prompt_style.3 b/libtecla-1.4.1/man3/gl_prompt_style.3 deleted file mode 100644 index 6bd3d1f..0000000 --- a/libtecla-1.4.1/man3/gl_prompt_style.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/gl_get_line.3 diff --git a/libtecla-1.4.1/man3/gl_range_of_history.3 b/libtecla-1.4.1/man3/gl_range_of_history.3 deleted file mode 100644 index 6bd3d1f..0000000 --- a/libtecla-1.4.1/man3/gl_range_of_history.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/gl_get_line.3 diff --git a/libtecla-1.4.1/man3/gl_resize_history.3 b/libtecla-1.4.1/man3/gl_resize_history.3 deleted file mode 100644 index 6bd3d1f..0000000 --- a/libtecla-1.4.1/man3/gl_resize_history.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/gl_get_line.3 diff --git a/libtecla-1.4.1/man3/gl_save_history.3 b/libtecla-1.4.1/man3/gl_save_history.3 deleted file mode 100644 index 6bd3d1f..0000000 --- a/libtecla-1.4.1/man3/gl_save_history.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/gl_get_line.3 diff --git a/libtecla-1.4.1/man3/gl_show_history.3 b/libtecla-1.4.1/man3/gl_show_history.3 deleted file mode 100644 index 6bd3d1f..0000000 --- a/libtecla-1.4.1/man3/gl_show_history.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/gl_get_line.3 diff --git a/libtecla-1.4.1/man3/gl_size_of_history.3 b/libtecla-1.4.1/man3/gl_size_of_history.3 deleted file mode 100644 index 6bd3d1f..0000000 --- a/libtecla-1.4.1/man3/gl_size_of_history.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/gl_get_line.3 diff --git a/libtecla-1.4.1/man3/gl_state_of_history.3 b/libtecla-1.4.1/man3/gl_state_of_history.3 deleted file mode 100644 index 6bd3d1f..0000000 --- a/libtecla-1.4.1/man3/gl_state_of_history.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/gl_get_line.3 diff --git a/libtecla-1.4.1/man3/gl_terminal_size.3 b/libtecla-1.4.1/man3/gl_terminal_size.3 deleted file mode 100644 index 6bd3d1f..0000000 --- a/libtecla-1.4.1/man3/gl_terminal_size.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/gl_get_line.3 diff --git a/libtecla-1.4.1/man3/gl_toggle_history.3 b/libtecla-1.4.1/man3/gl_toggle_history.3 deleted file mode 100644 index 6bd3d1f..0000000 --- a/libtecla-1.4.1/man3/gl_toggle_history.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/gl_get_line.3 diff --git a/libtecla-1.4.1/man3/gl_trap_signal.3 b/libtecla-1.4.1/man3/gl_trap_signal.3 deleted file mode 100644 index 6bd3d1f..0000000 --- a/libtecla-1.4.1/man3/gl_trap_signal.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/gl_get_line.3 diff --git a/libtecla-1.4.1/man3/gl_watch_fd.3 b/libtecla-1.4.1/man3/gl_watch_fd.3 deleted file mode 100644 index 6bd3d1f..0000000 --- a/libtecla-1.4.1/man3/gl_watch_fd.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/gl_get_line.3 diff --git a/libtecla-1.4.1/man3/libtecla.3 b/libtecla-1.4.1/man3/libtecla.3 deleted file mode 100644 index 611eb57..0000000 --- a/libtecla-1.4.1/man3/libtecla.3 +++ /dev/null @@ -1,160 +0,0 @@ -.\" Copyright (C) 2000, 2001 by Martin C. Shepherd -.\" -.\" All rights reserved. -.\" -.\" Permission is hereby granted, free of charge, to any person obtaining a -.\" copy of this software and associated documentation files (the -.\" "Software"), to deal in the Software without restriction, including -.\" without limitation the rights to use, copy, modify, merge, publish, -.\" distribute, and/or sell copies of the Software, and to permit persons -.\" to whom the Software is furnished to do so, provided that the above -.\" copyright notice(s) and this permission notice appear in all copies of -.\" the Software and that both the above copyright notice(s) and this -.\" permission notice appear in supporting documentation. -.\" -.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -.\" OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -.\" HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL -.\" INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING -.\" FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, -.\" NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION -.\" WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -.\" -.\" Except as contained in this notice, the name of a copyright holder -.\" shall not be used in advertising or otherwise to promote the sale, use -.\" or other dealings in this Software without prior written authorization -.\" of the copyright holder. -.TH libtecla 3 -.SH NAME -libtecla - An interactive command-line input library. -.SH SYNOPSIS -.nf -gcc ... -ltecla -lcurses -.fi - -.SH DESCRIPTION - -The \f3tecla\f1 library provides programs with interactive command -line editing facilities, similar to those of the unix \f3tcsh\f1 -shell. In addition to simple command-line editing, it supports recall -of previously entered command lines, TAB completion of file names or -other tokens, and in-line wild-card expansion of filenames. The -internal functions which perform file-name completion and wild-card -expansion are also available externally for optional use by the -calling program. -.sp -The various parts of the library are documented in the following man -pages: - -.nf - gl_get_line(3) - The interactive line-input module. - cpl_complete_word(3) - The word completion module. - ef_expand_file(3) - The filename expansion module. - pca_lookup_file(3) - A directory-list based filename - lookup and completion module. -.fi - -In addition there is one optional application distributed -with the library: - -.nf - enhance(3) - Add command-line editing to third - party applications. -.fi - -.SH THREAD SAFETY - -If the library is compiled with -D_POSIX_C_SOURCE=199506L, reentrant -versions of as many functions as possible are used. This includes -using getpwuid_r() and getpwnam_r() instead of getpwuid() and -getpwnam() when looking up the home directories of specific users in -the password file (for ~user/ expansion), and readdir_r() instead of -readdir() for reading directory entries when doing filename -completion. The reentrant version of the library is usually called -libtecla_r.a instead of libtecla.a, so if only the latter is -available, it probably isn't the correct version to link with -threaded programs. - -Reentrant functions for iterating through the password file aren't -available, so when the library is compiled to be reentrant, TAB -completion of incomplete usernames in \f3~username/\f1 expressions is -disabled. This doesn't disable expansion of complete \f3~username\f1 -expressions, which can be done reentrantly, or expansion of the parts -of filenames that follow them, so this doesn't remove much -functionality. - -The terminfo functions setupterm(), tigetstr(), tigetnum() and tputs() -also aren't reentrant, but very few programs will want to interact -with multiple terminals, so this shouldn't prevent this library from -being used in threaded programs. - -.SH LIBRARY VERSION NUMBER - -The version number of the library can be queried using the following -function. -.sp -.nf - void libtecla_version(int *major, int *minor, int *micro); -.fi -.sp - -On return, this function records the three components of the libtecla -version number in \f3*major\f1, \f3*minor\f1, \f3*micro\f1. The formal -meaning of the three components is as follows. - -.sp -.nf - major - Incrementing this number implies that a change has - been made to the library's public interface, which - makes it binary incompatible with programs that - were linked with previous shared versions of the - tecla library. - - minor - This number is incremented by one whenever - additional functionality, such as new functions or - modules, are added to the library. - - micro - This is incremented whenever modifications to the - library are made which make no changes to the - public interface, but which fix bugs and/or improve - the behind-the-scenes implementation. -.fi -.sp - -.SH TRIVIA - -In Spanish, a "tecla" is the key of a keyboard. Since this library -centers on keyboard input, and given that I wrote much of the library -while working in Chile, this seemed like a suitable name. - -.SH FILES -.nf -libtecla.a - The tecla library. -libtecla.h - The tecla header file. -~/.teclarc - The tecla personal customization file. -.fi - -.SH SEE ALSO -gl_get_line(3), ef_expand_file(3), cpl_complete_word(3), -pca_lookup_file(3), enhance(3) - -.SH AUTHOR -Martin Shepherd (mcs@astro.caltech.edu) - -.SH ACKNOWLEDGMENTS - -.nf -Markus Gyger - Lots of assistance, including help with - shared libraries, configuration information, - particularly for Solaris; modifications to - support C++ compilers, improvements for ksh - users, faster cursor motion, output - buffering, and changes to make gl_get_line() - 8-bit clean. -Mike MacFaden - Suggestions, feedback and testing that led - to many of the major new functions that were - added in version 1.4.0. -Tim Eliseo - Many vi-mode bindings and fixes. -.fi diff --git a/libtecla-1.4.1/man3/libtecla_version.3 b/libtecla-1.4.1/man3/libtecla_version.3 deleted file mode 100644 index 2c9c2c7..0000000 --- a/libtecla-1.4.1/man3/libtecla_version.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/libtecla.3 diff --git a/libtecla-1.4.1/man3/new_CplFileConf.3 b/libtecla-1.4.1/man3/new_CplFileConf.3 deleted file mode 100644 index 36c83a3..0000000 --- a/libtecla-1.4.1/man3/new_CplFileConf.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/cpl_complete_word.3 diff --git a/libtecla-1.4.1/man3/new_ExpandFile.3 b/libtecla-1.4.1/man3/new_ExpandFile.3 deleted file mode 100644 index f4299df..0000000 --- a/libtecla-1.4.1/man3/new_ExpandFile.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/ef_expand_file.3 diff --git a/libtecla-1.4.1/man3/new_GetLine.3 b/libtecla-1.4.1/man3/new_GetLine.3 deleted file mode 100644 index 6bd3d1f..0000000 --- a/libtecla-1.4.1/man3/new_GetLine.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/gl_get_line.3 diff --git a/libtecla-1.4.1/man3/new_PathCache.3 b/libtecla-1.4.1/man3/new_PathCache.3 deleted file mode 100644 index e5a136e..0000000 --- a/libtecla-1.4.1/man3/new_PathCache.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/pca_lookup_file.3 diff --git a/libtecla-1.4.1/man3/new_PcaPathConf.3 b/libtecla-1.4.1/man3/new_PcaPathConf.3 deleted file mode 100644 index e5a136e..0000000 --- a/libtecla-1.4.1/man3/new_PcaPathConf.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/pca_lookup_file.3 diff --git a/libtecla-1.4.1/man3/new_WordCompletion.3 b/libtecla-1.4.1/man3/new_WordCompletion.3 deleted file mode 100644 index 36c83a3..0000000 --- a/libtecla-1.4.1/man3/new_WordCompletion.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/cpl_complete_word.3 diff --git a/libtecla-1.4.1/man3/pca_last_error.3 b/libtecla-1.4.1/man3/pca_last_error.3 deleted file mode 100644 index e5a136e..0000000 --- a/libtecla-1.4.1/man3/pca_last_error.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/pca_lookup_file.3 diff --git a/libtecla-1.4.1/man3/pca_lookup_file.3 b/libtecla-1.4.1/man3/pca_lookup_file.3 deleted file mode 100644 index 131394a..0000000 --- a/libtecla-1.4.1/man3/pca_lookup_file.3 +++ /dev/null @@ -1,361 +0,0 @@ -.\" Copyright (C) 2001 by Martin C. Shepherd -.\" -.\" All rights reserved. -.\" -.\" Permission is hereby granted, free of charge, to any person obtaining a -.\" copy of this software and associated documentation files (the -.\" "Software"), to deal in the Software without restriction, including -.\" without limitation the rights to use, copy, modify, merge, publish, -.\" distribute, and/or sell copies of the Software, and to permit persons -.\" to whom the Software is furnished to do so, provided that the above -.\" copyright notice(s) and this permission notice appear in all copies of -.\" the Software and that both the above copyright notice(s) and this -.\" permission notice appear in supporting documentation. -.\" -.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -.\" OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -.\" HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL -.\" INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING -.\" FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, -.\" NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION -.\" WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -.\" -.\" Except as contained in this notice, the name of a copyright holder -.\" shall not be used in advertising or otherwise to promote the sale, use -.\" or other dealings in this Software without prior written authorization -.\" of the copyright holder. -.TH pca_lookup_file 3 -.SH NAME -pca_lookup_file, del_PathCache, del_PcaPathConf, new_PathCache, new_PcaPathConf, pca_last_error, pca_path_completions, pca_scan_path, pca_set_check_fn, ppc_file_start, ppc_literal_escapes \- lookup a file in a list of directories -.SH SYNOPSIS -.nf -#include <libtecla.h> - -PathCache *new_PathCache(void); - -PathCache *del_PathCache(PathCache *pc); - -int pca_scan_path(PathCache *pc, const char *path); - -void pca_set_check_fn(PathCache *pc, CplCheckFn *check_fn, - void *data); - -char *pca_lookup_file(PathCache *pc, const char *name, - int name_len, int literal); - -const char *pca_last_error(PathCache *pc); - -CPL_MATCH_FN(pca_path_completions); - -.fi - -.SH DESCRIPTION - -The \f3PathCache\f1 object is part of the tecla library (see the -libtecla(3) man page). -.sp -\f3PathCache\f1 objects allow an application to search for files in -any colon separated list of directories, such as the unix execution -PATH environment variable. Files in absolute directories are cached in -a \f3PathCache\f1 object, whereas relative directories are scanned as -needed. Using a \f3PathCache\f1 object, you can look up the full -pathname of a simple filename, or you can obtain a list of the -possible completions of a given filename prefix. By default all files -in the list of directories are targets for lookup and completion, but -a versatile mechanism is provided for only selecting specific types of -files. The obvious application of this facility is to provide -Tab-completion and lookup of executable commands in the unix PATH, so -an optional callback which rejects all but executable files, is -provided. -.sp -.SH AN EXAMPLE - -Under UNIX, the following example program looks up and displays the -full pathnames of each of the command names on the command line. -.sp -.nf - #include <stdio.h> - #include <stdlib.h> - #include <libtecla.h> - - int main(int argc, char *argv[]) - { - int i; - /* - * Create a cache for executable files. - */ - PathCache *pc = new_PathCache(); - if(!pc) - exit(1); - /* - * Scan the user's PATH for executables. - */ - if(pca_scan_path(pc, getenv("PATH"))) { - fprintf(stderr, "%s\\n", pca_last_error(pc)); - exit(1); - } - /* - * Arrange to only report executable files. - */ - pca_set_check_fn(pc, cpl_check_exe, NULL); - /* - * Lookup and display the full pathname of each of the - * commands listed on the command line. - */ - for(i=1; i<argc; i++) { - char *cmd = pca_lookup_file(pc, argv[i], -1, 0); - printf("The full pathname of '%s' is %s\\n", argv[i], - cmd ? cmd : "unknown"); - } - pc = del_PathCache(pc); /* Clean up */ - return 0; - } -.fi -.sp -The following is an example of what this does on my laptop under -linux: -.sp -.nf - $ ./example less more blob - The full pathname of 'less' is /usr/bin/less - The full pathname of 'more' is /bin/more - The full pathname of 'blob' is unknown - $ -.fi -.sp -.SH FUNCTION DESCRIPTIONS - -In order to use the facilities of this module, you must first allocate -a \f3PathCache\f1 object by calling the \f3new_PathCache()\f1 -constructor function. -.sp -.nf - PathCache *new_PathCache(void) -.fi -.sp -This function creates the resources needed to cache and lookup files -in a list of directories. It returns \f3NULL\f1 on error. -.sp -.SH POPULATING THE CACHE -Once you have created a cache, it needs to be populated with files. -To do this, call the \f3pca_scan_path()\f1 function. -.sp -.nf - int pca_scan_path(PathCache *pc, const char *path); -.fi -.sp -Whenever this function is called, it discards the current contents of -the cache, then scans the list of directories specified in its -\f3path\f1 argument for files. The \f3path\f1 argument must be a -string containing a colon-separated list of directories, such as -\f3"/usr/bin:/home/mcs/bin:."\f1. This can include directories -specified by absolute pathnames such as \f3"/usr/bin"\f1, as well as -sub-directories specified by relative pathnames such as \f3"."\f1 or -\f3"bin"\f1. Files in the absolute directories are immediately cached -in the specified \f3PathCache\f1 object, whereas sub-directories, -whose identities obviously change whenever the current working -directory is changed, are marked to be scanned on the fly whenever a -file is looked up. -.sp -On success this function return \f30\f1. On error it returns \f31\f1, -and a description of the error can be obtained by calling -\f3pca_last_error(pc)\f1. -.sp -.SH LOOKING UP FILES - -Once the cache has been populated with files, you can look up the full -pathname of a file, simply by specifying its filename to -\f3pca_lookup_file()\f1. -.sp -.nf - char *pca_lookup_file(PathCache *pc, const char *name, - int name_len, int literal); -.fi -.sp -To make it possible to pass this function a filename which is actually -part of a longer string, the \f3name_len\f1 argument can be used to -specify the length of the filename at the start of the \f3name[]\f1 -argument. If you pass \f3-1\f1 for this length, the length of the -string will be determined with \f3strlen()\f1. If the \f3name[]\f1 -string might contain backslashes that escape the special meanings of -spaces and tabs within the filename, give the \f3literal\f1 argument, -the value \f30\f1. Otherwise, if backslashes should be treated as -normal characters, pass \f31\f1 for the value of the \f3literal\f1 -argument. - -.SH FILENAME COMPLETION - -Looking up the potential completions of a filename-prefix in the -filename cache, is achieved by passing the provided -\f3pca_path_completions()\f1 callback function to the -\f3cpl_complete_word()\f1 function (see the \f3cpl_complete_word(3)\f1 -man page). -.sp -.nf - CPL_MATCH_FN(pca_path_completions); -.fi -.sp -This callback requires that its \f3data\f1 argument be a pointer to a -\f3PcaPathConf\f1 object. Configuration objects of this type are -allocated by calling \f3new_PcaPathConf()\f1. -.sp -.nf - PcaPathConf *new_PcaPathConf(PathCache *pc); -.fi -.sp -This function returns an object initialized with default configuration -parameters, which determine how the \f3cpl_path_completions()\f1 -callback function behaves. The functions which allow you to -individually change these parameters are discussed below. -.sp -By default, the \f3pca_path_completions()\f1 callback function -searches backwards for the start of the filename being completed, -looking for the first un-escaped space or the start of the input -line. If you wish to specify a different location, call -\f3ppc_file_start()\f1 with the index at which the filename starts in -the input line. Passing \f3start_index=-1\f1 re-enables the default -behavior. -.sp -.nf - void ppc_file_start(PcaPathConf *ppc, int start_index); -.fi -.sp -By default, when \f3pca_path_completions()\f1 looks at a filename in -the input line, each lone backslash in the input line is interpreted -as being a special character which removes any special significance of -the character which follows it, such as a space which should be taken -as part of the filename rather than delimiting the start of the -filename. These backslashes are thus ignored while looking for -completions, and subsequently added before spaces, tabs and literal -backslashes in the list of completions. To have unescaped backslashes -treated as normal characters, call \f3ppc_literal_escapes()\f1 with a -non-zero value in its \f3literal\f1 argument. -.sp -.nf - void ppc_literal_escapes(PcaPathConf *ppc, int literal); -.fi -.sp -When you have finished with a \f3PcaPathConf\f1 variable, you can pass -it to the \f3del_PcaPathConf()\f1 destructor function to reclaim its -memory. -.sp -.nf - PcaPathConf *del_PcaPathConf(PcaPathConf *ppc); -.fi -.sp - -.SH BEING SELECTIVE -If you are only interested in certain types or files, such as, for -example, executable files, or files whose names end in a particular -suffix, you can arrange for the file completion and lookup functions -to be selective in the filenames that they return. This is done by -registering a callback function with your \f3PathCache\f1 -object. Thereafter, whenever a filename is found which either matches -a filename being looked up, or matches a prefix which is being -completed, your callback function will be called with the full -pathname of the file, plus any application-specific data that you -provide, and if the callback returns \f31\f1 the filename will be -reported as a match, and if it returns \f30\f1, it will be ignored. -Suitable callback functions and their prototypes should be declared -with the following macro. The \f3CplCheckFn\f1 \f3typedef\f1 is also -provided in case you wish to declare pointers to such functions. -.sp -.nf - #define CPL_CHECK_FN(fn) int (fn)(void *data, \\ - const char *pathname) - typedef CPL_CHECK_FN(CplCheckFn); -.fi -.sp -Registering one of these functions involves calling the -\f3pca_set_check_fn()\f1 function. In addition to the callback -function, passed via the \f3check_fn\f1 argument, you can pass a -pointer to anything via the \f3data\f1 argument. This pointer will be -passed on to your callback function, via its own \f3data\f1 argument, -whenever it is called, so this provides a way to pass appplication -specific data to your callback. -.sp -.nf - void pca_set_check_fn(PathCache *pc, CplCheckFn *check_fn, - void *data); -.fi -.sp -Note that these callbacks are passed the full pathname of each -matching file, so the decision about whether a file is of interest can -be based on any property of the file, not just its filename. As an -example, the provided \f3cpl_check_exe()\f1 callback function looks at -the executable permissions of the file and the permissions of its -parent directories, and only returns \f31\f1 if the user has execute -permission to the file. This callback function can thus be used to -lookup or complete command names found in the directories listed in -the user's \f3PATH\f1 environment variable. The example program given -earlier in this man page provides a demonstration of this. -.sp -Beware that if somebody tries to complete an empty string, your -callback will get called once for every file in the cache, which could -number in the thousands. If your callback does anything time -consuming, this could result in an unacceptable delay for the user, so -callbacks should be kept short. -.sp -To improve performance, whenever one of these callbacks is called, the -choice that it makes is cached, and the next time the corresponding -file is looked up, instead of calling the callback again, the cached -record of whether it was accepted or rejected is used. Thus if -somebody tries to complete an empty string, and hits tab a second time -when nothing appears to happen, there will only be one long delay, -since the second pass will operate entirely from the cached -dispositions of the files. These cached dipositions are discarded -whenever \f3pca_scan_path()\f1 is called, and whenever -\f3pca_set_check_fn()\f1 is called with changed callback function or -data arguments. - -.SH ERROR HANDLING - -If \f3pca_scan_path()\f1 reports that an error occurred by returning -\f31\f1, you can obtain a terse description of the error by calling -\f3pca_last_error(pc)\f1. This returns an internal string containing -an error message. -.sp -.nf - const char *pca_last_error(PathCache *pc); -.fi -.sp - -.SH CLEANING UP - -Once you have finished using a \f3PathCache\f1 object, you can reclaim -its resources by passing it to the \f3del_PathCache()\f1 destructor -function. This takes a pointer to one of these objects, and always -returns \f3NULL\f1. -.sp -.nf - PathCache *del_PathCache(PathCache *pc); -.fi -.sp -.SH THREAD SAFETY - -In multi-threaded programs, you should use the \f3libtecla_r.a\f1 -version of the library. This uses POSIX reentrant functions where -available (hence the \f3_r\f1 suffix), and disables features that rely -on non-reentrant system functions. In the case of this module, the -only disabled feature is username completion in \f3~username/\f1 -expressions, in \f3cpl_path_completions()\f1. - -Using the \f3libtecla_r.a\f1 version of the library, it is safe to use -the facilities of this module in multiple threads, provided that each -thread uses a separately allocated \f3PathCache\f1 object. In other -words, if two threads want to do path searching, they should each call -\f3new_PathCache()\f1 to allocate their own caches. - -.SH FILES -.nf -libtecla.a - The tecla library -libtecla.h - The tecla header file. -.fi - -.SH SEE ALSO -libtecla(3), gl_get_line(3), ef_expand_file(3), cpl_complete_word(3) - -.SH AUTHOR -Martin Shepherd (mcs@astro.caltech.edu) diff --git a/libtecla-1.4.1/man3/pca_path_completions.3 b/libtecla-1.4.1/man3/pca_path_completions.3 deleted file mode 100644 index e5a136e..0000000 --- a/libtecla-1.4.1/man3/pca_path_completions.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/pca_lookup_file.3 diff --git a/libtecla-1.4.1/man3/pca_scan_path.3 b/libtecla-1.4.1/man3/pca_scan_path.3 deleted file mode 100644 index e5a136e..0000000 --- a/libtecla-1.4.1/man3/pca_scan_path.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/pca_lookup_file.3 diff --git a/libtecla-1.4.1/man3/pca_set_check_fn.3 b/libtecla-1.4.1/man3/pca_set_check_fn.3 deleted file mode 100644 index e5a136e..0000000 --- a/libtecla-1.4.1/man3/pca_set_check_fn.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/pca_lookup_file.3 diff --git a/libtecla-1.4.1/man3/ppc_file_start.3 b/libtecla-1.4.1/man3/ppc_file_start.3 deleted file mode 100644 index e5a136e..0000000 --- a/libtecla-1.4.1/man3/ppc_file_start.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/pca_lookup_file.3 diff --git a/libtecla-1.4.1/man3/ppc_literal_escapes.3 b/libtecla-1.4.1/man3/ppc_literal_escapes.3 deleted file mode 100644 index e5a136e..0000000 --- a/libtecla-1.4.1/man3/ppc_literal_escapes.3 +++ /dev/null @@ -1 +0,0 @@ -.so man3/pca_lookup_file.3 diff --git a/libtecla-1.4.1/pathutil.c b/libtecla-1.4.1/pathutil.c deleted file mode 100644 index 015504b..0000000 --- a/libtecla-1.4.1/pathutil.c +++ /dev/null @@ -1,532 +0,0 @@ -/* - * Copyright (c) 2000, 2001 by Martin C. Shepherd. - * - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL - * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <string.h> -#include <ctype.h> - -#include <unistd.h> -#include <sys/types.h> -#include <sys/stat.h> - -#include "pathutil.h" - -/*....................................................................... - * Create a new PathName object. - * - * Output: - * return PathName * The new object, or NULL on error. - */ -PathName *_new_PathName(void) -{ - PathName *path; /* The object to be returned */ -/* - * Allocate the container. - */ - path = (PathName *)malloc(sizeof(PathName)); - if(!path) { - fprintf(stderr, "_new_PathName: Insufficient memory.\n"); - return NULL; - }; -/* - * Before attempting any operation that might fail, initialize the - * container at least up to the point at which it can safely be passed - * to _del_PathName(). - */ - path->name = NULL; - path->dim = 0; -/* - * Figure out the maximum length of an expanded pathname. - */ - path->dim = _pu_pathname_dim(); - if(path->dim == 0) - return _del_PathName(path); -/* - * Allocate the pathname buffer. - */ - path->name = (char *)malloc(path->dim * sizeof(char)); - if(!path->name) { - fprintf(stderr, - "_new_PathName: Insufficient memory to allocate pathname buffer.\n"); - return _del_PathName(path); - }; - return path; -} - -/*....................................................................... - * Delete a PathName object. - * - * Input: - * path PathName * The object to be deleted. - * Output: - * return PathName * The deleted object (always NULL). - */ -PathName *_del_PathName(PathName *path) -{ - if(path) { - if(path->name) - free(path->name); - free(path); - }; - return NULL; -} - -/*....................................................................... - * Return the pathname to a zero-length string. - * - * Input: - * path PathName * The pathname container. - * Output: - * return char * The cleared pathname buffer, or NULL on error. - */ -char *_pn_clear_path(PathName *path) -{ -/* - * Check the arguments. - */ - if(!path) { - fprintf(stderr, "_pn_clear_path: NULL argument.\n"); - return NULL; - }; - path->name[0] = '\0'; - return path->name; -} - -/*....................................................................... - * Append a string to a pathname, increasing the size of the pathname - * buffer if needed. - * - * Input: - * path PathName * The pathname container. - * string const char * The string to be appended to the pathname. - * Note that regardless of the slen argument, - * this should be a '\0' terminated string. - * slen int The maximum number of characters to append - * from string[], or -1 to append the whole - * string. - * remove_escapes int If true, remove the backslashes that escape - * spaces, tabs, backslashes etc.. - * Output: - * return char * The pathname string path->name[], which may - * have been reallocated, or NULL if there was - * insufficient memory to extend the pathname. - */ -char *_pn_append_to_path(PathName *path, const char *string, int slen, - int remove_escapes) -{ - int pathlen; /* The length of the pathname */ - int i; -/* - * Check the arguments. - */ - if(!path || !string) { - fprintf(stderr, "_pn_append_to_path: NULL argument(s).\n"); - return NULL; - }; -/* - * Get the current length of the pathname. - */ - pathlen = strlen(path->name); -/* - * How many characters should be appended? - */ - if(slen < 0 || slen > strlen(string)) - slen = strlen(string); -/* - * Resize the pathname if needed. - */ - if(!_pn_resize_path(path, pathlen + slen)) - return NULL; -/* - * Append the string to the output pathname, removing any escape - * characters found therein. - */ - if(remove_escapes) { - int is_escape = 0; - for(i=0; i<slen; i++) { - is_escape = !is_escape && string[i] == '\\'; - if(!is_escape) - path->name[pathlen++] = string[i]; - }; -/* - * Terminate the string. - */ - path->name[pathlen] = '\0'; - } else { -/* - * Append the string directly to the pathname. - */ - memcpy(path->name + pathlen, string, slen); - path->name[pathlen + slen] = '\0'; - }; - return path->name; -} - -/*....................................................................... - * Prepend a string to a pathname, increasing the size of the pathname - * buffer if needed. - * - * Input: - * path PathName * The pathname container. - * string const char * The string to be prepended to the pathname. - * Note that regardless of the slen argument, - * this should be a '\0' terminated string. - * slen int The maximum number of characters to prepend - * from string[], or -1 to append the whole - * string. - * remove_escapes int If true, remove the backslashes that escape - * spaces, tabs, backslashes etc.. - * Output: - * return char * The pathname string path->name[], which may - * have been reallocated, or NULL if there was - * insufficient memory to extend the pathname. - */ -char *_pn_prepend_to_path(PathName *path, const char *string, int slen, - int remove_escapes) -{ - int pathlen; /* The length of the pathname */ - int shift; /* The number of characters to shift the suffix by */ - int i,j; -/* - * Check the arguments. - */ - if(!path || !string) { - fprintf(stderr, "_pn_prepend_to_path: NULL argument(s).\n"); - return NULL; - }; -/* - * Get the current length of the pathname. - */ - pathlen = strlen(path->name); -/* - * How many characters should be appended? - */ - if(slen < 0 || slen > strlen(string)) - slen = strlen(string); -/* - * Work out how far we need to shift the original path string to make - * way for the new prefix. When removing escape characters, we need - * final length of the new prefix, after unescaped backslashes have - * been removed. - */ - if(remove_escapes) { - int is_escape = 0; - for(shift=0,i=0; i<slen; i++) { - is_escape = !is_escape && string[i] == '\\'; - if(!is_escape) - shift++; - }; - } else { - shift = slen; - }; -/* - * Resize the pathname if needed. - */ - if(!_pn_resize_path(path, pathlen + shift)) - return NULL; -/* - * Make room for the prefix at the beginning of the string. - */ - memmove(path->name + shift, path->name, pathlen+1); -/* - * Copy the new prefix into the vacated space at the beginning of the - * output pathname, removing any escape characters if needed. - */ - if(remove_escapes) { - int is_escape = 0; - for(i=j=0; i<slen; i++) { - is_escape = !is_escape && string[i] == '\\'; - if(!is_escape) - path->name[j++] = string[i]; - }; - } else { - memcpy(path->name, string, slen); - }; - return path->name; -} - -/*....................................................................... - * If needed reallocate a given pathname buffer to allow a string of - * a given length to be stored in it. - * - * Input: - * path PathName * The pathname container object. - * length size_t The required length of the pathname buffer, - * not including the terminating '\0'. - * Output: - * return char * The pathname buffer, or NULL if there was - * insufficient memory (this isn't reported - * to stderr). - */ -char *_pn_resize_path(PathName *path, size_t length) -{ -/* - * Check the arguments. - */ - if(!path) { - fprintf(stderr, "_pn_resize_path: NULL argument(s).\n"); - return NULL; - }; -/* - * If the pathname buffer isn't large enough to accomodate a string - * of the specified length, attempt to reallocate it with the new - * size, plus space for a terminating '\0'. Also add a bit of - * head room to prevent too many reallocations if the initial length - * turned out to be very optimistic. - */ - if(length + 1 > path->dim) { - size_t dim = length + 1 + PN_PATHNAME_INC; - char *name = (char *) realloc(path->name, dim); - if(!name) - return NULL; - path->name = name; - path->dim = dim; - }; - return path->name; -} - -/*....................................................................... - * Estimate the largest amount of space needed to store a pathname. - * - * Output: - * return size_t The number of bytes needed, including space for the - * terminating '\0'. - */ -size_t _pu_pathname_dim(void) -{ - int maxlen; /* The return value excluding space for the '\0' */ -/* - * If the POSIX PATH_MAX macro is defined in limits.h, use it. - */ -#ifdef PATH_MAX - maxlen = PATH_MAX; -/* - * If we have pathconf, use it. - */ -#elif defined(_PC_PATH_MAX) - errno = 0; - maxlen = pathconf(FS_ROOT_DIR, _PC_PATH_MAX); - if(maxlen <= 0 || errno) - maxlen = MAX_PATHLEN_FALLBACK; -/* - * None of the above approaches worked, so substitute our fallback - * guess. - */ -#else - maxlen = MAX_PATHLEN_FALLBACK; -#endif -/* - * Return the amount of space needed to accomodate a pathname plus - * a terminating '\0'. - */ - return maxlen + 1; -} - -/*....................................................................... - * Return non-zero if the specified path name refers to a directory. - * - * Input: - * pathname const char * The path to test. - * Output: - * return int 0 - Not a directory. - * 1 - pathname[] refers to a directory. - */ -int _pu_path_is_dir(const char *pathname) -{ - struct stat statbuf; /* The file-statistics return buffer */ -/* - * Look up the file attributes. - */ - if(stat(pathname, &statbuf) < 0) - return 0; -/* - * Is the file a directory? - */ - return S_ISDIR(statbuf.st_mode) != 0; -} - -/*....................................................................... - * Return non-zero if the specified path name refers to a regular file. - * - * Input: - * pathname const char * The path to test. - * Output: - * return int 0 - Not a regular file. - * 1 - pathname[] refers to a regular file. - */ -int _pu_path_is_file(const char *pathname) -{ - struct stat statbuf; /* The file-statistics return buffer */ -/* - * Look up the file attributes. - */ - if(stat(pathname, &statbuf) < 0) - return 0; -/* - * Is the file a regular file? - */ - return S_ISREG(statbuf.st_mode) != 0; -} - -/*....................................................................... - * Return non-zero if the specified path name refers to an executable. - * - * Input: - * pathname const char * The path to test. - * Output: - * return int 0 - Not an executable file. - * 1 - pathname[] refers to an executable file. - */ -int _pu_path_is_exe(const char *pathname) -{ - struct stat statbuf; /* The file-statistics return buffer */ -/* - * Look up the file attributes. - */ - if(stat(pathname, &statbuf) < 0) - return 0; -/* - * Is the file a regular file which is executable by the current user. - */ - return S_ISREG(statbuf.st_mode) != 0 && - (statbuf.st_mode & (S_IXOTH | S_IXGRP | S_IXUSR)) && - access(pathname, X_OK) == 0; -} - -/*....................................................................... - * Search backwards for the potential start of a filename. This - * looks backwards from the specified index in a given string, - * stopping at the first unescaped space or the start of the line. - * - * Input: - * string const char * The string to search backwards in. - * back_from int The index of the first character in string[] - * that follows the pathname. - * Output: - * return char * The pointer to the first character of - * the potential pathname, or NULL on error. - */ -char *_pu_start_of_path(const char *string, int back_from) -{ - int i, j; -/* - * Check the arguments. - */ - if(!string || back_from < 0) { - fprintf(stderr, "_pu_start_path: Invalid argument(s).\n"); - return NULL; - }; -/* - * Search backwards from the specified index. - */ - for(i=back_from-1; i>=0; i--) { - int c = string[i]; -/* - * Stop on unescaped spaces. - */ - if(isspace((int)(unsigned char)c)) { -/* - * The space can't be escaped if we are at the start of the line. - */ - if(i==0) - break; -/* - * Find the extent of the escape characters which precedes the space. - */ - for(j=i-1; j>=0 && string[j]=='\\'; j--) - ; -/* - * If there isn't an odd number of escape characters before the space, - * then the space isn't escaped. - */ - if((i - 1 - j) % 2 == 0) - break; - }; - }; - return (char *)string + i + 1; -} - -/*....................................................................... - * Find the length of a potential filename starting from a given - * point. This looks forwards from the specified index in a given string, - * stopping at the first unescaped space or the end of the line. - * - * Input: - * string const char * The string to search backwards in. - * start_from int The index of the first character of the pathname - * in string[]. - * Output: - * return char * The pointer to the character that follows - * the potential pathname, or NULL on error. - */ -char *_pu_end_of_path(const char *string, int start_from) -{ - int c; /* The character being examined */ - int escaped = 0; /* True when the next character is escaped */ - int i; -/* - * Check the arguments. - */ - if(!string || start_from < 0) { - fprintf(stderr, "_pu_end_path: Invalid argument(s).\n"); - return NULL; - }; -/* - * Search forwards from the specified index. - */ - for(i=start_from; (c=string[i]) != '\0'; i++) { - if(escaped) { - escaped = 0; - } else if(isspace(c)) { - break; - } else if(c == '\\') { - escaped = 1; - }; - }; - return (char *)string + i; -} - -/*....................................................................... - * Return non-zero if the specified path name refers to an existing file. - * - * Input: - * pathname const char * The path to test. - * Output: - * return int 0 - The file doesn't exist. - * 1 - The file does exist. - */ -int _pu_file_exists(const char *pathname) -{ - struct stat statbuf; - return stat(pathname, &statbuf) == 0; -} diff --git a/libtecla-1.4.1/pathutil.h b/libtecla-1.4.1/pathutil.h deleted file mode 100644 index 2f4ece5..0000000 --- a/libtecla-1.4.1/pathutil.h +++ /dev/null @@ -1,122 +0,0 @@ -#ifndef pathutil_h -#define pathutil_h - -/* - * Copyright (c) 2000, 2001 by Martin C. Shepherd. - * - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL - * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - */ - -/* - * The following object encapsulates a buffer designed to be used to - * store pathnames. The pathname member of the object is initially - * allocated with the size that _pu_pathname_dim() returns, and then - * if this turns out to be pessimistic, the pathname can be reallocated - * via calls to pb_append_to_path() and/or pb_resize_path(). - */ -typedef struct { - char *name; /* The path buffer */ - size_t dim; /* The current allocated size of buffer[] */ -} PathName; - -PathName *_new_PathName(void); -PathName *_del_PathName(PathName *path); - -char *_pn_clear_path(PathName *path); -char *_pn_append_to_path(PathName *path, const char *string, int slen, - int remove_escapes); -char *_pn_prepend_to_path(PathName *path, const char *string, int slen, - int remove_escapes); -char *_pn_resize_path(PathName *path, size_t length); - -/* - * Search backwards for the potential start of a filename. This - * looks backwards from the specified index in a given string, - * stopping at the first unescaped space or the start of the line. - */ -char *_pu_start_of_path(const char *string, int back_from); - -/* - * Find the end of a potential filename, starting from a given index - * in the string. This looks forwards from the specified index in a - * given string, stopping at the first unescaped space or the end - * of the line. - */ -char *_pu_end_of_path(const char *string, int start_from); - - -/* - * Return an estimate of the the length of the longest pathname - * on the local system. - */ -size_t _pu_pathname_dim(void); - -/* - * Return non-zero if the specified path name refers to a directory. - */ -int _pu_path_is_dir(const char *pathname); - -/* - * Return non-zero if the specified path name refers to a regular file. - */ -int _pu_path_is_file(const char *pathname); - -/* - * Return non-zero if the specified path name refers to an executable. - */ -int _pu_path_is_exe(const char *pathname); - -/* - * Return non-zero if a file exists with the specified pathname. - */ -int _pu_file_exists(const char *pathname); - -/* - * If neither the POSIX PATH_MAX macro nor the pathconf() function - * can be used to find out the maximum pathlength on the target - * system, the following fallback maximum length is used. - */ -#define MAX_PATHLEN_FALLBACK 1024 - -/* - * If the pathname buffer turns out to be too small, it will be extended - * in chunks of the following amount (plus whatever is needed at the time). - */ -#define PN_PATHNAME_INC 100 - -/* - * Define the special character-sequences of the filesystem. - */ -#define FS_ROOT_DIR "/" /* The root directory */ -#define FS_ROOT_DIR_LEN (sizeof(FS_ROOT_DIR) - 1) -#define FS_PWD "." /* The current working directory */ -#define FS_PWD_LEN (sizeof(FS_PWD_LEN) - 1) -#define FS_DIR_SEP "/" /* The directory separator string */ -#define FS_DIR_SEP_LEN (sizeof(FS_DIR_SEP) - 1) - -#endif diff --git a/libtecla-1.4.1/pcache.c b/libtecla-1.4.1/pcache.c deleted file mode 100644 index bbea916..0000000 --- a/libtecla-1.4.1/pcache.c +++ /dev/null @@ -1,1688 +0,0 @@ -/* - * Copyright (c) 2000, 2001 by Martin C. Shepherd. - * - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL - * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - */ - -#include <stdlib.h> -#include <string.h> -#include <stdio.h> - -#include "libtecla.h" -#include "pathutil.h" -#include "homedir.h" -#include "freelist.h" -#include "direader.h" -#include "stringrp.h" - -/* - * The new_PcaPathConf() constructor sets the integer first member of - * the returned object to the following magic number. This is then - * checked for by pca_path_completions() as a sanity check. - */ -#define PPC_ID_CODE 4567 - -/* - * A pointer to a structure of the following type can be passed to - * the builtin path-completion callback function to modify its behavior. - */ -struct PcaPathConf { - int id; /* This is set to PPC_ID_CODE by new_PcaPathConf() */ - PathCache *pc; /* The path-list cache in which to look up the executables */ - int escaped; /* If non-zero, backslashes in the input line are */ - /* interpreted as escaping special characters and */ - /* spaces, and any special characters and spaces in */ - /* the listed completions will also be escaped with */ - /* added backslashes. This is the default behaviour. */ - /* If zero, backslashes are interpreted as being */ - /* literal parts of the file name, and none are added */ - /* to the completion suffixes. */ - int file_start; /* The index in the input line of the first character */ - /* of the file name. If you specify -1 here, */ - /* pca_path_completions() identifies the */ - /* the start of the file by looking backwards for */ - /* an unescaped space, or the beginning of the line. */ -}; - -/* - * Prepended to each chached filename is a character which contains - * one of the following status codes. When a given filename (minus - * this byte) is passed to the application's check_fn(), the result - * is recorded in this byte, such that the next time it is looked - * up, we don't have to call check_fn() again. These codes are cleared - * whenever the path is scanned and whenever the check_fn() callback - * is changed. - */ -typedef enum { - PCA_F_ENIGMA='?', /* The file remains to be checked */ - PCA_F_WANTED='+', /* The file has been selected by the caller's callback */ - PCA_F_IGNORE='-' /* The file has been rejected by the caller's callback */ -} PcaFileStatus; - -/* - * Encapsulate the memory management objects which supply memoy for - * the arrays of filenames. - */ -typedef struct { - StringGroup *sg; /* The memory used to record the names of files */ - size_t files_dim; /* The allocated size of files[] */ - char **files; /* Memory for 'files_dim' pointers to files */ - size_t nfiles; /* The number of filenames currently in files[] */ -} CacheMem; - -static CacheMem *new_CacheMem(void); -static CacheMem *del_CacheMem(CacheMem *cm); -static void rst_CacheMem(CacheMem *cm); - -/* - * Lists of nodes of the following type are used to record the - * names and contents of individual directories. - */ -typedef struct PathNode PathNode; -struct PathNode { - PathNode *next; /* The next directory in the path */ - int relative; /* True if the directory is a relative pathname */ - CacheMem *mem; /* The memory used to store dir[] and files[] */ - char *dir; /* The directory pathname (stored in pc->sg) */ - int nfile; /* The number of filenames stored in 'files' */ - char **files; /* Files of interest in the current directory, */ - /* or NULL if dir[] is a relative pathname */ - /* who's contents can't be cached. This array */ - /* and its contents are taken from pc->abs_mem */ - /* or pc->rel_mem */ -}; - -/* - * Append a new node to the list of directories in the path. - */ -static int add_PathNode(PathCache *pc, const char *dirname); - -/* - * Set the max length of the error-reporting string. There is no point - * in this being longer than the width of a typical terminal window. - * In composing error messages, I have assumed that this number is - * at least 80, so you don't decrease it below this number. - */ -#define ERRLEN 200 - -/* - * Set the maximum length allowed for usernames. - * names. - */ -#define USR_LEN 100 - -/* - * PathCache objects encapsulate the resources needed to record - * files of interest from comma-separated lists of directories. - */ -struct PathCache { - FreeList *node_mem; /* A free-list of PathNode objects */ - CacheMem *abs_mem; /* Memory for the filenames of absolute paths */ - CacheMem *rel_mem; /* Memory for the filenames of relative paths */ - PathNode *head; /* The head of the list of directories in the */ - /* path, or NULL if no path has been scanned yet. */ - PathNode *tail; /* The tail of the list of directories in the */ - /* path, or NULL if no path has been scanned yet. */ - PathName *path; /* The fully qualified name of a file */ - HomeDir *home; /* Home-directory lookup object */ - DirReader *dr; /* A portable directory reader */ - CplFileConf *cfc; /* Configuration parameters to pass to */ - /* cpl_file_completions() */ - CplCheckFn *check_fn; /* The callback used to determine if a given */ - /* filename should be recorded in the cache. */ - void *data; /* Annonymous data to be passed to pc->check_fn() */ - char usrnam[USR_LEN+1];/* The buffer used when reading the names of */ - /* users. */ - char errmsg[ERRLEN+1]; /* Error-report buffer */ -}; - -/* - * Empty the cache. - */ -static void pca_clear_cache(PathCache *pc); - -/* - * Read a username from string[] and record it in pc->usrnam[]. - */ -static int pca_read_username(PathCache *pc, const char *string, int slen, - int literal, const char **nextp); - -/* - * Extract the next component of a colon separated list of directory - * paths. - */ -static int pca_extract_dir(PathCache *pc, const char *path, - const char **nextp); - -/* - * Scan absolute directories for files of interest, recording their names - * in mem->sg and recording pointers to these names in mem->files[]. - */ -static int pca_scan_dir(PathCache *pc, const char *dirname, CacheMem *mem); - -/* - * A qsort() comparison function for comparing the cached filename - * strings pointed to by two (char **) array elements. Note that - * this ignores the initial cache-status byte of each filename. - */ -static int pca_cmp_matches(const void *v1, const void *v2); - -/* - * A qsort() comparison function for comparing a filename - * against an element of an array of pointers to filename cache - * entries. - */ -static int pca_cmp_file(const void *v1, const void *v2); - -/* - * Initialize a PcaPathConf configuration objects with the default - * options. - */ -static int pca_init_PcaPathConf(PcaPathConf *ppc, PathCache *pc); - -/* - * Make a copy of a completion suffix, suitable for passing to - * cpl_add_completion(). - */ -static int pca_prepare_suffix(PathCache *pc, const char *suffix, - int add_escapes); - -/* - * Return non-zero if the specified string appears to start with a pathname. - */ -static int cpa_cmd_contains_path(const char *prefix, int prefix_len); - -/* - * Return a given prefix with escapes optionally removed. - */ -static const char *pca_prepare_prefix(PathCache *pc, const char *prefix, - size_t prefix_len, int escaped); - -/* - * If there is a tilde expression at the beginning of the specified path, - * place the corresponding home directory into pc->path. Otherwise - * just clear pc->path. - */ -static int pca_expand_tilde(PathCache *pc, const char *path, int pathlen, - int literal, const char **endp); - -/* - * Clear the filename status codes that are recorded before each filename - * in the cache. - */ -static void pca_remove_marks(PathCache *pc); - -/* - * Specify how many PathNode's to allocate at a time. - */ -#define PATH_NODE_BLK 30 - -/* - * Specify the amount by which the files[] arrays are to be extended - * whenever they are found to be too small. - */ -#define FILES_BLK_FACT 256 - -/*....................................................................... - * Create a new object who's function is to maintain a cache of - * filenames found within a list of directories, and provide quick - * lookup and completion of selected files in this cache. - * - * Output: - * return PathCache * The new, initially empty cache, or NULL - * on error. - */ -PathCache *new_PathCache(void) -{ - PathCache *pc; /* The object to be returned */ -/* - * Allocate the container. - */ - pc = (PathCache *)malloc(sizeof(PathCache)); - if(!pc) { - fprintf(stderr, "new_PathCache: Insufficient memory.\n"); - return NULL; - }; -/* - * Before attempting any operation that might fail, initialize the - * container at least up to the point at which it can safely be passed - * to del_PathCache(). - */ - pc->node_mem = NULL; - pc->abs_mem = NULL; - pc->rel_mem = NULL; - pc->head = NULL; - pc->tail = NULL; - pc->path = NULL; - pc->home = NULL; - pc->dr = NULL; - pc->cfc = NULL; - pc->check_fn = 0; - pc->data = NULL; - pc->usrnam[0] = '\0'; - pc->errmsg[0] = '\0'; -/* - * Allocate the freelist of directory list nodes. - */ - pc->node_mem = _new_FreeList("new_PathCache", sizeof(PathNode), - PATH_NODE_BLK); - if(!pc->node_mem) - return del_PathCache(pc); -/* - * Allocate memory for recording names of files in absolute paths. - */ - pc->abs_mem = new_CacheMem(); - if(!pc->abs_mem) - return del_PathCache(pc); -/* - * Allocate memory for recording names of files in relative paths. - */ - pc->rel_mem = new_CacheMem(); - if(!pc->rel_mem) - return del_PathCache(pc); -/* - * Allocate a pathname buffer. - */ - pc->path = _new_PathName(); - if(!pc->path) - return del_PathCache(pc); -/* - * Allocate an object for looking up home-directories. - */ - pc->home = _new_HomeDir(); - if(!pc->home) - return del_PathCache(pc); -/* - * Allocate an object for reading directories. - */ - pc->dr = _new_DirReader(); - if(!pc->dr) - return del_PathCache(pc); -/* - * Allocate a cpl_file_completions() configuration object. - */ - pc->cfc = new_CplFileConf(); - if(!pc->cfc) - return del_PathCache(pc); -/* - * Configure cpl_file_completions() to use check_fn() to select - * files of interest. - */ - cfc_set_check_fn(pc->cfc, pc->check_fn, pc->data); -/* - * Return the cache, ready for use. - */ - return pc; -} - -/*....................................................................... - * Delete a given cache of files, returning the resources that it - * was using to the system. - * - * Input: - * pc PathCache * The cache to be deleted (can be NULL). - * Output: - * return PathCache * The deleted object (ie. allways NULL). - */ -PathCache *del_PathCache(PathCache *pc) -{ - if(pc) { -/* - * Delete the memory of the list of path nodes. - */ - pc->node_mem = _del_FreeList(NULL, pc->node_mem, 1); -/* - * Delete the memory used to record filenames. - */ - pc->abs_mem = del_CacheMem(pc->abs_mem); - pc->rel_mem = del_CacheMem(pc->rel_mem); -/* - * The list of PathNode's was already deleted when node_mem was - * deleted. - */ - pc->head = NULL; - pc->tail = NULL; -/* - * Delete the pathname buffer. - */ - pc->path = _del_PathName(pc->path); -/* - * Delete the home-directory lookup object. - */ - pc->home = _del_HomeDir(pc->home); -/* - * Delete the directory reader. - */ - pc->dr = _del_DirReader(pc->dr); -/* - * Delete the cpl_file_completions() config object. - */ - pc->cfc = del_CplFileConf(pc->cfc); -/* - * Delete the container. - */ - free(pc); - }; - return NULL; -} - -/*....................................................................... - * If you want subsequent calls to pca_lookup_file() and - * pca_path_completions() to only return the filenames of certain - * types of files, for example executables, or filenames ending in - * ".ps", call this function to register a file-selection callback - * function. This callback function takes the full pathname of a file, - * plus application-specific data, and returns 1 if the file is of - * interest, and zero otherwise. - * - * Input: - * pc PathCache * The filename cache. - * check_fn CplCheckFn * The function to call to see if the name of - * a given file should be included in the - * cache. This determines what type of files - * will reside in the cache. To revert to - * selecting all files, regardless of type, - * pass 0 here. - * data void * You can pass a pointer to anything you - * like here, including NULL. It will be - * passed to your check_fn() callback - * function, for its private use. - */ -void pca_set_check_fn(PathCache *pc, CplCheckFn *check_fn, void *data) -{ - if(pc) { -/* - * If the callback or its data pointer have changed, clear the cached - * statuses of files that were accepted or rejected by the previous - * calback. - */ - if(check_fn != pc->check_fn || data != pc->data) - pca_remove_marks(pc); -/* - * Record the new callback locally. - */ - pc->check_fn = check_fn; - pc->data = data; -/* - * Configure cpl_file_completions() to use the same callback to - * select files of interest. - */ - cfc_set_check_fn(pc->cfc, check_fn, data); - }; - return; -} - -/*....................................................................... - * Return a description of the last path-caching error that occurred. - * - * Input: - * pc PathCache * The filename cache that suffered the error. - * Output: - * return char * The description of the last error. - */ -const char *pca_last_error(PathCache *pc) -{ - return pc ? pc->errmsg : "NULL PathCache argument"; -} - -/*....................................................................... - * Discard all cached filenames. - * - * Input: - * pc PathCache * The cache to be cleared. - */ -static void pca_clear_cache(PathCache *pc) -{ - if(pc) { -/* - * Return all path-nodes to the freelist. - */ - _rst_FreeList(pc->node_mem); - pc->head = pc->tail = NULL; -/* - * Delete all filename strings. - */ - rst_CacheMem(pc->abs_mem); - rst_CacheMem(pc->rel_mem); - }; - return; -} - -/*....................................................................... - * Build the list of files of interest contained in a given - * colon-separated list of directories. - * - * Input: - * pc PathCache * The cache in which to store the names of - * the files that are found in the list of - * directories. - * path const char * A colon-separated list of directory - * paths. Under UNIX, when searching for - * executables, this should be the return - * value of getenv("PATH"). - * Output: - * return int 0 - OK. - * 1 - An error occurred. A description of - * the error can be acquired by calling - * pca_last_error(pc). - */ -int pca_scan_path(PathCache *pc, const char *path) -{ - const char *pptr; /* A pointer to the next unprocessed character in path[] */ - PathNode *node; /* A node in the list of directory paths */ - char **fptr; /* A pointer into pc->abs_mem->files[] */ -/* - * Check the arguments. - */ - if(!pc) - return 1; -/* - * Clear the outdated contents of the cache. - */ - pca_clear_cache(pc); -/* - * If no path list was provided, there is nothing to be added to the - * cache. - */ - if(!path) - return 0; -/* - * Extract directories from the path list, expanding tilde expressions - * on the fly into pc->pathname, then add them to the list of path - * nodes, along with a sorted list of the filenames of interest that - * the directories hold. - */ - pptr = path; - while(*pptr) { -/* - * Extract the next pathname component into pc->path->name. - */ - if(pca_extract_dir(pc, pptr, &pptr)) - return 1; -/* - * Add a new node to the list of paths, containing both the - * directory name and, if not a relative pathname, the list of - * files of interest in the directory. - */ - if(add_PathNode(pc, pc->path->name)) - return 1; - }; -/* - * The file arrays in each absolute directory node are sections of - * pc->abs_mem->files[]. Record pointers to the starts of each - * of these sections in each directory node. Note that this couldn't - * be done in add_PathNode(), because pc->abs_mem->files[] may - * get reallocated in subsequent calls to add_PathNode(), thus - * invalidating any pointers to it. - */ - fptr = pc->abs_mem->files; - for(node=pc->head; node; node=node->next) { - node->files = fptr; - fptr += node->nfile; - }; - return 0; -} - -/*....................................................................... - * Extract the next directory path from a colon-separated list of - * directories, expanding tilde home-directory expressions where needed. - * - * Input: - * pc PathCache * The cache of filenames. - * path const char * A pointer to the start of the next component - * in the path list. - * Input/Output: - * nextp const char ** A pointer to the next unprocessed character - * in path[] will be assigned to *nextp. - * Output: - * return int 0 - OK. The extracted path is in pc->path->name. - * 1 - Error. A description of the error will - * have been left in pc->errmsg. - */ -static int pca_extract_dir(PathCache *pc, const char *path, const char **nextp) -{ - const char *pptr; /* A pointer into path[] */ - const char *sptr; /* The path following tilde expansion */ - int escaped = 0; /* True if the last character was a backslash */ -/* - * If there is a tilde expression at the beginning of the specified path, - * place the corresponding home directory into pc->path. Otherwise - * just clear pc->path. - */ - if(pca_expand_tilde(pc, path, strlen(path), 0, &pptr)) - return 1; -/* - * Keep a record of the current location in the path. - */ - sptr = pptr; -/* - * Locate the end of the directory name in the pathname string, stopping - * when either the end of the string is reached, or an un-escaped colon - * separator is seen. - */ - while(*pptr && (escaped || *pptr != ':')) - escaped = !escaped && *pptr++ == '\\'; -/* - * Append the rest of the directory path to the pathname buffer. - */ - if(_pn_append_to_path(pc->path, sptr, pptr - sptr, 1) == NULL) { - strcpy(pc->errmsg, "Insufficient memory to record directory name"); - return 1; - }; -/* - * To facilitate subsequently appending filenames to the directory - * path name, make sure that the recorded directory name ends in a - * directory separator. - */ - { - int dirlen = strlen(pc->path->name); - if(dirlen < FS_DIR_SEP_LEN || - strncmp(pc->path->name + dirlen - FS_DIR_SEP_LEN, FS_DIR_SEP, - FS_DIR_SEP_LEN) != 0) { - if(_pn_append_to_path(pc->path, FS_DIR_SEP, FS_DIR_SEP_LEN, 0) == NULL) { - strcpy(pc->errmsg, "Insufficient memory to record directory name"); - return 1; - }; - }; - }; -/* - * Skip the separator unless we have reached the end of the path. - */ - if(*pptr==':') - pptr++; -/* - * Return the unprocessed tail of the path-list string. - */ - *nextp = pptr; - return 0; -} - -/*....................................................................... - * Read a username, stopping when a directory separator is seen, a colon - * separator is seen, the end of the string is reached, or the username - * buffer overflows. - * - * Input: - * pc PathCache * The cache of filenames. - * string char * The string who's prefix contains the name. - * slen int The max number of characters to read from string[]. - * literal int If true, treat backslashes as literal characters - * instead of escapes. - * Input/Output: - * nextp char ** A pointer to the next unprocessed character - * in string[] will be assigned to *nextp. - * Output: - * return int 0 - OK. The username can be found in pc->usrnam. - * 1 - Error. A description of the error message - * can be found in pc->errmsg. - */ -static int pca_read_username(PathCache *pc, const char *string, int slen, - int literal, const char **nextp) -{ - int usrlen; /* The number of characters in pc->usrnam[] */ - const char *sptr; /* A pointer into string[] */ - int escaped = 0; /* True if the last character was a backslash */ -/* - * Extract the username. - */ - for(sptr=string,usrlen=0; usrlen < USR_LEN && (sptr-string) < slen; sptr++) { -/* - * Stop if the end of the string is reached, or a directory separator - * or un-escaped colon separator is seen. - */ - if(!*sptr || strncmp(sptr, FS_DIR_SEP, FS_DIR_SEP_LEN)==0 || - (!escaped && *sptr == ':')) - break; -/* - * Escape the next character? - */ - if(!literal && !escaped && *sptr == '\\') { - escaped = 1; - } else { - escaped = 0; - pc->usrnam[usrlen++] = *sptr; - }; - }; -/* - * Did the username overflow the buffer? - */ - if(usrlen >= USR_LEN) { - strcpy(pc->errmsg, "Username too long"); - return 1; - }; -/* - * Terminate the string. - */ - pc->usrnam[usrlen] = '\0'; -/* - * Indicate where processing of the input string should continue. - */ - *nextp = sptr; - return 0; -} - - -/*....................................................................... - * Create a new CacheMem object. - * - * Output: - * return CacheMem * The new object, or NULL on error. - */ -static CacheMem *new_CacheMem(void) -{ - CacheMem *cm; /* The object to be returned */ -/* - * Allocate the container. - */ - cm = (CacheMem *)malloc(sizeof(CacheMem)); - if(!cm) { - fprintf(stderr, "new_CacheMem: Insufficient memory.\n"); - return NULL; - }; -/* - * Before attempting any operation that might fail, initialize the - * container at least up to the point at which it can safely be passed - * to del_CacheMem(). - */ - cm->sg = NULL; - cm->files_dim = 0; - cm->files = NULL; - cm->nfiles = 0; -/* - * Allocate a list of string segments for storing filenames. - */ - cm->sg = _new_StringGroup(_pu_pathname_dim()); - if(!cm->sg) - return del_CacheMem(cm); -/* - * Allocate an array of pointers to filenames. - * This will be extended later if needed. - */ - cm->files_dim = FILES_BLK_FACT; - cm->files = (char **) malloc(sizeof(*cm->files) * cm->files_dim); - if(!cm->files) { - fprintf(stderr, - "new_CacheMem: Insufficient memory to allocate array of files.\n"); - return del_CacheMem(cm); - }; - return cm; -} - -/*....................................................................... - * Delete a CacheMem object. - * - * Input: - * cm CacheMem * The object to be deleted. - * Output: - * return CacheMem * The deleted object (always NULL). - */ -static CacheMem *del_CacheMem(CacheMem *cm) -{ - if(cm) { -/* - * Delete the memory that was used to record filename strings. - */ - cm->sg = _del_StringGroup(cm->sg); -/* - * Delete the array of pointers to filenames. - */ - cm->files_dim = 0; - if(cm->files) { - free(cm->files); - cm->files = NULL; - }; -/* - * Delete the container. - */ - free(cm); - }; - return NULL; -} - -/*....................................................................... - * Re-initialize the memory used to allocate filename strings. - * - * Input: - * cm CacheMem * The memory cache to be cleared. - */ -static void rst_CacheMem(CacheMem *cm) -{ - _clr_StringGroup(cm->sg); - cm->nfiles = 0; - return; -} - -/*....................................................................... - * Append a new directory node to the list of directories read from the - * path. - * - * Input: - * pc PathCache * The filename cache. - * dirname const char * The name of the new directory. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int add_PathNode(PathCache *pc, const char *dirname) -{ - PathNode *node; /* The new directory list node */ - int relative; /* True if dirname[] is a relative pathname */ -/* - * Have we been passed a relative pathname or an absolute pathname? - */ - relative = strncmp(dirname, FS_ROOT_DIR, FS_ROOT_DIR_LEN) != 0; -/* - * If it's an absolute pathname, ignore it if the corresponding - * directory doesn't exist. - */ - if(!relative && !_pu_path_is_dir(dirname)) - return 0; -/* - * Allocate a new list node to record the specifics of the new directory. - */ - node = (PathNode *) _new_FreeListNode(pc->node_mem); - if(!node) { - sprintf(pc->errmsg, "Insufficient memory to cache new directory."); - return 1; - }; -/* - * Initialize the node. - */ - node->next = NULL; - node->relative = relative; - node->mem = relative ? pc->rel_mem : pc->abs_mem; - node->dir = NULL; - node->nfile = 0; - node->files = NULL; -/* - * Make a copy of the directory pathname. - */ - node->dir = _sg_store_string(pc->abs_mem->sg, dirname, 0); - if(!node->dir) { - strcpy(pc->errmsg, "Insufficient memory to store directory name."); - return 1; - }; -/* - * Scan absolute directories for files of interest, recording their names - * in node->mem->sg and appending pointers to these names to the - * node->mem->files[] array. - */ - if(!node->relative) { - int nfile = node->nfile = pca_scan_dir(pc, node->dir, node->mem); - if(nfile < 1) { /* No files matched or an error occurred */ - node = (PathNode *) _del_FreeListNode(pc->node_mem, node); - return nfile < 0; - }; - }; -/* - * Append the new node to the list. - */ - if(pc->head) { - pc->tail->next = node; - pc->tail = node; - } else { - pc->head = pc->tail = node; - }; - return 0; -} - -/*....................................................................... - * Scan a given directory for files of interest, record their names - * in mem->sg and append pointers to them to the mem->files[] array. - * - * Input: - * pc PathCache * The filename cache. - * dirname const char * The pathname of the directory to be scanned. - * mem CacheMem * The memory in which to store filenames of - * interest. - * Output: - * return int The number of files recorded, or -1 if a - * memory error occurs. Note that the - * inability to read the contents of the - * directory is not counted as an error. - */ -static int pca_scan_dir(PathCache *pc, const char *dirname, CacheMem *mem) -{ - int nfile = 0; /* The number of filenames recorded */ - const char *filename; /* The name of the file being looked at */ -/* - * Attempt to open the directory. If the directory can't be read then - * there are no accessible files of interest in the directory. - */ - if(_dr_open_dir(pc->dr, dirname, NULL)) - return 0; -/* - * Record the names of all files in the directory in the cache. - */ - while((filename = _dr_next_file(pc->dr))) { - char *copy; /* A copy of the filename */ -/* - * Make a temporary copy of the filename with an extra byte prepended. - */ - _pn_clear_path(pc->path); - if(_pn_append_to_path(pc->path, " ", 1, 0) == NULL || - _pn_append_to_path(pc->path, filename, -1, 1) == NULL) { - strcpy(pc->errmsg, "Insufficient memory to record filename"); - return -1; - }; -/* - * Store the filename. - */ - copy = _sg_store_string(mem->sg, pc->path->name, 0); - if(!copy) { - strcpy(pc->errmsg, "Insufficient memory to cache file name."); - return -1; - }; -/* - * Mark the filename as unchecked. - */ - copy[0] = PCA_F_ENIGMA; -/* - * Make room to store a pointer to the copy in mem->files[]. - */ - if(mem->nfiles + 1 > mem->files_dim) { - int needed = mem->files_dim + FILES_BLK_FACT; - char **files = (char **) realloc(mem->files, sizeof(*mem->files)*needed); - if(!files) { - strcpy(pc->errmsg, "Insufficient memory to extend filename cache."); - return 1; - }; - mem->files = files; - mem->files_dim = needed; - }; -/* - * Record a pointer to the copy of the filename at the end of the files[] - * array. - */ - mem->files[mem->nfiles++] = copy; -/* - * Keep a record of the number of files matched so far. - */ - nfile++; - }; -/* - * Sort the list of files into lexical order. - */ - qsort(mem->files + mem->nfiles - nfile, nfile, sizeof(*mem->files), - pca_cmp_matches); -/* - * Return the number of files recorded in mem->files[]. - */ - return nfile; -} - -/*....................................................................... - * A qsort() comparison function for comparing the cached filename - * strings pointed to by two (char **) array elements. Note that - * this ignores the initial cache-status byte of each filename. - * - * Input: - * v1, v2 void * Pointers to the pointers of two strings to be compared. - * Output: - * return int -1 -> v1 < v2. - * 0 -> v1 == v2 - * 1 -> v1 > v2 - */ -static int pca_cmp_matches(const void *v1, const void *v2) -{ - const char **s1 = (const char **) v1; - const char **s2 = (const char **) v2; - return strcmp(*s1+1, *s2+1); -} - -/*....................................................................... - * Given the simple name of a file, search the cached list of files - * in the order in which they where found in the list of directories - * previously presented to pca_scan_path(), and return the pathname - * of the first file which has this name. If a pathname to a file is - * given instead of a simple filename, this is returned without being - * looked up in the cache, but with any initial ~username expression - * expanded, and optionally, unescaped backslashes removed. - * - * Input: - * pc PathCache * The cached list of files. - * name const char * The name of the file to lookup. - * name_len int The length of the filename string at the - * beginning of name[], or -1 to indicate that - * the filename occupies the whole of the - * string. - * literal int If this argument is zero, lone backslashes - * in name[] are ignored during comparison - * with filenames in the cache, under the - * assumption that they were in the input line - * soley to escape the special significance of - * characters like spaces. To have them treated - * as normal characters, give this argument a - * non-zero value, such as 1. - * Output: - * return char * The pathname of the first matching file, - * or NULL if not found. Note that the returned - * pointer points to memory owned by *pc, and - * will become invalid on the next call to any - * function in the PathCache module. - */ -char *pca_lookup_file(PathCache *pc, const char *name, int name_len, - int literal) -{ - PathNode *node; /* A node in the list of directories in the path */ - char **match; /* A pointer to a matching filename string in the cache */ -/* - * Check the arguments. - */ - if(!pc || !name || name_len==0) - return NULL; -/* - * If no length was specified, determine the length of the string to - * be looked up. - */ - if(name_len < 0) - name_len = strlen(name); -/* - * If the word starts with a ~username expression, the root directory, - * of it contains any directory separators, then treat it isn't a simple - * filename that can be looked up in the cache, but rather appears to - * be the pathname of a file. If so, return a copy of this pathname with - * escapes removed, if requested, and any initial ~username expression - * expanded. - */ - if(cpa_cmd_contains_path(name, name_len)) { - const char *nptr; - if(pca_expand_tilde(pc, name, name_len, literal, &nptr) || - _pn_append_to_path(pc->path, nptr, name_len - (nptr-name), - !literal) == NULL) - return NULL; - return pc->path->name; - }; -/* - * Look up the specified filename in each of the directories of the path, - * in the same order that they were listed in the path, and stop as soon - * as an instance of the file is found. - */ - for(node=pc->head; node; node=node->next) { -/* - * If the directory of the latest node is a relative pathname, - * scan it for files of interest. - */ - if(node->relative) { - rst_CacheMem(node->mem); - if(pca_scan_dir(pc, node->dir, node->mem) < 1) - continue; - node->files = node->mem->files; - node->nfile = node->mem->nfiles; - }; -/* - * Copy the filename into a temporary buffer, while interpretting - * escape characters if needed. - */ - _pn_clear_path(pc->path); - if(_pn_append_to_path(pc->path, name, name_len, !literal) == NULL) - return NULL; -/* - * Perform a binary search for the requested filename. - */ - match = (char **)bsearch(pc->path->name, node->files, node->nfile, - sizeof(*node->files), pca_cmp_file); - if(match) { -/* - * Prepend the pathname in which the directory was found, which we have - * guaranteed to end in a directory separator, to the located filename. - */ - if(_pn_prepend_to_path(pc->path, node->dir, -1, 0) == NULL) - return NULL; -/* - * Return the matching pathname unless it is rejected by the application. - */ - if(!pc->check_fn || (*match)[0] == PCA_F_WANTED || - ((*match)[0]==PCA_F_ENIGMA && pc->check_fn(pc->data, pc->path->name))){ - (*match)[0] = PCA_F_WANTED; - return pc->path->name; - } else { - *(match)[0] = PCA_F_IGNORE; - }; - }; - }; -/* - * File not found. - */ - return NULL; -} - -/*....................................................................... - * A qsort() comparison function for comparing a filename string to - * a cached filename string pointed to by a (char **) array element. - * This ignores the initial code byte at the start of the cached filename - * string. - * - * Input: - * v1, v2 void * Pointers to the pointers of two strings to be compared. - * Output: - * return int -1 -> v1 < v2. - * 0 -> v1 == v2 - * 1 -> v1 > v2 - */ -static int pca_cmp_file(const void *v1, const void *v2) -{ - const char *file_name = (const char *) v1; - const char **cache_name = (const char **) v2; - return strcmp(file_name, *cache_name + 1); -} - -/*....................................................................... - * The PcaPathConf structure may have options added to it in the future. - * To allow your application to be linked against a shared version of the - * tecla library, without these additions causing your application to - * crash, you should use new_PcaPathConf() to allocate such structures. - * This will set all of the configuration options to their default values, - * which you can then change before passing the structure to - * pca_path_completions(). - * - * Input: - * pc PathCache * The filename cache in which to look for - * file name completions. - * Output: - * return PcaPathConf * The new configuration structure, or NULL - * on error. A descripition of the error - * can be found by calling pca_last_error(pc). - */ -PcaPathConf *new_PcaPathConf(PathCache *pc) -{ - PcaPathConf *ppc; /* The object to be returned */ -/* - * Check the arguments. - */ - if(!pc) - return NULL; -/* - * Allocate the container. - */ - ppc = (PcaPathConf *)malloc(sizeof(PcaPathConf)); - if(!ppc) { - strcpy(pc->errmsg, "Insufficient memory."); - return NULL; - }; -/* - * Before attempting any operation that might fail, initialize the - * container at least up to the point at which it can safely be passed - * to del_PcaPathConf(). - */ - if(pca_init_PcaPathConf(ppc, pc)) - return del_PcaPathConf(ppc); - return ppc; -} - -/*....................................................................... - * Initialize a PcaPathConf configuration structure with defaults. - * - * Input: - * ppc PcaPathConf * The structre to be initialized. - * pc PathCache * The cache in which completions will be looked up. - * Output: - * return int 0 - OK. - * 1 - Error. A description of the error can be - * obtained by calling pca_last_error(pc). - */ -static int pca_init_PcaPathConf(PcaPathConf *ppc, PathCache *pc) -{ -/* - * Check the arguments. - */ - if(!pc) - return 1; -/* - * Set the default options. - */ - ppc->id = PPC_ID_CODE; - ppc->pc = pc; - ppc->escaped = 1; - ppc->file_start = -1; - return 0; -} - -/*....................................................................... - * Delete a PcaPathConf object. - * - * Input: - * ppc PcaPathConf * The object to be deleted. - * Output: - * return PcaPathConf * The deleted object (always NULL). - */ -PcaPathConf *del_PcaPathConf(PcaPathConf *ppc) -{ - if(ppc) { - ppc->pc = NULL; /* It is up to the caller to delete the cache */ -/* - * Delete the container. - */ - free(ppc); - }; - return NULL; -} - -/*....................................................................... - * pca_path_completions() is a completion callback function for use - * directly with cpl_complete_word() or gl_customize_completions(), or - * indirectly from your own completion callback function. It requires - * that a CpaPathArgs object be passed via its 'void *data' argument. - */ -CPL_MATCH_FN(pca_path_completions) -{ - PcaPathConf *ppc; /* The configuration arguments */ - PathCache *pc; /* The cache in which to look for completions */ - PathNode *node; /* A node in the list of directories in the path */ - const char *filename; /* The name of the file being looked at */ - const char *start_path; /* The pointer to the start of the pathname */ - /* in line[]. */ - int word_start; /* The index in line[] corresponding to start_path */ - const char *prefix; /* The file-name prefix being searched for */ - size_t prefix_len; /* The length of the prefix being completed */ - int bot; /* The lowest index of the array not searched yet */ - int top; /* The highest index of the array not searched yet */ -/* - * Check the arguments. - */ - if(!cpl) - return 1; - if(!line || word_end < 0 || !data) { - cpl_record_error(cpl, "pca_path_completions: Invalid arguments."); - return 1; - }; -/* - * Get the configuration arguments. - */ - ppc = (PcaPathConf *) data; -/* - * Check that the callback data is a PcaPathConf structure returned - * by new_PcaPathConf(). - */ - if(ppc->id != PPC_ID_CODE) { - cpl_record_error(cpl, - "Invalid callback data passed to pca_path_completions()"); - return 1; - }; -/* - * Get the filename cache. - */ - pc = ppc->pc; -/* - * Get the start of the file name. If not specified by the caller, - * identify it by searching backwards in the input line for an - * unescaped space or the start of the line. - */ - if(ppc->file_start < 0) { - start_path = _pu_start_of_path(line, word_end); - if(!start_path) { - cpl_record_error(cpl, "Unable to find the start of the file name."); - return 1; - }; - } else { - start_path = line + ppc->file_start; - }; -/* - * Get the index of the start of the word being completed. - */ - word_start = start_path - line; -/* - * Work out the length of the prefix that is bein completed. - */ - prefix_len = word_end - word_start; -/* - * If the word starts with a ~username expression or the root directory, - * of it contains any directory separators, then completion must be - * delegated to cpl_file_completions(). - */ - if(cpa_cmd_contains_path(start_path, prefix_len)) { - cfc_file_start(pc->cfc, word_start); - return cpl_file_completions(cpl, pc->cfc, line, word_end); - }; -/* - * Look up the specified file name in each of the directories of the path, - * in the same order that they were listed in the path, and stop as soon - * as an instance of the file is found. - */ - for(node=pc->head; node; node=node->next) { -/* - * If the directory of the latest node is a relative pathname, - * scan it for files of interest. - */ - if(node->relative) { - rst_CacheMem(node->mem); - if(pca_scan_dir(pc, node->dir, node->mem) < 1) - continue; - node->files = node->mem->files; - node->nfile = node->mem->nfiles; - }; -/* - * If needed, make a copy of the file-name being matched, with - * escapes removed. Note that we need to do this anew every loop - * iteration, because the above call to pca_scan_dir() uses - * pc->path. - */ - prefix = pca_prepare_prefix(pc, start_path, prefix_len, ppc->escaped); - if(!prefix) - return 1; -/* - * The directory entries are sorted, so we can perform a binary - * search for an instance of the prefix being searched for. - */ - bot = 0; - top = node->nfile - 1; - while(top >= bot) { - int mid = (top + bot)/2; - int test = strncmp(node->files[mid]+1, prefix, prefix_len); - if(test > 0) - top = mid - 1; - else if(test < 0) - bot = mid + 1; - else { - top = bot = mid; - break; - }; - }; -/* - * If we found a match, look to see if any of its neigbors also match. - */ - if(top == bot) { - while(--bot >= 0 && strncmp(node->files[bot]+1, prefix, prefix_len) == 0) - ; - while(++top < node->nfile && - strncmp(node->files[top]+1, prefix, prefix_len) == 0) - ; -/* - * We will have gone one too far in each direction. - */ - bot++; - top--; -/* - * Add the completions to the list after checking them against the - * callers requirements. - */ - for( ; bot<=top; bot++) { - char *match = node->files[bot]; -/* - * Form the full pathname of the file. - */ - _pn_clear_path(pc->path); - if(_pn_append_to_path(pc->path, node->dir, -1, 0) == NULL || - _pn_append_to_path(pc->path, match+1, -1, 0) == NULL) { - strcpy(pc->errmsg, "Insufficient memory to complete file name"); - return 1; - }; -/* - * Should the file be included in the list of completions? - */ - if(!pc->check_fn || match[0] == PCA_F_WANTED || - (match[0]==PCA_F_ENIGMA && pc->check_fn(pc->data, pc->path->name))) { - match[0] = PCA_F_WANTED; -/* - * Copy the completion suffix into the work pathname pc->path->name, - * adding backslash escapes if needed. - */ - if(pca_prepare_suffix(pc, match + 1 + prefix_len, - ppc->escaped)) - return 1; -/* - * Record the completion. - */ - if(cpl_add_completion(cpl, line, word_start, word_end, pc->path->name, - "", " ")) - return 1; -/* - * The file was rejected by the application. - */ - } else { - match[0] = PCA_F_IGNORE; - }; - }; - }; - }; -/* - * We now need to search for subdirectories of the current directory which - * have matching prefixes. First, if needed, make a copy of the word being - * matched, with escapes removed. - */ - prefix = pca_prepare_prefix(pc, start_path, prefix_len, ppc->escaped); - if(!prefix) - return 1; -/* - * Now open the current directory. - */ - if(_dr_open_dir(pc->dr, FS_PWD, NULL)) - return 0; -/* - * Scan the current directory for sub-directories whos names start with - * the prefix that we are completing. - */ - while((filename = _dr_next_file(pc->dr))) { -/* - * Does the latest filename match the prefix, and is it a directory? - */ - if(strncmp(filename, prefix, prefix_len) == 0 && _pu_path_is_dir(filename)){ -/* - * Record the completion. - */ - if(pca_prepare_suffix(pc, filename + prefix_len, ppc->escaped) || - cpl_add_completion(cpl, line, word_start, word_end, pc->path->name, - FS_DIR_SEP, FS_DIR_SEP)) - return 1; -/* - * The prefix in pc->path->name will have been overwritten by - * pca_prepare_suffix(). Restore it here. - */ - prefix = pca_prepare_prefix(pc, start_path, prefix_len, ppc->escaped); - if(!prefix) - return 1; - }; - }; - _dr_close_dir(pc->dr); - return 0; -} - -/*....................................................................... - * Using the work buffer pc->path, make a suitably escaped copy of a - * given completion suffix, ready to be passed to cpl_add_completion(). - * - * Input: - * pc PathCache * The filename cache resource object. - * suffix char * The suffix to be copied. - * add_escapes int If true, escape special characters. - * Output: - * return int 0 - OK. - * 1 - Error. - */ -static int pca_prepare_suffix(PathCache *pc, const char *suffix, - int add_escapes) -{ - const char *sptr; /* A pointer into suffix[] */ - int nbsl; /* The number of backslashes to add to the suffix */ - int i; -/* - * How long is the suffix? - */ - int suffix_len = strlen(suffix); -/* - * Clear the work buffer. - */ - _pn_clear_path(pc->path); -/* - * Count the number of backslashes that will have to be added to - * escape spaces, tabs, backslashes and wildcard characters. - */ - nbsl = 0; - if(add_escapes) { - for(sptr = suffix; *sptr; sptr++) { - switch(*sptr) { - case ' ': case '\t': case '\\': case '*': case '?': case '[': - nbsl++; - break; - }; - }; - }; -/* - * Arrange for the output path buffer to have sufficient room for the - * both the suffix and any backslashes that have to be inserted. - */ - if(_pn_resize_path(pc->path, suffix_len + nbsl) == NULL) { - strcpy(pc->errmsg, "Insufficient memory to complete file name"); - return 1; - }; -/* - * If the suffix doesn't need any escapes, copy it directly into the - * work buffer. - */ - if(nbsl==0) { - strcpy(pc->path->name, suffix); - } else { -/* - * Make a copy with special characters escaped? - */ - if(nbsl > 0) { - const char *src = suffix; - char *dst = pc->path->name; - for(i=0; i<suffix_len; i++) { - switch(*src) { - case ' ': case '\t': case '\\': case '*': case '?': case '[': - *dst++ = '\\'; - }; - *dst++ = *src++; - }; - *dst = '\0'; - }; - }; - return 0; -} - -/*....................................................................... - * Return non-zero if the specified string appears to start with a pathname. - * - * Input: - * prefix const char * The filename prefix to check. - * prefix_len int The length of the prefix. - * Output: - * return int 0 - Doesn't start with a path name. - * 1 - Does start with a path name. - */ -static int cpa_cmd_contains_path(const char *prefix, int prefix_len) -{ - int i; -/* - * If the filename starts with a ~, then this implies a ~username - * expression, which constitutes a pathname. - */ - if(*prefix == '~') - return 1; -/* - * If the filename starts with the root directory, then it obviously - * starts with a pathname. - */ - if(prefix_len >= FS_ROOT_DIR_LEN && - strncmp(prefix, FS_ROOT_DIR, FS_ROOT_DIR_LEN) == 0) - return 1; -/* - * Search the prefix for directory separators, returning as soon as - * any are found, since their presence indicates that the filename - * starts with a pathname specification (valid or otherwise). - */ - for(i=0; i<prefix_len; i++) { - if(prefix_len - i >= FS_DIR_SEP_LEN && - strncmp(prefix + i, FS_DIR_SEP, FS_DIR_SEP_LEN) == 0) - return 1; - }; -/* - * The file name doesn't appear to start with a pathname specification. - */ - return 0; -} - -/*....................................................................... - * If needed make a new copy of the prefix being matched, in pc->path->name, - * but with escapes removed. If no escapes are to be removed, simply return - * the original prefix string. - * - * Input: - * pc PathCache * The cache being searched. - * prefix const char * The prefix to be processed. - * prefix_len size_t The length of the prefix. - * escaped int If true, return a copy with escapes removed. - * Output: - * return const char * The prepared prefix, or NULL on error, in - * which case an error message will have been - * left in pc->errmsg. - */ -static const char *pca_prepare_prefix(PathCache *pc, const char *prefix, - size_t prefix_len, int escaped) -{ -/* - * Make a copy with escapes removed? - */ - if(escaped) { - _pn_clear_path(pc->path); - if(_pn_append_to_path(pc->path, prefix, prefix_len, 1) == NULL) { - strcpy(pc->errmsg, "Insufficient memory to complete filename"); - return NULL; - }; - return pc->path->name; - }; - return prefix; -} - -/*....................................................................... - * If backslashes in the filename should be treated as literal - * characters, call the following function with literal=1. Otherwise - * the default is to treat them as escape characters, used for escaping - * spaces etc.. - * - * Input: - * ppc PcaPathConf * The pca_path_completions() configuration object - * to be configured. - * literal int Pass non-zero here to enable literal interpretation - * of backslashes. Pass 0 to turn off literal - * interpretation. - */ -void ppc_literal_escapes(PcaPathConf *ppc, int literal) -{ - if(ppc) - ppc->escaped = !literal; -} - -/*....................................................................... - * Call this function if you know where the index at which the - * filename prefix starts in the input line. Otherwise by default, - * or if you specify start_index to be -1, the filename is taken - * to start after the first unescaped space preceding the cursor, - * or the start of the line, which ever comes first. - * - * Input: - * ppc PcaPathConf * The pca_path_completions() configuration object - * to be configured. - * start_index int The index of the start of the filename in - * the input line, or -1 to select the default. - */ -void ppc_file_start(PcaPathConf *ppc, int start_index) -{ - if(ppc) - ppc->file_start = start_index; -} - -/*....................................................................... - * Expand any ~user expression found at the start of a path, leaving - * either an empty string in pc->path if there is no ~user expression, - * or the corresponding home directory. - * - * Input: - * pc PathCache * The filename cache. - * path const char * The path to expand. - * pathlen int The max number of characters to look at in path[]. - * literal int If true, treat backslashes as literal characters - * instead of escapes. - * Input/Output: - * endp const char * A pointer to the next unprocessed character in - * path[] will be assigned to *endp. - * Output: - * return int 0 - OK - * 1 - Error (a description will have been placed - * in pc->errmsg[]). - */ -static int pca_expand_tilde(PathCache *pc, const char *path, int pathlen, - int literal, const char **endp) -{ - const char *pptr = path; /* A pointer into path[] */ - const char *homedir=NULL; /* A home directory */ -/* - * Clear the pathname buffer. - */ - _pn_clear_path(pc->path); -/* - * If the first character is a tilde, then perform home-directory - * interpolation. - */ - if(*pptr == '~') { -/* - * Skip the tilde character and attempt to read the username that follows - * it, into pc->usrnam[]. - */ - if(pca_read_username(pc, ++pptr, pathlen-1, literal, &pptr)) - return 1; -/* - * Attempt to lookup the home directory of the user. - */ - homedir = _hd_lookup_home_dir(pc->home, pc->usrnam); - if(!homedir) { - strncpy(pc->errmsg, _hd_last_home_dir_error(pc->home), ERRLEN); - pc->errmsg[ERRLEN] = '\0'; - return 1; - }; -/* - * Append the home directory to the pathname string. - */ - if(_pn_append_to_path(pc->path, homedir, -1, 0) == NULL) { - strcpy(pc->errmsg, "Insufficient memory for home directory expansion"); - return 1; - }; - }; -/* - * ~user and ~ are usually followed by a directory separator to - * separate them from the file contained in the home directory. - * If the home directory is the root directory, then we don't want - * to follow the home directory by a directory separator, so we should - * skip over it so that it doesn't get copied into the output pathname - */ - if(homedir && strcmp(homedir, FS_ROOT_DIR) == 0 && - (pptr-path) + FS_DIR_SEP_LEN < pathlen && - strncmp(pptr, FS_DIR_SEP, FS_DIR_SEP_LEN) == 0) { - pptr += FS_DIR_SEP_LEN; - }; -/* - * Return a pointer to the next unprocessed character. - */ - *endp = pptr; - return 0; -} - -/*....................................................................... - * Clear the filename status codes that are recorded before each filename - * in the cache. - * - * Input: - * pc PathCache * The filename cache. - */ -static void pca_remove_marks(PathCache *pc) -{ - PathNode *node; /* A node in the list of directories in the path */ - int i; -/* - * Traverse the absolute directories of the path, clearing the - * filename status marks that precede each filename. - */ - for(node=pc->head; node; node=node->next) { - if(!node->relative) { - for(i=0; i<node->nfile; i++) - *node->files[i] = PCA_F_ENIGMA; - }; - }; - return; -} diff --git a/libtecla-1.4.1/stringrp.c b/libtecla-1.4.1/stringrp.c deleted file mode 100644 index fe7d875..0000000 --- a/libtecla-1.4.1/stringrp.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright (c) 2000, 2001 by Martin C. Shepherd. - * - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL - * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - */ -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "freelist.h" -#include "stringrp.h" - -/* - * StringSegment objects store lots of small strings in larger - * character arrays. Since the total length of all of the strings can't - * be known in advance, an extensible list of large character arrays, - * called string-segments are used. - */ -typedef struct StringSegment StringSegment; -struct StringSegment { - StringSegment *next; /* A pointer to the next segment in the list */ - char *block; /* An array of characters to be shared between strings */ - int unused; /* The amount of unused space at the end of block[] */ -}; - -/* - * StringGroup is typedef'd in stringrp.h. - */ -struct StringGroup { - FreeList *node_mem; /* The StringSegment free-list */ - int block_size; /* The dimension of each character array block */ - StringSegment *head; /* The list of character arrays */ -}; - -/* - * Specify how many StringSegment's to allocate at a time. - */ -#define STR_SEG_BLK 20 - -/*....................................................................... - * Create a new StringGroup object. - * - * Input: - * segment_size int The length of each of the large character - * arrays in which multiple strings will be - * stored. This sets the length of longest - * string that can be stored, and for efficiency - * should be at least 10 times as large as - * the average string that will be stored. - * Output: - * return StringGroup * The new object, or NULL on error. - */ -StringGroup *_new_StringGroup(int segment_size) -{ - StringGroup *sg; /* The object to be returned */ -/* - * Check the arguments. - */ - if(segment_size < 1) { - fprintf(stderr, "_new_StringGroup: Invalid segment_size argument.\n"); - return NULL; - }; -/* - * Allocate the container. - */ - sg = (StringGroup *) malloc(sizeof(StringGroup)); - if(!sg) { - fprintf(stderr, "_new_StringGroup: Insufficient memory.\n"); - return NULL; - }; -/* - * Before attempting any operation that might fail, initialize the - * container at least up to the point at which it can safely be passed - * to _del_StringGroup(). - */ - sg->node_mem = NULL; - sg->head = NULL; - sg->block_size = segment_size; -/* - * Allocate the free list that is used to allocate list nodes. - */ - sg->node_mem = _new_FreeList("_new_StringGroup", sizeof(StringSegment), - STR_SEG_BLK); - if(!sg->node_mem) - return _del_StringGroup(sg); - return sg; -} - -/*....................................................................... - * Delete a StringGroup object. - * - * Input: - * sg StringGroup * The object to be deleted. - * Output: - * return StringGroup * The deleted object (always NULL). - */ -StringGroup *_del_StringGroup(StringGroup *sg) -{ - if(sg) { - StringSegment *node; -/* - * Delete the character arrays. - */ - for(node=sg->head; node; node=node->next) { - if(node->block) - free(node->block); - node->block = NULL; - }; -/* - * Delete the list nodes that contained the string segments. - */ - sg->node_mem = _del_FreeList("_del_StringGroup", sg->node_mem, 1); - sg->head = NULL; /* Already deleted by deleting sg->node_mem */ -/* - * Delete the container. - */ - free(sg); - }; - return NULL; -} - -/*....................................................................... - * Make a copy of a string in the specified string group, and return - * a pointer to the copy. - * - * Input: - * sg StringGroup * The group to store the string in. - * string const char * The string to be recorded. - * remove_escapes int If true, omit backslashes which escape - * other characters when making the copy. - * Output: - * return char * The pointer to the copy of the string, - * or NULL if there was insufficient memory. - */ -char *_sg_store_string(StringGroup *sg, const char *string, int remove_escapes) -{ - char *copy; /* The recorded copy of string[] */ -/* - * Check the arguments. - */ - if(!sg || !string) - return NULL; -/* - * Get memory for the string. - */ - copy = _sg_alloc_string(sg, strlen(string)); - if(copy) { -/* - * If needed, remove backslash escapes while copying the input string - * into the cache string. - */ - if(remove_escapes) { - int escaped = 0; /* True if the next character should be */ - /* escaped. */ - const char *src = string; /* A pointer into the input string */ - char *dst = copy; /* A pointer into the cached copy of the */ - /* string. */ - while(*src) { - if(!escaped && *src == '\\') { - escaped = 1; - src++; - } else { - escaped = 0; - *dst++ = *src++; - }; - }; - *dst = '\0'; -/* - * If escapes have already been removed, copy the input string directly - * into the cache. - */ - } else { - strcpy(copy, string); - }; - }; -/* - * Return a pointer to the copy of the string (or NULL if the allocation - * failed). - */ - return copy; -} - -/*....................................................................... - * Allocate memory for a string of a given length. - * - * Input: - * sg StringGroup * The group to store the string in. - * length int The required length of the string. - * Output: - * return char * The pointer to the copy of the string, - * or NULL if there was insufficient memory. - */ -char *_sg_alloc_string(StringGroup *sg, int length) -{ - StringSegment *node; /* A node of the list of string segments */ - char *copy; /* The allocated string */ -/* - * If the string is longer than block_size, then we can't record it. - */ - if(length > sg->block_size || length < 0) - return NULL; -/* - * See if there is room to record the string in one of the existing - * string segments. - */ - for(node=sg->head; node && node->unused <= length; node=node->next) - ; -/* - * If there wasn't room, allocate a new string segment. - */ - if(!node) { - node = (StringSegment *) _new_FreeListNode(sg->node_mem); - if(!node) - return NULL; -/* - * Initialize the segment. - */ - node->next = NULL; - node->block = NULL; - node->unused = sg->block_size; -/* - * Attempt to allocate the string segment character array. - */ - node->block = (char *) malloc(sg->block_size); - if(!node->block) - return NULL; -/* - * Prepend the node to the list. - */ - node->next = sg->head; - sg->head = node; - }; -/* - * Get memory for the string. - */ - copy = node->block + sg->block_size - node->unused; - node->unused -= length + 1; -/* - * Return a pointer to the string memory. - */ - return copy; -} - -/*....................................................................... - * Delete all of the strings that are currently stored by a specified - * StringGroup object. - * - * Input: - * sg StringGroup * The group of strings to clear. - */ -void _clr_StringGroup(StringGroup *sg) -{ - StringSegment *node; /* A node in the list of string segments */ -/* - * Mark all of the string segments as unoccupied. - */ - for(node=sg->head; node; node=node->next) - node->unused = sg->block_size; - return; -} diff --git a/libtecla-1.4.1/stringrp.h b/libtecla-1.4.1/stringrp.h deleted file mode 100644 index 8b15ce9..0000000 --- a/libtecla-1.4.1/stringrp.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef stringrp_h -#define stringrp_h -/* - * Copyright (c) 2000, 2001 by Martin C. Shepherd. - * - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL - * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - */ - -/* - * StringGroup objects provide memory for modules that need to - * allocate lots of small strings without needing to free any of them - * individually, but rather is happy to free them all at the same - * time. Taking advantage of these properties, StringGroup objects - * avoid the heap fragmentation that tends to occur when lots of small - * strings are allocated directly from the heap and later free'd. They - * do this by allocating a list of large character arrays in each of - * which multiple strings are stored. Thus instead of allocating lots - * of small strings, a few large character arrays are allocated. When - * the strings are free'd on mass, this list of character arrays is - * maintained, ready for subsequent use in recording another set of - * strings. - */ -typedef struct StringGroup StringGroup; - -/* - * The following constructor allocates a string-allocation object. - * The segment_size argument specifies how long each string segment - * array should be. This should be at least 10 times the length of - * the average string to be recorded in the string group, and - * sets the length of the longest string that can be stored. - */ -StringGroup *_new_StringGroup(int segment_size); - -/* - * Delete all of the strings that are currently stored by a specified - * StringGroup object. - */ -void _clr_StringGroup(StringGroup *sg); - -/* - * Make a copy of the specified string, returning a pointer to - * the copy, or NULL if there was insufficient memory. If the - * remove_escapes argument is non-zero, backslashes that escape - * other characters will be removed. - */ -char *_sg_store_string(StringGroup *sg, const char *string, int remove_escapes); - -/* - * Allocate memory for a string of a given length. - */ -char *_sg_alloc_string(StringGroup *sg, int length); - -/* - * Delete a StringGroup object (and all of the strings that it - * contains). - */ -StringGroup *_del_StringGroup(StringGroup *sg); - -#endif diff --git a/libtecla-1.4.1/strngmem.c b/libtecla-1.4.1/strngmem.c deleted file mode 100644 index fedf4ff..0000000 --- a/libtecla-1.4.1/strngmem.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) 2000, 2001 by Martin C. Shepherd. - * - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL - * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - */ - -#include <stdlib.h> -#include <stdio.h> - -#include "strngmem.h" -#include "freelist.h" - -struct StringMem { - unsigned long nmalloc; /* The number of strings allocated with malloc */ - FreeList *fl; /* The free-list */ -}; - -/*....................................................................... - * Create a string free-list container and the first block of its free-list. - * - * Input: - * caller const char * The name of the calling function, or NULL - * to not report errors to stderr. - * blocking_factor int The blocking_factor argument specifies how - * many strings of length SM_STRLEN - * bytes (see stringmem.h) are allocated in each - * free-list block. - * For example if blocking_factor=64 and - * SM_STRLEN=16, then each new - * free-list block will take 1K of memory. - * Output: - * return StringMem * The new free-list container, or NULL on - * error. - */ -StringMem *_new_StringMem(const char *caller, unsigned blocking_factor) -{ - StringMem *sm; /* The container to be returned. */ -/* - * Check arguments. - */ - if(blocking_factor < 1) { - if(caller) { - fprintf(stderr, "_new_StringMem (%s): Bad blocking factor (%d).\n", - caller, blocking_factor); - }; - return NULL; - }; -/* - * Allocate the container. - */ - sm = (StringMem *) malloc(sizeof(StringMem)); - if(!sm) { - if(caller) - fprintf(stderr, "_new_StringMem (%s): Insufficient memory.\n", caller); - return NULL; - }; -/* - * Before attempting any operation that might fail, initialize - * the container at least up to the point at which it can safely - * be passed to _del_StringMem(). - */ - sm->nmalloc = 0; - sm->fl = NULL; -/* - * Allocate the free-list. - */ - sm->fl = _new_FreeList(caller, SM_STRLEN, blocking_factor); - if(!sm->fl) - return _del_StringMem(caller, sm, 1); -/* - * Return the free-list container. - */ - return sm; -} - -/*....................................................................... - * Delete a string free-list. - * - * Input: - * caller const char * The name of the calling function, or NULL to - * not report errors to stderr. - * sm StringMem * The string free-list to be deleted, or NULL. - * force int If force==0 then _del_StringMem() will complain - * and refuse to delete the free-list if any - * of nodes have not been returned to the free-list. - * If force!=0 then _del_StringMem() will not check - * whether any nodes are still in use and will - * always delete the list. - * Output: - * return StringMem * Always NULL (even if the list couldn't be - * deleted). - */ -StringMem *_del_StringMem(const char *caller, StringMem *sm, int force) -{ - if(sm) { -/* - * Check whether any strings have not been returned to the free-list. - */ - if(!force && (sm->nmalloc > 0 || _busy_FreeListNodes(sm->fl) > 0)) { - if(caller) - fprintf(stderr, "_del_StringMem (%s): Free-list in use.\n", caller); - return NULL; - }; -/* - * Delete the free-list. - */ - sm->fl = _del_FreeList(caller, sm->fl, force); -/* - * Delete the container. - */ - free(sm); - }; - return NULL; -} - -/*....................................................................... - * Allocate an array of 'length' chars. - * - * Input: - * sm StringMem * The string free-list to allocate from. - * length size_t The length of the new string (including '\0'). - * Output: - * return char * The new string or NULL on error. - */ -char *_new_StringMemString(StringMem *sm, size_t length) -{ - char *string; /* The string to be returned */ - int was_malloc; /* True if malloc was used to allocate the string */ -/* - * Check arguments. - */ - if(!sm) - return NULL; - if(length < 1) - length = 1; -/* - * Allocate the new node from the free list if possible. - */ - if(length < SM_STRLEN) { - string = (char *)_new_FreeListNode(sm->fl); - if(!string) - return NULL; - was_malloc = 0; - } else { - string = (char *) malloc(length+1); /* Leave room for the flag byte */ - if(!string) - return NULL; -/* - * Count malloc allocations. - */ - was_malloc = 1; - sm->nmalloc++; - }; -/* - * Use the first byte of the string to record whether the string was - * allocated with malloc or from the free-list. Then return the rest - * of the string for use by the user. - */ - string[0] = (char) was_malloc; - return string + 1; -} - -/*....................................................................... - * Free a string that was previously returned by _new_StringMemString(). - * - * Input: - * sm StringMem * The free-list from which the string was originally - * allocated. - * s char * The string to be returned to the free-list, or NULL. - * Output: - * return char * Always NULL. - */ -char *_del_StringMemString(StringMem *sm, char *s) -{ - int was_malloc; /* True if the string originally came from malloc() */ -/* - * Is there anything to be deleted? - */ - if(s && sm) { -/* - * Retrieve the true string pointer. This is one less than the one - * returned by _new_StringMemString() because the first byte of the - * allocated memory is reserved by _new_StringMemString as a flag byte - * to say whether the memory was allocated from the free-list or directly - * from malloc(). - */ - s--; -/* - * Get the origination flag. - */ - was_malloc = s[0]; - if(was_malloc) { - free(s); - s = NULL; - sm->nmalloc--; - } else { - s = (char *) _del_FreeListNode(sm->fl, s); - }; - }; - return NULL; -} diff --git a/libtecla-1.4.1/strngmem.h b/libtecla-1.4.1/strngmem.h deleted file mode 100644 index 5737ae0..0000000 --- a/libtecla-1.4.1/strngmem.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef stringmem_h -#define stringmem_h -/* - * Copyright (c) 2000, 2001 by Martin C. Shepherd. - * - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL - * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING - * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - */ - -typedef struct StringMem StringMem; - -/* - * Applications that dynamically allocate lots of small strings - * run the risk of significantly fragmenting the heap. This module - * aims to reduce this risk by allocating large arrays of small fixed - * length strings, arranging them as a free-list and allowing - * callers to allocate from the list. Strings that are too long - * to be allocated from the free-list are allocated from the heap. - * Since typical implementations of malloc() eat up a minimum of - * 16 bytes per call to malloc() [because of alignment and space - * management constraints] it makes sense to set the free-list - * string size to 16 bytes. Note that unlike malloc() which typically - * keeps 8 bytes per allocation for its own use, our allocator will - * return all but one of the 16 bytes for use. One hidden byte of overhead - * is reserved for flagging whether the string was allocated directly - * from malloc or from the free-list. - */ - -/* - * Set the length of each free-list string. The longest string that - * will be returned without calling malloc() will be one less than - * this number. - */ -#define SM_STRLEN 16 - -/* - * Create a string free-list container and the first block of its free-list. - */ -StringMem *_new_StringMem(const char *caller, unsigned blocking_factor); - -/* - * Delete a string free-list. - */ -StringMem *_del_StringMem(const char *caller, StringMem *sm, int force); - -/* - * Allocate an array of 'length' chars. - */ -char *_new_StringMemString(StringMem *sm, size_t size); - -/* - * Free a string that was previously returned by _new_StringMemString(). - */ -char *_del_StringMemString(StringMem *sm, char *s); - -#endif diff --git a/libtecla-1.4.1/update_html b/libtecla-1.4.1/update_html deleted file mode 100755 index 35625a7..0000000 --- a/libtecla-1.4.1/update_html +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/sh - -# Convert man pages to html files. - -cd man3 -for page in *.3;do - if [ "`wc -l $page | awk '{print $1}'`" -gt 1 ]; then - html="../html/`echo $page | sed -e 's/.3$/.html/'`" - man2html $page > $html - for ref in "libtecla(3)" "cpl_complete_word(3)" "ef_expand_file(3)" "gl_get_line(3)" "pca_lookup_file(3)" "enhance(3)"; do - link="`echo $ref | sed 's/(3)/.html/'`" - ed -s $html << EOF - 1,\$s|$ref|<a href="$link">&</a>|g - w - q -EOF - done - fi -done - -# Convert the change log into a web page. - -cd ../html -echo '<HEAD><TITLE>The tecla library change log</TITLE></HEAD>' > changes.html -echo '<BODY bgcolor=add8e6><PRE>' >> changes.html -cat ../CHANGES >> changes.html -echo '</PRE></BODY>' >> changes.html - -# Do the same to the release-notes file. - -cd ../html -echo '<HEAD><TITLE>The tecla library release notes</TITLE></HEAD>' > release.html -echo '<BODY bgcolor=add8e6><PRE>' >> release.html -cat ../RELEASE.NOTES >> release.html -echo '</PRE></BODY>' >> release.html diff --git a/libtecla-1.4.1/update_version b/libtecla-1.4.1/update_version deleted file mode 100755 index c18f714..0000000 --- a/libtecla-1.4.1/update_version +++ /dev/null @@ -1,82 +0,0 @@ -#!/bin/sh -#----------------------------------------------------------------------- -# Change the version number of the library. This changes the number in -# every file that it is known to appear in. -# -# Usage: -# update_version major minor micro -#----------------------------------------------------------------------- - -usage="$0 major minor micro" - -if [ $# -ne 3 ]; then - echo $usage - exit 1 -fi - -# Get the three components of the version number. - -major="$1" -minor="$2" -micro="$3" - -# Everything will need to be reconfigured after this change, so -# discard any existing configuration. - -make distclean 2>/dev/null - -# Check that the version components are all positive integers. - -for c in $major $minor $micro; do - if echo "$c" | awk '{exit $1 ~ /^[0-9]+$/}'; then - echo 'Version number components must all be positive integers.' - exit 1 - fi -done - -# -# Update the version number in the configure.in script. -# -ed -s configure.in << EOF -/^MAJOR_VER=\"[0-9][0-9]*\"/ s/^.*$/MAJOR_VER=\"$major\"/ -/^MINOR_VER=\"[0-9][0-9]*\"/ s/^.*$/MINOR_VER=\"$minor\"/ -/^MICRO_VER=\"[0-9][0-9]*\"/ s/^.*$/MICRO_VER=\"$micro\"/ -w -q -EOF - -if which autoconf 1>/dev/null 2>&1; then - autoconf -else - echo 'Note that autoconf needs to be run.' -fi - -# -# Update the version number in the libtecla header file script. -# -ed -s libtecla.h << EOF -/^#define TECLA_MAJOR_VER [0-9][0-9]*/ s/^.*$/#define TECLA_MAJOR_VER $major/ -/^#define TECLA_MINOR_VER [0-9][0-9]*/ s/^.*$/#define TECLA_MINOR_VER $minor/ -/^#define TECLA_MICRO_VER [0-9][0-9]*/ s/^.*$/#define TECLA_MICRO_VER $micro/ -w -q -EOF - -# -# Update the version number in the README file. -# -ed -s README << EOF -/version [0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]* / s/version [0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*/version $major.$minor.$micro/ -w -q -EOF - -# -# Update the version number in the html index file. -# -ed -s html/index.html << EOF -/version [0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\./ s/version [0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*/version $major.$minor.$micro/g -/libtecla-[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\./ s/libtecla-[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\./libtecla-$major.$minor.$micro./g -w -q -EOF diff --git a/libtecla-1.4.1/version.c b/libtecla-1.4.1/version.c deleted file mode 100644 index 9e1275e..0000000 --- a/libtecla-1.4.1/version.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "libtecla.h" - -/*....................................................................... - * Return the version number of the tecla library. - * - * Input: - * major int * The major version number of the library - * will be assigned to *major. This number is - * only incremented when a change to the library is - * made that breaks binary (shared library) and/or - * compilation backwards compatibility. - * minor int * The minor version number of the library - * will be assigned to *minor. This number is - * incremented whenever new functions are added to - * the public API. - * micro int * The micro version number of the library will be - * assigned to *micro. This number is incremented - * whenever internal changes are made that don't - * change the public API, such as bug fixes and - * performance enhancements. - */ -void libtecla_version(int *major, int *minor, int *micro) -{ - if(major) - *major = TECLA_MAJOR_VER; - if(minor) - *minor = TECLA_MINOR_VER; - if(micro) - *micro = TECLA_MICRO_VER; -} |